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 2015/09/03 00:16:05 UTC

[17/50] incubator-calcite git commit: Change the argument types of SqlOperator.getMonotonicity to allow it to be used for RexNode as well as SqlNode

Change the argument types of SqlOperator.getMonotonicity to allow it to be used for RexNode as well as SqlNode


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

Branch: refs/heads/branch-release
Commit: f7ec3e847eb3ba82c182a63327fd1da490df648b
Parents: ef5833f
Author: Julian Hyde <jh...@apache.org>
Authored: Mon Jul 6 17:42:16 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Jul 20 20:58:24 2015 -0700

----------------------------------------------------------------------
 .../calcite/rel/metadata/RelMdCollation.java    | 13 +++-
 .../org/apache/calcite/rex/RexCallBinding.java  | 50 ++++++++++++++--
 .../java/org/apache/calcite/rex/RexLiteral.java |  4 ++
 .../org/apache/calcite/sql/SqlAsOperator.java   |  6 +-
 .../apache/calcite/sql/SqlBinaryOperator.java   | 20 +++----
 .../java/org/apache/calcite/sql/SqlCall.java    |  6 +-
 .../org/apache/calcite/sql/SqlCallBinding.java  | 54 +++++++++--------
 .../java/org/apache/calcite/sql/SqlLiteral.java | 61 +++++++++++++++++++
 .../org/apache/calcite/sql/SqlOperator.java     | 16 +++++
 .../apache/calcite/sql/SqlOperatorBinding.java  | 39 ++++++++++++
 .../apache/calcite/sql/SqlPrefixOperator.java   |  9 +--
 .../sql/fun/SqlAbstractTimeFunction.java        |  6 +-
 .../apache/calcite/sql/fun/SqlCastFunction.java | 13 ++--
 .../calcite/sql/fun/SqlCurrentDateFunction.java |  7 +--
 .../sql/fun/SqlDatetimeSubtractionOperator.java |  8 +--
 .../calcite/sql/fun/SqlExtractFunction.java     | 12 ++--
 .../calcite/sql/fun/SqlFloorFunction.java       |  8 +--
 .../sql/fun/SqlMonotonicBinaryOperator.java     | 63 ++++++++++----------
 .../sql/fun/SqlMonotonicUnaryFunction.java      |  9 +--
 .../sql/fun/SqlStringContextVariable.java       |  7 +--
 .../calcite/sql/fun/SqlSubstringFunction.java   | 24 +++-----
 21 files changed, 286 insertions(+), 149 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
index 614c111..52a7c43 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
@@ -35,10 +35,13 @@ import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.core.Values;
 import org.apache.calcite.rel.core.Window;
 import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexCallBinding;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexProgram;
+import org.apache.calcite.sql.validate.SqlMonotonicity;
 import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.Pair;
