This is an automated email from the ASF dual-hosted git repository.
zabetak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push:
new 3b970251f45 HIVE-28222: Ambiguous table alias exception for queries
with self joins (#5998)
3b970251f45 is described below
commit 3b970251f456f49a73297e06bc5f2e1a794dad2a
Author: Stamatis Zampetakis <[email protected]>
AuthorDate: Mon Aug 11 12:43:18 2025 +0300
HIVE-28222: Ambiguous table alias exception for queries with self joins
(#5998)
Some queries that contain joins of the same table more than twice fail
during compilation while trying to transform the optimized AST (obtained from
CBO) to an Operator tree. The "Ambiguous table alias" exception is raised when
a HiveJoin contains the same table scan multiple times (without an interleaving
project) cause the generated AST is ambiguous.
1. Implement SelfJoinHandler for tracking table aliases in the plan and
introducing a derived table (Project) whenever there are conflicts under a join.
2. Extract the alias handling logic in a separate step/traversal of the
RelNode tree for readability, encapsulation, and maintainability.
3. Enhance HiveRelShuttle to handle HiveJdbcConverter, which is a built-in
Hive operator, that simplifies the `SelfJoinHandler`
---
.../hive/ql/optimizer/calcite/HiveRelShuttle.java | 2 +
.../ql/optimizer/calcite/HiveRelShuttleImpl.java | 6 ++
.../reloperators/jdbc/HiveJdbcConverter.java | 10 +++
.../calcite/translator/PlanModifierForASTConv.java | 99 +++++++++++++++-------
.../cbo_self_join_ambiguous_alias_cte.q | 6 ++
.../cbo_self_join_ambiguous_alias_mv.q | 13 +++
.../cbo_self_join_ambiguous_alias_subquery.q | 7 ++
.../llap/cbo_self_join_ambiguous_alias_cte.q.out | 34 ++++++++
.../llap/cbo_self_join_ambiguous_alias_mv.q.out | 52 ++++++++++++
.../cbo_self_join_ambiguous_alias_subquery.q.out | 36 ++++++++
.../clientpositive/llap/external_jdbc_table2.q.out | 4 +-
.../clientpositive/llap/external_jdbc_table4.q.out | 4 +-
12 files changed, 238 insertions(+), 35 deletions(-)
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveRelShuttle.java
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveRelShuttle.java
index 36f91a68e6e..8479556f5e4 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveRelShuttle.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveRelShuttle.java
@@ -25,6 +25,7 @@
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveProject;
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveSortLimit;
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveTableScan;
+import
org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.jdbc.HiveJdbcConverter;
/**
* Visitor that has methods for the common logical relational expressions.
@@ -39,6 +40,7 @@ public interface HiveRelShuttle extends RelShuttle {
RelNode visit(HiveAggregate aggregate);
RelNode visit(HiveSortLimit hiveSortLimit);
RelNode visit(HiveTableScan scan);
+ RelNode visit(HiveJdbcConverter conv);
}
// End RelShuttle.java
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveRelShuttleImpl.java
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveRelShuttleImpl.java
index c22a73af1c6..ee85b00d560 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveRelShuttleImpl.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveRelShuttleImpl.java
@@ -43,6 +43,7 @@
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveProject;
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveSortLimit;
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveTableScan;
+import
org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.jdbc.HiveJdbcConverter;
import java.util.ArrayList;
import java.util.List;
@@ -171,6 +172,11 @@ public RelNode visit(HiveSortLimit hiveSortLimit) {
public RelNode visit(HiveTableScan scan) {
return scan;
}
+
+ @Override
+ public RelNode visit(HiveJdbcConverter conv) {
+ return visitChild(conv, 0, conv.getInput());
+ }
}
// End RelShuttleImpl.java
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/reloperators/jdbc/HiveJdbcConverter.java
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/reloperators/jdbc/HiveJdbcConverter.java
index 7bb7539506e..164395d32d6 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/reloperators/jdbc/HiveJdbcConverter.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/reloperators/jdbc/HiveJdbcConverter.java
@@ -27,6 +27,7 @@
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelShuttle;
import org.apache.calcite.rel.RelVisitor;
import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.convert.ConverterImpl;
@@ -38,6 +39,7 @@
import org.apache.calcite.sql.SqlDialect;
import org.apache.calcite.util.ControlFlowException;
+import org.apache.hadoop.hive.ql.optimizer.calcite.HiveRelShuttle;
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveRelNode;
import
org.apache.hadoop.hive.ql.optimizer.calcite.rules.jdbc.HiveJdbcImplementor;
@@ -86,6 +88,14 @@ public RelNode copy(
return new HiveJdbcConverter(getCluster(), traitSet, sole(inputs),
convention, url, user);
}
+ @Override
+ public RelNode accept(RelShuttle shuttle) {
+ if (shuttle instanceof HiveRelShuttle) {
+ return ((HiveRelShuttle) shuttle).visit(this);
+ }
+ return super.accept(shuttle);
+ }
+
public RelNode copy(RelTraitSet traitSet, RelNode input) {
return new HiveJdbcConverter(getCluster(), traitSet, input, convention,
url, user);
}
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/PlanModifierForASTConv.java
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/PlanModifierForASTConv.java
index 8ed19079dd1..f1dd9dd6e0c 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/PlanModifierForASTConv.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/PlanModifierForASTConv.java
@@ -18,10 +18,14 @@
package org.apache.hadoop.hive.ql.optimizer.calcite.translator;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
+import com.google.common.collect.Sets;
import org.apache.calcite.adapter.druid.DruidQuery;
import org.apache.calcite.adapter.jdbc.JdbcConvention;
import org.apache.calcite.adapter.jdbc.JdbcRel;
@@ -53,8 +57,10 @@
import org.apache.hadoop.hive.ql.optimizer.calcite.CalciteSemanticException;
import org.apache.hadoop.hive.ql.optimizer.calcite.HiveCalciteUtil;
import org.apache.hadoop.hive.ql.optimizer.calcite.HiveRelFactories;
+import org.apache.hadoop.hive.ql.optimizer.calcite.HiveRelShuttleImpl;
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveAggregate;
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveAntiJoin;
+import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveJoin;
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveValues;
import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveProject;
import
org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveSortExchange;
@@ -100,6 +106,11 @@ public static RelNode convertOpTree(RelNode rel,
List<FieldSchema> resultSchema,
LOG.debug("Plan after nested convertOpTree\n " +
RelOptUtil.toString(newTopNode));
}
+ newTopNode = newTopNode.accept(new SelfJoinHandler());
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Plan after self-join disambiguation\n " +
RelOptUtil.toString(newTopNode));
+ }
+
if (alignColumns) {
HiveRelColumnsAlignment propagator = new HiveRelColumnsAlignment(
HiveRelFactories.HIVE_BUILDER.create(newTopNode.getCluster(), null));
@@ -123,31 +134,6 @@ public static RelNode convertOpTree(RelNode rel,
List<FieldSchema> resultSchema,
return newTopNode;
}
- private static String getTblAlias(RelNode rel) {
-
- if (null == rel) {
- return null;
- }
- if (rel instanceof HiveTableScan) {
- return ((HiveTableScan)rel).getTableAlias();
- }
- if (rel instanceof DruidQuery) {
- DruidQuery dq = (DruidQuery) rel;
- return ((HiveTableScan) dq.getTableScan()).getTableAlias();
- }
- if (rel instanceof HiveJdbcConverter) {
- HiveJdbcConverter conv = (HiveJdbcConverter) rel;
- return conv.getTableScan().getHiveTableScan().getTableAlias();
- }
- if (rel instanceof Project) {
- return null;
- }
- if (rel.getInputs().size() == 1) {
- return getTblAlias(rel.getInput(0));
- }
- return null;
- }
-
private static void convertOpTree(RelNode rel, RelNode parent) {
if (rel instanceof HepRelVertex) {
@@ -156,12 +142,6 @@ private static void convertOpTree(RelNode rel, RelNode
parent) {
if (!validJoinParent(rel, parent)) {
introduceDerivedTable(rel, parent);
}
- String leftChild = getTblAlias(((Join)rel).getLeft());
- if (null != leftChild &&
leftChild.equalsIgnoreCase(getTblAlias(((Join)rel).getRight()))) {
- // introduce derived table above one child, if this is self-join
- // since user provided aliases are lost at this point.
- introduceDerivedTable(((Join)rel).getLeft(), rel);
- }
} else if (rel instanceof MultiJoin) {
throw new RuntimeException("Found MultiJoin");
} else if (rel instanceof RelSubset) {
@@ -230,6 +210,63 @@ private static void convertOpTree(RelNode rel, RelNode
parent) {
}
}
+ /**
+ * A handler that detects self-joins in the plan and rewrites them to
resolve ambiguous aliases.
+ * The handler traverses the plan and collects aliases of tables it
encounters for each join branch.
+ * When the same alias occurs in both branches of a join, it introduces a
derive table (Project)
+ * over the left branch to break the ambiguity.
+ */
+ private static class SelfJoinHandler extends HiveRelShuttleImpl {
+ private final Set<String> aliases = new HashSet<>();
+
+ @Override
+ public RelNode visit(HiveJoin join) {
+ SelfJoinHandler lf = new SelfJoinHandler();
+ RelNode newL = join.getLeft().accept(lf);
+ SelfJoinHandler rf = new SelfJoinHandler();
+ RelNode newR = join.getRight().accept(rf);
+ if (Sets.intersection(lf.aliases, rf.aliases).isEmpty()) {
+ // No self-join detected, return the join as is
+ aliases.addAll(lf.aliases);
+ aliases.addAll(rf.aliases);
+ return join.copy(join.getTraitSet(), Arrays.asList(newL, newR));
+ }
+ // Self-join detected, introduce a derived table for the left side
+ aliases.addAll(rf.aliases);
+ introduceDerivedTable(newL, join);
+ return join;
+ }
+
+ @Override
+ public RelNode visit(HiveProject project) {
+ RelNode rel = super.visit(project);
+ // Project denotes a derived table, so aliases can be cleared
+ aliases.clear();
+ return rel;
+ }
+
+ @Override
+ public RelNode visit(HiveTableScan scan) {
+ aliases.add(scan.getTableAlias().toLowerCase());
+ return scan;
+ }
+
+ @Override
+ public RelNode visit(HiveJdbcConverter conv) {
+
aliases.add(conv.getTableScan().getHiveTableScan().getTableAlias().toLowerCase());
+ return conv;
+ }
+
+ @Override
+ public RelNode visit(final RelNode rel) {
+ if (rel instanceof DruidQuery dq) {
+ aliases.add(((HiveTableScan)
dq.getTableScan()).getTableAlias().toLowerCase());
+ return dq;
+ }
+ return super.visit(rel);
+ }
+ }
+
public static RelNode renameTopLevelSelectInResultSchema(final RelNode
rootRel,
Pair<RelNode, RelNode> topSelparentPair, List<FieldSchema> resultSchema)
throws CalciteSemanticException {
diff --git
a/ql/src/test/queries/clientpositive/cbo_self_join_ambiguous_alias_cte.q
b/ql/src/test/queries/clientpositive/cbo_self_join_ambiguous_alias_cte.q
new file mode 100644
index 00000000000..3293a409ed2
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/cbo_self_join_ambiguous_alias_cte.q
@@ -0,0 +1,6 @@
+create table t1 (key int, value int);
+
+explain cbo
+with cte as
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1)
+select * from cte a join cte b join cte c
diff --git
a/ql/src/test/queries/clientpositive/cbo_self_join_ambiguous_alias_mv.q
b/ql/src/test/queries/clientpositive/cbo_self_join_ambiguous_alias_mv.q
new file mode 100644
index 00000000000..c21b294a39c
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/cbo_self_join_ambiguous_alias_mv.q
@@ -0,0 +1,13 @@
+set hive.support.concurrency=true;
+set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
+
+create table t1 (key int, value int) stored as orc TBLPROPERTIES
('transactional'='true');
+
+create materialized view mv as
+select * from t1 where key < 6;
+
+explain cbo
+select * from
+ (select * from t1 where key < 6) a join
+ (select * from t1 where key < 6) b join
+ (select * from t1 where key < 6) c;
diff --git
a/ql/src/test/queries/clientpositive/cbo_self_join_ambiguous_alias_subquery.q
b/ql/src/test/queries/clientpositive/cbo_self_join_ambiguous_alias_subquery.q
new file mode 100644
index 00000000000..8298d9a3da3
--- /dev/null
+++
b/ql/src/test/queries/clientpositive/cbo_self_join_ambiguous_alias_subquery.q
@@ -0,0 +1,7 @@
+create table t1 (key int, value int);
+
+explain cbo
+select * from
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1) a join
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1) b join
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1) c;
diff --git
a/ql/src/test/results/clientpositive/llap/cbo_self_join_ambiguous_alias_cte.q.out
b/ql/src/test/results/clientpositive/llap/cbo_self_join_ambiguous_alias_cte.q.out
new file mode 100644
index 00000000000..327da794726
--- /dev/null
+++
b/ql/src/test/results/clientpositive/llap/cbo_self_join_ambiguous_alias_cte.q.out
@@ -0,0 +1,34 @@
+PREHOOK: query: create table t1 (key int, value int)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t1
+POSTHOOK: query: create table t1 (key int, value int)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t1
+Warning: Shuffle Join MERGEJOIN[13][tables = [$hdt$_0, t1]] in Stage 'Reducer
2' is a cross product
+Warning: Shuffle Join MERGEJOIN[14][tables = [$hdt$_0, t1]] in Stage 'Reducer
3' is a cross product
+PREHOOK: query: explain cbo
+with cte as
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1)
+select * from cte a join cte b join cte c
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t1
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo
+with cte as
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1)
+select * from cte a join cte b join cte c
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t1
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(key=[$0], value=[$1], BLOCK__OFFSET__INSIDE__FILE=[$2],
INPUT__FILE__NAME=[$3], ROW__ID=[$4], ROW__IS__DELETED=[$5], key0=[$12],
value0=[$13], BLOCK__OFFSET__INSIDE__FILE0=[$14], INPUT__FILE__NAME0=[$15],
ROW__ID0=[$16], ROW__IS__DELETED0=[$17], key1=[$6], value1=[$7],
BLOCK__OFFSET__INSIDE__FILE1=[$8], INPUT__FILE__NAME1=[$9], ROW__ID1=[$10],
ROW__IS__DELETED1=[$11])
+ HiveJoin(condition=[true], joinType=[inner], algorithm=[none], cost=[not
available])
+ HiveProject(key=[$0], value=[$1], BLOCK__OFFSET__INSIDE__FILE=[$2],
INPUT__FILE__NAME=[$3], ROW__ID=[$4], ROW__IS__DELETED=[$5], key0=[$6],
value0=[$7], BLOCK__OFFSET__INSIDE__FILE0=[$8], INPUT__FILE__NAME0=[$9],
ROW__ID0=[$10], ROW__IS__DELETED0=[$11])
+ HiveJoin(condition=[true], joinType=[inner], algorithm=[none], cost=[not
available])
+ HiveProject(key=[$0], value=[$1], BLOCK__OFFSET__INSIDE__FILE=[$2],
INPUT__FILE__NAME=[$3], ROW__ID=[$4], ROW__IS__DELETED=[$5])
+ HiveTableScan(table=[[default, t1]], table:alias=[t1])
+ HiveTableScan(table=[[default, t1]], table:alias=[t1])
+ HiveTableScan(table=[[default, t1]], table:alias=[t1])
+
diff --git
a/ql/src/test/results/clientpositive/llap/cbo_self_join_ambiguous_alias_mv.q.out
b/ql/src/test/results/clientpositive/llap/cbo_self_join_ambiguous_alias_mv.q.out
new file mode 100644
index 00000000000..b77ea313988
--- /dev/null
+++
b/ql/src/test/results/clientpositive/llap/cbo_self_join_ambiguous_alias_mv.q.out
@@ -0,0 +1,52 @@
+PREHOOK: query: create table t1 (key int, value int) stored as orc
TBLPROPERTIES ('transactional'='true')
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t1
+POSTHOOK: query: create table t1 (key int, value int) stored as orc
TBLPROPERTIES ('transactional'='true')
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t1
+PREHOOK: query: create materialized view mv as
+select * from t1 where key < 6
+PREHOOK: type: CREATE_MATERIALIZED_VIEW
+PREHOOK: Input: default@t1
+PREHOOK: Output: database:default
+PREHOOK: Output: default@mv
+POSTHOOK: query: create materialized view mv as
+select * from t1 where key < 6
+POSTHOOK: type: CREATE_MATERIALIZED_VIEW
+POSTHOOK: Input: default@t1
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@mv
+POSTHOOK: Lineage: mv.key SIMPLE [(t1)t1.FieldSchema(name:key, type:int,
comment:null), ]
+POSTHOOK: Lineage: mv.value SIMPLE [(t1)t1.FieldSchema(name:value, type:int,
comment:null), ]
+Warning: Shuffle Join MERGEJOIN[13][tables = [$hdt$_0, default.mv]] in Stage
'Reducer 2' is a cross product
+Warning: Shuffle Join MERGEJOIN[14][tables = [$hdt$_0, default.mv]] in Stage
'Reducer 3' is a cross product
+PREHOOK: query: explain cbo
+select * from
+ (select * from t1 where key < 6) a join
+ (select * from t1 where key < 6) b join
+ (select * from t1 where key < 6) c
+PREHOOK: type: QUERY
+PREHOOK: Input: default@mv
+PREHOOK: Input: default@t1
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo
+select * from
+ (select * from t1 where key < 6) a join
+ (select * from t1 where key < 6) b join
+ (select * from t1 where key < 6) c
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@mv
+POSTHOOK: Input: default@t1
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(key=[$0], value=[$1], key0=[$4], value0=[$5], key1=[$2],
value1=[$3])
+ HiveJoin(condition=[true], joinType=[inner], algorithm=[none], cost=[not
available])
+ HiveProject(key=[$0], value=[$1], key0=[$2], value0=[$3])
+ HiveJoin(condition=[true], joinType=[inner], algorithm=[none], cost=[not
available])
+ HiveProject(key=[$0], value=[$1])
+ HiveTableScan(table=[[default, mv]], table:alias=[default.mv])
+ HiveTableScan(table=[[default, mv]], table:alias=[default.mv])
+ HiveTableScan(table=[[default, mv]], table:alias=[default.mv])
+
diff --git
a/ql/src/test/results/clientpositive/llap/cbo_self_join_ambiguous_alias_subquery.q.out
b/ql/src/test/results/clientpositive/llap/cbo_self_join_ambiguous_alias_subquery.q.out
new file mode 100644
index 00000000000..56ad6d900ea
--- /dev/null
+++
b/ql/src/test/results/clientpositive/llap/cbo_self_join_ambiguous_alias_subquery.q.out
@@ -0,0 +1,36 @@
+PREHOOK: query: create table t1 (key int, value int)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t1
+POSTHOOK: query: create table t1 (key int, value int)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t1
+Warning: Shuffle Join MERGEJOIN[13][tables = [$hdt$_0, t1]] in Stage 'Reducer
2' is a cross product
+Warning: Shuffle Join MERGEJOIN[14][tables = [$hdt$_0, t1]] in Stage 'Reducer
3' is a cross product
+PREHOOK: query: explain cbo
+select * from
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1) a join
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1) b join
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1) c
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t1
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo
+select * from
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1) a join
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1) b join
+(select key, value, BLOCK__OFFSET__INSIDE__FILE, INPUT__FILE__NAME, ROW__ID,
ROW__IS__DELETED from t1) c
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t1
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(key=[$0], value=[$1], BLOCK__OFFSET__INSIDE__FILE=[$2],
INPUT__FILE__NAME=[$3], ROW__ID=[$4], ROW__IS__DELETED=[$5], key0=[$12],
value0=[$13], BLOCK__OFFSET__INSIDE__FILE0=[$14], INPUT__FILE__NAME0=[$15],
ROW__ID0=[$16], ROW__IS__DELETED0=[$17], key1=[$6], value1=[$7],
BLOCK__OFFSET__INSIDE__FILE1=[$8], INPUT__FILE__NAME1=[$9], ROW__ID1=[$10],
ROW__IS__DELETED1=[$11])
+ HiveJoin(condition=[true], joinType=[inner], algorithm=[none], cost=[not
available])
+ HiveProject(key=[$0], value=[$1], BLOCK__OFFSET__INSIDE__FILE=[$2],
INPUT__FILE__NAME=[$3], ROW__ID=[$4], ROW__IS__DELETED=[$5], key0=[$6],
value0=[$7], BLOCK__OFFSET__INSIDE__FILE0=[$8], INPUT__FILE__NAME0=[$9],
ROW__ID0=[$10], ROW__IS__DELETED0=[$11])
+ HiveJoin(condition=[true], joinType=[inner], algorithm=[none], cost=[not
available])
+ HiveProject(key=[$0], value=[$1], BLOCK__OFFSET__INSIDE__FILE=[$2],
INPUT__FILE__NAME=[$3], ROW__ID=[$4], ROW__IS__DELETED=[$5])
+ HiveTableScan(table=[[default, t1]], table:alias=[t1])
+ HiveTableScan(table=[[default, t1]], table:alias=[t1])
+ HiveTableScan(table=[[default, t1]], table:alias=[t1])
+
diff --git a/ql/src/test/results/clientpositive/llap/external_jdbc_table2.q.out
b/ql/src/test/results/clientpositive/llap/external_jdbc_table2.q.out
index 895591440c1..65ea5424f61 100644
--- a/ql/src/test/results/clientpositive/llap/external_jdbc_table2.q.out
+++ b/ql/src/test/results/clientpositive/llap/external_jdbc_table2.q.out
@@ -420,7 +420,7 @@ POSTHOOK: Input: default@db1_ext_auth2
#### A masked pattern was here ####
-20 -20 -20.0 -20.0 -20 8 9.0 11.0
20 20 20.0 20.0 20 20 20.0 20.0
-Warning: Shuffle Join MERGEJOIN[10][tables = [$hdt$_0, $hdt$_1]] in Stage
'Reducer 2' is a cross product
+Warning: Shuffle Join MERGEJOIN[9][tables = [$hdt$_0, $hdt$_1]] in Stage
'Reducer 2' is a cross product
PREHOOK: query: EXPLAIN
SELECT db1_ext_auth1.ikey, b.ikey * 2 FROM db1_ext_auth1 JOIN (SELECT * FROM
db1_ext_auth1) b
PREHOOK: type: QUERY
@@ -512,7 +512,7 @@ FROM "EXTERNAL_JDBC_SIMPLE_DERBY2_TABLE1"
Processor Tree:
ListSink
-Warning: Shuffle Join MERGEJOIN[10][tables = [$hdt$_0, $hdt$_1]] in Stage
'Reducer 2' is a cross product
+Warning: Shuffle Join MERGEJOIN[9][tables = [$hdt$_0, $hdt$_1]] in Stage
'Reducer 2' is a cross product
PREHOOK: query: SELECT db1_ext_auth1.ikey, b.ikey * 2 FROM db1_ext_auth1 JOIN
(SELECT * FROM db1_ext_auth1) b
PREHOOK: type: QUERY
PREHOOK: Input: default@db1_ext_auth1
diff --git a/ql/src/test/results/clientpositive/llap/external_jdbc_table4.q.out
b/ql/src/test/results/clientpositive/llap/external_jdbc_table4.q.out
index 76abbd5d91a..4d49e1680cf 100644
--- a/ql/src/test/results/clientpositive/llap/external_jdbc_table4.q.out
+++ b/ql/src/test/results/clientpositive/llap/external_jdbc_table4.q.out
@@ -420,7 +420,7 @@ POSTHOOK: Input: default@db1_ext_auth2
#### A masked pattern was here ####
-20 -20 -20.0 -20.0 -20 8 9.0 11.0
20 20 20.0 20.0 20 20 20.0 20.0
-Warning: Shuffle Join MERGEJOIN[10][tables = [$hdt$_0, $hdt$_1]] in Stage
'Reducer 2' is a cross product
+Warning: Shuffle Join MERGEJOIN[9][tables = [$hdt$_0, $hdt$_1]] in Stage
'Reducer 2' is a cross product
PREHOOK: query: EXPLAIN
SELECT db1_ext_auth1.ikey, b.ikey * 2 FROM db1_ext_auth1 JOIN (SELECT * FROM
db1_ext_auth1) b
PREHOOK: type: QUERY
@@ -512,7 +512,7 @@ FROM "EXTERNAL_JDBC_SIMPLE_DERBY2_TABLE1"
Processor Tree:
ListSink
-Warning: Shuffle Join MERGEJOIN[10][tables = [$hdt$_0, $hdt$_1]] in Stage
'Reducer 2' is a cross product
+Warning: Shuffle Join MERGEJOIN[9][tables = [$hdt$_0, $hdt$_1]] in Stage
'Reducer 2' is a cross product
PREHOOK: query: SELECT db1_ext_auth1.ikey, b.ikey * 2 FROM db1_ext_auth1 JOIN
(SELECT * FROM db1_ext_auth1) b
PREHOOK: type: QUERY
PREHOOK: Input: default@db1_ext_auth1