-
Notifications
You must be signed in to change notification settings - Fork 409
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Storages: Fix comparing null in MinMaxIndex #9373
Changes from 3 commits
322c3cd
93a6341
b2f0cb4
37e4b8b
cbd08e1
a7a2451
aa0a0ba
9335f8c
a57235c
6e6573a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2662,4 +2662,82 @@ try | |||||||||||||
} | ||||||||||||||
} | ||||||||||||||
CATCH | ||||||||||||||
|
||||||||||||||
TEST_F(MinMaxIndexTest, CheckCmpNullValue) | ||||||||||||||
try | ||||||||||||||
{ | ||||||||||||||
auto col_type = DataTypeFactory::instance().get("Int64"); | ||||||||||||||
auto minmax_index = createMinMaxIndex(*col_type, min_max_check_test_data); | ||||||||||||||
auto rs_index = RSIndex(col_type, minmax_index); | ||||||||||||||
RSCheckParam param; | ||||||||||||||
param.indexes.emplace(DEFAULT_COL_ID, rs_index); | ||||||||||||||
|
||||||||||||||
Field null_value; | ||||||||||||||
ASSERT_TRUE(null_value.isNull()); | ||||||||||||||
|
||||||||||||||
auto check = [&](RSOperatorPtr rs, RSResult expected_res) { | ||||||||||||||
auto results = rs->roughCheck(0, min_max_check_test_data.size(), param); | ||||||||||||||
for (auto actual_res : results) | ||||||||||||||
ASSERT_EQ(actual_res, expected_res) << fmt::format("actual: {}, expected: {}", actual_res, expected_res); | ||||||||||||||
}; | ||||||||||||||
|
||||||||||||||
check(createGreater(attr("Int64"), null_value), RSResult::NoneNull); | ||||||||||||||
check(createGreaterEqual(attr("Int64"), null_value), RSResult::NoneNull); | ||||||||||||||
check(createLess(attr("Int64"), null_value), RSResult::AllNull); | ||||||||||||||
check(createLessEqual(attr("Int64"), null_value), RSResult::AllNull); | ||||||||||||||
check(createEqual(attr("Int64"), null_value), RSResult::NoneNull); | ||||||||||||||
check(createNotEqual(attr("Int64"), null_value), RSResult::AllNull); | ||||||||||||||
Comment on lines
+2684
to
+2689
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why "less"/"lessequal"/"noteuqal" return "AllNull" but others return "NoneNull"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because
tiflash/dbms/src/Storages/DeltaMerge/Filter/Less.h Lines 32 to 37 in d113404
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||
} | ||||||||||||||
CATCH | ||||||||||||||
|
||||||||||||||
TEST_F(MinMaxIndexTest, CheckInNullValue) | ||||||||||||||
try | ||||||||||||||
{ | ||||||||||||||
auto col_type = DataTypeFactory::instance().get("Nullable(Int64)"); | ||||||||||||||
auto minmax_index = createMinMaxIndex(*col_type, min_max_check_test_data); | ||||||||||||||
auto rs_index = RSIndex(col_type, minmax_index); | ||||||||||||||
RSCheckParam param; | ||||||||||||||
param.indexes.emplace(DEFAULT_COL_ID, rs_index); | ||||||||||||||
|
||||||||||||||
Field null_value; | ||||||||||||||
ASSERT_TRUE(null_value.isNull()); | ||||||||||||||
|
||||||||||||||
{ | ||||||||||||||
auto rs = createIn(attr("Nullable(Int64)"), {null_value}); | ||||||||||||||
auto results = rs->roughCheck(0, min_max_check_test_data.size(), param); | ||||||||||||||
auto excepted_results = { | ||||||||||||||
RSResult::NoneNull, | ||||||||||||||
RSResult::NoneNull, | ||||||||||||||
RSResult::SomeNull, // All the fields are null, the default value is null, meet the compatibility check | ||||||||||||||
RSResult::NoneNull, | ||||||||||||||
RSResult::NoneNull, | ||||||||||||||
RSResult::SomeNull, // All the fields are null, the default value is null, meet the compatibility check | ||||||||||||||
RSResult::SomeNull, // All the fields are deleted, the default value is null, meet the compatibility check | ||||||||||||||
RSResult::SomeNull, // All the fields are deleted, the default value is null, meet the compatibility check | ||||||||||||||
RSResult::NoneNull, | ||||||||||||||
RSResult::NoneNull, | ||||||||||||||
}; | ||||||||||||||
ASSERT_TRUE(std::equal(results.cbegin(), results.cend(), excepted_results.begin())); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
{ | ||||||||||||||
auto rs = createIn(attr("Nullable(Int64)"), {Field{static_cast<Int64>(1)}, null_value}); | ||||||||||||||
auto results = rs->roughCheck(0, min_max_check_test_data.size(), param); | ||||||||||||||
auto excepted_results = { | ||||||||||||||
RSResult::SomeNull, | ||||||||||||||
RSResult::NoneNull, | ||||||||||||||
RSResult::SomeNull, // All the fields are null, the default value is null, meet the compatibility check | ||||||||||||||
RSResult::SomeNull, | ||||||||||||||
RSResult::NoneNull, | ||||||||||||||
RSResult::SomeNull, // All the fields are null, the default value is null, meet the compatibility check | ||||||||||||||
RSResult::SomeNull, // All the fields are deleted, the default value is null, meet the compatibility check | ||||||||||||||
RSResult::SomeNull, // All the fields are deleted, the default value is null, meet the compatibility check | ||||||||||||||
RSResult::All, | ||||||||||||||
RSResult::AllNull, | ||||||||||||||
}; | ||||||||||||||
ASSERT_TRUE(std::equal(results.cbegin(), results.cend(), excepted_results.begin())); | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
CATCH | ||||||||||||||
|
||||||||||||||
} // namespace DB::DM::tests |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better add some test case about this: https://dev.mysql.com/doc/refman/8.4/en/working-with-null.html
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
# Copyright 2024 PingCAP, Inc. | ||
# | ||
# Licensed 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. | ||
|
||
# Must enable DT rough set filter and open debug level log to run this test, otherwise disable this test | ||
mysql> drop table if exists test.t; | ||
|
||
mysql> create table test.t (a date); | ||
|
||
mysql> insert into test.t values('2024-08-26'),('2024-08-25'),('2024-08-24'),('2024-08-23'); | ||
|
||
mysql> alter table test.t set tiflash replica 1; | ||
|
||
func> wait_table test t | ||
|
||
mysql> alter table test.t compact tiflash replica; | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a between NULL and '2024-08-25'; | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where not (a between NULL and '2024-08-25'); | ||
+------------+ | ||
| a | | ||
+------------+ | ||
| 2024-08-26 | | ||
+------------+ | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a in (NULL); | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a not in (NULL); | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a in (NULL, '2024-08-26'); | ||
+------------+ | ||
| a | | ||
+------------+ | ||
| 2024-08-26 | | ||
+------------+ | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a not in (NULL, '2024-08-26'); | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a in (NULL, '2024-09-01'); | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a not in (NULL, '2024-09-01'); | ||
|
||
mysql> drop table if exists test.t; | ||
|
||
mysql> create table test.t (a date); | ||
|
||
mysql> insert into test.t values('2024-08-26'),('2024-08-26'),('2024-08-26'),('2024-08-26'); | ||
|
||
mysql> alter table test.t set tiflash replica 1; | ||
|
||
func> wait_table test t | ||
|
||
mysql> alter table test.t compact tiflash replica; | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a in (NULL, '2024-08-26'); | ||
+------------+ | ||
| a | | ||
+------------+ | ||
| 2024-08-26 | | ||
| 2024-08-26 | | ||
| 2024-08-26 | | ||
| 2024-08-26 | | ||
+------------+ | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a not in (NULL, '2024-08-26'); | ||
|
||
# not null | ||
|
||
mysql> drop table if exists test.t; | ||
|
||
mysql> create table test.t (a date not null); | ||
|
||
mysql> insert into test.t values('2024-08-26'),('2024-08-25'),('2024-08-24'),('2024-08-23'); | ||
|
||
mysql> alter table test.t set tiflash replica 1; | ||
|
||
func> wait_table test t | ||
|
||
mysql> alter table test.t compact tiflash replica; | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a between NULL and '2024-08-25'; | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where not (a between NULL and '2024-08-25'); | ||
+------------+ | ||
| a | | ||
+------------+ | ||
| 2024-08-26 | | ||
+------------+ | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a in (NULL); | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a not in (NULL); | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a in (NULL, '2024-08-26'); | ||
+------------+ | ||
| a | | ||
+------------+ | ||
| 2024-08-26 | | ||
+------------+ | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a not in (NULL, '2024-08-26'); | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a in (NULL, '2024-09-01'); | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a not in (NULL, '2024-09-01'); | ||
|
||
mysql> drop table if exists test.t; | ||
|
||
mysql> create table test.t (a date not null); | ||
|
||
mysql> insert into test.t values('2024-08-26'),('2024-08-26'),('2024-08-26'),('2024-08-26'); | ||
|
||
mysql> alter table test.t set tiflash replica 1; | ||
|
||
func> wait_table test t | ||
|
||
mysql> alter table test.t compact tiflash replica; | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a in (NULL, '2024-08-26'); | ||
+------------+ | ||
| a | | ||
+------------+ | ||
| 2024-08-26 | | ||
| 2024-08-26 | | ||
| 2024-08-26 | | ||
| 2024-08-26 | | ||
+------------+ | ||
|
||
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t where a not in (NULL, '2024-08-26'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just move some
results
to a smaller scope.