Skip to content

Commit a9da193

Browse files
committed
Reject cases where a query in WITH rewrites to just NOTIFY.
Since the executor can't cope with a utility statement appearing as a node of a plan tree, we can't support cases where a rewrite rule inserts a NOTIFY into an INSERT/UPDATE/DELETE command appearing in a WITH clause of a larger query. (One can imagine ways around that, but it'd be a new feature not a bug fix, and so far there's been no demand for it.) RewriteQuery checked for this, but it missed the case where the DML command rewrites to *only* a NOTIFY. That'd lead to crashes later on in planning. Add the missed check, and improve the level of testing of this area. Per bug #17094 from Yaoguang Chen. It's been busted since WITH was introduced, so back-patch to all supported branches. Discussion: https://postgr.es/m/17094-bf15dff55eaf2e28@postgresql.org
1 parent ca2e447 commit a9da193

File tree

3 files changed

+63
-3
lines changed

3 files changed

+63
-3
lines changed

src/backend/rewrite/rewriteHandler.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3585,15 +3585,29 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
35853585

35863586
/*
35873587
* Currently we can only handle unconditional, single-statement DO
3588-
* INSTEAD rules correctly; we have to get exactly one Query out of
3589-
* the rewrite operation to stuff back into the CTE node.
3588+
* INSTEAD rules correctly; we have to get exactly one non-utility
3589+
* Query out of the rewrite operation to stuff back into the CTE node.
35903590
*/
35913591
if (list_length(newstuff) == 1)
35923592
{
3593-
/* Push the single Query back into the CTE node */
3593+
/* Must check it's not a utility command */
35943594
ctequery = linitial_node(Query, newstuff);
3595+
if (!(ctequery->commandType == CMD_SELECT ||
3596+
ctequery->commandType == CMD_UPDATE ||
3597+
ctequery->commandType == CMD_INSERT ||
3598+
ctequery->commandType == CMD_DELETE))
3599+
{
3600+
/*
3601+
* Currently it could only be NOTIFY; this error message will
3602+
* need work if we ever allow other utility commands in rules.
3603+
*/
3604+
ereport(ERROR,
3605+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3606+
errmsg("DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH")));
3607+
}
35953608
/* WITH queries should never be canSetTag */
35963609
Assert(!ctequery->canSetTag);
3610+
/* Push the single Query back into the CTE node */
35973611
cte->ctequery = (Node *) ctequery;
35983612
}
35993613
else if (newstuff == NIL)

src/test/regress/expected/with.out

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2969,6 +2969,31 @@ WITH t AS (
29692969
)
29702970
VALUES(FALSE);
29712971
ERROR: conditional DO INSTEAD rules are not supported for data-modifying statements in WITH
2972+
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO INSTEAD NOTHING;
2973+
WITH t AS (
2974+
INSERT INTO y VALUES(0)
2975+
)
2976+
VALUES(FALSE);
2977+
ERROR: DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH
2978+
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO INSTEAD NOTIFY foo;
2979+
WITH t AS (
2980+
INSERT INTO y VALUES(0)
2981+
)
2982+
VALUES(FALSE);
2983+
ERROR: DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH
2984+
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO ALSO NOTIFY foo;
2985+
WITH t AS (
2986+
INSERT INTO y VALUES(0)
2987+
)
2988+
VALUES(FALSE);
2989+
ERROR: DO ALSO rules are not supported for data-modifying statements in WITH
2990+
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y
2991+
DO INSTEAD (NOTIFY foo; NOTIFY bar);
2992+
WITH t AS (
2993+
INSERT INTO y VALUES(0)
2994+
)
2995+
VALUES(FALSE);
2996+
ERROR: multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH
29722997
DROP RULE y_rule ON y;
29732998
-- check that parser lookahead for WITH doesn't cause any odd behavior
29742999
create table foo (with baz); -- fail, WITH is a reserved word

src/test/regress/sql/with.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,6 +1375,27 @@ WITH t AS (
13751375
INSERT INTO y VALUES(0)
13761376
)
13771377
VALUES(FALSE);
1378+
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO INSTEAD NOTHING;
1379+
WITH t AS (
1380+
INSERT INTO y VALUES(0)
1381+
)
1382+
VALUES(FALSE);
1383+
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO INSTEAD NOTIFY foo;
1384+
WITH t AS (
1385+
INSERT INTO y VALUES(0)
1386+
)
1387+
VALUES(FALSE);
1388+
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO ALSO NOTIFY foo;
1389+
WITH t AS (
1390+
INSERT INTO y VALUES(0)
1391+
)
1392+
VALUES(FALSE);
1393+
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y
1394+
DO INSTEAD (NOTIFY foo; NOTIFY bar);
1395+
WITH t AS (
1396+
INSERT INTO y VALUES(0)
1397+
)
1398+
VALUES(FALSE);
13781399
DROP RULE y_rule ON y;
13791400

13801401
-- check that parser lookahead for WITH doesn't cause any odd behavior

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy