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, bool is_notvalid)
 
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, Oid *intersectoperoid)
 
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,
bool  is_notvalid 
)

Definition at line 741 of file pg_constraint.c.

743{
744 HeapTuple tup;
745
747 if (HeapTupleIsValid(tup))
748 {
749 Relation pg_constraint;
750 Form_pg_constraint conform;
751 bool changed = false;
752
753 pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
754 conform = (Form_pg_constraint) GETSTRUCT(tup);
755
756 /*
757 * If the NO INHERIT flag we're asked for doesn't match what the
758 * existing constraint has, throw an error.
759 */
760 if (is_no_inherit != conform->connoinherit)
762 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
763 errmsg("cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"",
764 NameStr(conform->conname), get_rel_name(relid)),
765 errhint("You might need to make the existing constraint inheritable using %s.",
766 "ALTER TABLE ... ALTER CONSTRAINT ... INHERIT"));
767
768 /*
769 * Throw an error if the existing constraint is NOT VALID and caller
770 * wants a valid one.
771 */
772 if (!is_notvalid && !conform->convalidated)
774 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
775 errmsg("incompatible NOT VALID constraint \"%s\" on relation \"%s\"",
776 NameStr(conform->conname), get_rel_name(relid)),
777 errhint("You might need to validate it using %s.",
778 "ALTER TABLE ... VALIDATE CONSTRAINT"));
779
780 if (!is_local)
781 {
782 if (pg_add_s16_overflow(conform->coninhcount, 1,
783 &conform->coninhcount))
785 errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
786 errmsg("too many inheritance parents"));
787 changed = true;
788 }
789 else if (!conform->conislocal)
790 {
791 conform->conislocal = true;
792 changed = true;
793 }
794
795 if (changed)
796 CatalogTupleUpdate(pg_constraint, &tup->t_self, tup);
797
798 table_close(pg_constraint, RowExclusiveLock);
799
800 return true;
801 }
802
803 return false;
804}
#define NameStr(name)
Definition: c.h:717
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
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:2068
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(), errhint(), 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 1038 of file pg_constraint.c.

1040{
1041 Relation conRel;
1042 ScanKeyData key[2];
1043 SysScanDesc scan;
1044 HeapTuple tup;
1045
1046 conRel = table_open(ConstraintRelationId, RowExclusiveLock);
1047
1048 ScanKeyInit(&key[0],
1049 Anum_pg_constraint_conrelid,
1050 BTEqualStrategyNumber, F_OIDEQ,
1051 ObjectIdGetDatum(isType ? InvalidOid : ownerId));
1052 ScanKeyInit(&key[1],
1053 Anum_pg_constraint_contypid,
1054 BTEqualStrategyNumber, F_OIDEQ,
1055 ObjectIdGetDatum(isType ? ownerId : InvalidOid));
1056
1057 scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId, true,
1058 NULL, 2, key);
1059
1060 while (HeapTupleIsValid((tup = systable_getnext(scan))))
1061 {
1063 ObjectAddress thisobj;
1064
1065 ObjectAddressSet(thisobj, ConstraintRelationId, conform->oid);
1066
1067 if (object_address_present(&thisobj, objsMoved))
1068 continue;
1069
1070 /* Don't update if the object is already part of the namespace */
1071 if (conform->connamespace == oldNspId && oldNspId != newNspId)
1072 {
1073 tup = heap_copytuple(tup);
1074 conform = (Form_pg_constraint) GETSTRUCT(tup);
1075
1076 conform->connamespace = newNspId;
1077
1078 CatalogTupleUpdate(conRel, &tup->t_self, tup);
1079
1080 /*
1081 * Note: currently, the constraint will not have its own
1082 * dependency on the namespace, so we don't need to do
1083 * changeDependencyFor().
1084 */
1085 }
1086
1087 InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
1088
1089 add_exact_object_address(&thisobj, objsMoved);
1090 }
1091
1092 systable_endscan(scan);
1093
1095}
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:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:388
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:35
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 1723 of file pg_constraint.c.

