jose1003 opened a new issue, #68685: URL: https://github.com/apache/doris/issues/68685
### Search before asking - [x] I had searched in the [issues](https://github.com/apache/doris/issues?q=is%3Aissue) and found no similar issues. ### Version ustom build, binary reports `2.1.12-stable` (docker image tag `local/doris-be:4.0.8` is misleading). Built from `doris_release` with ldb-toolchain v0.26 (GCC 15), per the stack trace paths (`/home/zcp/repo_center/doris_release/doris/be/...`). ### What's Wrong? The BE process **aborts (SIGABRT)** when a query contains a binary predicate on a VARCHAR column whose constant side is a constant *expression* (e.g. `COALESCE(NULLIF(CAST('' AS CHAR), ''), 'x')`) instead of a plain literal. During predicate pushdown, `OlapScanLocalState::_should_push_down_binary_predicate` (`be/src/pipeline/exec/olap_scan_operator.cpp:113`) does an unchecked `assert_cast<const ColumnConst*>` on the constant side of the predicate. When the constant was const-folded by BE, the resulting column is a plain `ColumnStr<uint32_t>` (not wrapped in `ColumnConst`), so `assert_cast` throws: ``` [E-7412] Bad cast from type:doris::vectorized::ColumnStr<unsigned int>* to doris::vectorized::ColumnConst const* ``` The same predicate is first rejected several times as a `Status` warning (recoverable), but on the next fragment the exception escapes through a `noexcept` frame and hits `std::terminate`: 0# doris::signal::FailureSignalHandler at be/src/common/signal_handler.h:420 1-4# libc: pthread_kill / raise / abort 5# ... in /opt/apache-doris/be/lib/doris_be 6# __cxxabiv1::__terminate 7# __cxa_call_terminate 8# __gxx_personality_v0 9# _Unwind_RaiseException_Phase2 10# _Unwind_Resume 11# doris::vectorized::assert_cast<ColumnConst const*, ...> at be/src/vec/common/assert_cast.h:75 12# doris::pipeline::OlapScanLocalState::_should_push_down_binary_predicate at be/src/pipeline/exec/olap_scan_operator.cpp :113 13# doris::pipeline::ScanLocalState<OlapScanLocalState>::_normalize_binary_predicate<(doris::PrimitiveType)10> at be/src/p ipeline/exec/scan_operator.cpp:812 14# ... ScanLocalState::_normalize_predicate / _normalize_conjuncts 17# doris::pipeline::OlapScanLocalState::_process_conjuncts at be/src/pipeline/exec/olap_scan_operator.cpp:386 18# doris::pipeline::ScanLocalState<...>::open at be/src/pipeline/exec/scan_operator.cpp:189 20# doris::pipeline::PipelineTask::_open at be/src/pipeline/pipeline_task.cpp:269 22# doris::pipeline::TaskScheduler::_do_work at be/src/pipeline/task_scheduler.cpp:153 ``` `(PrimitiveType)10` = `TYPE_VARCHAR`, i.e. the predicate is on a varchar column. Because the failing query keeps being re-submitted (in our case by a BI dashboard every ~30s), the BE enters a **crash loop** and all other queries/loads on the node fail with "tablet has no queryable replicas" while it is down. ## What You Expected? The query should execute (or fail with a query-level error). A user-level SQL expression must never be able to abort the BE process. ### What You Expected? Fix the bug ### How to Reproduce? 1. Create any table with a VARCHAR column, e.g.: ```sql CREATE TABLE t (k INT, v VARCHAR(64)) DUPLICATE KEY(k) DISTRIBUTED BY HASH(k) BUCKETS 1; INSERT INTO t VALUES (1, 'a'); ``` 2. Run a query where the constant side of a binary predicate on the varchar column is a const-folded expression instead of a plain literal: ```sql SELECT * FROM t WHERE v = COALESCE(NULLIF(CAST('' AS CHAR), ''), 'a'); ``` 3. The BE aborts with the stack above. (The exact folding shape may matter; the key point is that the constant side is a constant expression rather than a plain literal, so BE's folded column is a bare `ColumnStr` instead of a `ColumnConst`.) Real-world trigger in our case (dashboard-generated SQL): ```sql SELECT MAX(_date) AS period, COUNT(*) AS value FROM player_sessions WHERE _date >= '2026-08-31' AND _date < '2026-09-30' AND session_state = 'session_end' AND player_nr = COALESCE(NULLIF(CAST('' AS CHAR), ''), '224768403') ### Anything Else? Root cause and suggested fix: - `_should_push_down_binary_predicate` assumes `expr->is_constant()` implies the impl column is a `ColumnConst` wrapper and uses an unchecked `assert_cast`. That assumption does not hold for const-folded expressions. - The sibling function `_should_push_down_function_filter` already handles this safely using `get_const_col()` + `check_and_get_column<ColumnConst>()` and falls back to `PushDownType::UNACCEPTABLE`. Applying the same pattern in `_should_push_down_binary_predicate` (skip pushdown instead of casting) should fix the crash. Workaround for affected users: rewrite the predicate so the constant side is a plain literal (e.g. `player_nr = '224768403'`). ### Are you willing to submit PR? - [ ] Yes I am willing to submit a PR! ### Code of Conduct - [x] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
