PostgreSQL Source Code  git master
pg_inherits.h File Reference
#include "catalog/genbki.h"
#include "catalog/pg_inherits_d.h"
#include "nodes/pg_list.h"
#include "storage/lock.h"
Include dependency graph for pg_inherits.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define InheritsRelidSeqnoIndexId   2680
 
#define InheritsParentIndexId   2187
 

Typedefs

typedef FormData_pg_inheritsForm_pg_inherits
 

Functions

 CATALOG (pg_inherits, 2611, InheritsRelationId)
 
 DECLARE_UNIQUE_INDEX (pg_inherits_relid_seqno_index, 2680, on pg_inherits using btree(inhrelid oid_ops, inhseqno int4_ops))
 
 DECLARE_INDEX (pg_inherits_parent_index, 2187, on pg_inherits using btree(inhparent oid_ops))
 
Listfind_inheritance_children (Oid parentrelId, LOCKMODE lockmode)
 
Listfind_all_inheritors (Oid parentrelId, LOCKMODE lockmode, List **parents)
 
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)
 

Variables

 FormData_pg_inherits
 

Macro Definition Documentation

◆ InheritsParentIndexId

#define InheritsParentIndexId   2187

◆ InheritsRelidSeqnoIndexId

Typedef Documentation

◆ Form_pg_inherits

Definition at line 44 of file pg_inherits.h.

Function Documentation

◆ CATALOG()

CATALOG ( pg_inherits  ,
2611  ,
InheritsRelationId   
)

Definition at line 32 of file pg_inherits.h.

33 {
34  Oid inhrelid;
35  Oid inhparent;
36  int32 inhseqno;
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:417
FormData_pg_inherits
Definition: pg_inherits.h:37

◆ DECLARE_INDEX()

DECLARE_INDEX ( pg_inherits_parent_index  ,
2187  ,
on pg_inherits using   btreeinhparent oid_ops 
)

◆ DECLARE_UNIQUE_INDEX()

DECLARE_UNIQUE_INDEX ( pg_inherits_relid_seqno_index  ,
2680  ,
on pg_inherits using   btreeinhrelid oid_ops, inhseqno int4_ops 
)

◆ DeleteInheritsTuple()

bool DeleteInheritsTuple ( Oid  inhrelid,
Oid  inhparent 
)

Definition at line 453 of file pg_inherits.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), GETSTRUCT, HeapTupleIsValid, InheritsRelidSeqnoIndexId, sort-test::key, ObjectIdGetDatum, OidIsValid, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by index_concurrently_swap(), index_drop(), and RemoveInheritance().

454 {
455  bool found = false;
456  Relation catalogRelation;
458  SysScanDesc scan;
459  HeapTuple inheritsTuple;
460 
461  /*
462  * Find pg_inherits entries by inhrelid.
463  */
464  catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
465  ScanKeyInit(&key,
466  Anum_pg_inherits_inhrelid,
467  BTEqualStrategyNumber, F_OIDEQ,
468  ObjectIdGetDatum(inhrelid));
469  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
470  true, NULL, 1, &key);
471 
472  while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
473  {
474  Oid parent;
475 
476  /* Compare inhparent if it was given, and do the actual deletion. */
477  parent = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhparent;
478  if (!OidIsValid(inhparent) || parent == inhparent)
479  {
480  CatalogTupleDelete(catalogRelation, &inheritsTuple->t_self);
481  found = true;
482  }
483  }
484 
485  /* Done */
486  systable_endscan(scan);
487  table_close(catalogRelation, RowExclusiveLock);
488 
489  return found;
490 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define InheritsRelidSeqnoIndexId
Definition: pg_inherits.h:47
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:351
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:698
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:381
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:500
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ find_all_inheritors()

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

Definition at line 165 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(), SeenRelsEntry::list_index, list_length(), list_make1_int, list_make1_oid, and list_nth_cell().

Referenced by acquire_inherited_sample_rows(), apply_handle_truncate(), ATCheckPartitionsNotInUse(), ATExecAddInherit(), ATExecAttachPartition(), ATExecValidateConstraint(), ATPrepAlterColumnType(), ATSimpleRecursion(), check_default_partition_contents(), CloneFkReferencing(), CreateTrigger(), ExecuteTruncate(), expand_inherited_rtentry(), expand_vacuum_rel(), GetPublicationRelations(), LockTableRecurse(), OpenTableList(), pg_partition_tree(), ProcessUtilitySlow(), ReindexPartitions(), rename_constraint_internal(), renameatt_internal(), and sepgsql_dml_privileges().

