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 0012df65a1f branch-4.1: [fix](exec) preserve NULL in pushed-down CHAR
MIN/MAX #65952 (#66583)
0012df65a1f is described below
commit 0012df65a1f8c3cfac20ecb8bb201fe3dc9d02e7
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sun Aug 9 07:25:07 2026 +0800
branch-4.1: [fix](exec) preserve NULL in pushed-down CHAR MIN/MAX #65952
(#66583)
Cherry-picked from #65952
Co-authored-by: Mryange <[email protected]>
---
be/src/storage/iterator/vgeneric_iterators.cpp | 4 +-
be/test/exec/scan/vgeneric_iterators_test.cpp | 79 ++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 2 deletions(-)
diff --git a/be/src/storage/iterator/vgeneric_iterators.cpp
b/be/src/storage/iterator/vgeneric_iterators.cpp
index 3fb2b360712..941c36ed5e3 100644
--- a/be/src/storage/iterator/vgeneric_iterators.cpp
+++ b/be/src/storage/iterator/vgeneric_iterators.cpp
@@ -82,8 +82,8 @@ Status VStatisticsIterator::next_batch(Block* block) {
_schema.column(cid)->type() ==
FieldType::OLAP_FIELD_TYPE_CHAR) {
auto col = columns[i]->clone_empty();
for (size_t j = 0; j < columns[i]->size(); ++j) {
- const auto& ref =
columns[i]->get_data_at(j).trim_tail_padding_zero();
-
col->insert(Field::create_field<TYPE_CHAR>(ref.to_string()));
+ const auto ref =
columns[i]->get_data_at(j).trim_tail_padding_zero();
+ col->insert_data(ref.data, ref.size);
}
columns[i].swap(col);
}
diff --git a/be/test/exec/scan/vgeneric_iterators_test.cpp
b/be/test/exec/scan/vgeneric_iterators_test.cpp
index fae7b164f8c..cd43d149db4 100644
--- a/be/test/exec/scan/vgeneric_iterators_test.cpp
+++ b/be/test/exec/scan/vgeneric_iterators_test.cpp
@@ -23,15 +23,23 @@
#include <memory>
#include <vector>
+#include "core/assert_cast.h"
#include "core/block/column_with_type_and_name.h"
#include "core/column/column.h"
+#include "core/column/column_nullable.h"
#include "core/data_type/data_type.h"
#include "core/field.h"
#include "gtest/gtest_pred_impl.h"
+#include "io/fs/file_writer.h"
+#include "io/fs/local_file_system.h"
#include "storage/olap_common.h"
+#include "storage/row_cursor.h"
#include "storage/schema.h"
#include "storage/segment/column_reader.h"
+#include "storage/segment/segment.h"
+#include "storage/segment/test_segment_writer.h"
#include "storage/tablet/tablet_schema.h"
+#include "storage/tablet/tablet_schema_helper.h"
namespace doris {
using namespace ErrorCode;
@@ -107,6 +115,77 @@ TEST(VGenericIteratorsTest, AutoIncrement) {
}
}
+TEST(VGenericIteratorsTest, StatisticsIteratorPreservesNullForNullableChar) {
+ constexpr auto test_dir = "./ut_dir/vgeneric_iterators_test";
+ constexpr auto segment_path =
"./ut_dir/vgeneric_iterators_test/nullable_char_segment.dat";
+ constexpr auto row_count = 3;
+
+ auto fs = io::global_local_filesystem();
+ ASSERT_TRUE(fs->delete_directory(test_dir).ok());
+ ASSERT_TRUE(fs->create_directory(test_dir).ok());
+
+ auto tablet_schema = std::make_shared<TabletSchema>();
+ tablet_schema->append_column(*create_int_key(0, false));
+ auto nullable_char = std::make_shared<TabletColumn>();
+ nullable_char->set_unique_id(1);
+ nullable_char->set_name("1");
+ nullable_char->set_type(FieldType::OLAP_FIELD_TYPE_CHAR);
+ nullable_char->set_is_nullable(true);
+ nullable_char->set_length(8);
+ nullable_char->set_index_length(8);
+
nullable_char->set_aggregation_method(FieldAggregationMethod::OLAP_FIELD_AGGREGATION_NONE);
+ tablet_schema->append_column(*nullable_char);
+ tablet_schema->set_storage_page_size(4096);
+
+ io::FileWriterPtr file_writer;
+ ASSERT_TRUE(fs->create_file(segment_path, &file_writer).ok());
+ SegmentWriterOptions writer_options;
+ writer_options.num_rows_per_block = 1024;
+ TestSegmentWriter writer(file_writer.get(), 0, tablet_schema, nullptr,
nullptr, writer_options,
+ nullptr);
+ ASSERT_TRUE(writer.init().ok());
+
+ RowCursor row;
+ std::vector<Field> fields(tablet_schema->num_columns(),
Field(PrimitiveType::TYPE_NULL));
+ ASSERT_TRUE(row.init_scan_key(tablet_schema, std::move(fields)).ok());
+ for (int i = 0; i < row_count; ++i) {
+ row.mutable_field(0) = Field::create_field<TYPE_INT>(i);
+ ASSERT_TRUE(writer.append_row(row).ok());
+ }
+ uint64_t file_size = 0;
+ uint64_t index_size = 0;
+ ASSERT_TRUE(writer.finalize(&file_size, &index_size).ok());
+ ASSERT_TRUE(file_writer->close().ok());
+
+ std::shared_ptr<segment_v2::Segment> segment;
+ ASSERT_TRUE(segment_v2::Segment::open(fs, segment_path, 100, 0, RowsetId
{.version = 1},
+ tablet_schema, io::FileReaderOptions
{}, &segment)
+ .ok());
+
+ std::vector<ColumnId> column_ids {0, 1};
+ Schema schema(tablet_schema->columns(), column_ids);
+ VStatisticsIterator iterator(segment, schema);
+ StorageReadOptions read_options;
+ OlapReaderStatistics stats;
+ read_options.push_down_agg_type_opt = TPushAggOp::MINMAX;
+ read_options.stats = &stats;
+ read_options.tablet_schema = tablet_schema;
+ ASSERT_TRUE(iterator.init(read_options).ok());
+
+ Block block;
+ create_block(schema, block);
+ ASSERT_TRUE(iterator.next_batch(&block).ok());
+ ASSERT_EQ(2, block.rows());
+
+ const auto& nullable_column =
+ assert_cast<const
ColumnNullable&>(*block.get_by_position(1).column);
+ EXPECT_TRUE(nullable_column.is_null_at(0));
+ EXPECT_TRUE(nullable_column.is_null_at(1));
+ ASSERT_TRUE(iterator.next_batch(&block).is<ErrorCode::END_OF_FILE>());
+
+ ASSERT_TRUE(fs->delete_directory(test_dir).ok());
+}
+
TEST(VGenericIteratorsTest, Union) {
auto schema = create_schema();
auto output_schema = std::make_shared<Schema>(schema);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]