From 8fb91e4c830591ee1a663b49c4a263d916ebd390 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 26 Sep 2019 15:10:58 -0700
Subject: [PATCH v1 07/12] WIP: explain: Output hash keys in verbose mode.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/commands/explain.c                | 29 ++++++-
 src/test/regress/expected/join.out            | 82 +++++++++++++++----
 src/test/regress/expected/join_hash.out       | 12 ++-
 src/test/regress/expected/plpgsql.out         |  2 +
 src/test/regress/expected/select_parallel.out |  6 +-
 5 files changed, 109 insertions(+), 22 deletions(-)

diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 2f3bd8a459a..1f613d31376 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -96,7 +96,7 @@ static void show_tablesample(TableSampleClause *tsc, PlanState *planstate,
 							 List *ancestors, ExplainState *es);
 static void show_sort_info(SortState *sortstate, ExplainState *es);
 static void show_agg_info(AggState *aggstate, List *ancestors, ExplainState *es);
-static void show_hash_info(HashState *hashstate, ExplainState *es);
+static void show_hash_info(HashState *hashstate, List *ancestors, ExplainState *es);
 static void show_tidbitmap_info(BitmapHeapScanState *planstate,
 								ExplainState *es);
 static void show_instrumentation_count(const char *qlabel, int which,
@@ -1863,6 +1863,17 @@ ExplainNode(PlanState *planstate, List *ancestors,
 			if (plan->qual)
 				show_instrumentation_count("Rows Removed by Filter", 2,
 										   planstate, es);
+			if (es->verbose)
+			{
+				ListCell *lc1, *lc2;
+
+				forboth(lc1, ((HashJoin *) plan)->hashkeys,
+						lc2, ((HashJoinState *) planstate)->hj_OuterHashKeys)
+				{
+					show_expression(lfirst(lc1), lfirst(lc2), "Outer Hash Key",
+									planstate, ancestors, true, es);
+				}
+			}
 			break;
 		case T_Agg:
 			show_upper_qual(plan->qual, planstate->qual, "Filter", planstate,
@@ -1903,7 +1914,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 								  es);
 			break;
 		case T_Hash:
-			show_hash_info(castNode(HashState, planstate), es);
+			show_hash_info(castNode(HashState, planstate), ancestors, es);
 			break;
 		default:
 			break;
@@ -3087,7 +3098,7 @@ show_agg_info(AggState *aggstate, List *ancestors, ExplainState *es)
  * Show information on hash buckets/batches.
  */
 static void
-show_hash_info(HashState *hashstate, ExplainState *es)
+show_hash_info(HashState *hashstate, List *ancestors, ExplainState *es)
 {
 	HashInstrumentation hinstrument = {0};
 
@@ -3184,6 +3195,18 @@ show_hash_info(HashState *hashstate, ExplainState *es)
 							 spacePeakKb);
 		}
 	}
