1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-26 01:22:12 +03:00

Do some minor code refactoring in preparation for changing the APIs of

find_inheritance_children() and find_all_inheritors().  I got annoyed that
these are buried inside the planner but mostly used elsewhere.  So, create
a new file catalog/pg_inherits.c and put them there, along with a couple
of other functions that search pg_inherits.

The code that modifies pg_inherits is (still) in tablecmds.c --- it's
kind of entangled with unrelated code that modifies pg_depend and other
stuff, so pulling it out seemed like a bigger change than I wanted to make
right now.  But this file provides a natural home for it if anyone ever
gets around to that.

This commit just moves code around; it doesn't change anything, except
I succumbed to the temptation to make a couple of trivial optimizations
in typeInheritsFrom().
This commit is contained in:
Tom Lane
2009-05-12 00:56:05 +00:00
parent 6480c143ee
commit 0ada559187
12 changed files with 282 additions and 242 deletions

View File

@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.168 2009/03/31 22:12:48 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.169 2009/05/12 00:56:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -32,6 +32,7 @@
#include "access/heapam.h"
#include "access/sysattr.h"
#include "catalog/namespace.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
@ -39,7 +40,6 @@
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "optimizer/plancat.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
#include "optimizer/prep.h"
@ -1081,47 +1081,6 @@ generate_setop_grouplist(SetOperationStmt *op, List *targetlist)
}
/*
* find_all_inheritors -
* Returns a list of relation OIDs including the given rel plus
* all relations that inherit from it, directly or indirectly.
*/
List *
find_all_inheritors(Oid parentrel)
{
List *rels_list;
ListCell *l;
/*
* We build a list starting with the given rel and adding all direct and
* indirect children. We can use a single list as both the record of
* already-found rels and the agenda of rels yet to be scanned for more
* children. This is a bit tricky but works because the foreach() macro
* doesn't fetch the next list element until the bottom of the loop.
*/
rels_list = list_make1_oid(parentrel);
foreach(l, rels_list)
{
Oid currentrel = lfirst_oid(l);
List *currentchildren;
/* Get the direct children of this rel */
currentchildren = find_inheritance_children(currentrel);
/*
* Add to the queue only those children not already seen. This avoids
* making duplicate entries in case of multiple inheritance paths from
* the same parent. (It'll also keep us from getting into an infinite
* loop, though theoretically there can't be any cycles in the
* inheritance graph anyway.)
*/
rels_list = list_concat_unique_oid(rels_list, currentchildren);
}
return rels_list;
}
/*
* expand_inherited_tables
* Expand each rangetable entry that represents an inheritance set

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.156 2009/03/05 23:06:45 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.157 2009/05/12 00:56:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -22,7 +22,6 @@
#include "access/sysattr.h"
#include "access/transam.h"
#include "catalog/catalog.h"
#include "catalog/pg_inherits.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
@ -35,12 +34,9 @@
#include "parser/parsetree.h"
#include "rewrite/rewriteManip.h"
#include "storage/bufmgr.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
/* GUC parameter */
@ -850,79 +846,6 @@ join_selectivity(PlannerInfo *root,
return (Selectivity) result;
}
/*
* find_inheritance_children
*
* Returns a 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)
{
List *list = NIL;
Relation relation;
HeapScanDesc scan;
HeapTuple inheritsTuple;
Oid inhrelid;
ScanKeyData key[1];
/*
* Can skip the scan if pg_class shows the relation has never had a
* subclass.
*/
if (!has_subclass(inhparent))
return NIL;
ScanKeyInit(&key[0],
Anum_pg_inherits_inhparent,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(inhparent));
relation = heap_open(InheritsRelationId, AccessShareLock);
scan = heap_beginscan(relation, SnapshotNow, 1, key);
while ((inheritsTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid;
list = lappend_oid(list, inhrelid);
}
heap_endscan(scan);
heap_close(relation, AccessShareLock);
return list;
}
/*
* 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 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)
{
HeapTuple tuple;
bool result;
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(relationId),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u", relationId);
result = ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass;
ReleaseSysCache(tuple);
return result;
}
/*
* has_unique_index
*