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

Go to the source code of this file.

Typedefs

typedef FormData_pg_constraintForm_pg_constraint
 
typedef enum ConstraintCategory ConstraintCategory
 

Enumerations

enum  ConstraintCategory { CONSTRAINT_RELATION , CONSTRAINT_DOMAIN , CONSTRAINT_ASSERTION }
 

Functions

 CATALOG (pg_constraint, 2606, ConstraintRelationId)
 
 DECLARE_TOAST (pg_constraint, 2832, 2833)
 
 DECLARE_INDEX (pg_constraint_conname_nsp_index, 2664, ConstraintNameNspIndexId, on pg_constraint using btree(conname name_ops, connamespace oid_ops))
 
 DECLARE_UNIQUE_INDEX (pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, on pg_constraint using btree(conrelid oid_ops, contypid oid_ops, conname name_ops))
 
 DECLARE_INDEX (pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, on pg_constraint using btree(contypid oid_ops))
 
 DECLARE_UNIQUE_INDEX_PKEY (pg_constraint_oid_index, 2667, ConstraintOidIndexId, on pg_constraint using btree(oid oid_ops))
 
 DECLARE_INDEX (pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, on pg_constraint using btree(conparentid oid_ops))
 
 DECLARE_ARRAY_FOREIGN_KEY_OPT ((conrelid, conkey), pg_attribute,(attrelid, attnum))
 
 DECLARE_ARRAY_FOREIGN_KEY ((confrelid, confkey), pg_attribute,(attrelid, attnum))
 
