PostgreSQL Source Code  git master
pg_constraint.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/tablecmds.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for pg_constraint.c:

Go to the source code of this file.

Functions

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)
 
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 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_relation_idx_constraint_oid (Oid relationId, Oid indexId)
 
Oid get_domain_constraint_oid (Oid typid, const char *conname, bool missing_ok)
 
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)
 

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:649
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h: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:600
#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().

◆ check_functional_grouping()

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

Definition at line 1333 of file pg_constraint.c.

1337 {
1338  Bitmapset *pkattnos;
1339  Bitmapset *groupbyattnos;
1340  Oid constraintOid;
1341  ListCell *gl;
1342 
1343  /* If the rel has no PK, then we can't prove functional dependency */
1344  pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
1345  if (pkattnos == NULL)
1346  return false;
1347 
1348  /* Identify all the rel's columns that appear in grouping_columns */
1349  groupbyattnos = NULL;
1350  foreach(gl, grouping_columns)
1351  {
1352  Var *gvar = (Var *) lfirst(gl);
1353 
1354  if (IsA(gvar, Var) &&
1355  gvar->varno == varno &&
1356  gvar->varlevelsup == varlevelsup)
1357  groupbyattnos = bms_add_member(groupbyattnos,
1359  }
1360 
1361  if (bms_is_subset(pkattnos, groupbyattnos))
1362  {
1363  /* The PK is a subset of grouping_columns, so we win */
1364  *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
1365  return true;
1366  }
1367 
1368  return false;
1369 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:316
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:739
List * lappend_oid(List *list, Oid datum)
Definition: list.c:374
#define IsA(nodeptr, _type_)
Definition: nodes.h:168
Bitmapset * get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
#define lfirst(lc)
Definition: pg_list.h:170
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:205
AttrNumber varattno
Definition: primnodes.h:217
int varno
Definition: primnodes.h:212
Index varlevelsup
Definition: primnodes.h:230
#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:2331
#define AccessShareLock
Definition: lockdefs.h:36
void pfree(void *pointer)
Definition: mcxt.c:1306
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:698

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 }
@ CONSTRAINT_DOMAIN
@ CONSTRAINT_RELATION

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  constrForm->conparentid = parentConstrId;
809 
810  CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
811 
812  ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
813 
814  ObjectAddressSet(referenced, ConstraintRelationId, parentConstrId);
815  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
816 
817  ObjectAddressSet(referenced, RelationRelationId, childTableId);
818  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
819  }
820  else
821  {
822  constrForm->coninhcount--;
823  constrForm->conislocal = true;
824  constrForm->conparentid = InvalidOid;
825 
826  /* Make sure there's no further inheritance. */
827  Assert(constrForm->coninhcount == 0);
828 
829  CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
830 
831  deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
832  ConstraintRelationId,
834  deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
835  RelationRelationId,
837  }
838 
839  ReleaseSysCache(tuple);
840  table_close(constrRel, RowExclusiveLock);
841 }
#define OidIsValid(objectId)
Definition: c.h:711
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
#define ERROR
Definition: elog.h:35
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:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
@ CONSTROID
Definition: syscache.h:53

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

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

◆ CreateConstraintEntry()

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

Definition at line 50 of file pg_constraint.c.

81 {
82  Relation conDesc;
83  Oid conOid;
84  HeapTuple tup;
85  bool nulls[Natts_pg_constraint];
86  Datum values[Natts_pg_constraint];
87  ArrayType *conkeyArray;
88  ArrayType *confkeyArray;
89  ArrayType *conpfeqopArray;
90  ArrayType *conppeqopArray;
91  ArrayType *conffeqopArray;
92  ArrayType *conexclopArray;
93  ArrayType *confdelsetcolsArray;
95  int i;
96  ObjectAddress conobject;
97  ObjectAddresses *addrs_auto;
98  ObjectAddresses *addrs_normal;
99 
100  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
101 
102  Assert(constraintName);
103  namestrcpy(&cname, constraintName);
104 
105  /*
106  * Convert C arrays into Postgres arrays.
107  */
108  if (constraintNKeys > 0)
109  {
110  Datum *conkey;
111 
112  conkey = (Datum *) palloc(constraintNKeys * sizeof(Datum));
113  for (i = 0; i < constraintNKeys; i++)
114  conkey[i] = Int16GetDatum(constraintKey[i]);
115  conkeyArray = construct_array_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] = Int32GetDatum(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:3338
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:85
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c: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:1639
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2526
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:221
int i
Definition: isn.c:73
void * palloc(Size size)
Definition: mcxt.c:1199
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:670
uintptr_t Datum
Definition: postgres.h:412
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:520
static Datum BoolGetDatum(bool X)
Definition: postgres.h:450
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:721
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:560
static Datum CharGetDatum(char X)
Definition: postgres.h:470
#define RelationGetDescr(relation)
Definition: rel.h:527
Definition: c.h:677

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(), Int32GetDatum(), InvokeObjectPostCreateHookArg, NameGetDatum(), namestrcpy(), new_object_addresses(), ObjectAddressSet, ObjectAddressSubSet, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, OidIsValid, palloc(), PointerGetDatum(), record_object_address_dependencies(), recordDependencyOnSingleRelExpr(), RelationGetDescr, RowExclusiveLock, table_close(), table_open(), and values.

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

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

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

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

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

◆ get_domain_constraint_oid()

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

Definition at line 1043 of file pg_constraint.c.

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

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

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

Referenced by check_functional_grouping(), and remove_useless_groupby_columns().

◆ get_relation_constraint_attnos()

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

Definition at line 907 of file pg_constraint.c.

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

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

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

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

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:350
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define RelationGetRelationName(relation)
Definition: rel.h:535
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:179
@ RELOID
Definition: syscache.h:89

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

Referenced by doDeletion().

◆ RenameConstraintById()

void RenameConstraintById ( Oid  conId,
const char *  newname 
)

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