Skip to content

[CALCITE-7724] SqlUtil#lookupSubjectRoutines rejects a valid operator… - #5187

Open
sbroeder wants to merge 2 commits into
apache:mainfrom
sbroeder:7724
Open

[CALCITE-7724] SqlUtil#lookupSubjectRoutines rejects a valid operator…#5187
sbroeder wants to merge 2 commits into
apache:mainfrom
sbroeder:7724

Conversation

@sbroeder

Copy link
Copy Markdown
Contributor

… when getFunctionKind() remaps its kind and 2+ candidates share a name

filterOperatorRoutinesByKind's "fourth pass" only runs once at least two candidates survive the earlier passes (a single surviving candidate short-circuits before this pass). It compares candidate.getKind().getFunctionKind() against the call's own, already-bound SqlKind - but that comparison applies getFunctionKind()'s remapping (introduced for this method) to the candidate side only, not to the requested side.

For any SqlKind that getFunctionKind() maps to something else - POSITION and the newly-dedicated CHAR_LENGTH both map to OTHER_FUNCTION, along with ~90 others in that switch - this asymmetry means an operator can fail to match even itself, once a second candidate for the same name is present (e.g. because two chained operator tables both contribute an entry for it). The call is rejected outright with "No match found for function signature ...", even though exactly the intended operator was available.

Jira Link

CALCITE-7724

Changes Proposed

… when getFunctionKind() remaps its kind and 2+ candidates share a name

filterOperatorRoutinesByKind's "fourth pass" only runs once at least
two candidates survive the earlier passes (a single surviving
candidate short-circuits before this pass). It compares
candidate.getKind().getFunctionKind() against the call's own,
already-bound SqlKind - but that comparison applies getFunctionKind()'s
remapping (introduced for this method) to the candidate side only, not
to the requested side.

For any SqlKind that getFunctionKind() maps to something else -
POSITION and the newly-dedicated CHAR_LENGTH both map to
OTHER_FUNCTION, along with ~90 others in that switch - this asymmetry
means an operator can fail to match even itself, once a second
candidate for the same name is present (e.g. because two chained
operator tables both contribute an entry for it). The call is rejected
outright with "No match found for function signature ...", even though
exactly the intended operator was available.

Fix: map both sides of the comparison through getFunctionKind() before
comparing, matching normal-case comparisons for kinds it doesn't remap.

Added a regression test (chaining the standard operator table with
itself to force the two-candidate precondition, the minimal way to
reach the buggy pass) and verified the entire SqlValidatorTest suite
(589 tests) still passes with the fix.

private static Iterator<SqlOperator> filterOperatorRoutinesByKind(
Iterator<SqlOperator> routines, final SqlKind sqlKind) {
// Map both sides through getFunctionKind() so a candidate can still match a call

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment could be shorter

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack

@@ -1043,6 +1025,43 @@ void testDyadicCollateOperator() {
.fails("Parameters must be of the same type");
}

/** Test case for <a href="https://issues.apache.org/jira/browse/CALCITE-7724">

@mihaibudiu mihaibudiu Aug 18, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment is too long; please do not submit useless comments, they will take time from reviewers now and forever when they will be read

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack

* spurious "No match found for function signature" validation error for an otherwise
* perfectly valid call. */
@Test void testFunctionKindMismatchWithDuplicateOperatorTableEntry() {
// Chaining the standard operator table with itself is a minimal way to force two

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enough to say that each function will appear twice

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack

@mihaibudiu mihaibudiu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is better. But at least Claude writes some horrible horrible comments. I highly recommend never submitting them as they are.

* 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure how useful this paragraph is.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to keep it short and be clear. Two competing goals. Are you okay with the comments as they are or do you have a preferred change?

@sonarqubecloud

Copy link
Copy Markdown

@mihaibudiu

Copy link
Copy Markdown
Contributor

I have approved

@mihaibudiu mihaibudiu added the LGTM-will-merge-soon Overall PR looks OK. Only minor things left. label Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

LGTM-will-merge-soon Overall PR looks OK. Only minor things left.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants