PostgreSQL Source Code  git master
pg_inherits.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/indexing.h"
#include "catalog/pg_inherits.h"
#include "parser/parse_type.h"
#include "storage/lmgr.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for pg_inherits.c:

Go to the source code of this file.

Data Structures

struct  SeenRelsEntry
 

Typedefs

typedef struct SeenRelsEntry SeenRelsEntry
 

Functions

Listfind_inheritance_children (Oid parentrelId, LOCKMODE lockmode)
 
Listfind_all_inheritors (Oid parentrelId, LOCKMODE lockmode, List **numparents)
 
bool has_subclass (Oid relationId)
 
bool has_superclass (Oid relationId)
 
bool typeInheritsFrom (Oid subclassTypeId, Oid superclassTypeId)
 
void StoreSingleInheritance (Oid relationId, Oid parentOid, int32 seqNumber)
 
bool DeleteInheritsTuple (Oid inhrelid, Oid inhparent)
 

Typedef Documentation

◆ SeenRelsEntry

Function Documentation

◆ DeleteInheritsTuple()

bool DeleteInheritsTuple ( Oid  inhrelid,
Oid  inhparent 
)

Definition at line 449 of file pg_inherits.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, InheritsRelidSeqnoIndexId, ObjectIdGetDatum, OidIsValid, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by index_drop(), and RemoveInheritance().

450 {
451  bool found = false;
452  Relation catalogRelation;
453  ScanKeyData key;
454  SysScanDesc scan;
455  HeapTuple inheritsTuple;
456 
457  /*
458  * Find pg_inherits entries by inhrelid.
459  */
460  catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
461  ScanKeyInit(&key,
462  Anum_pg_inherits_inhrelid,
463  BTEqualStrategyNumber, F_OIDEQ,
464  ObjectIdGetDatum(inhrelid));
465  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
466  true, NULL, 1, &key);
467 
468  while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
469  {
470  Oid parent;
471 
472  /* Compare inhparent if it was given, and do the actual deletion. */
473  parent = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhparent;
474  if (!OidIsValid(inhparent) || parent == inhparent)
475  {
476  CatalogTupleDelete(catalogRelation, &inheritsTuple->t_self);
477  found = true;
478  }
479  }
480 
481  /* Done */
482  systable_endscan(scan);
483  heap_close(catalogRelation, RowExclusiveLock);
484 
485  return found;
486 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define InheritsRelidSeqnoIndexId
Definition: indexing.h:169
FormData_pg_inherits * Form_pg_inherits
Definition: pg_inherits.h:44
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ find_all_inheritors()

List* find_all_inheritors ( Oid  parentrelId,
LOCKMODE  lockmode,
List **  numparents 
)

Definition at line 166 of file pg_inherits.c.

References CurrentMemoryContext, HASHCTL::entrysize, find_inheritance_children(), HASH_BLOBS, HASH_CONTEXT, hash_create(), hash_destroy(), HASH_ELEM, HASH_ENTER, hash_search(), HASHCTL::hcxt, HASHCTL::keysize, lappend_int(), lappend_oid(), lfirst_int, lfirst_oid, list_free(), list_make1_int, list_make1_oid, SeenRelsEntry::numparents_cell, and List::tail.

Referenced by acquire_inherited_sample_rows(), ATExecAddInherit(), ATExecAttachPartition(), ATExecValidateConstraint(), ATPrepAlterColumnType(), ATSimpleRecursion(), check_default_allows_bound(), CreateTrigger(), ExecSetupPartitionTupleRouting(), ExecuteTruncate(), expand_inherited_rtentry(), expand_vacuum_rel(), OpenTableList(), ProcessUtilitySlow(), rename_constraint_internal(), renameatt_internal(), and sepgsql_dml_privileges().

