You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by kg...@apache.org on 2018/10/12 10:22:10 UTC

hive git commit: HIVE-20712: HivePointLookupOptimizer should extract deep cases (Zoltan Haindrich reviewed by Jesus Camacho Rodriguez)

Repository: hive
Updated Branches:
  refs/heads/master bdbd3bcff -> 1e45c4537


HIVE-20712: HivePointLookupOptimizer should extract deep cases (Zoltan Haindrich reviewed by Jesus Camacho Rodriguez)

Signed-off-by: Zoltan Haindrich <ki...@rxd.hu>


Project: http://git-wip-us.apache.org/repos/asf/hive/repo
Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/1e45c453
Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/1e45c453
Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/1e45c453

Branch: refs/heads/master
Commit: 1e45c453740c443f2fbe9f69bdce1566b71b0efe
Parents: bdbd3bc
Author: Zoltan Haindrich <ki...@rxd.hu>
Authored: Fri Oct 12 12:21:54 2018 +0200
Committer: Zoltan Haindrich <ki...@rxd.hu>
Committed: Fri Oct 12 12:21:54 2018 +0200

----------------------------------------------------------------------
 .../rules/HivePointLookupOptimizerRule.java     |  46 ++-----
 .../rules/TestHivePointLookupOptimizerRule.java |  43 ++++++
 .../test/queries/clientpositive/pointlookup5.q  |  20 +++
 .../clientpositive/filter_cond_pushdown.q.out   |   4 +-
 .../clientpositive/perf/spark/query13.q.out     |   2 +-
 .../clientpositive/perf/spark/query48.q.out     |   2 +-
 .../clientpositive/perf/spark/query85.q.out     |   2 +-
 .../clientpositive/perf/tez/query13.q.out       |   2 +-
 .../clientpositive/perf/tez/query48.q.out       |   2 +-
 .../clientpositive/perf/tez/query85.q.out       |   2 +-
 .../results/clientpositive/pointlookup5.q.out   | 134 +++++++++++++++++++
 11 files changed, 217 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HivePointLookupOptimizerRule.java
----------------------------------------------------------------------
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HivePointLookupOptimizerRule.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HivePointLookupOptimizerRule.java
index 4d42ab4..04800cc 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HivePointLookupOptimizerRule.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HivePointLookupOptimizerRule.java
@@ -171,48 +171,26 @@ public abstract class HivePointLookupOptimizerRule extends RelOptRule {
       this.minNumORClauses = minNumORClauses;
     }
 
