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, pg_constraint, btree(conname name_ops, connamespace oid_ops))
 
 DECLARE_UNIQUE_INDEX (pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, pg_constraint, btree(conrelid oid_ops, contypid oid_ops, conname name_ops))
 
 DECLARE_INDEX (pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, pg_constraint, btree(contypid oid_ops))
 
 DECLARE_UNIQUE_INDEX_PKEY (pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops))
 
 DECLARE_INDEX (pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, pg_constraint, btree(conparentid oid_ops))
 
 MAKE_SYSCACHE (CONSTROID, pg_constraint_oid_index, 16)
 
 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, int16 conInhCount, bool conNoInherit, bool conPeriod, bool is_internal)
 
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)
 
HeapTuple findNotNullConstraintAttnum (Oid relid, AttrNumber attnum)
 
HeapTuple findNotNullConstraint (Oid relid, const char *colname)
 
HeapTuple findDomainNotNullConstraint (Oid typid)
 
AttrNumber extractNotNullColumn (HeapTuple constrTup)
 
bool AdjustNotNullInheritance (Oid relid, AttrNumber attnum, bool is_local, bool is_no_inherit)
 
ListRelationGetNotNullConstraints (Oid relid, bool cooked, bool include_noinh)
 
void RemoveConstraintById (Oid conId)
 
void RenameConstraintById (Oid conId, const char *newname)
 
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)
 
void FindFKPeriodOpers (Oid opclass, Oid *containedbyoperoid, Oid *aggedcontainedbyoperoid)
 
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 174 of file pg_constraint.h.

Enumeration Type Documentation

◆ ConstraintCategory

Enumerator
CONSTRAINT_RELATION 
CONSTRAINT_DOMAIN 
CONSTRAINT_ASSERTION 

Definition at line 212 of file pg_constraint.h.

213 {
216  CONSTRAINT_ASSERTION, /* for future expansion */
ConstraintCategory
@ CONSTRAINT_DOMAIN
@ CONSTRAINT_RELATION
@ CONSTRAINT_ASSERTION

Function Documentation

◆ AdjustNotNullInheritance()

bool AdjustNotNullInheritance ( Oid  relid,
AttrNumber  attnum,
bool  is_local,
bool  is_no_inherit 
)

Definition at line 724 of file pg_constraint.c.

726 {
727  HeapTuple tup;
728 
729  tup = findNotNullConstraintAttnum(relid, attnum);
730  if (HeapTupleIsValid(tup))
731  {
732  Relation pg_constraint;
733  Form_pg_constraint conform;
734  bool changed = false;
735 
736  pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
737  conform = (Form_pg_constraint) GETSTRUCT(tup);
738 
739  /*
740  * If the NO INHERIT flag we're asked for doesn't match what the
741  * existing constraint has, throw an error.
742  */
743  if (is_no_inherit != conform->connoinherit)
744  ereport(ERROR,
745  errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
746  errmsg("cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"",
747  NameStr(conform->conname), get_rel_name(relid)));
748 
749  if (!is_local)
750  {
751  if (pg_add_s16_overflow(conform->coninhcount, 1,
752  &conform->coninhcount))
753  ereport(ERROR,
754  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
755  errmsg("too many inheritance parents"));
756  changed = true;
757  }
758  else if (!conform->conislocal)
759  {
760  conform->conislocal = true;
761  changed = true;
762  }
763 
764  if (changed)
765  CatalogTupleUpdate(pg_constraint, &tup->t_self, tup);
766 
767  table_close(pg_constraint, RowExclusiveLock);
768 
769  return true;
770  }
771 
772  return false;
773 }
#define NameStr(name)
Definition: c.h:725
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#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
static bool pg_add_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:67
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
int16 attnum
Definition: pg_attribute.h:74
HeapTuple findNotNullConstraintAttnum(Oid relid, AttrNumber attnum)
FormData_pg_constraint * Form_pg_constraint
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 attnum, CatalogTupleUpdate(), ereport, errcode(), errmsg(), ERROR, findNotNullConstraintAttnum(), get_rel_name(), GETSTRUCT, HeapTupleIsValid, NameStr, pg_add_s16_overflow(), RowExclusiveLock, HeapTupleData::t_self, table_close(), and table_open().

Referenced by AddRelationNewConstraints().

◆ AlterConstraintNamespaces()

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

Definition at line 1005 of file pg_constraint.c.

1007 {
1008  Relation conRel;
1009  ScanKeyData key[2];
1010  SysScanDesc scan;
1011  HeapTuple tup;
1012 
1013  conRel = table_open(ConstraintRelationId, RowExclusiveLock);
1014 
1015  ScanKeyInit(&key[0],
1016  Anum_pg_constraint_conrelid,
1017  BTEqualStrategyNumber, F_OIDEQ,
1018  ObjectIdGetDatum(isType ? InvalidOid : ownerId));
1019  ScanKeyInit(&key[1],
1020  Anum_pg_constraint_contypid,
1021  BTEqualStrategyNumber, F_OIDEQ,
1022  ObjectIdGetDatum(isType ? ownerId : InvalidOid));
1023 
1024  scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId, true,
1025  NULL, 2, key);
1026 
1027  while (HeapTupleIsValid((tup = systable_getnext(scan))))
1028  {
1030  ObjectAddress thisobj;
1031 
1032  ObjectAddressSet(thisobj, ConstraintRelationId, conform->oid);
1033 
1034  if (object_address_present(&thisobj, objsMoved))
1035  continue;
1036 
1037  /* Don't update if the object is already part of the namespace */
1038  if (conform->connamespace == oldNspId && oldNspId != newNspId)
1039  {
1040  tup = heap_copytuple(tup);
1041  conform = (Form_pg_constraint) GETSTRUCT(tup);
1042 
1043  conform->connamespace = newNspId;
1044 
1045  CatalogTupleUpdate(conRel, &tup->t_self, tup);
1046 
1047  /*
1048  * Note: currently, the constraint will not have its own
1049  * dependency on the namespace, so we don't need to do
1050  * changeDependencyFor().
1051  */
1052  }
1053 
1054  InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
1055 
1056  add_exact_object_address(&thisobj, objsMoved);
1057  }
1058 
1059  systable_endscan(scan);
1060 
1061  table_close(conRel, RowExclusiveLock);
1062 }
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2593
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2533
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:511
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:776
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
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

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  /*
111  * For primary keys, unique constraints, and foreign keys, signifies the
112  * last column uses overlaps instead of equals.
113  */
114  bool conperiod;
115 
116 #ifdef CATALOG_VARLEN /* variable-length fields start here */
117 
118  /*
119  * Columns of conrelid that the constraint applies to, if known (this is
120  * NULL for trigger constraints)
121  */
122  int16 conkey[1];
123 
124  /*
125  * If a foreign key, the referenced columns of confrelid
126  */
127  int16 confkey[1];
128 
129  /*
130  * If a foreign key, the OIDs of the PK = FK equality/overlap operators
131  * for each column of the constraint
132  */
133  Oid conpfeqop[1] BKI_LOOKUP(pg_operator);
134 
135  /*
136  * If a foreign key, the OIDs of the PK = PK equality/overlap operators
137  * for each column of the constraint (i.e., equality for the referenced
138  * columns)
139  */
140  Oid conppeqop[1] BKI_LOOKUP(pg_operator);
141 
142  /*
143  * If a foreign key, the OIDs of the FK = FK equality/overlap operators
144  * for each column of the constraint (i.e., equality for the referencing
145  * columns)
146  */
147  Oid conffeqop[1] BKI_LOOKUP(pg_operator);
148 
149  /*
150  * If a foreign key with an ON DELETE SET NULL/DEFAULT action, the subset
151  * of conkey to updated. If null, all columns are updated.
152  */
153  int16 confdelsetcols[1];
154 
155  /*
156  * If an exclusion constraint, the OIDs of the exclusion operators for
157  * each column of the constraint. Also set for unique constraints/primary
158  * keys using WITHOUT OVERLAPS.
159  */
160  Oid conexclop[1] BKI_LOOKUP(pg_operator);
161 
162  /*
163  * If a check constraint, nodeToString representation of expression
164  */
165  pg_node_tree conbin;
166 #endif
signed short int16
Definition: c.h:481
#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:720

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

