00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include <limits.h>
00019
00020 #include "access/htup_details.h"
00021 #include "executor/executor.h"
00022 #include "executor/nodeAgg.h"
00023 #include "miscadmin.h"
00024 #include "nodes/makefuncs.h"
00025 #ifdef OPTIMIZER_DEBUG
00026 #include "nodes/print.h"
00027 #endif
00028 #include "optimizer/clauses.h"
00029 #include "optimizer/cost.h"
00030 #include "optimizer/pathnode.h"
00031 #include "optimizer/paths.h"
00032 #include "optimizer/plancat.h"
00033 #include "optimizer/planmain.h"
00034 #include "optimizer/planner.h"
00035 #include "optimizer/prep.h"
00036 #include "optimizer/subselect.h"
00037 #include "optimizer/tlist.h"
00038 #include "parser/analyze.h"
00039 #include "parser/parsetree.h"
00040 #include "rewrite/rewriteManip.h"
00041 #include "utils/rel.h"
00042
00043
00044
00045 double cursor_tuple_fraction = DEFAULT_CURSOR_TUPLE_FRACTION;
00046
00047
00048 planner_hook_type planner_hook = NULL;
00049
00050
00051
00052 #define EXPRKIND_QUAL 0
00053 #define EXPRKIND_TARGET 1
00054 #define EXPRKIND_RTFUNC 2
00055 #define EXPRKIND_RTFUNC_LATERAL 3
00056 #define EXPRKIND_VALUES 4
00057 #define EXPRKIND_VALUES_LATERAL 5
00058 #define EXPRKIND_LIMIT 6
00059 #define EXPRKIND_APPINFO 7
00060 #define EXPRKIND_PHV 8
00061
00062
00063 typedef struct
00064 {
00065 List *tlist;
00066 List *activeWindows;
00067 } standard_qp_extra;
00068
00069
00070 static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
00071 static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode);
00072 static Plan *inheritance_planner(PlannerInfo *root);
00073 static Plan *grouping_planner(PlannerInfo *root, double tuple_fraction);
00074 static void preprocess_rowmarks(PlannerInfo *root);
00075 static double preprocess_limit(PlannerInfo *root,
00076 double tuple_fraction,
00077 int64 *offset_est, int64 *count_est);
00078 static bool limit_needed(Query *parse);
00079 static void preprocess_groupclause(PlannerInfo *root);
00080 static void standard_qp_callback(PlannerInfo *root, void *extra);
00081 static bool choose_hashed_grouping(PlannerInfo *root,
00082 double tuple_fraction, double limit_tuples,
00083 double path_rows, int path_width,
00084 Path *cheapest_path, Path *sorted_path,
00085 double dNumGroups, AggClauseCosts *agg_costs);
00086 static bool choose_hashed_distinct(PlannerInfo *root,
00087 double tuple_fraction, double limit_tuples,
00088 double path_rows, int path_width,
00089 Cost cheapest_startup_cost, Cost cheapest_total_cost,
00090 Cost sorted_startup_cost, Cost sorted_total_cost,
00091 List *sorted_pathkeys,
00092 double dNumDistinctRows);
00093 static List *make_subplanTargetList(PlannerInfo *root, List *tlist,
00094 AttrNumber **groupColIdx, bool *need_tlist_eval);
00095 static int get_grouping_column_index(Query *parse, TargetEntry *tle);
00096 static void locate_grouping_columns(PlannerInfo *root,
00097 List *tlist,
00098 List *sub_tlist,
00099 AttrNumber *groupColIdx);
00100 static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist);
00101 static List *select_active_windows(PlannerInfo *root, WindowFuncLists *wflists);
00102 static List *make_windowInputTargetList(PlannerInfo *root,
00103 List *tlist, List *activeWindows);
00104 static List *make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
00105 List *tlist);
00106 static void get_column_info_for_window(PlannerInfo *root, WindowClause *wc,
00107 List *tlist,
00108 int numSortCols, AttrNumber *sortColIdx,
00109 int *partNumCols,
00110 AttrNumber **partColIdx,
00111 Oid **partOperators,
00112 int *ordNumCols,
00113 AttrNumber **ordColIdx,
00114 Oid **ordOperators);
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 PlannedStmt *
00131 planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
00132 {
00133 PlannedStmt *result;
00134
00135 if (planner_hook)
00136 result = (*planner_hook) (parse, cursorOptions, boundParams);
00137 else
00138 result = standard_planner(parse, cursorOptions, boundParams);
00139 return result;
00140 }
00141
00142 PlannedStmt *
00143 standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
00144 {
00145 PlannedStmt *result;
00146 PlannerGlobal *glob;
00147 double tuple_fraction;
00148 PlannerInfo *root;
00149 Plan *top_plan;
00150 ListCell *lp,
00151 *lr;
00152
00153
00154 if (parse->utilityStmt &&
00155 IsA(parse->utilityStmt, DeclareCursorStmt))
00156 cursorOptions |= ((DeclareCursorStmt *) parse->utilityStmt)->options;
00157
00158
00159
00160
00161
00162
00163
00164 glob = makeNode(PlannerGlobal);
00165
00166 glob->boundParams = boundParams;
00167 glob->subplans = NIL;
00168 glob->subroots = NIL;
00169 glob->rewindPlanIDs = NULL;
00170 glob->finalrtable = NIL;
00171 glob->finalrowmarks = NIL;
00172 glob->resultRelations = NIL;
00173 glob->relationOids = NIL;
00174 glob->invalItems = NIL;
00175 glob->nParamExec = 0;
00176 glob->lastPHId = 0;
00177 glob->lastRowMarkId = 0;
00178 glob->transientPlan = false;
00179
00180
00181 if (cursorOptions & CURSOR_OPT_FAST_PLAN)
00182 {
00183
00184
00185
00186
00187
00188
00189
00190 tuple_fraction = cursor_tuple_fraction;
00191
00192
00193
00194
00195
00196
00197 if (tuple_fraction >= 1.0)
00198 tuple_fraction = 0.0;
00199 else if (tuple_fraction <= 0.0)
00200 tuple_fraction = 1e-10;
00201 }
00202 else
00203 {
00204
00205 tuple_fraction = 0.0;
00206 }
00207
00208
00209 top_plan = subquery_planner(glob, parse, NULL,
00210 false, tuple_fraction, &root);
00211
00212
00213
00214
00215
00216 if (cursorOptions & CURSOR_OPT_SCROLL)
00217 {
00218 if (!ExecSupportsBackwardScan(top_plan))
00219 top_plan = materialize_finished_plan(top_plan);
00220 }
00221
00222
00223 Assert(glob->finalrtable == NIL);
00224 Assert(glob->finalrowmarks == NIL);
00225 Assert(glob->resultRelations == NIL);
00226 top_plan = set_plan_references(root, top_plan);
00227
00228 Assert(list_length(glob->subplans) == list_length(glob->subroots));
00229 forboth(lp, glob->subplans, lr, glob->subroots)
00230 {
00231 Plan *subplan = (Plan *) lfirst(lp);
00232 PlannerInfo *subroot = (PlannerInfo *) lfirst(lr);
00233
00234 lfirst(lp) = set_plan_references(subroot, subplan);
00235 }
00236
00237
00238 result = makeNode(PlannedStmt);
00239
00240 result->commandType = parse->commandType;
00241 result->queryId = parse->queryId;
00242 result->hasReturning = (parse->returningList != NIL);
00243 result->hasModifyingCTE = parse->hasModifyingCTE;
00244 result->canSetTag = parse->canSetTag;
00245 result->transientPlan = glob->transientPlan;
00246 result->planTree = top_plan;
00247 result->rtable = glob->finalrtable;
00248 result->resultRelations = glob->resultRelations;
00249 result->utilityStmt = parse->utilityStmt;
00250 result->subplans = glob->subplans;
00251 result->rewindPlanIDs = glob->rewindPlanIDs;
00252 result->rowMarks = glob->finalrowmarks;
00253 result->relationOids = glob->relationOids;
00254 result->invalItems = glob->invalItems;
00255 result->nParamExec = glob->nParamExec;
00256
00257 return result;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 Plan *
00289 subquery_planner(PlannerGlobal *glob, Query *parse,
00290 PlannerInfo *parent_root,
00291 bool hasRecursion, double tuple_fraction,
00292 PlannerInfo **subroot)
00293 {
00294 int num_old_subplans = list_length(glob->subplans);
00295 PlannerInfo *root;
00296 Plan *plan;
00297 List *newHaving;
00298 bool hasOuterJoins;
00299 ListCell *l;
00300
00301
00302 root = makeNode(PlannerInfo);
00303 root->parse = parse;
00304 root->glob = glob;
00305 root->query_level = parent_root ? parent_root->query_level + 1 : 1;
00306 root->parent_root = parent_root;
00307 root->plan_params = NIL;
00308 root->planner_cxt = CurrentMemoryContext;
00309 root->init_plans = NIL;
00310 root->cte_plan_ids = NIL;
00311 root->eq_classes = NIL;
00312 root->append_rel_list = NIL;
00313 root->rowMarks = NIL;
00314 root->hasInheritedTarget = false;
00315
00316 root->hasRecursion = hasRecursion;
00317 if (hasRecursion)
00318 root->wt_param_id = SS_assign_special_param(root);
00319 else
00320 root->wt_param_id = -1;
00321 root->non_recursive_plan = NULL;
00322
00323
00324
00325
00326
00327 if (parse->cteList)
00328 SS_process_ctes(root);
00329
00330
00331
00332
00333
00334
00335
00336 if (parse->hasSubLinks)
00337 pull_up_sublinks(root);
00338
00339
00340
00341
00342
00343
00344 inline_set_returning_functions(root);
00345
00346
00347
00348
00349
00350 parse->jointree = (FromExpr *)
00351 pull_up_subqueries(root, (Node *) parse->jointree);
00352
00353
00354
00355
00356
00357
00358
00359 if (parse->setOperations)
00360 flatten_simple_union_all(root);
00361
00362
00363
00364
00365
00366
00367
00368
00369 root->hasJoinRTEs = false;
00370 root->hasLateralRTEs = false;
00371 hasOuterJoins = false;
00372 foreach(l, parse->rtable)
00373 {
00374 RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
00375
00376 if (rte->rtekind == RTE_JOIN)
00377 {
00378 root->hasJoinRTEs = true;
00379 if (IS_OUTER_JOIN(rte->jointype))
00380 hasOuterJoins = true;
00381 }
00382 if (rte->lateral)
00383 root->hasLateralRTEs = true;
00384 }
00385
00386
00387
00388
00389
00390
00391
00392 preprocess_rowmarks(root);
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 expand_inherited_tables(root);
00403
00404
00405
00406
00407
00408
00409 root->hasHavingQual = (parse->havingQual != NULL);
00410
00411
00412 root->hasPseudoConstantQuals = false;
00413
00414
00415
00416
00417
00418
00419
00420 parse->targetList = (List *)
00421 preprocess_expression(root, (Node *) parse->targetList,
00422 EXPRKIND_TARGET);
00423
00424 parse->returningList = (List *)
00425 preprocess_expression(root, (Node *) parse->returningList,
00426 EXPRKIND_TARGET);
00427
00428 preprocess_qual_conditions(root, (Node *) parse->jointree);
00429
00430 parse->havingQual = preprocess_expression(root, parse->havingQual,
00431 EXPRKIND_QUAL);
00432
00433 foreach(l, parse->windowClause)
00434 {
00435 WindowClause *wc = (WindowClause *) lfirst(l);
00436
00437
00438 wc->startOffset = preprocess_expression(root, wc->startOffset,
00439 EXPRKIND_LIMIT);
00440 wc->endOffset = preprocess_expression(root, wc->endOffset,
00441 EXPRKIND_LIMIT);
00442 }
00443
00444 parse->limitOffset = preprocess_expression(root, parse->limitOffset,
00445 EXPRKIND_LIMIT);
00446 parse->limitCount = preprocess_expression(root, parse->limitCount,
00447 EXPRKIND_LIMIT);
00448
00449 root->append_rel_list = (List *)
00450 preprocess_expression(root, (Node *) root->append_rel_list,
00451 EXPRKIND_APPINFO);
00452
00453
00454 foreach(l, parse->rtable)
00455 {
00456 RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
00457 int kind;
00458
00459 if (rte->rtekind == RTE_SUBQUERY)
00460 {
00461
00462
00463
00464
00465
00466
00467
00468 if (rte->lateral && root->hasJoinRTEs)
00469 rte->subquery = (Query *)
00470 flatten_join_alias_vars(root, (Node *) rte->subquery);
00471 }
00472 else if (rte->rtekind == RTE_FUNCTION)
00473 {
00474
00475 kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC;
00476 rte->funcexpr = preprocess_expression(root, rte->funcexpr, kind);
00477 }
00478 else if (rte->rtekind == RTE_VALUES)
00479 {
00480
00481 kind = rte->lateral ? EXPRKIND_VALUES_LATERAL : EXPRKIND_VALUES;
00482 rte->values_lists = (List *)
00483 preprocess_expression(root, (Node *) rte->values_lists, kind);
00484 }
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 newHaving = NIL;
00513 foreach(l, (List *) parse->havingQual)
00514 {
00515 Node *havingclause = (Node *) lfirst(l);
00516
00517 if (contain_agg_clause(havingclause) ||
00518 contain_volatile_functions(havingclause) ||
00519 contain_subplans(havingclause))
00520 {
00521
00522 newHaving = lappend(newHaving, havingclause);
00523 }
00524 else if (parse->groupClause)
00525 {
00526
00527 parse->jointree->quals = (Node *)
00528 lappend((List *) parse->jointree->quals, havingclause);
00529 }
00530 else
00531 {
00532
00533 parse->jointree->quals = (Node *)
00534 lappend((List *) parse->jointree->quals,
00535 copyObject(havingclause));
00536 newHaving = lappend(newHaving, havingclause);
00537 }
00538 }
00539 parse->havingQual = (Node *) newHaving;
00540
00541
00542
00543
00544
00545
00546 if (hasOuterJoins)
00547 reduce_outer_joins(root);
00548
00549
00550
00551
00552
00553 if (parse->resultRelation &&
00554 rt_fetch(parse->resultRelation, parse->rtable)->inh)
00555 plan = inheritance_planner(root);
00556 else
00557 {
00558 plan = grouping_planner(root, tuple_fraction);
00559
00560 if (parse->commandType != CMD_SELECT)
00561 {
00562 List *returningLists;
00563 List *rowMarks;
00564
00565
00566
00567
00568 if (parse->returningList)
00569 returningLists = list_make1(parse->returningList);
00570 else
00571 returningLists = NIL;
00572
00573
00574
00575
00576
00577
00578 if (parse->rowMarks)
00579 rowMarks = NIL;
00580 else
00581 rowMarks = root->rowMarks;
00582
00583 plan = (Plan *) make_modifytable(root,
00584 parse->commandType,
00585 parse->canSetTag,
00586 list_make1_int(parse->resultRelation),
00587 list_make1(plan),
00588 returningLists,
00589 rowMarks,
00590 SS_assign_special_param(root));
00591 }
00592 }
00593
00594
00595
00596
00597
00598
00599 if (list_length(glob->subplans) != num_old_subplans ||
00600 root->glob->nParamExec > 0)
00601 SS_finalize_plan(root, plan, true);
00602
00603
00604 if (subroot)
00605 *subroot = root;
00606
00607 return plan;
00608 }
00609
00610
00611
00612
00613
00614
00615
00616 static Node *
00617 preprocess_expression(PlannerInfo *root, Node *expr, int kind)
00618 {
00619
00620
00621
00622
00623
00624 if (expr == NULL)
00625 return NULL;
00626
00627
00628
00629
00630
00631
00632
00633
00634 if (root->hasJoinRTEs &&
00635 !(kind == EXPRKIND_RTFUNC || kind == EXPRKIND_VALUES))
00636 expr = flatten_join_alias_vars(root, expr);
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 expr = eval_const_expressions(root, expr);
00654
00655
00656
00657
00658 if (kind == EXPRKIND_QUAL)
00659 {
00660 expr = (Node *) canonicalize_qual((Expr *) expr);
00661
00662 #ifdef OPTIMIZER_DEBUG
00663 printf("After canonicalize_qual()\n");
00664 pprint(expr);
00665 #endif
00666 }
00667
00668
00669 if (root->parse->hasSubLinks)
00670 expr = SS_process_sublinks(root, expr, (kind == EXPRKIND_QUAL));
00671
00672
00673
00674
00675
00676
00677
00678 if (root->query_level > 1)
00679 expr = SS_replace_correlation_vars(root, expr);
00680
00681
00682
00683
00684
00685
00686
00687 if (kind == EXPRKIND_QUAL)
00688 expr = (Node *) make_ands_implicit((Expr *) expr);
00689
00690 return expr;
00691 }
00692
00693
00694
00695
00696
00697
00698 static void
00699 preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
00700 {
00701 if (jtnode == NULL)
00702 return;
00703 if (IsA(jtnode, RangeTblRef))
00704 {
00705
00706 }
00707 else if (IsA(jtnode, FromExpr))
00708 {
00709 FromExpr *f = (FromExpr *) jtnode;
00710 ListCell *l;
00711
00712 foreach(l, f->fromlist)
00713 preprocess_qual_conditions(root, lfirst(l));
00714
00715 f->quals = preprocess_expression(root, f->quals, EXPRKIND_QUAL);
00716 }
00717 else if (IsA(jtnode, JoinExpr))
00718 {
00719 JoinExpr *j = (JoinExpr *) jtnode;
00720
00721 preprocess_qual_conditions(root, j->larg);
00722 preprocess_qual_conditions(root, j->rarg);
00723
00724 j->quals = preprocess_expression(root, j->quals, EXPRKIND_QUAL);
00725 }
00726 else
00727 elog(ERROR, "unrecognized node type: %d",
00728 (int) nodeTag(jtnode));
00729 }
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 Expr *
00743 preprocess_phv_expression(PlannerInfo *root, Expr *expr)
00744 {
00745 return (Expr *) preprocess_expression(root, (Node *) expr, EXPRKIND_PHV);
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 static Plan *
00764 inheritance_planner(PlannerInfo *root)
00765 {
00766 Query *parse = root->parse;
00767 int parentRTindex = parse->resultRelation;
00768 List *final_rtable = NIL;
00769 int save_rel_array_size = 0;
00770 RelOptInfo **save_rel_array = NULL;
00771 List *subplans = NIL;
00772 List *resultRelations = NIL;
00773 List *returningLists = NIL;
00774 List *rowMarks;
00775 ListCell *lc;
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792 foreach(lc, root->append_rel_list)
00793 {
00794 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
00795 PlannerInfo subroot;
00796 Plan *subplan;
00797 Index rti;
00798
00799
00800 if (appinfo->parent_relid != parentRTindex)
00801 continue;
00802
00803
00804
00805
00806
00807 memcpy(&subroot, root, sizeof(PlannerInfo));
00808
00809
00810
00811
00812
00813
00814
00815 subroot.parse = (Query *)
00816 adjust_appendrel_attrs(root,
00817 (Node *) parse,
00818 appinfo);
00819
00820
00821
00822
00823
00824
00825
00826 subroot.rowMarks = (List *) copyObject(root->rowMarks);
00827
00828
00829
00830
00831
00832
00833
00834 while (list_length(subroot.parse->rtable) < list_length(final_rtable))
00835 subroot.parse->rtable = lappend(subroot.parse->rtable,
00836 makeNode(RangeTblEntry));
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 if (final_rtable != NIL)
00847 {
00848 ListCell *lr;
00849
00850 rti = 1;
00851 foreach(lr, parse->rtable)
00852 {
00853 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lr);
00854
00855 if (rte->rtekind == RTE_SUBQUERY)
00856 {
00857 Index newrti;
00858
00859
00860
00861
00862
00863
00864
00865 newrti = list_length(subroot.parse->rtable) + 1;
00866 ChangeVarNodes((Node *) subroot.parse, rti, newrti, 0);
00867 ChangeVarNodes((Node *) subroot.rowMarks, rti, newrti, 0);
00868 rte = copyObject(rte);
00869 subroot.parse->rtable = lappend(subroot.parse->rtable,
00870 rte);
00871 }
00872 rti++;
00873 }
00874 }
00875
00876
00877
00878 Assert(subroot.join_info_list == NIL);
00879 Assert(subroot.lateral_info_list == NIL);
00880
00881 Assert(subroot.placeholder_list == NIL);
00882
00883 subroot.hasInheritedTarget = true;
00884
00885
00886 subplan = grouping_planner(&subroot, 0.0 );
00887
00888
00889
00890
00891
00892 if (is_dummy_plan(subplan))
00893 continue;
00894
00895 subplans = lappend(subplans, subplan);
00896
00897
00898
00899
00900
00901
00902 if (final_rtable == NIL)
00903 final_rtable = subroot.parse->rtable;
00904 else
00905 final_rtable = list_concat(final_rtable,
00906 list_copy_tail(subroot.parse->rtable,
00907 list_length(final_rtable)));
00908
00909
00910
00911
00912
00913
00914
00915
00916 Assert(subroot.simple_rel_array_size >= save_rel_array_size);
00917 for (rti = 1; rti < save_rel_array_size; rti++)
00918 {
00919 RelOptInfo *brel = save_rel_array[rti];
00920
00921 if (brel)
00922 subroot.simple_rel_array[rti] = brel;
00923 }
00924 save_rel_array_size = subroot.simple_rel_array_size;
00925 save_rel_array = subroot.simple_rel_array;
00926
00927
00928 root->init_plans = subroot.init_plans;
00929
00930
00931 resultRelations = lappend_int(resultRelations, appinfo->child_relid);
00932
00933
00934 if (parse->returningList)
00935 returningLists = lappend(returningLists,
00936 subroot.parse->returningList);
00937 }
00938
00939
00940 root->query_pathkeys = NIL;
00941
00942
00943
00944
00945
00946 if (subplans == NIL)
00947 {
00948
00949 List *tlist;
00950
00951 tlist = preprocess_targetlist(root, parse->targetList);
00952 return (Plan *) make_result(root,
00953 tlist,
00954 (Node *) list_make1(makeBoolConst(false,
00955 false)),
00956 NULL);
00957 }
00958
00959
00960
00961
00962 parse->rtable = final_rtable;
00963 root->simple_rel_array_size = save_rel_array_size;
00964 root->simple_rel_array = save_rel_array;
00965
00966
00967
00968
00969
00970
00971 if (parse->rowMarks)
00972 rowMarks = NIL;
00973 else
00974 rowMarks = root->rowMarks;
00975
00976
00977 return (Plan *) make_modifytable(root,
00978 parse->commandType,
00979 parse->canSetTag,
00980 resultRelations,
00981 subplans,
00982 returningLists,
00983 rowMarks,
00984 SS_assign_special_param(root));
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006 static Plan *
01007 grouping_planner(PlannerInfo *root, double tuple_fraction)
01008 {
01009 Query *parse = root->parse;
01010 List *tlist = parse->targetList;
01011 int64 offset_est = 0;
01012 int64 count_est = 0;
01013 double limit_tuples = -1.0;
01014 Plan *result_plan;
01015 List *current_pathkeys;
01016 double dNumGroups = 0;
01017 bool use_hashed_distinct = false;
01018 bool tested_hashed_distinct = false;
01019
01020
01021 if (parse->limitCount || parse->limitOffset)
01022 {
01023 tuple_fraction = preprocess_limit(root, tuple_fraction,
01024 &offset_est, &count_est);
01025
01026
01027
01028
01029
01030 if (count_est > 0 && offset_est >= 0)
01031 limit_tuples = (double) count_est + (double) offset_est;
01032 }
01033
01034 if (parse->setOperations)
01035 {
01036 List *set_sortclauses;
01037
01038
01039
01040
01041
01042
01043
01044 if (parse->sortClause)
01045 tuple_fraction = 0.0;
01046
01047
01048
01049
01050
01051
01052
01053 result_plan = plan_set_operations(root, tuple_fraction,
01054 &set_sortclauses);
01055
01056
01057
01058
01059
01060
01061 current_pathkeys = make_pathkeys_for_sortclauses(root,
01062 set_sortclauses,
01063 result_plan->targetlist);
01064
01065
01066
01067
01068
01069
01070
01071
01072 Assert(parse->commandType == CMD_SELECT);
01073
01074 tlist = postprocess_setop_tlist(copyObject(result_plan->targetlist),
01075 tlist);
01076
01077
01078
01079
01080
01081 if (parse->rowMarks)
01082 ereport(ERROR,
01083 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01084 errmsg("row-level locks are not allowed with UNION/INTERSECT/EXCEPT")));
01085
01086
01087
01088
01089 Assert(parse->distinctClause == NIL);
01090 root->sort_pathkeys = make_pathkeys_for_sortclauses(root,
01091 parse->sortClause,
01092 tlist);
01093 }
01094 else
01095 {
01096
01097 List *sub_tlist;
01098 double sub_limit_tuples;
01099 AttrNumber *groupColIdx = NULL;
01100 bool need_tlist_eval = true;
01101 standard_qp_extra qp_extra;
01102 Path *cheapest_path;
01103 Path *sorted_path;
01104 Path *best_path;
01105 long numGroups = 0;
01106 AggClauseCosts agg_costs;
01107 int numGroupCols;
01108 double path_rows;
01109 int path_width;
01110 bool use_hashed_grouping = false;
01111 WindowFuncLists *wflists = NULL;
01112 List *activeWindows = NIL;
01113
01114 MemSet(&agg_costs, 0, sizeof(AggClauseCosts));
01115
01116
01117 Assert(!root->hasRecursion);
01118
01119
01120 if (parse->groupClause)
01121 preprocess_groupclause(root);
01122 numGroupCols = list_length(parse->groupClause);
01123
01124
01125 tlist = preprocess_targetlist(root, tlist);
01126
01127
01128
01129
01130
01131
01132
01133 if (parse->hasWindowFuncs)
01134 {
01135 wflists = find_window_functions((Node *) tlist,
01136 list_length(parse->windowClause));
01137 if (wflists->numWindowFuncs > 0)
01138 activeWindows = select_active_windows(root, wflists);
01139 else
01140 parse->hasWindowFuncs = false;
01141 }
01142
01143
01144
01145
01146
01147 sub_tlist = make_subplanTargetList(root, tlist,
01148 &groupColIdx, &need_tlist_eval);
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 if (parse->hasAggs)
01159 {
01160
01161
01162
01163
01164
01165 count_agg_clauses(root, (Node *) tlist, &agg_costs);
01166 count_agg_clauses(root, parse->havingQual, &agg_costs);
01167
01168
01169
01170
01171
01172
01173
01174 preprocess_minmax_aggregates(root, tlist);
01175 }
01176
01177
01178
01179
01180
01181
01182
01183 if (parse->groupClause ||
01184 parse->distinctClause ||
01185 parse->hasAggs ||
01186 parse->hasWindowFuncs ||
01187 root->hasHavingQual)
01188 sub_limit_tuples = -1.0;
01189 else
01190 sub_limit_tuples = limit_tuples;
01191
01192
01193 qp_extra.tlist = tlist;
01194 qp_extra.activeWindows = activeWindows;
01195
01196
01197
01198
01199
01200
01201
01202
01203 query_planner(root, sub_tlist, tuple_fraction, sub_limit_tuples,
01204 standard_qp_callback, &qp_extra,
01205 &cheapest_path, &sorted_path, &dNumGroups);
01206
01207
01208
01209
01210
01211
01212 if (cheapest_path->parent)
01213 {
01214 path_rows = cheapest_path->parent->rows;
01215 path_width = cheapest_path->parent->width;
01216 }
01217 else
01218 {
01219 path_rows = 1;
01220 path_width = 100;
01221 }
01222
01223 if (parse->groupClause)
01224 {
01225
01226
01227
01228 use_hashed_grouping =
01229 choose_hashed_grouping(root,
01230 tuple_fraction, limit_tuples,
01231 path_rows, path_width,
01232 cheapest_path, sorted_path,
01233 dNumGroups, &agg_costs);
01234
01235 numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
01236 }
01237 else if (parse->distinctClause && sorted_path &&
01238 !root->hasHavingQual && !parse->hasAggs && !activeWindows)
01239 {
01240
01241
01242
01243
01244
01245 use_hashed_distinct =
01246 choose_hashed_distinct(root,
01247 tuple_fraction, limit_tuples,
01248 path_rows, path_width,
01249 cheapest_path->startup_cost,
01250 cheapest_path->total_cost,
01251 sorted_path->startup_cost,
01252 sorted_path->total_cost,
01253 sorted_path->pathkeys,
01254 dNumGroups);
01255 tested_hashed_distinct = true;
01256 }
01257
01258
01259
01260
01261
01262
01263 if (use_hashed_grouping || use_hashed_distinct || !sorted_path)
01264 best_path = cheapest_path;
01265 else
01266 best_path = sorted_path;
01267
01268
01269
01270
01271
01272
01273
01274 result_plan = optimize_minmax_aggregates(root,
01275 tlist,
01276 &agg_costs,
01277 best_path);
01278 if (result_plan != NULL)
01279 {
01280
01281
01282
01283
01284 current_pathkeys = NIL;
01285 }
01286 else
01287 {
01288
01289
01290
01291
01292 bool need_sort_for_grouping = false;
01293
01294 result_plan = create_plan(root, best_path);
01295 current_pathkeys = best_path->pathkeys;
01296
01297
01298 if (parse->groupClause && !use_hashed_grouping &&
01299 !pathkeys_contained_in(root->group_pathkeys, current_pathkeys))
01300 {
01301 need_sort_for_grouping = true;
01302
01303
01304
01305
01306
01307 need_tlist_eval = true;
01308 }
01309
01310
01311
01312
01313
01314
01315
01316 if (need_tlist_eval)
01317 {
01318
01319
01320
01321
01322
01323
01324 if (!is_projection_capable_plan(result_plan) &&
01325 !tlist_same_exprs(sub_tlist, result_plan->targetlist))
01326 {
01327 result_plan = (Plan *) make_result(root,
01328 sub_tlist,
01329 NULL,
01330 result_plan);
01331 }
01332 else
01333 {
01334
01335
01336
01337
01338 result_plan->targetlist = sub_tlist;
01339 }
01340
01341
01342
01343
01344
01345 add_tlist_costs_to_plan(root, result_plan, sub_tlist);
01346 }
01347 else
01348 {
01349
01350
01351
01352
01353
01354 locate_grouping_columns(root, tlist, result_plan->targetlist,
01355 groupColIdx);
01356 }
01357
01358
01359
01360
01361
01362
01363
01364 if (use_hashed_grouping)
01365 {
01366
01367 result_plan = (Plan *) make_agg(root,
01368 tlist,
01369 (List *) parse->havingQual,
01370 AGG_HASHED,
01371 &agg_costs,
01372 numGroupCols,
01373 groupColIdx,
01374 extract_grouping_ops(parse->groupClause),
01375 numGroups,
01376 result_plan);
01377
01378 current_pathkeys = NIL;
01379 }
01380 else if (parse->hasAggs)
01381 {
01382
01383 AggStrategy aggstrategy;
01384
01385 if (parse->groupClause)
01386 {
01387 if (need_sort_for_grouping)
01388 {
01389 result_plan = (Plan *)
01390 make_sort_from_groupcols(root,
01391 parse->groupClause,
01392 groupColIdx,
01393 result_plan);
01394 current_pathkeys = root->group_pathkeys;
01395 }
01396 aggstrategy = AGG_SORTED;
01397
01398
01399
01400
01401
01402 }
01403 else
01404 {
01405 aggstrategy = AGG_PLAIN;
01406
01407 current_pathkeys = NIL;
01408 }
01409
01410 result_plan = (Plan *) make_agg(root,
01411 tlist,
01412 (List *) parse->havingQual,
01413 aggstrategy,
01414 &agg_costs,
01415 numGroupCols,
01416 groupColIdx,
01417 extract_grouping_ops(parse->groupClause),
01418 numGroups,
01419 result_plan);
01420 }
01421 else if (parse->groupClause)
01422 {
01423
01424
01425
01426
01427
01428
01429
01430 if (need_sort_for_grouping)
01431 {
01432 result_plan = (Plan *)
01433 make_sort_from_groupcols(root,
01434 parse->groupClause,
01435 groupColIdx,
01436 result_plan);
01437 current_pathkeys = root->group_pathkeys;
01438 }
01439
01440 result_plan = (Plan *) make_group(root,
01441 tlist,
01442 (List *) parse->havingQual,
01443 numGroupCols,
01444 groupColIdx,
01445 extract_grouping_ops(parse->groupClause),
01446 dNumGroups,
01447 result_plan);
01448
01449 }
01450 else if (root->hasHavingQual)
01451 {
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464 result_plan = (Plan *) make_result(root,
01465 tlist,
01466 parse->havingQual,
01467 NULL);
01468 }
01469 }
01470
01471
01472
01473
01474
01475
01476 if (activeWindows)
01477 {
01478 List *window_tlist;
01479 ListCell *l;
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493 if (!is_projection_capable_plan(result_plan))
01494 {
01495 result_plan = (Plan *) make_result(root,
01496 NIL,
01497 NULL,
01498 result_plan);
01499 }
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 window_tlist = make_windowInputTargetList(root,
01514 tlist,
01515 activeWindows);
01516
01517
01518
01519
01520
01521
01522 result_plan->targetlist = (List *) copyObject(window_tlist);
01523
01524 foreach(l, activeWindows)
01525 {
01526 WindowClause *wc = (WindowClause *) lfirst(l);
01527 List *window_pathkeys;
01528 int partNumCols;
01529 AttrNumber *partColIdx;
01530 Oid *partOperators;
01531 int ordNumCols;
01532 AttrNumber *ordColIdx;
01533 Oid *ordOperators;
01534
01535 window_pathkeys = make_pathkeys_for_window(root,
01536 wc,
01537 tlist);
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550 if (window_pathkeys)
01551 {
01552 Sort *sort_plan;
01553
01554 sort_plan = make_sort_from_pathkeys(root,
01555 result_plan,
01556 window_pathkeys,
01557 -1.0);
01558 if (!pathkeys_contained_in(window_pathkeys,
01559 current_pathkeys))
01560 {
01561
01562 result_plan = (Plan *) sort_plan;
01563 current_pathkeys = window_pathkeys;
01564 }
01565
01566 get_column_info_for_window(root, wc, tlist,
01567 sort_plan->numCols,
01568 sort_plan->sortColIdx,
01569 &partNumCols,
01570 &partColIdx,
01571 &partOperators,
01572 &ordNumCols,
01573 &ordColIdx,
01574 &ordOperators);
01575 }
01576 else
01577 {
01578
01579 partNumCols = 0;
01580 partColIdx = NULL;
01581 partOperators = NULL;
01582 ordNumCols = 0;
01583 ordColIdx = NULL;
01584 ordOperators = NULL;
01585 }
01586
01587 if (lnext(l))
01588 {
01589
01590 window_tlist = add_to_flat_tlist(window_tlist,
01591 wflists->windowFuncs[wc->winref]);
01592 }
01593 else
01594 {
01595
01596 window_tlist = tlist;
01597 }
01598
01599
01600 result_plan = (Plan *)
01601 make_windowagg(root,
01602 (List *) copyObject(window_tlist),
01603 wflists->windowFuncs[wc->winref],
01604 wc->winref,
01605 partNumCols,
01606 partColIdx,
01607 partOperators,
01608 ordNumCols,
01609 ordColIdx,
01610 ordOperators,
01611 wc->frameOptions,
01612 wc->startOffset,
01613 wc->endOffset,
01614 result_plan);
01615 }
01616 }
01617 }
01618
01619
01620
01621
01622 if (parse->distinctClause)
01623 {
01624 double dNumDistinctRows;
01625 long numDistinctRows;
01626
01627
01628
01629
01630
01631
01632
01633 if (parse->groupClause || root->hasHavingQual || parse->hasAggs)
01634 dNumDistinctRows = result_plan->plan_rows;
01635 else
01636 dNumDistinctRows = dNumGroups;
01637
01638
01639 numDistinctRows = (long) Min(dNumDistinctRows, (double) LONG_MAX);
01640
01641
01642 if (!tested_hashed_distinct)
01643 {
01644
01645
01646
01647
01648
01649 use_hashed_distinct =
01650 choose_hashed_distinct(root,
01651 tuple_fraction, limit_tuples,
01652 result_plan->plan_rows,
01653 result_plan->plan_width,
01654 result_plan->startup_cost,
01655 result_plan->total_cost,
01656 result_plan->startup_cost,
01657 result_plan->total_cost,
01658 current_pathkeys,
01659 dNumDistinctRows);
01660 }
01661
01662 if (use_hashed_distinct)
01663 {
01664
01665 result_plan = (Plan *) make_agg(root,
01666 result_plan->targetlist,
01667 NIL,
01668 AGG_HASHED,
01669 NULL,
01670 list_length(parse->distinctClause),
01671 extract_grouping_cols(parse->distinctClause,
01672 result_plan->targetlist),
01673 extract_grouping_ops(parse->distinctClause),
01674 numDistinctRows,
01675 result_plan);
01676
01677 current_pathkeys = NIL;
01678 }
01679 else
01680 {
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692 List *needed_pathkeys;
01693
01694 if (parse->hasDistinctOn &&
01695 list_length(root->distinct_pathkeys) <
01696 list_length(root->sort_pathkeys))
01697 needed_pathkeys = root->sort_pathkeys;
01698 else
01699 needed_pathkeys = root->distinct_pathkeys;
01700
01701 if (!pathkeys_contained_in(needed_pathkeys, current_pathkeys))
01702 {
01703 if (list_length(root->distinct_pathkeys) >=
01704 list_length(root->sort_pathkeys))
01705 current_pathkeys = root->distinct_pathkeys;
01706 else
01707 {
01708 current_pathkeys = root->sort_pathkeys;
01709
01710 Assert(pathkeys_contained_in(root->distinct_pathkeys,
01711 current_pathkeys));
01712 }
01713
01714 result_plan = (Plan *) make_sort_from_pathkeys(root,
01715 result_plan,
01716 current_pathkeys,
01717 -1.0);
01718 }
01719
01720 result_plan = (Plan *) make_unique(result_plan,
01721 parse->distinctClause);
01722 result_plan->plan_rows = dNumDistinctRows;
01723
01724 }
01725 }
01726
01727
01728
01729
01730
01731 if (parse->sortClause)
01732 {
01733 if (!pathkeys_contained_in(root->sort_pathkeys, current_pathkeys))
01734 {
01735 result_plan = (Plan *) make_sort_from_pathkeys(root,
01736 result_plan,
01737 root->sort_pathkeys,
01738 limit_tuples);
01739 current_pathkeys = root->sort_pathkeys;
01740 }
01741 }
01742
01743
01744
01745
01746
01747
01748
01749 if (parse->rowMarks)
01750 {
01751 result_plan = (Plan *) make_lockrows(result_plan,
01752 root->rowMarks,
01753 SS_assign_special_param(root));
01754
01755
01756
01757
01758
01759 current_pathkeys = NIL;
01760 }
01761
01762
01763
01764
01765 if (limit_needed(parse))
01766 {
01767 result_plan = (Plan *) make_limit(result_plan,
01768 parse->limitOffset,
01769 parse->limitCount,
01770 offset_est,
01771 count_est);
01772 }
01773
01774
01775
01776
01777
01778 root->query_pathkeys = current_pathkeys;
01779
01780 return result_plan;
01781 }
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810 void
01811 add_tlist_costs_to_plan(PlannerInfo *root, Plan *plan, List *tlist)
01812 {
01813 QualCost tlist_cost;
01814 double tlist_rows;
01815
01816 cost_qual_eval(&tlist_cost, tlist, root);
01817 plan->startup_cost += tlist_cost.startup;
01818 plan->total_cost += tlist_cost.startup +
01819 tlist_cost.per_tuple * plan->plan_rows;
01820
01821 tlist_rows = tlist_returns_set_rows(tlist);
01822 if (tlist_rows > 1)
01823 {
01824
01825
01826
01827
01828
01829
01830
01831 plan->total_cost += plan->plan_rows * (tlist_rows - 1) *
01832 cpu_tuple_cost / 2;
01833
01834 plan->plan_rows *= tlist_rows;
01835 }
01836 }
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847 bool
01848 is_dummy_plan(Plan *plan)
01849 {
01850 if (IsA(plan, Result))
01851 {
01852 List *rcqual = (List *) ((Result *) plan)->resconstantqual;
01853
01854 if (list_length(rcqual) == 1)
01855 {
01856 Const *constqual = (Const *) linitial(rcqual);
01857
01858 if (constqual && IsA(constqual, Const))
01859 {
01860 if (!constqual->constisnull &&
01861 !DatumGetBool(constqual->constvalue))
01862 return true;
01863 }
01864 }
01865 }
01866 return false;
01867 }
01868
01869
01870
01871
01872
01873
01874
01875
01876 static Bitmapset *
01877 get_base_rel_indexes(Node *jtnode)
01878 {
01879 Bitmapset *result;
01880
01881 if (jtnode == NULL)
01882 return NULL;
01883 if (IsA(jtnode, RangeTblRef))
01884 {
01885 int varno = ((RangeTblRef *) jtnode)->rtindex;
01886
01887 result = bms_make_singleton(varno);
01888 }
01889 else if (IsA(jtnode, FromExpr))
01890 {
01891 FromExpr *f = (FromExpr *) jtnode;
01892 ListCell *l;
01893
01894 result = NULL;
01895 foreach(l, f->fromlist)
01896 result = bms_join(result,
01897 get_base_rel_indexes(lfirst(l)));
01898 }
01899 else if (IsA(jtnode, JoinExpr))
01900 {
01901 JoinExpr *j = (JoinExpr *) jtnode;
01902
01903 result = bms_join(get_base_rel_indexes(j->larg),
01904 get_base_rel_indexes(j->rarg));
01905 }
01906 else
01907 {
01908 elog(ERROR, "unrecognized node type: %d",
01909 (int) nodeTag(jtnode));
01910 result = NULL;
01911 }
01912 return result;
01913 }
01914
01915
01916
01917
01918 static void
01919 preprocess_rowmarks(PlannerInfo *root)
01920 {
01921 Query *parse = root->parse;
01922 Bitmapset *rels;
01923 List *prowmarks;
01924 ListCell *l;
01925 int i;
01926
01927 if (parse->rowMarks)
01928 {
01929
01930
01931
01932
01933
01934
01935 CheckSelectLocking(parse);
01936 }
01937 else
01938 {
01939
01940
01941
01942 if (parse->commandType != CMD_UPDATE &&
01943 parse->commandType != CMD_DELETE)
01944 return;
01945 }
01946
01947
01948
01949
01950
01951
01952 rels = get_base_rel_indexes((Node *) parse->jointree);
01953 if (parse->resultRelation)
01954 rels = bms_del_member(rels, parse->resultRelation);
01955
01956
01957
01958
01959 prowmarks = NIL;
01960 foreach(l, parse->rowMarks)
01961 {
01962 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
01963 RangeTblEntry *rte = rt_fetch(rc->rti, parse->rtable);
01964 PlanRowMark *newrc;
01965
01966
01967
01968
01969
01970
01971 Assert(rc->rti != parse->resultRelation);
01972
01973
01974
01975
01976
01977
01978
01979 if (rte->rtekind != RTE_RELATION)
01980 continue;
01981
01982
01983
01984
01985
01986
01987
01988 if (rte->relkind == RELKIND_FOREIGN_TABLE)
01989 continue;
01990
01991 rels = bms_del_member(rels, rc->rti);
01992
01993 newrc = makeNode(PlanRowMark);
01994 newrc->rti = newrc->prti = rc->rti;
01995 newrc->rowmarkId = ++(root->glob->lastRowMarkId);
01996 switch (rc->strength)
01997 {
01998 case LCS_FORUPDATE:
01999 newrc->markType = ROW_MARK_EXCLUSIVE;
02000 break;
02001 case LCS_FORNOKEYUPDATE:
02002 newrc->markType = ROW_MARK_NOKEYEXCLUSIVE;
02003 break;
02004 case LCS_FORSHARE:
02005 newrc->markType = ROW_MARK_SHARE;
02006 break;
02007 case LCS_FORKEYSHARE:
02008 newrc->markType = ROW_MARK_KEYSHARE;
02009 break;
02010 }
02011 newrc->noWait = rc->noWait;
02012 newrc->isParent = false;
02013
02014 prowmarks = lappend(prowmarks, newrc);
02015 }
02016
02017
02018
02019
02020 i = 0;
02021 foreach(l, parse->rtable)
02022 {
02023 RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
02024 PlanRowMark *newrc;
02025
02026 i++;
02027 if (!bms_is_member(i, rels))
02028 continue;
02029
02030 newrc = makeNode(PlanRowMark);
02031 newrc->rti = newrc->prti = i;
02032 newrc->rowmarkId = ++(root->glob->lastRowMarkId);
02033
02034 if (rte->rtekind == RTE_RELATION &&
02035 rte->relkind != RELKIND_FOREIGN_TABLE)
02036 newrc->markType = ROW_MARK_REFERENCE;
02037 else
02038 newrc->markType = ROW_MARK_COPY;
02039 newrc->noWait = false;
02040 newrc->isParent = false;
02041
02042 prowmarks = lappend(prowmarks, newrc);
02043 }
02044
02045 root->rowMarks = prowmarks;
02046 }
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065 static double
02066 preprocess_limit(PlannerInfo *root, double tuple_fraction,
02067 int64 *offset_est, int64 *count_est)
02068 {
02069 Query *parse = root->parse;
02070 Node *est;
02071 double limit_fraction;
02072
02073
02074 Assert(parse->limitCount || parse->limitOffset);
02075
02076
02077
02078
02079
02080 if (parse->limitCount)
02081 {
02082 est = estimate_expression_value(root, parse->limitCount);
02083 if (est && IsA(est, Const))
02084 {
02085 if (((Const *) est)->constisnull)
02086 {
02087
02088 *count_est = 0;
02089 }
02090 else
02091 {
02092 *count_est = DatumGetInt64(((Const *) est)->constvalue);
02093 if (*count_est <= 0)
02094 *count_est = 1;
02095 }
02096 }
02097 else
02098 *count_est = -1;
02099 }
02100 else
02101 *count_est = 0;
02102
02103 if (parse->limitOffset)
02104 {
02105 est = estimate_expression_value(root, parse->limitOffset);
02106 if (est && IsA(est, Const))
02107 {
02108 if (((Const *) est)->constisnull)
02109 {
02110
02111 *offset_est = 0;
02112 }
02113 else
02114 {
02115 *offset_est = DatumGetInt64(((Const *) est)->constvalue);
02116 if (*offset_est < 0)
02117 *offset_est = 0;
02118 }
02119 }
02120 else
02121 *offset_est = -1;
02122 }
02123 else
02124 *offset_est = 0;
02125
02126 if (*count_est != 0)
02127 {
02128
02129
02130
02131
02132
02133 if (*count_est < 0 || *offset_est < 0)
02134 {
02135
02136 limit_fraction = 0.10;
02137 }
02138 else
02139 {
02140
02141 limit_fraction = (double) *count_est + (double) *offset_est;
02142 }
02143
02144
02145
02146
02147
02148
02149
02150
02151 if (tuple_fraction >= 1.0)
02152 {
02153 if (limit_fraction >= 1.0)
02154 {
02155
02156 tuple_fraction = Min(tuple_fraction, limit_fraction);
02157 }
02158 else
02159 {
02160
02161 }
02162 }
02163 else if (tuple_fraction > 0.0)
02164 {
02165 if (limit_fraction >= 1.0)
02166 {
02167
02168 tuple_fraction = limit_fraction;
02169 }
02170 else
02171 {
02172
02173 tuple_fraction = Min(tuple_fraction, limit_fraction);
02174 }
02175 }
02176 else
02177 {
02178
02179 tuple_fraction = limit_fraction;
02180 }
02181 }
02182 else if (*offset_est != 0 && tuple_fraction > 0.0)
02183 {
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193 if (*offset_est < 0)
02194 limit_fraction = 0.10;
02195 else
02196 limit_fraction = (double) *offset_est;
02197
02198
02199
02200
02201
02202
02203
02204 if (tuple_fraction >= 1.0)
02205 {
02206 if (limit_fraction >= 1.0)
02207 {
02208
02209 tuple_fraction += limit_fraction;
02210 }
02211 else
02212 {
02213
02214 tuple_fraction = limit_fraction;
02215 }
02216 }
02217 else
02218 {
02219 if (limit_fraction >= 1.0)
02220 {
02221
02222 }
02223 else
02224 {
02225
02226 tuple_fraction += limit_fraction;
02227 if (tuple_fraction >= 1.0)
02228 tuple_fraction = 0.0;
02229 }
02230 }
02231 }
02232
02233 return tuple_fraction;
02234 }
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250 static bool
02251 limit_needed(Query *parse)
02252 {
02253 Node *node;
02254
02255 node = parse->limitCount;
02256 if (node)
02257 {
02258 if (IsA(node, Const))
02259 {
02260
02261 if (!((Const *) node)->constisnull)
02262 return true;
02263 }
02264 else
02265 return true;
02266 }
02267
02268 node = parse->limitOffset;
02269 if (node)
02270 {
02271 if (IsA(node, Const))
02272 {
02273
02274 if (!((Const *) node)->constisnull)
02275 {
02276 int64 offset = DatumGetInt64(((Const *) node)->constvalue);
02277
02278
02279 if (offset > 0)
02280 return true;
02281 }
02282 }
02283 else
02284 return true;
02285 }
02286
02287 return false;
02288 }
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307 static void
02308 preprocess_groupclause(PlannerInfo *root)
02309 {
02310 Query *parse = root->parse;
02311 List *new_groupclause;
02312 bool partial_match;
02313 ListCell *sl;
02314 ListCell *gl;
02315
02316
02317 if (parse->sortClause == NIL)
02318 return;
02319
02320
02321
02322
02323
02324
02325
02326 new_groupclause = NIL;
02327 foreach(sl, parse->sortClause)
02328 {
02329 SortGroupClause *sc = (SortGroupClause *) lfirst(sl);
02330
02331 foreach(gl, parse->groupClause)
02332 {
02333 SortGroupClause *gc = (SortGroupClause *) lfirst(gl);
02334
02335 if (equal(gc, sc))
02336 {
02337 new_groupclause = lappend(new_groupclause, gc);
02338 break;
02339 }
02340 }
02341 if (gl == NULL)
02342 break;
02343 }
02344
02345
02346 partial_match = (sl != NULL);
02347
02348
02349 if (new_groupclause == NIL)
02350 return;
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360 foreach(gl, parse->groupClause)
02361 {
02362 SortGroupClause *gc = (SortGroupClause *) lfirst(gl);
02363
02364 if (list_member_ptr(new_groupclause, gc))
02365 continue;
02366 if (partial_match)
02367 return;
02368 if (!OidIsValid(gc->sortop))
02369 return;
02370 new_groupclause = lappend(new_groupclause, gc);
02371 }
02372
02373
02374 Assert(list_length(parse->groupClause) == list_length(new_groupclause));
02375 parse->groupClause = new_groupclause;
02376 }
02377
02378
02379
02380
02381 static void
02382 standard_qp_callback(PlannerInfo *root, void *extra)
02383 {
02384 Query *parse = root->parse;
02385 standard_qp_extra *qp_extra = (standard_qp_extra *) extra;
02386 List *tlist = qp_extra->tlist;
02387 List *activeWindows = qp_extra->activeWindows;
02388
02389
02390
02391
02392
02393
02394 if (parse->groupClause &&
02395 grouping_is_sortable(parse->groupClause))
02396 root->group_pathkeys =
02397 make_pathkeys_for_sortclauses(root,
02398 parse->groupClause,
02399 tlist);
02400 else
02401 root->group_pathkeys = NIL;
02402
02403
02404 if (activeWindows != NIL)
02405 {
02406 WindowClause *wc = (WindowClause *) linitial(activeWindows);
02407
02408 root->window_pathkeys = make_pathkeys_for_window(root,
02409 wc,
02410 tlist);
02411 }
02412 else
02413 root->window_pathkeys = NIL;
02414
02415 if (parse->distinctClause &&
02416 grouping_is_sortable(parse->distinctClause))
02417 root->distinct_pathkeys =
02418 make_pathkeys_for_sortclauses(root,
02419 parse->distinctClause,
02420 tlist);
02421 else
02422 root->distinct_pathkeys = NIL;
02423
02424 root->sort_pathkeys =
02425 make_pathkeys_for_sortclauses(root,
02426 parse->sortClause,
02427 tlist);
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447 if (root->group_pathkeys)
02448 root->query_pathkeys = root->group_pathkeys;
02449 else if (root->window_pathkeys)
02450 root->query_pathkeys = root->window_pathkeys;
02451 else if (list_length(root->distinct_pathkeys) >
02452 list_length(root->sort_pathkeys))
02453 root->query_pathkeys = root->distinct_pathkeys;
02454 else if (root->sort_pathkeys)
02455 root->query_pathkeys = root->sort_pathkeys;
02456 else
02457 root->query_pathkeys = NIL;
02458 }
02459
02460
02461
02462
02463
02464
02465 static bool
02466 choose_hashed_grouping(PlannerInfo *root,
02467 double tuple_fraction, double limit_tuples,
02468 double path_rows, int path_width,
02469 Path *cheapest_path, Path *sorted_path,
02470 double dNumGroups, AggClauseCosts *agg_costs)
02471 {
02472 Query *parse = root->parse;
02473 int numGroupCols = list_length(parse->groupClause);
02474 bool can_hash;
02475 bool can_sort;
02476 Size hashentrysize;
02477 List *target_pathkeys;
02478 List *current_pathkeys;
02479 Path hashed_p;
02480 Path sorted_p;
02481
02482
02483
02484
02485
02486
02487
02488 can_hash = (agg_costs->numOrderedAggs == 0 &&
02489 grouping_is_hashable(parse->groupClause));
02490 can_sort = grouping_is_sortable(parse->groupClause);
02491
02492
02493 if (!(can_hash && can_sort))
02494 {
02495 if (can_hash)
02496 return true;
02497 else if (can_sort)
02498 return false;
02499 else
02500 ereport(ERROR,
02501 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02502 errmsg("could not implement GROUP BY"),
02503 errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
02504 }
02505
02506
02507 if (!enable_hashagg)
02508 return false;
02509
02510
02511
02512
02513
02514
02515
02516 hashentrysize = MAXALIGN(path_width) + MAXALIGN(sizeof(MinimalTupleData));
02517
02518 hashentrysize += agg_costs->transitionSpace;
02519
02520 hashentrysize += hash_agg_entry_size(agg_costs->numAggs);
02521
02522 if (hashentrysize * dNumGroups > work_mem * 1024L)
02523 return false;
02524
02525
02526
02527
02528
02529
02530
02531
02532 if (list_length(root->distinct_pathkeys) >
02533 list_length(root->sort_pathkeys))
02534 target_pathkeys = root->distinct_pathkeys;
02535 else
02536 target_pathkeys = root->sort_pathkeys;
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554 cost_agg(&hashed_p, root, AGG_HASHED, agg_costs,
02555 numGroupCols, dNumGroups,
02556 cheapest_path->startup_cost, cheapest_path->total_cost,
02557 path_rows);
02558
02559 if (target_pathkeys)
02560 cost_sort(&hashed_p, root, target_pathkeys, hashed_p.total_cost,
02561 dNumGroups, path_width,
02562 0.0, work_mem, limit_tuples);
02563
02564 if (sorted_path)
02565 {
02566 sorted_p.startup_cost = sorted_path->startup_cost;
02567 sorted_p.total_cost = sorted_path->total_cost;
02568 current_pathkeys = sorted_path->pathkeys;
02569 }
02570 else
02571 {
02572 sorted_p.startup_cost = cheapest_path->startup_cost;
02573 sorted_p.total_cost = cheapest_path->total_cost;
02574 current_pathkeys = cheapest_path->pathkeys;
02575 }
02576 if (!pathkeys_contained_in(root->group_pathkeys, current_pathkeys))
02577 {
02578 cost_sort(&sorted_p, root, root->group_pathkeys, sorted_p.total_cost,
02579 path_rows, path_width,
02580 0.0, work_mem, -1.0);
02581 current_pathkeys = root->group_pathkeys;
02582 }
02583
02584 if (parse->hasAggs)
02585 cost_agg(&sorted_p, root, AGG_SORTED, agg_costs,
02586 numGroupCols, dNumGroups,
02587 sorted_p.startup_cost, sorted_p.total_cost,
02588 path_rows);
02589 else
02590 cost_group(&sorted_p, root, numGroupCols, dNumGroups,
02591 sorted_p.startup_cost, sorted_p.total_cost,
02592 path_rows);
02593
02594 if (target_pathkeys &&
02595 !pathkeys_contained_in(target_pathkeys, current_pathkeys))
02596 cost_sort(&sorted_p, root, target_pathkeys, sorted_p.total_cost,
02597 dNumGroups, path_width,
02598 0.0, work_mem, limit_tuples);
02599
02600
02601
02602
02603
02604 if (tuple_fraction >= 1.0)
02605 tuple_fraction /= dNumGroups;
02606
02607 if (compare_fractional_path_costs(&hashed_p, &sorted_p,
02608 tuple_fraction) < 0)
02609 {
02610
02611 return true;
02612 }
02613 return false;
02614 }
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635 static bool
02636 choose_hashed_distinct(PlannerInfo *root,
02637 double tuple_fraction, double limit_tuples,
02638 double path_rows, int path_width,
02639 Cost cheapest_startup_cost, Cost cheapest_total_cost,
02640 Cost sorted_startup_cost, Cost sorted_total_cost,
02641 List *sorted_pathkeys,
02642 double dNumDistinctRows)
02643 {
02644 Query *parse = root->parse;
02645 int numDistinctCols = list_length(parse->distinctClause);
02646 bool can_sort;
02647 bool can_hash;
02648 Size hashentrysize;
02649 List *current_pathkeys;
02650 List *needed_pathkeys;
02651 Path hashed_p;
02652 Path sorted_p;
02653
02654
02655
02656
02657
02658 can_sort = grouping_is_sortable(parse->distinctClause);
02659 if (can_sort && parse->hasDistinctOn)
02660 return false;
02661
02662 can_hash = grouping_is_hashable(parse->distinctClause);
02663
02664
02665 if (!(can_hash && can_sort))
02666 {
02667 if (can_hash)
02668 return true;
02669 else if (can_sort)
02670 return false;
02671 else
02672 ereport(ERROR,
02673 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02674 errmsg("could not implement DISTINCT"),
02675 errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
02676 }
02677
02678
02679 if (!enable_hashagg)
02680 return false;
02681
02682
02683
02684
02685
02686 hashentrysize = MAXALIGN(path_width) + MAXALIGN(sizeof(MinimalTupleData));
02687
02688 if (hashentrysize * dNumDistinctRows > work_mem * 1024L)
02689 return false;
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704 cost_agg(&hashed_p, root, AGG_HASHED, NULL,
02705 numDistinctCols, dNumDistinctRows,
02706 cheapest_startup_cost, cheapest_total_cost,
02707 path_rows);
02708
02709
02710
02711
02712
02713 if (parse->sortClause)
02714 cost_sort(&hashed_p, root, root->sort_pathkeys, hashed_p.total_cost,
02715 dNumDistinctRows, path_width,
02716 0.0, work_mem, limit_tuples);
02717
02718
02719
02720
02721
02722 sorted_p.startup_cost = sorted_startup_cost;
02723 sorted_p.total_cost = sorted_total_cost;
02724 current_pathkeys = sorted_pathkeys;
02725 if (parse->hasDistinctOn &&
02726 list_length(root->distinct_pathkeys) <
02727 list_length(root->sort_pathkeys))
02728 needed_pathkeys = root->sort_pathkeys;
02729 else
02730 needed_pathkeys = root->distinct_pathkeys;
02731 if (!pathkeys_contained_in(needed_pathkeys, current_pathkeys))
02732 {
02733 if (list_length(root->distinct_pathkeys) >=
02734 list_length(root->sort_pathkeys))
02735 current_pathkeys = root->distinct_pathkeys;
02736 else
02737 current_pathkeys = root->sort_pathkeys;
02738 cost_sort(&sorted_p, root, current_pathkeys, sorted_p.total_cost,
02739 path_rows, path_width,
02740 0.0, work_mem, -1.0);
02741 }
02742 cost_group(&sorted_p, root, numDistinctCols, dNumDistinctRows,
02743 sorted_p.startup_cost, sorted_p.total_cost,
02744 path_rows);
02745 if (parse->sortClause &&
02746 !pathkeys_contained_in(root->sort_pathkeys, current_pathkeys))
02747 cost_sort(&sorted_p, root, root->sort_pathkeys, sorted_p.total_cost,
02748 dNumDistinctRows, path_width,
02749 0.0, work_mem, limit_tuples);
02750
02751
02752
02753
02754
02755 if (tuple_fraction >= 1.0)
02756 tuple_fraction /= dNumDistinctRows;
02757
02758 if (compare_fractional_path_costs(&hashed_p, &sorted_p,
02759 tuple_fraction) < 0)
02760 {
02761
02762 return true;
02763 }
02764 return false;
02765 }
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806 static List *
02807 make_subplanTargetList(PlannerInfo *root,
02808 List *tlist,
02809 AttrNumber **groupColIdx,
02810 bool *need_tlist_eval)
02811 {
02812 Query *parse = root->parse;
02813 List *sub_tlist;
02814 List *non_group_cols;
02815 List *non_group_vars;
02816 int numCols;
02817
02818 *groupColIdx = NULL;
02819
02820
02821
02822
02823
02824 if (!parse->hasAggs && !parse->groupClause && !root->hasHavingQual &&
02825 !parse->hasWindowFuncs)
02826 {
02827 *need_tlist_eval = true;
02828 return tlist;
02829 }
02830
02831
02832
02833
02834
02835 sub_tlist = NIL;
02836 non_group_cols = NIL;
02837 *need_tlist_eval = false;
02838
02839 numCols = list_length(parse->groupClause);
02840 if (numCols > 0)
02841 {
02842
02843
02844
02845
02846
02847
02848
02849 AttrNumber *grpColIdx;
02850 ListCell *tl;
02851
02852 grpColIdx = (AttrNumber *) palloc0(sizeof(AttrNumber) * numCols);
02853 *groupColIdx = grpColIdx;
02854
02855 foreach(tl, tlist)
02856 {
02857 TargetEntry *tle = (TargetEntry *) lfirst(tl);
02858 int colno;
02859
02860 colno = get_grouping_column_index(parse, tle);
02861 if (colno >= 0)
02862 {
02863
02864
02865
02866
02867 TargetEntry *newtle;
02868
02869 newtle = makeTargetEntry(tle->expr,
02870 list_length(sub_tlist) + 1,
02871 NULL,
02872 false);
02873 sub_tlist = lappend(sub_tlist, newtle);
02874
02875 Assert(grpColIdx[colno] == 0);
02876 grpColIdx[colno] = newtle->resno;
02877
02878 if (!(newtle->expr && IsA(newtle->expr, Var)))
02879 *need_tlist_eval = true;
02880 }
02881 else
02882 {
02883
02884
02885
02886
02887
02888 non_group_cols = lappend(non_group_cols, tle->expr);
02889 }
02890 }
02891 }
02892 else
02893 {
02894
02895
02896
02897
02898 non_group_cols = list_copy(tlist);
02899 }
02900
02901
02902
02903
02904 if (parse->havingQual)
02905 non_group_cols = lappend(non_group_cols, parse->havingQual);
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915 non_group_vars = pull_var_clause((Node *) non_group_cols,
02916 PVC_RECURSE_AGGREGATES,
02917 PVC_INCLUDE_PLACEHOLDERS);
02918 sub_tlist = add_to_flat_tlist(sub_tlist, non_group_vars);
02919
02920
02921 list_free(non_group_vars);
02922 list_free(non_group_cols);
02923
02924 return sub_tlist;
02925 }
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935 static int
02936 get_grouping_column_index(Query *parse, TargetEntry *tle)
02937 {
02938 int colno = 0;
02939 Index ressortgroupref = tle->ressortgroupref;
02940 ListCell *gl;
02941
02942
02943 if (ressortgroupref == 0)
02944 return -1;
02945
02946 foreach(gl, parse->groupClause)
02947 {
02948 SortGroupClause *grpcl = (SortGroupClause *) lfirst(gl);
02949
02950 if (grpcl->tleSortGroupRef == ressortgroupref)
02951 return colno;
02952 colno++;
02953 }
02954
02955 return -1;
02956 }
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966 static void
02967 locate_grouping_columns(PlannerInfo *root,
02968 List *tlist,
02969 List *sub_tlist,
02970 AttrNumber *groupColIdx)
02971 {
02972 int keyno = 0;
02973 ListCell *gl;
02974
02975
02976
02977
02978 if (!root->parse->groupClause)
02979 {
02980 Assert(groupColIdx == NULL);
02981 return;
02982 }
02983 Assert(groupColIdx != NULL);
02984
02985 foreach(gl, root->parse->groupClause)
02986 {
02987 SortGroupClause *grpcl = (SortGroupClause *) lfirst(gl);
02988 Node *groupexpr = get_sortgroupclause_expr(grpcl, tlist);
02989 TargetEntry *te = tlist_member(groupexpr, sub_tlist);
02990
02991 if (!te)
02992 elog(ERROR, "failed to locate grouping columns");
02993 groupColIdx[keyno++] = te->resno;
02994 }
02995 }
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007 static List *
03008 postprocess_setop_tlist(List *new_tlist, List *orig_tlist)
03009 {
03010 ListCell *l;
03011 ListCell *orig_tlist_item = list_head(orig_tlist);
03012
03013 foreach(l, new_tlist)
03014 {
03015 TargetEntry *new_tle = (TargetEntry *) lfirst(l);
03016 TargetEntry *orig_tle;
03017
03018
03019 if (new_tle->resjunk)
03020 continue;
03021
03022 Assert(orig_tlist_item != NULL);
03023 orig_tle = (TargetEntry *) lfirst(orig_tlist_item);
03024 orig_tlist_item = lnext(orig_tlist_item);
03025 if (orig_tle->resjunk)
03026 elog(ERROR, "resjunk output columns are not implemented");
03027 Assert(new_tle->resno == orig_tle->resno);
03028 new_tle->ressortgroupref = orig_tle->ressortgroupref;
03029 }
03030 if (orig_tlist_item != NULL)
03031 elog(ERROR, "resjunk output columns are not implemented");
03032 return new_tlist;
03033 }
03034
03035
03036
03037
03038
03039
03040 static List *
03041 select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
03042 {
03043 List *result;
03044 List *actives;
03045 ListCell *lc;
03046
03047
03048 actives = NIL;
03049 foreach(lc, root->parse->windowClause)
03050 {
03051 WindowClause *wc = (WindowClause *) lfirst(lc);
03052
03053
03054 Assert(wc->winref <= wflists->maxWinRef);
03055 if (wflists->windowFuncs[wc->winref] != NIL)
03056 actives = lappend(actives, wc);
03057 }
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071 result = NIL;
03072 while (actives != NIL)
03073 {
03074 WindowClause *wc = (WindowClause *) linitial(actives);
03075 ListCell *prev;
03076 ListCell *next;
03077
03078
03079 actives = list_delete_first(actives);
03080 result = lappend(result, wc);
03081
03082
03083 prev = NULL;
03084 for (lc = list_head(actives); lc; lc = next)
03085 {
03086 WindowClause *wc2 = (WindowClause *) lfirst(lc);
03087
03088 next = lnext(lc);
03089
03090 if (equal(wc->partitionClause, wc2->partitionClause) &&
03091 equal(wc->orderClause, wc2->orderClause))
03092 {
03093 actives = list_delete_cell(actives, lc, prev);
03094 result = lappend(result, wc2);
03095 }
03096 else
03097 prev = lc;
03098 }
03099 }
03100
03101 return result;
03102 }
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137 static List *
03138 make_windowInputTargetList(PlannerInfo *root,
03139 List *tlist,
03140 List *activeWindows)
03141 {
03142 Query *parse = root->parse;
03143 Bitmapset *sgrefs;
03144 List *new_tlist;
03145 List *flattenable_cols;
03146 List *flattenable_vars;
03147 ListCell *lc;
03148
03149 Assert(parse->hasWindowFuncs);
03150
03151
03152
03153
03154
03155 sgrefs = NULL;
03156 foreach(lc, activeWindows)
03157 {
03158 WindowClause *wc = (WindowClause *) lfirst(lc);
03159 ListCell *lc2;
03160
03161 foreach(lc2, wc->partitionClause)
03162 {
03163 SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc2);
03164
03165 sgrefs = bms_add_member(sgrefs, sortcl->tleSortGroupRef);
03166 }
03167 foreach(lc2, wc->orderClause)
03168 {
03169 SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc2);
03170
03171 sgrefs = bms_add_member(sgrefs, sortcl->tleSortGroupRef);
03172 }
03173 }
03174
03175
03176 foreach(lc, parse->groupClause)
03177 {
03178 SortGroupClause *grpcl = (SortGroupClause *) lfirst(lc);
03179
03180 sgrefs = bms_add_member(sgrefs, grpcl->tleSortGroupRef);
03181 }
03182
03183
03184
03185
03186
03187 new_tlist = NIL;
03188 flattenable_cols = NIL;
03189
03190 foreach(lc, tlist)
03191 {
03192 TargetEntry *tle = (TargetEntry *) lfirst(lc);
03193
03194
03195
03196
03197
03198
03199 if (tle->ressortgroupref != 0 &&
03200 bms_is_member(tle->ressortgroupref, sgrefs))
03201 {
03202
03203 TargetEntry *newtle;
03204
03205 newtle = makeTargetEntry(tle->expr,
03206 list_length(new_tlist) + 1,
03207 NULL,
03208 false);
03209
03210 newtle->ressortgroupref = tle->ressortgroupref;
03211 new_tlist = lappend(new_tlist, newtle);
03212 }
03213 else
03214 {
03215
03216
03217
03218
03219
03220 flattenable_cols = lappend(flattenable_cols, tle->expr);
03221 }
03222 }
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233 flattenable_vars = pull_var_clause((Node *) flattenable_cols,
03234 PVC_INCLUDE_AGGREGATES,
03235 PVC_INCLUDE_PLACEHOLDERS);
03236 new_tlist = add_to_flat_tlist(new_tlist, flattenable_vars);
03237
03238
03239 list_free(flattenable_vars);
03240 list_free(flattenable_cols);
03241
03242 return new_tlist;
03243 }
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254 static List *
03255 make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
03256 List *tlist)
03257 {
03258 List *window_pathkeys;
03259 List *window_sortclauses;
03260
03261
03262 if (!grouping_is_sortable(wc->partitionClause))
03263 ereport(ERROR,
03264 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03265 errmsg("could not implement window PARTITION BY"),
03266 errdetail("Window partitioning columns must be of sortable datatypes.")));
03267 if (!grouping_is_sortable(wc->orderClause))
03268 ereport(ERROR,
03269 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03270 errmsg("could not implement window ORDER BY"),
03271 errdetail("Window ordering columns must be of sortable datatypes.")));
03272
03273
03274 window_sortclauses = list_concat(list_copy(wc->partitionClause),
03275 list_copy(wc->orderClause));
03276 window_pathkeys = make_pathkeys_for_sortclauses(root,
03277 window_sortclauses,
03278 tlist);
03279 list_free(window_sortclauses);
03280 return window_pathkeys;
03281 }
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308 static void
03309 get_column_info_for_window(PlannerInfo *root, WindowClause *wc, List *tlist,
03310 int numSortCols, AttrNumber *sortColIdx,
03311 int *partNumCols,
03312 AttrNumber **partColIdx,
03313 Oid **partOperators,
03314 int *ordNumCols,
03315 AttrNumber **ordColIdx,
03316 Oid **ordOperators)
03317 {
03318 int numPart = list_length(wc->partitionClause);
03319 int numOrder = list_length(wc->orderClause);
03320
03321 if (numSortCols == numPart + numOrder)
03322 {
03323
03324 *partNumCols = numPart;
03325 *partColIdx = sortColIdx;
03326 *partOperators = extract_grouping_ops(wc->partitionClause);
03327 *ordNumCols = numOrder;
03328 *ordColIdx = sortColIdx + numPart;
03329 *ordOperators = extract_grouping_ops(wc->orderClause);
03330 }
03331 else
03332 {
03333 List *sortclauses;
03334 List *pathkeys;
03335 int scidx;
03336 ListCell *lc;
03337
03338
03339 *partNumCols = 0;
03340 *partColIdx = (AttrNumber *) palloc(numPart * sizeof(AttrNumber));
03341 *partOperators = (Oid *) palloc(numPart * sizeof(Oid));
03342 *ordNumCols = 0;
03343 *ordColIdx = (AttrNumber *) palloc(numOrder * sizeof(AttrNumber));
03344 *ordOperators = (Oid *) palloc(numOrder * sizeof(Oid));
03345 sortclauses = NIL;
03346 pathkeys = NIL;
03347 scidx = 0;
03348 foreach(lc, wc->partitionClause)
03349 {
03350 SortGroupClause *sgc = (SortGroupClause *) lfirst(lc);
03351 List *new_pathkeys;
03352
03353 sortclauses = lappend(sortclauses, sgc);
03354 new_pathkeys = make_pathkeys_for_sortclauses(root,
03355 sortclauses,
03356 tlist);
03357 if (list_length(new_pathkeys) > list_length(pathkeys))
03358 {
03359
03360 (*partColIdx)[*partNumCols] = sortColIdx[scidx++];
03361 (*partOperators)[*partNumCols] = sgc->eqop;
03362 (*partNumCols)++;
03363 pathkeys = new_pathkeys;
03364 }
03365 }
03366 foreach(lc, wc->orderClause)
03367 {
03368 SortGroupClause *sgc = (SortGroupClause *) lfirst(lc);
03369 List *new_pathkeys;
03370
03371 sortclauses = lappend(sortclauses, sgc);
03372 new_pathkeys = make_pathkeys_for_sortclauses(root,
03373 sortclauses,
03374 tlist);
03375 if (list_length(new_pathkeys) > list_length(pathkeys))
03376 {
03377
03378 (*ordColIdx)[*ordNumCols] = sortColIdx[scidx++];
03379 (*ordOperators)[*ordNumCols] = sgc->eqop;
03380 (*ordNumCols)++;
03381 pathkeys = new_pathkeys;
03382 }
03383 }
03384
03385 if (scidx != numSortCols)
03386 elog(ERROR, "failed to deconstruct sort operators into partitioning/ordering operators");
03387 }
03388 }
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413 Expr *
03414 expression_planner(Expr *expr)
03415 {
03416 Node *result;
03417
03418
03419
03420
03421
03422 result = eval_const_expressions(NULL, (Node *) expr);
03423
03424
03425 fix_opfuncids(result);
03426
03427 return (Expr *) result;
03428 }
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442 bool
03443 plan_cluster_use_sort(Oid tableOid, Oid indexOid)
03444 {
03445 PlannerInfo *root;
03446 Query *query;
03447 PlannerGlobal *glob;
03448 RangeTblEntry *rte;
03449 RelOptInfo *rel;
03450 IndexOptInfo *indexInfo;
03451 QualCost indexExprCost;
03452 Cost comparisonCost;
03453 Path *seqScanPath;
03454 Path seqScanAndSortPath;
03455 IndexPath *indexScanPath;
03456 ListCell *lc;
03457
03458
03459 query = makeNode(Query);
03460 query->commandType = CMD_SELECT;
03461
03462 glob = makeNode(PlannerGlobal);
03463
03464 root = makeNode(PlannerInfo);
03465 root->parse = query;
03466 root->glob = glob;
03467 root->query_level = 1;
03468 root->planner_cxt = CurrentMemoryContext;
03469 root->wt_param_id = -1;
03470
03471
03472 rte = makeNode(RangeTblEntry);
03473 rte->rtekind = RTE_RELATION;
03474 rte->relid = tableOid;
03475 rte->relkind = RELKIND_RELATION;
03476 rte->lateral = false;
03477 rte->inh = false;
03478 rte->inFromCl = true;
03479 query->rtable = list_make1(rte);
03480
03481
03482 setup_simple_rel_arrays(root);
03483
03484
03485 rel = build_simple_rel(root, 1, RELOPT_BASEREL);
03486
03487
03488 indexInfo = NULL;
03489 foreach(lc, rel->indexlist)
03490 {
03491 indexInfo = (IndexOptInfo *) lfirst(lc);
03492 if (indexInfo->indexoid == indexOid)
03493 break;
03494 }
03495
03496
03497
03498
03499
03500
03501
03502
03503 if (lc == NULL)
03504 return true;
03505
03506
03507
03508
03509
03510 rel->rows = rel->tuples;
03511 rel->width = get_relation_data_width(tableOid, NULL);
03512
03513 root->total_table_pages = rel->pages;
03514
03515
03516
03517
03518
03519
03520
03521 cost_qual_eval(&indexExprCost, indexInfo->indexprs, root);
03522 comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
03523
03524
03525 seqScanPath = create_seqscan_path(root, rel, NULL);
03526 cost_sort(&seqScanAndSortPath, root, NIL,
03527 seqScanPath->total_cost, rel->tuples, rel->width,
03528 comparisonCost, maintenance_work_mem, -1.0);
03529
03530
03531 indexScanPath = create_index_path(root, indexInfo,
03532 NIL, NIL, NIL, NIL, NIL,
03533 ForwardScanDirection, false,
03534 NULL, 1.0);
03535
03536 return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
03537 }