From 8ff8705b3fe068878428184074f846db4d17c8f2 Mon Sep 17 00:00:00 2001 From: Jerry Hu Date: Fri, 2 Jun 2023 13:52:57 +0800 Subject: [PATCH] [fix](olap) deletion statement with space conditions did not take effect (#20349) Deletion statement like this: delete from tb where k1 = ' '; The rows whose k1's value is ' ' will not be deleted. --- be/src/olap/delete_handler.cpp | 10 +++- be/test/olap/delete_handler_test.cpp | 40 +++++++++++-- .../data/delete_p0/test_delete.out | 45 ++++++++++++++ .../suites/delete_p0/test_delete.groovy | 59 +++++++++++++++++++ 4 files changed, 146 insertions(+), 8 deletions(-) diff --git a/be/src/olap/delete_handler.cpp b/be/src/olap/delete_handler.cpp index 9beafe634f..7356512315 100644 --- a/be/src/olap/delete_handler.cpp +++ b/be/src/olap/delete_handler.cpp @@ -110,7 +110,7 @@ std::string DeleteHandler::construct_sub_predicates(const TCondition& condition) } else if (op == "!*=") { op = "!="; } - condition_str = condition.column_name + op + condition.condition_values[0]; + condition_str = condition.column_name + op + "'" + condition.condition_values[0] + "'"; } return condition_str; } @@ -218,7 +218,7 @@ bool DeleteHandler::_parse_condition(const std::string& condition_str, TConditio // group2: ((?:=)|(?:!=)|(?:>>)|(?:<<)|(?:>=)|(?:<=)|(?:\*=)|(?:IS)) matches "=" // group3: ((?:[\s\S]+)?) matches "1597751948193618247 and length(source)<1;\n;\n" const char* const CONDITION_STR_PATTERN = - R"((\w+)\s*((?:=)|(?:!=)|(?:>>)|(?:<<)|(?:>=)|(?:<=)|(?:\*=)|(?:IS))\s*((?:[\s\S]+)?))"; + R"((\w+)\s*((?:=)|(?:!=)|(?:>>)|(?:<<)|(?:>=)|(?:<=)|(?:\*=)|(?:IS))\s*('((?:[\s\S]+)?)'|(?:[\s\S]+)?))"; regex ex(CONDITION_STR_PATTERN); if (regex_match(condition_str, what, ex)) { if (condition_str.size() != what[0].str().size()) { @@ -238,7 +238,11 @@ bool DeleteHandler::_parse_condition(const std::string& condition_str, TConditio } condition->column_name = what[1].str(); condition->condition_op = what[2].str(); - condition->condition_values.push_back(what[3].str()); + if (what[4].matched) { // match string with single quotes, eg. a = 'b' + condition->condition_values.push_back(what[4].str()); + } else { // match string without quote, compat with old conditions, eg. a = b + condition->condition_values.push_back(what[3].str()); + } return true; } diff --git a/be/test/olap/delete_handler_test.cpp b/be/test/olap/delete_handler_test.cpp index 588884cc46..9f51e2976e 100644 --- a/be/test/olap/delete_handler_test.cpp +++ b/be/test/olap/delete_handler_test.cpp @@ -366,12 +366,12 @@ TEST_F(TestDeleteConditionHandler, StoreCondSucceed) { // 验证存储在header中的过滤条件正确 EXPECT_EQ(size_t(6), del_pred.sub_predicates_size()); - EXPECT_STREQ("k1=1", del_pred.sub_predicates(0).c_str()); - EXPECT_STREQ("k2>>3", del_pred.sub_predicates(1).c_str()); - EXPECT_STREQ("k3<=5", del_pred.sub_predicates(2).c_str()); + EXPECT_STREQ("k1='1'", del_pred.sub_predicates(0).c_str()); + EXPECT_STREQ("k2>>'3'", del_pred.sub_predicates(1).c_str()); + EXPECT_STREQ("k3<='5'", del_pred.sub_predicates(2).c_str()); EXPECT_STREQ("k4 IS NULL", del_pred.sub_predicates(3).c_str()); - EXPECT_STREQ("k5=7", del_pred.sub_predicates(4).c_str()); - EXPECT_STREQ("k12!=9", del_pred.sub_predicates(5).c_str()); + EXPECT_STREQ("k5='7'", del_pred.sub_predicates(4).c_str()); + EXPECT_STREQ("k12!='9'", del_pred.sub_predicates(5).c_str()); EXPECT_EQ(size_t(1), del_pred.in_predicates_size()); EXPECT_FALSE(del_pred.in_predicates(0).is_not_in()); @@ -899,6 +899,36 @@ protected: std::string _json_rowset_meta; }; +TEST_F(TestDeleteHandler, ValueWithQuote) { + DeletePredicatePB del_predicate; + del_predicate.add_sub_predicates("k1='b'"); + del_predicate.add_sub_predicates("k1='b"); + del_predicate.add_sub_predicates("k1=b'"); + del_predicate.add_sub_predicates("k1=''b'"); + del_predicate.add_sub_predicates("k1='b''"); + del_predicate.add_sub_predicates("k1=''b''"); + del_predicate.set_version(2); + + add_delete_predicate(del_predicate, 2); + + auto res = _delete_handler.init(tablet->tablet_schema(), tablet->delete_predicates(), 5); + EXPECT_EQ(Status::OK(), res); + _delete_handler.finalize(); +} + +TEST_F(TestDeleteHandler, ValueWithoutQuote) { + DeletePredicatePB del_predicate; + del_predicate.add_sub_predicates("k1=b"); + del_predicate.add_sub_predicates("k2=123"); + del_predicate.set_version(2); + + add_delete_predicate(del_predicate, 2); + + auto res = _delete_handler.init(tablet->tablet_schema(), tablet->delete_predicates(), 5); + EXPECT_EQ(Status::OK(), res); + _delete_handler.finalize(); +} + TEST_F(TestDeleteHandler, InitSuccess) { Status res; std::vector conditions; diff --git a/regression-test/data/delete_p0/test_delete.out b/regression-test/data/delete_p0/test_delete.out index 30765c79b8..a58fbf8a09 100644 --- a/regression-test/data/delete_p0/test_delete.out +++ b/regression-test/data/delete_p0/test_delete.out @@ -45,3 +45,48 @@ abcdef 2022-08-12 2022-08-16T12:11:11 2022-08-16T12:11:11.111 2022-08-12 2022-08 -- !sql10 -- +-- !check_data -- + 1 + 2 + 3 + 4 +abc 5 +'d 6 +'e' 7 +f' 8 + +-- !check_data2 -- + 1 + 3 + 4 +abc 5 +'d 6 +'e' 7 +f' 8 + +-- !check_data3 -- + 1 + 3 +abc 5 +'d 6 +'e' 7 +f' 8 + +-- !check_data4 -- + 1 + 3 +abc 5 +'e' 7 +f' 8 + +-- !check_data5 -- + 1 + 3 +abc 5 +f' 8 + +-- !check_data6 -- + 1 + 3 +abc 5 + diff --git a/regression-test/suites/delete_p0/test_delete.groovy b/regression-test/suites/delete_p0/test_delete.groovy index ff3c9b0fbe..c0eda6e787 100644 --- a/regression-test/suites/delete_p0/test_delete.groovy +++ b/regression-test/suites/delete_p0/test_delete.groovy @@ -118,4 +118,63 @@ suite("test_delete") { qt_sql9 """select * from tb_test1;""" sql """ delete from tb_test1 where DT = '20221001'; """ qt_sql10 """select * from tb_test1;""" + + sql """ DROP TABLE IF EXISTS delete_test_tb """ + sql """ + CREATE TABLE `delete_test_tb` ( + `k1` varchar(30) NULL, + `v1` varchar(30) NULL + ) + UNIQUE KEY(`k1`) + DISTRIBUTED BY HASH(`k1`) BUCKETS 4 + PROPERTIES + ( + "replication_num" = "1" + ); + """ + + sql """ + insert into delete_test_tb values + (' ', '1'), (' ', '2'), (' ', '3'), (' ', '4'), + ('abc', '5'), ("'d", '6'), ("'e'", '7'), ("f'", '8'); + """ + + qt_check_data """ + select k1, v1 from delete_test_tb order by v1; + """ + + sql """ + delete from delete_test_tb where k1 = ' '; + """ + qt_check_data2 """ + select k1, v1 from delete_test_tb order by v1; + """ + + sql """ + delete from delete_test_tb where k1 = ' '; + """ + qt_check_data3 """ + select k1, v1 from delete_test_tb order by v1; + """ + + sql """ + delete from delete_test_tb where k1 = "'d"; + """ + qt_check_data4 """ + select k1, v1 from delete_test_tb order by v1; + """ + + sql """ + delete from delete_test_tb where k1 = "'e'"; + """ + qt_check_data5 """ + select k1, v1 from delete_test_tb order by v1; + """ + + sql """ + delete from delete_test_tb where k1 = "f'"; + """ + qt_check_data6 """ + select k1, v1 from delete_test_tb order by v1; + """ }