PostgreSQL Source Code: src/backend/optimizer/prep/prepunion.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
25
26#include <math.h>
27
41
42
45 List *colTypes, List *colCollations,
46 List *refnames_tlist,
47 List **pTargetList,
48 bool *istrivial_tlist);
51 List *refnames_tlist,
52 List **pTargetList);
54 bool trivial_tlist, List *child_tlist,
55 List *interesting_pathkeys,
56 double *pNumGroups);
58 List *refnames_tlist,
59 List **pTargetList);
61 List *refnames_tlist,
62 List **pTargetList);
65 List *refnames_tlist,
66 List **tlist_list,
67 List **istrivial_tlist);
71 bool hack_constants,
72 List *input_tlist,
73 List *refnames_tlist,
74 bool *trivial_tlist);
76 List *input_tlists,
77 List *refnames_tlist);
80 List *child_pathlist);
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
98{
103 Query *leftmostQuery;
105 List *top_tlist;
106
108
109
116
117
118
119
120
121
122
124 root->ec_merging_done = true;
125
126
127
128
129
130
132
133
134
135
136
137 node = topop->larg;
141 leftmostRTE = root->simple_rte_array[((RangeTblRef *) node)->rtindex];
142 leftmostQuery = leftmostRTE->subquery;
143 Assert(leftmostQuery != NULL);
144
145
146
147
148 if (root->hasRecursion)
149 {
152 &top_tlist);
153 }
154 else
155 {
156 bool trivial_tlist;
157
158
159
160
161
162
164 NULL,
165 topop->colTypes, topop->colCollations,
167 &top_tlist,
168 &trivial_tlist);
169 }
170
171
172 root->processed_tlist = top_tlist;
173
174 return setop_rel;
175}
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
215 List *colTypes, List *colCollations,
216 List *refnames_tlist,
217 List **pTargetList,
218 bool *istrivial_tlist)
219{
221
222 *istrivial_tlist = true;
223
224
226
228 {
234 bool trivial_tlist;
235 char *plan_name;
236
237 Assert(subquery != NULL);
238
239
241
242
244
245
246
247
248
249
252 plan_name, root,
253 false, root->tuple_fraction,
254 parentOp);
255
256
257
258
259
260 if (root->plan_params)
261 elog(ERROR, "unexpected outer reference in set operation subquery");
262
263
266 true,
268 refnames_tlist,
269 &trivial_tlist);
271
272
273 *pTargetList = tlist;
274 *istrivial_tlist = trivial_tlist;
275 }
277 {
279
280
283 refnames_tlist,
284 pTargetList);
285 else
287 refnames_tlist,
288 pTargetList);
289
290
291
292
293
294
295
296
297
298
299
300
301
302
305 {
307 bool trivial_tlist;
309
311 0,
312 false,
313 *pTargetList,
314 refnames_tlist,
315 &trivial_tlist);
316 *istrivial_tlist = trivial_tlist;
318
319
321 {
324
328
331 }
332
333
335 {
338
340
341
345 }
346 }
348 }
349 else
350 {
351 elog(ERROR, "unrecognized node type: %d",
353 *pTargetList = NIL;
354 rel = NULL;
355 }
356
357 return rel;
358}
359
360
361
362
365 List *refnames_tlist,
366 List **pTargetList)
367{
371 *rrel;
374 List *lpath_tlist;
375 bool lpath_trivial_tlist;
376 List *rpath_tlist;
377 bool rpath_trivial_tlist;
379 List *groupList;
380 double dNumGroups;
381
382
384 elog(ERROR, "only UNION queries can be recursive");
385
387
388
389
390
391
393 NULL,
394 setOp->colTypes, setOp->colCollations,
395 refnames_tlist,
396 &lpath_tlist,
397 &lpath_trivial_tlist);
400 NIL, NULL);
402
403 root->non_recursive_path = lpath;
405 NULL,
406 setOp->colTypes, setOp->colCollations,
407 refnames_tlist,
408 &rpath_tlist,
409 &rpath_trivial_tlist);
412 NIL, NULL);
414 root->non_recursive_path = NULL;
415
416
417
418
420 list_make2(lpath_tlist, rpath_tlist),
421 refnames_tlist);
422
423 *pTargetList = tlist;
424
425
429
430
431
432
433 if (setOp->all)
434 {
435 groupList = NIL;
436 dNumGroups = 0;
437 }
438 else
439 {
440
442
443
446 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
447 errmsg("could not implement recursive UNION"),
448 errdetail("All column datatypes must be hashable.")));
449
450
451
452
453
454 dNumGroups = lpath->rows + rpath->rows * 10;
455 }
456
457
458
459
461 result_rel,
462 lpath,
463 rpath,
465 groupList,
466 root->wt_param_id,
467 dNumGroups);
468
471 return result_rel;
472}
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487static void
489 bool trivial_tlist, List *child_tlist,
490 List *interesting_pathkeys, double *pNumGroups)
491{
495
496
498
499
500 if (interesting_pathkeys != NIL)
502 rel,
503 child_tlist,
504 interesting_pathkeys);
505
506
507
508
509
510
512
513
514
515
516
519
520
521 foreach(lc, final_rel->pathlist)
522 {
524 List *pathkeys;
526 bool is_sorted;
527 int presorted_keys;
528
529
531 {
533 continue;
534 }
535
536
537
538
539
540
541 if (subpath == cheapest_input_path)
542 {
543
546
547
549 rel,
551 trivial_tlist,
552 pathkeys,
553 NULL));
554 }
555
556
557 if (interesting_pathkeys == NIL)
558 continue;
559
560
561
562
563
564
567 &presorted_keys);
568
569 if (!is_sorted)
570 {
572
573
574
575
576
577
578
579
580 if (subpath != cheapest_input_path &&
582 continue;
583
584
585
586
587
588
591 final_rel,
593 setop_pathkeys,
594 limittuples);
595 else
597 final_rel,
599 setop_pathkeys,
600 presorted_keys,
601 limittuples);
602 }
603
604
605
606
607
608
609 if (subpath != cheapest_input_path)
610 {
611
614
615
617 rel,
619 trivial_tlist,
620 pathkeys,
621 NULL));
622 }
623 }
624
625
628
629
630
631
632
633
636 {
637 Path *partial_subpath;
638 Path *partial_path;
639
641 partial_path = (Path *)
643 trivial_tlist,
644 NIL, NULL);
646 }
647
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668 if (pNumGroups)
669 {
672
675 subquery->hasAggs)
677 else
681 NULL,
682 NULL);
683 }
684}
685
686
687
688
691 List *refnames_tlist,
692 List **pTargetList)
693{
694 Relids relids = NULL;
699 List *cheapest_pathlist = NIL;
700 List *ordered_pathlist = NIL;
701 List *partial_pathlist = NIL;
702 bool partial_paths_valid = true;
703 bool consider_parallel = true;
704 List *rellist;
705 List *tlist_list;
706 List *trivial_tlist_list;
710 Path *gpath = NULL;
711 bool try_sorted = false;
712 List *union_pathkeys = NIL;
713
714
715
716
717
718
719
721 op,
722 refnames_tlist,
723 &tlist_list,
724 &trivial_tlist_list);
725
726
727
728
729
730
731
732
734 tlist_list, refnames_tlist);
735 *pTargetList = tlist;
736
737
738 if (!op->all)
739 {
740
742
744 {
745 try_sorted = true;
746
748 tlist);
749
750 root->query_pathkeys = union_pathkeys;
751 }
752 }
753
754
755
756
757
758 forthree(lc, rellist, lc2, trivial_tlist_list, lc3, tlist_list)
759 {
761 bool trivial_tlist = lfirst_int(lc2);
763
764
767 union_pathkeys, NULL);
768 }
769
770
771 foreach(lc, rellist)
772 {
774 Path *ordered_path;
775
776
777
778
779
781
782
784 continue;
785
786 cheapest_pathlist = lappend(cheapest_pathlist,
788
789 if (try_sorted)
790 {
792 union_pathkeys,
793 NULL,
795 false);
796
797 if (ordered_path != NULL)
798 ordered_pathlist = lappend(ordered_pathlist, ordered_path);
799 else
800 {
801
802
803
804
805
806
807 try_sorted = false;
808 }
809 }
810
811 if (consider_parallel)
812 {
814 {
815 consider_parallel = false;
816 partial_paths_valid = false;
817 }
819 partial_paths_valid = false;
820 else
821 partial_pathlist = lappend(partial_pathlist,
823 }
824 }
825
826
829 cheapest_pathlist);
832
833
834 if (cheapest_pathlist == NIL)
835 {
837
838 return result_rel;
839 }
840
841
842
843
844
846 NIL, NIL, NULL, 0, false, -1);
847
848
849
850
851
852
853 result_rel->rows = apath->rows;
854
855
856
857
858
859 if (partial_paths_valid)
860 {
861 Path *papath;
862 int parallel_workers = 0;
863
864
865 foreach(lc, partial_pathlist)
866 {
868
869 parallel_workers = Max(parallel_workers,
870 subpath->parallel_workers);
871 }
872 Assert(parallel_workers > 0);
873
874
875
876
877
878
879
880
882 {
883 parallel_workers = Max(parallel_workers,
885 parallel_workers = Min(parallel_workers,
887 }
888 Assert(parallel_workers > 0);
889
890 papath = (Path *)
892 NIL, NULL, parallel_workers,
894 gpath = (Path *)
896 result_rel->reltarget, NULL, NULL);
897 }
898
899 if (!op->all)
900 {
901 double dNumGroups;
904 Path *first_path = linitial(cheapest_pathlist);
905
906
907
908
909
910
911
912
913
914 if (list_length(cheapest_pathlist) == 1 &&
916 {
918 first_path->pathtarget->exprs,
919 first_path->rows,
920 NULL,
921 NULL);
922 }
923 else
924 {
925
926
927
928
929
930
931
932
933 dNumGroups = apath->rows;
934 }
935
936 if (can_hash)
937 {
939
940
941
942
943
945 result_rel,
946 apath,
950 groupList,
952 NULL,
953 dNumGroups);
955
956
957 if (gpath != NULL)
958 {
959
961 result_rel,
962 gpath,
966 groupList,
968 NULL,
969 dNumGroups);
971 }
972 }
973
974 if (can_sort)
975 {
976 Path *path = apath;
977
978
979 if (groupList != NIL)
982 -1.0);
983
985 result_rel,
986 path,
988 dNumGroups);
989
991
992
993 if (gpath != NULL)
994 {
995 path = gpath;
996
999 -1.0);
1000
1002 result_rel,
1003 path,
1005 dNumGroups);
1007 }
1008 }
1009
1010
1011
1012
1013
1014 if (try_sorted && groupList != NIL)
1015 {
1017
1019 result_rel,
1020 ordered_pathlist,
1021 union_pathkeys,
1022 NULL);
1023
1024
1026 result_rel,
1027 path,
1029 dNumGroups);
1030
1032 }
1033 }
1034 else
1035 {
1036
1037 add_path(result_rel, apath);
1038
1039 if (gpath != NULL)
1040 add_path(result_rel, gpath);
1041 }
1042
1043 return result_rel;
1044}
1045
1046
1047
1048
1051 List *refnames_tlist,
1052 List **pTargetList)
1053{
1056 *rrel;
1057 double save_fraction = root->tuple_fraction;
1058 Path *lpath,
1059 *rpath,
1060 *path;
1061 List *lpath_tlist,
1062 *rpath_tlist,
1063 *tlist,
1064 *groupList;
1065 bool lpath_trivial_tlist,
1066 rpath_trivial_tlist,
1067 result_trivial_tlist;
1068 List *nonunion_pathkeys = NIL;
1069 double dLeftGroups,
1070 dRightGroups,
1071 dNumGroups,
1072 dNumOutputRows;
1073 bool can_sort;
1074 bool can_hash;
1076
1077
1078
1079
1080 root->tuple_fraction = 0.0;
1081
1082
1084 op,
1085 op->colTypes, op->colCollations,
1086 refnames_tlist,
1087 &lpath_tlist,
1088 &lpath_trivial_tlist);
1089
1091 op,
1092 op->colTypes, op->colCollations,
1093 refnames_tlist,
1094 &rpath_tlist,
1095 &rpath_trivial_tlist);
1096
1097
1098
1099
1100
1101
1102
1103
1105 0, false, lpath_tlist, refnames_tlist,
1106 &result_trivial_tlist);
1107
1108
1109 Assert(result_trivial_tlist);
1110
1111 *pTargetList = tlist;
1112
1113
1115
1116
1119 if (!can_sort && !can_hash)
1121 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1122
1123 errmsg("could not implement %s",
1125 errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
1126
1127 if (can_sort)
1128 {
1129
1131 tlist);
1132
1133 root->query_pathkeys = nonunion_pathkeys;
1134 }
1135
1136
1137
1138
1141 nonunion_pathkeys, &dLeftGroups);
1142 else
1143 dLeftGroups = lrel->rows;
1146 nonunion_pathkeys, &dRightGroups);
1147 else
1148 dRightGroups = rrel->rows;
1149
1150
1151 root->tuple_fraction = save_fraction;
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161 if (op->op != SETOP_EXCEPT && dLeftGroups > dRightGroups)
1162 {
1163
1165 List *tmplist;
1166 double tmpd;
1167
1168 tmprel = lrel;
1169 lrel = rrel;
1170 rrel = tmprel;
1171 tmplist = lpath_tlist;
1172 lpath_tlist = rpath_tlist;
1173 rpath_tlist = tmplist;
1174 tmpd = dLeftGroups;
1175 dLeftGroups = dRightGroups;
1176 dRightGroups = tmpd;
1177 }
1178
1181
1182
1185
1186
1187
1188
1189
1190
1194 else
1197
1198
1200 {
1201
1202
1203
1204
1205
1207 {
1209
1210 return result_rel;
1211 }
1212
1213
1215 {
1216 if (op->all)
1217 {
1218 Path *apath;
1219
1220
1221
1222
1223
1224
1225
1226
1228 NIL, NIL, NULL, 0, false, -1);
1229
1230 add_path(result_rel, apath);
1231
1232 return result_rel;
1233 }
1234 else
1235 {
1236
1237
1238
1239
1240
1241
1242 }
1243 }
1244 }
1245 else
1246 {
1247
1248
1249
1250
1251
1252
1254 {
1256
1257 return result_rel;
1258 }
1259 }
1260
1261
1262
1263
1264
1265
1266
1267
1268
1270 {
1271 dNumGroups = dLeftGroups;
1272 dNumOutputRows = op->all ? lpath->rows : dNumGroups;
1273 }
1274 else
1275 {
1276 dNumGroups = dLeftGroups;
1277 dNumOutputRows = op->all ? Min(lpath->rows, rpath->rows) : dNumGroups;
1278 }
1279 result_rel->rows = dNumOutputRows;
1280
1281
1282 switch (op->op)
1283 {
1286 break;
1289 break;
1290 default:
1291 elog(ERROR, "unrecognized set op: %d", (int) op->op);
1293 break;
1294 }
1295
1296
1297
1298
1299 if (can_hash)
1300 {
1302 result_rel,
1303 lpath,
1304 rpath,
1305 cmd,
1307 groupList,
1308 dNumGroups,
1309 dNumOutputRows);
1311 }
1312
1313
1314
1315
1316
1317 if (can_sort)
1318 {
1319 List *pathkeys;
1320 Path *slpath,
1321 *srpath;
1322
1323
1325 groupList,
1326 lpath_tlist);
1328 slpath = lpath;
1329 else
1330 {
1332 nonunion_pathkeys,
1333 NULL,
1335 false);
1336
1337 if (slpath == NULL)
1339 lpath->parent,
1340 lpath,
1341 pathkeys,
1342 -1.0);
1343 }
1344
1345
1347 groupList,
1348 rpath_tlist);
1350 srpath = rpath;
1351 else
1352 {
1354 nonunion_pathkeys,
1355 NULL,
1357 false);
1358
1359 if (srpath == NULL)
1361 rpath->parent,
1362 rpath,
1363 pathkeys,
1364 -1.0);
1365 }
1366
1368 result_rel,
1369 slpath,
1370 srpath,
1371 cmd,
1373 groupList,
1374 dNumGroups,
1375 dNumOutputRows);
1377 }
1378
1379 return result_rel;
1380}
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394static List *
1397 List *refnames_tlist,
1398 List **tlist_list,
1399 List **istrivial_tlist)
1400{
1403 List *child_tlist;
1404 bool trivial_tlist;
1405
1406 *tlist_list = NIL;
1407 *istrivial_tlist = NIL;
1408
1409 while (pending_rels != NIL)
1410 {
1412
1414
1416 {
1418
1419 if (op->op == top_union->op &&
1420 (op->all == top_union->all || op->all) &&
1421 equal(op->colTypes, top_union->colTypes) &&
1422 equal(op->colCollations, top_union->colCollations))
1423 {
1424
1425 pending_rels = lcons(op->rarg, pending_rels);
1426 pending_rels = lcons(op->larg, pending_rels);
1427 continue;
1428 }
1429 }
1430
1431
1432
1433
1434
1435
1436
1437
1438
1440 top_union->all ? NULL : top_union,
1441 top_union->colTypes,
1442 top_union->colCollations,
1443 refnames_tlist,
1444 &child_tlist,
1445 &trivial_tlist));
1446 *tlist_list = lappend(*tlist_list, child_tlist);
1447 *istrivial_tlist = lappend_int(*istrivial_tlist, trivial_tlist);
1448 }
1449
1450 return result;
1451}
1452
1453
1454
1455
1456static void
1458{
1459
1460
1461
1462
1465 NULL, rel, NULL);
1466
1467
1469}
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482static List *
1485 bool hack_constants,
1486 List *input_tlist,
1487 List *refnames_tlist,
1488 bool *trivial_tlist)
1489{
1491 int resno = 1;
1493 *cclc,
1494 *itlc,
1495 *rtlc;
1498
1499 *trivial_tlist = true;
1500
1501 forfour(ctlc, colTypes, cclc, colCollations,
1502 itlc, input_tlist, rtlc, refnames_tlist)
1503 {
1508
1511 Assert(!inputtle->resjunk);
1512 Assert(!reftle->resjunk);
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530 if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const))
1531 expr = (Node *) inputtle->expr;
1532 else
1534 inputtle->resno,
1538 0);
1539
1540 if (exprType(expr) != colType)
1541 {
1542
1543
1544
1545
1546
1547
1548
1549
1551 expr,
1552 colType,
1553 "UNION/INTERSECT/EXCEPT");
1554 *trivial_tlist = false;
1555 }
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1569 {
1573 *trivial_tlist = false;
1574 }
1575
1578 pstrdup(reftle->resname),
1579 false);
1580
1581
1582
1583
1584
1585
1587
1588 tlist = lappend(tlist, tle);
1589 }
1590
1591 return tlist;
1592}
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610static List *
1612 List *input_tlists,
1613 List *refnames_tlist)
1614{
1616 int resno = 1;
1620 int colindex;
1624 int32 *colTypmods;
1625
1626
1627
1628
1629
1630
1631
1633
1634 foreach(tlistl, input_tlists)
1635 {
1638
1639 curColType = list_head(colTypes);
1640 colindex = 0;
1641 foreach(subtlistl, subtlist)
1642 {
1644
1645 Assert(!subtle->resjunk);
1646 Assert(curColType != NULL);
1648 {
1649
1651
1652 if (tlistl == list_head(input_tlists))
1653 colTypmods[colindex] = subtypmod;
1654 else if (subtypmod != colTypmods[colindex])
1655 colTypmods[colindex] = -1;
1656 }
1657 else
1658 {
1659
1660 colTypmods[colindex] = -1;
1661 }
1662 curColType = lnext(colTypes, curColType);
1663 colindex++;
1664 }
1665 Assert(curColType == NULL);
1666 }
1667
1668
1669
1670
1671 colindex = 0;
1672 forthree(curColType, colTypes, curColCollation, colCollations,
1673 ref_tl_item, refnames_tlist)
1674 {
1676 int32 colTypmod = colTypmods[colindex++];
1679
1681 Assert(!reftle->resjunk);
1683 resno,
1684 colType,
1685 colTypmod,
1686 colColl,
1687 0);
1690 pstrdup(reftle->resname),
1691 false);
1692
1693
1694
1695
1696
1697
1699
1700 tlist = lappend(tlist, tle);
1701 }
1702
1703 pfree(colTypmods);
1704
1705 return tlist;
1706}
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719static List *
1721{
1725
1727 foreach(lt, targetlist)
1728 {
1731
1732 Assert(!tle->resjunk);
1733
1734
1736
1737
1740 lg = lnext(grouplist, lg);
1742
1744 }
1746 return grouplist;
1747}
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1761{
1764 double parent_rows = 0;
1765 double parent_size = 0;
1766
1768
1769
1770 foreach(lc, child_pathlist)
1771 {
1773
1774 parent_rows += path->rows;
1775 parent_size += path->parent->reltarget->width * path->rows;
1776 }
1777
1778 if (parent_rows > 0)
1779 reltarget->width = rint(parent_size / parent_rows);
1780
1781 return reltarget;
1782}
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
int max_parallel_workers_per_gather
void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel)
bool enable_parallel_append
bool enable_incremental_sort
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
bool equal(const void *a, const void *b)
void add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel, List *child_tlist, List *setop_pathkeys)
#define palloc_array(type, count)
Assert(PointerIsAligned(start, uint64))
bool is_dummy_rel(RelOptInfo *rel)
void mark_dummy_rel(RelOptInfo *rel)
List * lappend(List *list, void *datum)
List * list_delete_first(List *list)
List * lappend_int(List *list, int datum)
List * lcons(void *datum, List *list)
Datum subpath(PG_FUNCTION_ARGS)
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
char * pstrdup(const char *in)
void pfree(void *pointer)
Oid exprType(const Node *expr)
int32 exprTypmod(const Node *expr)
Oid exprCollation(const Node *expr)
Node * applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat, int rlocation, bool overwrite_ok)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
Node * coerce_to_common_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *context)
Path * get_cheapest_path_for_pathkeys(List *paths, List *pathkeys, Relids required_outer, CostSelector cost_criterion, bool require_parallel_safe)
bool pathkeys_count_contained_in(List *keys1, List *keys2, int *n_common)
List * make_pathkeys_for_sortclauses(PlannerInfo *root, List *sortclauses, List *tlist)
List * convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, List *subquery_pathkeys, List *subquery_tlist)
bool pathkeys_contained_in(List *keys1, List *keys2)
SetOpPath * create_setop_path(PlannerInfo *root, RelOptInfo *rel, Path *leftpath, Path *rightpath, SetOpCmd cmd, SetOpStrategy strategy, List *groupList, double numGroups, double outputRows)
ProjectionPath * create_projection_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
Path * apply_projection_to_path(PlannerInfo *root, RelOptInfo *rel, Path *path, PathTarget *target)
void set_cheapest(RelOptInfo *parent_rel)
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
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)
SubqueryScanPath * create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, bool trivial_pathtarget, List *pathkeys, Relids required_outer)
IncrementalSortPath * create_incremental_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, int presorted_keys, double limit_tuples)
SortPath * create_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)
GatherPath * create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, Relids required_outer, double *rows)
void add_path(RelOptInfo *parent_rel, Path *new_path)
UniquePath * create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, int numCols, double numGroups)
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)
RecursiveUnionPath * create_recursiveunion_path(PlannerInfo *root, RelOptInfo *rel, Path *leftpath, Path *rightpath, PathTarget *target, List *distinctList, int wtParam, double numGroups)
MergeAppendPath * create_merge_append_path(PlannerInfo *root, RelOptInfo *rel, List *subpaths, List *pathkeys, Relids required_outer)
static int pg_leftmost_one_pos32(uint32 word)
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define forthree(cell1, list1, cell2, list2, cell3, list3)
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
static ListCell * list_head(const List *l)
static ListCell * lnext(const List *l, const ListCell *c)
#define list_make2(x1, x2)
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)
create_upper_paths_hook_type create_upper_paths_hook
RelOptInfo * plan_set_operations(PlannerInfo *root)
static List * generate_setop_grouplist(SetOperationStmt *op, List *targetlist)
static RelOptInfo * generate_union_paths(SetOperationStmt *op, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
static RelOptInfo * generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
static PathTarget * create_setop_pathtarget(PlannerInfo *root, List *tlist, List *child_pathlist)
static void postprocess_setop_rel(PlannerInfo *root, RelOptInfo *rel)
static List * generate_setop_tlist(List *colTypes, List *colCollations, Index varno, bool hack_constants, List *input_tlist, List *refnames_tlist, bool *trivial_tlist)
static RelOptInfo * recurse_set_operations(Node *setOp, PlannerInfo *root, SetOperationStmt *parentOp, List *colTypes, List *colCollations, List *refnames_tlist, List **pTargetList, bool *istrivial_tlist)
static RelOptInfo * generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
static List * generate_append_tlist(List *colTypes, List *colCollations, List *input_tlists, List *refnames_tlist)
static List * plan_union_children(PlannerInfo *root, SetOperationStmt *top_union, List *refnames_tlist, List **tlist_list, List **istrivial_tlist)
static void build_setop_child_paths(PlannerInfo *root, RelOptInfo *rel, bool trivial_tlist, List *child_tlist, List *interesting_pathkeys, double *pNumGroups)
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
void setup_simple_rel_arrays(PlannerInfo *root)
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset, EstimationInfo *estinfo)
void check_stack_depth(void)
struct PathTarget * reltarget
struct Path * cheapest_total_path
bool tlist_same_collations(List *tlist, List *colCollations, bool junkOK)
bool grouping_is_sortable(List *groupClause)
List * make_tlist_from_pathtarget(PathTarget *target)
List * get_tlist_exprs(List *tlist, bool includeJunk)
bool grouping_is_hashable(List *groupClause)
bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
#define create_pathtarget(root, tlist)