SPI_execute — exécute une commande
int SPI_execute(const char *command
, boolread_only
, longcount
)
SPI_exec
lance la commande SQL spécifiée
pour count
lignes. Si read_only
est true
, la commande doit être en lecture seule et la surcharge
de l'exécution est quelque peu réduite.
Cette fonction ne devrait être appelée qu'à partir d'une fonction C connectée.
Si count
vaut zéro, alors la commande est exécutée
pour toutes les lignes auxquelles elle s'applique. Si
count
est supérieur à 0, alors pas plus de
count
lignes seront récupérées. L'exécution s'arrêtera
quand le compte est atteint, un peu comme l'ajout d'une clause
LIMIT
à une requête. Par exemple :
SPI_execute("SELECT * FROM foo", true, 5);
récupérera 5 lignes tout au plus à partir de la table. Notez qu'une telle limite n'est efficace qu'à partir du moment où la requête renvoie des lignes. Par exemple :
SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);
insérera toutes les lignes de bar
, en ignorant le
paramètre count
. Cependant, avec
SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5);
au plus cinq lignes seront insérées car l'exécution s'arrêtera après la
cinquième ligne renvoyée par RETURNING
.
Vous pourriez passer plusieurs commandes dans une chaîne.
SPI_execute
renvoie le résultat pour la dernière
commande exécutée. La limite count
s'applique à
chaque commande séparément (même si seul le dernier résultat sera renvoyé).
La limite n'est pas appliquée à toute commande cachée générée par les règles.
Quand read_only
vaut false
,
SPI_execute
incrémente le compteur de la commande
et calcule une nouvelle image avant d'exécuter chaque
commande dans la chaîne. L'image n'est pas réellement modifiée si le
niveau d'isolation de la transaction en cours est
SERIALIZABLE
ou REPEATABLE READ
mais, en mode
READ COMMITTED
, la mise
à jour de l'image permet à chaque commande de voir les résultats des
transactions nouvellement validées à partir des autres sessions. Ceci est
essentiel pour un comportement cohérent quand les commandes modifient la
base de données.
Quand read_only
vaut true
,
SPI_execute
ne met à jour ni l'image ni le compteur de
commandes, et il autorise seulement les commandes SELECT
dans
la chaîne des commandes. Elles sont exécutées en utilisant l'image
précédemment établie par la requête englobante. Ce mode d'exécution est
un peu plus rapide que le mode lecture/écriture à cause de l'élimination
de la surcharge par commande. Il autorise aussi directement la construction
des fonctions stable comme les exécutions successives
utiliseront toutes la même image, il n'y aura aucune modification dans les
résultats.
Il n'est généralement pas conseillé de mixer les commandes en lecture seule et les commandes en lecture/écriture à l'intérieur d'une seule fonction utilisant SPI ; ceci pourrait causer un comportement portant confusion car les requêtes en mode lecture seule devraient ne pas voir les résultats de toute mise à jour de la base de données effectuées par les requêtes en lecture/écriture.
Le nombre réel de lignes pour lesquelles la (dernière) commande a été
lancée
est retourné dans la variable globale SPI_processed
.
Si la valeur de retour de la fonction est SPI_OK_SELECT
,
SPI_OK_INSERT_RETURNING
, SPI_OK_DELETE_RETURNING
ou SPI_OK_UPDATE_RETURNING
, alors vous pouvez utiliser le
pointeur global SPITupleTable *SPI_tuptable
pour
accéder aux lignes de résultat. Quelques commandes (comme
EXPLAIN
) renvoient aussi des ensembles de lignes et
SPI_tuptable
contiendra aussi le résultat dans ces cas.
Certaines commandes utilitaires (COPY
, CREATE
TABLE AS
) ne renvoient pas un ensemble de lignes, donc
SPI_tuptable
est NULL, mais elles renvoient malgré tout
le nombre de lignes traitées dans SPI_processed
.
La structure SPITupleTable
est définie
comme suit :
typedef struct { MemoryContext tuptabcxt; /* contexte mémoire de la table de résultat */ uint64 alloced; /* nombre de valeurs allouées */ uint64 free; /* nombre de valeurs libres */ TupleDesc tupdesc; /* descripteur de rangées */ HeapTuple *vals; /* rangées */ } SPITupleTable;
vals
est un tableau de pointeurs vers des lignes (le
nombre d'entrées valables est donné par SPI_processed
).
tupdesc
est un descripteur de ligne que vous pouvez passer
aux fonctions SPI qui traitent des lignes. tuptabcxt
,
alloced
et free
sont des champs
internes non conçus pour être utilisés par des routines SPI appelantes.
SPI_finish
libère tous les
SPITupleTable
s allouées pendant la fonction C
courante. Vous pouvez libérer une table de résultats donnée plus tôt, si vous
en avez terminé avec elle, en appelant SPI_freetuptable
.
const char * command
chaîne contenant la commande à exécuter
bool read_only
true
en cas d'exécution en lecture seule
long count
nombre maximum de lignes à traiter ou 0
pour aucune
limite
Si l'exécution de la commande a réussi, alors l'une des valeurs (positives) suivantes sera renvoyée :
SPI_OK_SELECT
si un SELECT
(mais pas SELECT
INTO
) a été lancé
SPI_OK_SELINTO
si un SELECT INTO
a été lancé
SPI_OK_INSERT
si un INSERT
a été lancé
SPI_OK_DELETE
si un DELETE
a été lancé
SPI_OK_UPDATE
si un UPDATE
a été lancé
SPI_OK_INSERT_RETURNING
si un INSERT RETURNING
a été lancé
SPI_OK_DELETE_RETURNING
si un DELETE RETURNING
a été lancé
SPI_OK_UPDATE_RETURNING
si un UPDATE RETURNING
a été lancé
SPI_OK_UTILITY
si une commande utilitaire (c'est-à-dire CREATE TABLE
)
a été lancée
SPI_OK_REWRITTEN
si la commande a été réécrite dans un autre style de commande
(c'est-à-dire que UPDATE
devient un
INSERT
) par une règle.
Sur une erreur, l'une des valeurs négatives suivante est renvoyée :
SPI_ERROR_ARGUMENT
si command
est NULL
ou
count
est inférieur à 0
SPI_ERROR_COPY
si COPY TO stdout
ou COPY FROM stdin
ont été tentés
SPI_ERROR_TRANSACTION
Si une commande de manipulation de transaction a été
tentée
(BEGIN
,
COMMIT
,
ROLLBACK
,
SAVEPOINT
,
PREPARE TRANSACTION
,
COMMIT PREPARED
,
ROLLBACK PREPARED
ou toute variante de ces dernières)
SPI_ERROR_OPUNKNOWN
si le type de commande est inconnu (ce qui ne devrait pas arriver)
SPI_ERROR_UNCONNECTED
si appel à partir d'une fonction C non connectée
Toutes les fonctions d'exécution de requêtes SPI changent à la fois
SPI_processed
et
SPI_tuptable
(juste le pointeur, pas le contenu
de la structure). Sauvegardez ces deux variables globales dans des variables
locales de fonctions C si vous voulez accéder à la table des résultats de
SPI_execute
ou d'une fonction d'exécution de requêtes
sur plusieurs appels.