Fix PG community merge tests (pgmerge)

pgmerge.sql:
This is a clone of the PostgreSQL community's merge.sql test, adapted
for Citus by converting tables into Citus local tables. The expectation
is that any MERGE syntax that works on PostgreSQL should work on Citus
as-is, utilizing our MERGE deparser.

Diffs, which primarily seem to stem fromtwo major features in MERGE introduced by the community:

RETURNING support for MERGE
MERGE support for updatable views

Currently, Citus code does not support these features. For now, I have
implemented changes to catch these cases and raise clean exceptions.
With these adjustments, the pgmerge tests now pass without diffs.
fix-pgmerge
Teja Mupparti 2024-12-04 20:02:32 -08:00
parent 6be064927c
commit 29858d70f9
5 changed files with 2216 additions and 2 deletions

View File

@ -346,6 +346,9 @@ static LocalCopyStatus GetLocalCopyStatus(void);
static bool ShardIntervalListHasLocalPlacements(List *shardIntervalList);
static void LogLocalCopyToRelationExecution(uint64 shardId);
static void LogLocalCopyToFileExecution(uint64 shardId);
#if PG_VERSION_NUM >= PG_VERSION_15
static void ErrorIfMergeInCopy(CopyStmt *copyStatement);
#endif
/* exports for SQL callable functions */
@ -2828,6 +2831,25 @@ CopyStatementHasFormat(CopyStmt *copyStatement, char *formatName)
}
#if PG_VERSION_NUM >= PG_VERSION_15
/*
* ErrorIfMergeInCopy Raises an exception if the MERGE is called in the COPY.
*/
static void
ErrorIfMergeInCopy(CopyStmt *copyStatement)
{
if (!copyStatement->relation && (IsA(copyStatement->query, MergeStmt)))
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("MERGE not supported in COPY")));
}
}
#endif
/*
* ProcessCopyStmt handles Citus specific concerns for COPY like supporting
* COPYing from distributed tables and preventing unsupported actions. The
@ -2838,6 +2860,10 @@ Node *
ProcessCopyStmt(CopyStmt *copyStatement, QueryCompletion *completionTag, const
char *queryString)
{
#if PG_VERSION_NUM >= PG_VERSION_15
ErrorIfMergeInCopy(copyStatement);
#endif
/*
* Handle special COPY "resultid" FROM STDIN WITH (format result) commands
* for sending intermediate results to workers.

View File

@ -97,6 +97,7 @@ static DistributedPlan * CreateNonPushableMergePlan(Oid targetRelationId, uint64
plannerRestrictionContext,
ParamListInfo boundParams);
static char * MergeCommandResultIdPrefix(uint64 planId);
static void ErrorIfMergeHasReturningList(Query *query);
#endif
@ -949,9 +950,24 @@ ConvertSourceRTEIntoSubquery(Query *mergeQuery, RangeTblEntry *sourceRte,
}
/*
* ErrorIfMergeHasReturningList raises an exception if the MERGE
* has a RETURNING clause.
*/
static void
ErrorIfMergeHasReturningList(Query *query)
{
if (query->returningList)
{
ereport(ERROR, (errmsg("MERGE with RETURNING is not yet supported")));
}
}
/*
* ErrorIfMergeNotSupported Checks for conditions that are not supported in either
* the routable or repartition strategies. It checks for
* - MERGE with a RETURNING clause
* - Supported table types and their combinations
* - Check the target lists and quals of both the query and merge actions
* - Supported CTEs
@ -959,6 +975,7 @@ ConvertSourceRTEIntoSubquery(Query *mergeQuery, RangeTblEntry *sourceRte,
static void
ErrorIfMergeNotSupported(Query *query, Oid targetRelationId, List *rangeTableList)
{
ErrorIfMergeHasReturningList(query);
ErrorIfMergeHasUnsupportedTables(targetRelationId, rangeTableList);
ErrorIfMergeQueryQualAndTargetListNotSupported(targetRelationId, query);
ErrorIfUnsupportedCTEs(query);

View File

@ -174,9 +174,21 @@ COPY (
WHEN MATCHED THEN DELETE
) TO stdout;
ERROR: MERGE not supported in COPY
-- used in a CTE with RETURNING
WITH foo AS (
MERGE INTO target USING source ON (true)
WHEN MATCHED THEN DELETE RETURNING target.*
) SELECT * FROM foo;
ERROR: syntax error at or near "RETURNING"
-- used in COPY with RETURNING
COPY (
MERGE INTO target USING source ON (true)
WHEN MATCHED THEN DELETE RETURNING target.*
) TO stdout;
ERROR: syntax error at or near "RETURNING"
-- unsupported relation types
-- view
CREATE VIEW tv AS SELECT * FROM target;
CREATE VIEW tv AS SELECT count(tid) AS tid FROM target;
MERGE INTO tv t
USING source s
ON t.tid = s.sid

File diff suppressed because it is too large Load Diff

View File

@ -126,10 +126,20 @@ COPY (
MERGE INTO target USING source ON (true)
WHEN MATCHED THEN DELETE
) TO stdout;
-- used in a CTE with RETURNING
WITH foo AS (
MERGE INTO target USING source ON (true)
WHEN MATCHED THEN DELETE RETURNING target.*
) SELECT * FROM foo;
-- used in COPY with RETURNING
COPY (
MERGE INTO target USING source ON (true)
WHEN MATCHED THEN DELETE RETURNING target.*
) TO stdout;
-- unsupported relation types
-- view
CREATE VIEW tv AS SELECT * FROM target;
CREATE VIEW tv AS SELECT count(tid) AS tid FROM target;
MERGE INTO tv t
USING source s
ON t.tid = s.sid