[CP][to #37396440] fix dynamic sql question mark count

This commit is contained in:
obdev
2022-11-09 08:10:33 +00:00
committed by wangzelin.wzl
parent 8e02660bcd
commit 4dd45dfcff
8 changed files with 26 additions and 32 deletions

View File

@ -915,14 +915,18 @@ int ObSql::do_real_prepare(const ObString &sql,
ObExecContext &ectx = result.get_exec_context();
ObParser parser(allocator, session.get_sql_mode(), session.get_local_collation_connection());
ParseMode parse_mode = context.is_dbms_sql_ ? DBMS_SQL_MODE :
context.is_dynamic_sql_ ? DYNAMIC_SQL_MODE :
(context.is_dynamic_sql_ || !is_inner_sql) ? DYNAMIC_SQL_MODE :
session.is_for_trigger_package() ? TRIGGER_MODE : STD_MODE;
bool is_normal_ps_prepare = is_inner_sql ? false : true;
// normal ps sql also a dynamic sql, we adjust is_dynamic_sql_ for normal ps sql parser.
context.is_dynamic_sql_ = !context.is_dynamic_sql_ ? !is_inner_sql : context.is_dynamic_sql_;
bool is_from_pl = (NULL != context.secondary_namespace_ || result.is_simple_ps_protocol());
ObPlanCacheCtx pc_ctx(sql, true, /*is_ps_mode*/
allocator, context, ectx, session.get_effective_tenant_id());
ParamStore param_store( (ObWrapperAllocator(&allocator)) );
pc_ctx.set_is_inner_sql(is_inner_sql);
CHECK_COMPATIBILITY_MODE(context.session_info_);
if (OB_ISNULL(context.session_info_) || OB_ISNULL(context.schema_guard_)) {
@ -931,8 +935,7 @@ int ObSql::do_real_prepare(const ObString &sql,
} else if (OB_FAIL(parser.parse(sql,
parse_result,
parse_mode,
false/*is_batched_multi_stmt_split_on*/,
is_normal_ps_prepare))) {
false/*is_batched_multi_stmt_split_on*/))) {
LOG_WARN("generate syntax tree failed", K(sql), K(ret));
} else if (is_mysql_mode()
&& ObSQLUtils::is_mysql_ps_not_support_stmt(parse_result)) {
@ -949,12 +952,8 @@ int ObSql::do_real_prepare(const ObString &sql,
&& context.is_prepare_protocol_
&& context.is_prepare_stage_
&& context.is_pre_execute_)) {
if (parse_result.is_dynamic_sql_) {
context.is_dynamic_sql_ = true;
}
param_cnt = parse_result.question_mark_ctx_.count_;
normalized_sql = context.is_dynamic_sql_ && parse_result.no_param_sql_len_ > 0
? ObString(parse_result.no_param_sql_len_, parse_result.no_param_sql_) : sql;
normalized_sql = sql;
if (stmt::T_ANONYMOUS_BLOCK == stmt_type
&& context.is_prepare_protocol_
&& context.is_prepare_stage_
@ -968,9 +967,6 @@ int ObSql::do_real_prepare(const ObString &sql,
}
}
} else {
if (parse_result.is_dynamic_sql_) {
context.is_dynamic_sql_ = true;
}
if (context.is_dynamic_sql_ && !context.is_dbms_sql_) {
parse_result.input_sql_ = parse_result.no_param_sql_;
parse_result.input_sql_len_ = parse_result.no_param_sql_len_;
@ -1478,6 +1474,10 @@ int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id,
context.is_prepare_protocol_ = true;
ObPsStmtId inner_stmt_id = client_stmt_id;
context.stmt_type_ = stmt_type;
// normal ps execute sql also a dynamic sql, here we adjust is_dynamic_sql_.
context.is_dynamic_sql_ = !context.is_dynamic_sql_ ? !is_inner_sql : context.is_dynamic_sql_;
ObIAllocator &allocator = result.get_mem_pool();
ObSQLSessionInfo &session = result.get_session();
ObExecContext &ectx = result.get_exec_context();
@ -1538,6 +1538,7 @@ int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id,
#ifndef NDEBUG
LOG_INFO("Begin to handle execute stmtement", K(session.get_sessid()), K(sql));
#endif
if (!ps_info->get_fixed_raw_params().empty()) {
pctx->set_is_ps_rewrite_sql();
}
@ -1545,7 +1546,6 @@ int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id,
LOG_WARN("store query string fail", K(ret));
} else if (FALSE_IT(generate_ps_sql_id(sql, context))) {
} else if (OB_LIKELY(ObStmt::is_dml_stmt(stmt_type))) {
context.is_dynamic_sql_ = ps_info->get_is_dynamic_sql();
//if plan not exist, generate plan
ObPlanCacheCtx pc_ctx(sql, true, /*is_ps_mode*/
allocator, context, ectx, session.get_effective_tenant_id());
@ -2162,7 +2162,10 @@ int ObSql::generate_stmt(ParseResult &parse_result,
SQL_LOG(DEBUG, "SET STMT PARAM COUNT", K(resolver.get_params().prepare_param_count_), K(&resolver_ctx));
//secondary_namespace_不为空,说明是PL里sql的prepare阶段
//带有returning子句的动态sql也需要rebuild,用来去除into子句
bool in_pl = NULL != resolver_ctx.secondary_namespace_ || resolver_ctx.is_dynamic_sql_ || resolver_ctx.is_dbms_sql_;
//pl context not null indicate PL dynamic sql, only need rebuild PL dynamic sql
bool in_pl = NULL != resolver_ctx.secondary_namespace_
|| (resolver_ctx.is_dynamic_sql_ && OB_NOT_NULL(result.get_session().get_pl_context()))
|| resolver_ctx.is_dbms_sql_;
bool need_rebuild = lib::is_mysql_mode() ? false : resolver_ctx.is_prepare_stage_ && in_pl;
bool is_returning_into = false;
if (stmt->is_insert_stmt() || stmt->is_update_stmt() || stmt->is_delete_stmt()) {

View File

@ -638,7 +638,7 @@ int ObParser::split_multiple_stmt(const ObString &stmt,
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
if (OB_FAIL(tmp_ret = parse(part, parse_result, parse_mode, false, false, true))) {
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;
@ -720,7 +720,7 @@ int ObParser::reconstruct_insert_sql(const common::ObString &stmt,
allocator.set_label("InsMultiValOpt");
ObIAllocator *bak_allocator = allocator_;
allocator_ = &allocator;
if (OB_FAIL(parse(stmt, parse_result, parse_mode, false, false, true))) {
if (OB_FAIL(parse(stmt, parse_result, parse_mode, false, true))) {
// if parser SQL failed,then we won't rewrite it and keep it as it is
LOG_WARN("failed to parser insert sql", K(ret));
} else if (parse_result.ins_multi_value_res_->values_count_ == 1) {
@ -944,7 +944,6 @@ int ObParser::parse(const ObString &query,
ParseResult &parse_result,
ParseMode parse_mode,
const bool is_batched_multi_stmt_split_on,
const bool is_normal_ps_prepare,
const bool no_throw_parser_error)
{
int ret = OB_SUCCESS;
@ -979,7 +978,6 @@ 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_normal_ps_prepare_ = is_normal_ps_prepare;
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;
@ -1008,7 +1006,7 @@ int ObParser::parse(const ObString &query,
}
}
if (parse_result.is_fp_ || parse_result.is_dynamic_sql_ || parse_result.is_normal_ps_prepare_) {
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_);
if (OB_UNLIKELY(NULL == buf)) {

View File

@ -85,7 +85,6 @@ public:
ParseResult &parse_result,
ParseMode mode=STD_MODE,
const bool is_batched_multi_stmt_split_on = false,
const bool is_normal_ps_prepare = false,
const bool no_throw_parser_error = false);
virtual void free_result(ParseResult &parse_result);

View File

@ -332,8 +332,8 @@ do {
do { \
if (NULL == result) { \
YY_UNEXPECTED_ERROR("invalid var node\n"); \
} else if ((result->pl_parse_info_.is_pl_parse_ && NULL == result->pl_parse_info_.pl_ns_) || \
result->is_dynamic_sql_) { \
} else if ((result->pl_parse_info_.is_pl_parse_ && NULL == result->pl_parse_info_.pl_ns_) \
|| result->is_dynamic_sql_) { \
if (result->no_param_sql_len_ + (start - result->pl_parse_info_.last_pl_symbol_pos_ - 1) \
+ (int)(log10(idx)) + 3 \
> result->no_param_sql_buf_len_) { \

View File

@ -289,7 +289,6 @@ ObPsStmtInfo::ObPsStmtInfo(ObIAllocator *inner_allocator)
is_expired_evicted_(false),
allocator_(inner_allocator),
external_allocator_(inner_allocator),
is_dynamic_sql_(false),
num_of_returning_into_(-1),
no_param_sql_(),
is_sensitive_sql_(false),
@ -319,7 +318,6 @@ ObPsStmtInfo::ObPsStmtInfo(ObIAllocator *inner_allocator,
is_expired_evicted_(false),
allocator_(inner_allocator),
external_allocator_(external_allocator),
is_dynamic_sql_(false),
num_of_returning_into_(-1),
no_param_sql_(),
is_sensitive_sql_(false),
@ -450,7 +448,6 @@ int ObPsStmtInfo::deep_copy(const ObPsStmtInfo &other)
ps_stmt_checksum_ = other.ps_stmt_checksum_;
db_id_ = other.db_id_;
question_mark_count_ = other.question_mark_count_;
is_dynamic_sql_ = other.is_dynamic_sql_;
num_of_returning_into_ = other.num_of_returning_into_;
is_sensitive_sql_ = other.is_sensitive_sql_;
can_direct_use_param_ = other.can_direct_use_param();

View File

@ -160,8 +160,7 @@ public:
inline void set_can_direct_use_param(bool v) { can_direct_use_param_ = v; }
inline void set_ps_stmt_checksum(uint64_t ps_checksum) { ps_stmt_checksum_ = ps_checksum; }
inline uint64_t get_ps_stmt_checksum() const { return ps_stmt_checksum_; }
inline void set_is_dynamic_sql(const bool is_dynamic_sql) { is_dynamic_sql_ = is_dynamic_sql; }
inline bool get_is_dynamic_sql() const { return is_dynamic_sql_; }
inline void set_num_of_returning_into(int32_t num_of_returning_into)
{ num_of_returning_into_ = num_of_returning_into; }
inline int32_t get_num_of_returning_into() const { return num_of_returning_into_; }
@ -246,7 +245,6 @@ private:
common::ObIAllocator *allocator_;
//指向ObPsPlancache中的inner_allocator_, 用于释放整个ObPsStmtItem的内存
common::ObIAllocator *external_allocator_;
bool is_dynamic_sql_;
int32_t num_of_returning_into_;
common::ObString no_param_sql_;
bool is_sensitive_sql_;

View File

@ -559,9 +559,6 @@ int ObPsCache::fill_ps_stmt_info(const ObResultSet &result,
}
if (OB_SUCC(ret)) {
int64_t info_size = 0;
if (!sql_ctx->is_dbms_sql_) {
ps_stmt_info.set_is_dynamic_sql(sql_ctx->is_dynamic_sql_);
}
if (OB_FAIL(ps_stmt_info.get_convert_size(info_size))) {
LOG_WARN("fail to get convert size", K(ret));
} else {

View File

@ -2316,7 +2316,9 @@ int ObRawExprResolverImpl::process_datatype_or_questionmark(const ParseNode &nod
c_expr->set_expr_obj_meta(question_mark_meta);
if (NULL == ctx_.external_param_info_) {
/*do nothing...*/
} else if (ctx_.is_for_dynamic_sql_ || ctx_.is_for_dbms_sql_) {
} else if (ctx_.is_for_dbms_sql_
|| (ctx_.is_for_dynamic_sql_ && OB_NOT_NULL(session_info->get_pl_context()))){
//NOTICE: only need to process PL dynamic sql and dbms sql
/*dynmaic and dbms sql already prepare question mark in parse stage.*/
bool need_save = true;
for (int64_t i = 0; OB_SUCC(ret) && i < ctx_.external_param_info_->count(); ++i) {