HappenLee commented on code in PR #62222:
URL: https://github.com/apache/doris/pull/62222#discussion_r3208703151
##########
be/src/exec/operator/olap_scan_operator.cpp:
##########
@@ -462,8 +520,64 @@ Status
OlapScanLocalState::_should_push_down_function_filter(VectorizedFnCall* f
return Status::OK();
}
-bool OlapScanLocalState::_should_push_down_common_expr() {
- return state()->enable_common_expr_pushdown() && _storage_no_merge();
+bool OlapScanLocalState::_should_push_down_common_expr(const VExprSPtr& expr) {
+ // This switch controls both pushed filter execution and LIMIT accounting
in SegmentIterator.
+ // Index-only expressions must also enter SegmentIterator even without
slot children.
+ if (!state()->enable_segment_filter_and_limit_pushdown() ||
+ !_check_expr_storage_filter(expr,
ExprStorageFilterCheckMode::HAS_SEGMENT_EVALUABLE_EXPR)) {
+ return false;
+ }
+
+ // Runtime filters may arrive after scanner initialization. If LIMIT is
also pushed into
+ // SegmentIterator, a late filter could make the segment stop before
enough post-filter rows are
+ // produced, so keep LIMIT+RF cases above storage.
+ if (_parent->limit() >= 0 && _helper.runtime_filter_nums() > 0) {
+ return false;
+ }
+
+ // DUP and UNIQUE-MOW/MOR-as-DUP do not need storage aggregation/merge, so
any slot-based common
+ // expression can be evaluated together with SegmentIterator lazy
materialization.
+ if (_storage_no_merge()) {
+ return true;
+ }
+
+ // AGG and UNIQUE-MOR may still merge value columns above SegmentIterator.
Push only key-column
+ // expressions so filtering does not observe pre-merge values.
+ return !_check_expr_storage_filter(expr,
ExprStorageFilterCheckMode::HAS_NON_KEY_SLOT);
+}
+
+bool OlapScanLocalState::_check_expr_storage_filter(const VExprSPtr& expr,
+ ExprStorageFilterCheckMode
mode) {
+ DORIS_CHECK(expr != nullptr);
+ if (expr->node_type() == TExprNodeType::SEARCH_EXPR) {
+ if (mode == ExprStorageFilterCheckMode::HAS_NON_KEY_SLOT) {
+ if (expr->children().empty()) {
+ return true;
+ }
+ return std::ranges::any_of(expr->children(), [this, mode](const
auto& child) {
+ return _check_expr_storage_filter(child, mode);
+ });
+ }
+ return mode == ExprStorageFilterCheckMode::HAS_SEGMENT_EVALUABLE_EXPR;
+ }
+ if (expr->node_type() == TExprNodeType::MATCH_PRED &&
+ mode == ExprStorageFilterCheckMode::HAS_SEGMENT_EVALUABLE_EXPR) {
+ return true;
+ }
+ if (expr->is_slot_ref()) {
+ const auto* slot_ref = assert_cast<const VSlotRef*>(expr.get());
+ return mode == ExprStorageFilterCheckMode::HAS_SEGMENT_EVALUABLE_EXPR
||
+ !_is_key_column(slot_ref->expr_name());
+ }
+ if (expr->is_virtual_slot_ref()) {
Review Comment:
no need check the logic, the virtual slot should not valid because the array
should not be key column
--
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]