summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planmain.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/planmain.c')
-rw-r--r--src/backend/optimizer/plan/planmain.c103
1 files changed, 65 insertions, 38 deletions
diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index fc97a1bb507..f9f4b12db71 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -61,44 +61,6 @@ query_planner(PlannerInfo *root, List *tlist,
RelOptInfo *final_rel;
/*
- * If the query has an empty join tree, then it's something easy like
- * "SELECT 2+2;" or "INSERT ... VALUES()". Fall through quickly.
- */
- if (parse->jointree->fromlist == NIL)
- {
- /* We need a dummy joinrel to describe the empty set of baserels */
- final_rel = build_empty_join_rel(root);
-
- /*
- * If query allows parallelism in general, check whether the quals are
- * parallel-restricted. (We need not check final_rel->reltarget
- * because it's empty at this point. Anything parallel-restricted in
- * the query tlist will be dealt with later.)
- */
- if (root->glob->parallelModeOK)
- final_rel->consider_parallel =
- is_parallel_safe(root, parse->jointree->quals);
-
- /* The only path for it is a trivial Result path */
- add_path(final_rel, (Path *)
- create_result_path(root, final_rel,
- final_rel->reltarget,
- (List *) parse->jointree->quals));
-
- /* Select cheapest path (pretty easy in this case...) */
- set_cheapest(final_rel);
-
- /*
- * We still are required to call qp_callback, in case it's something
- * like "SELECT 2+2 ORDER BY 1".
- */
- root->canon_pathkeys = NIL;
- (*qp_callback) (root, qp_extra);
-
- return final_rel;
- }
-
- /*
* Init planner lists to empty.
*
* NOTE: append_rel_list was set up by subquery_planner, so do not touch
@@ -125,6 +87,71 @@ query_planner(PlannerInfo *root, List *tlist,
setup_simple_rel_arrays(root);
/*
+ * In the trivial case where the jointree is a single RTE_RESULT relation,
+ * bypass all the rest of this function and just make a RelOptInfo and its
+ * one access path. This is worth optimizing because it applies for
+ * common cases like "SELECT expression" and "INSERT ... VALUES()".
+ */
+ Assert(parse->jointree->fromlist != NIL);
+ if (list_length(parse->jointree->fromlist) == 1)
+ {
+ Node *jtnode = (Node *) linitial(parse->jointree->fromlist);
+
+ if (IsA(jtnode, RangeTblRef))
+ {
+ int varno = ((RangeTblRef *) jtnode)->rtindex;
+ RangeTblEntry *rte = root->simple_rte_array[varno];
+
+ Assert(rte != NULL);
+ if (rte->rtekind == RTE_RESULT)
+ {
+ /* Make the RelOptInfo for it directly */
+ final_rel = build_simple_rel(root, varno, NULL);
+
+ /*
+ * If query allows parallelism in general, check whether the
+ * quals are parallel-restricted. (We need not check
+ * final_rel->reltarget because it's empty at this point.
+ * Anything parallel-restricted in the query tlist will be
+ * dealt with later.) This is normally pretty silly, because
+ * a Result-only plan would never be interesting to
+ * parallelize. However, if force_parallel_mode is on, then
+ * we want to execute the Result in a parallel worker if
+ * possible, so we must do this.
+ */
+ if (root->glob->parallelModeOK &&
+ force_parallel_mode != FORCE_PARALLEL_OFF)
+ final_rel->consider_parallel =
+ is_parallel_safe(root, parse->jointree->quals);
+
+ /*
+ * The only path for it is a trivial Result path. We cheat a
+ * bit here by using a GroupResultPath, because that way we
+ * can just jam the quals into it without preprocessing them.
+ * (But, if you hold your head at the right angle, a FROM-less
+ * SELECT is a kind of degenerate-grouping case, so it's not
+ * that much of a cheat.)
+ */
+ add_path(final_rel, (Path *)
+ create_group_result_path(root, final_rel,
+ final_rel->reltarget,
+ (List *) parse->jointree->quals));
+
+ /* Select cheapest path (pretty easy in this case...) */
+ set_cheapest(final_rel);
+
+ /*
+ * We still are required to call qp_callback, in case it's
+ * something like "SELECT 2+2 ORDER BY 1".
+ */
+ (*qp_callback) (root, qp_extra);
+
+ return final_rel;
+ }
+ }
+ }
+
+ /*
* Populate append_rel_array with each AppendRelInfo to allow direct
* lookups by child relid.
*/