1727{
1728 Bitmapset *pkattnos;
1729 Bitmapset *groupbyattnos;
1730 Oid constraintOid;
1731 ListCell *gl;
1732
1733 /* If the rel has no PK, then we can't prove functional dependency */
1734 pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
1735 if (pkattnos == NULL)
1736 return false;
1737
1738 /* Identify all the rel's columns that appear in grouping_columns */
1739 groupbyattnos = NULL;
1740 foreach(gl, grouping_columns)
1741 {
1742 Var *gvar = (Var *) lfirst(gl);
1743
1744 if (IsA(gvar, Var) &&
1745 gvar->varno == varno &&
1746 gvar->varlevelsup == varlevelsup)
1747 groupbyattnos = bms_add_member(groupbyattnos,
1749 }
1750
1751 if (bms_is_subset(pkattnos, groupbyattnos))
1752 {
1753 /* The PK is a subset of grouping_columns, so we win */
1754 *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
1755 return true;
1756 }
1757
1758 return false;
1759}
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:164
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:30
Definition: primnodes.h:262
AttrNumber varattno
Definition: primnodes.h:274
int varno
Definition: primnodes.h:269
Index varlevelsup
Definition: primnodes.h:294
#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 513 of file pg_constraint.c.

516{
517 int pass = 0;
518 char *conname = NULL;
519 char modlabel[NAMEDATALEN];
520 Relation conDesc;
521 SysScanDesc conscan;
522 ScanKeyData skey[2];
523 bool found;
524 ListCell *l;
525
526 conDesc = table_open(ConstraintRelationId, AccessShareLock);
527
528 /* try the unmodified label first, unless it's empty */
529 if (label[0] != '\0')
530 strlcpy(modlabel, label, sizeof(modlabel));
531 else
532 snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
533
534 for (;;)
535 {
536 conname = makeObjectName(name1, name2, modlabel);
537
538 found = false;
539
540 foreach(l, others)
541 {
542 if (strcmp((char *) lfirst(l), conname) == 0)
543 {
544 found = true;
545 break;
546 }
547 }
548
549 if (!found)
550 {
551 ScanKeyInit(&skey[0],
552 Anum_pg_constraint_conname,
553 BTEqualStrategyNumber, F_NAMEEQ,
554 CStringGetDatum(conname));
555
556 ScanKeyInit(&skey[1],
557 Anum_pg_constraint_connamespace,
558 BTEqualStrategyNumber, F_OIDEQ,
559 ObjectIdGetDatum(namespaceid));
560
561 conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
562 NULL, 2, skey);
563
564 found = (HeapTupleIsValid(systable_getnext(conscan)));
565
566 systable_endscan(conscan);
567 }
568
569 if (!found)
570 break;
571
572 /* found a conflict, so try a new name component */
573 pfree(conname);
574 snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
575 }
576
578
579 return conname;
580}
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition: indexcmds.c:2518
#define AccessShareLock
Definition: lockdefs.h:36
void pfree(void *pointer)
Definition: mcxt.c:2152
static char * label
#define NAMEDATALEN
#define snprintf
Definition: port.h:239
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 457 of file pg_constraint.c.

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

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

414{
415 bool found;
416 Relation conDesc;
417 SysScanDesc conscan;
418 ScanKeyData skey[3];
419
420 conDesc = table_open(ConstraintRelationId, AccessShareLock);
421
422 ScanKeyInit(&skey[0],
423 Anum_pg_constraint_conrelid,
424 BTEqualStrategyNumber, F_OIDEQ,
426 ? objId : InvalidOid));
427 ScanKeyInit(&skey[1],
428 Anum_pg_constraint_contypid,
429 BTEqualStrategyNumber, F_OIDEQ,
431 ? objId : InvalidOid));
432 ScanKeyInit(&skey[2],
433 Anum_pg_constraint_conname,
434 BTEqualStrategyNumber, F_NAMEEQ,
435 CStringGetDatum(conname));
436
437 conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId,
438 true, NULL, 3, skey);
439
440 /* There can be at most one matching row */
441 found = (HeapTupleIsValid(systable_getnext(conscan)));
442
443 systable_endscan(conscan);
445
446 return found;
447}
@ 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 1107 of file pg_constraint.c.

