PostgreSQL Source Code git master
pg_constraint.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/gist.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 "common/int.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 isEnforced, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int16 conInhCount, bool conNoInherit, bool conPeriod, bool is_internal)
 
bool ConstraintNameIsUsed (ConstraintCategory conCat, Oid objId, const char *conname)
 
bool ConstraintNameExists (const char *conname, Oid namespaceid)
 
char * ChooseConstraintName (const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
 
HeapTuple findNotNullConstraintAttnum (Oid relid, AttrNumber attnum)
 
HeapTuple findNotNullConstraint (Oid relid, const char *colname)
 
HeapTuple findDomainNotNullConstraint (Oid typid)
 
AttrNumber extractNotNullColumn (HeapTuple constrTup)
 
bool AdjustNotNullInheritance (Oid relid, AttrNumber attnum, bool is_local, bool is_no_inherit)
 
ListRelationGetNotNullConstraints (Oid relid, bool cooked, bool include_noinh)
 
void RemoveConstraintById (Oid conId)
 
void RenameConstraintById (Oid conId, const char *newname)
 
void AlterConstraintNamespaces (Oid ownerId, Oid oldNspId, Oid newNspId, bool isType, ObjectAddresses *objsMoved)
 
void ConstraintSetParentConstraint (Oid childConstrId, Oid parentConstrId, Oid childTableId)
 
Oid get_relation_constraint_oid (Oid relid, const char *conname, bool missing_ok)
 
Bitmapsetget_relation_constraint_attnos (Oid relid, const char *conname, bool missing_ok, Oid *constraintOid)
 
Oid get_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)
 
void FindFKPeriodOpers (Oid opclass, Oid *containedbyoperoid, Oid *aggedcontainedbyoperoid)
 
bool check_functional_grouping (Oid relid, Index varno, Index varlevelsup, List *grouping_columns, List **constraintDeps)
 

Function Documentation

◆ AdjustNotNullInheritance()

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

Definition at line 731 of file pg_constraint.c.

733{
734 HeapTuple tup;
735
737 if (HeapTupleIsValid(tup))
738 {
739 Relation pg_constraint;
740 Form_pg_constraint conform;
741 bool changed = false;
742
743 pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
744 conform = (Form_pg_constraint) GETSTRUCT(tup);
745
746 /*
747 * If the NO INHERIT flag we're asked for doesn't match what the
748 * existing constraint has, throw an error.
749 */
750 if (is_no_inherit != conform->connoinherit)
752 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
753 errmsg("cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"",
754 NameStr(conform->conname), get_rel_name(relid)));
755
756 if (!is_local)
757 {
758 if (pg_add_s16_overflow(conform->coninhcount, 1,
759 &conform->coninhcount))
761 errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
762 errmsg("too many inheritance parents"));
763 changed = true;
764 }
765 else if (!conform->conislocal)
766 {
767 conform->conislocal = true;
768 changed = true;
769 }
770
771 if (changed)
772 CatalogTupleUpdate(pg_constraint, &tup->t_self, tup);
773
774 table_close(pg_constraint, RowExclusiveLock);
775
776 return true;
777 }
778
779 return false;
780}
#define NameStr(name)
Definition: c.h:703
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
static bool pg_add_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:67
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
int16 attnum
Definition: pg_attribute.h:74
HeapTuple findNotNullConstraintAttnum(Oid relid, AttrNumber attnum)
FormData_pg_constraint * Form_pg_constraint
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

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

Referenced by AddRelationNewConstraints().

◆ AlterConstraintNamespaces()

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

Definition at line 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
1071}
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2608
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2548
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:606
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:513
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:778
#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:257
#define InvalidOid
Definition: postgres_ext.h:37
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 1684 of file pg_constraint.c.