167 {
168  /* hash table for O(1) rel_oid -> rel_numparents cell lookup */
169  HTAB *seen_rels;
170  HASHCTL ctl;
171  List *rels_list,
172  *rel_numparents;
173  ListCell *l;
174 
175  memset(&ctl, 0, sizeof(ctl));
176  ctl.keysize = sizeof(Oid);
177  ctl.entrysize = sizeof(SeenRelsEntry);
179 
180  seen_rels = hash_create("find_all_inheritors temporary table",
181  32, /* start small and extend */
182  &ctl,
184 
185  /*
186  * We build a list starting with the given rel and adding all direct and
187  * indirect children. We can use a single list as both the record of
188  * already-found rels and the agenda of rels yet to be scanned for more
189  * children. This is a bit tricky but works because the foreach() macro
190  * doesn't fetch the next list element until the bottom of the loop.
191  */
192  rels_list = list_make1_oid(parentrelId);
193  rel_numparents = list_make1_int(0);
194 
195  foreach(l, rels_list)
196  {
197  Oid currentrel = lfirst_oid(l);
198  List *currentchildren;
199  ListCell *lc;
200 
201  /* Get the direct children of this rel */
202  currentchildren = find_inheritance_children(currentrel, lockmode);
203 
204  /*
205  * Add to the queue only those children not already seen. This avoids
206  * making duplicate entries in case of multiple inheritance paths from
207  * the same parent. (It'll also keep us from getting into an infinite
208  * loop, though theoretically there can't be any cycles in the
209  * inheritance graph anyway.)
210  */
211  foreach(lc, currentchildren)
212  {
213  Oid child_oid = lfirst_oid(lc);
214  bool found;
215  SeenRelsEntry *hash_entry;
216 
217  hash_entry = hash_search(seen_rels, &child_oid, HASH_ENTER, &found);
218  if (found)
219  {
220  /* if the rel is already there, bump number-of-parents counter */
221  lfirst_int(hash_entry->numparents_cell)++;
222  }
223  else
224  {
225  /* if it's not there, add it. expect 1 parent, initially. */
226  rels_list = lappend_oid(rels_list, child_oid);
227  rel_numparents = lappend_int(rel_numparents, 1);
228  hash_entry->numparents_cell = rel_numparents->tail;
229  }
230  }
231  }
232 
233  if (numparents)
234  *numparents = rel_numparents;
235  else
236  list_free(rel_numparents);
237 
238  hash_destroy(seen_rels);
239 
240  return rels_list;
241 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:814
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
Size entrysize
Definition: hsearch.h:73
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
ListCell * numparents_cell
Definition: pg_inherits.c:41
Definition: dynahash.c:208
#define lfirst_int(lc)
Definition: pg_list.h:107
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define list_make1_int(x1)
Definition: pg_list.h:145
List * lappend_int(List *list, int datum)
Definition: list.c:146
struct SeenRelsEntry SeenRelsEntry
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
#define list_make1_oid(x1)
Definition: pg_list.h:151
Size keysize
Definition: hsearch.h:72
List * find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
Definition: pg_inherits.c:56
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
#define lfirst_oid(lc)
Definition: pg_list.h:108
ListCell * tail
Definition: pg_list.h:50

◆ find_inheritance_children()

List* find_inheritance_children ( Oid  parentrelId,
LOCKMODE  lockmode 
)

Definition at line 56 of file pg_inherits.c.

References AccessShareLock, BTEqualStrategyNumber, GETSTRUCT, has_subclass(), heap_close, heap_open(), i, InheritsParentIndexId, lappend_oid(), sort-test::list, LockRelationOid(), NIL, NoLock, ObjectIdGetDatum, oid_cmp(), palloc(), pfree(), qsort, RELOID, repalloc(), ScanKeyInit(), SearchSysCacheExists1, systable_beginscan(), systable_endscan(), systable_getnext(), and UnlockRelationOid().

Referenced by ATAddCheckConstraint(), ATExecAddColumn(), ATExecDropColumn(), ATExecDropConstraint(), ATPrepAlterColumnType(), CreateTrigger(), find_all_inheritors(), LockTableRecurse(), RelationBuildPartitionDesc(), rename_constraint_internal(), and renameatt_internal().

57 {
58  List *list = NIL;
59  Relation relation;
60  SysScanDesc scan;
61  ScanKeyData key[1];
62  HeapTuple inheritsTuple;
63  Oid inhrelid;
64  Oid *oidarr;
65  int maxoids,
66  numoids,
67  i;
68 
69  /*
70  * Can skip the scan if pg_class shows the relation has never had a
71  * subclass.
72  */
73  if (!has_subclass(parentrelId))
74  return NIL;
75 
76  /*
77  * Scan pg_inherits and build a working array of subclass OIDs.
78  */
79  maxoids = 32;
80  oidarr = (Oid *) palloc(maxoids * sizeof(Oid));
81  numoids = 0;
82 
83  relation = heap_open(InheritsRelationId, AccessShareLock);
84 
85  ScanKeyInit(&key[0],
86  Anum_pg_inherits_inhparent,
87  BTEqualStrategyNumber, F_OIDEQ,
88  ObjectIdGetDatum(parentrelId));
89 
90  scan = systable_beginscan(relation, InheritsParentIndexId, true,
91  NULL, 1, key);
92 
93  while ((inheritsTuple = systable_getnext(scan)) != NULL)
94  {
95  inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid;
96  if (numoids >= maxoids)
97  {
98  maxoids *= 2;
99  oidarr = (Oid *) repalloc(oidarr, maxoids * sizeof(Oid));
100  }
101  oidarr[numoids++] = inhrelid;
102  }
103 
104  systable_endscan(scan);
105 
106  heap_close(relation, AccessShareLock);
107 
108  /*
109  * If we found more than one child, sort them by OID. This ensures
110  * reasonably consistent behavior regardless of the vagaries of an
111  * indexscan. This is important since we need to be sure all backends
112  * lock children in the same order to avoid needless deadlocks.
113  */
114  if (numoids > 1)
115  qsort(oidarr, numoids, sizeof(Oid), oid_cmp);
116 
117  /*
118  * Acquire locks and build the result list.
119  */
120  for (i = 0; i < numoids; i++)
121  {
122  inhrelid = oidarr[i];
123 
124  if (lockmode != NoLock)
125  {
126  /* Get the lock to synchronize against concurrent drop */
127  LockRelationOid(inhrelid, lockmode);
128 
129  /*
130  * Now that we have the lock, double-check to see if the relation
131  * really exists or not. If not, assume it was dropped while we
132  * waited to acquire lock, and ignore it.
133  */
135  {
136  /* Release useless lock */
137  UnlockRelationOid(inhrelid, lockmode);
138  /* And ignore this relation */
139  continue;
140  }
141  }
142 
143  list = lappend_oid(list, inhrelid);
144  }
145 
146  pfree(oidarr);
147 
148  return list;
149 }
#define NIL
Definition: pg_list.h:69
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:182
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:182
void pfree(void *pointer)
Definition: mcxt.c:1031
bool has_subclass(Oid relationId)
Definition: pg_inherits.c:261
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define NoLock
Definition: lockdefs.h:34
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define InheritsParentIndexId
Definition: indexing.h:171
int oid_cmp(const void *p1, const void *p2)
Definition: oid.c:336
FormData_pg_inherits * Form_pg_inherits
Definition: pg_inherits.h:44
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
void * palloc(Size size)
Definition: mcxt.c:924
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define qsort(a, b, c, d)
Definition: port.h:421
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ has_subclass()

bool has_subclass ( Oid  relationId)

Definition at line 261 of file pg_inherits.c.

References elog, ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), relhassubclass, RELOID, and SearchSysCache1().

Referenced by expand_inherited_rtentry(), find_inheritance_children(), and typeInheritsFrom().

262 {
263  HeapTuple tuple;
264  bool result;
265 
266  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationId));
267  if (!HeapTupleIsValid(tuple))
268  elog(ERROR, "cache lookup failed for relation %u", relationId);
269 
270  result = ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass;
271  ReleaseSysCache(tuple);
272  return result;
273 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
bool relhassubclass
Definition: pg_class.h:63
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
#define elog
Definition: elog.h:219

