Skip to content

Commit ba1737c

Browse files
srinathshankarrxin
authored andcommitted
[SPARK-17158][SQL] Change error message for out of range numeric literals
## What changes were proposed in this pull request? Modifies error message for numeric literals to Numeric literal <literal> does not fit in range [min, max] for type <T> ## How was this patch tested? Fixed up the error messages for literals.sql in SqlQueryTestSuite and re-ran via sbt. Also fixed up error messages in ExpressionParserSuite Author: Srinath Shankar <[email protected]> Closes #14721 from srinathshankar/sc4296.
1 parent a117afa commit ba1737c

File tree

3 files changed

+27
-17
lines changed

3 files changed

+27
-17
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,10 +1278,17 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with Logging {
12781278
}
12791279

12801280
/** Create a numeric literal expression. */
1281-
private def numericLiteral(ctx: NumberContext)(f: String => Any): Literal = withOrigin(ctx) {
1282-
val raw = ctx.getText
1281+
private def numericLiteral
1282+
(ctx: NumberContext, minValue: BigDecimal, maxValue: BigDecimal, typeName: String)
1283+
(converter: String => Any): Literal = withOrigin(ctx) {
1284+
val rawStrippedQualifier = ctx.getText.substring(0, ctx.getText.length - 1)
12831285
try {
1284-
Literal(f(raw.substring(0, raw.length - 1)))
1286+
val rawBigDecimal = BigDecimal(rawStrippedQualifier)
1287+
if (rawBigDecimal < minValue || rawBigDecimal > maxValue) {
1288+
throw new ParseException(s"Numeric literal ${rawStrippedQualifier} does not " +
1289+
s"fit in range [${minValue}, ${maxValue}] for type ${typeName}", ctx)
1290+
}
1291+
Literal(converter(rawStrippedQualifier))
12851292
} catch {
12861293
case e: NumberFormatException =>
12871294
throw new ParseException(e.getMessage, ctx)
@@ -1291,29 +1298,29 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with Logging {
12911298
/**
12921299
* Create a Byte Literal expression.
12931300
*/
1294-
override def visitTinyIntLiteral(ctx: TinyIntLiteralContext): Literal = numericLiteral(ctx) {
1295-
_.toByte
1301+
override def visitTinyIntLiteral(ctx: TinyIntLiteralContext): Literal = {
1302+
numericLiteral(ctx, Byte.MinValue, Byte.MaxValue, ByteType.simpleString)(_.toByte)
12961303
}
12971304

12981305
/**
12991306
* Create a Short Literal expression.
13001307
*/
1301-
override def visitSmallIntLiteral(ctx: SmallIntLiteralContext): Literal = numericLiteral(ctx) {
1302-
_.toShort
1308+
override def visitSmallIntLiteral(ctx: SmallIntLiteralContext): Literal = {
1309+
numericLiteral(ctx, Short.MinValue, Short.MaxValue, ShortType.simpleString)(_.toShort)
13031310
}
13041311

13051312
/**
13061313
* Create a Long Literal expression.
13071314
*/
1308-
override def visitBigIntLiteral(ctx: BigIntLiteralContext): Literal = numericLiteral(ctx) {
1309-
_.toLong
1315+
override def visitBigIntLiteral(ctx: BigIntLiteralContext): Literal = {
1316+
numericLiteral(ctx, Long.MinValue, Long.MaxValue, LongType.simpleString)(_.toLong)
13101317
}
13111318

13121319
/**
13131320
* Create a Double Literal expression.
13141321
*/
1315-
override def visitDoubleLiteral(ctx: DoubleLiteralContext): Literal = numericLiteral(ctx) {
1316-
_.toDouble
1322+
override def visitDoubleLiteral(ctx: DoubleLiteralContext): Literal = {
1323+
numericLiteral(ctx, Double.MinValue, Double.MaxValue, DoubleType.simpleString)(_.toDouble)
13171324
}
13181325

13191326
/**

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,18 +375,21 @@ class ExpressionParserSuite extends PlanTest {
375375

376376
// Tiny Int Literal
377377
assertEqual("10Y", Literal(10.toByte))
378-
intercept("-1000Y")
378+
intercept("-1000Y", s"does not fit in range [${Byte.MinValue}, ${Byte.MaxValue}]")
379379

380380
// Small Int Literal
381381
assertEqual("10S", Literal(10.toShort))
382-
intercept("40000S")
382+
intercept("40000S", s"does not fit in range [${Short.MinValue}, ${Short.MaxValue}]")
383383

384384
// Long Int Literal
385385
assertEqual("10L", Literal(10L))
386-
intercept("78732472347982492793712334L")
386+
intercept("78732472347982492793712334L",
387+
s"does not fit in range [${Long.MinValue}, ${Long.MaxValue}]")
387388

388389
// Double Literal
389390
assertEqual("10.0D", Literal(10.0D))
391+
intercept("-1.8E308D", s"does not fit in range")
392+
intercept("1.8E308D", s"does not fit in range")
390393
// TODO we need to figure out if we should throw an exception here!
391394
assertEqual("1E309", Literal(Double.PositiveInfinity))
392395
}

sql/core/src/test/resources/sql-tests/results/literals.sql.out

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct<>
4141
-- !query 4 output
4242
org.apache.spark.sql.catalyst.parser.ParseException
4343

44-
Value out of range. Value:"128" Radix:10(line 1, pos 7)
44+
Numeric literal 128 does not fit in range [-128, 127] for type tinyint(line 1, pos 7)
4545

4646
== SQL ==
4747
select 128Y
@@ -71,7 +71,7 @@ struct<>
7171
-- !query 7 output
7272
org.apache.spark.sql.catalyst.parser.ParseException
7373

74-
Value out of range. Value:"32768" Radix:10(line 1, pos 7)
74+
Numeric literal 32768 does not fit in range [-32768, 32767] for type smallint(line 1, pos 7)
7575

7676
== SQL ==
7777
select 32768S
@@ -101,7 +101,7 @@ struct<>
101101
-- !query 10 output
102102
org.apache.spark.sql.catalyst.parser.ParseException
103103

104-
For input string: "9223372036854775808"(line 1, pos 7)
104+
Numeric literal 9223372036854775808 does not fit in range [-9223372036854775808, 9223372036854775807] for type bigint(line 1, pos 7)
105105

106106
== SQL ==
107107
select 9223372036854775808L

0 commit comments

Comments
 (0)