PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pg_constraint.h File Reference
#include "catalog/dependency.h"
#include "catalog/genbki.h"
#include "catalog/pg_constraint_d.h"
#include "nodes/pg_list.h"
Include dependency graph for pg_constraint.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef FormData_pg_constraintForm_pg_constraint
 
typedef enum ConstraintCategory ConstraintCategory
 

Enumerations

enum  ConstraintCategory { CONSTRAINT_RELATION , CONSTRAINT_DOMAIN , CONSTRAINT_ASSERTION }
 

Functions

 CATALOG (pg_constraint, 2606, ConstraintRelationId)
 
 DECLARE_TOAST (pg_constraint, 2832, 2833)
 
 DECLARE_INDEX (pg_constraint_conname_nsp_index, 2664, ConstraintNameNspIndexId, pg_constraint, btree(conname name_ops, connamespace oid_ops))
 
 DECLARE_UNIQUE_INDEX (pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, pg_constraint, btree(conrelid oid_ops, contypid oid_ops, conname name_ops))
 
 DECLARE_INDEX (pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, pg_constraint, btree(contypid oid_ops))
 
 DECLARE_UNIQUE_INDEX_PKEY (pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops))
 
 DECLARE_INDEX (pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, pg_constraint, btree(conparentid oid_ops))
 
 MAKE_SYSCACHE (CONSTROID, pg_constraint_oid_index, 16)
 
 DECLARE_ARRAY_FOREIGN_KEY_OPT ((conrelid, conkey), pg_attribute,(attrelid, attnum))
 
 DECLARE_ARRAY_FOREIGN_KEY ((confrelid, confkey), pg_attribute,(attrelid, attnum))
 
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_domain_constraint_oid (Oid typid, const char *conname, bool missing_ok)
 
Oid get_relation_idx_constraint_oid (Oid relationId, Oid indexId)
 
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)
 

Variables

 FormData_pg_constraint
 

Typedef Documentation

◆ ConstraintCategory

◆ Form_pg_constraint

Definition at line 175 of file pg_constraint.h.

Enumeration Type Documentation

◆ ConstraintCategory

Enumerator
CONSTRAINT_RELATION 
CONSTRAINT_DOMAIN 
CONSTRAINT_ASSERTION 

Definition at line 213 of file pg_constraint.h.

214{
217 CONSTRAINT_ASSERTION, /* for future expansion */
ConstraintCategory
@ CONSTRAINT_DOMAIN
@ CONSTRAINT_RELATION
@ CONSTRAINT_ASSERTION

Function Documentation

◆ AdjustNotNullInheritance()

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

Definition at line 736 of file pg_constraint.c.

738{
739 HeapTuple tup;
740
742 if (HeapTupleIsValid(tup))
743 {
744 Relation pg_constraint;
745 Form_pg_constraint conform;
746 bool changed = false;
747
748 pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
749 conform = (Form_pg_constraint) GETSTRUCT(tup);
750
751 /*
752 * If the NO INHERIT flag we're asked for doesn't match what the
753 * existing constraint has, throw an error.
754 */
755 if (is_no_inherit != conform->connoinherit)
757 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
758 errmsg("cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"",
759 NameStr(conform->conname), get_rel_name(relid)),
760 errhint("You might need to make the existing constraint inheritable using %s.",
761 "ALTER TABLE ... ALTER CONSTRAINT ... INHERIT"));
762
763 /*
764 * Throw an error if the existing constraint is NOT VALID and caller
765 * wants a valid one.
766 */
767 if (!is_notvalid && !conform->convalidated)
769 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
770 errmsg("incompatible NOT VALID constraint \"%s\" on relation \"%s\"",
771 NameStr(conform->conname), get_rel_name(relid)),
772 errhint("You might need to validate it using %s.",
773 "ALTER TABLE ... VALIDATE CONSTRAINT"));
774
775 if (!is_local)
776 {
777 if (pg_add_s16_overflow(conform->coninhcount, 1,
778 &conform->coninhcount))
780 errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
781 errmsg("too many inheritance parents"));
782 changed = true;
783 }
784 else if (!conform->conislocal)
785 {
786 conform->conislocal = true;
787 changed = true;
788 }
789
790 if (changed)
791 CatalogTupleUpdate(pg_constraint, &tup->t_self, tup);
792
793 table_close(pg_constraint, RowExclusiveLock);
794
795 return true;
796 }
797
798 return false;
799}
#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 1033 of file pg_constraint.c.

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