1679 {
1680  Bitmapset *pkattnos;
1681  Bitmapset *groupbyattnos;
1682  Oid constraintOid;
1683  ListCell *gl;
1684 
1685  /* If the rel has no PK, then we can't prove functional dependency */
1686  pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
1687  if (pkattnos == NULL)
1688  return false;
1689 
1690  /* Identify all the rel's columns that appear in grouping_columns */
1691  groupbyattnos = NULL;
1692  foreach(gl, grouping_columns)
1693  {
1694  Var *gvar = (Var *) lfirst(gl);
1695 
1696  if (IsA(gvar, Var) &&
1697  gvar->varno == varno &&
1698  gvar->varlevelsup == varlevelsup)
1699  groupbyattnos = bms_add_member(groupbyattnos,
1701  }
1702 
1703  if (bms_is_subset(pkattnos, groupbyattnos))
1704  {
1705  /* The PK is a subset of grouping_columns, so we win */
1706  *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
1707  return true;
1708  }
1709 
1710  return false;
1711 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
Bitmapset * get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
#define lfirst(lc)
Definition: pg_list.h:172
Definition: primnodes.h:248
AttrNumber varattno
Definition: primnodes.h:260
int varno
Definition: primnodes.h:255
Index varlevelsup
Definition: primnodes.h:280
#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 substitute_grouped_columns_mutator().

◆ ChooseConstraintName()

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

Definition at line 502 of file pg_constraint.c.

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

◆ ConstraintNameExists()

bool ConstraintNameExists ( const char *  conname,
Oid  namespaceid 
)

Definition at line 448 of file pg_constraint.c.

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

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

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

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 addFkConstraint(), AddRelationNewConstraints(), ATExecAddConstraint(), domainAddCheckConstraint(), domainAddNotNullConstraint(), index_create(), and RenameConstraintById().

◆ ConstraintSetParentConstraint()

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

Definition at line 1074 of file pg_constraint.c.

1077 {
1078  Relation constrRel;
1079  Form_pg_constraint constrForm;
1080  HeapTuple tuple,
1081  newtup;
1082  ObjectAddress depender;
1083  ObjectAddress referenced;
1084 
1085  constrRel = table_open(ConstraintRelationId, RowExclusiveLock);
1086  tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(childConstrId));
1087  if (!HeapTupleIsValid(tuple))
1088  elog(ERROR, "cache lookup failed for constraint %u", childConstrId);
1089  newtup = heap_copytuple(tuple);
1090  constrForm = (Form_pg_constraint) GETSTRUCT(newtup);
1091  if (OidIsValid(parentConstrId))
1092  {
1093  /* don't allow setting parent for a constraint that already has one */
1094  Assert(constrForm->coninhcount == 0);
1095  if (constrForm->conparentid != InvalidOid)
1096  elog(ERROR, "constraint %u already has a parent constraint",
1097  childConstrId);
1098 
1099  constrForm->conislocal = false;
1100  if (pg_add_s16_overflow(constrForm->coninhcount, 1,
1101  &constrForm->coninhcount))
1102  ereport(ERROR,
1103  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1104  errmsg("too many inheritance parents"));
1105 
1106  constrForm->conparentid = parentConstrId;
1107 
1108  CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
1109 
1110  ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
1111 
1112  ObjectAddressSet(referenced, ConstraintRelationId, parentConstrId);
1113  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
1114 
1115  ObjectAddressSet(referenced, RelationRelationId, childTableId);
1116  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
1117  }
1118  else
1119  {
1120  constrForm->coninhcount--;
1121  constrForm->conislocal = true;
1122  constrForm->conparentid = InvalidOid;
1123 
1124  /* Make sure there's no further inheritance. */
1125  Assert(constrForm->coninhcount == 0);
1126 
1127  CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
1128 
1129  deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
1130  ConstraintRelationId,
1132  deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
1133  RelationRelationId,
1135  }
1136 
1137  ReleaseSysCache(tuple);
1138  table_close(constrRel, RowExclusiveLock);
1139 }
#define Assert(condition)
Definition: c.h:837
#define OidIsValid(objectId)
Definition: c.h:754
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
#define elog(elevel,...)
Definition: elog.h:225
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:45
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:351
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

References Assert, CatalogTupleUpdate(), deleteDependencyRecordsForClass(), DEPENDENCY_PARTITION_PRI, DEPENDENCY_PARTITION_SEC, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, heap_copytuple(), HeapTupleIsValid, InvalidOid, ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, pg_add_s16_overflow(), 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,
int16  conInhCount,
bool  conNoInherit,
bool  conPeriod,
bool  is_internal 
)

