]> granicus.if.org Git - postgresql/blobdiff - src/backend/optimizer/plan/planner.c
Turn the rangetable used by the executor into a flat list, and avoid storing
[postgresql] / src / backend / optimizer / plan / planner.c
index f4a940175ea5c89c08ed9c8bd2e703072fcd585a..b45288dc5b8faafe9a827aacb56fbcccd69c6a0c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.213 2007/02/19 07:03:29 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.215 2007/02/22 22:00:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -79,13 +79,17 @@ static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist);
  *        Query optimizer entry point
  *
  *****************************************************************************/
-Plan *
+PlannedStmt *
 planner(Query *parse, bool isCursor, int cursorOptions,
                ParamListInfo boundParams)
 {
+       PlannedStmt *result;
        PlannerGlobal *glob;
        double          tuple_fraction;
-       Plan       *result_plan;
+       PlannerInfo *root;
+       Plan       *top_plan;
+       ListCell   *lp,
+                          *lr;
 
        /*
         * Set up global state for this planner invocation.  This data is needed
@@ -97,7 +101,9 @@ planner(Query *parse, bool isCursor, int cursorOptions,
 
        glob->boundParams = boundParams;
        glob->paramlist = NIL;
-       glob->next_plan_id = 0;
+       glob->subplans = NIL;
+       glob->subrtables = NIL;
+       glob->finalrtable = NIL;
 
        /* Determine what fraction of the plan is likely to be scanned */
        if (isCursor)
@@ -117,7 +123,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
        }
 
        /* primary planning entry point (may recurse for subqueries) */
-       result_plan = subquery_planner(glob, parse, 1, tuple_fraction, NULL);
+       top_plan = subquery_planner(glob, parse, 1, tuple_fraction, &root);
 
        /*
         * If creating a plan for a scrollable cursor, make sure it can run
@@ -125,17 +131,38 @@ planner(Query *parse, bool isCursor, int cursorOptions,
         */
        if (isCursor && (cursorOptions & CURSOR_OPT_SCROLL))
        {
-               if (!ExecSupportsBackwardScan(result_plan))
-                       result_plan = materialize_finished_plan(result_plan);
+               if (!ExecSupportsBackwardScan(top_plan))
+                       top_plan = materialize_finished_plan(top_plan);
        }
 
        /* final cleanup of the plan */
-       result_plan = set_plan_references(result_plan, parse->rtable);
+       Assert(glob->finalrtable == NIL);
+       top_plan = set_plan_references(glob, top_plan, root->parse->rtable);
+       /* ... and the subplans (both regular subplans and initplans) */
+       Assert(list_length(glob->subplans) == list_length(glob->subrtables));
+       forboth(lp, glob->subplans, lr, glob->subrtables)
+       {
+               Plan   *subplan = (Plan *) lfirst(lp);
+               List   *subrtable = (List *) lfirst(lr);
 
-       /* executor wants to know total number of Params used overall */
-       result_plan->nParamExec = list_length(glob->paramlist);
+               lfirst(lp) = set_plan_references(glob, subplan, subrtable);
+       }
 
-       return result_plan;
+       /* build the PlannedStmt result */
+       result = makeNode(PlannedStmt);
+
+       result->commandType = parse->commandType;
+       result->canSetTag = parse->canSetTag;
+       result->planTree = top_plan;
+       result->rtable = glob->finalrtable;
+       result->resultRelations = root->resultRelations;
+       result->into = parse->into;
+       result->subplans = glob->subplans;
+       result->returningLists = root->returningLists;
+       result->rowMarks = parse->rowMarks;
+       result->nParamExec = list_length(glob->paramlist);
+
+       return result;
 }
 
 
