[SPARK-20786][SQL] Improve ceil and floor handle the value which is not expected

## What changes were proposed in this pull request?

spark-sql>SELECT ceil(1234567890123456);
1234567890123456

spark-sql>SELECT ceil(12345678901234567);
12345678901234568

spark-sql>SELECT ceil(123456789012345678);
123456789012345680

when the length of the getText is greater than 16. long to double will be precision loss.

but mysql handle the value is ok.

mysql> SELECT ceil(1234567890123456);
+------------------------+
| ceil(1234567890123456) |
+------------------------+
|       1234567890123456 |
+------------------------+
1 row in set (0.00 sec)

mysql> SELECT ceil(12345678901234567);
+-------------------------+
| ceil(12345678901234567) |
+-------------------------+
|       12345678901234567 |
+-------------------------+
1 row in set (0.00 sec)

mysql> SELECT ceil(123456789012345678);
+--------------------------+
| ceil(123456789012345678) |
+--------------------------+
|       123456789012345678 |
+--------------------------+
1 row in set (0.00 sec)

## How was this patch tested?

Supplement the unit test.

Author: caoxuewen <cao.xuewen@zte.com.cn>

Closes #18016 from heary-cao/ceil_long.
This commit is contained in:
caoxuewen 2017-05-21 22:39:07 -07:00 committed by Xiao Li
parent 0f2f56c37b
commit 3c9eef35a8
4 changed files with 99 additions and 3 deletions

View file

@ -232,9 +232,10 @@ case class Ceil(child: Expression) extends UnaryMathExpression(math.ceil, "CEIL"
}
override def inputTypes: Seq[AbstractDataType] =
Seq(TypeCollection(DoubleType, DecimalType))
Seq(TypeCollection(LongType, DoubleType, DecimalType))
protected override def nullSafeEval(input: Any): Any = child.dataType match {
case LongType => input.asInstanceOf[Long]
case DoubleType => f(input.asInstanceOf[Double]).toLong
case DecimalType.Fixed(precision, scale) => input.asInstanceOf[Decimal].ceil
}
@ -347,9 +348,10 @@ case class Floor(child: Expression) extends UnaryMathExpression(math.floor, "FLO
}
override def inputTypes: Seq[AbstractDataType] =
Seq(TypeCollection(DoubleType, DecimalType))
Seq(TypeCollection(LongType, DoubleType, DecimalType))
protected override def nullSafeEval(input: Any): Any = child.dataType match {
case LongType => input.asInstanceOf[Long]
case DoubleType => f(input.asInstanceOf[Double]).toLong
case DecimalType.Fixed(precision, scale) => input.asInstanceOf[Decimal].floor
}

View file

@ -262,7 +262,7 @@ class AnalysisSuite extends AnalysisTest with ShouldMatchers {
val plan = testRelation2.select('c).orderBy(Floor('a).asc)
val expected = testRelation2.select(c, a)
.orderBy(Floor(Cast(a, DoubleType, Option(TimeZone.getDefault().getID))).asc).select(c)
.orderBy(Floor(Cast(a, LongType, Option(TimeZone.getDefault().getID))).asc).select(c)
checkAnalysis(plan, expected)
}

View file

@ -59,3 +59,17 @@ select cot(1);
select cot(null);
select cot(0);
select cot(-1);
-- ceil and ceiling
select ceiling(0);
select ceiling(1);
select ceil(1234567890123456);
select ceil(12345678901234567);
select ceiling(1234567890123456);
select ceiling(12345678901234567);
-- floor
select floor(0);
select floor(1);
select floor(1234567890123456);
select floor(12345678901234567);

View file

@ -316,3 +316,83 @@ select cot(-1)
struct<COT(CAST(-1 AS DOUBLE)):double>
-- !query 37 output
-0.6420926159343306
-- !query 38
select ceiling(0)
-- !query 38 schema
struct<CEIL(CAST(0 AS BIGINT)):bigint>
-- !query 38 output
0
-- !query 39
select ceiling(1)
-- !query 39 schema
struct<CEIL(CAST(1 AS BIGINT)):bigint>
-- !query 39 output
1
-- !query 40
select ceil(1234567890123456)
-- !query 40 schema
struct<CEIL(1234567890123456):bigint>
-- !query 40 output
1234567890123456
-- !query 41
select ceil(12345678901234567)
-- !query 41 schema
struct<CEIL(12345678901234567):bigint>
-- !query 41 output
12345678901234567
-- !query 42
select ceiling(1234567890123456)
-- !query 42 schema
struct<CEIL(1234567890123456):bigint>
-- !query 42 output
1234567890123456
-- !query 43
select ceiling(12345678901234567)
-- !query 43 schema
struct<CEIL(12345678901234567):bigint>
-- !query 43 output
12345678901234567
-- !query 44
select floor(0)
-- !query 44 schema
struct<FLOOR(CAST(0 AS BIGINT)):bigint>
-- !query 44 output
0
-- !query 45
select floor(1)
-- !query 45 schema
struct<FLOOR(CAST(1 AS BIGINT)):bigint>
-- !query 45 output
1
-- !query 46
select floor(1234567890123456)
-- !query 46 schema
struct<FLOOR(1234567890123456):bigint>
-- !query 46 output
1234567890123456
-- !query 47
select floor(12345678901234567)
-- !query 47 schema
struct<FLOOR(12345678901234567):bigint>
-- !query 47 output
12345678901234567