PostgreSQL Source Code: src/backend/executor/spi.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
36
37
38
39
40
41
42
43
47
52
54{
58
61
63
65
68 bool fire_triggers);
69
72
75
77
81
84
90
91
92
93
94int
96{
98}
99
100int
102{
103 int newdepth;
104
105
107 {
109 elog(ERROR, "SPI stack corrupted");
110 newdepth = 16;
115 }
116 else
117 {
119 elog(ERROR, "SPI stack corrupted");
121 {
127 }
128 }
129
130
133
148
149
150
151
152
153
154
155
156
157
158
159
160
161
163 "SPI Proc",
166 "SPI Exec",
168
170
171
172
173
174
178
180}
181
182int
184{
185 int res;
186
187 res = _SPI_begin_call(false);
188 if (res < 0)
189 return res;
190
191
193
194
199
200
201
202
203
207
208
212 else
214
216}
217
218
219
220
221
222void
224{
225}
226
227static void
229{
232
233
234
235
236
237
238
241 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
242 errmsg("invalid transaction termination")));
243
244
245
246
247
248
249
250
251
252
253
256 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
257 errmsg("cannot commit while a subtransaction is active")));
258
259 if (chain)
261
262
264 {
265
267
268
269
270
271
272
274
275
277
278
280
281
283 if (chain)
285
287
289 }
291 {
293
294
298
299
300
301
302
304
305
307 if (chain)
309
311
313
314
316 }
318}
319
320void
322{
324}
325
326void
328{
330}
331
332static void
334{
337
338
341 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
342 errmsg("invalid transaction termination")));
343
344
347 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
348 errmsg("cannot roll back while a subtransaction is active")));
349
350 if (chain)
352
353
355 {
356
358
359
360
361
362
363
364
366
367
369
370
372
373
375 if (chain)
377
379
381 }
383 {
385
386
390
391
392
393
394
395
397
398
400 if (chain)
402
404
406
407
409 }
411}
412
413void
415{
417}
418
419void
421{
423}
424
425
426
427
428void
430{
431 bool found = false;
432
433
434
435
436
438 {
440
442 break;
443
444 found = true;
445
446
447
448
449
450
451
452
453
454
455
456
460
464 else
466 }
467
468
469 if (found && isCommit)
471 (errcode(ERRCODE_WARNING),
472 errmsg("transaction left non-empty SPI stack"),
473 errhint("Check for missing \"SPI_finish\" calls.")));
474}
475
476
477
478
479
480
481
482void
484{
485 bool found = false;
486
488 {
490
491 if (connection->connectSubid != mySubid)
492 break;
493
495 break;
496
497 found = true;
498
499
500
501
503 {
506 }
508 {
511 }
512
513
514
515
516
517
521
525 else
527 }
528
529 if (found && isCommit)
531 (errcode(ERRCODE_WARNING),
532 errmsg("subtransaction left non-empty SPI stack"),
533 errhint("Check for missing \"SPI_finish\" calls.")));
534
535
536
537
538
540 {
542
543
544
545
546
548 {
551 }
552
553
555 {
557
559 if (tuptable->subid >= mySubid)
560 {
561
562
563
564
565
566
573 }
574 }
575 }
576}
577
578
579
580
581bool
583{
585 return false;
586
588 return false;
590 return false;
591 return true;
592}
593
594
595
596int
597SPI_execute(const char *src, bool read_only, long tcount)
598{
601 int res;
602
603 if (src == NULL || tcount < 0)
605
607 if (res < 0)
608 return res;
609
614
616
618 options.read_only = read_only;
620
623 true);
624
626 return res;
627}
628
629
630int
632{
634}
635
636
637int
640{
641 int res;
643
644 if (src == NULL || options == NULL)
646
648 if (res < 0)
649 return res;
650
656 {
657 plan.parserSetup = options->params->parserSetup;
658 plan.parserSetupArg = options->params->parserSetupArg;
659 }
660
662
665 true);
666
668 return res;
669}
670
671
672int
674 bool read_only, long tcount)
675{
677 int res;
678
681
682 if (plan->nargs > 0 && Values == NULL)
684
686 if (res < 0)
687 return res;
688
692 options.read_only = read_only;
694
697 true);
698
700 return res;
701}
702
703
704int
706{
708}
709
710
711int
714{
715 int res;
716
719
721 if (res < 0)
722 return res;
723
726 true);
727
729 return res;
730}
731
732
733int
735 bool read_only, long tcount)
736{
738 int res;
739
742
744 if (res < 0)
745 return res;
746
749 options.read_only = read_only;
751
754 true);
755
757 return res;
758}
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773int
777 bool read_only, bool fire_triggers, long tcount)
778{
780 int res;
781
784
785 if (plan->nargs > 0 && Values == NULL)
787
789 if (res < 0)
790 return res;
791
795 options.read_only = read_only;
797
799 snapshot, crosscheck_snapshot,
800 fire_triggers);
801
803 return res;
804}
805
806
807
808
809
810
811
812int
814 int nargs, Oid *argtypes,
816 bool read_only, long tcount)
817{
818 int res;
822
823 if (src == NULL || nargs < 0 || tcount < 0)
825
826 if (nargs > 0 && (argtypes == NULL || Values == NULL))
828
830 if (res < 0)
831 return res;
832
837 plan.nargs = nargs;
838 plan.argtypes = argtypes;
839 plan.parserSetup = NULL;
840 plan.parserSetupArg = NULL;
841
844
846
848 options.params = paramLI;
849 options.read_only = read_only;
851
854 true);
855
857 return res;
858}
859
862{
864}
865
868 int cursorOptions)
869{
872
873 if (src == NULL || nargs < 0 || (nargs > 0 && argtypes == NULL))
874 {
876 return NULL;
877 }
878
881 return NULL;
882
886 plan.cursor_options = cursorOptions;
887 plan.nargs = nargs;
888 plan.argtypes = argtypes;
889 plan.parserSetup = NULL;
890 plan.parserSetupArg = NULL;
891
893
894
896
898
899 return result;
900}
901
905{
908
909 if (src == NULL || options == NULL)
910 {
912 return NULL;
913 }
914
917 return NULL;
918
922 plan.cursor_options = options->cursorOptions;
923 plan.nargs = 0;
924 plan.argtypes = NULL;
926 plan.parserSetupArg = options->parserSetupArg;
927
929
930
932
934
935 return result;
936}
937
941 void *parserSetupArg,
942 int cursorOptions)
943{
946
947 if (src == NULL)
948 {
950 return NULL;
951 }
952
955 return NULL;
956
960 plan.cursor_options = cursorOptions;
961 plan.nargs = 0;
962 plan.argtypes = NULL;
963 plan.parserSetup = parserSetup;
964 plan.parserSetupArg = parserSetupArg;
965
967
968
970
972
973 return result;
974}
975
976int
978{
980
982 plan->saved || plan->oneshot)
984
985
986
987
988
989
990 plan->saved = true;
992
993 foreach(lc, plan->plancache_list)
994 {
996
998 }
999
1000 return 0;
1001}
1002
1005{
1007
1009 {
1011 return NULL;
1012 }
1013
1016 return NULL;
1017
1019
1021
1022 return newplan;
1023}
1024
1025int
1027{
1029
1032
1033
1034 foreach(lc, plan->plancache_list)
1035 {
1037
1039 }
1040
1041
1043
1044 return 0;
1045}
1046
1049{
1052
1053 if (tuple == NULL)
1054 {
1056 return NULL;
1057 }
1058
1060 {
1062 return NULL;
1063 }
1064
1066
1068
1070
1071 return ctuple;
1072}
1073
1076{
1079
1080 if (tuple == NULL || tupdesc == NULL)
1081 {
1083 return NULL;
1084 }
1085
1087 {
1089 return NULL;
1090 }
1091
1092
1093 if (tupdesc->tdtypeid == RECORDOID &&
1096
1098
1100
1102
1103 return dtup;
1104}
1105
1109{
1112 int numberOfAttributes;
1114 bool *n;
1115 int i;
1116
1117 if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)
1118 {
1120 return NULL;
1121 }
1122
1124 {
1126 return NULL;
1127 }
1128
1130
1132
1133 numberOfAttributes = rel->rd_att->natts;
1135 n = (bool *) palloc(numberOfAttributes * sizeof(bool));
1136
1137
1139
1140
1141 for (i = 0; i < natts; i++)
1142 {
1143 if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)
1144 break;
1145 v[attnum[i] - 1] = Values[i];
1147 }
1148
1149 if (i == natts)
1150 {
1152
1153
1154
1155
1156
1160 }
1161 else
1162 {
1163 mtuple = NULL;
1165 }
1166
1169
1171
1172 return mtuple;
1173}
1174
1175int
1177{
1178 int res;
1180
1181 for (res = 0; res < tupdesc->natts; res++)
1182 {
1184
1185 if (namestrcmp(&attr->attname, fname) == 0 &&
1186 !attr->attisdropped)
1187 return res + 1;
1188 }
1189
1191 if (sysatt != NULL)
1192 return sysatt->attnum;
1193
1194
1196}
1197
1198char *
1200{
1202
1204
1205 if (fnumber > tupdesc->natts || fnumber == 0 ||
1207 {
1209 return NULL;
1210 }
1211
1212 if (fnumber > 0)
1214 else
1216
1218}
1219
1220char *
1222{
1224 bool isnull;
1225 Oid typoid,
1226 foutoid;
1227 bool typisvarlena;
1228
1230
1231 if (fnumber > tupdesc->natts || fnumber == 0 ||
1233 {
1235 return NULL;
1236 }
1237
1239 if (isnull)
1240 return NULL;
1241
1242 if (fnumber > 0)
1243 typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1244 else
1246
1248
1250}
1251
1254{
1256
1257 if (fnumber > tupdesc->natts || fnumber == 0 ||
1259 {
1261 *isnull = true;
1262 return (Datum) NULL;
1263 }
1264
1265 return heap_getattr(tuple, fnumber, tupdesc, isnull);
1266}
1267
1268char *
1270{
1271 Oid typoid;
1273 char *result;
1274
1276
1277 if (fnumber > tupdesc->natts || fnumber == 0 ||
1279 {
1281 return NULL;
1282 }
1283
1284 if (fnumber > 0)
1285 typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1286 else
1288
1290
1292 {
1294 return NULL;
1295 }
1296
1299 return result;
1300}
1301
1302
1303
1304
1305
1306
1307
1310{
1312
1313 if (fnumber > tupdesc->natts || fnumber == 0 ||
1315 {
1318 }
1319
1320 if (fnumber > 0)
1321 return TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1322 else
1324}
1325
1326char *
1328{
1330}
1331
1332char *
1334{
1336}
1337
1338void *
1340{
1342 elog(ERROR, "SPI_palloc called while not connected to SPI");
1343
1345}
1346
1347void *
1349{
1350
1351 return repalloc(pointer, size);
1352}
1353
1354void
1356{
1357
1359}
1360
1363{
1366
1368 elog(ERROR, "SPI_datumTransfer called while not connected to SPI");
1369
1371
1373
1375
1376 return result;
1377}
1378
1379void
1381{
1382
1384}
1385
1386void
1388{
1389 bool found = false;
1390
1391
1392 if (tuptable == NULL)
1393 return;
1394
1395
1396
1397
1399 {
1401
1402
1404 {
1406
1408 if (tt == tuptable)
1409 {
1411 found = true;
1412 break;
1413 }
1414 }
1415 }
1416
1417
1418
1419
1420
1421
1422
1423 if (!found)
1424 {
1425 elog(WARNING, "attempt to delete invalid SPITupleTable %p", tuptable);
1426 return;
1427 }
1428
1429
1434
1435
1437}
1438
1439
1440
1441
1442
1443
1444
1448 bool read_only)
1449{
1452
1453
1456
1458
1459
1460 if (paramLI)
1462
1463 return portal;
1464}
1465
1466
1467
1468
1469
1470
1471
1474 const char *src,
1475 int nargs, Oid *argtypes,
1477 bool read_only, int cursorOptions)
1478{
1482
1483 if (src == NULL || nargs < 0)
1484 elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
1485
1486 if (nargs > 0 && (argtypes == NULL || Values == NULL))
1487 elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
1488
1491 elog(ERROR, "SPI_cursor_open_with_args called while not connected");
1492
1496 plan.cursor_options = cursorOptions;
1497 plan.nargs = nargs;
1498 plan.argtypes = argtypes;
1499 plan.parserSetup = NULL;
1500 plan.parserSetupArg = NULL;
1501
1502
1505
1507
1508
1509
1511
1512
1514
1515 return result;
1516}
1517
1518
1519
1520
1521
1522
1523
1524
1528{
1530}
1531
1532
1535 const char *src,
1537{
1540
1541 if (src == NULL || options == NULL)
1542 elog(ERROR, "SPI_cursor_parse_open called with invalid arguments");
1543
1546 elog(ERROR, "SPI_cursor_parse_open called while not connected");
1547
1551 plan.cursor_options = options->cursorOptions;
1553 {
1554 plan.parserSetup = options->params->parserSetup;
1555 plan.parserSetupArg = options->params->parserSetupArg;
1556 }
1557
1559
1560
1561
1564
1565
1567
1568 return result;
1569}
1570
1571
1572
1573
1574
1575
1576
1580{
1583 List *stmt_list;
1584 char *query_string;
1590
1591
1592
1593
1594
1596 {
1597
1598 const char *cmdtag;
1599
1602 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1603 errmsg("cannot open multi-query plan as cursor")));
1605
1606 if (plansource->commandTag == CMDTAG_SELECT)
1607 cmdtag = "SELECT INTO";
1608 else
1611 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1612
1613 errmsg("cannot open %s query as cursor", cmdtag)));
1614 }
1615
1618
1619
1621 elog(ERROR, "SPI_cursor_open called while not connected");
1622
1623
1628
1629
1630 if (name == NULL || name[0] == '\0')
1631 {
1632
1634 }
1635 else
1636 {
1637
1639 }
1640
1641
1644
1645
1646
1647
1648
1650 spicallbackarg.mode = plan->parse_mode;
1652 spierrcontext.arg = &spicallbackarg;
1655
1656
1657
1658
1659
1660
1661
1662
1665
1666 if (->saved)
1667 {
1668
1669
1670
1671
1672
1673
1678 cplan = NULL;
1679 }
1680
1681
1682
1683
1685 NULL,
1686 query_string,
1688 stmt_list,
1689 cplan,
1690 plansource);
1691
1692
1693
1694
1695
1698 {
1704 else
1706 }
1707
1708
1709
1710
1711
1712
1714 {
1719 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1720 errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
1721 errdetail("Scrollable cursors must be READ ONLY.")));
1722 }
1723
1724
1726
1727
1728
1729
1730
1731
1732
1733
1734 if (read_only)
1735 {
1737
1738 foreach(lc, stmt_list)
1739 {
1741
1744 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1745
1746 errmsg("%s is not allowed in a non-volatile function",
1748 }
1749 }
1750
1751
1752 if (read_only)
1754 else
1755 {
1758 }
1759
1760
1761
1762
1763
1764
1765 if (paramLI)
1766 {
1770 }
1771
1772
1773
1774
1775 PortalStart(portal, paramLI, 0, snapshot);
1776
1778
1779
1781
1782
1784
1785
1786 return portal;
1787}
1788
1789
1790
1791
1792
1793
1794
1797{
1799}
1800
1801
1802
1803
1804
1805
1806
1807void
1809{
1813
1814}
1815
1816
1817
1818
1819
1820
1821
1822void
1824{
1828}
1829
1830
1831
1832
1833
1834
1835
1836void
1838{
1840 direction, count,
1842
1843}
1844
1845
1846
1847
1848
1849
1850
1851void
1853{
1855}
1856
1857
1858
1859
1860
1861
1862
1863void
1865{
1867 elog(ERROR, "invalid portal in SPI cursor operation");
1868
1870}
1871
1872
1873
1874
1875
1878{
1880 argIndex < 0 || argIndex >= plan->nargs)
1881 {
1884 }
1885 return plan->argtypes[argIndex];
1886}
1887
1888
1889
1890
1891int
1893{
1895 {
1897 return -1;
1898 }
1899 return plan->nargs;
1900}
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911bool
1913{
1915
1917 {
1919 return false;
1920 }
1921
1923 {
1925 return false;
1926 }
1928
1929
1930
1931
1932
1933
1935
1936
1938 return true;
1939
1940 return false;
1941}
1942
1943
1944
1945
1946
1947
1948
1949bool
1951{
1953
1955
1956 foreach(lc, plan->plancache_list)
1957 {
1959
1961 return false;
1962 }
1963 return true;
1964}
1965
1966
1967
1968
1969
1970
1971
1972
1973const char *
1975{
1976 static char buf[64];
1977
1978 switch (code)
1979 {
1981 return "SPI_ERROR_CONNECT";
1983 return "SPI_ERROR_COPY";
1985 return "SPI_ERROR_OPUNKNOWN";
1987 return "SPI_ERROR_UNCONNECTED";
1989 return "SPI_ERROR_ARGUMENT";
1991 return "SPI_ERROR_PARAM";
1993 return "SPI_ERROR_TRANSACTION";
1995 return "SPI_ERROR_NOATTRIBUTE";
1997 return "SPI_ERROR_NOOUTFUNC";
1999 return "SPI_ERROR_TYPUNKNOWN";
2001 return "SPI_ERROR_REL_DUPLICATE";
2003 return "SPI_ERROR_REL_NOT_FOUND";
2005 return "SPI_OK_CONNECT";
2007 return "SPI_OK_FINISH";
2009 return "SPI_OK_FETCH";
2011 return "SPI_OK_UTILITY";
2013 return "SPI_OK_SELECT";
2015 return "SPI_OK_SELINTO";
2017 return "SPI_OK_INSERT";
2019 return "SPI_OK_DELETE";
2021 return "SPI_OK_UPDATE";
2023 return "SPI_OK_CURSOR";
2025 return "SPI_OK_INSERT_RETURNING";
2027 return "SPI_OK_DELETE_RETURNING";
2029 return "SPI_OK_UPDATE_RETURNING";
2031 return "SPI_OK_REWRITTEN";
2033 return "SPI_OK_REL_REGISTER";
2035 return "SPI_OK_REL_UNREGISTER";
2037 return "SPI_OK_TD_REGISTER";
2039 return "SPI_OK_MERGE";
2041 return "SPI_OK_MERGE_RETURNING";
2042 }
2043
2044 sprintf(buf, "Unrecognized SPI code %d", code);
2045 return buf;
2046}
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2060{
2062 return plan->plancache_list;
2063}
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2079{
2084
2086
2087
2088 if (plan->oneshot)
2089 return NULL;
2090
2091
2093 return NULL;
2095
2096
2098 spicallbackarg.mode = plan->parse_mode;
2100 spierrcontext.arg = &spicallbackarg;
2103
2104
2109
2110
2112
2113 return cplan;
2114}
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124void
2126{
2130
2132 elog(ERROR, "spi_dest_startup called while not connected to SPI");
2133
2135 elog(ERROR, "improper call to spi_dest_startup");
2136
2137
2138
2139 oldcxt = _SPI_procmem();
2140
2142 "SPI TupTable",
2145
2148 tuptable->tuptabcxt = tuptabcxt;
2150
2151
2152
2153
2154
2155
2157
2158
2159 tuptable->alloced = 128;
2163
2165}
2166
2167
2168
2169
2170
2171
2172bool
2174{
2177
2179 elog(ERROR, "spi_printtup called while not connected to SPI");
2180
2182 if (tuptable == NULL)
2183 elog(ERROR, "improper call to spi_printtup");
2184
2186
2188 {
2189
2191
2193 newalloced * sizeof(HeapTuple));
2194 tuptable->alloced = newalloced;
2195 }
2196
2199
2201
2202 return true;
2203}
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222static void
2224{
2225 List *raw_parsetree_list;
2226 List *plancache_list;
2230
2231
2232
2233
2234 spicallbackarg.query = src;
2235 spicallbackarg.mode = plan->parse_mode;
2237 spierrcontext.arg = &spicallbackarg;
2240
2241
2242
2243
2244 raw_parsetree_list = raw_parser(src, plan->parse_mode);
2245
2246
2247
2248
2249
2250 plancache_list = NIL;
2251
2252 foreach(list_item, raw_parsetree_list)
2253 {
2255 List *stmt_list;
2257
2258
2259
2260
2261
2263 src,
2265
2266
2267
2268
2269
2270 if (plan->parserSetup != NULL)
2271 {
2274 src,
2275 plan->parserSetup,
2276 plan->parserSetupArg,
2278 }
2279 else
2280 {
2282 src,
2283 plan->argtypes,
2284 plan->nargs,
2286 }
2287
2288
2290 stmt_list,
2291 NULL,
2292 plan->argtypes,
2293 plan->nargs,
2294 plan->parserSetup,
2295 plan->parserSetupArg,
2296 plan->cursor_options,
2297 false);
2298
2299 plancache_list = lappend(plancache_list, plansource);
2300 }
2301
2302 plan->plancache_list = plancache_list;
2303 plan->oneshot = false;
2304
2305
2306
2307
2309}
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330static void
2332{
2333 List *raw_parsetree_list;
2334 List *plancache_list;
2338
2339
2340
2341
2342 spicallbackarg.query = src;
2343 spicallbackarg.mode = plan->parse_mode;
2345 spierrcontext.arg = &spicallbackarg;
2348
2349
2350
2351
2352 raw_parsetree_list = raw_parser(src, plan->parse_mode);
2353
2354
2355
2356
2357 plancache_list = NIL;
2358
2359 foreach(list_item, raw_parsetree_list)
2360 {
2363
2365 src,
2367
2368 plancache_list = lappend(plancache_list, plansource);
2369 }
2370
2371 plan->plancache_list = plancache_list;
2372 plan->oneshot = true;
2373
2374
2375
2376
2378}
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400static int
2403 bool fire_triggers)
2404{
2405 int my_res = 0;
2406 uint64 my_processed = 0;
2408 int res = 0;
2409 bool allow_nonatomic;
2410 bool pushed_active_snap = false;
2416
2417
2418
2419
2420
2421
2422
2423 allow_nonatomic = options->allow_nonatomic &&
2425
2426
2427
2428
2429 spicallbackarg.query = NULL;
2430 spicallbackarg.mode = plan->parse_mode;
2432 spierrcontext.arg = &spicallbackarg;
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2464 {
2465
2468 {
2470 pushed_active_snap = true;
2471 }
2472 else
2473 {
2474
2476 pushed_active_snap = true;
2477 }
2478 }
2479
2480
2481
2482
2483
2484 if (->saved)
2485 plan_owner = NULL;
2486 else if (plan_owner == NULL)
2488
2489
2490
2491
2492
2493
2494
2495 if (options->must_return_tuples && plan->plancache_list == NIL)
2497 (errcode(ERRCODE_SYNTAX_ERROR),
2498 errmsg("empty query does not return tuples")));
2499
2500 foreach(lc1, plan->plancache_list)
2501 {
2503 List *stmt_list;
2505 int query_index = 0;
2506
2508
2509
2510
2511
2512 if (plan->oneshot)
2513 {
2516 List *querytree_list;
2517
2518
2519
2520
2521
2522 if (parsetree == NULL)
2523 querytree_list = NIL;
2524 else if (plan->parserSetup != NULL)
2525 {
2528 src,
2529 plan->parserSetup,
2530 plan->parserSetupArg,
2532 }
2533 else
2534 {
2536 src,
2537 plan->argtypes,
2538 plan->nargs,
2540 }
2541
2542
2544 querytree_list,
2545 NULL,
2546 plan->argtypes,
2547 plan->nargs,
2548 plan->parserSetup,
2549 plan->parserSetupArg,
2550 plan->cursor_options,
2551 false);
2552 }
2553
2554
2555
2556
2557
2558
2559
2561 {
2562
2563 const char *cmdtag;
2564
2565
2566 if (plansource->commandTag == CMDTAG_SELECT)
2567 cmdtag = "SELECT INTO";
2568 else
2571 (errcode(ERRCODE_SYNTAX_ERROR),
2572
2573 errmsg("%s query does not return tuples", cmdtag)));
2574 }
2575
2576
2577
2578
2579
2582
2584
2585
2586
2587
2588
2593 stmt_list)))))
2594 {
2595
2596
2597
2598
2599
2600
2601
2602
2603
2605
2606
2607
2608
2609
2610
2611
2612 if (->read_only && !allow_nonatomic)
2613 {
2614 if (pushed_active_snap)
2617 pushed_active_snap = true;
2618 }
2619 }
2620
2621 foreach(lc2, stmt_list)
2622 {
2624 bool canSetTag = stmt->canSetTag;
2626
2627
2628
2629
2630
2631
2632
2635
2636
2637 if (stmt->utilityStmt)
2638 {
2640 {
2642
2644 {
2646 goto fail;
2647 }
2648 }
2650 {
2652 goto fail;
2653 }
2654 }
2655
2658 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2659
2660 errmsg("%s is not allowed in a non-volatile function",
2662
2663
2664
2665
2666
2667
2668 if (->read_only && pushed_active_snap)
2669 {
2672 }
2673
2674
2675
2676
2677
2678 if (!canSetTag)
2682 else
2684
2685 if (stmt->utilityStmt == NULL)
2686 {
2689
2692 else
2694
2696 cplan,
2698 snap, crosscheck_snapshot,
2702 0);
2703
2704 res = _SPI_pquery(qdesc, fire_triggers, canSetTag ? options->tcount : 0,
2705 plansource, query_index);
2707 }
2708 else
2709 {
2712
2713
2714
2715
2716
2717 if (allow_nonatomic)
2719 else
2721
2725 true,
2726 context,
2730 &qc);
2731
2732
2735
2737
2738
2739
2740
2741
2743 {
2745
2748 else
2749 {
2750
2751
2752
2753
2757 }
2758
2759
2760
2761
2762
2765 }
2767 {
2770 }
2771 }
2772
2773
2774
2775
2776
2777
2778 if (canSetTag)
2779 {
2783 my_res = res;
2784 }
2785 else
2786 {
2789 }
2790
2791
2792
2793
2794
2795
2796
2797 if (res < 0)
2798 {
2799 my_res = res;
2800 goto fail;
2801 }
2802
2803 query_index++;
2804 }
2805
2806
2808 cplan = NULL;
2809
2810
2811
2812
2813
2814
2815 if (->read_only)
2817 }
2818
2819fail:
2820
2821
2822 if (pushed_active_snap)
2824
2825
2826 if (cplan)
2828
2829
2830
2831
2833
2834
2837
2838
2840
2841
2842
2843
2844
2845
2846 if (my_res == 0)
2848
2849 return my_res;
2850}
2851
2852
2853
2854
2858{
2860
2861 if (nargs > 0)
2862 {
2864
2865 for (int i = 0; i < nargs; i++)
2866 {
2868
2872 prm->ptype = argtypes[i];
2873 }
2874 }
2875 else
2876 paramLI = NULL;
2877 return paramLI;
2878}
2879
2880static int
2883{
2884 int operation = queryDesc->operation;
2885 int eflags;
2886 int res;
2887
2888 switch (operation)
2889 {
2892 {
2893
2895 }
2896 else
2898 break;
2902 else
2904 break;
2908 else
2910 break;
2914 else
2916 break;
2920 else
2922 break;
2923 default:
2925 }
2926
2927#ifdef SPI_EXECUTOR_STATS
2928 if (ShowExecutorStats)
2930#endif
2931
2932
2933 if (fire_triggers)
2934 eflags = 0;
2935 else
2937
2938 if (queryDesc->cplan)
2939 {
2942 }
2943 else
2944 {
2946 elog(ERROR, "ExecutorStart() failed unexpectedly");
2947 }
2948
2950
2952
2955 {
2957 elog(ERROR, "consistency check on SPI tuple count failed");
2958 }
2959
2962
2963
2964#ifdef SPI_EXECUTOR_STATS
2965 if (ShowExecutorStats)
2966 ShowUsage("SPI EXECUTOR STATS");
2967#endif
2968
2969 return res;
2970}
2971
2972
2973
2974
2975
2976
2977static void
2979{
2981 const char *query = carg->query;
2982 int syntaxerrposition;
2983
2984 if (query == NULL)
2985 return;
2986
2987
2988
2989
2990
2992 if (syntaxerrposition > 0)
2993 {
2997 }
2998 else
2999 {
3000
3001 switch (carg->mode)
3002 {
3004 errcontext("PL/pgSQL expression \"%s\"", query);
3005 break;
3009 errcontext("PL/pgSQL assignment \"%s\"", query);
3010 break;
3011 default:
3012 errcontext("SQL statement \"%s\"", query);
3013 break;
3014 }
3015 }
3016}
3017
3018
3019
3020
3021
3022
3023static void
3026{
3028
3029
3031 elog(ERROR, "invalid portal in SPI cursor operation");
3032
3033
3035 elog(ERROR, "SPI cursor operation called while not connected");
3036
3037
3042
3043
3045 direction,
3046 count,
3048
3049
3050
3051
3052
3053
3054
3055
3056
3058
3060 elog(ERROR, "consistency check on SPI tuple count failed");
3061
3062
3065
3066
3068
3069
3071}
3072
3073
3076{
3078}
3079
3082{
3084}
3085
3086
3087
3088
3089
3090
3091
3092
3093static int
3095{
3098
3099 if (use_exec)
3100 {
3101
3103
3105 }
3106
3107 return 0;
3108}
3109
3110
3111
3112
3113
3114
3115
3116
3117static int
3119{
3120 if (use_exec)
3121 {
3122
3124
3126
3128 }
3129
3130 return 0;
3131}
3132
3133static bool
3135{
3138 bool failed = false;
3139
3140 if (tuptable == NULL)
3141 failed = true;
3142 else if (processed != tuptable->numvals)
3143 failed = true;
3144
3145 return failed;
3146}
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3159{
3165
3166
3169
3171
3172
3173
3174
3175
3177 "SPI Plan",
3180
3181
3184 newplan->plancxt = plancxt;
3188 if (plan->nargs > 0)
3189 {
3192 }
3193 else
3197
3198
3199
3200
3201
3202
3203
3204 foreach(lc, plan->plancache_list)
3205 {
3207
3209
3210
3212 }
3213
3215
3216
3217 plan->plancache_list = NIL;
3218
3219 return newplan;
3220}
3221
3222
3223
3224
3227{
3232
3233
3235
3236
3237
3238
3239
3240
3242 "SPI Plan",
3245
3246
3249 newplan->plancxt = plancxt;
3253 if (plan->nargs > 0)
3254 {
3257 }
3258 else
3262
3263
3264 foreach(lc, plan->plancache_list)
3265 {
3268
3271 }
3272
3274
3275
3276
3277
3278
3279
3280 newplan->saved = true;
3282
3284 {
3286
3288 }
3289
3290 return newplan;
3291}
3292
3293
3294
3295
3298{
3299
3301
3302
3304 return NULL;
3305
3307}
3308
3309
3310
3311
3312
3313int
3315{
3317 int res;
3318
3319 if (enr == NULL || enr->md.name == NULL)
3321
3322 res = _SPI_begin_call(false);
3323 if (res < 0)
3324 return res;
3325
3327 if (match)
3329 else
3330 {
3333
3336 }
3337
3339
3340 return res;
3341}
3342
3343
3344
3345
3346
3347int
3349{
3351 int res;
3352
3353 if (name == NULL)
3355
3356 res = _SPI_begin_call(false);
3357 if (res < 0)
3358 return res;
3359
3361 if (match)
3362 {
3365 }
3366 else
3368
3370
3371 return res;
3372}
3373
3374
3375
3376
3377
3378
3379
3380int
3382{
3383 if (tdata == NULL)
3385
3387 {
3390 int rc;
3391
3400 return rc;
3401 }
3402
3404 {
3407 int rc;
3408
3417 return rc;
3418 }
3419
3421}
List * raw_parser(const char *str, RawParseMode mode)
static bool Nulls[MAXATTR]
#define InvalidSubTransactionId
void InitializeQueryCompletion(QueryCompletion *qc)
const char * GetCommandTagName(CommandTag commandTag)
Datum datumTransfer(Datum value, bool typByVal, int typLen)
DestReceiver * CreateDestReceiver(CommandDest dest)
DestReceiver * None_Receiver
int internalerrquery(const char *query)
int internalerrposition(int cursorpos)
int errdetail(const char *fmt,...)
ErrorContextCallback * error_context_stack
void ReThrowError(ErrorData *edata)
ErrorData * CopyErrorData(void)
void FlushErrorState(void)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
int errposition(int cursorpos)
#define ereport(elevel,...)
bool ExecSupportsBackwardScan(Plan *node)
bool ExecutorStart(QueryDesc *queryDesc, int eflags)
void ExecutorStartCachedPlan(QueryDesc *queryDesc, int eflags, CachedPlanSource *plansource, int query_index)
void ExecutorEnd(QueryDesc *queryDesc)
void ExecutorFinish(QueryDesc *queryDesc)
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
#define EXEC_FLAG_SKIP_TRIGGERS
char * OidOutputFunctionCall(Oid functionId, Datum val)
#define DatumGetHeapTupleHeader(X)
Assert(PointerIsAligned(start, uint64))
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)
HeapTuple heap_copytuple(HeapTuple tuple)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
static void * GETSTRUCT(const HeapTupleData *tuple)
static void slist_delete_current(slist_mutable_iter *iter)
#define slist_foreach_modify(iter, lhead)
static void slist_init(slist_head *head)
static void slist_push_head(slist_head *head, slist_node *node)
#define slist_container(type, membername, ptr)
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
char * get_namespace_name(Oid nspid)
char * MemoryContextStrdup(MemoryContext context, const char *string)
void * MemoryContextAlloc(MemoryContext context, Size size)
void MemoryContextReset(MemoryContext context)
MemoryContext TopTransactionContext
char * pstrdup(const char *in)
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext TopMemoryContext
MemoryContext CurrentMemoryContext
MemoryContext CacheMemoryContext
void MemoryContextDelete(MemoryContext context)
void * repalloc_huge(void *pointer, Size size)
MemoryContext PortalContext
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define ALLOCSET_SMALL_SIZES
int namestrcmp(Name name, const char *str)
#define IsA(nodeptr, _type_)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
ParamListInfo makeParamList(int numParams)
ParamListInfo copyParamList(ParamListInfo from)
void(* ParserSetupHook)(struct ParseState *pstate, void *arg)
#define CURSOR_OPT_SCROLL
#define CURSOR_OPT_PARALLEL_OK
#define CURSOR_OPT_NO_SCROLL
@ RAW_PARSE_PLPGSQL_ASSIGN2
@ RAW_PARSE_PLPGSQL_ASSIGN1
@ RAW_PARSE_PLPGSQL_ASSIGN3
FormData_pg_attribute * Form_pg_attribute
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define linitial_node(type, l)
FormData_pg_type * Form_pg_type
void CachedPlanSetParentContext(CachedPlanSource *plansource, MemoryContext newcontext)
bool CachedPlanIsValid(CachedPlanSource *plansource)
void DropCachedPlan(CachedPlanSource *plansource)
void SaveCachedPlan(CachedPlanSource *plansource)
void CompleteCachedPlan(CachedPlanSource *plansource, List *querytree_list, MemoryContext querytree_context, Oid *param_types, int num_params, ParserSetupHook parserSetup, void *parserSetupArg, int cursor_options, bool fixed_result)
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
CachedPlanSource * CreateOneShotCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
CachedPlanSource * CopyCachedPlan(CachedPlanSource *plansource)
void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, CommandTag commandTag, List *stmts, CachedPlan *cplan, CachedPlanSource *plansource)
Portal CreateNewPortal(void)
void HoldPinnedPortals(void)
void PortalDrop(Portal portal, bool isTopCommit)
Portal GetPortalByName(const char *name)
Portal CreatePortal(const char *name, bool allowDup, bool dupSilent)
void ForgetPortalSnapshots(void)
List * pg_analyze_and_rewrite_withcb(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
void ShowUsage(const char *title)
static Datum ObjectIdGetDatum(Oid X)
void FreeQueryDesc(QueryDesc *qdesc)
bool PlannedStmtRequiresSnapshot(PlannedStmt *pstmt)
void EnsurePortalSnapshotExists(void)
void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, CachedPlan *cplan, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
EphemeralNamedRelation get_ENR(QueryEnvironment *queryEnv, const char *name)
void unregister_ENR(QueryEnvironment *queryEnv, const char *name)
QueryEnvironment * create_queryEnv(void)
void register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)
#define RelationGetRelationName(relation)
#define RelationGetNamespace(relation)
ResourceOwner CurrentResourceOwner
Snapshot GetTransactionSnapshot(void)
void PushActiveSnapshot(Snapshot snapshot)
void UpdateActiveSnapshotCommandId(void)
bool ActiveSnapshotSet(void)
void PopActiveSnapshot(void)
void PushCopiedSnapshot(Snapshot snapshot)
Snapshot GetActiveSnapshot(void)
void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)
List * SPI_plan_get_plan_sources(SPIPlanPtr plan)
SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, int cursorOptions)
static int _SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options, Snapshot snapshot, Snapshot crosscheck_snapshot, bool fire_triggers)
int SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params, bool read_only, long tcount)
bool spi_printtup(TupleTableSlot *slot, DestReceiver *self)
static void _SPI_error_callback(void *arg)
static int _SPI_connected
void SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count)
static SPIPlanPtr _SPI_save_plan(SPIPlanPtr plan)
void SPI_cursor_move(Portal portal, bool forward, long count)
void SPI_freetuple(HeapTuple tuple)
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
void spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
static int _SPI_end_call(bool use_exec)
bool SPI_plan_is_valid(SPIPlanPtr plan)
void SPI_commit_and_chain(void)
bool SPI_is_cursor_plan(SPIPlanPtr plan)
char * SPI_gettype(TupleDesc tupdesc, int fnumber)
void * SPI_repalloc(void *pointer, Size size)
SPIPlanPtr SPI_prepare_extended(const char *src, const SPIPrepareOptions *options)
Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber)
static _SPI_connection * _SPI_stack
HeapTupleHeader SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc)
int SPI_freeplan(SPIPlanPtr plan)
const char * SPI_result_code_string(int code)
void SPI_rollback_and_chain(void)
SPITupleTable * SPI_tuptable
Portal SPI_cursor_find(const char *name)
int SPI_unregister_relation(const char *name)
bool SPI_inside_nonatomic_context(void)
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
int SPI_execute_snapshot(SPIPlanPtr plan, Datum *Values, const char *Nulls, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, long tcount)
int SPI_execute_plan_extended(SPIPlanPtr plan, const SPIExecuteOptions *options)
SPIPlanPtr SPI_prepare_params(const char *src, ParserSetupHook parserSetup, void *parserSetupArg, int cursorOptions)
SPIPlanPtr SPI_saveplan(SPIPlanPtr plan)
void SPI_cursor_fetch(Portal portal, bool forward, long count)
Portal SPI_cursor_parse_open(const char *name, const char *src, const SPIParseOpenOptions *options)
int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
static _SPI_connection * _SPI_current
Datum SPI_datumTransfer(Datum value, bool typByVal, int typLen)
CachedPlan * SPI_plan_get_cached_plan(SPIPlanPtr plan)
int SPI_register_trigger_data(TriggerData *tdata)
static int _SPI_stack_depth
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan, ParamListInfo params, bool read_only)
Portal SPI_cursor_open_with_args(const char *name, const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, int cursorOptions)
void SPI_freetuptable(SPITupleTable *tuptable)
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
int SPI_exec(const char *src, long tcount)
static int _SPI_begin_call(bool use_exec)
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
int SPI_register_relation(EphemeralNamedRelation enr)
HeapTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum, Datum *Values, const char *Nulls)
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
int SPI_keepplan(SPIPlanPtr plan)
void SPI_cursor_close(Portal portal)
void SPI_pfree(void *pointer)
int SPI_connect_ext(int options)
int SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
char * SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
void SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count)
char * SPI_getnspname(Relation rel)
static void _SPI_commit(bool chain)
int SPI_execute_extended(const char *src, const SPIExecuteOptions *options)
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount, CachedPlanSource *plansource, int query_index)
void * SPI_palloc(Size size)
static bool _SPI_checktuples(void)
static EphemeralNamedRelation _SPI_find_ENR_by_name(const char *name)
static MemoryContext _SPI_execmem(void)
static MemoryContext _SPI_procmem(void)
int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, long tcount)
void SPI_start_transaction(void)
HeapTuple SPI_copytuple(HeapTuple tuple)
int SPI_getargcount(SPIPlanPtr plan)
struct SPICallbackArg SPICallbackArg
void AtEOXact_SPI(bool isCommit)
int SPI_execute(const char *src, bool read_only, long tcount)
Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
static void _SPI_rollback(bool chain)
char * SPI_getrelname(Relation rel)
char * SPI_fname(TupleDesc tupdesc, int fnumber)
Oid SPI_getargtypeid(SPIPlanPtr plan, int argIndex)
static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)
#define SPI_ERROR_TRANSACTION
#define SPI_ERROR_REL_NOT_FOUND
#define SPI_ERROR_REL_DUPLICATE
#define SPI_OPT_NONATOMIC
#define SPI_OK_TD_REGISTER
#define SPI_OK_REL_REGISTER
#define SPI_ERROR_OPUNKNOWN
#define SPI_OK_UPDATE_RETURNING
#define SPI_ERROR_UNCONNECTED
#define SPI_OK_REL_UNREGISTER
#define SPI_ERROR_ARGUMENT
#define SPI_ERROR_NOATTRIBUTE
#define SPI_OK_INSERT_RETURNING
#define SPI_ERROR_NOOUTFUNC
#define SPI_OK_DELETE_RETURNING
struct _SPI_plan * SPIPlanPtr
#define SPI_ERROR_TYPUNKNOWN
#define SPI_OK_MERGE_RETURNING
#define SPI_ERROR_CONNECT
struct CachedPlan * gplan
const char * query_string
struct RawStmt * raw_parse_tree
EphemeralNamedRelationMetadataData md
struct ErrorContextCallback * previous
void(* callback)(void *arg)
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
QueryEnvironment * queryEnv
MemoryContext portalContext
PlannedStmt * plannedstmt
Tuplestorestate * tg_oldtable
Tuplestorestate * tg_newtable
SubTransactionId connectSubid
SPITupleTable * outer_tuptable
QueryEnvironment * queryEnv
SubTransactionId execSubid
ParserSetupHook parserSetup
#define FirstLowInvalidHeapAttributeNumber
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
int64 tuplestore_tuple_count(Tuplestorestate *state)
static HeapTuple ExecCopySlotHeapTuple(TupleTableSlot *slot)
void assign_record_type_typmod(TupleDesc tupDesc)
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
bool CommandIsReadOnly(PlannedStmt *pstmt)
CommandTag CreateCommandTag(Node *parsetree)
static const char * CreateCommandName(Node *parsetree)
@ PROCESS_UTILITY_QUERY_NONATOMIC
void SaveTransactionCharacteristics(SavedTransactionCharacteristics *s)
void RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)
SubTransactionId GetCurrentSubTransactionId(void)
void CommandCounterIncrement(void)
void StartTransactionCommand(void)
bool IsSubTransaction(void)
void CommitTransactionCommand(void)
void AbortCurrentTransaction(void)