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

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


The following commit(s) were added to refs/heads/main by this push:
     new 328878b4b3 [CALCITE-6823] Cannot convert CHAR to Integer when applying 
SubstitutionVisitor
328878b4b3 is described below

commit 328878b4b3e2cf27881dc86f607c4701719e6bce
Author: Yu Xu <[email protected]>
AuthorDate: Thu May 28 23:04:45 2026 +0800

    [CALCITE-6823] Cannot convert CHAR to Integer when applying 
SubstitutionVisitor
---
 .../apache/calcite/plan/VisitorDataContext.java    | 87 +++++++++++++++++++++-
 .../MaterializedViewSubstitutionVisitorTest.java   | 15 ++++
 2 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/plan/VisitorDataContext.java 
b/core/src/main/java/org/apache/calcite/plan/VisitorDataContext.java
index 1b48b8c64f..388a074883 100644
--- a/core/src/main/java/org/apache/calcite/plan/VisitorDataContext.java
+++ b/core/src/main/java/org/apache/calcite/plan/VisitorDataContext.java
@@ -28,8 +28,11 @@
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.util.DateString;
 import org.apache.calcite.util.NlsString;
 import org.apache.calcite.util.Pair;
+import org.apache.calcite.util.TimeString;
+import org.apache.calcite.util.TimestampString;
 import org.apache.calcite.util.trace.CalciteLogger;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -38,6 +41,8 @@
 import java.math.BigDecimal;
 import java.util.List;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * DataContext for evaluating a RexExpression.
  */
@@ -107,6 +112,26 @@ public VisitorDataContext(@Nullable Object[] values) {
     return new VisitorDataContext(values);
   }
 
+  /**
+   * Extracts a value from a RexLiteral for use in DataContext.
+   *
+   * <p>Returns a Pair of (column index, value) if extraction is successful,
+   * or null if the value cannot be extracted or is invalid.
+   *
+   * <p>Returns null when:
+   * <ul>
+   *   <li>Arguments are not valid RexInputRef and RexLiteral</li>
+   *   <li>Type conversion fails (e.g., invalid date/time format)</li>
+   *   <li>Type combination is unsupported</li>
+   * </ul>
+   *
+   * <p>When null is returned, the containing optimization (e.g.,
+   * materialized view substitution) cannot be applied and is skipped.
+   *
+   * @param inputRef the input reference (column)
+   * @param literal the literal value to extract
+   * @return a Pair of (column index, value) or null
+   */
   public static @Nullable Pair<Integer, ? extends @Nullable Object> getValue(
       @Nullable RexNode inputRef, @Nullable RexNode literal) {
     inputRef = inputRef == null ? null : RexUtil.removeCast(inputRef);
@@ -140,10 +165,68 @@ public VisitorDataContext(@Nullable Object[] values) {
       case DECIMAL:
         return Pair.of(index, rexLiteral.getValueAs(BigDecimal.class));
       case DATE:
+        switch (rexLiteral.getType().getSqlTypeName()) {
+        case DATE:
+          return Pair.of(index, rexLiteral.getValueAs(Integer.class));
+        case CHAR:
+        case VARCHAR:
+          try {
+            return Pair.of(index,
+                new 
DateString(requireNonNull(rexLiteral.getValueAs(String.class)))
+                    .getDaysSinceEpoch());
+          } catch (IllegalArgumentException e) {
+            LOGGER.warn(
+                "Cannot convert string literal '{}' to DATE type; "
+                    + "materialized view optimization will be skipped",
+                rexLiteral.getValueAs(String.class), e);
+            return null;
+          }
+        default:
+          break;
+        }
+        break;
       case TIME:
-        return Pair.of(index, rexLiteral.getValueAs(Integer.class));
+        switch (rexLiteral.getType().getSqlTypeName()) {
+        case TIME:
+          return Pair.of(index, rexLiteral.getValueAs(Integer.class));
+        case CHAR:
+        case VARCHAR:
+          try {
+            return Pair.of(index,
+                new 
TimeString(requireNonNull(rexLiteral.getValueAs(String.class)))
+                    .getMillisOfDay());
+          } catch (IllegalArgumentException e) {
+            LOGGER.debug(
+                "Cannot convert string literal '{}' to TIME type; "
+                    + "materialized view optimization will be skipped",
+                rexLiteral.getValueAs(String.class), e);
+            return null;
+          }
+        default:
+          break;
+        }
+        break;
       case TIMESTAMP:
-        return Pair.of(index, rexLiteral.getValueAs(Long.class));
+        switch (rexLiteral.getType().getSqlTypeName()) {
+        case TIMESTAMP:
+          return Pair.of(index, rexLiteral.getValueAs(Long.class));
+        case CHAR:
+        case VARCHAR:
+          try {
+            return Pair.of(index,
+                new 
TimestampString(requireNonNull(rexLiteral.getValueAs(String.class)))
+                    .getMillisSinceEpoch());
+          } catch (IllegalArgumentException e) {
+            LOGGER.debug(
+                "Cannot convert string literal '{}' to TIMESTAMP type; "
+                    + "materialized view optimization will be skipped",
+                rexLiteral.getValueAs(String.class), e);
+            return null;
+          }
+        default:
+          break;
+        }
+        break;
       case CHAR:
         return Pair.of(index, rexLiteral.getValueAs(Character.class));
       case VARCHAR:
diff --git 
a/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java
 
b/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java
index 22fa948ed6..a19cd683d2 100644
--- 
a/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java
+++ 
b/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java
@@ -112,6 +112,21 @@ protected final MaterializedViewFixture sql(String 
materialize,
         .ok();
   }
 
+  /** Test case of
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6823";>[CALCITE-6823]
+   * Cannot convert CHAR to Integer when applying SubstitutionVisitor</a>. */
+  @Test void testDateFilter() {
+    sql("SELECT HIREDATE FROM EMP WHERE HIREDATE > '1990-10-01'",
+        "SELECT * FROM EMP WHERE HIREDATE > '1990-05-01'")
+        .withDefaultSchemaSpec(CalciteAssert.SchemaSpec.SCOTT)
+        .noMat();
+
+    sql("SELECT HIREDATE FROM EMP WHERE HIREDATE > '1990-10-01'",
+        "SELECT * FROM EMP WHERE HIREDATE > 'invalid-date'")
+        .withDefaultSchemaSpec(CalciteAssert.SchemaSpec.SCOTT)
+        .noMat();
+  }
+
   @Test void testFilterToProject0() {
     sql("select *, \"empid\" * 2 from \"emps\"",
         "select * from \"emps\" where (\"empid\" * 2) > 3")

Reply via email to