diff --git a/src/pl/ob_pl_resolver.cpp b/src/pl/ob_pl_resolver.cpp index 86fd59a14a..e13c6a31a9 100644 --- a/src/pl/ob_pl_resolver.cpp +++ b/src/pl/ob_pl_resolver.cpp @@ -355,6 +355,7 @@ int ObPLResolver::resolve(const ObStmtNodeTree *parse_tree, ObPLFunctionAST &fun break; case T_VARIABLE_SET: { RESOLVE_STMT(PL_ASSIGN, resolve_assign, ObPLAssignStmt); + OZ (try_transform_assign_to_dynamic_SQL(stmt, func)); } break; case T_SP_IF: { @@ -9978,6 +9979,111 @@ int ObPLResolver::transform_subquery_expr(const ParseNode *node, return ret; } +int ObPLResolver::try_transform_assign_to_dynamic_SQL(ObPLStmt *&old_stmt, ObPLFunctionAST &func) +{ + int ret = OB_SUCCESS; + int64_t into_count = OB_INVALID_COUNT; + int64_t value_count = OB_INVALID_COUNT; + int64_t expr_count = OB_INVALID_COUNT; + ObPLAssignStmt * assign_stmt = NULL; + CK (OB_NOT_NULL(assign_stmt = static_cast(old_stmt))); + OX (into_count = assign_stmt->get_into_count()); + OX (value_count = assign_stmt->get_value_count()); + if(lib::is_mysql_mode() && into_count > 0 && value_count > 0 && into_count == value_count) { + bool is_need_transform_to_dynamic = false; + ObSEArray var_val_pos_array; + OX (expr_count = func.get_expr_count()); + for(int64_t i = 0; i < into_count && OB_SUCC(ret); i++) { + ObRawExpr* sql_expr = NULL; + ObRawExpr* into_expr = NULL; + int64_t sql_expr_index = assign_stmt->get_value_index(i); + int64_t into_expr_index = assign_stmt->get_into_index(i); + CK (sql_expr_index >= 0 && sql_expr_index < expr_count && into_expr_index >= 0 && into_expr_index < expr_count); + CK (OB_NOT_NULL(sql_expr = func.get_expr(sql_expr_index))); + CK (OB_NOT_NULL(into_expr = func.get_expr(into_expr_index))); + if(OB_SUCC(ret) && sql_expr->get_expr_type() == T_FUN_SUBQUERY && + into_expr->get_expr_type() == T_OP_GET_USER_VAR) { + OZ (transform_to_new_assign_stmt(var_val_pos_array, assign_stmt)); + OZ (transform_var_val_to_dynamic_SQL(sql_expr_index, into_expr_index, func)); + OX (is_need_transform_to_dynamic = true); + LOG_INFO("try transform var_val to dynamic SQL!",K(ret), K(sql_expr_index), K(into_expr_index), K(i)); + } else { + OZ (var_val_pos_array.push_back(i)); + } + } + if(OB_SUCC(ret) && is_need_transform_to_dynamic) { + if(!var_val_pos_array.empty()) { + OZ (transform_to_new_assign_stmt(var_val_pos_array, assign_stmt)); + } + old_stmt->~ObPLStmt(); + OX (old_stmt = NULL); + } + } + return ret; +} + +int ObPLResolver::transform_var_val_to_dynamic_SQL(int64_t sql_expr_index, int64_t into_expr_index, ObPLFunctionAST &func) +{ + int ret = OB_SUCCESS; + ObPLStmt *stmt = NULL; + ObPLExecuteStmt* execute_stmt = NULL; + ObObjParam val; + ObString str_val; + ObConstRawExpr *c_expr = NULL; + ObPlQueryRefRawExpr* sql = NULL; + ObCollationType collation_connection = CS_TYPE_INVALID; + OZ (stmt_factory_.allocate(PL_EXECUTE, current_block_, stmt)); + CK (OB_NOT_NULL(execute_stmt = static_cast(stmt))); + CK (OB_NOT_NULL(sql = static_cast(func.get_expr(sql_expr_index)))); + // for SQL, construct an ObConstRawExpr from ObPlQueryRefRawExpr + OZ (ob_write_string(resolve_ctx_.allocator_, sql->get_ps_sql(), str_val)); + OX (val.set_string(ObCharType, str_val)); + OX (val.set_collation_level(CS_LEVEL_COERCIBLE)); + OZ (current_block_->get_namespace().get_external_ns()->get_resolve_ctx().session_info_.get_collation_connection(collation_connection)); + OX (val.set_collation_type(collation_connection)); + OZ (expr_factory_.create_raw_expr(T_CHAR, c_expr)); + OX (c_expr->set_value(val)); + OZ (func.add_expr(c_expr)); + OX (execute_stmt->set_sql(func.get_expr_count() - 1)); + // for into + OZ (execute_stmt->add_into(into_expr_index, current_block_->get_namespace(), *func.get_expr(into_expr_index))); + // for using + if(OB_SUCC(ret)) { + for(int64_t param_pos = 0; param_pos < sql->get_param_count() && OB_SUCC(ret); param_pos++) { + for(int64_t using_pos = 0; using_pos < func.get_expr_count() && OB_SUCC(ret); using_pos++) { + if(func.get_expr(using_pos) == sql->get_param_expr(param_pos)) { + // CK (func.get_expr(using_pos)->get_expr_type() == T_QUESTIONMARK); + OZ (execute_stmt->get_using().push_back(InOutParam(using_pos, PL_PARAM_IN, OB_INVALID_INDEX))); + break; + } else { + CK (using_pos < func.get_expr_count() - 1); + } + } + } + } + OZ (current_block_->add_stmt(stmt)); + LOG_INFO("now transform var_val to dynamic SQL!",K(ret), K(sql_expr_index), K(into_expr_index), K(str_val)); + return ret; +} + +int ObPLResolver::transform_to_new_assign_stmt(ObIArray &transform_array, ObPLAssignStmt *&old_stmt) +{ + int ret = OB_SUCCESS; + if(!transform_array.empty()) { + ObPLStmt *stmt = NULL; + ObPLAssignStmt * new_assign_stmt = NULL; + OZ (stmt_factory_.allocate(PL_ASSIGN, current_block_, stmt)); + CK (OB_NOT_NULL(new_assign_stmt = static_cast(stmt))); + for(int64_t i = 0; i < transform_array.count() && OB_SUCC(ret); i++) { + OZ (new_assign_stmt->add_into(old_stmt->get_into_index(transform_array.at(i)))); + OZ (new_assign_stmt->add_value(old_stmt->get_value_index(transform_array.at(i)))); + } + OX (transform_array.reset()); + OZ (current_block_->add_stmt(stmt)); + } + return ret; +} + int ObPLResolver::check_expr_can_pre_calc(ObRawExpr *expr, bool &pre_calc) { int ret = OB_SUCCESS; diff --git a/src/pl/ob_pl_resolver.h b/src/pl/ob_pl_resolver.h index 400c451f73..bd409c4667 100644 --- a/src/pl/ob_pl_resolver.h +++ b/src/pl/ob_pl_resolver.h @@ -1019,6 +1019,9 @@ private: ObRawExpr *&expr, const ObPLDataType *expected_type, ObPLCompileUnitAST &func); + int try_transform_assign_to_dynamic_SQL(ObPLStmt *&old_stmt, ObPLFunctionAST &func); + int transform_var_val_to_dynamic_SQL(int64_t sql_expr_index, int64_t into_expr_index, ObPLFunctionAST &func); + int transform_to_new_assign_stmt(ObIArray &transform_array, ObPLAssignStmt *&old_stmt); int replace_to_const_expr_if_need(ObRawExpr *&expr); int build_seq_value_expr(ObRawExpr *&expr, diff --git a/src/pl/ob_pl_stmt.h b/src/pl/ob_pl_stmt.h index 89ad9f82dd..34e549700a 100644 --- a/src/pl/ob_pl_stmt.h +++ b/src/pl/ob_pl_stmt.h @@ -2080,11 +2080,13 @@ public: inline const sql::ObRawExpr *get_into_expr(int64_t i) const { return get_expr(into_.at(i));} inline int set_into(ObPLSEArray &idxs) { return append(into_, idxs); } inline int add_into(int64_t idx) { return into_.push_back(idx); } + inline int64_t get_into_count() { return into_.count(); } inline const common::ObIArray &get_value() const { return value_;} inline int64_t get_value_index(int64_t i) const { return value_.at(i);} inline const sql::ObRawExpr *get_value_expr(int64_t i) const { return get_expr(value_.at(i)); } inline int set_value(ObPLSEArray &idxs) { return append(value_, idxs); } inline int add_value(int64_t idx) { return value_.push_back(idx); } + inline int64_t get_value_count() { return value_.count(); } private: ObPLSEArray into_; ObPLSEArray value_; diff --git a/src/sql/ob_sql.cpp b/src/sql/ob_sql.cpp index 7c49cc5b36..8cb85297ae 100644 --- a/src/sql/ob_sql.cpp +++ b/src/sql/ob_sql.cpp @@ -2839,7 +2839,8 @@ int ObSql::generate_stmt(ParseResult &parse_result, 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 need_rebuild = (lib::is_mysql_mode() ? (resolver_ctx.is_dynamic_sql_ && + OB_NOT_NULL(result.get_session().get_pl_context()) && resolver_ctx.is_prepare_stage_) : 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()) { ObDelUpdStmt &dml_stmt = static_cast(*stmt); diff --git a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_pad.result b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_pad.result index 36c01f16f4..6a38e514d9 100644 --- a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_pad.result +++ b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_pad.result @@ -6324,3 +6324,4 @@ select rpad("", cast(c1 as decimal), "123") from t1; +--------------------------------------+ drop table t1; +SET GLOBAL max_allowed_packet = 16777216; diff --git a/tools/deploy/mysql_test/test_suite/static_engine/t/expr_pad.test b/tools/deploy/mysql_test/test_suite/static_engine/t/expr_pad.test index 4f15d69d65..66745abcae 100644 --- a/tools/deploy/mysql_test/test_suite/static_engine/t/expr_pad.test +++ b/tools/deploy/mysql_test/test_suite/static_engine/t/expr_pad.test @@ -54,6 +54,7 @@ while ($left <= $cnt) } --disable_query_log +let $max_allowed_packet=`select @@global.max_allowed_packet`; SET GLOBAL max_allowed_packet = 4194304; connection default; disconnect conn_admin; @@ -130,3 +131,4 @@ select rpad("", cast(c1 as decimal), "123") from t1; drop table t1; --sleep 2 +eval SET GLOBAL max_allowed_packet = $max_allowed_packet; \ No newline at end of file