+
+	if (es->verbose)
+	{
+		ListCell *lc1, *lc2;
+
+		forboth(lc1, ((Hash *) hashstate->ps.plan)->hashkeys,
+				lc2, hashstate->hashkeys)
+		{
+			show_expression(lfirst(lc1), (ExprState *) lfirst(lc2), "Hash Key",
+							&hashstate->ps, ancestors, true, es);
+		}
+	}
 }
 
 /*
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 1ddc4423888..2ba48596622 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -3792,6 +3792,7 @@ select t1.* from
  Hash Left Join
    Project: t1.f1
    Hash Cond: (i8.q2 = i4.f1)
+   Outer Hash Key: i8.q2
    ->  Nested Loop Left Join
          Project: t1.f1, i8.q2
          Join Filter: (t1.f1 = '***'::text)
@@ -3802,24 +3803,29 @@ select t1.* from
                ->  Hash Right Join
                      Project: i8.q2
                      Hash Cond: ((NULL::integer) = i8b1.q2)
+                     Outer Hash Key: (NULL::integer)
                      ->  Hash Join
                            Project: i8.q2, (NULL::integer)
                            Hash Cond: (i8.q1 = i8b2.q1)
+                           Outer Hash Key: i8.q1
                            ->  Seq Scan on public.int8_tbl i8
                                  Output: i8.q1, i8.q2
                            ->  Hash
                                  Output: i8b2.q1, (NULL::integer)
+                                 Hash Key: i8b2.q1
                                  ->  Seq Scan on public.int8_tbl i8b2
                                        Project: i8b2.q1, NULL::integer
                      ->  Hash
                            Output: i8b1.q2
+                           Hash Key: i8b1.q2
                            ->  Seq Scan on public.int8_tbl i8b1
                                  Project: i8b1.q2
    ->  Hash
          Output: i4.f1
+         Hash Key: i4.f1
          ->  Seq Scan on public.int4_tbl i4
                Output: i4.f1
-(30 rows)
+(36 rows)
 
 select t1.* from
   text_tbl t1
@@ -3853,6 +3859,7 @@ select t1.* from
  Hash Left Join
    Project: t1.f1
    Hash Cond: (i8.q2 = i4.f1)
+   Outer Hash Key: i8.q2
    ->  Nested Loop Left Join
          Project: t1.f1, i8.q2
          Join Filter: (t1.f1 = '***'::text)
@@ -3863,9 +3870,11 @@ select t1.* from
                ->  Hash Right Join
                      Project: i8.q2
                      Hash Cond: ((NULL::integer) = i8b1.q2)
+                     Outer Hash Key: (NULL::integer)
                      ->  Hash Right Join
                            Project: i8.q2, (NULL::integer)
                            Hash Cond: (i8b2.q1 = i8.q1)
+                           Outer Hash Key: i8b2.q1
                            ->  Nested Loop
                                  Project: i8b2.q1, NULL::integer
                                  ->  Seq Scan on public.int8_tbl i8b2
@@ -3874,17 +3883,20 @@ select t1.* from
                                        ->  Seq Scan on public.int4_tbl i4b2
                            ->  Hash
                                  Output: i8.q1, i8.q2
+                                 Hash Key: i8.q1
                                  ->  Seq Scan on public.int8_tbl i8
                                        Output: i8.q1, i8.q2
                      ->  Hash
                            Output: i8b1.q2
+                           Hash Key: i8b1.q2
                            ->  Seq Scan on public.int8_tbl i8b1
                                  Project: i8b1.q2
    ->  Hash
          Output: i4.f1
+         Hash Key: i4.f1
          ->  Seq Scan on public.int4_tbl i4
                Output: i4.f1
-(34 rows)
+(40 rows)
 
 select t1.* from
   text_tbl t1
@@ -3919,6 +3931,7 @@ select t1.* from
  Hash Left Join
    Project: t1.f1
    Hash Cond: (i8.q2 = i4.f1)
+   Outer Hash Key: i8.q2
    ->  Nested Loop Left Join
          Project: t1.f1, i8.q2
          Join Filter: (t1.f1 = '***'::text)
@@ -3929,31 +3942,38 @@ select t1.* from
                ->  Hash Right Join
                      Project: i8.q2
                      Hash Cond: ((NULL::integer) = i8b1.q2)
+                     Outer Hash Key: (NULL::integer)
                      ->  Hash Right Join
                            Project: i8.q2, (NULL::integer)
                            Hash Cond: (i8b2.q1 = i8.q1)
+                           Outer Hash Key: i8b2.q1
                            ->  Hash Join
                                  Project: i8b2.q1, NULL::integer
                                  Hash Cond: (i8b2.q1 = i4b2.f1)
+                                 Outer Hash Key: i8b2.q1
                                  ->  Seq Scan on public.int8_tbl i8b2
                                        Output: i8b2.q1, i8b2.q2
                                  ->  Hash
                                        Output: i4b2.f1
+                                       Hash Key: i4b2.f1
                                        ->  Seq Scan on public.int4_tbl i4b2
                                              Output: i4b2.f1
                            ->  Hash
                                  Output: i8.q1, i8.q2
+                                 Hash Key: i8.q1
                                  ->  Seq Scan on public.int8_tbl i8
                                        Output: i8.q1, i8.q2
                      ->  Hash
                            Output: i8b1.q2
+                           Hash Key: i8b1.q2
                            ->  Seq Scan on public.int8_tbl i8b1
                                  Project: i8b1.q2
    ->  Hash
          Output: i4.f1
+         Hash Key: i4.f1
          ->  Seq Scan on public.int4_tbl i4
                Output: i4.f1
-(37 rows)
+(45 rows)
 
 select t1.* from
   text_tbl t1
@@ -4177,6 +4197,7 @@ where ss1.c2 = 0;
    ->  Hash Join
          Project: i41.f1, i42.f1, i8.q1, i8.q2, i43.f1, 42
          Hash Cond: (i41.f1 = i42.f1)
+         Outer Hash Key: i41.f1
          ->  Nested Loop
                Project: i8.q1, i8.q2, i43.f1, i41.f1
                ->  Nested Loop
@@ -4191,13 +4212,14 @@ where ss1.c2 = 0;
                      Output: i41.f1
          ->  Hash
                Output: i42.f1
+               Hash Key: i42.f1
                ->  Seq Scan on public.int4_tbl i42
                      Output: i42.f1
    ->  Limit
          Output: (i41.f1), (i8.q1), (i8.q2), (i42.f1), (i43.f1), ((42))
          ->  Seq Scan on public.text_tbl
                Project: i41.f1, i8.q1, i8.q2, i42.f1, i43.f1, (42)
-(25 rows)
+(27 rows)
 
 select ss2.* from
   int4_tbl i41
@@ -5259,13 +5281,15 @@ select * from int4_tbl i left join
  Hash Left Join
    Project: i.f1, j.f1
    Hash Cond: (i.f1 = j.f1)
+   Outer Hash Key: i.f1
    ->  Seq Scan on public.int4_tbl i
          Output: i.f1
    ->  Hash
          Output: j.f1
+         Hash Key: j.f1
          ->  Seq Scan on public.int2_tbl j
                Output: j.f1
-(9 rows)
+(11 rows)
 
 select * from int4_tbl i left join
   lateral (select * from int2_tbl j where i.f1 = j.f1) k on true;
@@ -5317,14 +5341,16 @@ select * from int4_tbl a,
    ->  Hash Left Join
          Project: b.f1, c.q1, c.q2
          Hash Cond: (b.f1 = c.q1)
+         Outer Hash Key: b.f1
          ->  Seq Scan on public.int4_tbl b
                Output: b.f1
          ->  Hash
                Output: c.q1, c.q2
+               Hash Key: c.q1
                ->  Seq Scan on public.int8_tbl c
                      Output: c.q1, c.q2
                      Filter: (a.f1 = c.q2)
-(14 rows)
+(16 rows)
 
 select * from int4_tbl a,
   lateral (
@@ -5449,26 +5475,30 @@ select * from
    ->  Hash Right Join
          Project: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))
          Hash Cond: (d.q1 = c.q2)
+         Outer Hash Key: d.q1
          ->  Nested Loop
                Project: a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))
                ->  Hash Left Join
                      Project: a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint))
                      Hash Cond: (a.q2 = b.q1)
+                     Outer Hash Key: a.q2
                      ->  Seq Scan on public.int8_tbl a
                            Output: a.q1, a.q2
                      ->  Hash
                            Output: b.q1, (COALESCE(b.q2, '42'::bigint))
+                           Hash Key: b.q1
                            ->  Seq Scan on public.int8_tbl b
                                  Project: b.q1, COALESCE(b.q2, '42'::bigint)
                ->  Seq Scan on public.int8_tbl d
                      Project: d.q1, COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)
          ->  Hash
                Output: c.q1, c.q2
+               Hash Key: c.q2
                ->  Seq Scan on public.int8_tbl c
                      Output: c.q1, c.q2
    ->  Result
          Project: (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))
-(24 rows)
+(28 rows)
 
 -- case that breaks the old ph_may_need optimization
 explain (verbose, costs off)
@@ -5490,11 +5520,13 @@ select c.*,a.*,ss1.q1,ss2.q1,ss3.* from
    ->  Hash Right Join
          Project: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2))
          Hash Cond: (d.q1 = c.q2)
+         Outer Hash Key: d.q1
          ->  Nested Loop
                Project: a.q1, a.q2, b.q1, d.q1, (COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2))
                ->  Hash Right Join
                      Project: a.q1, a.q2, b.q1, (COALESCE(b.q2, (b2.f1)::bigint))
                      Hash Cond: (b.q1 = a.q2)
+                     Outer Hash Key: b.q1
                      ->  Nested Loop
                            Project: b.q1, COALESCE(b.q2, (b2.f1)::bigint)
                            Join Filter: (b.q1 < b2.f1)
@@ -5506,19 +5538,21 @@ select c.*,a.*,ss1.q1,ss2.q1,ss3.* from
                                        Output: b2.f1
                      ->  Hash
                            Output: a.q1, a.q2
+                           Hash Key: a.q2
                            ->  Seq Scan on public.int8_tbl a
                                  Output: a.q1, a.q2
                ->  Seq Scan on public.int8_tbl d
                      Project: d.q1, COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)
          ->  Hash
                Output: c.q1, c.q2
+               Hash Key: c.q2
                ->  Seq Scan on public.int8_tbl c
                      Output: c.q1, c.q2
    ->  Materialize
          Output: i.f1
          ->  Seq Scan on public.int4_tbl i
                Output: i.f1
-(34 rows)
+(38 rows)
 
 -- check processing of postponed quals (bug #9041)
 explain (verbose, costs off)
@@ -5791,10 +5825,12 @@ select t1.b, ss.phv from join_ut1 t1 left join lateral
          ->  Hash Join
                Project: t2.a, LEAST(t1.a, t2.a, t3.a)
                Hash Cond: (t3.b = t2.a)
+               Outer Hash Key: t3.b
                ->  Seq Scan on public.join_ut1 t3
                      Output: t3.a, t3.b, t3.c
                ->  Hash
                      Output: t2.a
+                     Hash Key: t2.a
                      ->  Append
                            ->  Seq Scan on public.join_pt1p1p1 t2
                                  Project: t2.a
@@ -5802,7 +5838,7 @@ select t1.b, ss.phv from join_ut1 t1 left join lateral
                            ->  Seq Scan on public.join_pt1p2 t2_1
                                  Project: t2_1.a
                                  Filter: (t1.a = t2_1.a)
-(21 rows)
+(23 rows)
 
 select t1.b, ss.phv from join_ut1 t1 left join lateral
               (select t2.a as t2a, t3.a t3a, least(t1.a, t2.a, t3.a) phv
@@ -5872,13 +5908,15 @@ select * from j1 inner join j2 on j1.id = j2.id;
    Project: j1.id, j2.id
    Inner Unique: true
    Hash Cond: (j1.id = j2.id)
+   Outer Hash Key: j1.id
    ->  Seq Scan on public.j1
          Output: j1.id
    ->  Hash
          Output: j2.id
+         Hash Key: j2.id
          ->  Seq Scan on public.j2
                Output: j2.id
-(10 rows)
+(12 rows)
 
 -- ensure join is not unique when not an equi-join
 explain (verbose, costs off)
@@ -5905,13 +5943,15 @@ select * from j1 inner join j3 on j1.id = j3.id;
    Project: j1.id, j3.id
    Inner Unique: true
    Hash Cond: (j3.id = j1.id)
+   Outer Hash Key: j3.id
    ->  Seq Scan on public.j3
          Output: j3.id
    ->  Hash
          Output: j1.id
+         Hash Key: j1.id
          ->  Seq Scan on public.j1
                Output: j1.id
-(10 rows)
+(12 rows)
 
 -- ensure left join is marked as unique
 explain (verbose, costs off)
@@ -5922,13 +5962,15 @@ select * from j1 left join j2 on j1.id = j2.id;
    Project: j1.id, j2.id
    Inner Unique: true
    Hash Cond: (j1.id = j2.id)
+   Outer Hash Key: j1.id
    ->  Seq Scan on public.j1
          Output: j1.id
    ->  Hash
          Output: j2.id
+         Hash Key: j2.id
          ->  Seq Scan on public.j2
                Output: j2.id
-(10 rows)
+(12 rows)
 
 -- ensure right join is marked as unique
 explain (verbose, costs off)
@@ -5939,13 +5981,15 @@ select * from j1 right join j2 on j1.id = j2.id;
    Project: j1.id, j2.id
    Inner Unique: true
    Hash Cond: (j2.id = j1.id)
+   Outer Hash Key: j2.id
    ->  Seq Scan on public.j2
          Output: j2.id
    ->  Hash
          Output: j1.id
+         Hash Key: j1.id
          ->  Seq Scan on public.j1
                Output: j1.id
-(10 rows)
+(12 rows)
 
 -- ensure full join is marked as unique
 explain (verbose, costs off)
@@ -5956,13 +6000,15 @@ select * from j1 full join j2 on j1.id = j2.id;
    Project: j1.id, j2.id
    Inner Unique: true
    Hash Cond: (j1.id = j2.id)
+   Outer Hash Key: j1.id
    ->  Seq Scan on public.j1
          Output: j1.id
    ->  Hash
          Output: j2.id
+         Hash Key: j2.id
          ->  Seq Scan on public.j2
                Output: j2.id
-(10 rows)
+(12 rows)
 
 -- a clauseless (cross) join can't be unique
 explain (verbose, costs off)
@@ -5988,13 +6034,15 @@ select * from j1 natural join j2;
    Project: j1.id
    Inner Unique: true
    Hash Cond: (j1.id = j2.id)
+   Outer Hash Key: j1.id
    ->  Seq Scan on public.j1
          Output: j1.id
    ->  Hash
          Output: j2.id
+         Hash Key: j2.id
          ->  Seq Scan on public.j2
                Output: j2.id
-(10 rows)
+(12 rows)
 
 -- ensure a distinct clause allows the inner to become unique
 explain (verbose, costs off)
@@ -6170,6 +6218,7 @@ where exists (select 1 from tenk1 t3
    ->  Hash Join
          Project: t1.unique1, t3.tenthous
          Hash Cond: (t3.thousand = t1.unique1)
+         Outer Hash Key: t3.thousand
          ->  HashAggregate
                Project: t3.thousand, t3.tenthous
                Phase 0 using strategy "Hash":
@@ -6178,13 +6227,14 @@ where exists (select 1 from tenk1 t3
                      Output: t3.thousand, t3.tenthous
          ->  Hash
                Output: t1.unique1
+               Hash Key: t1.unique1
                ->  Index Only Scan using onek_unique1 on public.onek t1
                      Output: t1.unique1
                      Index Cond: (t1.unique1 < 1)
    ->  Index Only Scan using tenk1_hundred on public.tenk1 t2
          Output: t2.hundred
          Index Cond: (t2.hundred = t3.tenthous)
-(19 rows)
+(21 rows)
 
 -- ... unless it actually is unique
 create table j3 as select unique1, tenthous from onek;
diff --git a/src/test/regress/expected/join_hash.out b/src/test/regress/expected/join_hash.out
index 4e405ebbd76..379b3b1566e 100644
--- a/src/test/regress/expected/join_hash.out
+++ b/src/test/regress/expected/join_hash.out
@@ -919,6 +919,8 @@ WHERE
    Project: hjtest_1.a, hjtest_2.a, (hjtest_1.tableoid)::regclass, (hjtest_2.tableoid)::regclass
    Hash Cond: ((hjtest_1.id = (SubPlan 1)) AND ((SubPlan 2) = (SubPlan 3)))
    Join Filter: (hjtest_1.a <> hjtest_2.b)
+   Outer Hash Key: hjtest_1.id
+   Outer Hash Key: (SubPlan 2)
    ->  Seq Scan on public.hjtest_1
          Project: hjtest_1.a, hjtest_1.tableoid, hjtest_1.id, hjtest_1.b
          Filter: ((SubPlan 4) < 50)
@@ -927,6 +929,8 @@ WHERE
                  Project: (hjtest_1.b * 5)
    ->  Hash
          Output: hjtest_2.a, hjtest_2.tableoid, hjtest_2.id, hjtest_2.c, hjtest_2.b
+         Hash Key: (SubPlan 1)
+         Hash Key: (SubPlan 3)
          ->  Seq Scan on public.hjtest_2
                Project: hjtest_2.a, hjtest_2.tableoid, hjtest_2.id, hjtest_2.c, hjtest_2.b
                Filter: ((SubPlan 5) < 55)
@@ -943,7 +947,7 @@ WHERE
    SubPlan 2
      ->  Result
            Project: (hjtest_1.b * 5)
-(28 rows)
+(32 rows)
 
 SELECT hjtest_1.a a1, hjtest_2.a a2,hjtest_1.tableoid::regclass t1, hjtest_2.tableoid::regclass t2
 FROM hjtest_1, hjtest_2
@@ -973,6 +977,8 @@ WHERE
    Project: hjtest_1.a, hjtest_2.a, (hjtest_1.tableoid)::regclass, (hjtest_2.tableoid)::regclass
    Hash Cond: (((SubPlan 1) = hjtest_1.id) AND ((SubPlan 3) = (SubPlan 2)))
    Join Filter: (hjtest_1.a <> hjtest_2.b)
+   Outer Hash Key: (SubPlan 1)
+   Outer Hash Key: (SubPlan 3)
    ->  Seq Scan on public.hjtest_2
          Project: hjtest_2.a, hjtest_2.tableoid, hjtest_2.id, hjtest_2.c, hjtest_2.b
          Filter: ((SubPlan 5) < 55)
@@ -981,6 +987,8 @@ WHERE
                  Project: (hjtest_2.c * 5)
    ->  Hash
          Output: hjtest_1.a, hjtest_1.tableoid, hjtest_1.id, hjtest_1.b
+         Hash Key: hjtest_1.id
+         Hash Key: (SubPlan 2)
          ->  Seq Scan on public.hjtest_1
                Project: hjtest_1.a, hjtest_1.tableoid, hjtest_1.id, hjtest_1.b
                Filter: ((SubPlan 4) < 50)
@@ -997,7 +1005,7 @@ WHERE
    SubPlan 3
      ->  Result
            Project: (hjtest_2.c * 5)
-(28 rows)
+(32 rows)
 
 SELECT hjtest_1.a a1, hjtest_2.a a2,hjtest_1.tableoid::regclass t1, hjtest_2.tableoid::regclass t2
 FROM hjtest_2, hjtest_1
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index 92421090755..9d06f8467b2 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -5209,10 +5209,12 @@ UPDATE transition_table_base
 INFO:  Hash Full Join
   Project: COALESCE(ot.id, nt.id), ot.val, nt.val
   Hash Cond: (ot.id = nt.id)
+  Outer Hash Key: ot.id
   ->  Named Tuplestore Scan
         Output: ot.id, ot.val
   ->  Hash
         Output: nt.id, nt.val
+        Hash Key: nt.id
         ->  Named Tuplestore Scan
               Output: nt.id, nt.val
 
diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out
index 1338857e5f6..ce35a137ea5 100644
--- a/src/test/regress/expected/select_parallel.out
+++ b/src/test/regress/expected/select_parallel.out
@@ -985,6 +985,8 @@ explain (costs off, verbose)
      All Group
    ->  Hash Semi Join
          Hash Cond: ((a.unique1 = b.unique1) AND (a.two = (row_number() OVER (?))))
+         Outer Hash Key: a.unique1
+         Outer Hash Key: a.two
          ->  Gather
                Output: a.unique1, a.two
                Workers Planned: 4
@@ -992,6 +994,8 @@ explain (costs off, verbose)
                      Project: a.unique1, a.two
          ->  Hash
                Output: b.unique1, (row_number() OVER (?))
+               Hash Key: b.unique1
+               Hash Key: (row_number() OVER (?))
                ->  WindowAgg
                      Project: b.unique1, row_number() OVER (?)
                      ->  Gather
@@ -999,7 +1003,7 @@ explain (costs off, verbose)
                            Workers Planned: 4
                            ->  Parallel Index Only Scan using tenk1_unique1 on public.tenk1 b
                                  Output: b.unique1
-(21 rows)
+(25 rows)
 
 -- LIMIT/OFFSET within sub-selects can't be pushed to workers.
 explain (costs off)
-- 
2.23.0.162.gf1d4a28250

