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]

Reply via email to