This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.1 by this push:
new dd73768c734 branch-4.1: [fix](be) Materialize const columns before
block merge #65770 (#65920)
dd73768c734 is described below
commit dd73768c7345af67044070cd02c11ceac12011ab
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Jul 23 14:22:34 2026 +0800
branch-4.1: [fix](be) Materialize const columns before block merge #65770
(#65920)
Cherry-picked from #65770
Co-authored-by: Gabriel <[email protected]>
---
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 ffd3adc672f..70c07fb878c 100644
--- a/be/src/core/block/block.h
+++ b/be/src/core/block/block.h
@@ -449,6 +449,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.
@@ -588,6 +597,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());
@@ -621,6 +631,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 271be13f106..87e189b2d4a 100644
--- a/be/test/core/block/block_test.cpp
+++ b/be/test/core/block/block_test.cpp
@@ -1145,6 +1145,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]