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 "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/heap.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 "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 conPeriod, bool is_internal)
 
bool ConstraintNameIsUsed (ConstraintCategory conCat, Oid objId, const char *conname)
 
bool ConstraintNameExists (const char *conname, Oid namespaceid)
 
char * ChooseConstraintName (const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
 
HeapTuple findNotNullConstraintAttnum (Oid relid, AttrNumber attnum)
 
HeapTuple findNotNullConstraint (Oid relid, const char *colname)
 
AttrNumber extractNotNullColumn (HeapTuple constrTup)
 
bool AdjustNotNullInheritance1 (Oid relid, AttrNumber attnum, int count, bool is_no_inherit)
 
void AdjustNotNullInheritance (Oid relid, Bitmapset *columns, int count)
 
ListRelationGetNotNullConstraints (Oid relid, bool cooked)
 
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

◆ AdjustNotNullInheritance()

void AdjustNotNullInheritance ( Oid  relid,
Bitmapset columns,
int  count 
)

Definition at line 738 of file pg_constraint.c.

739 {
740  Relation pg_constraint;
741  int attnum;
742 
743  pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
744 
745  /*
746  * Scan the set of columns and bump inhcount for each.
747  */
748  attnum = -1;
749  while ((attnum = bms_next_member(columns, attnum)) >= 0)
750  {
751  HeapTuple tup;
752  Form_pg_constraint conform;
753 
754  tup = findNotNullConstraintAttnum(relid, attnum);
755  if (!HeapTupleIsValid(tup))
756  ereport(ERROR,
757  errcode(ERRCODE_DATATYPE_MISMATCH),
758  errmsg("column \"%s\" in child table must be marked NOT NULL",
759  get_attname(relid, attnum,
760  false)));
761 
762  conform = (Form_pg_constraint) GETSTRUCT(tup);
763  conform->coninhcount += count;
764  if (conform->coninhcount < 0)
765  elog(ERROR, "invalid inhcount %d for constraint \"%s\" on relation \"%s\"",
766  conform->coninhcount, NameStr(conform->conname),
767  get_rel_name(relid));
768 
769  /*
770  * If the constraints are no longer inherited, mark them local. It's
771  * arguable that we should drop them instead, but it's hard to see
772  * that being better. The user can drop it manually later.
773  */
774  if (conform->coninhcount == 0)
775  conform->conislocal = true;
776 
777  CatalogTupleUpdate(pg_constraint, &tup->t_self, tup);
778  }
779 
780  table_close(pg_constraint, RowExclusiveLock);
781 }
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
#define NameStr(name)
Definition: c.h:733
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1906
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:827
int16 attnum
Definition: pg_attribute.h:74
HeapTuple findNotNullConstraintAttnum(Oid relid, AttrNumber attnum)
FormData_pg_constraint * Form_pg_constraint
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References attnum, bms_next_member(), CatalogTupleUpdate(), elog, ereport, errcode(), errmsg(), ERROR, findNotNullConstraintAttnum(), get_attname(), get_rel_name(), GETSTRUCT, HeapTupleIsValid, NameStr, RowExclusiveLock, HeapTupleData::t_self, table_close(), and table_open().

Referenced by ATInheritAdjustNotNulls().

◆ AdjustNotNullInheritance1()

bool AdjustNotNullInheritance1 ( Oid  relid,
AttrNumber  attnum,
int  count,
bool  is_no_inherit 
)

Definition at line 672 of file pg_constraint.c.

674 {
675  HeapTuple tup;
676 
677  tup = findNotNullConstraintAttnum(relid, attnum);
678  if (HeapTupleIsValid(tup))
679  {
680  Relation pg_constraint;
681  Form_pg_constraint conform;
682 
683  pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
684  conform = (Form_pg_constraint) GETSTRUCT(tup);
685 
686  /*
687  * Don't let the NO INHERIT status change (but don't complain
688  * unnecessarily.) In the future it might be useful to let an
689  * inheritable constraint replace a non-inheritable one, but we'd need
690  * to recurse to children to get it added there.
691  */
692  if (is_no_inherit != conform->connoinherit)
693  ereport(ERROR,
694  errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
695  errmsg("cannot change NO INHERIT status of inherited NOT NULL constraint \"%s\" on relation \"%s\"",
696  NameStr(conform->conname), get_rel_name(relid)));
697 
698  if (count > 0)
699  conform->coninhcount += count;
700 
701  /* sanity check */
702  if (conform->coninhcount < 0)
703  elog(ERROR, "invalid inhcount %d for constraint \"%s\" on relation \"%s\"",
704  conform->coninhcount, NameStr(conform->conname),
705  get_rel_name(relid));
706 
707  /*
708  * If the constraint is no longer inherited, mark it local. It's
709  * arguable that we should drop it instead, but it's hard to see that
710  * being better. The user can drop it manually later.
711  */
712  if (conform->coninhcount == 0)
713  conform->conislocal = true;
714 
715  CatalogTupleUpdate(pg_constraint, &tup->t_self, tup);
716 
717  table_close(pg_constraint, RowExclusiveLock);
718 
719  return true;
720  }
721 
722  return false;
723 }

References attnum, CatalogTupleUpdate(), elog, ereport, errcode(), errmsg(), ERROR, findNotNullConstraintAttnum(), get_rel_name(), GETSTRUCT, HeapTupleIsValid, NameStr, RowExclusiveLock, HeapTupleData::t_self, table_close(), and table_open().

Referenced by AddRelationNewConstraints().

◆ AlterConstraintNamespaces()

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

Definition at line 1012 of file pg_constraint.c.

1014 {
1015  Relation conRel;
1016  ScanKeyData key[2];
1017  SysScanDesc scan;
1018  HeapTuple tup;
1019 
1020  conRel = table_open(ConstraintRelationId, RowExclusiveLock);
1021 
1022  ScanKeyInit(&key[0],
1023  Anum_pg_constraint_conrelid,
1024  BTEqualStrategyNumber, F_OIDEQ,
1025  ObjectIdGetDatum(isType ? InvalidOid : ownerId));
1026  ScanKeyInit(&key[1],
1027  Anum_pg_constraint_contypid,
1028  BTEqualStrategyNumber, F_OIDEQ,
1029  ObjectIdGetDatum(isType ? ownerId : InvalidOid));
1030 
1031  scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId, true,
1032  NULL, 2, key);
1033 
1034  while (HeapTupleIsValid((tup = systable_getnext(scan))))
1035  {
1037  ObjectAddress thisobj;
1038 
1039  ObjectAddressSet(thisobj, ConstraintRelationId, conform->oid);
1040 
1041  if (object_address_present(&thisobj, objsMoved))
1042  continue;
1043 
1044  /* Don't update if the object is already part of the namespace */
1045  if (conform->connamespace == oldNspId && oldNspId != newNspId)
1046  {
1047  tup = heap_copytuple(tup);
1048  conform = (Form_pg_constraint) GETSTRUCT(tup);
1049 
1050  conform->connamespace = newNspId;
1051 
1052  CatalogTupleUpdate(conRel, &tup->t_self, tup);
1053 
1054  /*
1055  * Note: currently, the constraint will not have its own
1056  * dependency on the namespace, so we don't need to do
1057  * changeDependencyFor().
1058  */
1059  }
1060 
1061  InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
1062 
1063  add_exact_object_address(&thisobj, objsMoved);
1064  }
1065 
1066  systable_endscan(scan);
1067 
1068  table_close(conRel, RowExclusiveLock);
1069 }
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2589
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2529
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:596
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:503
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:384
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
#define InvalidOid
Definition: postgres_ext.h:36
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

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

