PostgreSQL Source Code  git master
pg_inherits.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.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/snapmgr.h"
#include "utils/syscache.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, bool include_detached, 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, bool expect_detach_pending, const char *childname)
 
bool PartitionHasPendingDetach (Oid partoid)
 

Typedef Documentation

◆ SeenRelsEntry

typedef struct SeenRelsEntry SeenRelsEntry

Function Documentation

◆ DeleteInheritsTuple()

bool DeleteInheritsTuple ( Oid  inhrelid,
Oid  inhparent,
bool  expect_detach_pending,
const char *  childname 
)

Definition at line 499 of file pg_inherits.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, 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().

501 {
502  bool found = false;
503  Relation catalogRelation;
505  SysScanDesc scan;
506  HeapTuple inheritsTuple;
507 
508  /*
509  * Find pg_inherits entries by inhrelid.
510  */
511  catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
512  ScanKeyInit(&key,
513  Anum_pg_inherits_inhrelid,
514  BTEqualStrategyNumber, F_OIDEQ,
515  ObjectIdGetDatum(inhrelid));
516  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
517  true, NULL, 1, &key);
518 
519  while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
520  {
521  Oid parent;
522 
523  /* Compare inhparent if it was given, and do the actual deletion. */
524  parent = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhparent;
525  if (!OidIsValid(inhparent) || parent == inhparent)
526  {
527  bool detach_pending;
528 
529  detach_pending =
530  ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhdetachpending;
531 
532  /*
533  * Raise error depending on state. This should only happen for
534  * partitions, but we have no way to cross-check.
535  */
536  if (detach_pending && !expect_detach_pending)
537  ereport(ERROR,
538  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
539  errmsg("cannot detach partition \"%s\"",
540  childname ? childname : "unknown relation"),
541  errdetail("The partition is being detached concurrently or has an unfinished detach."),
542  errhint("Use ALTER TABLE ... DETACH PARTITION ... FINALIZE to complete the pending detach operation")));
543  if (!detach_pending && expect_detach_pending)
544  ereport(ERROR,
545  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
546  errmsg("cannot complete detaching partition \"%s\"",
547  childname ? childname : "unknown relation"),
548  errdetail("There's no pending concurrent detach.")));
549 
550  CatalogTupleDelete(catalogRelation, &inheritsTuple->t_self);
551  found = true;
552  }
553  }
554 
555  /* Done */
556  systable_endscan(scan);
557  table_close(catalogRelation, RowExclusiveLock);
558 
559  return found;
560 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int errhint(const char *fmt,...)
Definition: elog.c:1156
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define InheritsRelidSeqnoIndexId
Definition: pg_inherits.h:48
int errcode(int sqlerrcode)
Definition: elog.c:698
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_inherits * Form_pg_inherits
Definition: pg_inherits.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:909
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 **  numparents 
)

Definition at line 201 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().

202 {
203  /* hash table for O(1) rel_oid -> rel_numparents cell lookup */
204  HTAB *seen_rels;
205  HASHCTL ctl;
206  List *rels_list,
207  *rel_numparents;
208  ListCell *l;
209 
210  ctl.keysize = sizeof(Oid);
211  ctl.entrysize = sizeof(SeenRelsEntry);
213 
214  seen_rels = hash_create("find_all_inheritors temporary table",
215  32, /* start small and extend */
216  &ctl,
218 
219  /*
220  * We build a list starting with the given rel and adding all direct and
221  * indirect children. We can use a single list as both the record of
222  * already-found rels and the agenda of rels yet to be scanned for more
223  * children. This is a bit tricky but works because the foreach() macro
224  * doesn't fetch the next list element until the bottom of the loop. Note
225  * that we can't keep pointers into the output lists; but an index is
226  * sufficient.
227  */
228  rels_list = list_make1_oid(parentrelId);
229  rel_numparents = list_make1_int(0);
230 
231  foreach(l, rels_list)
232  {
233  Oid currentrel = lfirst_oid(l);
234  List *currentchildren;
235  ListCell *lc;
236 
237  /* Get the direct children of this rel */
238  currentchildren = find_inheritance_children(currentrel, false,
239  lockmode);
240 
241  /*
242  * Add to the queue only those children not already seen. This avoids
243  * making duplicate entries in case of multiple inheritance paths from
244  * the same parent. (It'll also keep us from getting into an infinite
245  * loop, though theoretically there can't be any cycles in the
246  * inheritance graph anyway.)
247  */
248  foreach(lc, currentchildren)
249  {
250  Oid child_oid = lfirst_oid(lc);
251  bool found;
252  SeenRelsEntry *hash_entry;
253 
254  hash_entry = hash_search(seen_rels, &child_oid, HASH_ENTER, &found);
255  if (found)
256  {
257  /* if the rel is already there, bump number-of-parents counter */
258  ListCell *numparents_cell;
259 
260  numparents_cell = list_nth_cell(rel_numparents,
261  hash_entry->list_index);
262  lfirst_int(numparents_cell)++;
263  }
264  else
265  {
266  /* if it's not there, add it. expect 1 parent, initially. */
267  hash_entry->list_index = list_length(rels_list);
268  rels_list = lappend_oid(rels_list, child_oid);
269  rel_numparents = lappend_int(rel_numparents, 1);
270  }
271  }
272  }
273 
274  if (numparents)
275  *numparents = rel_numparents;
276  else
277  list_free(rel_numparents);
278 
279  hash_destroy(seen_rels);
280 
281  return rels_list;
282 }
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:42
#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, bool include_detached, LOCKMODE lockmode)
Definition: pg_inherits.c:60
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,
bool  include_detached,
LOCKMODE  lockmode 
)

