13
13
*
14
14
*
15
15
* 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 $
17
17
*
18
18
*-------------------------------------------------------------------------
19
19
*/
20
20
#include "postgres.h"
21
21
22
+ #include "access/genam.h"
22
23
#include "access/heapam.h"
24
+ #include "catalog/indexing.h"
23
25
#include "catalog/pg_class.h"
24
26
#include "catalog/pg_inherits.h"
25
27
#include "catalog/pg_inherits_fn.h"
29
31
#include "utils/syscache.h"
30
32
#include "utils/tqual.h"
31
33
34
+ static int oid_cmp (const void * p1 , const void * p2 );
35
+
32
36
33
37
/*
34
38
* find_inheritance_children
@@ -46,10 +50,14 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
46
50
{
47
51
List * list = NIL ;
48
52
Relation relation ;
49
- HeapScanDesc scan ;
53
+ SysScanDesc scan ;
50
54
ScanKeyData key [1 ];
51
55
HeapTuple inheritsTuple ;
52
56
Oid inhrelid ;
57
+ Oid * oidarr ;
58
+ int maxoids ,
59
+ numoids ,
60
+ i ;
53
61
54
62
/*
55
63
* 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)
59
67
return NIL ;
60
68
61
69
/*
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.
66
71
*/
72
+ maxoids = 32 ;
73
+ oidarr = (Oid * ) palloc (maxoids * sizeof (Oid ));
74
+ numoids = 0 ;
75
+
67
76
relation = heap_open (InheritsRelationId , AccessShareLock );
77
+
68
78
ScanKeyInit (& key [0 ],
69
79
Anum_pg_inherits_inhparent ,
70
80
BTEqualStrategyNumber , F_OIDEQ ,
71
81
ObjectIdGetDatum (parentrelId ));
72
- scan = heap_beginscan (relation , SnapshotNow , 1 , key );
73
82
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 )
75
87
{
76
88
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 ];
77
116
78
117
if (lockmode != NoLock )
79
118
{
@@ -99,8 +138,7 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
99
138
list = lappend_oid (list , inhrelid );
100
139
}
101
140
102
- heap_endscan (scan );
103
- heap_close (relation , AccessShareLock );
141
+ pfree (oidarr );
104
142
105
143
return list ;
106
144
}
@@ -231,7 +269,7 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
231
269
{
232
270
Oid this_relid = lfirst_oid (queue_item );
233
271
ScanKeyData skey ;
234
- HeapScanDesc inhscan ;
272
+ SysScanDesc inhscan ;
235
273
HeapTuple inhtup ;
236
274
237
275
/*
@@ -255,9 +293,10 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
255
293
BTEqualStrategyNumber , F_OIDEQ ,
256
294
ObjectIdGetDatum (this_relid ));
257
295
258
- inhscan = heap_beginscan (inhrel , SnapshotNow , 1 , & skey );
296
+ inhscan = systable_beginscan (inhrel , InheritsRelidSeqnoIndexId , true,
297
+ SnapshotNow , 1 , & skey );
259
298
260
- while ((inhtup = heap_getnext (inhscan , ForwardScanDirection )) != NULL )
299
+ while ((inhtup = systable_getnext (inhscan )) != NULL )
261
300
{
262
301
Form_pg_inherits inh = (Form_pg_inherits ) GETSTRUCT (inhtup );
263
302
Oid inhparent = inh -> inhparent ;
@@ -273,7 +312,7 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
273
312
queue = lappend_oid (queue , inhparent );
274
313
}
275
314
276
- heap_endscan (inhscan );
315
+ systable_endscan (inhscan );
277
316
278
317
if (result )
279
318
break ;
@@ -287,3 +326,18 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
287
326
288
327
return result ;
289
328
}
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