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 09258e4f275 Revert "[opt](column) avoid redundant COW column clones" 
(#64920)
09258e4f275 is described below

commit 09258e4f2751911d52a59e00f0a61b428626bdea
Author: Mryange <[email protected]>
AuthorDate: Mon Jun 29 16:45:44 2026 +0800

    Revert "[opt](column) avoid redundant COW column clones" (#64920)
    
    Reverts apache/doris#64735
---
 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, 107 insertions(+), 93 deletions(-)

diff --git a/be/src/core/block/block.cpp b/be/src/core/block/block.cpp
index 726e3b2c3a5..d94f6b3a186 100644
--- a/be/src/core/block/block.cpp
+++ b/be/src/core/block/block.cpp
@@ -89,13 +89,17 @@ bool is_recursively_exclusive(const IColumn& column) {
     }
 
     bool exclusive = true;
-    IColumn::ColumnCallback callback = [&](const IColumn& subcolumn) {
+    IColumn::ColumnCallback callback = [&](IColumn::WrappedPtr& subcolumn) {
         if (!exclusive) {
             return;
         }
-        exclusive = is_recursively_exclusive(subcolumn);
+        const ColumnPtr& subcolumn_ptr = const_cast<const 
IColumn::WrappedPtr&>(subcolumn);
+        DCHECK(subcolumn_ptr);
+        exclusive = is_recursively_exclusive(*subcolumn_ptr);
     };
-    column.for_each_subcolumn(callback);
+    // `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);
     return exclusive;
 }
 
diff --git a/be/src/core/column/column.cpp b/be/src/core/column/column.cpp
index 68048b10053..3fea47f9388 100644
--- a/be/src/core/column/column.cpp
+++ b/be/src/core/column/column.cpp
@@ -32,11 +32,12 @@ std::string IColumn::dump_structure() const {
     std::stringstream res;
     res << get_name() << "(size = " << size();
 
-    ColumnCallback callback = [&](const IColumn& subcolumn) {
-        res << ", " << subcolumn.dump_structure();
+    ColumnCallback callback = [&](ColumnPtr& subcolumn) {
+        res << ", " << subcolumn->dump_structure();
     };
 
-    for_each_subcolumn(callback);
+    // simply read using for_each_subcolumn without modification; const_cast 
can be used.
+    const_cast<IColumn*>(this)->for_each_subcolumn(callback);
 
     res << ")";
     return res.str();
@@ -44,10 +45,11 @@ std::string IColumn::dump_structure() const {
 
 int IColumn::count_const_column() const {
     int count = is_column_const(*this) ? 1 : 0;
-    ColumnCallback callback = [&](const IColumn& subcolumn) {
-        count += subcolumn.count_const_column();
+    ColumnCallback callback = [&](ColumnPtr& subcolumn) {
+        count += subcolumn->count_const_column();
     };
-    for_each_subcolumn(callback);
+    // simply read using for_each_subcolumn without modification; const_cast 
can be used.
+    const_cast<IColumn*>(this)->for_each_subcolumn(callback);
     return count;
 }
 
@@ -93,12 +95,13 @@ bool IColumn::column_boolean_check() const {
     };
 
     bool is_valid = check_boolean_is_zero_or_one(*this);
-    ColumnCallback callback = [&](const IColumn& subcolumn) {
-        if (!subcolumn.column_boolean_check()) {
+    ColumnCallback callback = [&](ColumnPtr& subcolumn) {
+        if (!subcolumn->column_boolean_check()) {
             is_valid = false;
         }
     };
-    for_each_subcolumn(callback);
+    // simply read using for_each_subcolumn without modification; const_cast 
can be used.
+    const_cast<IColumn*>(this)->for_each_subcolumn(callback);
     return is_valid;
 }
 
@@ -119,12 +122,13 @@ bool IColumn::null_map_check() const {
     };
 
     bool is_valid = check_null_map_is_zero_or_one(*this);
-    ColumnCallback callback = [&](const IColumn& subcolumn) {
-        if (!subcolumn.null_map_check()) {
+    ColumnCallback callback = [&](ColumnPtr& subcolumn) {
+        if (!subcolumn->null_map_check()) {
             is_valid = false;
         }
     };
-    for_each_subcolumn(callback);
+    // simply read using for_each_subcolumn without modification; const_cast 
can be used.
+    const_cast<IColumn*>(this)->for_each_subcolumn(callback);
     return is_valid;
 }
 
@@ -227,14 +231,15 @@ bool is_column_const(const IColumn& column) {
 }
 
 void IColumn::check_const_only_in_top_level() const {
-    ColumnCallback throw_if_const = [&](const IColumn& column) {
-        if (is_column_const(column)) {
+    ColumnCallback throw_if_const = [&](WrappedPtr& column) {
+        const ColumnPtr& col = const_cast<const WrappedPtr&>(column);
+        if (is_column_const(*col)) {
             throw doris::Exception(ErrorCode::INTERNAL_ERROR,
                                    "const column is not allowed to be nested, 
but got {}",
-                                   column.get_name());
+                                   col->get_name());
         }
     };
-    for_each_subcolumn(throw_if_const);
+    const_cast<IColumn*>(this)->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 6e5b69d9077..ecd0245d718 100644
--- a/be/src/core/column/column.h
+++ b/be/src/core/column/column.h
@@ -563,10 +563,9 @@ 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 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 {}
+    using ColumnCallback = std::function<void(WrappedPtr&)>;
+    using ImutableColumnCallback = std::function<void(const IColumn&)>;
+    virtual void for_each_subcolumn(ColumnCallback) {}
 
     /// 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 0f2ef78a26c..9c4e37ed794 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(MutableColumnCallback callback) override {
+    void for_each_subcolumn(ColumnCallback callback) override {
         IColumn::WrappedPtr 
offsets_column(std::move(static_cast<ColumnOffsets::Ptr&>(offsets)));
         Defer defer([&] {
             static_cast<ColumnOffsets::Ptr&>(offsets) =
@@ -226,11 +226,6 @@ 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 fa647aca466..238d0f971b5 100644
--- a/be/src/core/column/column_const.h
+++ b/be/src/core/column/column_const.h
@@ -261,11 +261,7 @@ public:
         }
     }
 
-    void for_each_subcolumn(MutableColumnCallback callback) override { 
callback(data); }
-
-    void for_each_subcolumn(ColumnCallback callback) const override {
-        callback(*static_cast<const IColumn::Ptr&>(data));
-    }
+    void for_each_subcolumn(ColumnCallback callback) override { 
callback(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 d8f40a8fa98..f5bb29d8be5 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(MutableColumnCallback callback) override {
+    void for_each_subcolumn(ColumnCallback callback) override {
         IColumn::WrappedPtr 
offsets(std::move(static_cast<COffsets::Ptr&>(offsets_column)));
         Defer defer([&] {
             static_cast<COffsets::Ptr&>(offsets_column) =
@@ -85,12 +85,6 @@ 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 2161260bf9f..563d5e7011d 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(MutableColumnCallback callback) override {
+    void for_each_subcolumn(ColumnCallback callback) override {
         callback(_nested_column);
 
         IColumn::WrappedPtr 
null_map(std::move(static_cast<ColumnUInt8::Ptr&>(_null_map)));
@@ -260,11 +260,6 @@ 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 9b0c5d2d27a..e2a90432c56 100644
--- a/be/src/core/column/column_struct.cpp
+++ b/be/src/core/column/column_struct.cpp
@@ -379,18 +379,12 @@ bool ColumnStruct::has_enough_capacity(const IColumn& 
src) const {
     return true;
 }
 
-void ColumnStruct::for_each_subcolumn(MutableColumnCallback callback) {
+void ColumnStruct::for_each_subcolumn(ColumnCallback 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 19b5259ee50..e1f81950ddc 100644
--- a/be/src/core/column/column_struct.h
+++ b/be/src/core/column/column_struct.h
@@ -155,8 +155,7 @@ 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(MutableColumnCallback callback) override;
-    void for_each_subcolumn(ColumnCallback callback) const override;
+    void for_each_subcolumn(ColumnCallback callback) 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 d4f1cb1e4bd..723d52d46b9 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(MutableColumnCallback callback) {
+void ColumnVariant::for_each_subcolumn(ColumnCallback callback) {
     for (auto& entry : subcolumns) {
         for (auto& part : entry->data.data) {
             callback(part);
@@ -839,16 +839,6 @@ void 
ColumnVariant::for_each_subcolumn(MutableColumnCallback 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);
@@ -2385,7 +2375,7 @@ size_t ColumnVariant::filter(const Filter& filter) {
         for (auto& subcolumn : subcolumns) {
             subcolumn->data.num_rows = count;
         }
-        MutableColumnCallback callback = [&](IColumn::WrappedPtr& part) {
+        for_each_subcolumn([&](auto& part) {
             if (part->size() != count) {
                 if (part->is_exclusive()) {
                     const auto result_size = part->filter(filter);
@@ -2400,8 +2390,7 @@ 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 cccf4d4031d..1d5c4eed137 100644
--- a/be/src/core/column/column_variant.h
+++ b/be/src/core/column/column_variant.h
@@ -469,8 +469,7 @@ public:
 
     bool has_enough_capacity(const IColumn& src) const override { return 
false; }
 
-    void for_each_subcolumn(MutableColumnCallback callback) override;
-    void for_each_subcolumn(ColumnCallback callback) const override;
+    void for_each_subcolumn(ColumnCallback callback) 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 04aa6a18dcf..2b9e663ce07 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));
+                local_state._output_expr_contexts, *output_block, block, 
true));
         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 9e0f6821380..0a3b0843115 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));
+                                                                       
&output_block, false));
     materialize_block_inplace(output_block);
     return _write_prepared_block(output_block);
 }
@@ -436,8 +436,23 @@ Status VIcebergTableWriter::_write_prepared_block(Block& 
output_block) {
 
 Status VIcebergTableWriter::_filter_block(doris::Block& block, const 
IColumn::Filter* filter,
                                           doris::Block* output_block) {
-    *output_block = block;
-    Block::filter_block_internal(output_block, *filter);
+    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);
     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 a35eb325fd4..a7818ea01d2 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));
+                                                                       
&output_block, false));
     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 ee8e2a88bbb..04a0c04c1dd 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));
+                                                                       
&output_block, false));
     materialize_block_inplace(output_block);
 
     std::unordered_map<std::shared_ptr<VHivePartitionWriter>, IColumn::Filter> 
writer_positions;
@@ -220,8 +220,24 @@ Status VHiveTableWriter::write(RuntimeState* state, Block& 
block) {
 
 Status VHiveTableWriter::_filter_block(doris::Block& block, const 
IColumn::Filter* filter,
                                        doris::Block* output_block) {
-    *output_block = block;
-    Block::filter_block_internal(output_block, *filter);
+    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);
     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 9dc63c98b6a..db82c465000 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
-        ColumnPtr array_column_offset;
+        MutableColumnPtr 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,7 +158,8 @@ public:
             if (i == 0) {
                 nested_array_column_rows = col_array.get_data_ptr()->size();
                 first_array_offsets = col_array.get_offsets_ptr();
-                array_column_offset = first_array_offsets;
+                const auto& off_data = col_array.get_offsets_column();
+                array_column_offset = 
off_data.clone_resized(col_array.get_offsets_column().size());
                 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;
@@ -199,8 +200,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), 
array_column_offset);
+            auto result_array_column = 
ColumnArray::create(std::move(empty_nested_column),
+                                                           
std::move(array_column_offset));
 
             if (is_nullable) {
                 result_column = 
ColumnNullable::create(std::move(result_array_column),
@@ -299,7 +300,7 @@ public:
         if (result_type->is_nullable()) {
             if (res_type->is_nullable()) {
                 result_column = ColumnNullable::create(
-                        ColumnArray::create(std::move(result_col), 
array_column_offset),
+                        ColumnArray::create(std::move(result_col), 
std::move(array_column_offset)),
                         std::move(outside_null_map));
             } else {
                 // deal with eg: select array_map(x -> x is null, [null, 1, 
2]);
@@ -309,18 +310,19 @@ public:
                 result_column = ColumnNullable::create(
                         
ColumnArray::create(ColumnNullable::create(std::move(result_col),
                                                                    
std::move(nested_null_map)),
-                                            array_column_offset),
+                                            std::move(array_column_offset)),
                         std::move(outside_null_map));
             }
         } else {
             if (res_type->is_nullable()) {
-                result_column = ColumnArray::create(std::move(result_col), 
array_column_offset);
+                result_column =
+                        ColumnArray::create(std::move(result_col), 
std::move(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)),
-                        array_column_offset);
+                        std::move(array_column_offset));
             }
         }
         return Status::OK();
diff --git a/be/src/exprs/vcondition_expr.cpp b/be/src/exprs/vcondition_expr.cpp
index 61d1b561165..ab8f694c2c5 100644
--- a/be/src/exprs/vcondition_expr.cpp
+++ b/be/src/exprs/vcondition_expr.cpp
@@ -369,8 +369,7 @@ Status VectorizedIfExpr::execute_for_null_condition(Block& 
block, const ColumnNu
     handled = false;
 
     if (cond_is_null) {
-        DCHECK_EQ(arg_else.column->size(), arg_cond.column->size());
-        block.replace_by_position(result, arg_else.column);
+        block.replace_by_position(result, 
arg_else.column->clone_resized(arg_cond.column->size()));
         handled = true;
         return Status::OK();
     }
diff --git a/be/src/exprs/vexpr_context.cpp b/be/src/exprs/vexpr_context.cpp
index 29cff202ab9..b9abce25588 100644
--- a/be/src/exprs/vexpr_context.cpp
+++ b/be/src/exprs/vexpr_context.cpp
@@ -386,8 +386,15 @@ 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) {
+        const VExprContextSPtrs& output_vexpr_ctxs, const Block& input_block, 
Block* output_block,
+        bool do_projection) {
+    auto rows = input_block.rows();
     ColumnsWithTypeAndName result_columns;
     _reset_memory_usage(output_vexpr_ctxs);
 
@@ -399,7 +406,12 @@ Status VExprContext::get_output_block_after_execute_exprs(
         const auto& name = vexpr_ctx->expr_name();
 
         vexpr_ctx->_memory_usage += result_column->allocated_bytes();
-        result_columns.emplace_back(result_column, type, name);
+        if (do_projection) {
+            result_columns.emplace_back(result_column->clone_resized(rows), 
type, name);
+
+        } else {
+            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 3b9f08d6474..72398c71d05 100644
--- a/be/src/exprs/vexpr_context.h
+++ b/be/src/exprs/vexpr_context.h
@@ -319,7 +319,8 @@ public:
                                                      int column_to_keep, 
IColumn::Filter& filter);
 
     [[nodiscard]] static Status get_output_block_after_execute_exprs(const 
VExprContextSPtrs&,
-                                                                     const 
Block&, Block*);
+                                                                     const 
Block&, Block*,
+                                                                     bool 
do_projection = false);
 
     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