diff --git a/be/src/vec/functions/comparison_equal_for_null.cpp b/be/src/vec/functions/comparison_equal_for_null.cpp index 983d40424001be..36c6a86f6dafe1 100644 --- a/be/src/vec/functions/comparison_equal_for_null.cpp +++ b/be/src/vec/functions/comparison_equal_for_null.cpp @@ -66,6 +66,37 @@ class FunctionEqForNull : public IFunction { size_t result, size_t input_rows_count) const override { ColumnWithTypeAndName& col_left = block.get_by_position(arguments[0]); ColumnWithTypeAndName& col_right = block.get_by_position(arguments[1]); + bool left_only_null = col_left.column->only_null(); + bool right_only_null = col_right.column->only_null(); + if (left_only_null && right_only_null) { + auto result_column = ColumnVector::create(input_rows_count, 1); + block.get_by_position(result).column = std::move(result_column); + return Status::OK(); + } else if (left_only_null) { + auto right_type_nullable = col_right.type->is_nullable(); + if (!right_type_nullable) { + block.get_by_position(result).column = + ColumnVector::create(input_rows_count); + } else { + auto const* nullable_right_col = + assert_cast(col_right.column.get()); + block.get_by_position(result).column = + nullable_right_col->get_null_map_column().clone_resized(input_rows_count); + } + return Status::OK(); + } else if (right_only_null) { + auto left_type_nullable = col_left.type->is_nullable(); + if (!left_type_nullable) { + block.get_by_position(result).column = + ColumnVector::create(input_rows_count, (UInt8)0); + } else { + auto const* nullable_left_col = + assert_cast(col_left.column.get()); + block.get_by_position(result).column = + nullable_left_col->get_null_map_column().clone_resized(input_rows_count); + } + return Status::OK(); + } const auto& [left_col, left_const] = unpack_if_const(col_left.column); const auto& [right_col, right_const] = unpack_if_const(col_right.column); @@ -153,15 +184,15 @@ class FunctionEqForNull : public IFunction { bool right_const) { if (left_const) { for (int i = 0; i < rows; ++i) { - result[i] |= left[0] & (left[0] == right[i]); + result[i] &= (left[0] == right[i]); } } else if (right_const) { for (int i = 0; i < rows; ++i) { - result[i] |= left[i] & (left[i] == right[0]); + result[i] &= (left[i] == right[0]); } } else { for (int i = 0; i < rows; ++i) { - result[i] |= left[i] & (left[i] == right[i]); + result[i] &= (left[i] == right[i]); } } } diff --git a/regression-test/data/correctness_p0/test_null_equal.out b/regression-test/data/correctness_p0/test_null_equal.out new file mode 100644 index 00000000000000..39d74087270819 --- /dev/null +++ b/regression-test/data/correctness_p0/test_null_equal.out @@ -0,0 +1,196 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !test_const1 -- +true + +-- !test_const2 -- +false + +-- !test_const3 -- +false + +-- !test1 -- + +-- !test2 -- + +-- !test3 -- +1 1 +2 2 +3 3 + +-- !test4 -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N + +-- !test5 -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N + +-- !test6 -- +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +\N \N +1 1 +2 2 +3 3 + diff --git a/regression-test/suites/correctness_p0/test_null_equal.groovy b/regression-test/suites/correctness_p0/test_null_equal.groovy new file mode 100644 index 00000000000000..a9c9ea5ca00659 --- /dev/null +++ b/regression-test/suites/correctness_p0/test_null_equal.groovy @@ -0,0 +1,74 @@ +// 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. + +suite("test_null_equal") { + qt_test_const1 "select null <=> null;" + qt_test_const2 "select null <=> 0;" + qt_test_const3 "select 1 <=> null;" + + sql "drop table if exists test_eq_for_null_not_nullable;" + sql """ + create table test_eq_for_null_not_nullable( + k1 int not null + ) distributed by hash(k1) properties("replication_num"="1"); + """ + sql """ + insert into test_eq_for_null_not_nullable values + (1),(2),(3); + """ + sql "sync" + qt_test1 "select * from test_eq_for_null_not_nullable where k1 <=> null;" + qt_test2 "select * from test_eq_for_null_not_nullable where null <=> k1;" + + sql "drop table if exists test_eq_for_null_nullable;" + sql """ + create table test_eq_for_null_nullable( + k1 int + ) distributed by hash(k1) properties("replication_num"="1"); + """ + sql """ + insert into test_eq_for_null_nullable values + (1),(2),(3), + (null), (null), (null),(null),(null),(null),(null),(null), + (null), (null), (null),(null),(null),(null),(null),(null), + (null), (null), (null),(null),(null),(null),(null),(null), + (null), (null), (null),(null),(null),(null),(null),(null), + (null), (null), (null),(null),(null),(null),(null),(null), + (null), (null), (null),(null),(null),(null),(null),(null), + (null), (null), (null),(null),(null),(null),(null),(null); + """ + sql "sync" + qt_test3 "select * from test_eq_for_null_not_nullable l, test_eq_for_null_nullable r where l.k1 <=> r.k1 order by 1;" + qt_test4 "select * from test_eq_for_null_nullable where k1 <=> null;" + qt_test5 "select * from test_eq_for_null_nullable where null <=> k1;" + + sql "drop table if exists test_eq_for_null_nullable2;" + sql """ + create table test_eq_for_null_nullable2( + k1 int + ) distributed by hash(k1) properties("replication_num"="1"); + """ + sql """ + insert into test_eq_for_null_nullable2 values + (null),(0),(1),(2),(3); + """ + sql "sync" + + qt_test6 "select * from test_eq_for_null_nullable a, test_eq_for_null_nullable2 b where a.k1 <=> b.k1 order by 1;" + + +} \ No newline at end of file