Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0ada559

Browse files
committed
Do some minor code refactoring in preparation for changing the APIs of
find_inheritance_children() and find_all_inheritors(). I got annoyed thatthese are buried inside the planner but mostly used elsewhere. So, createa new file catalog/pg_inherits.c and put them there, along with a coupleof other functions that search pg_inherits.The code that modifies pg_inherits is (still) in tablecmds.c --- it'skind of entangled with unrelated code that modifies pg_depend and otherstuff, so pulling it out seemed like a bigger change than I wanted to makeright now. But this file provides a natural home for it if anyone evergets around to that.This commit just moves code around; it doesn't change anything, exceptI succumbed to the temptation to make a couple of trivial optimizationsin typeInheritsFrom().
1 parent6480c14 commit0ada559

File tree

12 files changed

+282
-242
lines changed

12 files changed

+282
-242
lines changed

‎src/backend/catalog/Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# Makefile for backend/catalog
44
#
5-
# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.69 2009/02/09 20:57:59 alvherre Exp $
5+
# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.70 2009/05/12 00:56:05 tgl Exp $
66
#
77
#-------------------------------------------------------------------------
88

@@ -12,8 +12,8 @@ include $(top_builddir)/src/Makefile.global
1212

1313
OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o\
1414
pg_aggregate.o pg_constraint.o pg_conversion.o pg_depend.o pg_enum.o\
15-
pg_largeobject.o pg_namespace.o pg_operator.o pg_proc.o pg_shdepend.o\
16-
pg_type.o storage.o toasting.o
15+
pg_inherits.opg_largeobject.o pg_namespace.o pg_operator.o pg_proc.o\
16+
pg_shdepend.opg_type.o storage.o toasting.o
1717

1818
BKIFILES = postgres.bki postgres.description postgres.shdescription
1919

