Skip to content

Commit

Permalink
[SPARK-15557] [SQL] cast the string into DoubleType when it's used to…
Browse files Browse the repository at this point in the history
…gether with decimal

In this case, the result type of the expression becomes DECIMAL(38, 36) as we promote the individual string literals to DECIMAL(38, 18) when we handle string promotions for `BinaryArthmaticExpression`.

I think we need to cast the string literals to Double type instead. I looked at the history and found that  this was changed to use decimal instead of double to avoid potential loss of precision when we cast decimal to double.

To double check i ran the query against hive, mysql. This query returns non NULL result for both the databases and both promote the expression to use double.
Here is the output.

- Hive
```SQL
hive> create table l2 as select (cast(99 as decimal(19,6)) + '2') from l1;
OK
hive> describe l2;
OK
_c0                 	double
```
- MySQL
```SQL
mysql> create table foo2 as select (cast(99 as decimal(19,6)) + '2') from test;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> describe foo2;
+-----------------------------------+--------+------+-----+---------+-------+
| Field                             | Type   | Null | Key | Default | Extra |
+-----------------------------------+--------+------+-----+---------+-------+
| (cast(99 as decimal(19,6)) + '2') | double | NO   |     | 0       |       |
+-----------------------------------+--------+------+-----+---------+-------+
```

## How was this patch tested?
Added a new test in SQLQuerySuite

Author: Dilip Biswal <[email protected]>

Closes #13368 from dilipbiswal/spark-15557.

(cherry picked from commit dfe2cbe)
Signed-off-by: Davies Liu <[email protected]>
  • Loading branch information
dilipbiswal authored and davies committed May 31, 2016
1 parent acf56c5 commit 8657942
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,6 @@ object TypeCoercion {
// Skip nodes who's children have not been resolved yet.
case e if !e.childrenResolved => e

case a @ BinaryArithmetic(left @ StringType(), right @ DecimalType.Expression(_, _)) =>
a.makeCopy(Array(Cast(left, DecimalType.SYSTEM_DEFAULT), right))
case a @ BinaryArithmetic(left @ DecimalType.Expression(_, _), right @ StringType()) =>
a.makeCopy(Array(left, Cast(right, DecimalType.SYSTEM_DEFAULT)))

case a @ BinaryArithmetic(left @ StringType(), right) =>
a.makeCopy(Array(Cast(left, DoubleType), right))
case a @ BinaryArithmetic(left, right @ StringType()) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,7 @@ class AnalysisSuite extends AnalysisTest {
assert(pl(0).dataType == DoubleType)
assert(pl(1).dataType == DoubleType)
assert(pl(2).dataType == DoubleType)
// StringType will be promoted into Decimal(38, 18)
assert(pl(3).dataType == DecimalType(38, 22))
assert(pl(3).dataType == DoubleType)
assert(pl(4).dataType == DoubleType)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,13 +446,13 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
// Number and String conflict: resolve the type as number in this query.
checkAnswer(
sql("select num_str + 1.2 from jsonTable where num_str > 14"),
Row(BigDecimal("92233720368547758071.2"))
Row(92233720368547758071.2)
)

// Number and String conflict: resolve the type as number in this query.
checkAnswer(
sql("select num_str + 1.2 from jsonTable where num_str >= 92233720368547758060"),
Row(new java.math.BigDecimal("92233720368547758071.2"))
Row(new java.math.BigDecimal("92233720368547758071.2").doubleValue)
)

// String and Boolean conflict: resolve the type as string.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1560,4 +1560,23 @@ class SQLQuerySuite extends QueryTest with SQLTestUtils with TestHiveSingleton {
checkAnswer(sql("SELECT * FROM tbl"), Row(1, "a"))
}
}

test("spark-15557 promote string test") {
withTable("tbl") {
sql("CREATE TABLE tbl(c1 string, c2 string)")
sql("insert into tbl values ('3', '2.3')")
checkAnswer(
sql("select (cast (99 as decimal(19,6)) + cast('3' as decimal)) * cast('2.3' as decimal)"),
Row(204.0)
)
checkAnswer(
sql("select (cast(99 as decimal(19,6)) + '3') *'2.3' from tbl"),
Row(234.6)
)
checkAnswer(
sql("select (cast(99 as decimal(19,6)) + c1) * c2 from tbl"),
Row(234.6)
)
}
}
}

0 comments on commit 8657942

Please sign in to comment.