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/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 "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 conWithoutOverlaps, 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 740 of file pg_constraint.c.

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

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

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

1016 {
1017  Relation conRel;
1018  ScanKeyData key[2];
1019  SysScanDesc scan;
1020  HeapTuple tup;
1021 
1022  conRel = table_open(ConstraintRelationId, RowExclusiveLock);
1023 
1024  ScanKeyInit(&key[0],
1025  Anum_pg_constraint_conrelid,
1026  BTEqualStrategyNumber, F_OIDEQ,
1027  ObjectIdGetDatum(isType ? InvalidOid : ownerId));
1028  ScanKeyInit(&key[1],
1029  Anum_pg_constraint_contypid,
1030  BTEqualStrategyNumber, F_OIDEQ,
1031  ObjectIdGetDatum(isType ? ownerId : InvalidOid));
1032 
1033  scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId, true,
1034  NULL, 2, key);
1035 
1036  while (HeapTupleIsValid((tup = systable_getnext(scan))))
1037  {
1039  ObjectAddress thisobj;
1040 
1041  ObjectAddressSet(thisobj, ConstraintRelationId, conform->oid);
1042 
1043  if (object_address_present(&thisobj, objsMoved))
1044  continue;
1045 
1046  /* Don't update if the object is already part of the namespace */
1047  if (conform->connamespace == oldNspId && oldNspId != newNspId)
1048  {
1049  tup = heap_copytuple(tup);
1050  conform = (Form_pg_constraint) GETSTRUCT(tup);
1051 
1052  conform->connamespace = newNspId;
1053 
1054  CatalogTupleUpdate(conRel, &tup->t_self, tup);
1055 
1056  /*
1057  * Note: currently, the constraint will not have its own
1058  * dependency on the namespace, so we don't need to do
1059  * changeDependencyFor().
1060  */
1061  }
1062 
1063  InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
1064 
1065  add_exact_object_address(&thisobj, objsMoved);
1066  }
1067 
1068  systable_endscan(scan);
1069 
1070  table_close(conRel, RowExclusiveLock);
1071 }
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2648
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2588
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:777
#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 1626 of file pg_constraint.c.