‎src/backend/catalog/pg_inherits.c

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* pg_inherits.c
4+
* routines to support manipulation of the pg_inherits relation
5+
*
6+
* Note: currently, this module only contains inquiry functions; the actual
7+
* creation and deletion of pg_inherits entries is done in tablecmds.c.
8+
* Perhaps someday that code should be moved here, but it'd have to be
9+
* disentangled from other stuff such as pg_depend updates.
10+
*
11+
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
12+
* Portions Copyright (c) 1994, Regents of the University of California
13+
*
14+
*
15+
* IDENTIFICATION
16+
* $PostgreSQL: pgsql/src/backend/catalog/pg_inherits.c,v 1.1 2009/05/12 00:56:05 tgl Exp $
17+
*
18+
*-------------------------------------------------------------------------
19+
*/
20+
#include"postgres.h"
21+
22+
#include"access/heapam.h"
23+
#include"catalog/pg_class.h"
24+
#include"catalog/pg_inherits.h"
25+
#include"parser/parse_type.h"
26+
#include"utils/fmgroids.h"
27+
#include"utils/syscache.h"
28+
#include"utils/tqual.h"
29+
30+
31+
/*
32+
* find_inheritance_children
33+
*
34+
* Returns a list containing the OIDs of all relations which
35+
* inherit *directly* from the relation with OID 'parentrelId'.
36+
*/
37+
List*
38+
find_inheritance_children(OidparentrelId)
39+
{
40+
List*list=NIL;
41+
Relationrelation;
42+
HeapScanDescscan;
43+
ScanKeyDatakey[1];
44+
HeapTupleinheritsTuple;
45+
Oidinhrelid;
46+
47+
/*
48+
* Can skip the scan if pg_class shows the relation has never had a
49+
* subclass.
50+
*/
51+
if (!has_subclass(parentrelId))
52+
returnNIL;
53+
54+
/*
55+
* XXX might be a good idea to create an index on pg_inherits' inhparent
56+
* field, so that we can use an indexscan instead of sequential scan here.
57+
* However, in typical databases pg_inherits won't have enough entries to
58+
* justify an indexscan...
59+
*/
60+
relation=heap_open(InheritsRelationId,AccessShareLock);
61+
ScanKeyInit(&key[0],
62+
Anum_pg_inherits_inhparent,
63+
BTEqualStrategyNumber,F_OIDEQ,
64+
ObjectIdGetDatum(parentrelId));
65+
scan=heap_beginscan(relation,SnapshotNow,1,key);
66+
while ((inheritsTuple=heap_getnext(scan,ForwardScanDirection))!=NULL)
67+
{
68+
inhrelid= ((Form_pg_inherits)GETSTRUCT(inheritsTuple))->inhrelid;
69+
list=lappend_oid(list,inhrelid);
70+
}
71+
heap_endscan(scan);
72+
heap_close(relation,AccessShareLock);
73+
returnlist;
74+
}
75+
76+
77+
/*
78+
* find_all_inheritors -
79+
*Returns a list of relation OIDs including the given rel plus
80+
*all relations that inherit from it, directly or indirectly.
81+
*/
82+
List*
83+
find_all_inheritors(OidparentrelId)
84+
{
85+
List*rels_list;
86+
ListCell*l;
87+
88+
/*
89+
* We build a list starting with the given rel and adding all direct and
90+
* indirect children. We can use a single list as both the record of
91+
* already-found rels and the agenda of rels yet to be scanned for more
92+
* children. This is a bit tricky but works because the foreach() macro
93+
* doesn't fetch the next list element until the bottom of the loop.
94+
*/
95+
rels_list=list_make1_oid(parentrelId);
96+
97+
foreach(l,rels_list)
98+
{
99+
Oidcurrentrel=lfirst_oid(l);
100+
List*currentchildren;
101+
102+
/* Get the direct children of this rel */
103+
currentchildren=find_inheritance_children(currentrel);
104+
105+
/*
106+
* Add to the queue only those children not already seen. This avoids
107+
* making duplicate entries in case of multiple inheritance paths from
108+
* the same parent. (It'll also keep us from getting into an infinite
109+
* loop, though theoretically there can't be any cycles in the
110+
* inheritance graph anyway.)
111+
*/
112+
rels_list=list_concat_unique_oid(rels_list,currentchildren);
113+
}
114+
115+
returnrels_list;
116+
}
117+
118+
119+
/*
120+
* has_subclass - does this relation have any children?
121+
*
122+
* In the current implementation, has_subclass returns whether a
123+
* particular class *might* have a subclass. It will not return the
124+
* correct result if a class had a subclass which was later dropped.
125+
* This is because relhassubclass in pg_class is not updated when a
126+
* subclass is dropped, primarily because of concurrency concerns.
127+
*
128+
* Currently has_subclass is only used as an efficiency hack to skip
129+
* unnecessary inheritance searches, so this is OK.
130+
*
131+
* Although this doesn't actually touch pg_inherits, it seems reasonable
132+
* to keep it here since it's normally used with the other routines here.
133+
*/
134+
bool
135+
has_subclass(OidrelationId)
136+
{
137+
HeapTupletuple;
138+
boolresult;
139+
140+
tuple=SearchSysCache(RELOID,
141+
ObjectIdGetDatum(relationId),
142+
0,0,0);
143+
if (!HeapTupleIsValid(tuple))
144+
elog(ERROR,"cache lookup failed for relation %u",relationId);
145+
146+
result= ((Form_pg_class)GETSTRUCT(tuple))->relhassubclass;
147+
ReleaseSysCache(tuple);
148+
returnresult;
149+
}
150+
151+
152+
/*
153+
* Given two type OIDs, determine whether the first is a complex type
154+
* (class type) that inherits from the second.
155+
*/
156+
bool
157+
typeInheritsFrom(OidsubclassTypeId,OidsuperclassTypeId)
158+
{
159+
boolresult= false;
160+
OidsubclassRelid;
161+
OidsuperclassRelid;
162+
Relationinhrel;
163+
List*visited,
164+
*queue;
165+
ListCell*queue_item;
166+
167+
/* We need to work with the associated relation OIDs */
168+
subclassRelid=typeidTypeRelid(subclassTypeId);
169+
if (subclassRelid==InvalidOid)
170+
return false;/* not a complex type */
171+
superclassRelid=typeidTypeRelid(superclassTypeId);
172+
if (superclassRelid==InvalidOid)
173+
return false;/* not a complex type */
174+
175+
/* No point in searching if the superclass has no subclasses */
176+
if (!has_subclass(superclassRelid))
177+
return false;
178+
179+
/*
180+
* Begin the search at the relation itself, so add its relid to the queue.
181+
*/
182+
queue=list_make1_oid(subclassRelid);
183+
visited=NIL;
184+
185+
inhrel=heap_open(InheritsRelationId,AccessShareLock);
186+
187+
/*
188+
* Use queue to do a breadth-first traversal of the inheritance graph from
189+
* the relid supplied up to the root. Notice that we append to the queue
190+
* inside the loop --- this is okay because the foreach() macro doesn't
191+
* advance queue_item until the next loop iteration begins.
192+
*/
193+
foreach(queue_item,queue)
194+
{
195+
Oidthis_relid=lfirst_oid(queue_item);
196+
ScanKeyDataskey;
197+
HeapScanDescinhscan;
198+
HeapTupleinhtup;
199+
200+
/*
201+
* If we've seen this relid already, skip it. This avoids extra
202+
* work in multiple-inheritance scenarios, and also protects us
203+
* from an infinite loop in case there is a cycle in pg_inherits
204+
* (though theoretically that shouldn't happen).
205+
*/
206+
if (list_member_oid(visited,this_relid))
207+
continue;
208+
209+
/*
210+
* Okay, this is a not-yet-seen relid. Add it to the list of
211+
* already-visited OIDs, then find all the types this relid inherits
212+
* from and add them to the queue.
213+
*/
214+
visited=lappend_oid(visited,this_relid);
215+
216+
ScanKeyInit(&skey,
217+
Anum_pg_inherits_inhrelid,
218+
BTEqualStrategyNumber,F_OIDEQ,
219+
ObjectIdGetDatum(this_relid));
220+
221+
inhscan=heap_beginscan(inhrel,SnapshotNow,1,&skey);
222+
223+
while ((inhtup=heap_getnext(inhscan,ForwardScanDirection))!=NULL)
224+
{
225+
Form_pg_inheritsinh= (Form_pg_inherits)GETSTRUCT(inhtup);
226+
Oidinhparent=inh->inhparent;
227+
228+
/* If this is the target superclass, we're done */
229+
if (inhparent==superclassRelid)
230+
{
231+
result= true;
232+
break;
233+
}
234+
235+
/* Else add to queue */
236+
queue=lappend_oid(queue,inhparent);
237+
}
238+
239+
heap_endscan(inhscan);
240+
241+
if (result)
242+
break;
243+
}
244+
245+
/* clean up ... */
246+
heap_close(inhrel,AccessShareLock);
247+
248+
list_free(visited);
249+
list_free(queue);
250+
251+
returnresult;
252+
}

