diff options
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 4465f002c8f..272710eed2d 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -611,6 +611,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse, List *newWithCheckOptions; List *newHaving; bool hasOuterJoins; + bool hasResultRTEs; RelOptInfo *final_rel; ListCell *l; @@ -652,6 +653,12 @@ subquery_planner(PlannerGlobal *glob, Query *parse, SS_process_ctes(root); /* + * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so + * that we don't need so many special cases to deal with that situation. + */ + replace_empty_jointree(parse); + + /* * Look for ANY and EXISTS SubLinks in WHERE and JOIN/ON clauses, and try * to transform them into joins. Note that this step does not descend * into subqueries; if we pull up any subqueries below, their SubLinks are @@ -684,14 +691,16 @@ subquery_planner(PlannerGlobal *glob, Query *parse, /* * Detect whether any rangetable entries are RTE_JOIN kind; if not, we can - * avoid the expense of doing flatten_join_alias_vars(). Also check for - * outer joins --- if none, we can skip reduce_outer_joins(). And check - * for LATERAL RTEs, too. This must be done after we have done - * pull_up_subqueries(), of course. + * avoid the expense of doing flatten_join_alias_vars(). Likewise check + * whether any are RTE_RESULT kind; if not, we can skip + * remove_useless_result_rtes(). Also check for outer joins --- if none, + * we can skip reduce_outer_joins(). And check for LATERAL RTEs, too. + * This must be done after we have done pull_up_subqueries(), of course. */ root->hasJoinRTEs = false; root->hasLateralRTEs = false; hasOuterJoins = false; + hasResultRTEs = false; foreach(l, parse->rtable) { RangeTblEntry *rte = lfirst_node(RangeTblEntry, l); @@ -702,6 +711,10 @@ subquery_planner(PlannerGlobal *glob, Query *parse, if (IS_OUTER_JOIN(rte->jointype)) hasOuterJoins = true; } + else if (rte->rtekind == RTE_RESULT) + { + hasResultRTEs = true; + } if (rte->lateral) root->hasLateralRTEs = true; } @@ -717,10 +730,10 @@ subquery_planner(PlannerGlobal *glob, Query *parse, /* * Expand any rangetable entries that are inheritance sets into "append * relations". This can add entries to the rangetable, but they must be - * plain base relations not joins, so it's OK (and marginally more - * efficient) to do it after checking for join RTEs. We must do it after - * pulling up subqueries, else we'd fail to handle inherited tables in - * subqueries. + * plain RTE_RELATION entries, so it's OK (and marginally more efficient) + * to do it after checking for joins and other special RTEs. We must do + * this after pulling up subqueries, else we'd fail to handle inherited + * tables in subqueries. */ expand_inherited_tables(root); @@ -968,6 +981,14 @@ subquery_planner(PlannerGlobal *glob, Query *parse, reduce_outer_joins(root); /* + * If we have any RTE_RESULT relations, see if they can be deleted from + * the jointree. This step is most effectively done after we've done + * expression preprocessing and outer join reduction. + */ + if (hasResultRTEs) + remove_useless_result_rtes(root); + + /* * Do the main planning. If we have an inherited target relation, that * needs special processing, else go straight to grouping_planner. */ @@ -3894,9 +3915,9 @@ create_degenerate_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, while (--nrows >= 0) { path = (Path *) - create_result_path(root, grouped_rel, - grouped_rel->reltarget, - (List *) parse->havingQual); + create_group_result_path(root, grouped_rel, + grouped_rel->reltarget, + (List *) parse->havingQual); paths = lappend(paths, path); } path = (Path *) @@ -3914,9 +3935,9 @@ create_degenerate_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, { /* No grouping sets, or just one, so one output row */ path = (Path *) - create_result_path(root, grouped_rel, - grouped_rel->reltarget, - (List *) parse->havingQual); + create_group_result_path(root, grouped_rel, + grouped_rel->reltarget, + (List *) parse->havingQual); } add_path(grouped_rel, path); |