1688{
1689 Bitmapset *pkattnos;
1690 Bitmapset *groupbyattnos;
1691 Oid constraintOid;
1692 ListCell *gl;
1693
1694 /* If the rel has no PK, then we can't prove functional dependency */
1695 pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
1696 if (pkattnos == NULL)
1697 return false;
1698
1699 /* Identify all the rel's columns that appear in grouping_columns */
1700 groupbyattnos = NULL;
1701 foreach(gl, grouping_columns)
1702 {
1703 Var *gvar = (Var *) lfirst(gl);
1704
1705 if (IsA(gvar, Var) &&
1706 gvar->varno == varno &&
1707 gvar->varlevelsup == varlevelsup)
1708 groupbyattnos = bms_add_member(groupbyattnos,
1710 }
1711
1712 if (bms_is_subset(pkattnos, groupbyattnos))
1713 {
1714 /* The PK is a subset of grouping_columns, so we win */
1715 *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
1716 return true;
1717 }
1718
1719 return false;
1720}
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:32
Definition: primnodes.h:261
AttrNumber varattno
Definition: primnodes.h:273
int varno
Definition: primnodes.h:268
Index varlevelsup
Definition: primnodes.h:293
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27

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

Referenced by substitute_grouped_columns_mutator().

◆ ChooseConstraintName()

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

Definition at line 509 of file pg_constraint.c.

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

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

Referenced by addFkConstraint(), AddRelationNewConstraints(), AddRelationNotNullConstraints(), ATExecAddConstraint(), ATExecSetNotNull(), domainAddCheckConstraint(), and domainAddNotNullConstraint().

◆ ConstraintNameExists()

bool ConstraintNameExists ( const char *  conname,
Oid  namespaceid 
)

Definition at line 455 of file pg_constraint.c.

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

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

412{
413 bool found;
414 Relation conDesc;
415 SysScanDesc conscan;
416 ScanKeyData skey[3];
417
418 conDesc = table_open(ConstraintRelationId, AccessShareLock);
419
420 ScanKeyInit(&skey[0],
421 Anum_pg_constraint_conrelid,
422 BTEqualStrategyNumber, F_OIDEQ,
424 ? objId : InvalidOid));
425 ScanKeyInit(&skey[1],
426 Anum_pg_constraint_contypid,
427 BTEqualStrategyNumber, F_OIDEQ,
429 ? objId : InvalidOid));
430 ScanKeyInit(&skey[2],
431 Anum_pg_constraint_conname,
432 BTEqualStrategyNumber, F_NAMEEQ,
433 CStringGetDatum(conname));
434
435 conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId,
436 true, NULL, 3, skey);
437
438 /* There can be at most one matching row */
439 found = (HeapTupleIsValid(systable_getnext(conscan)));
440
441 systable_endscan(conscan);
443
444 return found;
445}
@ 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 addFkConstraint(), AddRelationNewConstraints(), ATExecAddConstraint(), domainAddCheckConstraint(), domainAddNotNullConstraint(), 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 if (pg_add_s16_overflow(constrForm->coninhcount, 1,
1110 &constrForm->coninhcount))
1111 ereport(ERROR,
1112 errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1113 errmsg("too many inheritance parents"));
1114
1115 constrForm->conparentid = parentConstrId;
1116
1117 CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
1118
1119 ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
1120
1121 ObjectAddressSet(referenced, ConstraintRelationId, parentConstrId);
1122 recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
1123
1124 ObjectAddressSet(referenced, RelationRelationId, childTableId);
1125 recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
1126 }
1127 else
1128 {
1129 constrForm->coninhcount--;
1130 constrForm->conislocal = true;
1131 constrForm->conparentid = InvalidOid;
1132
1133 /* Make sure there's no further inheritance. */
1134 Assert(constrForm->coninhcount == 0);
1135
1136 CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
1137
1138 deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
1139 ConstraintRelationId,
1141 deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
1142 RelationRelationId,
1144 }
1145
1146 ReleaseSysCache(tuple);
1147 table_close(constrRel, RowExclusiveLock);
1148}
#define Assert(condition)
Definition: c.h:815
#define OidIsValid(objectId)
Definition: c.h:732
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
#define elog(elevel,...)
Definition: elog.h:225
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:45
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:351
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

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

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

◆ CreateConstraintEntry()

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

Definition at line 51 of file pg_constraint.c.

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

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

Referenced by addFkConstraint(), CreateTriggerFiringOn(), domainAddCheckConstraint(), domainAddNotNullConstraint(), index_constraint_create(), StoreRelCheck(), and StoreRelNotNull().

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

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

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

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

◆ extractNotNullColumn()

AttrNumber extractNotNullColumn ( HeapTuple  constrTup)

Definition at line 696 of file pg_constraint.c.

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

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

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

◆ findDomainNotNullConstraint()

HeapTuple findDomainNotNullConstraint ( Oid  typid)

Definition at line 652 of file pg_constraint.c.

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

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

Referenced by AlterDomainNotNull().

◆ FindFKPeriodOpers()

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

Definition at line 1623 of file pg_constraint.c.

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

References COMPARE_CONTAINED_BY, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, get_opclass_opfamily_and_input_type(), GetOperatorFromCompareType(), and InvalidOid.