Oid CreateConstraintEntry (const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
 
void RemoveConstraintById (Oid conId)
 
void RenameConstraintById (Oid conId, const char *newname)
 
bool ConstraintNameIsUsed (ConstraintCategory conCat, Oid objId, const char *conname)
 
bool ConstraintNameExists (const char *conname, Oid namespaceid)
 
char * ChooseConstraintName (const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
 
void AlterConstraintNamespaces (Oid ownerId, Oid oldNspId, Oid newNspId, bool isType, ObjectAddresses *objsMoved)
 
void ConstraintSetParentConstraint (Oid childConstrId, Oid parentConstrId, Oid childTableId)
 
Oid get_relation_constraint_oid (Oid relid, const char *conname, bool missing_ok)
 
Bitmapsetget_relation_constraint_attnos (Oid relid, const char *conname, bool missing_ok, Oid *constraintOid)
 
Oid get_domain_constraint_oid (Oid typid, const char *conname, bool missing_ok)
 
Oid get_relation_idx_constraint_oid (Oid relationId, Oid indexId)
 
Bitmapsetget_primary_key_attnos (Oid relid, bool deferrableOk, Oid *constraintOid)
 
void DeconstructFkConstraintRow (HeapTuple tuple, int *numfks, AttrNumber *conkey, AttrNumber *confkey, Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs, int *num_fk_del_set_cols, AttrNumber *fk_del_set_cols)
 
bool check_functional_grouping (Oid relid, Index varno, Index varlevelsup, List *grouping_columns, List **constraintDeps)
 

Variables

 FormData_pg_constraint
 

Typedef Documentation

◆ ConstraintCategory

◆ Form_pg_constraint

Definition at line 165 of file pg_constraint.h.

Enumeration Type Documentation

◆ ConstraintCategory

Enumerator
CONSTRAINT_RELATION 
CONSTRAINT_DOMAIN 
CONSTRAINT_ASSERTION 

Definition at line 200 of file pg_constraint.h.

201 {
204  CONSTRAINT_ASSERTION /* for future expansion */
ConstraintCategory
@ CONSTRAINT_DOMAIN
@ CONSTRAINT_RELATION
@ CONSTRAINT_ASSERTION

Function Documentation

◆ AlterConstraintNamespaces()

void AlterConstraintNamespaces ( Oid  ownerId,
Oid  oldNspId,
Oid  newNspId,
bool  isType,
ObjectAddresses objsMoved 
)

Definition at line 719 of file pg_constraint.c.

721 {
722  Relation conRel;
723  ScanKeyData key[2];
724  SysScanDesc scan;
725  HeapTuple tup;
726 
727  conRel = table_open(ConstraintRelationId, RowExclusiveLock);
728 
729  ScanKeyInit(&key[0],
730  Anum_pg_constraint_conrelid,
731  BTEqualStrategyNumber, F_OIDEQ,
732  ObjectIdGetDatum(isType ? InvalidOid : ownerId));
733  ScanKeyInit(&key[1],
734  Anum_pg_constraint_contypid,
735  BTEqualStrategyNumber, F_OIDEQ,
736  ObjectIdGetDatum(isType ? ownerId : InvalidOid));
737 
738  scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId, true,
739  NULL, 2, key);
740 
741  while (HeapTupleIsValid((tup = systable_getnext(scan))))
742  {
744  ObjectAddress thisobj;
745 
746  ObjectAddressSet(thisobj, ConstraintRelationId, conform->oid);
747 
748  if (object_address_present(&thisobj, objsMoved))
749  continue;
750 
751  /* Don't update if the object is already part of the namespace */
752  if (conform->connamespace == oldNspId && oldNspId != newNspId)
753  {
754  tup = heap_copytuple(tup);
755  conform = (Form_pg_constraint) GETSTRUCT(tup);
756 
757  conform->connamespace = newNspId;
758 
759  CatalogTupleUpdate(conRel, &tup->t_self, tup);
760 
761  /*
762  * Note: currently, the constraint will not have its own
763  * dependency on the namespace, so we don't need to do
764  * changeDependencyFor().
765  */
766  }
767 
768  InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
769 
770  add_exact_object_address(&thisobj, objsMoved);
771  }
772 
773  systable_endscan(scan);
774 
775  table_close(conRel, RowExclusiveLock);
776 }
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2562
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2502
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:598
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:505
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:386
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:195
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
FormData_pg_constraint * Form_pg_constraint
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define InvalidOid
Definition: postgres_ext.h:36
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

References add_exact_object_address(), BTEqualStrategyNumber, CatalogTupleUpdate(), GETSTRUCT, heap_copytuple(), HeapTupleIsValid, InvalidOid, InvokeObjectPostAlterHook, sort-test::key, object_address_present(), ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by AlterTableNamespaceInternal(), and AlterTypeNamespaceInternal().

◆ CATALOG()

CATALOG ( pg_constraint  ,
2606  ,
ConstraintRelationId   
)

Definition at line 31 of file pg_constraint.h.

32 {
33  Oid oid; /* oid */
34 
35  /*
36  * conname + connamespace is deliberately not unique; we allow, for
37  * example, the same name to be used for constraints of different
38  * relations. This is partly for backwards compatibility with past
39  * Postgres practice, and partly because we don't want to have to obtain a
40  * global lock to generate a globally unique name for a nameless
41  * constraint. We associate a namespace with constraint names only for
42  * SQL-spec compatibility.
43  *
44  * However, we do require conname to be unique among the constraints of a
45  * single relation or domain. This is enforced by a unique index on
46  * conrelid + contypid + conname.
47  */
48  NameData conname; /* name of this constraint */
49  Oid connamespace BKI_LOOKUP(pg_namespace); /* OID of namespace
50  * containing constraint */
51  char contype; /* constraint type; see codes below */
52  bool condeferrable; /* deferrable constraint? */
53  bool condeferred; /* deferred by default? */
54  bool convalidated; /* constraint has been validated? */
55 
56  /*
57  * conrelid and conkey are only meaningful if the constraint applies to a
58  * specific relation (this excludes domain constraints and assertions).
59  * Otherwise conrelid is 0 and conkey is NULL.
60  */
61  Oid conrelid BKI_LOOKUP_OPT(pg_class); /* relation this
62  * constraint constrains */
63 
64  /*
65  * contypid links to the pg_type row for a domain if this is a domain
66  * constraint. Otherwise it's 0.
67  *
68  * For SQL-style global ASSERTIONs, both conrelid and contypid would be
69  * zero. This is not presently supported, however.
70  */
71  Oid contypid BKI_LOOKUP_OPT(pg_type); /* domain this constraint
72  * constrains */
73 
74  /*
75  * conindid links to the index supporting the constraint, if any;
76  * otherwise it's 0. This is used for unique, primary-key, and exclusion
77  * constraints, and less obviously for foreign-key constraints (where the
78  * index is a unique index on the referenced relation's referenced
79  * columns). Notice that the index is on conrelid in the first case but
80  * confrelid in the second.
81  */
82  Oid conindid BKI_LOOKUP_OPT(pg_class); /* index supporting this
83  * constraint */
84 
85  /*
86  * If this constraint is on a partition inherited from a partitioned
87  * table, this is the OID of the corresponding constraint in the parent.
88  */
89  Oid conparentid BKI_LOOKUP_OPT(pg_constraint);
90 
91  /*
92  * These fields, plus confkey, are only meaningful for a foreign-key
93  * constraint. Otherwise confrelid is 0 and the char fields are spaces.
94  */
95  Oid confrelid BKI_LOOKUP_OPT(pg_class); /* relation referenced by
96  * foreign key */
97  char confupdtype; /* foreign key's ON UPDATE action */
98  char confdeltype; /* foreign key's ON DELETE action */
99  char confmatchtype; /* foreign key's match type */
100 
101  /* Has a local definition (hence, do not drop when coninhcount is 0) */
102  bool conislocal;
103 
104  /* Number of times inherited from direct parent relation(s) */
105  int32 coninhcount;
106 
107  /* Has a local definition and cannot be inherited */
108  bool connoinherit;
109 
110 #ifdef CATALOG_VARLEN /* variable-length fields start here */
111 
112  /*
113  * Columns of conrelid that the constraint applies to, if known (this is
114  * NULL for trigger constraints)
115  */
116  int16 conkey[1];
117 
118  /*
119  * If a foreign key, the referenced columns of confrelid
120  */
121  int16 confkey[1];
122 
123  /*
124  * If a foreign key, the OIDs of the PK = FK equality operators for each
125  * column of the constraint
126  */
127  Oid conpfeqop[1] BKI_LOOKUP(pg_operator);
128 
129  /*
130  * If a foreign key, the OIDs of the PK = PK equality operators for each
131  * column of the constraint (i.e., equality for the referenced columns)
132  */
133  Oid conppeqop[1] BKI_LOOKUP(pg_operator);
134 
135  /*
136  * If a foreign key, the OIDs of the FK = FK equality operators for each
137  * column of the constraint (i.e., equality for the referencing columns)
138  */
139  Oid conffeqop[1] BKI_LOOKUP(pg_operator);
140 
141  /*
142  * If a foreign key with an ON DELETE SET NULL/DEFAULT action, the subset
143  * of conkey to updated. If null, all columns are updated.
144  */
145  int16 confdelsetcols[1];
146 
147  /*
148  * If an exclusion constraint, the OIDs of the exclusion operators for
149  * each column of the constraint
150  */
151  Oid conexclop[1] BKI_LOOKUP(pg_operator);
152 
153  /*
154  * If a check constraint, nodeToString representation of expression
155  */
156  pg_node_tree conbin;
157 #endif
signed short int16
Definition: c.h:428
signed int int32
Definition: c.h:429
#define BKI_LOOKUP(catalog)
Definition: genbki.h:46
#define BKI_LOOKUP_OPT(catalog)
Definition: genbki.h:47
FormData_pg_constraint
unsigned int Oid
Definition: postgres_ext.h:31
Definition: c.h:676

References BKI_LOOKUP, and BKI_LOOKUP_OPT.

◆ check_functional_grouping()

bool check_functional_grouping ( Oid  relid,
Index  varno,
Index  varlevelsup,
List grouping_columns,
List **  constraintDeps 
)

Definition at line 1329 of file pg_constraint.c.

1333 {
1334  Bitmapset *pkattnos;
1335  Bitmapset *groupbyattnos;
1336  Oid constraintOid;
1337  ListCell *gl;
1338 
1339  /* If the rel has no PK, then we can't prove functional dependency */
1340  pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
1341  if (pkattnos == NULL)
1342  return false;
1343 
1344  /* Identify all the rel's columns that appear in grouping_columns */
1345  groupbyattnos = NULL;
1346  foreach(gl, grouping_columns)
1347  {
1348  Var *gvar = (Var *) lfirst(gl);
1349 
1350  if (IsA(gvar, Var) &&
1351  gvar->varno == varno &&
1352  gvar->varlevelsup == varlevelsup)
1353  groupbyattnos = bms_add_member(groupbyattnos,
1355  }
1356 
1357  if (bms_is_subset(pkattnos, groupbyattnos))
1358  {
1359  /* The PK is a subset of grouping_columns, so we win */
1360  *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
1361  return true;
1362  }
1363 
1364  return false;
1365 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:738
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
Bitmapset * get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
#define lfirst(lc)
Definition: pg_list.h:169
Definition: primnodes.h:196
AttrNumber varattno
Definition: primnodes.h:200
int varno
Definition: primnodes.h:198
Index varlevelsup
Definition: primnodes.h:205
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27

References bms_add_member(), bms_is_subset(), FirstLowInvalidHeapAttributeNumber, get_primary_key_attnos(), IsA, lappend_oid(), lfirst, Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by check_ungrouped_columns_walker().

◆ ChooseConstraintName()

char* ChooseConstraintName ( const char *  name1,
const char *  name2,
const char *  label,
Oid  namespaceid,
List others 
)

Definition at line 506 of file pg_constraint.c.

509 {
510  int pass = 0;
511  char *conname = NULL;
512  char modlabel[NAMEDATALEN];
513  Relation conDesc;
514  SysScanDesc conscan;
515  ScanKeyData skey[2];
516  bool found;
517  ListCell *l;
518 
519  conDesc = table_open(ConstraintRelationId, AccessShareLock);
520 
521  /* try the unmodified label first */
522  strlcpy(modlabel, label, sizeof(modlabel));
523 
524  for (;;)
525  {
526  conname = makeObjectName(name1, name2, modlabel);
527 
528  found = false;
529 
530  foreach(l, others)
531  {
532  if (strcmp((char *) lfirst(l), conname) == 0)
533  {
534  found = true;
535  break;
536  }
537  }
538 
539  if (!found)
540  {
541  ScanKeyInit(&skey[0],
542  Anum_pg_constraint_conname,
543  BTEqualStrategyNumber, F_NAMEEQ,
544  CStringGetDatum(conname));
545 
546  ScanKeyInit(&skey[1],
547  Anum_pg_constraint_connamespace,
548  BTEqualStrategyNumber, F_OIDEQ,
549  ObjectIdGetDatum(namespaceid));
550 
551  conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
552  NULL, 2, skey);
553 
554  found = (HeapTupleIsValid(systable_getnext(conscan)));
555 
556  systable_endscan(conscan);
557  }
558 
559  if (!found)
560  break;
561 
562  /* found a conflict, so try a new name component */
563  pfree(conname);
564  snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
565  }
566 
567  table_close(conDesc, AccessShareLock);
568 
569  return conname;
570 }
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition: indexcmds.c:2251
#define AccessShareLock
Definition: lockdefs.h:36
void pfree(void *pointer)
Definition: mcxt.c:1175
static char * label
#define NAMEDATALEN
#define snprintf
Definition: port.h:225
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define CStringGetDatum(X)
Definition: postgres.h:622

References AccessShareLock, BTEqualStrategyNumber, CStringGetDatum, HeapTupleIsValid, label, lfirst, makeObjectName(), NAMEDATALEN, ObjectIdGetDatum, pfree(), ScanKeyInit(), snprintf, strlcpy(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by addFkRecurseReferenced(), addFkRecurseReferencing(), AddRelationNewConstraints(), ATExecAddConstraint(), CloneFkReferencing(), and domainAddConstraint().

◆ ConstraintNameExists()

bool ConstraintNameExists ( const char *  conname,
Oid  namespaceid 
)

Definition at line 452 of file pg_constraint.c.

453 {
454  bool found;
455  Relation conDesc;
456  SysScanDesc conscan;
457  ScanKeyData skey[2];
458 
459  conDesc = table_open(ConstraintRelationId, AccessShareLock);
460 
461  ScanKeyInit(&skey[0],
462  Anum_pg_constraint_conname,
463  BTEqualStrategyNumber, F_NAMEEQ,
464  CStringGetDatum(conname));
465 
466  ScanKeyInit(&skey[1],
467  Anum_pg_constraint_connamespace,
468  BTEqualStrategyNumber, F_OIDEQ,
469  ObjectIdGetDatum(namespaceid));
470 
471  conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
472  NULL, 2, skey);
473 
474  found = (HeapTupleIsValid(systable_getnext(conscan)));
475 
476  systable_endscan(conscan);
477  table_close(conDesc, AccessShareLock);
478 
479  return found;
480 }

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

Referenced by ChooseRelationName().

◆ ConstraintNameIsUsed()

bool ConstraintNameIsUsed ( ConstraintCategory  conCat,
Oid  objId,
const char *  conname 
)

Definition at line 407 of file pg_constraint.c.

409 {
410  bool found;
411  Relation conDesc;
412  SysScanDesc conscan;
413  ScanKeyData skey[3];
414 
415  conDesc = table_open(ConstraintRelationId, AccessShareLock);
416 
417  ScanKeyInit(&skey[0],
418  Anum_pg_constraint_conrelid,
419  BTEqualStrategyNumber, F_OIDEQ,
421  ? objId : InvalidOid));
422  ScanKeyInit(&skey[1],
423  Anum_pg_constraint_contypid,
424  BTEqualStrategyNumber, F_OIDEQ,
426  ? objId : InvalidOid));
427  ScanKeyInit(&skey[2],
428  Anum_pg_constraint_conname,
429  BTEqualStrategyNumber, F_NAMEEQ,
430  CStringGetDatum(conname));
431 
432  conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId,
433  true, NULL, 3, skey);
434 
435  /* There can be at most one matching row */
436  found = (HeapTupleIsValid(systable_getnext(conscan)));
437 
438  systable_endscan(conscan);
439  table_close(conDesc, AccessShareLock);
440 
441  return found;
442 }

References AccessShareLock, BTEqualStrategyNumber, CONSTRAINT_DOMAIN, CONSTRAINT_RELATION, CStringGetDatum, HeapTupleIsValid, InvalidOid, ObjectIdGetDatum, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by addFkRecurseReferenced(), addFkRecurseReferencing(), ATExecAddConstraint(), CloneFkReferencing(), domainAddConstraint(), index_create(), and RenameConstraintById().

◆ ConstraintSetParentConstraint()

void ConstraintSetParentConstraint ( Oid  childConstrId,
Oid  parentConstrId,
Oid  childTableId 
)

Definition at line 788 of file pg_constraint.c.

791 {
792  Relation constrRel;
793  Form_pg_constraint constrForm;
794  HeapTuple tuple,
795  newtup;
796  ObjectAddress depender;
797  ObjectAddress referenced;
798 
799  constrRel = table_open(ConstraintRelationId, RowExclusiveLock);
800  tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(childConstrId));
801  if (!HeapTupleIsValid(tuple))
802  elog(ERROR, "cache lookup failed for constraint %u", childConstrId);
803  newtup = heap_copytuple(tuple);
804  constrForm = (Form_pg_constraint) GETSTRUCT(newtup);
805  if (OidIsValid(parentConstrId))
806  {
807  /* don't allow setting parent for a constraint that already has one */
808  Assert(constrForm->coninhcount == 0);
809  if (constrForm->conparentid != InvalidOid)
810  elog(ERROR, "constraint %u already has a parent constraint",
811  childConstrId);
812 
813  constrForm->conislocal = false;
814  constrForm->coninhcount++;
815  constrForm->conparentid = parentConstrId;
816 
817  CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
818 
819  ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
820 
821  ObjectAddressSet(referenced, ConstraintRelationId, parentConstrId);
822  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
823 
824  ObjectAddressSet(referenced, RelationRelationId, childTableId);
825  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
826  }
827  else
828  {
829  constrForm->coninhcount--;
830  constrForm->conislocal = true;
831  constrForm->conparentid = InvalidOid;
832 
833  /* Make sure there's no further inheritance. */
834  Assert(constrForm->coninhcount == 0);
835 
836  CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
837 
838  deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
839  ConstraintRelationId,
841  deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
842  RelationRelationId,
844  }
845 
846  ReleaseSysCache(tuple);
847  table_close(constrRel, RowExclusiveLock);
848 }
#define OidIsValid(objectId)
Definition: c.h:710
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
Assert(fmt[strlen(fmt) - 1] !='\n')
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:293
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
@ CONSTROID
Definition: syscache.h:53

