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
39
40
41
42
43
44typedef struct
45{
50
51
52
53
54
55
56
57
58
59
60
61
62typedef enum
63{
66
68{
71 bool setsResult;
76
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
112{
114
117
120
124 bool returnsSet;
125 bool returnsTuple;
128
130
132 int num_queries;
133 bool raw_source;
134
136
140
142{
144
146 bool shutdown_reg;
148 bool randomAccess;
149 bool ownSubcontext;
150
152
155
157 int jf_generation;
158
159
160
161
162
163
164
165
166
167
168
172
176
177
179
181
183
185
186
189
191
192
193
198 int paramno, int location);
200 const char *paramname, int location);
202 bool lazyEvalOK);
209 bool forValidator);
227 char prokind, bool insertDroppedCols);
229 Oid res_type, int32 res_typmod,
230 bool tlist_is_modifiable,
231 List **upper_tlist,
232 bool *upper_tlist_nontrivial);
238
239
240
241
242
243
244
245
246
247
250 Node *call_expr,
251 Oid inputCollation)
252{
255 int nargs;
256
258
259
261
262
263 pinfo->collation = inputCollation;
264
265
266
267
268
269 pinfo->nargs = nargs = procedureStruct->pronargs;
270 if (nargs > 0)
271 {
272 Oid *argOidVect;
273 int argnum;
274
275 argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
276 memcpy(argOidVect,
277 procedureStruct->proargtypes.values,
278 nargs * sizeof(Oid));
279
280 for (argnum = 0; argnum < nargs; argnum++)
281 {
282 Oid argtype = argOidVect[argnum];
283
284 if (IsPolymorphicType(argtype))
285 {
289 (errcode(ERRCODE_DATATYPE_MISMATCH),
290 errmsg("could not determine actual type of argument declared %s",
292 argOidVect[argnum] = argtype;
293 }
294 }
295
296 pinfo->argtypes = argOidVect;
297 }
298
299
300
301
302 if (nargs > 0)
303 {
304 Datum proargnames;
305 Datum proargmodes;
306 int n_arg_names;
307 bool isNull;
308
309 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
310 Anum_pg_proc_proargnames,
311 &isNull);
312 if (isNull)
313 proargnames = PointerGetDatum(NULL);
314
315 proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
316 Anum_pg_proc_proargmodes,
317 &isNull);
318 if (isNull)
319 proargmodes = PointerGetDatum(NULL);
320
323
324
325 if (n_arg_names < nargs)
327 }
328 else
330
331 return pinfo;
332}
333
334
335
336
337void
339{
343
345}
346
347
348
349
352{
354 int nnames;
355 Node *field1;
356 Node *subfield = NULL;
357 const char *name1;
358 const char *name2 = NULL;
360
361
362
363
364
365
366 if (var != NULL)
367 return NULL;
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
386
387 if (nnames > 3)
388 return NULL;
389
391 nnames--;
392
394 name1 = strVal(field1);
395 if (nnames > 1)
396 {
398 name2 = strVal(subfield);
399 }
400
401 if (nnames == 3)
402 {
403
404
405
406
407
408 if (strcmp(name1, pinfo->fname) != 0)
409 return NULL;
410
412
415 }
416 else if (nnames == 2 && strcmp(name1, pinfo->fname) == 0)
417 {
418
419
420
421
423
424 if (param)
425 {
426
427 subfield = NULL;
428 }
429 else
430 {
431
433 }
434 }
435 else
436 {
437
439 }
440
441 if (!param)
442 return NULL;
443
444 if (subfield)
445 {
446
447
448
449
450
455 NULL,
456 false,
458 }
459
460 return param;
461}
462
463
464
465
468{
470 int paramno = pref->number;
471
472
473 if (paramno <= 0 || paramno > pinfo->nargs)
474 return NULL;
475
477}
478
479
480
481
484 int paramno, int location)
485{
487
490 param->paramid = paramno;
492 param->paramtypmod = -1;
495
496
497
498
499
500
502 param->paramcollid = pinfo->collation;
503
504 return (Node *) param;
505}
506
507
508
509
510
511
514 const char *paramname, int location)
515{
516 int i;
517
519 return NULL;
520
521 for (i = 0; i < pinfo->nargs; i++)
522 {
523 if (pinfo->argnames[i] && strcmp(pinfo->argnames[i], paramname) == 0)
525 }
526
527 return NULL;
528}
529
530
531
532
535{
539
540
541
542
543
544
545
547 if (fcache == NULL)
548 {
556 }
557
558
559
560
561
562
563
564 if (fcache->eslist != NULL)
565 {
567 return fcache;
568 }
569
570
571
572
573
574
575
582 true,
583 false);
584
585
586
587
588
589
590
591 if (func != fcache->func)
592 {
593 if (fcache->func != NULL)
594 {
597 }
598 fcache->func = func;
600
602 }
603
604
605
606
607
609
610
613
614
615 fcache->eslist = NULL;
618
619 return fcache;
620}
621
622
623
624
625
626
627
628static bool
630{
634 int nstmts;
636
637
638
639
640 if (fcache->cplan)
641 {
643 fcache->cplan = NULL;
644 }
645 fcache->eslist = NULL;
646
647
648
649
650
651
652
654 {
656 return false;
659 }
660 else
662
666
667
668
669
670
671
672
677 NULL);
678
679
680
681
684 {
685 if (fcache->esarray == NULL)
689 else
693 }
694
695
696
697
699 {
702
703
704
705
706
708 {
710 ((CopyStmt *) stmt->utilityStmt)->filename == NULL)
712 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
713 errmsg("cannot COPY to/from client in an SQL function")));
714
717 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
718
719 errmsg("%s is not allowed in an SQL function",
721 }
722
725 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
726
727 errmsg("%s is not allowed in a non-volatile function",
729
730
732 if (preves)
733 preves->next = newes;
734 else
735 fcache->eslist = newes;
736
737 newes->next = NULL;
739 newes->setsResult = false;
740 newes->lazyEval = false;
742 newes->qd = NULL;
743
744 if (stmt->canSetTag)
745 lasttages = newes;
746
747 preves = newes;
748 }
749
750
751
752
753
755 return true;
756
757
758
759
760
761
762
763
764
765
766
767
768
769
773 {
775 List *resulttlist;
777
778
781 "SQL function junkfilter",
783 else
786
788
789
790
791
792
793
795
796
797
798
799
800
801
802
803
807 slot);
808 else
810
811
812
813
814
815
816
817
818
819
821
822
825
826
828
830 }
831
835 {
836
837
838
839
840
842 }
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
859 {
865 }
866
867 return true;
868}
869
870
871
872
873
874
875static void
877{
878 int qindex;
879 bool islast;
881 List *queryTree_list;
883
884
886 Assert(qindex < func->num_queries);
887 islast = (qindex + 1 >= func->num_queries);
888
889
890
891
892
893
894
895
896
897
899 {
900
902
905 func->src,
909 }
910 else
911 {
912
914
917 func->src,
920 func->src,
923 NULL);
924 }
925
926
927
928
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949 if (islast)
954 false);
955
956
957
958
959
961 queryTree_list,
962 NULL,
963 NULL,
964 0,
968 false);
969
970
971
972
973
976 islast ? func : NULL);
977
978
979
980
981
985
986
987
988
989
991
992
993
994
995
996
997 if (islast)
998 {
999 func->source_list = NIL;
1002 }
1003}
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015static void
1020 bool forValidator)
1021{
1028 Oid rettype;
1031 bool isNull;
1032 List *source_list;
1033
1034
1035
1036
1037
1039 comperrcontext.arg = func;
1042
1043
1044
1045
1046
1048 "SQL function",
1050
1051
1052
1053
1054
1056 "SQL function parse trees",
1059
1060
1061
1062
1063
1065 NameStr(procedureStruct->proname));
1067
1068
1069
1070
1071
1073
1074 func->rettype = rettype;
1075 if (rettupdesc)
1076 {
1080 }
1081
1082
1084
1085
1086 func->returnsSet = procedureStruct->proretset;
1087
1088
1090 (procedureStruct->provolatile != PROVOLATILE_VOLATILE);
1091
1092
1093 func->prokind = procedureStruct->prokind;
1094
1095
1096
1097
1098
1099
1105
1106
1107
1108
1109
1114
1115
1116
1117
1121
1122
1124 procedureTuple,
1125 Anum_pg_proc_prosqlbody,
1126 &isNull);
1127 if (!isNull)
1128 {
1129
1131
1135 else
1138 }
1139 else
1140 {
1141
1144 }
1145
1146
1147
1148
1149
1151
1152
1153
1154
1155
1156
1157
1158 if (func->num_queries == 0 && rettype != VOIDOID)
1160 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1161 errmsg("return type mismatch in function declared to return %s",
1163 errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));
1164
1165
1169
1170
1171
1172
1173
1174
1175
1178
1180}
1181
1182
1183
1184
1185
1186
1187
1188static void
1190{
1193
1194
1196 {
1198
1200 }
1202
1203
1204
1205
1206
1210}
1211
1212
1213
1214
1215
1216
1217
1218static void
1220{
1221
1222
1223
1224
1225
1227
1228
1229
1230
1231
1232
1233 if (arg != NULL)
1234 {
1236 bool returnsTuple;
1237
1242 false);
1245 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1246 errmsg("cached plan must not change result type")));
1247 }
1248}
1249
1250
1251static void
1253{
1256
1258
1259
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1274 {
1276 "SQL function execution",
1279 }
1281 {
1282
1283
1284
1285
1286
1287
1288
1289
1291 "SQL function execution",
1294 }
1295 else
1296 {
1299 }
1300
1301
1302
1303
1304
1306 {
1309 {
1313 }
1314 }
1315
1316
1318
1319
1320
1321
1322
1324 {
1326
1328
1331 myState->tstore = fcache->tstore;
1333
1334
1336 }
1337 else
1339
1341 NULL,
1348 0);
1349
1350
1352 {
1353
1354
1355
1356
1357
1358
1359
1360 int eflags;
1361
1364 else
1365 eflags = 0;
1367 elog(ERROR, "ExecutorStart() failed unexpectedly");
1368 }
1369
1371
1373}
1374
1375
1376
1377static bool
1379{
1380 bool result;
1382
1383
1385
1387 {
1390 true,
1395 NULL);
1396 result = true;
1397 }
1398 else
1399 {
1400
1402
1404
1405
1406
1407
1408
1410 }
1411
1413
1414 return result;
1415}
1416
1417
1418static void
1420{
1422
1423
1425
1426
1428
1429
1431 {
1434 }
1435
1437
1439 es->qd = NULL;
1440
1442
1443
1447}
1448
1449
1450static void
1453{
1454 int nargs = fcinfo->nargs;
1455
1456 if (nargs > 0)
1457 {
1461
1462 if (fcache->paramLI == NULL)
1463 {
1464
1466
1469 fcache->paramLI = paramLI;
1471 }
1472 else
1473 {
1474 paramLI = fcache->paramLI;
1476 }
1477
1478 for (int i = 0; i < nargs; i++)
1479 {
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1497 argtyplen[i]);
1498
1500 prm->ptype = argtypes[i];
1501 }
1502 }
1503 else
1505}
1506
1507
1508
1509
1510
1511
1512
1517{
1519
1520
1521
1522
1523
1524
1525
1527 {
1528
1529 fcinfo->isnull = false;
1531 }
1532 else
1533 {
1534
1535
1536
1537
1539
1540 if (!fcinfo->isnull)
1542 }
1543
1544
1546
1548}
1549
1550
1551
1552
1555{
1559 bool randomAccess;
1560 bool lazyEvalOK;
1561 bool pushed_snapshot;
1565
1566
1567 if (fcinfo->flinfo->fn_retset)
1568 {
1570
1571
1572
1573
1574
1575
1576
1581 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1582 errmsg("set-valued function called in context that cannot accept a set")));
1585
1587 }
1588 else
1589 {
1590 randomAccess = false;
1591 lazyEvalOK = true;
1592
1593 tscontext = NULL;
1594 }
1595
1596
1597
1598
1600
1601
1604
1605
1606
1607
1609 sqlerrcontext.arg = fcache;
1612
1613
1614
1615
1616
1617 do
1618 {
1619 es = fcache->eslist;
1621 es = es->next;
1622 if (es)
1623 break;
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644 pushed_snapshot = false;
1645 while (es)
1646 {
1647 bool completed;
1648
1650 {
1651
1652
1653
1654
1655
1656
1658 {
1660 if (!pushed_snapshot)
1661 {
1663 pushed_snapshot = true;
1664 }
1665 else
1667 }
1668
1670 }
1672 {
1673
1675 pushed_snapshot = true;
1676 }
1677
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1702 break;
1703
1704
1705
1706
1707 es = es->next;
1708 while (!es)
1709 {
1710
1711
1712
1713
1714
1715
1716 if (pushed_snapshot)
1717 {
1719 pushed_snapshot = false;
1720 }
1721
1723 break;
1724
1725 es = fcache->eslist;
1726 }
1727 }
1728
1729
1730
1731
1732
1734 {
1736
1737 if (es)
1738 {
1739
1740
1741
1742
1744
1748
1750
1751
1752
1753
1755
1756
1757
1758
1759
1761 {
1766 }
1767 }
1769 {
1770
1771
1772
1773
1775
1776 fcinfo->isnull = true;
1777 result = (Datum) 0;
1778
1779
1781 {
1786 }
1787 }
1788 else
1789 {
1790
1791
1792
1793
1794
1795
1796
1797
1798
1802 fcache->tstore = NULL;
1803
1806
1807 fcinfo->isnull = true;
1808 result = (Datum) 0;
1809
1810
1812 {
1817 }
1818 }
1819 }
1820 else
1821 {
1822
1823
1824
1826 {
1827
1831 else
1832 {
1833 fcinfo->isnull = true;
1834 result = (Datum) 0;
1835 }
1836 }
1837 else
1838 {
1839
1841 fcinfo->isnull = true;
1842 result = (Datum) 0;
1843 }
1844 }
1845
1846
1847 if (pushed_snapshot)
1849
1850
1851
1852
1853
1854 if (es == NULL)
1855 fcache->eslist = NULL;
1856
1858
1859 return result;
1860}
1861
1862
1863
1864
1865
1866static void
1868{
1870 int syntaxerrposition;
1871
1872
1873
1874
1875
1876 if (func->fname == NULL)
1877 return;
1878
1879
1880
1881
1883 if (syntaxerrposition > 0 && func->src != NULL)
1884 {
1888 }
1889
1890
1891
1892
1893
1894 errcontext("SQL function \"%s\" during startup", func->fname);
1895}
1896
1897
1898
1899
1900static void
1902{
1904 int syntaxerrposition;
1905
1906
1907
1908
1910 if (syntaxerrposition > 0 && fcache->func->src != NULL)
1911 {
1915 }
1916
1917
1918
1919
1920
1922 errcontext("SQL function \"%s\" statement %d",
1924 else
1926}
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938static void
1940{
1943
1944 es = fcache->eslist;
1945 while (es)
1946 {
1947
1949 {
1950
1953
1955
1958 }
1959 es = es->next;
1960 }
1961 fcache->eslist = NULL;
1962
1963
1966 fcache->tstore = NULL;
1967
1968
1969 if (fcache->cplan)
1971 fcache->cplan = NULL;
1972
1973
1975}
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985static void
1987{
1989
1990
1991 if (fcache->func != NULL)
1992 {
1995
1996 fcache->func = NULL;
1997 }
1998}
1999
2000
2001
2002
2003
2004
2005
2006void
2008{
2010
2011
2012 foreach(lc, queryTreeLists)
2013 {
2015
2017 }
2018}
2019
2020
2021
2022
2023static void
2025{
2027
2028 foreach(lc, queryTreeList)
2029 {
2031
2032
2033
2034
2035
2036
2037
2038
2041 {
2043
2046 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2047 errmsg("calling procedures with output arguments is not supported in SQL functions")));
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
2086
2087bool
2090 char prokind,
2091 bool insertDroppedCols)
2092{
2093 List *queryTreeList;
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107 if (queryTreeLists != NIL)
2109 else
2110 queryTreeList = NIL;
2111
2113 rettype, rettupdesc,
2114 prokind, insertDroppedCols);
2115}
2116
2117
2118
2119
2120
2121static bool
2124 char prokind, bool insertDroppedCols)
2125{
2126 bool is_tuple_result = false;
2129 List *tlist;
2130 int tlistlen;
2131 bool tlist_is_modifiable;
2132 char fn_typtype;
2134 bool upper_tlist_nontrivial = false;
2136
2137
2138
2139
2140
2141 if (rettype == VOIDOID)
2142 return false;
2143
2144
2145
2146
2147
2148
2150 parse_cell = NULL;
2151 foreach(lc, queryTreeList)
2152 {
2154
2155 if (q->canSetTag)
2156 {
2158 parse_cell = lc;
2159 }
2160 }
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2175 {
2176 tlist = parse->targetList;
2177
2178 tlist_is_modifiable = (parse->setOperations == NULL);
2179 }
2180 else if (parse &&
2185 parse->returningList)
2186 {
2187 tlist = parse->returningList;
2188
2189 tlist_is_modifiable = true;
2190 }
2191 else
2192 {
2193
2195 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2196 errmsg("return type mismatch in function declared to return %s",
2198 errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));
2199 return false;
2200 }
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2216
2218
2219 if (fn_typtype == TYPTYPE_BASE ||
2220 fn_typtype == TYPTYPE_DOMAIN ||
2221 fn_typtype == TYPTYPE_ENUM ||
2222 fn_typtype == TYPTYPE_RANGE ||
2223 fn_typtype == TYPTYPE_MULTIRANGE)
2224 {
2225
2226
2227
2228
2230
2231 if (tlistlen != 1)
2233 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2234 errmsg("return type mismatch in function declared to return %s",
2236 errdetail("Final statement must return exactly one column.")));
2237
2238
2240 Assert(!tle->resjunk);
2241
2243 tlist_is_modifiable,
2244 &upper_tlist,
2245 &upper_tlist_nontrivial))
2247 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2248 errmsg("return type mismatch in function declared to return %s",
2250 errdetail("Actual return type is %s.",
2252 }
2253 else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
2254 {
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266 int tupnatts;
2267 int tuplogcols;
2268 int colindex;
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291 if (tlistlen == 1 && prokind != PROKIND_PROCEDURE)
2292 {
2294
2295 Assert(!tle->resjunk);
2297 tlist_is_modifiable,
2298 &upper_tlist,
2299 &upper_tlist_nontrivial))
2300 {
2301
2302 goto tlist_coercion_finished;
2303 }
2304 }
2305
2306
2307
2308
2309
2310 if (rettupdesc == NULL)
2311 return true;
2312
2313
2314
2315
2316
2317
2318
2319 tupnatts = rettupdesc->natts;
2320 tuplogcols = 0;
2321 colindex = 0;
2322
2323 foreach(lc, tlist)
2324 {
2327
2328
2329 if (tle->resjunk)
2330 continue;
2331
2332 do
2333 {
2334 colindex++;
2335 if (colindex > tupnatts)
2337 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2338 errmsg("return type mismatch in function declared to return %s",
2340 errdetail("Final statement returns too many columns.")));
2342 if (attr->attisdropped && insertDroppedCols)
2343 {
2344 Expr *null_expr;
2345
2346
2348 -1,
2352 true,
2353 true );
2354 upper_tlist = lappend(upper_tlist,
2357 NULL,
2358 false));
2359 upper_tlist_nontrivial = true;
2360 }
2361 } while (attr->attisdropped);
2362 tuplogcols++;
2363
2365 attr->atttypid, attr->atttypmod,
2366 tlist_is_modifiable,
2367 &upper_tlist,
2368 &upper_tlist_nontrivial))
2370 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2371 errmsg("return type mismatch in function declared to return %s",
2373 errdetail("Final statement returns %s instead of %s at column %d.",
2376 tuplogcols)));
2377 }
2378
2379
2380 for (colindex++; colindex <= tupnatts; colindex++)
2381 {
2384 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2385 errmsg("return type mismatch in function declared to return %s",
2387 errdetail("Final statement returns too few columns.")));
2388 if (insertDroppedCols)
2389 {
2390 Expr *null_expr;
2391
2392
2394 -1,
2398 true,
2399 true );
2400 upper_tlist = lappend(upper_tlist,
2403 NULL,
2404 false));
2405 upper_tlist_nontrivial = true;
2406 }
2407 }
2408
2409
2410 is_tuple_result = true;
2411 }
2412 else
2414 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2415 errmsg("return type %s is not supported for SQL functions",
2417
2418tlist_coercion_finished:
2419
2420
2421
2422
2423
2424
2425
2426 if (upper_tlist_nontrivial)
2427 {
2428 Query *newquery;
2429 List *colnames;
2432
2434
2435
2438 newquery->querySource = parse->querySource;
2439 newquery->canSetTag = true;
2441
2442
2443 colnames = NIL;
2444 foreach(lc, parse->targetList)
2445 {
2447
2448 if (tle->resjunk)
2449 continue;
2450 colnames = lappend(colnames,
2451 makeString(tle->resname ? tle->resname : ""));
2452 }
2453
2454
2458 rte->eref = rte->alias = makeAlias("*SELECT*", colnames);
2459 rte->lateral = false;
2460 rte->inh = false;
2461 rte->inFromCl = true;
2463
2467
2468
2469
2470
2471
2472 newquery->hasRowSecurity = parse->hasRowSecurity;
2473
2474
2475 lfirst(parse_cell) = newquery;
2476 }
2477
2478 return is_tuple_result;
2479}
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491static bool
2493 Oid res_type,
2494 int32 res_typmod,
2495 bool tlist_is_modifiable,
2496 List **upper_tlist,
2497 bool *upper_tlist_nontrivial)
2498{
2500 Expr *new_tle_expr;
2501 Node *cast_result;
2502
2503
2504
2505
2506
2507
2508
2509 if (tlist_is_modifiable && src_tle->ressortgroupref == 0)
2510 {
2511
2515 res_type, res_typmod,
2518 -1);
2519 if (cast_result == NULL)
2520 return false;
2522 src_tle->expr = (Expr *) cast_result;
2523
2525 }
2526 else
2527 {
2528
2530
2532 (Node *) var,
2533 var->vartype,
2534 res_type, res_typmod,
2537 -1);
2538 if (cast_result == NULL)
2539 return false;
2541
2542 if (cast_result != (Node *) var)
2543 *upper_tlist_nontrivial = true;
2544 new_tle_expr = (Expr *) cast_result;
2545 }
2548 src_tle->resname, false);
2549 *upper_tlist = lappend(*upper_tlist, new_tle);
2550 return true;
2551}
2552
2553
2554
2555
2556
2557static List *
2559{
2562
2563 foreach(lc, queryTreeList)
2564 {
2566
2567 if (q->canSetTag)
2569 }
2572 return parse->targetList;
2573 else if (parse &&
2578 parse->returningList)
2579 return parse->returningList;
2580 else
2581 return NIL;
2582}
2583
2584
2585
2586
2587
2590{
2592
2598
2599
2600
2602}
2603
2604
2605
2606
2607static void
2609{
2610
2611}
2612
2613
2614
2615
2616static bool
2618{
2620
2621 if (myState->tstore)
2622 {
2623
2624
2625
2627
2628
2630 }
2631 else
2632 {
2633
2634
2635
2636
2638 {
2639
2642
2643
2645 }
2646 }
2647
2648 return true;
2649}
2650
2651
2652
2653
2654static void
2656{
2657
2658}
2659
2660
2661
2662
2663static void
2665{
2667}
#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)
bool ExecutorStart(QueryDesc *queryDesc, int eflags)
void ExecutorEnd(QueryDesc *queryDesc)
void ExecutorFinish(QueryDesc *queryDesc)
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, CachedPlan *cplan, 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)