On 2025-Mar-25, Álvaro Herrera wrote:

> With commit f4e53e10b6ce we introduced a way to flip the NO INHERIT bit
> on not-null constraints.  However, because of the way the grammar
> dealt with ALTER CONSTRAINT, we were too blind to see a way to implement
> it using the existing production.

Patch attached.

-- 
Álvaro Herrera         PostgreSQL Developer  —  https://www.EnterpriseDB.com/
"Someone said that it is at least an order of magnitude more work to do
production software than a prototype. I think he is wrong by at least
an order of magnitude."                              (Brian Kernighan)
>From ad94ec630c4d4daa3ca2e2983ca2087e089ae120 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Herrera?= <alvhe...@alvh.no-ip.org>
Date: Tue, 25 Mar 2025 17:03:32 +0100
Subject: [PATCH] change syntax from SET NO INHERIT to just NO INHERIT

---
 doc/src/sgml/ref/alter_table.sgml         |  6 ++---
 src/backend/parser/gram.y                 | 26 ++++++--------------
 src/test/regress/expected/foreign_key.out |  4 +--
 src/test/regress/expected/inherit.out     | 30 +++++++++++------------
 src/test/regress/sql/inherit.sql          | 30 +++++++++++------------
 5 files changed, 42 insertions(+), 54 deletions(-)

diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 4f15b89a98f..11d1bc7dbe1 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -59,7 +59,7 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
     ADD <replaceable class="parameter">table_constraint</replaceable> [ NOT VALID ]
     ADD <replaceable class="parameter">table_constraint_using_index</replaceable>
     ALTER CONSTRAINT <replaceable class="parameter">constraint_name</replaceable> [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
-    ALTER CONSTRAINT <replaceable class="parameter">constraint_name</replaceable> SET [ INHERIT | NO INHERIT ]
+    ALTER CONSTRAINT <replaceable class="parameter">constraint_name</replaceable> [ INHERIT | NO INHERIT ]
     VALIDATE CONSTRAINT <replaceable class="parameter">constraint_name</replaceable>
     DROP CONSTRAINT [ IF EXISTS ]  <replaceable class="parameter">constraint_name</replaceable> [ RESTRICT | CASCADE ]
     DISABLE TRIGGER [ <replaceable class="parameter">trigger_name</replaceable> | ALL | USER ]
@@ -564,8 +564,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
    </varlistentry>
 
    <varlistentry id="sql-altertable-desc-alter-constraint-inherit">
-    <term><literal>ALTER CONSTRAINT ... SET INHERIT</literal></term>
-    <term><literal>ALTER CONSTRAINT ... SET NO INHERIT</literal></term>
+    <term><literal>ALTER CONSTRAINT ... INHERIT</literal></term>
+    <term><literal>ALTER CONSTRAINT ... NO INHERIT</literal></term>
     <listitem>
      <para>
       These forms modify a inheritable constraint so that it becomes not
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 271ae26cbaf..0fc502a3a40 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -2662,15 +2662,19 @@ alter_table_cmd:
 					n->subtype = AT_AlterConstraint;
 					n->def = (Node *) c;
 					c->conname = $3;
-					c->alterDeferrability = true;
+					if ($4 & (CAS_DEFERRABLE | CAS_NOT_DEFERRABLE |
+							  CAS_INITIALLY_DEFERRED | CAS_INITIALLY_IMMEDIATE))
+						c->alterDeferrability = true;
+					if ($4 & CAS_NO_INHERIT)
+						c->alterInheritability = true;
 					processCASbits($4, @4, "FOREIGN KEY",
 									&c->deferrable,
 									&c->initdeferred,
-									NULL, NULL, NULL, yyscanner);
+									NULL, NULL, &c->noinherit, yyscanner);
 					$$ = (Node *) n;
 				}
-			/* ALTER TABLE <name> ALTER CONSTRAINT SET INHERIT */
-			| ALTER CONSTRAINT name SET INHERIT
+			/* ALTER TABLE <name> ALTER CONSTRAINT INHERIT */
+			| ALTER CONSTRAINT name INHERIT
 				{
 					AlterTableCmd *n = makeNode(AlterTableCmd);
 					ATAlterConstraint *c = makeNode(ATAlterConstraint);
@@ -2681,20 +2685,6 @@ alter_table_cmd:
 					c->alterInheritability = true;
 					c->noinherit = false;
 
-					$$ = (Node *) n;
-				}
-			/* ALTER TABLE <name> ALTER CONSTRAINT SET NO INHERIT */
-			| ALTER CONSTRAINT name SET NO INHERIT
-				{
-					AlterTableCmd *n = makeNode(AlterTableCmd);
-					ATAlterConstraint *c = makeNode(ATAlterConstraint);
-
-					n->subtype = AT_AlterConstraint;
-					n->def = (Node *) c;
-					c->conname = $3;
-					c->alterInheritability = true;
-					c->noinherit = true;
-
 					$$ = (Node *) n;
 				}
 			/* ALTER TABLE <name> VALIDATE CONSTRAINT ... */
diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out
index 6a3374d5152..7f678349a8e 100644
--- a/src/test/regress/expected/foreign_key.out
+++ b/src/test/regress/expected/foreign_key.out
@@ -1284,9 +1284,7 @@ ERROR:  constraint declared INITIALLY DEFERRED must be DEFERRABLE
 LINE 1: ...e ALTER CONSTRAINT fktable_fk_fkey NOT DEFERRABLE INITIALLY ...
                                                              ^
 ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NO INHERIT;
-ERROR:  FOREIGN KEY constraints cannot be marked NO INHERIT
-LINE 1: ...ER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NO INHERIT...
-                                                             ^
+ERROR:  constraint "fktable_fk_fkey" of relation "fktable" is not a not-null constraint
 ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT VALID;
 ERROR:  FOREIGN KEY constraints cannot be marked NOT VALID
 LINE 1: ...ER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT VALID;
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index e671975a281..58461e7f53f 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -2754,7 +2754,7 @@ alter table inh_nn2 inherit inh_nn1;
 create table inh_nn3 (f4 float) inherits (inh_nn2);
 create table inh_nn4 (f5 int, f4 float, f2 text, f3 int, f1 int);
 alter table inh_nn4 inherit inh_nn2, inherit inh_nn1, inherit inh_nn3;
-alter table inh_nn1 alter constraint inh_nn1_f1_not_null set inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit;
 select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit
  from pg_constraint where contype = 'n' and
  conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4')
@@ -2767,8 +2767,8 @@ select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinheri
  inh_nn4  | inh_nn1_f1_not_null | {5}    |           3 | f          | f
 (4 rows)
 
--- ALTER CONSTRAINT SET NO INHERIT should work on top-level constraints
-alter table inh_nn1 alter constraint inh_nn1_f1_not_null set no inherit;
+-- ALTER CONSTRAINT NO INHERIT should work on top-level constraints
+alter table inh_nn1 alter constraint inh_nn1_f1_not_null no inherit;
 select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit
  from pg_constraint where contype = 'n' and
  conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4')
@@ -2799,15 +2799,15 @@ drop table inh_nn1, inh_nn2, inh_nn3, inh_nn4;
 create table inh_nn1 (f1 int not null no inherit);
 create table inh_nn2 (f2 text, f3 int) inherits (inh_nn1);
 insert into inh_nn2 values(NULL, 'sample', 1);
-alter table inh_nn1 alter constraint inh_nn1_f1_not_null set inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit;
 ERROR:  column "f1" of relation "inh_nn2" contains null values
 delete from inh_nn2;
 create table inh_nn3 () inherits (inh_nn2);
 create table inh_nn4 () inherits (inh_nn1, inh_nn2);
 NOTICE:  merging multiple inherited definitions of column "f1"
 alter table inh_nn1	-- test multicommand alter table while at it
-   alter constraint inh_nn1_f1_not_null set inherit,
-   alter constraint inh_nn1_f1_not_null set no inherit;
+   alter constraint inh_nn1_f1_not_null inherit,
+   alter constraint inh_nn1_f1_not_null no inherit;
 select conrelid::regclass, conname, coninhcount, conislocal, connoinherit
  from pg_constraint where contype = 'n' and
  conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4')
@@ -2837,10 +2837,10 @@ select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinheri
 (2 rows)
 
 -- error: inh_nn3 has an incompatible NO INHERIT constraint
-alter table inh_nn1 alter constraint inh_nn1_f1_not_null set inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit;
 ERROR:  cannot change NO INHERIT status of NOT NULL constraint "nn3_f1" on relation "inh_nn3"
-alter table inh_nn3 alter constraint nn3_f1 set inherit;
-alter table inh_nn1 alter constraint inh_nn1_f1_not_null set inherit; -- now it works
+alter table inh_nn3 alter constraint nn3_f1 inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit; -- now it works
 select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit
  from pg_constraint where contype = 'n' and
  conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3')
@@ -2853,21 +2853,21 @@ select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinheri
 (3 rows)
 
 drop table inh_nn1, inh_nn2, inh_nn3;
--- Negative scenarios for alter constraint .. set inherit.
+-- Negative scenarios for alter constraint .. inherit.
 create table inh_nn1 (f1 int check(f1 > 5) primary key references inh_nn1, f2 int not null);
 -- constraints other than not-null are not supported
-alter table inh_nn1 alter constraint inh_nn1_f1_check set inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_check inherit;
 ERROR:  constraint "inh_nn1_f1_check" of relation "inh_nn1" is not a not-null constraint
-alter table inh_nn1 alter constraint inh_nn1_pkey set inherit;
+alter table inh_nn1 alter constraint inh_nn1_pkey inherit;
 ERROR:  constraint "inh_nn1_pkey" of relation "inh_nn1" is not a not-null constraint
