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();