aboutsummaryrefslogtreecommitdiff
path: root/src/backend/catalog/heap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/heap.c')
-rw-r--r--src/backend/catalog/heap.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index dbd609493f9..ea06a5739a8 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -105,6 +105,7 @@ static void StoreConstraints(Relation rel, List *cooked_constraints,
bool is_internal);
static bool MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
bool allow_merge, bool is_local,
+ bool is_initially_valid,
bool is_no_inherit);
static void SetRelationNumChecks(Relation rel, int numchecks);
static Node *cookConstraint(ParseState *pstate,
@@ -2301,6 +2302,7 @@ AddRelationNewConstraints(Relation rel,
*/
if (MergeWithExistingConstraint(rel, ccname, expr,
allow_merge, is_local,
+ cdef->initially_valid,
cdef->is_no_inherit))
continue;
}
@@ -2389,6 +2391,7 @@ AddRelationNewConstraints(Relation rel,
static bool
MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
bool allow_merge, bool is_local,
+ bool is_initially_valid,
bool is_no_inherit)
{
bool found;
@@ -2436,22 +2439,47 @@ MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
if (equal(expr, stringToNode(TextDatumGetCString(val))))
found = true;
}
+
+ /*
+ * If the existing constraint is purely inherited (no local
+ * definition) then interpret addition of a local constraint as a
+ * legal merge. This allows ALTER ADD CONSTRAINT on parent and
+ * child tables to be given in either order with same end state.
+ */
+ if (is_local && !con->conislocal)
+ allow_merge = true;
+
if (!found || !allow_merge)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("constraint \"%s\" for relation \"%s\" already exists",
ccname, RelationGetRelationName(rel))));
- tup = heap_copytuple(tup);
- con = (Form_pg_constraint) GETSTRUCT(tup);
-
- /* If the constraint is "no inherit" then cannot merge */
+ /* If the child constraint is "no inherit" then cannot merge */
if (con->connoinherit)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
ccname, RelationGetRelationName(rel))));
+ /*
+ * If the child constraint is "not valid" then cannot merge with a
+ * valid parent constraint
+ */
+ if (is_initially_valid && !con->convalidated)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
+ ccname, RelationGetRelationName(rel))));
+
+ /* OK to update the tuple */
+ ereport(NOTICE,
+ (errmsg("merging constraint \"%s\" with inherited definition",
+ ccname)));
+
+ tup = heap_copytuple(tup);
+ con = (Form_pg_constraint) GETSTRUCT(tup);
+
if (is_local)
con->conislocal = true;
else
@@ -2461,10 +2489,6 @@ MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
Assert(is_local);
con->connoinherit = true;
}
- /* OK to update the tuple */
- ereport(NOTICE,
- (errmsg("merging constraint \"%s\" with inherited definition",
- ccname)));
simple_heap_update(conDesc, &tup->t_self, tup);
CatalogUpdateIndexes(conDesc, tup);
break;