PostgreSQL Source Code: src/backend/optimizer/plan/subselect.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
18
41
42
44{
48
50{
54
56{
60
62{
67
68
72 Node *testexpr, List *testexpr_paramids,
73 bool unknownEqFalse);
75 List **paramIds);
79 Node *testexpr,
80 List *subst_nodes);
96 Node **testexpr, List **paramIds);
102 int gather_param,
108
109
110
111
112
113
114
115
116
117
118
119static void
121 Oid *colcollation)
122{
123
124 if (plan->targetlist)
125 {
127
128 if (!tent->resjunk)
129 {
133 return;
134 }
135 }
136 *coltype = VOIDOID;
137 *coltypmod = -1;
139}
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
166 Node *testexpr, bool isTopQual)
167{
169 bool simple_exists = false;
170 double tuple_fraction;
173 Path *best_path;
175 List *plan_params;
176 Node *result;
178
179
180
181
182
183
184
185 subquery = copyObject(orig_subquery);
186
187
188
189
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
213 tuple_fraction = 1.0;
216 tuple_fraction = 0.5;
217 else
218 tuple_fraction = 0.0;
219
220
222
223
226 root, false, tuple_fraction, NULL);
227
228
229 plan_params = root->plan_params;
231
232
233
234
235
238
240
241
243 subroot, plan_params,
244 subLinkType, subLinkId,
245 testexpr, NIL, isTopQual);
246
247
248
249
250
251
252
253
254
255
256 if (simple_exists && IsA(result, SubPlan))
257 {
258 Node *newtestexpr;
259 List *paramIds;
260
261
262 subquery = copyObject(orig_subquery);
263
265 Assert(simple_exists);
266
268 &newtestexpr, ¶mIds);
269 if (subquery)
270 {
271 char *plan_name;
272
273
276 root, false, 0.0, NULL);
277
278
279 plan_params = root->plan_params;
281
282
285
286
288 {
291
292
294
295
298 subroot, plan_params,
300 newtestexpr,
301 paramIds,
302 true));
303
306
307
310 result = (Node *) asplan;
311 root->hasAlternativeSubPlans = true;
312 }
313 }
314 }
315
316 return result;
317}
318
319
320
321
322
323
324
329 Node *testexpr, List *testexpr_paramids,
330 bool unknownEqFalse)
331{
332 Node *result;
335
336
337
338
339
340
354
355
356
357
358
359 foreach(lc, plan_params)
360 {
363
364
365
366
367
368
369
370
371
372
373
379
382 }
383
384
385
386
387
388
389
390
391
392
393
394
396 {
398
399 Assert(testexpr == NULL);
403 result = (Node *) prm;
404 }
406 {
409
410 Assert(!te->resjunk);
411 Assert(testexpr == NULL);
418 result = (Node *) prm;
419 }
421 {
423 Oid arraytype;
425
426 Assert(!te->resjunk);
427 Assert(testexpr == NULL);
430 elog(ERROR, "could not find array type for datatype %s",
433 arraytype,
438 result = (Node *) prm;
439 }
441 {
442
443 List *params;
444
445 Assert(testexpr != NULL);
447 plan->targetlist,
450 testexpr,
451 params);
454
455
456
457
458
459 }
461 {
462
463
464
465
466 List *params;
467
468 Assert(testexpr == NULL);
470 plan->targetlist,
472
473
474
475
476
477
483
484
486 {
489 }
490 else
491 {
493 result = (Node *) splan;
494 }
495 }
496 else
497 {
498
499
500
501
502 if (testexpr && testexpr_paramids == NIL)
503 {
504 List *params;
505
507 plan->targetlist,
510 testexpr,
511 params);
512 }
513 else
514 {
516 splan->paramIds = testexpr_paramids;
517 }
518
519
520
521
522
523
524
525
531
532
533
534
535
536
537
538
539
540
541
545
546 result = (Node *) splan;
548 }
549
550
551
552
554 root->glob->subpaths = lappend(root->glob->subpaths, path);
555 root->glob->subroots = lappend(root->glob->subroots, subroot);
557
560
561
562
563
564
565
566
567
571
572
574
575 return result;
576}
577
578
579
580
581
582
583
586{
587 List *result;
590
591 result = ids = NIL;
592 foreach(lc, tlist)
593 {
596
597 if (tent->resjunk)
598 continue;
599
604 result = lappend(result, param);
606 }
607
608 *paramIds = ids;
609 return result;
610}
611
612
613
614
615
616
619{
620 List *result;
622
623 result = NIL;
624 foreach(lc, tlist)
625 {
627 Var *var;
628
629 if (tent->resjunk)
630 continue;
631
633 result = lappend(result, var);
634 }
635
636 return result;
637}
638
639
640
641
642
643
644
645
648 Node *testexpr,
649 List *subst_nodes)
650{
652
656}
657
661{
662 if (node == NULL)
663 return NULL;
665 {
667
669 {
670 if (param->paramid <= 0 ||
672 elog(ERROR, "unexpected PARAM_SUBLINK ID: %d", param->paramid);
673
674
675
676
677
678
681 }
682 }
684 {
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703 return node;
704 }
706}
707
708
709
710
711
712
713
714static bool
716{
717 Size hashtablesize;
718
719
720
721
722
723
725 plan->plan_width,
726 unknownEqFalse);
728 return false;
729
730 return true;
731}
732
733
734
735
736
737
738static bool
740{
741 Size hashtablesize;
742
743
744
745
746
747
749 path->pathtarget->width,
750 unknownEqFalse);
752 return false;
753
754 return true;
755}
756
757
758
759
760
761
762
763static bool
765{
766
767
768
769
770 if (testexpr && IsA(testexpr, OpExpr))
771 {
773 return true;
774 }
776 {
778
780 {
782
784 return false;
786 return false;
787 }
788 return true;
789 }
790
791 return false;
792}
793
794static bool
796{
797
798
799
800
801
802
803
804
806 return false;
807
808
809
810
811
812
813
814
815
816
817
818
820 return false;
822 return false;
824 return false;
825 return true;
826}
827
828
829
830
831
832
833
834static bool
836{
838
839
841 return false;
842 if (opid == ARRAY_EQ_OP ||
843 opid == RECORD_EQ_OP)
844 {
845
847
849 }
850 else
851 {
852
855
858 elog(ERROR, "cache lookup failed for operator %u", opid);
860 if (!optup->oprcanhash || (optup->oprcode))
861 {
863 return false;
864 }
866 return true;
867 }
868}
869
870
871
872
873
874
875
876
877
878
879
880
881
882void
884{
886
888
889 foreach(lc, root->parse->cteList)
890 {
896 Path *best_path;
899 int paramid;
900
901
902
903
904 if (cte->cterefcount == 0 && cmdType == CMD_SELECT)
905 {
906
908 continue;
909 }
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
944 cte->cterefcount == 1)) &&
945 !cte->cterecursive &&
948 (cte->cterefcount <= 1 ||
951 {
953
955 continue;
956 }
957
958
959
960
961
963
964
966
967
968
969
970
973 root, cte->cterecursive, 0.0, NULL);
974
975
976
977
978
979
980 if (root->plan_params)
981 elog(ERROR, "unexpected outer reference in CTE query");
982
983
984
985
986
989
991
992
993
994
995
996
997
1007
1008
1009
1010
1011
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1034
1035
1036
1037
1039 root->glob->subpaths = lappend(root->glob->subpaths, best_path);
1040 root->glob->subroots = lappend(root->glob->subroots, subroot);
1042
1044
1046
1047
1049 }
1050}
1051
1052
1053
1054
1055
1056
1057static bool
1059{
1061}
1062
1063static bool
1065{
1066 if (node == NULL)
1067 return false;
1069 {
1071
1074 return true;
1075
1077 }
1079}
1080
1081
1082
1083
1084static bool
1086{
1087 Index depth = 0;
1088
1089
1090
1091
1092
1094
1096}
1097
1098static bool
1100{
1101 if (node == NULL)
1102 return false;
1104 {
1106
1107
1108
1109
1110
1112 rte->self_reference &&
1114 return true;
1115 return false;
1116 }
1118 {
1119
1121 bool result;
1122
1123 (*depth)++;
1124
1127
1128 (*depth)--;
1129
1130 return result;
1131 }
1133}
1134
1135
1136
1137
1138static void
1140{
1142
1144
1147
1149}
1150
1151static bool
1153{
1154 if (node == NULL)
1155 return false;
1157 {
1159
1161
1162
1163
1164
1165
1166
1169
1171
1172 return false;
1173 }
1175 {
1177
1181 {
1182
1183
1184
1185
1186
1188
1191
1192
1193
1194
1195
1196
1197
1198
1199
1202 rte->security_barrier = false;
1203
1204
1207 rte->self_reference = false;
1208 rte->coltypes = NIL;
1209 rte->coltypmods = NIL;
1210 rte->colcollations = NIL;
1211 }
1212
1213 return false;
1214 }
1215
1217}
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1230{
1232 Node *leftop;
1233 Node *rightop;
1234 Oid opno;
1236 Oid inputcollid;
1238
1239
1240
1241
1242
1246 values->limitCount != NULL ||
1247 values->limitOffset != NULL ||
1250 return NULL;
1251
1255 opno = ((OpExpr *) testexpr)->opno;
1256 inputcollid = ((OpExpr *) testexpr)->inputcollid;
1257
1258
1259
1260
1261
1265 return NULL;
1266
1268 {
1271
1272
1273
1274
1275
1277
1278
1279
1280
1281
1283
1284
1285
1286
1287
1289 return NULL;
1290
1292 }
1293
1294
1296 linitial_oid(rte->colcollations), inputcollid,
1297 exprs, false);
1298}
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1336 Relids available_rels)
1337{
1341 Relids upper_varnos;
1342 int rtindex;
1346 List *subquery_vars;
1347 Node *quals;
1349 Relids sub_ref_outer_relids;
1350 bool use_lateral;
1351
1353
1354
1355
1356
1357
1359 use_lateral = (sub_ref_outer_relids);
1360
1361
1362
1363
1364
1365 if ((sub_ref_outer_relids, available_rels))
1366 return NULL;
1367
1368
1369
1370
1371
1372
1375 return NULL;
1376
1377
1378
1379
1380 if ((upper_varnos, available_rels))
1381 return NULL;
1382
1383
1384
1385
1387 return NULL;
1388
1389
1391
1392
1393
1394
1395
1396
1397
1398
1399
1401 subselect,
1402 NULL,
1403 use_lateral,
1404 false);
1405 rte = nsitem->p_rte;
1408
1409
1410
1411
1413 rtr->rtindex = rtindex;
1414
1415
1416
1417
1420 rtindex);
1421
1422
1423
1424
1426
1427
1428
1429
1433 result->larg = NULL;
1434 result->rarg = (Node *) rtr;
1435 result->usingClause = NIL;
1436 result->join_using_alias = NULL;
1437 result->quals = quals;
1438 result->alias = NULL;
1439 result->rtindex = 0;
1440
1441 return result;
1442}
1443
1444
1445
1446
1447
1448
1449
1450
1453 bool under_not, Relids available_rels)
1454{
1458 Node *whereClause;
1460 int rtoffset;
1461 int varno;
1462 Relids clause_varnos;
1463 Relids upper_varnos;
1464
1466
1467
1468
1469
1470
1471
1472
1473
1474
1476 return NULL;
1477
1478
1479
1480
1481
1483
1484
1485
1486
1487
1488
1489
1491 return NULL;
1492
1493
1494
1495
1496
1497
1500
1501
1502
1503
1504
1506 return NULL;
1507
1508
1509
1510
1511
1513 return NULL;
1514
1515
1516
1517
1519 return NULL;
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537 MemSet(&subroot, 0, sizeof(subroot));
1538 subroot.type = T_PlannerInfo;
1539 subroot.glob = root->glob;
1540 subroot.parse = subselect;
1543
1544
1545
1546
1549
1550
1551
1552
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1573
1574
1575
1576
1577
1578
1581
1582
1583
1584
1585
1586
1587
1589 upper_varnos = NULL;
1590 varno = -1;
1591 while ((varno = bms_next_member(clause_varnos, varno)) >= 0)
1592 {
1593 if (varno <= rtoffset)
1595 }
1598
1599
1600
1601
1602
1603 if ((upper_varnos, available_rels))
1604 return NULL;
1605
1606
1607
1608
1609
1611 subselect->rtable, subselect->rteperminfos);
1612
1613
1614
1615
1619 result->larg = NULL;
1620
1623 else
1625 result->usingClause = NIL;
1626 result->join_using_alias = NULL;
1627 result->quals = whereClause;
1628 result->alias = NULL;
1629 result->rtindex = 0;
1630
1631 return result;
1632}
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650static bool
1652{
1654
1655
1656
1657
1658
1659
1660
1661
1662
1665 query->hasAggs ||
1667 query->hasWindowFuncs ||
1668 query->hasTargetSRFs ||
1669 query->hasModifyingCTE ||
1673 return false;
1674
1675
1676
1677
1678
1679
1680
1681
1683 {
1684
1685
1686
1687
1688
1689
1690
1693
1694
1696
1698 return false;
1699
1700 limit = (Const *) node;
1702 if (!limit->constisnull && DatumGetInt64(limit->constvalue) <= 0)
1703 return false;
1704
1705
1707 }
1708
1709
1710
1711
1712
1713
1714
1715
1721 query->hasDistinctOn = false;
1722
1723
1724
1725
1726
1727 foreach(lc, query->rtable)
1728 {
1730
1731
1732
1733
1734
1735
1737 {
1738 Assert(query->hasGroupRTE);
1740 query->hasGroupRTE = false;
1741 break;
1742 }
1743 }
1744
1745 return true;
1746}
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1764 Node **testexpr, List **paramIds)
1765{
1766 Node *whereClause;
1768 List *leftargs,
1769 *rightargs,
1770 *opids,
1771 *opcollations,
1772 *newWhere,
1773 *tlist,
1774 *testlist,
1775 *paramids;
1777 *rc,
1778 *oc,
1779 *cc;
1781
1782
1783
1784
1785
1787
1788
1789
1790
1791
1792
1795
1796
1797
1798
1799
1800
1801
1802
1803
1805 return NULL;
1806
1807
1808
1809
1811 return NULL;
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831 MemSet(&subroot, 0, sizeof(subroot));
1832 subroot.type = T_PlannerInfo;
1834 subroot.parse = subselect;
1838
1839
1840
1841
1842
1843
1844
1845
1846 leftargs = rightargs = opids = opcollations = newWhere = NIL;
1847 foreach(lc, (List *) whereClause)
1848 {
1850
1853 {
1856
1858 {
1859 leftargs = lappend(leftargs, leftarg);
1860 rightargs = lappend(rightargs, rightarg);
1862 opcollations = lappend_oid(opcollations, expr->inputcollid);
1863 continue;
1864 }
1866 {
1867
1868
1869
1870
1871
1872
1875 {
1876 leftargs = lappend(leftargs, rightarg);
1877 rightargs = lappend(rightargs, leftarg);
1879 opcollations = lappend_oid(opcollations, expr->inputcollid);
1880 continue;
1881 }
1882
1883 return NULL;
1884 }
1885 }
1886
1887 newWhere = lappend(newWhere, expr);
1888 }
1889
1890
1891
1892
1893 if (leftargs == NIL)
1894 return NULL;
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1907 return NULL;
1908 if (root->parse->hasAggs &&
1911 return NULL;
1912
1913
1914
1915
1916
1917
1918
1920 return NULL;
1921
1922
1923
1924
1925
1927 return NULL;
1928
1929
1930
1931
1933
1934
1935
1936
1937 if (newWhere)
1939
1940
1941
1942
1943
1944
1945
1946 tlist = testlist = paramids = NIL;
1947 resno = 1;
1948 forfour(lc, leftargs, rc, rightargs, oc, opids, cc, opcollations)
1949 {
1955
1962 resno++,
1963 NULL,
1964 false));
1965 testlist = lappend(testlist,
1967 (Expr *) leftarg, (Expr *) param,
1970 }
1971
1972
1975 *paramIds = paramids;
1976
1977 return subselect;
1978}
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2008{
2009
2011}
2012
2013static Node *
2015{
2016 if (node == NULL)
2017 return NULL;
2019 {
2020 if (((Var *) node)->varlevelsup > 0)
2022 }
2024 {
2028 }
2030 {
2031 if (((Aggref *) node)->agglevelsup > 0)
2033 }
2035 {
2036 if (((GroupingFunc *) node)->agglevelsup > 0)
2038 }
2040 {
2044 }
2046 {
2050 }
2052}
2053
2054
2055
2056
2057
2058
2059
2060
2063{
2065
2069}
2070
2071static Node *
2073{
2075
2076 locContext.root = context->root;
2077
2078 if (node == NULL)
2079 return NULL;
2081 {
2083 Node *testexpr;
2084
2085
2086
2087
2088
2091
2092
2093
2094
2099 testexpr,
2101 }
2102
2103
2104
2105
2106
2107
2108
2109
2111 {
2113 return node;
2114 }
2116 {
2117 if (((Aggref *) node)->agglevelsup > 0)
2118 return node;
2119 }
2121 {
2122 if (((GroupingFunc *) node)->agglevelsup > 0)
2123 return node;
2124 }
2126 {
2128 return node;
2129 }
2130
2131
2132
2133
2134
2135
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2155 {
2158
2159
2161
2163 {
2164 Node *newarg;
2165
2169 else
2170 newargs = lappend(newargs, newarg);
2171 }
2173 }
2174
2176 {
2179
2180
2182
2184 {
2185 Node *newarg;
2186
2190 else
2191 newargs = lappend(newargs, newarg);
2192 }
2194 }
2195
2196
2197
2198
2199
2201
2204 &locContext);
2205}
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219void
2221{
2225
2226
2227
2228
2229
2230 if (root->glob->paramExecTypes == NIL)
2231 return;
2232
2233
2234
2235
2236
2237
2238
2239 outer_params = NULL;
2240 for (proot = root->parent_root; proot != NULL; proot = proot->parent_root)
2241 {
2242
2243
2244
2246 {
2248
2250 }
2251
2253 {
2256
2257 foreach(l2, initsubplan->setParam)
2258 {
2260 }
2261 }
2262
2265 }
2266 root->outer_params = outer_params;
2267}
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283void
2285{
2286 Cost initplan_cost;
2287 bool unsafe_initplans;
2289
2290
2291 if (root->init_plans == NIL)
2292 return;
2293
2294
2295
2296
2297
2299 &initplan_cost, &unsafe_initplans);
2300
2301
2302
2303
2304 foreach(lc, final_rel->pathlist)
2305 {
2307
2310 if (unsafe_initplans)
2312 }
2313
2314
2315
2316
2317
2318 if (unsafe_initplans)
2319 {
2322 }
2323 else
2324 {
2326 {
2328
2331 }
2332 }
2333
2334
2335}
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347void
2349 Cost *initplan_cost_p,
2350 bool *unsafe_initplans_p)
2351{
2352 Cost initplan_cost;
2353 bool unsafe_initplans;
2355
2356
2357
2358
2359
2360
2361 initplan_cost = 0;
2362 unsafe_initplans = false;
2363 foreach(lc, init_plans)
2364 {
2366
2369 unsafe_initplans = true;
2370 }
2371 *initplan_cost_p = initplan_cost;
2372 *unsafe_initplans_p = unsafe_initplans;
2373}
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388void
2390{
2391 plan->initPlan = root->init_plans;
2392}
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403void
2405{
2406
2408}
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2443 int gather_param,
2446{
2448 int locally_added_param;
2454
2455 if (plan == NULL)
2456 return NULL;
2457
2459 context.paramids = NULL;
2460 locally_added_param = -1;
2461 nestloop_params = NULL;
2462
2463
2464
2465
2466
2467
2468 initExtParam = initSetParam = NULL;
2469 foreach(l, plan->initPlan)
2470 {
2474
2476 foreach(l2, initsubplan->setParam)
2477 {
2479 }
2480 }
2481
2482
2483 if (initSetParam)
2484 valid_params = bms_union(valid_params, initSetParam);
2485
2486
2487
2488
2489
2490
2491
2492
2493
2496
2497
2498
2499
2500
2501 if (plan->parallel_aware)
2502 {
2503 if (gather_param < 0)
2504 elog(ERROR, "parallel-aware plan node is not below a Gather");
2507 }
2508
2509
2511 {
2512 case T_Result:
2514 &context);
2515 break;
2516
2517 case T_SeqScan:
2519 break;
2520
2521 case T_SampleScan:
2523 &context);
2525 break;
2526
2527 case T_IndexScan:
2529 &context);
2531 &context);
2532
2533
2534
2535
2536
2537
2539 break;
2540
2541 case T_IndexOnlyScan:
2543 &context);
2545 &context);
2547 &context);
2548
2549
2550
2551
2553 break;
2554
2555 case T_BitmapIndexScan:
2557 &context);
2558
2559
2560
2561
2562
2563 break;
2564
2565 case T_BitmapHeapScan:
2567 &context);
2569 break;
2570
2571 case T_TidScan:
2573 &context);
2575 break;
2576
2577 case T_TidRangeScan:
2579 &context);
2581 break;
2582
2583 case T_SubqueryScan:
2584 {
2588
2589
2592 if (gather_param >= 0)
2594 gather_param);
2596 subquery_params, NULL);
2597
2598
2601
2603 scan_params);
2604 }
2605 break;
2606
2607 case T_FunctionScan:
2608 {
2611
2612
2613
2614
2615
2616
2617
2619 {
2622
2623 funccontext = context;
2624 funccontext.paramids = NULL;
2625
2627
2628
2629 rtfunc->funcparams = funccontext.paramids;
2630
2631
2634 }
2635
2637 scan_params);
2638 }
2639 break;
2640
2641 case T_TableFuncScan:
2643 &context);
2645 break;
2646
2647 case T_ValuesScan:
2649 &context);
2651 break;
2652
2653 case T_CteScan:
2654 {
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666 int plan_id = ((CteScan *) plan)->ctePlanId;
2667 Plan *cteplan;
2668
2669
2670 if (plan_id < 1 || plan_id > list_length(root->glob->subplans))
2671 elog(ERROR, "could not find plan for CteScan referencing plan ID %d",
2672 plan_id);
2673 cteplan = (Plan *) list_nth(root->glob->subplans, plan_id - 1);
2676
2677#ifdef NOT_USED
2678
2682#endif
2683
2685 scan_params);
2686 }
2687 break;
2688
2689 case T_WorkTableScan:
2694 break;
2695
2696 case T_NamedTuplestoreScan:
2698 break;
2699
2700 case T_ForeignScan:
2701 {
2703
2705 &context);
2707 &context);
2708
2709
2711 scan_params);
2712 }
2713 break;
2714
2715 case T_CustomScan:
2716 {
2719
2721 &context);
2722
2725
2726
2728 {
2733 gather_param,
2734 valid_params,
2735 scan_params));
2736 }
2737 }
2738 break;
2739
2740 case T_ModifyTable:
2741 {
2743
2744
2745 locally_added_param = mtplan->epqParam;
2747 locally_added_param);
2749 locally_added_param);
2751 &context);
2753 &context);
2755 &context);
2756
2757 }
2758 break;
2759
2760 case T_Append:
2761 {
2762 foreach(l, ((Append *) plan)->appendplans)
2763 {
2768 gather_param,
2769 valid_params,
2770 scan_params));
2771 }
2772 }
2773 break;
2774
2775 case T_MergeAppend:
2776 {
2778 {
2783 gather_param,
2784 valid_params,
2785 scan_params));
2786 }
2787 }
2788 break;
2789
2790 case T_BitmapAnd:
2791 {
2793 {
2798 gather_param,
2799 valid_params,
2800 scan_params));
2801 }
2802 }
2803 break;
2804
2805 case T_BitmapOr:
2806 {
2807 foreach(l, ((BitmapOr *) plan)->bitmapplans)
2808 {
2813 gather_param,
2814 valid_params,
2815 scan_params));
2816 }
2817 }
2818 break;
2819
2820 case T_NestLoop:
2821 {
2823 &context);
2824
2826 {
2828
2831 }
2832 }
2833 break;
2834
2835 case T_MergeJoin:
2837 &context);
2839 &context);
2840 break;
2841
2842 case T_HashJoin:
2844 &context);
2846 &context);
2847 break;
2848
2849 case T_Hash:
2851 &context);
2852 break;
2853
2854 case T_Limit:
2856 &context);
2858 &context);
2859 break;
2860
2861 case T_RecursiveUnion:
2862
2865 locally_added_param);
2866
2867 break;
2868
2869 case T_LockRows:
2870
2871 locally_added_param = ((LockRows *) plan)->epqParam;
2873 locally_added_param);
2875 locally_added_param);
2876 break;
2877
2878 case T_Agg:
2879 {
2881
2882
2883
2884
2885
2887 {
2889
2893 &aggcontext);
2895 &aggcontext);
2897 }
2898 }
2899 break;
2900
2901 case T_WindowAgg:
2903 &context);
2905 &context);
2906 break;
2907
2908 case T_Gather:
2909
2910 locally_added_param = ((Gather *) plan)->rescan_param;
2911 if (locally_added_param >= 0)
2912 {
2914 locally_added_param);
2915
2916
2917
2918
2919
2920
2921 Assert(gather_param < 0);
2922
2923 gather_param = locally_added_param;
2924 }
2925
2926 break;
2927
2928 case T_GatherMerge:
2929
2930 locally_added_param = ((GatherMerge *) plan)->rescan_param;
2931 if (locally_added_param >= 0)
2932 {
2934 locally_added_param);
2935
2936
2937
2938
2939
2940
2941 Assert(gather_param < 0);
2942
2943 gather_param = locally_added_param;
2944 }
2945
2946 break;
2947
2948 case T_Memoize:
2950 &context);
2951 break;
2952
2953 case T_ProjectSet:
2954 case T_Material:
2955 case T_Sort:
2956 case T_IncrementalSort:
2957 case T_Unique:
2958 case T_SetOp:
2959 case T_Group:
2960
2961 break;
2962
2963 default:
2964 elog(ERROR, "unrecognized node type: %d",
2966 }
2967
2968
2970 plan->lefttree,
2971 gather_param,
2972 valid_params,
2973 scan_params);
2975
2976 if (nestloop_params)
2977 {
2978
2980 plan->righttree,
2981 gather_param,
2982 bms_union(nestloop_params, valid_params),
2983 scan_params);
2984
2985 child_params = bms_difference(child_params, nestloop_params);
2987 }
2988 else
2989 {
2990
2992 plan->righttree,
2993 gather_param,
2994 valid_params,
2995 scan_params);
2996 }
2998
2999
3000
3001
3002
3003
3004
3005 if (locally_added_param >= 0)
3006 {
3008 locally_added_param);
3009 }
3010
3011
3012
3014 elog(ERROR, "plan should not reference subplan's variable");
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3027
3029
3031
3032 return plan->allParam;
3033}
3034
3035
3036
3037
3038
3039static bool
3041{
3042 if (node == NULL)
3043 return false;
3045 {
3047 {
3048 int paramid = ((Param *) node)->paramid;
3049
3051 }
3052 return false;
3053 }
3055 {
3056
3057
3058
3059
3060
3061
3062
3063
3065 Param *aggparam;
3066
3068 if (aggparam != NULL)
3071
3072 }
3074 {
3079
3080
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091 foreach(lc, subplan->paramIds)
3092 {
3095 }
3096
3097
3099
3100
3101
3102
3103
3104
3106 foreach(lc, subplan->parParam)
3107 {
3109 }
3111
3112 return false;
3113 }
3115}
3116
3117
3118
3119
3120
3121
3122static bool
3124{
3125 if (node == NULL)
3126 return false;
3128 {
3130
3131
3134 return false;
3135 }
3137}
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3150 Oid resulttype, int32 resulttypmod,
3151 Oid resultcollation)
3152{
3154 resulttypmod, resultcollation);
3155}
3156
3157
3158
3159
3160
3161
3162
3163
3164void
3168{
3170
3171
3172
3173
3174
3175
3176
3177
3179 root->glob->subpaths = lappend(root->glob->subpaths, NULL);
3180 root->glob->subroots = lappend(root->glob->subroots, subroot);
3181
3182
3183
3184
3185
3186
3196
3198
3199
3200
3201
3202
3203
3204
3206}
3207
3208
3209
3210
3211static const char *
3213{
3214 switch (subLinkType)
3215 {
3217 return "exists";
3219 return "all";
3221 return "any";
3223 return "rowcompare";
3225 return "expr";
3227 return "multiexpr";
3229 return "array";
3231 return "cte";
3232 }
3234 return "???";
3235}
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
int bms_next_member(const Bitmapset *a, int prevbit)
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_del_member(Bitmapset *a, int x)
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
void bms_free(Bitmapset *a)
Bitmapset * bms_add_member(Bitmapset *a, int x)
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Bitmapset * bms_copy(const Bitmapset *a)
static Datum values[MAXATTR]
#define MemSet(start, val, len)
#define OidIsValid(objectId)
Node * eval_const_expressions(PlannerInfo *root, Node *node)
bool contain_subplans(Node *clause)
ScalarArrayOpExpr * make_SAOP_expr(Oid oper, Node *leftexpr, Oid coltype, Oid arraycollid, Oid inputcollid, List *exprs, bool haveNonConst)
bool contain_volatile_functions(Node *clause)
bool contain_exec_param(Node *clause, List *param_ids)
void cost_subplan(PlannerInfo *root, SubPlan *subplan, Plan *plan)
Plan * materialize_finished_plan(Plan *subplan)
Plan * create_plan(PlannerInfo *root, Path *best_path)
bool ExecMaterializesOutput(NodeTag plantype)
char * format_type_be(Oid type_oid)
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
List * lappend(List *list, void *datum)
List * list_concat(List *list1, const List *list2)
List * list_delete_cell(List *list, ListCell *cell)
List * list_copy(const List *oldlist)
List * lappend_int(List *list, int datum)
List * lappend_oid(List *list, Oid datum)
bool op_hashjoinable(Oid opno, Oid inputtype)
bool func_strict(Oid funcid)
Oid get_promoted_array_type(Oid typid)
Oid get_commutator(Oid opno)
Expr * make_orclause(List *orclauses)
Expr * make_ands_explicit(List *andclauses)
Var * makeVarFromTargetEntry(int varno, TargetEntry *tle)
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Expr * make_andclause(List *andclauses)
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
List * make_ands_implicit(Expr *clause)
Oid exprType(const Node *expr)
int32 exprTypmod(const Node *expr)
Oid exprCollation(const Node *expr)
#define expression_tree_mutator(n, m, c)
static bool is_andclause(const void *clause)
static bool is_orclause(const void *clause)
#define query_tree_walker(q, w, c, f)
#define QTW_EXAMINE_RTES_AFTER
#define expression_tree_walker(n, w, c)
#define QTW_EXAMINE_RTES_BEFORE
size_t get_hash_memory_limit(void)
Size EstimateSubplanHashTableSpace(double nentries, Size tupleWidth, bool unknownEqFalse)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
Param * replace_outer_merge_support(PlannerInfo *root, MergeSupportFunc *msf)
Param * generate_new_exec_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod, Oid paramcollation)
Param * replace_outer_agg(PlannerInfo *root, Aggref *agg)
Param * replace_outer_returning(PlannerInfo *root, ReturningExpr *rexpr)
Param * replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp)
Param * replace_outer_var(PlannerInfo *root, Var *var)
Param * replace_outer_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
int assign_special_exec_param(PlannerInfo *root)
ParseState * make_parsestate(ParseState *parentParseState)
ParseNamespaceItem * addRangeTableEntryForSubquery(ParseState *pstate, Query *subquery, Alias *alias, bool lateral, bool inFromCl)
#define planner_subplan_get_plan(root, subplan)
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define linitial_node(type, l)
static void * list_nth(const List *list, int n)
static ListCell * list_nth_cell(const List *list, int n)
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
#define list_make1_int(x1)
#define list_make2(x1, x2)
FormData_pg_operator * Form_pg_operator
char * choose_plan_name(PlannerGlobal *glob, const char *name, bool always_number)
PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, char *plan_name, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction, SetOperationStmt *setops)
Path * get_cheapest_fractional_path(RelOptInfo *rel, double tuple_fraction)
static int64 DatumGetInt64(Datum X)
static Datum ObjectIdGetDatum(Oid X)
void replace_empty_jointree(Query *parse)
Query * preprocess_relation_rtes(PlannerInfo *root)
Expr * canonicalize_qual(Expr *qual, bool is_check)
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
void OffsetVarNodes(Node *node, int offset, int sublevels_up)
void CombineRangeTables(List **dst_rtable, List **dst_perminfos, List *src_rtable, List *src_perminfos)
bool contain_aggs_of_level(Node *node, int levelsup)
void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, int min_sublevels_up)
Param * find_minmax_agg_replacement_param(PlannerInfo *root, Aggref *aggref)
CTEMaterialize ctematerialized
struct Path * cheapest_total_path
JoinExpr * convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink, Relids available_rels)
static bool contain_dml_walker(Node *node, void *context)
static bool subpath_is_hashable(Path *path, bool unknownEqFalse)
static bool subplan_is_hashable(Plan *plan, bool unknownEqFalse)
static bool testexpr_is_hashable(Node *testexpr, List *param_ids)
Node * SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual)
void SS_process_ctes(PlannerInfo *root)
static const char * sublinktype_to_string(SubLinkType subLinkType)
void SS_identify_outer_params(PlannerInfo *root)
static bool finalize_agg_primnode(Node *node, finalize_primnode_context *context)
static bool contain_outer_selfref(Node *node)
static List * generate_subquery_vars(PlannerInfo *root, List *tlist, Index varno)
Node * SS_replace_correlation_vars(PlannerInfo *root, Node *expr)
static bool contain_dml(Node *node)
void SS_finalize_plan(PlannerInfo *root, Plan *plan)
static Query * convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect, Node **testexpr, List **paramIds)
static Node * process_sublinks_mutator(Node *node, process_sublinks_context *context)
struct process_sublinks_context process_sublinks_context
static Node * replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
static bool test_opexpr_is_hashable(OpExpr *testexpr, List *param_ids)
static List * generate_subquery_params(PlannerInfo *root, List *tlist, List **paramIds)
static Node * convert_testexpr(PlannerInfo *root, Node *testexpr, List *subst_nodes)
static Node * make_subplan(PlannerInfo *root, Query *orig_subquery, SubLinkType subLinkType, int subLinkId, Node *testexpr, bool isTopQual)
static bool contain_outer_selfref_walker(Node *node, Index *depth)
struct convert_testexpr_context convert_testexpr_context
static bool hash_ok_operator(OpExpr *expr)
ScalarArrayOpExpr * convert_VALUES_to_ANY(PlannerInfo *root, Node *testexpr, Query *values)
static void inline_cte(PlannerInfo *root, CommonTableExpr *cte)
static bool simplify_EXISTS_query(PlannerInfo *root, Query *query)
struct finalize_primnode_context finalize_primnode_context
static bool finalize_primnode(Node *node, finalize_primnode_context *context)
static void get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod, Oid *colcollation)
static bool inline_cte_walker(Node *node, inline_cte_walker_context *context)
void SS_attach_initplans(PlannerInfo *root, Plan *plan)
JoinExpr * convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink, bool under_not, Relids available_rels)
void SS_compute_initplan_cost(List *init_plans, Cost *initplan_cost_p, bool *unsafe_initplans_p)
void SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
static Node * convert_testexpr_mutator(Node *node, convert_testexpr_context *context)
Param * SS_make_initplan_output_param(PlannerInfo *root, Oid resulttype, int32 resulttypmod, Oid resultcollation)
struct inline_cte_walker_context inline_cte_walker_context
static Node * build_subplan(PlannerInfo *root, Plan *plan, Path *path, PlannerInfo *subroot, List *plan_params, SubLinkType subLinkType, int subLinkId, Node *testexpr, List *testexpr_paramids, bool unknownEqFalse)
void SS_make_initplan_from_plan(PlannerInfo *root, PlannerInfo *subroot, Plan *plan, Param *prm)
static Bitmapset * finalize_plan(PlannerInfo *root, Plan *plan, int gather_param, Bitmapset *valid_params, Bitmapset *scan_params)
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
bool contain_vars_of_level(Node *node, int levelsup)
bool contain_var_clause(Node *node)
Relids pull_varnos_of_level(PlannerInfo *root, Node *node, int levelsup)
Relids pull_varnos(PlannerInfo *root, Node *node)