提交 035d3acd 编写于 作者: J Jakob Odersky 提交者: Reynold Xin

[SPARK-7286][SQL] Deprecate !== in favour of =!=

This PR replaces #9925 which had issues with CI. **Please see the original PR for any previous discussions.**

## What changes were proposed in this pull request?
Deprecate the SparkSQL column operator !== and use =!= as an alternative.
Fixes subtle issues related to operator precedence (basically, !== does not have the same priority as its logical negation, ===).

## How was this patch tested?
All currently existing tests.

Author: Jakob Odersky <jodersky@gmail.com>

Closes #11588 from jodersky/SPARK-7286.
上级 cc4ab37e
...@@ -83,7 +83,7 @@ package object dsl { ...@@ -83,7 +83,7 @@ package object dsl {
def >= (other: Expression): Predicate = GreaterThanOrEqual(expr, other) def >= (other: Expression): Predicate = GreaterThanOrEqual(expr, other)
def === (other: Expression): Predicate = EqualTo(expr, other) def === (other: Expression): Predicate = EqualTo(expr, other)
def <=> (other: Expression): Predicate = EqualNullSafe(expr, other) def <=> (other: Expression): Predicate = EqualNullSafe(expr, other)
def !== (other: Expression): Predicate = Not(EqualTo(expr, other)) def =!= (other: Expression): Predicate = Not(EqualTo(expr, other))
def in(list: Expression*): Expression = In(expr, list) def in(list: Expression*): Expression = In(expr, list)
......
...@@ -253,6 +253,23 @@ class Column(protected[sql] val expr: Expression) extends Logging { ...@@ -253,6 +253,23 @@ class Column(protected[sql] val expr: Expression) extends Logging {
*/ */
def equalTo(other: Any): Column = this === other def equalTo(other: Any): Column = this === other
/**
* Inequality test.
* {{{
* // Scala:
* df.select( df("colA") =!= df("colB") )
* df.select( !(df("colA") === df("colB")) )
*
* // Java:
* import static org.apache.spark.sql.functions.*;
* df.filter( col("colA").notEqual(col("colB")) );
* }}}
*
* @group expr_ops
* @since 2.0.0
*/
def =!= (other: Any): Column = withExpr{ Not(EqualTo(expr, lit(other).expr)) }
/** /**
* Inequality test. * Inequality test.
* {{{ * {{{
...@@ -268,7 +285,8 @@ class Column(protected[sql] val expr: Expression) extends Logging { ...@@ -268,7 +285,8 @@ class Column(protected[sql] val expr: Expression) extends Logging {
* @group expr_ops * @group expr_ops
* @since 1.3.0 * @since 1.3.0
*/ */
def !== (other: Any): Column = withExpr{ Not(EqualTo(expr, lit(other).expr)) } @deprecated("!== does not have the same precedence as ===, use =!= instead", "2.0.0")
def !== (other: Any): Column = this =!= other
/** /**
* Inequality test. * Inequality test.
......
...@@ -349,7 +349,7 @@ class ColumnExpressionSuite extends QueryTest with SharedSQLContext { ...@@ -349,7 +349,7 @@ class ColumnExpressionSuite extends QueryTest with SharedSQLContext {
testData2.collect().toSeq.filter(r => r.getInt(0) == r.getInt(1))) testData2.collect().toSeq.filter(r => r.getInt(0) == r.getInt(1)))
} }
test("!==") { test("=!=") {
val nullData = sqlContext.createDataFrame(sparkContext.parallelize( val nullData = sqlContext.createDataFrame(sparkContext.parallelize(
Row(1, 1) :: Row(1, 1) ::
Row(1, 2) :: Row(1, 2) ::
......
...@@ -347,7 +347,7 @@ class JoinSuite extends QueryTest with SharedSQLContext { ...@@ -347,7 +347,7 @@ class JoinSuite extends QueryTest with SharedSQLContext {
Row(null, null, 6, "F") :: Nil) Row(null, null, 6, "F") :: Nil)
checkAnswer( checkAnswer(
left.join(right, ($"left.N" === $"right.N") && ($"left.N" !== 3), "full"), left.join(right, ($"left.N" === $"right.N") && ($"left.N" =!= 3), "full"),
Row(1, "A", null, null) :: Row(1, "A", null, null) ::
Row(2, "B", null, null) :: Row(2, "B", null, null) ::
Row(3, "C", null, null) :: Row(3, "C", null, null) ::
...@@ -357,7 +357,7 @@ class JoinSuite extends QueryTest with SharedSQLContext { ...@@ -357,7 +357,7 @@ class JoinSuite extends QueryTest with SharedSQLContext {
Row(null, null, 6, "F") :: Nil) Row(null, null, 6, "F") :: Nil)
checkAnswer( checkAnswer(
left.join(right, ($"left.N" === $"right.N") && ($"right.N" !== 3), "full"), left.join(right, ($"left.N" === $"right.N") && ($"right.N" =!= 3), "full"),
Row(1, "A", null, null) :: Row(1, "A", null, null) ::
Row(2, "B", null, null) :: Row(2, "B", null, null) ::
Row(3, "C", null, null) :: Row(3, "C", null, null) ::
......
...@@ -120,7 +120,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex ...@@ -120,7 +120,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex
checkFilterPredicate('_1 === true, classOf[Eq[_]], true) checkFilterPredicate('_1 === true, classOf[Eq[_]], true)
checkFilterPredicate('_1 <=> true, classOf[Eq[_]], true) checkFilterPredicate('_1 <=> true, classOf[Eq[_]], true)
checkFilterPredicate('_1 !== true, classOf[NotEq[_]], false) checkFilterPredicate('_1 =!= true, classOf[NotEq[_]], false)
} }
} }
...@@ -131,7 +131,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex ...@@ -131,7 +131,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex
checkFilterPredicate('_1 === 1, classOf[Eq[_]], 1) checkFilterPredicate('_1 === 1, classOf[Eq[_]], 1)
checkFilterPredicate('_1 <=> 1, classOf[Eq[_]], 1) checkFilterPredicate('_1 <=> 1, classOf[Eq[_]], 1)
checkFilterPredicate('_1 !== 1, classOf[NotEq[_]], (2 to 4).map(Row.apply(_))) checkFilterPredicate('_1 =!= 1, classOf[NotEq[_]], (2 to 4).map(Row.apply(_)))
checkFilterPredicate('_1 < 2, classOf[Lt[_]], 1) checkFilterPredicate('_1 < 2, classOf[Lt[_]], 1)
checkFilterPredicate('_1 > 3, classOf[Gt[_]], 4) checkFilterPredicate('_1 > 3, classOf[Gt[_]], 4)
...@@ -157,7 +157,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex ...@@ -157,7 +157,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex
checkFilterPredicate('_1 === 1, classOf[Eq[_]], 1) checkFilterPredicate('_1 === 1, classOf[Eq[_]], 1)
checkFilterPredicate('_1 <=> 1, classOf[Eq[_]], 1) checkFilterPredicate('_1 <=> 1, classOf[Eq[_]], 1)
checkFilterPredicate('_1 !== 1, classOf[NotEq[_]], (2 to 4).map(Row.apply(_))) checkFilterPredicate('_1 =!= 1, classOf[NotEq[_]], (2 to 4).map(Row.apply(_)))
checkFilterPredicate('_1 < 2, classOf[Lt[_]], 1) checkFilterPredicate('_1 < 2, classOf[Lt[_]], 1)
checkFilterPredicate('_1 > 3, classOf[Gt[_]], 4) checkFilterPredicate('_1 > 3, classOf[Gt[_]], 4)
...@@ -183,7 +183,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex ...@@ -183,7 +183,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex
checkFilterPredicate('_1 === 1, classOf[Eq[_]], 1) checkFilterPredicate('_1 === 1, classOf[Eq[_]], 1)
checkFilterPredicate('_1 <=> 1, classOf[Eq[_]], 1) checkFilterPredicate('_1 <=> 1, classOf[Eq[_]], 1)
checkFilterPredicate('_1 !== 1, classOf[NotEq[_]], (2 to 4).map(Row.apply(_))) checkFilterPredicate('_1 =!= 1, classOf[NotEq[_]], (2 to 4).map(Row.apply(_)))
checkFilterPredicate('_1 < 2, classOf[Lt[_]], 1) checkFilterPredicate('_1 < 2, classOf[Lt[_]], 1)
checkFilterPredicate('_1 > 3, classOf[Gt[_]], 4) checkFilterPredicate('_1 > 3, classOf[Gt[_]], 4)
...@@ -209,7 +209,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex ...@@ -209,7 +209,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex
checkFilterPredicate('_1 === 1, classOf[Eq[_]], 1) checkFilterPredicate('_1 === 1, classOf[Eq[_]], 1)
checkFilterPredicate('_1 <=> 1, classOf[Eq[_]], 1) checkFilterPredicate('_1 <=> 1, classOf[Eq[_]], 1)
checkFilterPredicate('_1 !== 1, classOf[NotEq[_]], (2 to 4).map(Row.apply(_))) checkFilterPredicate('_1 =!= 1, classOf[NotEq[_]], (2 to 4).map(Row.apply(_)))
checkFilterPredicate('_1 < 2, classOf[Lt[_]], 1) checkFilterPredicate('_1 < 2, classOf[Lt[_]], 1)
checkFilterPredicate('_1 > 3, classOf[Gt[_]], 4) checkFilterPredicate('_1 > 3, classOf[Gt[_]], 4)
...@@ -238,7 +238,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex ...@@ -238,7 +238,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex
checkFilterPredicate('_1 === "1", classOf[Eq[_]], "1") checkFilterPredicate('_1 === "1", classOf[Eq[_]], "1")
checkFilterPredicate('_1 <=> "1", classOf[Eq[_]], "1") checkFilterPredicate('_1 <=> "1", classOf[Eq[_]], "1")
checkFilterPredicate( checkFilterPredicate(
'_1 !== "1", classOf[NotEq[_]], (2 to 4).map(i => Row.apply(i.toString))) '_1 =!= "1", classOf[NotEq[_]], (2 to 4).map(i => Row.apply(i.toString)))
checkFilterPredicate('_1 < "2", classOf[Lt[_]], "1") checkFilterPredicate('_1 < "2", classOf[Lt[_]], "1")
checkFilterPredicate('_1 > "3", classOf[Gt[_]], "4") checkFilterPredicate('_1 > "3", classOf[Gt[_]], "4")
...@@ -272,7 +272,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex ...@@ -272,7 +272,7 @@ class ParquetFilterSuite extends QueryTest with ParquetTest with SharedSQLContex
'_1.isNotNull, classOf[NotEq[_]], (1 to 4).map(i => Row.apply(i.b)).toSeq) '_1.isNotNull, classOf[NotEq[_]], (1 to 4).map(i => Row.apply(i.b)).toSeq)
checkBinaryFilterPredicate( checkBinaryFilterPredicate(
'_1 !== 1.b, classOf[NotEq[_]], (2 to 4).map(i => Row.apply(i.b)).toSeq) '_1 =!= 1.b, classOf[NotEq[_]], (2 to 4).map(i => Row.apply(i.b)).toSeq)
checkBinaryFilterPredicate('_1 < 2.b, classOf[Lt[_]], 1.b) checkBinaryFilterPredicate('_1 < 2.b, classOf[Lt[_]], 1.b)
checkBinaryFilterPredicate('_1 > 3.b, classOf[Gt[_]], 4.b) checkBinaryFilterPredicate('_1 > 3.b, classOf[Gt[_]], 4.b)
......
...@@ -47,7 +47,7 @@ class ExpressionSQLBuilderSuite extends SQLBuilderTest { ...@@ -47,7 +47,7 @@ class ExpressionSQLBuilderSuite extends SQLBuilderTest {
test("binary comparisons") { test("binary comparisons") {
checkSQL('a.int === 'b.int, "(`a` = `b`)") checkSQL('a.int === 'b.int, "(`a` = `b`)")
checkSQL('a.int <=> 'b.int, "(`a` <=> `b`)") checkSQL('a.int <=> 'b.int, "(`a` <=> `b`)")
checkSQL('a.int !== 'b.int, "(NOT (`a` = `b`))") checkSQL('a.int =!= 'b.int, "(NOT (`a` = `b`))")
checkSQL('a.int < 'b.int, "(`a` < `b`)") checkSQL('a.int < 'b.int, "(`a` < `b`)")
checkSQL('a.int <= 'b.int, "(`a` <= `b`)") checkSQL('a.int <= 'b.int, "(`a` <= `b`)")
......
...@@ -211,7 +211,7 @@ class OrcFilterSuite extends QueryTest with OrcTest { ...@@ -211,7 +211,7 @@ class OrcFilterSuite extends QueryTest with OrcTest {
|expr = (not leaf-0)""".stripMargin.trim |expr = (not leaf-0)""".stripMargin.trim
) )
checkFilterPredicate( checkFilterPredicate(
'_1 !== 1, '_1 =!= 1,
"""leaf-0 = (EQUALS _1 1) """leaf-0 = (EQUALS _1 1)
|expr = (not leaf-0)""".stripMargin.trim |expr = (not leaf-0)""".stripMargin.trim
) )
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册