-alter table inh_nn1 alter constraint inh_nn1_f1_fkey set inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_fkey inherit;
 ERROR:  constraint "inh_nn1_f1_fkey" of relation "inh_nn1" is not a not-null constraint
 -- try to drop a nonexistant constraint
-alter table inh_nn1 alter constraint foo set inherit;
+alter table inh_nn1 alter constraint foo inherit;
 ERROR:  constraint "foo" of relation "inh_nn1" does not exist
 -- Can't modify inheritability of inherited constraints
 create table inh_nn2 () inherits (inh_nn1);
-alter table inh_nn2 alter constraint inh_nn1_f2_not_null set no inherit;
+alter table inh_nn2 alter constraint inh_nn1_f2_not_null no inherit;
 ERROR:  cannot alter inherited constraint "inh_nn1_f2_not_null" on relation "inh_nn2"
 drop table inh_nn1, inh_nn2;
 --
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
index 4e73c70495c..8df0f8af08a 100644
--- a/src/test/regress/sql/inherit.sql
+++ b/src/test/regress/sql/inherit.sql
@@ -1099,13 +1099,13 @@ alter table inh_nn2 inherit inh_nn1;
 create table inh_nn3 (f4 float) inherits (inh_nn2);
 create table inh_nn4 (f5 int, f4 float, f2 text, f3 int, f1 int);
 alter table inh_nn4 inherit inh_nn2, inherit inh_nn1, inherit inh_nn3;
-alter table inh_nn1 alter constraint inh_nn1_f1_not_null set inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit;
 select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit
  from pg_constraint where contype = 'n' and
  conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4')
  order by 2, 1;
--- ALTER CONSTRAINT SET NO INHERIT should work on top-level constraints
-alter table inh_nn1 alter constraint inh_nn1_f1_not_null set no inherit;
+-- ALTER CONSTRAINT NO INHERIT should work on top-level constraints
+alter table inh_nn1 alter constraint inh_nn1_f1_not_null no inherit;
 select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit
  from pg_constraint where contype = 'n' and
  conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4')
@@ -1122,13 +1122,13 @@ drop table inh_nn1, inh_nn2, inh_nn3, inh_nn4;
 create table inh_nn1 (f1 int not null no inherit);
 create table inh_nn2 (f2 text, f3 int) inherits (inh_nn1);
 insert into inh_nn2 values(NULL, 'sample', 1);
-alter table inh_nn1 alter constraint inh_nn1_f1_not_null set inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit;
 delete from inh_nn2;
 create table inh_nn3 () inherits (inh_nn2);
 create table inh_nn4 () inherits (inh_nn1, inh_nn2);
 alter table inh_nn1	-- test multicommand alter table while at it
-   alter constraint inh_nn1_f1_not_null set inherit,
-   alter constraint inh_nn1_f1_not_null set no inherit;
+   alter constraint inh_nn1_f1_not_null inherit,
+   alter constraint inh_nn1_f1_not_null no inherit;
 select conrelid::regclass, conname, coninhcount, conislocal, connoinherit
  from pg_constraint where contype = 'n' and
  conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4')
@@ -1144,26 +1144,26 @@ select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinheri
  conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3')
  order by 2, 1;
 -- error: inh_nn3 has an incompatible NO INHERIT constraint
-alter table inh_nn1 alter constraint inh_nn1_f1_not_null set inherit;
-alter table inh_nn3 alter constraint nn3_f1 set inherit;
-alter table inh_nn1 alter constraint inh_nn1_f1_not_null set inherit; -- now it works
+alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit;
+alter table inh_nn3 alter constraint nn3_f1 inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit; -- now it works
 select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit
  from pg_constraint where contype = 'n' and
  conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3')
  order by 2, 1;
 drop table inh_nn1, inh_nn2, inh_nn3;
 
--- Negative scenarios for alter constraint .. set inherit.
+-- Negative scenarios for alter constraint .. inherit.
 create table inh_nn1 (f1 int check(f1 > 5) primary key references inh_nn1, f2 int not null);
 -- constraints other than not-null are not supported
-alter table inh_nn1 alter constraint inh_nn1_f1_check set inherit;
-alter table inh_nn1 alter constraint inh_nn1_pkey set inherit;
-alter table inh_nn1 alter constraint inh_nn1_f1_fkey set inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_check inherit;
+alter table inh_nn1 alter constraint inh_nn1_pkey inherit;
+alter table inh_nn1 alter constraint inh_nn1_f1_fkey inherit;
 -- try to drop a nonexistant constraint
-alter table inh_nn1 alter constraint foo set inherit;
+alter table inh_nn1 alter constraint foo inherit;
 -- Can't modify inheritability of inherited constraints
 create table inh_nn2 () inherits (inh_nn1);
-alter table inh_nn2 alter constraint inh_nn1_f2_not_null set no inherit;
+alter table inh_nn2 alter constraint inh_nn1_f2_not_null no inherit;
 
 drop table inh_nn1, inh_nn2;
 
-- 
2.39.5

Reply via email to