1630 {
1631  Bitmapset *pkattnos;
1632  Bitmapset *groupbyattnos;
1633  Oid constraintOid;
1634  ListCell *gl;
1635 
1636  /* If the rel has no PK, then we can't prove functional dependency */
1637  pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
1638  if (pkattnos == NULL)
1639  return false;
1640 
1641  /* Identify all the rel's columns that appear in grouping_columns */
1642  groupbyattnos = NULL;
1643  foreach(gl, grouping_columns)
1644  {
1645  Var *gvar = (Var *) lfirst(gl);
1646 
1647  if (IsA(gvar, Var) &&
1648  gvar->varno == varno &&
1649  gvar->varlevelsup == varlevelsup)
1650  groupbyattnos = bms_add_member(groupbyattnos,
1652  }
1653 
1654  if (bms_is_subset(pkattnos, groupbyattnos))
1655  {
1656  /* The PK is a subset of grouping_columns, so we win */
1657  *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
1658  return true;
1659  }
1660 
1661  return false;
1662 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:425
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:828
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 502 of file pg_constraint.c.

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

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

References AccessShareLock, BTEqualStrategyNumber, CStringGetDatum(), HeapTupleIsValid, ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ChooseRelationName().

◆ ConstraintNameIsUsed()

bool ConstraintNameIsUsed ( ConstraintCategory  conCat,
Oid  objId,
const char *  conname 
)

Definition at line 403 of file pg_constraint.c.

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

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

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  conWithoutOverlaps,
bool  is_internal 
)

Definition at line 51 of file pg_constraint.c.

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

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

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

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

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

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

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

Referenced by ATExecDropNotNull(), and dropconstraint_internal().

◆ findNotNullConstraintAttnum()

HeapTuple findNotNullConstraintAttnum ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 577 of file pg_constraint.c.

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

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

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

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

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

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

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

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

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

798 {
799  List *notnulls = NIL;
800  Relation constrRel;
801  HeapTuple htup;
802  SysScanDesc conscan;
803  ScanKeyData skey;
804 
805  constrRel = table_open(ConstraintRelationId, AccessShareLock);
806  ScanKeyInit(&skey,
807  Anum_pg_constraint_conrelid,
808  BTEqualStrategyNumber, F_OIDEQ,
809  ObjectIdGetDatum(relid));
810  conscan = systable_beginscan(constrRel, ConstraintRelidTypidNameIndexId, true,
811  NULL, 1, &skey);
812 
813  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
814  {
816  AttrNumber colnum;
817 
818  if (conForm->contype != CONSTRAINT_NOTNULL)
819  continue;
820  if (conForm->connoinherit)
821  continue;
822 
823  colnum = extractNotNullColumn(htup);
824 
825  if (cooked)
826  {
827  CookedConstraint *cooked;
828 
829  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
830 
831  cooked->contype = CONSTR_NOTNULL;
832  cooked->name = pstrdup(NameStr(conForm->conname));
833  cooked->attnum = colnum;
834  cooked->expr = NULL;
835  cooked->skip_validation = false;
836  cooked->is_local = true;
837  cooked->inhcount = 0;
838  cooked->is_no_inherit = conForm->connoinherit;
839 
840  notnulls = lappend(notnulls, cooked);
841  }
842  else
843  {
844  Constraint *constr;
845 
846  constr = makeNode(Constraint);
847  constr->contype = CONSTR_NOTNULL;
848  constr->conname = pstrdup(NameStr(conForm->conname));
849  constr->deferrable = false;
850  constr->initdeferred = false;
851  constr->location = -1;
852  constr->keys = list_make1(makeString(get_attname(relid, colnum,
853  false)));
854  constr->skip_validation = false;
855  constr->initially_valid = true;
856  notnulls = lappend(notnulls, constr);
857  }
858  }
859 
860  systable_endscan(conscan);
861  table_close(constrRel, AccessShareLock);
862 
863  return notnulls;
864 }
List * lappend(List *list, void *datum)
Definition: list.c:339
char * pstrdup(const char *in)
Definition: mcxt.c:1619
#define makeNode(_type_)
Definition: nodes.h:155
@ CONSTR_NOTNULL
Definition: parsenodes.h:2540
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
bool initdeferred
Definition: parsenodes.h:2577
List * keys
Definition: parsenodes.h:2591
ConstrType contype
Definition: parsenodes.h:2572
bool initially_valid
Definition: parsenodes.h:2624
bool skip_validation
Definition: parsenodes.h:2623
bool deferrable
Definition: parsenodes.h:2576
char * conname
Definition: parsenodes.h:2575
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 871 of file pg_constraint.c.

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

963 {
964  Relation conDesc;
965  HeapTuple tuple;
966  Form_pg_constraint con;
967 
968  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
969 
970  tuple = SearchSysCacheCopy1(CONSTROID, ObjectIdGetDatum(conId));
971  if (!HeapTupleIsValid(tuple))
972  elog(ERROR, "cache lookup failed for constraint %u", conId);
973  con = (Form_pg_constraint) GETSTRUCT(tuple);
974 
975  /*
976  * For user-friendliness, check whether the name is already in use.
977  */
978  if (OidIsValid(con->conrelid) &&
980  con->conrelid,
981  newname))
982  ereport(ERROR,
984  errmsg("constraint \"%s\" for relation \"%s\" already exists",
985  newname, get_rel_name(con->conrelid))));
986  if (OidIsValid(con->contypid) &&
988  con->contypid,
989  newname))
990  ereport(ERROR,
992  errmsg("constraint \"%s\" for domain %s already exists",
993  newname, format_type_be(con->contypid))));
994 
995  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
996  namestrcpy(&(con->conname), newname);
997 
998  CatalogTupleUpdate(conDesc, &tuple->t_self, tuple);
999 
1000  InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
1001 
1002  heap_freetuple(tuple);
1003  table_close(conDesc, RowExclusiveLock);
1004 }
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().