@@ -150,8 +177,8 @@ planner(Query *parse, bool isCursor, int cursorOptions,
  * tuple_fraction is the fraction of tuples we expect will be retrieved.
  * tuple_fraction is interpreted as explained for grouping_planner, below.
  *
- * If subquery_pathkeys isn't NULL, it receives a list of pathkeys indicating
- * the output sort ordering of the completed plan.
+ * If subroot isn't NULL, we pass back the query's final PlannerInfo struct;
+ * among other things this tells the output sort ordering of the plan.
  *
  * Basically, this routine does the stuff that should only be done once
  * per Query object.  It then calls grouping_planner.  At one time,
@@ -168,9 +195,9 @@ planner(Query *parse, bool isCursor, int cursorOptions,
 Plan *
 subquery_planner(PlannerGlobal *glob, Query *parse,
                                 Index level, double tuple_fraction,
-                                List **subquery_pathkeys)
+                                PlannerInfo **subroot)
 {
-       int                     saved_plan_id = glob->next_plan_id;
+       int                     num_old_subplans = list_length(glob->subplans);
        PlannerInfo *root;
        Plan       *plan;
        List       *newHaving;
@@ -372,12 +399,13 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
         * initPlan list and extParam/allParam sets for plan nodes, and attach the
         * initPlans to the top plan node.
         */
-       if (root->glob->next_plan_id != saved_plan_id || root->query_level > 1)
+       if (list_length(glob->subplans) != num_old_subplans ||
+               root->query_level > 1)
                SS_finalize_plan(root, plan);
 
-       /* Return sort ordering info if caller wants it */
-       if (subquery_pathkeys)
-               *subquery_pathkeys = root->query_pathkeys;
+       /* Return internal info if caller wants it */
+       if (subroot)
+               *subroot = root;
 
        return plan;
 }
@@ -593,14 +621,14 @@ inheritance_planner(PlannerInfo *root)
                /* Build list of per-relation RETURNING targetlists */
                if (parse->returningList)
                {
-                       Assert(list_length(subroot.parse->returningLists) == 1);
+                       Assert(list_length(subroot.returningLists) == 1);
                        returningLists = list_concat(returningLists,
-                                                                                subroot.parse->returningLists);
+                                                                                subroot.returningLists);
                }
        }
 
-       parse->resultRelations = resultRelations;
-       parse->returningLists = returningLists;
+       root->resultRelations = resultRelations;
+       root->returningLists = returningLists;
 
        /* Mark result as unordered (probably unnecessary) */
        root->query_pathkeys = NIL;
@@ -609,7 +637,8 @@ inheritance_planner(PlannerInfo *root)
         * If we managed to exclude every child rel, return a dummy plan
         */
        if (subplans == NIL)
-               return (Plan *) make_result(tlist,
+               return (Plan *) make_result(root,
+                                                                       tlist,
                                                                        (Node *) list_make1(makeBoolConst(false,
                                                                                                                                          false)),
                                                                        NULL);
@@ -627,6 +656,10 @@ inheritance_planner(PlannerInfo *root)
         */
        parse->rtable = rtable;
 
+       /* Suppress Append if there's only one surviving child rel */
+       if (list_length(subplans) == 1)
+               return (Plan *) linitial(subplans);
+
        return (Plan *) make_append(subplans, true, tlist);
 }
 
@@ -885,7 +918,9 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
                                 */
                                if (!is_projection_capable_plan(result_plan))
                                {
-                                       result_plan = (Plan *) make_result(sub_tlist, NULL,
+                                       result_plan = (Plan *) make_result(root,
+                                                                                                          sub_tlist,
+                                                                                                          NULL,
                                                                                                           result_plan);
                                }
                                else
@@ -916,7 +951,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
                                 * tuples) --- so make_agg() and make_group() are responsible
                                 * for computing the added cost.
                                 */
-                               cost_qual_eval(&tlist_cost, sub_tlist);
+                               cost_qual_eval(&tlist_cost, sub_tlist, root);
                                result_plan->startup_cost += tlist_cost.startup;
                                result_plan->total_cost += tlist_cost.startup +
                                        tlist_cost.per_tuple * result_plan->plan_rows;
@@ -1039,7 +1074,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
                                 * this routine to avoid having to generate the plan in the
                                 * first place.
                                 */
-                               result_plan = (Plan *) make_result(tlist,
+                               result_plan = (Plan *) make_result(root,
+                                                                                                  tlist,
                                                                                                   parse->havingQual,
                                                                                                   NULL);
                        }
@@ -1098,11 +1134,20 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
        {
                List       *rlist;
 
+               Assert(parse->resultRelation);
                rlist = set_returning_clause_references(parse->returningList,
                                                                                                result_plan,
                                                                                                parse->resultRelation);
-               parse->returningLists = list_make1(rlist);
+               root->returningLists = list_make1(rlist);
        }
+       else
+               root->returningLists = NIL;
+
+       /* Compute result-relations list if needed */
+       if (parse->resultRelation)
+               root->resultRelations = list_make1_int(parse->resultRelation);
+       else
+               root->resultRelations = NIL;
 
        /*
         * Return the actual output ordering in query_pathkeys for possible use by
@@ -1524,7 +1569,7 @@ choose_hashed_grouping(PlannerInfo *root, double tuple_fraction,
  * pass down only c,d,a+b, but it's not really worth the trouble to
  * eliminate simple var references from the subplan.  We will avoid doing
  * the extra computation to recompute a+b at the outer level; see
- * replace_vars_with_subplan_refs() in setrefs.c.)
+ * fix_upper_expr() in setrefs.c.)
  *
  * If we are grouping or aggregating, *and* there are no non-Var grouping
  * expressions, then the returned tlist is effectively dummy; we do not