◆ CATALOG()

CATALOG ( pg_constraint  ,
2606  ,
ConstraintRelationId   
)

Definition at line 31 of file pg_constraint.h.

32{
33 Oid oid; /* oid */
34
35 /*
36 * conname + connamespace is deliberately not unique; we allow, for
37 * example, the same name to be used for constraints of different
38 * relations. This is partly for backwards compatibility with past
39 * Postgres practice, and partly because we don't want to have to obtain a
40 * global lock to generate a globally unique name for a nameless
41 * constraint. We associate a namespace with constraint names only for
42 * SQL-spec compatibility.
43 *
44 * However, we do require conname to be unique among the constraints of a
45 * single relation or domain. This is enforced by a unique index on
46 * conrelid + contypid + conname.
47 */
48 NameData conname; /* name of this constraint */
49 Oid connamespace BKI_LOOKUP(pg_namespace); /* OID of namespace
50 * containing constraint */
51 char contype; /* constraint type; see codes below */
52 bool condeferrable; /* deferrable constraint? */
53 bool condeferred; /* deferred by default? */
54 bool conenforced; /* enforced constraint? */
55 bool convalidated; /* constraint has been validated? */
56
57 /*
58 * conrelid and conkey are only meaningful if the constraint applies to a
59 * specific relation (this excludes domain constraints and assertions).
60 * Otherwise conrelid is 0 and conkey is NULL.
61 */
62 Oid conrelid BKI_LOOKUP_OPT(pg_class); /* relation this
63 * constraint constrains */
64
65 /*
66 * contypid links to the pg_type row for a domain if this is a domain
67 * constraint. Otherwise it's 0.
68 *
69 * For SQL-style global ASSERTIONs, both conrelid and contypid would be
70 * zero. This is not presently supported, however.
71 */
72 Oid contypid BKI_LOOKUP_OPT(pg_type); /* domain this constraint
73 * constrains */
74
75 /*
76 * conindid links to the index supporting the constraint, if any;
77 * otherwise it's 0. This is used for unique, primary-key, and exclusion
78 * constraints, and less obviously for foreign-key constraints (where the
79 * index is a unique index on the referenced relation's referenced
80 * columns). Notice that the index is on conrelid in the first case but
81 * confrelid in the second.
82 */
83 Oid conindid BKI_LOOKUP_OPT(pg_class); /* index supporting this
84 * constraint */
85
86 /*
87 * If this constraint is on a partition inherited from a partitioned
88 * table, this is the OID of the corresponding constraint in the parent.
89 */
90 Oid conparentid BKI_LOOKUP_OPT(pg_constraint);
91
92 /*
93 * These fields, plus confkey, are only meaningful for a foreign-key
94 * constraint. Otherwise confrelid is 0 and the char fields are spaces.
95 */
96 Oid confrelid BKI_LOOKUP_OPT(pg_class); /* relation referenced by
97 * foreign key */
98 char confupdtype; /* foreign key's ON UPDATE action */
99 char confdeltype; /* foreign key's ON DELETE action */
100 char confmatchtype; /* foreign key's match type */
101
102 /* Has a local definition (hence, do not drop when coninhcount is 0) */
103 bool conislocal;
104
105 /* Number of times inherited from direct parent relation(s) */
106 int16 coninhcount;
107
108 /* Has a local definition and cannot be inherited */
109 bool connoinherit;
110
111 /*
112 * For primary keys, unique constraints, and foreign keys, signifies the
113 * last column uses overlaps instead of equals.
114 */
115 bool conperiod;
116
117#ifdef CATALOG_VARLEN /* variable-length fields start here */
118
119 /*
120 * Columns of conrelid that the constraint applies to, if known (this is
121 * NULL for trigger constraints)
122 */
123 int16 conkey[1];
124
125 /*
126 * If a foreign key, the referenced columns of confrelid
127 */
128 int16 confkey[1];
129
130 /*
131 * If a foreign key, the OIDs of the PK = FK equality/overlap operators
132 * for each column of the constraint
133 */
134 Oid conpfeqop[1] BKI_LOOKUP(pg_operator);
135
136 /*
137 * If a foreign key, the OIDs of the PK = PK equality/overlap operators
138 * for each column of the constraint (i.e., equality for the referenced
139 * columns)
140 */
141 Oid conppeqop[1] BKI_LOOKUP(pg_operator);
142
143 /*
144 * If a foreign key, the OIDs of the FK = FK equality/overlap operators
145 * for each column of the constraint (i.e., equality for the referencing
146 * columns)
147 */
148 Oid conffeqop[1] BKI_LOOKUP(pg_operator);
149
150 /*
151 * If a foreign key with an ON DELETE SET NULL/DEFAULT action, the subset
152 * of conkey to updated. If null, all columns are updated.
153 */
154 int16 confdelsetcols[1];
155
156 /*
157 * If an exclusion constraint, the OIDs of the exclusion operators for
158 * each column of the constraint. Also set for unique constraints/primary
159 * keys using WITHOUT OVERLAPS.
160 */
161 Oid conexclop[1] BKI_LOOKUP(pg_operator);
162
163 /*
164 * If a check constraint, nodeToString representation of expression
165 */
166 pg_node_tree conbin;
167#endif
int16_t int16
Definition: c.h:497
#define BKI_LOOKUP(catalog)
Definition: genbki.h:46
#define BKI_LOOKUP_OPT(catalog)
Definition: genbki.h:47
FormData_pg_constraint
unsigned int Oid
Definition: postgres_ext.h:30
Definition: c.h:712

References BKI_LOOKUP, and BKI_LOOKUP_OPT.

◆ check_functional_grouping()

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

Definition at line 1718 of file pg_constraint.c.

1722{
1723 Bitmapset *pkattnos;
1724 Bitmapset *groupbyattnos;
1725 Oid constraintOid;
1726 ListCell *gl;
1727
1728 /* If the rel has no PK, then we can't prove functional dependency */
1729 pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
1730 if (pkattnos == NULL)
1731 return false;
1732
1733 /* Identify all the rel's columns that appear in grouping_columns */
1734 groupbyattnos = NULL;
1735 foreach(gl, grouping_columns)
1736 {
1737 Var *gvar = (Var *) lfirst(gl);
1738
1739 if (IsA(gvar, Var) &&
1740 gvar->varno == varno &&
1741 gvar->varlevelsup == varlevelsup)
1742 groupbyattnos = bms_add_member(groupbyattnos,
1744 }
1745
1746 if (bms_is_subset(pkattnos, groupbyattnos))
1747 {
1748 /* The PK is a subset of grouping_columns, so we win */
1749 *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
1750 return true;
1751 }
1752
1753 return false;
1754}
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
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 511 of file pg_constraint.c.

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

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

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

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

◆ DECLARE_ARRAY_FOREIGN_KEY()

DECLARE_ARRAY_FOREIGN_KEY ( (confrelid, confkey)  ,
pg_attribute  ,
(attrelid, attnum  
)

◆ DECLARE_ARRAY_FOREIGN_KEY_OPT()

DECLARE_ARRAY_FOREIGN_KEY_OPT ( (conrelid, conkey)  ,
pg_attribute  ,
(attrelid, attnum  
)

◆ DECLARE_INDEX() [1/3]

DECLARE_INDEX ( pg_constraint_conname_nsp_index  ,
2664  ,
ConstraintNameNspIndexId  ,
pg_constraint  ,
btree(conname name_ops, connamespace oid_ops)   
)

◆ DECLARE_INDEX() [2/3]

DECLARE_INDEX ( pg_constraint_conparentid_index  ,
2579  ,
ConstraintParentIndexId  ,
pg_constraint  ,
btree(conparentid oid_ops)   
)

◆ DECLARE_INDEX() [3/3]

DECLARE_INDEX ( pg_constraint_contypid_index  ,
2666  ,
ConstraintTypidIndexId  ,
pg_constraint  ,
btree(contypid oid_ops)   
)

◆ DECLARE_TOAST()

DECLARE_TOAST ( pg_constraint  ,
2832  ,
2833   
)

◆ DECLARE_UNIQUE_INDEX()

DECLARE_UNIQUE_INDEX ( pg_constraint_conrelid_contypid_conname_index  ,
2665  ,
ConstraintRelidTypidNameIndexId  ,
pg_constraint  ,
btree(conrelid oid_ops, contypid oid_ops, conname name_ops)   
)

◆ DECLARE_UNIQUE_INDEX_PKEY()

DECLARE_UNIQUE_INDEX_PKEY ( pg_constraint_oid_index  ,
2667  ,
ConstraintOidIndexId  ,
pg_constraint  ,
btree(oid oid_ops)   
)

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

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

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

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

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

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

638{
640
641 attnum = get_attnum(relid, colname);
643 return NULL;
644
645 return findNotNullConstraintAttnum(relid, attnum);
646}
#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 587 of file pg_constraint.c.

588{
589 Relation pg_constraint;
590 HeapTuple conTup,
591 retval = NULL;
592 SysScanDesc scan;
594
595 pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
597 Anum_pg_constraint_conrelid,
598 BTEqualStrategyNumber, F_OIDEQ,
599 ObjectIdGetDatum(relid));
600 scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
601 true, NULL, 1, &key);
602
603 while (HeapTupleIsValid(conTup = systable_getnext(scan)))
604 {
606 AttrNumber conkey;
607
608 /*
609 * We're looking for a NOTNULL constraint with the column we're
610 * looking for as the sole element in conkey.
611 */
612 if (con->contype != CONSTRAINT_NOTNULL)
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 1369 of file pg_constraint.c.

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

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

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

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

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

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

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

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

◆ MAKE_SYSCACHE()

MAKE_SYSCACHE ( CONSTROID  ,
pg_constraint_oid_index  ,
16   
)

◆ RelationGetNotNullConstraints()

List * RelationGetNotNullConstraints ( Oid  relid,
bool  cooked,
bool  include_noinh 
)

Definition at line 812 of file pg_constraint.c.

813{
814 List *notnulls = NIL;
815 Relation constrRel;
816 HeapTuple htup;
817 SysScanDesc conscan;
818 ScanKeyData skey;
819
820 constrRel = table_open(ConstraintRelationId, AccessShareLock);
821 ScanKeyInit(&skey,
822 Anum_pg_constraint_conrelid,
823 BTEqualStrategyNumber, F_OIDEQ,
824 ObjectIdGetDatum(relid));
825 conscan = systable_beginscan(constrRel, ConstraintRelidTypidNameIndexId, true,
826 NULL, 1, &skey);
827
828 while (HeapTupleIsValid(htup = systable_getnext(conscan)))
829 {
831 AttrNumber colnum;
832
833 if (conForm->contype != CONSTRAINT_NOTNULL)
834 continue;
835 if (conForm->connoinherit && !include_noinh)
836 continue;
837
838 colnum = extractNotNullColumn(htup);
839
840 if (cooked)
841 {
842 CookedConstraint *cooked;
843
844 cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
845
846 cooked->contype = CONSTR_NOTNULL;
847 cooked->conoid = conForm->oid;
848 cooked->name = pstrdup(NameStr(conForm->conname));
849 cooked->attnum = colnum;
850 cooked->expr = NULL;
851 cooked->is_enforced = true;
852 cooked->skip_validation = !conForm->convalidated;
853 cooked->is_local = true;
854 cooked->inhcount = 0;
855 cooked->is_no_inherit = conForm->connoinherit;
856
857 notnulls = lappend(notnulls, cooked);
858 }
859 else
860 {
861 Constraint *constr;
862
863 constr = makeNode(Constraint);
864 constr->contype = CONSTR_NOTNULL;
865 constr->conname = pstrdup(NameStr(conForm->conname));
866 constr->deferrable = false;
867 constr->initdeferred = false;
868 constr->location = -1;
869 constr->keys = list_make1(makeString(get_attname(relid, colnum,
870 false)));
871 constr->is_enforced = true;
872 constr->skip_validation = !conForm->convalidated;
873 constr->initially_valid = true;
874 constr->is_no_inherit = conForm->connoinherit;
875 notnulls = lappend(notnulls, constr);
876 }
877 }
878
879 systable_endscan(conscan);
880 table_close(constrRel, AccessShareLock);
881
882 return notnulls;
883}
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:2325
#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 890 of file pg_constraint.c.

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

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

Variable Documentation

◆ FormData_pg_constraint

FormData_pg_constraint

Definition at line 168 of file pg_constraint.h.