aboutsummaryrefslogtreecommitdiff
path: root/sql/catalyst/src/test
diff options
context:
space:
mode:
authorWenchen Fan <wenchen@databricks.com>2016-08-03 11:15:09 -0700
committerYin Huai <yhuai@databricks.com>2016-08-03 11:15:09 -0700
commitb55f34370f695de355b72c1518b5f2a45c324af0 (patch)
tree37b2d3e984c8de7e1c2e1cf43d31eed716981077 /sql/catalyst/src/test
parent639df046a250873c26446a037cb832ab28cb5272 (diff)
downloadspark-b55f34370f695de355b72c1518b5f2a45c324af0.tar.gz
spark-b55f34370f695de355b72c1518b5f2a45c324af0.tar.bz2
spark-b55f34370f695de355b72c1518b5f2a45c324af0.zip
[SPARK-16714][SPARK-16735][SPARK-16646] array, map, greatest, least's type coercion should handle decimal type
## What changes were proposed in this pull request? Here is a table about the behaviours of `array`/`map` and `greatest`/`least` in Hive, MySQL and Postgres: | |Hive|MySQL|Postgres| |---|---|---|---|---| |`array`/`map`|can find a wider type with decimal type arguments, and will truncate the wider decimal type if necessary|can find a wider type with decimal type arguments, no truncation problem|can find a wider type with decimal type arguments, no truncation problem| |`greatest`/`least`|can find a wider type with decimal type arguments, and truncate if necessary, but can't do string promotion|can find a wider type with decimal type arguments, no truncation problem, but can't do string promotion|can find a wider type with decimal type arguments, no truncation problem, but can't do string promotion| I think these behaviours makes sense and Spark SQL should follow them. This PR fixes `array` and `map` by using `findWiderCommonType` to get the wider type. This PR fixes `greatest` and `least` by add a `findWiderTypeWithoutStringPromotion`, which provides similar semantic of `findWiderCommonType`, but without string promotion. ## How was this patch tested? new tests in `TypeCoersionSuite` Author: Wenchen Fan <wenchen@databricks.com> Author: Yin Huai <yhuai@databricks.com> Closes #14439 from cloud-fan/bug.
Diffstat (limited to 'sql/catalyst/src/test')
-rw-r--r--sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/ExpressionTypeCheckingSuite.scala1
-rw-r--r--sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionSuite.scala67
2 files changed, 67 insertions, 1 deletions
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/ExpressionTypeCheckingSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/ExpressionTypeCheckingSuite.scala
index 35f75697b7..542e654bbc 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/ExpressionTypeCheckingSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/ExpressionTypeCheckingSuite.scala
@@ -209,7 +209,6 @@ class ExpressionTypeCheckingSuite extends SparkFunSuite {
for (operator <- Seq[(Seq[Expression] => Expression)](Greatest, Least)) {
assertError(operator(Seq('booleanField)), "requires at least 2 arguments")
assertError(operator(Seq('intField, 'stringField)), "should all have the same type")
- assertError(operator(Seq('intField, 'decimalField)), "should all have the same type")
assertError(operator(Seq('mapField, 'mapField)), "does not support ordering")
}
}
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionSuite.scala
index 971c99b671..a13c45fe2f 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionSuite.scala
@@ -283,6 +283,24 @@ class TypeCoercionSuite extends PlanTest {
:: Cast(Literal(1), StringType)
:: Cast(Literal("a"), StringType)
:: Nil))
+
+ ruleTest(TypeCoercion.FunctionArgumentConversion,
+ CreateArray(Literal.create(null, DecimalType(5, 3))
+ :: Literal(1)
+ :: Nil),
+ CreateArray(Literal.create(null, DecimalType(5, 3)).cast(DecimalType(13, 3))
+ :: Literal(1).cast(DecimalType(13, 3))
+ :: Nil))
+
+ ruleTest(TypeCoercion.FunctionArgumentConversion,
+ CreateArray(Literal.create(null, DecimalType(5, 3))
+ :: Literal.create(null, DecimalType(22, 10))
+ :: Literal.create(null, DecimalType(38, 38))
+ :: Nil),
+ CreateArray(Literal.create(null, DecimalType(5, 3)).cast(DecimalType(38, 38))
+ :: Literal.create(null, DecimalType(22, 10)).cast(DecimalType(38, 38))
+ :: Literal.create(null, DecimalType(38, 38)).cast(DecimalType(38, 38))
+ :: Nil))
}
test("CreateMap casts") {
@@ -298,6 +316,17 @@ class TypeCoercionSuite extends PlanTest {
:: Cast(Literal.create(2.0, FloatType), FloatType)
:: Literal("b")
:: Nil))
+ ruleTest(TypeCoercion.FunctionArgumentConversion,
+ CreateMap(Literal.create(null, DecimalType(5, 3))
+ :: Literal("a")
+ :: Literal.create(2.0, FloatType)
+ :: Literal("b")
+ :: Nil),
+ CreateMap(Literal.create(null, DecimalType(5, 3)).cast(DoubleType)
+ :: Literal("a")
+ :: Literal.create(2.0, FloatType).cast(DoubleType)
+ :: Literal("b")
+ :: Nil))
// type coercion for map values
ruleTest(TypeCoercion.FunctionArgumentConversion,
CreateMap(Literal(1)
@@ -310,6 +339,17 @@ class TypeCoercionSuite extends PlanTest {
:: Literal(2)
:: Cast(Literal(3.0), StringType)
:: Nil))
+ ruleTest(TypeCoercion.FunctionArgumentConversion,
+ CreateMap(Literal(1)
+ :: Literal.create(null, DecimalType(38, 0))
+ :: Literal(2)
+ :: Literal.create(null, DecimalType(38, 38))
+ :: Nil),
+ CreateMap(Literal(1)
+ :: Literal.create(null, DecimalType(38, 0)).cast(DecimalType(38, 38))
+ :: Literal(2)
+ :: Literal.create(null, DecimalType(38, 38)).cast(DecimalType(38, 38))
+ :: Nil))
// type coercion for both map keys and values
ruleTest(TypeCoercion.FunctionArgumentConversion,
CreateMap(Literal(1)
@@ -344,6 +384,33 @@ class TypeCoercionSuite extends PlanTest {
:: Cast(Literal(1), DecimalType(22, 0))
:: Cast(Literal(new java.math.BigDecimal("1000000000000000000000")), DecimalType(22, 0))
:: Nil))
+ ruleTest(TypeCoercion.FunctionArgumentConversion,
+ operator(Literal(1.0)
+ :: Literal.create(null, DecimalType(10, 5))
+ :: Literal(1)
+ :: Nil),
+ operator(Literal(1.0).cast(DoubleType)
+ :: Literal.create(null, DecimalType(10, 5)).cast(DoubleType)
+ :: Literal(1).cast(DoubleType)
+ :: Nil))
+ ruleTest(TypeCoercion.FunctionArgumentConversion,
+ operator(Literal.create(null, DecimalType(15, 0))
+ :: Literal.create(null, DecimalType(10, 5))
+ :: Literal(1)
+ :: Nil),
+ operator(Literal.create(null, DecimalType(15, 0)).cast(DecimalType(20, 5))
+ :: Literal.create(null, DecimalType(10, 5)).cast(DecimalType(20, 5))
+ :: Literal(1).cast(DecimalType(20, 5))
+ :: Nil))
+ ruleTest(TypeCoercion.FunctionArgumentConversion,
+ operator(Literal.create(2L, LongType)
+ :: Literal(1)
+ :: Literal.create(null, DecimalType(10, 5))
+ :: Nil),
+ operator(Literal.create(2L, LongType).cast(DecimalType(25, 5))
+ :: Literal(1).cast(DecimalType(25, 5))
+ :: Literal.create(null, DecimalType(10, 5)).cast(DecimalType(25, 5))
+ :: Nil))
}
}