References Assert(), CatalogTupleUpdate(), CONSTROID, deleteDependencyRecordsForClass(), DEPENDENCY_PARTITION_PRI, DEPENDENCY_PARTITION_SEC, elog, ERROR, GETSTRUCT, heap_copytuple(), HeapTupleIsValid, InvalidOid, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, recordDependencyOn(), ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by ATExecAttachPartitionIdx(), AttachPartitionEnsureIndexes(), DefineIndex(), DetachPartitionFinalize(), and tryAttachPartitionForeignKey().

◆ CreateConstraintEntry()

Oid CreateConstraintEntry ( const char *  constraintName,
Oid  constraintNamespace,
char  constraintType,
bool  isDeferrable,
bool  isDeferred,
bool  isValidated,
Oid  parentConstrId,
Oid  relId,
const int16 constraintKey,
int  constraintNKeys,
int  constraintNTotalKeys,
Oid  domainId,
Oid  indexRelId,
Oid  foreignRelId,
const int16 foreignKey,
const Oid pfEqOp,
const Oid ppEqOp,
const Oid ffEqOp,
int  foreignNKeys,
char  foreignUpdateType,
char  foreignDeleteType,
const int16 fkDeleteSetCols,
int  numFkDeleteSetCols,
char  foreignMatchType,
const Oid exclOp,
Node conExpr,
const char *  conBin,
bool  conIsLocal,
int  conInhCount,
bool  conNoInherit,
bool  is_internal 
)

Definition at line 50 of file pg_constraint.c.

