[FEAT MERGE]implement user-defined rewrite rules
This commit is contained in:
@ -12,6 +12,7 @@
|
||||
|
||||
#define USING_LOG_PREFIX SQL_PARSER
|
||||
#include "ob_fast_parser.h"
|
||||
#include "sql/udr/ob_udr_struct.h"
|
||||
#include "share/ob_define.h"
|
||||
#include "lib/ash/ob_active_session_guard.h"
|
||||
#include "lib/worker.h"
|
||||
@ -30,24 +31,22 @@ do { \
|
||||
} while (0)
|
||||
|
||||
int ObFastParser::parse(const common::ObString &stmt,
|
||||
const bool enable_batched_multi_stmt,
|
||||
const FPContext &fp_ctx,
|
||||
common::ObIAllocator &allocator,
|
||||
char *&no_param_sql,
|
||||
int64_t &no_param_sql_len,
|
||||
ParamList *¶m_list,
|
||||
int64_t ¶m_num,
|
||||
ObCollationType connection_collation,
|
||||
common::ObIAllocator &allocator,
|
||||
ObSQLMode sql_mode /* default = 0*/)
|
||||
int64_t ¶m_num)
|
||||
{
|
||||
ObActiveSessionGuard::get_stat().in_parse_ = true;
|
||||
int ret = OB_SUCCESS;
|
||||
if (!lib::is_oracle_mode()) {
|
||||
ObFastParserMysql fp(allocator, connection_collation, enable_batched_multi_stmt, sql_mode);
|
||||
ObFastParserMysql fp(allocator, fp_ctx);
|
||||
if (OB_FAIL(fp.parse(stmt, no_param_sql, no_param_sql_len, param_list, param_num))) {
|
||||
LOG_WARN("failed to fast parser", K(stmt));
|
||||
}
|
||||
} else {
|
||||
ObFastParserOracle fp(allocator, connection_collation, enable_batched_multi_stmt);
|
||||
ObFastParserOracle fp(allocator, fp_ctx);
|
||||
if (OB_FAIL(fp.parse(stmt, no_param_sql, no_param_sql_len, param_list, param_num))) {
|
||||
LOG_WARN("failed to fast parser", K(stmt));
|
||||
}
|
||||
@ -56,6 +55,36 @@ int ObFastParser::parse(const common::ObString &stmt,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObFastParser::parse(const common::ObString &stmt,
|
||||
const FPContext &fp_ctx,
|
||||
common::ObIAllocator &allocator,
|
||||
char *&no_param_sql,
|
||||
int64_t &no_param_sql_len,
|
||||
ParamList *¶m_list,
|
||||
int64_t ¶m_num,
|
||||
ObQuestionMarkCtx &ctx)
|
||||
{
|
||||
ObActiveSessionGuard::get_stat().in_parse_ = true;
|
||||
int ret = OB_SUCCESS;
|
||||
if (!lib::is_oracle_mode()) {
|
||||
ObFastParserMysql fp(allocator, fp_ctx);
|
||||
if (OB_FAIL(fp.parse(stmt, no_param_sql, no_param_sql_len, param_list, param_num))) {
|
||||
LOG_WARN("failed to fast parser", K(stmt));
|
||||
} else {
|
||||
ctx = fp.get_question_mark_ctx();
|
||||
}
|
||||
} else {
|
||||
ObFastParserOracle fp(allocator, fp_ctx);
|
||||
if (OB_FAIL(fp.parse(stmt, no_param_sql, no_param_sql_len, param_list, param_num))) {
|
||||
LOG_WARN("failed to fast parser", K(stmt));
|
||||
} else {
|
||||
ctx = fp.get_question_mark_ctx();
|
||||
}
|
||||
}
|
||||
ObActiveSessionGuard::get_stat().in_parse_ = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int64_t ObFastParserBase::ObRawSql::strncasecmp(
|
||||
int64_t pos, const char *str, const int64_t size)
|
||||
{
|
||||
@ -75,11 +104,12 @@ inline int64_t ObFastParserBase::ObRawSql::strncasecmp(
|
||||
|
||||
ObFastParserBase::ObFastParserBase(
|
||||
ObIAllocator &allocator,
|
||||
const ObCollationType connection_collation,
|
||||
const bool enable_batched_multi_stmt) :
|
||||
const FPContext fp_ctx) :
|
||||
no_param_sql_(nullptr), no_param_sql_len_(0),
|
||||
param_num_(0), is_oracle_mode_(false),
|
||||
is_batched_multi_stmt_split_on_(enable_batched_multi_stmt),
|
||||
is_batched_multi_stmt_split_on_(fp_ctx.enable_batched_multi_stmt_),
|
||||
is_udr_mode_(fp_ctx.is_udr_mode_),
|
||||
def_name_ctx_(fp_ctx.def_name_ctx_),
|
||||
is_mysql_compatible_comment_(false),
|
||||
cur_token_begin_pos_(0), copy_begin_pos_(0), copy_end_pos_(0),
|
||||
tmp_buf_(nullptr), tmp_buf_len_(0), last_escape_check_pos_(0),
|
||||
@ -88,11 +118,12 @@ ObFastParserBase::ObFastParserBase(
|
||||
parse_next_token_func_(nullptr), process_idf_func_(nullptr)
|
||||
{
|
||||
question_mark_ctx_.count_ = 0;
|
||||
question_mark_ctx_.capacity_ = 0;
|
||||
question_mark_ctx_.by_ordinal_ = false;
|
||||
question_mark_ctx_.by_name_ = false;
|
||||
question_mark_ctx_.name_ = nullptr;
|
||||
charset_type_ = ObCharset::charset_type_by_coll(connection_collation);
|
||||
charset_info_ = ObCharset::get_charset(connection_collation);
|
||||
charset_type_ = ObCharset::charset_type_by_coll(fp_ctx.conn_coll_);
|
||||
charset_info_ = ObCharset::get_charset(fp_ctx.conn_coll_);
|
||||
}
|
||||
|
||||
int ObFastParserBase::parse(const ObString &stmt,
|
||||
@ -850,6 +881,25 @@ int64_t ObFastParserBase::get_question_mark(ObQuestionMarkCtx *ctx,
|
||||
return idx;
|
||||
}
|
||||
|
||||
int64_t ObFastParserBase::get_question_mark_by_defined_name(QuestionMarkDefNameCtx *ctx,
|
||||
const char *name,
|
||||
const int64_t name_len)
|
||||
{
|
||||
int64_t idx = -1;
|
||||
if (OB_UNLIKELY(NULL == ctx || NULL == name)) {
|
||||
(void)fprintf(stderr, "ERROR question mark ctx or name is NULL\n");
|
||||
} else if (ctx->name_ != NULL) {
|
||||
for (int64_t i = 0; -1 == idx && i < ctx->count_; ++i) {
|
||||
if (NULL == ctx->name_[i]) {
|
||||
(void)fprintf(stderr, "ERROR name_ in question mark ctx is null\n");
|
||||
} else if (0 == STRNCASECMP(ctx->name_[i], name, name_len)) {
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
inline char* ObFastParserBase::parse_strndup(const char *str, size_t nbyte, char *buf)
|
||||
{
|
||||
MEMMOVE(buf, str, nbyte);
|
||||
@ -1293,8 +1343,11 @@ int ObFastParserBase::process_question_mark()
|
||||
cur_token_type_ = PARAM_TOKEN;
|
||||
int64_t need_mem_size = FIEXED_PARAM_NODE_SIZE;
|
||||
int64_t text_len = raw_sql_.cur_pos_ - cur_token_begin_pos_;
|
||||
// allocate all the memory needed at once
|
||||
if (OB_ISNULL(buf = static_cast<char *>(allocator_.alloc(need_mem_size)))) {
|
||||
if (question_mark_ctx_.by_name_) {
|
||||
ret = OB_ERR_PARSER_SYNTAX;
|
||||
LOG_WARN("parser syntax error", K(ret), K(raw_sql_.to_string()), K_(raw_sql_.cur_pos));
|
||||
} else if (OB_ISNULL(buf = static_cast<char *>(allocator_.alloc(need_mem_size)))) {
|
||||
// allocate all the memory needed at once
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("fail to alloc memory", K(ret), K(need_mem_size));
|
||||
} else {
|
||||
@ -1309,6 +1362,72 @@ int ObFastParserBase::process_question_mark()
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObFastParserBase::process_ps_statement()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
char *buf = nullptr;
|
||||
cur_token_type_ = PARAM_TOKEN;
|
||||
char ch = raw_sql_.char_at(raw_sql_.cur_pos_);
|
||||
bool is_num = is_digit(ch) ? true : false;
|
||||
if (is_num) { // ":"{int_num}
|
||||
ch = raw_sql_.scan();
|
||||
while (is_digit(ch)) {
|
||||
ch = raw_sql_.scan();
|
||||
}
|
||||
} else {
|
||||
int64_t next_idf_pos = raw_sql_.cur_pos_;
|
||||
while (-1 != (next_idf_pos = is_identifier_flags(next_idf_pos))) {
|
||||
raw_sql_.cur_pos_ = next_idf_pos;
|
||||
}
|
||||
}
|
||||
int64_t need_mem_size = FIEXED_PARAM_NODE_SIZE;
|
||||
int64_t text_len = raw_sql_.cur_pos_ - cur_token_begin_pos_;
|
||||
need_mem_size += (text_len + 1);
|
||||
if (question_mark_ctx_.by_ordinal_) {
|
||||
ret = OB_ERR_PARSER_SYNTAX;
|
||||
LOG_WARN("parser syntax error", K(ret), K(raw_sql_.to_string()), K_(raw_sql_.cur_pos));
|
||||
} else if (OB_ISNULL(buf = static_cast<char *>(allocator_.alloc(need_mem_size)))) {
|
||||
// allocate all the memory needed at once
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("fail to alloc memory", K(ret), K(need_mem_size));
|
||||
} else {
|
||||
ParseNode *node = new_node(buf, T_QUESTIONMARK);
|
||||
node->text_len_ = text_len;
|
||||
node->raw_text_ = raw_sql_.ptr(cur_token_begin_pos_);
|
||||
if (is_num) {
|
||||
if (is_udr_mode_) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "question mark by number");
|
||||
LOG_WARN("question mark by number not supported", K(ret));
|
||||
} else {
|
||||
node->value_ = strtoll(&node->raw_text_[1], NULL, 10);
|
||||
}
|
||||
} else {
|
||||
int64_t ind = -1;
|
||||
if (is_udr_mode_ && nullptr != def_name_ctx_) {
|
||||
ind = get_question_mark_by_defined_name(def_name_ctx_, node->raw_text_, text_len);
|
||||
} else {
|
||||
ind = get_question_mark(&question_mark_ctx_, &allocator_,
|
||||
node->raw_text_, text_len, buf);
|
||||
}
|
||||
node->value_ = ind;
|
||||
// buf points to the beginning of the next available memory
|
||||
buf += text_len + 1;
|
||||
question_mark_ctx_.by_name_ = true;
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (node->value_ < 0) {
|
||||
ret = OB_ERR_PARSER_SYNTAX;
|
||||
LOG_WARN("parser syntax error", K(ret), K(raw_sql_.to_string()), K_(raw_sql_.cur_pos));
|
||||
} else {
|
||||
node->raw_sql_offset_ = cur_token_begin_pos_;
|
||||
lex_store_param(node, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Used to process '`' and keep all characters before the next '`'
|
||||
int ObFastParserBase::process_backtick()
|
||||
{
|
||||
@ -1750,42 +1869,6 @@ inline void ObFastParserBase::append_no_param_sql()
|
||||
no_param_sql_[no_param_sql_len_] = '\0';
|
||||
}
|
||||
|
||||
int ObFastParserMysql::process_ps_statement()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
char *buf = nullptr;
|
||||
cur_token_type_ = PARAM_TOKEN;
|
||||
char ch = raw_sql_.char_at(raw_sql_.cur_pos_);
|
||||
while (is_digit(ch)) {
|
||||
ch = raw_sql_.scan();
|
||||
}
|
||||
int64_t need_mem_size = FIEXED_PARAM_NODE_SIZE;
|
||||
int64_t text_len = raw_sql_.cur_pos_ - cur_token_begin_pos_;
|
||||
need_mem_size += (text_len + 1);
|
||||
// allocate all the memory needed at once
|
||||
if (OB_ISNULL(buf = static_cast<char *>(allocator_.alloc(need_mem_size)))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("fail to alloc memory", K(ret), K(need_mem_size));
|
||||
} else {
|
||||
ParseNode *node = new_node(buf, T_QUESTIONMARK);
|
||||
node->text_len_ = text_len;
|
||||
node->raw_text_ = raw_sql_.ptr(cur_token_begin_pos_);
|
||||
int64_t ind = get_question_mark(&question_mark_ctx_, &allocator_,
|
||||
node->raw_text_, text_len, buf);
|
||||
if (-1 == ind) {
|
||||
ret = OB_ERR_PARSER_SYNTAX;
|
||||
LOG_WARN("parser syntax error", K(ret), K(raw_sql_.to_string()), K_(raw_sql_.cur_pos));
|
||||
} else {
|
||||
// buf points to the beginning of the next available memory
|
||||
buf += text_len + 1;
|
||||
node->value_ = ind;
|
||||
node->raw_sql_offset_ = cur_token_begin_pos_;
|
||||
lex_store_param(node, buf);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObFastParserMysql::process_zero_identifier()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -2174,7 +2257,7 @@ int ObFastParserMysql::parse_next_token()
|
||||
}
|
||||
case ':': {
|
||||
// [":"{int_num}]
|
||||
if (is_digit(raw_sql_.peek())) {
|
||||
if (-1 != is_first_identifier_flags(raw_sql_.cur_pos_ + 1) || is_digit(raw_sql_.peek())) {
|
||||
raw_sql_.scan();
|
||||
OZ (process_ps_statement());
|
||||
} else {
|
||||
@ -2233,58 +2316,6 @@ int ObFastParserMysql::parse_next_token()
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObFastParserOracle::process_ps_statement()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
char *buf = nullptr;
|
||||
cur_token_type_ = PARAM_TOKEN;
|
||||
char ch = raw_sql_.char_at(raw_sql_.cur_pos_);
|
||||
bool is_num = is_digit(ch) ? true : false;
|
||||
if (is_num) { // ":"{int_num}
|
||||
ch = raw_sql_.scan();
|
||||
while (is_digit(ch)) {
|
||||
ch = raw_sql_.scan();
|
||||
}
|
||||
} else {
|
||||
int64_t next_idf_pos = raw_sql_.cur_pos_;
|
||||
while (-1 != (next_idf_pos = is_identifier_flags(next_idf_pos))) {
|
||||
raw_sql_.cur_pos_ = next_idf_pos;
|
||||
}
|
||||
}
|
||||
int64_t need_mem_size = FIEXED_PARAM_NODE_SIZE;
|
||||
int64_t text_len = raw_sql_.cur_pos_ - cur_token_begin_pos_;
|
||||
need_mem_size += (text_len + 1);
|
||||
// allocate all the memory needed at once
|
||||
if (OB_ISNULL(buf = static_cast<char *>(allocator_.alloc(need_mem_size)))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("fail to alloc memory", K(ret), K(need_mem_size));
|
||||
} else {
|
||||
ParseNode *node = new_node(buf, T_QUESTIONMARK);
|
||||
node->text_len_ = text_len;
|
||||
node->raw_text_ = raw_sql_.ptr(cur_token_begin_pos_);
|
||||
if (is_num) {
|
||||
node->value_ = strtoll(&node->raw_text_[1], NULL, 10);
|
||||
} else {
|
||||
int64_t ind = get_question_mark(&question_mark_ctx_, &allocator_,
|
||||
node->raw_text_, text_len, buf);
|
||||
if (-1 == ind) {
|
||||
ret = OB_ERR_PARSER_SYNTAX;
|
||||
LOG_WARN("parser syntax error", K(ret), K(raw_sql_.to_string()), K_(raw_sql_.cur_pos));
|
||||
} else {
|
||||
question_mark_ctx_.by_name_ = true;
|
||||
node->value_ = ind;
|
||||
// buf points to the beginning of the next available memory
|
||||
buf += text_len + 1;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
node->raw_sql_offset_ = cur_token_begin_pos_;
|
||||
lex_store_param(node, buf);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [in] : if in_q_quote is true, means that the current token
|
||||
* starts with ("N"|"n")?("Q"|"q"){sqbegin}
|
||||
|
||||
Reference in New Issue
Block a user