diff options
author | Wenchen Fan <cloud0fan@outlook.com> | 2015-10-20 13:36:03 -0700 |
---|---|---|
committer | Davies Liu <davies.liu@gmail.com> | 2015-10-20 13:38:25 -0700 |
commit | 478c7ce8628c05ebce2972e631d76317accebe9c (patch) | |
tree | cb4154abc51ae79fefede5468112d4a6df0e6dae /sql/catalyst/src | |
parent | 2f6dd634c169a34811738a3c230cce4462612748 (diff) | |
download | spark-478c7ce8628c05ebce2972e631d76317accebe9c.tar.gz spark-478c7ce8628c05ebce2972e631d76317accebe9c.tar.bz2 spark-478c7ce8628c05ebce2972e631d76317accebe9c.zip |
[SPARK-6740] [SQL] correctly parse NOT operator with comparison operations
We can't parse `NOT` operator with comparison operations like `SELECT NOT TRUE > TRUE`, this PR fixed it.
Takes over https://github.com/apache/spark/pull/6326.
Author: Wenchen Fan <cloud0fan@outlook.com>
Closes #8617 from cloud-fan/not.
Diffstat (limited to 'sql/catalyst/src')
3 files changed, 21 insertions, 8 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 2595e1f90c..08ca325b21 100644 --- 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 @@ -218,7 +218,10 @@ object SqlParser extends AbstractSparkSQLParser with DataTypeParser { andExpression * (OR ^^^ { (e1: Expression, e2: Expression) => Or(e1, e2) }) protected lazy val andExpression: Parser[Expression] = - comparisonExpression * (AND ^^^ { (e1: Expression, e2: Expression) => And(e1, e2) }) + notExpression * (AND ^^^ { (e1: Expression, e2: Expression) => And(e1, e2) }) + + protected lazy val notExpression: Parser[Expression] = + NOT.? ~ comparisonExpression ^^ { case maybeNot ~ e => maybeNot.map(_ => Not(e)).getOrElse(e) } protected lazy val comparisonExpression: Parser[Expression] = ( termExpression ~ ("=" ~> termExpression) ^^ { case e1 ~ e2 => EqualTo(e1, e2) } @@ -246,7 +249,6 @@ object SqlParser extends AbstractSparkSQLParser with DataTypeParser { } | termExpression <~ IS ~ NULL ^^ { case e => IsNull(e) } | termExpression <~ IS ~ NOT ~ NULL ^^ { case e => IsNotNull(e) } - | NOT ~> termExpression ^^ {e => Not(e)} | termExpression ) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/SqlParserSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/SqlParserSuite.scala index b93a3abc6e..79b4846cb9 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/SqlParserSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/SqlParserSuite.scala @@ -17,10 +17,10 @@ package org.apache.spark.sql.catalyst -import org.apache.spark.SparkFunSuite -import org.apache.spark.sql.catalyst.expressions.Attribute -import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan -import org.apache.spark.sql.catalyst.plans.logical.Command +import org.apache.spark.sql.catalyst.analysis.UnresolvedAlias +import org.apache.spark.sql.catalyst.expressions.{Literal, GreaterThan, Not, Attribute} +import org.apache.spark.sql.catalyst.plans.PlanTest +import org.apache.spark.sql.catalyst.plans.logical.{OneRowRelation, Project, LogicalPlan, Command} private[sql] case class TestCommand(cmd: String) extends LogicalPlan with Command { override def output: Seq[Attribute] = Seq.empty @@ -49,7 +49,7 @@ private[sql] class CaseInsensitiveTestParser extends AbstractSparkSQLParser { } } -class SqlParserSuite extends SparkFunSuite { +class SqlParserSuite extends PlanTest { test("test long keyword") { val parser = new SuperLongKeywordTestParser @@ -63,4 +63,15 @@ class SqlParserSuite extends SparkFunSuite { assert(TestCommand("NotRealCommand") === parser.parse("execute NotRealCommand")) assert(TestCommand("NotRealCommand") === parser.parse("exEcute NotRealCommand")) } + + test("test NOT operator with comparison operations") { + val parsed = SqlParser.parse("SELECT NOT TRUE > TRUE") + val expected = Project( + UnresolvedAlias( + Not( + GreaterThan(Literal(true), Literal(true))) + ) :: Nil, + OneRowRelation) + comparePlans(parsed, expected) + } } diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/plans/PlanTest.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/plans/PlanTest.scala index f76a903dcc..2efee1fc54 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/plans/PlanTest.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/plans/PlanTest.scala @@ -25,7 +25,7 @@ import org.apache.spark.sql.catalyst.util._ /** * Provides helper methods for comparing plans. */ -class PlanTest extends SparkFunSuite { +abstract class PlanTest extends SparkFunSuite { /** * Since attribute references are given globally unique ids during analysis, * we must normalize them to check if two different queries are identical. |