1110{
1111 Relation constrRel;
1112 Form_pg_constraint constrForm;
1113 HeapTuple tuple,
1114 newtup;
1115 ObjectAddress depender;
1116 ObjectAddress referenced;
1117
1118 constrRel = table_open(ConstraintRelationId, RowExclusiveLock);
1119 tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(childConstrId));
1120 if (!HeapTupleIsValid(tuple))
1121 elog(ERROR, "cache lookup failed for constraint %u", childConstrId);
1122 newtup = heap_copytuple(tuple);
1123 constrForm = (Form_pg_constraint) GETSTRUCT(newtup);
1124 if (OidIsValid(parentConstrId))
1125 {
1126 /* don't allow setting parent for a constraint that already has one */
1127 Assert(constrForm->coninhcount == 0);
1128 if (constrForm->conparentid != InvalidOid)
1129 elog(ERROR, "constraint %u already has a parent constraint",
1130 childConstrId);
1131
1132 constrForm->conislocal = false;
1133 if (pg_add_s16_overflow(constrForm->coninhcount, 1,
1134 &constrForm->coninhcount))
1135 ereport(ERROR,
1136 errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1137 errmsg("too many inheritance parents"));
1138
1139 constrForm->conparentid = parentConstrId;
1140
1141 CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
1142
1143 ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
1144
1145 ObjectAddressSet(referenced, ConstraintRelationId, parentConstrId);
1146 recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
1147
1148 ObjectAddressSet(referenced, RelationRelationId, childTableId);
1149 recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
1150 }
1151 else
1152 {
1153 constrForm->coninhcount--;
1154 constrForm->conislocal = true;
1155 constrForm->conparentid = InvalidOid;
1156
1157 /* Make sure there's no further inheritance. */
1158 Assert(constrForm->coninhcount == 0);
1159
1160 CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
1161
1162 deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
1163 ConstraintRelationId,
1165 deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
1166 RelationRelationId,
1168 }
1169
1170 ReleaseSysCache(tuple);
1171 table_close(constrRel, RowExclusiveLock);
1172}
#define OidIsValid(objectId)
Definition: c.h:746
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
#define elog(elevel,...)
Definition: elog.h:225
Assert(PointerIsAligned(start, uint64))
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(), AttachPartitionForeignKey(), DefineIndex(), and DetachPartitionFinalize().

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

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, Max, 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 1519 of file pg_constraint.c.

1523{
1524 Datum adatum;
1525 bool isNull;
1526 ArrayType *arr;
1527 int numkeys;
1528
1529 /*
1530 * We expect the arrays to be 1-D arrays of the right types; verify that.
1531 * We don't need to use deconstruct_array() since the array data is just
1532 * going to look like a C array of values.
1533 */
1534 adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
1535 Anum_pg_constraint_conkey);
1536 arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1537 if (ARR_NDIM(arr) != 1 ||
1538 ARR_HASNULL(arr) ||
1539 ARR_ELEMTYPE(arr) != INT2OID)
1540 elog(ERROR, "conkey is not a 1-D smallint array");
1541 numkeys = ARR_DIMS(arr)[0];
1542 if (numkeys <= 0 || numkeys > INDEX_MAX_KEYS)
1543 elog(ERROR, "foreign key constraint cannot have %d columns", numkeys);
1544 memcpy(conkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
1545 if ((Pointer) arr != DatumGetPointer(adatum))
1546 pfree(arr); /* free de-toasted copy, if any */
1547
1548 adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
1549 Anum_pg_constraint_confkey);
1550 arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1551 if (ARR_NDIM(arr) != 1 ||
1552 ARR_DIMS(arr)[0] != numkeys ||
1553 ARR_HASNULL(arr) ||
1554 ARR_ELEMTYPE(arr) != INT2OID)
1555 elog(ERROR, "confkey is not a 1-D smallint array");
1556 memcpy(confkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
1557 if ((Pointer) arr != DatumGetPointer(adatum))
1558 pfree(arr); /* free de-toasted copy, if any */
1559
1560 if (pf_eq_oprs)
1561 {
1562 adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
1563 Anum_pg_constraint_conpfeqop);
1564 arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1565 /* see TryReuseForeignKey if you change the test below */
1566 if (ARR_NDIM(arr) != 1 ||
1567 ARR_DIMS(arr)[0] != numkeys ||
1568 ARR_HASNULL(arr) ||
1569 ARR_ELEMTYPE(arr) != OIDOID)
1570 elog(ERROR, "conpfeqop is not a 1-D Oid array");
1571 memcpy(pf_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
1572 if ((Pointer) arr != DatumGetPointer(adatum))
1573 pfree(arr); /* free de-toasted copy, if any */
1574 }
1575
1576 if (pp_eq_oprs)
1577 {
1578 adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
1579 Anum_pg_constraint_conppeqop);
1580 arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1581 if (ARR_NDIM(arr) != 1 ||
1582 ARR_DIMS(arr)[0] != numkeys ||
1583 ARR_HASNULL(arr) ||
1584 ARR_ELEMTYPE(arr) != OIDOID)
1585 elog(ERROR, "conppeqop is not a 1-D Oid array");
1586 memcpy(pp_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
1587 if ((Pointer) arr != DatumGetPointer(adatum))
1588 pfree(arr); /* free de-toasted copy, if any */
1589 }
1590
1591 if (ff_eq_oprs)
1592 {
1593 adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
1594 Anum_pg_constraint_conffeqop);
1595 arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1596 if (ARR_NDIM(arr) != 1 ||
1597 ARR_DIMS(arr)[0] != numkeys ||
1598 ARR_HASNULL(arr) ||
1599 ARR_ELEMTYPE(arr) != OIDOID)
1600 elog(ERROR, "conffeqop is not a 1-D Oid array");
1601 memcpy(ff_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
1602 if ((Pointer) arr != DatumGetPointer(adatum))
1603 pfree(arr); /* free de-toasted copy, if any */
1604 }
1605
1606 if (fk_del_set_cols)
1607 {
1608 adatum = SysCacheGetAttr(CONSTROID, tuple,
1609 Anum_pg_constraint_confdelsetcols, &isNull);
1610 if (isNull)
1611 {
1612 *num_fk_del_set_cols = 0;
1613 }
1614 else
1615 {
1616 int num_delete_cols;
1617
1618 arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1619 if (ARR_NDIM(arr) != 1 ||
1620 ARR_HASNULL(arr) ||
1621 ARR_ELEMTYPE(arr) != INT2OID)
1622 elog(ERROR, "confdelsetcols is not a 1-D smallint array");
1623 num_delete_cols = ARR_DIMS(arr)[0];
1624 memcpy(fk_del_set_cols, ARR_DATA_PTR(arr), num_delete_cols * sizeof(int16));
1625 if ((Pointer) arr != DatumGetPointer(adatum))
1626 pfree(arr); /* free de-toasted copy, if any */
1627
1628 *num_fk_del_set_cols = num_delete_cols;
1629 }
1630 }
1631
1632 *numfks = numkeys;
1633}
#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:493
int16_t int16
Definition: c.h:497
#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 702 of file pg_constraint.c.

