Skip to content

Commit 635d42e

Browse files
committed
Fix inheritance_planner() to delete dummy subplans from its Append plan
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.
1 parent 1d28bf2 commit 635d42e

File tree

1 file changed

+62
-14
lines changed

1 file changed

+62
-14
lines changed

src/backend/optimizer/plan/planner.c

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
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);
5858
static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode);
5959
static Plan *inheritance_planner(PlannerInfo *root);
6060
static Plan *grouping_planner(PlannerInfo *root, double tuple_fraction);
61+
static bool is_dummy_plan(Plan *plan);
6162
static 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

Comments
 (0)