8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -58,6 +58,7 @@ static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
58
58
static void preprocess_qual_conditions (PlannerInfo * root , Node * jtnode );
59
59
static Plan * inheritance_planner (PlannerInfo * root );
60
60
static Plan * grouping_planner (PlannerInfo * root , double tuple_fraction );
61
+ static bool is_dummy_plan (Plan * plan );
61
62
static double preprocess_limit (PlannerInfo * root ,
62
63
double tuple_fraction ,
63
64
int64 * offset_est , int64 * count_est );
@@ -553,12 +554,11 @@ inheritance_planner(PlannerInfo *root)
553
554
Query * parse = root -> parse ;
554
555
int parentRTindex = parse -> resultRelation ;
555
556
List * subplans = NIL ;
557
+ List * rtable = NIL ;
556
558
List * tlist = NIL ;
557
559
PlannerInfo subroot ;
558
560
ListCell * l ;
559
561
560
- subroot .parse = NULL ; /* catch it if no matches in loop */
561
-
562
562
parse -> resultRelations = NIL ;
563
563
564
564
foreach (l , root -> append_rel_list )
@@ -570,10 +570,6 @@ inheritance_planner(PlannerInfo *root)
570
570
if (appinfo -> parent_relid != parentRTindex )
571
571
continue ;
572
572
573
- /* Build target-relations list for the executor */
574
- parse -> resultRelations = lappend_int (parse -> resultRelations ,
575
- appinfo -> child_relid );
576
-
577
573
/*
578
574
* Generate modified query with this rel as target. We have to be
579
575
* prepared to translate varnos in in_info_list as well as in the
@@ -592,13 +588,39 @@ inheritance_planner(PlannerInfo *root)
592
588
/* Generate plan */
593
589
subplan = grouping_planner (& subroot , 0.0 /* retrieve all tuples */ );
594
590
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 ;
596
597
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 ;
599
602
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 );
600
610
}
601
611
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
+
602
624
/*
603
625
* Planning might have modified the rangetable, due to changes of the
604
626
* Query structures inside subquery RTEs. We have to ensure that this
@@ -610,10 +632,7 @@ inheritance_planner(PlannerInfo *root)
610
632
*
611
633
* XXX should clean this up someday
612
634
*/
613
- parse -> rtable = subroot .parse -> rtable ;
614
-
615
- /* Mark result as unordered (probably unnecessary) */
616
- root -> query_pathkeys = NIL ;
635
+ parse -> rtable = rtable ;
617
636
618
637
return (Plan * ) make_append (subplans , true, tlist );
619
638
}
@@ -1072,6 +1091,35 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
1072
1091
return result_plan ;
1073
1092
}
1074
1093
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
+
1075
1123
/*
1076
1124
* preprocess_limit - do pre-estimation for LIMIT and/or OFFSET clauses
1077
1125
*
0 commit comments