diff --git a/be/src/vec/columns/column.h b/be/src/vec/columns/column.h index 99ea1f66a42a73..5faecbdeacf05c 100644 --- a/be/src/vec/columns/column.h +++ b/be/src/vec/columns/column.h @@ -587,6 +587,8 @@ class IColumn : public COW { /// It's a special kind of column, that contain single value, but is not a ColumnConst. virtual bool is_dummy() const { return false; } + virtual bool is_exclusive() const { return use_count() == 1; } + /// Clear data of column, just like vector clear virtual void clear() {} diff --git a/be/src/vec/columns/column_nullable.h b/be/src/vec/columns/column_nullable.h index c48e3c80a18eed..8f2e9eab379cef 100644 --- a/be/src/vec/columns/column_nullable.h +++ b/be/src/vec/columns/column_nullable.h @@ -225,6 +225,11 @@ class ColumnNullable final : public COWHelper { bool is_column_array() const override { return get_nested_column().is_column_array(); } bool is_fixed_and_contiguous() const override { return false; } bool values_have_fixed_size() const override { return nested_column->values_have_fixed_size(); } + + bool is_exclusive() const override { + return IColumn::is_exclusive() && nested_column->is_exclusive() && null_map->is_exclusive(); + } + size_t size_of_value_if_fixed() const override { return null_map->size_of_value_if_fixed() + nested_column->size_of_value_if_fixed(); } diff --git a/be/src/vec/core/block.cpp b/be/src/vec/core/block.cpp index 1c97c9f5322532..cc09d53cd2998d 100644 --- a/be/src/vec/core/block.cpp +++ b/be/src/vec/core/block.cpp @@ -668,7 +668,7 @@ void Block::filter_block_internal(Block* block, const std::vector& col for (auto& col : columns_to_filter) { auto& column = block->get_by_position(col).column; if (column->size() != count) { - if (column->use_count() == 1) { + if (column->is_exclusive()) { const auto result_size = column->assume_mutable()->filter(filter); CHECK_EQ(result_size, count); } else { diff --git a/regression-test/data/correctness_p0/test_null_predicate.out b/regression-test/data/correctness_p0/test_null_predicate.out index 8de8224c733610..18d6d319210886 100644 --- a/regression-test/data/correctness_p0/test_null_predicate.out +++ b/regression-test/data/correctness_p0/test_null_predicate.out @@ -174,3 +174,8 @@ -- !select14 -- 13 +-- !select15 -- +1 \N abc +3 \N ccc +5 \N eeee + diff --git a/regression-test/suites/correctness_p0/test_null_predicate.groovy b/regression-test/suites/correctness_p0/test_null_predicate.groovy index 92d403e3fe4d6d..5c8da7c23880db 100644 --- a/regression-test/suites/correctness_p0/test_null_predicate.groovy +++ b/regression-test/suites/correctness_p0/test_null_predicate.groovy @@ -85,4 +85,34 @@ suite("test_null_predicate") { qt_select12 """ select id, name from ${tableName} where id < 110 or name is not null order by id, name; """ qt_select13 """ select id, name from ${tableName} where id > 109 or name is not null order by id, name; """ qt_select14 """ select count(1) from ${tableName} where name is not null; """ + + sql """ DROP TABLE IF EXISTS test_null_predicate2 """ + // Here, create a table and make the "value" column nullable before the "name" column. + // Via: https://github.com/apache/doris/issues/17462 + sql """ + CREATE TABLE IF NOT EXISTS test_null_predicate2 ( + `id` INT, + `value` double NULL, + `name` varchar(30) + ) ENGINE=OLAP + DUPLICATE KEY(`id`) + COMMENT "OLAP" + DISTRIBUTED BY HASH(`id`) BUCKETS 1 + PROPERTIES ( + "replication_num" = "1", + "in_memory" = "false", + "storage_format" = "V2" + ); + """ + + sql """ + INSERT INTO test_null_predicate2 values + (1, null, "abc"), + (2, 2.0, "efg"), + (3, null, "ccc"), + (4, 4.0, "ddd"), + (5, null, "eeee"); + """ + + qt_select15 """ select * from test_null_predicate2 where `value` is null order by id; """ }