Definition at line 51 of file pg_constraint.c.

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

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 addFkConstraint(), CreateTriggerFiringOn(), domainAddCheckConstraint(), domainAddNotNullConstraint(), index_constraint_create(), StoreRelCheck(), and StoreRelNotNull().

◆ 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  ,
pg_constraint  ,
btree(conname name_ops, connamespace oid_ops)   
)

◆ DECLARE_INDEX() [2/3]

DECLARE_INDEX ( pg_constraint_conparentid_index  ,
2579  ,
ConstraintParentIndexId  ,
pg_constraint  ,
btree(conparentid oid_ops)   
)

◆ DECLARE_INDEX() [3/3]

DECLARE_INDEX ( pg_constraint_contypid_index  ,
2666  ,
ConstraintTypidIndexId  ,
pg_constraint  ,
btree(contypid oid_ops)   
)

◆ DECLARE_TOAST()

DECLARE_TOAST ( pg_constraint  ,
2832  ,
2833   
)

◆ DECLARE_UNIQUE_INDEX()

DECLARE_UNIQUE_INDEX ( pg_constraint_conrelid_contypid_conname_index  ,
2665  ,
ConstraintRelidTypidNameIndexId  ,
pg_constraint  ,
btree(conrelid oid_ops, contypid oid_ops, conname name_ops)   
)

◆ DECLARE_UNIQUE_INDEX_PKEY()