Referenced by AlterTableNamespaceInternal(), and AlterTypeNamespaceInternal().

◆ check_functional_grouping()

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

Definition at line 1624 of file pg_constraint.c.

1628 {
1629  Bitmapset *pkattnos;
1630  Bitmapset *groupbyattnos;
1631  Oid constraintOid;
1632  ListCell *gl;
1633 
1634  /* If the rel has no PK, then we can't prove functional dependency */
1635  pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
1636  if (pkattnos == NULL)
1637  return false;
1638 
1639  /* Identify all the rel's columns that appear in grouping_columns */
1640  groupbyattnos = NULL;
1641  foreach(gl, grouping_columns)
1642  {
1643  Var *gvar = (Var *) lfirst(gl);
1644 
1645  if (IsA(gvar, Var) &&
1646  gvar->varno == varno &&
1647  gvar->varlevelsup == varlevelsup)
1648  groupbyattnos = bms_add_member(groupbyattnos,
1650  }
1651 
1652  if (bms_is_subset(pkattnos, groupbyattnos))
1653  {
1654  /* The PK is a subset of grouping_columns, so we win */
1655  *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
1656  return true;
1657  }
1658 
1659  return false;
1660 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
Bitmapset * get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
#define lfirst(lc)
Definition: pg_list.h:172
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:234
AttrNumber varattno
Definition: primnodes.h:246
int varno
Definition: primnodes.h:241
Index varlevelsup
Definition: primnodes.h:266
#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 500 of file pg_constraint.c.

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

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

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

◆ ConstraintNameExists()

bool ConstraintNameExists ( const char *  conname,
Oid  namespaceid 
)

Definition at line 446 of file pg_constraint.c.

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

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

403 {
404  bool found;
405  Relation conDesc;
406  SysScanDesc conscan;
407  ScanKeyData skey[3];
408 
409  conDesc = table_open(ConstraintRelationId, AccessShareLock);
410 
411  ScanKeyInit(&skey[0],
412  Anum_pg_constraint_conrelid,
413  BTEqualStrategyNumber, F_OIDEQ,
415  ? objId : InvalidOid));
416  ScanKeyInit(&skey[1],
417  Anum_pg_constraint_contypid,
418  BTEqualStrategyNumber, F_OIDEQ,
420  ? objId : InvalidOid));
421  ScanKeyInit(&skey[2],
422  Anum_pg_constraint_conname,
423  BTEqualStrategyNumber, F_NAMEEQ,
424  CStringGetDatum(conname));
425 
426  conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId,
427  true, NULL, 3, skey);
428 
429  /* There can be at most one matching row */
430  found = (HeapTupleIsValid(systable_getnext(conscan)));
431 
432  systable_endscan(conscan);
433  table_close(conDesc, AccessShareLock);
434 
435  return found;
436 }
@ 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(), AddRelationNewConstraints(), ATExecAddConstraint(), CloneFkReferencing(), domainAddConstraint(), index_create(), and RenameConstraintById().

