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 712 of file pg_constraint.c.

714 {
715  Relation conRel;
716  ScanKeyData key[2];
717  SysScanDesc scan;
718  HeapTuple tup;
719 
720  conRel = table_open(ConstraintRelationId, RowExclusiveLock);
721 
722  ScanKeyInit(&key[0],
723  Anum_pg_constraint_conrelid,
724  BTEqualStrategyNumber, F_OIDEQ,
725  ObjectIdGetDatum(isType ? InvalidOid : ownerId));
726  ScanKeyInit(&key[1],
727  Anum_pg_constraint_contypid,
728  BTEqualStrategyNumber, F_OIDEQ,
729  ObjectIdGetDatum(isType ? ownerId : InvalidOid));
730 
731  scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId, true,
732  NULL, 2, key);
733 
734  while (HeapTupleIsValid((tup = systable_getnext(scan))))
735  {
737  ObjectAddress thisobj;
738 
739  ObjectAddressSet(thisobj, ConstraintRelationId, conform->oid);
740 
741  if (object_address_present(&thisobj, objsMoved))
742  continue;
743 
744  /* Don't update if the object is already part of the namespace */
745  if (conform->connamespace == oldNspId && oldNspId != newNspId)
746  {
747  tup = heap_copytuple(tup);
748  conform = (Form_pg_constraint) GETSTRUCT(tup);
749 
750  conform->connamespace = newNspId;
751 
752  CatalogTupleUpdate(conRel, &tup->t_self, tup);
753 
754  /*
755  * Note: currently, the constraint will not have its own
756  * dependency on the namespace, so we don't need to do
757  * changeDependencyFor().
758  */
759  }
760 
761  InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
762 
763  add_exact_object_address(&thisobj, objsMoved);
764  }
765 
766  systable_endscan(scan);
767 
768  table_close(conRel, RowExclusiveLock);
769 }
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2641
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2581
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
FormData_pg_constraint * Form_pg_constraint
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
#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:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

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  int16 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:477
#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:725

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 1324 of file pg_constraint.c.

