// 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. #include #include #include #include #include #include #include #include #include "olap/delete_handler.h" #include "olap/olap_define.h" #include "olap/olap_engine.h" #include "olap/push_handler.h" #include "olap/utils.h" #include "olap/options.h" #include "util/logging.h" using namespace std; using namespace doris; using namespace boost::assign; using google::protobuf::RepeatedPtrField; namespace doris { static const uint32_t MAX_PATH_LEN = 1024; static OLAPEngine* k_engine = nullptr; void set_up() { char buffer[MAX_PATH_LEN]; getcwd(buffer, MAX_PATH_LEN); config::storage_root_path = string(buffer) + "/data_test"; remove_all_dir(config::storage_root_path); remove_all_dir(string(getenv("DORIS_HOME")) + UNUSED_PREFIX); create_dir(config::storage_root_path); std::vector paths; paths.emplace_back(config::storage_root_path, -1); doris::EngineOptions options; options.store_paths = paths; doris::OLAPEngine::open(options, &k_engine); } void tear_down() { char buffer[MAX_PATH_LEN]; getcwd(buffer, MAX_PATH_LEN); config::storage_root_path = string(buffer) + "/data_test"; remove_all_dir(config::storage_root_path); remove_all_dir(string(getenv("DORIS_HOME")) + UNUSED_PREFIX); } void set_default_create_tablet_request(TCreateTabletReq* request) { request->tablet_id = 10003; request->__set_version(1); request->__set_version_hash(0); request->tablet_schema.schema_hash = 270068375; request->tablet_schema.short_key_column_count = 2; request->tablet_schema.keys_type = TKeysType::AGG_KEYS; request->tablet_schema.storage_type = TStorageType::COLUMN; TColumn k1; k1.column_name = "k1"; k1.__set_is_key(true); k1.column_type.type = TPrimitiveType::TINYINT; request->tablet_schema.columns.push_back(k1); TColumn k2; k2.column_name = "k2"; k2.__set_is_key(true); k2.column_type.type = TPrimitiveType::SMALLINT; request->tablet_schema.columns.push_back(k2); TColumn k3; k3.column_name = "k3"; k3.__set_is_key(true); k3.column_type.type = TPrimitiveType::INT; request->tablet_schema.columns.push_back(k3); TColumn k4; k4.column_name = "k4"; k4.__set_is_key(true); k4.column_type.type = TPrimitiveType::BIGINT; request->tablet_schema.columns.push_back(k4); TColumn k5; k5.column_name = "k5"; k5.__set_is_key(true); k5.column_type.type = TPrimitiveType::LARGEINT; request->tablet_schema.columns.push_back(k5); TColumn k9; k9.column_name = "k9"; k9.__set_is_key(true); k9.column_type.type = TPrimitiveType::DECIMAL; k9.column_type.__set_precision(6); k9.column_type.__set_scale(3); request->tablet_schema.columns.push_back(k9); TColumn k10; k10.column_name = "k10"; k10.__set_is_key(true); k10.column_type.type = TPrimitiveType::DATE; request->tablet_schema.columns.push_back(k10); TColumn k11; k11.column_name = "k11"; k11.__set_is_key(true); k11.column_type.type = TPrimitiveType::DATETIME; request->tablet_schema.columns.push_back(k11); TColumn k12; k12.column_name = "k12"; k12.__set_is_key(true); k12.column_type.__set_len(64); k12.column_type.type = TPrimitiveType::CHAR; request->tablet_schema.columns.push_back(k12); TColumn k13; k13.column_name = "k13"; k13.__set_is_key(true); k13.column_type.__set_len(64); k13.column_type.type = TPrimitiveType::VARCHAR; request->tablet_schema.columns.push_back(k13); TColumn v; v.column_name = "v"; v.__set_is_key(false); v.column_type.type = TPrimitiveType::BIGINT; v.__set_aggregation_type(TAggregationType::SUM); request->tablet_schema.columns.push_back(v); } void set_default_push_request(TPushReq* request) { request->tablet_id = 10003; request->schema_hash = 270068375; request->__set_version(2); request->__set_version_hash(1); request->timeout = 86400; request->push_type = TPushType::LOAD; } class TestDeleteConditionHandler : public testing::Test { protected: void SetUp() { // Create local data dir for OLAPEngine. char buffer[MAX_PATH_LEN]; getcwd(buffer, MAX_PATH_LEN); config::storage_root_path = string(buffer) + "/data_delete_condition"; remove_all_dir(config::storage_root_path); ASSERT_EQ(create_dir(config::storage_root_path), OLAP_SUCCESS); // Initialize all singleton object. // OLAPRootPath::get_instance()->reload_root_paths(config::storage_root_path.c_str()); // 1. Prepare for query split key. // create base tablet OLAPStatus res = OLAP_SUCCESS; set_default_create_tablet_request(&_create_tablet); res = k_engine->create_table(_create_tablet); ASSERT_EQ(OLAP_SUCCESS, res); _olap_table = k_engine->get_table( _create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash); ASSERT_TRUE(_olap_table.get() != NULL); _tablet_path = _olap_table->tablet_path(); } OLAPStatus push_empty_delta(int32_t version) { // push data TPushReq push_req; set_default_push_request(&push_req); push_req.version = version; push_req.version_hash = version; std::vector tablets_info; return k_engine->push(push_req, &tablets_info); } void TearDown() { // Remove all dir. _olap_table.reset(); OLAPEngine::get_instance()->drop_table( _create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash); while (0 == access(_tablet_path.c_str(), F_OK)) { sleep(1); } ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path)); } typedef RepeatedPtrField del_cond_array; std::string _tablet_path; OLAPTablePtr _olap_table; TCreateTabletReq _create_tablet; DeleteConditionHandler _delete_condition_handler; }; TEST_F(TestDeleteConditionHandler, StoreCondSucceed) { OLAPStatus success_res; std::vector conditions; TCondition condition; condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = ">"; condition.condition_values.clear(); condition.condition_values.push_back("3"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = "<="; condition.condition_values.clear(); condition.condition_values.push_back("5"); conditions.push_back(condition); success_res = _delete_condition_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_SUCCESS, success_res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(3)); // 验证存储在header中的过滤条件正确 const del_cond_array& delete_conditions = _olap_table->delete_data_conditions(); ASSERT_EQ(size_t(1), delete_conditions.size()); EXPECT_EQ(3, delete_conditions.Get(0).version()); ASSERT_EQ(size_t(3), delete_conditions.Get(0).sub_conditions_size()); EXPECT_STREQ("k1=1", delete_conditions.Get(0).sub_conditions(0).c_str()); EXPECT_STREQ("k2>>3", delete_conditions.Get(0).sub_conditions(1).c_str()); EXPECT_STREQ("k2<=5", delete_conditions.Get(0).sub_conditions(2).c_str()); // 再次存储相同版本号(版本号为3)的过滤条件 conditions.clear(); condition.column_name = "k1"; condition.condition_op = "!="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); success_res = _delete_condition_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_SUCCESS, success_res); // 验证存储相同版本号的过滤条件情况下,新的过滤条件替换掉旧的过滤条件 const del_cond_array& new_delete_conditions = _olap_table->delete_data_conditions(); ASSERT_EQ(size_t(1), new_delete_conditions.size()); EXPECT_EQ(3, new_delete_conditions.Get(0).version()); ASSERT_EQ(size_t(1), new_delete_conditions.Get(0).sub_conditions_size()); EXPECT_STREQ("k1!=1", new_delete_conditions.Get(0).sub_conditions(0).c_str()); // 第三次存储不同版本号(版本号为4)的过滤条件 conditions.clear(); condition.column_name = "k1"; condition.condition_op = "!="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); condition.column_name = "k1"; condition.condition_op = "!="; condition.condition_values.clear(); condition.condition_values.push_back("2"); conditions.push_back(condition); success_res = _delete_condition_handler.store_cond(_olap_table, 4, conditions); ASSERT_EQ(OLAP_SUCCESS, success_res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(4)); const del_cond_array& all_delete_conditions = _olap_table->delete_data_conditions(); ASSERT_EQ(size_t(2), all_delete_conditions.size()); EXPECT_EQ(3, all_delete_conditions.Get(0).version()); ASSERT_EQ(size_t(1), all_delete_conditions.Get(0).sub_conditions_size()); EXPECT_STREQ("k1!=1", all_delete_conditions.Get(0).sub_conditions(0).c_str()); EXPECT_EQ(4, all_delete_conditions.Get(1).version()); ASSERT_EQ(size_t(2), all_delete_conditions.Get(1).sub_conditions_size()); EXPECT_STREQ("k1!=1", all_delete_conditions.Get(1).sub_conditions(0).c_str()); EXPECT_STREQ("k1!=2", all_delete_conditions.Get(1).sub_conditions(1).c_str()); } // 检测参数不正确的情况,包括:空的过滤条件字符串,以及负的版本号 TEST_F(TestDeleteConditionHandler, StoreCondInvalidParameters) { // 空的过滤条件 std::vector conditions; OLAPStatus failed_res = _delete_condition_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_ERR_DELETE_INVALID_PARAMETERS, failed_res); // 负的版本号: -10 TCondition condition; condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("2"); conditions.push_back(condition); failed_res = _delete_condition_handler.store_cond(_olap_table, -10, conditions); ASSERT_EQ(OLAP_ERR_DELETE_INVALID_PARAMETERS, failed_res); } // 检测过滤条件中指定的列不存在,或者列不符合要求 TEST_F(TestDeleteConditionHandler, StoreCondNonexistentColumn) { // 'k100'是一个不存在的列 std::vector conditions; TCondition condition; condition.column_name = "k100"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("2"); conditions.push_back(condition); OLAPStatus failed_res = _delete_condition_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, failed_res); // 'v'是value列 conditions.clear(); condition.column_name = "v"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("5"); conditions.push_back(condition); failed_res = _delete_condition_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, failed_res); } // 只删除特定版本的过滤条件 TEST_F(TestDeleteConditionHandler, DeleteCondRemoveOneCondition) { OLAPStatus res; std::vector conditions; TCondition condition; condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = ">"; condition.condition_values.clear(); condition.condition_values.push_back("3"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = "<="; condition.condition_values.clear(); condition.condition_values.push_back("5"); conditions.push_back(condition); res = _delete_condition_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(3)); conditions.clear(); condition.column_name = "k1"; condition.condition_op = "!="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); res = _delete_condition_handler.store_cond(_olap_table, 4, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(4)); conditions.clear(); condition.column_name = "k2"; condition.condition_op = ">="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); res = _delete_condition_handler.store_cond(_olap_table, 5, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(5)); // 删除版本号为8的过滤条件 res = _delete_condition_handler.delete_cond(_olap_table, 5, false); ASSERT_EQ(OLAP_SUCCESS, res); const del_cond_array& all_delete_conditions = _olap_table->delete_data_conditions(); ASSERT_EQ(size_t(2), all_delete_conditions.size()); EXPECT_EQ(3, all_delete_conditions.Get(0).version()); ASSERT_EQ(size_t(3), all_delete_conditions.Get(0).sub_conditions_size()); EXPECT_STREQ("k1=1", all_delete_conditions.Get(0).sub_conditions(0).c_str()); EXPECT_STREQ("k2>>3", all_delete_conditions.Get(0).sub_conditions(1).c_str()); EXPECT_STREQ("k2<=5", all_delete_conditions.Get(0).sub_conditions(2).c_str()); EXPECT_EQ(4, all_delete_conditions.Get(1).version()); ASSERT_EQ(size_t(1), all_delete_conditions.Get(1).sub_conditions_size()); EXPECT_STREQ("k1!=1", all_delete_conditions.Get(1).sub_conditions(0).c_str()); } // 删除特定版本以及版本比它小的过滤条件 TEST_F(TestDeleteConditionHandler, DeleteCondRemovBelowCondition) { OLAPStatus res; std::vector conditions; TCondition condition; condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = ">"; condition.condition_values.clear(); condition.condition_values.push_back("3"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = "<="; condition.condition_values.clear(); condition.condition_values.push_back("5"); conditions.push_back(condition); res = _delete_condition_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(3)); conditions.clear(); condition.column_name = "k1"; condition.condition_op = "!="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); res = _delete_condition_handler.store_cond(_olap_table, 4, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(4)); conditions.clear(); condition.column_name = "k2"; condition.condition_op = ">="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); res = _delete_condition_handler.store_cond(_olap_table, 5, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(5)); // 删除版本号为7以及版本号小于7的过滤条件 res = _delete_condition_handler.delete_cond(_olap_table, 4, true); ASSERT_EQ(OLAP_SUCCESS, res); const del_cond_array& all_delete_conditions = _olap_table->delete_data_conditions(); ASSERT_EQ(size_t(1), all_delete_conditions.size()); EXPECT_EQ(5, all_delete_conditions.Get(0).version()); ASSERT_EQ(size_t(1), all_delete_conditions.Get(0).sub_conditions_size()); EXPECT_STREQ("k2>=1", all_delete_conditions.Get(0).sub_conditions(0).c_str()); } // 测试删除条件值不符合类型要求 class TestDeleteConditionHandler2 : public testing::Test { protected: void SetUp() { // Create local data dir for OLAPEngine. char buffer[MAX_PATH_LEN]; getcwd(buffer, MAX_PATH_LEN); config::storage_root_path = string(buffer) + "/data_delete_condition"; remove_all_dir(config::storage_root_path); ASSERT_EQ(create_dir(config::storage_root_path), OLAP_SUCCESS); // Initialize all singleton object. // OLAPRootPath::get_instance()->reload_root_paths(config::storage_root_path.c_str()); // 1. Prepare for query split key. // create base tablet OLAPStatus res = OLAP_SUCCESS; set_default_create_tablet_request(&_create_tablet); res = k_engine->create_table(_create_tablet); ASSERT_EQ(OLAP_SUCCESS, res); _olap_table = k_engine->get_table( _create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash); ASSERT_TRUE(_olap_table.get() != NULL); _tablet_path = _olap_table->tablet_path(); } void TearDown() { // Remove all dir. _olap_table.reset(); OLAPEngine::get_instance()->drop_table( _create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash); while (0 == access(_tablet_path.c_str(), F_OK)) { sleep(1); } ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path)); } typedef RepeatedPtrField del_cond_array; std::string _tablet_path; OLAPTablePtr _olap_table; TCreateTabletReq _create_tablet; }; TEST_F(TestDeleteConditionHandler2, ValidConditionValue) { OLAPStatus res; DeleteConditionHandler cond_handler; std::vector conditions; // 测试数据中, k1,k2,k3,k4类型分别为int8, int16, int32, int64 TCondition condition; condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("-1"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("-1"); conditions.push_back(condition); condition.column_name = "k3"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("-1"); conditions.push_back(condition); condition.column_name = "k4"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("-1"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_SUCCESS, res); // k5类型为int128 conditions.clear(); condition.column_name = "k5"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_SUCCESS, res); // k9类型为decimal, precision=6, frac=3 conditions.clear(); condition.column_name = "k9"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("2.3"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_SUCCESS, res); conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("2"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_SUCCESS, res); conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("-2"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_SUCCESS, res); conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("-2.3"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_SUCCESS, res); // k10,k11类型分别为date, datetime conditions.clear(); condition.column_name = "k10"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("2014-01-01"); conditions.push_back(condition); condition.column_name = "k10"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("2014-01-01 00:00:00"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_SUCCESS, res); // k12,k13类型分别为string(64), varchar(64) conditions.clear(); condition.column_name = "k12"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("YWFh"); conditions.push_back(condition); condition.column_name = "k13"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("YWFhYQ=="); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_SUCCESS, res); } TEST_F(TestDeleteConditionHandler2, InvalidConditionValue) { OLAPStatus res; DeleteConditionHandler cond_handler; std::vector conditions; // 测试k1的值越上界,k1类型为int8 TCondition condition; condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("1000"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k1的值越下界,k1类型为int8 conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("-1000"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k2的值越上界,k2类型为int16 conditions[0].condition_values.clear(); conditions[0].column_name = "k2"; conditions[0].condition_values.push_back("32768"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k2的值越下界,k2类型为int16 conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("-32769"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k3的值越上界,k3类型为int32 conditions[0].condition_values.clear(); conditions[0].column_name = "k3"; conditions[0].condition_values.push_back("2147483648"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k3的值越下界,k3类型为int32 conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("-2147483649"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k4的值越上界,k2类型为int64 conditions[0].condition_values.clear(); conditions[0].column_name = "k4"; conditions[0].condition_values.push_back("9223372036854775808"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k4的值越下界,k1类型为int64 conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("-9223372036854775809"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k5的值越上界,k5类型为int128 conditions[0].condition_values.clear(); conditions[0].column_name = "k5"; conditions[0].condition_values.push_back("170141183460469231731687303715884105728"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k5的值越下界,k5类型为int128 conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("-170141183460469231731687303715884105729"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k9整数部分长度过长,k9类型为decimal, precision=6, frac=3 conditions[0].condition_values.clear(); conditions[0].column_name = "k9"; conditions[0].condition_values.push_back("1234.5"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k9小数部分长度过长,k9类型为decimal, precision=6, frac=3 conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("1.2345"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k9没有小数部分,但包含小数点 conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("1."); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k10类型的过滤值不符合对应格式,k10为date conditions[0].condition_values.clear(); conditions[0].column_name = "k10"; conditions[0].condition_values.push_back("20130101"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("2013-64-01"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("2013-01-40"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k11类型的过滤值不符合对应格式,k11为datetime conditions[0].condition_values.clear(); conditions[0].column_name = "k11"; conditions[0].condition_values.push_back("20130101 00:00:00"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("2013-64-01 00:00:00"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("2013-01-40 00:00:00"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("2013-01-01 24:00:00"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("2013-01-01 00:60:00"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); conditions[0].condition_values.clear(); conditions[0].condition_values.push_back("2013-01-01 00:00:60"); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); // 测试k12和k13类型的过滤值过长,k12,k13类型分别为string(64), varchar(64) conditions[0].condition_values.clear(); conditions[0].column_name = "k12"; conditions[0].condition_values.push_back("YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW" "FhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW" "FhYWFhYWFhYWFhYWFhYWFhYWFhYWE=;k13=YWFhYQ=="); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); conditions[0].condition_values.clear(); conditions[0].column_name = "k13"; conditions[0].condition_values.push_back("YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW" "FhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW" "FhYWFhYWFhYWFhYWFhYWFhYWFhYWE=;k13=YWFhYQ=="); res = cond_handler.store_cond(_olap_table, 2, conditions); EXPECT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res); } class TestDeleteHandler : public testing::Test { protected: void SetUp() { // Create local data dir for OLAPEngine. char buffer[MAX_PATH_LEN]; getcwd(buffer, MAX_PATH_LEN); config::storage_root_path = string(buffer) + "/data_delete_condition"; remove_all_dir(config::storage_root_path); ASSERT_EQ(create_dir(config::storage_root_path), OLAP_SUCCESS); // Initialize all singleton object. // OLAPRootPath::get_instance()->reload_root_paths(config::storage_root_path.c_str()); // 1. Prepare for query split key. // create base tablet OLAPStatus res = OLAP_SUCCESS; set_default_create_tablet_request(&_create_tablet); res = k_engine->create_table(_create_tablet); ASSERT_EQ(OLAP_SUCCESS, res); _olap_table = k_engine->get_table( _create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash); ASSERT_TRUE(_olap_table.get() != NULL); _tablet_path = _olap_table->tablet_path(); _data_row_cursor.init(_olap_table->tablet_schema()); _data_row_cursor.allocate_memory_for_string_type(_olap_table->tablet_schema()); } OLAPStatus push_empty_delta(int32_t version) { // push data TPushReq push_req; set_default_push_request(&push_req); push_req.version = version; push_req.version_hash = version; std::vector tablets_info; return k_engine->push(push_req, &tablets_info); } void TearDown() { // Remove all dir. _olap_table.reset(); _delete_handler.finalize(); OLAPEngine::get_instance()->drop_table( _create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash); while (0 == access(_tablet_path.c_str(), F_OK)) { sleep(1); } ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path)); } typedef RepeatedPtrField del_cond_array; std::string _tablet_path; RowCursor _data_row_cursor; OLAPTablePtr _olap_table; TCreateTabletReq _create_tablet; DeleteHandler _delete_handler; }; TEST_F(TestDeleteHandler, InitSuccess) { OLAPStatus res; std::vector conditions; DeleteConditionHandler delete_condition_handler; // Header中还没有删除条件 res = _delete_handler.init(_olap_table, 2); ASSERT_EQ(OLAP_SUCCESS, res); // 往头文件中添加过滤条件 TCondition condition; condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = ">"; condition.condition_values.clear(); condition.condition_values.push_back("3"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = "<="; condition.condition_values.clear(); condition.condition_values.push_back("5"); conditions.push_back(condition); res = delete_condition_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(3)); conditions.clear(); condition.column_name = "k1"; condition.condition_op = "!="; condition.condition_values.clear(); condition.condition_values.push_back("3"); conditions.push_back(condition); res = delete_condition_handler.store_cond(_olap_table, 4, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(4)); conditions.clear(); condition.column_name = "k2"; condition.condition_op = ">="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); res = delete_condition_handler.store_cond(_olap_table, 5, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(5)); conditions.clear(); condition.column_name = "k2"; condition.condition_op = "!="; condition.condition_values.clear(); condition.condition_values.push_back("3"); conditions.push_back(condition); res = delete_condition_handler.store_cond(_olap_table, 6, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(6)); // 从header文件中取出版本号小于等于7的过滤条件 _delete_handler.finalize(); res = _delete_handler.init(_olap_table, 4); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(2, _delete_handler.conditions_num()); vector conds_version = _delete_handler.get_conds_version(); sort(conds_version.begin(), conds_version.end()); EXPECT_EQ(3, conds_version[0]); EXPECT_EQ(4, conds_version[1]); _delete_handler.finalize(); } // 测试一个过滤条件包含的子条件之间是and关系, // 即只有满足一条过滤条件包含的所有子条件,这条数据才会被过滤 TEST_F(TestDeleteHandler, FilterDataSubconditions) { OLAPStatus res; DeleteConditionHandler cond_handler; std::vector conditions; // 往Header中添加过滤条件 // 过滤条件1 TCondition condition; condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = "!="; condition.condition_values.clear(); condition.condition_values.push_back("4"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(3)); // 指定版本号为10以载入Header中的所有过滤条件(在这个case中,只有过滤条件1) _delete_handler.init(_olap_table, 10); // 构造一行测试数据 vector data_str; data_str.push_back("1"); data_str.push_back("6"); data_str.push_back("8"); data_str.push_back("-1"); data_str.push_back("16"); data_str.push_back("1.2"); data_str.push_back("2014-01-01"); data_str.push_back("2014-01-01 00:00:00"); data_str.push_back("YWFH"); data_str.push_back("YWFH=="); data_str.push_back("1"); OlapTuple tuple1(data_str); res = _data_row_cursor.from_tuple(tuple1); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_TRUE(_delete_handler.is_filter_data(1, _data_row_cursor)); // 构造一行测试数据 data_str[1] = "4"; OlapTuple tuple2(data_str); res = _data_row_cursor.from_tuple(tuple2); ASSERT_EQ(OLAP_SUCCESS, res); // 不满足子条件:k2!=4 ASSERT_FALSE(_delete_handler.is_filter_data(1, _data_row_cursor)); _delete_handler.finalize(); } // 测试多个过滤条件之间是or关系, // 即如果存在多个过滤条件,会一次检查数据是否符合这些过滤条件;只要有一个过滤条件符合,则过滤数据 TEST_F(TestDeleteHandler, FilterDataConditions) { OLAPStatus res; DeleteConditionHandler cond_handler; std::vector conditions; // 往Header中添加过滤条件 // 过滤条件1 TCondition condition; condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = "!="; condition.condition_values.clear(); condition.condition_values.push_back("4"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(3)); // 过滤条件2 conditions.clear(); condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("3"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 4, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(4)); // 过滤条件3 conditions.clear(); condition.column_name = "k2"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("5"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 5, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(5)); // 指定版本号为10以载入Header中的所有三条过滤条件 _delete_handler.init(_olap_table, 10); vector data_str; data_str.push_back("4"); data_str.push_back("5"); data_str.push_back("8"); data_str.push_back("-1"); data_str.push_back("16"); data_str.push_back("1.2"); data_str.push_back("2014-01-01"); data_str.push_back("2014-01-01 00:00:00"); data_str.push_back("YWFH"); data_str.push_back("YWFH=="); data_str.push_back("1"); OlapTuple tuple(data_str); res = _data_row_cursor.from_tuple(tuple); ASSERT_EQ(OLAP_SUCCESS, res); // 这行数据会因为过滤条件3而被过滤 ASSERT_TRUE(_delete_handler.is_filter_data(1, _data_row_cursor)); _delete_handler.finalize(); } // 测试在过滤时,版本号小于数据版本的过滤条件将不起作用 TEST_F(TestDeleteHandler, FilterDataVersion) { OLAPStatus res; DeleteConditionHandler cond_handler; std::vector conditions; // 往Header中添加过滤条件 // 过滤条件1 TCondition condition; condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("1"); conditions.push_back(condition); condition.column_name = "k2"; condition.condition_op = "!="; condition.condition_values.clear(); condition.condition_values.push_back("4"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 3, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(3)); // 过滤条件2 conditions.clear(); condition.column_name = "k1"; condition.condition_op = "="; condition.condition_values.clear(); condition.condition_values.push_back("3"); conditions.push_back(condition); res = cond_handler.store_cond(_olap_table, 4, conditions); ASSERT_EQ(OLAP_SUCCESS, res); ASSERT_EQ(OLAP_SUCCESS, push_empty_delta(4)); // 指定版本号为10以载入Header中的所有过滤条件(过滤条件1,过滤条件2) _delete_handler.init(_olap_table, 10); // 构造一行测试数据 vector data_str; data_str.push_back("1"); data_str.push_back("6"); data_str.push_back("8"); data_str.push_back("-1"); data_str.push_back("16"); data_str.push_back("1.2"); data_str.push_back("2014-01-01"); data_str.push_back("2014-01-01 00:00:00"); data_str.push_back("YWFH"); data_str.push_back("YWFH=="); data_str.push_back("1"); OlapTuple tuple(data_str); res = _data_row_cursor.from_tuple(tuple); ASSERT_EQ(OLAP_SUCCESS, res); // 如果数据版本小于6,则过滤条件1生效,这条数据被过滤 ASSERT_TRUE(_delete_handler.is_filter_data(1, _data_row_cursor)); // 如果数据版本大于6,则过滤条件1会被跳过 ASSERT_FALSE(_delete_handler.is_filter_data(4, _data_row_cursor)); _delete_handler.finalize(); } } // namespace doris int main(int argc, char** argv) { std::string conffile = std::string(getenv("DORIS_HOME")) + "/conf/be.conf"; if (!doris::config::init(conffile.c_str(), false)) { fprintf(stderr, "error read config file. \n"); return -1; } doris::init_glog("be-test"); int ret = doris::OLAP_SUCCESS; testing::InitGoogleTest(&argc, argv); doris::set_up(); ret = RUN_ALL_TESTS(); doris::tear_down(); google::protobuf::ShutdownProtobufLibrary(); return ret; }