Skip to content

Commit

Permalink
[SPARK-20211][SQL][BACKPORT-2.2] Fix the Precision and Scale of Decim…
Browse files Browse the repository at this point in the history
…al Values when the Input is BigDecimal between -1.0 and 1.0

This PR is to backport apache#18244 to 2.2

---

The precision and scale of decimal values are wrong when the input is BigDecimal between -1.0 and 1.0.

The BigDecimal's precision is the digit count starts from the leftmost nonzero digit based on the [JAVA's BigDecimal definition](https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html). However, our Decimal decision follows the database decimal standard, which is the total number of digits, including both to the left and the right of the decimal point. Thus, this PR is to fix the issue by doing the conversion.

Before this PR, the following queries failed:
```SQL
select 1 > 0.0001
select floor(0.0001)
select ceil(0.0001)
```

Added test cases.

Author: gatorsmile <gatorsmile@gmail.com>

Closes apache#18297 from gatorsmile/backport18244.

(cherry picked from commit 6265119)
Signed-off-by: Wenchen Fan <wenchen@databricks.com>
  • Loading branch information
gatorsmile authored and Vinitha Gankidi committed Nov 29, 2017
1 parent 38255e9 commit 55d5bbe
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,15 @@ final class Decimal extends Ordered[Decimal] with Serializable {
def set(decimal: BigDecimal): Decimal = {
this.decimalVal = decimal
this.longVal = 0L
this._precision = decimal.precision
if (decimal.precision <= decimal.scale) {
// For Decimal, we expect the precision is equal to or large than the scale, however,
// in BigDecimal, the digit count starts from the leftmost nonzero digit of the exact
// result. For example, the precision of 0.01 equals to 1 based on the definition, but
// the scale is 2. The expected precision should be 3.
this._precision = decimal.scale + 1
} else {
this._precision = decimal.precision
}
this._scale = decimal.scale
this
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ class DecimalSuite extends SparkFunSuite with PrivateMethodTester {

test("creating decimals") {
checkDecimal(new Decimal(), "0", 1, 0)
checkDecimal(Decimal(BigDecimal("0.09")), "0.09", 3, 2)
checkDecimal(Decimal(BigDecimal("0.9")), "0.9", 2, 1)
checkDecimal(Decimal(BigDecimal("0.90")), "0.90", 3, 2)
checkDecimal(Decimal(BigDecimal("0.0")), "0.0", 2, 1)
checkDecimal(Decimal(BigDecimal("0")), "0", 1, 0)
checkDecimal(Decimal(BigDecimal("1.0")), "1.0", 2, 1)
checkDecimal(Decimal(BigDecimal("-0.09")), "-0.09", 3, 2)
checkDecimal(Decimal(BigDecimal("-0.9")), "-0.9", 2, 1)
checkDecimal(Decimal(BigDecimal("-0.90")), "-0.90", 3, 2)
checkDecimal(Decimal(BigDecimal("-1.0")), "-1.0", 2, 1)
checkDecimal(Decimal(BigDecimal("10.030")), "10.030", 5, 3)
checkDecimal(Decimal(BigDecimal("10.030"), 4, 1), "10.0", 4, 1)
checkDecimal(Decimal(BigDecimal("-9.95"), 4, 1), "-10.0", 4, 1)
Expand Down
24 changes: 24 additions & 0 deletions sql/core/src/test/resources/sql-tests/inputs/arithmetic.sql
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,27 @@ select 1 - 2;
select 2 * 5;
select 5 % 3;
select pmod(-7, 3);

-- math functions
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 ceiling(1234567890123456);
select ceil(0.01);
select ceiling(-0.10);

-- floor
select floor(0);
select floor(1);
select floor(1234567890123456);
select floor(0.01);
select floor(-0.10);

-- comparison operator
select 1 > 0.00001
134 changes: 133 additions & 1 deletion sql/core/src/test/resources/sql-tests/results/arithmetic.sql.out
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-- Automatically generated by SQLQueryTestSuite
-- Number of queries: 28
-- Number of queries: 44


-- !query 0
Expand Down Expand Up @@ -224,3 +224,135 @@ select pmod(-7, 3)
struct<pmod(-7, 3):int>
-- !query 27 output
2


-- !query 28
select cot(1)
-- !query 28 schema
struct<>
-- !query 28 output
org.apache.spark.sql.AnalysisException
Undefined function: 'cot'. This function is neither a registered temporary function nor a permanent function registered in the database 'default'.; line 1 pos 7


-- !query 29
select cot(null)
-- !query 29 schema
struct<>
-- !query 29 output
org.apache.spark.sql.AnalysisException
Undefined function: 'cot'. This function is neither a registered temporary function nor a permanent function registered in the database 'default'.; line 1 pos 7


-- !query 30
select cot(0)
-- !query 30 schema
struct<>
-- !query 30 output
org.apache.spark.sql.AnalysisException
Undefined function: 'cot'. This function is neither a registered temporary function nor a permanent function registered in the database 'default'.; line 1 pos 7


-- !query 31
select cot(-1)
-- !query 31 schema
struct<>
-- !query 31 output
org.apache.spark.sql.AnalysisException
Undefined function: 'cot'. This function is neither a registered temporary function nor a permanent function registered in the database 'default'.; line 1 pos 7


-- !query 32
select ceiling(0)
-- !query 32 schema
struct<CEIL(CAST(0 AS DOUBLE)):bigint>
-- !query 32 output
0


-- !query 33
select ceiling(1)
-- !query 33 schema
struct<CEIL(CAST(1 AS DOUBLE)):bigint>
-- !query 33 output
1


-- !query 34
select ceil(1234567890123456)
-- !query 34 schema
struct<CEIL(1234567890123456):bigint>
-- !query 34 output
1234567890123456


-- !query 35
select ceiling(1234567890123456)
-- !query 35 schema
struct<CEIL(1234567890123456):bigint>
-- !query 35 output
1234567890123456


-- !query 36
select ceil(0.01)
-- !query 36 schema
struct<CEIL(0.01):decimal(1,0)>
-- !query 36 output
1


-- !query 37
select ceiling(-0.10)
-- !query 37 schema
struct<CEIL(-0.10):decimal(1,0)>
-- !query 37 output
0


-- !query 38
select floor(0)
-- !query 38 schema
struct<FLOOR(CAST(0 AS DOUBLE)):bigint>
-- !query 38 output
0


-- !query 39
select floor(1)
-- !query 39 schema
struct<FLOOR(CAST(1 AS DOUBLE)):bigint>
-- !query 39 output
1


-- !query 40
select floor(1234567890123456)
-- !query 40 schema
struct<FLOOR(1234567890123456):bigint>
-- !query 40 output
1234567890123456


-- !query 41
select floor(0.01)
-- !query 41 schema
struct<FLOOR(0.01):decimal(1,0)>
-- !query 41 output
0


-- !query 42
select floor(-0.10)
-- !query 42 schema
struct<FLOOR(-0.10):decimal(1,0)>
-- !query 42 output
-1


-- !query 43
select 1 > 0.00001
-- !query 43 schema
struct<(CAST(1 AS BIGINT) > 0):boolean>
-- !query 43 output
true

0 comments on commit 55d5bbe

Please sign in to comment.