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
147 bool shutdown_reg;
149 bool randomAccess;
150 bool ownSubcontext;
151
153
156
158 int jf_generation;
159
160
161
162
163
164
165
166
167
168
169
173
177
178
180
182
184
186
187
190
192
193
194
199 int paramno, int location);
201 const char *paramname, int location);
203 bool lazyEvalOK);
210 bool forValidator);
228 char prokind, bool insertDroppedCols);
230 Oid res_type, int32 res_typmod,
231 bool tlist_is_modifiable,
232 List **upper_tlist,
233 bool *upper_tlist_nontrivial);
239
240
241
242
243
244
245
246
247
248
251 Node *call_expr,
252 Oid inputCollation)
253{
256 int nargs;
257
259
260
262
263
264 pinfo->collation = inputCollation;
265
266
267
268
269
270 pinfo->nargs = nargs = procedureStruct->pronargs;
271 if (nargs > 0)
272 {
273 Oid *argOidVect;
274 int argnum;
275
276 argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
277 memcpy(argOidVect,
278 procedureStruct->proargtypes.values,
279 nargs * sizeof(Oid));
280
281 for (argnum = 0; argnum < nargs; argnum++)
282 {
283 Oid argtype = argOidVect[argnum];
284
285 if (IsPolymorphicType(argtype))
286 {
290 (errcode(ERRCODE_DATATYPE_MISMATCH),
291 errmsg("could not determine actual type of argument declared %s",
293 argOidVect[argnum] = argtype;
294 }
295 }
296
297 pinfo->argtypes = argOidVect;
298 }
299
300
301
302
303 if (nargs > 0)
304 {
305 Datum proargnames;
306 Datum proargmodes;
307 int n_arg_names;
308 bool isNull;
309
310 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
311 Anum_pg_proc_proargnames,
312 &isNull);
313 if (isNull)
314 proargnames = PointerGetDatum(NULL);
315
316 proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
317 Anum_pg_proc_proargmodes,
318 &isNull);
319 if (isNull)
320 proargmodes = PointerGetDatum(NULL);
321
324
325
326 if (n_arg_names < nargs)
328 }
329 else
331
332 return pinfo;
333}
334
335
336
337
338void
340{
344
346}
347
348
349
350
353{
355 int nnames;
356 Node *field1;
357 Node *subfield = NULL;
358 const char *name1;
359 const char *name2 = NULL;
361
362
363
364
365
366
367 if (var != NULL)
368 return NULL;
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
387
388 if (nnames > 3)
389 return NULL;
390
392 nnames--;
393
395 name1 = strVal(field1);
396 if (nnames > 1)
397 {
399 name2 = strVal(subfield);
400 }
401
402 if (nnames == 3)
403 {
404
405
406
407
408
409 if (strcmp(name1, pinfo->fname) != 0)
410 return NULL;
411
413
416 }
417 else if (nnames == 2 && strcmp(name1, pinfo->fname) == 0)
418 {
419
420
421
422
424
425 if (param)
426 {
427
428 subfield = NULL;
429 }
430 else
431 {
432
434 }
435 }
436 else
437 {
438
440 }
441
442 if (!param)
443 return NULL;
444
445 if (subfield)
446 {
447
448
449
450
451
456 NULL,
457 false,
459 }
460
461 return param;
462}
463
464
465
466
469{
471 int paramno = pref->number;
472
473
474 if (paramno <= 0 || paramno > pinfo->nargs)
475 return NULL;
476
478}
479
480
481
482
485 int paramno, int location)
486{
488
491 param->paramid = paramno;
493 param->paramtypmod = -1;
496
497
498
499
500
501
503 param->paramcollid = pinfo->collation;
504
505 return (Node *) param;
506}
507
508
509
510
511
512
515 const char *paramname, int location)
516{
517 int i;
518
520 return NULL;
521
522 for (i = 0; i < pinfo->nargs; i++)
523 {
524 if (pinfo->argnames[i] && strcmp(pinfo->argnames[i], paramname) == 0)
526 }
527
528 return NULL;
529}
530
531
532
533
536{
540
541
542
543
544
545
546
548 if (fcache == NULL)
549 {
557 }
558
559
560
561
562
563
564
565 if (fcache->eslist != NULL)
566 {
568 return fcache;
569 }
570
571
572
573
574
575
576
583 true,
584 false);
585
586
587
588
589
590
591
592 if (func != fcache->func)
593 {
594 if (fcache->func != NULL)
595 {
598 }
599 fcache->func = func;
601
603 }
604
605
606
607
608
610
611
614
615
616 fcache->eslist = NULL;
619
620 return fcache;
621}
622
623
624
625
626
627
628
629static bool
631{
635 int nstmts;
637
638
639
640
641 if (fcache->cplan)
642 {
644 fcache->cplan = NULL;
645 }
646 fcache->eslist = NULL;
647
648
649
650
651
652
653
655 {
657 return false;
660 }
661 else
663
667
668
669
670
671
672
673
678 NULL);
679
680
681
682
685 {
686 if (fcache->esarray == NULL)
690 else
694 }
695
696
697
698
700 {
703
704
705
706
707
709 {
711 ((CopyStmt *) stmt->utilityStmt)->filename == NULL)
713 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
714 errmsg("cannot COPY to/from client in an SQL function")));
715
718 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
719
720 errmsg("%s is not allowed in an SQL function",
722 }
723
726 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
727
728 errmsg("%s is not allowed in a non-volatile function",
730
731
733 if (preves)
734 preves->next = newes;
735 else
736 fcache->eslist = newes;
737
738 newes->next = NULL;
740 newes->setsResult = false;
741 newes->lazyEval = false;
743 newes->qd = NULL;
744
745 if (stmt->canSetTag)
746 lasttages = newes;
747
748 preves = newes;
749 }
750
751
752
753
754
756 return true;
757
758
759
760
761
762
763
764
765
766
767
768
769
770
774 {
776 List *resulttlist;
778
779
782 "SQL function junkfilter",
784 else
787
789
790
791
792
793
794
796
797
798
799
800
801
802
803
804
808 slot);
809 else
811
812
813
814
815
816
817
818
819
820
822
823
826
827
829
831 }
832
836 {
837
838
839
840
841
843 }
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
860 {
866 }
867
868 return true;
869}
870
871
872
873
874
875
876static void
878{
879 int qindex;
880 bool islast;
882 List *queryTree_list;
884
885
887 Assert(qindex < func->num_queries);
888 islast = (qindex + 1 >= func->num_queries);
889
890
891
892
893
894
895
896
897
898
900 {
901
903
906 func->src,
910 }
911 else
912 {
913
915
918 func->src,
921 func->src,
924 NULL);
925 }
926
927
928
929
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950 if (islast)
955 false);
956
957
958
959
960
962 queryTree_list,
963 NULL,
964 NULL,
965 0,
969 false);
970
971
972
973
974
977 islast ? func : NULL);
978
979
980
981
982
986
987
988
989
990
992
993
994
995
996
997
998 if (islast)
999 {
1000 func->source_list = NIL;
1003 }
1004}
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016static void
1021 bool forValidator)
1022{
1029 Oid rettype;
1032 bool isNull;
1033 List *source_list;
1034
1035
1036
1037
1038
1040 comperrcontext.arg = func;
1043
1044
1045
1046
1047
1049 "SQL function",
1051
1052
1053
1054
1055
1057 "SQL function parse trees",
1060
1061
1062
1063
1064
1066 NameStr(procedureStruct->proname));
1068
1069
1070
1071
1072
1074
1075 func->rettype = rettype;
1076 if (rettupdesc)
1077 {
1081 }
1082
1083
1085
1086
1087 func->returnsSet = procedureStruct->proretset;
1088
1089
1091 (procedureStruct->provolatile != PROVOLATILE_VOLATILE);
1092
1093
1094 func->prokind = procedureStruct->prokind;
1095
1096
1097
1098
1099
1100
1106
1107
1108
1109
1110
1115
1116
1117
1118
1122
1123
1125 procedureTuple,
1126 Anum_pg_proc_prosqlbody,
1127 &isNull);
1128 if (!isNull)
1129 {
1130
1132
1136 else
1139 }
1140 else
1141 {
1142
1145 }
1146
1147
1148
1149
1150
1152
1153
1154
1155
1156
1157
1158
1159 if (func->num_queries == 0 && rettype != VOIDOID)
1161 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1162 errmsg("return type mismatch in function declared to return %s",
1164 errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));
1165
1166
1170
1171
1172
1173
1174
1175
1176
1179
1181}
1182
1183
1184
1185
1186
1187
1188
1189static void
1191{
1194
1195
1197 {
1199
1201 }
1203
1204
1205
1206
1207
1211}
1212
1213
1214
1215
1216
1217
1218
1219static void
1221{
1222
1223
1224
1225
1226
1228
1229
1230
1231
1232
1233
1234 if (arg != NULL)
1235 {
1237 bool returnsTuple;
1238
1243 false);
1246 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1247 errmsg("cached plan must not change result type")));
1248 }
1249}
1250
1251
1252static void
1254{
1257
1259
1260
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1275 {
1277 "SQL function execution",
1280 }
1282 {
1283
1284
1285
1286
1287
1288
1289
1290
1292 "SQL function execution",
1295 }
1296 else
1297 {
1300 }
1301
1302
1303
1304
1305
1307 {
1310 {
1314 }
1315 }
1316
1317
1319
1320
1321
1322
1323
1325 {
1327
1329
1332 myState->tstore = fcache->tstore;
1334
1335
1337 }
1338 else
1340
1348 0);
1349
1350
1352 {
1353
1354
1355
1356
1357
1358
1359
1360 int eflags;
1361
1364 else
1365 eflags = 0;
1367 }
1368
1370
1372}
1373
1374
1375
1376static bool
1378{
1379 bool result;
1381
1382
1384
1386 {
1389 true,
1394 NULL);
1395 result = true;
1396 }
1397 else
1398 {
1399
1401
1403
1404
1405
1406
1407
1409 }
1410
1412
1413 return result;
1414}
1415
1416
1417static void
1419{
1421
1422
1424
1425
1427
1428
1430 {
1433 }
1434
1436
1438 es->qd = NULL;
1439
1441
1442
1446}
1447
1448
1449static void
1452{
1453 int nargs = fcinfo->nargs;
1454
1455 if (nargs > 0)
1456 {
1460
1461 if (fcache->paramLI == NULL)
1462 {
1463
1465
1468 fcache->paramLI = paramLI;
1470 }
1471 else
1472 {
1473 paramLI = fcache->paramLI;
1475 }
1476
1477 for (int i = 0; i < nargs; i++)
1478 {
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1496 argtyplen[i]);
1497
1499 prm->ptype = argtypes[i];
1500 }
1501 }
1502 else
1504}
1505
1506
1507
1508
1509
1510
1511
1516{
1518
1519
1520
1521
1522
1523
1524
1526 {
1527
1528 fcinfo->isnull = false;
1530 }
1531 else
1532 {
1533
1534
1535
1536
1538
1539 if (!fcinfo->isnull)
1541 }
1542
1543
1545
1547}
1548
1549
1550
1551
1554{
1558 bool randomAccess;
1559 bool lazyEvalOK;
1560 bool pushed_snapshot;
1564
1565
1566 if (fcinfo->flinfo->fn_retset)
1567 {
1569
1570
1571
1572
1573
1574
1575
1580 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1581 errmsg("set-valued function called in context that cannot accept a set")));
1584
1586 }
1587 else
1588 {
1589 randomAccess = false;
1590 lazyEvalOK = true;
1591
1592 tscontext = NULL;
1593 }
1594
1595
1596
1597
1599
1600
1603
1604
1605
1606
1608 sqlerrcontext.arg = fcache;
1611
1612
1613
1614
1615
1616 do
1617 {
1618 es = fcache->eslist;
1620 es = es->next;
1621 if (es)
1622 break;
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643 pushed_snapshot = false;
1644 while (es)
1645 {
1646 bool completed;
1647
1649 {
1650
1651
1652
1653
1654
1655
1657 {
1659 if (!pushed_snapshot)
1660 {
1662 pushed_snapshot = true;
1663 }
1664 else
1666 }
1667
1669 }
1671 {
1672
1674 pushed_snapshot = true;
1675 }
1676
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1701 break;
1702
1703
1704
1705
1706 es = es->next;
1707 while (!es)
1708 {
1709
1710
1711
1712
1713
1714
1715 if (pushed_snapshot)
1716 {
1718 pushed_snapshot = false;
1719 }
1720
1722 break;
1723
1724 es = fcache->eslist;
1725 }
1726 }
1727
1728
1729
1730
1731
1733 {
1735
1736 if (es)
1737 {
1738
1739
1740
1741
1743
1747
1749
1750
1751
1752
1754
1755
1756
1757
1758
1760 {
1765 }
1766 }
1768 {
1769
1770
1771
1772
1774
1775 fcinfo->isnull = true;
1776 result = (Datum) 0;
1777
1778
1780 {
1785 }
1786 }
1787 else
1788 {
1789
1790
1791
1792
1793
1794
1795
1796
1797
1801 fcache->tstore = NULL;
1802
1805
1806 fcinfo->isnull = true;
1807 result = (Datum) 0;
1808
1809
1811 {
1816 }
1817 }
1818 }
1819 else
1820 {
1821
1822
1823
1825 {
1826
1830 else
1831 {
1832 fcinfo->isnull = true;
1833 result = (Datum) 0;
1834 }
1835 }
1836 else
1837 {
1838
1840 fcinfo->isnull = true;
1841 result = (Datum) 0;
1842 }
1843 }
1844
1845
1846 if (pushed_snapshot)
1848
1849
1850
1851
1852
1853 if (es == NULL)
1854 fcache->eslist = NULL;
1855
1857
1858 return result;
1859}
1860
1861
1862
1863
1864
1865static void
1867{
1869 int syntaxerrposition;
1870
1871
1872
1873
1874
1875 if (func->fname == NULL)
1876 return;
1877
1878
1879
1880
1882 if (syntaxerrposition > 0 && func->src != NULL)
1883 {
1887 }
1888
1889
1890
1891
1892
1893 errcontext("SQL function \"%s\" during startup", func->fname);
1894}
1895
1896
1897
1898
1899static void
1901{
1903 int syntaxerrposition;
1904
1905
1906
1907
1909 if (syntaxerrposition > 0 && fcache->func->src != NULL)
1910 {
1914 }
1915
1916
1917
1918
1919
1921 errcontext("SQL function \"%s\" statement %d",
1923 else
1925}
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937static void
1939{
1942
1943 es = fcache->eslist;
1944 while (es)
1945 {
1946
1948 {
1949
1952
1954
1957 }
1958 es = es->next;
1959 }
1960 fcache->eslist = NULL;
1961
1962
1965 fcache->tstore = NULL;
1966
1967
1968 if (fcache->cplan)
1970 fcache->cplan = NULL;
1971
1972
1974}
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984static void
1986{
1988
1989
1990 if (fcache->func != NULL)
1991 {
1994
1995 fcache->func = NULL;
1996 }
1997}
1998
1999
2000
2001
2002
2003
2004
2005void
2007{
2009
2010
2011 foreach(lc, queryTreeLists)
2012 {
2014
2016 }
2017}
2018
2019
2020
2021
2022static void
2024{
2026
2027 foreach(lc, queryTreeList)
2028 {
2030
2031
2032
2033
2034
2035
2036
2037
2040 {
2042
2045 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2046 errmsg("calling procedures with output arguments is not supported in SQL functions")));
2047 }
2048 }
2049}
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086bool
2089 char prokind,
2090 bool insertDroppedCols)
2091{
2092 List *queryTreeList;
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106 if (queryTreeLists != NIL)
2108 else
2109 queryTreeList = NIL;
2110
2112 rettype, rettupdesc,
2113 prokind, insertDroppedCols);
2114}
2115
2116
2117
2118
2119
2120static bool
2123 char prokind, bool insertDroppedCols)
2124{
2125 bool is_tuple_result = false;
2128 List *tlist;
2129 int tlistlen;
2130 bool tlist_is_modifiable;
2131 char fn_typtype;
2133 bool upper_tlist_nontrivial = false;
2135
2136
2137
2138
2139
2140 if (rettype == VOIDOID)
2141 return false;
2142
2143
2144
2145
2146
2147
2149 parse_cell = NULL;
2150 foreach(lc, queryTreeList)
2151 {
2153
2154 if (q->canSetTag)
2155 {
2157 parse_cell = lc;
2158 }
2159 }
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2174 {
2175 tlist = parse->targetList;
2176
2177 tlist_is_modifiable = (parse->setOperations == NULL);
2178 }
2179 else if (parse &&
2184 parse->returningList)
2185 {
2186 tlist = parse->returningList;
2187
2188 tlist_is_modifiable = true;
2189 }
2190 else
2191 {
2192
2194 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2195 errmsg("return type mismatch in function declared to return %s",
2197 errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));
2198 return false;
2199 }
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2215
2217
2218 if (fn_typtype == TYPTYPE_BASE ||
2219 fn_typtype == TYPTYPE_DOMAIN ||
2220 fn_typtype == TYPTYPE_ENUM ||
2221 fn_typtype == TYPTYPE_RANGE ||
2222 fn_typtype == TYPTYPE_MULTIRANGE)
2223 {
2224
2225
2226
2227
2229
2230 if (tlistlen != 1)
2232 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2233 errmsg("return type mismatch in function declared to return %s",
2235 errdetail("Final statement must return exactly one column.")));
2236
2237
2239 Assert(!tle->resjunk);
2240
2242 tlist_is_modifiable,
2243 &upper_tlist,
2244 &upper_tlist_nontrivial))
2246 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2247 errmsg("return type mismatch in function declared to return %s",
2249 errdetail("Actual return type is %s.",
2251 }
2252 else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
2253 {
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265 int tupnatts;
2266 int tuplogcols;
2267 int colindex;
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290 if (tlistlen == 1 && prokind != PROKIND_PROCEDURE)
2291 {
2293
2294 Assert(!tle->resjunk);
2296 tlist_is_modifiable,
2297 &upper_tlist,
2298 &upper_tlist_nontrivial))
2299 {
2300
2301 goto tlist_coercion_finished;
2302 }
2303 }
2304
2305
2306
2307
2308
2309 if (rettupdesc == NULL)
2310 return true;
2311
2312
2313
2314
2315
2316
2317
2318 tupnatts = rettupdesc->natts;
2319 tuplogcols = 0;
2320 colindex = 0;
2321
2322 foreach(lc, tlist)
2323 {
2326
2327
2328 if (tle->resjunk)
2329 continue;
2330
2331 do
2332 {
2333 colindex++;
2334 if (colindex > tupnatts)
2336 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2337 errmsg("return type mismatch in function declared to return %s",
2339 errdetail("Final statement returns too many columns.")));
2341 if (attr->attisdropped && insertDroppedCols)
2342 {
2343 Expr *null_expr;
2344
2345
2347 -1,
2351 true,
2352 true );
2353 upper_tlist = lappend(upper_tlist,
2356 NULL,
2357 false));
2358 upper_tlist_nontrivial = true;
2359 }
2360 } while (attr->attisdropped);
2361 tuplogcols++;
2362
2364 attr->atttypid, attr->atttypmod,
2365 tlist_is_modifiable,
2366 &upper_tlist,
2367 &upper_tlist_nontrivial))
2369 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2370 errmsg("return type mismatch in function declared to return %s",
2372 errdetail("Final statement returns %s instead of %s at column %d.",
2375 tuplogcols)));
2376 }
2377
2378
2379 for (colindex++; colindex <= tupnatts; colindex++)
2380 {
2383 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2384 errmsg("return type mismatch in function declared to return %s",
2386 errdetail("Final statement returns too few columns.")));
2387 if (insertDroppedCols)
2388 {
2389 Expr *null_expr;
2390
2391
2393 -1,
2397 true,
2398 true );
2399 upper_tlist = lappend(upper_tlist,
2402 NULL,
2403 false));
2404 upper_tlist_nontrivial = true;
2405 }
2406 }
2407
2408
2409 is_tuple_result = true;
2410 }
2411 else
2413 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2414 errmsg("return type %s is not supported for SQL functions",
2416
2417tlist_coercion_finished:
2418
2419
2420
2421
2422
2423
2424
2425 if (upper_tlist_nontrivial)
2426 {
2427 Query *newquery;
2428 List *colnames;
2431
2433
2434
2437 newquery->querySource = parse->querySource;
2438 newquery->canSetTag = true;
2440
2441
2442 colnames = NIL;
2443 foreach(lc, parse->targetList)
2444 {
2446
2447 if (tle->resjunk)
2448 continue;
2449 colnames = lappend(colnames,
2450 makeString(tle->resname ? tle->resname : ""));
2451 }
2452
2453
2457 rte->eref = rte->alias = makeAlias("*SELECT*", colnames);
2458 rte->lateral = false;
2459 rte->inh = false;
2460 rte->inFromCl = true;
2462
2466
2467
2468
2469
2470
2471 newquery->hasRowSecurity = parse->hasRowSecurity;
2472
2473
2474 lfirst(parse_cell) = newquery;
2475 }
2476
2477 return is_tuple_result;
2478}
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490static bool
2492 Oid res_type,
2493 int32 res_typmod,
2494 bool tlist_is_modifiable,
2495 List **upper_tlist,
2496 bool *upper_tlist_nontrivial)
2497{
2499 Expr *new_tle_expr;
2500 Node *cast_result;
2501
2502
2503
2504
2505
2506
2507
2508 if (tlist_is_modifiable && src_tle->ressortgroupref == 0)
2509 {
2510
2514 res_type, res_typmod,
2517 -1);
2518 if (cast_result == NULL)
2519 return false;
2521 src_tle->expr = (Expr *) cast_result;
2522
2524 }
2525 else
2526 {
2527
2529
2531 (Node *) var,
2532 var->vartype,
2533 res_type, res_typmod,
2536 -1);
2537 if (cast_result == NULL)
2538 return false;
2540
2541 if (cast_result != (Node *) var)
2542 *upper_tlist_nontrivial = true;
2543 new_tle_expr = (Expr *) cast_result;
2544 }
2547 src_tle->resname, false);
2548 *upper_tlist = lappend(*upper_tlist, new_tle);
2549 return true;
2550}
2551
2552
2553
2554
2555
2556static List *
2558{
2561
2562 foreach(lc, queryTreeList)
2563 {
2565
2566 if (q->canSetTag)
2568 }
2571 return parse->targetList;
2572 else if (parse &&
2577 parse->returningList)
2578 return parse->returningList;
2579 else
2580 return NIL;
2581}
2582
2583
2584
2585
2586
2589{
2591
2597
2598
2599
2601}
2602
2603
2604
2605
2606static void
2608{
2609
2610}
2611
2612
2613
2614
2615static bool
2617{
2619
2620 if (myState->tstore)
2621 {
2622
2623
2624
2626
2627
2629 }
2630 else
2631 {
2632
2633
2634
2635
2637 {
2638
2641
2642
2644 }
2645 }
2646
2647 return true;
2648}
2649
2650
2651
2652
2653static void
2655{
2656
2657}
2658
2659
2660
2661
2662static void
2664{
2666}
#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)
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)
void * palloc0(Size size)
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)(struct 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)