◆ has_superclass()

bool has_superclass ( Oid  relationId)

Definition at line 281 of file pg_inherits.c.

References AccessShareLock, BTEqualStrategyNumber, heap_close, heap_open(), HeapTupleIsValid, InheritsRelidSeqnoIndexId, ObjectIdGetDatum, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by ATExecDetachPartition(), CreateTrigger(), and DefineIndex().

282 {
283  Relation catalog;
284  SysScanDesc scan;
285  ScanKeyData skey;
286  bool result;
287 
288  catalog = heap_open(InheritsRelationId, AccessShareLock);
289  ScanKeyInit(&skey, Anum_pg_inherits_inhrelid, BTEqualStrategyNumber,
290  F_OIDEQ, ObjectIdGetDatum(relationId));
291  scan = systable_beginscan(catalog, InheritsRelidSeqnoIndexId, true,
292  NULL, 1, &skey);
293  result = HeapTupleIsValid(systable_getnext(scan));
294  systable_endscan(scan);
295  heap_close(catalog, AccessShareLock);
296 
297  return result;
298 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define InheritsRelidSeqnoIndexId
Definition: indexing.h:169
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ StoreSingleInheritance()

void StoreSingleInheritance ( Oid  relationId,
Oid  parentOid,
int32  seqNumber 
)

Definition at line 412 of file pg_inherits.c.

References CatalogTupleInsert(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), Int32GetDatum, ObjectIdGetDatum, RelationGetDescr, RowExclusiveLock, and values.

Referenced by index_create(), and StoreCatalogInheritance1().

413 {
414  Datum values[Natts_pg_inherits];
415  bool nulls[Natts_pg_inherits];
416  HeapTuple tuple;
417  Relation inhRelation;
418 
419  inhRelation = heap_open(InheritsRelationId, RowExclusiveLock);
420 
421  /*
422  * Make the pg_inherits entry
423  */
424  values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId);
425  values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid);
426  values[Anum_pg_inherits_inhseqno - 1] = Int32GetDatum(seqNumber);
427 
428  memset(nulls, 0, sizeof(nulls));
429 
430  tuple = heap_form_tuple(RelationGetDescr(inhRelation), values, nulls);
431 
432  CatalogTupleInsert(inhRelation, tuple);
433 
434  heap_freetuple(tuple);
435 
436  heap_close(inhRelation, RowExclusiveLock);
437 }
#define RelationGetDescr(relation)
Definition: rel.h:433
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
#define RowExclusiveLock
Definition: lockdefs.h:38
uintptr_t Datum
Definition: postgres.h:365
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define Int32GetDatum(X)
Definition: postgres.h:462