DECLARE_UNIQUE_INDEX_PKEY ( pg_constraint_oid_index  ,
2667  ,
ConstraintOidIndexId  ,
pg_constraint  ,
btree(oid 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 1486 of file pg_constraint.c.

1490 {
1491  Datum adatum;
1492  bool isNull;
1493  ArrayType *arr;
1494  int numkeys;
1495 
1496  /*
1497  * We expect the arrays to be 1-D arrays of the right types; verify that.
1498  * We don't need to use deconstruct_array() since the array data is just
1499  * going to look like a C array of values.
1500  */
1501  adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
1502  Anum_pg_constraint_conkey);
1503  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1504  if (ARR_NDIM(arr) != 1 ||
1505  ARR_HASNULL(arr) ||
1506  ARR_ELEMTYPE(arr) != INT2OID)
1507  elog(ERROR, "conkey is not a 1-D smallint array");
1508  numkeys = ARR_DIMS(arr)[0];
1509  if (numkeys <= 0 || numkeys > INDEX_MAX_KEYS)
1510  elog(ERROR, "foreign key constraint cannot have %d columns", numkeys);
1511  memcpy(conkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
1512  if ((Pointer) arr != DatumGetPointer(adatum))
1513  pfree(arr); /* free de-toasted copy, if any */
1514 
1515  adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
1516  Anum_pg_constraint_confkey);
1517  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1518  if (ARR_NDIM(arr) != 1 ||
1519  ARR_DIMS(arr)[0] != numkeys ||
1520  ARR_HASNULL(arr) ||
1521  ARR_ELEMTYPE(arr) != INT2OID)
1522  elog(ERROR, "confkey is not a 1-D smallint array");
1523  memcpy(confkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
1524  if ((Pointer) arr != DatumGetPointer(adatum))
1525  pfree(arr); /* free de-toasted copy, if any */
1526 
1527  if (pf_eq_oprs)
1528  {
1529  adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
1530  Anum_pg_constraint_conpfeqop);
1531  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1532  /* see TryReuseForeignKey if you change the test below */
1533  if (ARR_NDIM(arr) != 1 ||
1534  ARR_DIMS(arr)[0] != numkeys ||
1535  ARR_HASNULL(arr) ||
1536  ARR_ELEMTYPE(arr) != OIDOID)
1537  elog(ERROR, "conpfeqop is not a 1-D Oid array");
1538  memcpy(pf_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
1539  if ((Pointer) arr != DatumGetPointer(adatum))
1540  pfree(arr); /* free de-toasted copy, if any */
1541  }
1542 
1543  if (pp_eq_oprs)
1544  {
1545  adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
1546  Anum_pg_constraint_conppeqop);
1547  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1548  if (ARR_NDIM(arr) != 1 ||
1549  ARR_DIMS(arr)[0] != numkeys ||
1550  ARR_HASNULL(arr) ||
1551  ARR_ELEMTYPE(arr) != OIDOID)
1552  elog(ERROR, "conppeqop is not a 1-D Oid array");
1553  memcpy(pp_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
1554  if ((Pointer) arr != DatumGetPointer(adatum))
1555  pfree(arr); /* free de-toasted copy, if any */
1556  }
1557 
1558  if (ff_eq_oprs)
1559  {
1560  adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
1561  Anum_pg_constraint_conffeqop);
1562  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1563  if (ARR_NDIM(arr) != 1 ||
1564  ARR_DIMS(arr)[0] != numkeys ||
1565  ARR_HASNULL(arr) ||
1566  ARR_ELEMTYPE(arr) != OIDOID)
1567  elog(ERROR, "conffeqop is not a 1-D Oid array");
1568  memcpy(ff_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
1569  if ((Pointer) arr != DatumGetPointer(adatum))
1570  pfree(arr); /* free de-toasted copy, if any */
1571  }
1572 
1573  if (fk_del_set_cols)
1574  {
1575  adatum = SysCacheGetAttr(CONSTROID, tuple,
1576  Anum_pg_constraint_confdelsetcols, &isNull);
1577  if (isNull)
1578  {
1579  *num_fk_del_set_cols = 0;
1580  }
1581  else
1582  {
1583  int num_delete_cols;
1584 
1585  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1586  if (ARR_NDIM(arr) != 1 ||
1587  ARR_HASNULL(arr) ||
1588  ARR_ELEMTYPE(arr) != INT2OID)
1589  elog(ERROR, "confdelsetcols is not a 1-D smallint array");
1590  num_delete_cols = ARR_DIMS(arr)[0];
1591  memcpy(fk_del_set_cols, ARR_DATA_PTR(arr), num_delete_cols * sizeof(int16));
1592  if ((Pointer) arr != DatumGetPointer(adatum))
1593  pfree(arr); /* free de-toasted copy, if any */
1594 
1595  *num_fk_del_set_cols = num_delete_cols;
1596  }
1597  }
1598 
1599  *numfks = numkeys;
1600 }
#define ARR_NDIM(a)
Definition: array.h:290
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
#define ARR_DIMS(a)
Definition: array.h:294
#define ARR_HASNULL(a)
Definition: array.h:291
char * Pointer
Definition: c.h:472
#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:600
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:631

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

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

◆ extractNotNullColumn()

AttrNumber extractNotNullColumn ( HeapTuple  constrTup)

Definition at line 689 of file pg_constraint.c.

690 {
691  Datum adatum;
692  ArrayType *arr;
693 
694  /* only tuples for not-null constraints should be given */
695  Assert(((Form_pg_constraint) GETSTRUCT(constrTup))->contype == CONSTRAINT_NOTNULL);
696 
697  adatum = SysCacheGetAttrNotNull(CONSTROID, constrTup,
698  Anum_pg_constraint_conkey);
699  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
700  if (ARR_NDIM(arr) != 1 ||
701  ARR_HASNULL(arr) ||
702  ARR_ELEMTYPE(arr) != INT2OID ||
703  ARR_DIMS(arr)[0] != 1)
704  elog(ERROR, "conkey is not a 1-D smallint array");
705 
706  /* We leak the detoasted datum, but we don't care */
707 
708  return ((AttrNumber *) ARR_DATA_PTR(arr))[0];
709 }
int16 AttrNumber
Definition: attnum.h:21

References ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, Assert, DatumGetArrayTypeP, elog, ERROR, GETSTRUCT, and SysCacheGetAttrNotNull().

Referenced by dropconstraint_internal(), findNotNullConstraintAttnum(), MergeConstraintsIntoExisting(), pg_get_constraintdef_worker(), RelationGetNotNullConstraints(), and RemoveInheritance().

◆ findDomainNotNullConstraint()

HeapTuple findDomainNotNullConstraint ( Oid  typid)

Definition at line 645 of file pg_constraint.c.

646 {
647  Relation pg_constraint;
648  HeapTuple conTup,
649  retval = NULL;
650  SysScanDesc scan;
652 
653  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
654  ScanKeyInit(&key,
655  Anum_pg_constraint_contypid,
656  BTEqualStrategyNumber, F_OIDEQ,
657  ObjectIdGetDatum(typid));
658  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
659  true, NULL, 1, &key);
660 
661  while (HeapTupleIsValid(conTup = systable_getnext(scan)))
662  {
664 
665  /*
666  * We're looking for a NOTNULL constraint that's marked validated.
667  */
668  if (con->contype != CONSTRAINT_NOTNULL)
669  continue;
670  if (!con->convalidated)
671  continue;
672 
673  /* Found it */
674  retval = heap_copytuple(conTup);
675  break;
676  }
677 
678  systable_endscan(scan);
679  table_close(pg_constraint, AccessShareLock);
680 
681  return retval;
682 }

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

Referenced by AlterDomainNotNull().

◆ FindFKPeriodOpers()

void FindFKPeriodOpers ( Oid  opclass,
Oid containedbyoperoid,
Oid aggedcontainedbyoperoid 
)

Definition at line 1614 of file pg_constraint.c.

1617 {
1618  Oid opfamily = InvalidOid;
1619  Oid opcintype = InvalidOid;
1620  StrategyNumber strat;
1621 
1622  /* Make sure we have a range or multirange. */
1623  if (get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype))
1624  {
1625  if (opcintype != ANYRANGEOID && opcintype != ANYMULTIRANGEOID)
1626  ereport(ERROR,
1627  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1628  errmsg("invalid type for PERIOD part of foreign key"),
1629  errdetail("Only range and multirange are supported."));
1630 
1631  }
1632  else
1633  elog(ERROR, "cache lookup failed for opclass %u", opclass);
1634 
1635  /*
1636  * Look up the ContainedBy operator whose lhs and rhs are the opclass's
1637  * type. We use this to optimize RI checks: if the new value includes all
1638  * of the old value, then we can treat the attribute as if it didn't
1639  * change, and skip the RI check.
1640  */
1643  InvalidOid,
1644  containedbyoperoid,
1645  &strat);
1646 
1647  /*
1648  * Now look up the ContainedBy operator. Its left arg must be the type of
1649  * the column (or rather of the opclass). Its right arg must match the
1650  * return type of the support proc.
1651  */
1654  ANYMULTIRANGEOID,
1655  aggedcontainedbyoperoid,
1656  &strat);
1657 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
void GetOperatorFromWellKnownStrategy(Oid opclass, Oid rhstype, Oid *opid, StrategyNumber *strat)
Definition: indexcmds.c:2441
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Definition: lsyscache.c:1235
uint16 StrategyNumber
Definition: stratnum.h:22
#define RTContainedByStrategyNumber
Definition: stratnum.h:58

