Skip to content
Snippets Groups Projects
Commit 478c7ce8 authored by Wenchen Fan's avatar Wenchen Fan Committed by Davies Liu
Browse files

[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.
parent 2f6dd634
No related branches found
No related tags found
No related merge requests found
......@@ -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
)
......
......@@ -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)
}
}
......@@ -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.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment