This is an automated email from the ASF dual-hosted git repository.

Mryange pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new ad269d4dd27 [opt](column) avoid redundant COW column clones (#64735)
ad269d4dd27 is described below

commit ad269d4dd279d0d3658d5d434022dd562f02bf37
Author: Mryange <[email protected]>
AuthorDate: Thu Jun 25 14:46:53 2026 +0800

    [opt](column) avoid redundant COW column clones (#64735)
    
    ### What problem does this PR solve?
    
    Several expression and writer paths cloned columns even though they only
    needed a shared COW view before passing data to existing COW-aware APIs.
    
    Root cause:
    array_map copied array offsets for result wrapping, Hive/Iceberg
    partition filtering cloned every column before calling
    Block::filter_block_internal, the IF null-condition path cloned the
    pass-through else column, and get_output_block_after_execute_exprs kept
    a legacy do_projection clone path for an old Block::clear_column_data
    ownership issue.
    
    This change reuses shared ColumnPtr values in those non-mutating paths,
    removes the obsolete do_projection branch, and lets the COW-aware block
    helpers detach only when mutation is actually needed.
    
    
    ### Release note
    
    None
---
 be/src/core/block/block.cpp                        | 10 ++----
 be/src/core/column/column.cpp                      | 37 ++++++++++------------
 be/src/core/column/column.h                        |  7 ++--
 be/src/core/column/column_array.h                  |  7 +++-
 be/src/core/column/column_const.h                  |  6 +++-
 be/src/core/column/column_map.h                    |  8 ++++-
 be/src/core/column/column_nullable.h               |  7 +++-
 be/src/core/column/column_struct.cpp               |  8 ++++-
 be/src/core/column/column_struct.h                 |  3 +-
 be/src/core/column/column_variant.cpp              | 17 ++++++++--
 be/src/core/column/column_variant.h                |  3 +-
 .../operator/multi_cast_data_stream_source.cpp     |  2 +-
 .../sink/writer/iceberg/viceberg_table_writer.cpp  | 21 ++----------
 .../sink/writer/maxcompute/vmc_table_writer.cpp    |  2 +-
 be/src/exec/sink/writer/vhive_table_writer.cpp     | 22 ++-----------
 .../exprs/lambda_function/varray_map_function.cpp  | 18 +++++------
 be/src/exprs/vcondition_expr.cpp                   |  3 +-
 be/src/exprs/vexpr_context.cpp                     | 16 ++--------
 be/src/exprs/vexpr_context.h                       |  3 +-
 19 files changed, 93 insertions(+), 107 deletions(-)

diff --git a/be/src/core/block/block.cpp b/be/src/core/block/block.cpp
index d94f6b3a186..726e3b2c3a5 100644
--- a/be/src/core/block/block.cpp
+++ b/be/src/core/block/block.cpp
@@ -89,17 +89,13 @@ bool is_recursively_exclusive(const IColumn& column) {
     }
 
     bool exclusive = true;
-    IColumn::ColumnCallback callback = [&](IColumn::WrappedPtr& subcolumn) {
+    IColumn::ColumnCallback callback = [&](const IColumn& subcolumn) {
         if (!exclusive) {
             return;
         }
-        const ColumnPtr& subcolumn_ptr = const_cast<const 
IColumn::WrappedPtr&>(subcolumn);
-        DCHECK(subcolumn_ptr);
-        exclusive = is_recursively_exclusive(*subcolumn_ptr);
+        exclusive = is_recursively_exclusive(subcolumn);
     };
-    // `for_each_subcolumn` only exposes a mutable callback type. This callback
-    // only reads the wrapped pointers and never calls the non-const accessors.
-    const_cast<IColumn&>(column).for_each_subcolumn(callback);
+    column.for_each_subcolumn(callback);
     return exclusive;
 }
 
diff --git a/be/src/core/column/column.cpp b/be/src/core/column/column.cpp
index 3fea47f9388..68048b10053 100644
--- a/be/src/core/column/column.cpp
+++ b/be/src/core/column/column.cpp
@@ -32,12 +32,11 @@ std::string IColumn::dump_structure() const {
     std::stringstream res;
     res << get_name() << "(size = " << size();
 
-    ColumnCallback callback = [&](ColumnPtr& subcolumn) {
-        res << ", " << subcolumn->dump_structure();
+    ColumnCallback callback = [&](const IColumn& subcolumn) {
+        res << ", " << subcolumn.dump_structure();
     };
 
-    // simply read using for_each_subcolumn without modification; const_cast 
can be used.
-    const_cast<IColumn*>(this)->for_each_subcolumn(callback);
+    for_each_subcolumn(callback);
 
     res << ")";
     return res.str();
@@ -45,11 +44,10 @@ std::string IColumn::dump_structure() const {
 
 int IColumn::count_const_column() const {
     int count = is_column_const(*this) ? 1 : 0;
-    ColumnCallback callback = [&](ColumnPtr& subcolumn) {
-        count += subcolumn->count_const_column();
+    ColumnCallback callback = [&](const IColumn& subcolumn) {
+        count += subcolumn.count_const_column();
     };
-    // simply read using for_each_subcolumn without modification; const_cast 
can be used.
-    const_cast<IColumn*>(this)->for_each_subcolumn(callback);
+    for_each_subcolumn(callback);
     return count;
 }
 
@@ -95,13 +93,12 @@ bool IColumn::column_boolean_check() const {
     };
 
     bool is_valid = check_boolean_is_zero_or_one(*this);
-    ColumnCallback callback = [&](ColumnPtr& subcolumn) {
-        if (!subcolumn->column_boolean_check()) {
+    ColumnCallback callback = [&](const IColumn& subcolumn) {
+        if (!subcolumn.column_boolean_check()) {
             is_valid = false;
         }
     };
-    // simply read using for_each_subcolumn without modification; const_cast 
can be used.
-    const_cast<IColumn*>(this)->for_each_subcolumn(callback);
+    for_each_subcolumn(callback);
     return is_valid;
 }
 
@@ -122,13 +119,12 @@ bool IColumn::null_map_check() const {
     };
 
     bool is_valid = check_null_map_is_zero_or_one(*this);
-    ColumnCallback callback = [&](ColumnPtr& subcolumn) {
-        if (!subcolumn->null_map_check()) {
+    ColumnCallback callback = [&](const IColumn& subcolumn) {
+        if (!subcolumn.null_map_check()) {
             is_valid = false;
         }
     };
-    // simply read using for_each_subcolumn without modification; const_cast 
can be used.
-    const_cast<IColumn*>(this)->for_each_subcolumn(callback);
+    for_each_subcolumn(callback);
     return is_valid;
 }
 
@@ -231,15 +227,14 @@ bool is_column_const(const IColumn& column) {
 }
 
 void IColumn::check_const_only_in_top_level() const {
-    ColumnCallback throw_if_const = [&](WrappedPtr& column) {
-        const ColumnPtr& col = const_cast<const WrappedPtr&>(column);
-        if (is_column_const(*col)) {
+    ColumnCallback throw_if_const = [&](const IColumn& column) {
+        if (is_column_const(column)) {
             throw doris::Exception(ErrorCode::INTERNAL_ERROR,
                                    "const column is not allowed to be nested, 
but got {}",
-                                   col->get_name());
+                                   column.get_name());
         }
     };
-    const_cast<IColumn*>(this)->for_each_subcolumn(throw_if_const);
+    for_each_subcolumn(throw_if_const);
 }
 
 } // namespace doris
diff --git a/be/src/core/column/column.h b/be/src/core/column/column.h
index ecd0245d718..6e5b69d9077 100644
--- a/be/src/core/column/column.h
+++ b/be/src/core/column/column.h
@@ -563,9 +563,10 @@ public:
 
     /// If the column contains subcolumns (such as Array, Nullable, etc), do 
callback on them.
     /// Shallow: doesn't do recursive calls; don't do call for itself.
-    using ColumnCallback = std::function<void(WrappedPtr&)>;
-    using ImutableColumnCallback = std::function<void(const IColumn&)>;
-    virtual void for_each_subcolumn(ColumnCallback) {}
+    using MutableColumnCallback = std::function<void(WrappedPtr&)>;
+    using ColumnCallback = std::function<void(const IColumn&)>;
+    virtual void for_each_subcolumn(MutableColumnCallback) {}
+    virtual void for_each_subcolumn(ColumnCallback) const {}
 
     /// Columns have equal structure.
     /// If true - you can use "compare_at", "insert_from", etc. methods.
diff --git a/be/src/core/column/column_array.h 
b/be/src/core/column/column_array.h
index 9c4e37ed794..0f2ef78a26c 100644
--- a/be/src/core/column/column_array.h
+++ b/be/src/core/column/column_array.h
@@ -216,7 +216,7 @@ public:
         return get_offsets()[i] - get_offsets()[i - 1];
     }
 
-    void for_each_subcolumn(ColumnCallback callback) override {
+    void for_each_subcolumn(MutableColumnCallback callback) override {
         IColumn::WrappedPtr 
offsets_column(std::move(static_cast<ColumnOffsets::Ptr&>(offsets)));
         Defer defer([&] {
             static_cast<ColumnOffsets::Ptr&>(offsets) =
@@ -226,6 +226,11 @@ public:
         callback(data);
     }
 
+    void for_each_subcolumn(ColumnCallback callback) const override {
+        callback(*static_cast<const ColumnOffsets::Ptr&>(offsets));
+        callback(*static_cast<const IColumn::Ptr&>(data));
+    }
+
     ColumnPtr convert_column_if_overflow() override {
         data = data->convert_column_if_overflow();
         return IColumn::convert_column_if_overflow();
diff --git a/be/src/core/column/column_const.h 
b/be/src/core/column/column_const.h
index 238d0f971b5..fa647aca466 100644
--- a/be/src/core/column/column_const.h
+++ b/be/src/core/column/column_const.h
@@ -261,7 +261,11 @@ public:
         }
     }
 
-    void for_each_subcolumn(ColumnCallback callback) override { 
callback(data); }
+    void for_each_subcolumn(MutableColumnCallback callback) override { 
callback(data); }
+
+    void for_each_subcolumn(ColumnCallback callback) const override {
+        callback(*static_cast<const IColumn::Ptr&>(data));
+    }
 
     bool structure_equals(const IColumn& rhs) const override {
         if (const auto* rhs_concrete = 
check_and_get_column<ColumnConst>(&rhs)) {
diff --git a/be/src/core/column/column_map.h b/be/src/core/column/column_map.h
index f5bb29d8be5..d8f40a8fa98 100644
--- a/be/src/core/column/column_map.h
+++ b/be/src/core/column/column_map.h
@@ -74,7 +74,7 @@ public:
 
     std::string get_name() const override;
 
-    void for_each_subcolumn(ColumnCallback callback) override {
+    void for_each_subcolumn(MutableColumnCallback callback) override {
         IColumn::WrappedPtr 
offsets(std::move(static_cast<COffsets::Ptr&>(offsets_column)));
         Defer defer([&] {
             static_cast<COffsets::Ptr&>(offsets_column) =
@@ -85,6 +85,12 @@ public:
         callback(offsets);
     }
 
+    void for_each_subcolumn(ColumnCallback callback) const override {
+        callback(*static_cast<const IColumn::Ptr&>(keys_column));
+        callback(*static_cast<const IColumn::Ptr&>(values_column));
+        callback(*static_cast<const COffsets::Ptr&>(offsets_column));
+    }
+
     void sanity_check() const override {
         keys_column->sanity_check();
         values_column->sanity_check();
diff --git a/be/src/core/column/column_nullable.h 
b/be/src/core/column/column_nullable.h
index 563d5e7011d..2161260bf9f 100644
--- a/be/src/core/column/column_nullable.h
+++ b/be/src/core/column/column_nullable.h
@@ -250,7 +250,7 @@ public:
         return get_ptr();
     }
 
-    void for_each_subcolumn(ColumnCallback callback) override {
+    void for_each_subcolumn(MutableColumnCallback callback) override {
         callback(_nested_column);
 
         IColumn::WrappedPtr 
null_map(std::move(static_cast<ColumnUInt8::Ptr&>(_null_map)));
@@ -260,6 +260,11 @@ public:
         callback(null_map);
     }
 
+    void for_each_subcolumn(ColumnCallback callback) const override {
+        callback(*static_cast<const IColumn::Ptr&>(_nested_column));
+        callback(*static_cast<const ColumnUInt8::Ptr&>(_null_map));
+    }
+
     bool structure_equals(const IColumn& rhs) const override {
         if (const auto* rhs_nullable = 
check_and_get_column<ColumnNullable>(&rhs)) {
             return 
_nested_column->structure_equals(*rhs_nullable->_nested_column);
diff --git a/be/src/core/column/column_struct.cpp 
b/be/src/core/column/column_struct.cpp
index e2a90432c56..9b0c5d2d27a 100644
--- a/be/src/core/column/column_struct.cpp
+++ b/be/src/core/column/column_struct.cpp
@@ -379,12 +379,18 @@ bool ColumnStruct::has_enough_capacity(const IColumn& 
src) const {
     return true;
 }
 
-void ColumnStruct::for_each_subcolumn(ColumnCallback callback) {
+void ColumnStruct::for_each_subcolumn(MutableColumnCallback callback) {
     for (auto& column : columns) {
         callback(column);
     }
 }
 
+void ColumnStruct::for_each_subcolumn(ColumnCallback callback) const {
+    for (const auto& column : columns) {
+        callback(*static_cast<const IColumn::Ptr&>(column));
+    }
+}
+
 bool ColumnStruct::structure_equals(const IColumn& rhs) const {
     if (const auto* rhs_tuple = check_and_get_column<ColumnStruct>(&rhs)) {
         const size_t tuple_size = columns.size();
diff --git a/be/src/core/column/column_struct.h 
b/be/src/core/column/column_struct.h
index e1f81950ddc..19b5259ee50 100644
--- a/be/src/core/column/column_struct.h
+++ b/be/src/core/column/column_struct.h
@@ -155,7 +155,8 @@ public:
     size_t byte_size() const override;
     size_t allocated_bytes() const override;
     bool has_enough_capacity(const IColumn& src) const override;
-    void for_each_subcolumn(ColumnCallback callback) override;
+    void for_each_subcolumn(MutableColumnCallback callback) override;
+    void for_each_subcolumn(ColumnCallback callback) const override;
     bool structure_equals(const IColumn& rhs) const override;
 
     size_t tuple_size() const { return columns.size(); }
diff --git a/be/src/core/column/column_variant.cpp 
b/be/src/core/column/column_variant.cpp
index 723d52d46b9..d4f1cb1e4bd 100644
--- a/be/src/core/column/column_variant.cpp
+++ b/be/src/core/column/column_variant.cpp
@@ -826,7 +826,7 @@ size_t ColumnVariant::allocated_bytes() const {
     return res;
 }
 
-void ColumnVariant::for_each_subcolumn(ColumnCallback callback) {
+void ColumnVariant::for_each_subcolumn(MutableColumnCallback callback) {
     for (auto& entry : subcolumns) {
         for (auto& part : entry->data.data) {
             callback(part);
@@ -839,6 +839,16 @@ void ColumnVariant::for_each_subcolumn(ColumnCallback 
callback) {
     ENABLE_CHECK_CONSISTENCY(this);
 }
 
+void ColumnVariant::for_each_subcolumn(ColumnCallback callback) const {
+    for (const auto& entry : subcolumns) {
+        for (const auto& part : entry->data.data) {
+            callback(*static_cast<const IColumn::Ptr&>(part));
+        }
+    }
+    callback(*static_cast<const IColumn::Ptr&>(serialized_sparse_column));
+    callback(*static_cast<const IColumn::Ptr&>(serialized_doc_value_column));
+}
+
 void ColumnVariant::insert_from(const IColumn& src, size_t n) {
     const auto* src_v = assert_cast<const ColumnVariant*>(&src);
     ENABLE_CHECK_CONSISTENCY(src_v);
@@ -2375,7 +2385,7 @@ size_t ColumnVariant::filter(const Filter& filter) {
         for (auto& subcolumn : subcolumns) {
             subcolumn->data.num_rows = count;
         }
-        for_each_subcolumn([&](auto& part) {
+        MutableColumnCallback callback = [&](IColumn::WrappedPtr& part) {
             if (part->size() != count) {
                 if (part->is_exclusive()) {
                     const auto result_size = part->filter(filter);
@@ -2390,7 +2400,8 @@ size_t ColumnVariant::filter(const Filter& filter) {
                     part = part->filter(filter, count);
                 }
             }
-        });
+        };
+        for_each_subcolumn(callback);
     }
     num_rows = count;
     ENABLE_CHECK_CONSISTENCY(this);
diff --git a/be/src/core/column/column_variant.h 
b/be/src/core/column/column_variant.h
index 1d5c4eed137..cccf4d4031d 100644
--- a/be/src/core/column/column_variant.h
+++ b/be/src/core/column/column_variant.h
@@ -469,7 +469,8 @@ public:
 
     bool has_enough_capacity(const IColumn& src) const override { return 
false; }
 
-    void for_each_subcolumn(ColumnCallback callback) override;
+    void for_each_subcolumn(MutableColumnCallback callback) override;
+    void for_each_subcolumn(ColumnCallback callback) const override;
 
     // Do nothing, call try_insert instead
     void insert(const Field& field) override { try_insert(field); }
diff --git a/be/src/exec/operator/multi_cast_data_stream_source.cpp 
b/be/src/exec/operator/multi_cast_data_stream_source.cpp
index 2b9e663ce07..04aa6a18dcf 100644
--- a/be/src/exec/operator/multi_cast_data_stream_source.cpp
+++ b/be/src/exec/operator/multi_cast_data_stream_source.cpp
@@ -110,7 +110,7 @@ Status 
MultiCastDataStreamerSourceOperatorX::get_block_impl(RuntimeState* state,
     if (!local_state._output_expr_contexts.empty() && output_block->rows() > 
0) {
         SCOPED_TIMER(local_state._materialize_data_timer);
         RETURN_IF_ERROR(VExprContext::get_output_block_after_execute_exprs(
-                local_state._output_expr_contexts, *output_block, block, 
true));
+                local_state._output_expr_contexts, *output_block, block));
         materialize_block_inplace(*block);
     }
     return Status::OK();
diff --git a/be/src/exec/sink/writer/iceberg/viceberg_table_writer.cpp 
b/be/src/exec/sink/writer/iceberg/viceberg_table_writer.cpp
index 0a3b0843115..9e0f6821380 100644
--- a/be/src/exec/sink/writer/iceberg/viceberg_table_writer.cpp
+++ b/be/src/exec/sink/writer/iceberg/viceberg_table_writer.cpp
@@ -206,7 +206,7 @@ Status VIcebergTableWriter::write(RuntimeState* state, 
Block& block) {
     }
     Block output_block;
     
RETURN_IF_ERROR(VExprContext::get_output_block_after_execute_exprs(_vec_output_expr_ctxs,
 block,
-                                                                       
&output_block, false));
+                                                                       
&output_block));
     materialize_block_inplace(output_block);
     return _write_prepared_block(output_block);
 }
@@ -436,23 +436,8 @@ Status VIcebergTableWriter::_write_prepared_block(Block& 
output_block) {
 
 Status VIcebergTableWriter::_filter_block(doris::Block& block, const 
IColumn::Filter* filter,
                                           doris::Block* output_block) {
-    const ColumnsWithTypeAndName& columns_with_type_and_name =
-            block.get_columns_with_type_and_name();
-    ColumnsWithTypeAndName result_columns;
-    for (const auto& col : columns_with_type_and_name) {
-        
result_columns.emplace_back(col.column->clone_resized(col.column->size()), 
col.type,
-                                    col.name);
-    }
-    *output_block = {std::move(result_columns)};
-
-    std::vector<uint32_t> columns_to_filter;
-    int column_to_keep = output_block->columns();
-    columns_to_filter.resize(column_to_keep);
-    for (uint32_t i = 0; i < column_to_keep; ++i) {
-        columns_to_filter[i] = i;
-    }
-
-    Block::filter_block_internal(output_block, columns_to_filter, *filter);
+    *output_block = block;
+    Block::filter_block_internal(output_block, *filter);
     return Status::OK();
 }
 
diff --git a/be/src/exec/sink/writer/maxcompute/vmc_table_writer.cpp 
b/be/src/exec/sink/writer/maxcompute/vmc_table_writer.cpp
index a7818ea01d2..a35eb325fd4 100644
--- a/be/src/exec/sink/writer/maxcompute/vmc_table_writer.cpp
+++ b/be/src/exec/sink/writer/maxcompute/vmc_table_writer.cpp
@@ -145,7 +145,7 @@ Status VMCTableWriter::write(RuntimeState* state, Block& 
block) {
 
     Block output_block;
     
RETURN_IF_ERROR(VExprContext::get_output_block_after_execute_exprs(_vec_output_expr_ctxs,
 block,
-                                                                       
&output_block, false));
+                                                                       
&output_block));
     materialize_block_inplace(output_block);
 
     _row_count += output_block.rows();
diff --git a/be/src/exec/sink/writer/vhive_table_writer.cpp 
b/be/src/exec/sink/writer/vhive_table_writer.cpp
index 04a0c04c1dd..ee8e2a88bbb 100644
--- a/be/src/exec/sink/writer/vhive_table_writer.cpp
+++ b/be/src/exec/sink/writer/vhive_table_writer.cpp
@@ -92,7 +92,7 @@ Status VHiveTableWriter::write(RuntimeState* state, Block& 
block) {
     }
     Block output_block;
     
RETURN_IF_ERROR(VExprContext::get_output_block_after_execute_exprs(_vec_output_expr_ctxs,
 block,
-                                                                       
&output_block, false));
+                                                                       
&output_block));
     materialize_block_inplace(output_block);
 
     std::unordered_map<std::shared_ptr<VHivePartitionWriter>, IColumn::Filter> 
writer_positions;
@@ -220,24 +220,8 @@ Status VHiveTableWriter::write(RuntimeState* state, Block& 
block) {
 
 Status VHiveTableWriter::_filter_block(doris::Block& block, const 
IColumn::Filter* filter,
                                        doris::Block* output_block) {
-    const ColumnsWithTypeAndName& columns_with_type_and_name =
-            block.get_columns_with_type_and_name();
-    ColumnsWithTypeAndName result_columns;
-    for (int i = 0; i < columns_with_type_and_name.size(); ++i) {
-        const auto& col = columns_with_type_and_name[i];
-        
result_columns.emplace_back(col.column->clone_resized(col.column->size()), 
col.type,
-                                    col.name);
-    }
-    *output_block = {std::move(result_columns)};
-
-    std::vector<uint32_t> columns_to_filter;
-    int column_to_keep = output_block->columns();
-    columns_to_filter.resize(column_to_keep);
-    for (uint32_t i = 0; i < column_to_keep; ++i) {
-        columns_to_filter[i] = i;
-    }
-
-    Block::filter_block_internal(output_block, columns_to_filter, *filter);
+    *output_block = block;
+    Block::filter_block_internal(output_block, *filter);
     return Status::OK();
 }
 
diff --git a/be/src/exprs/lambda_function/varray_map_function.cpp 
b/be/src/exprs/lambda_function/varray_map_function.cpp
index db82c465000..9dc63c98b6a 100644
--- a/be/src/exprs/lambda_function/varray_map_function.cpp
+++ b/be/src/exprs/lambda_function/varray_map_function.cpp
@@ -121,7 +121,7 @@ public:
         auto outside_null_map = ColumnUInt8::create(
                 
arguments[0].column->convert_to_full_column_if_const()->size(), 0);
         // offset column
-        MutableColumnPtr array_column_offset;
+        ColumnPtr array_column_offset;
         size_t nested_array_column_rows = 0;
         ColumnPtr first_array_offsets = nullptr;
         //2. get the result column from executed expr, and the needed is 
nested column of array
@@ -158,8 +158,7 @@ public:
             if (i == 0) {
                 nested_array_column_rows = col_array.get_data_ptr()->size();
                 first_array_offsets = col_array.get_offsets_ptr();
-                const auto& off_data = col_array.get_offsets_column();
-                array_column_offset = 
off_data.clone_resized(col_array.get_offsets_column().size());
+                array_column_offset = first_array_offsets;
                 args_info.offsets_ptr = &col_array.get_offsets();
             } else {
                 // select array_map((x,y)->x+y,c_array1,[0,1,2,3]) from 
array_test2;
@@ -200,8 +199,8 @@ public:
             auto empty_nested_column = assert_cast<const 
DataTypeArray*>(nested_type.get())
                                                ->get_nested_type()
                                                ->create_column();
-            auto result_array_column = 
ColumnArray::create(std::move(empty_nested_column),
-                                                           
std::move(array_column_offset));
+            auto result_array_column =
+                    ColumnArray::create(std::move(empty_nested_column), 
array_column_offset);
 
             if (is_nullable) {
                 result_column = 
ColumnNullable::create(std::move(result_array_column),
@@ -300,7 +299,7 @@ public:
         if (result_type->is_nullable()) {
             if (res_type->is_nullable()) {
                 result_column = ColumnNullable::create(
-                        ColumnArray::create(std::move(result_col), 
std::move(array_column_offset)),
+                        ColumnArray::create(std::move(result_col), 
array_column_offset),
                         std::move(outside_null_map));
             } else {
                 // deal with eg: select array_map(x -> x is null, [null, 1, 
2]);
@@ -310,19 +309,18 @@ public:
                 result_column = ColumnNullable::create(
                         
ColumnArray::create(ColumnNullable::create(std::move(result_col),
                                                                    
std::move(nested_null_map)),
-                                            std::move(array_column_offset)),
+                                            array_column_offset),
                         std::move(outside_null_map));
             }
         } else {
             if (res_type->is_nullable()) {
-                result_column =
-                        ColumnArray::create(std::move(result_col), 
std::move(array_column_offset));
+                result_column = ColumnArray::create(std::move(result_col), 
array_column_offset);
             } else {
                 auto nested_null_map = ColumnUInt8::create(result_col->size(), 
0);
 
                 result_column = ColumnArray::create(
                         ColumnNullable::create(std::move(result_col), 
std::move(nested_null_map)),
-                        std::move(array_column_offset));
+                        array_column_offset);
             }
         }
         return Status::OK();
diff --git a/be/src/exprs/vcondition_expr.cpp b/be/src/exprs/vcondition_expr.cpp
index ab8f694c2c5..61d1b561165 100644
--- a/be/src/exprs/vcondition_expr.cpp
+++ b/be/src/exprs/vcondition_expr.cpp
@@ -369,7 +369,8 @@ Status VectorizedIfExpr::execute_for_null_condition(Block& 
block, const ColumnNu
     handled = false;
 
     if (cond_is_null) {
-        block.replace_by_position(result, 
arg_else.column->clone_resized(arg_cond.column->size()));
+        DCHECK_EQ(arg_else.column->size(), arg_cond.column->size());
+        block.replace_by_position(result, arg_else.column);
         handled = true;
         return Status::OK();
     }
diff --git a/be/src/exprs/vexpr_context.cpp b/be/src/exprs/vexpr_context.cpp
index b9abce25588..29cff202ab9 100644
--- a/be/src/exprs/vexpr_context.cpp
+++ b/be/src/exprs/vexpr_context.cpp
@@ -386,15 +386,8 @@ Status 
VExprContext::execute_conjuncts_and_filter_block(const VExprContextSPtrs&
     return Status::OK();
 }
 
-// do_projection: for some query(e.g. in 
MultiCastDataStreamerSourceOperator::get_block()),
-// output_vexpr_ctxs will output the same column more than once, and if the 
output_block
-// is mem-reused later, it will trigger DCHECK_EQ(d.column->use_count(), 1) 
failure when
-// doing Block::clear_column_data, set do_projection to true to copy the 
column data to
-// avoid this problem.
 Status VExprContext::get_output_block_after_execute_exprs(
-        const VExprContextSPtrs& output_vexpr_ctxs, const Block& input_block, 
Block* output_block,
-        bool do_projection) {
-    auto rows = input_block.rows();
+        const VExprContextSPtrs& output_vexpr_ctxs, const Block& input_block, 
Block* output_block) {
     ColumnsWithTypeAndName result_columns;
     _reset_memory_usage(output_vexpr_ctxs);
 
@@ -406,12 +399,7 @@ Status VExprContext::get_output_block_after_execute_exprs(
         const auto& name = vexpr_ctx->expr_name();
 
         vexpr_ctx->_memory_usage += result_column->allocated_bytes();
-        if (do_projection) {
-            result_columns.emplace_back(result_column->clone_resized(rows), 
type, name);
-
-        } else {
-            result_columns.emplace_back(result_column, type, name);
-        }
+        result_columns.emplace_back(result_column, type, name);
     }
     *output_block = {result_columns};
     return Status::OK();
diff --git a/be/src/exprs/vexpr_context.h b/be/src/exprs/vexpr_context.h
index 72398c71d05..3b9f08d6474 100644
--- a/be/src/exprs/vexpr_context.h
+++ b/be/src/exprs/vexpr_context.h
@@ -319,8 +319,7 @@ public:
                                                      int column_to_keep, 
IColumn::Filter& filter);
 
     [[nodiscard]] static Status get_output_block_after_execute_exprs(const 
VExprContextSPtrs&,
-                                                                     const 
Block&, Block*,
-                                                                     bool 
do_projection = false);
+                                                                     const 
Block&, Block*);
 
     int get_last_result_column_id() const {
         DCHECK(_last_result_column_id != -1);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to