v3-0001-Fix-error-handling-of-ALTER-CONSTRAINT-NOT-VALID.patch

text/plain

Filename: v3-0001-Fix-error-handling-of-ALTER-CONSTRAINT-NOT-VALID.patch
Type: text/plain
Part: 0
Message: Re: ALTER TABLE ALTER CONSTRAINT misleading error message

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v3-0001
Subject: Fix error handling of ALTER CONSTRAINT NOT VALID.
File+
src/backend/commands/tablecmds.c 9 0
src/backend/parser/gram.y 14 2
src/include/nodes/parsenodes.h 7 0
src/test/regress/expected/foreign_key.out 1 3
From 59b5f5c711331be0e9376f01948412f5079ca424 Mon Sep 17 00:00:00 2001
From: Fujii Masao <fujii@postgresql.org>
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