From 9324f96e5f6e438e70482e91675c0583faa79984 Mon Sep 17 00:00:00 2001 From: akaError <97499944+akaError@users.noreply.github.com> Date: Wed, 2 Mar 2022 14:52:25 +0800 Subject: [PATCH] =?UTF-8?q?fix=20bug=EF=BC=9A=E8=BF=9E=E7=BB=AD=E5=A4=9A?= =?UTF-8?q?=E8=A1=8C=E7=9A=84=E5=8D=95=E8=A1=8C=E6=B3=A8=E9=87=8A=E6=8A=A5?= =?UTF-8?q?=E9=94=99=20bug=20#783=20(#789)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test * fix multi comment with ';' * fix multi comment with ';' Author: akaError --- src/sql/parser/ob_parser.cpp | 74 ++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/src/sql/parser/ob_parser.cpp b/src/sql/parser/ob_parser.cpp index 867e05ba8..700bae268 100644 --- a/src/sql/parser/ob_parser.cpp +++ b/src/sql/parser/ob_parser.cpp @@ -21,7 +21,7 @@ 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) : allocator_(&allocator), sql_mode_(mode), connection_collation_(conn_collation) {} @@ -30,14 +30,14 @@ ObParser::~ObParser() #define ISSPACE(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t' || (c) == '\f' || (c) == '\v') -bool ObParser::is_pl_stmt(const ObString& stmt, bool* is_create_func) +bool ObParser::is_pl_stmt(const ObString &stmt, bool *is_create_func) { UNUSED(stmt); UNUSED(is_create_func); return false; } -bool ObParser::is_single_stmt(const ObString& stmt) +bool ObParser::is_single_stmt(const ObString &stmt) { int64_t count = 0; int64_t end_trim_offset = stmt.length(); @@ -62,7 +62,7 @@ bool ObParser::is_single_stmt(const ObString& stmt) // Actually, sql executor only executes the first stmt(create t1) and ignore the others // even though try to execute stmts like 'create t1; create t2; create t3;' int ObParser::split_multiple_stmt( - const ObString& stmt, ObIArray& queries, ObMPParseStat& parse_stat, bool is_ret_first_stmt) + const ObString &stmt, ObIArray &queries, ObMPParseStat &parse_stat, bool is_ret_first_stmt) { int ret = OB_SUCCESS; @@ -76,13 +76,11 @@ int ObParser::split_multiple_stmt( int64_t remain = stmt.length(); parse_stat.reset(); - while (remain > 0 && ISSPACE(stmt[remain - 1])) { + while (remain > 0 && (ISSPACE(stmt[remain - 1]) || '\0' == stmt[remain - 1])) { --remain; } - if (remain > 0 && '\0' == stmt[remain - 1]) { - --remain; - } - while (remain > 0 && ISSPACE(stmt[remain - 1])) { + // case like: "select * from t1;;;;;;"->"select * from t1;" + while (remain > 1 && ';' == stmt[remain - 1] && ';' == stmt[remain - 2]) { --remain; } @@ -96,20 +94,32 @@ int ObParser::split_multiple_stmt( while (remain > 0 && OB_SUCC(ret) && !parse_stat.parse_fail_ && need_continue) { ObArenaAllocator allocator(CURRENT_CONTEXT->get_malloc_allocator()); allocator.set_label("SplitMultiStmt"); - ObIAllocator* bak_allocator = allocator_; + ObIAllocator *bak_allocator = allocator_; allocator_ = &allocator; int64_t str_len = 0; - //for save memory allocate in parser, we need try find the single stmt length in advance - while (stmt[str_len + offset] != ';' && str_len < remain) { - ++ str_len; + // for save memory allocate in parser, we need try find the single stmt length in advance + while (str_len < remain) { + if (';' == stmt[str_len + offset]) { + break; + } else if ('#' == stmt[str_len + offset]) { + while (str_len + 1 < remain && '\n' != stmt[str_len + offset + 1]) { + ++str_len; + } + } else if ('-' == stmt[str_len + offset]) { + if (str_len + 1 < remain && '-' == stmt[str_len + offset + 1]) { + ++str_len; + while (str_len + 1 < remain && '\n' != stmt[str_len + offset + 1]) { + ++str_len; + } + } + } + ++str_len; } str_len = str_len == remain ? str_len : str_len + 1; ObString part(str_len, stmt.ptr() + offset); ObString remain_part(remain, stmt.ptr() + offset); - //first try parse part str, because it's have less length and need less memory + // first try parse part str, because it's have less length and need less memory if (OB_FAIL(tmp_ret = parse(part, parse_result, parse_mode, false, true))) { - //if parser part str failed, then try parse all remain part, avoid parse many times: - //bug: https://work.aone.alibaba-inc.com/issue/34642901 tmp_ret = OB_SUCCESS; tmp_ret = parse(remain_part, parse_result, parse_mode); } @@ -118,16 +128,15 @@ int ObParser::split_multiple_stmt( if (is_ret_first_stmt) { ObString first_query(single_stmt_length, stmt.ptr()); ret = queries.push_back(first_query); - need_continue = false; // only return the first stmt, so ignore the remaining stmts + need_continue = false; // only return the first stmt, so ignore the remaining stmts } else { - ObString query(single_stmt_length,stmt.ptr() + offset); + ObString query(single_stmt_length, stmt.ptr() + offset); ret = queries.push_back(query); } remain -= parse_result.end_col_; offset += parse_result.end_col_; if (remain < 0 || offset > stmt.length()) { - LOG_ERROR("split_multiple_stmt data error", - K(remain), K(offset), K(stmt.length()), K(ret)); + LOG_ERROR("split_multiple_stmt data error", K(remain), K(offset), K(stmt.length()), K(ret)); } } else { ObString query(static_cast(remain), stmt.ptr() + offset); @@ -146,10 +155,10 @@ int ObParser::split_multiple_stmt( return ret; } -int ObParser::parse_sql(const ObString& stmt, ParseResult& parse_result, const bool no_throw_parser_error) +int ObParser::parse_sql(const ObString &stmt, ParseResult &parse_result, const bool no_throw_parser_error) { int ret = OB_SUCCESS; - ObSQLParser sql_parser(*(ObIAllocator*)(parse_result.malloc_pool_), sql_mode_); + ObSQLParser sql_parser(*(ObIAllocator *)(parse_result.malloc_pool_), sql_mode_); if (OB_FAIL(sql_parser.parse(stmt.ptr(), stmt.length(), parse_result))) { if (!no_throw_parser_error) { LOG_INFO("failed to parse stmt as sql", K(stmt), K(ret)); @@ -207,9 +216,8 @@ int ObParser::parse_sql(const ObString& stmt, ParseResult& parse_result, const b return ret; } -int ObParser::parse( - const ObString& query, ParseResult& parse_result, ParseMode parse_mode, const bool is_batched_multi_stmt_split_on, - const bool no_throw_parser_error) +int ObParser::parse(const ObString &query, ParseResult &parse_result, ParseMode parse_mode, + const bool is_batched_multi_stmt_split_on, const bool no_throw_parser_error) { int ret = OB_SUCCESS; @@ -261,7 +269,7 @@ int ObParser::parse( if (parse_result.is_fp_ || parse_result.is_dynamic_sql_) { int64_t new_length = parse_result.is_fp_ ? stmt.length() + 1 : stmt.length() * 2; - char* buf = (char*)parse_malloc(new_length, parse_result.malloc_pool_); + char *buf = (char *)parse_malloc(new_length, parse_result.malloc_pool_); if (OB_UNLIKELY(NULL == buf)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("no memory for parser"); @@ -288,7 +296,7 @@ int ObParser::parse( return ret; } -int ObParser::prepare_parse(const ObString& query, void* ns, ParseResult& parse_result) +int ObParser::prepare_parse(const ObString &query, void *ns, ParseResult &parse_result) { int ret = OB_SUCCESS; @@ -311,7 +319,7 @@ int ObParser::prepare_parse(const ObString& query, void* ns, ParseResult& parse_ parse_result.sql_mode_ = sql_mode_; parse_result.pl_parse_info_.is_pl_parse_ = true; parse_result.pl_parse_info_.is_pl_parse_expr_ = false; - char* buf = (char*)parse_malloc(stmt.length() * 2, parse_result.malloc_pool_); + char *buf = (char *)parse_malloc(stmt.length() * 2, parse_result.malloc_pool_); if (OB_UNLIKELY(NULL == buf)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("no memory for parser"); @@ -324,7 +332,7 @@ int ObParser::prepare_parse(const ObString& query, void* ns, ParseResult& parse_ } if (OB_SUCC(ret)) { - ObSQLParser sql_parser(*(ObIAllocator*)(parse_result.malloc_pool_), sql_mode_); + ObSQLParser sql_parser(*(ObIAllocator *)(parse_result.malloc_pool_), sql_mode_); if (OB_FAIL(sql_parser.parse(stmt.ptr(), stmt.length(), parse_result))) { LOG_WARN("failed to parse the statement", K(parse_result.yyscan_info_), @@ -362,7 +370,7 @@ int ObParser::prepare_parse(const ObString& query, void* ns, ParseResult& parse_ return ret; } -int ObParser::pre_parse(const common::ObString& stmt, PreParseResult& res) +int ObParser::pre_parse(const common::ObString &stmt, PreParseResult &res) { int ret = OB_SUCCESS; // /*tracd_id=xxx*/ @@ -371,7 +379,7 @@ int ObParser::pre_parse(const common::ObString& stmt, PreParseResult& res) // do_nothing } else { int32_t pos = 0; - const char* ptr = stmt.ptr(); + const char *ptr = stmt.ptr(); while (pos < len && is_space(ptr[pos])) { pos++; }; @@ -446,7 +454,7 @@ int ObParser::pre_parse(const common::ObString& stmt, PreParseResult& res) return ret; } -int ObParser::scan_trace_id(const char* ptr, int64_t len, int32_t& pos, ObString& trace_id) +int ObParser::scan_trace_id(const char *ptr, int64_t len, int32_t &pos, ObString &trace_id) { int ret = OB_SUCCESS; trace_id.reset(); @@ -483,7 +491,7 @@ bool ObParser::is_trace_id_end(char ch) return is_space(ch) || ch == ',' || ch == '*'; } -void ObParser::free_result(ParseResult& parse_result) +void ObParser::free_result(ParseResult &parse_result) { UNUSED(parse_result); // destroy_tree(parse_result.result_tree_);