Repository navigation
[fix](be) Support a VARBINARY result in CASE WHEN - #69568
Conversation
### What problem does this PR solve? Issue Number: None Related PR: apache#69567 Problem Summary: A CASE WHEN whose result type is VARBINARY failed in BE with "argument_type VarBinary not supported" (Nullable(VarBinary) for a nullable result), e.g. SELECT CASE WHEN number % 3 = 0 THEN CAST(concat('a', number) AS VARBINARY) WHEN number % 3 = 1 THEN CAST('y' AS VARBINARY) ELSE CAST('x' AS VARBINARY) END FROM numbers('number' = '6') in every constant-folding mode. VCaseExpr::_execute_update_result dispatches the result column by primitive type and had no TYPE_VARBINARY entry. A CASE with a single WHEN and an ELSE did not fail only because Nereids rewrites it to if(), which copies values through IColumn::insert_from for any column. TYPE_VARBINARY now maps to ColumnVarbinary and takes the per-row copy that CASE uses for strings (update_result_normal), with and without a nullable result. branch-4.2 has the same gap. ### Release note Fix: CASE WHEN with two or more WHEN branches and a VARBINARY result failed with "argument_type VarBinary not supported". ### Check List (For Author) - Test: Unit Test / Regression test - VCaseVarbinaryTest: a VARBINARY result with ELSE (column, constant branch, NUL and non-UTF-8 bytes) and a nullable one without ELSE (NULL rows from a branch and from no match); both fail without the change - Regression query_p0 suite for CASE WHEN with a VARBINARY result in the three folding modes - Behavior changed: No - Does this need documentation: No Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
|
run buildall |
|
/review |
There was a problem hiding this comment.
Reviewed all four changed files at 2e14addd82146902041b3ea7a66768d4515f7b35 and the relevant FE coercion, CASE/IF execution, column insertion and exception paths. No actionable findings were identified. There were no existing inline findings to carry forward and no additional user focus points.
The new TYPE_VARBINARY dispatch uses ColumnVarbinary and the established per-row selection path for both nullable and non-nullable results. Constant branches are unpacked before nullable checks; selected nested values and null-map entries use the same source row; missing ELSE inserts NULL. Binary values are copied into result-owned inline or arena storage, preserving NUL and non-UTF-8 bytes.
| Required checkpoint | Conclusion |
|---|---|
| Goal and evidence | The change addresses unsupported multi-WHEN VARBINARY results. Two direct BE unit tests and regression queries target the dispatch and observable bytes/NULLs. |
| Scope and clarity | The three production additions are focused and reuse existing selection code. |
| Concurrency and locking | No shared mutable state, threads or locks are introduced. |
| Lifecycle and static initialization | Inputs remain owned during selection; the fresh result owns copied values. No new static initialization or reference cycle. |
| Configuration | No configuration items are added; tests vary existing folding settings. |
| Compatibility | No symbol signature, wire or storage format changes. Older BEs retain their prior lack of support for these CASE results. |
| Thrift/protobuf field IDs | No generated protocol definitions are changed. |
| Parallel paths | Both nullable modes and branch-index widths use the new dispatch. Single-WHEN CASE rewrites to IF; IF and short-circuit CASE already support VARBINARY through generic insertion. |
| Conditional checks | The compile-time type condition correctly excludes VARBINARY from numeric selection. No speculative runtime error check is added. |
| Test coverage | Covers column/constant branches, selected NULLs, implicit NULL, empty bytes, embedded NUL/high bytes and three folding modes. Dedicated long-value and constant-nullable VARBINARY cases are absent; their mechanisms were checked statically. |
| Expected results | All 12 new golden sections match the SQL by inspection. Test execution and output-generation provenance were not independently verified. |
| Observability | Existing error propagation and expression/type checks are sufficient for this local selection change; no new metrics/logs are needed. |
| Transactions and persistence | Production transaction, visibility/version, delete-bitmap, EditLog and persistence paths are unchanged. |
| Data writes and atomicity | No production write path is modified; test inserts use existing behavior. |
| FE/BE variable propagation | No new transmitted variables. Existing CASE coercion and nullable metadata agree with the selected BE column type. |
| Performance | Reuses row-wise copying without materializing constant branch columns. Selection remains O(rows * WHEN-count), followed by O(rows + branches + selected bytes) copying; numeric dispatch is unchanged. |
| Other issues | No further actionable issue found in error propagation, COW ownership, header conventions, or the remaining changed code. |
Review coverage is complete for the static scope. Builds, unit/regression tests, formatter/static-analysis execution, and release ELF/runtime compatibility checks were not run under the review-only contract. The review does not independently establish runtime test results.
Review converged after 2 round(s).
TPC-H: Total hot run time: 28284 ms |
TPC-DS: Total hot run time: 150437 ms |
ClickBench: Total hot run time: 24.41 s |
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
|
run cloud_p0 |
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
What problem does this PR solve?
Issue Number: None
Related PR: #69567
Problem Summary:
In short. A CASE WHEN whose result type is VARBINARY and that has two or more WHEN branches failed in BE with
argument_type VarBinary not supported. BE now selects VARBINARY values the way it selects strings.Background. VARBINARY values reach queries through external tables (Iceberg, Paimon and Hive binary columns map to VARBINARY) and through
CAST(... AS VARBINARY). BE evaluates CASE WHEN inVCaseExpr: it computes, for every row, the index of the branch that the row takes, and thenVCaseExpr::_execute_update_resultbuilds the result column, dispatching on the result's primitive type to a typed copy loop. Nereids rewrites a CASE with a single WHEN and an ELSE intoif(), whose generic path copies values throughIColumn::insert_fromand accepts any column type.The problem, and what it cost. The dispatch in
_execute_update_resulthad no entry forTYPE_VARBINARY, so it fell through toNOT_IMPLEMENTED_ERROR. Every query with such a CASE failed, whatever the constant-folding mode (the CASE is evaluated by BE, not folded), for exampleOnly a CASE with one WHEN and an ELSE worked, because it is evaluated as
if(). branch-4.2 has the same gap.How this PR fixes it.
TYPE_VARBINARYnow maps toColumnVarbinary, andColumnVarbinarytakes the per-row copy (update_result_normal) that CASE already uses for strings, both for a nullable result (including CASE without ELSE, whose unmatched rows are NULL) and for a non-nullable one. FE needs no change.Results.
argument_type VarBinary not supportedargument_type Nullable(VarBinary) not supportedif())VCaseVarbinaryTestadds two cases through_execute_update_result: a non-nullable result with ELSE (a column branch, a constant branch, NUL and non-UTF-8 bytes) and a nullable result without ELSE (NULL from a branch and from unmatched rows). Both fail without the change with the error above.VCaseSelectionTeststill passes (50 cases in total).query_p0/sql_functions/binary_functions/test_varbinary_case_whenruns CASE with and without ELSE over a table, overnumbers()and on constants, in the three constant-folding modes (FE folding, folding by BE, no folding); the results match in all modes.Release note
Fix: a CASE WHEN with two or more WHEN branches and a VARBINARY result failed with "argument_type VarBinary not supported".
Check List (For Author)
Test
Behavior changed:
Does this need documentation?
Check List (For Reviewer who merge this PR)