252 lines
11 KiB
C++
252 lines
11 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 "sql/parser/ob_parser.h"
|
|
#include "sql/parser/ob_fast_parser.h"
|
|
#include <gtest/gtest.h>
|
|
#include "lib/worker.h"
|
|
#include "lib/allocator/page_arena.h"
|
|
#include <fstream>
|
|
#include <iterator>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <iostream>
|
|
|
|
using namespace oceanbase;
|
|
using namespace oceanbase::common;
|
|
using namespace oceanbase::sql;
|
|
|
|
namespace test {
|
|
class TestFastParser
|
|
{
|
|
public:
|
|
TestFastParser();
|
|
~TestFastParser();
|
|
int load_sql(const std::string file_path, std::vector<std::string> &sql_array);
|
|
int parse(const ObString &sql);
|
|
bool compare_parser_result(
|
|
const ParseResult &parse_result,
|
|
const char *no_param_sql_ptr,
|
|
const int64_t no_param_sql_len,
|
|
ParamList *p_list,
|
|
const int64_t param_num);
|
|
|
|
private:
|
|
ObArenaAllocator allocator_;
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(TestFastParser);
|
|
};
|
|
|
|
TestFastParser::TestFastParser()
|
|
: allocator_(ObModIds::TEST)
|
|
{
|
|
|
|
}
|
|
|
|
TestFastParser::~TestFastParser()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
int TestFastParser::load_sql(const std::string file_path, std::vector<std::string> &sql_array)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
std::ifstream in(file_path);
|
|
if (!in.is_open()) {
|
|
ret = OB_ERROR;
|
|
SQL_PC_LOG(ERROR, "failed to open file");
|
|
}
|
|
std::string line;
|
|
while (std::getline(in, line)) {
|
|
if (line.size() <= 0) continue;
|
|
std::size_t begin = line.find_first_not_of('\t');
|
|
if (line.at(begin) == '#') continue;
|
|
std::size_t end = line.find_last_not_of('\t');
|
|
std::string sql = line.substr(begin, end - begin + 1);
|
|
sql_array.push_back(sql);
|
|
}
|
|
in.close();
|
|
return ret;
|
|
}
|
|
|
|
bool TestFastParser::compare_parser_result(
|
|
const ParseResult &parse_result,
|
|
const char *no_param_sql_ptr,
|
|
const int64_t no_param_sql_len,
|
|
ParamList *p_list,
|
|
const int64_t param_num)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t cmp_param_num = parse_result.param_node_num_;
|
|
char *cmp_no_param_sql_ptr = parse_result.no_param_sql_;
|
|
int64_t cmp_no_param_sql_len = parse_result.no_param_sql_len_;
|
|
ParamList *cmp_p_list = parse_result.param_nodes_;
|
|
if (param_num != cmp_param_num) {
|
|
SQL_PC_LOG(ERROR, "param_num diff", K(param_num), K(cmp_param_num),
|
|
K(ObString(no_param_sql_len, no_param_sql_ptr)),
|
|
K(ObString(cmp_no_param_sql_len, cmp_no_param_sql_ptr)));
|
|
return false;
|
|
} else if (cmp_no_param_sql_len != no_param_sql_len) {
|
|
SQL_PC_LOG(ERROR, "param sql len diff", K(no_param_sql_len), K(cmp_no_param_sql_len),
|
|
K(ObString(no_param_sql_len, no_param_sql_ptr)),
|
|
K(ObString(cmp_no_param_sql_len, cmp_no_param_sql_ptr)));
|
|
return false;
|
|
} else {
|
|
if (0 != (strncmp(no_param_sql_ptr, cmp_no_param_sql_ptr, no_param_sql_len))) {
|
|
SQL_PC_LOG(ERROR, "no_param_sql diff",
|
|
K(ObString(no_param_sql_len, no_param_sql_ptr)),
|
|
K(ObString(cmp_no_param_sql_len, cmp_no_param_sql_ptr)));
|
|
return false;
|
|
} else {
|
|
ParamList *fp_p_list = p_list;
|
|
for (int64_t i = 0; i < param_num && NULL != fp_p_list; i++) {
|
|
if (fp_p_list->node_->type_ != cmp_p_list->node_->type_) {
|
|
SQL_PC_LOG(ERROR, "type diff", K(fp_p_list->node_->type_), K(cmp_p_list->node_->type_), K(i),
|
|
K(fp_p_list->node_->value_), K(cmp_p_list->node_->value_));
|
|
return false;
|
|
} else if (fp_p_list->node_->num_child_ != cmp_p_list->node_->num_child_) {
|
|
SQL_PC_LOG(ERROR, "num child diff", K(fp_p_list->node_->num_child_), K(cmp_p_list->node_->num_child_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->is_neg_ != cmp_p_list->node_->is_neg_) {
|
|
SQL_PC_LOG(ERROR, "neg diff", K(fp_p_list->node_->is_neg_), K(cmp_p_list->node_->is_neg_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->is_hidden_const_ != cmp_p_list->node_->is_hidden_const_) {
|
|
SQL_PC_LOG(ERROR, "hidden const diff", K(fp_p_list->node_->is_hidden_const_), K(cmp_p_list->node_->is_hidden_const_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->is_tree_not_param_ != cmp_p_list->node_->is_tree_not_param_) {
|
|
SQL_PC_LOG(ERROR, "not param diff", K(fp_p_list->node_->is_tree_not_param_), K(cmp_p_list->node_->is_tree_not_param_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->length_semantics_ != cmp_p_list->node_->length_semantics_) {
|
|
SQL_PC_LOG(ERROR, "length semantics diff", K(fp_p_list->node_->length_semantics_), K(cmp_p_list->node_->length_semantics_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->is_val_paramed_item_idx_ != cmp_p_list->node_->is_val_paramed_item_idx_) {
|
|
SQL_PC_LOG(ERROR, "val paramed item idx diff", K(fp_p_list->node_->is_val_paramed_item_idx_), K(cmp_p_list->node_->is_val_paramed_item_idx_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->is_copy_raw_text_ != cmp_p_list->node_->is_copy_raw_text_) {
|
|
SQL_PC_LOG(ERROR, "copy row text diff", K(fp_p_list->node_->is_copy_raw_text_), K(cmp_p_list->node_->is_copy_raw_text_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->is_column_varchar_ != cmp_p_list->node_->is_column_varchar_) {
|
|
SQL_PC_LOG(ERROR, "column varchar diff", K(fp_p_list->node_->is_column_varchar_), K(cmp_p_list->node_->is_column_varchar_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->is_assigned_from_child_ != cmp_p_list->node_->is_assigned_from_child_) {
|
|
SQL_PC_LOG(ERROR, "assigned from child diff", K(fp_p_list->node_->is_assigned_from_child_), K(cmp_p_list->node_->is_assigned_from_child_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->is_trans_from_minus_ != cmp_p_list->node_->is_trans_from_minus_) {
|
|
SQL_PC_LOG(ERROR, "is trans from minus diff", K(fp_p_list->node_->is_trans_from_minus_), K(cmp_p_list->node_->is_trans_from_minus_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->is_num_must_be_pos_ != cmp_p_list->node_->is_num_must_be_pos_) {
|
|
SQL_PC_LOG(ERROR, "is num must be pos diff", K(fp_p_list->node_->is_num_must_be_pos_), K(cmp_p_list->node_->is_num_must_be_pos_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->value_ != cmp_p_list->node_->value_) {
|
|
SQL_PC_LOG(ERROR, "value diff", K(fp_p_list->node_->value_), K(cmp_p_list->node_->value_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->pos_ != cmp_p_list->node_->pos_) {
|
|
SQL_PC_LOG(ERROR, "pos diff", K(fp_p_list->node_->pos_), K(cmp_p_list->node_->pos_), K(i));
|
|
return false;
|
|
} else if (fp_p_list->node_->text_len_ != cmp_p_list->node_->text_len_) {
|
|
SQL_PC_LOG(ERROR, "text len diff", K(fp_p_list->node_->text_len_), K(cmp_p_list->node_->text_len_), K(i));
|
|
return false;
|
|
} else if (0 != strncmp(fp_p_list->node_->raw_text_,
|
|
cmp_p_list->node_->raw_text_,
|
|
fp_p_list->node_->text_len_)) {
|
|
SQL_PC_LOG(ERROR, "raw_text diff", K(i), K(ObString(fp_p_list->node_->text_len_, fp_p_list->node_->raw_text_)),
|
|
K(ObString(fp_p_list->node_->text_len_, cmp_p_list->node_->raw_text_)));
|
|
return false;
|
|
} else if (fp_p_list->node_->str_len_ != cmp_p_list->node_->str_len_) {
|
|
SQL_PC_LOG(ERROR, "str len diff", K(fp_p_list->node_->str_len_), K(cmp_p_list->node_->str_len_), K(i));
|
|
return false;
|
|
} else if (0 != strncmp(fp_p_list->node_->str_value_,
|
|
cmp_p_list->node_->str_value_,
|
|
fp_p_list->node_->str_len_)) {
|
|
SQL_PC_LOG(ERROR, "str value diff", K(i), K(ObString(fp_p_list->node_->str_len_, fp_p_list->node_->str_value_)),
|
|
K(ObString(fp_p_list->node_->str_len_, cmp_p_list->node_->str_value_)));
|
|
return false;
|
|
} else if (fp_p_list->node_->raw_param_idx_ != cmp_p_list->node_->raw_param_idx_) {
|
|
SQL_PC_LOG(ERROR, "raw param idx diff",
|
|
K(fp_p_list->node_->raw_param_idx_), K(cmp_p_list->node_->raw_param_idx_), K(i));
|
|
return false;
|
|
} else {
|
|
fp_p_list = fp_p_list->next_;
|
|
cmp_p_list = cmp_p_list->next_;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int TestFastParser::parse(const ObString &sql)
|
|
{
|
|
ObSQLMode mode = SMO_DEFAULT;
|
|
ParseResult parse_result;
|
|
ObCharsets4Parser charsets4parser;
|
|
if (lib::is_oracle_mode()) {
|
|
parse_result.sql_mode_ = (DEFAULT_ORACLE_MODE | SMO_ORACLE);
|
|
mode = (DEFAULT_ORACLE_MODE | SMO_ORACLE);
|
|
} else {
|
|
parse_result.sql_mode_ = DEFAULT_MYSQL_MODE;
|
|
mode = DEFAULT_MYSQL_MODE;
|
|
}
|
|
ObParser parser(allocator_, mode, charsets4parser);
|
|
MEMSET(&parse_result, 0, sizeof(parse_result));
|
|
int ret1 = parser.parse(sql, parse_result, FP_MODE);
|
|
int64_t param_num = 0;
|
|
char *no_param_sql_ptr = NULL;
|
|
int64_t no_param_sql_len = 0;
|
|
ParamList *p_list = NULL;
|
|
FPContext fp_ctx(charsets4parser);
|
|
fp_ctx.enable_batched_multi_stmt_ = false;
|
|
fp_ctx.is_udr_mode_ = false;
|
|
int ret2 = ObFastParser::parse(sql, fp_ctx, allocator_,
|
|
no_param_sql_ptr, no_param_sql_len, p_list, param_num);
|
|
if ((OB_SUCCESS == ret1) != (OB_SUCCESS == ret2)) {
|
|
SQL_PC_LOG_RET(ERROR, OB_ERROR, "parser results are not equal", K(ret1), K(ret2), K(sql));
|
|
return OB_ERROR;
|
|
}
|
|
if (OB_SUCCESS == ret1) {
|
|
bool is_same = compare_parser_result(parse_result, no_param_sql_ptr,
|
|
no_param_sql_len, p_list, param_num);
|
|
return is_same ? OB_SUCCESS : OB_ERROR;
|
|
}
|
|
return OB_SUCCESS;
|
|
}
|
|
|
|
void run()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const std::string file_path = "test_fast_parser.sql";
|
|
std::vector<std::string> sql_array;
|
|
TestFastParser fast_parser;
|
|
fast_parser.load_sql(file_path, sql_array);
|
|
for (uint32_t i = 0; i < sql_array.size(); i++) {
|
|
ObString sql = ObString::make_string(sql_array.at(i).c_str());
|
|
if (OB_FAIL(fast_parser.parse(sql))) {
|
|
SQL_PC_LOG(ERROR, "parser failed", K(sql));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
UNUSED(argc);
|
|
UNUSED(argv);
|
|
OB_LOGGER.set_log_level("ERROR");
|
|
OB_LOGGER.set_file_name("test_fast_parser.log", false);
|
|
set_compat_mode(lib::Worker::CompatMode::MYSQL);
|
|
::test::run();
|
|
set_compat_mode(lib::Worker::CompatMode::ORACLE);
|
|
::test::run();
|
|
return 0;
|
|
}
|