Reject MERGE in CTEs and COPY

The grammar added for MERGE inadvertently made it accepted syntax in
places that were not prepared to deal with it -- namely COPY and inside
CTEs, but invoking these things with MERGE currently causes assertion
failures or weird misbehavior in non-assertion builds.  Protect those
places by checking for it explicitly until somebody decides to implement
it.

Reported-by: Alexey Borzov <borz_off@cs.msu.su>
Discussion: https://postgr.es/m/17579-82482cd7b267b862@postgresql.org
This commit is contained in:
Alvaro Herrera 2022-08-12 12:05:50 +02:00
parent e7a552f303
commit 92af9143f1
No known key found for this signature in database
GPG Key ID: 1C20ACB9D5C564AE
4 changed files with 37 additions and 0 deletions

View File

@ -273,6 +273,12 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
{
Assert(stmt->query);
/* MERGE is allowed by parser, but unimplemented. Reject for now */
if (IsA(stmt->query, MergeStmt))
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("MERGE not supported in COPY"));
query = makeNode(RawStmt);
query->stmt = stmt->query;
query->stmt_location = stmt_location;

View File

@ -126,6 +126,13 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
ListCell *rest;
/* MERGE is allowed by parser, but unimplemented. Reject for now */
if (IsA(cte->ctequery, MergeStmt))
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("MERGE not supported in WITH query"),
parser_errposition(pstate, cte->location));
for_each_cell(rest, withClause->ctes, lnext(withClause->ctes, lc))
{
CommonTableExpr *cte2 = (CommonTableExpr *) lfirst(rest);

View File

@ -123,6 +123,20 @@ ON tid = tid
WHEN MATCHED THEN DO NOTHING;
ERROR: name "target" specified more than once
DETAIL: The name is used both as MERGE target table and data source.
-- used in a CTE
WITH foo AS (
MERGE INTO target USING source ON (true)
WHEN MATCHED THEN DELETE
) SELECT * FROM foo;
ERROR: MERGE not supported in WITH query
LINE 1: WITH foo AS (
^
-- used in COPY
COPY (
MERGE INTO target USING source ON (true)
WHEN MATCHED THEN DELETE
) TO stdout;
ERROR: MERGE not supported in COPY
-- unsupported relation types
-- view
CREATE VIEW tv AS SELECT * FROM target;

View File

@ -88,6 +88,16 @@ MERGE INTO target
USING target
ON tid = tid
WHEN MATCHED THEN DO NOTHING;
-- used in a CTE
WITH foo AS (
MERGE INTO target USING source ON (true)
WHEN MATCHED THEN DELETE
) SELECT * FROM foo;
-- used in COPY
COPY (
MERGE INTO target USING source ON (true)
WHEN MATCHED THEN DELETE
) TO stdout;
-- unsupported relation types
-- view