1313 *
1414 *
1515 * IDENTIFICATION
16- * $PostgreSQL: pgsql/src/backend/catalog/pg_inherits.c,v 1.3 2009/06/11 14:48:55 momjian Exp $
16+ * $PostgreSQL: pgsql/src/backend/catalog/pg_inherits.c,v 1.4 2009/12/29 22:00:12 tgl Exp $
1717 *
1818 *-------------------------------------------------------------------------
1919 */
2020#include "postgres.h"
2121
22+ #include "access/genam.h"
2223#include "access/heapam.h"
24+ #include "catalog/indexing.h"
2325#include "catalog/pg_class.h"
2426#include "catalog/pg_inherits.h"
2527#include "catalog/pg_inherits_fn.h"
2931#include "utils/syscache.h"
3032#include "utils/tqual.h"
3133
34+ static int oid_cmp (const void * p1 , const void * p2 );
35+
3236
3337/*
3438 * find_inheritance_children
@@ -46,10 +50,14 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
4650{
4751 List * list = NIL ;
4852 Relation relation ;
49- HeapScanDesc scan ;
53+ SysScanDesc scan ;
5054 ScanKeyData key [1 ];
5155 HeapTuple inheritsTuple ;
5256 Oid inhrelid ;
57+ Oid * oidarr ;
58+ int maxoids ,
59+ numoids ,
60+ i ;
5361
5462 /*
5563 * Can skip the scan if pg_class shows the relation has never had a
@@ -59,21 +67,52 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
5967 return NIL ;
6068
6169 /*
62- * XXX might be a good idea to create an index on pg_inherits' inhparent
63- * field, so that we can use an indexscan instead of sequential scan here.
64- * However, in typical databases pg_inherits won't have enough entries to
65- * justify an indexscan...
70+ * Scan pg_inherits and build a working array of subclass OIDs.
6671 */
72+ maxoids = 32 ;
73+ oidarr = (Oid * ) palloc (maxoids * sizeof (Oid ));
74+ numoids = 0 ;
75+
6776 relation = heap_open (InheritsRelationId , AccessShareLock );
77+
6878 ScanKeyInit (& key [0 ],
6979 Anum_pg_inherits_inhparent ,
7080 BTEqualStrategyNumber , F_OIDEQ ,
7181 ObjectIdGetDatum (parentrelId ));
72- scan = heap_beginscan (relation , SnapshotNow , 1 , key );
7382
74- while ((inheritsTuple = heap_getnext (scan , ForwardScanDirection )) != NULL )
83+ scan = systable_beginscan (relation , InheritsParentIndexId , true,
84+ SnapshotNow , 1 , key );
85+
86+ while ((inheritsTuple = systable_getnext (scan )) != NULL )
7587 {
7688 inhrelid = ((Form_pg_inherits ) GETSTRUCT (inheritsTuple ))-> inhrelid ;
89+ if (numoids >= maxoids )
90+ {
91+ maxoids *= 2 ;
92+ oidarr = (Oid * ) repalloc (oidarr , maxoids * sizeof (Oid ));
93+ }
94+ oidarr [numoids ++ ] = inhrelid ;
95+ }
96+
97+ systable_endscan (scan );
98+
99+ heap_close (relation , AccessShareLock );
100+
101+ /*
102+ * If we found more than one child, sort them by OID. This ensures
103+ * reasonably consistent behavior regardless of the vagaries of an
104+ * indexscan. This is important since we need to be sure all backends
105+ * lock children in the same order to avoid needless deadlocks.
106+ */
107+ if (numoids > 1 )
108+ qsort (oidarr , numoids , sizeof (Oid ), oid_cmp );
109+
110+ /*
111+ * Acquire locks and build the result list.
112+ */
113+ for (i = 0 ; i < numoids ; i ++ )
114+ {
115+ inhrelid = oidarr [i ];
77116
78117 if (lockmode != NoLock )
79118 {
@@ -99,8 +138,7 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
99138 list = lappend_oid (list , inhrelid );
100139 }
101140
102- heap_endscan (scan );
103- heap_close (relation , AccessShareLock );
141+ pfree (oidarr );
104142
105143 return list ;
106144}
@@ -231,7 +269,7 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
231269 {
232270 Oid this_relid = lfirst_oid (queue_item );
233271 ScanKeyData skey ;
234- HeapScanDesc inhscan ;
272+ SysScanDesc inhscan ;
235273 HeapTuple inhtup ;
236274
237275 /*
@@ -255,9 +293,10 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
255293 BTEqualStrategyNumber , F_OIDEQ ,
256294 ObjectIdGetDatum (this_relid ));
257295
258- inhscan = heap_beginscan (inhrel , SnapshotNow , 1 , & skey );
296+ inhscan = systable_beginscan (inhrel , InheritsRelidSeqnoIndexId , true,
297+ SnapshotNow , 1 , & skey );
259298
260- while ((inhtup = heap_getnext (inhscan , ForwardScanDirection )) != NULL )
299+ while ((inhtup = systable_getnext (inhscan )) != NULL )
261300 {
262301 Form_pg_inherits inh = (Form_pg_inherits ) GETSTRUCT (inhtup );
263302 Oid inhparent = inh -> inhparent ;
@@ -273,7 +312,7 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
273312 queue = lappend_oid (queue , inhparent );
274313 }
275314
276- heap_endscan (inhscan );
315+ systable_endscan (inhscan );
277316
278317 if (result )
279318 break ;
@@ -287,3 +326,18 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
287326
288327 return result ;
289328}
329+
330+
331+ /* qsort comparison function */
332+ static int
333+ oid_cmp (const void * p1 , const void * p2 )
334+ {
335+ Oid v1 = * ((const Oid * ) p1 );
336+ Oid v2 = * ((const Oid * ) p2 );
337+
338+ if (v1 < v2 )
339+ return -1 ;
340+ if (v1 > v2 )
341+ return 1 ;
342+ return 0 ;
343+ }
0 commit comments