From 0c8647a7ad5280068a79ef99d5a350fd7e6ee1ed Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Thu, 27 Jun 2019 14:23:42 +0900
Subject: [PATCH v3 3/3] Add multi-relation EC child members in a separate pass

A given multi-relation EC member should be translated when building
the child joinrel that will be able to supply the necessary child
expression.
---
 src/backend/optimizer/path/allpaths.c        |   2 +-
 src/backend/optimizer/path/equivclass.c      |  68 ++++++--
 src/backend/optimizer/util/relnode.c         |  20 ++-
 src/include/optimizer/paths.h                |   3 +-
 src/test/regress/expected/partition_join.out | 243 ++++++++++++++++++++++++++-
 5 files changed, 304 insertions(+), 32 deletions(-)

diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index db3a68a51d..70d0be691e 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1067,7 +1067,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
 		 * paths that produce those sort orderings).
 		 */
 		if (rel->has_eclass_joins || has_useful_pathkeys(root, rel))
-			add_child_rel_equivalences(root, appinfo, rel, childrel);
+			add_child_rel_equivalences(root, &appinfo, 1, rel, childrel);
 		childrel->has_eclass_joins = rel->has_eclass_joins;
 
 		/*
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index ccc07ba9f0..67756ab671 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -1193,6 +1193,20 @@ generate_join_implied_equalities(PlannerInfo *root,
 		result = list_concat(result, sublist);
 	}
 
+	/*
+	 * Remember the EC indexes that were found to refer to this joinrel.  This
+	 * is useful in add_child_rel_equivalences() where we need to add child
+	 * versions of the expressions in each of these ECs.
+	 */
+	if (!bms_is_empty(matching_ecs))
+	{
+		RelOptInfo *joinrel = find_join_rel(root, join_relids);
+
+		if (joinrel)
+			joinrel->eclass_indexes = bms_add_members(joinrel->eclass_indexes,
+													  matching_ecs);
+	}
+
 	return result;
 }
 
