IMPALA-3125: Fix assignment of equality predicates from an outer-join On-clause.

Impala used to incorrectly assign On-clause equality predicates from an
outer join if those predicates referenced multiple tables, but only one
side of the outer join.

The fix is to add an additional check in Analyzer.getEqJoinConjuncts()
to prevent that incorrect assignment.

Change-Id: I719e0eeacccad070b1f9509d80aaf761b572add0
Reviewed-on: http://gerrit.cloudera.org:8080/4986
Reviewed-by: Alex Behm <alex.behm@cloudera.com>
Tested-by: Internal Jenkins
This commit is contained in:
Alex Behm
2016-11-07 17:32:57 -08:00
committed by Internal Jenkins
parent 852e272b32
commit 12cc508178
2 changed files with 44 additions and 3 deletions

View File

@@ -1316,9 +1316,11 @@ public class Analyzer {
Expr e = globalState_.conjuncts.get(conjunctId);
Preconditions.checkState(e != null);
if (!canEvalFullOuterJoinedConjunct(e, nodeTblRefIds) ||
!canEvalAntiJoinedConjunct(e, nodeTblRefIds)) {
!canEvalAntiJoinedConjunct(e, nodeTblRefIds) ||
!canEvalOuterJoinedConjunct(e, nodeTblRefIds)) {
continue;
}
if (ojClauseConjuncts != null && !ojClauseConjuncts.contains(conjunctId)) continue;
result.add(e);
}
@@ -1326,8 +1328,8 @@ public class Analyzer {
}
/**
* Checks if a conjunct can be evaluated at a node materializing a list of tuple ids
* 'tids'.
* Returns false if 'e' references a full outer joined tuple and it is incorrect to
* evaluate 'e' at a node materializing 'tids'. Returns true otherwise.
*/
public boolean canEvalFullOuterJoinedConjunct(Expr e, List<TupleId> tids) {
TableRef fullOuterJoin = getFullOuterJoinRef(e);
@@ -1335,6 +1337,16 @@ public class Analyzer {
return tids.containsAll(fullOuterJoin.getAllTableRefIds());
}
/**
* Returns false if 'e' originates from an outer-join On-clause and it is incorrect to
* evaluate 'e' at a node materializing 'tids'. Returns true otherwise.
*/
public boolean canEvalOuterJoinedConjunct(Expr e, List<TupleId> tids) {
TableRef outerJoin = globalState_.ojClauseByConjunct.get(e.getId());
if (outerJoin == null) return true;
return tids.containsAll(outerJoin.getAllTableRefIds());
}
/**
* Returns true if predicate 'e' can be correctly evaluated by a tree materializing
* 'tupleIds', otherwise false:

View File

@@ -890,3 +890,32 @@ PLAN-ROOT SINK
04:SCAN HDFS [functional.alltypestiny e]
partitions=4/4 files=4 size=460B
====
# IMPALA-3125: Test that the On-clause predicates from an outer join are assigned to the
# corresponding outer-join node, even if the predicates do not reference the join rhs.
select a.id aid, b.id bid, a.int_col aint, b.int_col bint
from functional.alltypes a
inner join functional.alltypes b
on a.int_col = b.int_col
left outer join functional.alltypes c
on a.id = b.id and b.bigint_col = c.bigint_col
---- PLAN
PLAN-ROOT SINK
|
04:HASH JOIN [LEFT OUTER JOIN]
| hash predicates: b.bigint_col = c.bigint_col
| other join predicates: a.id = b.id
|
|--02:SCAN HDFS [functional.alltypes c]
| partitions=24/24 files=24 size=478.45KB
|
03:HASH JOIN [INNER JOIN]
| hash predicates: b.int_col = a.int_col
| runtime filters: RF000 <- a.int_col
|
|--00:SCAN HDFS [functional.alltypes a]
| partitions=24/24 files=24 size=478.45KB
|
01:SCAN HDFS [functional.alltypes b]
partitions=24/24 files=24 size=478.45KB
runtime filters: RF000 -> b.int_col
====