◆ ConstraintSetParentConstraint()

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

Definition at line 1081 of file pg_constraint.c.

1084 {
1085  Relation constrRel;
1086  Form_pg_constraint constrForm;
1087  HeapTuple tuple,
1088  newtup;
1089  ObjectAddress depender;
1090  ObjectAddress referenced;
1091 
1092  constrRel = table_open(ConstraintRelationId, RowExclusiveLock);
1093  tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(childConstrId));
1094  if (!HeapTupleIsValid(tuple))
1095  elog(ERROR, "cache lookup failed for constraint %u", childConstrId);
1096  newtup = heap_copytuple(tuple);
1097  constrForm = (Form_pg_constraint) GETSTRUCT(newtup);
1098  if (OidIsValid(parentConstrId))
1099  {
1100  /* don't allow setting parent for a constraint that already has one */
1101  Assert(constrForm->coninhcount == 0);
1102  if (constrForm->conparentid != InvalidOid)
1103  elog(ERROR, "constraint %u already has a parent constraint",
1104  childConstrId);
1105 
1106  constrForm->conislocal = false;
1107  constrForm->coninhcount++;
1108  if (constrForm->coninhcount < 0)
1109  ereport(ERROR,
1110  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1111  errmsg("too many inheritance parents"));
1112  constrForm->conparentid = parentConstrId;
1113 
1114  CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
1115 
1116  ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
1117 
1118  ObjectAddressSet(referenced, ConstraintRelationId, parentConstrId);
1119  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
1120 
1121  ObjectAddressSet(referenced, RelationRelationId, childTableId);
1122  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
1123  }
1124  else
1125  {
1126  constrForm->coninhcount--;
1127  constrForm->conislocal = true;
1128  constrForm->conparentid = InvalidOid;
1129 
1130  /* Make sure there's no further inheritance. */
1131  Assert(constrForm->coninhcount == 0);
1132 
1133  CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
1134 
1135  deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
1136  ConstraintRelationId,
1138  deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
1139  RelationRelationId,
1141  }
1142 
1143  ReleaseSysCache(tuple);
1144  table_close(constrRel, RowExclusiveLock);
1145 }
#define OidIsValid(objectId)
Definition: c.h:762
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
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:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218

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

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

◆ CreateConstraintEntry()

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

Definition at line 49 of file pg_constraint.c.

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

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

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

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

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

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

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

◆ extractNotNullColumn()

AttrNumber extractNotNullColumn ( HeapTuple  constrTup)

Definition at line 637 of file pg_constraint.c.

638 {
639  AttrNumber colnum;
640  Datum adatum;
641  ArrayType *arr;
642 
643  /* only tuples for not-null constraints should be given */
644  Assert(((Form_pg_constraint) GETSTRUCT(constrTup))->contype == CONSTRAINT_NOTNULL);
645 
646  adatum = SysCacheGetAttrNotNull(CONSTROID, constrTup,
647  Anum_pg_constraint_conkey);
648  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
649  if (ARR_NDIM(arr) != 1 ||
650  ARR_HASNULL(arr) ||
651  ARR_ELEMTYPE(arr) != INT2OID ||
652  ARR_DIMS(arr)[0] != 1)
653  elog(ERROR, "conkey is not a 1-D smallint array");
654 
655  memcpy(&colnum, ARR_DATA_PTR(arr), sizeof(AttrNumber));
656 
657  if ((Pointer) arr != DatumGetPointer(adatum))
658  pfree(arr); /* free de-toasted copy, if any */
659 
660  return colnum;
661 }
int16 AttrNumber
Definition: attnum.h:21

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

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

◆ findNotNullConstraint()

HeapTuple findNotNullConstraint ( Oid  relid,
const char *  colname 
)

