From 2aab5cf3e3486845039aeaf536cf7a6e728fa266 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Sat, 15 Feb 2020 14:13:06 -0600
Subject: [PATCH v4 3/7] Gross hack to put hash stats of subplans in the
 right(?) place

---
 src/backend/commands/explain.c                | 46 +++++++++++++++------------
 src/test/regress/expected/select_parallel.out |  4 +--
 src/test/regress/expected/subselect.out       |  8 ++---
 3 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index e262108..67a9840 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -66,7 +66,7 @@ static double elapsed_time(instr_time *starttime);
 static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used);
 static void ExplainNode(PlanState *planstate, List *ancestors,
 						const char *relationship, const char *plan_name,
-						ExplainState *es);
+						ExplainState *es, SubPlanState *subplanstate);
 static void show_plan_tlist(PlanState *planstate, List *ancestors,
 							ExplainState *es);
 static void show_expression(Node *node, const char *qlabel,
@@ -718,7 +718,7 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
 		ps = outerPlanState(ps);
 		es->hide_workers = true;
 	}
-	ExplainNode(ps, NIL, NULL, NULL, es);
+	ExplainNode(ps, NIL, NULL, NULL, es, NULL);
 
 	/*
 	 * If requested, include information about GUC parameters with values that
@@ -1080,7 +1080,7 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
 static void
 ExplainNode(PlanState *planstate, List *ancestors,
 			const char *relationship, const char *plan_name,
-			ExplainState *es)
+			ExplainState *es, SubPlanState *subplanstate)
 {
 	Plan	   *plan = planstate->plan;
 	const char *pname;			/* node type name for text output */
@@ -1337,6 +1337,16 @@ ExplainNode(PlanState *planstate, List *ancestors,
 			ExplainIndentText(es);
 			appendStringInfo(es->str, "%s\n", plan_name);
 			es->indent++;
+
+			Assert(subplanstate != NULL);
+			/* Show hash stats for hashed subplan */
+			if (subplanstate->hashtable)
+				show_tuplehash_info(&subplanstate->hashtable->instrument, es);
+			if (subplanstate->hashnulls) {
+				ExplainIndentText(es);
+				appendStringInfoString(es->str, "Null hashtable: ");
+				show_tuplehash_info(&subplanstate->hashnulls->instrument, es);
+			}
 		}
 		if (es->indent)
 		{
@@ -1365,6 +1375,13 @@ ExplainNode(PlanState *planstate, List *ancestors,
 		if (custom_name)
 			ExplainPropertyText("Custom Plan Provider", custom_name, es);
 		ExplainPropertyBool("Parallel Aware", plan->parallel_aware, es);
+		if (subplanstate && subplanstate->hashtable)
+			show_tuplehash_info(&subplanstate->hashtable->instrument, es);
+		if (subplanstate && subplanstate->hashnulls) {
+			ExplainOpenGroup("Null hashtable", "Null hashtable", true, es);
+			show_tuplehash_info(&subplanstate->hashnulls->instrument, es);
+			ExplainCloseGroup("Null hashtable", "Null hashtable", true, es);
+		}
 	}
 
 	switch (nodeTag(plan))
@@ -2037,12 +2054,12 @@ ExplainNode(PlanState *planstate, List *ancestors,
 	/* lefttree */
 	if (outerPlanState(planstate))
 		ExplainNode(outerPlanState(planstate), ancestors,
-					"Outer", NULL, es);
+					"Outer", NULL, es, NULL);
 
 	/* righttree */
 	if (innerPlanState(planstate))
 		ExplainNode(innerPlanState(planstate), ancestors,
-					"Inner", NULL, es);
+					"Inner", NULL, es, NULL);
 
 	/* special child plans */
 	switch (nodeTag(plan))
