Cette section contient un exemple très simple d'utilisation de SPI. La
procédure execq
prend une commande SQL comme
premier argument et un compteur de lignes comme second, exécute la commande
en utilisant SPI_exec
et renvoie le nombre de lignes
qui ont été traitées par la commande. Vous trouverez des exemples plus
complexes pour SPI dans l'arborescence source dans
src/test/regress/regress.c
et dans le module
spi.
#include "postgres.h" #include "executor/spi.h" #include "utils/builtins.h" #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif PG_FUNCTION_INFO_V1(execq); Datum execq(PG_FUNCTION_ARGS) { char *command; int cnt; int ret; uint64 proc; /* Convert given text object to a C string */ command = text_to_cstring(PG_GETARG_TEXT_PP(0)); cnt = PG_GETARG_INT32(1); SPI_connect(); ret = SPI_exec(command, cnt); proc = SPI_processed; /* * Si des lignes ont été récupérées, * alors les afficher via elog(INFO). */ if (ret > 0 && SPI_tuptable != NULL) { TupleDesc tupdesc = SPI_tuptable->tupdesc; SPITupleTable *tuptable = SPI_tuptable; char buf[8192]; int64 j; for (j = 0; j < proc; j++) { HeapTuple tuple = tuptable->vals[j]; int i; for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++) snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %s%s", SPI_getvalue(tuple, tupdesc, i), (i == tupdesc->natts) ? " " : " |"); elog(INFO, "EXECQ: %s", buf); } } SPI_finish(); pfree(command); PG_RETURN_INT64(proc); }
Voici comment déclarer la fonction après l'avoir compilée en une bibliothèque partagée (les détails sont dans Section 37.9.5) :
CREATE FUNCTION execq(text, integer) RETURNS int8
AS 'filename
'
LANGUAGE C STRICT;
Voici une session d'exemple :
=> SELECT execq('CREATE TABLE a (x integer)', 0); execq ------- 0 (1 row) => INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)', 0)); INSERT 0 1 => SELECT execq('SELECT * FROM a', 0); INFO: EXECQ: 0 -- inséré par execq INFO: EXECQ: 1 -- retourné par execq et inséré par l'INSERT précédant execq ------- 2 (1 row) => SELECT execq('INSERT INTO a SELECT x + 2 FROM a', 1); execq ------- 1 (1 row) => SELECT execq('SELECT * FROM a', 10); INFO: EXECQ: 0 INFO: EXECQ: 1 INFO: EXECQ: 2 -- 0 + 2, une seule ligne insérée - comme spécifié execq ------- 3 -- 10 est la valeur max seulement, 3 est le nombre réel de rangées (1 row) => DELETE FROM a; DELETE 3 => INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); INSERT 0 1 => SELECT * FROM a; x --- 1 -- aucune rangée dans a (0) + 1 (1 row) => INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); INFO: EXECQ: 1 INSERT 0 1 => SELECT * FROM a; x --- 1 2 -- il y a une rangée dans a + 1 (2 rows) -- Ceci montre la règle de visibilité de modifications de données : => INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a; INFO: EXECQ: 1 INFO: EXECQ: 2 INFO: EXECQ: 1 INFO: EXECQ: 2 INFO: EXECQ: 2 INSERT 0 2 => SELECT * FROM a; x --- 1 2 2 -- 2 rangées * 1 (x dans la première rangée) 6 -- 3 rangées (2 + 1 juste insérée) * 2 (x dans la deuxième rangée) (4 rows) ^^^^^^^ rangées visible à execq() dans des invocations différentes