]> granicus.if.org Git - postgresql/commitdiff
Fix inheritance_planner() to delete dummy subplans from its Append plan
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 5 Aug 2006 17:21:52 +0000 (17:21 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 5 Aug 2006 17:21:52 +0000 (17:21 +0000)
list, when some of the child rels have been excluded by constraint
exclusion.  This doesn't save a huge amount of time but it'll save some,
and it makes the EXPLAIN output look saner.  We already did the
equivalent thing in set_append_rel_pathlist(), but not here.

src/backend/optimizer/plan/planner.c

index 42ae15cd4832fdc029dec3ccc5263f943dac43e3..0eeaff064ff4f1f25499436b544a687da7cc4f13 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.206 2006/08/02 01:59:46 joe Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.207 2006/08/05 17:21:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,6 +58,7 @@ static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
 static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode);
 static Plan *inheritance_planner(PlannerInfo *root);
 static Plan *grouping_planner(PlannerInfo *root, double tuple_fraction);
+static bool is_dummy_plan(Plan *plan);
 static double preprocess_limit(PlannerInfo *root,
                                 double tuple_fraction,
                                 int64 *offset_est, int64 *count_est);
@@ -553,12 +554,11 @@ inheritance_planner(PlannerInfo *root)
        Query      *parse = root->parse;
        int                     parentRTindex = parse->resultRelation;
        List       *subplans = NIL;
+       List       *rtable = NIL;
        List       *tlist = NIL;
        PlannerInfo subroot;
        ListCell   *l;
 
-       subroot.parse = NULL;           /* catch it if no matches in loop */
-
        parse->resultRelations = NIL;
 
        foreach(l, root->append_rel_list)
@@ -570,10 +570,6 @@ inheritance_planner(PlannerInfo *root)
                if (appinfo->parent_relid != parentRTindex)
                        continue;
 
-               /* Build target-relations list for the executor */
-               parse->resultRelations = lappend_int(parse->resultRelations,
-                                                                                        appinfo->child_relid);
-
                /*
                 * Generate modified query with this rel as target.  We have to be
                 * prepared to translate varnos in in_info_list as well as in the
@@ -592,13 +588,39 @@ inheritance_planner(PlannerInfo *root)
                /* Generate plan */
                subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ );
 
-               subplans = lappend(subplans, subplan);
+               /*
+                * If this child rel was excluded by constraint exclusion, exclude
+                * it from the plan.
+                */
+               if (is_dummy_plan(subplan))
+                       continue;
 
-               /* Save preprocessed tlist from first rel for use in Append */
-               if (tlist == NIL)
+               /* Save rtable and tlist from first rel for use below */
+               if (subplans == NIL)
+               {
+                       rtable = subroot.parse->rtable;
                        tlist = subplan->targetlist;
+               }
+
+               subplans = lappend(subplans, subplan);
+
+               /* Build target-relations list for the executor */
+               parse->resultRelations = lappend_int(parse->resultRelations,
+                                                                                        appinfo->child_relid);
        }
 
+       /* Mark result as unordered (probably unnecessary) */
+       root->query_pathkeys = NIL;
+
+       /*
+        * If we managed to exclude every child rel, return a dummy plan
+        */
+       if (subplans == NIL)
+               return (Plan *) make_result(tlist,
+                                                                       (Node *) list_make1(makeBoolConst(false,
+                                                                                                                                         false)),
+                                                                       NULL);
+
        /*
         * Planning might have modified the rangetable, due to changes of the
         * Query structures inside subquery RTEs.  We have to ensure that this
@@ -610,10 +632,7 @@ inheritance_planner(PlannerInfo *root)
         *
         * XXX should clean this up someday
         */
-       parse->rtable = subroot.parse->rtable;
-
-       /* Mark result as unordered (probably unnecessary) */
-       root->query_pathkeys = NIL;
+       parse->rtable = rtable;
 
        return (Plan *) make_append(subplans, true, tlist);
 }
@@ -1072,6 +1091,35 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
        return result_plan;
 }
 
+/*
+ * Detect whether a plan node is a "dummy" plan created when a relation
+ * is deemed not to need scanning due to constraint exclusion.
+ *
+ * Currently, such dummy plans are Result nodes with constant FALSE
+ * filter quals.
+ */
+static bool
+is_dummy_plan(Plan *plan)
+{
+       if (IsA(plan, Result))
+       {
+               List *rcqual = (List *) ((Result *) plan)->resconstantqual;
+
+               if (list_length(rcqual) == 1)
+               {
+                       Const *constqual = (Const *) linitial(rcqual);
+
+                       if (constqual && IsA(constqual, Const))
+                       {
+                               if (!constqual->constisnull &&
+                                       !DatumGetBool(constqual->constvalue))
+                                       return true;
+                       }
+               }
+       }
+       return false;
+}
+
 /*
  * preprocess_limit - do pre-estimation for LIMIT and/or OFFSET clauses
  *