1/*-------------------------------------------------------------------------
4 * routines to support manipulation of the pg_constraint relation
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/catalog/pg_constraint.c
13 *-------------------------------------------------------------------------
34#include "utils/fmgroids.h"
41 * CreateConstraintEntry
42 * Create a constraint table entry.
44 * Subsidiary records (such as triggers or indexes to implement the
45 * constraint) are *not* created here. But we do make dependency links
46 * from the constraint to the things it depends on.
48 * The new constraint's OID is returned.
52 Oid constraintNamespace,
60 const int16 *constraintKey,
62 int constraintNTotalKeys,
66 const int16 *foreignKey,
71 char foreignUpdateType,
72 char foreignDeleteType,
73 const int16 *fkDeleteSetCols,
74 int numFkDeleteSetCols,
75 char foreignMatchType,
88 bool nulls[Natts_pg_constraint];
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);
115 * Convert C arrays into Postgres arrays.
117 if (constraintNKeys > 0)
122 for (
i = 0;
i < constraintNKeys;
i++)
129 if (foreignNKeys > 0)
132 int nkeys =
Max(foreignNKeys, numFkDeleteSetCols);
135 for (
i = 0;
i < foreignNKeys;
i++)
138 for (
i = 0;
i < foreignNKeys;
i++)
141 for (
i = 0;
i < foreignNKeys;
i++)
144 for (
i = 0;
i < foreignNKeys;
i++)
148 if (numFkDeleteSetCols > 0)
150 for (
i = 0;
i < numFkDeleteSetCols;
i++)
155 confdelsetcolsArray = NULL;
160 conpfeqopArray = NULL;
161 conppeqopArray = NULL;
162 conffeqopArray = NULL;
163 confdelsetcolsArray = NULL;
171 for (
i = 0;
i < constraintNKeys;
i++)
176 conexclopArray = NULL;
178 /* initialize nulls and values */
179 for (
i = 0;
i < Natts_pg_constraint;
i++)
186 Anum_pg_constraint_oid);
211 nulls[Anum_pg_constraint_conkey - 1] =
true;
216 nulls[Anum_pg_constraint_confkey - 1] =
true;
221 nulls[Anum_pg_constraint_conpfeqop - 1] =
true;
226 nulls[Anum_pg_constraint_conppeqop - 1] =
true;
231 nulls[Anum_pg_constraint_conffeqop - 1] =
true;
233 if (confdelsetcolsArray)
236 nulls[Anum_pg_constraint_confdelsetcols - 1] =
true;
241 nulls[Anum_pg_constraint_conexclop - 1] =
true;
246 nulls[Anum_pg_constraint_conbin - 1] =
true;
256 /* Handle set of auto dependencies */
262 * Register auto dependency from constraint to owning relation, or to
263 * specific column(s) if any are mentioned.
267 if (constraintNTotalKeys > 0)
269 for (
i = 0;
i < constraintNTotalKeys;
i++)
286 * Register auto dependency from constraint to owning domain
298 /* Handle set of normal dependencies */
304 * Register normal dependency from constraint to foreign relation, or
305 * to specific column(s) if any are mentioned.
309 if (foreignNKeys > 0)
311 for (
i = 0;
i < foreignNKeys;
i++)
314 foreignRelId, foreignKey[
i]);
325 if (
OidIsValid(indexRelId) && constraintType == CONSTRAINT_FOREIGN)
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
339 if (foreignNKeys > 0)
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
349 oprobject.
classId = OperatorRelationId;
352 for (
i = 0;
i < foreignNKeys;
i++)
356 if (ppEqOp[
i] != pfEqOp[
i])
361 if (ffEqOp[
i] != pfEqOp[
i])
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.)
384 * Register dependencies from constraint to objects mentioned in CHECK
392 /* Post creation hook for new constraint */
400 * Test whether given name is currently used as a constraint name
401 * for the given object (relation or domain).
403 * This is used to decide whether to accept a user-specified constraint name.
404 * It is deliberately not the same test as ChooseConstraintName uses to decide
405 * whether an auto-generated name is OK: here, we will allow it unless there
406 * is an identical constraint name in use *on the same object*.
408 * NB: Caller should hold exclusive lock on the given object, else
409 * this test can be fooled by concurrent additions.
423 Anum_pg_constraint_conrelid,
428 Anum_pg_constraint_contypid,
433 Anum_pg_constraint_conname,
438 true, NULL, 3, skey);
440 /* There can be at most one matching row */
450 * Does any constraint of the given name exist in the given namespace?
452 * This is used for code that wants to match ChooseConstraintName's rule
453 * that we should avoid autogenerating duplicate constraint names within a
467 Anum_pg_constraint_conname,
472 Anum_pg_constraint_connamespace,
488 * Select a nonconflicting name for a new constraint.
490 * The objective here is to choose a name that is unique within the
491 * specified namespace. Postgres does not require this, but the SQL
492 * spec does, and some apps depend on it. Therefore we avoid choosing
493 * default names that so conflict.
495 * name1, name2, and label are used the same way as for makeObjectName(),
496 * except that the label can't be NULL; digits will be appended to the label
497 * if needed to create a name that is unique within the specified namespace.
498 * If the given label is empty, we only consider names that include at least
501 * 'others' can be a list of string names already chosen within the current
502 * command (but not yet reflected into the catalogs); we will not choose
503 * a duplicate of one of these either.
505 * Note: it is theoretically possible to get a collision anyway, if someone
506 * else chooses the same name concurrently. This is fairly unlikely to be
507 * a problem in practice, especially if one is holding an exclusive lock on
508 * the relation identified by name1.
510 * Returns a palloc'd string.
518 char *conname = NULL;
528 /* try the unmodified label first, unless it's empty */
529 if (
label[0] !=
'0円')
542 if (strcmp((
char *)
lfirst(l), conname) == 0)
552 Anum_pg_constraint_conname,
557 Anum_pg_constraint_connamespace,
572 /* found a conflict, so try a new name component */
583 * Find and return a copy of the pg_constraint tuple that implements a
584 * (possibly not valid) not-null constraint for the given column of the
585 * given relation. If no such constraint exists, return NULL.
587 * XXX This would be easier if we had pg_attribute.notnullconstr with the OID
588 * of the constraint that implements the not-null constraint for that column.
589 * I'm not sure it's worth the catalog bloat and de-normalization, however.
602 Anum_pg_constraint_conrelid,
606 true, NULL, 1, &
key);
614 * We're looking for a NOTNULL constraint with the column we're
615 * looking for as the sole element in conkey.
617 if (con->contype != CONSTRAINT_NOTNULL)
636 * Find and return a copy of the pg_constraint tuple that implements a
637 * (possibly not valid) not-null constraint for the given column of the
639 * If no such column or no such constraint exists, return NULL.
654 * Find and return the pg_constraint tuple that implements a validated
655 * not-null constraint for the given domain.
668 Anum_pg_constraint_contypid,
672 true, NULL, 1, &
key);
679 * We're looking for a NOTNULL constraint that's marked validated.
681 if (con->contype != CONSTRAINT_NOTNULL)
683 if (!con->convalidated)
698 * Given a pg_constraint tuple for a not-null constraint, return the column
707 /* only tuples for not-null constraints should be given */
711 Anum_pg_constraint_conkey);
717 elog(
ERROR,
"conkey is not a 1-D smallint array");
719 /* We leak the detoasted datum, but we don't care */
725 * AdjustNotNullInheritance
726 * Adjust inheritance status for a single not-null constraint
728 * If no not-null constraint is found for the column, return false.
729 * Caller can create one.
731 * If a constraint exists but the connoinherit flag is not what the caller
732 * wants, throw an error about the incompatibility. If the desired
733 * constraint is valid but the existing constraint is not valid, also
734 * throw an error about that (the opposite case is acceptable).
736 * If everything checks out, we adjust conislocal/coninhcount and return
737 * true. If is_local is true we flip conislocal true, or do nothing if
738 * it's already true; otherwise we increment coninhcount by 1.
742 bool is_local,
bool is_no_inherit,
bool is_notvalid)
751 bool changed =
false;
757 * If the NO INHERIT flag we're asked for doesn't match what the
758 * existing constraint has, throw an error.
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\"",
765 errhint(
"You might need to make the existing constraint inheritable using %s.",
766 "ALTER TABLE ... ALTER CONSTRAINT ... INHERIT"));
769 * Throw an error if the existing constraint is NOT VALID and caller
772 if (!is_notvalid && !conform->convalidated)
774 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
775 errmsg(
"incompatible NOT VALID constraint \"%s\" on relation \"%s\"",
777 errhint(
"You might need to validate it using %s.",
778 "ALTER TABLE ... VALIDATE CONSTRAINT"));
783 &conform->coninhcount))
785 errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
786 errmsg(
"too many inheritance parents"));
789 else if (!conform->conislocal)
791 conform->conislocal =
true;
807 * RelationGetNotNullConstraints
808 * Return the list of not-null constraints for the given rel
810 * Caller can request cooked constraints, or raw.
812 * This is seldom needed, so we just scan pg_constraint each time.
814 * 'include_noinh' determines whether to include NO INHERIT constraints or not.
827 Anum_pg_constraint_conrelid,
838 if (conForm->contype != CONSTRAINT_NOTNULL)
840 if (conForm->connoinherit && !include_noinh)
852 cooked->
conoid = conForm->oid;
862 notnulls =
lappend(notnulls, cooked);
880 notnulls =
lappend(notnulls, constr);
892 * Delete a single constraint record.
905 elog(
ERROR,
"cache lookup failed for constraint %u", conId);
909 * Special processing depending on what the constraint is for.
916 * If the constraint is for a relation, open and exclusive-lock the
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.
926 if (con->contype == CONSTRAINT_CHECK)
936 elog(
ERROR,
"cache lookup failed for relation %u",
940 if (classForm->relchecks == 0)
/* should not happen */
941 elog(
ERROR,
"relation \"%s\" has relchecks = 0",
943 classForm->relchecks--;
952 /* Keep lock on constraint's rel until end of xact */
958 * XXX for now, do nothing special when dropping a domain constraint
960 * Probably there should be some form of locking on the domain type,
961 * but we have no such concept at the moment.
965 elog(
ERROR,
"constraint %u is not of a known type", conId);
967 /* Fry the constraint itself */
976 * RenameConstraintById
977 * Rename a constraint.
979 * Note: this isn't intended to be a user-exposed function; it doesn't check
980 * permissions etc. Currently this is only invoked when renaming an index
981 * that is associated with a constraint, but it's made a little more general
982 * than that with the expectation of someday having ALTER TABLE RENAME
996 elog(
ERROR,
"cache lookup failed for constraint %u", conId);
1000 * For user-friendliness, check whether the name is already in use.
1008 errmsg(
"constraint \"%s\" for relation \"%s\" already exists",
1016 errmsg(
"constraint \"%s\" for domain %s already exists",
1019 /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
1031 * AlterConstraintNamespaces
1032 * Find any constraints belonging to the specified object,
1033 * and move them to the specified new namespace.
1035 * isType indicates whether the owning object is a type or a relation.
1049 Anum_pg_constraint_conrelid,
1053 Anum_pg_constraint_contypid,
1070 /* Don't update if the object is already part of the namespace */
1071 if (conform->connamespace == oldNspId && oldNspId != newNspId)
1076 conform->connamespace = newNspId;
1081 * Note: currently, the constraint will not have its own
1082 * dependency on the namespace, so we don't need to do
1083 * changeDependencyFor().
1098 * ConstraintSetParentConstraint
1099 * Set a partition's constraint as child of its parent constraint,
1100 * or remove the linkage if parentConstrId is InvalidOid.
1102 * This updates the constraint's pg_constraint row to show it as inherited, and
1103 * adds PARTITION dependencies to prevent the constraint from being deleted
1104 * on its own. Alternatively, reverse that.
1121 elog(
ERROR,
"cache lookup failed for constraint %u", childConstrId);
1126 /* don't allow setting parent for a constraint that already has one */
1127 Assert(constrForm->coninhcount == 0);
1129 elog(
ERROR,
"constraint %u already has a parent constraint",
1132 constrForm->conislocal =
false;
1134 &constrForm->coninhcount))
1136 errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1137 errmsg(
"too many inheritance parents"));
1139 constrForm->conparentid = parentConstrId;
1153 constrForm->coninhcount--;
1154 constrForm->conislocal =
true;
1157 /* Make sure there's no further inheritance. */
1158 Assert(constrForm->coninhcount == 0);
1163 ConstraintRelationId,
1176 * get_relation_constraint_oid
1177 * Find a constraint on the specified relation with the specified name.
1178 * Returns constraint's OID.
1192 Anum_pg_constraint_conrelid,
1196 Anum_pg_constraint_contypid,
1200 Anum_pg_constraint_conname,
1207 /* There can be at most one matching row */
1213 /* If no such constraint exists, complain */
1216 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1217 errmsg(
"constraint \"%s\" for table \"%s\" does not exist",
1226 * get_relation_constraint_attnos
1227 * Find a constraint on the specified relation with the specified name
1228 * and return the constrained columns.
1230 * Returns a Bitmapset of the column attnos of the constrained columns, with
1231 * attnos being offset by FirstLowInvalidHeapAttributeNumber so that system
1232 * columns can be represented.
1234 * *constraintOid is set to the OID of the constraint, or InvalidOid on
1239 bool missing_ok,
Oid *constraintOid)
1247 /* Set *constraintOid, to avoid complaints about uninitialized vars */
1253 Anum_pg_constraint_conrelid,
1257 Anum_pg_constraint_contypid,
1261 Anum_pg_constraint_conname,
1268 /* There can be at most one matching row */
1276 /* Extract the conkey array, ie, attnums of constrained columns */
1277 adatum =
heap_getattr(tuple, Anum_pg_constraint_conkey,
1292 elog(
ERROR,
"conkey is not a 1-D smallint array");
1295 /* Construct the result value */
1296 for (
i = 0;
i < numcols;
i++)
1306 /* If no such constraint exists, complain */
1307 if (!
OidIsValid(*constraintOid) && !missing_ok)
1309 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1310 errmsg(
"constraint \"%s\" for table \"%s\" does not exist",
1319 * Return the OID of the constraint enforced by the given index in the
1320 * given relation; or InvalidOid if no such index is cataloged.
1322 * Much like get_constraint_index, this function is concerned only with the
1323 * one constraint that "owns" the given index. Therefore, constraints of
1324 * types other than unique, primary-key, and exclusion are ignored.
1338 Anum_pg_constraint_conrelid,
1343 true, NULL, 1, &
key);
1351 if (constrForm->contype != CONSTRAINT_PRIMARY &&
1352 constrForm->contype != CONSTRAINT_UNIQUE &&
1353 constrForm->contype != CONSTRAINT_EXCLUSION)
1356 if (constrForm->conindid == indexId)
1358 constraintId = constrForm->oid;
1365 return constraintId;
1369 * get_domain_constraint_oid
1370 * Find a constraint on the specified domain with the specified name.
1371 * Returns constraint's OID.
1385 Anum_pg_constraint_conrelid,
1389 Anum_pg_constraint_contypid,
1393 Anum_pg_constraint_conname,
1400 /* There can be at most one matching row */
1406 /* If no such constraint exists, complain */
1409 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1410 errmsg(
"constraint \"%s\" for domain %s does not exist",
1419 * get_primary_key_attnos
1420 * Identify the columns in a relation's primary key, if any.
1422 * Returns a Bitmapset of the column attnos of the primary key's columns,
1423 * with attnos being offset by FirstLowInvalidHeapAttributeNumber so that
1424 * system columns can be represented.
1426 * If there is no primary key, return NULL. We also return NULL if the pkey
1427 * constraint is deferrable and deferrableOk is false.
1429 * *constraintOid is set to the OID of the pkey constraint, or InvalidOid
1441 /* Set *constraintOid, to avoid complaints about uninitialized vars */
1444 /* Scan pg_constraint for constraints of the target rel */
1448 Anum_pg_constraint_conrelid,
1465 /* Skip constraints that are not PRIMARY KEYs */
1466 if (con->contype != CONSTRAINT_PRIMARY)
1470 * If the primary key is deferrable, but we've been instructed to
1471 * ignore deferrable constraints, then we might as well give up
1472 * searching, since there can only be a single primary key on a table.
1474 if (con->condeferrable && !deferrableOk)
1477 /* Extract the conkey array, ie, attnums of PK's columns */
1478 adatum =
heap_getattr(tuple, Anum_pg_constraint_conkey,
1481 elog(
ERROR,
"null conkey for constraint %u",
1489 elog(
ERROR,
"conkey is not a 1-D smallint array");
1492 /* Construct the result value */
1493 for (
i = 0;
i < numkeys;
i++)
1500 /* No need to search further */
1512 * Extract data from the pg_constraint tuple of a foreign-key constraint.
1514 * All arguments save the first are output arguments. All output arguments
1515 * other than numfks, conkey and confkey can be passed as NULL if caller
1516 * doesn't need them.
1521 Oid *pf_eq_oprs,
Oid *pp_eq_oprs,
Oid *ff_eq_oprs,
1522 int *num_fk_del_set_cols,
AttrNumber *fk_del_set_cols)
1530 * We expect the arrays to be 1-D arrays of the right types; verify that.
1531 * We don't need to use deconstruct_array() since the array data is just
1532 * going to look like a C array of values.
1535 Anum_pg_constraint_conkey);
1540 elog(
ERROR,
"conkey is not a 1-D smallint array");
1543 elog(
ERROR,
"foreign key constraint cannot have %d columns", numkeys);
1546 pfree(arr);
/* free de-toasted copy, if any */
1549 Anum_pg_constraint_confkey);
1555 elog(
ERROR,
"confkey is not a 1-D smallint array");
1558 pfree(arr);
/* free de-toasted copy, if any */
1563 Anum_pg_constraint_conpfeqop);
1565 /* see TryReuseForeignKey if you change the test below */
1570 elog(
ERROR,
"conpfeqop is not a 1-D Oid array");
1573 pfree(arr);
/* free de-toasted copy, if any */
1579 Anum_pg_constraint_conppeqop);
1585 elog(
ERROR,
"conppeqop is not a 1-D Oid array");
1588 pfree(arr);
/* free de-toasted copy, if any */
1594 Anum_pg_constraint_conffeqop);
1600 elog(
ERROR,
"conffeqop is not a 1-D Oid array");
1603 pfree(arr);
/* free de-toasted copy, if any */
1606 if (fk_del_set_cols)
1609 Anum_pg_constraint_confdelsetcols, &isNull);
1612 *num_fk_del_set_cols = 0;
1616 int num_delete_cols;
1622 elog(
ERROR,
"confdelsetcols is not a 1-D smallint array");
1623 num_delete_cols =
ARR_DIMS(arr)[0];
1626 pfree(arr);
/* free de-toasted copy, if any */
1628 *num_fk_del_set_cols = num_delete_cols;
1636 * FindFKPeriodOpers -
1638 * Looks up the operator oids used for the PERIOD part of a temporal foreign key.
1639 * The opclass should be the opclass of that PERIOD element.
1640 * Everything else is an output: containedbyoperoid is the ContainedBy operator for
1641 * types matching the PERIOD element.
1642 * aggedcontainedbyoperoid is also a ContainedBy operator,
1643 * but one whose rhs is a multirange.
1644 * That way foreign keys can compare fkattr <@ range_agg(pkattr).
1645 * intersectoperoid is used by NO ACTION constraints to trim the range being considered
1646 * to just what was updated/deleted.
1650 Oid *containedbyoperoid,
1651 Oid *aggedcontainedbyoperoid,
1652 Oid *intersectoperoid)
1658 /* Make sure we have a range or multirange. */
1661 if (opcintype != ANYRANGEOID && opcintype != ANYMULTIRANGEOID)
1663 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1664 errmsg(
"invalid type for PERIOD part of foreign key"),
1665 errdetail(
"Only range and multirange are supported."));
1669 elog(
ERROR,
"cache lookup failed for opclass %u", opclass);
1672 * Look up the ContainedBy operator whose lhs and rhs are the opclass's
1673 * type. We use this to optimize RI checks: if the new value includes all
1674 * of the old value, then we can treat the attribute as if it didn't
1675 * change, and skip the RI check.
1684 * Now look up the ContainedBy operator. Its left arg must be the type of
1685 * the column (or rather of the opclass). Its right arg must match the
1686 * return type of the support proc.
1691 aggedcontainedbyoperoid,
1697 *intersectoperoid = OID_RANGE_INTERSECT_RANGE_OP;
1699 case ANYMULTIRANGEOID:
1700 *intersectoperoid = OID_MULTIRANGE_INTERSECT_MULTIRANGE_OP;
1703 elog(
ERROR,
"unexpected opcintype: %u", opcintype);
1708 * Determine whether a relation can be proven functionally dependent on
1709 * a set of grouping columns. If so, return true and add the pg_constraint
1710 * OIDs of the constraints needed for the proof to the *constraintDeps list.
1712 * grouping_columns is a list of grouping expressions, in which columns of
1713 * the rel of interest are Vars with the indicated varno/varlevelsup.
1715 * Currently we only check to see if the rel has a primary key that is a
1716 * subset of the grouping_columns. We could also use plain unique constraints
1717 * if all their columns are known not null, but there's a problem: we need
1718 * to be able to represent the not-null-ness as part of the constraints added
1719 * to *constraintDeps. FIXME whenever not-null constraints get represented
1725 List *grouping_columns,
1726 List **constraintDeps)
1733 /* If the rel has no PK, then we can't prove functional dependency */
1735 if (pkattnos == NULL)
1738 /* Identify all the rel's columns that appear in grouping_columns */
1739 groupbyattnos = NULL;
1740 foreach(gl, grouping_columns)
1745 gvar->
varno == varno &&
1753 /* The PK is a subset of grouping_columns, so we win */
1754 *constraintDeps =
lappend_oid(*constraintDeps, constraintOid);
#define DatumGetArrayTypeP(X)
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
#define InvalidAttrNumber
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_add_member(Bitmapset *a, int x)
static Datum values[MAXATTR]
#define CStringGetTextDatum(s)
#define OidIsValid(objectId)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
@ DEPENDENCY_PARTITION_PRI
@ DEPENDENCY_PARTITION_SEC
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void systable_endscan(SysScanDesc sysscan)
HeapTuple systable_getnext(SysScanDesc sysscan)
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_copytuple(HeapTuple tuple)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
static void * GETSTRUCT(const HeapTupleData *tuple)
char * makeObjectName(const char *name1, const char *name2, const char *label)
void GetOperatorFromCompareType(Oid opclass, Oid rhstype, CompareType cmptype, Oid *opid, StrategyNumber *strat)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
static bool pg_add_s16_overflow(int16 a, int16 b, int16 *result)
List * lappend(List *list, void *datum)
List * lappend_oid(List *list, Oid datum)
#define AccessExclusiveLock
char * get_rel_name(Oid relid)
AttrNumber get_attnum(Oid relid, const char *attname)
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
char * pstrdup(const char *in)
void pfree(void *pointer)
void namestrcpy(Name name, const char *str)
#define IsA(nodeptr, _type_)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
#define ObjectAddressSet(addr, class_id, object_id)
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
FormData_pg_class * Form_pg_class
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)
HeapTuple findNotNullConstraint(Oid relid, const char *colname)
bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId, const char *conname)
void RemoveConstraintById(Oid conId)
void FindFKPeriodOpers(Oid opclass, Oid *containedbyoperoid, Oid *aggedcontainedbyoperoid, Oid *intersectoperoid)
void RenameConstraintById(Oid conId, const char *newname)
Oid get_relation_idx_constraint_oid(Oid relationId, Oid indexId)
void ConstraintSetParentConstraint(Oid childConstrId, Oid parentConstrId, Oid childTableId)
Bitmapset * get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
HeapTuple findDomainNotNullConstraint(Oid typid)
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)
HeapTuple findNotNullConstraintAttnum(Oid relid, AttrNumber attnum)
void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId, Oid newNspId, bool isType, ObjectAddresses *objsMoved)
List * RelationGetNotNullConstraints(Oid relid, bool cooked, bool include_noinh)
bool ConstraintNameExists(const char *conname, Oid namespaceid)
char * ChooseConstraintName(const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
bool check_functional_grouping(Oid relid, Index varno, Index varlevelsup, List *grouping_columns, List **constraintDeps)
Bitmapset * get_relation_constraint_attnos(Oid relid, const char *conname, bool missing_ok, Oid *constraintOid)
Oid get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok)
AttrNumber extractNotNullColumn(HeapTuple constrTup)
bool AdjustNotNullInheritance(Oid relid, AttrNumber attnum, bool is_local, bool is_no_inherit, bool is_notvalid)
Oid get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok)
FormData_pg_constraint * Form_pg_constraint
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
size_t strlcpy(char *dst, const char *src, size_t siz)
static Datum PointerGetDatum(const void *X)
static Datum Int16GetDatum(int16 X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Datum NameGetDatum(const NameData *X)
static Pointer DatumGetPointer(Datum X)
static Datum CStringGetDatum(const char *X)
static Datum CharGetDatum(char X)
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
#define BTEqualStrategyNumber
#define ERRCODE_DUPLICATE_OBJECT
#define FirstLowInvalidHeapAttributeNumber
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
#define SearchSysCacheCopy1(cacheId, key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
String * makeString(char *str)