Referenced by ATAddForeignKeyConstraint(), and ri_LoadConstraintInfo().

◆ findNotNullConstraint()

HeapTuple findNotNullConstraint ( Oid  relid,
const char *  colname 
)

Definition at line 636 of file pg_constraint.c.

637{
639
640 attnum = get_attnum(relid, colname);
642 return NULL;
643
644 return findNotNullConstraintAttnum(relid, attnum);
645}
#define InvalidAttrNumber
Definition: attnum.h:23
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:858

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

Referenced by dropconstraint_internal().

◆ findNotNullConstraintAttnum()

HeapTuple findNotNullConstraintAttnum ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 585 of file pg_constraint.c.

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

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

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

◆ get_domain_constraint_oid()

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

Definition at line 1350 of file pg_constraint.c.

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

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

◆ get_relation_constraint_attnos()

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

Definition at line 1214 of file pg_constraint.c.

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

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

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

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

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

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,
bool  include_noinh 
)

Definition at line 793 of file pg_constraint.c.

794{
795 List *notnulls = NIL;
796 Relation constrRel;
797 HeapTuple htup;
798 SysScanDesc conscan;
799 ScanKeyData skey;
800
801 constrRel = table_open(ConstraintRelationId, AccessShareLock);
802 ScanKeyInit(&skey,
803 Anum_pg_constraint_conrelid,
804 BTEqualStrategyNumber, F_OIDEQ,
805 ObjectIdGetDatum(relid));
806 conscan = systable_beginscan(constrRel, ConstraintRelidTypidNameIndexId, true,
807 NULL, 1, &skey);
808
809 while (HeapTupleIsValid(htup = systable_getnext(conscan)))
810 {
812 AttrNumber colnum;
813
814 if (conForm->contype != CONSTRAINT_NOTNULL)
815 continue;
816 if (conForm->connoinherit && !include_noinh)
817 continue;
818
819 colnum = extractNotNullColumn(htup);
820
821 if (cooked)
822 {
823 CookedConstraint *cooked;
824
825 cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
826
827 cooked->contype = CONSTR_NOTNULL;
828 cooked->conoid = conForm->oid;
829 cooked->name = pstrdup(NameStr(conForm->conname));
830 cooked->attnum = colnum;
831 cooked->expr = NULL;
832 cooked->is_enforced = true;
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->is_enforced = true;
853 constr->skip_validation = false;
854 constr->initially_valid = true;
855 constr->is_no_inherit = conForm->connoinherit;
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 * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:827
char * pstrdup(const char *in)
Definition: mcxt.c:1696
#define makeNode(_type_)
Definition: nodes.h:155
@ CONSTR_NOTNULL
Definition: parsenodes.h:2770
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
bool initdeferred
Definition: parsenodes.h:2805
ParseLoc location
Definition: parsenodes.h:2845
List * keys
Definition: parsenodes.h:2816
ConstrType contype
Definition: parsenodes.h:2802
bool is_no_inherit
Definition: parsenodes.h:2809
bool is_enforced
Definition: parsenodes.h:2806
bool initially_valid
Definition: parsenodes.h:2808
bool skip_validation
Definition: parsenodes.h:2807
bool deferrable
Definition: parsenodes.h:2804
char * conname
Definition: parsenodes.h:2803
Oid conoid
Definition: heap.h:39
char * name
Definition: heap.h:40
AttrNumber attnum
Definition: heap.h:41
bool skip_validation
Definition: heap.h:44
bool is_enforced
Definition: heap.h:43
bool is_no_inherit
Definition: heap.h:47
int16 inhcount
Definition: heap.h:46
bool is_local
Definition: heap.h:45
ConstrType contype
Definition: heap.h:37
Node * expr
Definition: heap.h:42
Definition: pg_list.h:54
String * makeString(char *str)
Definition: value.c:63

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

Referenced by MergeAttributes(), and transformTableLikeClause().

◆ RemoveConstraintById()

void RemoveConstraintById ( Oid  conId)

Definition at line 871 of file pg_constraint.c.

872{
873 Relation conDesc;
874 HeapTuple tup;
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);
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:539
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:91

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

Referenced by doDeletion().

◆ RenameConstraintById()

void RenameConstraintById ( Oid  conId,
const char *  newname 
)

Definition at line 962 of file pg_constraint.c.

963{
964 Relation conDesc;
965 HeapTuple tuple;
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))
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))
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:30

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

Referenced by rename_constraint_internal(), and RenameRelationInternal().