Definition at line 60 of file pg_inherits.c.

References AccessShareLock, ActiveSnapshotSet(), BTEqualStrategyNumber, GetActiveSnapshot(), GETSTRUCT, has_subclass(), HeapTupleHeaderGetXmin, 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(), HeapTupleData::t_data, table_close(), table_open(), UnlockRelationOid(), and XidInMVCCSnapshot().

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

62 {
63  List *list = NIL;
64  Relation relation;
65  SysScanDesc scan;
66  ScanKeyData key[1];
67  HeapTuple inheritsTuple;
68  Oid inhrelid;
69  Oid *oidarr;
70  int maxoids,
71  numoids,
72  i;
73 
74  /*
75  * Can skip the scan if pg_class shows the relation has never had a
76  * subclass.
77  */
78  if (!has_subclass(parentrelId))
79  return NIL;
80 
81  /*
82  * Scan pg_inherits and build a working array of subclass OIDs.
83  */
84  maxoids = 32;
85  oidarr = (Oid *) palloc(maxoids * sizeof(Oid));
86  numoids = 0;
87 
88  relation = table_open(InheritsRelationId, AccessShareLock);
89 
90  ScanKeyInit(&key[0],
91  Anum_pg_inherits_inhparent,
92  BTEqualStrategyNumber, F_OIDEQ,
93  ObjectIdGetDatum(parentrelId));
94 
95  scan = systable_beginscan(relation, InheritsParentIndexId, true,
96  NULL, 1, key);
97 
98  while ((inheritsTuple = systable_getnext(scan)) != NULL)
99  {
100  /*
101  * Cope with partitions concurrently being detached. When we see a
102  * partition marked "detach pending", we only include it in the set of
103  * visible partitions if caller requested all detached partitions, or
104  * if its pg_inherits tuple's xmin is still visible to the active
105  * snapshot.
106  *
107  * The reason for this check is that we want to avoid seeing the
108  * partition as alive in RI queries during REPEATABLE READ or
109  * SERIALIZABLE transactions. (If there's no active snapshot set,
110  * that means we're not running a user query, so it's OK to always
111  * include detached partitions in that case.)
112  */
113  if (((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhdetachpending &&
114  !include_detached &&
116  {
117  TransactionId xmin;
118  Snapshot snap;
119 
120  xmin = HeapTupleHeaderGetXmin(inheritsTuple->t_data);
121  snap = GetActiveSnapshot();
122 
123  if (!XidInMVCCSnapshot(xmin, snap))
124  continue;
125  }
126 
127  inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid;
128  if (numoids >= maxoids)
129  {
130  maxoids *= 2;
131  oidarr = (Oid *) repalloc(oidarr, maxoids * sizeof(Oid));
132  }
133  oidarr[numoids++] = inhrelid;
134  }
135 
136  systable_endscan(scan);
137 
138  table_close(relation, AccessShareLock);
139 
140  /*
141  * If we found more than one child, sort them by OID. This ensures
142  * reasonably consistent behavior regardless of the vagaries of an
143  * indexscan. This is important since we need to be sure all backends
144  * lock children in the same order to avoid needless deadlocks.
145  */
146  if (numoids > 1)
147  qsort(oidarr, numoids, sizeof(Oid), oid_cmp);
148 
149  /*
150  * Acquire locks and build the result list.
151  */
152  for (i = 0; i < numoids; i++)
153  {
154  inhrelid = oidarr[i];
155 
156  if (lockmode != NoLock)
157  {
158  /* Get the lock to synchronize against concurrent drop */
159  LockRelationOid(inhrelid, lockmode);
160 
161  /*
162  * Now that we have the lock, double-check to see if the relation
163  * really exists or not. If not, assume it was dropped while we
164  * waited to acquire lock, and ignore it.
165  */
167  {
168  /* Release useless lock */
169  UnlockRelationOid(inhrelid, lockmode);
170  /* And ignore this relation */
171  continue;
172  }
173  }
174 
175  list = lappend_oid(list, inhrelid);
176  }
177 
178  pfree(oidarr);
179 
180  return list;
181 }
#define NIL
Definition: pg_list.h:65
bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
Definition: snapmgr.c:2242
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
uint32 TransactionId
Definition: c.h:587
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:200
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:786
#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:383
HeapTupleHeader t_data
Definition: htup.h:68
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:184
void pfree(void *pointer)
Definition: mcxt.c:1169
bool has_subclass(Oid relationId)
Definition: pg_inherits.c:302
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define NoLock
Definition: lockdefs.h:34
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:798
#define InheritsParentIndexId
Definition: pg_inherits.h:50
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:313
int oid_cmp(const void *p1, const void *p2)
Definition: oid.c:336
FormData_pg_inherits * Form_pg_inherits
Definition: pg_inherits.h:45
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
void * palloc(Size size)
Definition: mcxt.c:1062
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:504
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
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 302 of file pg_inherits.c.

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

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

303 {
304  HeapTuple tuple;
305  bool result;
306 
307  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationId));
308  if (!HeapTupleIsValid(tuple))
309  elog(ERROR, "cache lookup failed for relation %u", relationId);
310 
311  result = ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass;
312  ReleaseSysCache(tuple);
313  return result;
314 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
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:232

◆ has_superclass()

bool has_superclass ( Oid  relationId)

Definition at line 324 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 CreateTrigger(), DefineIndex(), DefineQueryRewrite(), and DetachPartitionFinalize().

325 {
326  Relation catalog;
327  SysScanDesc scan;
328  ScanKeyData skey;
329  bool result;
330 
331  catalog = table_open(InheritsRelationId, AccessShareLock);
332  ScanKeyInit(&skey, Anum_pg_inherits_inhrelid, BTEqualStrategyNumber,
333  F_OIDEQ, ObjectIdGetDatum(relationId));
334  scan = systable_beginscan(catalog, InheritsRelidSeqnoIndexId, true,
335  NULL, 1, &skey);
336  result = HeapTupleIsValid(systable_getnext(scan));
337  systable_endscan(scan);
338  table_close(catalog, AccessShareLock);
339 
340  return result;
341 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define InheritsRelidSeqnoIndexId
Definition: pg_inherits.h:48
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#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

◆ PartitionHasPendingDetach()

bool PartitionHasPendingDetach ( Oid  partoid)

Definition at line 567 of file pg_inherits.c.

References BTEqualStrategyNumber, elog, ERROR, GETSTRUCT, HeapTupleIsValid, InheritsRelidSeqnoIndexId, sort-test::key, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ATPrepCmd().

568 {
569  Relation catalogRelation;
571  SysScanDesc scan;
572  HeapTuple inheritsTuple;
573 
574  /* We don't have a good way to verify it is in fact a partition */
575 
576  /*
577  * Find the pg_inherits entry by inhrelid. (There should only be one.)
578  */
579  catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
580  ScanKeyInit(&key,
581  Anum_pg_inherits_inhrelid,
582  BTEqualStrategyNumber, F_OIDEQ,
583  ObjectIdGetDatum(partoid));
584  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
585  true, NULL, 1, &key);
586 
587  while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
588  {
589  bool detached;
590 
591  detached =
592  ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhdetachpending;
593 
594  /* Done */
595  systable_endscan(scan);
596  table_close(catalogRelation, RowExclusiveLock);
597 
598  return detached;
599  }
600 
601  elog(ERROR, "relation %u is not a partition", partoid);
602  return false; /* keep compiler quiet */
603 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define InheritsRelidSeqnoIndexId
Definition: pg_inherits.h:48
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define RowExclusiveLock
Definition: lockdefs.h:38
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_inherits * Form_pg_inherits
Definition: pg_inherits.h:45
#define elog(elevel,...)
Definition: elog.h:232
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 455 of file pg_inherits.c.

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

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

456 {
457  Datum values[Natts_pg_inherits];
458  bool nulls[Natts_pg_inherits];
459  HeapTuple tuple;
460  Relation inhRelation;
461 
462  inhRelation = table_open(InheritsRelationId, RowExclusiveLock);
463 
464  /*
465  * Make the pg_inherits entry
466  */
467  values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId);
468  values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid);
469  values[Anum_pg_inherits_inhseqno - 1] = Int32GetDatum(seqNumber);
470  values[Anum_pg_inherits_inhdetachpending - 1] = BoolGetDatum(false);
471 
472  memset(nulls, 0, sizeof(nulls));
473 
474  tuple = heap_form_tuple(RelationGetDescr(inhRelation), values, nulls);
475 
476  CatalogTupleInsert(inhRelation, tuple);
477 
478  heap_freetuple(tuple);
479 
480  table_close(inhRelation, RowExclusiveLock);
481 }
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:551
#define RowExclusiveLock
Definition: lockdefs.h:38
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define Int32GetDatum(X)
Definition: postgres.h:523
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ typeInheritsFrom()

bool typeInheritsFrom ( Oid  subclassTypeId,
Oid  superclassTypeId 
)

Definition at line 353 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().

354 {
355  bool result = false;
356  Oid subclassRelid;
357  Oid superclassRelid;
358  Relation inhrel;
359  List *visited,
360  *queue;
361  ListCell *queue_item;
362 
363  /* We need to work with the associated relation OIDs */
364  subclassRelid = typeOrDomainTypeRelid(subclassTypeId);
365  if (subclassRelid == InvalidOid)
366  return false; /* not a complex type or domain over one */
367  superclassRelid = typeidTypeRelid(superclassTypeId);
368  if (superclassRelid == InvalidOid)
369  return false; /* not a complex type */
370 
371  /* No point in searching if the superclass has no subclasses */
372  if (!has_subclass(superclassRelid))
373  return false;
374 
375  /*
376  * Begin the search at the relation itself, so add its relid to the queue.
377  */
378  queue = list_make1_oid(subclassRelid);
379  visited = NIL;
380 
381  inhrel = table_open(InheritsRelationId, AccessShareLock);
382 
383  /*
384  * Use queue to do a breadth-first traversal of the inheritance graph from
385  * the relid supplied up to the root. Notice that we append to the queue
386  * inside the loop --- this is okay because the foreach() macro doesn't
387  * advance queue_item until the next loop iteration begins.
388  */
389  foreach(queue_item, queue)
390  {
391  Oid this_relid = lfirst_oid(queue_item);
392  ScanKeyData skey;
393  SysScanDesc inhscan;
394  HeapTuple inhtup;
395 
396  /*
397  * If we've seen this relid already, skip it. This avoids extra work
398  * in multiple-inheritance scenarios, and also protects us from an
399  * infinite loop in case there is a cycle in pg_inherits (though
400  * theoretically that shouldn't happen).
401  */
402  if (list_member_oid(visited, this_relid))
403  continue;
404 
405  /*
406  * Okay, this is a not-yet-seen relid. Add it to the list of
407  * already-visited OIDs, then find all the types this relid inherits
408  * from and add them to the queue.
409  */
410  visited = lappend_oid(visited, this_relid);
411 
412  ScanKeyInit(&skey,
413  Anum_pg_inherits_inhrelid,
414  BTEqualStrategyNumber, F_OIDEQ,
415  ObjectIdGetDatum(this_relid));
416 
417  inhscan = systable_beginscan(inhrel, InheritsRelidSeqnoIndexId, true,
418  NULL, 1, &skey);
419 
420  while ((inhtup = systable_getnext(inhscan)) != NULL)
421  {
423  Oid inhparent = inh->inhparent;
424 
425  /* If this is the target superclass, we're done */
426  if (inhparent == superclassRelid)
427  {
428  result = true;
429  break;
430  }
431 
432  /* Else add to queue */
433  queue = lappend_oid(queue, inhparent);
434  }
435 
436  systable_endscan(inhscan);
437 
438  if (result)
439  break;
440  }
441 
442  /* clean up ... */
443  table_close(inhrel, AccessShareLock);
444 
445  list_free(visited);
446  list_free(queue);
447 
448  return result;
449 }
#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:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid typeOrDomainTypeRelid(Oid type_id)
Definition: parse_type.c:687
#define InheritsRelidSeqnoIndexId
Definition: pg_inherits.h:48
#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:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
bool has_subclass(Oid relationId)
Definition: pg_inherits.c:302
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#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:45
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