From 6a57a457cf7d3409579868ef17de6725ec6e67ca Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 21 Oct 2024 15:08:22 -0400 Subject: [PATCH] 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 --- src/backend/commands/copy.c | 8 ++++++-- src/test/regress/expected/copydml.out | 10 +++++++--- src/test/regress/sql/copydml.sql | 4 ++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index cd2446f8acb..dd2ffba0eae 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -1547,7 +1547,7 @@ BeginCopy(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, @@ -1564,7 +1564,11 @@ BeginCopy(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 1b533962c6b..fda09cff7f4 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 9a29f9c9acc..f7a480b1ff0 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 -- 2.39.5