00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "postgres.h"
00018
00019 #include <limits.h>
00020 #include <math.h>
00021
00022 #include "access/skey.h"
00023 #include "catalog/pg_class.h"
00024 #include "foreign/fdwapi.h"
00025 #include "miscadmin.h"
00026 #include "nodes/makefuncs.h"
00027 #include "nodes/nodeFuncs.h"
00028 #include "optimizer/clauses.h"
00029 #include "optimizer/cost.h"
00030 #include "optimizer/paths.h"
00031 #include "optimizer/placeholder.h"
00032 #include "optimizer/plancat.h"
00033 #include "optimizer/planmain.h"
00034 #include "optimizer/planner.h"
00035 #include "optimizer/predtest.h"
00036 #include "optimizer/restrictinfo.h"
00037 #include "optimizer/subselect.h"
00038 #include "optimizer/tlist.h"
00039 #include "optimizer/var.h"
00040 #include "parser/parse_clause.h"
00041 #include "parser/parsetree.h"
00042 #include "utils/lsyscache.h"
00043
00044
00045 static Plan *create_plan_recurse(PlannerInfo *root, Path *best_path);
00046 static Plan *create_scan_plan(PlannerInfo *root, Path *best_path);
00047 static List *build_relation_tlist(RelOptInfo *rel);
00048 static bool use_physical_tlist(PlannerInfo *root, RelOptInfo *rel);
00049 static void disuse_physical_tlist(Plan *plan, Path *path);
00050 static Plan *create_gating_plan(PlannerInfo *root, Plan *plan, List *quals);
00051 static Plan *create_join_plan(PlannerInfo *root, JoinPath *best_path);
00052 static Plan *create_append_plan(PlannerInfo *root, AppendPath *best_path);
00053 static Plan *create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path);
00054 static Result *create_result_plan(PlannerInfo *root, ResultPath *best_path);
00055 static Material *create_material_plan(PlannerInfo *root, MaterialPath *best_path);
00056 static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path);
00057 static SeqScan *create_seqscan_plan(PlannerInfo *root, Path *best_path,
00058 List *tlist, List *scan_clauses);
00059 static Scan *create_indexscan_plan(PlannerInfo *root, IndexPath *best_path,
00060 List *tlist, List *scan_clauses, bool indexonly);
00061 static BitmapHeapScan *create_bitmap_scan_plan(PlannerInfo *root,
00062 BitmapHeapPath *best_path,
00063 List *tlist, List *scan_clauses);
00064 static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
00065 List **qual, List **indexqual, List **indexECs);
00066 static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
00067 List *tlist, List *scan_clauses);
00068 static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root, Path *best_path,
00069 List *tlist, List *scan_clauses);
00070 static FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path,
00071 List *tlist, List *scan_clauses);
00072 static ValuesScan *create_valuesscan_plan(PlannerInfo *root, Path *best_path,
00073 List *tlist, List *scan_clauses);
00074 static CteScan *create_ctescan_plan(PlannerInfo *root, Path *best_path,
00075 List *tlist, List *scan_clauses);
00076 static WorkTableScan *create_worktablescan_plan(PlannerInfo *root, Path *best_path,
00077 List *tlist, List *scan_clauses);
00078 static ForeignScan *create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
00079 List *tlist, List *scan_clauses);
00080 static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path,
00081 Plan *outer_plan, Plan *inner_plan);
00082 static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path,
00083 Plan *outer_plan, Plan *inner_plan);
00084 static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path,
00085 Plan *outer_plan, Plan *inner_plan);
00086 static Node *replace_nestloop_params(PlannerInfo *root, Node *expr);
00087 static Node *replace_nestloop_params_mutator(Node *node, PlannerInfo *root);
00088 static void process_subquery_nestloop_params(PlannerInfo *root,
00089 List *subplan_params);
00090 static List *fix_indexqual_references(PlannerInfo *root, IndexPath *index_path);
00091 static List *fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path);
00092 static Node *fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol);
00093 static List *get_switched_clauses(List *clauses, Relids outerrelids);
00094 static List *order_qual_clauses(PlannerInfo *root, List *clauses);
00095 static void copy_path_costsize(Plan *dest, Path *src);
00096 static void copy_plan_costsize(Plan *dest, Plan *src);
00097 static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
00098 static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
00099 Oid indexid, List *indexqual, List *indexqualorig,
00100 List *indexorderby, List *indexorderbyorig,
00101 ScanDirection indexscandir);
00102 static IndexOnlyScan *make_indexonlyscan(List *qptlist, List *qpqual,
00103 Index scanrelid, Oid indexid,
00104 List *indexqual, List *indexorderby,
00105 List *indextlist,
00106 ScanDirection indexscandir);
00107 static BitmapIndexScan *make_bitmap_indexscan(Index scanrelid, Oid indexid,
00108 List *indexqual,
00109 List *indexqualorig);
00110 static BitmapHeapScan *make_bitmap_heapscan(List *qptlist,
00111 List *qpqual,
00112 Plan *lefttree,
00113 List *bitmapqualorig,
00114 Index scanrelid);
00115 static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
00116 List *tidquals);
00117 static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
00118 Index scanrelid, Node *funcexpr, List *funccolnames,
00119 List *funccoltypes, List *funccoltypmods,
00120 List *funccolcollations);
00121 static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,
00122 Index scanrelid, List *values_lists);
00123 static CteScan *make_ctescan(List *qptlist, List *qpqual,
00124 Index scanrelid, int ctePlanId, int cteParam);
00125 static WorkTableScan *make_worktablescan(List *qptlist, List *qpqual,
00126 Index scanrelid, int wtParam);
00127 static BitmapAnd *make_bitmap_and(List *bitmapplans);
00128 static BitmapOr *make_bitmap_or(List *bitmapplans);
00129 static NestLoop *make_nestloop(List *tlist,
00130 List *joinclauses, List *otherclauses, List *nestParams,
00131 Plan *lefttree, Plan *righttree,
00132 JoinType jointype);
00133 static HashJoin *make_hashjoin(List *tlist,
00134 List *joinclauses, List *otherclauses,
00135 List *hashclauses,
00136 Plan *lefttree, Plan *righttree,
00137 JoinType jointype);
00138 static Hash *make_hash(Plan *lefttree,
00139 Oid skewTable,
00140 AttrNumber skewColumn,
00141 bool skewInherit,
00142 Oid skewColType,
00143 int32 skewColTypmod);
00144 static MergeJoin *make_mergejoin(List *tlist,
00145 List *joinclauses, List *otherclauses,
00146 List *mergeclauses,
00147 Oid *mergefamilies,
00148 Oid *mergecollations,
00149 int *mergestrategies,
00150 bool *mergenullsfirst,
00151 Plan *lefttree, Plan *righttree,
00152 JoinType jointype);
00153 static Sort *make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
00154 AttrNumber *sortColIdx, Oid *sortOperators,
00155 Oid *collations, bool *nullsFirst,
00156 double limit_tuples);
00157 static Plan *prepare_sort_from_pathkeys(PlannerInfo *root,
00158 Plan *lefttree, List *pathkeys,
00159 Relids relids,
00160 const AttrNumber *reqColIdx,
00161 bool adjust_tlist_in_place,
00162 int *p_numsortkeys,
00163 AttrNumber **p_sortColIdx,
00164 Oid **p_sortOperators,
00165 Oid **p_collations,
00166 bool **p_nullsFirst);
00167 static EquivalenceMember *find_ec_member_for_tle(EquivalenceClass *ec,
00168 TargetEntry *tle,
00169 Relids relids);
00170 static Material *make_material(Plan *lefttree);
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 Plan *
00189 create_plan(PlannerInfo *root, Path *best_path)
00190 {
00191 Plan *plan;
00192
00193
00194 Assert(root->plan_params == NIL);
00195
00196
00197 root->curOuterRels = NULL;
00198 root->curOuterParams = NIL;
00199
00200
00201 plan = create_plan_recurse(root, best_path);
00202
00203
00204 if (root->curOuterParams != NIL)
00205 elog(ERROR, "failed to assign all NestLoopParams to plan nodes");
00206
00207
00208
00209
00210
00211 root->plan_params = NIL;
00212
00213 return plan;
00214 }
00215
00216
00217
00218
00219
00220 static Plan *
00221 create_plan_recurse(PlannerInfo *root, Path *best_path)
00222 {
00223 Plan *plan;
00224
00225 switch (best_path->pathtype)
00226 {
00227 case T_SeqScan:
00228 case T_IndexScan:
00229 case T_IndexOnlyScan:
00230 case T_BitmapHeapScan:
00231 case T_TidScan:
00232 case T_SubqueryScan:
00233 case T_FunctionScan:
00234 case T_ValuesScan:
00235 case T_CteScan:
00236 case T_WorkTableScan:
00237 case T_ForeignScan:
00238 plan = create_scan_plan(root, best_path);
00239 break;
00240 case T_HashJoin:
00241 case T_MergeJoin:
00242 case T_NestLoop:
00243 plan = create_join_plan(root,
00244 (JoinPath *) best_path);
00245 break;
00246 case T_Append:
00247 plan = create_append_plan(root,
00248 (AppendPath *) best_path);
00249 break;
00250 case T_MergeAppend:
00251 plan = create_merge_append_plan(root,
00252 (MergeAppendPath *) best_path);
00253 break;
00254 case T_Result:
00255 plan = (Plan *) create_result_plan(root,
00256 (ResultPath *) best_path);
00257 break;
00258 case T_Material:
00259 plan = (Plan *) create_material_plan(root,
00260 (MaterialPath *) best_path);
00261 break;
00262 case T_Unique:
00263 plan = create_unique_plan(root,
00264 (UniquePath *) best_path);
00265 break;
00266 default:
00267 elog(ERROR, "unrecognized node type: %d",
00268 (int) best_path->pathtype);
00269 plan = NULL;
00270 break;
00271 }
00272
00273 return plan;
00274 }
00275
00276
00277
00278
00279
00280 static Plan *
00281 create_scan_plan(PlannerInfo *root, Path *best_path)
00282 {
00283 RelOptInfo *rel = best_path->parent;
00284 List *tlist;
00285 List *scan_clauses;
00286 Plan *plan;
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 if (use_physical_tlist(root, rel))
00297 {
00298 if (best_path->pathtype == T_IndexOnlyScan)
00299 {
00300
00301 tlist = copyObject(((IndexPath *) best_path)->indexinfo->indextlist);
00302 }
00303 else
00304 {
00305 tlist = build_physical_tlist(root, rel);
00306
00307 if (tlist == NIL)
00308 tlist = build_relation_tlist(rel);
00309 }
00310 }
00311 else
00312 {
00313 tlist = build_relation_tlist(rel);
00314
00315
00316
00317
00318
00319
00320
00321 if (rel->reloptkind != RELOPT_BASEREL && best_path->param_info)
00322 tlist = (List *) replace_nestloop_params(root, (Node *) tlist);
00323 }
00324
00325
00326
00327
00328
00329
00330 scan_clauses = rel->baserestrictinfo;
00331
00332
00333
00334
00335
00336
00337
00338 if (best_path->param_info)
00339 scan_clauses = list_concat(list_copy(scan_clauses),
00340 best_path->param_info->ppi_clauses);
00341
00342 switch (best_path->pathtype)
00343 {
00344 case T_SeqScan:
00345 plan = (Plan *) create_seqscan_plan(root,
00346 best_path,
00347 tlist,
00348 scan_clauses);
00349 break;
00350
00351 case T_IndexScan:
00352 plan = (Plan *) create_indexscan_plan(root,
00353 (IndexPath *) best_path,
00354 tlist,
00355 scan_clauses,
00356 false);
00357 break;
00358
00359 case T_IndexOnlyScan:
00360 plan = (Plan *) create_indexscan_plan(root,
00361 (IndexPath *) best_path,
00362 tlist,
00363 scan_clauses,
00364 true);
00365 break;
00366
00367 case T_BitmapHeapScan:
00368 plan = (Plan *) create_bitmap_scan_plan(root,
00369 (BitmapHeapPath *) best_path,
00370 tlist,
00371 scan_clauses);
00372 break;
00373
00374 case T_TidScan:
00375 plan = (Plan *) create_tidscan_plan(root,
00376 (TidPath *) best_path,
00377 tlist,
00378 scan_clauses);
00379 break;
00380
00381 case T_SubqueryScan:
00382 plan = (Plan *) create_subqueryscan_plan(root,
00383 best_path,
00384 tlist,
00385 scan_clauses);
00386 break;
00387
00388 case T_FunctionScan:
00389 plan = (Plan *) create_functionscan_plan(root,
00390 best_path,
00391 tlist,
00392 scan_clauses);
00393 break;
00394
00395 case T_ValuesScan:
00396 plan = (Plan *) create_valuesscan_plan(root,
00397 best_path,
00398 tlist,
00399 scan_clauses);
00400 break;
00401
00402 case T_CteScan:
00403 plan = (Plan *) create_ctescan_plan(root,
00404 best_path,
00405 tlist,
00406 scan_clauses);
00407 break;
00408
00409 case T_WorkTableScan:
00410 plan = (Plan *) create_worktablescan_plan(root,
00411 best_path,
00412 tlist,
00413 scan_clauses);
00414 break;
00415
00416 case T_ForeignScan:
00417 plan = (Plan *) create_foreignscan_plan(root,
00418 (ForeignPath *) best_path,
00419 tlist,
00420 scan_clauses);
00421 break;
00422
00423 default:
00424 elog(ERROR, "unrecognized node type: %d",
00425 (int) best_path->pathtype);
00426 plan = NULL;
00427 break;
00428 }
00429
00430
00431
00432
00433
00434
00435 if (root->hasPseudoConstantQuals)
00436 plan = create_gating_plan(root, plan, scan_clauses);
00437
00438 return plan;
00439 }
00440
00441
00442
00443
00444 static List *
00445 build_relation_tlist(RelOptInfo *rel)
00446 {
00447 List *tlist = NIL;
00448 int resno = 1;
00449 ListCell *v;
00450
00451 foreach(v, rel->reltargetlist)
00452 {
00453
00454 Node *node = (Node *) copyObject(lfirst(v));
00455
00456 tlist = lappend(tlist, makeTargetEntry((Expr *) node,
00457 resno,
00458 NULL,
00459 false));
00460 resno++;
00461 }
00462 return tlist;
00463 }
00464
00465
00466
00467
00468
00469
00470 static bool
00471 use_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
00472 {
00473 int i;
00474 ListCell *lc;
00475
00476
00477
00478
00479
00480 if (rel->rtekind != RTE_RELATION &&
00481 rel->rtekind != RTE_SUBQUERY &&
00482 rel->rtekind != RTE_FUNCTION &&
00483 rel->rtekind != RTE_VALUES &&
00484 rel->rtekind != RTE_CTE)
00485 return false;
00486
00487
00488
00489
00490
00491 if (rel->reloptkind != RELOPT_BASEREL)
00492 return false;
00493
00494
00495
00496
00497
00498
00499 for (i = rel->min_attr; i <= 0; i++)
00500 {
00501 if (!bms_is_empty(rel->attr_needed[i - rel->min_attr]))
00502 return false;
00503 }
00504
00505
00506
00507
00508
00509 foreach(lc, root->placeholder_list)
00510 {
00511 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
00512
00513 if (bms_nonempty_difference(phinfo->ph_needed, rel->relids) &&
00514 bms_is_subset(phinfo->ph_eval_at, rel->relids))
00515 return false;
00516 }
00517
00518 return true;
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 static void
00531 disuse_physical_tlist(Plan *plan, Path *path)
00532 {
00533
00534 switch (path->pathtype)
00535 {
00536 case T_SeqScan:
00537 case T_IndexScan:
00538 case T_IndexOnlyScan:
00539 case T_BitmapHeapScan:
00540 case T_TidScan:
00541 case T_SubqueryScan:
00542 case T_FunctionScan:
00543 case T_ValuesScan:
00544 case T_CteScan:
00545 case T_WorkTableScan:
00546 case T_ForeignScan:
00547 plan->targetlist = build_relation_tlist(path->parent);
00548 break;
00549 default:
00550 break;
00551 }
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 static Plan *
00574 create_gating_plan(PlannerInfo *root, Plan *plan, List *quals)
00575 {
00576 List *pseudoconstants;
00577
00578
00579 quals = order_qual_clauses(root, quals);
00580
00581
00582 pseudoconstants = extract_actual_clauses(quals, true);
00583
00584 if (!pseudoconstants)
00585 return plan;
00586
00587 return (Plan *) make_result(root,
00588 plan->targetlist,
00589 (Node *) pseudoconstants,
00590 plan);
00591 }
00592
00593
00594
00595
00596
00597
00598 static Plan *
00599 create_join_plan(PlannerInfo *root, JoinPath *best_path)
00600 {
00601 Plan *outer_plan;
00602 Plan *inner_plan;
00603 Plan *plan;
00604 Relids saveOuterRels = root->curOuterRels;
00605
00606 outer_plan = create_plan_recurse(root, best_path->outerjoinpath);
00607
00608
00609 if (best_path->path.pathtype == T_NestLoop)
00610 root->curOuterRels = bms_union(root->curOuterRels,
00611 best_path->outerjoinpath->parent->relids);
00612
00613 inner_plan = create_plan_recurse(root, best_path->innerjoinpath);
00614
00615 switch (best_path->path.pathtype)
00616 {
00617 case T_MergeJoin:
00618 plan = (Plan *) create_mergejoin_plan(root,
00619 (MergePath *) best_path,
00620 outer_plan,
00621 inner_plan);
00622 break;
00623 case T_HashJoin:
00624 plan = (Plan *) create_hashjoin_plan(root,
00625 (HashPath *) best_path,
00626 outer_plan,
00627 inner_plan);
00628 break;
00629 case T_NestLoop:
00630
00631 bms_free(root->curOuterRels);
00632 root->curOuterRels = saveOuterRels;
00633
00634 plan = (Plan *) create_nestloop_plan(root,
00635 (NestPath *) best_path,
00636 outer_plan,
00637 inner_plan);
00638 break;
00639 default:
00640 elog(ERROR, "unrecognized node type: %d",
00641 (int) best_path->path.pathtype);
00642 plan = NULL;
00643 break;
00644 }
00645
00646
00647
00648
00649
00650
00651 if (root->hasPseudoConstantQuals)
00652 plan = create_gating_plan(root, plan, best_path->joinrestrictinfo);
00653
00654 #ifdef NOT_USED
00655
00656
00657
00658
00659
00660
00661 if (get_loc_restrictinfo(best_path) != NIL)
00662 set_qpqual((Plan) plan,
00663 list_concat(get_qpqual((Plan) plan),
00664 get_actual_clauses(get_loc_restrictinfo(best_path))));
00665 #endif
00666
00667 return plan;
00668 }
00669
00670
00671
00672
00673
00674
00675
00676
00677 static Plan *
00678 create_append_plan(PlannerInfo *root, AppendPath *best_path)
00679 {
00680 Append *plan;
00681 RelOptInfo *rel = best_path->path.parent;
00682 List *tlist = build_relation_tlist(rel);
00683 List *subplans = NIL;
00684 ListCell *subpaths;
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 if (best_path->subpaths == NIL)
00696 {
00697
00698
00699
00700
00701
00702
00703
00704 if (rel->rtekind == RTE_SUBQUERY)
00705 {
00706 Assert(is_dummy_plan(rel->subplan));
00707 return (Plan *) make_subqueryscan(tlist,
00708 NIL,
00709 rel->relid,
00710 rel->subplan);
00711 }
00712 else
00713 {
00714
00715 return (Plan *) make_result(root,
00716 tlist,
00717 (Node *) list_make1(makeBoolConst(false,
00718 false)),
00719 NULL);
00720 }
00721 }
00722
00723
00724 foreach(subpaths, best_path->subpaths)
00725 {
00726 Path *subpath = (Path *) lfirst(subpaths);
00727
00728 subplans = lappend(subplans, create_plan_recurse(root, subpath));
00729 }
00730
00731
00732
00733
00734
00735
00736
00737
00738 plan = make_append(subplans, tlist);
00739
00740 return (Plan *) plan;
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750 static Plan *
00751 create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
00752 {
00753 MergeAppend *node = makeNode(MergeAppend);
00754 Plan *plan = &node->plan;
00755 List *tlist = build_relation_tlist(best_path->path.parent);
00756 List *pathkeys = best_path->path.pathkeys;
00757 List *subplans = NIL;
00758 ListCell *subpaths;
00759
00760
00761
00762
00763
00764
00765
00766 copy_path_costsize(plan, (Path *) best_path);
00767 plan->targetlist = tlist;
00768 plan->qual = NIL;
00769 plan->lefttree = NULL;
00770 plan->righttree = NULL;
00771
00772
00773 (void) prepare_sort_from_pathkeys(root, plan, pathkeys,
00774 NULL,
00775 NULL,
00776 true,
00777 &node->numCols,
00778 &node->sortColIdx,
00779 &node->sortOperators,
00780 &node->collations,
00781 &node->nullsFirst);
00782
00783
00784
00785
00786
00787
00788 foreach(subpaths, best_path->subpaths)
00789 {
00790 Path *subpath = (Path *) lfirst(subpaths);
00791 Plan *subplan;
00792 int numsortkeys;
00793 AttrNumber *sortColIdx;
00794 Oid *sortOperators;
00795 Oid *collations;
00796 bool *nullsFirst;
00797
00798
00799 subplan = create_plan_recurse(root, subpath);
00800
00801
00802 subplan = prepare_sort_from_pathkeys(root, subplan, pathkeys,
00803 subpath->parent->relids,
00804 node->sortColIdx,
00805 false,
00806 &numsortkeys,
00807 &sortColIdx,
00808 &sortOperators,
00809 &collations,
00810 &nullsFirst);
00811
00812
00813
00814
00815
00816
00817
00818 Assert(numsortkeys == node->numCols);
00819 if (memcmp(sortColIdx, node->sortColIdx,
00820 numsortkeys * sizeof(AttrNumber)) != 0)
00821 elog(ERROR, "MergeAppend child's targetlist doesn't match MergeAppend");
00822 Assert(memcmp(sortOperators, node->sortOperators,
00823 numsortkeys * sizeof(Oid)) == 0);
00824 Assert(memcmp(collations, node->collations,
00825 numsortkeys * sizeof(Oid)) == 0);
00826 Assert(memcmp(nullsFirst, node->nullsFirst,
00827 numsortkeys * sizeof(bool)) == 0);
00828
00829
00830 if (!pathkeys_contained_in(pathkeys, subpath->pathkeys))
00831 subplan = (Plan *) make_sort(root, subplan, numsortkeys,
00832 sortColIdx, sortOperators,
00833 collations, nullsFirst,
00834 best_path->limit_tuples);
00835
00836 subplans = lappend(subplans, subplan);
00837 }
00838
00839 node->mergeplans = subplans;
00840
00841 return (Plan *) node;
00842 }
00843
00844
00845
00846
00847
00848
00849
00850
00851 static Result *
00852 create_result_plan(PlannerInfo *root, ResultPath *best_path)
00853 {
00854 List *tlist;
00855 List *quals;
00856
00857
00858 Assert(best_path->path.parent == NULL);
00859 tlist = NIL;
00860
00861
00862
00863 quals = order_qual_clauses(root, best_path->quals);
00864
00865 return make_result(root, tlist, (Node *) quals, NULL);
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875 static Material *
00876 create_material_plan(PlannerInfo *root, MaterialPath *best_path)
00877 {
00878 Material *plan;
00879 Plan *subplan;
00880
00881 subplan = create_plan_recurse(root, best_path->subpath);
00882
00883
00884 disuse_physical_tlist(subplan, best_path->subpath);
00885
00886 plan = make_material(subplan);
00887
00888 copy_path_costsize(&plan->plan, (Path *) best_path);
00889
00890 return plan;
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900 static Plan *
00901 create_unique_plan(PlannerInfo *root, UniquePath *best_path)
00902 {
00903 Plan *plan;
00904 Plan *subplan;
00905 List *in_operators;
00906 List *uniq_exprs;
00907 List *newtlist;
00908 int nextresno;
00909 bool newitems;
00910 int numGroupCols;
00911 AttrNumber *groupColIdx;
00912 int groupColPos;
00913 ListCell *l;
00914
00915 subplan = create_plan_recurse(root, best_path->subpath);
00916
00917
00918 if (best_path->umethod == UNIQUE_PATH_NOOP)
00919 return subplan;
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 in_operators = best_path->in_operators;
00938 uniq_exprs = best_path->uniq_exprs;
00939
00940
00941 newtlist = build_relation_tlist(best_path->path.parent);
00942 nextresno = list_length(newtlist) + 1;
00943 newitems = false;
00944
00945 foreach(l, uniq_exprs)
00946 {
00947 Node *uniqexpr = lfirst(l);
00948 TargetEntry *tle;
00949
00950 tle = tlist_member(uniqexpr, newtlist);
00951 if (!tle)
00952 {
00953 tle = makeTargetEntry((Expr *) uniqexpr,
00954 nextresno,
00955 NULL,
00956 false);
00957 newtlist = lappend(newtlist, tle);
00958 nextresno++;
00959 newitems = true;
00960 }
00961 }
00962
00963 if (newitems || best_path->umethod == UNIQUE_PATH_SORT)
00964 {
00965
00966
00967
00968
00969
00970 if (!is_projection_capable_plan(subplan) &&
00971 !tlist_same_exprs(newtlist, subplan->targetlist))
00972 subplan = (Plan *) make_result(root, newtlist, NULL, subplan);
00973 else
00974 subplan->targetlist = newtlist;
00975 }
00976
00977
00978
00979
00980
00981
00982
00983 newtlist = subplan->targetlist;
00984 numGroupCols = list_length(uniq_exprs);
00985 groupColIdx = (AttrNumber *) palloc(numGroupCols * sizeof(AttrNumber));
00986
00987 groupColPos = 0;
00988 foreach(l, uniq_exprs)
00989 {
00990 Node *uniqexpr = lfirst(l);
00991 TargetEntry *tle;
00992
00993 tle = tlist_member(uniqexpr, newtlist);
00994 if (!tle)
00995 elog(ERROR, "failed to find unique expression in subplan tlist");
00996 groupColIdx[groupColPos++] = tle->resno;
00997 }
00998
00999 if (best_path->umethod == UNIQUE_PATH_HASH)
01000 {
01001 long numGroups;
01002 Oid *groupOperators;
01003
01004 numGroups = (long) Min(best_path->path.rows, (double) LONG_MAX);
01005
01006
01007
01008
01009
01010
01011
01012 groupOperators = (Oid *) palloc(numGroupCols * sizeof(Oid));
01013 groupColPos = 0;
01014 foreach(l, in_operators)
01015 {
01016 Oid in_oper = lfirst_oid(l);
01017 Oid eq_oper;
01018
01019 if (!get_compatible_hash_operators(in_oper, NULL, &eq_oper))
01020 elog(ERROR, "could not find compatible hash operator for operator %u",
01021 in_oper);
01022 groupOperators[groupColPos++] = eq_oper;
01023 }
01024
01025
01026
01027
01028
01029
01030 plan = (Plan *) make_agg(root,
01031 build_relation_tlist(best_path->path.parent),
01032 NIL,
01033 AGG_HASHED,
01034 NULL,
01035 numGroupCols,
01036 groupColIdx,
01037 groupOperators,
01038 numGroups,
01039 subplan);
01040 }
01041 else
01042 {
01043 List *sortList = NIL;
01044
01045
01046 groupColPos = 0;
01047 foreach(l, in_operators)
01048 {
01049 Oid in_oper = lfirst_oid(l);
01050 Oid sortop;
01051 Oid eqop;
01052 TargetEntry *tle;
01053 SortGroupClause *sortcl;
01054
01055 sortop = get_ordering_op_for_equality_op(in_oper, false);
01056 if (!OidIsValid(sortop))
01057 elog(ERROR, "could not find ordering operator for equality operator %u",
01058 in_oper);
01059
01060
01061
01062
01063
01064
01065
01066 eqop = get_equality_op_for_ordering_op(sortop, NULL);
01067 if (!OidIsValid(eqop))
01068 elog(ERROR, "could not find equality operator for ordering operator %u",
01069 sortop);
01070
01071 tle = get_tle_by_resno(subplan->targetlist,
01072 groupColIdx[groupColPos]);
01073 Assert(tle != NULL);
01074
01075 sortcl = makeNode(SortGroupClause);
01076 sortcl->tleSortGroupRef = assignSortGroupRef(tle,
01077 subplan->targetlist);
01078 sortcl->eqop = eqop;
01079 sortcl->sortop = sortop;
01080 sortcl->nulls_first = false;
01081 sortcl->hashable = false;
01082 sortList = lappend(sortList, sortcl);
01083 groupColPos++;
01084 }
01085 plan = (Plan *) make_sort_from_sortclauses(root, sortList, subplan);
01086 plan = (Plan *) make_unique(plan, sortList);
01087 }
01088
01089
01090 plan->plan_rows = best_path->path.rows;
01091
01092 return plan;
01093 }
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108 static SeqScan *
01109 create_seqscan_plan(PlannerInfo *root, Path *best_path,
01110 List *tlist, List *scan_clauses)
01111 {
01112 SeqScan *scan_plan;
01113 Index scan_relid = best_path->parent->relid;
01114
01115
01116 Assert(scan_relid > 0);
01117 Assert(best_path->parent->rtekind == RTE_RELATION);
01118
01119
01120 scan_clauses = order_qual_clauses(root, scan_clauses);
01121
01122
01123 scan_clauses = extract_actual_clauses(scan_clauses, false);
01124
01125
01126 if (best_path->param_info)
01127 {
01128 scan_clauses = (List *)
01129 replace_nestloop_params(root, (Node *) scan_clauses);
01130 }
01131
01132 scan_plan = make_seqscan(tlist,
01133 scan_clauses,
01134 scan_relid);
01135
01136 copy_path_costsize(&scan_plan->plan, best_path);
01137
01138 return scan_plan;
01139 }
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151 static Scan *
01152 create_indexscan_plan(PlannerInfo *root,
01153 IndexPath *best_path,
01154 List *tlist,
01155 List *scan_clauses,
01156 bool indexonly)
01157 {
01158 Scan *scan_plan;
01159 List *indexquals = best_path->indexquals;
01160 List *indexorderbys = best_path->indexorderbys;
01161 Index baserelid = best_path->path.parent->relid;
01162 Oid indexoid = best_path->indexinfo->indexoid;
01163 List *qpqual;
01164 List *stripped_indexquals;
01165 List *fixed_indexquals;
01166 List *fixed_indexorderbys;
01167 ListCell *l;
01168
01169
01170 Assert(baserelid > 0);
01171 Assert(best_path->path.parent->rtekind == RTE_RELATION);
01172
01173
01174
01175
01176
01177 stripped_indexquals = get_actual_clauses(indexquals);
01178
01179
01180
01181
01182
01183 fixed_indexquals = fix_indexqual_references(root, best_path);
01184
01185
01186
01187
01188 fixed_indexorderbys = fix_indexorderby_references(root, best_path);
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220 qpqual = NIL;
01221 foreach(l, scan_clauses)
01222 {
01223 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
01224
01225 Assert(IsA(rinfo, RestrictInfo));
01226 if (rinfo->pseudoconstant)
01227 continue;
01228 if (list_member_ptr(indexquals, rinfo))
01229 continue;
01230 if (is_redundant_derived_clause(rinfo, indexquals))
01231 continue;
01232 if (!contain_mutable_functions((Node *) rinfo->clause))
01233 {
01234 List *clausel = list_make1(rinfo->clause);
01235
01236 if (predicate_implied_by(clausel, indexquals))
01237 continue;
01238 if (best_path->indexinfo->indpred)
01239 {
01240 if (baserelid != root->parse->resultRelation &&
01241 get_parse_rowmark(root->parse, baserelid) == NULL)
01242 if (predicate_implied_by(clausel,
01243 best_path->indexinfo->indpred))
01244 continue;
01245 }
01246 }
01247 qpqual = lappend(qpqual, rinfo);
01248 }
01249
01250
01251 qpqual = order_qual_clauses(root, qpqual);
01252
01253
01254 qpqual = extract_actual_clauses(qpqual, false);
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265 if (best_path->path.param_info)
01266 {
01267 stripped_indexquals = (List *)
01268 replace_nestloop_params(root, (Node *) stripped_indexquals);
01269 qpqual = (List *)
01270 replace_nestloop_params(root, (Node *) qpqual);
01271 indexorderbys = (List *)
01272 replace_nestloop_params(root, (Node *) indexorderbys);
01273 }
01274
01275
01276 if (indexonly)
01277 scan_plan = (Scan *) make_indexonlyscan(tlist,
01278 qpqual,
01279 baserelid,
01280 indexoid,
01281 fixed_indexquals,
01282 fixed_indexorderbys,
01283 best_path->indexinfo->indextlist,
01284 best_path->indexscandir);
01285 else
01286 scan_plan = (Scan *) make_indexscan(tlist,
01287 qpqual,
01288 baserelid,
01289 indexoid,
01290 fixed_indexquals,
01291 stripped_indexquals,
01292 fixed_indexorderbys,
01293 indexorderbys,
01294 best_path->indexscandir);
01295
01296 copy_path_costsize(&scan_plan->plan, &best_path->path);
01297
01298 return scan_plan;
01299 }
01300
01301
01302
01303
01304
01305
01306 static BitmapHeapScan *
01307 create_bitmap_scan_plan(PlannerInfo *root,
01308 BitmapHeapPath *best_path,
01309 List *tlist,
01310 List *scan_clauses)
01311 {
01312 Index baserelid = best_path->path.parent->relid;
01313 Plan *bitmapqualplan;
01314 List *bitmapqualorig;
01315 List *indexquals;
01316 List *indexECs;
01317 List *qpqual;
01318 ListCell *l;
01319 BitmapHeapScan *scan_plan;
01320
01321
01322 Assert(baserelid > 0);
01323 Assert(best_path->path.parent->rtekind == RTE_RELATION);
01324
01325
01326 bitmapqualplan = create_bitmap_subplan(root, best_path->bitmapqual,
01327 &bitmapqualorig, &indexquals,
01328 &indexECs);
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355 qpqual = NIL;
01356 foreach(l, scan_clauses)
01357 {
01358 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
01359 Node *clause = (Node *) rinfo->clause;
01360
01361 Assert(IsA(rinfo, RestrictInfo));
01362 if (rinfo->pseudoconstant)
01363 continue;
01364 if (list_member(indexquals, clause))
01365 continue;
01366 if (rinfo->parent_ec && list_member_ptr(indexECs, rinfo->parent_ec))
01367 continue;
01368 if (!contain_mutable_functions(clause))
01369 {
01370 List *clausel = list_make1(clause);
01371
01372 if (predicate_implied_by(clausel, indexquals))
01373 continue;
01374 }
01375 qpqual = lappend(qpqual, rinfo);
01376 }
01377
01378
01379 qpqual = order_qual_clauses(root, qpqual);
01380
01381
01382 qpqual = extract_actual_clauses(qpqual, false);
01383
01384
01385
01386
01387
01388
01389
01390 bitmapqualorig = list_difference_ptr(bitmapqualorig, qpqual);
01391
01392
01393
01394
01395
01396
01397 if (best_path->path.param_info)
01398 {
01399 qpqual = (List *)
01400 replace_nestloop_params(root, (Node *) qpqual);
01401 bitmapqualorig = (List *)
01402 replace_nestloop_params(root, (Node *) bitmapqualorig);
01403 }
01404
01405
01406 scan_plan = make_bitmap_heapscan(tlist,
01407 qpqual,
01408 bitmapqualplan,
01409 bitmapqualorig,
01410 baserelid);
01411
01412 copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
01413
01414 return scan_plan;
01415 }
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440 static Plan *
01441 create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
01442 List **qual, List **indexqual, List **indexECs)
01443 {
01444 Plan *plan;
01445
01446 if (IsA(bitmapqual, BitmapAndPath))
01447 {
01448 BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
01449 List *subplans = NIL;
01450 List *subquals = NIL;
01451 List *subindexquals = NIL;
01452 List *subindexECs = NIL;
01453 ListCell *l;
01454
01455
01456
01457
01458
01459
01460
01461
01462 foreach(l, apath->bitmapquals)
01463 {
01464 Plan *subplan;
01465 List *subqual;
01466 List *subindexqual;
01467 List *subindexEC;
01468
01469 subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
01470 &subqual, &subindexqual,
01471 &subindexEC);
01472 subplans = lappend(subplans, subplan);
01473 subquals = list_concat_unique(subquals, subqual);
01474 subindexquals = list_concat_unique(subindexquals, subindexqual);
01475
01476 subindexECs = list_concat(subindexECs, subindexEC);
01477 }
01478 plan = (Plan *) make_bitmap_and(subplans);
01479 plan->startup_cost = apath->path.startup_cost;
01480 plan->total_cost = apath->path.total_cost;
01481 plan->plan_rows =
01482 clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
01483 plan->plan_width = 0;
01484 *qual = subquals;
01485 *indexqual = subindexquals;
01486 *indexECs = subindexECs;
01487 }
01488 else if (IsA(bitmapqual, BitmapOrPath))
01489 {
01490 BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
01491 List *subplans = NIL;
01492 List *subquals = NIL;
01493 List *subindexquals = NIL;
01494 bool const_true_subqual = false;
01495 bool const_true_subindexqual = false;
01496 ListCell *l;
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507 foreach(l, opath->bitmapquals)
01508 {
01509 Plan *subplan;
01510 List *subqual;
01511 List *subindexqual;
01512 List *subindexEC;
01513
01514 subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
01515 &subqual, &subindexqual,
01516 &subindexEC);
01517 subplans = lappend(subplans, subplan);
01518 if (subqual == NIL)
01519 const_true_subqual = true;
01520 else if (!const_true_subqual)
01521 subquals = lappend(subquals,
01522 make_ands_explicit(subqual));
01523 if (subindexqual == NIL)
01524 const_true_subindexqual = true;
01525 else if (!const_true_subindexqual)
01526 subindexquals = lappend(subindexquals,
01527 make_ands_explicit(subindexqual));
01528 }
01529
01530
01531
01532
01533
01534 if (list_length(subplans) == 1)
01535 {
01536 plan = (Plan *) linitial(subplans);
01537 }
01538 else
01539 {
01540 plan = (Plan *) make_bitmap_or(subplans);
01541 plan->startup_cost = opath->path.startup_cost;
01542 plan->total_cost = opath->path.total_cost;
01543 plan->plan_rows =
01544 clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);
01545 plan->plan_width = 0;
01546 }
01547
01548
01549
01550
01551
01552
01553 if (const_true_subqual)
01554 *qual = NIL;
01555 else if (list_length(subquals) <= 1)
01556 *qual = subquals;
01557 else
01558 *qual = list_make1(make_orclause(subquals));
01559 if (const_true_subindexqual)
01560 *indexqual = NIL;
01561 else if (list_length(subindexquals) <= 1)
01562 *indexqual = subindexquals;
01563 else
01564 *indexqual = list_make1(make_orclause(subindexquals));
01565 *indexECs = NIL;
01566 }
01567 else if (IsA(bitmapqual, IndexPath))
01568 {
01569 IndexPath *ipath = (IndexPath *) bitmapqual;
01570 IndexScan *iscan;
01571 List *subindexECs;
01572 ListCell *l;
01573
01574
01575 iscan = (IndexScan *) create_indexscan_plan(root, ipath,
01576 NIL, NIL, false);
01577 Assert(IsA(iscan, IndexScan));
01578
01579 plan = (Plan *) make_bitmap_indexscan(iscan->scan.scanrelid,
01580 iscan->indexid,
01581 iscan->indexqual,
01582 iscan->indexqualorig);
01583 plan->startup_cost = 0.0;
01584 plan->total_cost = ipath->indextotalcost;
01585 plan->plan_rows =
01586 clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
01587 plan->plan_width = 0;
01588 *qual = get_actual_clauses(ipath->indexclauses);
01589 *indexqual = get_actual_clauses(ipath->indexquals);
01590 foreach(l, ipath->indexinfo->indpred)
01591 {
01592 Expr *pred = (Expr *) lfirst(l);
01593
01594
01595
01596
01597
01598
01599
01600 if (!predicate_implied_by(list_make1(pred), ipath->indexclauses))
01601 {
01602 *qual = lappend(*qual, pred);
01603 *indexqual = lappend(*indexqual, pred);
01604 }
01605 }
01606 subindexECs = NIL;
01607 foreach(l, ipath->indexquals)
01608 {
01609 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
01610
01611 if (rinfo->parent_ec)
01612 subindexECs = lappend(subindexECs, rinfo->parent_ec);
01613 }
01614 *indexECs = subindexECs;
01615 }
01616 else
01617 {
01618 elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
01619 plan = NULL;
01620 }
01621
01622 return plan;
01623 }
01624
01625
01626
01627
01628
01629
01630 static TidScan *
01631 create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
01632 List *tlist, List *scan_clauses)
01633 {
01634 TidScan *scan_plan;
01635 Index scan_relid = best_path->path.parent->relid;
01636 List *tidquals = best_path->tidquals;
01637 List *ortidquals;
01638
01639
01640 Assert(scan_relid > 0);
01641 Assert(best_path->path.parent->rtekind == RTE_RELATION);
01642
01643
01644 scan_clauses = order_qual_clauses(root, scan_clauses);
01645
01646
01647 scan_clauses = extract_actual_clauses(scan_clauses, false);
01648
01649
01650 if (best_path->path.param_info)
01651 {
01652 tidquals = (List *)
01653 replace_nestloop_params(root, (Node *) tidquals);
01654 scan_clauses = (List *)
01655 replace_nestloop_params(root, (Node *) scan_clauses);
01656 }
01657
01658
01659
01660
01661
01662 ortidquals = tidquals;
01663 if (list_length(ortidquals) > 1)
01664 ortidquals = list_make1(make_orclause(ortidquals));
01665 scan_clauses = list_difference(scan_clauses, ortidquals);
01666
01667 scan_plan = make_tidscan(tlist,
01668 scan_clauses,
01669 scan_relid,
01670 tidquals);
01671
01672 copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
01673
01674 return scan_plan;
01675 }
01676
01677
01678
01679
01680
01681
01682 static SubqueryScan *
01683 create_subqueryscan_plan(PlannerInfo *root, Path *best_path,
01684 List *tlist, List *scan_clauses)
01685 {
01686 SubqueryScan *scan_plan;
01687 Index scan_relid = best_path->parent->relid;
01688
01689
01690 Assert(scan_relid > 0);
01691 Assert(best_path->parent->rtekind == RTE_SUBQUERY);
01692
01693
01694 scan_clauses = order_qual_clauses(root, scan_clauses);
01695
01696
01697 scan_clauses = extract_actual_clauses(scan_clauses, false);
01698
01699
01700 if (best_path->param_info)
01701 {
01702 scan_clauses = (List *)
01703 replace_nestloop_params(root, (Node *) scan_clauses);
01704 process_subquery_nestloop_params(root,
01705 best_path->parent->subplan_params);
01706 }
01707
01708 scan_plan = make_subqueryscan(tlist,
01709 scan_clauses,
01710 scan_relid,
01711 best_path->parent->subplan);
01712
01713 copy_path_costsize(&scan_plan->scan.plan, best_path);
01714
01715 return scan_plan;
01716 }
01717
01718
01719
01720
01721
01722
01723 static FunctionScan *
01724 create_functionscan_plan(PlannerInfo *root, Path *best_path,
01725 List *tlist, List *scan_clauses)
01726 {
01727 FunctionScan *scan_plan;
01728 Index scan_relid = best_path->parent->relid;
01729 RangeTblEntry *rte;
01730 Node *funcexpr;
01731
01732
01733 Assert(scan_relid > 0);
01734 rte = planner_rt_fetch(scan_relid, root);
01735 Assert(rte->rtekind == RTE_FUNCTION);
01736 funcexpr = rte->funcexpr;
01737
01738
01739 scan_clauses = order_qual_clauses(root, scan_clauses);
01740
01741
01742 scan_clauses = extract_actual_clauses(scan_clauses, false);
01743
01744
01745 if (best_path->param_info)
01746 {
01747 scan_clauses = (List *)
01748 replace_nestloop_params(root, (Node *) scan_clauses);
01749
01750 funcexpr = replace_nestloop_params(root, funcexpr);
01751 }
01752
01753 scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
01754 funcexpr,
01755 rte->eref->colnames,
01756 rte->funccoltypes,
01757 rte->funccoltypmods,
01758 rte->funccolcollations);
01759
01760 copy_path_costsize(&scan_plan->scan.plan, best_path);
01761
01762 return scan_plan;
01763 }
01764
01765
01766
01767
01768
01769
01770 static ValuesScan *
01771 create_valuesscan_plan(PlannerInfo *root, Path *best_path,
01772 List *tlist, List *scan_clauses)
01773 {
01774 ValuesScan *scan_plan;
01775 Index scan_relid = best_path->parent->relid;
01776 RangeTblEntry *rte;
01777 List *values_lists;
01778
01779
01780 Assert(scan_relid > 0);
01781 rte = planner_rt_fetch(scan_relid, root);
01782 Assert(rte->rtekind == RTE_VALUES);
01783 values_lists = rte->values_lists;
01784
01785
01786 scan_clauses = order_qual_clauses(root, scan_clauses);
01787
01788
01789 scan_clauses = extract_actual_clauses(scan_clauses, false);
01790
01791
01792 if (best_path->param_info)
01793 {
01794 scan_clauses = (List *)
01795 replace_nestloop_params(root, (Node *) scan_clauses);
01796
01797 values_lists = (List *)
01798 replace_nestloop_params(root, (Node *) values_lists);
01799 }
01800
01801 scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid,
01802 values_lists);
01803
01804 copy_path_costsize(&scan_plan->scan.plan, best_path);
01805
01806 return scan_plan;
01807 }
01808
01809
01810
01811
01812
01813
01814 static CteScan *
01815 create_ctescan_plan(PlannerInfo *root, Path *best_path,
01816 List *tlist, List *scan_clauses)
01817 {
01818 CteScan *scan_plan;
01819 Index scan_relid = best_path->parent->relid;
01820 RangeTblEntry *rte;
01821 SubPlan *ctesplan = NULL;
01822 int plan_id;
01823 int cte_param_id;
01824 PlannerInfo *cteroot;
01825 Index levelsup;
01826 int ndx;
01827 ListCell *lc;
01828
01829 Assert(scan_relid > 0);
01830 rte = planner_rt_fetch(scan_relid, root);
01831 Assert(rte->rtekind == RTE_CTE);
01832 Assert(!rte->self_reference);
01833
01834
01835
01836
01837 levelsup = rte->ctelevelsup;
01838 cteroot = root;
01839 while (levelsup-- > 0)
01840 {
01841 cteroot = cteroot->parent_root;
01842 if (!cteroot)
01843 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
01844 }
01845
01846
01847
01848
01849
01850
01851 ndx = 0;
01852 foreach(lc, cteroot->parse->cteList)
01853 {
01854 CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
01855
01856 if (strcmp(cte->ctename, rte->ctename) == 0)
01857 break;
01858 ndx++;
01859 }
01860 if (lc == NULL)
01861 elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
01862 if (ndx >= list_length(cteroot->cte_plan_ids))
01863 elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
01864 plan_id = list_nth_int(cteroot->cte_plan_ids, ndx);
01865 Assert(plan_id > 0);
01866 foreach(lc, cteroot->init_plans)
01867 {
01868 ctesplan = (SubPlan *) lfirst(lc);
01869 if (ctesplan->plan_id == plan_id)
01870 break;
01871 }
01872 if (lc == NULL)
01873 elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
01874
01875
01876
01877
01878
01879 cte_param_id = linitial_int(ctesplan->setParam);
01880
01881
01882 scan_clauses = order_qual_clauses(root, scan_clauses);
01883
01884
01885 scan_clauses = extract_actual_clauses(scan_clauses, false);
01886
01887
01888 if (best_path->param_info)
01889 {
01890 scan_clauses = (List *)
01891 replace_nestloop_params(root, (Node *) scan_clauses);
01892 }
01893
01894 scan_plan = make_ctescan(tlist, scan_clauses, scan_relid,
01895 plan_id, cte_param_id);
01896
01897 copy_path_costsize(&scan_plan->scan.plan, best_path);
01898
01899 return scan_plan;
01900 }
01901
01902
01903
01904
01905
01906
01907 static WorkTableScan *
01908 create_worktablescan_plan(PlannerInfo *root, Path *best_path,
01909 List *tlist, List *scan_clauses)
01910 {
01911 WorkTableScan *scan_plan;
01912 Index scan_relid = best_path->parent->relid;
01913 RangeTblEntry *rte;
01914 Index levelsup;
01915 PlannerInfo *cteroot;
01916
01917 Assert(scan_relid > 0);
01918 rte = planner_rt_fetch(scan_relid, root);
01919 Assert(rte->rtekind == RTE_CTE);
01920 Assert(rte->self_reference);
01921
01922
01923
01924
01925
01926
01927 levelsup = rte->ctelevelsup;
01928 if (levelsup == 0)
01929 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
01930 levelsup--;
01931 cteroot = root;
01932 while (levelsup-- > 0)
01933 {
01934 cteroot = cteroot->parent_root;
01935 if (!cteroot)
01936 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
01937 }
01938 if (cteroot->wt_param_id < 0)
01939 elog(ERROR, "could not find param ID for CTE \"%s\"", rte->ctename);
01940
01941
01942 scan_clauses = order_qual_clauses(root, scan_clauses);
01943
01944
01945 scan_clauses = extract_actual_clauses(scan_clauses, false);
01946
01947
01948 if (best_path->param_info)
01949 {
01950 scan_clauses = (List *)
01951 replace_nestloop_params(root, (Node *) scan_clauses);
01952 }
01953
01954 scan_plan = make_worktablescan(tlist, scan_clauses, scan_relid,
01955 cteroot->wt_param_id);
01956
01957 copy_path_costsize(&scan_plan->scan.plan, best_path);
01958
01959 return scan_plan;
01960 }
01961
01962
01963
01964
01965
01966
01967 static ForeignScan *
01968 create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
01969 List *tlist, List *scan_clauses)
01970 {
01971 ForeignScan *scan_plan;
01972 RelOptInfo *rel = best_path->path.parent;
01973 Index scan_relid = rel->relid;
01974 RangeTblEntry *rte;
01975 int i;
01976
01977
01978 Assert(scan_relid > 0);
01979 Assert(rel->rtekind == RTE_RELATION);
01980 rte = planner_rt_fetch(scan_relid, root);
01981 Assert(rte->rtekind == RTE_RELATION);
01982
01983
01984
01985
01986
01987 scan_clauses = order_qual_clauses(root, scan_clauses);
01988
01989
01990
01991
01992
01993
01994
01995
01996 scan_plan = rel->fdwroutine->GetForeignPlan(root, rel, rte->relid,
01997 best_path,
01998 tlist, scan_clauses);
01999
02000
02001 copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
02002
02003
02004
02005
02006
02007
02008
02009
02010 if (best_path->path.param_info)
02011 {
02012 scan_plan->scan.plan.qual = (List *)
02013 replace_nestloop_params(root, (Node *) scan_plan->scan.plan.qual);
02014 scan_plan->fdw_exprs = (List *)
02015 replace_nestloop_params(root, (Node *) scan_plan->fdw_exprs);
02016 }
02017
02018
02019
02020
02021
02022
02023 scan_plan->fsSystemCol = false;
02024 for (i = rel->min_attr; i < 0; i++)
02025 {
02026 if (!bms_is_empty(rel->attr_needed[i - rel->min_attr]))
02027 {
02028 scan_plan->fsSystemCol = true;
02029 break;
02030 }
02031 }
02032
02033 return scan_plan;
02034 }
02035
02036
02037
02038
02039
02040
02041
02042
02043 static NestLoop *
02044 create_nestloop_plan(PlannerInfo *root,
02045 NestPath *best_path,
02046 Plan *outer_plan,
02047 Plan *inner_plan)
02048 {
02049 NestLoop *join_plan;
02050 List *tlist = build_relation_tlist(best_path->path.parent);
02051 List *joinrestrictclauses = best_path->joinrestrictinfo;
02052 List *joinclauses;
02053 List *otherclauses;
02054 Relids outerrelids;
02055 List *nestParams;
02056 ListCell *cell;
02057 ListCell *prev;
02058 ListCell *next;
02059
02060
02061 joinrestrictclauses = order_qual_clauses(root, joinrestrictclauses);
02062
02063
02064
02065 if (IS_OUTER_JOIN(best_path->jointype))
02066 {
02067 extract_actual_join_clauses(joinrestrictclauses,
02068 &joinclauses, &otherclauses);
02069 }
02070 else
02071 {
02072
02073 joinclauses = extract_actual_clauses(joinrestrictclauses, false);
02074 otherclauses = NIL;
02075 }
02076
02077
02078 if (best_path->path.param_info)
02079 {
02080 joinclauses = (List *)
02081 replace_nestloop_params(root, (Node *) joinclauses);
02082 otherclauses = (List *)
02083 replace_nestloop_params(root, (Node *) otherclauses);
02084 }
02085
02086
02087
02088
02089
02090 outerrelids = best_path->outerjoinpath->parent->relids;
02091 nestParams = NIL;
02092 prev = NULL;
02093 for (cell = list_head(root->curOuterParams); cell; cell = next)
02094 {
02095 NestLoopParam *nlp = (NestLoopParam *) lfirst(cell);
02096
02097 next = lnext(cell);
02098 if (IsA(nlp->paramval, Var) &&
02099 bms_is_member(nlp->paramval->varno, outerrelids))
02100 {
02101 root->curOuterParams = list_delete_cell(root->curOuterParams,
02102 cell, prev);
02103 nestParams = lappend(nestParams, nlp);
02104 }
02105 else if (IsA(nlp->paramval, PlaceHolderVar) &&
02106 bms_overlap(((PlaceHolderVar *) nlp->paramval)->phrels,
02107 outerrelids) &&
02108 bms_is_subset(find_placeholder_info(root,
02109 (PlaceHolderVar *) nlp->paramval,
02110 false)->ph_eval_at,
02111 outerrelids))
02112 {
02113 root->curOuterParams = list_delete_cell(root->curOuterParams,
02114 cell, prev);
02115 nestParams = lappend(nestParams, nlp);
02116 }
02117 else
02118 prev = cell;
02119 }
02120
02121 join_plan = make_nestloop(tlist,
02122 joinclauses,
02123 otherclauses,
02124 nestParams,
02125 outer_plan,
02126 inner_plan,
02127 best_path->jointype);
02128
02129 copy_path_costsize(&join_plan->join.plan, &best_path->path);
02130
02131 return join_plan;
02132 }
02133
02134 static MergeJoin *
02135 create_mergejoin_plan(PlannerInfo *root,
02136 MergePath *best_path,
02137 Plan *outer_plan,
02138 Plan *inner_plan)
02139 {
02140 List *tlist = build_relation_tlist(best_path->jpath.path.parent);
02141 List *joinclauses;
02142 List *otherclauses;
02143 List *mergeclauses;
02144 List *outerpathkeys;
02145 List *innerpathkeys;
02146 int nClauses;
02147 Oid *mergefamilies;
02148 Oid *mergecollations;
02149 int *mergestrategies;
02150 bool *mergenullsfirst;
02151 MergeJoin *join_plan;
02152 int i;
02153 ListCell *lc;
02154 ListCell *lop;
02155 ListCell *lip;
02156
02157
02158
02159 joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
02160
02161
02162
02163 if (IS_OUTER_JOIN(best_path->jpath.jointype))
02164 {
02165 extract_actual_join_clauses(joinclauses,
02166 &joinclauses, &otherclauses);
02167 }
02168 else
02169 {
02170
02171 joinclauses = extract_actual_clauses(joinclauses, false);
02172 otherclauses = NIL;
02173 }
02174
02175
02176
02177
02178
02179 mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
02180 joinclauses = list_difference(joinclauses, mergeclauses);
02181
02182
02183
02184
02185
02186 if (best_path->jpath.path.param_info)
02187 {
02188 joinclauses = (List *)
02189 replace_nestloop_params(root, (Node *) joinclauses);
02190 otherclauses = (List *)
02191 replace_nestloop_params(root, (Node *) otherclauses);
02192 }
02193
02194
02195
02196
02197
02198
02199 mergeclauses = get_switched_clauses(best_path->path_mergeclauses,
02200 best_path->jpath.outerjoinpath->parent->relids);
02201
02202
02203
02204
02205
02206 if (best_path->outersortkeys)
02207 {
02208 disuse_physical_tlist(outer_plan, best_path->jpath.outerjoinpath);
02209 outer_plan = (Plan *)
02210 make_sort_from_pathkeys(root,
02211 outer_plan,
02212 best_path->outersortkeys,
02213 -1.0);
02214 outerpathkeys = best_path->outersortkeys;
02215 }
02216 else
02217 outerpathkeys = best_path->jpath.outerjoinpath->pathkeys;
02218
02219 if (best_path->innersortkeys)
02220 {
02221 disuse_physical_tlist(inner_plan, best_path->jpath.innerjoinpath);
02222 inner_plan = (Plan *)
02223 make_sort_from_pathkeys(root,
02224 inner_plan,
02225 best_path->innersortkeys,
02226 -1.0);
02227 innerpathkeys = best_path->innersortkeys;
02228 }
02229 else
02230 innerpathkeys = best_path->jpath.innerjoinpath->pathkeys;
02231
02232
02233
02234
02235
02236 if (best_path->materialize_inner)
02237 {
02238 Plan *matplan = (Plan *) make_material(inner_plan);
02239
02240
02241
02242
02243
02244
02245 copy_plan_costsize(matplan, inner_plan);
02246 matplan->total_cost += cpu_operator_cost * matplan->plan_rows;
02247
02248 inner_plan = matplan;
02249 }
02250
02251
02252
02253
02254
02255
02256
02257 nClauses = list_length(mergeclauses);
02258 Assert(nClauses == list_length(best_path->path_mergeclauses));
02259 mergefamilies = (Oid *) palloc(nClauses * sizeof(Oid));
02260 mergecollations = (Oid *) palloc(nClauses * sizeof(Oid));
02261 mergestrategies = (int *) palloc(nClauses * sizeof(int));
02262 mergenullsfirst = (bool *) palloc(nClauses * sizeof(bool));
02263
02264 lop = list_head(outerpathkeys);
02265 lip = list_head(innerpathkeys);
02266 i = 0;
02267 foreach(lc, best_path->path_mergeclauses)
02268 {
02269 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
02270 EquivalenceClass *oeclass;
02271 EquivalenceClass *ieclass;
02272 PathKey *opathkey;
02273 PathKey *ipathkey;
02274 EquivalenceClass *opeclass;
02275 EquivalenceClass *ipeclass;
02276 ListCell *l2;
02277
02278
02279 Assert(IsA(rinfo, RestrictInfo));
02280 if (rinfo->outer_is_left)
02281 {
02282 oeclass = rinfo->left_ec;
02283 ieclass = rinfo->right_ec;
02284 }
02285 else
02286 {
02287 oeclass = rinfo->right_ec;
02288 ieclass = rinfo->left_ec;
02289 }
02290 Assert(oeclass != NULL);
02291 Assert(ieclass != NULL);
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305 if (lop)
02306 {
02307 opathkey = (PathKey *) lfirst(lop);
02308 opeclass = opathkey->pk_eclass;
02309 if (oeclass == opeclass)
02310 {
02311
02312 lop = lnext(lop);
02313 }
02314 else
02315 {
02316
02317 foreach(l2, outerpathkeys)
02318 {
02319 if (l2 == lop)
02320 break;
02321 opathkey = (PathKey *) lfirst(l2);
02322 opeclass = opathkey->pk_eclass;
02323 if (oeclass == opeclass)
02324 break;
02325 }
02326 if (oeclass != opeclass)
02327 elog(ERROR, "outer pathkeys do not match mergeclauses");
02328 }
02329 }
02330 else
02331 {
02332
02333 opathkey = NULL;
02334 opeclass = NULL;
02335 foreach(l2, outerpathkeys)
02336 {
02337 opathkey = (PathKey *) lfirst(l2);
02338 opeclass = opathkey->pk_eclass;
02339 if (oeclass == opeclass)
02340 break;
02341 }
02342 if (l2 == NULL)
02343 elog(ERROR, "outer pathkeys do not match mergeclauses");
02344 }
02345
02346 if (lip)
02347 {
02348 ipathkey = (PathKey *) lfirst(lip);
02349 ipeclass = ipathkey->pk_eclass;
02350 if (ieclass == ipeclass)
02351 {
02352
02353 lip = lnext(lip);
02354 }
02355 else
02356 {
02357
02358 foreach(l2, innerpathkeys)
02359 {
02360 if (l2 == lip)
02361 break;
02362 ipathkey = (PathKey *) lfirst(l2);
02363 ipeclass = ipathkey->pk_eclass;
02364 if (ieclass == ipeclass)
02365 break;
02366 }
02367 if (ieclass != ipeclass)
02368 elog(ERROR, "inner pathkeys do not match mergeclauses");
02369 }
02370 }
02371 else
02372 {
02373
02374 ipathkey = NULL;
02375 ipeclass = NULL;
02376 foreach(l2, innerpathkeys)
02377 {
02378 ipathkey = (PathKey *) lfirst(l2);
02379 ipeclass = ipathkey->pk_eclass;
02380 if (ieclass == ipeclass)
02381 break;
02382 }
02383 if (l2 == NULL)
02384 elog(ERROR, "inner pathkeys do not match mergeclauses");
02385 }
02386
02387
02388 if (opathkey->pk_opfamily != ipathkey->pk_opfamily ||
02389 opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation ||
02390 opathkey->pk_strategy != ipathkey->pk_strategy ||
02391 opathkey->pk_nulls_first != ipathkey->pk_nulls_first)
02392 elog(ERROR, "left and right pathkeys do not match in mergejoin");
02393
02394
02395 mergefamilies[i] = opathkey->pk_opfamily;
02396 mergecollations[i] = opathkey->pk_eclass->ec_collation;
02397 mergestrategies[i] = opathkey->pk_strategy;
02398 mergenullsfirst[i] = opathkey->pk_nulls_first;
02399 i++;
02400 }
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411 join_plan = make_mergejoin(tlist,
02412 joinclauses,
02413 otherclauses,
02414 mergeclauses,
02415 mergefamilies,
02416 mergecollations,
02417 mergestrategies,
02418 mergenullsfirst,
02419 outer_plan,
02420 inner_plan,
02421 best_path->jpath.jointype);
02422
02423
02424 copy_path_costsize(&join_plan->join.plan, &best_path->jpath.path);
02425
02426 return join_plan;
02427 }
02428
02429 static HashJoin *
02430 create_hashjoin_plan(PlannerInfo *root,
02431 HashPath *best_path,
02432 Plan *outer_plan,
02433 Plan *inner_plan)
02434 {
02435 List *tlist = build_relation_tlist(best_path->jpath.path.parent);
02436 List *joinclauses;
02437 List *otherclauses;
02438 List *hashclauses;
02439 Oid skewTable = InvalidOid;
02440 AttrNumber skewColumn = InvalidAttrNumber;
02441 bool skewInherit = false;
02442 Oid skewColType = InvalidOid;
02443 int32 skewColTypmod = -1;
02444 HashJoin *join_plan;
02445 Hash *hash_plan;
02446
02447
02448 joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
02449
02450
02451
02452
02453 if (IS_OUTER_JOIN(best_path->jpath.jointype))
02454 {
02455 extract_actual_join_clauses(joinclauses,
02456 &joinclauses, &otherclauses);
02457 }
02458 else
02459 {
02460
02461 joinclauses = extract_actual_clauses(joinclauses, false);
02462 otherclauses = NIL;
02463 }
02464
02465
02466
02467
02468
02469 hashclauses = get_actual_clauses(best_path->path_hashclauses);
02470 joinclauses = list_difference(joinclauses, hashclauses);
02471
02472
02473
02474
02475
02476 if (best_path->jpath.path.param_info)
02477 {
02478 joinclauses = (List *)
02479 replace_nestloop_params(root, (Node *) joinclauses);
02480 otherclauses = (List *)
02481 replace_nestloop_params(root, (Node *) otherclauses);
02482 }
02483
02484
02485
02486
02487
02488 hashclauses = get_switched_clauses(best_path->path_hashclauses,
02489 best_path->jpath.outerjoinpath->parent->relids);
02490
02491
02492 disuse_physical_tlist(inner_plan, best_path->jpath.innerjoinpath);
02493
02494
02495 if (best_path->num_batches > 1)
02496 disuse_physical_tlist(outer_plan, best_path->jpath.outerjoinpath);
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506 if (list_length(hashclauses) == 1)
02507 {
02508 OpExpr *clause = (OpExpr *) linitial(hashclauses);
02509 Node *node;
02510
02511 Assert(is_opclause(clause));
02512 node = (Node *) linitial(clause->args);
02513 if (IsA(node, RelabelType))
02514 node = (Node *) ((RelabelType *) node)->arg;
02515 if (IsA(node, Var))
02516 {
02517 Var *var = (Var *) node;
02518 RangeTblEntry *rte;
02519
02520 rte = root->simple_rte_array[var->varno];
02521 if (rte->rtekind == RTE_RELATION)
02522 {
02523 skewTable = rte->relid;
02524 skewColumn = var->varattno;
02525 skewInherit = rte->inh;
02526 skewColType = var->vartype;
02527 skewColTypmod = var->vartypmod;
02528 }
02529 }
02530 }
02531
02532
02533
02534
02535 hash_plan = make_hash(inner_plan,
02536 skewTable,
02537 skewColumn,
02538 skewInherit,
02539 skewColType,
02540 skewColTypmod);
02541 join_plan = make_hashjoin(tlist,
02542 joinclauses,
02543 otherclauses,
02544 hashclauses,
02545 outer_plan,
02546 (Plan *) hash_plan,
02547 best_path->jpath.jointype);
02548
02549 copy_path_costsize(&join_plan->join.plan, &best_path->jpath.path);
02550
02551 return join_plan;
02552 }
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570 static Node *
02571 replace_nestloop_params(PlannerInfo *root, Node *expr)
02572 {
02573
02574 return replace_nestloop_params_mutator(expr, root);
02575 }
02576
02577 static Node *
02578 replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
02579 {
02580 if (node == NULL)
02581 return NULL;
02582 if (IsA(node, Var))
02583 {
02584 Var *var = (Var *) node;
02585 Param *param;
02586 NestLoopParam *nlp;
02587 ListCell *lc;
02588
02589
02590 Assert(var->varlevelsup == 0);
02591
02592 if (!bms_is_member(var->varno, root->curOuterRels))
02593 return node;
02594
02595 param = assign_nestloop_param_var(root, var);
02596
02597 foreach(lc, root->curOuterParams)
02598 {
02599 nlp = (NestLoopParam *) lfirst(lc);
02600 if (nlp->paramno == param->paramid)
02601 {
02602 Assert(equal(var, nlp->paramval));
02603
02604 return (Node *) param;
02605 }
02606 }
02607
02608 nlp = makeNode(NestLoopParam);
02609 nlp->paramno = param->paramid;
02610 nlp->paramval = var;
02611 root->curOuterParams = lappend(root->curOuterParams, nlp);
02612
02613 return (Node *) param;
02614 }
02615 if (IsA(node, PlaceHolderVar))
02616 {
02617 PlaceHolderVar *phv = (PlaceHolderVar *) node;
02618 Param *param;
02619 NestLoopParam *nlp;
02620 ListCell *lc;
02621
02622
02623 Assert(phv->phlevelsup == 0);
02624
02625
02626
02627
02628
02629
02630
02631 if (!bms_overlap(phv->phrels, root->curOuterRels))
02632 return node;
02633 if (!bms_is_subset(find_placeholder_info(root, phv, false)->ph_eval_at,
02634 root->curOuterRels))
02635 return node;
02636
02637 param = assign_nestloop_param_placeholdervar(root, phv);
02638
02639 foreach(lc, root->curOuterParams)
02640 {
02641 nlp = (NestLoopParam *) lfirst(lc);
02642 if (nlp->paramno == param->paramid)
02643 {
02644 Assert(equal(phv, nlp->paramval));
02645
02646 return (Node *) param;
02647 }
02648 }
02649
02650 nlp = makeNode(NestLoopParam);
02651 nlp->paramno = param->paramid;
02652 nlp->paramval = (Var *) phv;
02653 root->curOuterParams = lappend(root->curOuterParams, nlp);
02654
02655 return (Node *) param;
02656 }
02657 return expression_tree_mutator(node,
02658 replace_nestloop_params_mutator,
02659 (void *) root);
02660 }
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675 static void
02676 process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
02677 {
02678 ListCell *ppl;
02679
02680 foreach(ppl, subplan_params)
02681 {
02682 PlannerParamItem *pitem = (PlannerParamItem *) lfirst(ppl);
02683
02684 if (IsA(pitem->item, Var))
02685 {
02686 Var *var = (Var *) pitem->item;
02687 NestLoopParam *nlp;
02688 ListCell *lc;
02689
02690
02691 if (!bms_is_member(var->varno, root->curOuterRels))
02692 elog(ERROR, "non-LATERAL parameter required by subquery");
02693
02694 foreach(lc, root->curOuterParams)
02695 {
02696 nlp = (NestLoopParam *) lfirst(lc);
02697 if (nlp->paramno == pitem->paramId)
02698 {
02699 Assert(equal(var, nlp->paramval));
02700
02701 break;
02702 }
02703 }
02704 if (lc == NULL)
02705 {
02706
02707 nlp = makeNode(NestLoopParam);
02708 nlp->paramno = pitem->paramId;
02709 nlp->paramval = copyObject(var);
02710 root->curOuterParams = lappend(root->curOuterParams, nlp);
02711 }
02712 }
02713 else if (IsA(pitem->item, PlaceHolderVar))
02714 {
02715 PlaceHolderVar *phv = (PlaceHolderVar *) pitem->item;
02716 NestLoopParam *nlp;
02717 ListCell *lc;
02718
02719
02720 if (!bms_is_subset(find_placeholder_info(root, phv, false)->ph_eval_at,
02721 root->curOuterRels))
02722 elog(ERROR, "non-LATERAL parameter required by subquery");
02723
02724 foreach(lc, root->curOuterParams)
02725 {
02726 nlp = (NestLoopParam *) lfirst(lc);
02727 if (nlp->paramno == pitem->paramId)
02728 {
02729 Assert(equal(phv, nlp->paramval));
02730
02731 break;
02732 }
02733 }
02734 if (lc == NULL)
02735 {
02736
02737 nlp = makeNode(NestLoopParam);
02738 nlp->paramno = pitem->paramId;
02739 nlp->paramval = copyObject(phv);
02740 root->curOuterParams = lappend(root->curOuterParams, nlp);
02741 }
02742 }
02743 else
02744 elog(ERROR, "unexpected type of subquery parameter");
02745 }
02746 }
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767 static List *
02768 fix_indexqual_references(PlannerInfo *root, IndexPath *index_path)
02769 {
02770 IndexOptInfo *index = index_path->indexinfo;
02771 List *fixed_indexquals;
02772 ListCell *lcc,
02773 *lci;
02774
02775 fixed_indexquals = NIL;
02776
02777 forboth(lcc, index_path->indexquals, lci, index_path->indexqualcols)
02778 {
02779 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcc);
02780 int indexcol = lfirst_int(lci);
02781 Node *clause;
02782
02783 Assert(IsA(rinfo, RestrictInfo));
02784
02785
02786
02787
02788
02789
02790
02791 clause = replace_nestloop_params(root, (Node *) rinfo->clause);
02792
02793 if (IsA(clause, OpExpr))
02794 {
02795 OpExpr *op = (OpExpr *) clause;
02796
02797 if (list_length(op->args) != 2)
02798 elog(ERROR, "indexqual clause is not binary opclause");
02799
02800
02801
02802
02803
02804
02805 if (!bms_equal(rinfo->left_relids, index->rel->relids))
02806 CommuteOpExpr(op);
02807
02808
02809
02810
02811 linitial(op->args) = fix_indexqual_operand(linitial(op->args),
02812 index,
02813 indexcol);
02814 }
02815 else if (IsA(clause, RowCompareExpr))
02816 {
02817 RowCompareExpr *rc = (RowCompareExpr *) clause;
02818 Expr *newrc;
02819 List *indexcolnos;
02820 bool var_on_left;
02821 ListCell *lca,
02822 *lcai;
02823
02824
02825
02826
02827 newrc = adjust_rowcompare_for_index(rc,
02828 index,
02829 indexcol,
02830 &indexcolnos,
02831 &var_on_left);
02832
02833
02834
02835
02836
02837
02838 if (newrc != (Expr *) rc)
02839 elog(ERROR, "inconsistent results from adjust_rowcompare_for_index");
02840
02841
02842
02843
02844
02845 if (!var_on_left)
02846 CommuteRowCompareExpr(rc);
02847
02848
02849
02850
02851 Assert(list_length(rc->largs) == list_length(indexcolnos));
02852 forboth(lca, rc->largs, lcai, indexcolnos)
02853 {
02854 lfirst(lca) = fix_indexqual_operand(lfirst(lca),
02855 index,
02856 lfirst_int(lcai));
02857 }
02858 }
02859 else if (IsA(clause, ScalarArrayOpExpr))
02860 {
02861 ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
02862
02863
02864
02865
02866 linitial(saop->args) = fix_indexqual_operand(linitial(saop->args),
02867 index,
02868 indexcol);
02869 }
02870 else if (IsA(clause, NullTest))
02871 {
02872 NullTest *nt = (NullTest *) clause;
02873
02874
02875 nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg,
02876 index,
02877 indexcol);
02878 }
02879 else
02880 elog(ERROR, "unsupported indexqual type: %d",
02881 (int) nodeTag(clause));
02882
02883 fixed_indexquals = lappend(fixed_indexquals, clause);
02884 }
02885
02886 return fixed_indexquals;
02887 }
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900 static List *
02901 fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path)
02902 {
02903 IndexOptInfo *index = index_path->indexinfo;
02904 List *fixed_indexorderbys;
02905 ListCell *lcc,
02906 *lci;
02907
02908 fixed_indexorderbys = NIL;
02909
02910 forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
02911 {
02912 Node *clause = (Node *) lfirst(lcc);
02913 int indexcol = lfirst_int(lci);
02914
02915
02916
02917
02918
02919
02920
02921 clause = replace_nestloop_params(root, clause);
02922
02923 if (IsA(clause, OpExpr))
02924 {
02925 OpExpr *op = (OpExpr *) clause;
02926
02927 if (list_length(op->args) != 2)
02928 elog(ERROR, "indexorderby clause is not binary opclause");
02929
02930
02931
02932
02933 linitial(op->args) = fix_indexqual_operand(linitial(op->args),
02934 index,
02935 indexcol);
02936 }
02937 else
02938 elog(ERROR, "unsupported indexorderby type: %d",
02939 (int) nodeTag(clause));
02940
02941 fixed_indexorderbys = lappend(fixed_indexorderbys, clause);
02942 }
02943
02944 return fixed_indexorderbys;
02945 }
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957 static Node *
02958 fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol)
02959 {
02960 Var *result;
02961 int pos;
02962 ListCell *indexpr_item;
02963
02964
02965
02966
02967 if (IsA(node, RelabelType))
02968 node = (Node *) ((RelabelType *) node)->arg;
02969
02970 Assert(indexcol >= 0 && indexcol < index->ncolumns);
02971
02972 if (index->indexkeys[indexcol] != 0)
02973 {
02974
02975 if (IsA(node, Var) &&
02976 ((Var *) node)->varno == index->rel->relid &&
02977 ((Var *) node)->varattno == index->indexkeys[indexcol])
02978 {
02979 result = (Var *) copyObject(node);
02980 result->varno = INDEX_VAR;
02981 result->varattno = indexcol + 1;
02982 return (Node *) result;
02983 }
02984 else
02985 elog(ERROR, "index key does not match expected index column");
02986 }
02987
02988
02989 indexpr_item = list_head(index->indexprs);
02990 for (pos = 0; pos < index->ncolumns; pos++)
02991 {
02992 if (index->indexkeys[pos] == 0)
02993 {
02994 if (indexpr_item == NULL)
02995 elog(ERROR, "too few entries in indexprs list");
02996 if (pos == indexcol)
02997 {
02998 Node *indexkey;
02999
03000 indexkey = (Node *) lfirst(indexpr_item);
03001 if (indexkey && IsA(indexkey, RelabelType))
03002 indexkey = (Node *) ((RelabelType *) indexkey)->arg;
03003 if (equal(node, indexkey))
03004 {
03005 result = makeVar(INDEX_VAR, indexcol + 1,
03006 exprType(lfirst(indexpr_item)), -1,
03007 exprCollation(lfirst(indexpr_item)),
03008 0);
03009 return (Node *) result;
03010 }
03011 else
03012 elog(ERROR, "index key does not match expected index column");
03013 }
03014 indexpr_item = lnext(indexpr_item);
03015 }
03016 }
03017
03018
03019 elog(ERROR, "index key does not match expected index column");
03020 return NULL;
03021 }
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032 static List *
03033 get_switched_clauses(List *clauses, Relids outerrelids)
03034 {
03035 List *t_list = NIL;
03036 ListCell *l;
03037
03038 foreach(l, clauses)
03039 {
03040 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
03041 OpExpr *clause = (OpExpr *) restrictinfo->clause;
03042
03043 Assert(is_opclause(clause));
03044 if (bms_is_subset(restrictinfo->right_relids, outerrelids))
03045 {
03046
03047
03048
03049
03050
03051 OpExpr *temp = makeNode(OpExpr);
03052
03053 temp->opno = clause->opno;
03054 temp->opfuncid = InvalidOid;
03055 temp->opresulttype = clause->opresulttype;
03056 temp->opretset = clause->opretset;
03057 temp->opcollid = clause->opcollid;
03058 temp->inputcollid = clause->inputcollid;
03059 temp->args = list_copy(clause->args);
03060 temp->location = clause->location;
03061
03062 CommuteOpExpr(temp);
03063 t_list = lappend(t_list, temp);
03064 restrictinfo->outer_is_left = false;
03065 }
03066 else
03067 {
03068 Assert(bms_is_subset(restrictinfo->left_relids, outerrelids));
03069 t_list = lappend(t_list, clause);
03070 restrictinfo->outer_is_left = true;
03071 }
03072 }
03073 return t_list;
03074 }
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098 static List *
03099 order_qual_clauses(PlannerInfo *root, List *clauses)
03100 {
03101 typedef struct
03102 {
03103 Node *clause;
03104 Cost cost;
03105 } QualItem;
03106 int nitems = list_length(clauses);
03107 QualItem *items;
03108 ListCell *lc;
03109 int i;
03110 List *result;
03111
03112
03113 if (nitems <= 1)
03114 return clauses;
03115
03116
03117
03118
03119
03120 items = (QualItem *) palloc(nitems * sizeof(QualItem));
03121 i = 0;
03122 foreach(lc, clauses)
03123 {
03124 Node *clause = (Node *) lfirst(lc);
03125 QualCost qcost;
03126
03127 cost_qual_eval_node(&qcost, clause, root);
03128 items[i].clause = clause;
03129 items[i].cost = qcost.per_tuple;
03130 i++;
03131 }
03132
03133
03134
03135
03136
03137
03138 for (i = 1; i < nitems; i++)
03139 {
03140 QualItem newitem = items[i];
03141 int j;
03142
03143
03144 for (j = i; j > 0; j--)
03145 {
03146 if (newitem.cost >= items[j - 1].cost)
03147 break;
03148 items[j] = items[j - 1];
03149 }
03150 items[j] = newitem;
03151 }
03152
03153
03154 result = NIL;
03155 for (i = 0; i < nitems; i++)
03156 result = lappend(result, items[i].clause);
03157
03158 return result;
03159 }
03160
03161
03162
03163
03164
03165 static void
03166 copy_path_costsize(Plan *dest, Path *src)
03167 {
03168 if (src)
03169 {
03170 dest->startup_cost = src->startup_cost;
03171 dest->total_cost = src->total_cost;
03172 dest->plan_rows = src->rows;
03173 dest->plan_width = src->parent->width;
03174 }
03175 else
03176 {
03177 dest->startup_cost = 0;
03178 dest->total_cost = 0;
03179 dest->plan_rows = 0;
03180 dest->plan_width = 0;
03181 }
03182 }
03183
03184
03185
03186
03187
03188 static void
03189 copy_plan_costsize(Plan *dest, Plan *src)
03190 {
03191 if (src)
03192 {
03193 dest->startup_cost = src->startup_cost;
03194 dest->total_cost = src->total_cost;
03195 dest->plan_rows = src->plan_rows;
03196 dest->plan_width = src->plan_width;
03197 }
03198 else
03199 {
03200 dest->startup_cost = 0;
03201 dest->total_cost = 0;
03202 dest->plan_rows = 0;
03203 dest->plan_width = 0;
03204 }
03205 }
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217 static SeqScan *
03218 make_seqscan(List *qptlist,
03219 List *qpqual,
03220 Index scanrelid)
03221 {
03222 SeqScan *node = makeNode(SeqScan);
03223 Plan *plan = &node->plan;
03224
03225
03226 plan->targetlist = qptlist;
03227 plan->qual = qpqual;
03228 plan->lefttree = NULL;
03229 plan->righttree = NULL;
03230 node->scanrelid = scanrelid;
03231
03232 return node;
03233 }
03234
03235 static IndexScan *
03236 make_indexscan(List *qptlist,
03237 List *qpqual,
03238 Index scanrelid,
03239 Oid indexid,
03240 List *indexqual,
03241 List *indexqualorig,
03242 List *indexorderby,
03243 List *indexorderbyorig,
03244 ScanDirection indexscandir)
03245 {
03246 IndexScan *node = makeNode(IndexScan);
03247 Plan *plan = &node->scan.plan;
03248
03249
03250 plan->targetlist = qptlist;
03251 plan->qual = qpqual;
03252 plan->lefttree = NULL;
03253 plan->righttree = NULL;
03254 node->scan.scanrelid = scanrelid;
03255 node->indexid = indexid;
03256 node->indexqual = indexqual;
03257 node->indexqualorig = indexqualorig;
03258 node->indexorderby = indexorderby;
03259 node->indexorderbyorig = indexorderbyorig;
03260 node->indexorderdir = indexscandir;
03261
03262 return node;
03263 }
03264
03265 static IndexOnlyScan *
03266 make_indexonlyscan(List *qptlist,
03267 List *qpqual,
03268 Index scanrelid,
03269 Oid indexid,
03270 List *indexqual,
03271 List *indexorderby,
03272 List *indextlist,
03273 ScanDirection indexscandir)
03274 {
03275 IndexOnlyScan *node = makeNode(IndexOnlyScan);
03276 Plan *plan = &node->scan.plan;
03277
03278
03279 plan->targetlist = qptlist;
03280 plan->qual = qpqual;
03281 plan->lefttree = NULL;
03282 plan->righttree = NULL;
03283 node->scan.scanrelid = scanrelid;
03284 node->indexid = indexid;
03285 node->indexqual = indexqual;
03286 node->indexorderby = indexorderby;
03287 node->indextlist = indextlist;
03288 node->indexorderdir = indexscandir;
03289
03290 return node;
03291 }
03292
03293 static BitmapIndexScan *
03294 make_bitmap_indexscan(Index scanrelid,
03295 Oid indexid,
03296 List *indexqual,
03297 List *indexqualorig)
03298 {
03299 BitmapIndexScan *node = makeNode(BitmapIndexScan);
03300 Plan *plan = &node->scan.plan;
03301
03302
03303 plan->targetlist = NIL;
03304 plan->qual = NIL;
03305 plan->lefttree = NULL;
03306 plan->righttree = NULL;
03307 node->scan.scanrelid = scanrelid;
03308 node->indexid = indexid;
03309 node->indexqual = indexqual;
03310 node->indexqualorig = indexqualorig;
03311
03312 return node;
03313 }
03314
03315 static BitmapHeapScan *
03316 make_bitmap_heapscan(List *qptlist,
03317 List *qpqual,
03318 Plan *lefttree,
03319 List *bitmapqualorig,
03320 Index scanrelid)
03321 {
03322 BitmapHeapScan *node = makeNode(BitmapHeapScan);
03323 Plan *plan = &node->scan.plan;
03324
03325
03326 plan->targetlist = qptlist;
03327 plan->qual = qpqual;
03328 plan->lefttree = lefttree;
03329 plan->righttree = NULL;
03330 node->scan.scanrelid = scanrelid;
03331 node->bitmapqualorig = bitmapqualorig;
03332
03333 return node;
03334 }
03335
03336 static TidScan *
03337 make_tidscan(List *qptlist,
03338 List *qpqual,
03339 Index scanrelid,
03340 List *tidquals)
03341 {
03342 TidScan *node = makeNode(TidScan);
03343 Plan *plan = &node->scan.plan;
03344
03345
03346 plan->targetlist = qptlist;
03347 plan->qual = qpqual;
03348 plan->lefttree = NULL;
03349 plan->righttree = NULL;
03350 node->scan.scanrelid = scanrelid;
03351 node->tidquals = tidquals;
03352
03353 return node;
03354 }
03355
03356 SubqueryScan *
03357 make_subqueryscan(List *qptlist,
03358 List *qpqual,
03359 Index scanrelid,
03360 Plan *subplan)
03361 {
03362 SubqueryScan *node = makeNode(SubqueryScan);
03363 Plan *plan = &node->scan.plan;
03364
03365
03366
03367
03368
03369
03370 copy_plan_costsize(plan, subplan);
03371 plan->total_cost += cpu_tuple_cost * subplan->plan_rows;
03372
03373 plan->targetlist = qptlist;
03374 plan->qual = qpqual;
03375 plan->lefttree = NULL;
03376 plan->righttree = NULL;
03377 node->scan.scanrelid = scanrelid;
03378 node->subplan = subplan;
03379
03380 return node;
03381 }
03382
03383 static FunctionScan *
03384 make_functionscan(List *qptlist,
03385 List *qpqual,
03386 Index scanrelid,
03387 Node *funcexpr,
03388 List *funccolnames,
03389 List *funccoltypes,
03390 List *funccoltypmods,
03391 List *funccolcollations)
03392 {
03393 FunctionScan *node = makeNode(FunctionScan);
03394 Plan *plan = &node->scan.plan;
03395
03396
03397 plan->targetlist = qptlist;
03398 plan->qual = qpqual;
03399 plan->lefttree = NULL;
03400 plan->righttree = NULL;
03401 node->scan.scanrelid = scanrelid;
03402 node->funcexpr = funcexpr;
03403 node->funccolnames = funccolnames;
03404 node->funccoltypes = funccoltypes;
03405 node->funccoltypmods = funccoltypmods;
03406 node->funccolcollations = funccolcollations;
03407
03408 return node;
03409 }
03410
03411 static ValuesScan *
03412 make_valuesscan(List *qptlist,
03413 List *qpqual,
03414 Index scanrelid,
03415 List *values_lists)
03416 {
03417 ValuesScan *node = makeNode(ValuesScan);
03418 Plan *plan = &node->scan.plan;
03419
03420
03421 plan->targetlist = qptlist;
03422 plan->qual = qpqual;
03423 plan->lefttree = NULL;
03424 plan->righttree = NULL;
03425 node->scan.scanrelid = scanrelid;
03426 node->values_lists = values_lists;
03427
03428 return node;
03429 }
03430
03431 static CteScan *
03432 make_ctescan(List *qptlist,
03433 List *qpqual,
03434 Index scanrelid,
03435 int ctePlanId,
03436 int cteParam)
03437 {
03438 CteScan *node = makeNode(CteScan);
03439 Plan *plan = &node->scan.plan;
03440
03441
03442 plan->targetlist = qptlist;
03443 plan->qual = qpqual;
03444 plan->lefttree = NULL;
03445 plan->righttree = NULL;
03446 node->scan.scanrelid = scanrelid;
03447 node->ctePlanId = ctePlanId;
03448 node->cteParam = cteParam;
03449
03450 return node;
03451 }
03452
03453 static WorkTableScan *
03454 make_worktablescan(List *qptlist,
03455 List *qpqual,
03456 Index scanrelid,
03457 int wtParam)
03458 {
03459 WorkTableScan *node = makeNode(WorkTableScan);
03460 Plan *plan = &node->scan.plan;
03461
03462
03463 plan->targetlist = qptlist;
03464 plan->qual = qpqual;
03465 plan->lefttree = NULL;
03466 plan->righttree = NULL;
03467 node->scan.scanrelid = scanrelid;
03468 node->wtParam = wtParam;
03469
03470 return node;
03471 }
03472
03473 ForeignScan *
03474 make_foreignscan(List *qptlist,
03475 List *qpqual,
03476 Index scanrelid,
03477 List *fdw_exprs,
03478 List *fdw_private)
03479 {
03480 ForeignScan *node = makeNode(ForeignScan);
03481 Plan *plan = &node->scan.plan;
03482
03483
03484 plan->targetlist = qptlist;
03485 plan->qual = qpqual;
03486 plan->lefttree = NULL;
03487 plan->righttree = NULL;
03488 node->scan.scanrelid = scanrelid;
03489 node->fdw_exprs = fdw_exprs;
03490 node->fdw_private = fdw_private;
03491
03492 node->fsSystemCol = false;
03493
03494 return node;
03495 }
03496
03497 Append *
03498 make_append(List *appendplans, List *tlist)
03499 {
03500 Append *node = makeNode(Append);
03501 Plan *plan = &node->plan;
03502 double total_size;
03503 ListCell *subnode;
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516 plan->startup_cost = 0;
03517 plan->total_cost = 0;
03518 plan->plan_rows = 0;
03519 total_size = 0;
03520 foreach(subnode, appendplans)
03521 {
03522 Plan *subplan = (Plan *) lfirst(subnode);
03523
03524 if (subnode == list_head(appendplans))
03525 plan->startup_cost = subplan->startup_cost;
03526 plan->total_cost += subplan->total_cost;
03527 plan->plan_rows += subplan->plan_rows;
03528 total_size += subplan->plan_width * subplan->plan_rows;
03529 }
03530 if (plan->plan_rows > 0)
03531 plan->plan_width = rint(total_size / plan->plan_rows);
03532 else
03533 plan->plan_width = 0;
03534
03535 plan->targetlist = tlist;
03536 plan->qual = NIL;
03537 plan->lefttree = NULL;
03538 plan->righttree = NULL;
03539 node->appendplans = appendplans;
03540
03541 return node;
03542 }
03543
03544 RecursiveUnion *
03545 make_recursive_union(List *tlist,
03546 Plan *lefttree,
03547 Plan *righttree,
03548 int wtParam,
03549 List *distinctList,
03550 long numGroups)
03551 {
03552 RecursiveUnion *node = makeNode(RecursiveUnion);
03553 Plan *plan = &node->plan;
03554 int numCols = list_length(distinctList);
03555
03556 cost_recursive_union(plan, lefttree, righttree);
03557
03558 plan->targetlist = tlist;
03559 plan->qual = NIL;
03560 plan->lefttree = lefttree;
03561 plan->righttree = righttree;
03562 node->wtParam = wtParam;
03563
03564
03565
03566
03567
03568 node->numCols = numCols;
03569 if (numCols > 0)
03570 {
03571 int keyno = 0;
03572 AttrNumber *dupColIdx;
03573 Oid *dupOperators;
03574 ListCell *slitem;
03575
03576 dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
03577 dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
03578
03579 foreach(slitem, distinctList)
03580 {
03581 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
03582 TargetEntry *tle = get_sortgroupclause_tle(sortcl,
03583 plan->targetlist);
03584
03585 dupColIdx[keyno] = tle->resno;
03586 dupOperators[keyno] = sortcl->eqop;
03587 Assert(OidIsValid(dupOperators[keyno]));
03588 keyno++;
03589 }
03590 node->dupColIdx = dupColIdx;
03591 node->dupOperators = dupOperators;
03592 }
03593 node->numGroups = numGroups;
03594
03595 return node;
03596 }
03597
03598 static BitmapAnd *
03599 make_bitmap_and(List *bitmapplans)
03600 {
03601 BitmapAnd *node = makeNode(BitmapAnd);
03602 Plan *plan = &node->plan;
03603
03604
03605 plan->targetlist = NIL;
03606 plan->qual = NIL;
03607 plan->lefttree = NULL;
03608 plan->righttree = NULL;
03609 node->bitmapplans = bitmapplans;
03610
03611 return node;
03612 }
03613
03614 static BitmapOr *
03615 make_bitmap_or(List *bitmapplans)
03616 {
03617 BitmapOr *node = makeNode(BitmapOr);
03618 Plan *plan = &node->plan;
03619
03620
03621 plan->targetlist = NIL;
03622 plan->qual = NIL;
03623 plan->lefttree = NULL;
03624 plan->righttree = NULL;
03625 node->bitmapplans = bitmapplans;
03626
03627 return node;
03628 }
03629
03630 static NestLoop *
03631 make_nestloop(List *tlist,
03632 List *joinclauses,
03633 List *otherclauses,
03634 List *nestParams,
03635 Plan *lefttree,
03636 Plan *righttree,
03637 JoinType jointype)
03638 {
03639 NestLoop *node = makeNode(NestLoop);
03640 Plan *plan = &node->join.plan;
03641
03642
03643 plan->targetlist = tlist;
03644 plan->qual = otherclauses;
03645 plan->lefttree = lefttree;
03646 plan->righttree = righttree;
03647 node->join.jointype = jointype;
03648 node->join.joinqual = joinclauses;
03649 node->nestParams = nestParams;
03650
03651 return node;
03652 }
03653
03654 static HashJoin *
03655 make_hashjoin(List *tlist,
03656 List *joinclauses,
03657 List *otherclauses,
03658 List *hashclauses,
03659 Plan *lefttree,
03660 Plan *righttree,
03661 JoinType jointype)
03662 {
03663 HashJoin *node = makeNode(HashJoin);
03664 Plan *plan = &node->join.plan;
03665
03666
03667 plan->targetlist = tlist;
03668 plan->qual = otherclauses;
03669 plan->lefttree = lefttree;
03670 plan->righttree = righttree;
03671 node->hashclauses = hashclauses;
03672 node->join.jointype = jointype;
03673 node->join.joinqual = joinclauses;
03674
03675 return node;
03676 }
03677
03678 static Hash *
03679 make_hash(Plan *lefttree,
03680 Oid skewTable,
03681 AttrNumber skewColumn,
03682 bool skewInherit,
03683 Oid skewColType,
03684 int32 skewColTypmod)
03685 {
03686 Hash *node = makeNode(Hash);
03687 Plan *plan = &node->plan;
03688
03689 copy_plan_costsize(plan, lefttree);
03690
03691
03692
03693
03694
03695 plan->startup_cost = plan->total_cost;
03696 plan->targetlist = lefttree->targetlist;
03697 plan->qual = NIL;
03698 plan->lefttree = lefttree;
03699 plan->righttree = NULL;
03700
03701 node->skewTable = skewTable;
03702 node->skewColumn = skewColumn;
03703 node->skewInherit = skewInherit;
03704 node->skewColType = skewColType;
03705 node->skewColTypmod = skewColTypmod;
03706
03707 return node;
03708 }
03709
03710 static MergeJoin *
03711 make_mergejoin(List *tlist,
03712 List *joinclauses,
03713 List *otherclauses,
03714 List *mergeclauses,
03715 Oid *mergefamilies,
03716 Oid *mergecollations,
03717 int *mergestrategies,
03718 bool *mergenullsfirst,
03719 Plan *lefttree,
03720 Plan *righttree,
03721 JoinType jointype)
03722 {
03723 MergeJoin *node = makeNode(MergeJoin);
03724 Plan *plan = &node->join.plan;
03725
03726
03727 plan->targetlist = tlist;
03728 plan->qual = otherclauses;
03729 plan->lefttree = lefttree;
03730 plan->righttree = righttree;
03731 node->mergeclauses = mergeclauses;
03732 node->mergeFamilies = mergefamilies;
03733 node->mergeCollations = mergecollations;
03734 node->mergeStrategies = mergestrategies;
03735 node->mergeNullsFirst = mergenullsfirst;
03736 node->join.jointype = jointype;
03737 node->join.joinqual = joinclauses;
03738
03739 return node;
03740 }
03741
03742
03743
03744
03745
03746
03747
03748
03749 static Sort *
03750 make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
03751 AttrNumber *sortColIdx, Oid *sortOperators,
03752 Oid *collations, bool *nullsFirst,
03753 double limit_tuples)
03754 {
03755 Sort *node = makeNode(Sort);
03756 Plan *plan = &node->plan;
03757 Path sort_path;
03758
03759 copy_plan_costsize(plan, lefttree);
03760 cost_sort(&sort_path, root, NIL,
03761 lefttree->total_cost,
03762 lefttree->plan_rows,
03763 lefttree->plan_width,
03764 0.0,
03765 work_mem,
03766 limit_tuples);
03767 plan->startup_cost = sort_path.startup_cost;
03768 plan->total_cost = sort_path.total_cost;
03769 plan->targetlist = lefttree->targetlist;
03770 plan->qual = NIL;
03771 plan->lefttree = lefttree;
03772 plan->righttree = NULL;
03773 node->numCols = numCols;
03774 node->sortColIdx = sortColIdx;
03775 node->sortOperators = sortOperators;
03776 node->collations = collations;
03777 node->nullsFirst = nullsFirst;
03778
03779 return node;
03780 }
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806
03807
03808
03809
03810
03811
03812
03813
03814
03815
03816
03817
03818
03819
03820
03821
03822 static Plan *
03823 prepare_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
03824 Relids relids,
03825 const AttrNumber *reqColIdx,
03826 bool adjust_tlist_in_place,
03827 int *p_numsortkeys,
03828 AttrNumber **p_sortColIdx,
03829 Oid **p_sortOperators,
03830 Oid **p_collations,
03831 bool **p_nullsFirst)
03832 {
03833 List *tlist = lefttree->targetlist;
03834 ListCell *i;
03835 int numsortkeys;
03836 AttrNumber *sortColIdx;
03837 Oid *sortOperators;
03838 Oid *collations;
03839 bool *nullsFirst;
03840
03841
03842
03843
03844 numsortkeys = list_length(pathkeys);
03845 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
03846 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
03847 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
03848 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
03849
03850 numsortkeys = 0;
03851
03852 foreach(i, pathkeys)
03853 {
03854 PathKey *pathkey = (PathKey *) lfirst(i);
03855 EquivalenceClass *ec = pathkey->pk_eclass;
03856 EquivalenceMember *em;
03857 TargetEntry *tle = NULL;
03858 Oid pk_datatype = InvalidOid;
03859 Oid sortop;
03860 ListCell *j;
03861
03862 if (ec->ec_has_volatile)
03863 {
03864
03865
03866
03867
03868
03869 if (ec->ec_sortref == 0)
03870 elog(ERROR, "volatile EquivalenceClass has no sortref");
03871 tle = get_sortgroupref_tle(ec->ec_sortref, tlist);
03872 Assert(tle);
03873 Assert(list_length(ec->ec_members) == 1);
03874 pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
03875 }
03876 else if (reqColIdx != NULL)
03877 {
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887 tle = get_tle_by_resno(tlist, reqColIdx[numsortkeys]);
03888 if (tle)
03889 {
03890 em = find_ec_member_for_tle(ec, tle, relids);
03891 if (em)
03892 {
03893
03894 pk_datatype = em->em_datatype;
03895 }
03896 else
03897 tle = NULL;
03898 }
03899 }
03900 else
03901 {
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918 foreach(j, tlist)
03919 {
03920 tle = (TargetEntry *) lfirst(j);
03921 em = find_ec_member_for_tle(ec, tle, relids);
03922 if (em)
03923 {
03924
03925 pk_datatype = em->em_datatype;
03926 break;
03927 }
03928 tle = NULL;
03929 }
03930 }
03931
03932 if (!tle)
03933 {
03934
03935
03936
03937
03938
03939
03940
03941 Expr *sortexpr = NULL;
03942
03943 foreach(j, ec->ec_members)
03944 {
03945 EquivalenceMember *em = (EquivalenceMember *) lfirst(j);
03946 List *exprvars;
03947 ListCell *k;
03948
03949
03950
03951
03952
03953
03954 if (em->em_is_const)
03955 continue;
03956
03957
03958
03959
03960
03961 if (em->em_is_child &&
03962 !bms_equal(em->em_relids, relids))
03963 continue;
03964
03965 sortexpr = em->em_expr;
03966 exprvars = pull_var_clause((Node *) sortexpr,
03967 PVC_INCLUDE_AGGREGATES,
03968 PVC_INCLUDE_PLACEHOLDERS);
03969 foreach(k, exprvars)
03970 {
03971 if (!tlist_member_ignore_relabel(lfirst(k), tlist))
03972 break;
03973 }
03974 list_free(exprvars);
03975 if (!k)
03976 {
03977 pk_datatype = em->em_datatype;
03978 break;
03979 }
03980 }
03981 if (!j)
03982 elog(ERROR, "could not find pathkey item to sort");
03983
03984
03985
03986
03987 if (!adjust_tlist_in_place &&
03988 !is_projection_capable_plan(lefttree))
03989 {
03990
03991 tlist = copyObject(tlist);
03992 lefttree = (Plan *) make_result(root, tlist, NULL,
03993 lefttree);
03994 }
03995
03996
03997 adjust_tlist_in_place = true;
03998
03999
04000
04001
04002 tle = makeTargetEntry(sortexpr,
04003 list_length(tlist) + 1,
04004 NULL,
04005 true);
04006 tlist = lappend(tlist, tle);
04007 lefttree->targetlist = tlist;
04008 }
04009
04010
04011
04012
04013
04014 sortop = get_opfamily_member(pathkey->pk_opfamily,
04015 pk_datatype,
04016 pk_datatype,
04017 pathkey->pk_strategy);
04018 if (!OidIsValid(sortop))
04019 elog(ERROR, "could not find member %d(%u,%u) of opfamily %u",
04020 pathkey->pk_strategy, pk_datatype, pk_datatype,
04021 pathkey->pk_opfamily);
04022
04023
04024 sortColIdx[numsortkeys] = tle->resno;
04025 sortOperators[numsortkeys] = sortop;
04026 collations[numsortkeys] = ec->ec_collation;
04027 nullsFirst[numsortkeys] = pathkey->pk_nulls_first;
04028 numsortkeys++;
04029 }
04030
04031
04032 *p_numsortkeys = numsortkeys;
04033 *p_sortColIdx = sortColIdx;
04034 *p_sortOperators = sortOperators;
04035 *p_collations = collations;
04036 *p_nullsFirst = nullsFirst;
04037
04038 return lefttree;
04039 }
04040
04041
04042
04043
04044
04045
04046
04047 static EquivalenceMember *
04048 find_ec_member_for_tle(EquivalenceClass *ec,
04049 TargetEntry *tle,
04050 Relids relids)
04051 {
04052 Expr *tlexpr;
04053 ListCell *lc;
04054
04055
04056 tlexpr = tle->expr;
04057 while (tlexpr && IsA(tlexpr, RelabelType))
04058 tlexpr = ((RelabelType *) tlexpr)->arg;
04059
04060 foreach(lc, ec->ec_members)
04061 {
04062 EquivalenceMember *em = (EquivalenceMember *) lfirst(lc);
04063 Expr *emexpr;
04064
04065
04066
04067
04068
04069 if (em->em_is_const)
04070 continue;
04071
04072
04073
04074
04075 if (em->em_is_child &&
04076 !bms_equal(em->em_relids, relids))
04077 continue;
04078
04079
04080 emexpr = em->em_expr;
04081 while (emexpr && IsA(emexpr, RelabelType))
04082 emexpr = ((RelabelType *) emexpr)->arg;
04083
04084 if (equal(emexpr, tlexpr))
04085 return em;
04086 }
04087
04088 return NULL;
04089 }
04090
04091
04092
04093
04094
04095
04096
04097
04098
04099
04100 Sort *
04101 make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
04102 double limit_tuples)
04103 {
04104 int numsortkeys;
04105 AttrNumber *sortColIdx;
04106 Oid *sortOperators;
04107 Oid *collations;
04108 bool *nullsFirst;
04109
04110
04111 lefttree = prepare_sort_from_pathkeys(root, lefttree, pathkeys,
04112 NULL,
04113 NULL,
04114 false,
04115 &numsortkeys,
04116 &sortColIdx,
04117 &sortOperators,
04118 &collations,
04119 &nullsFirst);
04120
04121
04122 return make_sort(root, lefttree, numsortkeys,
04123 sortColIdx, sortOperators, collations,
04124 nullsFirst, limit_tuples);
04125 }
04126
04127
04128
04129
04130
04131
04132
04133
04134 Sort *
04135 make_sort_from_sortclauses(PlannerInfo *root, List *sortcls, Plan *lefttree)
04136 {
04137 List *sub_tlist = lefttree->targetlist;
04138 ListCell *l;
04139 int numsortkeys;
04140 AttrNumber *sortColIdx;
04141 Oid *sortOperators;
04142 Oid *collations;
04143 bool *nullsFirst;
04144
04145
04146 numsortkeys = list_length(sortcls);
04147 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
04148 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
04149 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
04150 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
04151
04152 numsortkeys = 0;
04153 foreach(l, sortcls)
04154 {
04155 SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
04156 TargetEntry *tle = get_sortgroupclause_tle(sortcl, sub_tlist);
04157
04158 sortColIdx[numsortkeys] = tle->resno;
04159 sortOperators[numsortkeys] = sortcl->sortop;
04160 collations[numsortkeys] = exprCollation((Node *) tle->expr);
04161 nullsFirst[numsortkeys] = sortcl->nulls_first;
04162 numsortkeys++;
04163 }
04164
04165 return make_sort(root, lefttree, numsortkeys,
04166 sortColIdx, sortOperators, collations,
04167 nullsFirst, -1.0);
04168 }
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183 Sort *
04184 make_sort_from_groupcols(PlannerInfo *root,
04185 List *groupcls,
04186 AttrNumber *grpColIdx,
04187 Plan *lefttree)
04188 {
04189 List *sub_tlist = lefttree->targetlist;
04190 ListCell *l;
04191 int numsortkeys;
04192 AttrNumber *sortColIdx;
04193 Oid *sortOperators;
04194 Oid *collations;
04195 bool *nullsFirst;
04196
04197
04198 numsortkeys = list_length(groupcls);
04199 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
04200 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
04201 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
04202 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
04203
04204 numsortkeys = 0;
04205 foreach(l, groupcls)
04206 {
04207 SortGroupClause *grpcl = (SortGroupClause *) lfirst(l);
04208 TargetEntry *tle = get_tle_by_resno(sub_tlist, grpColIdx[numsortkeys]);
04209
04210 sortColIdx[numsortkeys] = tle->resno;
04211 sortOperators[numsortkeys] = grpcl->sortop;
04212 collations[numsortkeys] = exprCollation((Node *) tle->expr);
04213 nullsFirst[numsortkeys] = grpcl->nulls_first;
04214 numsortkeys++;
04215 }
04216
04217 return make_sort(root, lefttree, numsortkeys,
04218 sortColIdx, sortOperators, collations,
04219 nullsFirst, -1.0);
04220 }
04221
04222 static Material *
04223 make_material(Plan *lefttree)
04224 {
04225 Material *node = makeNode(Material);
04226 Plan *plan = &node->plan;
04227
04228
04229 plan->targetlist = lefttree->targetlist;
04230 plan->qual = NIL;
04231 plan->lefttree = lefttree;
04232 plan->righttree = NULL;
04233
04234 return node;
04235 }
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247 Plan *
04248 materialize_finished_plan(Plan *subplan)
04249 {
04250 Plan *matplan;
04251 Path matpath;
04252
04253 matplan = (Plan *) make_material(subplan);
04254
04255
04256 cost_material(&matpath,
04257 subplan->startup_cost,
04258 subplan->total_cost,
04259 subplan->plan_rows,
04260 subplan->plan_width);
04261 matplan->startup_cost = matpath.startup_cost;
04262 matplan->total_cost = matpath.total_cost;
04263 matplan->plan_rows = subplan->plan_rows;
04264 matplan->plan_width = subplan->plan_width;
04265
04266
04267 matplan->extParam = bms_copy(subplan->extParam);
04268 matplan->allParam = bms_copy(subplan->allParam);
04269
04270 return matplan;
04271 }
04272
04273 Agg *
04274 make_agg(PlannerInfo *root, List *tlist, List *qual,
04275 AggStrategy aggstrategy, const AggClauseCosts *aggcosts,
04276 int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators,
04277 long numGroups,
04278 Plan *lefttree)
04279 {
04280 Agg *node = makeNode(Agg);
04281 Plan *plan = &node->plan;
04282 Path agg_path;
04283 QualCost qual_cost;
04284
04285 node->aggstrategy = aggstrategy;
04286 node->numCols = numGroupCols;
04287 node->grpColIdx = grpColIdx;
04288 node->grpOperators = grpOperators;
04289 node->numGroups = numGroups;
04290
04291 copy_plan_costsize(plan, lefttree);
04292 cost_agg(&agg_path, root,
04293 aggstrategy, aggcosts,
04294 numGroupCols, numGroups,
04295 lefttree->startup_cost,
04296 lefttree->total_cost,
04297 lefttree->plan_rows);
04298 plan->startup_cost = agg_path.startup_cost;
04299 plan->total_cost = agg_path.total_cost;
04300
04301
04302
04303
04304
04305 if (aggstrategy == AGG_PLAIN)
04306 plan->plan_rows = 1;
04307 else
04308 plan->plan_rows = numGroups;
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319 if (qual)
04320 {
04321 cost_qual_eval(&qual_cost, qual, root);
04322 plan->startup_cost += qual_cost.startup;
04323 plan->total_cost += qual_cost.startup;
04324 plan->total_cost += qual_cost.per_tuple * plan->plan_rows;
04325 }
04326 add_tlist_costs_to_plan(root, plan, tlist);
04327
04328 plan->qual = qual;
04329 plan->targetlist = tlist;
04330 plan->lefttree = lefttree;
04331 plan->righttree = NULL;
04332
04333 return node;
04334 }
04335
04336 WindowAgg *
04337 make_windowagg(PlannerInfo *root, List *tlist,
04338 List *windowFuncs, Index winref,
04339 int partNumCols, AttrNumber *partColIdx, Oid *partOperators,
04340 int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators,
04341 int frameOptions, Node *startOffset, Node *endOffset,
04342 Plan *lefttree)
04343 {
04344 WindowAgg *node = makeNode(WindowAgg);
04345 Plan *plan = &node->plan;
04346 Path windowagg_path;
04347
04348 node->winref = winref;
04349 node->partNumCols = partNumCols;
04350 node->partColIdx = partColIdx;
04351 node->partOperators = partOperators;
04352 node->ordNumCols = ordNumCols;
04353 node->ordColIdx = ordColIdx;
04354 node->ordOperators = ordOperators;
04355 node->frameOptions = frameOptions;
04356 node->startOffset = startOffset;
04357 node->endOffset = endOffset;
04358
04359 copy_plan_costsize(plan, lefttree);
04360 cost_windowagg(&windowagg_path, root,
04361 windowFuncs, partNumCols, ordNumCols,
04362 lefttree->startup_cost,
04363 lefttree->total_cost,
04364 lefttree->plan_rows);
04365 plan->startup_cost = windowagg_path.startup_cost;
04366 plan->total_cost = windowagg_path.total_cost;
04367
04368
04369
04370
04371
04372
04373
04374 add_tlist_costs_to_plan(root, plan, tlist);
04375
04376 plan->targetlist = tlist;
04377 plan->lefttree = lefttree;
04378 plan->righttree = NULL;
04379
04380 plan->qual = NIL;
04381
04382 return node;
04383 }
04384
04385 Group *
04386 make_group(PlannerInfo *root,
04387 List *tlist,
04388 List *qual,
04389 int numGroupCols,
04390 AttrNumber *grpColIdx,
04391 Oid *grpOperators,
04392 double numGroups,
04393 Plan *lefttree)
04394 {
04395 Group *node = makeNode(Group);
04396 Plan *plan = &node->plan;
04397 Path group_path;
04398 QualCost qual_cost;
04399
04400 node->numCols = numGroupCols;
04401 node->grpColIdx = grpColIdx;
04402 node->grpOperators = grpOperators;
04403
04404 copy_plan_costsize(plan, lefttree);
04405 cost_group(&group_path, root,
04406 numGroupCols, numGroups,
04407 lefttree->startup_cost,
04408 lefttree->total_cost,
04409 lefttree->plan_rows);
04410 plan->startup_cost = group_path.startup_cost;
04411 plan->total_cost = group_path.total_cost;
04412
04413
04414 plan->plan_rows = numGroups;
04415
04416
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428 if (qual)
04429 {
04430 cost_qual_eval(&qual_cost, qual, root);
04431 plan->startup_cost += qual_cost.startup;
04432 plan->total_cost += qual_cost.startup;
04433 plan->total_cost += qual_cost.per_tuple * plan->plan_rows;
04434 }
04435 add_tlist_costs_to_plan(root, plan, tlist);
04436
04437 plan->qual = qual;
04438 plan->targetlist = tlist;
04439 plan->lefttree = lefttree;
04440 plan->righttree = NULL;
04441
04442 return node;
04443 }
04444
04445
04446
04447
04448
04449
04450 Unique *
04451 make_unique(Plan *lefttree, List *distinctList)
04452 {
04453 Unique *node = makeNode(Unique);
04454 Plan *plan = &node->plan;
04455 int numCols = list_length(distinctList);
04456 int keyno = 0;
04457 AttrNumber *uniqColIdx;
04458 Oid *uniqOperators;
04459 ListCell *slitem;
04460
04461 copy_plan_costsize(plan, lefttree);
04462
04463
04464
04465
04466
04467
04468 plan->total_cost += cpu_operator_cost * plan->plan_rows * numCols;
04469
04470
04471
04472
04473
04474
04475
04476 plan->targetlist = lefttree->targetlist;
04477 plan->qual = NIL;
04478 plan->lefttree = lefttree;
04479 plan->righttree = NULL;
04480
04481
04482
04483
04484
04485 Assert(numCols > 0);
04486 uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
04487 uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
04488
04489 foreach(slitem, distinctList)
04490 {
04491 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
04492 TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
04493
04494 uniqColIdx[keyno] = tle->resno;
04495 uniqOperators[keyno] = sortcl->eqop;
04496 Assert(OidIsValid(uniqOperators[keyno]));
04497 keyno++;
04498 }
04499
04500 node->numCols = numCols;
04501 node->uniqColIdx = uniqColIdx;
04502 node->uniqOperators = uniqOperators;
04503
04504 return node;
04505 }
04506
04507
04508
04509
04510
04511
04512 SetOp *
04513 make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree,
04514 List *distinctList, AttrNumber flagColIdx, int firstFlag,
04515 long numGroups, double outputRows)
04516 {
04517 SetOp *node = makeNode(SetOp);
04518 Plan *plan = &node->plan;
04519 int numCols = list_length(distinctList);
04520 int keyno = 0;
04521 AttrNumber *dupColIdx;
04522 Oid *dupOperators;
04523 ListCell *slitem;
04524
04525 copy_plan_costsize(plan, lefttree);
04526 plan->plan_rows = outputRows;
04527
04528
04529
04530
04531
04532 plan->total_cost += cpu_operator_cost * lefttree->plan_rows * numCols;
04533
04534 plan->targetlist = lefttree->targetlist;
04535 plan->qual = NIL;
04536 plan->lefttree = lefttree;
04537 plan->righttree = NULL;
04538
04539
04540
04541
04542
04543 Assert(numCols > 0);
04544 dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
04545 dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
04546
04547 foreach(slitem, distinctList)
04548 {
04549 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
04550 TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
04551
04552 dupColIdx[keyno] = tle->resno;
04553 dupOperators[keyno] = sortcl->eqop;
04554 Assert(OidIsValid(dupOperators[keyno]));
04555 keyno++;
04556 }
04557
04558 node->cmd = cmd;
04559 node->strategy = strategy;
04560 node->numCols = numCols;
04561 node->dupColIdx = dupColIdx;
04562 node->dupOperators = dupOperators;
04563 node->flagColIdx = flagColIdx;
04564 node->firstFlag = firstFlag;
04565 node->numGroups = numGroups;
04566
04567 return node;
04568 }
04569
04570
04571
04572
04573
04574 LockRows *
04575 make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
04576 {
04577 LockRows *node = makeNode(LockRows);
04578 Plan *plan = &node->plan;
04579
04580 copy_plan_costsize(plan, lefttree);
04581
04582
04583 plan->total_cost += cpu_tuple_cost * plan->plan_rows;
04584
04585 plan->targetlist = lefttree->targetlist;
04586 plan->qual = NIL;
04587 plan->lefttree = lefttree;
04588 plan->righttree = NULL;
04589
04590 node->rowMarks = rowMarks;
04591 node->epqParam = epqParam;
04592
04593 return node;
04594 }
04595
04596
04597
04598
04599
04600
04601
04602
04603 Limit *
04604 make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount,
04605 int64 offset_est, int64 count_est)
04606 {
04607 Limit *node = makeNode(Limit);
04608 Plan *plan = &node->plan;
04609
04610 copy_plan_costsize(plan, lefttree);
04611
04612
04613
04614
04615
04616
04617
04618
04619
04620
04621 if (offset_est != 0)
04622 {
04623 double offset_rows;
04624
04625 if (offset_est > 0)
04626 offset_rows = (double) offset_est;
04627 else
04628 offset_rows = clamp_row_est(lefttree->plan_rows * 0.10);
04629 if (offset_rows > plan->plan_rows)
04630 offset_rows = plan->plan_rows;
04631 if (plan->plan_rows > 0)
04632 plan->startup_cost +=
04633 (plan->total_cost - plan->startup_cost)
04634 * offset_rows / plan->plan_rows;
04635 plan->plan_rows -= offset_rows;
04636 if (plan->plan_rows < 1)
04637 plan->plan_rows = 1;
04638 }
04639
04640 if (count_est != 0)
04641 {
04642 double count_rows;
04643
04644 if (count_est > 0)
04645 count_rows = (double) count_est;
04646 else
04647 count_rows = clamp_row_est(lefttree->plan_rows * 0.10);
04648 if (count_rows > plan->plan_rows)
04649 count_rows = plan->plan_rows;
04650 if (plan->plan_rows > 0)
04651 plan->total_cost = plan->startup_cost +
04652 (plan->total_cost - plan->startup_cost)
04653 * count_rows / plan->plan_rows;
04654 plan->plan_rows = count_rows;
04655 if (plan->plan_rows < 1)
04656 plan->plan_rows = 1;
04657 }
04658
04659 plan->targetlist = lefttree->targetlist;
04660 plan->qual = NIL;
04661 plan->lefttree = lefttree;
04662 plan->righttree = NULL;
04663
04664 node->limitOffset = limitOffset;
04665 node->limitCount = limitCount;
04666
04667 return node;
04668 }
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679 Result *
04680 make_result(PlannerInfo *root,
04681 List *tlist,
04682 Node *resconstantqual,
04683 Plan *subplan)
04684 {
04685 Result *node = makeNode(Result);
04686 Plan *plan = &node->plan;
04687
04688 if (subplan)
04689 copy_plan_costsize(plan, subplan);
04690 else
04691 {
04692 plan->startup_cost = 0;
04693 plan->total_cost = cpu_tuple_cost;
04694 plan->plan_rows = 1;
04695 plan->plan_width = 0;
04696 if (resconstantqual)
04697 {
04698 QualCost qual_cost;
04699
04700 cost_qual_eval(&qual_cost, (List *) resconstantqual, root);
04701
04702 plan->startup_cost += qual_cost.startup + qual_cost.per_tuple;
04703 plan->total_cost += qual_cost.startup + qual_cost.per_tuple;
04704 }
04705 }
04706
04707 plan->targetlist = tlist;
04708 plan->qual = NIL;
04709 plan->lefttree = subplan;
04710 plan->righttree = NULL;
04711 node->resconstantqual = resconstantqual;
04712
04713 return node;
04714 }
04715
04716
04717
04718
04719
04720
04721
04722
04723
04724
04725
04726 ModifyTable *
04727 make_modifytable(PlannerInfo *root,
04728 CmdType operation, bool canSetTag,
04729 List *resultRelations,
04730 List *subplans, List *returningLists,
04731 List *rowMarks, int epqParam)
04732 {
04733 ModifyTable *node = makeNode(ModifyTable);
04734 Plan *plan = &node->plan;
04735 double total_size;
04736 List *fdw_private_list;
04737 ListCell *subnode;
04738 ListCell *lc;
04739 int i;
04740
04741 Assert(list_length(resultRelations) == list_length(subplans));
04742 Assert(returningLists == NIL ||
04743 list_length(resultRelations) == list_length(returningLists));
04744
04745
04746
04747
04748 plan->startup_cost = 0;
04749 plan->total_cost = 0;
04750 plan->plan_rows = 0;
04751 total_size = 0;
04752 foreach(subnode, subplans)
04753 {
04754 Plan *subplan = (Plan *) lfirst(subnode);
04755
04756 if (subnode == list_head(subplans))
04757 plan->startup_cost = subplan->startup_cost;
04758 plan->total_cost += subplan->total_cost;
04759 plan->plan_rows += subplan->plan_rows;
04760 total_size += subplan->plan_width * subplan->plan_rows;
04761 }
04762 if (plan->plan_rows > 0)
04763 plan->plan_width = rint(total_size / plan->plan_rows);
04764 else
04765 plan->plan_width = 0;
04766
04767 node->plan.lefttree = NULL;
04768 node->plan.righttree = NULL;
04769 node->plan.qual = NIL;
04770
04771 node->plan.targetlist = NIL;
04772
04773 node->operation = operation;
04774 node->canSetTag = canSetTag;
04775 node->resultRelations = resultRelations;
04776 node->resultRelIndex = -1;
04777 node->plans = subplans;
04778 node->returningLists = returningLists;
04779 node->rowMarks = rowMarks;
04780 node->epqParam = epqParam;
04781
04782
04783
04784
04785
04786 fdw_private_list = NIL;
04787 i = 0;
04788 foreach(lc, resultRelations)
04789 {
04790 Index rti = lfirst_int(lc);
04791 FdwRoutine *fdwroutine;
04792 List *fdw_private;
04793
04794
04795
04796
04797
04798
04799
04800
04801 if (rti < root->simple_rel_array_size &&
04802 root->simple_rel_array[rti] != NULL)
04803 {
04804 RelOptInfo *resultRel = root->simple_rel_array[rti];
04805
04806 fdwroutine = resultRel->fdwroutine;
04807 }
04808 else
04809 {
04810 RangeTblEntry *rte = planner_rt_fetch(rti, root);
04811
04812 Assert(rte->rtekind == RTE_RELATION);
04813 if (rte->relkind == RELKIND_FOREIGN_TABLE)
04814 fdwroutine = GetFdwRoutineByRelId(rte->relid);
04815 else
04816 fdwroutine = NULL;
04817 }
04818
04819 if (fdwroutine != NULL &&
04820 fdwroutine->PlanForeignModify != NULL)
04821 fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);
04822 else
04823 fdw_private = NIL;
04824 fdw_private_list = lappend(fdw_private_list, fdw_private);
04825 i++;
04826 }
04827 node->fdwPrivLists = fdw_private_list;
04828
04829 return node;
04830 }
04831
04832
04833
04834
04835
04836 bool
04837 is_projection_capable_plan(Plan *plan)
04838 {
04839
04840 switch (nodeTag(plan))
04841 {
04842 case T_Hash:
04843 case T_Material:
04844 case T_Sort:
04845 case T_Unique:
04846 case T_SetOp:
04847 case T_LockRows:
04848 case T_Limit:
04849 case T_ModifyTable:
04850 case T_Append:
04851 case T_MergeAppend:
04852 case T_RecursiveUnion:
04853 return false;
04854 default:
04855 break;
04856 }
04857 return true;
04858 }