References elog, ereport, errcode(), errdetail(), errmsg(), ERROR, get_opclass_opfamily_and_input_type(), GetOperatorFromWellKnownStrategy(), InvalidOid, and RTContainedByStrategyNumber.

Referenced by ATAddForeignKeyConstraint(), and ri_LoadConstraintInfo().

◆ findNotNullConstraint()

HeapTuple findNotNullConstraint ( Oid  relid,
const char *  colname 
)

Definition at line 629 of file pg_constraint.c.

630 {
632 
633  attnum = get_attnum(relid, colname);
634  if (attnum <= InvalidAttrNumber)
635  return NULL;
636 
637  return findNotNullConstraintAttnum(relid, attnum);
638 }
#define InvalidAttrNumber
Definition: attnum.h:23
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:858

References attnum, findNotNullConstraintAttnum(), get_attnum(), and InvalidAttrNumber.

Referenced by dropconstraint_internal().

◆ findNotNullConstraintAttnum()

HeapTuple findNotNullConstraintAttnum ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 578 of file pg_constraint.c.

579 {
580  Relation pg_constraint;
581  HeapTuple conTup,
582  retval = NULL;
583  SysScanDesc scan;
585 
586  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
587  ScanKeyInit(&key,
588  Anum_pg_constraint_conrelid,
589  BTEqualStrategyNumber, F_OIDEQ,
590  ObjectIdGetDatum(relid));
591  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
592  true, NULL, 1, &key);
593 
594  while (HeapTupleIsValid(conTup = systable_getnext(scan)))
595  {
597  AttrNumber conkey;
598 
599  /*
600  * We're looking for a NOTNULL constraint that's marked validated,
601  * with the column we're looking for as the sole element in conkey.
602  */
603  if (con->contype != CONSTRAINT_NOTNULL)
604  continue;
605  if (!con->convalidated)
606  continue;
607 
608  conkey = extractNotNullColumn(conTup);
609  if (conkey != attnum)
610  continue;
611 
612  /* Found it */
613  retval = heap_copytuple(conTup);
614  break;
615  }
616 
617  systable_endscan(scan);
618  table_close(pg_constraint, AccessShareLock);
619 
620  return retval;
621 }
AttrNumber extractNotNullColumn(HeapTuple constrTup)

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

Referenced by AdjustNotNullInheritance(), ATExecDropNotNull(), ATExecSetNotNull(), findNotNullConstraint(), and MergeAttributesIntoExisting().

◆ get_domain_constraint_oid()

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

Definition at line 1341 of file pg_constraint.c.

1342 {
1343  Relation pg_constraint;
1344  HeapTuple tuple;
1345  SysScanDesc scan;
1346  ScanKeyData skey[3];
1347  Oid conOid = InvalidOid;
1348 
1349  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1350 
1351  ScanKeyInit(&skey[0],
1352  Anum_pg_constraint_conrelid,
1353  BTEqualStrategyNumber, F_OIDEQ,
1355  ScanKeyInit(&skey[1],
1356  Anum_pg_constraint_contypid,
1357  BTEqualStrategyNumber, F_OIDEQ,
1358  ObjectIdGetDatum(typid));
1359  ScanKeyInit(&skey[2],
1360  Anum_pg_constraint_conname,
1361  BTEqualStrategyNumber, F_NAMEEQ,
1362  CStringGetDatum(conname));
1363 
1364  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1365  NULL, 3, skey);
1366 
1367  /* There can be at most one matching row */
1368  if (HeapTupleIsValid(tuple = systable_getnext(scan)))
1369  conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1370 
1371  systable_endscan(scan);
1372 
1373  /* If no such constraint exists, complain */
1374  if (!OidIsValid(conOid) && !missing_ok)
1375  ereport(ERROR,
1376  (errcode(ERRCODE_UNDEFINED_OBJECT),
1377  errmsg("constraint \"%s\" for domain %s does not exist",
1378  conname, format_type_be(typid))));
1379 
1380  table_close(pg_constraint, AccessShareLock);
1381 
1382  return conOid;
1383 }
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 1400 of file pg_constraint.c.