@@ -2215,12 +2229,15 @@ match_eclasses_to_foreign_key_col(PlannerInfo *root,
  * Note that this function won't be called at all unless we have at least some
  * reason to believe that the EC members it generates will be useful.
  *
- * parent_rel and child_rel could be derived from appinfo, but since the
+ * parent_rel and child_rel could be derived from appinfos, but since the
  * caller has already computed them, we might as well just pass them in.
+ * Note that parent_rel and child_rel are either BASEREL and OTHER_MEMBER_REL,
+ * respectively, or JOINREL and OTHER_JOINREL.
  */
 void
 add_child_rel_equivalences(PlannerInfo *root,
-						   AppendRelInfo *appinfo,
+						   AppendRelInfo **appinfos,
+						   int		nappinfos,
 						   RelOptInfo *parent_rel,
 						   RelOptInfo *child_rel)
 {
@@ -2231,13 +2248,14 @@ add_child_rel_equivalences(PlannerInfo *root,
 	 * eclass_indexes to avoid searching all of root->eq_classes.
 	 */
 	Assert(root->ec_merging_done);
-	Assert(IS_SIMPLE_REL(parent_rel));
+	Assert(IS_SIMPLE_REL(parent_rel) || IS_JOIN_REL(parent_rel));
 
 	i = -1;
 	while ((i = bms_next_member(parent_rel->eclass_indexes, i)) >= 0)
 	{
 		EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i);
 		int			num_members;
+		EquivalenceMember *first_em;
 
 		/*
 		 * If this EC contains a volatile expression, then generating child
@@ -2247,8 +2265,21 @@ add_child_rel_equivalences(PlannerInfo *root,
 		if (cur_ec->ec_has_volatile)
 			continue;
 
+		first_em = (EquivalenceMember *) linitial(cur_ec->ec_members);
+
+		/*
+		 * Only translate ECs whose members expressions could possibly match
+		 * the parent relation.  That is, for "baserel" parent and child
+		 * relations only consider ECs that contain single-relation members,
+		 * whereas, for "joinrel" parent and child relations, only consider ECs
+		 * that contain multi-relation members.  Note that looking at the first
+		 * EC member is enough, because others should look the same.
+		 */
+		if (bms_membership(parent_rel->relids) != bms_membership(first_em->em_relids))
+			continue;
+
 		/* Sanity check eclass_indexes only contain ECs for parent_rel */
-		Assert(bms_is_subset(child_rel->top_parent_relids, cur_ec->ec_relids));
+		Assert(bms_overlap(child_rel->top_parent_relids, cur_ec->ec_relids));
 
 		/*
 		 * We don't use foreach() here because there's no point in scanning
@@ -2263,34 +2294,31 @@ add_child_rel_equivalences(PlannerInfo *root,
 			if (cur_em->em_is_const)
 				continue;		/* ignore consts here */
 
-			/*
-			 * We consider only original EC members here, not
-			 * already-transformed child members.  Otherwise, if some original
-			 * member expression references more than one appendrel, we'd get
-			 * an O(N^2) explosion of useless derived expressions for
-			 * combinations of children.
-			 */
-			if (cur_em->em_is_child)
-				continue;		/* ignore children here */
-
 			/* Does this member reference child's topmost parent rel? */
-			if (bms_overlap(cur_em->em_relids, child_rel->top_parent_relids))
+			if (bms_is_subset(cur_em->em_relids, child_rel->top_parent_relids))
 			{
 				/* Yes, generate transformed child version */
 				Expr	   *child_expr;
 				Relids		new_relids;
 				Relids		new_nullable_relids;
 
-				if (parent_rel->reloptkind == RELOPT_BASEREL)
+				/*
+				 * If the parent_rel is itself the topmost parent rel, transform
+				 * directly.
+				 */
+				if (parent_rel->reloptkind == RELOPT_BASEREL ||
+					parent_rel->reloptkind == RELOPT_JOINREL)
 				{
 					/* Simple single-level transformation */
 					child_expr = (Expr *)
 						adjust_appendrel_attrs(root,
 											   (Node *) cur_em->em_expr,
-											   1, &appinfo);
+											   nappinfos, appinfos);
 				}
 				else
 				{
+					Assert(parent_rel->reloptkind == RELOPT_OTHER_MEMBER_REL ||
+						   parent_rel->reloptkind == RELOPT_OTHER_JOINREL);
 					/* Must do multi-level transformation */
 					child_expr = (Expr *)
 						adjust_appendrel_attrs_multilevel(root,
@@ -2329,6 +2357,12 @@ add_child_rel_equivalences(PlannerInfo *root,
 
 				/* Record this EC index for the child rel */
 				child_rel->eclass_indexes = bms_add_member(child_rel->eclass_indexes, i);
+
+				/*
+				 * There aren't going to be more expressions to translate in
+				 * the same EC.
+				 */
+				break;
 			}
 		}
 	}
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 3417438108..7cbd9ebe94 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -671,6 +671,9 @@ build_join_rel(PlannerInfo *root,
 	joinrel->nullable_partexprs = NULL;
 	joinrel->partitioned_child_rels = NIL;
 
+	/* Add the joinrel to the PlannerInfo. */
+	add_join_rel(root, joinrel);
+
 	/* Compute information relevant to the foreign relations. */
 	set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
 
@@ -744,9 +747,6 @@ build_join_rel(PlannerInfo *root,
 		is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
 		joinrel->consider_parallel = true;
 
-	/* Add the joinrel to the PlannerInfo. */
-	add_join_rel(root, joinrel);
-
 	/*
 	 * Also, if dynamic-programming join search is active, add the new joinrel
 	 * to the appropriate sublist.  Note: you might think the Assert on number
@@ -864,6 +864,16 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
 														(Node *) parent_joinrel->joininfo,
 														nappinfos,
 														appinfos);
+
+	/*
+	 * If the parent joinrel has pending equivalence classes, so does the
+	 * child.
+	 */
+	if (parent_joinrel->has_eclass_joins ||
+		has_useful_pathkeys(root, parent_joinrel))
+			add_child_rel_equivalences(root, appinfos, nappinfos,
+									   parent_joinrel, joinrel);
+
 	pfree(appinfos);
 
 	/*
@@ -873,10 +883,6 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
 	joinrel->direct_lateral_relids = (Relids) bms_copy(parent_joinrel->direct_lateral_relids);
 	joinrel->lateral_relids = (Relids) bms_copy(parent_joinrel->lateral_relids);
 
-	/*
-	 * If the parent joinrel has pending equivalence classes, so does the
-	 * child.
-	 */
 	joinrel->has_eclass_joins = parent_joinrel->has_eclass_joins;
 
 	/* Is the join between partitions itself partitioned? */
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index 54610b8656..ca507f3ee7 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -147,7 +147,8 @@ extern EquivalenceClass *match_eclasses_to_foreign_key_col(PlannerInfo *root,
 														   ForeignKeyOptInfo *fkinfo,
 														   int colno);
 extern void add_child_rel_equivalences(PlannerInfo *root,
-									   AppendRelInfo *appinfo,
+									   AppendRelInfo **appinfos,
+									   int		nappinfos,
 									   RelOptInfo *parent_rel,
 									   RelOptInfo *child_rel);
 extern List *generate_implied_equalities_for_column(PlannerInfo *root,
diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out
index 3260a345ff..875a90fd62 100644
--- a/src/test/regress/expected/partition_join.out
+++ b/src/test/regress/expected/partition_join.out
@@ -2190,19 +2190,250 @@ SELECT * FROM prt1_n t1 INNER JOIN prt1_n t2 USING (c) FULL JOIN prt1_n t3 USING
 SET enable_hashjoin TO off;
 EXPLAIN (COSTS OFF)
 SELECT * FROM prt1_n t1 FULL JOIN prt1_n t2 USING (c) FULL JOIN prt1_n t3 USING (c) FULL JOIN prt1_n t4 USING (c) ORDER BY c LIMIT 5;
-ERROR:  could not find pathkey item to sort
+                                               QUERY PLAN                                                
+---------------------------------------------------------------------------------------------------------
+ Limit
+   ->  Sort
+         Sort Key: (COALESCE(COALESCE(COALESCE(t1.c, t2.c), t3.c), t4.c))
+         ->  Append
+               ->  Merge Full Join
+                     Merge Cond: (((COALESCE(COALESCE(t1.c, t2.c), t3.c))::text) = (t4.c)::text)
+                     ->  Sort
+                           Sort Key: ((COALESCE(COALESCE(t1.c, t2.c), t3.c))::text)
+                           ->  Merge Full Join
+                                 Merge Cond: (((COALESCE(t1.c, t2.c))::text) = (t3.c)::text)
+                                 ->  Sort
+                                       Sort Key: ((COALESCE(t1.c, t2.c))::text)
+                                       ->  Merge Full Join
+                                             Merge Cond: ((t1.c)::text = (t2.c)::text)
+                                             ->  Sort
+                                                   Sort Key: t1.c
+                                                   ->  Seq Scan on prt1_n_p1 t1
+                                             ->  Sort
+                                                   Sort Key: t2.c
+                                                   ->  Seq Scan on prt1_n_p1 t2
+                                 ->  Sort
+                                       Sort Key: t3.c
+                                       ->  Seq Scan on prt1_n_p1 t3
+                     ->  Sort
+                           Sort Key: t4.c
+                           ->  Seq Scan on prt1_n_p1 t4
+               ->  Merge Full Join
+                     Merge Cond: (((COALESCE(COALESCE(t1_1.c, t2_1.c), t3_1.c))::text) = (t4_1.c)::text)
+                     ->  Sort
+                           Sort Key: ((COALESCE(COALESCE(t1_1.c, t2_1.c), t3_1.c))::text)
+                           ->  Merge Full Join
+                                 Merge Cond: (((COALESCE(t1_1.c, t2_1.c))::text) = (t3_1.c)::text)
+                                 ->  Sort
+                                       Sort Key: ((COALESCE(t1_1.c, t2_1.c))::text)
+                                       ->  Merge Full Join
+                                             Merge Cond: ((t1_1.c)::text = (t2_1.c)::text)
+                                             ->  Sort
+                                                   Sort Key: t1_1.c
+                                                   ->  Seq Scan on prt1_n_p2_1 t1_1
+                                             ->  Sort
+                                                   Sort Key: t2_1.c
+                                                   ->  Seq Scan on prt1_n_p2_1 t2_1
+                                 ->  Sort
+                                       Sort Key: t3_1.c
+                                       ->  Seq Scan on prt1_n_p2_1 t3_1
+                     ->  Sort
+                           Sort Key: t4_1.c
+                           ->  Seq Scan on prt1_n_p2_1 t4_1
+               ->  Merge Full Join
+                     Merge Cond: (((COALESCE(COALESCE(t1_2.c, t2_2.c), t3_2.c))::text) = (t4_2.c)::text)
+                     ->  Sort
+                           Sort Key: ((COALESCE(COALESCE(t1_2.c, t2_2.c), t3_2.c))::text)
+                           ->  Merge Full Join
+                                 Merge Cond: (((COALESCE(t1_2.c, t2_2.c))::text) = (t3_2.c)::text)
+                                 ->  Sort
+                                       Sort Key: ((COALESCE(t1_2.c, t2_2.c))::text)
+                                       ->  Merge Full Join
+                                             Merge Cond: ((t1_2.c)::text = (t2_2.c)::text)
+                                             ->  Sort
+                                                   Sort Key: t1_2.c
+                                                   ->  Seq Scan on prt1_n_p2_2 t1_2
+                                             ->  Sort
+                                                   Sort Key: t2_2.c
+                                                   ->  Seq Scan on prt1_n_p2_2 t2_2
+                                 ->  Sort
+                                       Sort Key: t3_2.c
+                                       ->  Seq Scan on prt1_n_p2_2 t3_2
+                     ->  Sort
+                           Sort Key: t4_2.c
+                           ->  Seq Scan on prt1_n_p2_2 t4_2
+(70 rows)
+
 SELECT * FROM prt1_n t1 FULL JOIN prt1_n t2 USING (c) FULL JOIN prt1_n t3 USING (c) FULL JOIN prt1_n t4 USING (c) ORDER BY c LIMIT 5;
-ERROR:  could not find pathkey item to sort
+  c   | a | b | a | b | a | b | a | b 
+------+---+---+---+---+---+---+---+---
+ 0000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
+ 0002 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2
+ 0004 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4
+ 0006 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6
+ 0008 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8
+(5 rows)
+
 EXPLAIN (COSTS OFF)
 SELECT * FROM prt1_n t1 LEFT JOIN prt1_n t2 USING (c) FULL JOIN prt1_n t3 USING (c) FULL JOIN prt1_n t4 USING (c) ORDER BY c LIMIT 5;
-ERROR:  could not find pathkey item to sort
+                                      QUERY PLAN                                       
+---------------------------------------------------------------------------------------
+ Limit
+   ->  Sort
+         Sort Key: (COALESCE(COALESCE(t1.c, t3.c), t4.c))
+         ->  Append
+               ->  Merge Full Join
+                     Merge Cond: (((COALESCE(t1.c, t3.c))::text) = (t4.c)::text)
+                     ->  Sort
+                           Sort Key: ((COALESCE(t1.c, t3.c))::text)
+                           ->  Merge Full Join
+                                 Merge Cond: ((t1.c)::text = (t3.c)::text)
+                                 ->  Merge Left Join
+                                       Merge Cond: ((t1.c)::text = (t2.c)::text)
+                                       ->  Sort
+                                             Sort Key: t1.c
+                                             ->  Seq Scan on prt1_n_p1 t1
+                                       ->  Sort
+                                             Sort Key: t2.c
+                                             ->  Seq Scan on prt1_n_p1 t2
+                                 ->  Sort
+                                       Sort Key: t3.c
+                                       ->  Seq Scan on prt1_n_p1 t3
+                     ->  Sort
+                           Sort Key: t4.c
+                           ->  Seq Scan on prt1_n_p1 t4
+               ->  Merge Full Join
+                     Merge Cond: (((COALESCE(t1_1.c, t3_1.c))::text) = (t4_1.c)::text)
+                     ->  Sort
+                           Sort Key: ((COALESCE(t1_1.c, t3_1.c))::text)
+                           ->  Merge Full Join
+                                 Merge Cond: ((t1_1.c)::text = (t3_1.c)::text)
+                                 ->  Merge Left Join
+                                       Merge Cond: ((t1_1.c)::text = (t2_1.c)::text)
+                                       ->  Sort
+                                             Sort Key: t1_1.c
+                                             ->  Seq Scan on prt1_n_p2_1 t1_1
+                                       ->  Sort
+                                             Sort Key: t2_1.c
+                                             ->  Seq Scan on prt1_n_p2_1 t2_1
+                                 ->  Sort
+                                       Sort Key: t3_1.c
+                                       ->  Seq Scan on prt1_n_p2_1 t3_1
+                     ->  Sort
+                           Sort Key: t4_1.c
+                           ->  Seq Scan on prt1_n_p2_1 t4_1
+               ->  Merge Full Join
+                     Merge Cond: (((COALESCE(t1_2.c, t3_2.c))::text) = (t4_2.c)::text)
+                     ->  Sort
+                           Sort Key: ((COALESCE(t1_2.c, t3_2.c))::text)
+                           ->  Merge Full Join
+                                 Merge Cond: ((t1_2.c)::text = (t3_2.c)::text)
+                                 ->  Merge Left Join
+                                       Merge Cond: ((t1_2.c)::text = (t2_2.c)::text)
+                                       ->  Sort
+                                             Sort Key: t1_2.c
+                                             ->  Seq Scan on prt1_n_p2_2 t1_2
+                                       ->  Sort
+                                             Sort Key: t2_2.c
+                                             ->  Seq Scan on prt1_n_p2_2 t2_2
+                                 ->  Sort
+                                       Sort Key: t3_2.c
+                                       ->  Seq Scan on prt1_n_p2_2 t3_2
+                     ->  Sort
+                           Sort Key: t4_2.c
+                           ->  Seq Scan on prt1_n_p2_2 t4_2
+(64 rows)
+
 SELECT * FROM prt1_n t1 LEFT JOIN prt1_n t2 USING (c) FULL JOIN prt1_n t3 USING (c) FULL JOIN prt1_n t4 USING (c) ORDER BY c LIMIT 5;
-ERROR:  could not find pathkey item to sort
+  c   | a | b | a | b | a | b | a | b 
+------+---+---+---+---+---+---+---+---
+ 0000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
+ 0002 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2
+ 0004 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4
+ 0006 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6
+ 0008 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8
+(5 rows)
+
 EXPLAIN (COSTS OFF)
 SELECT * FROM prt1_n t1 INNER JOIN prt1_n t2 USING (c) FULL JOIN prt1_n t3 USING (c) FULL JOIN prt1_n t4 USING (c) ORDER BY c LIMIT 5;
-ERROR:  could not find pathkey item to sort
+                                      QUERY PLAN                                       
+---------------------------------------------------------------------------------------
+ Limit
+   ->  Sort
+         Sort Key: (COALESCE(COALESCE(t1.c, t3.c), t4.c))
+         ->  Append
+               ->  Merge Full Join
+                     Merge Cond: (((COALESCE(t1.c, t3.c))::text) = (t4.c)::text)
+                     ->  Sort
+                           Sort Key: ((COALESCE(t1.c, t3.c))::text)
+                           ->  Merge Full Join
+                                 Merge Cond: ((t1.c)::text = (t3.c)::text)
+                                 ->  Merge Join
+                                       Merge Cond: ((t1.c)::text = (t2.c)::text)
+                                       ->  Sort
+                                             Sort Key: t1.c
+                                             ->  Seq Scan on prt1_n_p1 t1
+                                       ->  Sort
+                                             Sort Key: t2.c
+                                             ->  Seq Scan on prt1_n_p1 t2
+                                 ->  Sort
+                                       Sort Key: t3.c
+                                       ->  Seq Scan on prt1_n_p1 t3
+                     ->  Sort
+                           Sort Key: t4.c
+                           ->  Seq Scan on prt1_n_p1 t4
+               ->  Merge Full Join
+                     Merge Cond: (((COALESCE(t1_1.c, t3_1.c))::text) = (t4_1.c)::text)
+                     ->  Sort
+                           Sort Key: ((COALESCE(t1_1.c, t3_1.c))::text)
+                           ->  Merge Full Join
+                                 Merge Cond: ((t1_1.c)::text = (t3_1.c)::text)
+                                 ->  Merge Join
+                                       Merge Cond: ((t1_1.c)::text = (t2_1.c)::text)
+                                       ->  Sort
+                                             Sort Key: t1_1.c
+                                             ->  Seq Scan on prt1_n_p2_1 t1_1
+                                       ->  Sort
+                                             Sort Key: t2_1.c
+                                             ->  Seq Scan on prt1_n_p2_1 t2_1
+                                 ->  Sort
+                                       Sort Key: t3_1.c
+                                       ->  Seq Scan on prt1_n_p2_1 t3_1
+                     ->  Sort
+                           Sort Key: t4_1.c
+                           ->  Seq Scan on prt1_n_p2_1 t4_1
+               ->  Merge Full Join
+                     Merge Cond: (((COALESCE(t1_2.c, t3_2.c))::text) = (t4_2.c)::text)
+                     ->  Sort
+                           Sort Key: ((COALESCE(t1_2.c, t3_2.c))::text)
+                           ->  Merge Full Join
+                                 Merge Cond: ((t1_2.c)::text = (t3_2.c)::text)
+                                 ->  Merge Join
+                                       Merge Cond: ((t1_2.c)::text = (t2_2.c)::text)
+                                       ->  Sort
+                                             Sort Key: t1_2.c
+                                             ->  Seq Scan on prt1_n_p2_2 t1_2
+                                       ->  Sort
+                                             Sort Key: t2_2.c
+                                             ->  Seq Scan on prt1_n_p2_2 t2_2
+                                 ->  Sort
+                                       Sort Key: t3_2.c
+                                       ->  Seq Scan on prt1_n_p2_2 t3_2
+                     ->  Sort
+                           Sort Key: t4_2.c
+                           ->  Seq Scan on prt1_n_p2_2 t4_2
+(64 rows)
+
 SELECT * FROM prt1_n t1 INNER JOIN prt1_n t2 USING (c) FULL JOIN prt1_n t3 USING (c) FULL JOIN prt1_n t4 USING (c) ORDER BY c LIMIT 5;
-ERROR:  could not find pathkey item to sort
+  c   | a | b | a | b | a | b | a | b 
+------+---+---+---+---+---+---+---+---
+ 0000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
+ 0002 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2
+ 0004 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4
+ 0006 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6
+ 0008 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8
+(5 rows)
+
 -- Beware of non-key join columns sneaking in the manually written COALESCE
 -- expressions; can't use partitionwise join in that case.
 ALTER TABLE prt1_n ADD d varchar DEFAULT '0002';
-- 
2.11.0

