]> begriffs open source - ai-pg/blob - full-docs/txt/spi-examples.txt
Convert HTML docs to more streamlined TXT
[ai-pg] / full-docs / txt / spi-examples.txt
1
2 45.6. Examples #
3
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.
10 #include "postgres.h"
11
12 #include "executor/spi.h"
13 #include "utils/builtins.h"
14
15 PG_MODULE_MAGIC;
16
17 PG_FUNCTION_INFO_V1(execq);
18
19 Datum
20 execq(PG_FUNCTION_ARGS)
21 {
22     char *command;
23     int cnt;
24     int ret;
25     uint64 proc;
26
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);
30
31     SPI_connect();
32
33     ret = SPI_exec(command, cnt);
34
35     proc = SPI_processed;
36
37     /*
38      * If some rows were fetched, print them via elog(INFO).
39      */
40     if (ret > 0 && SPI_tuptable != NULL)
41     {
42         SPITupleTable *tuptable = SPI_tuptable;
43         TupleDesc tupdesc = tuptable->tupdesc;
44         char buf[8192];
45         uint64 j;
46
47         for (j = 0; j < tuptable->numvals; j++)
48         {
49             HeapTuple tuple = tuptable->vals[j];
50             int i;
51
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);
57         }
58     }
59
60     SPI_finish();
61     pfree(command);
62
63     PG_RETURN_INT64(proc);
64 }
65
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
69     AS 'filename'
70     LANGUAGE C STRICT;
71
72    Here is a sample session:
73 => SELECT execq('CREATE TABLE a (x integer)', 0);
74  execq
75 -------
76      0
77 (1 row)
78
79 => INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)', 0));
80 INSERT 0 1
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
84
85  execq
86 -------
87      2
88 (1 row)
89
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
92  execq
93 -------
94      1
95 (1 row)
96
97 => SELECT execq('SELECT * FROM a', 10);
98 INFO:  EXECQ:  0
99 INFO:  EXECQ:  1
100 INFO:  EXECQ:  2
101
102  execq
103 -------
104      3              -- 10 is the max value only, 3 is the real number of rows
105 (1 row)
106
107 => SELECT execq('INSERT INTO a SELECT x + 10 FROM a', 1);
108  execq
109 -------
110      3              -- all rows processed; count does not stop it, because nothi
111 ng is returned
112 (1 row)
113
114 => SELECT * FROM a;
115  x
116 ----
117   0
118   1
119   2
120  10
121  11
122  12
123 (6 rows)
124
125 => DELETE FROM a;
126 DELETE 6
127 => INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1);
128 INSERT 0 1
129 => SELECT * FROM a;
130  x
131 ---
132  1                  -- 0 (no rows in a) + 1
133 (1 row)
134
135 => INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1);
136 INFO:  EXECQ:  1
137 INSERT 0 1
138 => SELECT * FROM a;
139  x
140 ---
141  1
142  2                  -- 1 (there was one row in a) + 1
143 (2 rows)
144
145 -- This demonstrates the data changes visibility rule.
146 -- execq is called twice and sees different numbers of rows each time:
147
148 => INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a;
149 INFO:  EXECQ:  1    -- results from first execq
150 INFO:  EXECQ:  2
151 INFO:  EXECQ:  1    -- results from second execq
152 INFO:  EXECQ:  2
153 INFO:  EXECQ:  2
154 INSERT 0 2
155 => SELECT * FROM a;
156  x
157 ---
158  1
159  2
160  2                  -- 2 rows * 1 (x in first row)
161  6                  -- 3 rows (2 + 1 just inserted) * 2 (x in second row)
162 (4 rows)