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

Gabriel39 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 6322a095ba7 [fix](be) Materialize const columns before block merge 
(#65770)
6322a095ba7 is described below

commit 6322a095ba70c3e453215c4627390daa390aba48
Author: Gabriel <[email protected]>
AuthorDate: Mon Jul 20 16:15:48 2026 +0800

    [fix](be) Materialize const columns before block merge (#65770)
    
    ### What problem does this PR solve?
    
    Issue Number: None
    
    Related PR: None
    
    Problem Summary:
    
    `ScopedMutableBlock` can retain a `ColumnConst` destination, while block
    merge materializes the incoming column before appending it. Appending
    that full column to the const destination fails with an internal error.
    
    This change materializes a const destination once before appending,
    keeping the destination and source representations compatible for both
    regular and ignore-overflow merges.
    
    ### Release note
    
    Fix block merge failures when scanner padding produces constant nullable
    columns.
    
    ### Check List (For Author)
    
    - Test
        - [ ] Regression test
        - [x] Unit Test
        - [ ] Manual test (add detailed scripts or steps below)
        - [ ] No need to test or manual test. Explain why:
    - [ ] This is a refactor/code format and no logic has been changed.
            - [ ] Previous test can cover this change.
            - [ ] No code files have been changed.
            - [ ] Other reason
    
    - Behavior changed:
        - [x] No.
        - [ ] Yes.
    
    - Does this need documentation?
        - [x] No.
        - [ ] Yes.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 be/src/core/block/block.h         | 11 +++++++++++
 be/test/core/block/block_test.cpp | 31 +++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/be/src/core/block/block.h b/be/src/core/block/block.h
index 6031be051f9..b45d4bd7d18 100644
--- a/be/src/core/block/block.h
+++ b/be/src/core/block/block.h
@@ -448,6 +448,15 @@ private:
     DataTypes _data_types;
     std::vector<std::string> _names;
 
+    void materialize_const_column(size_t position) {
+        if (is_column_const(*_columns[position])) {
+            // ScopedMutableBlock can retain a const destination while merge 
materializes
+            // its source, so normalize the destination before appending full 
columns.
+            _columns[position] =
+                    
IColumn::mutate(_columns[position]->convert_to_full_column_if_const());
+        }
+    }
+
 public:
     // Build from a consumed Block. This has no restore contract: the source
     // Block is left without columns and must not be used as a live output 
block.
@@ -587,6 +596,7 @@ public:
                                        dump_names(), dump_types(), 
block.dump_names(),
                                        block.dump_types());
             }
+            materialize_const_column(i);
             _columns[i]->insert_range_from_ignore_overflow(
                     
*block.get_by_position(i).column->convert_to_full_column_if_const().get(), 0,
                     block.rows());
@@ -620,6 +630,7 @@ public:
                         block.dump_names(), block.dump_types());
             }
             for (int i = 0; i < _columns.size(); ++i) {
+                materialize_const_column(i);
                 if (!_data_types[i]->equals(*block.get_by_position(i).type)) {
                     DCHECK(_data_types[i]->is_nullable())
                             << " target type: " << _data_types[i]->get_name()
diff --git a/be/test/core/block/block_test.cpp 
b/be/test/core/block/block_test.cpp
index 3b29f819e09..2a3f07e01c5 100644
--- a/be/test/core/block/block_test.cpp
+++ b/be/test/core/block/block_test.cpp
@@ -1154,6 +1154,37 @@ TEST(BlockTest, merge_impl) {
     EXPECT_ANY_THROW(st = mutable_block.merge_impl(std::move(block2)));
 }
 
+TEST(BlockTest, MergeMaterializesConstNullableDestination) {
+    for (bool ignore_overflow : {false, true}) {
+        auto nullable_type = make_nullable(std::make_shared<DataTypeInt64>());
+
+        auto const_data = nullable_type->create_column();
+        const_data->insert_default();
+        Block destination;
+        destination.insert(
+                {ColumnConst::create(std::move(const_data), 2), nullable_type, 
"lineage"});
+
+        auto source_column = nullable_type->create_column();
+        source_column->insert_default();
+        Block source;
+        source.insert({std::move(source_column), nullable_type, "lineage"});
+
+        {
+            ScopedMutableBlock scoped_destination(&destination);
+            auto status = ignore_overflow
+                                  ? 
scoped_destination.mutable_block().merge_ignore_overflow(source)
+                                  : 
scoped_destination.mutable_block().merge(source);
+            ASSERT_TRUE(status.ok()) << status.to_string();
+        }
+
+        ASSERT_EQ(destination.rows(), 3);
+        EXPECT_FALSE(is_column_const(*destination.get_by_position(0).column));
+        for (size_t i = 0; i < destination.rows(); ++i) {
+            EXPECT_TRUE(destination.get_by_position(0).column->is_null_at(i));
+        }
+    }
+}
+
 TEST(BlockTest, ctor) {
     TDescriptorTableBuilder builder;
     TTupleDescriptorBuilder tuple_builder;


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

Reply via email to