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 2017/02/23 22:28:39 UTC

calcite git commit: [CALCITE-1653] Pass an expression executor to RexUtil.simplify for constant reduction (Remus Rusanu)

Repository: calcite
Updated Branches:
  refs/heads/master 095acb100 -> 88d1d67d9


[CALCITE-1653] Pass an expression executor to RexUtil.simplify for constant reduction (Remus Rusanu)

Rename RelOptPlanner.Executor to RexExecutor.

Add an executor to RelBuilder, populated first from the context, next
from the planner, or lastly from RexUtil.EXECUTOR.

Close apache/calcite#379


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/88d1d67d
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/88d1d67d
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/88d1d67d

Branch: refs/heads/master
Commit: 88d1d67d98663a760039f9a507e66e23f83ef2bd
Parents: 095acb1
Author: Remus Rusanu <re...@apache.org>
Authored: Wed Feb 22 09:46:05 2017 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Feb 23 10:17:15 2017 -0800

----------------------------------------------------------------------
 .../calcite/plan/AbstractRelOptPlanner.java     |  7 +-
 .../org/apache/calcite/plan/RelOptPlanner.java  | 17 ++---
 .../calcite/plan/RexImplicationChecker.java     |  7 +-
 .../org/apache/calcite/prepare/PlannerImpl.java |  3 +-
 .../rel/rules/ReduceExpressionsRule.java        | 14 ++--
 .../org/apache/calcite/rex/RexExecutor.java     | 37 +++++++++++
 .../org/apache/calcite/rex/RexExecutorImpl.java |  3 +-
 .../java/org/apache/calcite/rex/RexUtil.java    | 70 ++++++++++++++------
 .../apache/calcite/tools/FrameworkConfig.java   |  4 +-
 .../org/apache/calcite/tools/Frameworks.java    | 12 ++--
 .../org/apache/calcite/tools/RelBuilder.java    |  7 +-
 11 files changed, 127 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java b/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java
index 698c790..81a297b 100644
--- a/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java
+++ b/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java
@@ -20,6 +20,7 @@ import org.apache.calcite.plan.volcano.RelSubset;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.metadata.RelMetadataProvider;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rex.RexExecutor;
 import org.apache.calcite.runtime.PredicateImpl;
 import org.apache.calcite.util.CancelFlag;
 
