Simplify syntax for ALTER TABLE ALTER CONSTRAINT NO INHERIT

Commit d45597f72fe5 introduced the ability to change a not-null
constraint from NO INHERIT to INHERIT and vice versa, but we included
the SET noise word in the syntax for it.  The SET turns out not to be
necessary and goes against what the SQL standard says for other ALTER
TABLE subcommands, so remove it.

This changes the way this command is processed for constraint types
other than not-null, so there are some error message changes.

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Suraj Kharage <suraj.kharage@enterprisedb.com>
Discussion: https://postgr.es/m/202503251602.vsxaehsyaoac@alvherre.pgsql
This commit is contained in:
Álvaro Herrera 2025-03-27 09:24:52 +01:00
parent 72c2f36d57
commit 4a02af8b1a
No known key found for this signature in database
GPG Key ID: 1C20ACB9D5C564AE
6 changed files with 43 additions and 55 deletions

View File

@ -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

View File

@ -12199,7 +12199,7 @@ ATExecAlterConstrInheritability(List **wqueue, ATAlterConstraint *cmdcon,
colName = get_attname(currcon->conrelid, colNum, false);
/*
* Propagate the change to children. For SET NO INHERIT, we don't
* Propagate the change to children. For this subcommand type we don't
* recursively affect children, just the immediate level.
*/
children = find_inheritance_children(RelationGetRelid(rel),

View File

@ -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 ... */

View File

@ -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;

View File

@ -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;
--

View File

@ -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;