166 {
167  /* hash table for O(1) rel_oid -> rel_numparents cell lookup */
168  HTAB *seen_rels;
169  HASHCTL ctl;
170  List *rels_list,
171  *rel_numparents;
172  ListCell *l;
173 
174  ctl.keysize = sizeof(Oid);
175  ctl.entrysize = sizeof(SeenRelsEntry);
177 
178  seen_rels = hash_create("find_all_inheritors temporary table",
179  32, /* start small and extend */
180  &ctl,
182 
183  /*
184  * We build a list starting with the given rel and adding all direct and
185  * indirect children. We can use a single list as both the record of
186  * already-found rels and the agenda of rels yet to be scanned for more
187  * children. This is a bit tricky but works because the foreach() macro
188  * doesn't fetch the next list element until the bottom of the loop. Note
189  * that we can't keep pointers into the output lists; but an index is
190  * sufficient.
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  ListCell *numparents_cell;
222 
223  numparents_cell = list_nth_cell(rel_numparents,
224  hash_entry->list_index);
225  lfirst_int(numparents_cell)++;
226  }
227  else
228  {
229  /* if it's not there, add it. expect 1 parent, initially. */
230  hash_entry->list_index = list_length(rels_list);
231  rels_list = lappend_oid(rels_list, child_oid);
232  rel_numparents = lappend_int(rel_numparents, 1);
233  }
234  }
235  }
236 
237  if (numparents)
238  *numparents = rel_numparents;
239  else
240  list_free(rel_numparents);
241 
242  hash_destroy(seen_rels);
243 
244  return rels_list;
245 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:862
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
static ListCell * list_nth_cell(const List *list, int n)
Definition: pg_list.h:256
MemoryContext hcxt
Definition: hsearch.h:86
Size entrysize
Definition: hsearch.h:76
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
Definition: dynahash.c:219
#define lfirst_int(lc)
Definition: pg_list.h:170
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define list_make1_int(x1)
Definition: pg_list.h:221
List * lappend_int(List *list, int datum)
Definition: list.c:354
struct SeenRelsEntry SeenRelsEntry
#define HASH_BLOBS
Definition: hsearch.h:97
#define list_make1_oid(x1)
Definition: pg_list.h:236
Size keysize
Definition: hsearch.h:75
List * find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
Definition: pg_inherits.c:55
static int list_length(const List *l)
Definition: pg_list.h:149
void list_free(List *list)
Definition: list.c:1391
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ find_inheritance_children()

List* find_inheritance_children ( Oid  parentrelId,
LOCKMODE  lockmode 
)

Definition at line 55 of file pg_inherits.c.

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

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

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

◆ has_subclass()

bool has_subclass ( Oid  relationId)

Definition at line 265 of file pg_inherits.c.

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

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

266 {
267  HeapTuple tuple;
268  bool result;
269 
270  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationId));
271  if (!HeapTupleIsValid(tuple))
272  elog(ERROR, "cache lookup failed for relation %u", relationId);
273 
274  result = ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass;
275  ReleaseSysCache(tuple);
276  return result;
277 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define elog(elevel,...)
Definition: elog.h:228

◆ has_superclass()

bool has_superclass ( Oid  relationId)

Definition at line 285 of file pg_inherits.c.

References AccessShareLock, BTEqualStrategyNumber, HeapTupleIsValid, InheritsRelidSeqnoIndexId, ObjectIdGetDatum, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

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

286 {
287  Relation catalog;
288  SysScanDesc scan;
289  ScanKeyData skey;
290  bool result;
291 
292  catalog = table_open(InheritsRelationId, AccessShareLock);
293  ScanKeyInit(&skey, Anum_pg_inherits_inhrelid, BTEqualStrategyNumber,
294  F_OIDEQ, ObjectIdGetDatum(relationId));
295  scan = systable_beginscan(catalog, InheritsRelidSeqnoIndexId, true,
296  NULL, 1, &skey);
297  result = HeapTupleIsValid(systable_getnext(scan));
298  systable_endscan(scan);
299  table_close(catalog, AccessShareLock);
300 
301  return result;
302 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#define InheritsRelidSeqnoIndexId
Definition: pg_inherits.h:47
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:381
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:500
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ StoreSingleInheritance()

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

Definition at line 416 of file pg_inherits.c.

References CatalogTupleInsert(), heap_form_tuple(), heap_freetuple(), Int32GetDatum, ObjectIdGetDatum, RelationGetDescr, RowExclusiveLock, table_close(), table_open(), and values.

Referenced by index_concurrently_swap(), index_create(), and StoreCatalogInheritance1().

417 {
418  Datum values[Natts_pg_inherits];
419  bool nulls[Natts_pg_inherits];
420  HeapTuple tuple;
421  Relation inhRelation;
422 
423  inhRelation = table_open(InheritsRelationId, RowExclusiveLock);
424 
425  /*
426  * Make the pg_inherits entry
427  */
428  values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId);
429  values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid);
430  values[Anum_pg_inherits_inhseqno - 1] = Int32GetDatum(seqNumber);
431 
432  memset(nulls, 0, sizeof(nulls));
433 
434  tuple = heap_form_tuple(RelationGetDescr(inhRelation), values, nulls);
435 
436  CatalogTupleInsert(inhRelation, tuple);
437 
438  heap_freetuple(tuple);
439 
440  table_close(inhRelation, RowExclusiveLock);
441 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define RelationGetDescr(relation)
Definition: rel.h:483
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define RowExclusiveLock
Definition: lockdefs.h:38
uintptr_t Datum
Definition: postgres.h:367
static Datum values[MAXATTR]
Definition: bootstrap.c:165
#define Int32GetDatum(X)
Definition: postgres.h:479
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:222

◆ typeInheritsFrom()

bool typeInheritsFrom ( Oid  subclassTypeId,
Oid  superclassTypeId 
)

Definition at line 314 of file pg_inherits.c.

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

Referenced by can_coerce_type(), and coerce_type().

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

Variable Documentation

◆ FormData_pg_inherits

FormData_pg_inherits

Definition at line 37 of file pg_inherits.h.