◆ typeInheritsFrom()

bool typeInheritsFrom ( Oid  subclassTypeId,
Oid  superclassTypeId 
)

Definition at line 310 of file pg_inherits.c.

References AccessShareLock, BTEqualStrategyNumber, GETSTRUCT, has_subclass(), heap_close, heap_open(), InheritsRelidSeqnoIndexId, InvalidOid, lappend_oid(), lfirst_oid, list_free(), list_make1_oid, list_member_oid(), NIL, ObjectIdGetDatum, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), typeidTypeRelid(), and typeOrDomainTypeRelid().

Referenced by can_coerce_type(), and coerce_type().

311 {
312  bool result = false;
313  Oid subclassRelid;
314  Oid superclassRelid;
315  Relation inhrel;
316  List *visited,
317  *queue;
318  ListCell *queue_item;
319 
320  /* We need to work with the associated relation OIDs */
321  subclassRelid = typeOrDomainTypeRelid(subclassTypeId);
322  if (subclassRelid == InvalidOid)
323  return false; /* not a complex type or domain over one */
324  superclassRelid = typeidTypeRelid(superclassTypeId);
325  if (superclassRelid == InvalidOid)
326  return false; /* not a complex type */
327 
328  /* No point in searching if the superclass has no subclasses */
329  if (!has_subclass(superclassRelid))
330  return false;
331 
332  /*
333  * Begin the search at the relation itself, so add its relid to the queue.
334  */
335  queue = list_make1_oid(subclassRelid);
336  visited = NIL;
337 
338  inhrel = heap_open(InheritsRelationId, AccessShareLock);
339 
340  /*
341  * Use queue to do a breadth-first traversal of the inheritance graph from
342  * the relid supplied up to the root. Notice that we append to the queue
343  * inside the loop --- this is okay because the foreach() macro doesn't
344  * advance queue_item until the next loop iteration begins.
345  */
346  foreach(queue_item, queue)
347  {
348  Oid this_relid = lfirst_oid(queue_item);
349  ScanKeyData skey;
350  SysScanDesc inhscan;
351  HeapTuple inhtup;
352 
353  /*
354  * If we've seen this relid already, skip it. This avoids extra work
355  * in multiple-inheritance scenarios, and also protects us from an
356  * infinite loop in case there is a cycle in pg_inherits (though
357  * theoretically that shouldn't happen).
358  */
359  if (list_member_oid(visited, this_relid))
360  continue;
361 
362  /*
363  * Okay, this is a not-yet-seen relid. Add it to the list of
364  * already-visited OIDs, then find all the types this relid inherits
365  * from and add them to the queue.
366  */
367  visited = lappend_oid(visited, this_relid);
368 
369  ScanKeyInit(&skey,
370  Anum_pg_inherits_inhrelid,
371  BTEqualStrategyNumber, F_OIDEQ,
372  ObjectIdGetDatum(this_relid));
373 
374  inhscan = systable_beginscan(inhrel, InheritsRelidSeqnoIndexId, true,
375  NULL, 1, &skey);
376 
377  while ((inhtup = systable_getnext(inhscan)) != NULL)
378  {
380  Oid inhparent = inh->inhparent;
381 
382  /* If this is the target superclass, we're done */
383  if (inhparent == superclassRelid)
384  {
385  result = true;
386  break;
387  }
388 
389  /* Else add to queue */
390  queue = lappend_oid(queue, inhparent);
391  }
392 
393  systable_endscan(inhscan);
394 
395  if (result)
396  break;
397  }
398 
399  /* clean up ... */
400  heap_close(inhrel, AccessShareLock);
401 
402  list_free(visited);
403  list_free(queue);
404 
405  return result;
406 }
#define NIL
Definition: pg_list.h:69
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
Oid typeOrDomainTypeRelid(Oid type_id)
Definition: parse_type.c:670
#define AccessShareLock
Definition: lockdefs.h:36
Oid typeidTypeRelid(Oid type_id)
Definition: parse_type.c:649
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
bool has_subclass(Oid relationId)
Definition: pg_inherits.c:261
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define list_make1_oid(x1)
Definition: pg_list.h:151
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define InvalidOid
Definition: postgres_ext.h:36
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define InheritsRelidSeqnoIndexId
Definition: indexing.h:169
FormData_pg_inherits * Form_pg_inherits
Definition: pg_inherits.h:44
void list_free(List *list)
Definition: list.c:1133
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:108