You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2021/05/28 18:50:48 UTC

[calcite] 01/03: Refactor: Add method SqlOperator.reverse()

This is an automated email from the ASF dual-hosted git repository.

jhyde pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git

commit 6a9832c14e7c7c02a0176920b87d15dab474300a
Author: Julian Hyde <jh...@apache.org>
AuthorDate: Mon May 24 22:11:38 2021 -0700

    Refactor: Add method SqlOperator.reverse()
    
    Deprecate SqlStdOperatorTable.reverse(SqlOperator);
    remove RexImplicationChecker.reverse(SqlOperator)
    and SqlImplementor.reverseOperatorDirection(SqlOperator).
---
 .../java/org/apache/calcite/plan/RelOptUtil.java   | 48 +++++++++++-----------
 .../apache/calcite/plan/RexImplicationChecker.java | 16 ++++----
 .../apache/calcite/rel/rel2sql/SqlImplementor.java | 21 +---------
 .../java/org/apache/calcite/rex/RexNormalize.java  | 12 +++---
 .../main/java/org/apache/calcite/rex/RexUtil.java  |  5 +--
 .../org/apache/calcite/sql/SqlBinaryOperator.java  | 26 ++++++++++++
 .../java/org/apache/calcite/sql/SqlOperator.java   | 23 ++++++++++-
 .../calcite/sql/fun/SqlStdOperatorTable.java       |  4 ++
 8 files changed, 92 insertions(+), 63 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index 61fb234..939a8a1 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -129,7 +129,6 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.NavigableSet;
-import java.util.Objects;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.function.Supplier;
@@ -137,6 +136,8 @@ import java.util.stream.Collectors;
 
 import static org.apache.calcite.rel.type.RelDataTypeImpl.NON_NULLABLE_SUFFIX;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * <code>RelOptUtil</code> defines static utility methods for use in optimizing
  * {@link RelNode}s.
@@ -1264,22 +1265,21 @@ public abstract class RelOptUtil {
       }
     }
 
