PostgreSQL Source Code git master
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 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:756
int errhint(const char *fmt,...)
Definition: elog.c:1330
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *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:2095
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 1040 of file pg_constraint.c.

1042{
1043 Relation conRel;
1044 ScanKeyData key[2];
1045 SysScanDesc scan;
1046 HeapTuple tup;
1047
1048 conRel = table_open(ConstraintRelationId, RowExclusiveLock);
1049
1050 ScanKeyInit(&key[0],
1051 Anum_pg_constraint_conrelid,
1052 BTEqualStrategyNumber, F_OIDEQ,
1053 ObjectIdGetDatum(isType ? InvalidOid : ownerId));
1054 ScanKeyInit(&key[1],
1055 Anum_pg_constraint_contypid,
1056 BTEqualStrategyNumber, F_OIDEQ,
1057 ObjectIdGetDatum(isType ? ownerId : InvalidOid));
1058
1059 scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId, true,
1060 NULL, 2, key);
1061
1062 while (HeapTupleIsValid((tup = systable_getnext(scan))))
1063 {
1065 ObjectAddress thisobj;
1066
1067 ObjectAddressSet(thisobj, ConstraintRelationId, conform->oid);
1068
1069 if (object_address_present(&thisobj, objsMoved))
1070 continue;
1071
1072 /* Don't update if the object is already part of the namespace */
1073 if (conform->connamespace == oldNspId && oldNspId != newNspId)
1074 {
1075 tup = heap_copytuple(tup);
1076 conform = (Form_pg_constraint) GETSTRUCT(tup);
1077
1078 conform->connamespace = newNspId;
1079
1080 CatalogTupleUpdate(conRel, &tup->t_self, tup);
1081
1082 /*
1083 * Note: currently, the constraint will not have its own
1084 * dependency on the namespace, so we don't need to do
1085 * changeDependencyFor().
1086 */
1087 }
1088
1089 InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
1090
1091 add_exact_object_address(&thisobj, objsMoved);
1092 }
1093
1094 systable_endscan(scan);
1095
1097}
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2721
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2661
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:262
#define InvalidOid
Definition: postgres_ext.h:37
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

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

Referenced by AlterTableNamespaceInternal(), and AlterTypeNamespaceInternal().

◆ 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:538
#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:32
Definition: c.h:751

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

1729{
1730 Bitmapset *pkattnos;
1731 Bitmapset *groupbyattnos;
1732 Oid constraintOid;
1733 ListCell *gl;
1734
1735 /* If the rel has no PK, then we can't prove functional dependency */
1736 pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
1737 if (pkattnos == NULL)
1738 return false;
1739
1740 /* Identify all the rel's columns that appear in grouping_columns */
1741 groupbyattnos = NULL;
1742 foreach(gl, grouping_columns)
1743 {
1744 Var *gvar = (Var *) lfirst(gl);
1745
1746 if (IsA(gvar, Var) &&
1747 gvar->varno == varno &&
1748 gvar->varlevelsup == varlevelsup)
1749 groupbyattnos = bms_add_member(groupbyattnos,
1751 }
1752
1753 if (bms_is_subset(pkattnos, groupbyattnos))
1754 {
1755 /* The PK is a subset of grouping_columns, so we win */
1756 *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
1757 return true;
1758 }
1759
1760 return false;
1761}
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:814
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 init_grouping_targets(), and 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:1594
static char * label
#define NAMEDATALEN
#define snprintf
Definition: port.h:260
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:360

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

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

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) 0;
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:3382
static Datum values[MAXATTR]
Definition: bootstrap.c:153
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define Max(x, y)
Definition: c.h:1002
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:448
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2870
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
Definition: dependency.c:1629
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2615
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2901
@ 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:1365
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:332
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:182
static Datum BoolGetDatum(bool X)
Definition: postgres.h:112
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:383
uint64_t Datum
Definition: postgres.h:70
static Datum CharGetDatum(char X)
Definition: postgres.h:132
#define RelationGetDescr(relation)
Definition: rel.h:541

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

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

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

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

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(), ATExecAddIdentity(), 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 1376 of file pg_constraint.c.

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

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

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

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

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

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(), rename_constraint_internal(), and transformTableLikeClause().

◆ get_relation_idx_constraint_oid()

Oid get_relation_idx_constraint_oid ( Oid  relationId,
Oid  indexId 
)

Definition at line 1329 of file pg_constraint.c.

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

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 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:920
char * pstrdup(const char *in)
Definition: mcxt.c:1759
#define makeNode(_type_)
Definition: nodes.h:161
@ CONSTR_NOTNULL
Definition: parsenodes.h:2801
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
bool initdeferred
Definition: parsenodes.h:2836
ParseLoc location
Definition: parsenodes.h:2877
List * keys
Definition: parsenodes.h:2848
ConstrType contype
Definition: parsenodes.h:2833
bool is_no_inherit
Definition: parsenodes.h:2840
bool is_enforced
Definition: parsenodes.h:2837
bool initially_valid
Definition: parsenodes.h:2839
bool skip_validation
Definition: parsenodes.h:2838
bool deferrable
Definition: parsenodes.h:2835
char * conname
Definition: parsenodes.h:2834
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)
941 classForm->relchecks--;
942 else
943 /* should not happen */
944 elog(WARNING, "relation \"%s\" has relchecks = %d",
945 RelationGetRelationName(rel), classForm->relchecks);
946
947 CatalogTupleUpdate(pgrel, &relTup->t_self, relTup);
948
949 heap_freetuple(relTup);
950
952 }
953
954 /* Keep lock on constraint's rel until end of xact */
955 table_close(rel, NoLock);
956 }
957 else if (OidIsValid(con->contypid))
958 {
959 /*
960 * XXX for now, do nothing special when dropping a domain constraint
961 *
962 * Probably there should be some form of locking on the domain type,
963 * but we have no such concept at the moment.
964 */
965 }
966 else
967 elog(ERROR, "constraint %u is not of a known type", conId);
968
969 /* Fry the constraint itself */
970 CatalogTupleDelete(conDesc, &tup->t_self);
971
972 /* Clean up */
973 ReleaseSysCache(tup);
975}
#define WARNING
Definition: elog.h:36
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *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:549
#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(), table_open(), and WARNING.

Referenced by doDeletion().

◆ RenameConstraintById()

void RenameConstraintById ( Oid  conId,
const char *  newname 
)

Definition at line 988 of file pg_constraint.c.

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