1328 {
1329  Bitmapset *pkattnos;
1330  Bitmapset *groupbyattnos;
1331  Oid constraintOid;
1332  ListCell *gl;
1333 
1334  /* If the rel has no PK, then we can't prove functional dependency */
1335  pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
1336  if (pkattnos == NULL)
1337  return false;
1338 
1339  /* Identify all the rel's columns that appear in grouping_columns */
1340  groupbyattnos = NULL;
1341  foreach(gl, grouping_columns)
1342  {
1343  Var *gvar = (Var *) lfirst(gl);
1344 
1345  if (IsA(gvar, Var) &&
1346  gvar->varno == varno &&
1347  gvar->varlevelsup == varlevelsup)
1348  groupbyattnos = bms_add_member(groupbyattnos,
1350  }
1351 
1352  if (bms_is_subset(pkattnos, groupbyattnos))
1353  {
1354  /* The PK is a subset of grouping_columns, so we win */
1355  *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
1356  return true;
1357  }
1358 
1359  return false;
1360 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:332
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:755
List * lappend_oid(List *list, Oid datum)
Definition: list.c:374
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
Bitmapset * get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
#define lfirst(lc)
Definition: pg_list.h:172
Definition: primnodes.h:226
AttrNumber varattno
Definition: primnodes.h:238
int varno
Definition: primnodes.h:233
Index varlevelsup
Definition: primnodes.h:258
#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 499 of file pg_constraint.c.

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

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 445 of file pg_constraint.c.

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

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 400 of file pg_constraint.c.

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

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 781 of file pg_constraint.c.

784 {
785  Relation constrRel;
786  Form_pg_constraint constrForm;
787  HeapTuple tuple,
788  newtup;
789  ObjectAddress depender;
790  ObjectAddress referenced;
791 
792  constrRel = table_open(ConstraintRelationId, RowExclusiveLock);
793  tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(childConstrId));
794  if (!HeapTupleIsValid(tuple))
795  elog(ERROR, "cache lookup failed for constraint %u", childConstrId);
796  newtup = heap_copytuple(tuple);
797  constrForm = (Form_pg_constraint) GETSTRUCT(newtup);
798  if (OidIsValid(parentConstrId))
799  {
800  /* don't allow setting parent for a constraint that already has one */
801  Assert(constrForm->coninhcount == 0);
802  if (constrForm->conparentid != InvalidOid)
803  elog(ERROR, "constraint %u already has a parent constraint",
804  childConstrId);
805 
806  constrForm->conislocal = false;
807  constrForm->coninhcount++;
808  if (constrForm->coninhcount < 0)
809  ereport(ERROR,
810  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
811  errmsg("too many inheritance parents"));
812  constrForm->conparentid = parentConstrId;
813 
814  CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
815 
816  ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
817 
818  ObjectAddressSet(referenced, ConstraintRelationId, parentConstrId);
819  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
820 
821  ObjectAddressSet(referenced, RelationRelationId, childTableId);
822  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
823  }
824  else
825  {
826  constrForm->coninhcount--;
827  constrForm->conislocal = true;
828  constrForm->conparentid = InvalidOid;
829 
830  /* Make sure there's no further inheritance. */
831  Assert(constrForm->coninhcount == 0);
832 
833  CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
834 
835  deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
836  ConstraintRelationId,
838  deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
839  RelationRelationId,
841  }
842 
843  ReleaseSysCache(tuple);
844  table_close(constrRel, RowExclusiveLock);
845 }
#define OidIsValid(objectId)
Definition: c.h:759
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
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:350
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:866
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:818
@ CONSTROID
Definition: syscache.h:53

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

References add_exact_object_address(), Assert(), BoolGetDatum(), CatalogTupleInsert(), CharGetDatum(), ObjectAddress::classId, construct_array_builtin(), CStringGetTextDatum, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, free_object_addresses(), GetNewOidWithIndex(), heap_form_tuple(), i, Int16GetDatum(), 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 1192 of file pg_constraint.c.

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

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

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 1047 of file pg_constraint.c.

1048 {
1049  Relation pg_constraint;
1050  HeapTuple tuple;
1051  SysScanDesc scan;
1052  ScanKeyData skey[3];
1053  Oid conOid = InvalidOid;
1054 
1055  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1056 
1057  ScanKeyInit(&skey[0],
1058  Anum_pg_constraint_conrelid,
1059  BTEqualStrategyNumber, F_OIDEQ,
1061  ScanKeyInit(&skey[1],
1062  Anum_pg_constraint_contypid,
1063  BTEqualStrategyNumber, F_OIDEQ,
1064  ObjectIdGetDatum(typid));
1065  ScanKeyInit(&skey[2],
1066  Anum_pg_constraint_conname,
1067  BTEqualStrategyNumber, F_NAMEEQ,
1068  CStringGetDatum(conname));
1069 
1070  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1071  NULL, 3, skey);
1072 
1073  /* There can be at most one matching row */
1074  if (HeapTupleIsValid(tuple = systable_getnext(scan)))
1075  conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1076 
1077  systable_endscan(scan);
1078 
1079  /* If no such constraint exists, complain */
1080  if (!OidIsValid(conOid) && !missing_ok)
1081  ereport(ERROR,
1082  (errcode(ERRCODE_UNDEFINED_OBJECT),
1083  errmsg("constraint \"%s\" for domain %s does not exist",
1084  conname, format_type_be(typid))));
1085 
1086  table_close(pg_constraint, AccessShareLock);
1087 
1088  return conOid;
1089 }
char * format_type_be(Oid type_oid)
Definition: format_type.c:339

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 1106 of file pg_constraint.c.

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

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 911 of file pg_constraint.c.

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

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 854 of file pg_constraint.c.

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

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 1000 of file pg_constraint.c.

1001 {
1002  Relation pg_constraint;
1003  SysScanDesc scan;
1004  ScanKeyData key;
1005  HeapTuple tuple;
1006  Oid constraintId = InvalidOid;
1007 
1008  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1009 
1010  ScanKeyInit(&key,
1011  Anum_pg_constraint_conrelid,
1013  F_OIDEQ,
1014  ObjectIdGetDatum(relationId));
1015  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
1016  true, NULL, 1, &key);
1017  while ((tuple = systable_getnext(scan)) != NULL)
1018  {
1019  Form_pg_constraint constrForm;
1020 
1021  constrForm = (Form_pg_constraint) GETSTRUCT(tuple);
1022 
1023  /* See above */
1024  if (constrForm->contype != CONSTRAINT_PRIMARY &&
1025  constrForm->contype != CONSTRAINT_UNIQUE &&
1026  constrForm->contype != CONSTRAINT_EXCLUSION)
1027  continue;
1028 
1029  if (constrForm->conindid == indexId)
1030  {
1031  constraintId = constrForm->oid;
1032  break;
1033  }
1034  }
1035  systable_endscan(scan);
1036 
1037  table_close(pg_constraint, AccessShareLock);
1038  return constraintId;
1039 }

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 569 of file pg_constraint.c.

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

661 {
662  Relation conDesc;
663  HeapTuple tuple;
664  Form_pg_constraint con;
665 
666  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
667 
669  if (!HeapTupleIsValid(tuple))
670  elog(ERROR, "cache lookup failed for constraint %u", conId);
671  con = (Form_pg_constraint) GETSTRUCT(tuple);
672 
673  /*
674  * For user-friendliness, check whether the name is already in use.
675  */
676  if (OidIsValid(con->conrelid) &&
678  con->conrelid,
679  newname))
680  ereport(ERROR,
682  errmsg("constraint \"%s\" for relation \"%s\" already exists",
683  newname, get_rel_name(con->conrelid))));
684  if (OidIsValid(con->contypid) &&
686  con->contypid,
687  newname))
688  ereport(ERROR,
690  errmsg("constraint \"%s\" for domain %s already exists",
691  newname, format_type_be(con->contypid))));
692 
693  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
694  namestrcpy(&(con->conname), newname);
695 
696  CatalogTupleUpdate(conDesc, &tuple->t_self, tuple);
697 
698  InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
699 
700  heap_freetuple(tuple);
701  table_close(conDesc, RowExclusiveLock);
702 }
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.