PostgreSQL Source Code: src/backend/executor/functions.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
40
41
42
43
44
45typedef struct
46{
51
52
53
54
55
56
57
58
59
60
61
62
63typedef enum
64{
67
69{
72 bool setsResult;
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
113{
115
118
121
125 bool returnsSet;
126 bool returnsTuple;
129
131
133 int num_queries;
134 bool raw_source;
135
137
141
143{
145
148 bool shutdown_reg;
150 bool randomAccess;
151 bool ownSubcontext;
152
154
157
159 int jf_generation;
160
161
162
163
164
165
166
167
168
169
170
174
178
179
181
183
185
187
188
191
193
194
195
200 int paramno, int location);
202 const char *paramname, int location);
204 bool lazyEvalOK);
211 bool forValidator);
229 char prokind, bool insertDroppedCols);
231 Oid res_type, int32 res_typmod,
232 bool tlist_is_modifiable,
233 List **upper_tlist,
234 bool *upper_tlist_nontrivial);
240
241
242
243
244
245
246
247
248
249
252 Node *call_expr,
253 Oid inputCollation)
254{
257 int nargs;
258
260
261
263
264
265 pinfo->collation = inputCollation;
266
267
268
269
270
271 pinfo->nargs = nargs = procedureStruct->pronargs;
272 if (nargs > 0)
273 {
274 Oid *argOidVect;
275 int argnum;
276
277 argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
278 memcpy(argOidVect,
279 procedureStruct->proargtypes.values,
280 nargs * sizeof(Oid));
281
282 for (argnum = 0; argnum < nargs; argnum++)
283 {
284 Oid argtype = argOidVect[argnum];
285
286 if (IsPolymorphicType(argtype))
287 {
291 (errcode(ERRCODE_DATATYPE_MISMATCH),
292 errmsg("could not determine actual type of argument declared %s",
294 argOidVect[argnum] = argtype;
295 }
296 }
297
298 pinfo->argtypes = argOidVect;
299 }
300
301
302
303
304 if (nargs > 0)
305 {
306 Datum proargnames;
307 Datum proargmodes;
308 int n_arg_names;
309 bool isNull;
310
311 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
312 Anum_pg_proc_proargnames,
313 &isNull);
314 if (isNull)
315 proargnames = PointerGetDatum(NULL);
316
317 proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
318 Anum_pg_proc_proargmodes,
319 &isNull);
320 if (isNull)
321 proargmodes = PointerGetDatum(NULL);
322
325
326
327 if (n_arg_names < nargs)
329 }
330 else
332
333 return pinfo;
334}
335
336
337
338
339void
341{
345
347}
348
349
350
351
354{
356 int nnames;
357 Node *field1;
358 Node *subfield = NULL;
359 const char *name1;
360 const char *name2 = NULL;
362
363
364
365
366
367
368 if (var != NULL)
369 return NULL;
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
388
389 if (nnames > 3)
390 return NULL;
391
393 nnames--;
394
396 name1 = strVal(field1);
397 if (nnames > 1)
398 {
400 name2 = strVal(subfield);
401 }
402
403 if (nnames == 3)
404 {
405
406
407
408
409
410 if (strcmp(name1, pinfo->fname) != 0)
411 return NULL;
412
414
417 }
418 else if (nnames == 2 && strcmp(name1, pinfo->fname) == 0)
419 {
420
421
422
423
425
426 if (param)
427 {
428
429 subfield = NULL;
430 }
431 else
432 {
433
435 }
436 }
437 else
438 {
439
441 }
442
443 if (!param)
444 return NULL;
445
446 if (subfield)
447 {
448
449
450
451
452
457 NULL,
458 false,
460 }
461
462 return param;
463}
464
465
466
467
470{
472 int paramno = pref->number;
473
474
475 if (paramno <= 0 || paramno > pinfo->nargs)
476 return NULL;
477
479}
480
481
482
483
486 int paramno, int location)
487{
489
492 param->paramid = paramno;
497
498
499
500
501
502
505
506 return (Node *) param;
507}
508
509
510
511
512
513
516 const char *paramname, int location)
517{
518 int i;
519
521 return NULL;
522
523 for (i = 0; i < pinfo->nargs; i++)
524 {
525 if (pinfo->argnames[i] && strcmp(pinfo->argnames[i], paramname) == 0)
527 }
528
529 return NULL;
530}
531
532
533
534
537{
541
542
543
544
545
546
547
549 if (fcache == NULL)
550 {
558 }
559
560
561
562
563
564
565
567 {
568
569
570
571
572
573
574
575 fcache->cplan = NULL;
576 fcache->eslist = NULL;
577 fcache->tstore = NULL;
579 fcache->active = false;
580 }
581
582
583
584
585
586
587
588 if (fcache->eslist != NULL)
589 {
591 return fcache;
592 }
593
594
595
596
597
598
599
606 true,
607 false);
608
609
610
611
612
613
614
615 if (func != fcache->func)
616 {
617 if (fcache->func != NULL)
618 {
621 }
622 fcache->func = func;
624
626 }
627
628
629
630
631
633
634
637
638
639 fcache->eslist = NULL;
642
643 return fcache;
644}
645
646
647
648
649
650
651
652static bool
654{
658 int nstmts;
660
661
662
663
664 if (fcache->cplan)
665 {
667 fcache->cplan = NULL;
668 }
669 fcache->eslist = NULL;
670
671
672
673
674
675
676
678 {
680 return false;
683 }
684 else
686
690
691
692
693
694
695
696
701 NULL);
702
703
704
705
708 {
709 if (fcache->esarray == NULL)
713 else
717 }
718
719
720
721
723 {
726
727
728
729
730
732 {
734 ((CopyStmt *) stmt->utilityStmt)->filename == NULL)
736 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
737 errmsg("cannot COPY to/from client in an SQL function")));
738
741 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
742
743 errmsg("%s is not allowed in an SQL function",
745 }
746
749 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
750
751 errmsg("%s is not allowed in a non-volatile function",
753
754
756 if (preves)
757 preves->next = newes;
758 else
759 fcache->eslist = newes;
760
761 newes->next = NULL;
763 newes->setsResult = false;
764 newes->lazyEval = false;
766 newes->qd = NULL;
767
768 if (stmt->canSetTag)
769 lasttages = newes;
770
771 preves = newes;
772 }
773
774
775
776
777
779 return true;
780
781
782
783
784
785
786
787
788
789
790
791
792
793
797 {
799 List *resulttlist;
801
802
805 "SQL function junkfilter",
807 else
810
812
813
814
815
816
817
819
820
821
822
823
824
825
826
827
831 slot);
832 else
834
835
836
837
838
839
840
841
842
843
845
846
849
850
852
854 }
855
859 {
860
861
862
863
864
866 }
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
883 {
889 }
890
891 return true;
892}
893
894
895
896
897
898
899static void
901{
902 int qindex;
903 bool islast;
905 List *queryTree_list;
907
908
910 Assert(qindex < func->num_queries);
911 islast = (qindex + 1 >= func->num_queries);
912
913
914
915
916
917
918
919
920
921
923 {
924
926
929 func->src,
933 }
934 else
935 {
936
938
941 func->src,
944 func->src,
947 NULL);
948 }
949
950
951
952
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973 if (islast)
978 false);
979
980
981
982
983
985 queryTree_list,
986 NULL,
987 NULL,
988 0,
992 false);
993
994
995
996
997
1000 islast ? func : NULL);
1001
1002
1003
1004
1005
1009
1010
1011
1012
1013
1015
1016
1017
1018
1019
1020
1021 if (islast)
1022 {
1023 func->source_list = NIL;
1026 }
1027}
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039static void
1044 bool forValidator)
1045{
1052 Oid rettype;
1055 bool isNull;
1056 List *source_list;
1057
1058
1059
1060
1061
1063 comperrcontext.arg = func;
1066
1067
1068
1069
1070
1072 "SQL function",
1074
1075
1076
1077
1078
1080 "SQL function parse trees",
1083
1084
1085
1086
1087
1089 NameStr(procedureStruct->proname));
1091
1092
1093
1094
1095
1097
1098 func->rettype = rettype;
1099 if (rettupdesc)
1100 {
1104 }
1105
1106
1108
1109
1110 func->returnsSet = procedureStruct->proretset;
1111
1112
1114 (procedureStruct->provolatile != PROVOLATILE_VOLATILE);
1115
1116
1117 func->prokind = procedureStruct->prokind;
1118
1119
1120
1121
1122
1123
1129
1130
1131
1132
1133
1138
1139
1140
1141
1145
1146
1148 procedureTuple,
1149 Anum_pg_proc_prosqlbody,
1150 &isNull);
1151 if (!isNull)
1152 {
1153
1155
1159 else
1162 }
1163 else
1164 {
1165
1168 }
1169
1170
1171
1172
1173
1175
1176
1177
1178
1179
1180
1181
1182 if (func->num_queries == 0 && rettype != VOIDOID)
1184 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1185 errmsg("return type mismatch in function declared to return %s",
1187 errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));
1188
1189
1193
1194
1195
1196
1197
1198
1199
1202
1204}
1205
1206
1207
1208
1209
1210
1211
1212static void
1214{
1217
1218
1220 {
1222
1224 }
1226
1227
1228
1229
1230
1234}
1235
1236
1237
1238
1239
1240
1241
1242static void
1244{
1245
1246
1247
1248
1249
1251
1252
1253
1254
1255
1256
1257 if (arg != NULL)
1258 {
1260 bool returnsTuple;
1261
1266 false);
1269 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1270 errmsg("cached plan must not change result type")));
1271 }
1272}
1273
1274
1275static void
1277{
1280
1282
1283
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1298 {
1300 "SQL function execution",
1303 }
1305 {
1306
1307
1308
1309
1310
1311
1312
1313
1315 "SQL function execution",
1318 }
1319 else
1320 {
1323 }
1324
1325
1326
1327
1328
1330 {
1333 {
1337 }
1338 }
1339
1340
1342
1343
1344
1345
1346
1348 {
1350
1352
1355 myState->tstore = fcache->tstore;
1357
1358
1360 }
1361 else
1363
1371 0);
1372
1373
1375 {
1376
1377
1378
1379
1380
1381
1382
1383 int eflags;
1384
1387 else
1388 eflags = 0;
1390 }
1391
1393
1395}
1396
1397
1398
1399static bool
1401{
1402 bool result;
1404
1405
1407
1409 {
1412 true,
1417 NULL);
1418 result = true;
1419 }
1420 else
1421 {
1422
1424
1426
1427
1428
1429
1430
1432 }
1433
1435
1436 return result;
1437}
1438
1439
1440static void
1442{
1444
1445
1447
1448
1450
1451
1453 {
1456 }
1457
1459
1461 es->qd = NULL;
1462
1464
1465
1469}
1470
1471
1472static void
1475{
1476 int nargs = fcinfo->nargs;
1477
1478 if (nargs > 0)
1479 {
1483
1484 if (fcache->paramLI == NULL)
1485 {
1486
1488
1491 fcache->paramLI = paramLI;
1493 }
1494 else
1495 {
1496 paramLI = fcache->paramLI;
1498 }
1499
1500 for (int i = 0; i < nargs; i++)
1501 {
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1519 argtyplen[i]);
1520
1522 prm->ptype = argtypes[i];
1523 }
1524 }
1525 else
1527}
1528
1529
1530
1531
1532
1533
1534
1539{
1541
1542
1543
1544
1545
1546
1547
1549 {
1550
1551 fcinfo->isnull = false;
1553 }
1554 else
1555 {
1556
1557
1558
1559
1561
1562 if (!fcinfo->isnull)
1564 }
1565
1566
1568
1570}
1571
1572
1573
1574
1577{
1581 bool randomAccess;
1582 bool lazyEvalOK;
1583 bool pushed_snapshot;
1587
1588
1589 if (fcinfo->flinfo->fn_retset)
1590 {
1592
1593
1594
1595
1596
1597
1598
1603 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1604 errmsg("set-valued function called in context that cannot accept a set")));
1607
1609 }
1610 else
1611 {
1612 randomAccess = false;
1613 lazyEvalOK = true;
1614
1615 tscontext = NULL;
1616 }
1617
1618
1619
1620
1622
1623
1624 fcache->active = true;
1625
1626
1629
1630
1631
1632
1634 sqlerrcontext.arg = fcache;
1637
1638
1639
1640
1641
1642 do
1643 {
1644 es = fcache->eslist;
1646 es = es->next;
1647 if (es)
1648 break;
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669 pushed_snapshot = false;
1670 while (es)
1671 {
1672 bool completed;
1673
1675 {
1676
1677
1678
1679
1680
1681
1683 {
1685 if (!pushed_snapshot)
1686 {
1688 pushed_snapshot = true;
1689 }
1690 else
1692 }
1693
1695 }
1697 {
1698
1700 pushed_snapshot = true;
1701 }
1702
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1727 break;
1728
1729
1730
1731
1732 es = es->next;
1733 while (!es)
1734 {
1735
1736
1737
1738
1739
1740
1741 if (pushed_snapshot)
1742 {
1744 pushed_snapshot = false;
1745 }
1746
1748 break;
1749
1750 es = fcache->eslist;
1751 }
1752 }
1753
1754
1755
1756
1757
1759 {
1761
1762 if (es)
1763 {
1764
1765
1766
1767
1769
1773
1775
1776
1777
1778
1780
1781
1782
1783
1784
1786 {
1791 }
1792 }
1794 {
1795
1796
1797
1798
1800
1801 fcinfo->isnull = true;
1802 result = (Datum) 0;
1803
1804
1806 {
1811 }
1812 }
1813 else
1814 {
1815
1816
1817
1818
1819
1820
1821
1822
1823
1827 fcache->tstore = NULL;
1828
1831
1832 fcinfo->isnull = true;
1833 result = (Datum) 0;
1834
1835
1837 {
1842 }
1843 }
1844 }
1845 else
1846 {
1847
1848
1849
1851 {
1852
1856 else
1857 {
1858 fcinfo->isnull = true;
1859 result = (Datum) 0;
1860 }
1861 }
1862 else
1863 {
1864
1866 fcinfo->isnull = true;
1867 result = (Datum) 0;
1868 }
1869 }
1870
1871
1872 if (pushed_snapshot)
1874
1875
1876
1877
1878
1879 if (es == NULL)
1880 fcache->eslist = NULL;
1881
1882
1883 fcache->active = false;
1884
1886
1887 return result;
1888}
1889
1890
1891
1892
1893
1894static void
1896{
1898 int syntaxerrposition;
1899
1900
1901
1902
1903
1904 if (func->fname == NULL)
1905 return;
1906
1907
1908
1909
1911 if (syntaxerrposition > 0 && func->src != NULL)
1912 {
1916 }
1917
1918
1919
1920
1921
1922 errcontext("SQL function \"%s\" during startup", func->fname);
1923}
1924
1925
1926
1927
1928static void
1930{
1932 int syntaxerrposition;
1933
1934
1935
1936
1938 if (syntaxerrposition > 0 && fcache->func->src != NULL)
1939 {
1943 }
1944
1945
1946
1947
1948
1950 errcontext("SQL function \"%s\" statement %d",
1952 else
1954}
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966static void
1968{
1971
1972 es = fcache->eslist;
1973 while (es)
1974 {
1975
1977 {
1978
1981
1983
1986 }
1987 es = es->next;
1988 }
1989 fcache->eslist = NULL;
1990
1991
1994 fcache->tstore = NULL;
1995
1996
1997 if (fcache->cplan)
1999 fcache->cplan = NULL;
2000
2001
2003}
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013static void
2015{
2017
2018
2019 if (fcache->func != NULL)
2020 {
2023
2024 fcache->func = NULL;
2025 }
2026}
2027
2028
2029
2030
2031
2032
2033
2034void
2036{
2038
2039
2040 foreach(lc, queryTreeLists)
2041 {
2043
2045 }
2046}
2047
2048
2049
2050
2051static void
2053{
2055
2056 foreach(lc, queryTreeList)
2057 {
2059
2060
2061
2062
2063
2064
2065
2066
2069 {
2071
2074 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2075 errmsg("calling procedures with output arguments is not supported in SQL functions")));
2076 }
2077 }
2078}
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115bool
2118 char prokind,
2119 bool insertDroppedCols)
2120{
2121 List *queryTreeList;
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135 if (queryTreeLists != NIL)
2137 else
2138 queryTreeList = NIL;
2139
2141 rettype, rettupdesc,
2142 prokind, insertDroppedCols);
2143}
2144
2145
2146
2147
2148
2149static bool
2152 char prokind, bool insertDroppedCols)
2153{
2154 bool is_tuple_result = false;
2157 List *tlist;
2158 int tlistlen;
2159 bool tlist_is_modifiable;
2160 char fn_typtype;
2162 bool upper_tlist_nontrivial = false;
2164
2165
2166
2167
2168
2169 if (rettype == VOIDOID)
2170 return false;
2171
2172
2173
2174
2175
2176
2178 parse_cell = NULL;
2179 foreach(lc, queryTreeList)
2180 {
2182
2183 if (q->canSetTag)
2184 {
2186 parse_cell = lc;
2187 }
2188 }
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2203 {
2204 tlist = parse->targetList;
2205
2206 tlist_is_modifiable = (parse->setOperations == NULL);
2207 }
2208 else if (parse &&
2213 parse->returningList)
2214 {
2215 tlist = parse->returningList;
2216
2217 tlist_is_modifiable = true;
2218 }
2219 else
2220 {
2221
2223 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2224 errmsg("return type mismatch in function declared to return %s",
2226 errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));
2227 return false;
2228 }
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2244
2246
2247 if (fn_typtype == TYPTYPE_BASE ||
2248 fn_typtype == TYPTYPE_DOMAIN ||
2249 fn_typtype == TYPTYPE_ENUM ||
2250 fn_typtype == TYPTYPE_RANGE ||
2251 fn_typtype == TYPTYPE_MULTIRANGE)
2252 {
2253
2254
2255
2256
2258
2259 if (tlistlen != 1)
2261 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2262 errmsg("return type mismatch in function declared to return %s",
2264 errdetail("Final statement must return exactly one column.")));
2265
2266
2268 Assert(!tle->resjunk);
2269
2271 tlist_is_modifiable,
2272 &upper_tlist,
2273 &upper_tlist_nontrivial))
2275 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2276 errmsg("return type mismatch in function declared to return %s",
2278 errdetail("Actual return type is %s.",
2280 }
2281 else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
2282 {
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294 int tupnatts;
2295 int tuplogcols;
2296 int colindex;
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319 if (tlistlen == 1 && prokind != PROKIND_PROCEDURE)
2320 {
2322
2323 Assert(!tle->resjunk);
2325 tlist_is_modifiable,
2326 &upper_tlist,
2327 &upper_tlist_nontrivial))
2328 {
2329
2330 goto tlist_coercion_finished;
2331 }
2332 }
2333
2334
2335
2336
2337
2338 if (rettupdesc == NULL)
2339 return true;
2340
2341
2342
2343
2344
2345
2346
2347 tupnatts = rettupdesc->natts;
2348 tuplogcols = 0;
2349 colindex = 0;
2350
2351 foreach(lc, tlist)
2352 {
2355
2356
2357 if (tle->resjunk)
2358 continue;
2359
2360 do
2361 {
2362 colindex++;
2363 if (colindex > tupnatts)
2365 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2366 errmsg("return type mismatch in function declared to return %s",
2368 errdetail("Final statement returns too many columns.")));
2370 if (attr->attisdropped && insertDroppedCols)
2371 {
2372 Expr *null_expr;
2373
2374
2376 -1,
2380 true,
2381 true );
2382 upper_tlist = lappend(upper_tlist,
2385 NULL,
2386 false));
2387 upper_tlist_nontrivial = true;
2388 }
2389 } while (attr->attisdropped);
2390 tuplogcols++;
2391
2393 attr->atttypid, attr->atttypmod,
2394 tlist_is_modifiable,
2395 &upper_tlist,
2396 &upper_tlist_nontrivial))
2398 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2399 errmsg("return type mismatch in function declared to return %s",
2401 errdetail("Final statement returns %s instead of %s at column %d.",
2404 tuplogcols)));
2405 }
2406
2407
2408 for (colindex++; colindex <= tupnatts; colindex++)
2409 {
2412 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2413 errmsg("return type mismatch in function declared to return %s",
2415 errdetail("Final statement returns too few columns.")));
2416 if (insertDroppedCols)
2417 {
2418 Expr *null_expr;
2419
2420
2422 -1,
2426 true,
2427 true );
2428 upper_tlist = lappend(upper_tlist,
2431 NULL,
2432 false));
2433 upper_tlist_nontrivial = true;
2434 }
2435 }
2436
2437
2438 is_tuple_result = true;
2439 }
2440 else
2442 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2443 errmsg("return type %s is not supported for SQL functions",
2445
2446tlist_coercion_finished:
2447
2448
2449
2450
2451
2452
2453
2454 if (upper_tlist_nontrivial)
2455 {
2456 Query *newquery;
2457 List *colnames;
2460
2462
2463
2466 newquery->querySource = parse->querySource;
2467 newquery->canSetTag = true;
2469
2470
2471 colnames = NIL;
2472 foreach(lc, parse->targetList)
2473 {
2475
2476 if (tle->resjunk)
2477 continue;
2478 colnames = lappend(colnames,
2479 makeString(tle->resname ? tle->resname : ""));
2480 }
2481
2482
2486 rte->eref = makeAlias("unnamed_subquery", colnames);
2487 rte->lateral = false;
2488 rte->inh = false;
2489 rte->inFromCl = true;
2491
2495
2496
2497
2498
2499
2500 newquery->hasRowSecurity = parse->hasRowSecurity;
2501
2502
2503 lfirst(parse_cell) = newquery;
2504 }
2505
2506 return is_tuple_result;
2507}
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519static bool
2521 Oid res_type,
2522 int32 res_typmod,
2523 bool tlist_is_modifiable,
2524 List **upper_tlist,
2525 bool *upper_tlist_nontrivial)
2526{
2528 Expr *new_tle_expr;
2529 Node *cast_result;
2530
2531
2532
2533
2534
2535
2536
2537 if (tlist_is_modifiable && src_tle->ressortgroupref == 0)
2538 {
2539
2543 res_type, res_typmod,
2546 -1);
2547 if (cast_result == NULL)
2548 return false;
2550 src_tle->expr = (Expr *) cast_result;
2551
2553 }
2554 else
2555 {
2556
2558
2560 (Node *) var,
2561 var->vartype,
2562 res_type, res_typmod,
2565 -1);
2566 if (cast_result == NULL)
2567 return false;
2569
2570 if (cast_result != (Node *) var)
2571 *upper_tlist_nontrivial = true;
2572 new_tle_expr = (Expr *) cast_result;
2573 }
2576 src_tle->resname, false);
2577 *upper_tlist = lappend(*upper_tlist, new_tle);
2578 return true;
2579}
2580
2581
2582
2583
2584
2585static List *
2587{
2590
2591 foreach(lc, queryTreeList)
2592 {
2594
2595 if (q->canSetTag)
2597 }
2600 return parse->targetList;
2601 else if (parse &&
2606 parse->returningList)
2607 return parse->returningList;
2608 else
2609 return NIL;
2610}
2611
2612
2613
2614
2615
2618{
2620
2626
2627
2628
2630}
2631
2632
2633
2634
2635static void
2637{
2638
2639}
2640
2641
2642
2643
2644static bool
2646{
2648
2649 if (myState->tstore)
2650 {
2651
2652
2653
2655
2656
2658 }
2659 else
2660 {
2661
2662
2663
2664
2666 {
2667
2670
2671
2673 }
2674 }
2675
2676 return true;
2677}
2678
2679
2680
2681
2682static void
2684{
2685
2686}
2687
2688
2689
2690
2691static void
2693{
2695}
#define TextDatumGetCString(d)
#define OidIsValid(objectId)
Datum datumCopy(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
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
int errposition(int cursorpos)
#define ereport(elevel,...)
JunkFilter * ExecInitJunkFilterConversion(List *targetList, TupleDesc cleanTupType, TupleTableSlot *slot)
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
JunkFilter * ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)
void ExecutorEnd(QueryDesc *queryDesc)
void ExecutorFinish(QueryDesc *queryDesc)
void ExecutorStart(QueryDesc *queryDesc, int eflags)
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)
const TupleTableSlotOps TTSOpsMinimalTuple
void UnregisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
void RegisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
int ExecCleanTargetListLength(List *targetlist)
@ SFRM_Materialize_Preferred
@ SFRM_Materialize_Random
#define EXEC_FLAG_SKIP_TRIGGERS
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
#define repalloc_array(pointer, type, count)
#define palloc0_object(type)
Oid get_call_expr_argtype(Node *expr, int argnum)
#define PG_GET_COLLATION()
char * format_type_be(Oid type_oid)
int get_func_input_arg_names(Datum proargnames, Datum proargmodes, char ***arg_names)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
CachedFunction * cached_function_compile(FunctionCallInfo fcinfo, CachedFunction *function, CachedFunctionCompileCallback ccallback, CachedFunctionDeleteCallback dcallback, Size cacheEntrySize, bool includeResultType, bool forValidator)
static void check_sql_fn_statement(List *queryTreeList)
static void sql_delete_callback(CachedFunction *cfunc)
static Datum postquel_get_single_result(TupleTableSlot *slot, FunctionCallInfo fcinfo, SQLFunctionCachePtr fcache)
Datum fmgr_sql(PG_FUNCTION_ARGS)
bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols)
void check_sql_fn_statements(List *queryTreeLists)
static void prepare_next_query(SQLFunctionHashEntry *func)
static List * get_sql_fn_result_tlist(List *queryTreeList)
static Node * sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo, const char *paramname, int location)
static void sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
static Node * sql_fn_param_ref(ParseState *pstate, ParamRef *pref)
static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
static bool check_sql_stmt_retval(List *queryTreeList, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols)
static void sql_compile_callback(FunctionCallInfo fcinfo, HeapTuple procedureTuple, const CachedFunctionHashKey *hashkey, CachedFunction *cfunc, bool forValidator)
static void postquel_sub_params(SQLFunctionCachePtr fcache, FunctionCallInfo fcinfo)
static bool sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self)
static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
static bool init_execution_state(SQLFunctionCachePtr fcache)
static void sql_compile_error_callback(void *arg)
DestReceiver * CreateSQLFunctionDestReceiver(void)
struct SQLFunctionCache SQLFunctionCache
static void sql_postrewrite_callback(List *querytree_list, void *arg)
static void postquel_end(execution_state *es, SQLFunctionCachePtr fcache)
struct execution_state execution_state
static void RemoveSQLFunctionCache(void *arg)
struct SQLFunctionHashEntry SQLFunctionHashEntry
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
static Node * sql_fn_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
static void sqlfunction_destroy(DestReceiver *self)
static void sql_exec_error_callback(void *arg)
static void sqlfunction_shutdown(DestReceiver *self)
static Node * sql_fn_make_param(SQLFunctionParseInfoPtr pinfo, int paramno, int location)
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
static void ShutdownSQLFunction(Datum arg)
static bool coerce_fn_result_column(TargetEntry *src_tle, Oid res_type, int32 res_typmod, bool tlist_is_modifiable, List **upper_tlist, bool *upper_tlist_nontrivial)
static SQLFunctionCache * init_sql_fcache(FunctionCallInfo fcinfo, bool lazyEvalOK)
SQLFunctionCache * SQLFunctionCachePtr
SQLFunctionParseInfo * SQLFunctionParseInfoPtr
Assert(PointerIsAligned(start, uint64))
static void * GETSTRUCT(const HeapTupleData *tuple)
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
bool type_is_rowtype(Oid typid)
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Oid get_typcollation(Oid typid)
int16 get_typlen(Oid typid)
char get_typtype(Oid typid)
Alias * makeAlias(const char *aliasname, List *colnames)
Var * makeVarFromTargetEntry(int varno, TargetEntry *tle)
FromExpr * makeFromExpr(List *fromlist, Node *quals)
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
char * MemoryContextStrdup(MemoryContext context, const char *string)
void * MemoryContextAlloc(MemoryContext context, Size size)
void MemoryContextReset(MemoryContext context)
void * MemoryContextAllocZero(MemoryContext context, Size size)
char * pstrdup(const char *in)
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
void pfree(void *pointer)
MemoryContext CurrentMemoryContext
MemoryContext CacheMemoryContext
void MemoryContextDelete(MemoryContext context)
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define ALLOCSET_SMALL_SIZES
Oid exprType(const Node *expr)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
ParamListInfo makeParamList(int numParams)
void(* ParserSetupHook)(ParseState *pstate, void *arg)
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *last_srf, FuncCall *fn, bool proc_call, int location)
#define CURSOR_OPT_PARALLEL_OK
#define CURSOR_OPT_NO_SCROLL
FormData_pg_attribute * Form_pg_attribute
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define linitial_node(type, l)
#define foreach_current_index(var_or_cell)
static void * list_nth(const List *list, int n)
#define list_nth_node(type, list, n)
#define llast_node(type, l)
FormData_pg_proc * Form_pg_proc
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 * CreateCachedPlanForQuery(Query *analyzed_parse_tree, const char *query_string, CommandTag commandTag)
void SetPostRewriteHook(CachedPlanSource *plansource, PostRewriteHook postRewrite, void *postRewriteArg)
CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
List * pg_analyze_and_rewrite_withcb(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
List * pg_parse_query(const char *query_string)
List * pg_rewrite_query(Query *query)
static Datum PointerGetDatum(const void *X)
static Pointer DatumGetPointer(Datum 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)
void * stringToNode(const char *str)
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
ResourceOwner CurrentResourceOwner
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
Snapshot GetTransactionSnapshot(void)
void PushActiveSnapshot(Snapshot snapshot)
void UpdateActiveSnapshotCommandId(void)
bool ActiveSnapshotSet(void)
void PopActiveSnapshot(void)
Snapshot GetActiveSnapshot(void)
struct ErrorContextCallback * previous
void(* callback)(void *arg)
MemoryContext ecxt_per_query_memory
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
TupleDesc jf_cleanTupType
TupleTableSlot * jf_resultSlot
MemoryContextCallbackFunction func
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
ParseParamRefHook p_paramref_hook
PreParseColumnRefHook p_pre_columnref_hook
PostParseColumnRefHook p_post_columnref_hook
PlannedStmt * plannedstmt
QueryEnvironment * queryEnv
SetFunctionReturnMode returnMode
Tuplestorestate * setResult
SQLFunctionHashEntry * func
execution_state * esarray
MemoryContextCallback mcb
SQLFunctionParseInfoPtr pinfo
TupleDesc tts_tupleDescriptor
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
void(* rShutdown)(DestReceiver *self)
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
void(* rDestroy)(DestReceiver *self)
struct execution_state * next
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
void tuplestore_end(Tuplestorestate *state)
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
static void ExecMaterializeSlot(TupleTableSlot *slot)
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)
String * makeString(char *str)
void CommandCounterIncrement(void)