[CALCITE-7437] Type coercion for quantifier operators is incomplete#4877
[CALCITE-7437] Type coercion for quantifier operators is incomplete#4877Dwrite wants to merge 3 commits intoapache:mainfrom
Conversation
|
This appears to be an AI-generated solution. We don't object to using AI to solve problems, but it's necessary to confirm that the code changes and comments meet review criteria before submission. For example, the title should be [CALCITE-7437], and the PR description should ideally follow the existing template. |
yeah. The initial draft of this description was generated with the assistance of Gemini to ensure clarity and professional phrasing, then reviewed and refined by me to accurately reflect the technical implementation. The core solution and logic were developed by myself. |
|
| if (!isSubQuery) { | ||
| return false; | ||
| } | ||
| // Subquery path: derive type2 from the first output column. |
There was a problem hiding this comment.
why only the first column and not the entire row?
| // There is no array wrapper to reconstruct. | ||
| coercedRight = false; | ||
| } else { | ||
| // For collection (ARRAY[...]), reconstruct the array type with the |
There was a problem hiding this comment.
why always ARRAY?
Why not a MULTISET, for example?
Or a MAP?
| <![CDATA[ | ||
| LogicalProject(DEPTNO=[$0], EXPR$1=[OR(AND(IS NOT NULL($5), <>($2, 0)), AND(<($3, $2), null, <>($2, 0), IS NULL($5)))]) | ||
| LogicalJoin(condition=[=($1, $4)], joinType=[left]) | ||
| LogicalJoin(condition=[=(CAST($1):INTEGER NOT NULL, $4)], joinType=[left]) |
There was a problem hiding this comment.
This looks dangerous: how do we know that $1 is not null?
A cast to a NOT NULL type may fail at runtime for a NULL value.



Summary
Fix RuntimeException when using SOME/ANY/ALL with mismatched types and all quantifiers should work in the same way, like IN.
The issue:
Calcite currently crashes with a RuntimeException when a quantifier operator (like SOME, ANY, or ALL) compares columns with different types—for example, a VARCHAR on the left and a SMALLINT from the subquery.
The error (SELECT deptno, dname > SOME(SELECT empno FROM emp) AS b FROM dept):
'java.lang.RuntimeException: while resolving method 'gt[class java.lang.String, short]' in c org.apache.calcite.runtime.SqlFunctions This happens because the SqlValidator doesn't trigger TypeCoercion for these operators, so no CAST is inserted. When it gets to code generation, Linq4j can't find a way to compare a raw String with a primitive short.
The fix:
I updated TypeCoercionImpl to handle these quantifier operators. Now, it follows the same implicit cast rules we use for standard comparisons or the IN operator.
Testing:
Added a case in sub-query.iq. The plan now correctly shows a CAST (e.g., CAST($1):SMALLINT) before the join condition.
Note: If the data itself is a non-numeric string (like "ACCOUNTING"), you'll still get a NumberFormatException at runtime, but this is expected behavior (similar to how CAST('A' AS INT) behaves in other engines). The fix ensures the engine can at least generate the correct execution plan instead of crashing during the validation or code-gen phase.