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

mihaibudiu 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 f9b66d4929 [CALCITE-7724] SqlUtil#lookupSubjectRoutines rejects a 
valid operator when getFunctionKind() remaps its kind and 2+ candidates share a 
name
f9b66d4929 is described below

commit f9b66d49297c525166cac172234cc2f336361f5a
Author: Sean Broeder <[email protected]>
AuthorDate: Wed Aug 19 06:54:26 2026 -0700

    [CALCITE-7724] SqlUtil#lookupSubjectRoutines rejects a valid operator when 
getFunctionKind() remaps its kind and 2+ candidates share a name
    
    Now map both sides of the comparison through getFunctionKind() before
    comparing.
---
 .../main/java/org/apache/calcite/sql/SqlUtil.java  |  5 ++++-
 .../org/apache/calcite/test/SqlValidatorTest.java  | 24 ++++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/core/src/main/java/org/apache/calcite/sql/SqlUtil.java 
b/core/src/main/java/org/apache/calcite/sql/SqlUtil.java
index b5c91a1c7a..1dba9d573e 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlUtil.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlUtil.java
@@ -558,9 +558,12 @@ public static SqlLiteral 
concatenateLiterals(List<SqlLiteral> lits) {
 
   private static Iterator<SqlOperator> filterOperatorRoutinesByKind(
       Iterator<SqlOperator> routines, final SqlKind sqlKind) {
+    // Mirror getFunctionKind() on both sides, or an operator whose kind maps 
to
+    // something else (e.g. POSITION -> OTHER_FUNCTION) can fail to match 
itself.
+    final SqlKind sqlFunctionKind = sqlKind.getFunctionKind();
     return Iterators.filter(routines,
         operator -> requireNonNull(operator, "operator")
-            .getKind().getFunctionKind() == sqlKind);
+            .getKind().getFunctionKind() == sqlFunctionKind);
   }
 
   /**
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java 
b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index 38f883743e..f0494539f0 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -1043,6 +1043,30 @@ void testDyadicCollateOperator() {
         .fails("Parameters must be of the same type");
   }
 
+  /** Test case for <a 
href="https://issues.apache.org/jira/browse/CALCITE-7724";>
+   * [CALCITE-7724] SqlUtil#lookupSubjectRoutines rejects a valid operator 
when its
+   * SqlKind is remapped by SqlKind#getFunctionKind() and two operator-table 
entries
+   * resolve to it</a>.
+   *
+   * <p>The kind-based fourth pass in {@code filterOperatorRoutinesByKind} 
maps only
+   * the candidate's kind through {@code getFunctionKind()}, not the call's 
own kind -
+   * so an operator whose kind is remapped (e.g. {@link SqlKind#POSITION}) can 
fail to
+   * match itself once a second candidate for the same name exists. */
+  @Test void testFunctionKindMismatchWithDuplicateOperatorTableEntry() {
+    // Chaining the operator table with itself ensures that each appears twice.
+    final SqlOperatorTable duplicated =
+        SqlOperatorTables.chain(SqlStdOperatorTable.instance(), 
SqlStdOperatorTable.instance());
+    expr("position('mouse' in 'house')")
+        .withOperatorTable(duplicated)
+        .ok();
+    expr("char_length('string')")
+        .withOperatorTable(duplicated)
+        .ok();
+    expr("character_length('string')")
+        .withOperatorTable(duplicated)
+        .ok();
+  }
+
   @Test void testTrim() {
     expr("trim('mustache' FROM 'beard')").ok();
     expr("trim(both 'mustache' FROM 'beard')").ok();

Reply via email to