mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
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.
This commit is contained in:
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode);
|
||||||
static Plan *inheritance_planner(PlannerInfo *root);
|
static Plan *inheritance_planner(PlannerInfo *root);
|
||||||
static Plan *grouping_planner(PlannerInfo *root, double tuple_fraction);
|
static Plan *grouping_planner(PlannerInfo *root, double tuple_fraction);
|
||||||
|
static bool is_dummy_plan(Plan *plan);
|
||||||
static double preprocess_limit(PlannerInfo *root,
|
static double preprocess_limit(PlannerInfo *root,
|
||||||
double tuple_fraction,
|
double tuple_fraction,
|
||||||
int64 *offset_est, int64 *count_est);
|
int64 *offset_est, int64 *count_est);
|
||||||
@ -553,12 +554,11 @@ inheritance_planner(PlannerInfo *root)
|
|||||||
Query *parse = root->parse;
|
Query *parse = root->parse;
|
||||||
int parentRTindex = parse->resultRelation;
|
int parentRTindex = parse->resultRelation;
|
||||||
List *subplans = NIL;
|
List *subplans = NIL;
|
||||||
|
List *rtable = NIL;
|
||||||
List *tlist = NIL;
|
List *tlist = NIL;
|
||||||
PlannerInfo subroot;
|
PlannerInfo subroot;
|
||||||
ListCell *l;
|
ListCell *l;
|
||||||
|
|
||||||
subroot.parse = NULL; /* catch it if no matches in loop */
|
|
||||||
|
|
||||||
parse->resultRelations = NIL;
|
parse->resultRelations = NIL;
|
||||||
|
|
||||||
foreach(l, root->append_rel_list)
|
foreach(l, root->append_rel_list)
|
||||||
@ -570,10 +570,6 @@ inheritance_planner(PlannerInfo *root)
|
|||||||
if (appinfo->parent_relid != parentRTindex)
|
if (appinfo->parent_relid != parentRTindex)
|
||||||
continue;
|
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
|
* 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
|
* prepared to translate varnos in in_info_list as well as in the
|
||||||
@ -592,13 +588,39 @@ inheritance_planner(PlannerInfo *root)
|
|||||||
/* Generate plan */
|
/* Generate plan */
|
||||||
subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ );
|
subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this child rel was excluded by constraint exclusion, exclude
|
||||||
|
* it from the plan.
|
||||||
|
*/
|
||||||
|
if (is_dummy_plan(subplan))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Save rtable and tlist from first rel for use below */
|
||||||
|
if (subplans == NIL)
|
||||||
|
{
|
||||||
|
rtable = subroot.parse->rtable;
|
||||||
|
tlist = subplan->targetlist;
|
||||||
|
}
|
||||||
|
|
||||||
subplans = lappend(subplans, subplan);
|
subplans = lappend(subplans, subplan);
|
||||||
|
|
||||||
/* Save preprocessed tlist from first rel for use in Append */
|
/* Build target-relations list for the executor */
|
||||||
if (tlist == NIL)
|
parse->resultRelations = lappend_int(parse->resultRelations,
|
||||||
tlist = subplan->targetlist;
|
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
|
* Planning might have modified the rangetable, due to changes of the
|
||||||
* Query structures inside subquery RTEs. We have to ensure that this
|
* 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
|
* XXX should clean this up someday
|
||||||
*/
|
*/
|
||||||
parse->rtable = subroot.parse->rtable;
|
parse->rtable = rtable;
|
||||||
|
|
||||||
/* Mark result as unordered (probably unnecessary) */
|
|
||||||
root->query_pathkeys = NIL;
|
|
||||||
|
|
||||||
return (Plan *) make_append(subplans, true, tlist);
|
return (Plan *) make_append(subplans, true, tlist);
|
||||||
}
|
}
|
||||||
@ -1072,6 +1091,35 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
|
|||||||
return result_plan;
|
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
|
* preprocess_limit - do pre-estimation for LIMIT and/or OFFSET clauses
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user