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 facf9cc50d4 [fix](virtual slot) Materialize constant virtual columns 
before caching (#67112)
facf9cc50d4 is described below

commit facf9cc50d47174571f1525feb67fdce38fb464b
Author: foxtail463 <[email protected]>
AuthorDate: Wed Aug 26 10:41:07 2026 +0800

    [fix](virtual slot) Materialize constant virtual columns before caching 
(#67112)
    
    Problem Summary:
    Virtual-column expressions may return ColumnConst, including all-NULL
    nullable constants. SegmentIterator previously stored these results
    directly in the
    output block, while downstream consumers expect row-aligned concrete
    columns. This could cause type assertion failures during CSE
    virtual-column queries with
    short-circuit evaluation.
    
    Solution:
    Materialize constant expression results with
    convert_to_full_column_if_const() before caching them in the
    virtual-column slot.
    
    Co-authored-by: yangtao555 <[email protected]>
---
 be/src/storage/segment/segment_iterator.cpp        |  3 +
 .../segment_iterator_virtual_column_test.cpp       | 82 ++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/be/src/storage/segment/segment_iterator.cpp 
b/be/src/storage/segment/segment_iterator.cpp
index c4787cb0968..8198e00b674 100644
--- a/be/src/storage/segment/segment_iterator.cpp
+++ b/be/src/storage/segment/segment_iterator.cpp
@@ -3406,6 +3406,9 @@ Status 
SegmentIterator::_materialization_of_virtual_column(Block* block) {
             ColumnPtr result_column;
             RETURN_IF_ERROR(column_expr->execute(block, result_column));
 
+            // The materialized value is cached in the block and later 
consumed as the slot's
+            // concrete column type, so do not let a ColumnConst cross this 
boundary.
+            result_column = result_column->convert_to_full_column_if_const();
             block->replace_by_position(idx_in_block, std::move(result_column));
             if (block->get_by_position(idx_in_block).column->size() == 0) {
                 LOG_WARNING("Result of expr column {} is empty. cid {}, 
idx_in_block {}",
diff --git a/be/test/storage/segment/segment_iterator_virtual_column_test.cpp 
b/be/test/storage/segment/segment_iterator_virtual_column_test.cpp
new file mode 100644
index 00000000000..489b0125d52
--- /dev/null
+++ b/be/test/storage/segment/segment_iterator_virtual_column_test.cpp
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <gtest/gtest.h>
+
+#include <memory>
+
+#include "core/column/column_nothing.h"
+#include "core/data_type/data_type_nullable.h"
+#include "core/data_type/data_type_number.h"
+#include "exprs/vexpr_context.h"
+#include "exprs/vliteral.h"
+#include "storage/olap_common.h"
+#include "storage/schema.h"
+#include "storage/segment/segment.h"
+#include "storage/segment/segment_iterator.h"
+#include "storage/tablet/tablet_schema.h"
+
+namespace doris::segment_v2 {
+namespace {
+
+TabletSchemaSPtr make_tablet_schema() {
+    TabletSchemaPB schema_pb;
+    schema_pb.set_keys_type(KeysType::DUP_KEYS);
+    auto* key_column = schema_pb.add_column();
+    key_column->set_unique_id(0);
+    key_column->set_name("id");
+    key_column->set_type("INT");
+    key_column->set_is_key(true);
+    key_column->set_is_nullable(false);
+    auto* virtual_column = schema_pb.add_column();
+    virtual_column->set_unique_id(1);
+    virtual_column->set_name("virtual_column");
+    virtual_column->set_type("DOUBLE");
+    virtual_column->set_is_key(false);
+    virtual_column->set_is_nullable(true);
+    auto tablet_schema = std::make_shared<TabletSchema>();
+    tablet_schema->init_from_pb(schema_pb);
+    return tablet_schema;
+}
+
+} // namespace
+
+TEST(SegmentIteratorVirtualColumnTest, 
MaterializationExpandsConstNullableResult) {
+    auto tablet_schema = make_tablet_schema();
+    auto segment = std::make_shared<Segment>(0, RowsetId(), tablet_schema, 
InvertedIndexFileInfo());
+    auto schema = std::make_shared<Schema>(tablet_schema->columns(), 
std::vector<ColumnId> {0, 1});
+    SegmentIterator iterator(segment, schema);
+
+    auto type = 
std::make_shared<DataTypeNullable>(std::make_shared<DataTypeFloat64>());
+    auto expr = std::make_shared<VLiteral>(type, Field());
+    iterator._virtual_column_exprs[1] = 
std::make_shared<VExprContext>(std::move(expr));
+    iterator._vir_cid_to_idx_in_block[1] = 1;
+
+    Block block;
+    block.insert({ColumnInt32::create(4, 1), 
std::make_shared<DataTypeInt32>(), "id"});
+    block.insert({ColumnNothing::create(0), type, "virtual_column"});
+
+    ASSERT_TRUE(iterator._materialization_of_virtual_column(&block).ok());
+    const auto& result = block.get_by_position(1).column;
+    EXPECT_FALSE(is_column_const(*result));
+    const auto* nullable = check_and_get_column<ColumnNullable>(result.get());
+    ASSERT_NE(nullable, nullptr);
+    EXPECT_EQ(nullable->size(), 4);
+    EXPECT_TRUE(nullable->only_null());
+}
+
+} // namespace doris::segment_v2


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

Reply via email to