703{
704 Datum adatum;
705 ArrayType *arr;
706
707 /* only tuples for not-null constraints should be given */
708 Assert(((Form_pg_constraint) GETSTRUCT(constrTup))->contype == CONSTRAINT_NOTNULL);
709
710 adatum = SysCacheGetAttrNotNull(CONSTROID, constrTup,
711 Anum_pg_constraint_conkey);
712 arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
713 if (ARR_NDIM(arr) != 1 ||
714 ARR_HASNULL(arr) ||
715 ARR_ELEMTYPE(arr) != INT2OID ||
716 ARR_DIMS(arr)[0] != 1)
717 elog(ERROR, "conkey is not a 1-D smallint array");
718
719 /* We leak the detoasted datum, but we don't care */
720
721 return ((AttrNumber *) ARR_DATA_PTR(arr))[0];
722}
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 ATExecAlterConstrInheritability(), CheckNNConstraintFetch(), dropconstraint_internal(), findNotNullConstraintAttnum(), MergeConstraintsIntoExisting(), pg_get_constraintdef_worker(), QueueNNConstraintValidation(), RelationGetNotNullConstraints(), and RemoveInheritance().

◆ findDomainNotNullConstraint()

HeapTuple findDomainNotNullConstraint ( Oid  typid)

Definition at line 658 of file pg_constraint.c.

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

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,
Oid intersectoperoid 
)

Definition at line 1649 of file pg_constraint.c.

1653{
1654 Oid opfamily = InvalidOid;
1655 Oid opcintype = InvalidOid;
1656 StrategyNumber strat;
1657
1658 /* Make sure we have a range or multirange. */
1659 if (get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype))
1660 {
1661 if (opcintype != ANYRANGEOID && opcintype != ANYMULTIRANGEOID)
1662 ereport(ERROR,
1663 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1664 errmsg("invalid type for PERIOD part of foreign key"),
1665 errdetail("Only range and multirange are supported."));
1666
1667 }
1668 else
1669 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1670
1671 /*
1672 * Look up the ContainedBy operator whose lhs and rhs are the opclass's
1673 * type. We use this to optimize RI checks: if the new value includes all
1674 * of the old value, then we can treat the attribute as if it didn't
1675 * change, and skip the RI check.
1676 */
1678 InvalidOid,
1680 containedbyoperoid,
1681 &strat);
1682
1683 /*
1684 * Now look up the ContainedBy operator. Its left arg must be the type of
1685 * the column (or rather of the opclass). Its right arg must match the
1686 * return type of the support proc.
1687 */
1689 ANYMULTIRANGEOID,
1691 aggedcontainedbyoperoid,
1692 &strat);
1693
1694 switch (opcintype)
1695 {
1696 case ANYRANGEOID:
1697 *intersectoperoid = OID_RANGE_INTERSECT_RANGE_OP;
1698 break;
1699 case ANYMULTIRANGEOID:
1700 *intersectoperoid = OID_MULTIRANGE_INTERSECT_MULTIRANGE_OP;
1701 break;
1702 default:
1703 elog(ERROR, "unexpected opcintype: %u", opcintype);
1704 }
1705}
@ COMPARE_CONTAINED_BY
Definition: cmptype.h:41
int errdetail(const char *fmt,...)
Definition: elog.c:1204
void GetOperatorFromCompareType(Oid opclass, Oid rhstype, CompareType cmptype, Oid *opid, StrategyNumber *strat)
Definition: indexcmds.c:2447
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Definition: lsyscache.c:1327
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 642 of file pg_constraint.c.