‎src/backend/commands/lockcmds.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.21 2009/01/1208:54:26 petere Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.22 2009/05/1200:56:05 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515
#include"postgres.h"
1616

1717
#include"access/heapam.h"
1818
#include"catalog/namespace.h"
19+
#include"catalog/pg_inherits.h"
1920
#include"commands/lockcmds.h"
2021
#include"miscadmin.h"
21-
#include"optimizer/prep.h"
2222
#include"parser/parse_clause.h"
2323
#include"utils/acl.h"
2424
#include"utils/lsyscache.h"

‎src/backend/commands/tablecmds.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.282 2009/05/07 22:58:28 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.283 2009/05/12 00:56:05 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -50,8 +50,6 @@
5050
#include"nodes/nodeFuncs.h"
5151
#include"nodes/parsenodes.h"
5252
#include"optimizer/clauses.h"
53-
#include"optimizer/plancat.h"
54-
#include"optimizer/prep.h"
5553
#include"parser/gramparse.h"
5654
#include"parser/parse_clause.h"
5755
#include"parser/parse_coerce.h"
@@ -1873,7 +1871,6 @@ renameatt(Oid myrelid,
18731871
ListCell*child;
18741872
List*children;
18751873

1876-
/* this routine is actually in the planner */
18771874
children=find_all_inheritors(myrelid);
18781875

18791876
/*
@@ -3292,7 +3289,6 @@ ATSimpleRecursion(List **wqueue, Relation rel,
32923289
ListCell*child;
32933290
List*children;
32943291

3295-
/* this routine is actually in the planner */
32963292
children=find_all_inheritors(relid);
32973293

32983294
/*
@@ -3331,7 +3327,6 @@ ATOneLevelRecursion(List **wqueue, Relation rel,
33313327
ListCell*child;
33323328
List*children;
33333329

3334-
/* this routine is actually in the planner */
33353330
children=find_inheritance_children(relid);
33363331

33373332
foreach(child,children)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp