diff options
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 116 |
1 files changed, 21 insertions, 95 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 032818423f6..ddd23878409 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -54,7 +54,6 @@ #include "optimizer/tlist.h" #include "parser/analyze.h" #include "parser/parse_agg.h" -#include "parser/parse_clause.h" #include "parser/parse_relation.h" #include "parser/parsetree.h" #include "partitioning/partdesc.h" @@ -120,15 +119,12 @@ typedef struct { List *activeWindows; /* active windows, if any */ grouping_sets_data *gset_data; /* grouping sets data, if any */ - SetOperationStmt *setop; /* parent set operation or NULL if not a - * subquery belonging to a set operation */ } standard_qp_extra; /* Local functions */ static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind); static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode); -static void grouping_planner(PlannerInfo *root, double tuple_fraction, - SetOperationStmt *setops); +static void grouping_planner(PlannerInfo *root, double tuple_fraction); static grouping_sets_data *preprocess_grouping_sets(PlannerInfo *root); static List *remap_to_groupclause_idx(List *groupClause, List *gsets, int *tleref_to_colnum_map); @@ -253,8 +249,6 @@ static bool group_by_has_partkey(RelOptInfo *input_rel, List *targetList, List *groupClause); static int common_prefix_cmp(const void *a, const void *b); -static List *generate_setop_child_grouplist(SetOperationStmt *op, - List *targetlist); /***************************************************************************** @@ -412,7 +406,8 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, } /* primary planning entry point (may recurse for subqueries) */ - root = subquery_planner(glob, parse, NULL, false, tuple_fraction, NULL); + root = subquery_planner(glob, parse, NULL, + false, tuple_fraction); /* Select best Path and turn it into a Plan */ final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL); @@ -603,10 +598,6 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, * hasRecursion is true if this is a recursive WITH query. * tuple_fraction is the fraction of tuples we expect will be retrieved. * tuple_fraction is interpreted as explained for grouping_planner, below. - * setops is used for set operation subqueries to provide the subquery with - * the context in which it's being used so that Paths correctly sorted for the - * set operation can be generated. NULL when not planning a set operation - * child. * * Basically, this routine does the stuff that should only be done once * per Query object. It then calls grouping_planner. At one time, @@ -625,9 +616,9 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, *-------------------- */ PlannerInfo * -subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, - bool hasRecursion, double tuple_fraction, - SetOperationStmt *setops) +subquery_planner(PlannerGlobal *glob, Query *parse, + PlannerInfo *parent_root, + bool hasRecursion, double tuple_fraction) { PlannerInfo *root; List *newWithCheckOptions; @@ -1086,7 +1077,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, /* * Do the main planning. */ - grouping_planner(root, tuple_fraction, setops); + grouping_planner(root, tuple_fraction); /* * Capture the set of outer-level param IDs we have access to, for use in @@ -1284,11 +1275,7 @@ preprocess_phv_expression(PlannerInfo *root, Expr *expr) * 0 < tuple_fraction < 1: expect the given fraction of tuples available * from the plan to be retrieved * tuple_fraction >= 1: tuple_fraction is the absolute number of tuples - * expected to be retrieved (ie, a LIMIT specification). - * setops is used for set operation subqueries to provide the subquery with - * the context in which it's being used so that Paths correctly sorted for the - * set operation can be generated. NULL when not planning a set operation - * child. + * expected to be retrieved (ie, a LIMIT specification) * * Returns nothing; the useful output is in the Paths we attach to the * (UPPERREL_FINAL, NULL) upperrel in *root. In addition, @@ -1299,8 +1286,7 @@ preprocess_phv_expression(PlannerInfo *root, Expr *expr) *-------------------- */ static void -grouping_planner(PlannerInfo *root, double tuple_fraction, - SetOperationStmt *setops) +grouping_planner(PlannerInfo *root, double tuple_fraction) { Query *parse = root->parse; int64 offset_est = 0; @@ -1336,6 +1322,17 @@ grouping_planner(PlannerInfo *root, double tuple_fraction, if (parse->setOperations) { /* + * If there's a top-level ORDER BY, assume we have to fetch all the + * tuples. This might be too simplistic given all the hackery below + * to possibly avoid the sort; but the odds of accurate estimates here + * are pretty low anyway. XXX try to get rid of this in favor of + * letting plan_set_operations generate both fast-start and + * cheapest-total paths. + */ + if (parse->sortClause) + root->tuple_fraction = 0.0; + + /* * Construct Paths for set operations. The results will not need any * work except perhaps a top-level sort and/or LIMIT. Note that any * special work for recursive unions is the responsibility of @@ -1505,12 +1502,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction, qp_extra.gset_data = gset_data; /* - * If we're a subquery for a set operation, store the SetOperationStmt - * in qp_extra. - */ - qp_extra.setop = setops; - - /* * Generate the best unsorted and presorted paths for the scan/join * portion of this Query, ie the processing represented by the * FROM/WHERE clauses. (Note there may not be any presorted paths.) @@ -3462,27 +3453,6 @@ standard_qp_callback(PlannerInfo *root, void *extra) parse->sortClause, tlist); - /* setting setop_pathkeys might be useful to the union planner */ - if (qp_extra->setop != NULL && - set_operation_ordered_results_useful(qp_extra->setop)) - { - List *groupClauses; - bool sortable; - - groupClauses = generate_setop_child_grouplist(qp_extra->setop, tlist); - - root->setop_pathkeys = - make_pathkeys_for_sortclauses_extended(root, - &groupClauses, - tlist, - false, - &sortable); - if (!sortable) - root->setop_pathkeys = NIL; - } - else - root->setop_pathkeys = NIL; - /* * Figure out whether we want a sorted result from query_planner. * @@ -3492,9 +3462,7 @@ standard_qp_callback(PlannerInfo *root, void *extra) * sortable DISTINCT clause that's more rigorous than the ORDER BY clause, * we try to produce output that's sufficiently well sorted for the * DISTINCT. Otherwise, if there is an ORDER BY clause, we want to sort - * by the ORDER BY clause. Otherwise, if we're a subquery being planned - * for a set operation which can benefit from presorted results and have a - * sortable targetlist, we want to sort by the target list. + * by the ORDER BY clause. * * Note: if we have both ORDER BY and GROUP BY, and ORDER BY is a superset * of GROUP BY, it would be tempting to request sort by ORDER BY --- but @@ -3512,8 +3480,6 @@ standard_qp_callback(PlannerInfo *root, void *extra) root->query_pathkeys = root->distinct_pathkeys; else if (root->sort_pathkeys) root->query_pathkeys = root->sort_pathkeys; - else if (root->setop_pathkeys != NIL) - root->query_pathkeys = root->setop_pathkeys; else root->query_pathkeys = NIL; } @@ -7957,43 +7923,3 @@ group_by_has_partkey(RelOptInfo *input_rel, return true; } - -/* - * generate_setop_child_grouplist - * Build a SortGroupClause list defining the sort/grouping properties - * of the child of a set operation. - * - * This is similar to generate_setop_grouplist() but differs as the setop - * child query's targetlist entries may already have a tleSortGroupRef - * assigned for other purposes, such as GROUP BYs. Here we keep the - * SortGroupClause list in the same order as 'op' groupClauses and just adjust - * the tleSortGroupRef to reference the TargetEntry's 'ressortgroupref'. - */ -static List * -generate_setop_child_grouplist(SetOperationStmt *op, List *targetlist) -{ - List *grouplist = copyObject(op->groupClauses); - ListCell *lg; - ListCell *lt; - - lg = list_head(grouplist); - foreach(lt, targetlist) - { - TargetEntry *tle = (TargetEntry *) lfirst(lt); - SortGroupClause *sgc; - - /* resjunk columns could have sortgrouprefs. Leave these alone */ - if (tle->resjunk) - continue; - - /* we expect every non-resjunk target to have a SortGroupClause */ - Assert(lg != NULL); - sgc = (SortGroupClause *) lfirst(lg); - lg = lnext(grouplist, lg); - - /* assign a tleSortGroupRef, or reuse the existing one */ - sgc->tleSortGroupRef = assignSortGroupRef(tle, targetlist); - } - Assert(lg == NULL); - return grouplist; -} |