4 This section contains a very simple example of SPI usage. The C
5 function execq takes an SQL command as its first argument and a row
6 count as its second, executes the command using SPI_exec and returns
7 the number of rows that were processed by the command. You can find
8 more complex examples for SPI in the source tree in
9 src/test/regress/regress.c and in the spi module.
12 #include "executor/spi.h"
13 #include "utils/builtins.h"
17 PG_FUNCTION_INFO_V1(execq);
20 execq(PG_FUNCTION_ARGS)
27 /* Convert given text object to a C string */
28 command = text_to_cstring(PG_GETARG_TEXT_PP(0));
29 cnt = PG_GETARG_INT32(1);
33 ret = SPI_exec(command, cnt);
38 * If some rows were fetched, print them via elog(INFO).
40 if (ret > 0 && SPI_tuptable != NULL)
42 SPITupleTable *tuptable = SPI_tuptable;
43 TupleDesc tupdesc = tuptable->tupdesc;
47 for (j = 0; j < tuptable->numvals; j++)
49 HeapTuple tuple = tuptable->vals[j];
52 for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++)
53 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %s%s",
54 SPI_getvalue(tuple, tupdesc, i),
55 (i == tupdesc->natts) ? " " : " |");
56 elog(INFO, "EXECQ: %s", buf);
63 PG_RETURN_INT64(proc);
66 This is how you declare the function after having compiled it into a
67 shared library (details are in Section 36.10.5.):
68 CREATE FUNCTION execq(text, integer) RETURNS int8
72 Here is a sample session:
73 => SELECT execq('CREATE TABLE a (x integer)', 0);
79 => INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)', 0));
81 => SELECT execq('SELECT * FROM a', 0);
82 INFO: EXECQ: 0 -- inserted by execq
83 INFO: EXECQ: 1 -- returned by execq and inserted by upper INSERT
90 => SELECT execq('INSERT INTO a SELECT x + 2 FROM a RETURNING *', 1);
91 INFO: EXECQ: 2 -- 0 + 2, then execution was stopped by count
97 => SELECT execq('SELECT * FROM a', 10);
104 3 -- 10 is the max value only, 3 is the real number of rows
107 => SELECT execq('INSERT INTO a SELECT x + 10 FROM a', 1);
110 3 -- all rows processed; count does not stop it, because nothi
127 => INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1);
132 1 -- 0 (no rows in a) + 1
135 => INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1);
142 2 -- 1 (there was one row in a) + 1
145 -- This demonstrates the data changes visibility rule.
146 -- execq is called twice and sees different numbers of rows each time:
148 => INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a;
149 INFO: EXECQ: 1 -- results from first execq
151 INFO: EXECQ: 1 -- results from second execq
160 2 -- 2 rows * 1 (x in first row)
161 6 -- 3 rows (2 + 1 just inserted) * 2 (x in second row)