This is an automated email from the ASF dual-hosted git repository.
jcamacho pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new ee1a9d2 [CALCITE-3914] Improve SubstitutionVisitor to consider
RexCall of type PLUS and TIMES for canonicalization (Vineet Garg)
ee1a9d2 is described below
commit ee1a9d2cacb67da4c5d7e8f0441c94a40dc69d66
Author: Vineet Garg <[email protected]>
AuthorDate: Fri Apr 10 15:07:18 2020 -0700
[CALCITE-3914] Improve SubstitutionVisitor to consider RexCall of type PLUS
and TIMES for canonicalization (Vineet Garg)
Close apache/calcite#1909
---
.../apache/calcite/plan/SubstitutionVisitor.java | 23 ++++++++-
.../apache/calcite/test/MaterializationTest.java | 59 ++++++++++++++++++++++
2 files changed, 80 insertions(+), 2 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
index 26a43fe..1c01ab5 100644
--- a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
+++ b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
@@ -345,13 +345,32 @@ public class SubstitutionVisitor {
case LESS_THAN_OR_EQUAL:
case GREATER_THAN_OR_EQUAL: {
RexCall call = (RexCall) condition;
- final RexNode left = call.getOperands().get(0);
- final RexNode right = call.getOperands().get(1);
+ RexNode left = canonizeNode(rexBuilder, call.getOperands().get(0));
+ RexNode right = canonizeNode(rexBuilder, call.getOperands().get(1));
+ call = (RexCall) rexBuilder.makeCall(call.getOperator(), left, right);
+
if (left.toString().compareTo(right.toString()) <= 0) {
return call;
}
return RexUtil.invert(rexBuilder, call);
}
+ case PLUS:
+ case TIMES: {
+ RexCall call = (RexCall) condition;
+ RexNode left = canonizeNode(rexBuilder, call.getOperands().get(0));
+ RexNode right = canonizeNode(rexBuilder, call.getOperands().get(1));
+
+ if (left.toString().compareTo(right.toString()) <= 0) {
+ return rexBuilder.makeCall(call.getOperator(), left, right);
+ }
+
+ RexNode newCall = rexBuilder.makeCall(call.getOperator(), right, left);
+ // new call should not be used if its inferred type is not same as old
+ if (!newCall.getType().equals(call.getType())) {
+ return call;
+ }
+ return newCall;
+ }
default:
return condition;
}
diff --git
a/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
b/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
index 8b33221..3caa53f 100644
--- a/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
+++ b/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
@@ -1297,6 +1297,35 @@ class MaterializationTest {
final RexNode z_eq_3 =
rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, z, i3); // $2 = 3
+ final RexNode x_plus_y_gt = // x + y > 2
+ rexBuilder.makeCall(
+ SqlStdOperatorTable.GREATER_THAN,
+ rexBuilder.makeCall(SqlStdOperatorTable.PLUS, x, y),
+ i2);
+ final RexNode y_plus_x_gt = // y + x > 2
+ rexBuilder.makeCall(
+ SqlStdOperatorTable.GREATER_THAN,
+ rexBuilder.makeCall(SqlStdOperatorTable.PLUS, y, x),
+ i2);
+
+ final RexNode x_times_y_gt = // x*y > 2
+ rexBuilder.makeCall(
+ SqlStdOperatorTable.GREATER_THAN,
+ rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, x, y),
+ i2);
+
+ final RexNode y_times_x_gt = // 2 < y*x
+ rexBuilder.makeCall(
+ SqlStdOperatorTable.LESS_THAN,
+ i2,
+ rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, y, x));
+
+ final RexNode x_plus_x_gt = // x + x > 2
+ rexBuilder.makeCall(
+ SqlStdOperatorTable.GREATER_THAN,
+ rexBuilder.makeCall(SqlStdOperatorTable.PLUS, x, y),
+ i2);
+
RexNode newFilter;
// Example 1.
@@ -1416,6 +1445,36 @@ class MaterializationTest {
x_eq_1,
x_eq_2);
assertNull(newFilter);
+
+ // Example 8.
+ // condition: x + y > 2
+ // target: y + x > 2
+ // yields
+ // residue: true
+ newFilter = SubstitutionVisitor.splitFilter(simplify,
+ x_plus_y_gt,
+ y_plus_x_gt);
+ assertThat(newFilter.isAlwaysTrue(), equalTo(true));
+
+ // Example 9.
+ // condition: x + x > 2
+ // target: x + x > 2
+ // yields
+ // residue: true
+ newFilter = SubstitutionVisitor.splitFilter(simplify,
+ x_plus_x_gt,
+ x_plus_x_gt);
+ assertThat(newFilter.isAlwaysTrue(), equalTo(true));
+
+ // Example 10.
+ // condition: x * y > 2
+ // target: 2 < y * x
+ // yields
+ // residue: true
+ newFilter = SubstitutionVisitor.splitFilter(simplify,
+ x_times_y_gt,
+ y_times_x_gt);
+ assertThat(newFilter.isAlwaysTrue(), equalTo(true));
}
/** Tests a complicated star-join query on a complicated materialized