Skip to content
Snippets Groups Projects
Commit dce2f8c9 authored by Dilip Biswal's avatar Dilip Biswal Committed by Michael Armbrust
Browse files

[SPARK-8654][SQL] Analysis exception when using NULL IN (...) : invalid cast

In the analysis phase , while processing the rules for IN predicate, we
compare the in-list types to the lhs expression type and generate
cast operation if necessary. In the case of NULL [NOT] IN expr1 , we end up
generating cast between in list types to NULL like cast (1 as NULL) which
is not a valid cast.

The fix is to find a common type between LHS and RHS expressions and cast
all the expression to the common type.

Author: Dilip Biswal <dbiswal@us.ibm.com>

This patch had conflicts when merged, resolved by
Committer: Michael Armbrust <michael@databricks.com>

Closes #9036 from dilipbiswal/spark_8654_new.
parent 19ad1863
No related branches found
No related tags found
No related merge requests found
......@@ -304,7 +304,11 @@ object HiveTypeCoercion {
}
/**
* Convert all expressions in in() list to the left operator type
* Convert the value and in list expressions to the common operator type
* by looking at all the argument types and finding the closest one that
* all the arguments can be cast to. When no common operator type is found
* the original expression will be returned and an Analysis Exception will
* be raised at type checking phase.
*/
object InConversion extends Rule[LogicalPlan] {
def apply(plan: LogicalPlan): LogicalPlan = plan resolveExpressions {
......@@ -312,7 +316,10 @@ object HiveTypeCoercion {
case e if !e.childrenResolved => e
case i @ In(a, b) if b.exists(_.dataType != a.dataType) =>
i.makeCopy(Array(a, b.map(Cast(_, a.dataType))))
findWiderCommonType(i.children.map(_.dataType)) match {
case Some(finalDataType) => i.withNewChildren(i.children.map(Cast(_, finalDataType)))
case None => i
}
}
}
......
......@@ -153,4 +153,25 @@ class AnalysisSuite extends AnalysisTest {
checkAnalysis(plan, expected)
}
test("SPARK-8654: invalid CAST in NULL IN(...) expression") {
val plan = Project(Alias(In(Literal(null), Seq(Literal(1), Literal(2))), "a")() :: Nil,
LocalRelation()
)
assertAnalysisSuccess(plan)
}
test("SPARK-8654: different types in inlist but can be converted to a commmon type") {
val plan = Project(Alias(In(Literal(null), Seq(Literal(1), Literal(1.2345))), "a")() :: Nil,
LocalRelation()
)
assertAnalysisSuccess(plan)
}
test("SPARK-8654: check type compatibility error") {
val plan = Project(Alias(In(Literal(null), Seq(Literal(true), Literal(1))), "a")() :: Nil,
LocalRelation()
)
assertAnalysisError(plan, Seq("data type mismatch: Arguments must be same type"))
}
}
......@@ -470,7 +470,8 @@ class HiveTypeCoercionSuite extends PlanTest {
)
ruleTest(inConversion,
In(Literal("a"), Seq(Literal(1), Literal("b"))),
In(Literal("a"), Seq(Cast(Literal(1), StringType), Cast(Literal("b"), StringType)))
In(Cast(Literal("a"), StringType),
Seq(Cast(Literal(1), StringType), Cast(Literal("b"), StringType)))
)
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment