You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by el...@apache.org on 2017/03/30 21:37:56 UTC
[06/50] [abbrv] calcite-avatica git commit: [CALCITE-1668] Simplify
"1 = 1" to true, "1 > 2" to false (Kevin Risden)
[CALCITE-1668] Simplify "1 = 1" to true, "1 > 2" to false (Kevin Risden)
Close apache/calcite#387
Project: http://git-wip-us.apache.org/repos/asf/calcite-avatica/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite-avatica/commit/255cd96a
Tree: http://git-wip-us.apache.org/repos/asf/calcite-avatica/tree/255cd96a
Diff: http://git-wip-us.apache.org/repos/asf/calcite-avatica/diff/255cd96a
Branch: refs/heads/master
Commit: 255cd96a79eb68fcf852b8e7af6299d7dfb356c7
Parents: 8df27ce
Author: Kevin Risden <ri...@avalonconsult.com>
Authored: Sun Feb 19 15:56:35 2017 -0600
Committer: Julian Hyde <jh...@apache.org>
Committed: Fri Mar 3 12:00:05 2017 -0800
----------------------------------------------------------------------
.../java/org/apache/calcite/rex/RexUtil.java | 81 +++++++++++++++-----
.../org/apache/calcite/test/RelBuilderTest.java | 14 ++++
.../org/apache/calcite/test/RexProgramTest.java | 65 ++++++++++++++++
3 files changed, 140 insertions(+), 20 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite-avatica/blob/255cd96a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexUtil.java b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
index a6b9e4e..fd60098 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -1641,33 +1641,74 @@ public class RexUtil {
case LESS_THAN:
case LESS_THAN_OR_EQUAL:
case NOT_EQUALS:
- final List<RexNode> operands = ((RexCall) e).getOperands();
- if (RexUtil.eq(operands.get(0), operands.get(1))
- && (unknownAsFalse
- || (!operands.get(0).getType().isNullable()
- && !operands.get(1).getType().isNullable()))) {
- switch (e.getKind()) {
- case EQUALS:
- case GREATER_THAN_OR_EQUAL:
- case LESS_THAN_OR_EQUAL:
- // "x = x" simplifies to "x is not null" (similarly <= and >=)
- return simplify(rexBuilder,
- rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL,
- operands.get(0)));
- default:
- // "x != x" simplifies to "false" (similarly < and >)
- return rexBuilder.makeLiteral(false);
- }
- }
- return simplifyCall(rexBuilder, (RexCall) e);
+ return simplifyComparison(rexBuilder, (RexCall) e, unknownAsFalse);
default:
return e;
}
}
- private static RexNode simplifyCall(RexBuilder rexBuilder, RexCall e) {
+ // e must be a comparison (=, >, >=, <, <=, !=)
+ private static RexNode simplifyComparison(RexBuilder rexBuilder, RexCall e,
+ boolean unknownAsFalse) {
final List<RexNode> operands = new ArrayList<>(e.operands);
simplifyList(rexBuilder, operands);
+
+ // Simplify "x <op> x"
+ final RexNode o0 = operands.get(0);
+ final RexNode o1 = operands.get(1);
+ if (RexUtil.eq(o0, o1)
+ && (unknownAsFalse
+ || (!o0.getType().isNullable()
+ && !o1.getType().isNullable()))) {
+ switch (e.getKind()) {
+ case EQUALS:
+ case GREATER_THAN_OR_EQUAL:
+ case LESS_THAN_OR_EQUAL:
+ // "x = x" simplifies to "x is not null" (similarly <= and >=)
+ return simplify(rexBuilder,
+ rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, o0));
+ default:
+ // "x != x" simplifies to "false" (similarly < and >)
+ return rexBuilder.makeLiteral(false);
+ }
+ }
+
+ // Simplify "<literal1> <op> <literal2>"
+ // For example, "1 = 2" becomes FALSE;
+ // "1 != 1" becomes FALSE;
+ // "1 != NULL" becomes UNKNOWN (or FALSE if unknownAsFalse);
+ // "1 != '1'" is unchanged because the types are not the same.
+ if (o0.isA(SqlKind.LITERAL)
+ && o1.isA(SqlKind.LITERAL)
+ && o0.getType().equals(o1.getType())) {
+ final Comparable v0 = ((RexLiteral) o0).getValue();
+ final Comparable v1 = ((RexLiteral) o1).getValue();
+ if (v0 == null || v1 == null) {
+ return unknownAsFalse
+ ? rexBuilder.makeLiteral(false)
+ : rexBuilder.makeNullLiteral(e.getType());
+ }
+ @SuppressWarnings("unchecked")
+ final int comparisonResult = v0.compareTo(v1);
+ switch (e.getKind()) {
+ case EQUALS:
+ return rexBuilder.makeLiteral(comparisonResult == 0);
+ case GREATER_THAN:
+ return rexBuilder.makeLiteral(comparisonResult > 0);
+ case GREATER_THAN_OR_EQUAL:
+ return rexBuilder.makeLiteral(comparisonResult >= 0);
+ case LESS_THAN:
+ return rexBuilder.makeLiteral(comparisonResult < 0);
+ case LESS_THAN_OR_EQUAL:
+ return rexBuilder.makeLiteral(comparisonResult <= 0);
+ case NOT_EQUALS:
+ return rexBuilder.makeLiteral(comparisonResult != 0);
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ // If none of the arguments were simplified, return the call unchanged.
if (operands.equals(e.operands)) {
return e;
}
http://git-wip-us.apache.org/repos/asf/calcite-avatica/blob/255cd96a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
index 842caf1..4eafeae 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -208,6 +208,20 @@ public class RelBuilderTest {
is("LogicalTableScan(table=[[scott, EMP]])\n"));
}
+ @Test public void testScanFilterTriviallyFalse() {
+ // Equivalent SQL:
+ // SELECT *
+ // FROM emp
+ // WHERE 1 = 2
+ final RelBuilder builder = RelBuilder.create(config().build());
+ RelNode root =
+ builder.scan("EMP")
+ .filter(builder.equals(builder.literal(1), builder.literal(2)))
+ .build();
+ assertThat(str(root),
+ is("LogicalValues(tuples=[[]])\n"));
+ }
+
@Test public void testScanFilterEquals() {
// Equivalent SQL:
// SELECT *
http://git-wip-us.apache.org/repos/asf/calcite-avatica/blob/255cd96a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
index 9ce8017..c1f567c 100644
--- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
@@ -1308,6 +1308,71 @@ public class RexProgramTest {
"1970-01-01 00:00:00"); // different from Hive
}
+ @Test public void testSimplifyLiterals() {
+ final RexLiteral literalAbc = rexBuilder.makeLiteral("abc");
+ final RexLiteral literalDef = rexBuilder.makeLiteral("def");
+
+ final RexLiteral literalZero = rexBuilder.makeExactLiteral(BigDecimal.ZERO);
+ final RexLiteral literalOne = rexBuilder.makeExactLiteral(BigDecimal.ONE);
+ final RexLiteral literalOneDotZero = rexBuilder.makeExactLiteral(new BigDecimal(1.0));
+
+ // Check string comparison
+ checkSimplify(eq(literalAbc, literalAbc), "true");
+ checkSimplify(eq(literalAbc, literalDef), "false");
+ checkSimplify(ne(literalAbc, literalAbc), "false");
+ checkSimplify(ne(literalAbc, literalDef), "true");
+ checkSimplify(gt(literalAbc, literalDef), "false");
+ checkSimplify(gt(literalDef, literalAbc), "true");
+ checkSimplify(gt(literalDef, literalDef), "false");
+ checkSimplify(ge(literalAbc, literalDef), "false");
+ checkSimplify(ge(literalDef, literalAbc), "true");
+ checkSimplify(ge(literalDef, literalDef), "true");
+ checkSimplify(lt(literalAbc, literalDef), "true");
+ checkSimplify(lt(literalAbc, literalDef), "true");
+ checkSimplify(lt(literalDef, literalDef), "false");
+ checkSimplify(le(literalAbc, literalDef), "true");
+ checkSimplify(le(literalDef, literalAbc), "false");
+ checkSimplify(le(literalDef, literalDef), "true");
+
+ // Check whole number comparison
+ checkSimplify(eq(literalZero, literalOne), "false");
+ checkSimplify(eq(literalOne, literalZero), "false");
+ checkSimplify(ne(literalZero, literalOne), "true");
+ checkSimplify(ne(literalOne, literalZero), "true");
+ checkSimplify(gt(literalZero, literalOne), "false");
+ checkSimplify(gt(literalOne, literalZero), "true");
+ checkSimplify(gt(literalOne, literalOne), "false");
+ checkSimplify(ge(literalZero, literalOne), "false");
+ checkSimplify(ge(literalOne, literalZero), "true");
+ checkSimplify(ge(literalOne, literalOne), "true");
+ checkSimplify(lt(literalZero, literalOne), "true");
+ checkSimplify(lt(literalOne, literalZero), "false");
+ checkSimplify(lt(literalOne, literalOne), "false");
+ checkSimplify(le(literalZero, literalOne), "true");
+ checkSimplify(le(literalOne, literalZero), "false");
+ checkSimplify(le(literalOne, literalOne), "true");
+
+ // Check decimal equality comparison
+ checkSimplify(eq(literalOne, literalOneDotZero), "true");
+ checkSimplify(eq(literalOneDotZero, literalOne), "true");
+ checkSimplify(ne(literalOne, literalOneDotZero), "false");
+ checkSimplify(ne(literalOneDotZero, literalOne), "false");
+
+ // Check different types shouldn't change simplification
+ checkSimplifyUnchanged(eq(literalZero, literalAbc));
+ checkSimplifyUnchanged(eq(literalAbc, literalZero));
+ checkSimplifyUnchanged(ne(literalZero, literalAbc));
+ checkSimplifyUnchanged(ne(literalAbc, literalZero));
+ checkSimplifyUnchanged(gt(literalZero, literalAbc));
+ checkSimplifyUnchanged(gt(literalAbc, literalZero));
+ checkSimplifyUnchanged(ge(literalZero, literalAbc));
+ checkSimplifyUnchanged(ge(literalAbc, literalZero));
+ checkSimplifyUnchanged(lt(literalZero, literalAbc));
+ checkSimplifyUnchanged(lt(literalAbc, literalZero));
+ checkSimplifyUnchanged(le(literalZero, literalAbc));
+ checkSimplifyUnchanged(le(literalAbc, literalZero));
+ }
+
private Calendar cal(int y, int m, int d, int h, int mm, int s) {
final Calendar c = Util.calendar();
c.set(Calendar.YEAR, y);