
Co-authored-by: SevenJ-swj <sevenjworkstation@gmail.com> Co-authored-by: dontknow9179 <545187809@qq.com>
263 lines
8.4 KiB
C++
263 lines
8.4 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <fstream>
|
|
#define private public
|
|
#define protected public
|
|
#include "lib/utility/ob_test_util.h"
|
|
#include "observer/ob_server.h"
|
|
#include "observer/ob_server_struct.h"
|
|
#include "sql/test_sql_utils.h"
|
|
#include "sql/ob_sql_init.h"
|
|
#include "sql/engine/basic/ob_select_into.h"
|
|
#include "sql/engine/dml/ob_table_insert.h"
|
|
#include "sql/engine/basic/ob_expr_values.h"
|
|
#include "sql/engine/table/ob_fake_table.h"
|
|
#include "sql/session/ob_sql_session_info.h"
|
|
#include "sql/engine/test_engine_util.h"
|
|
|
|
using namespace oceanbase::observer;
|
|
using namespace oceanbase::common;
|
|
using namespace oceanbase::sql;
|
|
|
|
class ObSelectIntoTest: public ::testing::Test
|
|
{
|
|
static const uint64_t TABLE_ID = 1099511677877;
|
|
public:
|
|
ObSelectIntoTest();
|
|
virtual ~ObSelectIntoTest();
|
|
protected:
|
|
void test_into_file(int64_t row_count, const char *name);
|
|
void init_op_for_file(ObSelectInto &op_into);
|
|
int add_rows(ObFakeTable &table, const int64_t row_num);
|
|
int init_op_for_variables(ObSelectInto *op_into);
|
|
int create_expr_values(int64_t num, ObExprValues *&expr_values);
|
|
int create_sql_expr(ObObj &obj, ObSqlExpression *&expr);
|
|
// disallow copy
|
|
ObSelectIntoTest(const ObSelectIntoTest &other);
|
|
ObSelectIntoTest& operator=(const ObSelectIntoTest &other);
|
|
private:
|
|
ObPhysicalPlan physical_plan_;
|
|
ObString vars_str_[10];
|
|
int64_t vars_count_;
|
|
ObObj obj_val_[10];
|
|
};
|
|
|
|
ObSelectIntoTest::ObSelectIntoTest()
|
|
{
|
|
|
|
}
|
|
|
|
ObSelectIntoTest::~ObSelectIntoTest()
|
|
{
|
|
}
|
|
|
|
|
|
int ObSelectIntoTest::create_sql_expr(ObObj &obj, ObSqlExpression *&expr)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObPostExprItem expr_item;
|
|
|
|
if (OB_SUCCESS != (ret = ObSqlExpressionUtil::make_sql_expr(&physical_plan_, expr))) {
|
|
SQL_ENG_LOG(WARN, "make expression failed", K(ret));
|
|
} else if (OB_SUCCESS != (ret = expr_item.assign(obj))) {
|
|
SQL_ENG_LOG(WARN, "assign expr item failed", K(ret));
|
|
} else if (OB_FAIL(expr->set_item_count(1))) {
|
|
SQL_ENG_LOG(WARN, "fail to set item count", K(ret));
|
|
} else if (OB_SUCCESS != (ret = expr->add_expr_item(expr_item))) {
|
|
SQL_ENG_LOG(WARN, "add expression item failed", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObSelectIntoTest::init_op_for_file(ObSelectInto &op_into)
|
|
{
|
|
UNUSED(op_into);
|
|
}
|
|
|
|
int ObSelectIntoTest::add_rows(ObFakeTable &table, const int64_t row_num)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObNewRow *row = NULL;
|
|
int64_t column_count = 5;
|
|
ObObj *objs = NULL;
|
|
if (OB_ISNULL(row = static_cast<ObNewRow *>(physical_plan_.get_allocator().alloc(sizeof(ObNewRow))))) {
|
|
SQL_ENG_LOG(WARN, "str is null", K(ret));
|
|
} else if (OB_ISNULL(objs = static_cast<ObObj *>(physical_plan_.get_allocator().alloc(sizeof(ObObj) * 5)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
} else {
|
|
for (int64_t i = 0 ; i < column_count ; i++) {
|
|
new(objs + i)ObObj();
|
|
(objs + i)->set_int(row_num * column_count + i);
|
|
}
|
|
row->cells_ = objs;
|
|
row->count_ = column_count;
|
|
ret = table.add_row(*row);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSelectIntoTest::init_op_for_variables(ObSelectInto *op_into)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
op_into->set_column_count(5);
|
|
op_into->set_id(1);
|
|
op_into->set_into_type(T_INTO_VARIABLES);
|
|
vars_count_ = 5;
|
|
common::ObSEArray<ObString, 16> user_vars;
|
|
for (int i = 0 ; i < vars_count_; i++) {
|
|
char *str = NULL;
|
|
if (OB_ISNULL(str = static_cast<char *>(physical_plan_.get_allocator().alloc(2)))) {
|
|
SQL_ENG_LOG(WARN, "str is null", K(ret));
|
|
} else {
|
|
str[0] = static_cast<char>('a' + i);
|
|
vars_str_[i].assign(str, 1);
|
|
if (OB_FAIL(user_vars.push_back(vars_str_[i]))) {
|
|
SQL_ENG_LOG(WARN, "push back varstr failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
op_into->set_user_vars(user_vars);
|
|
return ret;
|
|
}
|
|
|
|
int ObSelectIntoTest::create_expr_values(int64_t num, ObExprValues *&expr_values)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(physical_plan_.alloc_operator_by_type(PHY_EXPR_VALUES, expr_values))) {
|
|
} else {
|
|
expr_values->set_column_count(5);
|
|
ObObj obj;
|
|
if (OB_FAIL(expr_values->init_value_count(num))) {
|
|
SQL_ENG_LOG(WARN, "init expr values count failed", K(ret));
|
|
}
|
|
for (int64_t i = 0 ; i < num && OB_SUCC(ret);i++) {
|
|
ObSqlExpression *expr = NULL;
|
|
obj.set_int(i);
|
|
obj_val_[i] = obj;
|
|
if (OB_FAIL(create_sql_expr(obj, expr))) {
|
|
} else if (OB_FAIL(expr_values->add_value(expr))) {
|
|
} else {}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObSelectIntoTest::test_into_file(int64_t row_count, const char *name)
|
|
{
|
|
//int ret = OB_SUCCESS;
|
|
ObSelectInto op_into(physical_plan_.get_allocator());
|
|
ObFakeTable fake_op;
|
|
ObExecContext exec_ctx;
|
|
ObPhysicalPlan physical_plan;
|
|
|
|
// init op_into
|
|
op_into.set_column_count(5);
|
|
op_into.set_id(1);
|
|
op_into.set_into_type(T_INTO_OUTFILE);
|
|
ObObj file_name;
|
|
file_name.set_varchar(name);
|
|
op_into.set_outfile_name(file_name);
|
|
ObObj field_str;
|
|
field_str.set_varchar(",");
|
|
op_into.set_field_str(field_str);
|
|
ObObj line_str;
|
|
line_str.set_varchar("\n");
|
|
op_into.set_line_str(line_str);
|
|
char enclosed_str = '|';
|
|
bool is_optional = false;
|
|
op_into.set_closed_cht(enclosed_str);
|
|
op_into.set_is_optional(is_optional);
|
|
op_into.set_phy_plan(&physical_plan);
|
|
|
|
fake_op.set_id(0);
|
|
fake_op.set_phy_plan(&physical_plan);
|
|
fake_op.set_parent(&op_into);
|
|
fake_op.set_column_count(5);
|
|
for (int64_t i = 0 ;i < row_count ; ++i) {
|
|
ASSERT_EQ(OB_SUCCESS, add_rows(fake_op, i));
|
|
}
|
|
|
|
ASSERT_EQ(OB_SUCCESS, exec_ctx.init_phy_op(2));
|
|
ASSERT_EQ(OB_SUCCESS, exec_ctx.create_physical_plan_ctx());
|
|
ASSERT_EQ(OB_SUCCESS, create_test_session(exec_ctx));
|
|
ASSERT_EQ(OB_SUCCESS, exec_ctx.get_my_session()->set_time_zone(ObString("+8:00"), true, true));
|
|
my_session = exec_ctx.get_my_session();
|
|
ASSERT_TRUE(NULL != my_session);
|
|
ASSERT_EQ(OB_SUCCESS, ObPreProcessSysVars::init_sys_var());
|
|
ASSERT_EQ(OB_SUCCESS, my_session->load_default_sys_variable(false, false));
|
|
|
|
OK(op_into.set_child(0, fake_op)); // set child
|
|
OK(op_into.open(exec_ctx));
|
|
OK(op_into.close(exec_ctx));
|
|
}
|
|
|
|
TEST_F(ObSelectIntoTest, test_into_file)
|
|
{
|
|
const char* tmp_file = "test_select_into_file.tmp";
|
|
const char* result_file = "test_select_into_file.result";
|
|
std::remove(tmp_file);
|
|
|
|
test_into_file(100, tmp_file);
|
|
|
|
std::ifstream if_result(tmp_file);
|
|
ASSERT_TRUE(if_result.is_open());
|
|
std::istream_iterator<std::string> it_result(if_result);
|
|
std::ifstream if_expected(result_file);
|
|
ASSERT_TRUE(if_expected.is_open());
|
|
std::istream_iterator<std::string> it_expected(if_expected);
|
|
bool is_equal = std::equal(it_result, std::istream_iterator<std::string>(), it_expected);
|
|
if (is_equal) {
|
|
std::remove(tmp_file);
|
|
}
|
|
ASSERT_EQ(true, is_equal);
|
|
|
|
}
|
|
|
|
TEST_F(ObSelectIntoTest, test_into_variables)
|
|
{
|
|
ObExprValues *expr_values = NULL;
|
|
ASSERT_EQ(OB_SUCCESS, create_expr_values(5, expr_values));
|
|
ASSERT_TRUE(NULL != expr_values);
|
|
ObExecContext exec_ctx;
|
|
ASSERT_EQ(OB_SUCCESS, exec_ctx.init_phy_op(2));
|
|
ASSERT_EQ(OB_SUCCESS, exec_ctx.create_physical_plan_ctx());
|
|
ASSERT_EQ(OB_SUCCESS, create_test_session(exec_ctx));
|
|
session = exec_ctx.get_my_session();
|
|
ASSERT_TRUE(NULL != session);
|
|
ASSERT_EQ(OB_SUCCESS, exec_ctx.get_my_session()->set_time_zone(ObString("+8:00"), true, true));
|
|
ASSERT_EQ(OB_SUCCESS, ObPreProcessSysVars::init_sys_var());
|
|
ASSERT_EQ(OB_SUCCESS, session->load_default_sys_variable(false, false));
|
|
ObSelectInto *op_into = NULL;
|
|
ASSERT_EQ(OB_SUCCESS, physical_plan_.alloc_operator_by_type(PHY_SELECT_INTO, op_into));
|
|
ASSERT_TRUE(NULL != op_into);
|
|
ASSERT_EQ(OB_SUCCESS, init_op_for_variables(op_into));
|
|
ASSERT_EQ(OB_SUCCESS, op_into->set_child(0, *expr_values));
|
|
expr_values->set_parent(op_into);
|
|
ASSERT_EQ(OB_SUCCESS, op_into->open(exec_ctx));
|
|
ASSERT_EQ(OB_SUCCESS, op_into->close(exec_ctx));
|
|
ObObj val;
|
|
for (int64_t i = 0 ; i < vars_count_ ; ++i) {
|
|
ASSERT_EQ(OB_SUCCESS, session->get_user_variable_value(vars_str_[i], val));
|
|
ASSERT_EQ(val, obj_val_[i]);
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
init_sql_factories();
|
|
oceanbase::common::ObLogger::get_logger().set_log_level("DEBUG");
|
|
::testing::InitGoogleTest(&argc,argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|