643{
645
646 attnum = get_attnum(relid, colname);
648 return NULL;
649
650 return findNotNullConstraintAttnum(relid, attnum);
651}
#define InvalidAttrNumber
Definition: attnum.h:23
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:950

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

Referenced by ATExecAlterConstrInheritability(), ATPrepAddPrimaryKey(), dropconstraint_internal(), and QueueNNConstraintValidation().

◆ findNotNullConstraintAttnum()

HeapTuple findNotNullConstraintAttnum ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 592 of file pg_constraint.c.

593{
594 Relation pg_constraint;
595 HeapTuple conTup,
596 retval = NULL;
597 SysScanDesc scan;
599
600 pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
602 Anum_pg_constraint_conrelid,
603 BTEqualStrategyNumber, F_OIDEQ,
604 ObjectIdGetDatum(relid));
605 scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
606 true, NULL, 1, &key);
607
608 while (HeapTupleIsValid(conTup = systable_getnext(scan)))
609 {
611 AttrNumber conkey;
612
613 /*
614 * We're looking for a NOTNULL constraint with the column we're
615 * looking for as the sole element in conkey.
616 */
617 if (con->contype != CONSTRAINT_NOTNULL)
618 continue;
619
620 conkey = extractNotNullColumn(conTup);
621 if (conkey != attnum)
622 continue;
623
624 /* Found it */
625 retval = heap_copytuple(conTup);
626 break;
627 }
628
629 systable_endscan(scan);
630 table_close(pg_constraint, AccessShareLock);
631
632 return retval;
633}
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 1374 of file pg_constraint.c.

1375{
1376 Relation pg_constraint;
1377 HeapTuple tuple;
1378 SysScanDesc scan;
1379 ScanKeyData skey[3];
1380 Oid conOid = InvalidOid;
1381
1382 pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1383
1384 ScanKeyInit(&skey[0],
1385 Anum_pg_constraint_conrelid,
1386 BTEqualStrategyNumber, F_OIDEQ,
1388 ScanKeyInit(&skey[1],
1389 Anum_pg_constraint_contypid,
1390 BTEqualStrategyNumber, F_OIDEQ,
1391 ObjectIdGetDatum(typid));
1392 ScanKeyInit(&skey[2],
1393 Anum_pg_constraint_conname,
1394 BTEqualStrategyNumber, F_NAMEEQ,
1395 CStringGetDatum(conname));
1396
1397 scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1398 NULL, 3, skey);
1399
1400 /* There can be at most one matching row */
1401 if (HeapTupleIsValid(tuple = systable_getnext(scan)))
1402 conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1403
1404 systable_endscan(scan);
1405
1406 /* If no such constraint exists, complain */
1407 if (!OidIsValid(conOid) && !missing_ok)
1408 ereport(ERROR,
1409 (errcode(ERRCODE_UNDEFINED_OBJECT),
1410 errmsg("constraint \"%s\" for domain %s does not exist",
1411 conname, format_type_be(typid))));
1412
1413 table_close(pg_constraint, AccessShareLock);
1414
1415 return conOid;
1416}
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 1433 of file pg_constraint.c.

