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
74
76
80
83
89
90
91
92
93int
95{
97}
98
99int
101{
102 int newdepth;
103
104
106 {
108 elog(ERROR, "SPI stack corrupted");
109 newdepth = 16;
114 }
115 else
116 {
118 elog(ERROR, "SPI stack corrupted");
120 {
126 }
127 }
128
129
132
147
148
149
150
151
152
153
154
155
156
157
158
159
160
162 "SPI Proc",
165 "SPI Exec",
167
169
170
171
172
173
177
179}
180
181int
183{
184 int res;
185
186 res = _SPI_begin_call(false);
187 if (res < 0)
188 return res;
189
190
192
193
198
199
200
201
202
206
207
211 else
213
215}
216
217
218
219
220
221void
223{
224}
225
226static void
228{
231
232
233
234
235
236
237
240 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
241 errmsg("invalid transaction termination")));
242
243
244
245
246
247
248
249
250
251
252
255 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
256 errmsg("cannot commit while a subtransaction is active")));
257
258 if (chain)
260
261
263 {
264
266
267
268
269
270
271
273
274
276
277
279
280
282 if (chain)
284
286
288 }
290 {
292
293
297
298
299
300
301
303
304
306 if (chain)
308
310
312
313
315 }
317}
318
319void
321{
323}
324
325void
327{
329}
330
331static void
333{
336
337
340 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
341 errmsg("invalid transaction termination")));
342
343
346 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
347 errmsg("cannot roll back while a subtransaction is active")));
348
349 if (chain)
351
352
354 {
355
357
358
359
360
361
362
363
365
366
368
369
371
372
374 if (chain)
376
378
380 }
382 {
384
385
389
390
391
392
393
394
396
397
399 if (chain)
401
403
405
406
408 }
410}
411
412void
414{
416}
417
418void
420{
422}
423
424
425
426
427void
429{
430 bool found = false;
431
432
433
434
435
437 {
439
441 break;
442
443 found = true;
444
445
446
447
448
449
450
451
452
453
454
455
459
463 else
465 }
466
467
468 if (found && isCommit)
470 (errcode(ERRCODE_WARNING),
471 errmsg("transaction left non-empty SPI stack"),
472 errhint("Check for missing \"SPI_finish\" calls.")));
473}
474
475
476
477
478
479
480
481void
483{
484 bool found = false;
485
487 {
489
490 if (connection->connectSubid != mySubid)
491 break;
492
494 break;
495
496 found = true;
497
498
499
500
502 {
505 }
507 {
510 }
511
512
513
514
515
516
520
524 else
526 }
527
528 if (found && isCommit)
530 (errcode(ERRCODE_WARNING),
531 errmsg("subtransaction left non-empty SPI stack"),
532 errhint("Check for missing \"SPI_finish\" calls.")));
533
534
535
536
537
539 {
541
542
543
544
545
547 {
550 }
551
552
554 {
556
558 if (tuptable->subid >= mySubid)
559 {
560
561
562
563
564
565
572 }
573 }
574 }
575}
576
577
578
579
580bool
582{
584 return false;
585
587 return false;
589 return false;
590 return true;
591}
592
593
594
595int
596SPI_execute(const char *src, bool read_only, long tcount)
597{
600 int res;
601
602 if (src == NULL || tcount < 0)
604
606 if (res < 0)
607 return res;
608
613
615
617 options.read_only = read_only;
619
622 true);
623
625 return res;
626}
627
628
629int
631{
633}
634
635
636int
639{
640 int res;
642
643 if (src == NULL || options == NULL)
645
647 if (res < 0)
648 return res;
649
655 {
656 plan.parserSetup = options->params->parserSetup;
657 plan.parserSetupArg = options->params->parserSetupArg;
658 }
659
661
664 true);
665
667 return res;
668}
669
670
671int
673 bool read_only, long tcount)
674{
676 int res;
677
680
681 if (plan->nargs > 0 && Values == NULL)
683
685 if (res < 0)
686 return res;
687
691 options.read_only = read_only;
693
696 true);
697
699 return res;
700}
701
702
703int
705{
707}
708
709
710int
713{
714 int res;
715
718
720 if (res < 0)
721 return res;
722
725 true);
726
728 return res;
729}
730
731
732int
734 bool read_only, long tcount)
735{
737 int res;
738
741
743 if (res < 0)
744 return res;
745
748 options.read_only = read_only;
750
753 true);
754
756 return res;
757}
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772int
776 bool read_only, bool fire_triggers, long tcount)
777{
779 int res;
780
783
784 if (plan->nargs > 0 && Values == NULL)
786
788 if (res < 0)
789 return res;
790
794 options.read_only = read_only;
796
798 snapshot, crosscheck_snapshot,
799 fire_triggers);
800
802 return res;
803}
804
805
806
807
808
809
810
811int
813 int nargs, Oid *argtypes,
815 bool read_only, long tcount)
816{
817 int res;
821
822 if (src == NULL || nargs < 0 || tcount < 0)
824
825 if (nargs > 0 && (argtypes == NULL || Values == NULL))
827
829 if (res < 0)
830 return res;
831
836 plan.nargs = nargs;
837 plan.argtypes = argtypes;
838 plan.parserSetup = NULL;
839 plan.parserSetupArg = NULL;
840
843
845
847 options.params = paramLI;
848 options.read_only = read_only;
850
853 true);
854
856 return res;
857}
858
861{
863}
864
867 int cursorOptions)
868{
871
872 if (src == NULL || nargs < 0 || (nargs > 0 && argtypes == NULL))
873 {
875 return NULL;
876 }
877
880 return NULL;
881
885 plan.cursor_options = cursorOptions;
886 plan.nargs = nargs;
887 plan.argtypes = argtypes;
888 plan.parserSetup = NULL;
889 plan.parserSetupArg = NULL;
890
892
893
895
897
898 return result;
899}
900
904{
907
908 if (src == NULL || options == NULL)
909 {
911 return NULL;
912 }
913
916 return NULL;
917
921 plan.cursor_options = options->cursorOptions;
922 plan.nargs = 0;
923 plan.argtypes = NULL;
925 plan.parserSetupArg = options->parserSetupArg;
926
928
929
931
933
934 return result;
935}
936
940 void *parserSetupArg,
941 int cursorOptions)
942{
945
946 if (src == NULL)
947 {
949 return NULL;
950 }
951
954 return NULL;
955
959 plan.cursor_options = cursorOptions;
960 plan.nargs = 0;
961 plan.argtypes = NULL;
962 plan.parserSetup = parserSetup;
963 plan.parserSetupArg = parserSetupArg;
964
966
967
969
971
972 return result;
973}
974
975int
977{
979
981 plan->saved || plan->oneshot)
983
984
985
986
987
988
989 plan->saved = true;
991
992 foreach(lc, plan->plancache_list)
993 {
995
997 }
998
999 return 0;
1000}
1001
1004{
1006
1008 {
1010 return NULL;
1011 }
1012
1015 return NULL;
1016
1018
1020
1021 return newplan;
1022}
1023
1024int
1026{
1028
1031
1032
1033 foreach(lc, plan->plancache_list)
1034 {
1036
1038 }
1039
1040
1042
1043 return 0;
1044}
1045
1048{
1051
1052 if (tuple == NULL)
1053 {
1055 return NULL;
1056 }
1057
1059 {
1061 return NULL;
1062 }
1063
1065
1067
1069
1070 return ctuple;
1071}
1072
1075{
1078
1079 if (tuple == NULL || tupdesc == NULL)
1080 {
1082 return NULL;
1083 }
1084
1086 {
1088 return NULL;
1089 }
1090
1091
1092 if (tupdesc->tdtypeid == RECORDOID &&
1095
1097
1099
1101
1102 return dtup;
1103}
1104
1108{
1111 int numberOfAttributes;
1113 bool *n;
1114 int i;
1115
1116 if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)
1117 {
1119 return NULL;
1120 }
1121
1123 {
1125 return NULL;
1126 }
1127
1129
1131
1132 numberOfAttributes = rel->rd_att->natts;
1134 n = (bool *) palloc(numberOfAttributes * sizeof(bool));
1135
1136
1138
1139
1140 for (i = 0; i < natts; i++)
1141 {
1142 if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)
1143 break;
1144 v[attnum[i] - 1] = Values[i];
1146 }
1147
1148 if (i == natts)
1149 {
1151
1152
1153
1154
1155
1159 }
1160 else
1161 {
1162 mtuple = NULL;
1164 }
1165
1168
1170
1171 return mtuple;
1172}
1173
1174int
1176{
1177 int res;
1179
1180 for (res = 0; res < tupdesc->natts; res++)
1181 {
1183
1184 if (namestrcmp(&attr->attname, fname) == 0 &&
1185 !attr->attisdropped)
1186 return res + 1;
1187 }
1188
1190 if (sysatt != NULL)
1191 return sysatt->attnum;
1192
1193
1195}
1196
1197char *
1199{
1201
1203
1204 if (fnumber > tupdesc->natts || fnumber == 0 ||
1206 {
1208 return NULL;
1209 }
1210
1211 if (fnumber > 0)
1213 else
1215
1217}
1218
1219char *
1221{
1223 bool isnull;
1224 Oid typoid,
1225 foutoid;
1226 bool typisvarlena;
1227
1229
1230 if (fnumber > tupdesc->natts || fnumber == 0 ||
1232 {
1234 return NULL;
1235 }
1236
1238 if (isnull)
1239 return NULL;
1240
1241 if (fnumber > 0)
1242 typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1243 else
1245
1247
1249}
1250
1253{
1255
1256 if (fnumber > tupdesc->natts || fnumber == 0 ||
1258 {
1260 *isnull = true;
1261 return (Datum) NULL;
1262 }
1263
1264 return heap_getattr(tuple, fnumber, tupdesc, isnull);
1265}
1266
1267char *
1269{
1270 Oid typoid;
1272 char *result;
1273
1275
1276 if (fnumber > tupdesc->natts || fnumber == 0 ||
1278 {
1280 return NULL;
1281 }
1282
1283 if (fnumber > 0)
1284 typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1285 else
1287
1289
1291 {
1293 return NULL;
1294 }
1295
1298 return result;
1299}
1300
1301
1302
1303
1304
1305
1306
1309{
1311
1312 if (fnumber > tupdesc->natts || fnumber == 0 ||
1314 {
1317 }
1318
1319 if (fnumber > 0)
1320 return TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1321 else
1323}
1324
1325char *
1327{
1329}
1330
1331char *
1333{
1335}
1336
1337void *
1339{
1341 elog(ERROR, "SPI_palloc called while not connected to SPI");
1342
1344}
1345
1346void *
1348{
1349
1350 return repalloc(pointer, size);
1351}
1352
1353void
1355{
1356
1358}
1359
1362{
1365
1367 elog(ERROR, "SPI_datumTransfer called while not connected to SPI");
1368
1370
1372
1374
1375 return result;
1376}
1377
1378void
1380{
1381
1383}
1384
1385void
1387{
1388 bool found = false;
1389
1390
1391 if (tuptable == NULL)
1392 return;
1393
1394
1395
1396
1398 {
1400
1401
1403 {
1405
1407 if (tt == tuptable)
1408 {
1410 found = true;
1411 break;
1412 }
1413 }
1414 }
1415
1416
1417
1418
1419
1420
1421
1422 if (!found)
1423 {
1424 elog(WARNING, "attempt to delete invalid SPITupleTable %p", tuptable);
1425 return;
1426 }
1427
1428
1433
1434
1436}
1437
1438
1439
1440
1441
1442
1443
1447 bool read_only)
1448{
1451
1452
1455
1457
1458
1459 if (paramLI)
1461
1462 return portal;
1463}
1464
1465
1466
1467
1468
1469
1470
1473 const char *src,
1474 int nargs, Oid *argtypes,
1476 bool read_only, int cursorOptions)
1477{
1481
1482 if (src == NULL || nargs < 0)
1483 elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
1484
1485 if (nargs > 0 && (argtypes == NULL || Values == NULL))
1486 elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
1487
1490 elog(ERROR, "SPI_cursor_open_with_args called while not connected");
1491
1495 plan.cursor_options = cursorOptions;
1496 plan.nargs = nargs;
1497 plan.argtypes = argtypes;
1498 plan.parserSetup = NULL;
1499 plan.parserSetupArg = NULL;
1500
1501
1504
1506
1507
1508
1510
1511
1513
1514 return result;
1515}
1516
1517
1518
1519
1520
1521
1522
1523
1527{
1529}
1530
1531
1534 const char *src,
1536{
1539
1540 if (src == NULL || options == NULL)
1541 elog(ERROR, "SPI_cursor_parse_open called with invalid arguments");
1542
1545 elog(ERROR, "SPI_cursor_parse_open called while not connected");
1546
1550 plan.cursor_options = options->cursorOptions;
1552 {
1553 plan.parserSetup = options->params->parserSetup;
1554 plan.parserSetupArg = options->params->parserSetupArg;
1555 }
1556
1558
1559
1560
1563
1564
1566
1567 return result;
1568}
1569
1570
1571
1572
1573
1574
1575
1579{
1582 List *stmt_list;
1583 char *query_string;
1589
1590
1591
1592
1593
1595 {
1596
1597 const char *cmdtag;
1598
1601 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1602 errmsg("cannot open multi-query plan as cursor")));
1604
1605 if (plansource->commandTag == CMDTAG_SELECT)
1606 cmdtag = "SELECT INTO";
1607 else
1610 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1611
1612 errmsg("cannot open %s query as cursor", cmdtag)));
1613 }
1614
1617
1618
1620 elog(ERROR, "SPI_cursor_open called while not connected");
1621
1622
1627
1628
1629 if (name == NULL || name[0] == '\0')
1630 {
1631
1633 }
1634 else
1635 {
1636
1638 }
1639
1640
1643
1644
1645
1646
1647
1649 spicallbackarg.mode = plan->parse_mode;
1651 spierrcontext.arg = &spicallbackarg;
1654
1655
1656
1657
1658
1659
1660
1661
1664
1665 if (->saved)
1666 {
1667
1668
1669
1670
1671
1672
1677 cplan = NULL;
1678 }
1679
1680
1681
1682
1684 NULL,
1685 query_string,
1687 stmt_list,
1688 cplan);
1689
1690
1691
1692
1693
1696 {
1702 else
1704 }
1705
1706
1707
1708
1709
1710
1712 {
1717 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1718 errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
1719 errdetail("Scrollable cursors must be READ ONLY.")));
1720 }
1721
1722
1724
1725
1726
1727
1728
1729
1730
1731
1732 if (read_only)
1733 {
1735
1736 foreach(lc, stmt_list)
1737 {
1739
1742 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1743
1744 errmsg("%s is not allowed in a non-volatile function",
1746 }
1747 }
1748
1749
1750 if (read_only)
1752 else
1753 {
1756 }
1757
1758
1759
1760
1761
1762
1763 if (paramLI)
1764 {
1768 }
1769
1770
1771
1772
1773 PortalStart(portal, paramLI, 0, snapshot);
1774
1776
1777
1779
1780
1782
1783
1784 return portal;
1785}
1786
1787
1788
1789
1790
1791
1792
1795{
1797}
1798
1799
1800
1801
1802
1803
1804
1805void
1807{
1811
1812}
1813
1814
1815
1816
1817
1818
1819
1820void
1822{
1826}
1827
1828
1829
1830
1831
1832
1833
1834void
1836{
1838 direction, count,
1840
1841}
1842
1843
1844
1845
1846
1847
1848
1849void
1851{
1853}
1854
1855
1856
1857
1858
1859
1860
1861void
1863{
1865 elog(ERROR, "invalid portal in SPI cursor operation");
1866
1868}
1869
1870
1871
1872
1873
1876{
1878 argIndex < 0 || argIndex >= plan->nargs)
1879 {
1882 }
1883 return plan->argtypes[argIndex];
1884}
1885
1886
1887
1888
1889int
1891{
1893 {
1895 return -1;
1896 }
1897 return plan->nargs;
1898}
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909bool
1911{
1913
1915 {
1917 return false;
1918 }
1919
1921 {
1923 return false;
1924 }
1926
1927
1928
1929
1930
1931
1933
1934
1936 return true;
1937
1938 return false;
1939}
1940
1941
1942
1943
1944
1945
1946
1947bool
1949{
1951
1953
1954 foreach(lc, plan->plancache_list)
1955 {
1957
1959 return false;
1960 }
1961 return true;
1962}
1963
1964
1965
1966
1967
1968
1969
1970
1971const char *
1973{
1974 static char buf[64];
1975
1976 switch (code)
1977 {
1979 return "SPI_ERROR_CONNECT";
1981 return "SPI_ERROR_COPY";
1983 return "SPI_ERROR_OPUNKNOWN";
1985 return "SPI_ERROR_UNCONNECTED";
1987 return "SPI_ERROR_ARGUMENT";
1989 return "SPI_ERROR_PARAM";
1991 return "SPI_ERROR_TRANSACTION";
1993 return "SPI_ERROR_NOATTRIBUTE";
1995 return "SPI_ERROR_NOOUTFUNC";
1997 return "SPI_ERROR_TYPUNKNOWN";
1999 return "SPI_ERROR_REL_DUPLICATE";
2001 return "SPI_ERROR_REL_NOT_FOUND";
2003 return "SPI_OK_CONNECT";
2005 return "SPI_OK_FINISH";
2007 return "SPI_OK_FETCH";
2009 return "SPI_OK_UTILITY";
2011 return "SPI_OK_SELECT";
2013 return "SPI_OK_SELINTO";
2015 return "SPI_OK_INSERT";
2017 return "SPI_OK_DELETE";
2019 return "SPI_OK_UPDATE";
2021 return "SPI_OK_CURSOR";
2023 return "SPI_OK_INSERT_RETURNING";
2025 return "SPI_OK_DELETE_RETURNING";
2027 return "SPI_OK_UPDATE_RETURNING";
2029 return "SPI_OK_REWRITTEN";
2031 return "SPI_OK_REL_REGISTER";
2033 return "SPI_OK_REL_UNREGISTER";
2035 return "SPI_OK_TD_REGISTER";
2037 return "SPI_OK_MERGE";
2039 return "SPI_OK_MERGE_RETURNING";
2040 }
2041
2042 sprintf(buf, "Unrecognized SPI code %d", code);
2043 return buf;
2044}
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2058{
2060 return plan->plancache_list;
2061}
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2077{
2082
2084
2085
2086 if (plan->oneshot)
2087 return NULL;
2088
2089
2091 return NULL;
2093
2094
2096 spicallbackarg.mode = plan->parse_mode;
2098 spierrcontext.arg = &spicallbackarg;
2101
2102
2107
2108
2110
2111 return cplan;
2112}
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122void
2124{
2128
2130 elog(ERROR, "spi_dest_startup called while not connected to SPI");
2131
2133 elog(ERROR, "improper call to spi_dest_startup");
2134
2135
2136
2137 oldcxt = _SPI_procmem();
2138
2140 "SPI TupTable",
2143
2146 tuptable->tuptabcxt = tuptabcxt;
2148
2149
2150
2151
2152
2153
2155
2156
2157 tuptable->alloced = 128;
2161
2163}
2164
2165
2166
2167
2168
2169
2170bool
2172{
2175
2177 elog(ERROR, "spi_printtup called while not connected to SPI");
2178
2180 if (tuptable == NULL)
2181 elog(ERROR, "improper call to spi_printtup");
2182
2184
2186 {
2187
2189
2191 newalloced * sizeof(HeapTuple));
2192 tuptable->alloced = newalloced;
2193 }
2194
2197
2199
2200 return true;
2201}
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220static void
2222{
2223 List *raw_parsetree_list;
2224 List *plancache_list;
2228
2229
2230
2231
2232 spicallbackarg.query = src;
2233 spicallbackarg.mode = plan->parse_mode;
2235 spierrcontext.arg = &spicallbackarg;
2238
2239
2240
2241
2242 raw_parsetree_list = raw_parser(src, plan->parse_mode);
2243
2244
2245
2246
2247
2248 plancache_list = NIL;
2249
2250 foreach(list_item, raw_parsetree_list)
2251 {
2253 List *stmt_list;
2255
2256
2257
2258
2259
2261 src,
2263
2264
2265
2266
2267
2268 if (plan->parserSetup != NULL)
2269 {
2272 src,
2273 plan->parserSetup,
2274 plan->parserSetupArg,
2276 }
2277 else
2278 {
2280 src,
2281 plan->argtypes,
2282 plan->nargs,
2284 }
2285
2286
2288 stmt_list,
2289 NULL,
2290 plan->argtypes,
2291 plan->nargs,
2292 plan->parserSetup,
2293 plan->parserSetupArg,
2294 plan->cursor_options,
2295 false);
2296
2297 plancache_list = lappend(plancache_list, plansource);
2298 }
2299
2300 plan->plancache_list = plancache_list;
2301 plan->oneshot = false;
2302
2303
2304
2305
2307}
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328static void
2330{
2331 List *raw_parsetree_list;
2332 List *plancache_list;
2336
2337
2338
2339
2340 spicallbackarg.query = src;
2341 spicallbackarg.mode = plan->parse_mode;
2343 spierrcontext.arg = &spicallbackarg;
2346
2347
2348
2349
2350 raw_parsetree_list = raw_parser(src, plan->parse_mode);
2351
2352
2353
2354
2355 plancache_list = NIL;
2356
2357 foreach(list_item, raw_parsetree_list)
2358 {
2361
2363 src,
2365
2366 plancache_list = lappend(plancache_list, plansource);
2367 }
2368
2369 plan->plancache_list = plancache_list;
2370 plan->oneshot = true;
2371
2372
2373
2374
2376}
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398static int
2401 bool fire_triggers)
2402{
2403 int my_res = 0;
2404 uint64 my_processed = 0;
2406 int res = 0;
2407 bool allow_nonatomic;
2408 bool pushed_active_snap = false;
2414
2415
2416
2417
2418
2419
2420
2421 allow_nonatomic = options->allow_nonatomic &&
2423
2424
2425
2426
2427 spicallbackarg.query = NULL;
2428 spicallbackarg.mode = plan->parse_mode;
2430 spierrcontext.arg = &spicallbackarg;
2433
2434
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
2462 {
2463
2466 {
2468 pushed_active_snap = true;
2469 }
2470 else
2471 {
2472
2474 pushed_active_snap = true;
2475 }
2476 }
2477
2478
2479
2480
2481
2482 if (->saved)
2483 plan_owner = NULL;
2484 else if (plan_owner == NULL)
2486
2487
2488
2489
2490
2491
2492
2493 if (options->must_return_tuples && plan->plancache_list == NIL)
2495 (errcode(ERRCODE_SYNTAX_ERROR),
2496 errmsg("empty query does not return tuples")));
2497
2498 foreach(lc1, plan->plancache_list)
2499 {
2501 List *stmt_list;
2503
2505
2506
2507
2508
2509 if (plan->oneshot)
2510 {
2513 List *querytree_list;
2514
2515
2516
2517
2518
2519 if (parsetree == NULL)
2520 querytree_list = NIL;
2521 else if (plan->parserSetup != NULL)
2522 {
2525 src,
2526 plan->parserSetup,
2527 plan->parserSetupArg,
2529 }
2530 else
2531 {
2533 src,
2534 plan->argtypes,
2535 plan->nargs,
2537 }
2538
2539
2541 querytree_list,
2542 NULL,
2543 plan->argtypes,
2544 plan->nargs,
2545 plan->parserSetup,
2546 plan->parserSetupArg,
2547 plan->cursor_options,
2548 false);
2549 }
2550
2551
2552
2553
2554
2555
2556
2558 {
2559
2560 const char *cmdtag;
2561
2562
2563 if (plansource->commandTag == CMDTAG_SELECT)
2564 cmdtag = "SELECT INTO";
2565 else
2568 (errcode(ERRCODE_SYNTAX_ERROR),
2569
2570 errmsg("%s query does not return tuples", cmdtag)));
2571 }
2572
2573
2574
2575
2576
2579
2581
2582
2583
2584
2585
2590 stmt_list)))))
2591 {
2592
2593
2594
2595
2596
2597
2598
2599
2600
2602
2603
2604
2605
2606
2607
2608
2609 if (->read_only && !allow_nonatomic)
2610 {
2611 if (pushed_active_snap)
2614 pushed_active_snap = true;
2615 }
2616 }
2617
2618 foreach(lc2, stmt_list)
2619 {
2621 bool canSetTag = stmt->canSetTag;
2623
2624
2625
2626
2627
2628
2629
2632
2633
2634 if (stmt->utilityStmt)
2635 {
2637 {
2639
2641 {
2643 goto fail;
2644 }
2645 }
2647 {
2649 goto fail;
2650 }
2651 }
2652
2655 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2656
2657 errmsg("%s is not allowed in a non-volatile function",
2659
2660
2661
2662
2663
2664
2665 if (->read_only && pushed_active_snap)
2666 {
2669 }
2670
2671
2672
2673
2674
2675 if (!canSetTag)
2679 else
2681
2682 if (stmt->utilityStmt == NULL)
2683 {
2686
2689 else
2691
2694 snap, crosscheck_snapshot,
2698 0);
2700 canSetTag ? options->tcount : 0);
2702 }
2703 else
2704 {
2707
2708
2709
2710
2711
2712 if (allow_nonatomic)
2714 else
2716
2720 true,
2721 context,
2725 &qc);
2726
2727
2730
2732
2733
2734
2735
2736
2738 {
2740
2743 else
2744 {
2745
2746
2747
2748
2752 }
2753
2754
2755
2756
2757
2760 }
2762 {
2765 }
2766 }
2767
2768
2769
2770
2771
2772
2773 if (canSetTag)
2774 {
2778 my_res = res;
2779 }
2780 else
2781 {
2784 }
2785
2786
2787
2788
2789
2790
2791
2792 if (res < 0)
2793 {
2794 my_res = res;
2795 goto fail;
2796 }
2797 }
2798
2799
2801 cplan = NULL;
2802
2803
2804
2805
2806
2807
2808 if (->read_only)
2810 }
2811
2812fail:
2813
2814
2815 if (pushed_active_snap)
2817
2818
2819 if (cplan)
2821
2822
2823
2824
2826
2827
2830
2831
2833
2834
2835
2836
2837
2838
2839 if (my_res == 0)
2841
2842 return my_res;
2843}
2844
2845
2846
2847
2851{
2853
2854 if (nargs > 0)
2855 {
2857
2858 for (int i = 0; i < nargs; i++)
2859 {
2861
2865 prm->ptype = argtypes[i];
2866 }
2867 }
2868 else
2869 paramLI = NULL;
2870 return paramLI;
2871}
2872
2873static int
2875{
2876 int operation = queryDesc->operation;
2877 int eflags;
2878 int res;
2879
2880 switch (operation)
2881 {
2884 {
2885
2887 }
2888 else
2890 break;
2894 else
2896 break;
2900 else
2902 break;
2906 else
2908 break;
2912 else
2914 break;
2915 default:
2917 }
2918
2919#ifdef SPI_EXECUTOR_STATS
2920 if (ShowExecutorStats)
2922#endif
2923
2924
2925 if (fire_triggers)
2926 eflags = 0;
2927 else
2929
2931
2933
2935
2938 {
2940 elog(ERROR, "consistency check on SPI tuple count failed");
2941 }
2942
2945
2946
2947#ifdef SPI_EXECUTOR_STATS
2948 if (ShowExecutorStats)
2949 ShowUsage("SPI EXECUTOR STATS");
2950#endif
2951
2952 return res;
2953}
2954
2955
2956
2957
2958
2959
2960static void
2962{
2964 const char *query = carg->query;
2965 int syntaxerrposition;
2966
2967 if (query == NULL)
2968 return;
2969
2970
2971
2972
2973
2975 if (syntaxerrposition > 0)
2976 {
2980 }
2981 else
2982 {
2983
2984 switch (carg->mode)
2985 {
2987 errcontext("PL/pgSQL expression \"%s\"", query);
2988 break;
2992 errcontext("PL/pgSQL assignment \"%s\"", query);
2993 break;
2994 default:
2995 errcontext("SQL statement \"%s\"", query);
2996 break;
2997 }
2998 }
2999}
3000
3001
3002
3003
3004
3005
3006static void
3009{
3011
3012
3014 elog(ERROR, "invalid portal in SPI cursor operation");
3015
3016
3018 elog(ERROR, "SPI cursor operation called while not connected");
3019
3020
3025
3026
3028 direction,
3029 count,
3031
3032
3033
3034
3035
3036
3037
3038
3039
3041
3043 elog(ERROR, "consistency check on SPI tuple count failed");
3044
3045
3048
3049
3051
3052
3054}
3055
3056
3059{
3061}
3062
3065{
3067}
3068
3069
3070
3071
3072
3073
3074
3075
3076static int
3078{
3081
3082 if (use_exec)
3083 {
3084
3086
3088 }
3089
3090 return 0;
3091}
3092
3093
3094
3095
3096
3097
3098
3099
3100static int
3102{
3103 if (use_exec)
3104 {
3105
3107
3109
3111 }
3112
3113 return 0;
3114}
3115
3116static bool
3118{
3121 bool failed = false;
3122
3123 if (tuptable == NULL)
3124 failed = true;
3125 else if (processed != tuptable->numvals)
3126 failed = true;
3127
3128 return failed;
3129}
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3142{
3148
3149
3152
3154
3155
3156
3157
3158
3160 "SPI Plan",
3163
3164
3167 newplan->plancxt = plancxt;
3171 if (plan->nargs > 0)
3172 {
3175 }
3176 else
3180
3181
3182
3183
3184
3185
3186
3187 foreach(lc, plan->plancache_list)
3188 {
3190
3192
3193
3195 }
3196
3198
3199
3200 plan->plancache_list = NIL;
3201
3202 return newplan;
3203}
3204
3205
3206
3207
3210{
3215
3216
3218
3219
3220
3221
3222
3223
3225 "SPI Plan",
3228
3229
3232 newplan->plancxt = plancxt;
3236 if (plan->nargs > 0)
3237 {
3240 }
3241 else
3245
3246
3247 foreach(lc, plan->plancache_list)
3248 {
3251
3254 }
3255
3257
3258
3259
3260
3261
3262
3263 newplan->saved = true;
3265
3267 {
3269
3271 }
3272
3273 return newplan;
3274}
3275
3276
3277
3278
3281{
3282
3284
3285
3287 return NULL;
3288
3290}
3291
3292
3293
3294
3295
3296int
3298{
3300 int res;
3301
3302 if (enr == NULL || enr->md.name == NULL)
3304
3305 res = _SPI_begin_call(false);
3306 if (res < 0)
3307 return res;
3308
3310 if (match)
3312 else
3313 {
3316
3319 }
3320
3322
3323 return res;
3324}
3325
3326
3327
3328
3329
3330int
3332{
3334 int res;
3335
3336 if (name == NULL)
3338
3339 res = _SPI_begin_call(false);
3340 if (res < 0)
3341 return res;
3342
3344 if (match)
3345 {
3348 }
3349 else
3351
3353
3354 return res;
3355}
3356
3357
3358
3359
3360
3361
3362
3363int
3365{
3366 if (tdata == NULL)
3368
3370 {
3373 int rc;
3374
3383 return rc;
3384 }
3385
3387 {
3390 int rc;
3391
3400 return rc;
3401 }
3402
3404}
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)
void ExecutorEnd(QueryDesc *queryDesc)
void ExecutorFinish(QueryDesc *queryDesc)
void ExecutorStart(QueryDesc *queryDesc, int eflags)
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)
Portal CreateNewPortal(void)
void HoldPinnedPortals(void)
void PortalDrop(Portal portal, bool isTopCommit)
Portal GetPortalByName(const char *name)
void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, CommandTag commandTag, List *stmts, CachedPlan *cplan)
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)
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
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)
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
static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
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)
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)