[BugFix] Fix COALESCE(null, 42) returning wrong type string instead of int (#5175)#5315
Conversation
…f int (opensearch-project#5175) Root cause: In PPL, `null` is parsed as a QualifiedName (field name), not a literal. When COALESCE encounters an unresolvable field, the fallback method replaceWithNullLiteralInCoalesce() created a null literal typed as VARCHAR instead of NULL. This caused leastRestrictive([VARCHAR, INTEGER]) to return VARCHAR, producing string output for what should be an integer result. Fix (three parts): 1. QualifiedNameResolver: Use SqlTypeName.NULL instead of SqlTypeName.VARCHAR for null literals in COALESCE, so leastRestrictive([NULL, INTEGER]) returns INTEGER correctly. 2. EnhancedCoalesceFunction: Filter out NULL-typed operands before calling leastRestrictive in return type inference, with VARCHAR fallback when all operands are NULL. 3. CalciteRexNodeVisitor: Scope the inCoalesceFunction flag to direct COALESCE arguments only, preventing unresolved field names in nested functions from being silently replaced with null literals. Signed-off-by: Heng Qian <qianheng@amazon.com>
Decision LogRoot Cause: Approach: Three-part fix:
Alternatives Rejected:
Pitfalls:
Things to Watch: The |
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
Description
Fix COALESCE returning wrong type
stringinstead ofintwhen called with null and integer literals.Root Cause: In PPL,
nullis parsed as aQualifiedName(field name), not aLiteral. When COALESCE encounters an unresolvable field name likenull, it falls back toreplaceWithNullLiteralInCoalesce()which incorrectly created a null literal typed asVARCHAR. This causedleastRestrictive([VARCHAR, INTEGER])to returnVARCHAR, makingCOALESCE(null, 42)returnstringtype.Fix (three parts):
QualifiedNameResolver.java): Changed the null literal type fromSqlTypeName.VARCHARtoSqlTypeName.NULL(Calcite's bottom type, compatible with any type). This makesleastRestrictive([NULL, INTEGER])correctly returnINTEGER.EnhancedCoalesceFunction.java): Filter outNULL-typed operands in the return type inference before callingleastRestrictive, with fallback to VARCHAR when all operands are NULL.CalciteRexNodeVisitor.java): Scope theinCoalesceFunctioncontext flag to direct COALESCE arguments only, preventing unresolved field names in nested function calls (e.g.,nomvrewriting tocoalesce(mvjoin(array_compact(field), ...))) from being silently replaced with null literals.Related Issues
Resolves #5175
Check List
-s)spotlessCheckpassed.g4files synced (N/A - no grammar changes)