PostgreSQL Source Code: src/backend/optimizer/util/pathnode.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
17#include <math.h>
18
33
34typedef enum
35{
41
42
43
44
45
46
47#define STD_FUZZ_FACTOR 1.01
48
53 List *pathlist,
57
58
59
60
61
62
63
64
65
66
67
68int
70{
71
73 {
75 return -1;
76 else
77 return +1;
78 }
79
81 {
83 return -1;
85 return +1;
86
87
88
89
90
92 return -1;
94 return +1;
95 }
96 else
97 {
99 return -1;
101 return +1;
102
103
104
105
107 return -1;
109 return +1;
110 }
111 return 0;
112}
113
114
115
116
117
118
119
120
121
122
123int
125 double fraction)
126{
128 cost2;
129
130
132 {
134 return -1;
135 else
136 return +1;
137 }
138
139 if (fraction <= 0.0 || fraction >= 1.0)
145 if (cost1 < cost2)
146 return -1;
147 if (cost1 > cost2)
148 return +1;
149 return 0;
150}
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
183{
184#define CONSIDER_PATH_STARTUP_COST(p) \
185 ((p)->param_info == NULL ? (p)->parent->consider_startup : (p)->parent->consider_param_startup)
186
187
189 {
192 else
194 }
195
196
197
198
199
201 {
202
205 {
206
208 }
209
211 }
213 {
214
217 {
218
220 }
221
223 }
224
226 {
227
229 }
231 {
232
234 }
235
237
238#undef CONSIDER_PATH_STARTUP_COST
239}
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268void
270{
271 Path *cheapest_startup_path;
272 Path *cheapest_total_path;
273 Path *best_param_path;
274 List *parameterized_paths;
276
278
280 elog(ERROR, "could not devise a query plan for the given query");
281
282 cheapest_startup_path = cheapest_total_path = best_param_path = NULL;
283 parameterized_paths = NIL;
284
285 foreach(p, parent_rel->pathlist)
286 {
289
290 if (path->param_info)
291 {
292
293 parameterized_paths = lappend(parameterized_paths, path);
294
295
296
297
298
299 if (cheapest_total_path)
300 continue;
301
302
303
304
305
306
307 if (best_param_path == NULL)
308 best_param_path = path;
309 else
310 {
313 {
315
318 best_param_path = path;
319 break;
321
322 best_param_path = path;
323 break;
325
326 break;
328
329
330
331
332
333
334 break;
335 }
336 }
337 }
338 else
339 {
340
341 if (cheapest_total_path == NULL)
342 {
343 cheapest_startup_path = cheapest_total_path = path;
344 continue;
345 }
346
347
348
349
350
351
352
353
355 if (cmp > 0 ||
356 (cmp == 0 &&
359 cheapest_startup_path = path;
360
362 if (cmp > 0 ||
363 (cmp == 0 &&
366 cheapest_total_path = path;
367 }
368 }
369
370
371 if (cheapest_total_path)
372 parameterized_paths = lcons(cheapest_total_path, parameterized_paths);
373
374
375
376
377
378 if (cheapest_total_path == NULL)
379 cheapest_total_path = best_param_path;
380 Assert(cheapest_total_path != NULL);
381
386}
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460void
462{
463 bool accept_new = true;
464 int insert_at = 0;
465 List *new_path_pathkeys;
467
468
469
470
471
473
474
475 new_path_pathkeys = new_path->param_info ? NIL : new_path->pathkeys;
476
477
478
479
480
481
482 foreach(p1, parent_rel->pathlist)
483 {
485 bool remove_old = false;
489
490
491
492
495
496
497
498
499
500
501
502
503
504
505
506
508 {
509
510 List *old_path_pathkeys;
511
512 old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys;
514 old_path_pathkeys);
516 {
517 switch (costcmp)
518 {
523 {
526 new_path->rows <= old_path->rows &&
528 remove_old = true;
529 }
531 {
534 new_path->rows >= old_path->rows &&
536 accept_new = false;
537 }
538 else
539 {
541 {
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
559 remove_old = true;
562 accept_new = false;
563 else if (new_path->rows < old_path->rows)
564 remove_old = true;
565 else if (new_path->rows > old_path->rows)
566 accept_new = false;
568 old_path,
570 remove_old = true;
571 else
572 accept_new = false;
573
574 }
576 new_path->rows <= old_path->rows &&
578 remove_old = true;
580 new_path->rows >= old_path->rows &&
582 accept_new = false;
583
584 }
585 break;
588 {
593 new_path->rows <= old_path->rows &&
595 remove_old = true;
596 }
597 break;
600 {
605 new_path->rows >= old_path->rows &&
607 accept_new = false;
608 }
609 break;
611
612
613
614
615
616 break;
617 }
618 }
619 }
620
621
622
623
624 if (remove_old)
625 {
627 p1);
628
629
630
631
634 }
635 else
636 {
637
638
639
640
645 }
646
647
648
649
650
651
652 if (!accept_new)
653 break;
654 }
655
656 if (accept_new)
657 {
658
661 }
662 else
663 {
664
667 }
668}
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687bool
689 Cost startup_cost, Cost total_cost,
690 List *pathkeys, Relids required_outer)
691{
692 List *new_path_pathkeys;
693 bool consider_startup;
695
696
697 new_path_pathkeys = required_outer ? NIL : pathkeys;
698
699
701
702 foreach(p1, parent_rel->pathlist)
703 {
706
707
708
709
710
711
712
714 {
715 if (disabled_nodes < old_path->disabled_nodes)
716 break;
717 }
718 else if (total_cost <= old_path->total_cost * STD_FUZZ_FACTOR)
719 break;
720
721
722
723
724
725
726
727
728
729
731 !consider_startup)
732 {
733
734 List *old_path_pathkeys;
735
736 old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys;
738 old_path_pathkeys);
741 {
742
744 {
745
746 return false;
747 }
748 }
749 }
750 }
751
752 return true;
753}
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794void
796{
797 bool accept_new = true;
798 int insert_at = 0;
800
801
803
804
806
807
809
810
811
812
813
815 {
817 bool remove_old = false;
819
820
822
823
825 {
827 {
829 accept_new = false;
830 else
831 remove_old = true;
832 }
835 {
836
838 accept_new = false;
839 }
842 {
843
845 remove_old = true;
846 }
848 {
849
850 remove_old = true;
851 }
853 {
854
855 accept_new = false;
856 }
858 {
859
860 remove_old = true;
861 }
862 else
863 {
864
865
866
867
868 accept_new = false;
869 }
870 }
871
872
873
874
875 if (remove_old)
876 {
880 }
881 else
882 {
883
886 }
887
888
889
890
891
892
893 if (!accept_new)
894 break;
895 }
896
897 if (accept_new)
898 {
899
902 }
903 else
904 {
905
907 }
908}
909
910
911
912
913
914
915
916
917
918
919
920bool
922 Cost total_cost, List *pathkeys)
923{
925
926
927
928
929
930
931
932
933
934
935
936
938 {
941
944 {
947 return false;
950 return true;
951 }
952 }
953
954
955
956
957
958
959
960
961
962
963
964
965 if ((parent_rel, disabled_nodes, total_cost, total_cost,
966 pathkeys, NULL))
967 return false;
968
969 return true;
970}
971
972
973
974
975
976
977
978
979
980
981
984 Relids required_outer, int parallel_workers)
985{
987
988 pathnode->pathtype = T_SeqScan;
989 pathnode->parent = rel;
990 pathnode->pathtarget = rel->reltarget;
992 required_outer);
997
999
1000 return pathnode;
1001}
1002
1003
1004
1005
1006
1009{
1011
1012 pathnode->pathtype = T_SampleScan;
1013 pathnode->parent = rel;
1014 pathnode->pathtarget = rel->reltarget;
1016 required_outer);
1020 pathnode->pathkeys = NIL;
1021
1023
1024 return pathnode;
1025}
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1051 List *indexclauses,
1052 List *indexorderbys,
1053 List *indexorderbycols,
1054 List *pathkeys,
1056 bool indexonly,
1057 Relids required_outer,
1058 double loop_count,
1059 bool partial_path)
1060{
1063
1064 pathnode->path.pathtype = indexonly ? T_IndexOnlyScan : T_IndexScan;
1065 pathnode->path.parent = rel;
1068 required_outer);
1073
1079
1080 cost_index(pathnode, root, loop_count, partial_path);
1081
1082 return pathnode;
1083}
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1100 Path *bitmapqual,
1101 Relids required_outer,
1102 double loop_count,
1103 int parallel_degree)
1104{
1106
1108 pathnode->path.parent = rel;
1111 required_outer);
1116
1118
1120 pathnode->path.param_info,
1121 bitmapqual, loop_count);
1122
1123 return pathnode;
1124}
1125
1126
1127
1128
1129
1133 List *bitmapquals)
1134{
1136 Relids required_outer = NULL;
1138
1140 pathnode->path.parent = rel;
1142
1143
1144
1145
1146
1147
1148 foreach(lc, bitmapquals)
1149 {
1151
1154 }
1156 required_outer);
1157
1158
1159
1160
1161
1162
1163
1167
1169
1171
1172
1174
1175 return pathnode;
1176}
1177
1178
1179
1180
1181
1185 List *bitmapquals)
1186{
1188 Relids required_outer = NULL;
1190
1192 pathnode->path.parent = rel;
1194
1195
1196
1197
1198
1199
1200 foreach(lc, bitmapquals)
1201 {
1203
1206 }
1208 required_outer);
1209
1210
1211
1212
1213
1214
1215
1219
1221
1223
1224
1226
1227 return pathnode;
1228}
1229
1230
1231
1232
1233
1236 Relids required_outer)
1237{
1239
1241 pathnode->path.parent = rel;
1244 required_outer);
1249
1250 pathnode->tidquals = tidquals;
1251
1253 pathnode->path.param_info);
1254
1255 return pathnode;
1256}
1257
1258
1259
1260
1261
1262
1265 List *tidrangequals, Relids required_outer)
1266{
1268
1270 pathnode->path.parent = rel;
1273 required_outer);
1278
1280
1282 pathnode->path.param_info);
1283
1284 return pathnode;
1285}
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1302 List *subpaths, List *partial_subpaths,
1303 List *pathkeys, Relids required_outer,
1304 int parallel_workers, bool parallel_aware,
1305 double rows)
1306{
1309
1310 Assert(!parallel_aware || parallel_workers > 0);
1311
1313 pathnode->path.parent = rel;
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1329 rel,
1330 required_outer);
1331 else
1333 required_outer);
1334
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1350 {
1351
1352
1353
1354
1355
1357
1360 }
1363
1364
1365
1366
1367
1370 else
1372
1373 foreach(l, pathnode->subpaths)
1374 {
1376
1379
1380
1382 }
1383
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1397 {
1399
1401 {
1405 }
1406 else
1408
1410 }
1411 else
1413
1414
1415 if (rows >= 0)
1417
1418 return pathnode;
1419}
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430static int
1432{
1435 int cmp;
1436
1438 if (cmp != 0)
1439 return -cmp;
1440 return bms_compare(path1->parent->relids, path2->parent->relids);
1441}
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452static int
1454{
1457 int cmp;
1458
1460 if (cmp != 0)
1461 return -cmp;
1462 return bms_compare(path1->parent->relids, path2->parent->relids);
1463}
1464
1465
1466
1467
1468
1469
1473 List *subpaths,
1474 List *pathkeys,
1475 Relids required_outer)
1476{
1478 int input_disabled_nodes;
1479 Cost input_startup_cost;
1480 Cost input_total_cost;
1482
1483
1484
1485
1486
1488
1490 pathnode->path.parent = rel;
1492 pathnode->path.param_info = NULL;
1497 pathnode->subpaths = subpaths;
1498
1499
1500
1501
1502
1505 else
1507
1508
1509
1510
1512 input_disabled_nodes = 0;
1513 input_startup_cost = 0;
1514 input_total_cost = 0;
1515 foreach(l, subpaths)
1516 {
1518
1519
1521
1525
1527 {
1528
1529 input_disabled_nodes += subpath->disabled_nodes;
1530 input_startup_cost += subpath->startup_cost;
1531 input_total_cost += subpath->total_cost;
1532 }
1533 else
1534 {
1535
1536 Path sort_path;
1537
1540 pathkeys,
1541 subpath->disabled_nodes,
1544 subpath->pathtarget->width,
1545 0.0,
1549 input_startup_cost += sort_path.startup_cost;
1550 input_total_cost += sort_path.total_cost;
1551 }
1552 }
1553
1554
1555
1556
1557
1558
1559
1561 ((Path *) linitial(subpaths))->parallel_aware ==
1563 {
1567 }
1568 else
1571 input_disabled_nodes,
1572 input_startup_cost, input_total_cost,
1574
1575 return pathnode;
1576}
1577
1578
1579
1580
1581
1582
1583
1584
1588{
1590
1592 pathnode->path.parent = rel;
1593 pathnode->path.pathtarget = target;
1594 pathnode->path.param_info = NULL;
1599 pathnode->quals = havingqual;
1600
1601
1602
1603
1604
1605
1610
1611
1612
1613
1614
1615 if (havingqual)
1616 {
1618
1620
1623 }
1624
1625 return pathnode;
1626}
1627
1628
1629
1630
1631
1632
1635{
1637
1639
1641 pathnode->path.parent = rel;
1643 pathnode->path.param_info = subpath->param_info;
1649
1651
1653 subpath->disabled_nodes,
1657 subpath->pathtarget->width);
1658
1659 return pathnode;
1660}
1661
1662
1663
1664
1665
1668 List *param_exprs, List *hash_operators,
1669 bool singlerow, bool binary_mode, double calls)
1670{
1672
1674
1676 pathnode->path.parent = rel;
1678 pathnode->path.param_info = subpath->param_info;
1684
1688 pathnode->singlerow = singlerow;
1691
1692
1693
1694
1695
1696
1697
1699
1700
1703
1704
1705
1706
1707
1711
1712 return pathnode;
1713}
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1729{
1731 Path sort_path;
1732 Path agg_path;
1734 int numCols;
1735
1736
1739
1742
1743
1746
1747
1749 return NULL;
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1762
1764
1766 pathnode->path.parent = rel;
1768 pathnode->path.param_info = subpath->param_info;
1773
1774
1775
1776
1777
1779
1781
1782
1783
1784
1785
1786
1789
1790
1791
1792
1793
1794
1795
1800 {
1807
1809
1811
1812 return pathnode;
1813 }
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1825 {
1827
1829 {
1830 List *sub_tlist_colnos;
1831
1834
1835 if (sub_tlist_colnos &&
1837 sub_tlist_colnos,
1839 {
1846
1848
1850
1851 return pathnode;
1852 }
1853 }
1854 }
1855
1856
1860 NULL,
1861 NULL);
1863
1865 {
1866
1867
1868
1870 subpath->disabled_nodes,
1873 subpath->pathtarget->width,
1874 0.0,
1876 -1.0);
1877
1878
1879
1880
1881
1882
1883
1885 }
1886
1888 {
1889
1890
1891
1892
1893 int hashentrysize = subpath->pathtarget->width + 64;
1894
1896 {
1897
1898
1899
1900
1902 }
1903 else
1906 numCols, pathnode->path.rows,
1908 subpath->disabled_nodes,
1912 subpath->pathtarget->width);
1913 }
1914
1916 {
1921 else
1923 }
1928 else
1929 {
1930
1932 return NULL;
1933 }
1934
1936 {
1940 }
1941 else
1942 {
1946 }
1947
1949
1951
1952 return pathnode;
1953}
1954
1955
1956
1957
1958
1959
1960
1964 Relids required_outer, double *rows)
1965{
1967 int input_disabled_nodes = 0;
1968 Cost input_startup_cost = 0;
1969 Cost input_total_cost = 0;
1970
1973
1974
1975
1976
1977
1978
1979
1980
1982 elog(ERROR, "gather merge input not sufficiently sorted");
1983
1985 pathnode->path.parent = rel;
1987 required_outer);
1989
1993 pathnode->path.pathtarget = target ? target : rel->reltarget;
1994
1995 input_disabled_nodes += subpath->disabled_nodes;
1996 input_startup_cost += subpath->startup_cost;
1997 input_total_cost += subpath->total_cost;
1998
2000 input_disabled_nodes, input_startup_cost,
2001 input_total_cost, rows);
2002
2003 return pathnode;
2004}
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017static List *
2019{
2022
2023 foreach(l, tlist)
2024 {
2026
2027 if (!var || (var, Var) ||
2028 var->varno != relid)
2029 return NIL;
2030
2032 }
2033 return result;
2034}
2035
2036
2037
2038
2039
2040
2041
2042
2046{
2048
2050
2052 pathnode->path.parent = rel;
2053 pathnode->path.pathtarget = target;
2055 required_outer);
2059 pathnode->path.pathkeys = NIL;
2060
2064
2066 {
2070 }
2071
2073
2074 return pathnode;
2075}
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2089 bool trivial_pathtarget,
2090 List *pathkeys, Relids required_outer)
2091{
2093
2095 pathnode->path.parent = rel;
2098 required_outer);
2105
2107 trivial_pathtarget);
2108
2109 return pathnode;
2110}
2111
2112
2113
2114
2115
2116
2119 List *pathkeys, Relids required_outer)
2120{
2122
2123 pathnode->pathtype = T_FunctionScan;
2124 pathnode->parent = rel;
2125 pathnode->pathtarget = rel->reltarget;
2127 required_outer);
2131 pathnode->pathkeys = pathkeys;
2132
2134
2135 return pathnode;
2136}
2137
2138
2139
2140
2141
2142
2145 Relids required_outer)
2146{
2148
2149 pathnode->pathtype = T_TableFuncScan;
2150 pathnode->parent = rel;
2151 pathnode->pathtarget = rel->reltarget;
2153 required_outer);
2157 pathnode->pathkeys = NIL;
2158
2160
2161 return pathnode;
2162}
2163
2164
2165
2166
2167
2168
2171 Relids required_outer)
2172{
2174
2175 pathnode->pathtype = T_ValuesScan;
2176 pathnode->parent = rel;
2177 pathnode->pathtarget = rel->reltarget;
2179 required_outer);
2183 pathnode->pathkeys = NIL;
2184
2186
2187 return pathnode;
2188}
2189
2190
2191
2192
2193
2194
2197 List *pathkeys, Relids required_outer)
2198{
2200
2201 pathnode->pathtype = T_CteScan;
2202 pathnode->parent = rel;
2203 pathnode->pathtarget = rel->reltarget;
2205 required_outer);
2209 pathnode->pathkeys = pathkeys;
2210
2212
2213 return pathnode;
2214}
2215
2216
2217
2218
2219
2220
2223 Relids required_outer)
2224{
2226
2227 pathnode->pathtype = T_NamedTuplestoreScan;
2228 pathnode->parent = rel;
2229 pathnode->pathtarget = rel->reltarget;
2231 required_outer);
2235 pathnode->pathkeys = NIL;
2236
2238
2239 return pathnode;
2240}
2241
2242
2243
2244
2245
2246
2249 Relids required_outer)
2250{
2252
2253 pathnode->pathtype = T_Result;
2254 pathnode->parent = rel;
2255 pathnode->pathtarget = rel->reltarget;
2257 required_outer);
2261 pathnode->pathkeys = NIL;
2262
2264
2265 return pathnode;
2266}
2267
2268
2269
2270
2271
2272
2275 Relids required_outer)
2276{
2278
2279 pathnode->pathtype = T_WorkTableScan;
2280 pathnode->parent = rel;
2281 pathnode->pathtarget = rel->reltarget;
2283 required_outer);
2287 pathnode->pathkeys = NIL;
2288
2289
2291
2292 return pathnode;
2293}
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2309 double rows, int disabled_nodes,
2310 Cost startup_cost, Cost total_cost,
2311 List *pathkeys,
2312 Relids required_outer,
2313 Path *fdw_outerpath,
2314 List *fdw_restrictinfo,
2315 List *fdw_private)
2316{
2318
2319
2321
2323 pathnode->path.parent = rel;
2324 pathnode->path.pathtarget = target ? target : rel->reltarget;
2326 required_outer);
2335
2339
2340 return pathnode;
2341}
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2357 double rows, int disabled_nodes,
2358 Cost startup_cost, Cost total_cost,
2359 List *pathkeys,
2360 Relids required_outer,
2361 Path *fdw_outerpath,
2362 List *fdw_restrictinfo,
2363 List *fdw_private)
2364{
2366
2367
2368
2369
2370
2371
2372
2373
2375 elog(ERROR, "parameterized foreign joins are not supported yet");
2376
2378 pathnode->path.parent = rel;
2379 pathnode->path.pathtarget = target ? target : rel->reltarget;
2380 pathnode->path.param_info = NULL;
2389
2393
2394 return pathnode;
2395}
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2411 double rows, int disabled_nodes,
2412 Cost startup_cost, Cost total_cost,
2413 List *pathkeys,
2414 Path *fdw_outerpath,
2415 List *fdw_restrictinfo,
2416 List *fdw_private)
2417{
2419
2420
2421
2422
2423
2425
2427 pathnode->path.parent = rel;
2428 pathnode->path.pathtarget = target ? target : rel->reltarget;
2429 pathnode->path.param_info = NULL;
2438
2442
2443 return pathnode;
2444}
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2457 Relids outer_paramrels,
2459 Relids inner_paramrels)
2460{
2461 Relids required_outer;
2462
2463
2465
2466 if (!inner_paramrels)
2467 return bms_copy(outer_paramrels);
2468
2469 required_outer = bms_union(outer_paramrels, inner_paramrels);
2470
2472 outerrelids);
2473 return required_outer;
2474}
2475
2476
2477
2478
2479
2480
2481
2484{
2489 Relids required_outer;
2490
2491
2492
2493
2494
2495
2496
2497
2498 if (inner_path->parent->top_parent_relids)
2499 innerrelids = inner_path->parent->top_parent_relids;
2500 else
2501 innerrelids = inner_path->parent->relids;
2502
2503 if (outer_path->parent->top_parent_relids)
2504 outerrelids = outer_path->parent->top_parent_relids;
2505 else
2506 outerrelids = outer_path->parent->relids;
2507
2508
2511
2512 required_outer = bms_union(outer_paramrels, inner_paramrels);
2513
2514 return required_outer;
2515}
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2540 Path *outer_path,
2541 Path *inner_path,
2542 List *restrict_clauses,
2543 List *pathkeys,
2544 Relids required_outer)
2545{
2549
2550
2551
2552
2553
2554 if (outer_path->parent->top_parent_relids)
2555 outerrelids = outer_path->parent->top_parent_relids;
2556 else
2557 outerrelids = outer_path->parent->relids;
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567 if (bms_overlap(inner_req_outer, outerrelids))
2568 {
2572
2573 foreach(lc, restrict_clauses)
2574 {
2576
2578 jclauses = lappend(jclauses, rinfo);
2579 }
2580 restrict_clauses = jclauses;
2581 }
2582
2583 pathnode->jpath.path.pathtype = T_NestLoop;
2584 pathnode->jpath.path.parent = joinrel;
2585 pathnode->jpath.path.pathtarget = joinrel->reltarget;
2586 pathnode->jpath.path.param_info =
2588 joinrel,
2589 outer_path,
2590 inner_path,
2592 required_outer,
2593 &restrict_clauses);
2594 pathnode->jpath.path.parallel_aware = false;
2597
2599 pathnode->jpath.path.pathkeys = pathkeys;
2605
2607
2608 return pathnode;
2609}
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2637 Path *outer_path,
2638 Path *inner_path,
2639 List *restrict_clauses,
2640 List *pathkeys,
2641 Relids required_outer,
2642 List *mergeclauses,
2643 List *outersortkeys,
2644 List *innersortkeys,
2645 int outer_presorted_keys)
2646{
2648
2649 pathnode->jpath.path.pathtype = T_MergeJoin;
2650 pathnode->jpath.path.parent = joinrel;
2651 pathnode->jpath.path.pathtarget = joinrel->reltarget;
2652 pathnode->jpath.path.param_info =
2654 joinrel,
2655 outer_path,
2656 inner_path,
2658 required_outer,
2659 &restrict_clauses);
2660 pathnode->jpath.path.parallel_aware = false;
2663
2665 pathnode->jpath.path.pathkeys = pathkeys;
2675
2676
2677
2679
2680 return pathnode;
2681}
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2705 Path *outer_path,
2706 Path *inner_path,
2707 bool parallel_hash,
2708 List *restrict_clauses,
2709 Relids required_outer,
2710 List *hashclauses)
2711{
2713
2714 pathnode->jpath.path.pathtype = T_HashJoin;
2715 pathnode->jpath.path.parent = joinrel;
2716 pathnode->jpath.path.pathtarget = joinrel->reltarget;
2717 pathnode->jpath.path.param_info =
2719 joinrel,
2720 outer_path,
2721 inner_path,
2723 required_outer,
2724 &restrict_clauses);
2725 pathnode->jpath.path.parallel_aware =
2729
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743 pathnode->jpath.path.pathkeys = NIL;
2750
2751
2753
2754 return pathnode;
2755}
2756
2757
2758
2759
2760
2761
2762
2763
2764
2770{
2773
2774
2775
2776
2777
2778
2779
2780
2782 {
2784
2788 }
2789
2791 pathnode->path.parent = rel;
2792 pathnode->path.pathtarget = target;
2793
2794 pathnode->path.param_info = NULL;
2797 subpath->parallel_safe &&
2800
2802
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814 oldtarget = subpath->pathtarget;
2817 {
2818
2819 pathnode->dummypp = true;
2820
2821
2822
2823
2831 }
2832 else
2833 {
2834
2835 pathnode->dummypp = false;
2836
2837
2838
2839
2840
2848 }
2849
2850 return pathnode;
2851}
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2880{
2882
2883
2884
2885
2886
2889
2890
2891
2892
2893
2894 oldcost = path->pathtarget->cost;
2895 path->pathtarget = target;
2896
2900
2901
2902
2903
2904
2905
2906
2909 {
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2921 {
2923
2928 target);
2929 }
2930 else
2931 {
2933
2936 gmpath->subpath->parent,
2938 target);
2939 }
2940 }
2943 {
2944
2945
2946
2947
2948
2950 }
2951
2952 return path;
2953}
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2969{
2971 double tlist_rows;
2973
2975 pathnode->path.parent = rel;
2976 pathnode->path.pathtarget = target;
2977
2978 pathnode->path.param_info = NULL;
2981 subpath->parallel_safe &&
2984
2986
2988
2989
2990
2991
2992
2993 tlist_rows = 1;
2994 foreach(lc, target->exprs)
2995 {
2997 double itemrows;
2998
3000 if (tlist_rows < itemrows)
3001 tlist_rows = itemrows;
3002 }
3003
3004
3005
3006
3007
3008
3009
3018
3019 return pathnode;
3020}
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3038 List *pathkeys,
3039 int presorted_keys,
3040 double limit_tuples)
3041{
3044
3045 pathnode->path.pathtype = T_IncrementalSort;
3046 pathnode->path.parent = rel;
3047
3048 pathnode->path.pathtarget = subpath->pathtarget;
3049
3050 pathnode->path.param_info = NULL;
3056
3058
3060 root, pathkeys, presorted_keys,
3061 subpath->disabled_nodes,
3065 subpath->pathtarget->width,
3066 0.0,
3068
3069 sort->nPresortedCols = presorted_keys;
3070
3071 return sort;
3072}
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3088 List *pathkeys,
3089 double limit_tuples)
3090{
3092
3094 pathnode->path.parent = rel;
3095
3096 pathnode->path.pathtarget = subpath->pathtarget;
3097
3098 pathnode->path.param_info = NULL;
3104
3106
3108 subpath->disabled_nodes,
3111 subpath->pathtarget->width,
3112 0.0,
3114
3115 return pathnode;
3116}
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3133 List *groupClause,
3135 double numGroups)
3136{
3139
3141 pathnode->path.parent = rel;
3142 pathnode->path.pathtarget = target;
3143
3144 pathnode->path.param_info = NULL;
3149
3151
3153
3155 pathnode->qual = qual;
3156
3159 numGroups,
3160 qual,
3161 subpath->disabled_nodes,
3164
3165
3169
3170 return pathnode;
3171}
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3193 int numCols,
3194 double numGroups)
3195{
3197
3199 pathnode->path.parent = rel;
3200
3201 pathnode->path.pathtarget = subpath->pathtarget;
3202
3203 pathnode->path.param_info = NULL;
3208
3210
3212 pathnode->numkeys = numCols;
3213
3214
3215
3216
3217
3218
3223 pathnode->path.rows = numGroups;
3224
3225 return pathnode;
3226}
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3249 List *groupClause,
3252 double numGroups)
3253{
3255
3257 pathnode->path.parent = rel;
3258 pathnode->path.pathtarget = target;
3259
3260 pathnode->path.param_info = NULL;
3265
3267 {
3268
3269
3270
3271
3272
3273
3274
3275
3278 root->num_groupby_pathkeys);
3279 else
3281 }
3282 else
3283 pathnode->path.pathkeys = NIL;
3284
3286
3288 pathnode->aggsplit = aggsplit;
3289 pathnode->numGroups = numGroups;
3292 pathnode->qual = qual;
3293
3295 aggstrategy, aggcosts,
3297 qual,
3298 subpath->disabled_nodes,
3301
3302
3306
3307 return pathnode;
3308}
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3329 List *having_qual,
3331 List *rollups,
3333{
3337 bool is_first = true;
3338 bool is_first_sort = true;
3339
3340
3342 pathnode->path.parent = rel;
3343 pathnode->path.pathtarget = target;
3344 pathnode->path.param_info = subpath->param_info;
3350
3351
3352
3353
3354
3359
3363
3364
3365
3366
3367
3368
3371 else
3373
3375 pathnode->rollups = rollups;
3376 pathnode->qual = having_qual;
3378
3382
3383 foreach(lc, rollups)
3384 {
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399 if (is_first)
3400 {
3402 aggstrategy,
3403 agg_costs,
3404 numGroupCols,
3406 having_qual,
3407 subpath->disabled_nodes,
3411 subpath->pathtarget->width);
3412 is_first = false;
3414 is_first_sort = false;
3415 }
3416 else
3417 {
3418 Path sort_path;
3419 Path agg_path;
3420
3421 if (rollup->is_hashed || is_first_sort)
3422 {
3423
3424
3425
3426
3429 agg_costs,
3430 numGroupCols,
3432 having_qual,
3433 0, 0.0, 0.0,
3435 subpath->pathtarget->width);
3437 is_first_sort = false;
3438 }
3439 else
3440 {
3441
3443 0.0,
3445 subpath->pathtarget->width,
3446 0.0,
3448 -1.0);
3449
3450
3451
3454 agg_costs,
3455 numGroupCols,
3457 having_qual,
3461 sort_path.rows,
3462 subpath->pathtarget->width);
3463 }
3464
3468 }
3469 }
3470
3471
3475
3476 return pathnode;
3477}
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3492 List *mmaggregates,
3493 List *quals)
3494{
3496 Cost initplan_cost;
3497 int initplan_disabled_nodes = 0;
3499
3500
3502 pathnode->path.parent = rel;
3503 pathnode->path.pathtarget = target;
3504
3505 pathnode->path.param_info = NULL;
3509
3512
3514 pathnode->quals = quals;
3515
3516
3517 initplan_cost = 0;
3518 foreach(lc, mmaggregates)
3519 {
3521
3523 initplan_cost += mminfo->pathcost;
3526 }
3527
3528
3533
3534
3535
3536
3537
3538 if (quals)
3539 {
3541
3545 }
3546
3547
3548
3549
3550
3551
3552
3557
3558 return pathnode;
3559}
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3584 List *windowFuncs,
3585 List *runCondition,
3588 bool topwindow)
3589{
3591
3592
3593 Assert(qual == NIL || topwindow);
3594
3596 pathnode->path.parent = rel;
3597 pathnode->path.pathtarget = target;
3598
3599 pathnode->path.param_info = NULL;
3604
3606
3608 pathnode->winclause = winclause;
3609 pathnode->qual = qual;
3611 pathnode->topwindow = topwindow;
3612
3613
3614
3615
3616
3617
3618
3620 windowFuncs,
3621 winclause,
3622 subpath->disabled_nodes,
3626
3627
3631
3632 return pathnode;
3633}
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3655 Path *leftpath,
3656 Path *rightpath,
3659 List *groupList,
3660 double numGroups,
3661 double outputRows)
3662{
3664
3666 pathnode->path.parent = rel;
3668
3669 pathnode->path.param_info = NULL;
3675
3678
3679 pathnode->leftpath = leftpath;
3680 pathnode->rightpath = rightpath;
3681 pathnode->cmd = cmd;
3682 pathnode->strategy = strategy;
3683 pathnode->groupList = groupList;
3684 pathnode->numGroups = numGroups;
3685
3686
3687
3688
3689
3690
3694 {
3695
3696
3697
3698
3699
3705
3706
3707
3708
3709
3710
3712 }
3713 else
3714 {
3715 Size hashentrysize;
3716
3717
3718
3719
3720
3721
3726
3727
3728
3729
3730
3731
3733
3734
3735
3736
3737
3738
3741
3742
3743
3744
3745
3746 hashentrysize = MAXALIGN(leftpath->pathtarget->width) +
3750 }
3751 pathnode->path.rows = outputRows;
3752
3753 return pathnode;
3754}
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3773 Path *leftpath,
3774 Path *rightpath,
3776 List *distinctList,
3777 int wtParam,
3778 double numGroups)
3779{
3781
3783 pathnode->path.parent = rel;
3784 pathnode->path.pathtarget = target;
3785
3786 pathnode->path.param_info = NULL;
3790
3792
3794
3795 pathnode->leftpath = leftpath;
3796 pathnode->rightpath = rightpath;
3798 pathnode->wtParam = wtParam;
3799 pathnode->numGroups = numGroups;
3800
3802
3803 return pathnode;
3804}
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3818{
3820
3822 pathnode->path.parent = rel;
3823
3824 pathnode->path.pathtarget = subpath->pathtarget;
3825
3826 pathnode->path.param_info = NULL;
3831
3832
3833
3834
3835
3837
3839 pathnode->rowMarks = rowMarks;
3840 pathnode->epqParam = epqParam;
3841
3842
3843
3844
3845
3846
3851
3852 return pathnode;
3853}
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3882 CmdType operation, bool canSetTag,
3883 Index nominalRelation, Index rootRelation,
3884 bool partColsUpdated,
3885 List *resultRelations,
3886 List *updateColnosLists,
3887 List *withCheckOptionLists, List *returningLists,
3889 List *mergeActionLists, List *mergeJoinConditions,
3890 int epqParam)
3891{
3893
3897 updateColnosLists == NIL));
3898 Assert(withCheckOptionLists == NIL ||
3902
3904 pathnode->path.parent = rel;
3905
3907
3908 pathnode->path.param_info = NULL;
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3927 if (returningLists != NIL)
3928 {
3930
3931
3932
3933
3934
3935
3936
3937 pathnode->path.pathtarget->width = subpath->pathtarget->width;
3938 }
3939 else
3940 {
3942 pathnode->path.pathtarget->width = 0;
3943 }
3944
3946 pathnode->operation = operation;
3947 pathnode->canSetTag = canSetTag;
3955 pathnode->rowMarks = rowMarks;
3957 pathnode->epqParam = epqParam;
3960
3961 return pathnode;
3962}
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3984 Node *limitOffset, Node *limitCount,
3987{
3989
3991 pathnode->path.parent = rel;
3992
3993 pathnode->path.pathtarget = subpath->pathtarget;
3994
3995 pathnode->path.param_info = NULL;
4009
4010
4011
4012
4016 offset_est, count_est);
4017
4018 return pathnode;
4019}
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037void
4039 Cost *startup_cost,
4040 Cost *total_cost,
4041 int64 offset_est,
4042 int64 count_est)
4043{
4044 double input_rows = *rows;
4045 Cost input_startup_cost = *startup_cost;
4046 Cost input_total_cost = *total_cost;
4047
4048 if (offset_est != 0)
4049 {
4050 double offset_rows;
4051
4052 if (offset_est > 0)
4053 offset_rows = (double) offset_est;
4054 else
4056 if (offset_rows > *rows)
4057 offset_rows = *rows;
4058 if (input_rows > 0)
4059 *startup_cost +=
4060 (input_total_cost - input_startup_cost)
4061 * offset_rows / input_rows;
4062 *rows -= offset_rows;
4063 if (*rows < 1)
4064 *rows = 1;
4065 }
4066
4067 if (count_est != 0)
4068 {
4069 double count_rows;
4070
4071 if (count_est > 0)
4072 count_rows = (double) count_est;
4073 else
4075 if (count_rows > *rows)
4076 count_rows = *rows;
4077 if (input_rows > 0)
4078 *total_cost = *startup_cost +
4079 (input_total_cost - input_startup_cost)
4080 * count_rows / input_rows;
4081 *rows = count_rows;
4082 if (*rows < 1)
4083 *rows = 1;
4084 }
4085}
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4107 Relids required_outer,
4108 double loop_count)
4109{
4111
4112
4114 return NULL;
4116 {
4117 case T_SeqScan:
4119 case T_SampleScan:
4121 case T_IndexScan:
4122 case T_IndexOnlyScan:
4123 {
4126
4127
4128
4129
4130
4131
4132
4133
4134 memcpy(newpath, ipath, sizeof(IndexPath));
4135 newpath->path.param_info =
4138 return (Path *) newpath;
4139 }
4140 case T_BitmapHeapScan:
4141 {
4143
4145 rel,
4147 required_outer,
4148 loop_count, 0);
4149 }
4150 case T_SubqueryScan:
4151 {
4154 bool trivial_pathtarget;
4155
4156
4157
4158
4159
4160
4161
4162
4163 trivial_pathtarget =
4165
4167 rel,
4169 trivial_pathtarget,
4171 required_outer);
4172 }
4173 case T_Result:
4174
4177 break;
4178 case T_Append:
4179 {
4182 List *partialpaths = NIL;
4183 int i;
4185
4186
4187 i = 0;
4188 foreach(lc, apath->subpaths)
4189 {
4191
4193 required_outer,
4194 loop_count);
4195 if (spath == NULL)
4196 return NULL;
4197
4198 if (i < apath->first_partial_path)
4199 childpaths = lappend(childpaths, spath);
4200 else
4201 partialpaths = lappend(partialpaths, spath);
4202 i++;
4203 }
4204 return (Path *)
4209 -1);
4210 }
4211 case T_Material:
4212 {
4215
4217 required_outer,
4218 loop_count);
4219 if (spath == NULL)
4220 return NULL;
4222 }
4223 case T_Memoize:
4224 {
4227
4229 required_outer,
4230 loop_count);
4231 if (spath == NULL)
4232 return NULL;
4234 spath,
4240 }
4241 default:
4242 break;
4243 }
4244 return NULL;
4245}
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4274{
4275 Path *new_path;
4278 Relids required_outer;
4279
4280#define ADJUST_CHILD_ATTRS(node) \
4281 ((node) = (void *) adjust_appendrel_attrs_multilevel(root, \
4282 (Node *) (node), \
4283 child_rel, \
4284 child_rel->top_parent))
4285
4286#define REPARAMETERIZE_CHILD_PATH(path) \
4287do { \
4288 (path) = reparameterize_path_by_child(root, (path), child_rel); \
4289 if ((path) == NULL) \
4290 return NULL; \
4291} while(0)
4292
4293#define REPARAMETERIZE_CHILD_PATH_LIST(pathlist) \
4294do { \
4295 if ((pathlist) != NIL) \
4296 { \
4297 (pathlist) = reparameterize_pathlist_by_child(root, (pathlist), \
4298 child_rel); \
4299 if ((pathlist) == NIL) \
4300 return NULL; \
4301 } \
4302} while(0)
4303
4304
4305
4306
4307
4308 if (!path->param_info ||
4310 return path;
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4325 {
4326 case T_Path:
4327 new_path = path;
4329 if (path->pathtype == T_SampleScan)
4330 {
4331 Index scan_relid = path->parent->relid;
4333
4334
4335 Assert(scan_relid > 0);
4339
4341 }
4342 break;
4343
4344 case T_IndexPath:
4345 {
4347
4350 new_path = (Path *) ipath;
4351 }
4352 break;
4353
4354 case T_BitmapHeapPath:
4355 {
4357
4360 new_path = (Path *) bhpath;
4361 }
4362 break;
4363
4364 case T_BitmapAndPath:
4365 {
4367
4369 new_path = (Path *) bapath;
4370 }
4371 break;
4372
4373 case T_BitmapOrPath:
4374 {
4376
4378 new_path = (Path *) bopath;
4379 }
4380 break;
4381
4382 case T_ForeignPath:
4383 {
4386
4392
4393
4394 rfpc_func =
4395 path->parent->fdwroutine->ReparameterizeForeignPathByChild;
4396 if (rfpc_func)
4398 child_rel);
4399 new_path = (Path *) fpath;
4400 }
4401 break;
4402
4403 case T_CustomPath:
4404 {
4406
4416 child_rel);
4417 new_path = (Path *) cpath;
4418 }
4419 break;
4420
4421 case T_NestPath:
4422 {
4425
4429 new_path = (Path *) npath;
4430 }
4431 break;
4432
4433 case T_MergePath:
4434 {
4437
4442 new_path = (Path *) mpath;
4443 }
4444 break;
4445
4446 case T_HashPath:
4447 {
4450
4455 new_path = (Path *) hpath;
4456 }
4457 break;
4458
4459 case T_AppendPath:
4460 {
4462
4464 new_path = (Path *) apath;
4465 }
4466 break;
4467
4468 case T_MaterialPath:
4469 {
4471
4473 new_path = (Path *) mpath;
4474 }
4475 break;
4476
4477 case T_MemoizePath:
4478 {
4480
4483 new_path = (Path *) mpath;
4484 }
4485 break;
4486
4487 case T_GatherPath:
4488 {
4490
4492 new_path = (Path *) gpath;
4493 }
4494 break;
4495
4496 default:
4497
4498 return NULL;
4499 }
4500
4501
4502
4503
4504
4505
4506 old_ppi = new_path->param_info;
4507 required_outer =
4509 child_rel,
4510 child_rel->top_parent);
4511
4512
4514
4515
4516
4517
4518
4519
4520 if (new_ppi == NULL)
4521 {
4524
4526
4534
4536 }
4538
4539 new_path->param_info = new_ppi;
4540
4541
4542
4543
4544
4545
4546 if (bms_overlap(path->parent->lateral_relids,
4548 {
4549 new_path->pathtarget = copy_pathtarget(new_path->pathtarget);
4551 }
4552
4553 return new_path;
4554}
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567bool
4569{
4570#define REJECT_IF_PATH_NOT_REPARAMETERIZABLE(path) \
4571do { \
4572 if (!path_is_reparameterizable_by_child(path, child_rel)) \
4573 return false; \
4574} while(0)
4575
4576#define REJECT_IF_PATH_LIST_NOT_REPARAMETERIZABLE(pathlist) \
4577do { \
4578 if (!pathlist_is_reparameterizable_by_child(pathlist, child_rel)) \
4579 return false; \
4580} while(0)
4581
4582
4583
4584
4585
4586 if (!path->param_info ||
4588 return true;
4589
4590
4591
4592
4593
4595 {
4596 case T_Path:
4597 case T_IndexPath:
4598 break;
4599
4600 case T_BitmapHeapPath:
4601 {
4603
4605 }
4606 break;
4607
4608 case T_BitmapAndPath:
4609 {
4611
4613 }
4614 break;
4615
4616 case T_BitmapOrPath:
4617 {
4619
4621 }
4622 break;
4623
4624 case T_ForeignPath:
4625 {
4627
4630 }
4631 break;
4632
4633 case T_CustomPath:
4634 {
4636
4638 }
4639 break;
4640
4641 case T_NestPath:
4642 case T_MergePath:
4643 case T_HashPath:
4644 {
4646
4649 }
4650 break;
4651
4652 case T_AppendPath:
4653 {
4655
4657 }
4658 break;
4659
4660 case T_MaterialPath:
4661 {
4663
4665 }
4666 break;
4667
4668 case T_MemoizePath:
4669 {
4671
4673 }
4674 break;
4675
4676 case T_GatherPath:
4677 {
4679
4681 }
4682 break;
4683
4684 default:
4685
4686 return false;
4687 }
4688
4689 return true;
4690}
4691
4692
4693
4694
4695
4696
4697
4698static List *
4700 List *pathlist,
4702{
4705
4706 foreach(lc, pathlist)
4707 {
4709 child_rel);
4710
4711 if (path == NULL)
4712 {
4714 return NIL;
4715 }
4716
4717 result = lappend(result, path);
4718 }
4719
4720 return result;
4721}
4722
4723
4724
4725
4726
4727static bool
4729{
4731
4732 foreach(lc, pathlist)
4733 {
4735
4737 return false;
4738 }
4739
4740 return true;
4741}
Datum sort(PG_FUNCTION_ARGS)
bool query_is_distinct_for(Query *query, List *colnos, List *opids)
bool query_supports_distinctness(Query *query)
Relids adjust_child_relids_multilevel(PlannerInfo *root, Relids relids, RelOptInfo *childrel, RelOptInfo *parentrel)
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
void bms_free(Bitmapset *a)
bool bms_is_member(int x, const Bitmapset *a)
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
int bms_compare(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_copy(const Bitmapset *a)
#define PG_USED_FOR_ASSERTS_ONLY
bool is_parallel_safe(PlannerInfo *root, Node *node)
double expression_returns_set_rows(PlannerInfo *root, Node *clause)
void final_cost_hashjoin(PlannerInfo *root, HashPath *path, JoinCostWorkspace *workspace, JoinPathExtraData *extra)
void final_cost_mergejoin(PlannerInfo *root, MergePath *path, JoinCostWorkspace *workspace, JoinPathExtraData *extra)
void cost_windowagg(Path *path, PlannerInfo *root, List *windowFuncs, WindowClause *winclause, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples)
void cost_functionscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
void cost_material(Path *path, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double tuples, int width)
void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info, Path *bitmapqual, double loop_count)
void cost_tidrangescan(Path *path, PlannerInfo *root, RelOptInfo *baserel, List *tidrangequals, ParamPathInfo *param_info)
void cost_agg(Path *path, PlannerInfo *root, AggStrategy aggstrategy, const AggClauseCosts *aggcosts, int numGroupCols, double numGroups, List *quals, int disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples, double input_width)
void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, int input_disabled_nodes, Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
void final_cost_nestloop(PlannerInfo *root, NestPath *path, JoinCostWorkspace *workspace, JoinPathExtraData *extra)
void cost_gather_merge(GatherMergePath *path, PlannerInfo *root, RelOptInfo *rel, ParamPathInfo *param_info, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double *rows)
void cost_recursive_union(Path *runion, Path *nrterm, Path *rterm)
void cost_tablefuncscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
void cost_samplescan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
void cost_gather(GatherPath *path, PlannerInfo *root, RelOptInfo *rel, ParamPathInfo *param_info, double *rows)
void cost_namedtuplestorescan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
void cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
void cost_valuesscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
void cost_incremental_sort(Path *path, PlannerInfo *root, List *pathkeys, int presorted_keys, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
void cost_group(Path *path, PlannerInfo *root, int numGroupCols, double numGroups, List *quals, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples)
void cost_resultscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
void cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root)
void cost_tidscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, List *tidquals, ParamPathInfo *param_info)
void cost_merge_append(Path *path, PlannerInfo *root, List *pathkeys, int n_streams, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double tuples)
double clamp_row_est(double nrows)
void cost_subqueryscan(SubqueryScanPath *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info, bool trivial_pathtarget)
void cost_append(AppendPath *apath)
void cost_ctescan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
void cost_bitmap_or_node(BitmapOrPath *path, PlannerInfo *root)
void cost_index(IndexPath *path, PlannerInfo *root, double loop_count, bool partial_path)
bool is_projection_capable_path(Path *path)
bool equal(const void *a, const void *b)
List *(* ReparameterizeForeignPathByChild_function)(PlannerInfo *root, List *fdw_private, RelOptInfo *child_rel)
Assert(PointerIsAligned(start, uint64))
#define SizeofMinimalTupleHeader
bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List *exprlist, List *oprlist)
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
void list_sort(List *list, list_sort_comparator cmp)
List * list_concat(List *list1, const List *list2)
List * lappend_int(List *list, int datum)
List * lcons(void *datum, List *list)
void list_free(List *list)
List * list_copy_head(const List *oldlist, int len)
List * list_insert_nth(List *list, int pos, void *datum)
Datum subpath(PG_FUNCTION_ARGS)
void pfree(void *pointer)
MemoryContext GetMemoryChunkContext(void *pointer)
#define CHECK_FOR_INTERRUPTS()
size_t get_hash_memory_limit(void)
#define IsA(nodeptr, _type_)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
bool pathkeys_contained_in(List *keys1, List *keys2)
PathKeysComparison compare_pathkeys(List *keys1, List *keys2)
#define REPARAMETERIZE_CHILD_PATH_LIST(pathlist)
static int append_startup_cost_compare(const ListCell *a, const ListCell *b)
TidRangePath * create_tidrangescan_path(PlannerInfo *root, RelOptInfo *rel, List *tidrangequals, Relids required_outer)
#define REPARAMETERIZE_CHILD_PATH(path)
Relids calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path)
static PathCostComparison compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor)
ForeignPath * create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, int disabled_nodes, Cost startup_cost, Cost total_cost, List *pathkeys, Path *fdw_outerpath, List *fdw_restrictinfo, List *fdw_private)
BitmapAndPath * create_bitmap_and_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals)
Path * create_functionscan_path(PlannerInfo *root, RelOptInfo *rel, List *pathkeys, Relids required_outer)
bool path_is_reparameterizable_by_child(Path *path, RelOptInfo *child_rel)
Path * create_valuesscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
MinMaxAggPath * create_minmaxagg_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, List *mmaggregates, List *quals)
Path * create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
static bool pathlist_is_reparameterizable_by_child(List *pathlist, RelOptInfo *child_rel)
SetOpPath * create_setop_path(PlannerInfo *root, RelOptInfo *rel, Path *leftpath, Path *rightpath, SetOpCmd cmd, SetOpStrategy strategy, List *groupList, double numGroups, double outputRows)
Relids calc_nestloop_required_outer(Relids outerrelids, Relids outer_paramrels, Relids innerrelids, Relids inner_paramrels)
IndexPath * create_index_path(PlannerInfo *root, IndexOptInfo *index, List *indexclauses, List *indexorderbys, List *indexorderbycols, List *pathkeys, ScanDirection indexscandir, bool indexonly, Relids required_outer, double loop_count, bool partial_path)
MemoizePath * create_memoize_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *param_exprs, List *hash_operators, bool singlerow, bool binary_mode, double calls)
ProjectSetPath * create_set_projection_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
ProjectionPath * create_projection_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
#define REJECT_IF_PATH_LIST_NOT_REPARAMETERIZABLE(pathlist)
static List * reparameterize_pathlist_by_child(PlannerInfo *root, List *pathlist, RelOptInfo *child_rel)
WindowAggPath * create_windowagg_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, List *windowFuncs, List *runCondition, WindowClause *winclause, List *qual, bool topwindow)
Path * reparameterize_path_by_child(PlannerInfo *root, Path *path, RelOptInfo *child_rel)
LockRowsPath * create_lockrows_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *rowMarks, int epqParam)
Path * apply_projection_to_path(PlannerInfo *root, RelOptInfo *rel, Path *path, PathTarget *target)
Path * create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer, int parallel_workers)
GatherMergePath * create_gather_merge_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, List *pathkeys, Relids required_outer, double *rows)
HashPath * create_hashjoin_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, JoinCostWorkspace *workspace, JoinPathExtraData *extra, Path *outer_path, Path *inner_path, bool parallel_hash, List *restrict_clauses, Relids required_outer, List *hashclauses)
UniquePath * create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, SpecialJoinInfo *sjinfo)
void set_cheapest(RelOptInfo *parent_rel)
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
LimitPath * create_limit_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, Node *limitOffset, Node *limitCount, LimitOption limitOption, int64 offset_est, int64 count_est)
AppendPath * create_append_path(PlannerInfo *root, RelOptInfo *rel, List *subpaths, List *partial_subpaths, List *pathkeys, Relids required_outer, int parallel_workers, bool parallel_aware, double rows)
Path * create_namedtuplestorescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
SubqueryScanPath * create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, bool trivial_pathtarget, List *pathkeys, Relids required_outer)
#define ADJUST_CHILD_ATTRS(node)
int compare_fractional_path_costs(Path *path1, Path *path2, double fraction)
IncrementalSortPath * create_incremental_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, int presorted_keys, double limit_tuples)
BitmapOrPath * create_bitmap_or_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals)
GroupingSetsPath * create_groupingsets_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *having_qual, AggStrategy aggstrategy, List *rollups, const AggClauseCosts *agg_costs)
BitmapHeapPath * create_bitmap_heap_path(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual, Relids required_outer, double loop_count, int parallel_degree)
Path * create_tablefuncscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
#define REJECT_IF_PATH_NOT_REPARAMETERIZABLE(path)
SortPath * create_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)
GroupPath * create_group_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *groupClause, List *qual, double numGroups)
ForeignPath * create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, int disabled_nodes, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, List *fdw_restrictinfo, List *fdw_private)
TidPath * create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tidquals, Relids required_outer)
#define CONSIDER_PATH_STARTUP_COST(p)
GatherPath * create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, Relids required_outer, double *rows)
Path * create_samplescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
MaterialPath * create_material_path(RelOptInfo *rel, Path *subpath)
ForeignPath * create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, int disabled_nodes, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, List *fdw_restrictinfo, List *fdw_private)
void add_path(RelOptInfo *parent_rel, Path *new_path)
int compare_path_costs(Path *path1, Path *path2, CostSelector criterion)
bool add_path_precheck(RelOptInfo *parent_rel, int disabled_nodes, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer)
static int append_total_cost_compare(const ListCell *a, const ListCell *b)
Path * create_resultscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
UpperUniquePath * create_upper_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, int numCols, double numGroups)
void adjust_limit_rows_costs(double *rows, Cost *startup_cost, Cost *total_cost, int64 offset_est, int64 count_est)
Path * create_ctescan_path(PlannerInfo *root, RelOptInfo *rel, List *pathkeys, Relids required_outer)
AggPath * create_agg_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, AggStrategy aggstrategy, AggSplit aggsplit, List *groupClause, List *qual, const AggClauseCosts *aggcosts, double numGroups)
bool add_partial_path_precheck(RelOptInfo *parent_rel, int disabled_nodes, Cost total_cost, List *pathkeys)
ModifyTablePath * create_modifytable_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, CmdType operation, bool canSetTag, Index nominalRelation, Index rootRelation, bool partColsUpdated, List *resultRelations, List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, List *mergeActionLists, List *mergeJoinConditions, int epqParam)
MergePath * create_mergejoin_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, JoinCostWorkspace *workspace, JoinPathExtraData *extra, Path *outer_path, Path *inner_path, List *restrict_clauses, List *pathkeys, Relids required_outer, List *mergeclauses, List *outersortkeys, List *innersortkeys, int outer_presorted_keys)
static List * translate_sub_tlist(List *tlist, int relid)
RecursiveUnionPath * create_recursiveunion_path(PlannerInfo *root, RelOptInfo *rel, Path *leftpath, Path *rightpath, PathTarget *target, List *distinctList, int wtParam, double numGroups)
GroupResultPath * create_group_result_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, List *havingqual)
MergeAppendPath * create_merge_append_path(PlannerInfo *root, RelOptInfo *rel, List *subpaths, List *pathkeys, Relids required_outer)
Path * reparameterize_path(PlannerInfo *root, Path *path, Relids required_outer, double loop_count)
NestPath * create_nestloop_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, JoinCostWorkspace *workspace, JoinPathExtraData *extra, Path *outer_path, Path *inner_path, List *restrict_clauses, List *pathkeys, Relids required_outer)
#define IS_SIMPLE_REL(rel)
#define PATH_REQ_OUTER(path)
#define planner_rt_fetch(rti, root)
static int list_length(const List *l)
#define foreach_current_index(var_or_cell)
#define foreach_delete_current(lst, var_or_cell)
static int cmp(const chr *x, const chr *y, size_t len)
ParamPathInfo * get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
ParamPathInfo * get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, Relids required_outer, List **restrict_clauses)
ParamPathInfo * get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
ParamPathInfo * find_param_path_info(RelOptInfo *rel, Relids required_outer)
Bitmapset * get_param_path_clause_serials(Path *path)
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset, EstimationInfo *estinfo)
struct List *(* ReparameterizeCustomPathByChild)(PlannerInfo *root, List *custom_private, RelOptInfo *child_rel)
const struct CustomPathMethods * methods
List * custom_restrictinfo
ScanDirection indexscandir
List * withCheckOptionLists
List * mergeJoinConditions
OnConflictExpr * onconflict
struct TableSampleClause * tablesample
bool consider_param_startup
struct PathTarget * reltarget
List * cheapest_parameterized_paths
struct Path * cheapest_unique_path
struct Path * cheapest_startup_path
struct Path * cheapest_total_path
PathTarget * copy_pathtarget(PathTarget *src)