1434{
1435 Bitmapset *pkattnos = NULL;
1436 Relation pg_constraint;
1437 HeapTuple tuple;
1438 SysScanDesc scan;
1439 ScanKeyData skey[1];
1440
1441 /* Set *constraintOid, to avoid complaints about uninitialized vars */
1442 *constraintOid = InvalidOid;
1443
1444 /* Scan pg_constraint for constraints of the target rel */
1445 pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1446
1447 ScanKeyInit(&skey[0],
1448 Anum_pg_constraint_conrelid,
1449 BTEqualStrategyNumber, F_OIDEQ,
1450 ObjectIdGetDatum(relid));
1451
1452 scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1453 NULL, 1, skey);
1454
1455 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1456 {
1458 Datum adatum;
1459 bool isNull;
1460 ArrayType *arr;
1461 int16 *attnums;
1462 int numkeys;
1463 int i;
1464
1465 /* Skip constraints that are not PRIMARY KEYs */
1466 if (con->contype != CONSTRAINT_PRIMARY)
1467 continue;
1468
1469 /*
1470 * If the primary key is deferrable, but we've been instructed to
1471 * ignore deferrable constraints, then we might as well give up
1472 * searching, since there can only be a single primary key on a table.
1473 */
1474 if (con->condeferrable && !deferrableOk)
1475 break;
1476
1477 /* Extract the conkey array, ie, attnums of PK's columns */
1478 adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
1479 RelationGetDescr(pg_constraint), &isNull);
1480 if (isNull)
1481 elog(ERROR, "null conkey for constraint %u",
1482 ((Form_pg_constraint) GETSTRUCT(tuple))->oid);
1483 arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1484 numkeys = ARR_DIMS(arr)[0];
1485 if (ARR_NDIM(arr) != 1 ||
1486 numkeys < 0 ||
1487 ARR_HASNULL(arr) ||
1488 ARR_ELEMTYPE(arr) != INT2OID)
1489 elog(ERROR, "conkey is not a 1-D smallint array");
1490 attnums = (int16 *) ARR_DATA_PTR(arr);
1491
1492 /* Construct the result value */
1493 for (i = 0; i < numkeys; i++)
1494 {
1495 pkattnos = bms_add_member(pkattnos,
1497 }
1498 *constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1499
1500 /* No need to search further */
1501 break;
1502 }
1503
1504 systable_endscan(scan);
1505
1506 table_close(pg_constraint, AccessShareLock);
1507
1508 return pkattnos;
1509}
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:904

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

1240{
1241 Bitmapset *conattnos = NULL;
1242 Relation pg_constraint;
1243 HeapTuple tuple;
1244 SysScanDesc scan;
1245 ScanKeyData skey[3];
1246
1247 /* Set *constraintOid, to avoid complaints about uninitialized vars */
1248 *constraintOid = InvalidOid;
1249
1250 pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1251
1252 ScanKeyInit(&skey[0],
1253 Anum_pg_constraint_conrelid,
1254 BTEqualStrategyNumber, F_OIDEQ,
1255 ObjectIdGetDatum(relid));
1256 ScanKeyInit(&skey[1],
1257 Anum_pg_constraint_contypid,
1258 BTEqualStrategyNumber, F_OIDEQ,
1260 ScanKeyInit(&skey[2],
1261 Anum_pg_constraint_conname,
1262 BTEqualStrategyNumber, F_NAMEEQ,
1263 CStringGetDatum(conname));
1264
1265 scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1266 NULL, 3, skey);
1267
1268 /* There can be at most one matching row */
1269 if (HeapTupleIsValid(tuple = systable_getnext(scan)))
1270 {
1271 Datum adatum;
1272 bool isNull;
1273
1274 *constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1275
1276 /* Extract the conkey array, ie, attnums of constrained columns */
1277 adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
1278 RelationGetDescr(pg_constraint), &isNull);
1279 if (!isNull)
1280 {
1281 ArrayType *arr;
1282 int numcols;
1283 int16 *attnums;
1284 int i;
1285
1286 arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
1287 numcols = ARR_DIMS(arr)[0];
1288 if (ARR_NDIM(arr) != 1 ||
1289 numcols < 0 ||
1290 ARR_HASNULL(arr) ||
1291 ARR_ELEMTYPE(arr) != INT2OID)
1292 elog(ERROR, "conkey is not a 1-D smallint array");
1293 attnums = (int16 *) ARR_DATA_PTR(arr);
1294
1295 /* Construct the result value */
1296 for (i = 0; i < numcols; i++)
1297 {
1298 conattnos = bms_add_member(conattnos,
1300 }
1301 }
1302 }
1303
1304 systable_endscan(scan);
1305
1306 /* If no such constraint exists, complain */
1307 if (!OidIsValid(*constraintOid) && !missing_ok)
1308 ereport(ERROR,
1309 (errcode(ERRCODE_UNDEFINED_OBJECT),
1310 errmsg("constraint \"%s\" for table \"%s\" does not exist",
1311 conname, get_rel_name(relid))));
1312
1313 table_close(pg_constraint, AccessShareLock);
1314
1315 return conattnos;
1316}

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

