[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}
|
||||
|
||||
@ -19,23 +19,55 @@
|
||||
#include "sql/parser/ob_parser_utils.h"
|
||||
#include "sql/parser/ob_char_type.h"
|
||||
#include "sql/parser/parse_malloc.h"
|
||||
#include "sql/udr/ob_udr_struct.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
struct FPContext
|
||||
{
|
||||
public:
|
||||
bool enable_batched_multi_stmt_;
|
||||
bool is_udr_mode_;
|
||||
common::ObCollationType conn_coll_;
|
||||
ObSQLMode sql_mode_;
|
||||
QuestionMarkDefNameCtx *def_name_ctx_;
|
||||
|
||||
FPContext()
|
||||
: enable_batched_multi_stmt_(false),
|
||||
is_udr_mode_(false),
|
||||
conn_coll_(CS_TYPE_INVALID),
|
||||
sql_mode_(0),
|
||||
def_name_ctx_(nullptr)
|
||||
{}
|
||||
FPContext(common::ObCollationType conn_coll)
|
||||
: enable_batched_multi_stmt_(false),
|
||||
is_udr_mode_(false),
|
||||
conn_coll_(conn_coll),
|
||||
sql_mode_(0),
|
||||
def_name_ctx_(nullptr)
|
||||
{}
|
||||
};
|
||||
|
||||
struct ObFastParser final
|
||||
{
|
||||
public:
|
||||
static int 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);
|
||||
static int 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,
|
||||
common::ObCollationType connection_collation,
|
||||
common::ObIAllocator &allocator,
|
||||
ObSQLMode sql_mode = 0);
|
||||
ObQuestionMarkCtx &ctx);
|
||||
};
|
||||
|
||||
class ObFastParserBase
|
||||
@ -47,14 +79,14 @@ public:
|
||||
typedef int (ObFastParserBase::*ProcessIdfFunc) (bool is_number_begin);
|
||||
|
||||
explicit ObFastParserBase(common::ObIAllocator &allocator,
|
||||
const common::ObCollationType connection_collation,
|
||||
const bool enable_batched_multi_stmt);
|
||||
const FPContext fp_ctx);
|
||||
~ObFastParserBase() {}
|
||||
int parse(const common::ObString &stmt,
|
||||
char *&no_param_sql,
|
||||
int64_t &no_param_sql_len,
|
||||
ParamList *¶m_list,
|
||||
int64_t ¶m_num);
|
||||
const ObQuestionMarkCtx &get_question_mark_ctx() const { return question_mark_ctx_; }
|
||||
|
||||
protected:
|
||||
enum TokenType
|
||||
@ -382,6 +414,9 @@ protected:
|
||||
const char *name,
|
||||
const int64_t name_len,
|
||||
char *buf);
|
||||
int64_t get_question_mark_by_defined_name(QuestionMarkDefNameCtx *ctx,
|
||||
const char *name,
|
||||
const int64_t name_len);
|
||||
/**
|
||||
* The hexadecimal number in mysql mode has the following two representations:
|
||||
* x'([0-9A-F])*' or 0x([0-9A-F])+
|
||||
@ -398,6 +433,7 @@ protected:
|
||||
int process_binary(bool is_quote);
|
||||
int process_hint();
|
||||
int process_question_mark();
|
||||
int process_ps_statement();
|
||||
int process_number(bool has_minus);
|
||||
int process_negative();
|
||||
int process_identifier_begin_with_l(bool &need_process_ws);
|
||||
@ -489,6 +525,8 @@ protected:
|
||||
int param_num_;
|
||||
bool is_oracle_mode_;
|
||||
bool is_batched_multi_stmt_split_on_;
|
||||
bool is_udr_mode_;
|
||||
QuestionMarkDefNameCtx *def_name_ctx_;
|
||||
bool is_mysql_compatible_comment_;
|
||||
int64_t cur_token_begin_pos_;
|
||||
int64_t copy_begin_pos_;
|
||||
@ -515,10 +553,9 @@ class ObFastParserMysql final : public ObFastParserBase
|
||||
public:
|
||||
explicit ObFastParserMysql(
|
||||
common::ObIAllocator &allocator,
|
||||
const common::ObCollationType connection_collation,
|
||||
const bool enable_batched_multi_stmt,
|
||||
ObSQLMode sql_mode)
|
||||
: ObFastParserBase(allocator, connection_collation, enable_batched_multi_stmt),sql_mode_(sql_mode)
|
||||
const FPContext fp_ctx)
|
||||
: ObFastParserBase(allocator, fp_ctx),
|
||||
sql_mode_(fp_ctx.sql_mode_)
|
||||
{
|
||||
is_oracle_mode_ = false;
|
||||
set_callback_func(
|
||||
@ -541,7 +578,6 @@ private:
|
||||
*/
|
||||
int process_string(const char quote);
|
||||
int process_zero_identifier();
|
||||
int process_ps_statement();
|
||||
int process_identifier_begin_with_n();
|
||||
|
||||
private:
|
||||
@ -553,9 +589,8 @@ class ObFastParserOracle final : public ObFastParserBase
|
||||
public:
|
||||
explicit ObFastParserOracle(
|
||||
common::ObIAllocator &allocator,
|
||||
const common::ObCollationType connection_collation,
|
||||
const bool enable_batched_multi_stmt)
|
||||
: ObFastParserBase(allocator, connection_collation, enable_batched_multi_stmt)
|
||||
const FPContext fp_ctx)
|
||||
: ObFastParserBase(allocator, fp_ctx)
|
||||
{
|
||||
is_oracle_mode_ = true;
|
||||
set_callback_func(
|
||||
@ -573,7 +608,6 @@ private:
|
||||
* else, means that the current token starts with ("N"|"n")?{sqbegin }
|
||||
*/
|
||||
int process_string(const bool in_q_quote);
|
||||
int process_ps_statement();
|
||||
int process_identifier_begin_with_n();
|
||||
|
||||
private:
|
||||
|
||||
@ -23,10 +23,14 @@ using namespace oceanbase::pl;
|
||||
using namespace oceanbase::sql;
|
||||
using namespace oceanbase::common;
|
||||
|
||||
ObParser::ObParser(common::ObIAllocator &allocator, ObSQLMode mode, ObCollationType conn_collation)
|
||||
ObParser::ObParser(common::ObIAllocator &allocator,
|
||||
ObSQLMode mode,
|
||||
ObCollationType conn_collation,
|
||||
QuestionMarkDefNameCtx *ctx)
|
||||
:allocator_(&allocator),
|
||||
sql_mode_(mode),
|
||||
connection_collation_(conn_collation)
|
||||
connection_collation_(conn_collation),
|
||||
def_name_ctx_(ctx)
|
||||
{}
|
||||
|
||||
ObParser::~ObParser()
|
||||
@ -982,6 +986,7 @@ int ObParser::parse(const ObString &query,
|
||||
parse_result.is_for_trigger_ = (TRIGGER_MODE == parse_mode);
|
||||
parse_result.is_dynamic_sql_ = (DYNAMIC_SQL_MODE == parse_mode);
|
||||
parse_result.is_dbms_sql_ = (DBMS_SQL_MODE == parse_mode);
|
||||
parse_result.is_for_udr_ = (UDR_SQL_MODE == parse_mode);
|
||||
parse_result.is_batched_multi_enabled_split_ = is_batched_multi_stmt_split_on;
|
||||
parse_result.is_not_utf8_connection_ = ObCharset::is_valid_collation(connection_collation_) ?
|
||||
(ObCharset::charset_type_by_coll(connection_collation_) != CHARSET_UTF8MB4) : false;
|
||||
@ -999,6 +1004,11 @@ int ObParser::parse(const ObString &query,
|
||||
parse_result.connection_collation_ = connection_collation_;
|
||||
parse_result.mysql_compatible_comment_ = false;
|
||||
parse_result.enable_compatible_comment_ = true;
|
||||
if (nullptr != def_name_ctx_) {
|
||||
parse_result.question_mark_ctx_.by_defined_name_ = true;
|
||||
parse_result.question_mark_ctx_.name_ = def_name_ctx_->name_;
|
||||
parse_result.question_mark_ctx_.count_ = def_name_ctx_->count_;
|
||||
}
|
||||
|
||||
if (INS_MULTI_VALUES == parse_mode) {
|
||||
void *buffer = nullptr;
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "lib/string/ob_string.h"
|
||||
#include "lib/charset/ob_charset.h"
|
||||
#include "sql/parser/ob_parser_utils.h"
|
||||
#include "sql/udr/ob_udr_struct.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -49,7 +50,8 @@ class ObParser
|
||||
{
|
||||
public:
|
||||
explicit ObParser(common::ObIAllocator &allocator, ObSQLMode mode,
|
||||
common::ObCollationType conn_collation = common::CS_TYPE_UTF8MB4_GENERAL_CI);
|
||||
common::ObCollationType conn_collation = common::CS_TYPE_UTF8MB4_GENERAL_CI,
|
||||
QuestionMarkDefNameCtx *ctx = nullptr);
|
||||
virtual ~ObParser();
|
||||
/// @param queries Note that all three members of ObString is valid, size() is the length
|
||||
/// of the single statement, length() is the length of remainer statements
|
||||
@ -193,6 +195,7 @@ private:
|
||||
// we don't use it in parser now
|
||||
ObSQLMode sql_mode_;
|
||||
common::ObCollationType connection_collation_;
|
||||
QuestionMarkDefNameCtx *def_name_ctx_;
|
||||
};
|
||||
|
||||
} // end namespace sql
|
||||
|
||||
@ -751,6 +751,26 @@ int64_t get_question_mark(ObQuestionMarkCtx *ctx, void *malloc_pool, const char
|
||||
return idx;
|
||||
}
|
||||
|
||||
int64_t get_question_mark_by_defined_name(ObQuestionMarkCtx *ctx, const char *name)
|
||||
{
|
||||
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 == STRCASECMP(ctx->name_[i], name)) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(void)fprintf(stderr, "ERROR name_ in question mark ctx is null\n");
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
ParserLinkNode *new_link_node(void *malloc)
|
||||
{
|
||||
ParserLinkNode *new_node = (ParserLinkNode *)parse_malloc(sizeof(ParserLinkNode), malloc);
|
||||
|
||||
@ -91,6 +91,7 @@ enum ParseMode
|
||||
TRIGGER_MODE, /* treat ':xxx' as identifier */
|
||||
DYNAMIC_SQL_MODE, /*解析动态sql过程中,:idx和:identifier要根据语句类型确定是否检查placeholder的名字*/
|
||||
DBMS_SQL_MODE,
|
||||
UDR_SQL_MODE,
|
||||
INS_MULTI_VALUES,
|
||||
};
|
||||
|
||||
@ -227,6 +228,7 @@ typedef struct _ObQuestionMarkCtx
|
||||
int capacity_;
|
||||
bool by_ordinal_;
|
||||
bool by_name_;
|
||||
bool by_defined_name_;
|
||||
} ObQuestionMarkCtx;
|
||||
|
||||
|
||||
@ -301,7 +303,7 @@ typedef struct
|
||||
uint32_t is_include_old_new_in_trigger_ : 1;
|
||||
uint32_t is_normal_ps_prepare_ : 1;
|
||||
uint32_t is_multi_values_parser_ : 1;
|
||||
uint32_t reserved_ : 1;
|
||||
uint32_t is_for_udr_ : 1;
|
||||
};
|
||||
|
||||
ParseNode *result_tree_;
|
||||
@ -394,6 +396,7 @@ extern uint64_t parsenode_hash(const ParseNode *node, int *ret);
|
||||
extern bool parsenode_equal(const ParseNode *node1, const ParseNode *node2, int *ret);
|
||||
|
||||
extern int64_t get_question_mark(ObQuestionMarkCtx *ctx, void *malloc_pool, const char *name);
|
||||
extern int64_t get_question_mark_by_defined_name(ObQuestionMarkCtx *ctx, const char *name);
|
||||
|
||||
// compare ParseNode str_value_ to pattern
|
||||
// @param [in] node ParseNode
|
||||
|
||||
@ -73,7 +73,7 @@ int parse_sql(ParseResult *p, const char *buf, size_t len)
|
||||
p->comment_cnt_ = 0;
|
||||
p->stop_add_comment_ = false;
|
||||
#endif
|
||||
if (false == p->pl_parse_info_.is_pl_parse_) {//如果是PLParse调用的该接口,不去重置
|
||||
if (false == p->pl_parse_info_.is_pl_parse_ && !p->is_for_udr_) {//如果是PLParse调用的该接口,不去重置
|
||||
p->question_mark_ctx_.count_ = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1349,6 +1349,33 @@ BEGIN(in_c_comment);
|
||||
}
|
||||
}
|
||||
|
||||
":"{identifier} {
|
||||
ParseResult *p = (ParseResult *)yyextra;
|
||||
check_value(yylval);
|
||||
malloc_new_node(yylval->node, p->malloc_pool_, T_QUESTIONMARK, 0);
|
||||
if (p->question_mark_ctx_.by_defined_name_) {
|
||||
yylval->node->value_ = get_question_mark_by_defined_name(&p->question_mark_ctx_, yytext);
|
||||
if (yylval->node->value_ < 0) {
|
||||
YY_UNEXPECTED_ERROR("Invalid question mark idx\n");
|
||||
}
|
||||
} else {
|
||||
yylval->node->value_ = get_question_mark(&p->question_mark_ctx_, p->malloc_pool_, yytext);
|
||||
}
|
||||
p->question_mark_ctx_.by_name_ = true;
|
||||
if (OB_UNLIKELY(p->question_mark_ctx_.by_ordinal_)) {
|
||||
YY_UNEXPECTED_ERROR("Ordinal binding and Named binding cannot be combined\n");
|
||||
}
|
||||
copy_and_replace_questionmark(p, yylloc->first_column, yylloc->last_column, yylval->node->value_);
|
||||
if (IS_FAST_PARAMETERIZE) {
|
||||
yylval->node->raw_text_ = parse_strdup(yytext, p->malloc_pool_, &(yylval->node->text_len_));
|
||||
check_malloc(yylval->node->raw_text_);
|
||||
STORE_PARAM_NODE();
|
||||
} else {
|
||||
yylval->node->pos_ = yylloc->first_column - 1;
|
||||
return QUESTIONMARK;
|
||||
}
|
||||
}
|
||||
|
||||
":"{identifier}"."{identifier} {
|
||||
ParseResult *p = (ParseResult *)yyextra;
|
||||
check_value(yylval);
|
||||
|
||||
Reference in New Issue
Block a user