@@ -177,7 +180,6 @@ public class RelMdCollation {
   /** Helper method to determine a {@link Project}'s collation. */
   public static List<RelCollation> project(RelNode input,
       List<? extends RexNode> projects) {
-    // TODO: also monotonic expressions
     final SortedSet<RelCollation> collations = Sets.newTreeSet();
     final List<RelCollation> inputCollations =
         RelMetadataQuery.collations(input);
@@ -188,6 +190,15 @@ public class RelMdCollation {
     for (Ord<RexNode> project : Ord.zip(projects)) {
       if (project.e instanceof RexInputRef) {
         targets.put(((RexInputRef) project.e).getIndex(), project.i);
+      } else if (project.e instanceof RexCall) {
+        final RexCall call = (RexCall) project.e;
+        final RexCallBinding binding =
+            RexCallBinding.create(input.getCluster().getTypeFactory(), call);
+        if (false) {
+          final SqlMonotonicity monotonicity =
+              call.getOperator().getMonotonicity(binding);
+          // TODO: do something with this monotonicity
+        }
       }
     }
     final List<RelFieldCollation> fieldCollations = Lists.newArrayList();

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java b/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
index fc80c19..373b90f 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
@@ -24,6 +24,7 @@ import org.apache.calcite.sql.SqlOperator;
 import org.apache.calcite.sql.SqlOperatorBinding;
 import org.apache.calcite.sql.SqlUtil;
 import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.validate.SqlMonotonicity;
 import org.apache.calcite.sql.validate.SqlValidatorException;
 
 import com.google.common.collect.ImmutableList;
@@ -49,20 +50,37 @@ public class RexCallBinding extends SqlOperatorBinding {
     this.operands = ImmutableList.copyOf(operands);
   }
 
+  /** Creates a binding of the appropriate type. */
+  public static RexCallBinding create(RelDataTypeFactory typeFactory,
+      RexCall call) {
+    switch (call.getKind()) {
+    case CAST:
+      return new RexCastCallBinding(typeFactory, call.getOperator(),
+          call.getOperands(), call.getType());
+    }
+    return new RexCallBinding(typeFactory, call.getOperator(),
+        call.getOperands());
+  }
+
   //~ Methods ----------------------------------------------------------------
 
-  // implement SqlOperatorBinding
-  public String getStringLiteralOperand(int ordinal) {
+  @Override public String getStringLiteralOperand(int ordinal) {
     return RexLiteral.stringValue(operands.get(ordinal));
   }
 
-  // implement SqlOperatorBinding
-  public int getIntLiteralOperand(int ordinal) {
+  @Override public int getIntLiteralOperand(int ordinal) {
     return RexLiteral.intValue(operands.get(ordinal));
   }
 
-  // implement SqlOperatorBinding
-  public boolean isOperandNull(int ordinal, boolean allowCast) {
+  @Override public Comparable getOperandLiteralValue(int ordinal) {
+    return RexLiteral.value(operands.get(ordinal));
+  }
+
+  @Override public SqlMonotonicity getOperandMonotonicity(int ordinal) {
+    throw new AssertionError(); // to be completed
+  }
+
+  @Override public boolean isOperandNull(int ordinal, boolean allowCast) {
     return RexUtil.isNullLiteral(operands.get(ordinal), allowCast);
   }
 
@@ -80,6 +98,26 @@ public class RexCallBinding extends SqlOperatorBinding {
       Resources.ExInst<SqlValidatorException> e) {
     return SqlUtil.newContextException(SqlParserPos.ZERO, e);
   }
+
+  /** To be compatible with {@code SqlCall}, CAST needs to pretend that it
+   * has two arguments, the second of which is the target type. */
+  private static class RexCastCallBinding extends RexCallBinding {
+    private final RelDataType type;
+
+    public RexCastCallBinding(RelDataTypeFactory typeFactory,
+        SqlOperator sqlOperator, List<? extends RexNode> operands,
+        RelDataType type) {
+      super(typeFactory, sqlOperator, operands);
+      this.type = type;
+    }
+
+    @Override public RelDataType getOperandType(int ordinal) {
+      if (ordinal == 1) {
+        return type;
+      }
+      return super.getOperandType(ordinal);
+    }
+  }
 }
 
 // End RexCallBinding.java

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexLiteral.java b/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
index 767734d..0f8dceb 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
@@ -593,6 +593,10 @@ public class RexLiteral extends RexNode {
     return com.google.common.base.Objects.hashCode(value, type);
   }
 
+  public static Comparable value(RexNode node) {
+    return findValue(node);
+  }
+
   public static int intValue(RexNode node) {
     final Comparable value = findValue(node);
     return ((Number) value).intValue();

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/SqlAsOperator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlAsOperator.java b/core/src/main/java/org/apache/calcite/sql/SqlAsOperator.java
index 1d260cc..6f4aaf3 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlAsOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlAsOperator.java
@@ -124,10 +124,8 @@ public class SqlAsOperator extends SqlSpecialOperator {
     return validateOperands(validator, scope, call);
   }
 
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
-    return call.getOperandList().get(0).getMonotonicity(scope);
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
+    return call.getOperandMonotonicity(0);
   }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/SqlBinaryOperator.java
----------------------------------------------------------------------
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 bdcf961..c5f9f66 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlBinaryOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlBinaryOperator.java
@@ -180,20 +180,14 @@ public class SqlBinaryOperator extends SqlOperator {
     return type;
   }
 
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
     if (getName().equals("/")) {
-      final SqlNode operand0 = call.operand(0);
-      final SqlNode operand1 = call.operand(1);
-      final SqlMonotonicity mono0 = operand0.getMonotonicity(scope);
-      final SqlMonotonicity mono1 = operand1.getMonotonicity(scope);
+      final SqlMonotonicity mono0 = call.getOperandMonotonicity(0);
+      final SqlMonotonicity mono1 = call.getOperandMonotonicity(1);
       if (mono1 == SqlMonotonicity.CONSTANT) {
-        if (operand1 instanceof SqlLiteral) {
-          SqlLiteral literal = (SqlLiteral) operand1;
-          switch (
-              literal.bigDecimalValue().compareTo(
-                  BigDecimal.ZERO)) {
+        final Object o = call.getOperandLiteralValue(1);
+        if (o instanceof BigDecimal) {
+          switch (((BigDecimal) o).compareTo(BigDecimal.ZERO)) {
           case -1:
 
             // mono / -ve constant --> reverse mono, unstrict
@@ -211,7 +205,7 @@ public class SqlBinaryOperator extends SqlOperator {
       }
     }
 
-    return super.getMonotonicity(call, scope);
+    return super.getMonotonicity(call);
   }
 
   @Override public boolean validRexOperands(int count, boolean fail) {

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/SqlCall.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlCall.java b/core/src/main/java/org/apache/calcite/sql/SqlCall.java
index 7548e01..41e9eb3 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlCall.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlCall.java
@@ -156,7 +156,7 @@ public abstract class SqlCall extends SqlNode {
   protected String getCallSignature(
       SqlValidator validator,
       SqlValidatorScope scope) {
-    List<String> signatureList = new ArrayList<String>();
+    List<String> signatureList = new ArrayList<>();
     for (final SqlNode operand : getOperandList()) {
       final RelDataType argType = validator.deriveType(scope, operand);
       if (null == argType) {
@@ -169,7 +169,9 @@ public abstract class SqlCall extends SqlNode {
 
   public SqlMonotonicity getMonotonicity(SqlValidatorScope scope) {
     // Delegate to operator.
-    return getOperator().getMonotonicity(this, scope);
+    final SqlCallBinding binding =
+        new SqlCallBinding(scope.getValidator(), scope, this);
+    return getOperator().getMonotonicity(binding);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/SqlCallBinding.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlCallBinding.java b/core/src/main/java/org/apache/calcite/sql/SqlCallBinding.java
index ceb7b49..aaa8c96 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlCallBinding.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlCallBinding.java
@@ -21,13 +21,16 @@ import org.apache.calcite.runtime.CalciteException;
 import org.apache.calcite.runtime.Resources;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.validate.SelectScope;
+import org.apache.calcite.sql.validate.SqlMonotonicity;
 import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.sql.validate.SqlValidatorException;
 import org.apache.calcite.sql.validate.SqlValidatorNamespace;
 import org.apache.calcite.sql.validate.SqlValidatorScope;
 import org.apache.calcite.sql.validate.SqlValidatorUtil;
+import org.apache.calcite.util.NlsString;
 import org.apache.calcite.util.Util;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 import static org.apache.calcite.util.Static.RESOURCE;
@@ -109,43 +112,45 @@ public class SqlCallBinding extends SqlOperatorBinding {
     return call;
   }
 
-  // implement SqlOperatorBinding
-  public String getStringLiteralOperand(int ordinal) {
+  public SqlMonotonicity getOperandMonotonicity(int ordinal) {
+    return call.getOperandList().get(ordinal).getMonotonicity(scope);
+  }
+
+  @Override public String getStringLiteralOperand(int ordinal) {
     SqlNode node = call.operand(ordinal);
-    return SqlLiteral.stringValue(node);
+    final Object o = SqlLiteral.value(node);
+    return o instanceof NlsString ? ((NlsString) o).getValue() : null;
   }
 
-  // implement SqlOperatorBinding
-  public int getIntLiteralOperand(int ordinal) {
-    // todo: move this to SqlTypeUtil
+  @Override public int getIntLiteralOperand(int ordinal) {
     SqlNode node = call.operand(ordinal);
-    if (node instanceof SqlLiteral) {
-      SqlLiteral sqlLiteral = (SqlLiteral) node;
-      return sqlLiteral.intValue(true);
-    } else if (node instanceof SqlCall) {
-      final SqlCall c = (SqlCall) node;
-      if (c.getKind() == SqlKind.MINUS_PREFIX) {
-        SqlNode child = c.operand(0);
-        if (child instanceof SqlLiteral) {
-          return -((SqlLiteral) child).intValue(true);
-        }
+    final Object o = SqlLiteral.value(node);
+    if (o instanceof BigDecimal) {
+      BigDecimal bd = (BigDecimal) o;
+      try {
+        return bd.intValueExact();
+      } catch (ArithmeticException e) {
+        throw SqlUtil.newContextException(node.pos,
+            RESOURCE.numberLiteralOutOfRange(bd.toString()));
       }
     }
     throw Util.newInternal("should never come here");
   }
 
-  // implement SqlOperatorBinding
-  public boolean isOperandNull(int ordinal, boolean allowCast) {
+  @Override public Comparable getOperandLiteralValue(int ordinal) {
+    SqlNode node = call.operand(ordinal);
+    return SqlLiteral.value(node);
+  }
+
+  @Override public boolean isOperandNull(int ordinal, boolean allowCast) {
     return SqlUtil.isNullLiteral(call.operand(ordinal), allowCast);
   }
 
-  // implement SqlOperatorBinding
-  public int getOperandCount() {
+  @Override public int getOperandCount() {
     return call.getOperandList().size();
   }
 
-  // implement SqlOperatorBinding
-  public RelDataType getOperandType(int ordinal) {
+  @Override public RelDataType getOperandType(int ordinal) {
     final SqlNode operand = call.operand(ordinal);
     final RelDataType type = validator.deriveType(scope, operand);
     final SqlValidatorNamespace namespace = validator.getNamespace(operand);
@@ -155,7 +160,7 @@ public class SqlCallBinding extends SqlOperatorBinding {
     return type;
   }
 
-  public RelDataType getCursorOperand(int ordinal) {
+  @Override public RelDataType getCursorOperand(int ordinal) {
     final SqlNode operand = call.operand(ordinal);
     if (!SqlUtil.isCallTo(operand, SqlStdOperatorTable.CURSOR)) {
       return null;
@@ -165,8 +170,7 @@ public class SqlCallBinding extends SqlOperatorBinding {
     return validator.deriveType(scope, query);
   }
 
-  // implement SqlOperatorBinding
-  public String getColumnListParamInfo(
+  @Override public String getColumnListParamInfo(
       int ordinal,
       String paramName,
       List<String> columnList) {

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/SqlLiteral.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlLiteral.java b/core/src/main/java/org/apache/calcite/sql/SqlLiteral.java
index 3990a8a..b7aa493 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlLiteral.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlLiteral.java
@@ -259,9 +259,68 @@ public class SqlLiteral extends SqlNode {
   }
 
   /**
+   * Extracts the value from a literal.
+   *
+   * <p>Cases:
+   * <ul>
+   * <li>If the node is a character literal, a chain of string
+   * literals, or a CAST of a character literal, returns the value as a
+   * {@link NlsString}.
+   *
+   * <li>If the node is a numeric literal, or a negated numeric literal,
+   * returns the value as a {@link BigDecimal}.
+   *
+   * <li>If the node is a {@link SqlIntervalQualifier},
+   * returns its {@link TimeUnitRange}.
+   *
+   * <li>Otherwise the behavior is not specified.
+   * </ul>
+   */
+  public static Comparable value(SqlNode node) {
+    if (node instanceof SqlLiteral) {
+      SqlLiteral literal = (SqlLiteral) node;
+      switch (literal.getTypeName().getFamily()) {
+      case CHARACTER:
+        return (NlsString) literal.value;
+      case NUMERIC:
+        return (BigDecimal) literal.value;
+      }
+    }
+    if (SqlUtil.isLiteralChain(node)) {
+      assert node instanceof SqlCall;
+      final SqlLiteral literal =
+          SqlLiteralChainOperator.concatenateOperands((SqlCall) node);
+      assert SqlTypeUtil.inCharFamily(literal.getTypeName());
+      return (NlsString) literal.value;
+    }
+    if (node instanceof SqlIntervalQualifier) {
+      SqlIntervalQualifier qualifier = (SqlIntervalQualifier) node;
+      return qualifier.timeUnitRange;
+    }
+    switch (node.getKind()) {
+    case CAST:
+      assert node instanceof SqlCall;
+      return value(((SqlCall) node).operand(0));
+    case MINUS_PREFIX:
+      assert node instanceof SqlCall;
+      Comparable o = value(((SqlCall) node).operand(0));
+      if (o instanceof BigDecimal) {
+        BigDecimal bigDecimal = (BigDecimal) o;
+        return bigDecimal.negate();
+      }
+      // fall through
+    default:
+      throw Util.newInternal("invalid literal: " + node);
+    }
+  }
+
+  /**
    * Extracts the string value from a string literal, a chain of string
    * literals, or a CAST of a string literal.
+   *
+   * @deprecated Use {@link #value(SqlNode)}
    */
+  @Deprecated // to be removed before 2.0
   public static String stringValue(SqlNode node) {
     if (node instanceof SqlLiteral) {
       SqlLiteral literal = (SqlLiteral) node;
@@ -466,6 +525,7 @@ public class SqlLiteral extends SqlNode {
    *
    * @return -1, 0 or 1
    */
+  @Deprecated // to be removed before 2.0
   public int signum() {
     return bigDecimalValue().compareTo(
         BigDecimal.ZERO);
@@ -484,6 +544,7 @@ public class SqlLiteral extends SqlNode {
     }
   }
 
+  @Deprecated // to be removed before 2.0
   public String getStringValue() {
     return ((NlsString) value).getValue();
   }

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
----------------------------------------------------------------------
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 e8914b2..ee35b09 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
@@ -723,10 +723,26 @@ public abstract class SqlOperator {
    *
    * @param call  Call to this operator
    * @param scope Scope in which the call occurs
+   *
+   * @deprecated Use {@link #getMonotonicity(SqlOperatorBinding)}
    */
+  @Deprecated // to be removed before 2.0
   public SqlMonotonicity getMonotonicity(
       SqlCall call,
       SqlValidatorScope scope) {
+    return getMonotonicity(
+        new SqlCallBinding(scope.getValidator(), scope, call));
+  }
+
+  /**
+   * Returns whether a call to this operator is monotonic.
+   *
+   * <p>Default implementation returns {@link SqlMonotonicity#NOT_MONOTONIC}.
+   *
+   * @param call Call to this operator with particular arguments and information
+   *             about the monotonicity of the arguments
+   */
+  public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
     return SqlMonotonicity.NOT_MONOTONIC;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/SqlOperatorBinding.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlOperatorBinding.java b/core/src/main/java/org/apache/calcite/sql/SqlOperatorBinding.java
index 3e3b6f6..2ca13f9 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlOperatorBinding.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlOperatorBinding.java
@@ -20,6 +20,7 @@ import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.runtime.CalciteException;
 import org.apache.calcite.runtime.Resources;
+import org.apache.calcite.sql.validate.SqlMonotonicity;
 import org.apache.calcite.sql.validate.SqlValidatorException;
 
 import java.util.AbstractList;
@@ -94,6 +95,7 @@ public abstract class SqlOperatorBinding {
    * @param ordinal zero-based ordinal of operand of interest
    * @return string value
    */
+  @Deprecated // to be removed before 2.0
   public String getStringLiteralOperand(int ordinal) {
     throw new UnsupportedOperationException();
   }
@@ -104,11 +106,38 @@ public abstract class SqlOperatorBinding {
    * @param ordinal zero-based ordinal of operand of interest
    * @return integer value
    */
+  @Deprecated // to be removed before 2.0
   public int getIntLiteralOperand(int ordinal) {
     throw new UnsupportedOperationException();
   }
 
   /**
+   * Gets the value of a literal operand.
+   *
+   * <p>Cases:
+   * <ul>
+   * <li>If the operand is not a literal, the value is null.
+   *
+   * <li>If the operand is a string literal,
+   * the value will be of type {@link org.apache.calcite.util.NlsString}.
+   *
+   * <li>If the operand is a numeric literal,
+   * the value will be of type {@link java.math.BigDecimal}.
+   *
+   * <li>If the operand is an interval qualifier,
+   * the value will be of type {@link SqlIntervalQualifier}</li>
+   *
+   * <li>Otherwise the type is undefined, and the value may be null.
+   * </ul>
+   *
+   * @param ordinal zero-based ordinal of operand of interest
+   * @return value of operand
+   */
+  public Comparable getOperandLiteralValue(int ordinal) {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
    * Determines whether a bound operand is NULL.
    *
    * <p>This is only relevant for SQL validation.
@@ -136,6 +165,16 @@ public abstract class SqlOperatorBinding {
   public abstract RelDataType getOperandType(int ordinal);
 
   /**
+   * Gets the monotonicity of a bound operand.
+   *
+   * @param ordinal zero-based ordinal of operand of interest
+   * @return monotonicity of operand
+   */
+  public SqlMonotonicity getOperandMonotonicity(int ordinal) {
+    return SqlMonotonicity.NOT_MONOTONIC;
+  }
+
+  /**
    * Collects the types of the bound operands into a list.
    *
    * @return collected list

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/SqlPrefixOperator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlPrefixOperator.java b/core/src/main/java/org/apache/calcite/sql/SqlPrefixOperator.java
index b99abf2..8923645 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlPrefixOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlPrefixOperator.java
@@ -23,7 +23,6 @@ import org.apache.calcite.sql.type.SqlReturnTypeInference;
 import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
 import org.apache.calcite.sql.validate.SqlValidator;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
 import org.apache.calcite.util.Util;
 
 /**
@@ -90,14 +89,12 @@ public class SqlPrefixOperator extends SqlOperator {
     return type;
   }
 
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
     if (getName().equals("-")) {
-      return scope.getMonotonicity(call.operand(0)).reverse();
+      return call.getOperandMonotonicity(0).reverse();
     }
 
-    return super.getMonotonicity(call, scope);
+    return super.getMonotonicity(call);
   }
 
   @Override public boolean validRexOperands(int count, boolean fail) {

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/fun/SqlAbstractTimeFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlAbstractTimeFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlAbstractTimeFunction.java
index 6469927..82c660e 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlAbstractTimeFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlAbstractTimeFunction.java
@@ -17,7 +17,6 @@
 package org.apache.calcite.sql.fun;
 
 import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlFunction;
 import org.apache.calcite.sql.SqlFunctionCategory;
 import org.apache.calcite.sql.SqlKind;
@@ -28,7 +27,6 @@ import org.apache.calcite.sql.type.SqlOperandTypeChecker;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
 
 import static org.apache.calcite.util.Static.RESOURCE;
 
@@ -81,9 +79,7 @@ public class SqlAbstractTimeFunction extends SqlFunction {
   }
 
   // All of the time functions are increasing. Not strictly increasing.
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
     return SqlMonotonicity.INCREASING;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/fun/SqlCastFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlCastFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlCastFunction.java
index 08bd3b3..f4e933a 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlCastFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlCastFunction.java
@@ -37,7 +37,6 @@ import org.apache.calcite.sql.type.SqlOperandCountRanges;
 import org.apache.calcite.sql.type.SqlTypeFamily;
 import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
 
 import com.google.common.collect.ImmutableSet;
 
@@ -199,15 +198,11 @@ public class SqlCastFunction extends SqlFunction {
     writer.endFunCall(frame);
   }
 
-  @Override public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
-    RelDataTypeFamily castFrom =
-        scope.getValidator().deriveType(scope, call.operand(0)).getFamily();
-    RelDataTypeFamily castTo =
-        scope.getValidator().deriveType(scope, call.operand(1)).getFamily();
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
+    RelDataTypeFamily castFrom = call.getOperandType(0).getFamily();
+    RelDataTypeFamily castTo = call.getOperandType(1).getFamily();
     if (isMonotonicPreservingCast(castFrom, castTo)) {
-      return call.operand(0).getMonotonicity(scope);
+      return call.getOperandMonotonicity(0);
     } else {
       return SqlMonotonicity.NOT_MONOTONIC;
     }

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/fun/SqlCurrentDateFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlCurrentDateFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlCurrentDateFunction.java
index cdab873..ceb9b78 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlCurrentDateFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlCurrentDateFunction.java
@@ -16,15 +16,14 @@
  */
 package org.apache.calcite.sql.fun;
 
-import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlFunction;
 import org.apache.calcite.sql.SqlFunctionCategory;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlOperatorBinding;
 import org.apache.calcite.sql.SqlSyntax;
 import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
 
 /**
  * The <code>CURRENT_DATE</code> function.
@@ -48,9 +47,7 @@ public class SqlCurrentDateFunction extends SqlFunction {
     return SqlSyntax.FUNCTION_ID;
   }
 
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
     return SqlMonotonicity.INCREASING;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/fun/SqlDatetimeSubtractionOperator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlDatetimeSubtractionOperator.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlDatetimeSubtractionOperator.java
index 9ff4ee1..f79c366 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlDatetimeSubtractionOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlDatetimeSubtractionOperator.java
@@ -18,6 +18,7 @@ package org.apache.calcite.sql.fun;
 
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlOperatorBinding;
 import org.apache.calcite.sql.SqlSpecialOperator;
 import org.apache.calcite.sql.SqlSyntax;
 import org.apache.calcite.sql.SqlWriter;
@@ -25,7 +26,6 @@ import org.apache.calcite.sql.type.InferTypes;
 import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
 
 /**
  * A special operator for the subtraction of two DATETIMEs. The format of
@@ -70,10 +70,8 @@ public class SqlDatetimeSubtractionOperator extends SqlSpecialOperator {
     call.operand(2).unparse(writer, leftPrec, rightPrec);
   }
 
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
-    return SqlStdOperatorTable.MINUS.getMonotonicity(call, scope);
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
+    return SqlStdOperatorTable.MINUS.getMonotonicity(call);
   }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/fun/SqlExtractFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlExtractFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlExtractFunction.java
index 86c6893..fd3bad6 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlExtractFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlExtractFunction.java
@@ -16,16 +16,16 @@
  */
 package org.apache.calcite.sql.fun;
 
+import org.apache.calcite.avatica.util.TimeUnitRange;
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlFunction;
 import org.apache.calcite.sql.SqlFunctionCategory;
-import org.apache.calcite.sql.SqlIntervalQualifier;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlOperatorBinding;
 import org.apache.calcite.sql.SqlWriter;
 import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
 import org.apache.calcite.util.Util;
 
 /**
@@ -68,12 +68,10 @@ public class SqlExtractFunction extends SqlFunction {
     writer.endFunCall(frame);
   }
 
-  @Override public SqlMonotonicity getMonotonicity(SqlCall call,
-      SqlValidatorScope scope) {
-    final SqlIntervalQualifier o = call.operand(0);
-    switch (o.timeUnitRange) {
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
+    switch ((TimeUnitRange) call.getOperandLiteralValue(0)) {
     case YEAR:
-      return scope.getMonotonicity(call.operand(1)).unstrict();
+      return call.getOperandMonotonicity(1).unstrict();
     default:
       return SqlMonotonicity.NOT_MONOTONIC;
     }

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/fun/SqlFloorFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlFloorFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlFloorFunction.java
index e9d147f..c5986a0 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlFloorFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlFloorFunction.java
@@ -19,11 +19,11 @@ package org.apache.calcite.sql.fun;
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlFunctionCategory;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlOperatorBinding;
 import org.apache.calcite.sql.SqlWriter;
 import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
 
 import com.google.common.base.Preconditions;
 
@@ -48,11 +48,9 @@ public class SqlFloorFunction extends SqlMonotonicUnaryFunction {
 
   //~ Methods ----------------------------------------------------------------
 
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
     // Monotonic iff its first argument is, but not strict.
-    return scope.getMonotonicity(call.operand(0)).unstrict();
+    return call.getOperandMonotonicity(0).unstrict();
   }
 
   @Override public void unparse(SqlWriter writer, SqlCall call, int leftPrec,

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/fun/SqlMonotonicBinaryOperator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlMonotonicBinaryOperator.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlMonotonicBinaryOperator.java
index 42599a1..dc35783 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlMonotonicBinaryOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlMonotonicBinaryOperator.java
@@ -17,14 +17,15 @@
 package org.apache.calcite.sql.fun;
 
 import org.apache.calcite.sql.SqlBinaryOperator;
-import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlIntervalLiteral;
 import org.apache.calcite.sql.SqlKind;
-import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlOperatorBinding;
 import org.apache.calcite.sql.type.SqlOperandTypeChecker;
 import org.apache.calcite.sql.type.SqlOperandTypeInference;
 import org.apache.calcite.sql.type.SqlReturnTypeInference;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
+
+import java.math.BigDecimal;
 
 /**
  * Base class for binary operators such as addition, subtraction, and
@@ -54,11 +55,9 @@ public class SqlMonotonicBinaryOperator extends SqlBinaryOperator {
 
   //~ Methods ----------------------------------------------------------------
 
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
-    final SqlMonotonicity mono0 = scope.getMonotonicity(call.operand(0));
-    final SqlMonotonicity mono1 = scope.getMonotonicity(call.operand(1));
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
+    final SqlMonotonicity mono0 = call.getOperandMonotonicity(0);
+    final SqlMonotonicity mono1 = call.getOperandMonotonicity(1);
 
     // constant <op> constant --> constant
     if ((mono1 == SqlMonotonicity.CONSTANT)
@@ -75,24 +74,19 @@ public class SqlMonotonicBinaryOperator extends SqlBinaryOperator {
         return mono0;
       }
       assert getName().equals("*");
-      if (call.operand(1) instanceof SqlLiteral) {
-        SqlLiteral literal = call.operand(1);
-        switch (literal.signum()) {
-        case -1:
-
-          // mono0 * negative constant --> reverse mono0
-          return mono0.reverse();
-        case 0:
+      switch (signum(call.getOperandLiteralValue(1))) {
+      case -1:
+        // mono0 * negative constant --> reverse mono0
+        return mono0.reverse();
 
-          // mono0 * 0 --> constant (zero)
-          return SqlMonotonicity.CONSTANT;
-        default:
+      case 0:
+        // mono0 * 0 --> constant (zero)
+        return SqlMonotonicity.CONSTANT;
 
-          // mono0 * positiove constant --> mono0
-          return mono0;
-        }
+      default:
+        // mono0 * positive constant --> mono0
+        return mono0;
       }
-      return mono0;
     }
 
     // constant <op> mono
@@ -106,19 +100,18 @@ public class SqlMonotonicBinaryOperator extends SqlBinaryOperator {
         return mono1;
       }
       assert getName().equals("*");
-      if (call.operand(0) instanceof SqlLiteral) {
-        SqlLiteral literal = call.operand(0);
-        switch (literal.signum()) {
+      final Object v0 = call.getOperandLiteralValue(0);
+      if (v0 != null) {
+        switch (signum(v0)) {
         case -1:
-
           // negative constant * mono1 --> reverse mono1
           return mono1.reverse();
-        case 0:
 
+        case 0:
           // 0 * mono1 --> constant (zero)
           return SqlMonotonicity.CONSTANT;
-        default:
 
+        default:
           // positive constant * mono1 --> mono1
           return mono1;
         }
@@ -156,7 +149,17 @@ public class SqlMonotonicBinaryOperator extends SqlBinaryOperator {
       return SqlMonotonicity.NOT_MONOTONIC;
     }
 
-    return super.getMonotonicity(call, scope);
+    return super.getMonotonicity(call);
+  }
+
+  private int signum(Object o) {
+    if (o instanceof BigDecimal) {
+      return ((BigDecimal) o).signum();
+    } else if (o instanceof SqlIntervalLiteral.IntervalValue) {
+      return ((SqlIntervalLiteral.IntervalValue) o).getSign();
+    } else {
+      return 1;
+    }
   }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/fun/SqlMonotonicUnaryFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlMonotonicUnaryFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlMonotonicUnaryFunction.java
index d347fbc..2a194ba 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlMonotonicUnaryFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlMonotonicUnaryFunction.java
@@ -16,15 +16,14 @@
  */
 package org.apache.calcite.sql.fun;
 
-import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlFunction;
 import org.apache.calcite.sql.SqlFunctionCategory;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlOperatorBinding;
 import org.apache.calcite.sql.type.SqlOperandTypeChecker;
 import org.apache.calcite.sql.type.SqlOperandTypeInference;
 import org.apache.calcite.sql.type.SqlReturnTypeInference;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
 
 /**
  * Base class for unary operators such as FLOOR/CEIL which are monotonic for
@@ -51,10 +50,8 @@ public class SqlMonotonicUnaryFunction extends SqlFunction {
 
   //~ Methods ----------------------------------------------------------------
 
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
-    return scope.getMonotonicity(call.operand(0)).unstrict();
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
+    return call.getOperandMonotonicity(0).unstrict();
   }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/fun/SqlStringContextVariable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStringContextVariable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStringContextVariable.java
index db7057e..caedd64 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStringContextVariable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStringContextVariable.java
@@ -16,15 +16,14 @@
  */
 package org.apache.calcite.sql.fun;
 
-import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlFunction;
 import org.apache.calcite.sql.SqlFunctionCategory;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlOperatorBinding;
 import org.apache.calcite.sql.SqlSyntax;
 import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
 
 /**
  * Base class for functions such as "USER", "CURRENT_ROLE", and "CURRENT_PATH".
@@ -49,9 +48,7 @@ public class SqlStringContextVariable extends SqlFunction {
   }
 
   // All of the string constants are monotonic.
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
     return SqlMonotonicity.CONSTANT;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/f7ec3e84/core/src/main/java/org/apache/calcite/sql/fun/SqlSubstringFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlSubstringFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlSubstringFunction.java
index 5cac08f..73eda82 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlSubstringFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlSubstringFunction.java
@@ -23,9 +23,9 @@ import org.apache.calcite.sql.SqlCallBinding;
 import org.apache.calcite.sql.SqlFunction;
 import org.apache.calcite.sql.SqlFunctionCategory;
 import org.apache.calcite.sql.SqlKind;
-import org.apache.calcite.sql.SqlLiteral;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlOperandCountRange;
+import org.apache.calcite.sql.SqlOperatorBinding;
 import org.apache.calcite.sql.SqlUtil;
 import org.apache.calcite.sql.SqlWriter;
 import org.apache.calcite.sql.type.OperandTypes;
@@ -190,25 +190,19 @@ public class SqlSubstringFunction extends SqlFunction {
     writer.endFunCall(frame);
   }
 
-  public SqlMonotonicity getMonotonicity(
-      SqlCall call,
-      SqlValidatorScope scope) {
+  @Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
     // SUBSTRING(x FROM 0 FOR constant) has same monotonicity as x
-    final List<SqlNode> operands = call.getOperandList();
-    if (operands.size() == 3) {
-      final SqlNode op0 = operands.get(0);
-      final SqlNode op1 = operands.get(1);
-      final SqlNode op2 = operands.get(2);
-      final SqlMonotonicity mono0 = op0.getMonotonicity(scope);
+    if (call.getOperandCount() == 3) {
+      final SqlMonotonicity mono0 = call.getOperandMonotonicity(0);
       if ((mono0 != SqlMonotonicity.NOT_MONOTONIC)
-          && op1.getMonotonicity(scope) == SqlMonotonicity.CONSTANT
-          && op1 instanceof SqlLiteral
-          && ((SqlLiteral) op1).bigDecimalValue().equals(BigDecimal.ZERO)
-          && op2.getMonotonicity(scope) == SqlMonotonicity.CONSTANT) {
+          && call.getOperandMonotonicity(1) == SqlMonotonicity.CONSTANT
+          && call.getOperandLiteralValue(1) instanceof BigDecimal
+          && call.getOperandLiteralValue(1).equals(BigDecimal.ZERO)
+          && call.getOperandMonotonicity(2) == SqlMonotonicity.CONSTANT) {
         return mono0.unstrict();
       }
     }
-    return super.getMonotonicity(call, scope);
+    return super.getMonotonicity(call);
   }
 }