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 @@
*
*
* 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)
* Basically, this routine does the stuff that should only be done once
* 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
* 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
* recursing on the primary Query node, or subquery_planner when recursing
......@@ -107,10 +108,6 @@ planner(Query *parse)
Plan *
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
* (except it can only refer to grouped fields). If there are no aggs
......@@ -142,18 +139,6 @@ subquery_planner(Query *parse, double tuple_fraction)
parse->qual = eval_const_expressions(parse->qual);
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.
*
......@@ -257,10 +242,11 @@ union_planner(Query *parse,
List *group_pathkeys;
List *sort_pathkeys;
Index rt_index;
List *inheritors;
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 */
tlist = preprocess_targetlist(tlist,
parse->commandType,
......@@ -269,9 +255,8 @@ union_planner(Query *parse,
/*
* We leave current_pathkeys NIL indicating we do not know sort
* order. Actually, for a normal UNION we have done an explicit
* sort; ought to change interface to plan_union_queries to pass
* that info back!
* order. This is correct for the appended-together subplan
* results, even if the subplans themselves produced sorted results.
*/
/*
......@@ -283,7 +268,8 @@ union_planner(Query *parse,
sort_pathkeys = make_pathkeys_for_sortclauses(parse->sortClause,
tlist);
}
else if ((rt_index = first_inherit_rt_entry(rangetable)) != -1)
else if (find_inheritable_rt_entry(rangetable,
&rt_index, &inheritors))
{
List *sub_tlist;
......@@ -296,8 +282,8 @@ union_planner(Query *parse,
/*
* Recursively plan the subqueries needed for inheritance
*/
result_plan = (Plan *) plan_inherit_queries(parse, sub_tlist,
rt_index);
result_plan = plan_inherit_queries(parse, sub_tlist,
rt_index, inheritors);
/*
* Fix up outer target list. NOTE: unlike the case for
......
This diff is collapsed.
......@@ -9,7 +9,7 @@
*
*
* 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,
*
* Returns an integer list containing the OIDs of all relations which
* 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 *
find_inheritance_children(Oid inhparent)
......@@ -269,12 +274,19 @@ find_inheritance_children(Oid inhparent)
{0, Anum_pg_inherits_inhparent, F_OIDEQ}
};
HeapTuple inheritsTuple;
List *list = NIL;
Relation relation;
HeapScanDesc scan;
List *list = NIL;
HeapTuple inheritsTuple;
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);
key[0].sk_nargs = key[0].sk_func.fn_nargs;
key[0].sk_argument = ObjectIdGetDatum(inhparent);
......@@ -292,14 +304,16 @@ find_inheritance_children(Oid inhparent)
}
/*
* has_subclass -
* has_subclass
*
* In the current implementation, has_subclass returns whether a
* particular class *might* have a subclass. It will not return the
* correct result if a class had a subclass which was later dropped.
* This is because relhassubclass in pg_class is not updated,
* possibly because of efficiency and/or concurrency concerns.
* Currently has_subclass is only used as an efficiency hack, so this
* is ok.
* This is because relhassubclass in pg_class is not updated when a
* subclass is dropped, primarily because of concurrency concerns.
*
* Currently has_subclass is only used as an efficiency hack to skip
* unnecessary inheritance searches, so this is OK.
*/
bool
has_subclass(Oid relationId)
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* 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,
* prototypes for prepunion.c
*/
extern List *find_all_inheritors(Oid parentrel);
extern int first_inherit_rt_entry(List *rangetable);
extern Append *plan_union_queries(Query *parse);
extern Append *plan_inherit_queries(Query *parse, List *tlist, Index rt_index);
extern bool find_inheritable_rt_entry(List *rangetable,
Index *rt_index, List **inheritors);
extern Plan *plan_inherit_queries(Query *root, List *tlist,
Index rt_index, List *inheritors);
extern Plan *plan_union_queries(Query *parse);
#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