88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.206 2006/08/02 01:59:46 joe Exp $
11+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.207 2006/08/05 17:21:52 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -58,6 +58,7 @@ static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
5858static void preprocess_qual_conditions (PlannerInfo * root , Node * jtnode );
5959static Plan * inheritance_planner (PlannerInfo * root );
6060static Plan * grouping_planner (PlannerInfo * root , double tuple_fraction );
61+ static bool is_dummy_plan (Plan * plan );
6162static double preprocess_limit (PlannerInfo * root ,
6263 double tuple_fraction ,
6364 int64 * offset_est , int64 * count_est );
@@ -553,12 +554,11 @@ inheritance_planner(PlannerInfo *root)
553554 Query * parse = root -> parse ;
554555 int parentRTindex = parse -> resultRelation ;
555556 List * subplans = NIL ;
557+ List * rtable = NIL ;
556558 List * tlist = NIL ;
557559 PlannerInfo subroot ;
558560 ListCell * l ;
559561
560- subroot .parse = NULL ; /* catch it if no matches in loop */
561-
562562 parse -> resultRelations = NIL ;
563563
564564 foreach (l , root -> append_rel_list )
@@ -570,10 +570,6 @@ inheritance_planner(PlannerInfo *root)
570570 if (appinfo -> parent_relid != parentRTindex )
571571 continue ;
572572
573- /* Build target-relations list for the executor */
574- parse -> resultRelations = lappend_int (parse -> resultRelations ,
575- appinfo -> child_relid );
576-
577573 /*
578574 * Generate modified query with this rel as target. We have to be
579575 * prepared to translate varnos in in_info_list as well as in the
@@ -592,13 +588,39 @@ inheritance_planner(PlannerInfo *root)
592588 /* Generate plan */
593589 subplan = grouping_planner (& subroot , 0.0 /* retrieve all tuples */ );
594590
595- subplans = lappend (subplans , subplan );
591+ /*
592+ * If this child rel was excluded by constraint exclusion, exclude
593+ * it from the plan.
594+ */
595+ if (is_dummy_plan (subplan ))
596+ continue ;
596597
597- /* Save preprocessed tlist from first rel for use in Append */
598- if (tlist == NIL )
598+ /* Save rtable and tlist from first rel for use below */
599+ if (subplans == NIL )
600+ {
601+ rtable = subroot .parse -> rtable ;
599602 tlist = subplan -> targetlist ;
603+ }
604+
605+ subplans = lappend (subplans , subplan );
606+
607+ /* Build target-relations list for the executor */
608+ parse -> resultRelations = lappend_int (parse -> resultRelations ,
609+ appinfo -> child_relid );
600610 }
601611
612+ /* Mark result as unordered (probably unnecessary) */
613+ root -> query_pathkeys = NIL ;
614+
615+ /*
616+ * If we managed to exclude every child rel, return a dummy plan
617+ */
618+ if (subplans == NIL )
619+ return (Plan * ) make_result (tlist ,
620+ (Node * ) list_make1 (makeBoolConst (false,
621+ false)),
622+ NULL );
623+
602624 /*
603625 * Planning might have modified the rangetable, due to changes of the
604626 * Query structures inside subquery RTEs. We have to ensure that this
@@ -610,10 +632,7 @@ inheritance_planner(PlannerInfo *root)
610632 *
611633 * XXX should clean this up someday
612634 */
613- parse -> rtable = subroot .parse -> rtable ;
614-
615- /* Mark result as unordered (probably unnecessary) */
616- root -> query_pathkeys = NIL ;
635+ parse -> rtable = rtable ;
617636
618637 return (Plan * ) make_append (subplans , true, tlist );
619638}
@@ -1072,6 +1091,35 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
10721091 return result_plan ;
10731092}
10741093
1094+ /*
1095+ * Detect whether a plan node is a "dummy" plan created when a relation
1096+ * is deemed not to need scanning due to constraint exclusion.
1097+ *
1098+ * Currently, such dummy plans are Result nodes with constant FALSE
1099+ * filter quals.
1100+ */
1101+ static bool
1102+ is_dummy_plan (Plan * plan )
1103+ {
1104+ if (IsA (plan , Result ))
1105+ {
1106+ List * rcqual = (List * ) ((Result * ) plan )-> resconstantqual ;
1107+
1108+ if (list_length (rcqual ) == 1 )
1109+ {
1110+ Const * constqual = (Const * ) linitial (rcqual );
1111+
1112+ if (constqual && IsA (constqual , Const ))
1113+ {
1114+ if (!constqual -> constisnull &&
1115+ !DatumGetBool (constqual -> constvalue ))
1116+ return true;
1117+ }
1118+ }
1119+ }
1120+ return false;
1121+ }
1122+
10751123/*
10761124 * preprocess_limit - do pre-estimation for LIMIT and/or OFFSET clauses
10771125 *
0 commit comments