You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by kr...@apache.org on 2023/07/31 04:09:22 UTC
[hive] branch master updated: HIVE-27495: NPE when trying to transform using clause to on clause (Soumyakanti Das, reviewed by Stamatis Zampetakis, Stephen Carlin, John Sherman, Krisztian Kasa)
This is an automated email from the ASF dual-hosted git repository.
krisztiankasa 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 c03d45af62b HIVE-27495: NPE when trying to transform using clause to on clause (Soumyakanti Das, reviewed by Stamatis Zampetakis, Stephen Carlin, John Sherman, Krisztian Kasa)
c03d45af62b is described below
commit c03d45af62bc5f723688f4163eb964705d4d1e1b
Author: Soumyakanti Das <so...@cloudera.com>
AuthorDate: Sun Jul 30 21:09:15 2023 -0700
HIVE-27495: NPE when trying to transform using clause to on clause (Soumyakanti Das, reviewed by Stamatis Zampetakis, Stephen Carlin, John Sherman, Krisztian Kasa)
---
.../hadoop/hive/ql/parse/CalcitePlanner.java | 32 ++
.../apache/hadoop/hive/ql/parse/RowResolver.java | 18 ++
.../join_using_clause_ambiguous_table.q | 7 +
.../join_using_clause_wrong_column.q | 8 +
.../queries/clientpositive/join_using_clause.q | 77 +++++
.../join_using_clause_ambiguous_table.q.out | 13 +
.../join_using_clause_wrong_column.q.out | 13 +
.../clientpositive/llap/join_using_clause.q.out | 356 +++++++++++++++++++++
8 files changed, 524 insertions(+)
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java
index 662dbecddfa..ed4e5467adc 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java
@@ -2631,6 +2631,38 @@ public class CalcitePlanner extends SemanticAnalyzer {
unparseTranslator.addIdentifierTranslation((ASTNode) child);
}
namedColumns.add(columnName);
+
+ /*
+ In case of multiple joins, leftTableAlias can be null
+ as for the second join, the left side is a join token.
+
+ For example, if we have 3 tables with the following schemas:
+ t1 - (a), t2 - (a, b), t3 - (a, b, c)
+ and we were trying to run the following query:
+ select * from t1
+ join t2 using(a)
+ join t3 using(a);
+ For the second join, since left side is a join, leftTableAlias is null, and we have
+ to choose the correct alias to use from leftRR. Here we are choosing the rightmost
+ table containing column a, i.e., t2 and not t1.
+
+ And, for the query:
+ select * from t2
+ join t1 using(a)
+ join t3 using(b);
+ For the second join, leftTableAlias is again null, and the rightmost table containing
+ column b is t2 as b is not present in t1.
+ */
+ if (leftTableAlias == null) {
+ leftTableAlias = leftRR.getTableAliasContainingColumn(columnName);
+ }
+ // if it's still null, throw an exception as column is not present
+ // in left row resolver
+ if (leftTableAlias == null) {
+ throw new SemanticException("column '" + columnName +
+ "' not present in any of these tables: " + leftRR.getTableNames());
+ }
+
ASTNode left = ASTBuilder.qualifiedName(leftTableAlias, columnName);
ASTNode right = ASTBuilder.qualifiedName(rightTableAlias, columnName);
equal = (ASTNode) ParseDriver.adaptor.create(HiveParser.EQUAL, "=");
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/RowResolver.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/RowResolver.java
index 715e9bd6c88..dec7c57bc65 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/RowResolver.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/RowResolver.java
@@ -309,6 +309,24 @@ public class RowResolver implements Serializable{
return rslvMap.keySet();
}
+ /**
+ * Get alias of the last table containing column columnName
+ *
+ * @param columnName column
+ * @return table alias or null
+ */
+ public String getTableAliasContainingColumn(String columnName) {
+ String result = null;
+
+ for (Map.Entry<String, Map<String, ColumnInfo>> entry: this.rslvMap.entrySet()) {
+ if (entry.getValue().containsKey(columnName)) {
+ result = entry.getKey();
+ }
+ }
+
+ return result;
+ }
+
public String[] reverseLookup(String internalName) {
return invRslvMap.get(internalName);
}
diff --git a/ql/src/test/queries/clientnegative/join_using_clause_ambiguous_table.q b/ql/src/test/queries/clientnegative/join_using_clause_ambiguous_table.q
new file mode 100644
index 00000000000..19c3f6fc391
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/join_using_clause_ambiguous_table.q
@@ -0,0 +1,7 @@
+create table test(
+ a int
+);
+
+select * from test
+join test using(a)
+join test using(a);
diff --git a/ql/src/test/queries/clientnegative/join_using_clause_wrong_column.q b/ql/src/test/queries/clientnegative/join_using_clause_wrong_column.q
new file mode 100644
index 00000000000..2eb71d25bf0
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/join_using_clause_wrong_column.q
@@ -0,0 +1,8 @@
+
+create table test(
+ a int
+);
+
+select * from test t1
+join test t2 using(a)
+join test t3 using(b);
diff --git a/ql/src/test/queries/clientpositive/join_using_clause.q b/ql/src/test/queries/clientpositive/join_using_clause.q
new file mode 100644
index 00000000000..2a411d79ad9
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/join_using_clause.q
@@ -0,0 +1,77 @@
+
+create table test (
+ a int
+);
+
+insert into test values (1);
+
+create table test1 (
+ a int,
+ b int
+);
+
+insert into test1 values (1, 2);
+
+create table test2 (
+ a int,
+ b int,
+ c int
+);
+
+insert into test2 values (1, 2, 3);
+
+-- self join with 1 column
+select * from test t1
+join test t2 using(a)
+join test t3 using(a);
+
+explain cbo select * from test t1
+join test t2 using(a)
+join test t3 using(a);
+
+-- self join with multiple columns
+select * from test1 t1
+join test1 t2 using(a)
+join test1 t3 using(b);
+
+explain cbo select * from test1 t1
+join test1 t2 using(a)
+join test1 t3 using(b);
+
+-- joins with multiple tables and columns
+select * from test1 t1
+join test t2 using(a)
+join test2 t3 using(b);
+
+explain cbo select * from test1 t1
+join test t2 using(a)
+join test2 t3 using(b);
+
+select * from test t1
+join test1 t2 using(a)
+join test2 t3 using(b)
+join test2 t4 using(c);
+
+explain cbo select * from test t1
+join test1 t2 using(a)
+join test2 t3 using(b)
+join test2 t4 using(c);
+
+select * from test1 t1
+join test2 t2 using(a, b)
+join test2 t3 using(c, b)
+join test t4 using(a);
+
+explain cbo select * from test1 t1
+join test2 t2 using(a, b)
+join test2 t3 using(c, b)
+join test t4 using(a);
+
+-- joins without table alias
+select * from test1
+join test using(a)
+join test2 using(b);
+
+explain cbo select * from test1
+join test using(a)
+join test2 using(b);
diff --git a/ql/src/test/results/clientnegative/join_using_clause_ambiguous_table.q.out b/ql/src/test/results/clientnegative/join_using_clause_ambiguous_table.q.out
new file mode 100644
index 00000000000..628f8ad7614
--- /dev/null
+++ b/ql/src/test/results/clientnegative/join_using_clause_ambiguous_table.q.out
@@ -0,0 +1,13 @@
+PREHOOK: query: create table test(
+ a int
+)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@test
+POSTHOOK: query: create table test(
+ a int
+)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@test
+FAILED: SemanticException [Error 10008]: Line 4:5 Ambiguous table alias 'test'
diff --git a/ql/src/test/results/clientnegative/join_using_clause_wrong_column.q.out b/ql/src/test/results/clientnegative/join_using_clause_wrong_column.q.out
new file mode 100644
index 00000000000..3020ca46cdf
--- /dev/null
+++ b/ql/src/test/results/clientnegative/join_using_clause_wrong_column.q.out
@@ -0,0 +1,13 @@
+PREHOOK: query: create table test(
+ a int
+)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@test
+POSTHOOK: query: create table test(
+ a int
+)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@test
+FAILED: SemanticException column 'b' not present in any of these tables: [t1, t2]
diff --git a/ql/src/test/results/clientpositive/llap/join_using_clause.q.out b/ql/src/test/results/clientpositive/llap/join_using_clause.q.out
new file mode 100644
index 00000000000..af1b04c38b9
--- /dev/null
+++ b/ql/src/test/results/clientpositive/llap/join_using_clause.q.out
@@ -0,0 +1,356 @@
+PREHOOK: query: create table test (
+ a int
+)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@test
+POSTHOOK: query: create table test (
+ a int
+)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@test
+PREHOOK: query: insert into test values (1)
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@test
+POSTHOOK: query: insert into test values (1)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@test
+POSTHOOK: Lineage: test.a SCRIPT []
+PREHOOK: query: create table test1 (
+ a int,
+ b int
+)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@test1
+POSTHOOK: query: create table test1 (
+ a int,
+ b int
+)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@test1
+PREHOOK: query: insert into test1 values (1, 2)
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@test1
+POSTHOOK: query: insert into test1 values (1, 2)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@test1
+POSTHOOK: Lineage: test1.a SCRIPT []
+POSTHOOK: Lineage: test1.b SCRIPT []
+PREHOOK: query: create table test2 (
+ a int,
+ b int,
+ c int
+)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@test2
+POSTHOOK: query: create table test2 (
+ a int,
+ b int,
+ c int
+)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@test2
+PREHOOK: query: insert into test2 values (1, 2, 3)
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@test2
+POSTHOOK: query: insert into test2 values (1, 2, 3)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@test2
+POSTHOOK: Lineage: test2.a SCRIPT []
+POSTHOOK: Lineage: test2.b SCRIPT []
+POSTHOOK: Lineage: test2.c SCRIPT []
+PREHOOK: query: select * from test t1
+join test t2 using(a)
+join test t3 using(a)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test
+#### A masked pattern was here ####
+POSTHOOK: query: select * from test t1
+join test t2 using(a)
+join test t3 using(a)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test
+#### A masked pattern was here ####
+1
+PREHOOK: query: explain cbo select * from test t1
+join test t2 using(a)
+join test t3 using(a)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo select * from test t1
+join test t2 using(a)
+join test t3 using(a)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(a=[$1])
+ HiveJoin(condition=[=($1, $2)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveJoin(condition=[=($0, $1)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveProject(a=[$0])
+ HiveFilter(condition=[IS NOT NULL($0)])
+ HiveTableScan(table=[[default, test]], table:alias=[t1])
+ HiveProject(a=[$0])
+ HiveFilter(condition=[IS NOT NULL($0)])
+ HiveTableScan(table=[[default, test]], table:alias=[t2])
+ HiveProject(a=[$0])
+ HiveFilter(condition=[IS NOT NULL($0)])
+ HiveTableScan(table=[[default, test]], table:alias=[t3])
+
+PREHOOK: query: select * from test1 t1
+join test1 t2 using(a)
+join test1 t3 using(b)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test1
+#### A masked pattern was here ####
+POSTHOOK: query: select * from test1 t1
+join test1 t2 using(a)
+join test1 t3 using(b)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test1
+#### A masked pattern was here ####
+2 1 1 1
+PREHOOK: query: explain cbo select * from test1 t1
+join test1 t2 using(a)
+join test1 t3 using(b)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test1
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo select * from test1 t1
+join test1 t2 using(a)
+join test1 t3 using(b)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test1
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(b=[$1], a=[$2], a1=[$0], a2=[$3])
+ HiveJoin(condition=[=($1, $4)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveJoin(condition=[=($2, $0)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveProject(a=[$0], b=[$1])
+ HiveFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($1))])
+ HiveTableScan(table=[[default, test1]], table:alias=[t2])
+ HiveProject(a=[$0])
+ HiveFilter(condition=[IS NOT NULL($0)])
+ HiveTableScan(table=[[default, test1]], table:alias=[t1])
+ HiveProject(a=[$0], b=[$1])
+ HiveFilter(condition=[IS NOT NULL($1)])
+ HiveTableScan(table=[[default, test1]], table:alias=[t3])
+
+PREHOOK: query: select * from test1 t1
+join test t2 using(a)
+join test2 t3 using(b)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test
+PREHOOK: Input: default@test1
+PREHOOK: Input: default@test2
+#### A masked pattern was here ####
+POSTHOOK: query: select * from test1 t1
+join test t2 using(a)
+join test2 t3 using(b)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test
+POSTHOOK: Input: default@test1
+POSTHOOK: Input: default@test2
+#### A masked pattern was here ####
+2 1 1 1 3
+PREHOOK: query: explain cbo select * from test1 t1
+join test t2 using(a)
+join test2 t3 using(b)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test
+PREHOOK: Input: default@test1
+PREHOOK: Input: default@test2
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo select * from test1 t1
+join test t2 using(a)
+join test2 t3 using(b)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test
+POSTHOOK: Input: default@test1
+POSTHOOK: Input: default@test2
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(b=[$1], a=[$0], a1=[$2], a2=[$3], c=[$5])
+ HiveJoin(condition=[=($1, $4)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveJoin(condition=[=($0, $2)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveProject(a=[$0], b=[$1])
+ HiveFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($1))])
+ HiveTableScan(table=[[default, test1]], table:alias=[t1])
+ HiveProject(a=[$0])
+ HiveFilter(condition=[IS NOT NULL($0)])
+ HiveTableScan(table=[[default, test]], table:alias=[t2])
+ HiveProject(a=[$0], b=[$1], c=[$2])
+ HiveFilter(condition=[IS NOT NULL($1)])
+ HiveTableScan(table=[[default, test2]], table:alias=[t3])
+
+PREHOOK: query: select * from test t1
+join test1 t2 using(a)
+join test2 t3 using(b)
+join test2 t4 using(c)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test
+PREHOOK: Input: default@test1
+PREHOOK: Input: default@test2
+#### A masked pattern was here ####
+POSTHOOK: query: select * from test t1
+join test1 t2 using(a)
+join test2 t3 using(b)
+join test2 t4 using(c)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test
+POSTHOOK: Input: default@test1
+POSTHOOK: Input: default@test2
+#### A masked pattern was here ####
+3 1 1 2 1 2 1 2
+PREHOOK: query: explain cbo select * from test t1
+join test1 t2 using(a)
+join test2 t3 using(b)
+join test2 t4 using(c)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test
+PREHOOK: Input: default@test1
+PREHOOK: Input: default@test2
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo select * from test t1
+join test1 t2 using(a)
+join test2 t3 using(b)
+join test2 t4 using(c)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test
+POSTHOOK: Input: default@test1
+POSTHOOK: Input: default@test2
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(c=[$2], a=[$8], a1=[$6], b=[$7], a2=[$0], b1=[$1], a3=[$3], b2=[$4])
+ HiveJoin(condition=[=($7, $1)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveJoin(condition=[=($2, $5)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveProject(a=[$0], b=[$1], c=[$2])
+ HiveFilter(condition=[AND(IS NOT NULL($1), IS NOT NULL($2))])
+ HiveTableScan(table=[[default, test2]], table:alias=[t3])
+ HiveProject(a=[$0], b=[$1], c=[$2])
+ HiveFilter(condition=[IS NOT NULL($2)])
+ HiveTableScan(table=[[default, test2]], table:alias=[t4])
+ HiveProject(a=[$0], b=[$1], a0=[$2])
+ HiveJoin(condition=[=($2, $0)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveProject(a=[$0], b=[$1])
+ HiveFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($1))])
+ HiveTableScan(table=[[default, test1]], table:alias=[t2])
+ HiveProject(a=[$0])
+ HiveFilter(condition=[IS NOT NULL($0)])
+ HiveTableScan(table=[[default, test]], table:alias=[t1])
+
+PREHOOK: query: select * from test1 t1
+join test2 t2 using(a, b)
+join test2 t3 using(c, b)
+join test t4 using(a)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test
+PREHOOK: Input: default@test1
+PREHOOK: Input: default@test2
+#### A masked pattern was here ####
+POSTHOOK: query: select * from test1 t1
+join test2 t2 using(a, b)
+join test2 t3 using(c, b)
+join test t4 using(a)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test
+POSTHOOK: Input: default@test1
+POSTHOOK: Input: default@test2
+#### A masked pattern was here ####
+1 2 2 3 2 3
+PREHOOK: query: explain cbo select * from test1 t1
+join test2 t2 using(a, b)
+join test2 t3 using(c, b)
+join test t4 using(a)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test
+PREHOOK: Input: default@test1
+PREHOOK: Input: default@test2
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo select * from test1 t1
+join test2 t2 using(a, b)
+join test2 t3 using(c, b)
+join test t4 using(a)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test
+POSTHOOK: Input: default@test1
+POSTHOOK: Input: default@test2
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(a=[$5], b=[$4], b1=[$1], c=[$2], b2=[$6], c1=[$7])
+ HiveJoin(condition=[AND(=($2, $7), =($1, $6))], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveJoin(condition=[AND(=($3, $0), =($4, $1))], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveProject(a=[$0], b=[$1], c=[$2])
+ HiveFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($1), IS NOT NULL($2))])
+ HiveTableScan(table=[[default, test2]], table:alias=[t2])
+ HiveProject(a=[$0], b=[$1])
+ HiveFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($1))])
+ HiveTableScan(table=[[default, test1]], table:alias=[t1])
+ HiveProject(a=[$0], b=[$1], c=[$2], a0=[$3])
+ HiveJoin(condition=[=($0, $3)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveProject(a=[$0], b=[$1], c=[$2])
+ HiveFilter(condition=[AND(IS NOT NULL($2), IS NOT NULL($1), IS NOT NULL($0))])
+ HiveTableScan(table=[[default, test2]], table:alias=[t3])
+ HiveProject(a=[$0])
+ HiveFilter(condition=[IS NOT NULL($0)])
+ HiveTableScan(table=[[default, test]], table:alias=[t4])
+
+PREHOOK: query: select * from test1
+join test using(a)
+join test2 using(b)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test
+PREHOOK: Input: default@test1
+PREHOOK: Input: default@test2
+#### A masked pattern was here ####
+POSTHOOK: query: select * from test1
+join test using(a)
+join test2 using(b)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test
+POSTHOOK: Input: default@test1
+POSTHOOK: Input: default@test2
+#### A masked pattern was here ####
+2 1 1 1 3
+PREHOOK: query: explain cbo select * from test1
+join test using(a)
+join test2 using(b)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@test
+PREHOOK: Input: default@test1
+PREHOOK: Input: default@test2
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo select * from test1
+join test using(a)
+join test2 using(b)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@test
+POSTHOOK: Input: default@test1
+POSTHOOK: Input: default@test2
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject(b=[$1], a=[$0], a1=[$2], a2=[$3], c=[$5])
+ HiveJoin(condition=[=($1, $4)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveJoin(condition=[=($0, $2)], joinType=[inner], algorithm=[none], cost=[not available])
+ HiveProject(a=[$0], b=[$1])
+ HiveFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($1))])
+ HiveTableScan(table=[[default, test1]], table:alias=[test1])
+ HiveProject(a=[$0])
+ HiveFilter(condition=[IS NOT NULL($0)])
+ HiveTableScan(table=[[default, test]], table:alias=[test])
+ HiveProject(a=[$0], b=[$1], c=[$2])
+ HiveFilter(condition=[IS NOT NULL($1)])
+ HiveTableScan(table=[[default, test2]], table:alias=[test2])
+