mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-23 19:39:53 +08:00
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
This commit is contained in:
parent
ca2e4472ba
commit
a9da1934e9
@ -3585,15 +3585,29 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
|
||||
|
||||
/*
|
||||
* Currently we can only handle unconditional, single-statement DO
|
||||
* INSTEAD rules correctly; we have to get exactly one Query out of
|
||||
* the rewrite operation to stuff back into the CTE node.
|
||||
* INSTEAD rules correctly; we have to get exactly one non-utility
|
||||
* Query out of the rewrite operation to stuff back into the CTE node.
|
||||
*/
|
||||
if (list_length(newstuff) == 1)
|
||||
{
|
||||
/* Push the single Query back into the CTE node */
|
||||
/* Must check it's not a utility command */
|
||||
ctequery = linitial_node(Query, newstuff);
|
||||
if (!(ctequery->commandType == CMD_SELECT ||
|
||||
ctequery->commandType == CMD_UPDATE ||
|
||||
ctequery->commandType == CMD_INSERT ||
|
||||
ctequery->commandType == CMD_DELETE))
|
||||
{
|
||||
/*
|
||||
* Currently it could only be NOTIFY; this error message will
|
||||
* need work if we ever allow other utility commands in rules.
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH")));
|
||||
}
|
||||
/* WITH queries should never be canSetTag */
|
||||
Assert(!ctequery->canSetTag);
|
||||
/* Push the single Query back into the CTE node */
|
||||
cte->ctequery = (Node *) ctequery;
|
||||
}
|
||||
else if (newstuff == NIL)
|
||||
|
@ -2969,6 +2969,31 @@ WITH t AS (
|
||||
)
|
||||
VALUES(FALSE);
|
||||
ERROR: conditional DO INSTEAD rules are not supported for data-modifying statements in WITH
|
||||
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO INSTEAD NOTHING;
|
||||
WITH t AS (
|
||||
INSERT INTO y VALUES(0)
|
||||
)
|
||||
VALUES(FALSE);
|
||||
ERROR: DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH
|
||||
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO INSTEAD NOTIFY foo;
|
||||
WITH t AS (
|
||||
INSERT INTO y VALUES(0)
|
||||
)
|
||||
VALUES(FALSE);
|
||||
ERROR: DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH
|
||||
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO ALSO NOTIFY foo;
|
||||
WITH t AS (
|
||||
INSERT INTO y VALUES(0)
|
||||
)
|
||||
VALUES(FALSE);
|
||||
ERROR: DO ALSO rules are not supported for data-modifying statements in WITH
|
||||
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y
|
||||
DO INSTEAD (NOTIFY foo; NOTIFY bar);
|
||||
WITH t AS (
|
||||
INSERT INTO y VALUES(0)
|
||||
)
|
||||
VALUES(FALSE);
|
||||
ERROR: multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH
|
||||
DROP RULE y_rule ON y;
|
||||
-- check that parser lookahead for WITH doesn't cause any odd behavior
|
||||
create table foo (with baz); -- fail, WITH is a reserved word
|
||||
|
@ -1375,6 +1375,27 @@ WITH t AS (
|
||||
INSERT INTO y VALUES(0)
|
||||
)
|
||||
VALUES(FALSE);
|
||||
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO INSTEAD NOTHING;
|
||||
WITH t AS (
|
||||
INSERT INTO y VALUES(0)
|
||||
)
|
||||
VALUES(FALSE);
|
||||
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO INSTEAD NOTIFY foo;
|
||||
WITH t AS (
|
||||
INSERT INTO y VALUES(0)
|
||||
)
|
||||
VALUES(FALSE);
|
||||
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO ALSO NOTIFY foo;
|
||||
WITH t AS (
|
||||
INSERT INTO y VALUES(0)
|
||||
)
|
||||
VALUES(FALSE);
|
||||
CREATE OR REPLACE RULE y_rule AS ON INSERT TO y
|
||||
DO INSTEAD (NOTIFY foo; NOTIFY bar);
|
||||
WITH t AS (
|
||||
INSERT INTO y VALUES(0)
|
||||
)
|
||||
VALUES(FALSE);
|
||||
DROP RULE y_rule ON y;
|
||||
|
||||
-- check that parser lookahead for WITH doesn't cause any odd behavior
|
||||
|
Loading…
Reference in New Issue
Block a user