-    if (condition instanceof RexCall) {
-      RexCall call = (RexCall) condition;
-      if (call.getKind() == SqlKind.AND) {
-        for (RexNode operand : call.getOperands()) {
-          splitJoinCondition(
-              sysFieldList,
-              inputs,
-              operand,
-              joinKeys,
-              filterNulls,
-              rangeOp,
-              nonEquiList);
-        }
-        return;
+    if (condition.getKind() == SqlKind.AND) {
+      for (RexNode operand : ((RexCall) condition).getOperands()) {
+        splitJoinCondition(
+            sysFieldList,
+            inputs,
+            operand,
+            joinKeys,
+            filterNulls,
+            rangeOp,
+            nonEquiList);
       }
+      return;
+    }
 
+    if (condition instanceof RexCall) {
       RexNode leftKey = null;
       RexNode rightKey = null;
       int leftInput = 0;
@@ -1288,7 +1288,8 @@ public abstract class RelOptUtil {
       List<RelDataTypeField> rightFields = null;
       boolean reverse = false;
 
-      call = collapseExpandedIsNotDistinctFromExpr(call, rexBuilder);
+      final RexCall call =
+          collapseExpandedIsNotDistinctFromExpr((RexCall) condition, rexBuilder);
       SqlKind kind = call.getKind();
 
       // Only consider range operators if we haven't already seen one
@@ -1443,10 +1444,11 @@ public abstract class RelOptUtil {
         if (rangeOp != null
             && kind != SqlKind.EQUALS
             && kind != SqlKind.IS_DISTINCT_FROM) {
+          SqlOperator op = call.getOperator();
           if (reverse) {
-            kind = kind.reverse();
+            op = requireNonNull(op.reverse());
           }
-          rangeOp.add(op(kind, call.getOperator()));
+          rangeOp.add(op);
         }
         return;
       } // else fall through and add this condition as nonEqui condition
@@ -4322,7 +4324,7 @@ public abstract class RelOptUtil {
       } else if (type instanceof MultisetSqlType) {
         // E.g. "INTEGER NOT NULL MULTISET NOT NULL"
         RelDataType componentType =
-            Objects.requireNonNull(
+            requireNonNull(
                 type.getComponentType(),
                 () -> "type.getComponentType() for " + type);
         accept(componentType);
@@ -4419,9 +4421,9 @@ public abstract class RelOptUtil {
       if (call.getOperator() == RexBuilder.GET_OPERATOR) {
         RexLiteral literal = (RexLiteral) call.getOperands().get(1);
         if (extraFields != null) {
-          Objects.requireNonNull(literal, () -> "first operand in " + call);
+          requireNonNull(literal, () -> "first operand in " + call);
           String value2 = (String) literal.getValue2();
-          Objects.requireNonNull(value2, () -> "value of the first operand in " + call);
+          requireNonNull(value2, () -> "value of the first operand in " + call);
           extraFields.add(
               new RelDataTypeFieldImpl(
                   value2,
@@ -4527,11 +4529,11 @@ public abstract class RelOptUtil {
           type = leftDestFields.get(destIndex).getType();
         } else {
           type =
-              Objects.requireNonNull(rightDestFields, "rightDestFields")
+              requireNonNull(rightDestFields, "rightDestFields")
                   .get(destIndex - nLeftDestFields).getType();
         }
       } else {
-        type = Objects.requireNonNull(srcFields, "srcFields").get(srcIndex).getType();
+        type = requireNonNull(srcFields, "srcFields").get(srcIndex).getType();
       }
       if ((adjustments[srcIndex] != 0)
           || (srcFields == null)
diff --git a/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java b/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java
index f8d1028..3dff20b 100644
--- a/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java
+++ b/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java
@@ -43,9 +43,10 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Set;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * Checks whether one condition logically implies another.
  *
@@ -71,9 +72,9 @@ public class RexImplicationChecker {
       RexBuilder builder,
       RexExecutor executor,
       RelDataType rowType) {
-    this.builder = Objects.requireNonNull(builder, "builder");
-    this.executor = Objects.requireNonNull(executor, "executor");
-    this.rowType = Objects.requireNonNull(rowType, "rowType");
+    this.builder = requireNonNull(builder, "builder");
+    this.executor = requireNonNull(executor, "executor");
+    this.rowType = requireNonNull(rowType, "rowType");
   }
 
   /**
@@ -494,14 +495,11 @@ public class RexImplicationChecker {
 
       if (first.isA(SqlKind.LITERAL)
           && second.isA(SqlKind.INPUT_REF)) {
-        updateUsage(reverse(call.getOperator()), (RexInputRef) second, first);
+        updateUsage(requireNonNull(call.getOperator().reverse()),
+            (RexInputRef) second, first);
       }
     }
 
-    private static SqlOperator reverse(SqlOperator op) {
-      return RelOptUtil.op(op.getKind().reverse(), op);
-    }
-
     private void updateUsage(SqlOperator op, RexInputRef inputRef,
         @Nullable RexNode literal) {
       final InputRefUsage<SqlOperator, @Nullable RexNode> inputRefUse =
diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
index 8d5f965..efc7d5d 100644
--- a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
+++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
@@ -342,7 +342,7 @@ public abstract class SqlImplementor {
         if (op1.getIndex() < leftFieldCount
             && op0.getIndex() >= leftFieldCount) {
           // Arguments were of form 'op1 = op0'
-          return reverseOperatorDirection(op).createCall(POS,
+          return requireNonNull(op.reverse()).createCall(POS,
               leftContext.field(op1.getIndex()),
               rightContext.field(op0.getIndex() - leftFieldCount));
         }
@@ -424,25 +424,6 @@ public abstract class SqlImplementor {
     return node;
   }
 
-  private static SqlOperator reverseOperatorDirection(SqlOperator op) {
-    switch (op.kind) {
-    case GREATER_THAN:
-      return SqlStdOperatorTable.LESS_THAN;
-    case GREATER_THAN_OR_EQUAL:
-      return SqlStdOperatorTable.LESS_THAN_OR_EQUAL;
-    case LESS_THAN:
-      return SqlStdOperatorTable.GREATER_THAN;
-    case LESS_THAN_OR_EQUAL:
-      return SqlStdOperatorTable.GREATER_THAN_OR_EQUAL;
-    case EQUALS:
-    case IS_NOT_DISTINCT_FROM:
-    case NOT_EQUALS:
-      return op;
-    default:
-      throw new AssertionError(op);
-    }
-  }
-
   public static JoinType joinType(JoinRelType joinType) {
     switch (joinType) {
     case LEFT:
diff --git a/core/src/main/java/org/apache/calcite/rex/RexNormalize.java b/core/src/main/java/org/apache/calcite/rex/RexNormalize.java
index c5b9cf9..713a1f7 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexNormalize.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexNormalize.java
@@ -19,7 +19,6 @@ package org.apache.calcite.rex;
 import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlOperator;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.apache.calcite.util.Pair;
 
@@ -31,6 +30,8 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * Context required to normalize a row-expression.
  *
@@ -82,8 +83,7 @@ public class RexNormalize {
     final SqlKind reversedKind = kind.reverse();
     final int x = reversedKind.compareTo(kind);
     if (x < 0) {
-      return Pair.of(
-          SqlStdOperatorTable.reverse(operator),
+      return Pair.of(requireNonNull(operator.reverse()),
           ImmutableList.of(operand1, operand0));
     }
     if (x > 0) {
@@ -99,8 +99,7 @@ public class RexNormalize {
 
       // When $1 > $0 is normalized, the operation needs to be flipped
       // so we sort arguments first, then flip the sign.
-      return Pair.of(
-          SqlStdOperatorTable.reverse(operator),
+      return Pair.of(requireNonNull(operator.reverse()),
           ImmutableList.of(operand1, operand0));
     }
     return original;
@@ -125,8 +124,7 @@ public class RexNormalize {
     final SqlKind reversedKind = kind.reverse();
     final int x = reversedKind.compareTo(kind);
     if (x < 0) {
-      return Objects.hash(
-          SqlStdOperatorTable.reverse(operator),
+      return Objects.hash(requireNonNull(operator.reverse()),
           Arrays.asList(operands.get(1), operands.get(0)));
     }
     if (isSymmetricalCall(operator, operands.get(0), operands.get(1))) {
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 4870a82..d5b4bc3 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -2090,12 +2090,11 @@ public class RexUtil {
     case GREATER_THAN:
     case LESS_THAN_OR_EQUAL:
     case GREATER_THAN_OR_EQUAL:
-      final SqlOperator op = op(call.getKind().reverse());
+      final SqlOperator op = requireNonNull(call.getOperator().reverse());
       return rexBuilder.makeCall(op, Lists.reverse(call.getOperands()));
     default:
-      break;
+      return null;
     }
-    return null;
   }
 
   @Deprecated // to be removed before 2.0
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlBinaryOperator.java b/core/src/main/java/org/apache/calcite/sql/SqlBinaryOperator.java
index f2de703..96ef1aa 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlBinaryOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlBinaryOperator.java
@@ -99,6 +99,32 @@ public class SqlBinaryOperator extends SqlOperator {
     return !getName().equals(".");
   }
 
+  @Override public @Nullable SqlOperator reverse() {
+    switch (kind) {
+    case EQUALS:
+    case NOT_EQUALS:
+    case IS_DISTINCT_FROM:
+    case IS_NOT_DISTINCT_FROM:
+    case OR:
+    case AND:
+    case PLUS:
+    case TIMES:
+      return this;
+
+    case GREATER_THAN:
+      return SqlStdOperatorTable.LESS_THAN;
+    case GREATER_THAN_OR_EQUAL:
+      return SqlStdOperatorTable.LESS_THAN_OR_EQUAL;
+    case LESS_THAN:
+      return SqlStdOperatorTable.GREATER_THAN;
+    case LESS_THAN_OR_EQUAL:
+      return SqlStdOperatorTable.GREATER_THAN_OR_EQUAL;
+
+    default:
+      return null;
+    }
+  }
+
   @Override protected RelDataType adjustType(
       SqlValidator validator,
       final SqlCall call,
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlOperator.java b/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
index b7e00d8..ece841a 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
@@ -965,11 +965,32 @@ public abstract class SqlOperator {
    * {@code SqlStdOperatorTable.NOT_LIKE}, and vice versa.
    *
    * <p>By default, returns {@code null}, which means there is no inverse
-   * operator. */
+   * operator.
+   *
+   * @see #reverse */
   public @Nullable SqlOperator not() {
     return null;
   }
 
+  /** Returns the operator that has the same effect as this operator
+   * if its arguments are reversed.
+   *
+   * <p>For example, {@code SqlStdOperatorTable.GREATER_THAN.reverse()} returns
+   * {@code SqlStdOperatorTable.LESS_THAN}, and vice versa,
+   * because {@code a > b} is equivalent to {@code b < a}.
+   *
+   * <p>{@code SqlStdOperatorTable.EQUALS.reverse()} returns itself.
+   *
+   * <p>By default, returns {@code null}, which means there is no inverse
+   * operator.
+   *
+   * @see SqlOperator#not()
+   * @see SqlKind#reverse()
+   */
+  public @Nullable SqlOperator reverse() {
+    return null;
+  }
+
   /**
    * Returns the {@link Strong.Policy} strategy for this operator, or null if
    * there is no particular strategy, in which case this policy will be deducted
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index 76e170d..c228f39 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -2611,7 +2611,11 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
    * direction. Or returns this, if its kind is not reversible.
    *
    * <p>For example, {@code reverse(GREATER_THAN)} returns {@link #LESS_THAN}.
+   *
+   * @deprecated Use {@link SqlOperator#reverse()}, but beware that it has
+   * slightly different semantics
    */
+  @Deprecated // to be removed before 2.0
   public static SqlOperator reverse(SqlOperator operator) {
     switch (operator.getKind()) {
     case GREATER_THAN: