From 12e423e21d8ef47d95a099c12f625f6d191eaf92 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Wed, 18 May 2022 21:20:49 +0200
Subject: [PATCH] Fix EXPLAIN MERGE output when no tuples are processed

An 'else' clause was misplaced in commit 598ac10be1c2, making zero-rows
output look a bit silly.  Add a test case for it.

Pointed out by Tom Lane.

Discussion: https://postgr.es/m/21030.1652893083@sss.pgh.pa.us
---
 src/backend/commands/explain.c      | 27 +++++++++++++++------------
 src/test/regress/expected/merge.out | 20 +++++++++++++++++++-
 src/test/regress/sql/merge.sql      |  8 +++++++-
 3 files changed, 41 insertions(+), 14 deletions(-)

diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 2de546f16eb..5d1f7089daf 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4068,19 +4068,22 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
 			skipped_path = total - insert_path - update_path - delete_path;
 			Assert(skipped_path >= 0);
 
-			if (es->format == EXPLAIN_FORMAT_TEXT && total > 0)
+			if (es->format == EXPLAIN_FORMAT_TEXT)
 			{
-				ExplainIndentText(es);
-				appendStringInfoString(es->str, "Tuples:");
-				if (insert_path > 0)
-					appendStringInfo(es->str, " inserted=%.0f", insert_path);
-				if (update_path > 0)
-					appendStringInfo(es->str, " updated=%.0f", update_path);
-				if (delete_path > 0)
-					appendStringInfo(es->str, " deleted=%.0f", delete_path);
-				if (skipped_path > 0)
-					appendStringInfo(es->str, " skipped=%.0f", skipped_path);
-				appendStringInfoChar(es->str, '\n');
+				if (total > 0)
+				{
+					ExplainIndentText(es);
+					appendStringInfoString(es->str, "Tuples:");
+					if (insert_path > 0)
+						appendStringInfo(es->str, " inserted=%.0f", insert_path);
+					if (update_path > 0)
+						appendStringInfo(es->str, " updated=%.0f", update_path);
+					if (delete_path > 0)
+						appendStringInfo(es->str, " deleted=%.0f", delete_path);
+					if (skipped_path > 0)
+						appendStringInfo(es->str, " skipped=%.0f", skipped_path);
+					appendStringInfoChar(es->str, '\n');
+				}
 			}
 			else
 			{
diff --git a/src/test/regress/expected/merge.out b/src/test/regress/expected/merge.out
index 09d11ba7421..af670e28e7f 100644
--- a/src/test/regress/expected/merge.out
+++ b/src/test/regress/expected/merge.out
@@ -1316,7 +1316,7 @@ BEGIN
         EXECUTE 'explain (analyze, timing off, summary off, costs off) ' ||
 		  query
     LOOP
-        ln := regexp_replace(ln, 'Memory: \S*',  'Memory: xxx');
+        ln := regexp_replace(ln, '(Memory( Usage)?|Buckets|Batches): \S*',  '\1: xxx', 'g');
         RETURN NEXT ln;
     END LOOP;
 END;
@@ -1432,6 +1432,24 @@ WHEN NOT MATCHED AND s.a < 20 THEN
                ->  Seq Scan on ex_mtarget t (actual rows=49 loops=1)
 (12 rows)
 
+-- nothing
+SELECT explain_merge('
+MERGE INTO ex_mtarget t USING ex_msource s ON t.a = s.a AND t.a < -1000
+WHEN MATCHED AND t.a < 10 THEN
+	DO NOTHING');
+                           explain_merge                            
+--------------------------------------------------------------------
+ Merge on ex_mtarget t (actual rows=0 loops=1)
+   ->  Hash Join (actual rows=0 loops=1)
+         Hash Cond: (s.a = t.a)
+         ->  Seq Scan on ex_msource s (actual rows=1 loops=1)
+         ->  Hash (actual rows=0 loops=1)
+               Buckets: xxx  Batches: xxx  Memory Usage: xxx
+               ->  Seq Scan on ex_mtarget t (actual rows=0 loops=1)
+                     Filter: (a < '-1000'::integer)
+                     Rows Removed by Filter: 54
+(9 rows)
+
 DROP TABLE ex_msource, ex_mtarget;
 DROP FUNCTION explain_merge(text);
 -- Subqueries
diff --git a/src/test/regress/sql/merge.sql b/src/test/regress/sql/merge.sql
index 8815e0cc498..afeb212f3c8 100644
--- a/src/test/regress/sql/merge.sql
+++ b/src/test/regress/sql/merge.sql
@@ -878,7 +878,7 @@ BEGIN
         EXECUTE 'explain (analyze, timing off, summary off, costs off) ' ||
 		  query
     LOOP
-        ln := regexp_replace(ln, 'Memory: \S*',  'Memory: xxx');
+        ln := regexp_replace(ln, '(Memory( Usage)?|Buckets|Batches): \S*',  '\1: xxx', 'g');
         RETURN NEXT ln;
     END LOOP;
 END;
@@ -920,6 +920,12 @@ WHEN MATCHED AND t.a >= 30 AND t.a <= 40 THEN
 WHEN NOT MATCHED AND s.a < 20 THEN
 	INSERT VALUES (a, b)');
 
+-- nothing
+SELECT explain_merge('
+MERGE INTO ex_mtarget t USING ex_msource s ON t.a = s.a AND t.a < -1000
+WHEN MATCHED AND t.a < 10 THEN
+	DO NOTHING');
+
 DROP TABLE ex_msource, ex_mtarget;
 DROP FUNCTION explain_merge(text);