aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/tablecmds.c99
-rw-r--r--src/test/regress/expected/alter_table.out9
-rw-r--r--src/test/regress/sql/alter_table.sql8
3 files changed, 65 insertions, 51 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 1e8ad2b6716..7b241fd15da 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -6734,6 +6734,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
{
Oid childrelid = lfirst_oid(child);
Relation childrel;
+ HeapTuple copy_tuple;
/* find_inheritance_children already got lock */
childrel = heap_open(childrelid, NoLock);
@@ -6746,83 +6747,79 @@ ATExecDropConstraint(Relation rel, const char *constrName,
scan = systable_beginscan(conrel, ConstraintRelidIndexId,
true, SnapshotNow, 1, &key);
- found = false;
-
+ /* scan for matching tuple - there should only be one */
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
- HeapTuple copy_tuple;
-
con = (Form_pg_constraint) GETSTRUCT(tuple);
/* Right now only CHECK constraints can be inherited */
if (con->contype != CONSTRAINT_CHECK)
continue;
- if (strcmp(NameStr(con->conname), constrName) != 0)
- continue;
+ if (strcmp(NameStr(con->conname), constrName) == 0)
+ break;
+ }
- found = true;
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("constraint \"%s\" of relation \"%s\" does not exist",
+ constrName,
+ RelationGetRelationName(childrel))));
- if (con->coninhcount <= 0) /* shouldn't happen */
- elog(ERROR, "relation %u has non-inherited constraint \"%s\"",
- childrelid, constrName);
+ copy_tuple = heap_copytuple(tuple);
- copy_tuple = heap_copytuple(tuple);
- con = (Form_pg_constraint) GETSTRUCT(copy_tuple);
+ systable_endscan(scan);
- if (recurse)
- {
- /*
- * If the child constraint has other definition sources, just
- * decrement its inheritance count; if not, recurse to delete
- * it.
- */
- if (con->coninhcount == 1 && !con->conislocal)
- {
- /* Time to delete this child constraint, too */
- ATExecDropConstraint(childrel, constrName, behavior,
- true, true,
- false, lockmode);
- }
- else
- {
- /* Child constraint must survive my deletion */
- con->coninhcount--;
- simple_heap_update(conrel, &copy_tuple->t_self, copy_tuple);
- CatalogUpdateIndexes(conrel, copy_tuple);
+ con = (Form_pg_constraint) GETSTRUCT(copy_tuple);
- /* Make update visible */
- CommandCounterIncrement();
- }
+ if (con->coninhcount <= 0) /* shouldn't happen */
+ elog(ERROR, "relation %u has non-inherited constraint \"%s\"",
+ childrelid, constrName);
+
+ if (recurse)
+ {
+ /*
+ * If the child constraint has other definition sources, just
+ * decrement its inheritance count; if not, recurse to delete
+ * it.
+ */
+ if (con->coninhcount == 1 && !con->conislocal)
+ {
+ /* Time to delete this child constraint, too */
+ ATExecDropConstraint(childrel, constrName, behavior,
+ true, true,
+ false, lockmode);
}
else
{
- /*
- * If we were told to drop ONLY in this table (no recursion),
- * we need to mark the inheritors' constraints as locally
- * defined rather than inherited.
- */
+ /* Child constraint must survive my deletion */
con->coninhcount--;
- con->conislocal = true;
-
simple_heap_update(conrel, &copy_tuple->t_self, copy_tuple);
CatalogUpdateIndexes(conrel, copy_tuple);
/* Make update visible */
CommandCounterIncrement();
}
-
- heap_freetuple(copy_tuple);
}
+ else
+ {
+ /*
+ * If we were told to drop ONLY in this table (no recursion),
+ * we need to mark the inheritors' constraints as locally
+ * defined rather than inherited.
+ */
+ con->coninhcount--;
+ con->conislocal = true;
- systable_endscan(scan);
+ simple_heap_update(conrel, &copy_tuple->t_self, copy_tuple);
+ CatalogUpdateIndexes(conrel, copy_tuple);
- if (!found)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("constraint \"%s\" of relation \"%s\" does not exist",
- constrName,
- RelationGetRelationName(childrel))));
+ /* Make update visible */
+ CommandCounterIncrement();
+ }
+
+ heap_freetuple(copy_tuple);
heap_close(childrel, NoLock);
}
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 005a88b084b..1aa4f09ed28 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -2103,3 +2103,12 @@ ALTER TABLE tt7 NOT OF;
x | integer |
y | numeric(8,2) |
+-- make sure we can drop a constraint on the parent but it remains on the child
+CREATE TABLE test_drop_constr_parent (c text CHECK (c IS NOT NULL));
+CREATE TABLE test_drop_constr_child () INHERITS (test_drop_constr_parent);
+ALTER TABLE ONLY test_drop_constr_parent DROP CONSTRAINT "test_drop_constr_parent_c_check";
+-- should fail
+INSERT INTO test_drop_constr_child (c) VALUES (NULL);
+ERROR: new row for relation "test_drop_constr_child" violates check constraint "test_drop_constr_parent_c_check"
+DROP TABLE test_drop_constr_parent CASCADE;
+NOTICE: drop cascades to table test_drop_constr_child
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 95e898c0eac..a477f0401b4 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -1456,3 +1456,11 @@ CREATE TYPE tt_t1 AS (x int, y numeric(8,2));
ALTER TABLE tt7 OF tt_t1; -- reassign an already-typed table
ALTER TABLE tt7 NOT OF;
\d tt7
+
+-- make sure we can drop a constraint on the parent but it remains on the child
+CREATE TABLE test_drop_constr_parent (c text CHECK (c IS NOT NULL));
+CREATE TABLE test_drop_constr_child () INHERITS (test_drop_constr_parent);
+ALTER TABLE ONLY test_drop_constr_parent DROP CONSTRAINT "test_drop_constr_parent_c_check";
+-- should fail
+INSERT INTO test_drop_constr_child (c) VALUES (NULL);
+DROP TABLE test_drop_constr_parent CASCADE;