aboutsummaryrefslogtreecommitdiff
path: root/sql/catalyst
diff options
context:
space:
mode:
authorKousuke Saruta <sarutak@oss.nttdata.co.jp>2014-10-26 16:40:29 -0700
committerMichael Armbrust <michael@databricks.com>2014-10-26 16:40:29 -0700
commitace41e8bf2f4538115b28b90757b8424ca614682 (patch)
treeb990cb15bf40e34f5ad37169291a9f3d0aee5941 /sql/catalyst
parent974d7b238b415791975c60e4e202265d6fd31e2d (diff)
downloadspark-ace41e8bf2f4538115b28b90757b8424ca614682.tar.gz
spark-ace41e8bf2f4538115b28b90757b8424ca614682.tar.bz2
spark-ace41e8bf2f4538115b28b90757b8424ca614682.zip
[SPARK-3959][SPARK-3960][SQL] SqlParser fails to parse literal -9223372036854775808 (Long.MinValue). / We can apply unary minus only to literal.
SqlParser fails to parse -9223372036854775808 (Long.MinValue) so we cannot write queries such like as follows. SELECT value FROM someTable WHERE value > -9223372036854775808 Additionally, because of the wrong syntax definition, we cannot apply unary minus only to literal. So, we cannot write such expressions. -(value1 + value2) // Parenthesized expressions -column // Columns -MAX(column) // Functions Author: Kousuke Saruta <sarutak@oss.nttdata.co.jp> Closes #2816 from sarutak/spark-sql-dsl-improvement2 and squashes the following commits: 32a5005 [Kousuke Saruta] Remove test setting for thriftserver c2bab5e [Kousuke Saruta] Fixed SPARK-3959 and SPARK-3960
Diffstat (limited to 'sql/catalyst')
-rwxr-xr-xsql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/SqlParser.scala68
1 files changed, 54 insertions, 14 deletions
diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/SqlParser.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/SqlParser.scala
index 9bea990fce..4e967713ed 100755
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/SqlParser.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/SqlParser.scala
@@ -303,33 +303,73 @@ class SqlParser extends AbstractSparkSQLParser {
CAST ~ "(" ~> expression ~ (AS ~> dataType) <~ ")" ^^ { case exp ~ t => Cast(exp, t) }
protected lazy val literal: Parser[Literal] =
- ( numericLit ^^ {
- case i if i.toLong > Int.MaxValue => Literal(i.toLong)
- case i => Literal(i.toInt)
- }
- | NULL ^^^ Literal(null, NullType)
- | floatLit ^^ {case f => Literal(f.toDouble) }
+ ( numericLiteral
+ | booleanLiteral
| stringLit ^^ {case s => Literal(s, StringType) }
+ | NULL ^^^ Literal(null, NullType)
+ )
+
+ protected lazy val booleanLiteral: Parser[Literal] =
+ ( TRUE ^^^ Literal(true, BooleanType)
+ | FALSE ^^^ Literal(false, BooleanType)
+ )
+
+ protected lazy val numericLiteral: Parser[Literal] =
+ signedNumericLiteral | unsignedNumericLiteral
+
+ protected lazy val sign: Parser[String] =
+ "+" | "-"
+
+ protected lazy val signedNumericLiteral: Parser[Literal] =
+ ( sign ~ numericLit ^^ { case s ~ l => Literal(toNarrowestIntegerType(s + l)) }
+ | sign ~ floatLit ^^ { case s ~ f => Literal((s + f).toDouble) }
+ )
+
+ protected lazy val unsignedNumericLiteral: Parser[Literal] =
+ ( numericLit ^^ { n => Literal(toNarrowestIntegerType(n)) }
+ | floatLit ^^ { f => Literal(f.toDouble) }
)
+ private val longMax = BigDecimal(s"${Long.MaxValue}")
+ private val longMin = BigDecimal(s"${Long.MinValue}")
+ private val intMax = BigDecimal(s"${Int.MaxValue}")
+ private val intMin = BigDecimal(s"${Int.MinValue}")
+
+ private def toNarrowestIntegerType(value: String) = {
+ val bigIntValue = BigDecimal(value)
+
+ bigIntValue match {
+ case v if v < longMin || v > longMax => v
+ case v if v < intMin || v > intMax => v.toLong
+ case v => v.toInt
+ }
+ }
+
protected lazy val floatLit: Parser[String] =
- elem("decimal", _.isInstanceOf[lexical.FloatLit]) ^^ (_.chars)
+ ( "." ~> unsignedNumericLiteral ^^ { u => "0." + u }
+ | elem("decimal", _.isInstanceOf[lexical.FloatLit]) ^^ (_.chars)
+ )
+
+ protected lazy val baseExpression: Parser[Expression] =
+ ( "*" ^^^ Star(None)
+ | primary
+ )
- protected lazy val baseExpression: PackratParser[Expression] =
- ( expression ~ ("[" ~> expression <~ "]") ^^
+ protected lazy val signedPrimary: Parser[Expression] =
+ sign ~ primary ^^ { case s ~ e => if (s == "-") UnaryMinus(e) else e}
+
+ protected lazy val primary: PackratParser[Expression] =
+ ( literal
+ | expression ~ ("[" ~> expression <~ "]") ^^
{ case base ~ ordinal => GetItem(base, ordinal) }
| (expression <~ ".") ~ ident ^^
{ case base ~ fieldName => GetField(base, fieldName) }
- | TRUE ^^^ Literal(true, BooleanType)
- | FALSE ^^^ Literal(false, BooleanType)
| cast
| "(" ~> expression <~ ")"
| function
- | "-" ~> literal ^^ UnaryMinus
| dotExpressionHeader
| ident ^^ UnresolvedAttribute
- | "*" ^^^ Star(None)
- | literal
+ | signedPrimary
)
protected lazy val dotExpressionHeader: Parser[Expression] =