From 59b5f5c711331be0e9376f01948412f5079ca424 Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Fri, 27 Jun 2025 12:35:21 +0900 Subject: [PATCH v3] Fix error handling of ALTER CONSTRAINT NOT VALID. --- src/backend/commands/tablecmds.c | 9 +++++++++ src/backend/parser/gram.y | 16 ++++++++++++++-- src/include/nodes/parsenodes.h | 7 +++++++ src/test/regress/expected/foreign_key.out | 4 +--- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index e2b94c8c609..548473d60a6 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -12171,6 +12171,15 @@ ATExecAlterConstraint(List **wqueue, Relation rel, ATAlterConstraint *cmdcon, Form_pg_constraint currcon; ObjectAddress address; + /* + * Raise an error if NOT VALID is specified, since it's accepted by the + * syntax but not supported by ALTER CONSTRAINT. + */ + if (cmdcon->skip_validation) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("ALTER TABLE ... ALTER CONSTRAINT ... NOT VALID is not supported")); + /* * Disallow altering ONLY a partitioned table, as it would make no sense. * This is okay for legacy inheritance. diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 50f53159d58..5df301a76b7 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -2657,6 +2657,7 @@ alter_table_cmd: { AlterTableCmd *n = makeNode(AlterTableCmd); ATAlterConstraint *c = makeNode(ATAlterConstraint); + bool dummy; n->subtype = AT_AlterConstraint; n->def = (Node *) c; @@ -2668,11 +2669,22 @@ alter_table_cmd: c->alterDeferrability = true; if ($4 & CAS_NO_INHERIT) c->alterInheritability = true; - processCASbits($4, @4, "FOREIGN KEY", + + /* + * Mark whether NOT VALID was specified. If true, an error + * will be raised later in ATExecAlterConstraint(). + * processCASbits() is not used to set skip_validation, + * as it may set it to true for unrelated reasons, even if + * NOT VALID wan't specified. + */ + if ($4 & CAS_NOT_VALID) + c->skip_validation = true; + + processCASbits($4, @4, "", &c->deferrable, &c->initdeferred, &c->is_enforced, - NULL, + &dummy, &c->noinherit, yyscanner); $$ = (Node *) n; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index ba12678d1cb..99169282ed5 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -2507,6 +2507,13 @@ typedef struct ATAlterConstraint bool initdeferred; /* INITIALLY DEFERRED? */ bool alterInheritability; /* changing inheritability properties */ bool noinherit; + bool skip_validation; /* skip validation of existing rows? ALTER + * CONSTRAINT NOT VALID is allowed by the + * syntax, but not actually supported. + * This field tracks whether NOT VALID was + * specified. If it is set to true, an + * error will be raised later in + * ATExecAlterConstraint(). */ } ATAlterConstraint; /* Ad-hoc node for AT_ReplicaIdentity */ diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out index 6a8f3959345..21c1172fdd8 100644 --- a/src/test/regress/expected/foreign_key.out +++ b/src/test/regress/expected/foreign_key.out @@ -1359,9 +1359,7 @@ LINE 1: ...e ALTER CONSTRAINT fktable_fk_fkey NOT DEFERRABLE INITIALLY ... ALTER 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; - ^ +ERROR: ALTER TABLE ... ALTER CONSTRAINT ... NOT VALID is not supported ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey ENFORCED NOT ENFORCED; ERROR: conflicting constraint properties LINE 1: ...fktable ALTER CONSTRAINT fktable_fk_fkey ENFORCED NOT ENFORC... -- 2.49.0