From 458feed315f7d1f7c1f938ffda7d41fa05303daa Mon Sep 17 00:00:00 2001 From: Hironobu Suzuki Date: Fri, 6 Nov 2026 17:51:13 +0900 Subject: [PATCH v1] Fix EXPLAIN output of MERGE on partitioned tables When a ModifyTable node has multiple target relations, such as a partitioned table, show_modifytable_info() opens a "Target Tables" group but closed it only after emitting the ON CONFLICT and MERGE properties. For MERGE, that includes the "Tuples Inserted", "Tuples Updated", "Tuples Deleted" and "Tuples Skipped" counters shown by EXPLAIN ANALYZE. In the structured formats those properties therefore ended up inside the "Target Tables" list. In JSON this is invalid output (a bare "key": value pair inside an array); in YAML and XML the elements were nested under the wrong parent. Text format was not affected. Fix by closing the group right after the loop over the target relations, so that these properties are emitted as siblings of "Target Tables". Backpatch-through: 15 --- src/backend/commands/explain.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 4b1ad4227ac..f534d1f63ff 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -4876,6 +4876,13 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors, } } + /* + * Close the "Target Tables" group before emitting the properties below; + * they belong to the ModifyTable node itself, not to its target list. + */ + if (labeltargets) + ExplainCloseGroup("Target Tables", "Target Tables", false, es); + /* Gather names of ON CONFLICT arbiter indexes */ foreach(lst, node->arbiterIndexes) { @@ -4999,9 +5006,6 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors, } } } - - if (labeltargets) - ExplainCloseGroup("Target Tables", "Target Tables", false, es); } /* -- 2.39.5 (Apple Git-154)