1401 {
1402  Bitmapset *pkattnos = NULL;
1403  Relation pg_constraint;
1404  HeapTuple tuple;
1405  SysScanDesc scan;
1406  ScanKeyData skey[1];
1407 
1408  /* Set *constraintOid, to avoid complaints about uninitialized vars */
1409  *constraintOid = InvalidOid;
1410 
1411  /* Scan pg_constraint for constraints of the target rel */
1412  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1413 
1414  ScanKeyInit(&skey[0],
1415  Anum_pg_constraint_conrelid,
1416  BTEqualStrategyNumber, F_OIDEQ,
1417  ObjectIdGetDatum(relid));
1418 
1419  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1420  NULL, 1, skey);
1421 
1422  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1423  {
1425  Datum adatum;
1426  bool isNull;
1427  ArrayType *arr;
1428  int16 *attnums;
1429  int numkeys;
1430  int i;
1431 
1432  /* Skip constraints that are not PRIMARY KEYs */
1433  if (con->contype != CONSTRAINT_PRIMARY)
1434  continue;
1435 
1436  /*
1437  * If the primary key is deferrable, but we've been instructed to
1438  * ignore deferrable constraints, then we might as well give up
1439  * searching, since there can only be a single primary key on a table.
1440  */
1441  if (con->condeferrable && !deferrableOk)
1442  break;
1443 
1444  /* Extract the conkey array, ie, attnums of PK's columns */
1445  adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
1446  RelationGetDescr(pg_constraint), &isNull);
1447  if (isNull)
1448  elog(ERROR, "null conkey for constraint %u",
1449  ((Form_pg_constraint) GETSTRUCT(tuple))->oid);
1450  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1451  numkeys = ARR_DIMS(arr)[0];
1452  if (ARR_NDIM(arr) != 1 ||
1453  numkeys < 0 ||
1454  ARR_HASNULL(arr) ||
1455  ARR_ELEMTYPE(arr) != INT2OID)
1456  elog(ERROR, "conkey is not a 1-D smallint array");
1457  attnums = (int16 *) ARR_DATA_PTR(arr);
1458 
1459  /* Construct the result value */
1460  for (i = 0; i < numkeys; i++)
1461  {
1462  pkattnos = bms_add_member(pkattnos,
1464  }
1465  *constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1466 
1467  /* No need to search further */
1468  break;
1469  }
1470 
1471  systable_endscan(scan);
1472 
1473  table_close(pg_constraint, AccessShareLock);
1474 
1475  return pkattnos;
1476 }
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 1205 of file pg_constraint.c.

1207 {
1208  Bitmapset *conattnos = NULL;
1209  Relation pg_constraint;
1210  HeapTuple tuple;
1211  SysScanDesc scan;
1212  ScanKeyData skey[3];
1213 
1214  /* Set *constraintOid, to avoid complaints about uninitialized vars */
1215  *constraintOid = InvalidOid;
1216 
1217  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1218 
1219  ScanKeyInit(&skey[0],
1220  Anum_pg_constraint_conrelid,
1221  BTEqualStrategyNumber, F_OIDEQ,
1222  ObjectIdGetDatum(relid));
1223  ScanKeyInit(&skey[1],
1224  Anum_pg_constraint_contypid,
1225  BTEqualStrategyNumber, F_OIDEQ,
1227  ScanKeyInit(&skey[2],
1228  Anum_pg_constraint_conname,
1229  BTEqualStrategyNumber, F_NAMEEQ,
1230  CStringGetDatum(conname));
1231 
1232  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1233  NULL, 3, skey);
1234 
1235  /* There can be at most one matching row */
1236  if (HeapTupleIsValid(tuple = systable_getnext(scan)))
1237  {
1238  Datum adatum;
1239  bool isNull;
1240 
1241  *constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1242 
1243  /* Extract the conkey array, ie, attnums of constrained columns */
1244  adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
1245  RelationGetDescr(pg_constraint), &isNull);
1246  if (!isNull)
1247  {
1248  ArrayType *arr;
1249  int numcols;
1250  int16 *attnums;
1251  int i;
1252 
1253  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1254  numcols = ARR_DIMS(arr)[0];
1255  if (ARR_NDIM(arr) != 1 ||
1256  numcols < 0 ||
1257  ARR_HASNULL(arr) ||
1258  ARR_ELEMTYPE(arr) != INT2OID)
1259  elog(ERROR, "conkey is not a 1-D smallint array");
1260  attnums = (int16 *) ARR_DATA_PTR(arr);
1261 
1262  /* Construct the result value */
1263  for (i = 0; i < numcols; i++)
1264  {
1265  conattnos = bms_add_member(conattnos,
1267  }
1268  }
1269  }
1270 
1271  systable_endscan(scan);
1272 
1273  /* If no such constraint exists, complain */
1274  if (!OidIsValid(*constraintOid) && !missing_ok)
1275  ereport(ERROR,
1276  (errcode(ERRCODE_UNDEFINED_OBJECT),
1277  errmsg("constraint \"%s\" for table \"%s\" does not exist",
1278  conname, get_rel_name(relid))));
1279 
1280  table_close(pg_constraint, AccessShareLock);
1281 
1282  return conattnos;
1283 }

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