Definition at line 625 of file pg_constraint.c.

626 {
627  AttrNumber attnum = get_attnum(relid, colname);
628 
629  return findNotNullConstraintAttnum(relid, attnum);
630 }
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:858

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

Referenced by ATExecDropNotNull(), and dropconstraint_internal().

◆ findNotNullConstraintAttnum()

HeapTuple findNotNullConstraintAttnum ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 575 of file pg_constraint.c.

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

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

Referenced by AdjustNotNullInheritance(), AdjustNotNullInheritance1(), dropconstraint_internal(), findNotNullConstraint(), and MergeAttributesIntoExisting().

◆ get_domain_constraint_oid()

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

Definition at line 1347 of file pg_constraint.c.

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

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

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

Referenced by check_functional_grouping(), and remove_useless_groupby_columns().

◆ get_relation_constraint_attnos()

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

Definition at line 1211 of file pg_constraint.c.

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

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

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

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

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

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

◆ RelationGetNotNullConstraints()

List* RelationGetNotNullConstraints ( Oid  relid,
bool  cooked 
)

Definition at line 795 of file pg_constraint.c.

796 {
797  List *notnulls = NIL;
798  Relation constrRel;
799  HeapTuple htup;
800  SysScanDesc conscan;
801  ScanKeyData skey;
802 
803  constrRel = table_open(ConstraintRelationId, AccessShareLock);
804  ScanKeyInit(&skey,
805  Anum_pg_constraint_conrelid,
806  BTEqualStrategyNumber, F_OIDEQ,
807  ObjectIdGetDatum(relid));
808  conscan = systable_beginscan(constrRel, ConstraintRelidTypidNameIndexId, true,
809  NULL, 1, &skey);
810 
811  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
812  {
814  AttrNumber colnum;
815 
816  if (conForm->contype != CONSTRAINT_NOTNULL)
817  continue;
818  if (conForm->connoinherit)
819  continue;
820 
821  colnum = extractNotNullColumn(htup);
822 
823  if (cooked)
824  {
825  CookedConstraint *cooked;
826 
827  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
828 
829  cooked->contype = CONSTR_NOTNULL;
830  cooked->name = pstrdup(NameStr(conForm->conname));
831  cooked->attnum = colnum;
832  cooked->expr = NULL;
833  cooked->skip_validation = false;
834  cooked->is_local = true;
835  cooked->inhcount = 0;
836  cooked->is_no_inherit = conForm->connoinherit;
837 
838  notnulls = lappend(notnulls, cooked);
839  }
840  else
841  {
842  Constraint *constr;
843 
844  constr = makeNode(Constraint);
845  constr->contype = CONSTR_NOTNULL;
846  constr->conname = pstrdup(NameStr(conForm->conname));
847  constr->deferrable = false;
848  constr->initdeferred = false;
849  constr->location = -1;
850  constr->keys = list_make1(makeString(get_attname(relid, colnum,
851  false)));
852  constr->skip_validation = false;
853  constr->initially_valid = true;
854  notnulls = lappend(notnulls, constr);
855  }
856  }
857 
858  systable_endscan(conscan);
859  table_close(constrRel, AccessShareLock);
860 
861  return notnulls;
862 }
List * lappend(List *list, void *datum)
Definition: list.c:339
char * pstrdup(const char *in)
Definition: mcxt.c:1683
#define makeNode(_type_)
Definition: nodes.h:155
@ CONSTR_NOTNULL
Definition: parsenodes.h:2553
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
bool initdeferred
Definition: parsenodes.h:2586
List * keys
Definition: parsenodes.h:2598
ConstrType contype
Definition: parsenodes.h:2583
bool initially_valid
Definition: parsenodes.h:2588
bool skip_validation
Definition: parsenodes.h:2587
bool deferrable
Definition: parsenodes.h:2585
char * conname
Definition: parsenodes.h:2584
char * name
Definition: heap.h:40
AttrNumber attnum
Definition: heap.h:41
bool skip_validation
Definition: heap.h:43
bool is_no_inherit
Definition: heap.h:46
int inhcount
Definition: heap.h:45
bool is_local
Definition: heap.h:44
ConstrType contype
Definition: heap.h:37
Node * expr
Definition: heap.h:42
Definition: pg_list.h:54
String * makeString(char *str)
Definition: value.c:63

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

Referenced by expandTableLikeClause(), MergeAttributes(), and transformTableLikeClause().

◆ RemoveConstraintById()

void RemoveConstraintById ( Oid  conId)

Definition at line 869 of file pg_constraint.c.

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

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

Referenced by doDeletion().

◆ RenameConstraintById()

void RenameConstraintById ( Oid  conId,
const char *  newname 
)

Definition at line 960 of file pg_constraint.c.

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

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

Referenced by rename_constraint_internal(), and RenameRelationInternal().