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

zabetak 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 90712c8a18 [CALCITE-7201] ClassCastException in RexInterpreter#search 
with different NUMERIC values
90712c8a18 is described below

commit 90712c8a18df637571ccefe2c04a17e8c2059be9
Author: Stamatis Zampetakis <[email protected]>
AuthorDate: Mon Oct 20 15:08:23 2025 +0200

    [CALCITE-7201] ClassCastException in RexInterpreter#search with different 
NUMERIC values
---
 .../org/apache/calcite/rex/RexInterpreter.java     |  8 ++-
 .../org/apache/calcite/rex/RexInterpreterTest.java | 62 ++++++++++++++++++++++
 .../apache/calcite/rex/RexProgramBuilderBase.java  |  3 ++
 3 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/core/src/main/java/org/apache/calcite/rex/RexInterpreter.java 
b/core/src/main/java/org/apache/calcite/rex/RexInterpreter.java
index 9e2bd0e3a7..549efa5387 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexInterpreter.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexInterpreter.java
@@ -304,7 +304,7 @@ private Comparable similar(List<Comparable> values) {
 
   @SuppressWarnings({"rawtypes", "unchecked"})
   private static Comparable search(SqlTypeName typeName, List<Comparable> 
values) {
-    final Comparable value = values.get(0);
+    Comparable value = values.get(0);
     final Sarg sarg = (Sarg) values.get(1);
     if (value == N) {
       switch (sarg.nullAs) {
@@ -316,6 +316,9 @@ private static Comparable search(SqlTypeName typeName, 
List<Comparable> values)
         return N;
       }
     }
+    if (SqlTypeName.NUMERIC_TYPES.contains(typeName)) {
+      value = number(value);
+    }
     return translate(sarg.rangeSet, typeName).contains(value);
   }
 
@@ -332,6 +335,9 @@ private static RangeSet translate(RangeSet rangeSet, 
SqlTypeName typeName) {
     case TIMESTAMP:
       return RangeSets.copy(rangeSet, TimestampString::getMillisSinceEpoch);
     default:
+      if (SqlTypeName.NUMERIC_TYPES.contains(typeName)) {
+        return RangeSets.copy(rangeSet, RexInterpreter::number);
+      }
       return rangeSet;
     }
   }
diff --git a/core/src/test/java/org/apache/calcite/rex/RexInterpreterTest.java 
b/core/src/test/java/org/apache/calcite/rex/RexInterpreterTest.java
new file mode 100644
index 0000000000..ca91f20760
--- /dev/null
+++ b/core/src/test/java/org/apache/calcite/rex/RexInterpreterTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.apache.calcite.rel.metadata.NullSentinel;
+
+import org.junit.jupiter.api.Test;
+
+import static org.apache.calcite.rex.RexInterpreter.evaluate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import static java.util.Collections.emptyMap;
+
+/**
+ * Test for {@link RexInterpreter}.
+ */
+public final class RexInterpreterTest extends RexProgramBuilderBase {
+
+  @Test void testSearchWithNumerics() {
+    RexNode l100_35 = literal(100.35);
+    RexNode l222_34 = literal(222.34);
+    RexNode l350_34 = literal(350.34);
+    RexNode l100 = literal(100);
+    RexNode l200 = literal(200);
+    RexNode l300 = literal(300);
+    // Exact with exact numerics types
+    assertEquals(true, evaluate(in(l100, l100, l200), emptyMap()));
+    assertEquals(false, evaluate(in(l300, l100, l200), emptyMap()));
+    assertEquals(true, evaluate(in(l200, nullInt, l200), emptyMap()));
+    assertEquals(NullSentinel.INSTANCE, evaluate(in(l100, nullInt, l200), 
emptyMap()));
+    assertEquals(NullSentinel.INSTANCE, evaluate(in(nullInt, l100, l200), 
emptyMap()));
+    // Approximate with exact numerics types
+    assertEquals(false, evaluate(in(l100_35, l100, l200), emptyMap()));
+    assertEquals(NullSentinel.INSTANCE, evaluate(in(l100_35, nullInt, l200), 
emptyMap()));
+    assertEquals(NullSentinel.INSTANCE, evaluate(in(nullDouble, l100, l200), 
emptyMap()));
+    // Approximate with approximate numerics types
+    assertEquals(true, evaluate(in(l100_35, l100_35, l222_34), emptyMap()));
+    assertEquals(false, evaluate(in(l350_34, l100_35, l222_34), emptyMap()));
+    assertEquals(true, evaluate(in(l100_35, l100_35, nullDouble), emptyMap()));
+    assertEquals(NullSentinel.INSTANCE, evaluate(in(l100_35, nullDouble, 
l222_34), emptyMap()));
+    assertEquals(NullSentinel.INSTANCE, evaluate(in(nullDouble, l100_35, 
l222_34), emptyMap()));
+    // Exact with approximate numerics types
+    assertEquals(false, evaluate(in(l100, l100_35, l222_34), emptyMap()));
+    assertEquals(NullSentinel.INSTANCE, evaluate(in(l100, nullDouble, 
l222_34), emptyMap()));
+    assertEquals(NullSentinel.INSTANCE, evaluate(in(nullInt, l100_35, 
l222_34), emptyMap()));
+  }
+}
diff --git 
a/core/src/test/java/org/apache/calcite/rex/RexProgramBuilderBase.java 
b/core/src/test/java/org/apache/calcite/rex/RexProgramBuilderBase.java
index 5c451ca8e5..b0286bd73a 100644
--- a/core/src/test/java/org/apache/calcite/rex/RexProgramBuilderBase.java
+++ b/core/src/test/java/org/apache/calcite/rex/RexProgramBuilderBase.java
@@ -539,6 +539,9 @@ protected RexLiteral literal(String value) {
     return rexBuilder.makeLiteral(value, nonNullableVarchar);
   }
 
+  protected RexLiteral literal(double value) {
+    return rexBuilder.makeApproxLiteral(value, nonNullableDouble);
+  }
   // Variables
 
   /**

Reply via email to