Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -2631,6 +2631,38 @@ private RelNode genJoinRelNode(RelNode leftRel, String leftTableAlias, RelNode r
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, "=");
Expand Down
18 changes: 18 additions & 0 deletions ql/src/java/org/apache/hadoop/hive/ql/parse/RowResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,24 @@ public Set<String> getTableNames() {
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);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
create table test(
a int
);

select * from test
join test using(a)
join test using(a);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

create table test(
a int
);

select * from test t1
join test t2 using(a)
join test t3 using(b);
77 changes: 77 additions & 0 deletions ql/src/test/queries/clientpositive/join_using_clause.q
Original file line number Diff line number Diff line change
@@ -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);
Original file line number Diff line number Diff line change
@@ -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'
Original file line number Diff line number Diff line change
@@ -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]
Loading