Files
doris/be/test/olap/command_executor_test.cpp
李超勇 6486be64c3 fix license statement (#29)
* change picture to word

* change picture to word

* SHOW FULL TABLES WHERE Table_type != VIEW sql can not execute

* change license description
2017-08-18 19:16:23 +08:00

1849 lines
67 KiB
C++

// Copyright (c) 2017, Baidu.com, Inc. All Rights Reserved
// 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.
#include <stdlib.h>
#include <sys/file.h>
#include <unistd.h>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/filesystem.hpp>
#include <gtest/gtest.h>
#include "olap/command_executor.h"
#include "olap/field.h"
#include "olap/olap_engine.h"
#include "olap/olap_main.cpp"
#include "olap/olap_table.h"
#include "olap/utils.h"
#include "util/logging.h"
using std::nothrow;
using std::stringstream;
namespace palo {
// SQL for generate BASE_TABLE_PUSH_DATA & BASE_TABLE_PUSH_DATA_BIG & ROLLUP_TABLE_PUSH_DATA:
//
// create table delete_test_row (k1 tinyint, k2 bigint, k3 char(64),
// k6 DECIMAL, v bigint sum) engine=olap distributed by
// random buckets 1 properties ("storage_type" = "row", "short_key" = "2");
//
// alter table delete_test_row add rollup delete_test_row_rollup(k1, k3, v);
//
// load label label1 (data infile
// ("hdfs://host:port/dir")
// into table `delete_test_row` (k1,k2,v,k3,k4,k5,k6));
//
// load label label2 (data infile
// ("hdfs://host:port/dir")
// into table `delete_test_row` (k1,k2,v,k3,k4,k5,k6));
static const int64_t BASE_TABLE_PUSH_DATA_ROW_COUNT = 100;
static const char* BASE_TABLE_PUSH_DATA = "./be/test/olap/test_data/all_types_100";
static const int64_t BASE_TABLE_PUSH_DATA_BIG_ROW_COUNT = 100000;
static const char* BASE_TABLE_PUSH_DATA_BIG = "./be/test/olap/test_data/all_types_100000";
static const int64_t ROLLUP_TABLE_PUSH_DATA_ROW_COUNT = 100;
static const char* ROLLUP_TABLE_PUSH_DATA = "./be/test/olap/test_data/all_types_100_rollup";
// checksum for base table push data
static const uint32_t MAX_RETRY_TIMES = 10;
static const uint32_t BASE_TABLE_PUSH_DATA_CHECKSUM = 3878734322;
static const uint32_t MAX_PATH_LEN = 1024;
void set_up() {
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_test";
system("rm -rf ./test_run && mkdir -p ./test_run");
create_dir(config::storage_root_path);
touch_all_singleton();
}
void tear_down() {
system("rm -rf ./test_run");
remove_all_dir(string(getenv("PALO_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::ROW;
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::BIGINT;
request->tablet_schema.columns.push_back(k2);
TColumn k3;
k3.column_name = "k3";
k3.__set_is_key(true);
k3.column_type.type = TPrimitiveType::CHAR;
k3.column_type.__set_len(64);
request->tablet_schema.columns.push_back(k3);
TColumn k6;
k6.column_name = "k6";
k6.__set_is_key(true);
k6.column_type.type = TPrimitiveType::DECIMAL;
k6.column_type.__set_precision(6);
k6.column_type.__set_scale(3);
request->tablet_schema.columns.push_back(k6);
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_bloom_filter_create_tablet_request(TCreateTabletReq* request) {
request->tablet_id = 10004;
request->__set_version(1);
request->__set_version_hash(0);
request->tablet_schema.schema_hash = 270076533;
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::BIGINT;
request->tablet_schema.columns.push_back(k2);
TColumn k3;
k3.column_name = "k3";
k3.__set_is_key(true);
k3.column_type.type = TPrimitiveType::CHAR;
k3.column_type.__set_len(64);
request->tablet_schema.columns.push_back(k3);
TColumn k6;
k6.column_name = "k6";
k6.__set_is_key(true);
k6.column_type.type = TPrimitiveType::DECIMAL;
k6.column_type.__set_precision(6);
k6.column_type.__set_scale(3);
request->tablet_schema.columns.push_back(k6);
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(const TCreateTabletReq& request, TPushReq* push_request) {
push_request->tablet_id = request.tablet_id;
push_request->schema_hash = request.tablet_schema.schema_hash;
push_request->__set_version(request.version + 1);
push_request->__set_version_hash(request.version_hash + 1);
push_request->timeout = 86400;
push_request->push_type = TPushType::LOAD;
push_request->__set_http_file_path(BASE_TABLE_PUSH_DATA);
}
void set_alter_tablet_request(const TCreateTabletReq& base_tablet, TAlterTabletReq* request) {
request->base_tablet_id = base_tablet.tablet_id;
request->base_schema_hash = base_tablet.tablet_schema.schema_hash;
}
class TestCreateTable : public ::testing::Test {
public:
TestCreateTable() : _command_executor(NULL) {}
~TestCreateTable() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_create_table";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestCreateTable, create_tablet) {
OLAPStatus res = OLAP_SUCCESS;
// 1. Create table with error param.
TCreateTabletReq request;
set_default_create_tablet_request(&request);
request.tablet_schema.short_key_column_count = 5;
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_ERR_CE_CMD_PARAMS_ERROR, res);
// 2. Create table normally.
request.tablet_schema.short_key_column_count = 2;
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
// check create table result
SmartOLAPTable tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
ASSERT_EQ(0, access(tablet->header_file_name().c_str(), F_OK));
Version base_version(0, request.version);
string index_name = tablet->construct_index_file_path(base_version, request.version_hash, 0);
string data_name = tablet->construct_data_file_path(base_version, request.version_hash, 0);
ASSERT_EQ(0, access(index_name.c_str(), F_OK));
ASSERT_EQ(0, access(data_name.c_str(), F_OK));
Version delta_version(request.version + 1, request.version + 1);
index_name = tablet->construct_index_file_path(delta_version, 0, 0);
data_name = tablet->construct_data_file_path(delta_version, 0, 0);
ASSERT_EQ(0, access(index_name.c_str(), F_OK));
ASSERT_EQ(0, access(data_name.c_str(), F_OK));
// 3. Create table already existed.
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
// 4. Create table with different schema_hash.
request.tablet_schema.schema_hash = 0;
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_ERR_CE_TABLET_ID_EXIST, res);
}
TEST_F(TestCreateTable, column_create_tablet) {
OLAPStatus res = OLAP_SUCCESS;
TCreateTabletReq request;
set_default_create_tablet_request(&request);
request.tablet_id += 1;
request.tablet_schema.schema_hash += 1;
request.tablet_schema.storage_type = TStorageType::COLUMN;
res = _command_executor->create_table(request);
// check create table result
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
ASSERT_EQ(0, access(tablet->header_file_name().c_str(), F_OK));
Version base_version(0, request.version);
string index_name = tablet->construct_index_file_path(base_version, request.version_hash, 0);
string data_name = tablet->construct_data_file_path(base_version, request.version_hash, 0);
ASSERT_EQ(0, access(index_name.c_str(), F_OK));
ASSERT_EQ(0, access(data_name.c_str(), F_OK));
Version delta_version(request.version + 1, request.version + 1);
index_name = tablet->construct_index_file_path(delta_version, 0, 0);
data_name = tablet->construct_data_file_path(delta_version, 0, 0);
ASSERT_EQ(0, access(index_name.c_str(), F_OK));
ASSERT_EQ(0, access(data_name.c_str(), F_OK));
}
class TestGetTable : public ::testing::Test {
public:
TestGetTable() : _command_executor(NULL) {}
~TestGetTable() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_get_table";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestGetTable, get_table) {
SmartOLAPTable tablet;
OLAPStatus res = OLAP_SUCCESS;
TCreateTabletReq request;
set_default_create_tablet_request(&request);
// 1. Get table not existed.
tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() == NULL);
// 2. Get table normally.
// create table first
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
// get table
tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
}
class TestDropTable : public ::testing::Test {
public:
TestDropTable() : _command_executor(NULL) {}
~TestDropTable() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_drop_table";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestDropTable, drop_table) {
SmartOLAPTable tablet;
OLAPStatus res = OLAP_SUCCESS;
TCreateTabletReq request;
set_default_create_tablet_request(&request);
TDropTabletReq drop_request;
drop_request.tablet_id = request.tablet_id;
drop_request.schema_hash = request.tablet_schema.schema_hash;
// 1. Drop table not existed.
res = _command_executor->drop_table(drop_request);
ASSERT_EQ(OLAP_SUCCESS, res);
double usage = -1;
ASSERT_EQ(OLAPEngine::get_instance()->start_trash_sweep(&usage), OLAP_SUCCESS);
// 2. Drop table normally.
// create table first
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
res = _command_executor->drop_table(drop_request);
ASSERT_EQ(OLAP_SUCCESS, res);
// 3. Clear trash
// check dropped table exist after trash scan
std::set<std::string> dirs;
ASSERT_EQ(OLAPEngine::get_instance()->start_trash_sweep(&usage), OLAP_SUCCESS);
dir_walk(config::storage_root_path + TRASH_PREFIX, &dirs, nullptr);
OLAP_LOG_INFO("max disk usage is: %f", usage);
const double guard_usage = config::disk_capacity_insufficient_percentage / 100.0;
ASSERT_TRUE(usage > guard_usage ? dirs.empty() : !dirs.empty());
// check dirs really removed after timeout
config::trash_file_expire_time_sec = 1;
sleep(2); // wait for timeout
ASSERT_EQ(OLAPEngine::get_instance()->start_trash_sweep(&usage), OLAP_SUCCESS);
ASSERT_TRUE(0 <= usage && usage <= 100);
dirs.clear();
dir_walk(config::storage_root_path + TRASH_PREFIX, &dirs, nullptr);
ASSERT_TRUE(dirs.empty());
}
class TestReportTablet : public ::testing::Test {
public:
TestReportTablet() : _command_executor(NULL) {}
~TestReportTablet() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_report";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestReportTablet, report_tablet_info) {
OLAPStatus res = OLAP_SUCCESS;
TCreateTabletReq request;
set_default_create_tablet_request(&request);
TTabletInfo tablet_info;
tablet_info.tablet_id = request.tablet_id;
tablet_info.schema_hash = request.tablet_schema.schema_hash;
// 1. Report tablet info not existed.
res = _command_executor->report_tablet_info(&tablet_info);
ASSERT_EQ(OLAP_ERR_TABLE_NOT_FOUND, res);
// 2. Report tablet info normally.
// create tablet first
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
// report tablet info and check.
res = _command_executor->report_tablet_info(&tablet_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(request.version + 1, tablet_info.version);
ASSERT_EQ(request.version_hash, tablet_info.version_hash);
ASSERT_EQ(0, tablet_info.row_count);
}
class TestReportAllTablets : public ::testing::Test {
public:
TestReportAllTablets() : _command_executor(NULL) {}
~TestReportAllTablets() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_report_all";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestReportAllTablets, report_all_tablets_info) {
OLAPStatus res = OLAP_SUCCESS;
std::map<TTabletId, TTablet> tablets_info;
// 1. Report empty tablet.
tablets_info.clear();
res = _command_executor->report_all_tablets_info(&tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(0, tablets_info.size());
// 2. Report one tablets.
// create default tablet.
TCreateTabletReq request;
set_default_create_tablet_request(&request);
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
tablets_info.clear();
res = _command_executor->report_all_tablets_info(&tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
ASSERT_EQ(1, tablets_info[request.tablet_id].tablet_infos.size());
ASSERT_EQ(request.tablet_id, tablets_info[request.tablet_id].tablet_infos[0].tablet_id);
// 3. Report two tablets.
// create another tablet.
request.tablet_id = request.tablet_id + 1;
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
tablets_info.clear();
res = _command_executor->report_all_tablets_info(&tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(2, tablets_info.size());
ASSERT_EQ(1, tablets_info[request.tablet_id].tablet_infos.size());
ASSERT_EQ(request.tablet_id, tablets_info[request.tablet_id].tablet_infos[0].tablet_id);
}
class TestReloadRootPath : public ::testing::Test {
public:
TestReloadRootPath() : _command_executor(NULL) {}
~TestReloadRootPath() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_reload";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestReloadRootPath, reload_root_path) {
string root_path;
OLAPStatus res = OLAP_SUCCESS;
// create table in current root path
TCreateTabletReq request;
set_default_create_tablet_request(&request);
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
// 1. Reload empty root path
root_path = ";";
res = _command_executor->reload_root_path(root_path);
ASSERT_EQ(OLAP_ERR_INPUT_PARAMETER_ERROR, res);
// 2. Reload new root path not existed
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
root_path = string(buffer) + "/test_run/data_reload_new";
res = _command_executor->reload_root_path(root_path);
ASSERT_EQ(OLAP_ERR_INPUT_PARAMETER_ERROR, res);
tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
// 3. Reload new root path normally
remove_all_dir(root_path);
ASSERT_EQ(create_dir(root_path), OLAP_SUCCESS);
res = _command_executor->reload_root_path(root_path);
ASSERT_EQ(OLAP_SUCCESS, res);
tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() == NULL);
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
// 3. Reload same root path
res = _command_executor->reload_root_path(root_path);
ASSERT_EQ(OLAP_SUCCESS, res);
tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(root_path));
}
class TestGetRootPathStat : public ::testing::Test {
public:
TestGetRootPathStat() : _command_executor(NULL) {}
~TestGetRootPathStat() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_root_path_stat";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestGetRootPathStat, get_all_root_path_stat) {
OLAPStatus res = OLAP_SUCCESS;
std::vector<OLAPRootPathStat> root_paths_stat;
res = _command_executor->get_all_root_path_stat(&root_paths_stat);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, root_paths_stat.size());
EXPECT_STREQ(config::storage_root_path.c_str(), root_paths_stat[0].root_path.c_str());
}
class TestPush : public ::testing::Test {
public:
TestPush() : _command_executor(NULL) {}
~TestPush() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_push";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestPush, push) {
OLAPStatus res = OLAP_SUCCESS;
TCreateTabletReq request;
set_default_create_tablet_request(&request);
TPushReq push_req;
set_default_push_request(request, &push_req);
std::vector<TTabletInfo> tablets_info;
// 1. Push before tablet created.
tablets_info.clear();
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_ERR_TABLE_NOT_FOUND, res);
ASSERT_EQ(0, tablets_info.size());
// create tablet first
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
// 2. Push with wrong version.
push_req.version = 0;
tablets_info.clear();
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_ERR_PUSH_VERSION_INCORRECT, res);
ASSERT_EQ(0, tablets_info.size());
// 3. Push next version normally.
push_req.version = request.version + 1;
tablets_info.clear();
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
ASSERT_EQ(push_req.tablet_id, tablets_info[0].tablet_id);
ASSERT_EQ(push_req.schema_hash, tablets_info[0].schema_hash);
ASSERT_EQ(push_req.version, tablets_info[0].version);
ASSERT_EQ(push_req.version_hash, tablets_info[0].version_hash);
ASSERT_EQ(BASE_TABLE_PUSH_DATA_ROW_COUNT, tablets_info[0].row_count);
// 4. Push the same batch.
tablets_info.clear();
int64_t row_count = BASE_TABLE_PUSH_DATA_ROW_COUNT;
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
ASSERT_EQ(push_req.tablet_id, tablets_info[0].tablet_id);
ASSERT_EQ(push_req.schema_hash, tablets_info[0].schema_hash);
ASSERT_EQ(push_req.version, tablets_info[0].version);
ASSERT_EQ(push_req.version_hash, tablets_info[0].version_hash);
ASSERT_EQ(row_count, tablets_info[0].row_count);
// 5. Push the next batch.
push_req.version += 1;
push_req.version_hash += 1;
tablets_info.clear();
row_count += BASE_TABLE_PUSH_DATA_ROW_COUNT;
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
ASSERT_EQ(push_req.tablet_id, tablets_info[0].tablet_id);
ASSERT_EQ(push_req.schema_hash, tablets_info[0].schema_hash);
ASSERT_EQ(push_req.version, tablets_info[0].version);
ASSERT_EQ(push_req.version_hash, tablets_info[0].version_hash);
ASSERT_EQ(row_count, tablets_info[0].row_count);
}
TEST_F(TestPush, column_push) {
OLAPStatus res = OLAP_SUCCESS;
TCreateTabletReq request;
set_default_create_tablet_request(&request);
std::vector<TTabletInfo> tablets_info;
// create tablet first
request.tablet_id += 1;
request.tablet_schema.schema_hash += 1;
request.tablet_schema.storage_type = TStorageType::COLUMN;
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
tablets_info.clear();
TPushReq push_req;
set_default_push_request(request, &push_req);
push_req.tablet_id = request.tablet_id;
push_req.schema_hash = request.tablet_schema.schema_hash;
push_req.__set_http_file_path(BASE_TABLE_PUSH_DATA_BIG);
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
ASSERT_EQ(push_req.tablet_id, tablets_info[0].tablet_id);
ASSERT_EQ(push_req.schema_hash, tablets_info[0].schema_hash);
ASSERT_EQ(push_req.version, tablets_info[0].version);
ASSERT_EQ(push_req.version_hash, tablets_info[0].version_hash);
ASSERT_EQ(BASE_TABLE_PUSH_DATA_BIG_ROW_COUNT, tablets_info[0].row_count);
}
class TestComputeChecksum : public ::testing::Test {
public:
TestComputeChecksum() : _command_executor(NULL) {}
~TestComputeChecksum() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_compute_checksum";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestComputeChecksum, compute_checksum) {
uint32_t checksum = 0;
OLAPStatus res = OLAP_SUCCESS;
TCreateTabletReq request;
set_default_create_tablet_request(&request);
TPushReq push_req;
set_default_push_request(request, &push_req);
std::vector<TTabletInfo> tablets_info;
// 1. Compute checksum before tablet created.
res = _command_executor->compute_checksum(
request.tablet_id, request.tablet_schema.schema_hash,
request.version, request.version_hash, &checksum);
ASSERT_EQ(OLAP_ERR_TABLE_NOT_FOUND, res);
// 2. Compute checksum for empty tablet.
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
res = _command_executor->compute_checksum(
request.tablet_id, request.tablet_schema.schema_hash,
request.version, request.version_hash, &checksum);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(CRC32_INIT, checksum);
// 3. Compute checksum normally.
tablets_info.clear();
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
res = _command_executor->compute_checksum(
push_req.tablet_id, push_req.schema_hash,
push_req.version, push_req.version_hash, &checksum);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(BASE_TABLE_PUSH_DATA_CHECKSUM, checksum);
}
class TestBaseExpansion : public ::testing::Test {
public:
TestBaseExpansion() : _command_executor(NULL) {}
~TestBaseExpansion() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_base_expansion";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestBaseExpansion, TestBaseExpansion) {
OLAPStatus res = OLAP_SUCCESS;
TCreateTabletReq request;
set_default_create_tablet_request(&request);
TPushReq push_req;
set_default_push_request(request, &push_req);
std::vector<TTabletInfo> tablets_info;
// 1. Start BE before tablet created.
res = _command_executor->base_expansion(
push_req.tablet_id, push_req.schema_hash, push_req.version);
ASSERT_EQ(OLAP_ERR_TABLE_NOT_FOUND, res);
// 2. Start BE for error new base version.
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
res = _command_executor->base_expansion(
request.tablet_id, request.tablet_schema.schema_hash, request.version + 1);
ASSERT_EQ(OLAP_ERR_BE_NO_SUITABLE_VERSION, res);
}
// ######################### ALTER TABLE TEST BEGIN #########################
void set_create_tablet_request_1(const TCreateTabletReq& base_request, TCreateTabletReq* request) {
//sorting schema change
request->tablet_id = base_request.tablet_id + 1;
request->__set_version(base_request.version);
request->__set_version_hash(base_request.version_hash);
request->tablet_schema.schema_hash = base_request.tablet_schema.schema_hash + 1;
request->tablet_schema.short_key_column_count = 2;
request->tablet_schema.storage_type = TStorageType::ROW;
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[0]);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[2]);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[4]);
}
void set_create_tablet_request_2(const TCreateTabletReq& base_request, TCreateTabletReq* request) {
//directly schema change
request->tablet_id = base_request.tablet_id + 2;
request->__set_version(base_request.version);
request->__set_version_hash(base_request.version_hash);
request->tablet_schema.schema_hash = base_request.tablet_schema.schema_hash + 2;
request->tablet_schema.short_key_column_count = 1;
request->tablet_schema.storage_type = TStorageType::COLUMN;
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[0]);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[4]);
}
void set_create_tablet_request_3(const TCreateTabletReq& base_request, TCreateTabletReq* request) {
//linked schema change, add a value column
request->tablet_id = base_request.tablet_id + 3;
request->__set_version(base_request.version);
request->__set_version_hash(base_request.version_hash);
request->tablet_schema.schema_hash = base_request.tablet_schema.schema_hash + 3;
request->tablet_schema.short_key_column_count = 1;
request->tablet_schema.storage_type = TStorageType::COLUMN;
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[0]);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[4]);
TColumn v2;
v2.column_name = "v2";
v2.column_type.type = TPrimitiveType::BIGINT;
v2.__set_is_key(false);
v2.__set_default_value("0");
v2.__set_aggregation_type(TAggregationType::SUM);
request->tablet_schema.columns.push_back(v2);
}
void set_create_tablet_request_4(const TCreateTabletReq& base_request, TCreateTabletReq* request) {
//directly schema change, modify a key column type
request->tablet_id = base_request.tablet_id + 4;
request->__set_version(base_request.version);
request->__set_version_hash(base_request.version_hash);
request->tablet_schema.schema_hash = base_request.tablet_schema.schema_hash + 1;
request->tablet_schema.short_key_column_count = 1;
request->tablet_schema.storage_type = TStorageType::COLUMN;
TColumn k1;
k1.column_name = "k1";
k1.__set_is_key(true);
k1.column_type.type = TPrimitiveType::LARGEINT;
request->tablet_schema.columns.push_back(k1);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[1]);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[2]);
}
void set_create_tablet_request_bloom_filter(
const TCreateTabletReq& base_request, TCreateTabletReq* request) {
//sorting schema change
request->tablet_id = base_request.tablet_id + 5;
request->__set_version(base_request.version);
request->__set_version_hash(base_request.version_hash);
request->tablet_schema.schema_hash = base_request.tablet_schema.schema_hash + 1;
request->tablet_schema.short_key_column_count = 4;
request->tablet_schema.storage_type = TStorageType::COLUMN;
TColumn k3;
k3.column_name = "k3";
k3.__set_is_key(true);
k3.column_type.type = TPrimitiveType::CHAR;
k3.column_type.__set_len(64);
k3.is_bloom_filter_column = true;
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[0]);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[1]);
request->tablet_schema.columns.push_back(k3);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[3]);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[4]);
}
void set_create_tablet_request_char_to_varchar(
const TCreateTabletReq& base_request, TCreateTabletReq* request) {
//sorting schema change
request->tablet_id = base_request.tablet_id + 6;
request->__set_version(base_request.version);
request->__set_version_hash(base_request.version_hash);
request->tablet_schema.schema_hash = base_request.tablet_schema.schema_hash + 1;
request->tablet_schema.short_key_column_count = 4;
request->tablet_schema.storage_type = TStorageType::COLUMN;
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[0]);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[1]);
TColumn k3;
k3.column_name = "k3";
k3.__set_is_key(true);
k3.column_type.type = TPrimitiveType::VARCHAR;
k3.column_type.__set_len(128);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[2]);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[3]);
request->tablet_schema.columns.push_back(base_request.tablet_schema.columns[4]);
}
AlterTableStatus show_alter_table_status(
CommandExecutor* command_executor,
const TAlterTabletReq& request) {
AlterTableStatus status = ALTER_TABLE_RUNNING;
uint32_t max_retry = MAX_RETRY_TIMES;
while (max_retry > 0) {
status = command_executor->show_alter_table_status(
request.base_tablet_id, request.base_schema_hash);
if (status != ALTER_TABLE_RUNNING) {
break;
}
OLAP_LOG_INFO("doing alter table......");
--max_retry;
sleep(1);
}
return status;
}
class TestSchemaChange : public ::testing::Test {
public:
TestSchemaChange() : _command_executor(NULL) {}
~TestSchemaChange() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_schema_change";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestSchemaChange, tablet_schema_change_abnormal) {
OLAPStatus res = OLAP_SUCCESS;
// check not existed tablet id
TCreateTabletReq create_base_tablet;
set_default_create_tablet_request(&create_base_tablet);
TCreateTabletReq create_new_tablet;
set_create_tablet_request_1(create_base_tablet, &create_new_tablet);
TAlterTabletReq request;
set_alter_tablet_request(create_base_tablet, &request);
request.__set_new_tablet_req(create_new_tablet);
res = _command_executor->schema_change(request);
ASSERT_EQ(OLAP_ERR_TRY_LOCK_FAILED, res);
AlterTableStatus status = _command_executor->show_alter_table_status(
request.base_tablet_id, request.base_schema_hash);
ASSERT_EQ(ALTER_TABLE_FAILED, status);
}
TEST_F(TestSchemaChange, schema_change_bloom_filter) {
OLAPStatus res = OLAP_SUCCESS;
TCreateTabletReq create_base_tablet;
set_bloom_filter_create_tablet_request(&create_base_tablet);
res = _command_executor->create_table(create_base_tablet);
ASSERT_EQ(OLAP_SUCCESS, res);
TCreateTabletReq create_new_tablet;
set_create_tablet_request_bloom_filter(create_base_tablet, &create_new_tablet);
TAlterTabletReq request;
set_alter_tablet_request(create_base_tablet, &request);
request.__set_new_tablet_req(create_new_tablet);
res = _command_executor->schema_change(request);
ASSERT_EQ(OLAP_SUCCESS, res);
AlterTableStatus status = ALTER_TABLE_WAITING;
status = show_alter_table_status(_command_executor, request);
ASSERT_EQ(ALTER_TABLE_DONE, status);
res = OLAPEngine::get_instance()->drop_table(
request.base_tablet_id, request.base_schema_hash);
ASSERT_EQ(OLAP_SUCCESS, res);
}
TEST_F(TestSchemaChange, schema_change_char_to_varchar) {
OLAPStatus res = OLAP_SUCCESS;
AlterTableStatus status = ALTER_TABLE_WAITING;
// 1. Prepare for schema change.
// create base tablet
TCreateTabletReq create_base_tablet;
set_default_create_tablet_request(&create_base_tablet);
res = _command_executor->create_table(create_base_tablet);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
create_base_tablet.tablet_id, create_base_tablet.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
// push data
TPushReq push_req;
set_default_push_request(create_base_tablet, &push_req);
std::vector<TTabletInfo> tablets_info;
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
// set schema change request
TCreateTabletReq create_new_tablet;
set_create_tablet_request_char_to_varchar(create_base_tablet, &create_new_tablet);
TAlterTabletReq request;
set_alter_tablet_request(create_base_tablet, &request);
request.__set_new_tablet_req(create_new_tablet);
// 2. Submit schema change.
request.base_schema_hash = create_base_tablet.tablet_schema.schema_hash;
res = _command_executor->schema_change(request);
ASSERT_EQ(OLAP_SUCCESS, res);
// 3. Verify schema change result.
// show schema change status
status = show_alter_table_status(_command_executor, request);
ASSERT_EQ(ALTER_TABLE_DONE, status);
// check new tablet information
TTabletInfo tablet_info;
tablet_info.tablet_id = create_new_tablet.tablet_id;
tablet_info.schema_hash = create_new_tablet.tablet_schema.schema_hash;
res = _command_executor->report_tablet_info(&tablet_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(push_req.version, tablet_info.version);
ASSERT_EQ(push_req.version_hash, tablet_info.version_hash);
ASSERT_EQ(BASE_TABLE_PUSH_DATA_ROW_COUNT, tablet_info.row_count);
// 4. Retry the same schema change request.
res = _command_executor->schema_change(request);
ASSERT_EQ(OLAP_SUCCESS, res);
status = _command_executor->show_alter_table_status(
request.base_tablet_id, request.base_schema_hash);
ASSERT_EQ(ALTER_TABLE_DONE, status);
// 5. Do schema change continuously.
res = OLAPEngine::get_instance()->drop_table(
request.base_tablet_id, request.base_schema_hash);
ASSERT_EQ(OLAP_SUCCESS, res);
}
TEST_F(TestSchemaChange, schema_change) {
OLAPStatus res = OLAP_SUCCESS;
AlterTableStatus status = ALTER_TABLE_WAITING;
// 1. Prepare for schema change.
// create base tablet
TCreateTabletReq create_base_tablet;
set_default_create_tablet_request(&create_base_tablet);
res = _command_executor->create_table(create_base_tablet);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
create_base_tablet.tablet_id, create_base_tablet.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
// push data
TPushReq push_req;
set_default_push_request(create_base_tablet, &push_req);
std::vector<TTabletInfo> tablets_info;
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
// set schema change request
TCreateTabletReq create_new_tablet;
set_create_tablet_request_1(create_base_tablet, &create_new_tablet);
TAlterTabletReq request;
set_alter_tablet_request(create_base_tablet, &request);
request.__set_new_tablet_req(create_new_tablet);
// check schema change for non_existed tablet
request.base_schema_hash = 0;
res = _command_executor->schema_change(request);
ASSERT_EQ(OLAP_ERR_TABLE_NOT_FOUND, res);
// 2. Submit schema change.
request.base_schema_hash = create_base_tablet.tablet_schema.schema_hash;
res = _command_executor->schema_change(request);
ASSERT_EQ(OLAP_SUCCESS, res);
// 3. Verify schema change result.
// show schema change status
status = show_alter_table_status(_command_executor, request);
ASSERT_EQ(ALTER_TABLE_DONE, status);
// check new tablet information
TTabletInfo tablet_info;
tablet_info.tablet_id = create_new_tablet.tablet_id;
tablet_info.schema_hash = create_new_tablet.tablet_schema.schema_hash;
res = _command_executor->report_tablet_info(&tablet_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(push_req.version, tablet_info.version);
ASSERT_EQ(push_req.version_hash, tablet_info.version_hash);
ASSERT_EQ(BASE_TABLE_PUSH_DATA_ROW_COUNT, tablet_info.row_count);
// 4. Retry the same schema change request.
res = _command_executor->schema_change(request);
ASSERT_EQ(OLAP_SUCCESS, res);
status = _command_executor->show_alter_table_status(
request.base_tablet_id, request.base_schema_hash);
ASSERT_EQ(ALTER_TABLE_DONE, status);
// 5. Do schema change continuously.
res = OLAPEngine::get_instance()->drop_table(
request.base_tablet_id, request.base_schema_hash);
ASSERT_EQ(OLAP_SUCCESS, res);
TCreateTabletReq create_new_new_tablet;
set_create_tablet_request_2(create_base_tablet, &create_new_new_tablet);
TAlterTabletReq new_request;
set_alter_tablet_request(create_new_tablet, &new_request);
new_request.__set_new_tablet_req(create_new_new_tablet);
res = _command_executor->schema_change(new_request);
ASSERT_EQ(OLAP_SUCCESS, res);
// show alter table status
status = show_alter_table_status(_command_executor, new_request);
ASSERT_EQ(ALTER_TABLE_DONE, status);
res = OLAPEngine::get_instance()->drop_table(
new_request.base_tablet_id, new_request.base_schema_hash);
// check new tablet information
tablet_info.tablet_id = create_new_new_tablet.tablet_id;
tablet_info.schema_hash = create_new_new_tablet.tablet_schema.schema_hash;
res = _command_executor->report_tablet_info(&tablet_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(push_req.version, tablet_info.version);
ASSERT_EQ(push_req.version_hash, tablet_info.version_hash);
ASSERT_EQ(100, tablet_info.row_count);
//schema change, add a value column
TCreateTabletReq create_new_tablet3;
set_create_tablet_request_3(create_base_tablet, &create_new_tablet3);
TAlterTabletReq request3;
set_alter_tablet_request(create_new_new_tablet, &request3);
request3.__set_new_tablet_req(create_new_tablet3);
res = _command_executor->schema_change(request3);
ASSERT_EQ(OLAP_SUCCESS, res);
// show alter table status
status = show_alter_table_status(_command_executor, request3);
ASSERT_EQ(ALTER_TABLE_DONE, status);
res = OLAPEngine::get_instance()->drop_table(
request3.base_tablet_id, request3.base_schema_hash);
// check new tablet information
tablet_info.tablet_id = create_new_tablet3.tablet_id;
tablet_info.schema_hash = create_new_tablet3.tablet_schema.schema_hash;
res = _command_executor->report_tablet_info(&tablet_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(push_req.version, tablet_info.version);
ASSERT_EQ(push_req.version_hash, tablet_info.version_hash);
ASSERT_EQ(100, tablet_info.row_count);
//schema change, add a value column
TCreateTabletReq create_new_tablet4;
set_create_tablet_request_4(create_new_tablet3, &create_new_tablet4);
TAlterTabletReq request4;
set_alter_tablet_request(create_new_tablet3, &request4);
request4.__set_new_tablet_req(create_new_tablet4);
res = _command_executor->schema_change(request4);
ASSERT_EQ(OLAP_SUCCESS, res);
// show alter table status
status = show_alter_table_status(_command_executor, request4);
ASSERT_EQ(ALTER_TABLE_DONE, status);
res = OLAPEngine::get_instance()->drop_table(
request4.base_tablet_id, request4.base_schema_hash);
// check new tablet information
tablet_info.tablet_id = create_new_tablet4.tablet_id;
tablet_info.schema_hash = create_new_tablet4.tablet_schema.schema_hash;
res = _command_executor->report_tablet_info(&tablet_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(push_req.version, tablet_info.version);
ASSERT_EQ(push_req.version_hash, tablet_info.version_hash);
ASSERT_EQ(100, tablet_info.row_count);
}
class TestCreateRollupTable : public ::testing::Test {
public:
TestCreateRollupTable() : _command_executor(NULL) {}
~TestCreateRollupTable() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_create_rollup";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
}
void TearDown(){
// Remove all dir.
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
};
TEST_F(TestCreateRollupTable, create_rollup_table) {
OLAPStatus res = OLAP_SUCCESS;
AlterTableStatus status = ALTER_TABLE_WAITING;
// 1. Prepare for schema change.
// create base tablet
TCreateTabletReq create_base_tablet;
set_default_create_tablet_request(&create_base_tablet);
res = _command_executor->create_table(create_base_tablet);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
create_base_tablet.tablet_id, create_base_tablet.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
// push data
TPushReq push_req;
set_default_push_request(create_base_tablet, &push_req);
std::vector<TTabletInfo> tablets_info;
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
// set schema change request
TCreateTabletReq create_new_tablet;
set_create_tablet_request_1(create_base_tablet, &create_new_tablet);
TAlterTabletReq request;
set_alter_tablet_request(create_base_tablet, &request);
request.__set_new_tablet_req(create_new_tablet);
// 2. Submit schema change.
res = _command_executor->create_rollup_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
// 3. Verify schema change result.
// show schema change status
status = show_alter_table_status(_command_executor, request);
ASSERT_EQ(ALTER_TABLE_DONE, status);
// check new tablet information
int64_t rollup_row_count = BASE_TABLE_PUSH_DATA_ROW_COUNT;
TTabletInfo tablet_info;
tablet_info.tablet_id = create_new_tablet.tablet_id;
tablet_info.schema_hash = create_new_tablet.tablet_schema.schema_hash;
res = _command_executor->report_tablet_info(&tablet_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(push_req.version, tablet_info.version);
ASSERT_EQ(push_req.version_hash, tablet_info.version_hash);
ASSERT_EQ(BASE_TABLE_PUSH_DATA_ROW_COUNT, tablet_info.row_count);
// 4. Push base tablet.
tablets_info.clear();
push_req.version += 1;
push_req.version_hash += 1;
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(2, tablets_info.size());
ASSERT_TRUE(tablet->is_schema_changing() == true);
rollup_row_count += BASE_TABLE_PUSH_DATA_ROW_COUNT;
// 5. Push rollup tablet.
tablets_info.clear();
push_req.version += 1;
push_req.version_hash += 1;
push_req.tablet_id = create_new_tablet.tablet_id;
push_req.schema_hash = create_new_tablet.tablet_schema.schema_hash;
push_req.__set_http_file_path(ROLLUP_TABLE_PUSH_DATA);
res = _command_executor->push(push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
rollup_row_count += ROLLUP_TABLE_PUSH_DATA_ROW_COUNT;
ASSERT_EQ(rollup_row_count, tablets_info[0].row_count);
ASSERT_TRUE(tablet->is_schema_changing() == false);
}
// ######################### ALTER TABLE TEST END #########################
// ######################### ALTER CLONE BEGIN #########################
class TestClone : public ::testing::Test {
public:
TestClone() : _command_executor(NULL) {}
~TestClone() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_clone";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
// 1. Prepare for query split key.
// create base tablet
OLAPStatus res = OLAP_SUCCESS;
set_default_create_tablet_request(&_create_tablet);
res = _command_executor->create_table(_create_tablet);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
_create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
_header_file_name = tablet->header_file_name();
// push data
set_default_push_request(_create_tablet, &_push_req);
std::vector<TTabletInfo> tablets_info;
res = _command_executor->push(_push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
}
void TearDown(){
// Remove all dir.
OLAPEngine::get_instance()->drop_table(
_create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash);
ASSERT_EQ(access(_header_file_name.c_str(), F_OK), -1);
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
std::string _header_file_name;
TCreateTabletReq _create_tablet;
TPushReq _push_req;
};
TEST_F(TestClone, make_snapshot_abnormal) {
OLAPStatus res = OLAP_SUCCESS;
std::string snapshot_path;
// check tablet not existed
res = _command_executor->make_snapshot(0, 0, &snapshot_path);
ASSERT_EQ(OLAP_ERR_TABLE_NOT_FOUND, res);
// check tablet without delta
TCreateTabletReq request = _create_tablet;
request.tablet_id = 0;
request.__isset.version = false;
res = _command_executor->create_table(request);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
std::string header_file_name = tablet->header_file_name();
res = _command_executor->make_snapshot(
request.tablet_id, request.tablet_schema.schema_hash, &snapshot_path);
ASSERT_EQ(OLAP_ERR_VERSION_NOT_EXIST, res);
// clear
tablet.reset();
OLAPEngine::get_instance()->drop_table(
request.tablet_id, request.tablet_schema.schema_hash);
ASSERT_EQ(access(header_file_name.c_str(), F_OK), -1);
}
TEST_F(TestClone, make_snapshot) {
OLAPStatus res = OLAP_SUCCESS;
std::string snapshot_path;
res = _command_executor->make_snapshot(
_create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash, &snapshot_path);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(0, access(snapshot_path.c_str(), F_OK));
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(snapshot_path));
}
TEST_F(TestClone, release_snapshot_abnormal) {
std::string long_path = "/empty_storage_root/snapshot/path";
std::string short_path = "/s";
ASSERT_EQ(OLAP_ERR_CE_CMD_PARAMS_ERROR, _command_executor->release_snapshot(long_path));
ASSERT_EQ(OLAP_ERR_CE_CMD_PARAMS_ERROR, _command_executor->release_snapshot(short_path));
}
TEST_F(TestClone, release_snapshot) {
OLAPStatus res = OLAP_SUCCESS;
std::string snapshot_path;
res = _command_executor->make_snapshot(
_create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash, &snapshot_path);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(0, access(snapshot_path.c_str(), F_OK));
res = _command_executor->release_snapshot(snapshot_path);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(access(snapshot_path.c_str(), F_OK), -1);
}
TEST_F(TestClone, obtain_root_path_abnormal) {
OLAPStatus res = OLAP_SUCCESS;
std::string root_path;
OLAPRootPath::get_instance()->clear();
res = _command_executor->obtain_shard_path(TStorageMedium::HDD, &root_path);
ASSERT_EQ(OLAP_ERR_NO_AVAILABLE_ROOT_PATH, res);
OLAPRootPath::get_instance()->init();
}
TEST_F(TestClone, obtain_root_path) {
OLAPStatus res = OLAP_SUCCESS;
std::string root_path;
res = _command_executor->obtain_shard_path(TStorageMedium::HDD, &root_path);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(config::storage_root_path + DATA_PREFIX + "/0", root_path);
}
void set_clone_request(const TCreateTabletReq& create_tablet, TCloneReq* request) {
request->tablet_id = create_tablet.tablet_id;
request->schema_hash = create_tablet.tablet_schema.schema_hash;
}
TEST_F(TestClone, load_header_abnormal) {
OLAPStatus res = OLAP_SUCCESS;
std::string shard_path = config::storage_root_path + DATA_PREFIX + "/0";
TCloneReq request;
set_clone_request(_create_tablet, &request);
request.tablet_id = 0;
res = _command_executor->load_header(shard_path, request);
ASSERT_EQ(OLAP_ERR_FILE_NOT_EXIST, res);
request.tablet_id = _create_tablet.tablet_id;
res = _command_executor->load_header(shard_path, request);
ASSERT_EQ(OLAP_SUCCESS, res);
}
TEST_F(TestClone, load_header) {
OLAPStatus res = OLAP_SUCCESS;
std::string snapshot_path;
std::string root_path;
// 1. Make snapshot.
res = _command_executor->make_snapshot(
_create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash, &snapshot_path);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(0, access(snapshot_path.c_str(), F_OK));
// 2. Obtain root path.
res = _command_executor->obtain_shard_path(TStorageMedium::HDD, &root_path);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(config::storage_root_path + DATA_PREFIX + "/0", root_path);
// 3. Drop the old tablet and copy the snapshot to root_path.
// to avoid delete tablet has same name: .delete.schema_hash.datetime
OLAPEngine::get_instance()->drop_table(
_create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash);
ASSERT_EQ(access(_header_file_name.c_str(), F_OK), -1);
system(("rm -fr " + root_path + "/[^s]*").c_str());
system(("cp -r " + snapshot_path + "/* " + root_path).c_str());
// 4. Load header.
TCloneReq request;
set_clone_request(_create_tablet, &request);
res = _command_executor->load_header(root_path, request);
ASSERT_EQ(OLAP_SUCCESS, res);
// 5. Release snapshot.
res = _command_executor->release_snapshot(snapshot_path);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(access(snapshot_path.c_str(), F_OK), -1);
}
// ######################### ALTER CLONE END #########################
class TestDeleteData : public ::testing::Test {
public:
TestDeleteData() : _command_executor(NULL) {}
~TestDeleteData() {
SAFE_DELETE(_command_executor);
}
void SetUp() {
// Create local data dir for OLAPEngine.
char buffer[MAX_PATH_LEN];
getcwd(buffer, MAX_PATH_LEN);
config::storage_root_path = string(buffer) + "/test_run/data_delete_data";
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());
_command_executor = new(nothrow) CommandExecutor();
ASSERT_TRUE(_command_executor != NULL);
// 1. Prepare for query split key.
// create base tablet
OLAPStatus res = OLAP_SUCCESS;
set_default_create_tablet_request(&_create_tablet);
res = _command_executor->create_table(_create_tablet);
ASSERT_EQ(OLAP_SUCCESS, res);
SmartOLAPTable tablet = _command_executor->get_table(
_create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash);
ASSERT_TRUE(tablet.get() != NULL);
_header_file_name = tablet->header_file_name();
// push data
set_default_push_request(_create_tablet, &_push_req);
std::vector<TTabletInfo> tablets_info;
res = _command_executor->push(_push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
}
void TearDown(){
// Remove all dir.
OLAPEngine::get_instance()->drop_table(
_create_tablet.tablet_id, _create_tablet.tablet_schema.schema_hash);
while (0 == access(_header_file_name.c_str(), F_OK)) {
sleep(1);
}
ASSERT_EQ(OLAP_SUCCESS, remove_all_dir(config::storage_root_path));
}
CommandExecutor* _command_executor;
std::string _header_file_name;
TCreateTabletReq _create_tablet;
TPushReq _push_req;
};
void set_delete_data_condition(TPushReq* request) {
TCondition condition;
condition.column_name = "k1";
condition.condition_op = "=";
condition.condition_values.clear();
condition.condition_values.push_back("-120");
request->delete_conditions.push_back(condition);
condition.column_name = "k3";
condition.condition_op = "=";
condition.condition_values.clear();
condition.condition_values.push_back("ccc1aa42-e403-4964-a065-583f77e7ee98");
request->delete_conditions.push_back(condition);
condition.column_name = "k6";
condition.condition_op = "=";
condition.condition_values.clear();
condition.condition_values.push_back("89.779");
request->delete_conditions.push_back(condition);
}
TEST_F(TestDeleteData, delete_data_abnormal) {
OLAPStatus res = OLAP_SUCCESS;
std::vector<TTabletInfo> tablets_info;
set_delete_data_condition(&_push_req);
// check non_existed tablet
_push_req.tablet_id = 0;
res = _command_executor->delete_data(_push_req, &tablets_info);
ASSERT_EQ(OLAP_ERR_TABLE_NOT_FOUND, res);
// check invalid delete version
_push_req.version = 1;
_push_req.tablet_id = _create_tablet.tablet_id;
res = _command_executor->delete_data(_push_req, &tablets_info);
ASSERT_EQ(OLAP_ERR_PUSH_VERSION_INCORRECT, res);
// check invalid delete condition
_push_req.version += 2;
TCondition condition;
condition.column_name = "k1";
condition.condition_op = "=";
condition.condition_values.push_back("128");
_push_req.delete_conditions.push_back(condition);
res = _command_executor->delete_data(_push_req, &tablets_info);
ASSERT_EQ(OLAP_ERR_DELETE_INVALID_CONDITION, res);
}
TEST_F(TestDeleteData, delete_data) {
OLAPStatus res = OLAP_SUCCESS;
std::vector<TTabletInfo> tablets_info;
// 1. Submit delete data normally.
tablets_info.clear();
_push_req.version += 1;
_push_req.version_hash += 1;
_push_req.__isset.http_file_path = false;
set_delete_data_condition(&_push_req);
res = _command_executor->delete_data(_push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
ASSERT_EQ(_push_req.version, tablets_info[0].version);
ASSERT_EQ(_push_req.version_hash, tablets_info[0].version_hash);
ASSERT_EQ(BASE_TABLE_PUSH_DATA_ROW_COUNT, tablets_info[0].row_count);
// 2. Submit the the request.
tablets_info.clear();
res = _command_executor->delete_data(_push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
ASSERT_EQ(_push_req.version, tablets_info[0].version);
ASSERT_EQ(_push_req.version_hash, tablets_info[0].version_hash);
ASSERT_EQ(BASE_TABLE_PUSH_DATA_ROW_COUNT, tablets_info[0].row_count);
}
void set_cancel_delete_data_request(
const TPushReq& push_req,
TCancelDeleteDataReq* request) {
request->tablet_id = push_req.tablet_id;
request->schema_hash = push_req.schema_hash;
request->version = push_req.version;
request->version_hash = push_req.version_hash;
}
TEST_F(TestDeleteData, cancel_delete_abnormal) {
OLAPStatus res = OLAP_SUCCESS;
// check non_existed tablet
TCancelDeleteDataReq request;
set_cancel_delete_data_request(_push_req, &request);
request.tablet_id = 0;
res = _command_executor->cancel_delete(request);
ASSERT_EQ(OLAP_ERR_TABLE_NOT_FOUND, res);
// check invalid version
request.version = -1;
request.tablet_id = _push_req.tablet_id;
res = _command_executor->cancel_delete(request);
ASSERT_EQ(OLAP_ERR_DELETE_INVALID_PARAMETERS, res);
}
TEST_F(TestDeleteData, cancel_delete) {
OLAPStatus res = OLAP_SUCCESS;
std::vector<TTabletInfo> tablets_info;
// 1. Submit delete data first.
tablets_info.clear();
_push_req.version += 1;
_push_req.version_hash += 1;
_push_req.__isset.http_file_path = false;
set_delete_data_condition(&_push_req);
res = _command_executor->delete_data(_push_req, &tablets_info);
ASSERT_EQ(OLAP_SUCCESS, res);
ASSERT_EQ(1, tablets_info.size());
ASSERT_EQ(_push_req.version, tablets_info[0].version);
// 2. Cancel delete data request.
TCancelDeleteDataReq request;
set_cancel_delete_data_request(_push_req, &request);
res = _command_executor->cancel_delete(request);
ASSERT_EQ(OLAP_SUCCESS, res);
// 3. Cancel the delete data request again.
res = _command_executor->cancel_delete(request);
ASSERT_EQ(OLAP_SUCCESS, res);
}
} // namespace palo
int main(int argc, char** argv) {
std::string conffile = std::string(getenv("PALO_HOME")) + "/conf/be.conf";
if (!palo::config::init(conffile.c_str(), false)) {
fprintf(stderr, "error read config file. \n");
return -1;
}
palo::init_glog("be-test");
int ret = palo::OLAP_SUCCESS;
testing::InitGoogleTest(&argc, argv);
palo::set_up();
ret = RUN_ALL_TESTS();
palo::tear_down();
google::protobuf::ShutdownProtobufLibrary();
return ret;
}