1149 {
1150  Relation pg_constraint;
1151  HeapTuple tuple;
1152  SysScanDesc scan;
1153  ScanKeyData skey[3];
1154  Oid conOid = InvalidOid;
1155 
1156  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1157 
1158  ScanKeyInit(&skey[0],
1159  Anum_pg_constraint_conrelid,
1160  BTEqualStrategyNumber, F_OIDEQ,
1161  ObjectIdGetDatum(relid));
1162  ScanKeyInit(&skey[1],
1163  Anum_pg_constraint_contypid,
1164  BTEqualStrategyNumber, F_OIDEQ,
1166  ScanKeyInit(&skey[2],
1167  Anum_pg_constraint_conname,
1168  BTEqualStrategyNumber, F_NAMEEQ,
1169  CStringGetDatum(conname));
1170 
1171  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1172  NULL, 3, skey);
1173 
1174  /* There can be at most one matching row */
1175  if (HeapTupleIsValid(tuple = systable_getnext(scan)))
1176  conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1177 
1178  systable_endscan(scan);
1179 
1180  /* If no such constraint exists, complain */
1181  if (!OidIsValid(conOid) && !missing_ok)
1182  ereport(ERROR,
1183  (errcode(ERRCODE_UNDEFINED_OBJECT),
1184  errmsg("constraint \"%s\" for table \"%s\" does not exist",
1185  conname, get_rel_name(relid))));
1186 
1187  table_close(pg_constraint, AccessShareLock);
1188 
1189  return conOid;
1190 }

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

1295 {
1296  Relation pg_constraint;
1297  SysScanDesc scan;
1298  ScanKeyData key;
1299  HeapTuple tuple;
1300  Oid constraintId = InvalidOid;
1301 
1302  pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1303 
1304  ScanKeyInit(&key,
1305  Anum_pg_constraint_conrelid,
1307  F_OIDEQ,
1308  ObjectIdGetDatum(relationId));
1309  scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
1310  true, NULL, 1, &key);
1311  while ((tuple = systable_getnext(scan)) != NULL)
1312  {
1313  Form_pg_constraint constrForm;
1314 
1315  constrForm = (Form_pg_constraint) GETSTRUCT(tuple);
1316 
1317  /* See above */
1318  if (constrForm->contype != CONSTRAINT_PRIMARY &&
1319  constrForm->contype != CONSTRAINT_UNIQUE &&
1320  constrForm->contype != CONSTRAINT_EXCLUSION)
1321  continue;
1322 
1323  if (constrForm->conindid == indexId)
1324  {
1325  constraintId = constrForm->oid;
1326  break;
1327  }
1328  }
1329  systable_endscan(scan);
1330 
1331  table_close(pg_constraint, AccessShareLock);
1332  return constraintId;
1333 }

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().

◆ MAKE_SYSCACHE()

MAKE_SYSCACHE ( CONSTROID  ,
pg_constraint_oid_index  ,
16   
)

◆ RelationGetNotNullConstraints()

List* RelationGetNotNullConstraints ( Oid  relid,
bool  cooked,
bool  include_noinh 
)

Definition at line 786 of file pg_constraint.c.

787 {
788  List *notnulls = NIL;
789  Relation constrRel;
790  HeapTuple htup;
791  SysScanDesc conscan;
792  ScanKeyData skey;
793 
794  constrRel = table_open(ConstraintRelationId, AccessShareLock);
795  ScanKeyInit(&skey,
796  Anum_pg_constraint_conrelid,
797  BTEqualStrategyNumber, F_OIDEQ,
798  ObjectIdGetDatum(relid));
799  conscan = systable_beginscan(constrRel, ConstraintRelidTypidNameIndexId, true,
800  NULL, 1, &skey);
801 
802  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
803  {
805  AttrNumber colnum;
806 
807  if (conForm->contype != CONSTRAINT_NOTNULL)
808  continue;
809  if (conForm->connoinherit && !include_noinh)
810  continue;
811 
812  colnum = extractNotNullColumn(htup);
813 
814  if (cooked)
815  {
816  CookedConstraint *cooked;
817 
818  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
819 
820  cooked->contype = CONSTR_NOTNULL;
821  cooked->conoid = conForm->oid;
822  cooked->name = pstrdup(NameStr(conForm->conname));
823  cooked->attnum = colnum;
824  cooked->expr = NULL;
825  cooked->skip_validation = false;
826  cooked->is_local = true;
827  cooked->inhcount = 0;
828  cooked->is_no_inherit = conForm->connoinherit;
829 
830  notnulls = lappend(notnulls, cooked);
831  }
832  else
833  {
834  Constraint *constr;
835 
836  constr = makeNode(Constraint);
837  constr->contype = CONSTR_NOTNULL;
838  constr->conname = pstrdup(NameStr(conForm->conname));
839  constr->deferrable = false;
840  constr->initdeferred = false;
841  constr->location = -1;
842  constr->keys = list_make1(makeString(get_attname(relid, colnum,
843  false)));
844  constr->skip_validation = false;
845  constr->initially_valid = true;
846  constr->is_no_inherit = conForm->connoinherit;
847  notnulls = lappend(notnulls, constr);
848  }
849  }
850 
851  systable_endscan(conscan);
852  table_close(constrRel, AccessShareLock);
853 
854  return notnulls;
855 }
List * lappend(List *list, void *datum)
Definition: list.c:339
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:827
char * pstrdup(const char *in)
Definition: mcxt.c:1696
#define makeNode(_type_)
Definition: nodes.h:155
@ CONSTR_NOTNULL
Definition: parsenodes.h:2726
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
bool initdeferred
Definition: parsenodes.h:2759
ParseLoc location
Definition: parsenodes.h:2798
List * keys
Definition: parsenodes.h:2769
ConstrType contype
Definition: parsenodes.h:2756
bool is_no_inherit
Definition: parsenodes.h:2762
bool initially_valid
Definition: parsenodes.h:2761
bool skip_validation
Definition: parsenodes.h:2760
bool deferrable
Definition: parsenodes.h:2758
char * conname
Definition: parsenodes.h:2757
Oid conoid
Definition: heap.h:39
char * name
Definition: heap.h:40
AttrNumber attnum
Definition: heap.h:41
bool skip_validation
Definition: heap.h:43
bool is_no_inherit
Definition: heap.h:46
int16 inhcount
Definition: heap.h:45
bool is_local
Definition: heap.h:44
ConstrType contype
Definition: heap.h:37
Node * expr
Definition: heap.h:42
Definition: pg_list.h:54
String * makeString(char *str)
Definition: value.c:63

