Skip to content

Commit

Permalink
HIVE-13298 : nested join support causes undecipherable errors in Sema…
Browse files Browse the repository at this point in the history
…nticAnalyzer (Sergey Shelukhin, reviewed by Ashutosh Chauhan)
  • Loading branch information
sershe-apache committed Mar 21, 2016
1 parent 48aefe4 commit a6155b7
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 8 deletions.
38 changes: 30 additions & 8 deletions ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
Original file line number Diff line number Diff line change
Expand Up @@ -8379,6 +8379,7 @@ private QBJoinTree genJoinTree(QB qb, ASTNode joinParseTree,
QBJoinTree joinTree = new QBJoinTree();
JoinCond[] condn = new JoinCond[1];

int joinType = joinParseTree.getToken().getType();
switch (joinParseTree.getToken().getType()) {
case HiveParser.TOK_LEFTOUTERJOIN:
joinTree.setNoOuterJoin(false);
Expand Down Expand Up @@ -8406,10 +8407,27 @@ private QBJoinTree genJoinTree(QB qb, ASTNode joinParseTree,

ASTNode left = (ASTNode) joinParseTree.getChild(0);
ASTNode right = (ASTNode) joinParseTree.getChild(1);

if ((left.getToken().getType() == HiveParser.TOK_TABREF)
|| (left.getToken().getType() == HiveParser.TOK_SUBQUERY)
|| (left.getToken().getType() == HiveParser.TOK_PTBLFUNCTION)) {
boolean isValidLeftToken = isValidJoinSide(left);
boolean isJoinLeftToken = !isValidLeftToken && isJoinToken(left);
boolean isValidRightToken = isValidJoinSide(right);
boolean isJoinRightToken = !isValidRightToken && isJoinToken(right);
// TODO: if we didn't care about the column order, we could switch join sides here
// for TOK_JOIN and TOK_FULLOUTERJOIN.
if (!isValidLeftToken && !isJoinLeftToken) {
throw new SemanticException("Invalid token on the left side of the join: "
+ left.getToken().getText() + "; please rewrite your query");
} else if (!isValidRightToken) {
String advice= "";
if (isJoinRightToken && !isJoinLeftToken) {
advice = "; for example, put the nested join on the left side, or nest joins differently";
} else if (isJoinRightToken) {
advice = "; for example, nest joins differently";
}
throw new SemanticException("Invalid token on the right side of the join: "
+ right.getToken().getText() + "; please rewrite your query" + advice);
}

if (isValidLeftToken) {
String tableName = getUnescapedUnqualifiedTableName((ASTNode) left.getChild(0))
.toLowerCase();
String alias = extractJoinAlias(left, tableName);
Expand All @@ -8423,7 +8441,7 @@ private QBJoinTree genJoinTree(QB qb, ASTNode joinParseTree,
joinTree.setId(qb.getId());
joinTree.getAliasToOpInfo().put(
getModifiedAlias(qb, alias), aliasToOpInfo.get(alias));
} else if (isJoinToken(left)) {
} else if (isJoinLeftToken) {
QBJoinTree leftTree = genJoinTree(qb, left, aliasToOpInfo);
joinTree.setJoinSrc(leftTree);
String[] leftChildAliases = leftTree.getLeftAliases();
Expand All @@ -8437,9 +8455,7 @@ private QBJoinTree genJoinTree(QB qb, ASTNode joinParseTree,
assert (false);
}

if ((right.getToken().getType() == HiveParser.TOK_TABREF)
|| (right.getToken().getType() == HiveParser.TOK_SUBQUERY)
|| (right.getToken().getType() == HiveParser.TOK_PTBLFUNCTION)) {
if (isValidRightToken) {
String tableName = getUnescapedUnqualifiedTableName((ASTNode) right.getChild(0))
.toLowerCase();
String alias = extractJoinAlias(right, tableName);
Expand Down Expand Up @@ -8529,6 +8545,12 @@ private QBJoinTree genJoinTree(QB qb, ASTNode joinParseTree,
return joinTree;
}

private static boolean isValidJoinSide(ASTNode right) {
return (right.getToken().getType() == HiveParser.TOK_TABREF)
|| (right.getToken().getType() == HiveParser.TOK_SUBQUERY)
|| (right.getToken().getType() == HiveParser.TOK_PTBLFUNCTION);
}

private String extractJoinAlias(ASTNode node, String tableName) {
// ptf node form is:
// ^(TOK_PTBLFUNCTION $name $alias? partitionTableFunctionSource partitioningSpec? expression*)
Expand Down
12 changes: 12 additions & 0 deletions ql/src/test/queries/clientnegative/right_side_join.q
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
set hive.cbo.enable=false;

explain
select *
from alltypesorc,
(
(select csmallint from alltypesorc) a
left join
(select csmallint from alltypesorc) b
on a.csmallint = b.csmallint
);

1 change: 1 addition & 0 deletions ql/src/test/results/clientnegative/right_side_join.q.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FAILED: SemanticException Invalid token on the right side of the join: TOK_LEFTOUTERJOIN; please rewrite your query; for example, put the nested join on the left side, or nest joins differently

0 comments on commit a6155b7

Please sign in to comment.