-    @Override public RexNode visitCall(RexCall call) {
-      RexNode node;
-      switch (call.getKind()) {
-      // FIXME: I don't think there is a need for this right now...calcite have already done the flattening/etc
-      // removing this case clause will not miss the OR below AND
-      case AND:
-        ImmutableList<RexNode> operands = RexUtil.flattenAnd(call.getOperands());
-        List<RexNode> newOperands = new ArrayList<RexNode>();
-        for (RexNode operand : operands) {
-          RexNode newOperand;
-          if (operand.getKind() == SqlKind.OR) {
-            try {
-              newOperand = transformIntoInClauseCondition(rexBuilder,
-                  nodeOp.getRowType(), operand, minNumORClauses);
-              if (newOperand == null) {
-                newOperand = operand;
-              }
-            } catch (SemanticException e) {
-              LOG.error("Exception in HivePointLookupOptimizerRule", e);
-              return call;
-            }
-          } else {
-            newOperand = operand;
-          }
-          newOperands.add(newOperand);
-        }
-        node = RexUtil.composeConjunction(rexBuilder, newOperands, false);
-        break;
+    @Override
+    public RexNode visitCall(RexCall inputCall) {
+      RexNode node = super.visitCall(inputCall);
+      if (node instanceof RexCall) {
+        RexCall call = (RexCall) node;
+        switch (call.getKind()) {
         case OR:
           try {
-            node = transformIntoInClauseCondition(rexBuilder,
-                    nodeOp.getRowType(), call, minNumORClauses);
-            if (node == null) {
-              return super.visitCall(call);
+            RexNode newNode = transformIntoInClauseCondition(rexBuilder,
+                nodeOp.getRowType(), call, minNumORClauses);
+            if (newNode != null) {
+              return newNode;
             }
           } catch (SemanticException e) {
             LOG.error("Exception in HivePointLookupOptimizerRule", e);
             return call;
           }
-          break;
         default:
-          return super.visitCall(call);
+          break;
+        }
       }
       return node;
     }

http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/rules/TestHivePointLookupOptimizerRule.java
----------------------------------------------------------------------
diff --git a/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/rules/TestHivePointLookupOptimizerRule.java b/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/rules/TestHivePointLookupOptimizerRule.java
index a593201..2b37c54 100644
--- a/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/rules/TestHivePointLookupOptimizerRule.java
+++ b/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/rules/TestHivePointLookupOptimizerRule.java
@@ -60,6 +60,7 @@ public class TestHivePointLookupOptimizerRule {
   private static class MyRecord {
     public int f1;
     public int f2;
+    public int f3;
   }
 
   @Before
@@ -171,4 +172,46 @@ public class TestHivePointLookupOptimizerRule {
     System.out.println(condition);
     assertEquals("OR(IN($0, 1, 2), =($1, 99))", condition.toString());
   }
+
+  /** Despite that extraction happen at a higher level; nested parts should also be handled */
+  @Test
+  public void testRecursionIsNotObstructed() {
+
+    // @formatter:off
+    final RelNode basePlan = builder
+          .scan("t")
+          .filter(
+              and(
+                or(
+                    eq("f1",1),
+                    eq("f1",2)
+                    )
+                ,
+                or(
+                    and(
+                        or(eq("f2",1),eq("f2",2)),
+                        or(eq("f3",1),eq("f3",2))
+                        ),
+                    and(
+                        or(eq("f2",3),eq("f2",4)),
+                        or(eq("f3",3),eq("f3",4))
+                        )
+
+
+                )
+              ))
+
+          .build();
+    // @formatter:on
+
+    planner.setRoot(basePlan);
+    RelNode optimizedRelNode = planner.findBestExp();
+
+    HiveFilter filter = (HiveFilter) optimizedRelNode;
+    RexNode condition = filter.getCondition();
+    System.out.println(condition);
+    assertEquals("AND(IN($0, 1, 2), OR(AND(IN($1, 1, 2), IN($2, 1, 2)), AND(IN($1, 3, 4), IN($2, 3, 4))))",
+        condition.toString());
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/test/queries/clientpositive/pointlookup5.q
----------------------------------------------------------------------
diff --git a/ql/src/test/queries/clientpositive/pointlookup5.q b/ql/src/test/queries/clientpositive/pointlookup5.q
new file mode 100644
index 0000000..d2098ac
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/pointlookup5.q
@@ -0,0 +1,20 @@
+create table t(a integer);
+create table t2(b integer);
+
+insert into t values (1),(2),(3),(4);
+insert into t2 values (1),(2),(3),(4);
+
+explain
+select * from t,t2 where
+	a*a=b+3
+	and
+	a in (1,2,3,4)
+	and
+	b in (1,2,3,4)
+
+	and (
+		(a in (1,2) and b in (1,2) ) or 
+		(a in (2,3) and b in (2,3) )
+			)
+	;
+

http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/test/results/clientpositive/filter_cond_pushdown.q.out
----------------------------------------------------------------------
diff --git a/ql/src/test/results/clientpositive/filter_cond_pushdown.q.out b/ql/src/test/results/clientpositive/filter_cond_pushdown.q.out
index 086c291..c3275aa 100644
--- a/ql/src/test/results/clientpositive/filter_cond_pushdown.q.out
+++ b/ql/src/test/results/clientpositive/filter_cond_pushdown.q.out
@@ -194,7 +194,7 @@ STAGE PLANS:
           outputColumnNames: _col0, _col1, _col3
           Statistics: Num rows: 550 Data size: 5843 Basic stats: COMPLETE Column stats: NONE
           Filter Operator
-            predicate: ((((_col1 = '2008-04-08') or (_col1 = '2008-04-10')) and (_col3 = '2008-04-08')) or (_col1 = '2008-04-09')) (type: boolean)
+            predicate: (((_col1) IN ('2008-04-08', '2008-04-10') and (_col3 = '2008-04-08')) or (_col1 = '2008-04-09')) (type: boolean)
             Statistics: Num rows: 550 Data size: 5843 Basic stats: COMPLETE Column stats: NONE
             File Output Operator
               compressed: false
@@ -468,7 +468,7 @@ STAGE PLANS:
           outputColumnNames: _col0, _col1, _col3
           Statistics: Num rows: 550 Data size: 5843 Basic stats: COMPLETE Column stats: NONE
           Filter Operator
-            predicate: ((((_col1 = '2008-04-08') or (_col1 = '2008-04-10')) and ((_col1 = '2008-04-08') or (_col1 = '2008-04-09')) and (_col3 = '2008-04-10')) or (_col3 = '2008-04-08')) (type: boolean)
+            predicate: (((_col1) IN ('2008-04-08', '2008-04-10') and (_col1) IN ('2008-04-08', '2008-04-09') and (_col3 = '2008-04-10')) or (_col3 = '2008-04-08')) (type: boolean)
             Statistics: Num rows: 550 Data size: 5843 Basic stats: COMPLETE Column stats: NONE
             Select Operator
               expressions: _col0 (type: string), _col1 (type: string), _col3 (type: string)

http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/test/results/clientpositive/perf/spark/query13.q.out
----------------------------------------------------------------------
diff --git a/ql/src/test/results/clientpositive/perf/spark/query13.q.out b/ql/src/test/results/clientpositive/perf/spark/query13.q.out
index 4111fa5..6e03bbc 100644
--- a/ql/src/test/results/clientpositive/perf/spark/query13.q.out
+++ b/ql/src/test/results/clientpositive/perf/spark/query13.q.out
@@ -317,7 +317,7 @@ STAGE PLANS:
                 outputColumnNames: _col4, _col5, _col7, _col8, _col9, _col18
                 Statistics: Num rows: 22000000 Data size: 22327357890 Basic stats: COMPLETE Column stats: NONE
                 Filter Operator
-                  predicate: ((((_col18 = 'KY') or (_col18 = 'GA') or (_col18 = 'NM')) and _col9 BETWEEN 100 AND 200) or (((_col18 = 'MT') or (_col18 = 'OR') or (_col18 = 'IN')) and _col9 BETWEEN 150 AND 300) or (((_col18 = 'WI') or (_col18 = 'MO') or (_col18 = 'WV')) and _col9 BETWEEN 50 AND 250)) (type: boolean)
+                  predicate: (((_col18) IN ('KY', 'GA', 'NM') and _col9 BETWEEN 100 AND 200) or ((_col18) IN ('MT', 'OR', 'IN') and _col9 BETWEEN 150 AND 300) or ((_col18) IN ('WI', 'MO', 'WV') and _col9 BETWEEN 50 AND 250)) (type: boolean)
                   Statistics: Num rows: 7333332 Data size: 7442451276 Basic stats: COMPLETE Column stats: NONE
                   Map Join Operator
                     condition map:

http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/test/results/clientpositive/perf/spark/query48.q.out
----------------------------------------------------------------------
diff --git a/ql/src/test/results/clientpositive/perf/spark/query48.q.out b/ql/src/test/results/clientpositive/perf/spark/query48.q.out
index ed8d936..24f5425 100644
--- a/ql/src/test/results/clientpositive/perf/spark/query48.q.out
+++ b/ql/src/test/results/clientpositive/perf/spark/query48.q.out
@@ -303,7 +303,7 @@ STAGE PLANS:
                 outputColumnNames: _col3, _col4, _col6, _col13
                 Statistics: Num rows: 255550079 Data size: 22544702224 Basic stats: COMPLETE Column stats: NONE
                 Filter Operator
-                  predicate: ((((_col13 = 'KY') or (_col13 = 'GA') or (_col13 = 'NM')) and _col6 BETWEEN 0 AND 2000) or (((_col13 = 'MT') or (_col13 = 'OR') or (_col13 = 'IN')) and _col6 BETWEEN 150 AND 3000) or (((_col13 = 'WI') or (_col13 = 'MO') or (_col13 = 'WV')) and _col6 BETWEEN 50 AND 25000)) (type: boolean)
+                  predicate: (((_col13) IN ('KY', 'GA', 'NM') and _col6 BETWEEN 0 AND 2000) or ((_col13) IN ('MT', 'OR', 'IN') and _col6 BETWEEN 150 AND 3000) or ((_col13) IN ('WI', 'MO', 'WV') and _col6 BETWEEN 50 AND 25000)) (type: boolean)
                   Statistics: Num rows: 85183359 Data size: 7514900682 Basic stats: COMPLETE Column stats: NONE
                   Map Join Operator
                     condition map:

http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/test/results/clientpositive/perf/spark/query85.q.out
----------------------------------------------------------------------
diff --git a/ql/src/test/results/clientpositive/perf/spark/query85.q.out b/ql/src/test/results/clientpositive/perf/spark/query85.q.out
index 139a32b..dfa2679 100644
--- a/ql/src/test/results/clientpositive/perf/spark/query85.q.out
+++ b/ql/src/test/results/clientpositive/perf/spark/query85.q.out
@@ -461,7 +461,7 @@ STAGE PLANS:
                 outputColumnNames: _col6, _col7, _col12, _col14, _col19, _col27
                 Statistics: Num rows: 22000000 Data size: 22327357890 Basic stats: COMPLETE Column stats: NONE
                 Filter Operator
-                  predicate: ((((_col27 = 'KY') or (_col27 = 'GA') or (_col27 = 'NM')) and _col14 BETWEEN 100 AND 200) or (((_col27 = 'MT') or (_col27 = 'OR') or (_col27 = 'IN')) and _col14 BETWEEN 150 AND 300) or (((_col27 = 'WI') or (_col27 = 'MO') or (_col27 = 'WV')) and _col14 BETWEEN 50 AND 250)) (type: boolean)
+                  predicate: (((_col27) IN ('KY', 'GA', 'NM') and _col14 BETWEEN 100 AND 200) or ((_col27) IN ('MT', 'OR', 'IN') and _col14 BETWEEN 150 AND 300) or ((_col27) IN ('WI', 'MO', 'WV') and _col14 BETWEEN 50 AND 250)) (type: boolean)
                   Statistics: Num rows: 7333332 Data size: 7442451276 Basic stats: COMPLETE Column stats: NONE
                   Select Operator
                     expressions: _col6 (type: decimal(7,2)), _col7 (type: decimal(7,2)), _col12 (type: int), _col19 (type: string)

http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/test/results/clientpositive/perf/tez/query13.q.out
----------------------------------------------------------------------
diff --git a/ql/src/test/results/clientpositive/perf/tez/query13.q.out b/ql/src/test/results/clientpositive/perf/tez/query13.q.out
index ffef171..c33e50e 100644
--- a/ql/src/test/results/clientpositive/perf/tez/query13.q.out
+++ b/ql/src/test/results/clientpositive/perf/tez/query13.q.out
@@ -157,7 +157,7 @@ Stage-0
                   SHUFFLE [RS_32]
                     PartitionCols:_col4
                     Filter Operator [FIL_31] (rows=7333332 width=1014)
-                      predicate:((((_col18 = 'KY') or (_col18 = 'GA') or (_col18 = 'NM')) and _col9 BETWEEN 100 AND 200) or (((_col18 = 'MT') or (_col18 = 'OR') or (_col18 = 'IN')) and _col9 BETWEEN 150 AND 300) or (((_col18 = 'WI') or (_col18 = 'MO') or (_col18 = 'WV')) and _col9 BETWEEN 50 AND 250))
+                      predicate:(((_col18) IN ('KY', 'GA', 'NM') and _col9 BETWEEN 100 AND 200) or ((_col18) IN ('MT', 'OR', 'IN') and _col9 BETWEEN 150 AND 300) or ((_col18) IN ('WI', 'MO', 'WV') and _col9 BETWEEN 50 AND 250))
                       Merge Join Operator [MERGEJOIN_120] (rows=22000000 width=1014)
                         Conds:RS_28._col3=RS_148._col0(Inner),Output:["_col4","_col5","_col7","_col8","_col9","_col18"]
                       <-Map 14 [SIMPLE_EDGE] vectorized

http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/test/results/clientpositive/perf/tez/query48.q.out
----------------------------------------------------------------------
diff --git a/ql/src/test/results/clientpositive/perf/tez/query48.q.out b/ql/src/test/results/clientpositive/perf/tez/query48.q.out
index 24ad2da..e07c160 100644
--- a/ql/src/test/results/clientpositive/perf/tez/query48.q.out
+++ b/ql/src/test/results/clientpositive/perf/tez/query48.q.out
@@ -181,7 +181,7 @@ Stage-0
                 SHUFFLE [RS_25]
                   PartitionCols:_col3
                   Filter Operator [FIL_24] (rows=85183359 width=88)
-                    predicate:((((_col13 = 'KY') or (_col13 = 'GA') or (_col13 = 'NM')) and _col6 BETWEEN 0 AND 2000) or (((_col13 = 'MT') or (_col13 = 'OR') or (_col13 = 'IN')) and _col6 BETWEEN 150 AND 3000) or (((_col13 = 'WI') or (_col13 = 'MO') or (_col13 = 'WV')) and _col6 BETWEEN 50 AND 25000))
+                    predicate:(((_col13) IN ('KY', 'GA', 'NM') and _col6 BETWEEN 0 AND 2000) or ((_col13) IN ('MT', 'OR', 'IN') and _col6 BETWEEN 150 AND 3000) or ((_col13) IN ('WI', 'MO', 'WV') and _col6 BETWEEN 50 AND 25000))
                     Merge Join Operator [MERGEJOIN_95] (rows=255550079 width=88)
                       Conds:RS_21._col2=RS_115._col0(Inner),Output:["_col3","_col4","_col6","_col13"]
                     <-Map 11 [SIMPLE_EDGE] vectorized

http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/test/results/clientpositive/perf/tez/query85.q.out
----------------------------------------------------------------------
diff --git a/ql/src/test/results/clientpositive/perf/tez/query85.q.out b/ql/src/test/results/clientpositive/perf/tez/query85.q.out
index 5e2af5a..2708c72 100644
--- a/ql/src/test/results/clientpositive/perf/tez/query85.q.out
+++ b/ql/src/test/results/clientpositive/perf/tez/query85.q.out
@@ -220,7 +220,7 @@ Stage-0
                       Select Operator [SEL_47] (rows=7333332 width=1014)
                         Output:["_col6","_col7","_col12","_col19"]
                         Filter Operator [FIL_46] (rows=7333332 width=1014)
-                          predicate:((((_col27 = 'KY') or (_col27 = 'GA') or (_col27 = 'NM')) and _col14 BETWEEN 100 AND 200) or (((_col27 = 'MT') or (_col27 = 'OR') or (_col27 = 'IN')) and _col14 BETWEEN 150 AND 300) or (((_col27 = 'WI') or (_col27 = 'MO') or (_col27 = 'WV')) and _col14 BETWEEN 50 AND 250))
+                          predicate:(((_col27) IN ('KY', 'GA', 'NM') and _col14 BETWEEN 100 AND 200) or ((_col27) IN ('MT', 'OR', 'IN') and _col14 BETWEEN 150 AND 300) or ((_col27) IN ('WI', 'MO', 'WV') and _col14 BETWEEN 50 AND 250))
                           Merge Join Operator [MERGEJOIN_206] (rows=22000000 width=1014)
                             Conds:RS_43._col2=RS_238._col0(Inner),Output:["_col6","_col7","_col12","_col14","_col19","_col27"]
                           <-Map 18 [SIMPLE_EDGE] vectorized

http://git-wip-us.apache.org/repos/asf/hive/blob/1e45c453/ql/src/test/results/clientpositive/pointlookup5.q.out
----------------------------------------------------------------------
diff --git a/ql/src/test/results/clientpositive/pointlookup5.q.out b/ql/src/test/results/clientpositive/pointlookup5.q.out
new file mode 100644
index 0000000..da09693
--- /dev/null
+++ b/ql/src/test/results/clientpositive/pointlookup5.q.out
@@ -0,0 +1,134 @@
+PREHOOK: query: create table t(a integer)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t
+POSTHOOK: query: create table t(a integer)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t
+PREHOOK: query: create table t2(b integer)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t2
+POSTHOOK: query: create table t2(b integer)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t2
+PREHOOK: query: insert into t values (1),(2),(3),(4)
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@t
+POSTHOOK: query: insert into t values (1),(2),(3),(4)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@t
+POSTHOOK: Lineage: t.a SCRIPT []
+PREHOOK: query: insert into t2 values (1),(2),(3),(4)
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@t2
+POSTHOOK: query: insert into t2 values (1),(2),(3),(4)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@t2
+POSTHOOK: Lineage: t2.b SCRIPT []
+PREHOOK: query: explain
+select * from t,t2 where
+	a*a=b+3
+	and
+	a in (1,2,3,4)
+	and
+	b in (1,2,3,4)
+
+	and (
+		(a in (1,2) and b in (1,2) ) or 
+		(a in (2,3) and b in (2,3) )
+			)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t
+PREHOOK: Input: default@t2
+#### A masked pattern was here ####
+POSTHOOK: query: explain
+select * from t,t2 where
+	a*a=b+3
+	and
+	a in (1,2,3,4)
+	and
+	b in (1,2,3,4)
+
+	and (
+		(a in (1,2) and b in (1,2) ) or 
+		(a in (2,3) and b in (2,3) )
+			)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t
+POSTHOOK: Input: default@t2
+#### A masked pattern was here ####
+STAGE DEPENDENCIES:
+  Stage-1 is a root stage
+  Stage-0 depends on stages: Stage-1
+
+STAGE PLANS:
+  Stage: Stage-1
+    Map Reduce
+      Map Operator Tree:
+          TableScan
+            alias: t
+            filterExpr: (a) IN (1, 2, 3, 4) (type: boolean)
+            Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+            Filter Operator
+              predicate: (a) IN (1, 2, 3, 4) (type: boolean)
+              Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+              Select Operator
+                expressions: a (type: int)
+                outputColumnNames: _col0
+                Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+                Reduce Output Operator
+                  key expressions: (_col0 * _col0) (type: int)
+                  sort order: +
+                  Map-reduce partition columns: (_col0 * _col0) (type: int)
+                  Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+                  value expressions: _col0 (type: int)
+          TableScan
+            alias: t2
+            filterExpr: (b) IN (1, 2, 3, 4) (type: boolean)
+            Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+            Filter Operator
+              predicate: (b) IN (1, 2, 3, 4) (type: boolean)
+              Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+              Select Operator
+                expressions: b (type: int)
+                outputColumnNames: _col0
+                Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+                Reduce Output Operator
+                  key expressions: (_col0 + 3) (type: int)
+                  sort order: +
+                  Map-reduce partition columns: (_col0 + 3) (type: int)
+                  Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+                  value expressions: _col0 (type: int)
+      Reduce Operator Tree:
+        Join Operator
+          condition map:
+               Inner Join 0 to 1
+          keys:
+            0 (_col0 * _col0) (type: int)
+            1 (_col0 + 3) (type: int)
+          outputColumnNames: _col0, _col1
+          Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+          Filter Operator
+            predicate: (((_col0) IN (1, 2) and (_col1) IN (1, 2)) or ((_col0) IN (2, 3) and (_col1) IN (2, 3))) (type: boolean)
+            Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+            File Output Operator
+              compressed: false
+              Statistics: Num rows: 4 Data size: 4 Basic stats: COMPLETE Column stats: NONE
+              table:
+                  input format: org.apache.hadoop.mapred.SequenceFileInputFormat
+                  output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat
+                  serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
+
+  Stage: Stage-0
+    Fetch Operator
+      limit: -1
+      Processor Tree:
+        ListSink
+