@@ -2074,7 +2091,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 			break;
 		case T_SubqueryScan:
 			ExplainNode(((SubqueryScanState *) planstate)->subplan, ancestors,
-						"Subquery", NULL, es);
+						"Subquery", NULL, es, NULL);
 			break;
 		case T_CustomScan:
 			ExplainCustomChildren((CustomScanState *) planstate,
@@ -3473,7 +3490,7 @@ ExplainMemberNodes(PlanState **planstates, int nplans,
 
 	for (j = 0; j < nplans; j++)
 		ExplainNode(planstates[j], ancestors,
-					"Member", NULL, es);
+					"Member", NULL, es, NULL);
 }
 
 /*
@@ -3531,18 +3548,7 @@ ExplainSubPlans(List *plans, List *ancestors,
 		ancestors = lcons(sp, ancestors);
 
 		ExplainNode(sps->planstate, ancestors,
-					relationship, sp->plan_name, es);
-		if (sps->hashtable)
-			show_tuplehash_info(&sps->hashtable->instrument, es);
-		if (sps->hashnulls) {
-			ExplainOpenGroup("Null hashtable", "Null hashtable", true, es);
-			if (es->format == EXPLAIN_FORMAT_TEXT) {
-				ExplainIndentText(es);
-				appendStringInfoString(es->str, "Null hashtable: ");
-			}
-			show_tuplehash_info(&sps->hashnulls->instrument, es);
-			ExplainCloseGroup("Null hashtable", "Null hashtable", true, es);
-		}
+					relationship, sp->plan_name, es, sps);
 
 		ancestors = list_delete_first(ancestors);
 	}
@@ -3559,7 +3565,7 @@ ExplainCustomChildren(CustomScanState *css, List *ancestors, ExplainState *es)
 	(list_length(css->custom_ps) != 1 ? "children" : "child");
 
 	foreach(cell, css->custom_ps)
-		ExplainNode((PlanState *) lfirst(cell), ancestors, label, NULL, es);
+		ExplainNode((PlanState *) lfirst(cell), ancestors, label, NULL, es, NULL);
 }
 
 /*
diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out
index 783c1da..bc270e0 100644
--- a/src/test/regress/expected/select_parallel.out
+++ b/src/test/regress/expected/select_parallel.out
@@ -303,11 +303,11 @@ explain (costs off, timing off, summary off, analyze)
                ->  Parallel Seq Scan on tenk1 (actual rows=2000 loops=5)
                      Filter: (NOT (hashed SubPlan 1))
                      SubPlan 1
+                       Buckets: 16384
+                       Null hashtable: Buckets: 1024
                        ->  Seq Scan on tenk2 (actual rows=8990 loops=5)
                              Filter: (thousand > 100)
                              Rows Removed by Filter: 1010
-                     Buckets: 16384
-                     Null hashtable: Buckets: 1024
 (13 rows)
 
 select count(*) from tenk1 where (two, four) not in
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index 410daa0..a6b9595 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -788,11 +788,11 @@ select 'foo'::text in (select 'bar'::name union all select 'bar'::name);
 ----------------------------------------------
  Result (actual rows=1 loops=1)
    SubPlan 1
+     Buckets: 4 (originally 2)
+     Null hashtable: Buckets: 2
      ->  Append (actual rows=2 loops=1)
            ->  Result (actual rows=1 loops=1)
            ->  Result (actual rows=1 loops=1)
-   Buckets: 4 (originally 2)
-   Null hashtable: Buckets: 2
 (7 rows)
 
 select 'foo'::text in (select 'bar'::name union all select 'bar'::name);
@@ -999,10 +999,10 @@ select * from int4_tbl where
    ->  Seq Scan on int4_tbl (actual rows=5 loops=1)
    ->  Seq Scan on tenk1 b (actual rows=8000 loops=5)
    SubPlan 1
+     Buckets: 16384
+     Null hashtable: Buckets: 2
      ->  Index Only Scan using tenk1_unique1 on tenk1 a (actual rows=10000 loops=1)
            Heap Fetches: 0
-   Buckets: 16384
-   Null hashtable: Buckets: 2
 (10 rows)
 
 select * from int4_tbl where
-- 
2.7.4