@@ -70,7 +71,7 @@ public abstract class AbstractRelOptPlanner implements RelOptPlanner {
   /** External context. Never null. */
   protected final Context context;
 
-  private Executor executor;
+  private RexExecutor executor;
 
   //~ Constructors -----------------------------------------------------------
 
@@ -269,11 +270,11 @@ public abstract class AbstractRelOptPlanner implements RelOptPlanner {
     return ImmutableList.of();
   }
 
-  public void setExecutor(Executor executor) {
+  public void setExecutor(RexExecutor executor) {
     this.executor = executor;
   }
 
-  public Executor getExecutor() {
+  public RexExecutor getExecutor() {
     return executor;
   }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/core/src/main/java/org/apache/calcite/plan/RelOptPlanner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptPlanner.java b/core/src/main/java/org/apache/calcite/plan/RelOptPlanner.java
index 8791785..6143aa7 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptPlanner.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptPlanner.java
@@ -20,8 +20,7 @@ import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.metadata.CachingRelMetadataProvider;
 import org.apache.calcite.rel.metadata.RelMetadataProvider;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexExecutor;
 import org.apache.calcite.util.CancelFlag;
 import org.apache.calcite.util.trace.CalciteTrace;
 
@@ -326,21 +325,17 @@ public interface RelOptPlanner {
   RelTraitSet emptyTraitSet();
 
   /** Sets the object that can execute scalar expressions. */
-  void setExecutor(Executor executor);
+  void setExecutor(RexExecutor executor);
 
   /** Returns the executor used to evaluate constant expressions. */
-  Executor getExecutor();
+  RexExecutor getExecutor();
 
   /** Called when a relational expression is copied to a similar expression. */
   void onCopy(RelNode rel, RelNode newRel);
 
-  /** Can reduce expressions, writing a literal for each into a list. */
-  interface Executor {
-    /**
-     * Reduces expressions, and writes their results into {@code reducedValues}.
-     */
-    void reduce(RexBuilder rexBuilder, List<RexNode> constExps,
-        List<RexNode> reducedValues);
+  /** @deprecated Use {@link RexExecutor} */
+  @Deprecated // to be removed before 2.0
+  interface Executor extends RexExecutor {
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java
----------------------------------------------------------------------
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 ff6c347..466c38d 100644
--- a/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java
+++ b/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java
@@ -32,6 +32,7 @@ import org.apache.calcite.sql.fun.SqlCastFunction;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.trace.CalciteLogger;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
@@ -69,9 +70,9 @@ public class RexImplicationChecker {
       RexBuilder builder,
       RexExecutorImpl executor,
       RelDataType rowType) {
-    this.builder = builder;
-    this.executor = executor;
-    this.rowType = rowType;
+    this.builder = Preconditions.checkNotNull(builder);
+    this.executor = Preconditions.checkNotNull(executor);
+    this.rowType = Preconditions.checkNotNull(rowType);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/core/src/main/java/org/apache/calcite/prepare/PlannerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/prepare/PlannerImpl.java b/core/src/main/java/org/apache/calcite/prepare/PlannerImpl.java
index 7ad7f3c..6cb3d39 100644
--- a/core/src/main/java/org/apache/calcite/prepare/PlannerImpl.java
+++ b/core/src/main/java/org/apache/calcite/prepare/PlannerImpl.java
@@ -33,6 +33,7 @@ import org.apache.calcite.rel.RelRoot;
 import org.apache.calcite.rel.metadata.CachingRelMetadataProvider;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexExecutor;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlOperatorTable;
@@ -78,7 +79,7 @@ public class PlannerImpl implements Planner {
   private SchemaPlus defaultSchema;
   private JavaTypeFactory typeFactory;
   private RelOptPlanner planner;
-  private RelOptPlanner.Executor executor;
+  private RexExecutor executor;
 
   // set in STATE_4_VALIDATE
   private CalciteSqlValidator validator;

http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
index edc13de..11db392 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
@@ -16,7 +16,6 @@
  */
 package org.apache.calcite.rel.rules;
 
-import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelOptPredicateList;
 import org.apache.calcite.plan.RelOptRule;
 import org.apache.calcite.plan.RelOptRuleCall;
@@ -38,6 +37,7 @@ import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexCorrelVariable;
 import org.apache.calcite.rex.RexDynamicParam;
+import org.apache.calcite.rex.RexExecutor;
 import org.apache.calcite.rex.RexFieldAccess;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLiteral;
@@ -461,8 +461,13 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
 
     boolean reduced = reduceExpressionsInternal(rel, expList, predicates);
 
-    // Simplify preds in place
-    ExprSimplifier simplifier = new ExprSimplifier(rexBuilder, unknownAsFalse);
+    // Simplify predicates in place
+    RexExecutor executor = rel.getCluster().getPlanner().getExecutor();
+    if (executor == null) {
+      executor = RexUtil.EXECUTOR;
+    }
+    ExprSimplifier simplifier =
+        new ExprSimplifier(rexBuilder, unknownAsFalse, executor);
     boolean simplified = false;
     for (int i = 0; i < expList.size(); i++) {
       RexNode expr2 = simplifier.apply(expList.get(i));
@@ -532,8 +537,7 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
     }
 
     // Compute the values they reduce to.
-    RelOptPlanner.Executor executor =
-        rel.getCluster().getPlanner().getExecutor();
+    RexExecutor executor = rel.getCluster().getPlanner().getExecutor();
     if (executor == null) {
       // Cannot reduce expressions: caller has not set an executor in their
       // environment. Caller should execute something like the following before

http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/core/src/main/java/org/apache/calcite/rex/RexExecutor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexExecutor.java b/core/src/main/java/org/apache/calcite/rex/RexExecutor.java
new file mode 100644
index 0000000..bb45a9b
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/rex/RexExecutor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.calcite.rex;
+
+import java.util.List;
+
+/** Can reduce expressions, writing a literal for each into a list. */
+public interface RexExecutor {
+
+  /** Reduces expressions, and writes their results into {@code reducedValues}.
+   *
+   * <p>If an expression cannot be reduced, writes the original expression.
+   * For example, {@code CAST('abc' AS INTEGER)} gives an error when executed, so the executor
+   * ignores the error and writes the original expression.
+   *
+   * @param rexBuilder Rex builder
+   * @param constExps Expressions to be reduced
+   * @param reducedValues List to which reduced expressions are appended
+   */
+  void reduce(RexBuilder rexBuilder, List<RexNode> constExps, List<RexNode> reducedValues);
+}
+
+// End RexExecutor.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java b/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
index 6cd6f7e..5d8ef59 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
@@ -28,7 +28,6 @@ import org.apache.calcite.linq4j.tree.IndexExpression;
 import org.apache.calcite.linq4j.tree.MethodCallExpression;
 import org.apache.calcite.linq4j.tree.MethodDeclaration;
 import org.apache.calcite.linq4j.tree.ParameterExpression;
-import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
@@ -44,7 +43,7 @@ import java.util.List;
 /**
 * Evaluates a {@link RexNode} expression.
 */
-public class RexExecutorImpl implements RelOptPlanner.Executor {
+public class RexExecutorImpl implements RexExecutor {
 
   private final DataContext dataContext;
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/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 fa19883..b8ebf75 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -18,7 +18,6 @@ package org.apache.calcite.rex;
 
 import org.apache.calcite.linq4j.Ord;
 import org.apache.calcite.linq4j.function.Predicate1;
-import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.Strong;
 import org.apache.calcite.rel.RelCollation;
@@ -74,6 +73,7 @@ import java.util.Set;
  * Utility methods concerning row-expressions.
  */
 public class RexUtil {
+
   private static final Function<? super RexNode, ? extends RexNode> ADD_NOT =
       new Function<RexNode, RexNode>() {
         public RexNode apply(RexNode input) {
@@ -110,9 +110,8 @@ public class RexUtil {
         }
       };
 
-  /** Executor for a bit of constant reduction. Ideally we'd use the user's
-   * preferred executor, but that isn't available. */
-  private static final RelOptPlanner.Executor EXECUTOR =
+  /** Executor for a bit of constant reduction. The user can pass in another executor. */
+  public static final RexExecutor EXECUTOR =
       new RexExecutorImpl(Schemas.createDataContext(null));
 
   private RexUtil() {
@@ -1561,8 +1560,8 @@ public class RexUtil {
    * <p>This is useful if you are simplifying expressions in a
    * {@link Project}. */
   public static RexNode simplifyPreservingType(RexBuilder rexBuilder,
-      RexNode e) {
-    final RexNode e2 = simplify(rexBuilder, e, false);
+      RexNode e, RexExecutor executor) {
+    final RexNode e2 = simplify(rexBuilder, e, false, executor);
     if (e2.getType() == e.getType()) {
       return e2;
     }
@@ -1574,6 +1573,23 @@ public class RexUtil {
   }
 
   /**
+   * Simplifies a boolean expression, leaving UNKNOWN values as UNKNOWN, and
+   * using the default executor.
+   */
+  public static RexNode simplify(RexBuilder rexBuilder, RexNode e) {
+    return simplify(rexBuilder, e, false, EXECUTOR);
+  }
+
+  /**
+   * Simplifies a boolean expression,
+   * using the default executor.
+   */
+  public static RexNode simplify(RexBuilder rexBuilder, RexNode e,
+      boolean unknownAsFalse) {
+    return simplify(rexBuilder, e, unknownAsFalse, EXECUTOR);
+  }
+
+  /**
    * Simplifies a boolean expression.
    *
    * <p>In particular:</p>
@@ -1583,13 +1599,20 @@ public class RexUtil {
    * <li>{@code simplify(x = 1 AND FALSE)}
    * returns {@code FALSE}</li>
    * </ul>
+   *
+   * <p>If the expression is a predicate in a WHERE clause, UNKNOWN values have
+   * the same effect as FALSE. In situations like this, specify
+   * {@code unknownAsFalse = true}, so and we can switch from 3-valued logic to
+   * simpler 2-valued logic and make more optimizations.
+   *
+   * @param rexBuilder Rex builder
+   * @param e Expression to simplify
+   * @param unknownAsFalse Whether to convert UNKNOWN values to FALSE
+   * @param executor Executor for constant reduction, not null
    */
-  public static RexNode simplify(RexBuilder rexBuilder, RexNode e) {
-    return simplify(rexBuilder, e, false);
-  }
-
   public static RexNode simplify(RexBuilder rexBuilder, RexNode e,
-      boolean unknownAsFalse) {
+      boolean unknownAsFalse, RexExecutor executor) {
+    Preconditions.checkNotNull(executor);
     switch (e.getKind()) {
     case AND:
       return simplifyAnd(rexBuilder, (RexCall) e, unknownAsFalse);
@@ -1600,7 +1623,7 @@ public class RexUtil {
     case CASE:
       return simplifyCase(rexBuilder, (RexCall) e, unknownAsFalse);
     case CAST:
-      return simplifyCast(rexBuilder, (RexCall) e);
+      return simplifyCast(rexBuilder, (RexCall) e, executor);
     case IS_NULL:
     case IS_NOT_NULL:
     case IS_TRUE:
@@ -2044,6 +2067,7 @@ public class RexUtil {
    * UNKNOWN it will be interpreted as FALSE. */
   public static RexNode simplifyAnd2ForUnknownAsFalse(RexBuilder rexBuilder,
       List<RexNode> terms, List<RexNode> notTerms) {
+    final RexExecutor executor = EXECUTOR;
     for (RexNode term : terms) {
       if (term.isAlwaysFalse()) {
         return rexBuilder.makeLiteral(false);
@@ -2213,9 +2237,9 @@ public class RexUtil {
     }
     // Add the NOT disjunctions back in.
     for (RexNode notDisjunction : notTerms) {
-      terms.add(
-          simplify(rexBuilder,
-              rexBuilder.makeCall(SqlStdOperatorTable.NOT, notDisjunction), true));
+      final RexNode call =
+          rexBuilder.makeCall(SqlStdOperatorTable.NOT, notDisjunction);
+      terms.add(simplify(rexBuilder, call, true, executor));
     }
     // The negated terms: only deterministic expressions
     for (String negatedTerm : negatedTerms) {
@@ -2348,7 +2372,9 @@ public class RexUtil {
         && (call.operands.size() - i) % 2 == 1;
   }
 
-  private static RexNode simplifyCast(RexBuilder rexBuilder, RexCall e) {
+  private static RexNode simplifyCast(RexBuilder rexBuilder, RexCall e,
+      RexExecutor executor) {
+    Preconditions.checkNotNull(executor);
     final RexNode operand = e.getOperands().get(0);
     switch (operand.getKind()) {
     case LITERAL:
@@ -2373,7 +2399,7 @@ public class RexUtil {
         }
       }
       final List<RexNode> reducedValues = new ArrayList<>();
-      EXECUTOR.reduce(rexBuilder, ImmutableList.<RexNode>of(e), reducedValues);
+      executor.reduce(rexBuilder, ImmutableList.<RexNode>of(e), reducedValues);
       return Preconditions.checkNotNull(
           Iterables.getOnlyElement(reducedValues));
     default:
@@ -2941,11 +2967,14 @@ public class RexUtil {
   /** Deep expressions simplifier. */
   public static class ExprSimplifier extends RexShuttle {
     private final RexBuilder rexBuilder;
+    private final RexExecutor executor;
     private final boolean unknownAsFalse;
     private final Map<RexNode, Boolean> unknownAsFalseMap;
 
-    public ExprSimplifier(RexBuilder rexBuilder, boolean unknownAsFalse) {
-      this.rexBuilder = rexBuilder;
+    public ExprSimplifier(RexBuilder rexBuilder, boolean unknownAsFalse,
+        RexExecutor executor) {
+      this.rexBuilder = Preconditions.checkNotNull(rexBuilder);
+      this.executor = Preconditions.checkNotNull(executor);
       this.unknownAsFalse = unknownAsFalse;
       this.unknownAsFalseMap = new HashMap<>();
     }
@@ -2970,7 +2999,8 @@ public class RexUtil {
         }
       }
       RexNode node = super.visitCall(call);
-      RexNode simplifiedNode = simplify(rexBuilder, node, unknownAsFalseCall);
+      RexNode simplifiedNode =
+          simplify(rexBuilder, node, unknownAsFalseCall, executor);
       if (node == simplifiedNode) {
         return node;
       }

http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/core/src/main/java/org/apache/calcite/tools/FrameworkConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/FrameworkConfig.java b/core/src/main/java/org/apache/calcite/tools/FrameworkConfig.java
index 319c216..7921a80 100644
--- a/core/src/main/java/org/apache/calcite/tools/FrameworkConfig.java
+++ b/core/src/main/java/org/apache/calcite/tools/FrameworkConfig.java
@@ -18,9 +18,9 @@ package org.apache.calcite.tools;
 
 import org.apache.calcite.plan.Context;
 import org.apache.calcite.plan.RelOptCostFactory;
-import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelTraitDef;
 import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.rex.RexExecutor;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.sql.SqlOperatorTable;
 import org.apache.calcite.sql.parser.SqlParser;
@@ -49,7 +49,7 @@ public interface FrameworkConfig {
   /**
    * Returns the executor used to evaluate constant expressions.
    */
-  RelOptPlanner.Executor getExecutor();
+  RexExecutor getExecutor();
 
   /**
    * Returns a list of one or more programs used during the course of query

http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/core/src/main/java/org/apache/calcite/tools/Frameworks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/Frameworks.java b/core/src/main/java/org/apache/calcite/tools/Frameworks.java
index a4e43fc..7aba625 100644
--- a/core/src/main/java/org/apache/calcite/tools/Frameworks.java
+++ b/core/src/main/java/org/apache/calcite/tools/Frameworks.java
@@ -21,12 +21,12 @@ import org.apache.calcite.jdbc.CalciteSchema;
 import org.apache.calcite.plan.Context;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptCostFactory;
-import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelOptSchema;
 import org.apache.calcite.plan.RelTraitDef;
 import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.prepare.PlannerImpl;
 import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.rex.RexExecutor;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.server.CalciteServerStatement;
 import org.apache.calcite.sql.SqlOperatorTable;
@@ -180,7 +180,7 @@ public class Frameworks {
     private SqlParser.Config parserConfig =
         SqlParser.Config.DEFAULT;
     private SchemaPlus defaultSchema;
-    private RelOptPlanner.Executor executor;
+    private RexExecutor executor;
     private RelOptCostFactory costFactory;
     private RelDataTypeSystem typeSystem = RelDataTypeSystem.DEFAULT;
 
@@ -197,7 +197,7 @@ public class Frameworks {
       return this;
     }
 
-    public ConfigBuilder executor(RelOptPlanner.Executor executor) {
+    public ConfigBuilder executor(RexExecutor executor) {
       Preconditions.checkNotNull(executor);
       this.executor = executor;
       return this;
@@ -281,7 +281,7 @@ public class Frameworks {
     private final SchemaPlus defaultSchema;
     private final RelOptCostFactory costFactory;
     private final RelDataTypeSystem typeSystem;
-    private final RelOptPlanner.Executor executor;
+    private final RexExecutor executor;
 
     public StdFrameworkConfig(Context context,
         SqlRexConvertletTable convertletTable,
@@ -292,7 +292,7 @@ public class Frameworks {
         SchemaPlus defaultSchema,
         RelOptCostFactory costFactory,
         RelDataTypeSystem typeSystem,
-        RelOptPlanner.Executor executor) {
+        RexExecutor executor) {
       this.context = context;
       this.convertletTable = convertletTable;
       this.operatorTable = operatorTable;
@@ -313,7 +313,7 @@ public class Frameworks {
       return defaultSchema;
     }
 
-    public RelOptPlanner.Executor getExecutor() {
+    public RexExecutor getExecutor() {
       return executor;
     }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/88d1d67d/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
index 733e030..a0846c8 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -44,6 +44,7 @@ import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexCorrelVariable;
+import org.apache.calcite.rex.RexExecutor;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
@@ -131,6 +132,7 @@ public class RelBuilder {
   private final RelFactories.TableScanFactory scanFactory;
   private final Deque<Frame> stack = new ArrayDeque<>();
   private final boolean simplify;
+  private final RexExecutor executor;
 
   protected RelBuilder(Context context, RelOptCluster cluster,
       RelOptSchema relOptSchema) {
@@ -170,6 +172,9 @@ public class RelBuilder {
     this.scanFactory =
         Util.first(context.unwrap(RelFactories.TableScanFactory.class),
             RelFactories.DEFAULT_TABLE_SCAN_FACTORY);
+    this.executor =
+        Util.first(context.unwrap(RexExecutor.class),
+            Util.first(cluster.getPlanner().getExecutor(), RexUtil.EXECUTOR));
   }
 
   /** Creates a RelBuilder. */
@@ -864,7 +869,7 @@ public class RelBuilder {
     final Iterator<String> nameIterator = fieldNames.iterator();
     for (RexNode node : nodes) {
       if (simplify) {
-        node = RexUtil.simplifyPreservingType(getRexBuilder(), node);
+        node = RexUtil.simplifyPreservingType(getRexBuilder(), node, executor);
       }
       exprList.add(node);
       String name = nameIterator.hasNext() ? nameIterator.next() : null;