1182{
1183 Relation pg_constraint;
1184 HeapTuple tuple;
1185 SysScanDesc scan;
1186 ScanKeyData skey[3];
1187 Oid conOid = InvalidOid;
1188
1189 pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1190
1191 ScanKeyInit(&skey[0],
1192 Anum_pg_constraint_conrelid,
1193 BTEqualStrategyNumber, F_OIDEQ,
1194 ObjectIdGetDatum(relid));
1195 ScanKeyInit(&skey[1],
1196 Anum_pg_constraint_contypid,
1197 BTEqualStrategyNumber, F_OIDEQ,
1199 ScanKeyInit(&skey[2],
1200 Anum_pg_constraint_conname,
1201 BTEqualStrategyNumber, F_NAMEEQ,
1202 CStringGetDatum(conname));
1203
1204 scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
1205 NULL, 3, skey);
1206
1207 /* There can be at most one matching row */
1208 if (HeapTupleIsValid(tuple = systable_getnext(scan)))
1209 conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
1210
1211 systable_endscan(scan);
1212
1213 /* If no such constraint exists, complain */
1214 if (!OidIsValid(conOid) && !missing_ok)
1215 ereport(ERROR,
1216 (errcode(ERRCODE_UNDEFINED_OBJECT),
1217 errmsg("constraint \"%s\" for table \"%s\" does not exist",
1218 conname, get_rel_name(relid))));
1219
1220 table_close(pg_constraint, AccessShareLock);
1221
1222 return conOid;
1223}

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

1328{
1329 Relation pg_constraint;
1330 SysScanDesc scan;
1332 HeapTuple tuple;
1333 Oid constraintId = InvalidOid;
1334
1335 pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
1336
1338 Anum_pg_constraint_conrelid,
1340 F_OIDEQ,
1341 ObjectIdGetDatum(relationId));
1342 scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
1343 true, NULL, 1, &key);
1344 while ((tuple = systable_getnext(scan)) != NULL)
1345 {
1346 Form_pg_constraint constrForm;
1347
1348 constrForm = (Form_pg_constraint) GETSTRUCT(tuple);
1349
1350 /* See above */
1351 if (constrForm->contype != CONSTRAINT_PRIMARY &&
1352 constrForm->contype != CONSTRAINT_UNIQUE &&
1353 constrForm->contype != CONSTRAINT_EXCLUSION)
1354 continue;
1355
1356 if (constrForm->conindid == indexId)
1357 {
1358 constraintId = constrForm->oid;
1359 break;
1360 }
1361 }
1362 systable_endscan(scan);
1363
1364 table_close(pg_constraint, AccessShareLock);
1365 return constraintId;
1366}

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

818{
819 List *notnulls = NIL;
820 Relation constrRel;
821 HeapTuple htup;
822 SysScanDesc conscan;
823 ScanKeyData skey;
824
825 constrRel = table_open(ConstraintRelationId, AccessShareLock);
826 ScanKeyInit(&skey,
827 Anum_pg_constraint_conrelid,
828 BTEqualStrategyNumber, F_OIDEQ,
829 ObjectIdGetDatum(relid));
830 conscan = systable_beginscan(constrRel, ConstraintRelidTypidNameIndexId, true,
831 NULL, 1, &skey);
832
833 while (HeapTupleIsValid(htup = systable_getnext(conscan)))
834 {
836 AttrNumber colnum;
837
838 if (conForm->contype != CONSTRAINT_NOTNULL)
839 continue;
840 if (conForm->connoinherit && !include_noinh)
841 continue;
842
843 colnum = extractNotNullColumn(htup);
844
845 if (cooked)
846 {
847 CookedConstraint *cooked;
848
849 cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
850
851 cooked->contype = CONSTR_NOTNULL;
852 cooked->conoid = conForm->oid;
853 cooked->name = pstrdup(NameStr(conForm->conname));
854 cooked->attnum = colnum;
855 cooked->expr = NULL;
856 cooked->is_enforced = true;
857 cooked->skip_validation = !conForm->convalidated;
858 cooked->is_local = true;
859 cooked->inhcount = 0;
860 cooked->is_no_inherit = conForm->connoinherit;
861
862 notnulls = lappend(notnulls, cooked);
863 }
864 else
865 {
866 Constraint *constr;
867
868 constr = makeNode(Constraint);
869 constr->contype = CONSTR_NOTNULL;
870 constr->conname = pstrdup(NameStr(conForm->conname));
871 constr->deferrable = false;
872 constr->initdeferred = false;
873 constr->location = -1;
874 constr->keys = list_make1(makeString(get_attname(relid, colnum,
875 false)));
876 constr->is_enforced = true;
877 constr->skip_validation = !conForm->convalidated;
878 constr->initially_valid = true;
879 constr->is_no_inherit = conForm->connoinherit;
880 notnulls = lappend(notnulls, constr);
881 }
882 }
883
884 systable_endscan(conscan);
885 table_close(constrRel, AccessShareLock);
886
887 return notnulls;
888}
List * lappend(List *list, void *datum)
Definition: list.c:339
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:919
char * pstrdup(const char *in)
Definition: mcxt.c:2327
#define makeNode(_type_)
Definition: nodes.h:161
@ CONSTR_NOTNULL
Definition: parsenodes.h:2790
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
bool initdeferred
Definition: parsenodes.h:2825
ParseLoc location
Definition: parsenodes.h:2866
List * keys
Definition: parsenodes.h:2837
ConstrType contype
Definition: parsenodes.h:2822
bool is_no_inherit
Definition: parsenodes.h:2829
bool is_enforced
Definition: parsenodes.h:2826
bool initially_valid
Definition: parsenodes.h:2828
bool skip_validation
Definition: parsenodes.h:2827
bool deferrable
Definition: parsenodes.h:2824
char * conname
Definition: parsenodes.h:2823
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 895 of file pg_constraint.c.

