From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 21 Oct 2024 19:08:22 +0000 (-0400)
Subject: Fix wrong assertion and poor error messages in "COPY (query) TO".
X-Git-Tag: REL_14_14~43
X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=5e94f616c8321a2e95986a236c10dfa26a3a844a;p=postgresql.git

Fix wrong assertion and poor error messages in "COPY (query) TO".

If the query is rewritten into a NOTIFY command by a DO INSTEAD
rule, we'd get an assertion failure, or in non-assert builds
issue a rather confusing error message.  Improve that.

Also fix a longstanding grammar mistake in a nearby error message.

Per bug #18664 from Alexander Lakhin.  Back-patch to all supported
branches.

Tender Wang and Tom Lane

Discussion: https://postgr.es/m/18664-ffd0ebc2386598df@postgresql.org
---

diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index a9f422b71ce..99d65beac6b 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -466,7 +466,7 @@ BeginCopyTo(ParseState *pstate,
 				if (q->querySource == QSRC_NON_INSTEAD_RULE)
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-							 errmsg("DO ALSO rules are not supported for the COPY")));
+							 errmsg("DO ALSO rules are not supported for COPY")));
 			}
 
 			ereport(ERROR,
@@ -483,7 +483,11 @@ BeginCopyTo(ParseState *pstate,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("COPY (SELECT INTO) is not supported")));
 
-		Assert(query->utilityStmt == NULL);
+		/* The only other utility command we could see is NOTIFY */
+		if (query->utilityStmt != NULL)
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("COPY query must not be a utility command")));
 
 		/*
 		 * Similarly the grammar doesn't enforce the presence of a RETURNING
diff --git a/src/test/regress/expected/copydml.out b/src/test/regress/expected/copydml.out
index b5a225628f4..e91e83260aa 100644
--- a/src/test/regress/expected/copydml.out
+++ b/src/test/regress/expected/copydml.out
@@ -38,7 +38,7 @@ ERROR:  DO INSTEAD NOTHING rules are not supported for COPY
 drop rule qqq on copydml_test;
 create rule qqq as on insert to copydml_test do also delete from copydml_test;
 copy (insert into copydml_test default values) to stdout;
-ERROR:  DO ALSO rules are not supported for the COPY
+ERROR:  DO ALSO rules are not supported for COPY
 drop rule qqq on copydml_test;
 create rule qqq as on insert to copydml_test do instead (delete from copydml_test; delete from copydml_test);
 copy (insert into copydml_test default values) to stdout;
@@ -54,7 +54,7 @@ ERROR:  DO INSTEAD NOTHING rules are not supported for COPY
 drop rule qqq on copydml_test;
 create rule qqq as on update to copydml_test do also delete from copydml_test;
 copy (update copydml_test set t = 'f') to stdout;
-ERROR:  DO ALSO rules are not supported for the COPY
+ERROR:  DO ALSO rules are not supported for COPY
 drop rule qqq on copydml_test;
 create rule qqq as on update to copydml_test do instead (delete from copydml_test; delete from copydml_test);
 copy (update copydml_test set t = 'f') to stdout;
@@ -70,7 +70,7 @@ ERROR:  DO INSTEAD NOTHING rules are not supported for COPY
 drop rule qqq on copydml_test;
 create rule qqq as on delete to copydml_test do also insert into copydml_test default values;
 copy (delete from copydml_test) to stdout;
-ERROR:  DO ALSO rules are not supported for the COPY
+ERROR:  DO ALSO rules are not supported for COPY
 drop rule qqq on copydml_test;
 create rule qqq as on delete to copydml_test do instead (insert into copydml_test default values; insert into copydml_test default values);
 copy (delete from copydml_test) to stdout;
@@ -80,6 +80,10 @@ create rule qqq as on delete to copydml_test where old.t <> 'f' do instead inser
 copy (delete from copydml_test) to stdout;
 ERROR:  conditional DO INSTEAD rules are not supported for COPY
 drop rule qqq on copydml_test;
+create rule qqq as on insert to copydml_test do instead notify copydml_test;
+copy (insert into copydml_test default values) to stdout;
+ERROR:  COPY query must not be a utility command
+drop rule qqq on copydml_test;
 -- triggers
 create function qqq_trig() returns trigger as $$
 begin
diff --git a/src/test/regress/sql/copydml.sql b/src/test/regress/sql/copydml.sql
index 4578342253b..b7eeb0eed81 100644
--- a/src/test/regress/sql/copydml.sql
+++ b/src/test/regress/sql/copydml.sql
@@ -66,6 +66,10 @@ create rule qqq as on delete to copydml_test where old.t <> 'f' do instead inser
 copy (delete from copydml_test) to stdout;
 drop rule qqq on copydml_test;
 
+create rule qqq as on insert to copydml_test do instead notify copydml_test;
+copy (insert into copydml_test default values) to stdout;
+drop rule qqq on copydml_test;
+
 -- triggers
 create function qqq_trig() returns trigger as $$
 begin