Skip to content
Snippets Groups Projects
Commit 3a1709fa authored by Takuya UESHIN's avatar Takuya UESHIN Committed by Michael Armbrust
Browse files

[SPARK-2535][SQL] Add StringComparison case to NullPropagation.

`StringComparison` expressions including `null` literal cases could be added to `NullPropagation`.

Author: Takuya UESHIN <ueshin@happy-camper.st>

Closes #1451 from ueshin/issues/SPARK-2535 and squashes the following commits:

e99c237 [Takuya UESHIN] Add some tests.
8f9b984 [Takuya UESHIN] Add StringComparison case to NullPropagation.
parent d88f6be4
No related branches found
No related tags found
No related merge requests found
...@@ -188,6 +188,11 @@ object NullPropagation extends Rule[LogicalPlan] { ...@@ -188,6 +188,11 @@ object NullPropagation extends Rule[LogicalPlan] {
case left :: Literal(null, _) :: Nil => Literal(null, e.dataType) case left :: Literal(null, _) :: Nil => Literal(null, e.dataType)
case _ => e case _ => e
} }
case e: StringComparison => e.children match {
case Literal(null, _) :: right :: Nil => Literal(null, e.dataType)
case left :: Literal(null, _) :: Nil => Literal(null, e.dataType)
case _ => e
}
} }
} }
} }
......
...@@ -466,7 +466,28 @@ class ExpressionEvaluationSuite extends FunSuite { ...@@ -466,7 +466,28 @@ class ExpressionEvaluationSuite extends FunSuite {
checkEvaluation(c1 === c2, false, row) checkEvaluation(c1 === c2, false, row)
checkEvaluation(c1 !== c2, true, row) checkEvaluation(c1 !== c2, true, row)
} }
test("StringComparison") {
val row = new GenericRow(Array[Any]("abc", null))
val c1 = 'a.string.at(0)
val c2 = 'a.string.at(1)
checkEvaluation(Contains(c1, "b"), true, row)
checkEvaluation(Contains(c1, "x"), false, row)
checkEvaluation(Contains(c2, "b"), null, row)
checkEvaluation(Contains(c1, Literal(null, StringType)), null, row)
checkEvaluation(StartsWith(c1, "a"), true, row)
checkEvaluation(StartsWith(c1, "b"), false, row)
checkEvaluation(StartsWith(c2, "a"), null, row)
checkEvaluation(StartsWith(c1, Literal(null, StringType)), null, row)
checkEvaluation(EndsWith(c1, "c"), true, row)
checkEvaluation(EndsWith(c1, "b"), false, row)
checkEvaluation(EndsWith(c2, "b"), null, row)
checkEvaluation(EndsWith(c1, Literal(null, StringType)), null, row)
}
test("Substring") { test("Substring") {
val row = new GenericRow(Array[Any]("example", "example".toArray.map(_.toByte))) val row = new GenericRow(Array[Any]("example", "example".toArray.map(_.toByte)))
......
...@@ -205,7 +205,10 @@ class ConstantFoldingSuite extends PlanTest { ...@@ -205,7 +205,10 @@ class ConstantFoldingSuite extends PlanTest {
Substring(Literal(null, StringType), 0, 1) as 'c16, Substring(Literal(null, StringType), 0, 1) as 'c16,
Substring("abc", Literal(null, IntegerType), 1) as 'c17, Substring("abc", Literal(null, IntegerType), 1) as 'c17,
Substring("abc", 0, Literal(null, IntegerType)) as 'c18 Substring("abc", 0, Literal(null, IntegerType)) as 'c18,
Contains(Literal(null, StringType), "abc") as 'c19,
Contains("abc", Literal(null, StringType)) as 'c20
) )
val optimized = Optimize(originalQuery.analyze) val optimized = Optimize(originalQuery.analyze)
...@@ -237,7 +240,10 @@ class ConstantFoldingSuite extends PlanTest { ...@@ -237,7 +240,10 @@ class ConstantFoldingSuite extends PlanTest {
Literal(null, StringType) as 'c16, Literal(null, StringType) as 'c16,
Literal(null, StringType) as 'c17, Literal(null, StringType) as 'c17,
Literal(null, StringType) as 'c18 Literal(null, StringType) as 'c18,
Literal(null, BooleanType) as 'c19,
Literal(null, BooleanType) as 'c20
).analyze ).analyze
comparePlans(optimized, correctAnswer) comparePlans(optimized, correctAnswer)
......
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.spark.sql.catalyst.optimizer
import org.apache.spark.sql.catalyst.expressions._
import org.apache.spark.sql.catalyst.plans.logical._
import org.apache.spark.sql.catalyst.plans.PlanTest
import org.apache.spark.sql.catalyst.rules._
/* Implicit conversions */
import org.apache.spark.sql.catalyst.dsl.expressions._
import org.apache.spark.sql.catalyst.dsl.plans._
class LikeSimplificationSuite extends PlanTest {
object Optimize extends RuleExecutor[LogicalPlan] {
val batches =
Batch("Like Simplification", Once,
LikeSimplification) :: Nil
}
val testRelation = LocalRelation('a.string)
test("simplify Like into StartsWith") {
val originalQuery =
testRelation
.where(('a like "abc%") || ('a like "abc\\%"))
val optimized = Optimize(originalQuery.analyze)
val correctAnswer = testRelation
.where(StartsWith('a, "abc") || ('a like "abc\\%"))
.analyze
comparePlans(optimized, correctAnswer)
}
test("simplify Like into EndsWith") {
val originalQuery =
testRelation
.where('a like "%xyz")
val optimized = Optimize(originalQuery.analyze)
val correctAnswer = testRelation
.where(EndsWith('a, "xyz"))
.analyze
comparePlans(optimized, correctAnswer)
}
test("simplify Like into Contains") {
val originalQuery =
testRelation
.where(('a like "%mn%") || ('a like "%mn\\%"))
val optimized = Optimize(originalQuery.analyze)
val correctAnswer = testRelation
.where(Contains('a, "mn") || ('a like "%mn\\%"))
.analyze
comparePlans(optimized, correctAnswer)
}
test("simplify Like into EqualTo") {
val originalQuery =
testRelation
.where(('a like "") || ('a like "abc"))
val optimized = Optimize(originalQuery.analyze)
val correctAnswer = testRelation
.where(('a === "") || ('a === "abc"))
.analyze
comparePlans(optimized, correctAnswer)
}
}
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