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:2562
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2502
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:598
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:505
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:386
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:195
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
FormData_pg_constraint * Form_pg_constraint
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define InvalidOid
Definition: postgres_ext.h:36
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

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

Referenced by AlterTableNamespaceInternal(), and AlterTypeNamespaceInternal().

◆ check_functional_grouping()

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

Definition at line 1322 of file pg_constraint.c.

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

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

Referenced by check_ungrouped_columns_walker().

◆ ChooseConstraintName()

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

Definition at line 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:2317
#define AccessShareLock
Definition: lockdefs.h:36
void pfree(void *pointer)
Definition: mcxt.c:1175
static char * label
#define NAMEDATALEN
#define snprintf
Definition: port.h:225
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define CStringGetDatum(X)
Definition: postgres.h:622

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

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

◆ ConstraintNameExists()

bool ConstraintNameExists ( const char *  conname,
Oid  namespaceid 
)

Definition at line 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:710
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
Assert(fmt[strlen(fmt) - 1] !='\n')
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:293
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
@ CONSTROID
Definition: syscache.h:53

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

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

◆ CreateConstraintEntry()

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

Definition at line 50 of file pg_constraint.c.

81 {
82  Relation conDesc;
83  Oid conOid;
84  HeapTuple tup;
85  bool nulls[Natts_pg_constraint];
86  Datum values[Natts_pg_constraint];
87  ArrayType *conkeyArray;
88  ArrayType *confkeyArray;
89  ArrayType *conpfeqopArray;
90  ArrayType *conppeqopArray;
91  ArrayType *conffeqopArray;
92  ArrayType *conexclopArray;
93  ArrayType *confdelsetcolsArray;
95  int i;
96  ObjectAddress conobject;
97  ObjectAddresses *addrs_auto;
98  ObjectAddresses *addrs_normal;
99 
100  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
101 
102  Assert(constraintName);
103  namestrcpy(&cname, constraintName);
104 
105  /*
106  * Convert C arrays into Postgres arrays.
107  */
108  if (constraintNKeys > 0)
109  {
110  Datum *conkey;
111 
112  conkey = (Datum *) palloc(constraintNKeys * sizeof(Datum));
113  for (i = 0; i < constraintNKeys; i++)
114  conkey[i] = Int16GetDatum(constraintKey[i]);
115  conkeyArray = construct_array_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:3339
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:85
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:391
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2711
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
Definition: dependency.c:1631
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2447
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2742
@ DEPENDENCY_AUTO
Definition: dependency.h:34
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
int i
Definition: isn.c:73
void * palloc(Size size)
Definition: mcxt.c:1068
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:173
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
Definition: objectaddress.h:33
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define Int32GetDatum(X)
Definition: postgres.h:523
#define NameGetDatum(X)
Definition: postgres.h:639
#define Int16GetDatum(X)
Definition: postgres.h:495
#define CharGetDatum(X)
Definition: postgres.h:460
#define PointerGetDatum(X)
Definition: postgres.h:600
#define RelationGetDescr(relation)
Definition: rel.h:514
Definition: c.h:676

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

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

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

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

◆ get_domain_constraint_oid()

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

Definition at line 1032 of file pg_constraint.c.

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

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

Referenced by get_object_address(), and rename_constraint_internal().

◆ get_primary_key_attnos()

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

Definition at line 1091 of file pg_constraint.c.

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

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

Referenced by transformOnConflictArbiter().

◆ get_relation_constraint_oid()

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

Definition at line 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 992 of file pg_constraint.c.

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

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:522
#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().