81 {
82  Relation conDesc;
83  Oid conOid;
84  HeapTuple tup;
85  bool nulls[Natts_pg_constraint];
86  Datum values[Natts_pg_constraint];
87  ArrayType *conkeyArray;
88  ArrayType *confkeyArray;
89  ArrayType *conpfeqopArray;
90  ArrayType *conppeqopArray;
91  ArrayType *conffeqopArray;
92  ArrayType *conexclopArray;
93  ArrayType *confdelsetcolsArray;
95  int i;
96  ObjectAddress conobject;
97  ObjectAddresses *addrs_auto;
98  ObjectAddresses *addrs_normal;
99 
100  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
101 
102  Assert(constraintName);
103  namestrcpy(&cname, constraintName);
104 
105  /*
106  * Convert C arrays into Postgres arrays.
107  */
108  if (constraintNKeys > 0)
109  {
110  Datum *conkey;
111 
112  conkey = (Datum *) palloc(constraintNKeys * sizeof(Datum));
113  for (i = 0; i < constraintNKeys; i++)
114  conkey[i] = Int16GetDatum(constraintKey[i]);
115  conkeyArray = construct_array(conkey, constraintNKeys,
116  INT2OID, 2, true, TYPALIGN_SHORT);
117  }
118  else
119  conkeyArray = NULL;
120 
121  if (foreignNKeys > 0)
122  {
123  Datum *fkdatums;
124 
125  fkdatums = (Datum *) palloc(foreignNKeys * sizeof(Datum));
126  for (i = 0; i < foreignNKeys; i++)
127  fkdatums[i] = Int16GetDatum(foreignKey[i]);
128  confkeyArray = construct_array(fkdatums, foreignNKeys,
129  INT2OID, 2, true, TYPALIGN_SHORT);
130  for (i = 0; i < foreignNKeys; i++)
131  fkdatums[i] = ObjectIdGetDatum(pfEqOp[i]);
132  conpfeqopArray = construct_array(fkdatums, foreignNKeys,
133  OIDOID, sizeof(Oid), true, TYPALIGN_INT);
134  for (i = 0; i < foreignNKeys; i++)
135  fkdatums[i] = ObjectIdGetDatum(ppEqOp[i]);
136  conppeqopArray = construct_array(fkdatums, foreignNKeys,
137  OIDOID, sizeof(Oid), true, TYPALIGN_INT);
138  for (i = 0; i < foreignNKeys; i++)
139  fkdatums[i] = ObjectIdGetDatum(ffEqOp[i]);
140  conffeqopArray = construct_array(fkdatums, foreignNKeys,
141  OIDOID, sizeof(Oid), true, TYPALIGN_INT);
142 
143  if (numFkDeleteSetCols > 0)
144  {
145  for (i = 0; i < numFkDeleteSetCols; i++)
146  fkdatums[i] = Int16GetDatum(fkDeleteSetCols[i]);
147  confdelsetcolsArray = construct_array(fkdatums, numFkDeleteSetCols,
148  INT2OID, 2, true, TYPALIGN_SHORT);
149  }
150  else
151  confdelsetcolsArray = NULL;
152  }
153  else
154  {
155  confkeyArray = NULL;
156  conpfeqopArray = NULL;
157  conppeqopArray = NULL;
158  conffeqopArray = NULL;
159  confdelsetcolsArray = NULL;
160  }
161 
162  if (exclOp != NULL)
163  {
164  Datum *opdatums;
165 
166  opdatums = (Datum *) palloc(constraintNKeys * sizeof(Datum));
167  for (i = 0; i < constraintNKeys; i++)
168  opdatums[i] = ObjectIdGetDatum(exclOp[i]);
169  conexclopArray = construct_array(opdatums, constraintNKeys,
170  OIDOID, sizeof(Oid), true, TYPALIGN_INT);
171  }
172  else
173  conexclopArray = NULL;
174 
175  /* initialize nulls and values */
176  for (i = 0; i < Natts_pg_constraint; i++)
177  {
178  nulls[i] = false;
179  values[i] = (Datum) NULL;
180  }
181 
182  conOid = GetNewOidWithIndex(conDesc, ConstraintOidIndexId,
183  Anum_pg_constraint_oid);
184  values[Anum_pg_constraint_oid - 1] = ObjectIdGetDatum(conOid);
185  values[Anum_pg_constraint_conname - 1] = NameGetDatum(&cname);
186  values[Anum_pg_constraint_connamespace - 1] = ObjectIdGetDatum(constraintNamespace);
187  values[Anum_pg_constraint_contype - 1] = CharGetDatum(constraintType);
188  values[Anum_pg_constraint_condeferrable - 1] = BoolGetDatum(isDeferrable);
189  values[Anum_pg_constraint_condeferred - 1] = BoolGetDatum(isDeferred);
190  values[Anum_pg_constraint_convalidated - 1] = BoolGetDatum(isValidated);
191  values[Anum_pg_constraint_conrelid - 1] = ObjectIdGetDatum(relId);
192  values[Anum_pg_constraint_contypid - 1] = ObjectIdGetDatum(domainId);
193  values[Anum_pg_constraint_conindid - 1] = ObjectIdGetDatum(indexRelId);
194  values[Anum_pg_constraint_conparentid - 1] = ObjectIdGetDatum(parentConstrId);
195  values[Anum_pg_constraint_confrelid - 1] = ObjectIdGetDatum(foreignRelId);
196  values[Anum_pg_constraint_confupdtype - 1] = CharGetDatum(foreignUpdateType);
197  values[Anum_pg_constraint_confdeltype - 1] = CharGetDatum(foreignDeleteType);
198  values[Anum_pg_constraint_confmatchtype - 1] = CharGetDatum(foreignMatchType);
199  values[Anum_pg_constraint_conislocal - 1] = BoolGetDatum(conIsLocal);
200  values[Anum_pg_constraint_coninhcount - 1] = Int32GetDatum(conInhCount);
201  values[Anum_pg_constraint_connoinherit - 1] = BoolGetDatum(conNoInherit);
202 
203  if (conkeyArray)
204  values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray);
205  else
206  nulls[Anum_pg_constraint_conkey - 1] = true;
207 
208  if (confkeyArray)
209  values[Anum_pg_constraint_confkey - 1] = PointerGetDatum(confkeyArray);
210  else
211  nulls[Anum_pg_constraint_confkey - 1] = true;
212 
213  if (conpfeqopArray)
214  values[Anum_pg_constraint_conpfeqop - 1] = PointerGetDatum(conpfeqopArray);
215  else
216  nulls[Anum_pg_constraint_conpfeqop - 1] = true;
217 
218  if (conppeqopArray)
219  values[Anum_pg_constraint_conppeqop - 1] = PointerGetDatum(conppeqopArray);
220  else
221  nulls[Anum_pg_constraint_conppeqop - 1] = true;
222 
223  if (conffeqopArray)
224  values[Anum_pg_constraint_conffeqop - 1] = PointerGetDatum(conffeqopArray);
225  else
226  nulls[Anum_pg_constraint_conffeqop - 1] = true;
227 
228  if (confdelsetcolsArray)
229  values[Anum_pg_constraint_confdelsetcols - 1] = PointerGetDatum(confdelsetcolsArray);
230  else
231  nulls[Anum_pg_constraint_confdelsetcols - 1] = true;
232 
233  if (conexclopArray)
234  values[Anum_pg_constraint_conexclop - 1] = PointerGetDatum(conexclopArray);
235  else
236  nulls[Anum_pg_constraint_conexclop - 1] = true;
237 
238  if (conBin)
239  values[Anum_pg_constraint_conbin - 1] = CStringGetTextDatum(conBin);
240  else
241  nulls[Anum_pg_constraint_conbin - 1] = true;
242 
243  tup = heap_form_tuple(RelationGetDescr(conDesc), values, nulls);
244 
245  CatalogTupleInsert(conDesc, tup);
246 
247  ObjectAddressSet(conobject, ConstraintRelationId, conOid);
248 
249  table_close(conDesc, RowExclusiveLock);
250 
251  /* Handle set of auto dependencies */
252  addrs_auto = new_object_addresses();
253 
254  if (OidIsValid(relId))
255  {
256  /*
257  * Register auto dependency from constraint to owning relation, or to
258  * specific column(s) if any are mentioned.
259  */
260  ObjectAddress relobject;
261 
262  if (constraintNTotalKeys > 0)
263  {
264  for (i = 0; i < constraintNTotalKeys; i++)
265  {
266  ObjectAddressSubSet(relobject, RelationRelationId, relId,
267  constraintKey[i]);
268  add_exact_object_address(&relobject, addrs_auto);
269  }
270  }
271  else
272  {
273  ObjectAddressSet(relobject, RelationRelationId, relId);
274  add_exact_object_address(&relobject, addrs_auto);
275  }
276  }
277 
278  if (OidIsValid(domainId))
279  {
280  /*
281  * Register auto dependency from constraint to owning domain
282  */
283  ObjectAddress domobject;
284 
285  ObjectAddressSet(domobject, TypeRelationId, domainId);
286  add_exact_object_address(&domobject, addrs_auto);
287  }
288 
289  record_object_address_dependencies(&conobject, addrs_auto,
291  free_object_addresses(addrs_auto);
292 
293  /* Handle set of normal dependencies */
294  addrs_normal = new_object_addresses();
295 
296  if (OidIsValid(foreignRelId))
297  {
298  /*
299  * Register normal dependency from constraint to foreign relation, or
300  * to specific column(s) if any are mentioned.
301  */
302  ObjectAddress relobject;
303 
304  if (foreignNKeys > 0)
305  {
306  for (i = 0; i < foreignNKeys; i++)
307  {
308  ObjectAddressSubSet(relobject, RelationRelationId,
309  foreignRelId, foreignKey[i]);
310  add_exact_object_address(&relobject, addrs_normal);
311  }
312  }
313  else
314  {
315  ObjectAddressSet(relobject, RelationRelationId, foreignRelId);
316  add_exact_object_address(&relobject, addrs_normal);
317  }
318  }
319 
320  if (OidIsValid(indexRelId) && constraintType == CONSTRAINT_FOREIGN)
321  {
322  /*
323  * Register normal dependency on the unique index that supports a
324  * foreign-key constraint. (Note: for indexes associated with unique
325  * or primary-key constraints, the dependency runs the other way, and
326  * is not made here.)
327  */
328  ObjectAddress relobject;
329 
330  ObjectAddressSet(relobject, RelationRelationId, indexRelId);
331  add_exact_object_address(&relobject, addrs_normal);
332  }
333 
334  if (foreignNKeys > 0)
335  {
336  /*
337  * Register normal dependencies on the equality operators that support
338  * a foreign-key constraint. If the PK and FK types are the same then
339  * all three operators for a column are the same; otherwise they are
340  * different.
341  */
342  ObjectAddress oprobject;
343 
344  oprobject.classId = OperatorRelationId;
345  oprobject.objectSubId = 0;
346 
347  for (i = 0; i < foreignNKeys; i++)
348  {
349  oprobject.objectId = pfEqOp[i];
350  add_exact_object_address(&oprobject, addrs_normal);
351  if (ppEqOp[i] != pfEqOp[i])
352  {
353  oprobject.objectId = ppEqOp[i];
354  add_exact_object_address(&oprobject, addrs_normal);
355  }
356  if (ffEqOp[i] != pfEqOp[i])
357  {
358  oprobject.objectId = ffEqOp[i];
359  add_exact_object_address(&oprobject, addrs_normal);
360  }
361  }
362  }
363 
364  record_object_address_dependencies(&conobject, addrs_normal,
366  free_object_addresses(addrs_normal);
367 
368  /*
369  * We don't bother to register dependencies on the exclusion operators of
370  * an exclusion constraint. We assume they are members of the opclass
371  * supporting the index, so there's an indirect dependency via that. (This
372  * would be pretty dicey for cross-type operators, but exclusion operators
373  * can never be cross-type.)
374  */
375 
376  if (conExpr != NULL)
377  {
378  /*
379  * Register dependencies from constraint to objects mentioned in CHECK
380  * expression.
381  */
382  recordDependencyOnSingleRelExpr(&conobject, conExpr, relId,
384  DEPENDENCY_NORMAL, false);
385  }
386 
387  /* Post creation hook for new constraint */
388  InvokeObjectPostCreateHookArg(ConstraintRelationId, conOid, 0,
389  is_internal);
390 
391  return conOid;
392 }
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3319
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:85
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:391
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2711
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
Definition: dependency.c:1631
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2447
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2742
@ DEPENDENCY_AUTO
Definition: dependency.h:34
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
int i
Definition: isn.c:73
void * palloc(Size size)
Definition: mcxt.c:1068
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:173
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
Definition: objectaddress.h:33
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define Int32GetDatum(X)
Definition: postgres.h:523
#define NameGetDatum(X)
Definition: postgres.h:639
#define Int16GetDatum(X)
Definition: postgres.h:495
#define CharGetDatum(X)
Definition: postgres.h:460
#define PointerGetDatum(X)
Definition: postgres.h:600
#define RelationGetDescr(relation)
Definition: rel.h:515

References add_exact_object_address(), Assert(), BoolGetDatum, CatalogTupleInsert(), CharGetDatum, ObjectAddress::classId, construct_array(), CStringGetTextDatum, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, free_object_addresses(), GetNewOidWithIndex(), heap_form_tuple(), i, Int16GetDatum, Int32GetDatum, InvokeObjectPostCreateHookArg, NameGetDatum, namestrcpy(), new_object_addresses(), ObjectAddressSet, ObjectAddressSubSet, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, palloc(), PointerGetDatum, record_object_address_dependencies(), recordDependencyOnSingleRelExpr(), RelationGetDescr, RowExclusiveLock, table_close(), table_open(), and values.

Referenced by addFkRecurseReferenced(), addFkRecurseReferencing(), CloneFkReferencing(), CreateTriggerFiringOn(), domainAddConstraint(), index_constraint_create(), and StoreRelCheck().

◆ DECLARE_ARRAY_FOREIGN_KEY()

DECLARE_ARRAY_FOREIGN_KEY ( (confrelid, confkey)  ,
pg_attribute  ,
(attrelid, attnum  
)

◆ DECLARE_ARRAY_FOREIGN_KEY_OPT()

DECLARE_ARRAY_FOREIGN_KEY_OPT ( (conrelid, conkey)  ,
pg_attribute  ,
(attrelid, attnum  
)

◆ DECLARE_INDEX() [1/3]

DECLARE_INDEX ( pg_constraint_conname_nsp_index  ,
2664  ,
ConstraintNameNspIndexId  ,
on pg_constraint using   btreeconname name_ops, connamespace oid_ops 
)

◆ DECLARE_INDEX() [2/3]

DECLARE_INDEX ( pg_constraint_conparentid_index  ,
2579  ,
ConstraintParentIndexId  ,
on pg_constraint using   btreeconparentid oid_ops 
)

◆ DECLARE_INDEX() [3/3]

DECLARE_INDEX ( pg_constraint_contypid_index  ,
2666  ,
ConstraintTypidIndexId  ,
on pg_constraint using   btreecontypid oid_ops 
)

◆ DECLARE_TOAST()

DECLARE_TOAST ( pg_constraint  ,
2832  ,
2833   
)

◆ DECLARE_UNIQUE_INDEX()

DECLARE_UNIQUE_INDEX ( pg_constraint_conrelid_contypid_conname_index  ,
2665  ,
ConstraintRelidTypidNameIndexId  ,
on pg_constraint using   btreeconrelid oid_ops, contypid oid_ops, conname name_ops 
)

◆ DECLARE_UNIQUE_INDEX_PKEY()

DECLARE_UNIQUE_INDEX_PKEY ( pg_constraint_oid_index  ,
2667  ,
ConstraintOidIndexId  ,
on pg_constraint using   btreeoid oid_ops 
)

◆ DeconstructFkConstraintRow()

void DeconstructFkConstraintRow ( HeapTuple  tuple,
int *  numfks,
AttrNumber conkey,
AttrNumber confkey,
Oid pf_eq_oprs,
Oid pp_eq_oprs,
Oid ff_eq_oprs,
int *  num_fk_del_set_cols,
AttrNumber fk_del_set_cols 
)

Definition at line 1184 of file pg_constraint.c.

1188 {
1189  Oid constrId;
1190  Datum adatum;
1191  bool isNull;
1192  ArrayType *arr;
1193  int numkeys;
1194 
1195  constrId = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1196 
1197  /*
1198  * We expect the arrays to be 1-D arrays of the right types; verify that.
1199  * We don't need to use deconstruct_array() since the array data is just
1200  * going to look like a C array of values.
1201  */
1202  adatum = SysCacheGetAttr(CONSTROID, tuple,
1203  Anum_pg_constraint_conkey, &isNull);
1204  if (isNull)
1205  elog(ERROR, "null conkey for constraint %u", constrId);
1206  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1207  if (ARR_NDIM(arr) != 1 ||
1208  ARR_HASNULL(arr) ||
1209  ARR_ELEMTYPE(arr) != INT2OID)
1210  elog(ERROR, "conkey is not a 1-D smallint array");
1211  numkeys = ARR_DIMS(arr)[0];
1212  if (numkeys <= 0 || numkeys > INDEX_MAX_KEYS)
1213  elog(ERROR, "foreign key constraint cannot have %d columns", numkeys);
1214  memcpy(conkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
1215  if ((Pointer) arr != DatumGetPointer(adatum))
1216  pfree(arr); /* free de-toasted copy, if any */
1217 
1218  adatum = SysCacheGetAttr(CONSTROID, tuple,
1219  Anum_pg_constraint_confkey, &isNull);
1220  if (isNull)
1221  elog(ERROR, "null confkey for constraint %u", constrId);
1222  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1223  if (ARR_NDIM(arr) != 1 ||
1224  ARR_DIMS(arr)[0] != numkeys ||
1225  ARR_HASNULL(arr) ||
1226  ARR_ELEMTYPE(arr) != INT2OID)
1227  elog(ERROR, "confkey is not a 1-D smallint array");
1228  memcpy(confkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
1229  if ((Pointer) arr != DatumGetPointer(adatum))
1230  pfree(arr); /* free de-toasted copy, if any */
1231 
1232  if (pf_eq_oprs)
1233  {
1234  adatum = SysCacheGetAttr(CONSTROID, tuple,
1235  Anum_pg_constraint_conpfeqop, &isNull);
1236  if (isNull)
1237  elog(ERROR, "null conpfeqop for constraint %u", constrId);
1238  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1239  /* see TryReuseForeignKey if you change the test below */
1240  if (ARR_NDIM(arr) != 1 ||
1241  ARR_DIMS(arr)[0] != numkeys ||
1242  ARR_HASNULL(arr) ||
1243  ARR_ELEMTYPE(arr) != OIDOID)
1244  elog(ERROR, "conpfeqop is not a 1-D Oid array");
1245  memcpy(pf_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
1246  if ((Pointer) arr != DatumGetPointer(adatum))
1247  pfree(arr); /* free de-toasted copy, if any */
1248  }
1249 
1250  if (pp_eq_oprs)
1251  {
1252  adatum = SysCacheGetAttr(CONSTROID, tuple,
1253  Anum_pg_constraint_conppeqop, &isNull);
1254  if (isNull)
1255  elog(ERROR, "null conppeqop for constraint %u", constrId);
1256  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1257  if (ARR_NDIM(arr) != 1 ||
1258  ARR_DIMS(arr)[0] != numkeys ||
1259  ARR_HASNULL(arr) ||
1260  ARR_ELEMTYPE(arr) != OIDOID)
1261  elog(ERROR, "conppeqop is not a 1-D Oid array");
1262  memcpy(pp_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
1263  if ((Pointer) arr != DatumGetPointer(adatum))
1264  pfree(arr); /* free de-toasted copy, if any */
1265  }
1266 
1267  if (ff_eq_oprs)
1268  {
1269  adatum = SysCacheGetAttr(CONSTROID, tuple,
1270  Anum_pg_constraint_conffeqop, &isNull);
1271  if (isNull)
1272  elog(ERROR, "null conffeqop for constraint %u", constrId);
1273  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1274  if (ARR_NDIM(arr) != 1 ||
1275  ARR_DIMS(arr)[0] != numkeys ||
1276  ARR_HASNULL(arr) ||
1277  ARR_ELEMTYPE(arr) != OIDOID)
1278  elog(ERROR, "conffeqop is not a 1-D Oid array");
1279  memcpy(ff_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
1280  if ((Pointer) arr != DatumGetPointer(adatum))
1281  pfree(arr); /* free de-toasted copy, if any */
1282  }
1283 
1284  if (fk_del_set_cols)
1285  {
1286  adatum = SysCacheGetAttr(CONSTROID, tuple,
1287  Anum_pg_constraint_confdelsetcols, &isNull);
1288  if (isNull)
1289  {
1290  *num_fk_del_set_cols = 0;
1291  }
1292  else
1293  {
1294  int num_delete_cols;
1295 
1296  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1297  if (ARR_NDIM(arr) != 1 ||
1298  ARR_HASNULL(arr) ||
1299  ARR_ELEMTYPE(arr) != INT2OID)
1300  elog(ERROR, "confdelsetcols is not a 1-D smallint array");
1301  num_delete_cols = ARR_DIMS(arr)[0];
1302  memcpy(fk_del_set_cols, ARR_DATA_PTR(arr), num_delete_cols * sizeof(int16));
1303  if ((Pointer) arr != DatumGetPointer(adatum))
1304  pfree(arr); /* free de-toasted copy, if any */
1305 
1306  *num_fk_del_set_cols = num_delete_cols;
1307  }
1308  }
1309 
1310  *numfks = numkeys;
1311 }
#define ARR_NDIM(a)
Definition: array.h:283
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define DatumGetArrayTypeP(X)
Definition: array.h:254
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_HASNULL(a)
Definition: array.h:284
char * Pointer
Definition: c.h:418
#define INDEX_MAX_KEYS
#define DatumGetPointer(X)
Definition: postgres.h:593
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1434

References ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, CONSTROID, DatumGetArrayTypeP, DatumGetPointer, elog, ERROR, GETSTRUCT, INDEX_MAX_KEYS, pfree(), and SysCacheGetAttr().

Referenced by CloneFkReferenced(), CloneFkReferencing(), RelationGetFKeyList(), and ri_LoadConstraintInfo().

◆ get_domain_constraint_oid()

Oid get_domain_constraint_oid ( Oid  typid,
const char *  conname,
bool  missing_ok 
)

Definition at line 1039 of file pg_constraint.c.

1040 {
1041  Relation pg_constraint;
1042  HeapTuple tuple;
1043  SysScanDesc scan;
1044  ScanKeyData skey[3];
1045  Oid conOid = InvalidOid;
1046 
1047  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1048 
1049  ScanKeyInit(&skey[0],
1050  Anum_pg_constraint_conrelid,
1051  BTEqualStrategyNumber, F_OIDEQ,
1053  ScanKeyInit(&skey[1],
1054  Anum_pg_constraint_contypid,
1055  BTEqualStrategyNumber, F_OIDEQ,
1056  ObjectIdGetDatum(typid));
1057  ScanKeyInit(&skey[2],
1058  Anum_pg_constraint_conname,
1059  BTEqualStrategyNumber, F_NAMEEQ,
1060  CStringGetDatum(conname));
1061 
1062  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1063  NULL, 3, skey);
1064 
1065  /* There can be at most one matching row */
1066  if (HeapTupleIsValid(tuple = systable_getnext(scan)))
1067  conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1068 
1069  systable_endscan(scan);
1070 
1071  /* If no such constraint exists, complain */
1072  if (!OidIsValid(conOid) && !missing_ok)
1073  ereport(ERROR,
1074  (errcode(ERRCODE_UNDEFINED_OBJECT),
1075  errmsg("constraint \"%s\" for domain %s does not exist",
1076  conname, format_type_be(typid))));
1077 
1078  table_close(pg_constraint, AccessShareLock);
1079 
1080  return conOid;
1081 }
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ereport(elevel,...)
Definition: elog.h:143
char * format_type_be(Oid type_oid)
Definition: format_type.c:343

References AccessShareLock, BTEqualStrategyNumber, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, format_type_be(), GETSTRUCT, HeapTupleIsValid, InvalidOid, ObjectIdGetDatum, OidIsValid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by get_object_address(), and rename_constraint_internal().

◆ get_primary_key_attnos()

Bitmapset* get_primary_key_attnos ( Oid  relid,
bool  deferrableOk,
Oid constraintOid 
)

Definition at line 1098 of file pg_constraint.c.

1099 {
1100  Bitmapset *pkattnos = NULL;
1101  Relation pg_constraint;
1102  HeapTuple tuple;
1103  SysScanDesc scan;
1104  ScanKeyData skey[1];
1105 
1106  /* Set *constraintOid, to avoid complaints about uninitialized vars */
1107  *constraintOid = InvalidOid;
1108 
1109  /* Scan pg_constraint for constraints of the target rel */
1110  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1111 
1112  ScanKeyInit(&skey[0],
1113  Anum_pg_constraint_conrelid,
1114  BTEqualStrategyNumber, F_OIDEQ,
1115  ObjectIdGetDatum(relid));
1116 
1117  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1118  NULL, 1, skey);
1119 
1120  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1121  {
1123  Datum adatum;
1124  bool isNull;
1125  ArrayType *arr;
1126  int16 *attnums;
1127  int numkeys;
1128  int i;
1129 
1130  /* Skip constraints that are not PRIMARY KEYs */
1131  if (con->contype != CONSTRAINT_PRIMARY)
1132  continue;
1133 
1134  /*
1135  * If the primary key is deferrable, but we've been instructed to
1136  * ignore deferrable constraints, then we might as well give up
1137  * searching, since there can only be a single primary key on a table.
1138  */
1139  if (con->condeferrable && !deferrableOk)
1140  break;
1141 
1142  /* Extract the conkey array, ie, attnums of PK's columns */
1143  adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
1144  RelationGetDescr(pg_constraint), &isNull);
1145  if (isNull)
1146  elog(ERROR, "null conkey for constraint %u",
1147  ((Form_pg_constraint) GETSTRUCT(tuple))->oid);
1148  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1149  numkeys = ARR_DIMS(arr)[0];
1150  if (ARR_NDIM(arr) != 1 ||
1151  numkeys < 0 ||
1152  ARR_HASNULL(arr) ||
1153  ARR_ELEMTYPE(arr) != INT2OID)
1154  elog(ERROR, "conkey is not a 1-D smallint array");
1155  attnums = (int16 *) ARR_DATA_PTR(arr);
1156 
1157  /* Construct the result value */
1158  for (i = 0; i < numkeys; i++)
1159  {
1160  pkattnos = bms_add_member(pkattnos,
1162  }
1163  *constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1164 
1165  /* No need to search further */
1166  break;
1167  }
1168 
1169  systable_endscan(scan);
1170 
1171  table_close(pg_constraint, AccessShareLock);
1172 
1173  return pkattnos;
1174 }
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:788

References AccessShareLock, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, bms_add_member(), BTEqualStrategyNumber, DatumGetArrayTypeP, elog, ERROR, FirstLowInvalidHeapAttributeNumber, GETSTRUCT, heap_getattr(), HeapTupleIsValid, i, InvalidOid, ObjectIdGetDatum, RelationGetDescr, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by check_functional_grouping(), and remove_useless_groupby_columns().

◆ get_relation_constraint_attnos()

Bitmapset* get_relation_constraint_attnos ( Oid  relid,
const char *  conname,
bool  missing_ok,
Oid constraintOid 
)

Definition at line 914 of file pg_constraint.c.

916 {
917  Bitmapset *conattnos = NULL;
918  Relation pg_constraint;
919  HeapTuple tuple;
920  SysScanDesc scan;
921  ScanKeyData skey[3];
922 
923  /* Set *constraintOid, to avoid complaints about uninitialized vars */
924  *constraintOid = InvalidOid;
925 
926  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
927 
928  ScanKeyInit(&skey[0],
929  Anum_pg_constraint_conrelid,
930  BTEqualStrategyNumber, F_OIDEQ,
931  ObjectIdGetDatum(relid));
932  ScanKeyInit(&skey[1],
933  Anum_pg_constraint_contypid,
934  BTEqualStrategyNumber, F_OIDEQ,
936  ScanKeyInit(&skey[2],
937  Anum_pg_constraint_conname,
938  BTEqualStrategyNumber, F_NAMEEQ,
939  CStringGetDatum(conname));
940 
941  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
942  NULL, 3, skey);
943 
944  /* There can be at most one matching row */
945  if (HeapTupleIsValid(tuple = systable_getnext(scan)))
946  {
947  Datum adatum;
948  bool isNull;
949 
950  *constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
951 
952  /* Extract the conkey array, ie, attnums of constrained columns */
953  adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
954  RelationGetDescr(pg_constraint), &isNull);
955  if (!isNull)
956  {
957  ArrayType *arr;
958  int numcols;
959  int16 *attnums;
960  int i;
961 
962  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
963  numcols = ARR_DIMS(arr)[0];
964  if (ARR_NDIM(arr) != 1 ||
965  numcols < 0 ||
966  ARR_HASNULL(arr) ||
967  ARR_ELEMTYPE(arr) != INT2OID)
968  elog(ERROR, "conkey is not a 1-D smallint array");
969  attnums = (int16 *) ARR_DATA_PTR(arr);
970 
971  /* Construct the result value */
972  for (i = 0; i < numcols; i++)
973  {
974  conattnos = bms_add_member(conattnos,
976  }
977  }
978  }
979 
980  systable_endscan(scan);
981 
982  /* If no such constraint exists, complain */
983  if (!OidIsValid(*constraintOid) && !missing_ok)
984  ereport(ERROR,
985  (errcode(ERRCODE_UNDEFINED_OBJECT),
986  errmsg("constraint \"%s\" for table \"%s\" does not exist",
987  conname, get_rel_name(relid))));
988 
989  table_close(pg_constraint, AccessShareLock);
990 
991  return conattnos;
992 }
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1909

References AccessShareLock, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, bms_add_member(), BTEqualStrategyNumber, CStringGetDatum, DatumGetArrayTypeP, elog, ereport, errcode(), errmsg(), ERROR, FirstLowInvalidHeapAttributeNumber, get_rel_name(), GETSTRUCT, heap_getattr(), HeapTupleIsValid, i, InvalidOid, ObjectIdGetDatum, OidIsValid, RelationGetDescr, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by transformOnConflictArbiter().

◆ get_relation_constraint_oid()

Oid get_relation_constraint_oid ( Oid  relid,
const char *  conname,
bool  missing_ok 
)

Definition at line 857 of file pg_constraint.c.

858 {
859  Relation pg_constraint;
860  HeapTuple tuple;
861  SysScanDesc scan;
862  ScanKeyData skey[3];
863  Oid conOid = InvalidOid;
864 
865  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
866 
867  ScanKeyInit(&skey[0],
868  Anum_pg_constraint_conrelid,
869  BTEqualStrategyNumber, F_OIDEQ,
870  ObjectIdGetDatum(relid));
871  ScanKeyInit(&skey[1],
872  Anum_pg_constraint_contypid,
873  BTEqualStrategyNumber, F_OIDEQ,
875  ScanKeyInit(&skey[2],
876  Anum_pg_constraint_conname,
877  BTEqualStrategyNumber, F_NAMEEQ,
878  CStringGetDatum(conname));
879 
880  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
881  NULL, 3, skey);
882 
883  /* There can be at most one matching row */
884  if (HeapTupleIsValid(tuple = systable_getnext(scan)))
885  conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
886 
887  systable_endscan(scan);
888 
889  /* If no such constraint exists, complain */
890  if (!OidIsValid(conOid) && !missing_ok)
891  ereport(ERROR,
892  (errcode(ERRCODE_UNDEFINED_OBJECT),
893  errmsg("constraint \"%s\" for table \"%s\" does not exist",
894  conname, get_rel_name(relid))));
895 
896  table_close(pg_constraint, AccessShareLock);
897 
898  return conOid;
899 }

References AccessShareLock, BTEqualStrategyNumber, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, get_rel_name(), GETSTRUCT, HeapTupleIsValid, InvalidOid, ObjectIdGetDatum, OidIsValid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by expandTableLikeClause(), get_object_address_relobject(), and rename_constraint_internal().

◆ get_relation_idx_constraint_oid()

Oid get_relation_idx_constraint_oid ( Oid  relationId,
Oid  indexId 
)

Definition at line 999 of file pg_constraint.c.

1000 {
1001  Relation pg_constraint;
1002  SysScanDesc scan;
1003  ScanKeyData key;
1004  HeapTuple tuple;
1005  Oid constraintId = InvalidOid;
1006 
1007  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1008 
1009  ScanKeyInit(&key,
1010  Anum_pg_constraint_conrelid,
1012  F_OIDEQ,
1013  ObjectIdGetDatum(relationId));
1014  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
1015  true, NULL, 1, &key);
1016  while ((tuple = systable_getnext(scan)) != NULL)
1017  {
1018  Form_pg_constraint constrForm;
1019 
1020  constrForm = (Form_pg_constraint) GETSTRUCT(tuple);
1021  if (constrForm->conindid == indexId)
1022  {
1023  constraintId = constrForm->oid;
1024  break;
1025  }
1026  }
1027  systable_endscan(scan);
1028 
1029  table_close(pg_constraint, AccessShareLock);
1030  return constraintId;
1031 }

References AccessShareLock, BTEqualStrategyNumber, GETSTRUCT, InvalidOid, sort-test::key, ObjectIdGetDatum, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ATExecAttachPartitionIdx(), AttachPartitionEnsureIndexes(), DefineIndex(), and DetachPartitionFinalize().

◆ RemoveConstraintById()

void RemoveConstraintById ( Oid  conId)

Definition at line 576 of file pg_constraint.c.

577 {
578  Relation conDesc;
579  HeapTuple tup;
580  Form_pg_constraint con;
581 
582  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
583 
585  if (!HeapTupleIsValid(tup)) /* should not happen */
586  elog(ERROR, "cache lookup failed for constraint %u", conId);
587  con = (Form_pg_constraint) GETSTRUCT(tup);
588 
589  /*
590  * Special processing depending on what the constraint is for.
591  */
592  if (OidIsValid(con->conrelid))
593  {
594  Relation rel;
595 
596  /*
597  * If the constraint is for a relation, open and exclusive-lock the
598  * relation it's for.
599  */
600  rel = table_open(con->conrelid, AccessExclusiveLock);
601 
602  /*
603  * We need to update the relchecks count if it is a check constraint
604  * being dropped. This update will force backends to rebuild relcache
605  * entries when we commit.
606  */
607  if (con->contype == CONSTRAINT_CHECK)
608  {
609  Relation pgrel;
610  HeapTuple relTup;
611  Form_pg_class classForm;
612 
613  pgrel = table_open(RelationRelationId, RowExclusiveLock);
614  relTup = SearchSysCacheCopy1(RELOID,
615  ObjectIdGetDatum(con->conrelid));
616  if (!HeapTupleIsValid(relTup))
617  elog(ERROR, "cache lookup failed for relation %u",
618  con->conrelid);
619  classForm = (Form_pg_class) GETSTRUCT(relTup);
620 
621  if (classForm->relchecks == 0) /* should not happen */
622  elog(ERROR, "relation \"%s\" has relchecks = 0",
624  classForm->relchecks--;
625 
626  CatalogTupleUpdate(pgrel, &relTup->t_self, relTup);
627 
628  heap_freetuple(relTup);
629 
631  }
632 
633  /* Keep lock on constraint's rel until end of xact */
634  table_close(rel, NoLock);
635  }
636  else if (OidIsValid(con->contypid))
637  {
638  /*
639  * XXX for now, do nothing special when dropping a domain constraint
640  *
641  * Probably there should be some form of locking on the domain type,
642  * but we have no such concept at the moment.
643  */
644  }
645  else
646  elog(ERROR, "constraint %u is not of a known type", conId);
647 
648  /* Fry the constraint itself */
649  CatalogTupleDelete(conDesc, &tup->t_self);
650 
651  /* Clean up */
652  ReleaseSysCache(tup);
653  table_close(conDesc, RowExclusiveLock);
654 }
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define RelationGetRelationName(relation)
Definition: rel.h:523
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:179
@ RELOID
Definition: syscache.h:89

References AccessExclusiveLock, CatalogTupleDelete(), CatalogTupleUpdate(), CONSTROID, elog, ERROR, GETSTRUCT, heap_freetuple(), HeapTupleIsValid, NoLock, ObjectIdGetDatum, OidIsValid, RelationGetRelationName, ReleaseSysCache(), RELOID, RowExclusiveLock, SearchSysCache1(), SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

◆ RenameConstraintById()

void RenameConstraintById ( Oid  conId,
const char *  newname 
)

Definition at line 667 of file pg_constraint.c.

668 {
669  Relation conDesc;
670  HeapTuple tuple;
671  Form_pg_constraint con;
672 
673  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
674 
676  if (!HeapTupleIsValid(tuple))
677  elog(ERROR, "cache lookup failed for constraint %u", conId);
678  con = (Form_pg_constraint) GETSTRUCT(tuple);
679 
680  /*
681  * For user-friendliness, check whether the name is already in use.
682  */
683  if (OidIsValid(con->conrelid) &&
685  con->conrelid,
686  newname))
687  ereport(ERROR,
689  errmsg("constraint \"%s\" for relation \"%s\" already exists",
690  newname, get_rel_name(con->conrelid))));
691  if (OidIsValid(con->contypid) &&
693  con->contypid,
694  newname))
695  ereport(ERROR,
697  errmsg("constraint \"%s\" for domain %s already exists",
698  newname, format_type_be(con->contypid))));
699 
700  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
701  namestrcpy(&(con->conname), newname);
702 
703  CatalogTupleUpdate(conDesc, &tuple->t_self, tuple);
704 
705  InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
706 
707  heap_freetuple(tuple);
708  table_close(conDesc, RowExclusiveLock);
709 }
bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId, const char *conname)
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

References CatalogTupleUpdate(), CONSTRAINT_DOMAIN, CONSTRAINT_RELATION, ConstraintNameIsUsed(), CONSTROID, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), get_rel_name(), GETSTRUCT, heap_freetuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, namestrcpy(), ObjectIdGetDatum, OidIsValid, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), and table_open().

Referenced by rename_constraint_internal(), and RenameRelationInternal().

Variable Documentation

◆ FormData_pg_constraint

FormData_pg_constraint

Definition at line 158 of file pg_constraint.h.