References AccessShareLock, CookedConstraint::attnum, BTEqualStrategyNumber, Constraint::conname, CookedConstraint::conoid, CONSTR_NOTNULL, CookedConstraint::contype, Constraint::contype, Constraint::deferrable, CookedConstraint::expr, extractNotNullColumn(), get_attname(), GETSTRUCT, HeapTupleIsValid, CookedConstraint::inhcount, Constraint::initdeferred, Constraint::initially_valid, CookedConstraint::is_local, CookedConstraint::is_no_inherit, Constraint::is_no_inherit, Constraint::keys, lappend(), list_make1, Constraint::location, makeNode, makeString(), CookedConstraint::name, NameStr, NIL, ObjectIdGetDatum(), palloc(), pstrdup(), ScanKeyInit(), CookedConstraint::skip_validation, Constraint::skip_validation, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by MergeAttributes(), and transformTableLikeClause().

◆ RemoveConstraintById()

void RemoveConstraintById ( Oid  conId)

Definition at line 862 of file pg_constraint.c.

863 {
864  Relation conDesc;
865  HeapTuple tup;
866  Form_pg_constraint con;
867 
868  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
869 
870  tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conId));
871  if (!HeapTupleIsValid(tup)) /* should not happen */
872  elog(ERROR, "cache lookup failed for constraint %u", conId);
873  con = (Form_pg_constraint) GETSTRUCT(tup);
874 
875  /*
876  * Special processing depending on what the constraint is for.
877  */
878  if (OidIsValid(con->conrelid))
879  {
880  Relation rel;
881 
882  /*
883  * If the constraint is for a relation, open and exclusive-lock the
884  * relation it's for.
885  */
886  rel = table_open(con->conrelid, AccessExclusiveLock);
887 
888  /*
889  * We need to update the relchecks count if it is a check constraint
890  * being dropped. This update will force backends to rebuild relcache
891  * entries when we commit.
892  */
893  if (con->contype == CONSTRAINT_CHECK)
894  {
895  Relation pgrel;
896  HeapTuple relTup;
897  Form_pg_class classForm;
898 
899  pgrel = table_open(RelationRelationId, RowExclusiveLock);
900  relTup = SearchSysCacheCopy1(RELOID,
901  ObjectIdGetDatum(con->conrelid));
902  if (!HeapTupleIsValid(relTup))
903  elog(ERROR, "cache lookup failed for relation %u",
904  con->conrelid);
905  classForm = (Form_pg_class) GETSTRUCT(relTup);
906 
907  if (classForm->relchecks == 0) /* should not happen */
908  elog(ERROR, "relation \"%s\" has relchecks = 0",
910  classForm->relchecks--;
911 
912  CatalogTupleUpdate(pgrel, &relTup->t_self, relTup);
913 
914  heap_freetuple(relTup);
915 
917  }
918 
919  /* Keep lock on constraint's rel until end of xact */
920  table_close(rel, NoLock);
921  }
922  else if (OidIsValid(con->contypid))
923  {
924  /*
925  * XXX for now, do nothing special when dropping a domain constraint
926  *
927  * Probably there should be some form of locking on the domain type,
928  * but we have no such concept at the moment.
929  */
930  }
931  else
932  elog(ERROR, "constraint %u is not of a known type", conId);
933 
934  /* Fry the constraint itself */
935  CatalogTupleDelete(conDesc, &tup->t_self);
936 
937  /* Clean up */
938  ReleaseSysCache(tup);
939  table_close(conDesc, RowExclusiveLock);
940 }
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
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:539
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:91

References AccessExclusiveLock, CatalogTupleDelete(), CatalogTupleUpdate(), elog, ERROR, GETSTRUCT, heap_freetuple(), HeapTupleIsValid, NoLock, ObjectIdGetDatum(), OidIsValid, RelationGetRelationName, ReleaseSysCache(), 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 953 of file pg_constraint.c.

954 {
955  Relation conDesc;
956  HeapTuple tuple;
957  Form_pg_constraint con;
958 
959  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
960 
961  tuple = SearchSysCacheCopy1(CONSTROID, ObjectIdGetDatum(conId));
962  if (!HeapTupleIsValid(tuple))
963  elog(ERROR, "cache lookup failed for constraint %u", conId);
964  con = (Form_pg_constraint) GETSTRUCT(tuple);
965 
966  /*
967  * For user-friendliness, check whether the name is already in use.
968  */
969  if (OidIsValid(con->conrelid) &&
971  con->conrelid,
972  newname))
973  ereport(ERROR,
975  errmsg("constraint \"%s\" for relation \"%s\" already exists",
976  newname, get_rel_name(con->conrelid))));
977  if (OidIsValid(con->contypid) &&
979  con->contypid,
980  newname))
981  ereport(ERROR,
983  errmsg("constraint \"%s\" for domain %s already exists",
984  newname, format_type_be(con->contypid))));
985 
986  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
987  namestrcpy(&(con->conname), newname);
988 
989  CatalogTupleUpdate(conDesc, &tuple->t_self, tuple);
990 
991  InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
992 
993  heap_freetuple(tuple);
994  table_close(conDesc, RowExclusiveLock);
995 }
bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId, const char *conname)
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30

References CatalogTupleUpdate(), CONSTRAINT_DOMAIN, CONSTRAINT_RELATION, ConstraintNameIsUsed(), 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 167 of file pg_constraint.h.