Playing around with MERGE some more, I noticed that the command tag row count is wrong if it does a cross-partition update:
CREATE TABLE target (a int, b int) PARTITION BY LIST (b); CREATE TABLE target_p1 PARTITION OF target FOR VALUES IN (1); CREATE TABLE target_p2 PARTITION OF target FOR VALUES IN (2); INSERT INTO target VALUES (1,1); MERGE INTO target t USING (VALUES (1)) v(a) ON t.a = v.a WHEN MATCHED THEN UPDATE SET b = 2; which returns "MERGE 2" when only 1 row was updated, because ExecUpdateAct() will update estate->es_processed for a cross-partition update (but not for a normal update), and then ExecMergeMatched() will update it again. I think the best fix is to have ExecMergeMatched() pass canSetTag = false to ExecUpdateAct(), so that ExecMergeMatched() takes responsibility for updating estate->es_processed in all cases. Regards, Dean
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c new file mode 100644 index a94d7f8..6f0543a --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -2878,7 +2878,7 @@ lmerge_matched: } ExecUpdatePrepareSlot(resultRelInfo, newslot, context->estate); result = ExecUpdateAct(context, resultRelInfo, tupleid, NULL, - newslot, mtstate->canSetTag, &updateCxt); + newslot, false, &updateCxt); if (result == TM_Ok && updateCxt.updated) { ExecUpdateEpilogue(context, &updateCxt, resultRelInfo,