[FEAT MERGE]implement user-defined rewrite rules

This commit is contained in:
obdev
2022-12-30 08:10:42 +00:00
committed by ob-robot
parent 21c0bac716
commit 9dcc0a529e
100 changed files with 5540 additions and 315 deletions

View File

@ -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 *&param_list,
int64_t &param_num,
ObCollationType connection_collation,
common::ObIAllocator &allocator,
ObSQLMode sql_mode /* default = 0*/)
int64_t &param_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 *&param_list,
int64_t &param_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}

View File

@ -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 *&param_list,
int64_t &param_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 *&param_list,
int64_t &param_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 *&param_list,
int64_t &param_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:

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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);