summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2022-08-12 10:05:50 +0000
committerAlvaro Herrera2022-08-12 10:05:50 +0000
commit92af9143f13df8c54362ebbd4397cb53f207ff2d (patch)
tree910a3a67d8aeb757872f24578c7052a9698fd09f
parente7a552f303c56788d52ca4e46490236845662734 (diff)
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 <[email protected]> Discussion: https://postgr.es/m/[email protected]
-rw-r--r--src/backend/commands/copy.c6
-rw-r--r--src/backend/parser/parse_cte.c7
-rw-r--r--src/test/regress/expected/merge.out14
-rw-r--r--src/test/regress/sql/merge.sql10
4 files changed, 37 insertions, 0 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 3ac731803b..49924e476a 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -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;
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c
index efb4af706e..8fc8658608 100644
--- a/src/backend/parser/parse_cte.c
+++ b/src/backend/parser/parse_cte.c
@@ -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);
diff --git a/src/test/regress/expected/merge.out b/src/test/regress/expected/merge.out
index af670e28e7..729ae2eb06 100644
--- a/src/test/regress/expected/merge.out
+++ b/src/test/regress/expected/merge.out
@@ -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;
diff --git a/src/test/regress/sql/merge.sql b/src/test/regress/sql/merge.sql
index afeb212f3c..e0c450736b 100644
--- a/src/test/regress/sql/merge.sql
+++ b/src/test/regress/sql/merge.sql
@@ -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