896{
897 Relation conDesc;
898 HeapTuple tup;
900
901 conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
902
903 tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conId));
904 if (!HeapTupleIsValid(tup)) /* should not happen */
905 elog(ERROR, "cache lookup failed for constraint %u", conId);
906 con = (Form_pg_constraint) GETSTRUCT(tup);
907
908 /*
909 * Special processing depending on what the constraint is for.
910 */
911 if (OidIsValid(con->conrelid))
912 {
913 Relation rel;
914
915 /*
916 * If the constraint is for a relation, open and exclusive-lock the
917 * relation it's for.
918 */
919 rel = table_open(con->conrelid, AccessExclusiveLock);
920
921 /*
922 * We need to update the relchecks count if it is a check constraint
923 * being dropped. This update will force backends to rebuild relcache
924 * entries when we commit.
925 */
926 if (con->contype == CONSTRAINT_CHECK)
927 {
928 Relation pgrel;
929 HeapTuple relTup;
930 Form_pg_class classForm;
931
932 pgrel = table_open(RelationRelationId, RowExclusiveLock);
933 relTup = SearchSysCacheCopy1(RELOID,
934 ObjectIdGetDatum(con->conrelid));
935 if (!HeapTupleIsValid(relTup))
936 elog(ERROR, "cache lookup failed for relation %u",
937 con->conrelid);
938 classForm = (Form_pg_class) GETSTRUCT(relTup);
939
940 if (classForm->relchecks == 0) /* should not happen */
941 elog(ERROR, "relation \"%s\" has relchecks = 0",
943 classForm->relchecks--;
944
945 CatalogTupleUpdate(pgrel, &relTup->t_self, relTup);
946
947 heap_freetuple(relTup);
948
950 }
951
952 /* Keep lock on constraint's rel until end of xact */
953 table_close(rel, NoLock);
954 }
955 else if (OidIsValid(con->contypid))
956 {
957 /*
958 * XXX for now, do nothing special when dropping a domain constraint
959 *
960 * Probably there should be some form of locking on the domain type,
961 * but we have no such concept at the moment.
962 */
963 }
964 else
965 elog(ERROR, "constraint %u is not of a known type", conId);
966
967 /* Fry the constraint itself */
968 CatalogTupleDelete(conDesc, &tup->t_self);
969
970 /* Clean up */
971 ReleaseSysCache(tup);
973}
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:156
#define RelationGetRelationName(relation)
Definition: rel.h:550
#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 986 of file pg_constraint.c.

987{
988 Relation conDesc;
989 HeapTuple tuple;
991
992 conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
993
994 tuple = SearchSysCacheCopy1(CONSTROID, ObjectIdGetDatum(conId));
995 if (!HeapTupleIsValid(tuple))
996 elog(ERROR, "cache lookup failed for constraint %u", conId);
997 con = (Form_pg_constraint) GETSTRUCT(tuple);
998
999 /*
1000 * For user-friendliness, check whether the name is already in use.
1001 */
1002 if (OidIsValid(con->conrelid) &&
1004 con->conrelid,
1005 newname))
1006 ereport(ERROR,
1008 errmsg("constraint \"%s\" for relation \"%s\" already exists",
1009 newname, get_rel_name(con->conrelid))));
1010 if (OidIsValid(con->contypid) &&
1012 con->contypid,
1013 newname))
1014 ereport(ERROR,
1016 errmsg("constraint \"%s\" for domain %s already exists",
1017 newname, format_type_be(con->contypid))));
1018
1019 /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
1020 namestrcpy(&(con->conname), newname);
1021
1022 CatalogTupleUpdate(conDesc, &tuple->t_self, tuple);
1023
1024 InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
1025
1026 heap_freetuple(tuple);
1027 table_close(conDesc, RowExclusiveLock);
1028}
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().