Commit 38db5fab authored by Tom Lane's avatar Tom Lane

Make inheritance planning logic a little simpler and clearer,

hopefully even a little faster.
parent 996659f2
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.84 2000/06/18 22:44:09 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.85 2000/06/20 04:22:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -94,7 +94,8 @@ planner(Query *parse) ...@@ -94,7 +94,8 @@ planner(Query *parse)
* Basically, this routine does the stuff that should only be done once * Basically, this routine does the stuff that should only be done once
* per Query object. It then calls union_planner, which may be called * per Query object. It then calls union_planner, which may be called
* recursively on the same Query node in order to handle UNIONs and/or * recursively on the same Query node in order to handle UNIONs and/or
* inheritance. subquery_planner is called recursively from subselect.c. * inheritance. subquery_planner is called recursively from subselect.c
* to handle sub-Query nodes found within the query's expressions.
* *
* prepunion.c uses an unholy combination of calling union_planner when * prepunion.c uses an unholy combination of calling union_planner when
* recursing on the primary Query node, or subquery_planner when recursing * recursing on the primary Query node, or subquery_planner when recursing
...@@ -107,10 +108,6 @@ planner(Query *parse) ...@@ -107,10 +108,6 @@ planner(Query *parse)
Plan * Plan *
subquery_planner(Query *parse, double tuple_fraction) subquery_planner(Query *parse, double tuple_fraction)
{ {
List *l;
List *rangetable = parse->rtable;
RangeTblEntry *rangeTblEntry;
/* /*
* A HAVING clause without aggregates is equivalent to a WHERE clause * A HAVING clause without aggregates is equivalent to a WHERE clause
* (except it can only refer to grouped fields). If there are no aggs * (except it can only refer to grouped fields). If there are no aggs
...@@ -142,18 +139,6 @@ subquery_planner(Query *parse, double tuple_fraction) ...@@ -142,18 +139,6 @@ subquery_planner(Query *parse, double tuple_fraction)
parse->qual = eval_const_expressions(parse->qual); parse->qual = eval_const_expressions(parse->qual);
parse->havingQual = eval_const_expressions(parse->havingQual); parse->havingQual = eval_const_expressions(parse->havingQual);
/*
* If the query is going to look for subclasses, but no subclasses
* actually exist, then we can optimise away the union that would
* otherwise happen and thus save some time.
*/
foreach(l, rangetable)
{
rangeTblEntry = (RangeTblEntry *)lfirst(l);
if (rangeTblEntry->inh && !has_subclass(rangeTblEntry->relid))
rangeTblEntry->inh = FALSE;
}
/* /*
* Canonicalize the qual, and convert it to implicit-AND format. * Canonicalize the qual, and convert it to implicit-AND format.
* *
...@@ -257,10 +242,11 @@ union_planner(Query *parse, ...@@ -257,10 +242,11 @@ union_planner(Query *parse,
List *group_pathkeys; List *group_pathkeys;
List *sort_pathkeys; List *sort_pathkeys;
Index rt_index; Index rt_index;
List *inheritors;
if (parse->unionClause) if (parse->unionClause)
{ {
result_plan = (Plan *) plan_union_queries(parse); result_plan = plan_union_queries(parse);
/* XXX do we need to do this? bjm 12/19/97 */ /* XXX do we need to do this? bjm 12/19/97 */
tlist = preprocess_targetlist(tlist, tlist = preprocess_targetlist(tlist,
parse->commandType, parse->commandType,
...@@ -269,9 +255,8 @@ union_planner(Query *parse, ...@@ -269,9 +255,8 @@ union_planner(Query *parse,
/* /*
* We leave current_pathkeys NIL indicating we do not know sort * We leave current_pathkeys NIL indicating we do not know sort
* order. Actually, for a normal UNION we have done an explicit * order. This is correct for the appended-together subplan
* sort; ought to change interface to plan_union_queries to pass * results, even if the subplans themselves produced sorted results.
* that info back!
*/ */
/* /*
...@@ -283,7 +268,8 @@ union_planner(Query *parse, ...@@ -283,7 +268,8 @@ union_planner(Query *parse,
sort_pathkeys = make_pathkeys_for_sortclauses(parse->sortClause, sort_pathkeys = make_pathkeys_for_sortclauses(parse->sortClause,
tlist); tlist);
} }
else if ((rt_index = first_inherit_rt_entry(rangetable)) != -1) else if (find_inheritable_rt_entry(rangetable,
&rt_index, &inheritors))
{ {
List *sub_tlist; List *sub_tlist;
...@@ -296,8 +282,8 @@ union_planner(Query *parse, ...@@ -296,8 +282,8 @@ union_planner(Query *parse,
/* /*
* Recursively plan the subqueries needed for inheritance * Recursively plan the subqueries needed for inheritance
*/ */
result_plan = (Plan *) plan_inherit_queries(parse, sub_tlist, result_plan = plan_inherit_queries(parse, sub_tlist,
rt_index); rt_index, inheritors);
/* /*
* Fix up outer target list. NOTE: unlike the case for * Fix up outer target list. NOTE: unlike the case for
......
This diff is collapsed.
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.57 2000/06/17 21:48:51 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.58 2000/06/20 04:22:14 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -261,6 +261,11 @@ join_selectivity(Oid functionObjectId, ...@@ -261,6 +261,11 @@ join_selectivity(Oid functionObjectId,
* *
* Returns an integer list containing the OIDs of all relations which * Returns an integer list containing the OIDs of all relations which
* inherit *directly* from the relation with OID 'inhparent'. * inherit *directly* from the relation with OID 'inhparent'.
*
* XXX might be a good idea to create an index on pg_inherits' inhparent
* field, so that we can use an indexscan instead of sequential scan here.
* However, in typical databases pg_inherits won't have enough entries to
* justify an indexscan...
*/ */
List * List *
find_inheritance_children(Oid inhparent) find_inheritance_children(Oid inhparent)
...@@ -269,12 +274,19 @@ find_inheritance_children(Oid inhparent) ...@@ -269,12 +274,19 @@ find_inheritance_children(Oid inhparent)
{0, Anum_pg_inherits_inhparent, F_OIDEQ} {0, Anum_pg_inherits_inhparent, F_OIDEQ}
}; };
HeapTuple inheritsTuple; List *list = NIL;
Relation relation; Relation relation;
HeapScanDesc scan; HeapScanDesc scan;
List *list = NIL; HeapTuple inheritsTuple;
Oid inhrelid; Oid inhrelid;
/*
* Can skip the scan if pg_class shows the relation has never had
* a subclass.
*/
if (! has_subclass(inhparent))
return NIL;
fmgr_info(F_OIDEQ, &key[0].sk_func); fmgr_info(F_OIDEQ, &key[0].sk_func);
key[0].sk_nargs = key[0].sk_func.fn_nargs; key[0].sk_nargs = key[0].sk_func.fn_nargs;
key[0].sk_argument = ObjectIdGetDatum(inhparent); key[0].sk_argument = ObjectIdGetDatum(inhparent);
...@@ -292,14 +304,16 @@ find_inheritance_children(Oid inhparent) ...@@ -292,14 +304,16 @@ find_inheritance_children(Oid inhparent)
} }
/* /*
* has_subclass - * has_subclass
*
* In the current implementation, has_subclass returns whether a * In the current implementation, has_subclass returns whether a
* particular class *might* have a subclass. It will not return the * particular class *might* have a subclass. It will not return the
* correct result if a class had a subclass which was later dropped. * correct result if a class had a subclass which was later dropped.
* This is because relhassubclass in pg_class is not updated, * This is because relhassubclass in pg_class is not updated when a
* possibly because of efficiency and/or concurrency concerns. * subclass is dropped, primarily because of concurrency concerns.
* Currently has_subclass is only used as an efficiency hack, so this *
* is ok. * Currently has_subclass is only used as an efficiency hack to skip
* unnecessary inheritance searches, so this is OK.
*/ */
bool bool
has_subclass(Oid relationId) has_subclass(Oid relationId)
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: prep.h,v 1.22 2000/06/08 22:37:51 momjian Exp $ * $Id: prep.h,v 1.23 2000/06/20 04:22:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -33,8 +33,10 @@ extern List *preprocess_targetlist(List *tlist, int command_type, ...@@ -33,8 +33,10 @@ extern List *preprocess_targetlist(List *tlist, int command_type,
* prototypes for prepunion.c * prototypes for prepunion.c
*/ */
extern List *find_all_inheritors(Oid parentrel); extern List *find_all_inheritors(Oid parentrel);
extern int first_inherit_rt_entry(List *rangetable); extern bool find_inheritable_rt_entry(List *rangetable,
extern Append *plan_union_queries(Query *parse); Index *rt_index, List **inheritors);
extern Append *plan_inherit_queries(Query *parse, List *tlist, Index rt_index); extern Plan *plan_inherit_queries(Query *root, List *tlist,
Index rt_index, List *inheritors);
extern Plan *plan_union_queries(Query *parse);
#endif /* PREP_H */ #endif /* PREP_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment