From 08802d94f612752af2a75bdae5742ec6f7bafa75 Mon Sep 17 00:00:00 2001 From: obdev Date: Mon, 9 Jan 2023 08:47:31 +0000 Subject: [PATCH] [FEAT MERGE] 4.1 PL/SQL enhence & development --- .../src/lib/mysqlclient/ob_isql_connection.h | 2 - .../lib/mysqlclient/ob_mysql_connection.cpp | 8 +- .../src/lib/mysqlclient/ob_mysql_connection.h | 2 - deps/oblib/src/lib/oblog/ob_log_module.h | 6 +- src/objit/include/objit/common/ob_item_type.h | 1 + src/observer/mysql/obmp_stmt_execute.cpp | 2 +- src/observer/mysql/obmp_stmt_prexecute.cpp | 2 +- src/observer/ob_inner_sql_connection.cpp | 560 +---- src/observer/ob_inner_sql_connection.h | 65 +- src/observer/virtual_table/ob_gv_sql.cpp | 10 +- src/observer/virtual_table/ob_gv_sql.h | 2 +- src/pl/CMakeLists.txt | 4 + src/pl/ob_pl.cpp | 730 +++++-- src/pl/ob_pl.h | 151 +- src/pl/ob_pl_code_generator.cpp | 76 +- src/pl/ob_pl_code_generator.h | 5 +- src/pl/ob_pl_compile.cpp | 139 +- src/pl/ob_pl_compile.h | 17 +- src/pl/ob_pl_exception_handling.cpp | 3 + src/pl/ob_pl_exception_handling.h | 1 + src/pl/ob_pl_package_manager.cpp | 86 +- src/pl/ob_pl_resolver.cpp | 74 +- src/pl/ob_pl_resolver.h | 2 +- src/pl/ob_pl_stmt.cpp | 19 +- src/pl/ob_pl_stmt.h | 34 +- src/pl/ob_pl_type.cpp | 26 +- src/pl/ob_pl_type.h | 2 +- src/pl/parser/ob_pl_parser.cpp | 75 + src/pl/parser/ob_pl_parser.h | 3 +- src/pl/parser/parse_stmt_item_type.h | 8 + src/pl/parser/parse_stmt_node.h | 11 +- src/pl/parser/pl_parser_mysql_mode.y | 7 +- src/pl/pl_cache/ob_pl_cache.cpp | 986 +++++++++ src/pl/pl_cache/ob_pl_cache.h | 312 +++ src/pl/pl_cache/ob_pl_cache_mgr.cpp | 205 ++ src/pl/pl_cache/ob_pl_cache_mgr.h | 81 + src/pl/sys_package/ob_dbms_sql.cpp | 36 +- src/pl/sys_package/ob_dbms_sql.h | 12 +- src/rootserver/ob_ddl_operator.cpp | 15 + src/rootserver/ob_ddl_operator.h | 1 + src/rootserver/ob_ddl_service.cpp | 62 +- src/rootserver/ob_ddl_service.h | 1 + src/share/ob_rpc_struct.cpp | 19 +- src/share/ob_rpc_struct.h | 10 +- src/share/schema/ob_dependency_info.cpp | 59 +- src/share/schema/ob_error_info.cpp | 21 + src/share/schema/ob_error_info.h | 1 + src/share/schema/ob_trigger_info.cpp | 136 +- src/share/schema/ob_trigger_info.h | 11 +- src/share/schema/ob_trigger_sql_service.cpp | 20 +- .../code_generator/ob_expr_generator_impl.cpp | 2 +- src/sql/das/ob_das_utils.cpp | 5 +- src/sql/das/ob_das_utils.h | 4 +- src/sql/engine/cmd/ob_trigger_executor.cpp | 81 +- src/sql/engine/dml/ob_dml_service.cpp | 39 +- .../engine/expr/ob_expr_statement_digest.cpp | 2 +- src/sql/engine/expr/ob_pl_expr_subquery.cpp | 74 +- src/sql/engine/expr/ob_pl_expr_subquery.h | 11 +- src/sql/engine/ob_physical_plan.cpp | 2 +- src/sql/engine/table/ob_table_scan_op.cpp | 2 +- src/sql/ob_result_set.cpp | 9 +- src/sql/ob_result_set.h | 12 +- src/sql/ob_spi.cpp | 1910 +++++++++-------- src/sql/ob_spi.h | 191 +- src/sql/ob_sql.cpp | 526 ++++- src/sql/ob_sql.h | 56 +- src/sql/ob_sql_utils.cpp | 1 + src/sql/parser/parse_node.h | 34 +- src/sql/plan_cache/ob_cache_object.cpp | 6 +- src/sql/plan_cache/ob_cache_object.h | 5 - src/sql/plan_cache/ob_cache_object_factory.h | 5 + src/sql/plan_cache/ob_i_lib_cache_object.h | 5 + src/sql/plan_cache/ob_lib_cache_register.h | 10 +- src/sql/plan_cache/ob_pcv_set.cpp | 6 +- src/sql/plan_cache/ob_plan_cache.cpp | 211 +- src/sql/plan_cache/ob_plan_cache.h | 15 +- src/sql/plan_cache/ob_plan_cache_manager.cpp | 3 +- src/sql/plan_cache/ob_plan_cache_manager.h | 43 + src/sql/plan_cache/ob_plan_cache_struct.h | 57 +- src/sql/plan_cache/ob_plan_cache_value.cpp | 28 +- src/sql/plan_cache/ob_plan_set.cpp | 58 - src/sql/plan_cache/ob_plan_set.h | 23 - .../plan_cache/ob_sql_parameterization.cpp | 110 +- src/sql/plan_cache/ob_sql_parameterization.h | 5 +- src/sql/resolver/dcl/ob_dcl_resolver.cpp | 2 +- .../resolver/ddl/ob_alter_table_resolver.cpp | 1 + src/sql/resolver/ddl/ob_trigger_resolver.cpp | 111 +- src/sql/resolver/ddl/ob_trigger_resolver.h | 14 +- src/sql/resolver/expr/ob_raw_expr.cpp | 8 +- src/sql/resolver/expr/ob_raw_expr.h | 10 +- .../expr/ob_raw_expr_resolver_impl.cpp | 41 +- src/sql/resolver/expr/ob_raw_expr_util.cpp | 18 +- src/sql/resolver/ob_resolver_utils.cpp | 5 +- src/sql/resolver/ob_resolver_utils.h | 3 +- src/sql/udr/ob_udr_mgr.cpp | 6 +- src/sql/udr/ob_udr_utils.cpp | 16 +- .../sql/optimizer/test_optimizer_utils.cpp | 23 +- unittest/sql/optimizer/test_optimizer_utils.h | 6 +- 98 files changed, 5260 insertions(+), 2676 deletions(-) create mode 100644 src/pl/pl_cache/ob_pl_cache.cpp create mode 100644 src/pl/pl_cache/ob_pl_cache.h create mode 100644 src/pl/pl_cache/ob_pl_cache_mgr.cpp create mode 100644 src/pl/pl_cache/ob_pl_cache_mgr.h diff --git a/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h b/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h index e5899bf9a..e0253cb4d 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h +++ b/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h @@ -80,11 +80,9 @@ public: // sql execute interface virtual int execute_read(const uint64_t tenant_id, const char *sql, ObISQLClient::ReadResult &res, bool is_user_sql = false, - bool is_from_pl = false, const common::ObAddr *sql_exec_addr = nullptr) = 0; virtual int execute_read(const int64_t cluster_id, const uint64_t tenant_id, const ObString &sql, ObISQLClient::ReadResult &res, bool is_user_sql = false, - bool is_from_pl = false, const common::ObAddr *sql_exec_addr = nullptr) = 0; virtual int execute_write(const uint64_t tenant_id, const char *sql, int64_t &affected_rows, bool is_user_sql = false, diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.cpp index 5a4d076df..de77ff7b8 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.cpp @@ -399,17 +399,17 @@ int ObMySQLConnection::execute_write(const uint64_t tenant_id, const char *sql, } int ObMySQLConnection::execute_read(const int64_t cluster_id, const uint64_t tenant_id, - const ObString &sql, ObISQLClient::ReadResult &res, bool is_user_sql, bool is_from_pl, const common::ObAddr *sql_exec_addr) + const ObString &sql, ObISQLClient::ReadResult &res, bool is_user_sql, + const common::ObAddr *sql_exec_addr) { - UNUSEDx(cluster_id, tenant_id, sql, res, is_user_sql, is_from_pl, sql_exec_addr); + UNUSEDx(cluster_id, tenant_id, sql, res, is_user_sql, sql_exec_addr); return OB_NOT_SUPPORTED; } int ObMySQLConnection::execute_read(const uint64_t tenant_id, const char *sql, - ObISQLClient::ReadResult &res, bool is_user_sql, bool is_from_pl, const common::ObAddr *sql_exec_addr) + ObISQLClient::ReadResult &res, bool is_user_sql, const common::ObAddr *sql_exec_addr) { UNUSED(is_user_sql); - UNUSED(is_from_pl); UNUSED(sql_exec_addr); int ret = OB_SUCCESS; ObMySQLReadContext *read_ctx = NULL; diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.h b/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.h index 74ba9497e..5c83eb1d8 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.h +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.h @@ -68,12 +68,10 @@ public: virtual int execute_read(const uint64_t tenant_id, const char *sql, ObISQLClient::ReadResult &res, bool is_user_sql = false, - bool is_from_pl = false, const common::ObAddr *sql_exec_addr = nullptr) override; virtual int execute_read(const int64_t cluster_id, const uint64_t tenant_id, const ObString &sql, ObISQLClient::ReadResult &res, bool is_user_sql = false, - bool is_from_pl = false, const common::ObAddr *sql_exec_addr = nullptr) override; virtual int execute_write(const uint64_t tenant_id, const ObString &sql, diff --git a/deps/oblib/src/lib/oblog/ob_log_module.h b/deps/oblib/src/lib/oblog/ob_log_module.h index 6142341f9..4068b1e49 100644 --- a/deps/oblib/src/lib/oblog/ob_log_module.h +++ b/deps/oblib/src/lib/oblog/ob_log_module.h @@ -228,6 +228,7 @@ DEFINE_LOG_SUB_MOD(SPI) // service program interface DEFINE_LOG_SUB_MOD(PACK) // package DEFINE_LOG_SUB_MOD(TYPE) // type DEFINE_LOG_SUB_MOD(DEBUG) // debug +DEFINE_LOG_SUB_MOD(CACHE) // cache LOG_MOD_END(PL) } //namespace common @@ -583,7 +584,10 @@ LOG_MOD_END(PL) info_string, ##args) #define _PL_DEBUG_LOG(level, _fmt_, args...) _OB_SUB_MOD_LOG(PL, DEBUG, level, \ _fmt_, ##args) - +#define PL_CACHE_LOG(level, info_string, args...) OB_SUB_MOD_LOG(PL, CACHE, level, \ + info_string, ##args) +#define _PL_CACHE_LOG(level, _fmt_, args...) _OB_SUB_MOD_LOG(PL, CACHE, level, \ + _fmt_, ##args) #define RPC_FRAME_LOG(level, _fmt_, args...) \ diff --git a/src/objit/include/objit/common/ob_item_type.h b/src/objit/include/objit/common/ob_item_type.h index 698f6fe7a..72eb4fe9d 100755 --- a/src/objit/include/objit/common/ob_item_type.h +++ b/src/objit/include/objit/common/ob_item_type.h @@ -2162,6 +2162,7 @@ typedef enum ObItemType T_SINGLE_COLUMN_GROUP, T_NORMAL_COLUMN_GROUP, T_TRACE_FORMAT, + T_TG_ALTER_OPTIONS, T_MAX //Attention: add a new type before T_MAX } ObItemType; diff --git a/src/observer/mysql/obmp_stmt_execute.cpp b/src/observer/mysql/obmp_stmt_execute.cpp index b9179825b..cd06ffbbc 100644 --- a/src/observer/mysql/obmp_stmt_execute.cpp +++ b/src/observer/mysql/obmp_stmt_execute.cpp @@ -1000,7 +1000,7 @@ int ObMPStmtExecute::execute_response(ObSQLSessionInfo &session, OZ (session.make_dbms_cursor(cursor, stmt_id_)); CK (OB_NOT_NULL(cursor)); OX (cursor->set_stmt_type(stmt::T_SELECT)); - OX (cursor->set_stmt_id(inner_stmt_id)); + OX (cursor->set_ps_sql(ctx_.cur_sql_)); OZ (session.ps_use_stream_result_set(use_stream)); if (use_stream) { OX (cursor->set_streaming()); diff --git a/src/observer/mysql/obmp_stmt_prexecute.cpp b/src/observer/mysql/obmp_stmt_prexecute.cpp index cea7dccff..a199ac8c4 100644 --- a/src/observer/mysql/obmp_stmt_prexecute.cpp +++ b/src/observer/mysql/obmp_stmt_prexecute.cpp @@ -418,7 +418,7 @@ int ObMPStmtPrexecute::execute_response(ObSQLSessionInfo &session, CK (OB_NOT_NULL(cursor)); OX (cursor->set_stmt_type(stmt::T_SELECT)); OZ (session.get_inner_ps_stmt_id(stmt_id_, inner_stmt_id)); - OX (cursor->set_stmt_id(inner_stmt_id)); + OX (cursor->set_ps_sql(sql_)); OZ (session.ps_use_stream_result_set(use_stream)); if (use_stream) { OX (cursor->set_streaming()); diff --git a/src/observer/ob_inner_sql_connection.cpp b/src/observer/ob_inner_sql_connection.cpp index 4637dbde7..0bfa1a039 100644 --- a/src/observer/ob_inner_sql_connection.cpp +++ b/src/observer/ob_inner_sql_connection.cpp @@ -412,7 +412,6 @@ int ObInnerSQLConnection::init_result(ObInnerSQLResult &res, pl::ObPLBlockNS *secondary_namespace, bool is_prepare_protocol, bool is_prepare_stage, - bool is_from_pl, bool is_dynamic_sql, bool is_dbms_sql, bool is_cursor) @@ -427,8 +426,7 @@ int ObInnerSQLConnection::init_result(ObInnerSQLResult &res, res.sql_ctx().retry_times_ = retry_cnt; res.sql_ctx().session_info_ = &get_session(); res.sql_ctx().disable_privilege_check_ = OB_SYS_TENANT_ID == res.sql_ctx().session_info_->get_priv_tenant_id() - ? PRIV_CHECK_FLAG_DISABLE - : (is_from_pl ? PRIV_CHECK_FLAG_IN_PL : PRIV_CHECK_FLAG_DISABLE); + ? PRIV_CHECK_FLAG_DISABLE : PRIV_CHECK_FLAG_DISABLE; res.sql_ctx().secondary_namespace_ = secondary_namespace; res.sql_ctx().is_prepare_protocol_ = is_prepare_protocol; res.sql_ctx().is_prepare_stage_ = is_prepare_stage; @@ -450,8 +448,7 @@ int ObInnerSQLConnection::process_retry(ObInnerSQLResult &res, int last_ret, int64_t abs_timeout_us, bool &need_retry, - int64_t retry_cnt, - bool is_from_pl) + int64_t retry_cnt) { UNUSED(abs_timeout_us); UNUSED(retry_cnt); @@ -460,7 +457,7 @@ int ObInnerSQLConnection::process_retry(ObInnerSQLResult &res, bool is_inner_sql = true; retry_ctrl_.test_and_save_retry_state(GCTX, res.sql_ctx(), res.result_set(), last_ret, client_ret, - force_local_retry, is_inner_sql, is_from_pl); + force_local_retry, is_inner_sql); need_retry = (ObQueryRetryType::RETRY_TYPE_LOCAL == retry_ctrl_.get_retry_type()); return client_ret; } @@ -491,26 +488,27 @@ private: int64_t execute_end_timestamp_; }; -int ObInnerSQLConnection::process_record(ObInnerSQLResult &res, +int ObInnerSQLConnection::process_record(sql::ObResultSet &result_set, + sql::ObSqlCtx &sql_ctx, sql::ObSQLSessionInfo &session, ObITimeRecord &time_record, int last_ret, int64_t execution_id, int64_t ps_stmt_id, - int64_t routine_id, ObWaitEventDesc &max_wait_desc, ObWaitEventStat &total_wait_desc, ObExecRecord &exec_record, ObExecTimestamp &exec_timestamp, + bool has_tenant_resource, + const ObString &ps_sql, bool is_from_pl) { int ret = OB_SUCCESS; - UNUSED(routine_id); - if (res.has_tenant_resource()) { - sql::ObResultSet &result_set = res.result_set(); + + if (has_tenant_resource) { ObAuditRecordData &audit_record = session.get_raw_audit_record(); audit_record.try_cnt_++; - ObPhysicalPlan *plan = res.result_set().get_physical_plan(); + ObPhysicalPlan *plan = result_set.get_physical_plan(); audit_record.seq_ = 0; //don't use now audit_record.status_ = (0 == last_ret || OB_ITER_END == last_ret) ? obmysql::REQUEST_SUCC : last_ret; @@ -520,11 +518,15 @@ int ObInnerSQLConnection::process_record(ObInnerSQLResult &res, audit_record.user_group_ = THIS_WORKER.get_group_id(); audit_record.execution_id_ = execution_id; audit_record.ps_stmt_id_ = ps_stmt_id; - MEMCPY(audit_record.sql_id_, res.sql_ctx().sql_id_, (int32_t)sizeof(audit_record.sql_id_)); - audit_record.affected_rows_ = res.result_set().get_affected_rows(); - audit_record.return_rows_ = res.result_set().get_return_rows(); - if (NULL != res.result_set().get_exec_context().get_task_executor_ctx()) { - audit_record.partition_cnt_ = res.result_set().get_exec_context() + if (ps_sql.length() != 0) { + audit_record.sql_ = const_cast(ps_sql.ptr()); + audit_record.sql_len_ = min(ps_sql.length(), OB_MAX_SQL_LENGTH); + } + MEMCPY(audit_record.sql_id_, sql_ctx.sql_id_, (int32_t)sizeof(audit_record.sql_id_)); + audit_record.affected_rows_ = result_set.get_affected_rows(); + audit_record.return_rows_ = result_set.get_return_rows(); + if (NULL != result_set.get_exec_context().get_task_executor_ctx()) { + audit_record.partition_cnt_ = result_set.get_exec_context() .get_das_ctx() .get_related_tablet_cnt(); } @@ -534,16 +536,16 @@ int ObInnerSQLConnection::process_record(ObInnerSQLResult &res, exec_record.wait_time_end_ = total_wait_desc.time_waited_; exec_record.wait_count_end_ = total_wait_desc.total_waits_; - if (NULL != res.result_set().get_physical_plan()) { - audit_record.plan_type_ = res.result_set().get_physical_plan()->get_plan_type(); - audit_record.table_scan_ = res.result_set().get_physical_plan()->contain_table_scan(); - audit_record.plan_id_ = res.result_set().get_physical_plan()->get_plan_id(); - audit_record.plan_hash_ = res.result_set().get_physical_plan()->get_plan_hash_value(); + if (NULL != result_set.get_physical_plan()) { + audit_record.plan_type_ = result_set.get_physical_plan()->get_plan_type(); + audit_record.table_scan_ = result_set.get_physical_plan()->contain_table_scan(); + audit_record.plan_id_ = result_set.get_physical_plan()->get_plan_id(); + audit_record.plan_hash_ = result_set.get_physical_plan()->get_plan_hash_value(); } audit_record.is_executor_rpc_ = false; - audit_record.is_inner_sql_ = true; - audit_record.is_hit_plan_cache_ = res.result_set().get_is_from_plan_cache(); + audit_record.is_inner_sql_ = !is_from_pl; + audit_record.is_hit_plan_cache_ = result_set.get_is_from_plan_cache(); audit_record.is_multi_stmt_ = false; //是否是multi sql bool first_record = (1 == audit_record.try_cnt_); @@ -552,7 +554,7 @@ int ObInnerSQLConnection::process_record(ObInnerSQLResult &res, audit_record.exec_record_ = exec_record; ObIArray *table_row_count_list = NULL; - ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(res.result_set().get_exec_context()); + ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(result_set.get_exec_context()); if (NULL != plan_ctx) { audit_record.consistency_level_ = plan_ctx->get_consistency_level(); audit_record.table_scan_stat_ = plan_ctx->get_table_scan_stat(); @@ -565,23 +567,25 @@ int ObInnerSQLConnection::process_record(ObInnerSQLResult &res, //update v$sql statistics if (OB_SUCC(last_ret) && session.get_local_ob_enable_plan_cache()) { if (NULL != plan) { - if (!(res.sql_ctx().self_add_plan_) && res.sql_ctx().plan_cache_hit_) { + if (!(sql_ctx.self_add_plan_) && sql_ctx.plan_cache_hit_) { plan->update_plan_stat(audit_record, - false, // false mean not first update plan stat - res.result_set().get_exec_context().get_is_evolution(), - table_row_count_list); - } else if (res.sql_ctx().self_add_plan_ && !res.sql_ctx().plan_cache_hit_) { + false, // false mean not first update plan stat + result_set.get_exec_context().get_is_evolution(), + table_row_count_list); + } else if (sql_ctx.self_add_plan_ && !sql_ctx.plan_cache_hit_) { plan->update_plan_stat(audit_record, - true, - res.result_set().get_exec_context().get_is_evolution(), - table_row_count_list); + true, + result_set.get_exec_context().get_is_evolution(), + table_row_count_list); } } } record_stat(session, result_set.get_stmt_type(), is_from_pl); - ObSQLUtils::handle_audit_record(false, sql::PSCursor == exec_timestamp.exec_type_ ? EXECUTE_PS_EXECUTE - : is_from_pl ? EXECUTE_PL_EXECUTE : EXECUTE_INNER, session); + ObSQLUtils::handle_audit_record(false, sql::PSCursor == exec_timestamp.exec_type_ + ? EXECUTE_PS_EXECUTE : + (is_from_pl ? EXECUTE_PL_EXECUTE : EXECUTE_INNER), + session); } return ret; } @@ -645,8 +649,7 @@ int ObInnerSQLConnection::do_query(sqlclient::ObIExecutor &executor, ObInnerSQLR int ObInnerSQLConnection::query(sqlclient::ObIExecutor &executor, ObInnerSQLResult &res, - ObVirtualTableIteratorFactory *vt_iter_factory, - bool is_from_pl) + ObVirtualTableIteratorFactory *vt_iter_factory) { int ret = OB_SUCCESS; lib::CompatModeGuard g(get_compat_mode()); @@ -656,9 +659,7 @@ int ObInnerSQLConnection::query(sqlclient::ObIExecutor &executor, exec_timestamp.exec_type_ = sql::InnerSql; const ObGlobalContext &gctx = ObServer::get_instance().get_gctx(); int64_t start_time = ObTimeUtility::current_time(); - if (!is_from_pl) { - get_session().set_query_start_time(start_time); //FIXME 暂时写成这样 - } + get_session().set_query_start_time(start_time); //FIXME 暂时写成这样 get_session().set_trans_type(transaction::ObTxClass::SYS); int64_t abs_timeout_us = 0; int64_t execution_id = 0; @@ -680,7 +681,7 @@ int ObInnerSQLConnection::query(sqlclient::ObIExecutor &executor, ret = OB_REF_NUM_NOT_ZERO; LOG_ERROR("connection still be referred by previous sql result, can not execute sql now", K(ret), K(executor)); - } else if (OB_FAIL(set_timeout(abs_timeout_us, is_from_pl))) { + } else if (OB_FAIL(set_timeout(abs_timeout_us))) { LOG_WARN("set timeout failed", K(ret)); } else if (OB_ISNULL(ob_sql_)) { ret = OB_ERR_UNEXPECTED; @@ -706,7 +707,7 @@ int ObInnerSQLConnection::query(sqlclient::ObIExecutor &executor, for (int64_t retry_cnt = 0; need_retry; ++retry_cnt) { need_retry = false; retry_info.clear_state_before_each_retry(); - res.set_is_read((is_from_pl && lib::is_mysql_mode()) ? false : true); + res.set_is_read(true); if (retry_cnt > 0) { // reset result set bool is_user_sql = res.result_set().is_user_sql(); res.~ObInnerSQLResult(); @@ -715,7 +716,7 @@ int ObInnerSQLConnection::query(sqlclient::ObIExecutor &executor, LOG_WARN("fail to init result set", K(ret)); } else { res.result_set().set_user_sql(is_user_sql); - res.set_is_read((is_from_pl && lib::is_mysql_mode()) ? false : true); + res.set_is_read(true); } } get_session().get_raw_audit_record().request_memory_used_ = 0; @@ -728,9 +729,7 @@ int ObInnerSQLConnection::query(sqlclient::ObIExecutor &executor, ObWaitEventStat total_wait_desc; const bool enable_perf_event = lib::is_diagnose_info_enabled(); const bool enable_sql_audit = - GCONF.enable_sql_audit - && get_session().get_local_ob_enable_sql_audit() - && !is_from_pl; // PL的audit在SPI中记录 + GCONF.enable_sql_audit && get_session().get_local_ob_enable_sql_audit(); { ObMaxWaitGuard max_wait_guard(enable_perf_event ? &max_wait_desc : NULL); ObTotalWaitGuard total_wait_guard(enable_perf_event ? &total_wait_desc : NULL); @@ -747,7 +746,7 @@ int ObInnerSQLConnection::query(sqlclient::ObIExecutor &executor, } else if (OB_FAIL(gctx.schema_service_->get_tenant_schema_guard(tenant_id, res.schema_guard_))) { LOG_WARN("get schema guard failed", K(ret)); } else if (OB_FAIL(init_result(res, vt_iter_factory, retry_cnt, - res.schema_guard_, NULL, false, false, is_from_pl))) { + res.schema_guard_, NULL, false, false))) { LOG_WARN("failed to init result", K(ret)); } else if (OB_FAIL(res.schema_guard_.get_schema_version(tenant_id, local_tenant_schema_version))) { LOG_WARN("get tenant schema version failed", K(ret), K(ob_sql_)); @@ -764,7 +763,7 @@ int ObInnerSQLConnection::query(sqlclient::ObIExecutor &executor, } else if (OB_FAIL(SMART_CALL(do_query(executor, res)))) { ret_code = ret; LOG_WARN("execute failed", K(ret), K(tenant_id), K(executor), K(retry_cnt)); - ret = process_retry(res, ret, abs_timeout_us, need_retry, retry_cnt, is_from_pl); + ret = process_retry(res, ret, abs_timeout_us, need_retry, retry_cnt); // moved here from ObInnerSQLConnection::do_query() -> ObInnerSQLResult::open(). int close_ret = res.force_close(); if (OB_SUCCESS != close_ret) { @@ -787,11 +786,13 @@ int ObInnerSQLConnection::query(sqlclient::ObIExecutor &executor, if (enable_sql_audit && res.is_inited()) { ObInnerSQLTimeRecord time_record(get_session()); + ObString dummy_ps_sql; time_record.set_execute_start_timestamp(execute_start_timestamp_); time_record.set_execute_end_timestamp(execute_end_timestamp_); - int record_ret = process_record(res, get_session(), time_record, ret, - execution_id, OB_INVALID_ID, OB_INVALID_ID, - max_wait_desc, total_wait_desc, exec_record, exec_timestamp); + int record_ret = process_record(res.result_set(), res.sql_ctx(), get_session(), time_record, ret, + execution_id, OB_INVALID_ID, + max_wait_desc, total_wait_desc, exec_record, exec_timestamp, + res.has_tenant_resource(), dummy_ps_sql); if (OB_SUCCESS != record_ret) { LOG_WARN("failed to process record", K(executor), K(record_ret), K(ret)); } @@ -823,333 +824,6 @@ int ObInnerSQLConnection::query(sqlclient::ObIExecutor &executor, return ret; } -int ObInnerSQLConnection::do_prepare(const common::ObString &sql, ObInnerSQLResult &res) -{ - int ret = OB_SUCCESS; - WITH_CONTEXT(res.mem_context_) { - if (!inited_) { - ret = OB_NOT_INIT; - LOG_WARN("not init", K(ret)); - } else if (sql.empty()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(ret), K(sql)); - } else if (OB_FAIL(ob_sql_->stmt_prepare(sql, res.sql_ctx(), res.result_set()))) { - LOG_WARN("sql execute failed", K(ret), K(sql)); - } - } - return ret; -} - -int ObInnerSQLConnection::prepare(const ObString &sql, - pl::ObPLBlockNS *secondary_namespace, - bool is_dynamic_sql, - bool is_dbms_sql, - bool is_cursor, - ObInnerSQLResult &res, - ObVirtualTableIteratorFactory *vt_iter_factory) -{ - int ret = OB_SUCCESS; - FLTSpanGuard(inner_prepare); - ObExecRecord exec_record; - ObExecTimestamp exec_timestamp; - int64_t execution_id = 0; - exec_timestamp.exec_type_ = sql::InnerSql; - const ObGlobalContext &gctx = ObServer::get_instance().get_gctx(); - int64_t old_query_start_time = get_session().get_query_start_time(); - get_session().set_query_start_time(ObTimeUtility::current_time()); //FIXME 暂时写成这样 - get_session().set_trans_type(transaction::ObTxClass::SYS); - // get_session().store_query_string(sql); - int64_t abs_timeout_us = 0; - const uint64_t* trace_id_val = ObCurTraceId::get(); - bool is_trace_id_init = true; - ObQueryRetryInfo &retry_info = get_session().get_retry_info_for_update(); - if (0 == trace_id_val[0]) { - is_trace_id_init = false; - common::ObCurTraceId::init(observer::ObServer::get_instance().get_self()); - } - - // backup && restore worker/session timeout. - TimeoutGuard timeout_guard(*this); - - // %vt_iter_factory may be NULL - if (!inited_) { - ret = OB_NOT_INIT; - LOG_WARN("not init", K(ret)); - } else if (sql.empty()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(ret), K(sql)); - } else if (NULL != ref_ctx_) { - ret = OB_REF_NUM_NOT_ZERO; - LOG_ERROR("connection still be referred by previous sql result, can not execute sql now", - K(ret), K(sql)); - } else if (OB_FAIL(set_timeout(abs_timeout_us, true))) { - LOG_WARN("set timeout failed", K(ret)); - } else if (OB_ISNULL(ob_sql_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid sql engine", K(ret), K(ob_sql_)); - } else if (OB_UNLIKELY(retry_info.is_inited())) { - if (is_inner_session()) { - ret = OB_ERR_UNEXPECTED; - LOG_ERROR("retry info is inited", K(ret), K(retry_info), K(sql)); - } - } else if (OB_FAIL(retry_info.init())) { - LOG_WARN("fail to init retry info", K(ret), K(retry_info), K(sql)); - } - if (OB_SUCC(ret)) { - execution_id = ob_sql_->get_execution_id(); - retry_ctrl_.clear_state_before_each_retry(get_session().get_retry_info_for_update()); - retry_ctrl_.reset_retry_times(); - bool need_retry = true; - for (int64_t retry_cnt = 0; need_retry; ++retry_cnt) { - need_retry = false; - retry_info.clear_state_before_each_retry(); - if (retry_cnt > 0) { // reset result set - res.~ObInnerSQLResult(); - new (&res) ObInnerSQLResult(get_session()); - ret = res.init(); - } - const uint64_t tenant_id = get_session().get_effective_tenant_id(); - if (OB_FAIL(gctx.schema_service_->get_tenant_schema_guard(tenant_id, res.schema_guard_))) { - LOG_WARN("get schema guard failed", K(ret)); - } else if (OB_FAIL(init_result(res, vt_iter_factory, retry_cnt, - res.schema_guard_, secondary_namespace, true, true, true, - is_dynamic_sql, is_dbms_sql, is_cursor))) { - LOG_WARN("failed to init result", K(ret)); - } else if (OB_FAIL(do_prepare(sql, res))) { - LOG_WARN("execute sql failed", K(ret), K(sql), K(retry_cnt)); - ret = process_retry(res, ret, abs_timeout_us, need_retry, retry_cnt, true); - } - } - } - if (res.is_inited()) { - int aret = process_final(sql, res, ret); - if (OB_SUCCESS != aret) { - LOG_WARN("failed to process final", K(sql), K(aret), K(ret)); - } - } - if (false == is_trace_id_init) { - common::ObCurTraceId::reset(); - } - if (is_inner_session()) { - retry_info.reset(); - } - get_session().set_query_start_time(old_query_start_time); - - return ret; -} - -int ObInnerSQLConnection::do_execute(const ParamStore ¶ms, ObInnerSQLResult &res) -{ - int ret = OB_SUCCESS; - WITH_CONTEXT(res.mem_context_) { - if (!inited_) { - ret = OB_NOT_INIT; - LOG_WARN("not init", K(ret)); - } else if (OB_ISNULL(ob_sql_)) { - ret = OB_ERR_UNEXPECTED; - LOG_ERROR("ob_sql_ is NULL", K(ret)); - } else if (OB_FAIL(ob_sql_->stmt_execute(res.result_set().get_statement_id(), - res.result_set().get_stmt_type(), - params, - res.sql_ctx(), - res.result_set(), - true /* is_inner_sql */))) { - LOG_WARN("sql execute failed", K(res.result_set().get_statement_id()), K(ret)); - } else { - ObSQLSessionInfo &session = res.result_set().get_session(); - if (OB_ISNULL(res.sql_ctx().schema_guard_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("schema guard is null"); - } else if (OB_FAIL(session.update_query_sensitive_system_variable(*(res.sql_ctx().schema_guard_)))) { - LOG_WARN("update query affacted system variable failed", K(ret)); - } else if (OB_UNLIKELY(NULL != sql_modifier_) - && OB_FAIL(sql_modifier_->modify(res.result_set()))) { - LOG_WARN("fail modify sql", K(res.result_set().get_statement_name()), K(ret)); - } else if (OB_FAIL(res.open())) { - LOG_WARN("result set open failed", K(res.result_set().get_statement_id()), K(ret)); - } else { /*do nothing*/ } - } - } - return ret; -} - -int ObInnerSQLConnection::execute(ParamStore ¶ms, - ObInnerSQLResult &res, - ObVirtualTableIteratorFactory *vt_iter_factory, - bool is_from_pl, - bool is_dynamic, - bool is_forall, - int64_t array_binding_count) -{ - int ret = OB_SUCCESS; - ObExecRecord exec_record; - ObExecTimestamp exec_timestamp; - exec_timestamp.exec_type_ = sql::InnerSql; - const ObGlobalContext &gctx = ObServer::get_instance().get_gctx(); - const ObString &sql = res.result_set().get_statement_name(); - int64_t start_time = ObTimeUtility::current_time(); - if (!is_from_pl) { - get_session().set_query_start_time(start_time); //FIXME 暂时写成这样 - } - get_session().set_trans_type(transaction::ObTxClass::SYS); - int64_t abs_timeout_us = 0; - int64_t execution_id = 0; - uint64_t stmt_id = res.result_set().get_statement_id(); - sql::stmt::StmtType stmt_type = res.result_set().get_stmt_type(); - const uint64_t* trace_id_val = ObCurTraceId::get(); - bool is_trace_id_init = true; - ObQueryRetryInfo &retry_info = get_session().get_retry_info_for_update(); - if (0 == trace_id_val[0]) { - is_trace_id_init = false; - common::ObCurTraceId::init(observer::ObServer::get_instance().get_self()); - } - - // backup && restore worker/session timeout. - TimeoutGuard timeout_guard(*this); - - // %vt_iter_factory may be NULL - if (!inited_) { - ret = OB_NOT_INIT; - LOG_WARN("not init", K(ret)); - } else if (NULL != ref_ctx_) { - ret = OB_REF_NUM_NOT_ZERO; - LOG_ERROR("connection still be referred by previous sql result, can not execute sql now", - K(ret), K(sql)); - } else if (OB_FAIL(set_timeout(abs_timeout_us, is_from_pl))) { - LOG_WARN("set timeout failed", K(ret)); - } else if (OB_ISNULL(ob_sql_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid sql engine", K(ret), K(ob_sql_)); - } else if (OB_UNLIKELY(retry_info.is_inited())) { - if (is_inner_session()) { - ret = OB_ERR_UNEXPECTED; - LOG_ERROR("retry info is inited", K(ret), K(retry_info), K(sql)); - } - } else if (OB_FAIL(retry_info.init())) { - LOG_WARN("fail to init retry info", K(ret), K(retry_info), K(sql)); - } - if (OB_SUCC(ret)) { - execution_id = ob_sql_->get_execution_id(); - bool need_retry = true; - retry_ctrl_.clear_state_before_each_retry(get_session().get_retry_info_for_update()); - retry_ctrl_.reset_retry_times(); - for (int64_t retry_cnt = 0; need_retry; ++retry_cnt) { - need_retry = false; - retry_info.clear_state_before_each_retry(); - res.set_is_read((is_from_pl && lib::is_mysql_mode()) ? false : true); - if (retry_cnt > 0) { // reset result set - res.~ObInnerSQLResult(); - new (&res) ObInnerSQLResult(get_session()); - ret = res.init(); - if (OB_SUCC(ret)) { - res.result_set().set_ps_protocol(); - res.result_set().set_statement_id(stmt_id); - res.result_set().set_stmt_type(stmt_type); - res.set_is_read((is_from_pl && lib::is_mysql_mode()) ? false : true); - } - } - get_session().get_raw_audit_record().request_memory_used_ = 0; - observer::ObProcessMallocCallback pmcb(0, - get_session().get_raw_audit_record().request_memory_used_); - ObMallocCallbackGuard guard(pmcb); - ObWaitEventDesc max_wait_desc; - ObWaitEventStat total_wait_desc; - const bool enable_perf_event = lib::is_diagnose_info_enabled(); - const bool enable_sql_audit = - GCONF.enable_sql_audit - && get_session().get_local_ob_enable_sql_audit() - && !is_from_pl; // PL中的SQL语句Audit在SPI中记录 - { - ObMaxWaitGuard max_wait_guard(enable_perf_event ? &max_wait_desc : NULL); - ObTotalWaitGuard total_wait_guard(enable_perf_event ? &total_wait_desc : NULL); - - //监控项统计开始 - if (enable_sql_audit) { - exec_record.record_start(); - } - if (OB_SUCC(ret) && is_forall) { - res.sql_ctx().multi_stmt_item_.set_ps_mode(true); - res.sql_ctx().multi_stmt_item_.set_ab_cnt(array_binding_count); - } - - const uint64_t tenant_id = get_session().get_effective_tenant_id(); - int ret_code = OB_SUCCESS; - if (OB_FAIL(ret)) { - } else if (OB_FAIL(gctx.schema_service_->get_tenant_schema_guard(tenant_id, res.schema_guard_))) { - LOG_WARN("get schema guard failed", K(ret)); - } else if (OB_FAIL(init_result(res, vt_iter_factory, retry_cnt, res.schema_guard_, NULL, - false, false, is_from_pl, is_dynamic))) { - LOG_WARN("failed to init result", K(ret)); - } else if (OB_FAIL(do_execute(params, res))) { - LOG_WARN("execute sql failed", K(ret), K(sql), K(retry_cnt)); - ret_code = ret; - ret = process_retry(res, ret, abs_timeout_us, need_retry, retry_cnt, is_from_pl); - // moved here from ObInnerSQLConnection::do_execute() -> ObInnerSQLResult::open(). - int close_ret = res.force_close(); - if (OB_SUCCESS != close_ret) { - LOG_WARN("failed to close result", K(close_ret), K(ret), K(sql)); - } - } - if (OB_NOT_NULL(res.get_result_set())) { - ObSQLSessionInfo &session = res.result_set().get_session(); - session.set_session_in_retry(need_retry, ret_code); - LOG_DEBUG("after process_retry", K(retry_cnt), K(ret), K(need_retry), - K(inner_session_), KP(&inner_session_), - K(inner_session_.get_is_in_retry()), - K(session.get_is_in_retry_for_dup_tbl()), - K(session), K(&session), K(session.get_is_in_retry())); - } - - execute_start_timestamp_ = (res.get_execute_start_ts() > 0) - ? res.get_execute_start_ts() - : ObTimeUtility::current_time(); - execute_end_timestamp_ = (res.get_execute_end_ts() > 0) - ? res.get_execute_end_ts() - : ObTimeUtility::current_time(); - //监控项统计结束 - if (enable_sql_audit) { - exec_record.record_end(); - } - } - - if (enable_sql_audit && res.is_inited()) { - ObInnerSQLTimeRecord time_record(get_session()); - time_record.set_execute_start_timestamp(execute_start_timestamp_); - time_record.set_execute_end_timestamp(execute_end_timestamp_); - int record_ret = process_record(res, get_session(), time_record, ret, - execution_id, stmt_id, OB_INVALID_ID, - max_wait_desc, total_wait_desc, exec_record, exec_timestamp); - if (OB_SUCCESS != record_ret) { - LOG_WARN("failed to process record", K(sql), K(record_ret), K(ret)); - } - } - - - if (get_session().get_in_transaction()) { - if (ObStmt::is_dml_write_stmt(stmt_type)) { - get_session().set_has_inner_dml_write(true); - } - } - } - } - if (res.is_inited()) { - int aret = process_final(sql, res, ret); - if (OB_SUCCESS != aret) { - LOG_WARN("failed to process final", K(sql), K(aret), K(ret)); - } - } - - if (false == is_trace_id_init) { - common::ObCurTraceId::reset(); - } - - if (is_inner_session()) { - retry_info.reset(); - } - - return ret; -} - common::sqlclient::ObCommonServerConnectionPool *ObInnerSQLConnection::get_common_server_pool() { return NULL; @@ -1170,7 +844,7 @@ int ObInnerSQLConnection::retry_while_no_tenant_resource(const int64_t cluster_i get_session().set_query_start_time(start_time); TimeoutGuard timeout_guard(*this); // backup && restore worker/session timeout. - if (OB_FAIL(set_timeout(abs_timeout_us, false))) { + if (OB_FAIL(set_timeout(abs_timeout_us))) { LOG_WARN("set timeout failed", K(ret)); } else { do { @@ -1948,7 +1622,7 @@ int ObInnerSQLConnection::get_session_timeout_for_rpc(int64_t &query_timeout, in int64_t abs_timeout_us = 0; int64_t start_time = ObTimeUtility::current_time(); get_session().set_query_start_time(start_time); - if (OB_FAIL(set_timeout(abs_timeout_us, false))) { + if (OB_FAIL(set_timeout(abs_timeout_us))) { LOG_WARN("set timeout failed", K(ret)); } else if (OB_FAIL(get_session().get_query_timeout(query_timeout)) || OB_FAIL(get_session().get_tx_timeout(trx_timeout))) { @@ -1961,10 +1635,9 @@ int ObInnerSQLConnection::execute_read(const uint64_t tenant_id, const char *sql, ObISQLClient::ReadResult &res, bool is_user_sql, - bool is_from_pl, const common::ObAddr *sql_exec_addr) { - return execute_read(GCONF.cluster_id, tenant_id, sql, res, is_user_sql, is_from_pl, sql_exec_addr); + return execute_read(GCONF.cluster_id, tenant_id, sql, res, is_user_sql, sql_exec_addr); } int ObInnerSQLConnection::execute_read(const int64_t cluster_id, @@ -1972,12 +1645,11 @@ int ObInnerSQLConnection::execute_read(const int64_t cluster_id, const ObString &sql, ObISQLClient::ReadResult &res, bool is_user_sql, - bool is_from_pl, const common::ObAddr *sql_exec_addr) { int ret = OB_SUCCESS; - auto function = [&]() { return execute_read_inner(cluster_id, tenant_id, sql, res, is_user_sql, is_from_pl, sql_exec_addr); }; + auto function = [&]() { return execute_read_inner(cluster_id, tenant_id, sql, res, is_user_sql, sql_exec_addr); }; if (OB_FAIL(retry_while_no_tenant_resource(cluster_id, tenant_id, function))) { LOG_WARN("execute_read failed", K(ret), K(cluster_id), K(tenant_id)); } @@ -2009,7 +1681,6 @@ int ObInnerSQLConnection::execute_read_inner(const int64_t cluster_id, const ObString &sql, ObISQLClient::ReadResult &res, bool is_user_sql, - bool is_from_pl, const common::ObAddr *sql_exec_addr) { int ret = OB_SUCCESS; @@ -2039,7 +1710,7 @@ int ObInnerSQLConnection::execute_read_inner(const int64_t cluster_id, } else if (local_execute) { read_ctx->get_result().result_set().set_user_sql(is_user_sql); if (OB_FAIL(query(executor, read_ctx->get_result(), - &read_ctx->get_vt_iter_factory(), is_from_pl))) { + &read_ctx->get_vt_iter_factory()))) { LOG_WARN("execute sql failed", K(ret), K(tenant_id), K(sql)); } } else if (is_resource_conn()) { @@ -2117,8 +1788,7 @@ int ObInnerSQLConnection::execute_read_inner(const int64_t cluster_id, handler->get_result()->get_stmt_type()))) { } else if (OB_FAIL(read_ctx->get_result().open())) { LOG_WARN("result set open failed", K(ret)); - } else if (FALSE_IT(read_ctx->get_result().set_is_read( - (is_from_pl && lib::is_mysql_mode()) ? false : true))) { + } else if (FALSE_IT(read_ctx->get_result().set_is_read(true))) { } else if (FALSE_IT(get_session().set_trans_type(transaction::ObTxClass::SYS))) { } } @@ -2148,7 +1818,7 @@ int ObInnerSQLConnection::nonblock_get_leader( if (OB_ISNULL(GCTX.location_service_)) { ret = OB_NOT_INIT; LOG_WARN("location cache is NULL", K(ret)); - } else if (OB_FAIL(set_timeout(abs_timeout_us, false))) { + } else if (OB_FAIL(set_timeout(abs_timeout_us))) { LOG_WARN("set timeout failed", K(ret)); } else { const int64_t retry_interval_us = 200 * 1000; @@ -2209,97 +1879,6 @@ int ObInnerSQLConnection::execute( return ret; } - -int ObInnerSQLConnection::prepare(const uint64_t tenant_id, - const ObString &sql, - pl::ObPLBlockNS *secondary_namespace, - bool is_dynamic_sql, - bool is_dbms_sql, - bool is_cursor, - ObISQLClient::ReadResult &res) -{ - int ret = OB_SUCCESS; - ObInnerSQLReadContext *read_ctx = NULL; - if (!inited_) { - ret = OB_NOT_INIT; - LOG_WARN("connection not inited", K(ret)); - } else if (NULL == sql || '\0' == *sql || OB_INVALID_ID == tenant_id) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(ret), K(sql), K(tenant_id)); - } else if (OB_FAIL(switch_tenant(tenant_id))) { - LOG_WARN("switch tenant_id failed", K(ret), K(tenant_id)); - } else if (OB_FAIL(res.create_handler(read_ctx, *this))) { - LOG_WARN("create result handler failed", K(ret)); - } else if (OB_FAIL(read_ctx->get_result().init())) { - LOG_WARN("init result set", K(ret)); - } else if (OB_FAIL(prepare(sql, - secondary_namespace, - is_dynamic_sql, - is_dbms_sql, - is_cursor, - read_ctx->get_result(), - &read_ctx->get_vt_iter_factory()))) { - LOG_WARN("execute sql failed", K(ret), K(tenant_id), K(sql)); - } - if (OB_SUCC(ret)) { - ref_ctx_ = read_ctx; - } - return ret; -} - -int ObInnerSQLConnection::execute(const uint64_t tenant_id, - const ObPsStmtId stmt_id, - const stmt::StmtType stmt_type, - ParamStore ¶ms, - ObISQLClient::ReadResult &res, - bool is_from_pl, - bool is_dynamic, - bool is_forall, - int64_t array_binding_count) -{ - int ret = OB_SUCCESS; - FLTSpanGuard(inner_execute); - ObInnerSQLReadContext *read_ctx = NULL; - ObPsStmtInfoGuard ps_guard; - ObPsStmtInfo *ps_info = NULL; - ObPsCache *ps_cache = get_session().get_ps_cache(); - if (!inited_) { - ret = OB_NOT_INIT; - LOG_WARN("connection not inited", K(ret)); - } else if (OB_INVALID_ID == tenant_id) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(ret), K(stmt_id), K(tenant_id)); - } else if (OB_FAIL(switch_tenant(tenant_id))) { - LOG_WARN("switch tenant_id failed", K(ret), K(tenant_id)); - } else if (OB_FAIL(res.create_handler(read_ctx, *this))) { - LOG_WARN("create result handler failed", K(ret)); - } else if (OB_FAIL(read_ctx->get_result().init())) { - LOG_WARN("init result set", K(ret)); - } else if (OB_ISNULL(ps_cache)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("ps cache is null", K(ret), K(ps_cache)); - } else if (OB_FAIL(ps_cache->get_stmt_info_guard(stmt_id, ps_guard))) { - LOG_WARN("get stmt info guard failed", K(ret), K(stmt_id)); - } else if (OB_ISNULL(ps_info = ps_guard.get_stmt_info())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get stmt info is null", K(ret), K(ps_info), K(stmt_id)); - } else { - read_ctx->get_result().result_set().set_ps_protocol(); - read_ctx->get_result().result_set().set_statement_id(stmt_id); - read_ctx->get_result().result_set().set_stmt_type(stmt_type); - get_session().store_query_string(ps_info->get_ps_sql()); - - if (OB_FAIL(execute(params, read_ctx->get_result(), &read_ctx->get_vt_iter_factory(), - is_from_pl, is_dynamic, is_forall, array_binding_count))) { - LOG_WARN("execute sql failed", K(ret), K(tenant_id), K(stmt_id)); - } - } - if (OB_SUCC(ret)) { - ref_ctx_ = read_ctx; - } - return ret; -} - int ObInnerSQLConnection::switch_tenant(const uint64_t tenant_id) { int ret = OB_SUCCESS; @@ -2319,7 +1898,7 @@ int ObInnerSQLConnection::switch_tenant(const uint64_t tenant_id) return ret; } -int ObInnerSQLConnection::set_timeout(int64_t &abs_timeout_us, bool is_from_pl) +int ObInnerSQLConnection::set_timeout(int64_t &abs_timeout_us) { int ret = OB_SUCCESS; const ObTimeoutCtx &ctx = ObTimeoutCtx::get_ctx(); @@ -2377,22 +1956,11 @@ int ObInnerSQLConnection::set_timeout(int64_t &abs_timeout_us, bool is_from_pl) // no need to set session timeout for outer session if no timeout ctx if (OB_SUCC(ret) - && (is_inner_session() || ctx.is_timeout_set() || ctx.is_trx_timeout_set() || is_from_pl)) { - if (!is_from_pl) { - if (OB_FAIL(set_session_timeout(timeout, trx_timeout))) { - LOG_WARN("set session timeout failed", K(timeout), K(trx_timeout), K(ret)); - } else { - THIS_WORKER.set_timeout_ts(get_session().get_query_start_time() + timeout); - } + && (is_inner_session() || ctx.is_timeout_set() || ctx.is_trx_timeout_set())) { + if (OB_FAIL(set_session_timeout(timeout, trx_timeout))) { + LOG_WARN("set session timeout failed", K(timeout), K(trx_timeout), K(ret)); } else { - int64_t query_timeout; - OZ (get_session().get_query_timeout(query_timeout)); - OX (abs_timeout_us = get_session().get_query_start_time() > 0 - ? get_session().get_query_start_time() + query_timeout - : ObTimeUtility::current_time() + query_timeout); - if (OB_SUCC(ret) && THIS_WORKER.get_timeout_ts() > abs_timeout_us) { - OX (THIS_WORKER.set_timeout_ts(abs_timeout_us)); - } + THIS_WORKER.set_timeout_ts(get_session().get_query_start_time() + timeout); } } return ret; diff --git a/src/observer/ob_inner_sql_connection.h b/src/observer/ob_inner_sql_connection.h index c27bcd589..5c3ed5216 100644 --- a/src/observer/ob_inner_sql_connection.h +++ b/src/observer/ob_inner_sql_connection.h @@ -131,20 +131,16 @@ public: int destroy(void); inline void reset() { destroy(); } virtual int execute_read(const uint64_t tenant_id, const char *sql, - common::ObISQLClient::ReadResult &res, - bool is_user_sql = false, bool is_from_pl = false, + common::ObISQLClient::ReadResult &res, bool is_user_sql = false, const common::ObAddr *sql_exec_addr = nullptr/* ddl inner sql execution addr */) override; virtual int execute_read(const int64_t cluster_id, const uint64_t tenant_id, const ObString &sql, - common::ObISQLClient::ReadResult &res, - bool is_user_sql = false, bool is_from_pl = false, + common::ObISQLClient::ReadResult &res, bool is_user_sql = false, const common::ObAddr *sql_exec_addr = nullptr/* ddl inner sql execution addr */) override; virtual int execute_write(const uint64_t tenant_id, const char *sql, - int64_t &affected_rows, - bool is_user_sql = false, + int64_t &affected_rows, bool is_user_sql = false, const common::ObAddr *sql_exec_addr = nullptr/* ddl inner sql execution addr */) override; virtual int execute_write(const uint64_t tenant_id, const ObString &sql, - int64_t &affected_rows, - bool is_user_sql = false, + int64_t &affected_rows, bool is_user_sql = false, const common::ObAddr *sql_exec_addr = nullptr) override; virtual int start_transaction(const uint64_t &tenant_id, bool with_snap_shot = false) override; virtual int register_multi_data_source(const uint64_t &tenant_id, @@ -235,22 +231,8 @@ public: { resource_conn_id_ = OB_INVALID_ID; last_query_timestamp_ = 0; resource_svr_.reset(); } public: - int prepare(const uint64_t tenant_id, - const ObString &sql, - pl::ObPLBlockNS *secondary_namespace, - bool is_dynamic_sql, - bool is_dbms_sql, - bool is_cursor, - common::ObISQLClient::ReadResult &res); - int execute(const uint64_t tenant_id, - const ObPsStmtId client_stmt_id, - const sql::stmt::StmtType stmt_type, - ParamStore ¶ms, - common::ObISQLClient::ReadResult &res, - bool is_from_pl = false, - bool is_dynamic = false, - bool is_forall = false, - int64_t array_binding_count = 0); + + sql::ObSql *get_sql_engine() { return ob_sql_; } virtual int execute(const uint64_t tenant_id, sqlclient::ObIExecutor &executor) override; @@ -271,17 +253,19 @@ public: int set_session_timeout(int64_t query_timeout, int64_t trx_timeout); public: - static int process_record(ObInnerSQLResult &res, + static int process_record(sql::ObResultSet &result_set, + sql::ObSqlCtx &sql_ctx, sql::ObSQLSessionInfo &session, ObITimeRecord &time_record, int last_ret, int64_t execution_id, int64_t ps_stmt_id, - int64_t routine_id, ObWaitEventDesc &max_wait_desc, ObWaitEventStat &total_wait_desc, sql::ObExecRecord &exec_record, sql::ObExecTimestamp &exec_timestamp, + bool has_tenant_resource, + const ObString &ps_sql, bool is_from_pl = false); static void record_stat(sql::ObSQLSessionInfo &session, const sql::stmt::StmtType type, @@ -310,7 +294,6 @@ private: pl::ObPLBlockNS *secondary_namespace, bool is_prepare_protocol = false, bool is_prepare_stage = false, - bool is_from_pl = false, bool is_dynamic_sql = false, bool is_dbms_sql = false, bool is_cursor = false); @@ -318,8 +301,7 @@ private: int do_ret, int64_t abs_timeout_us, bool &need_retry, - int64_t retry_cnt, - bool is_from_pl); + int64_t retry_cnt); template int process_final(const T &sql, ObInnerSQLResult &res, @@ -327,30 +309,13 @@ private: // execute with retry int query(sqlclient::ObIExecutor &executor, ObInnerSQLResult &res, - ObVirtualTableIteratorFactory *vt_iter_factory = NULL, - bool is_from_pl = false); + ObVirtualTableIteratorFactory *vt_iter_factory = NULL); int do_query(sqlclient::ObIExecutor &executor, ObInnerSQLResult &res); - int prepare(const common::ObString &sql, - pl::ObPLBlockNS *secondary_namespace, - bool is_dynamic_sql, - bool is_dbms_sql, - bool is_cursor, - ObInnerSQLResult &res, - ObVirtualTableIteratorFactory *vt_iter_factory = NULL); - int do_prepare(const common::ObString &sql, ObInnerSQLResult &res); - int execute(ParamStore ¶ms, - ObInnerSQLResult &res, - ObVirtualTableIteratorFactory *vt_iter_factory = NULL, - bool is_from_pl = false, - bool is_dynamic = false, - bool is_forall = false, - int64_t array_binding_count = 0); - int do_execute(const ParamStore ¶ms, ObInnerSQLResult &res); int switch_tenant(const uint64_t tenant_id); // set timeout to session variable - int set_timeout(int64_t &abs_timeout_us, bool is_from_pl); + int set_timeout(int64_t &abs_timeout_us); lib::Worker::CompatMode get_compat_mode() const; @@ -363,8 +328,8 @@ private: bool is_local_execute(const int64_t cluster_id, const uint64_t tenant_id); int execute_read_inner(const int64_t cluster_id, const uint64_t tenant_id, const ObString &sql, - common::ObISQLClient::ReadResult &res, - bool is_user_sql = false, bool is_from_pl = false, const common::ObAddr *sql_exec_addr = nullptr); + common::ObISQLClient::ReadResult &res, bool is_user_sql = false, + const common::ObAddr *sql_exec_addr = nullptr); int execute_write_inner(const uint64_t tenant_id, const ObString &sql, int64_t &affected_rows, bool is_user_sql = false, const common::ObAddr *sql_exec_addr = nullptr); int start_transaction_inner(const uint64_t &tenant_id, bool with_snap_shot = false); diff --git a/src/observer/virtual_table/ob_gv_sql.cpp b/src/observer/virtual_table/ob_gv_sql.cpp index eb6c9950e..e775e2493 100644 --- a/src/observer/virtual_table/ob_gv_sql.cpp +++ b/src/observer/virtual_table/ob_gv_sql.cpp @@ -128,17 +128,17 @@ int ObGVSql::get_row_from_specified_tenant(uint64_t tenant_id, bool &is_end) ++plan_id_array_idx_; ObCacheObjGuard guard(GV_SQL_HANDLE); int tmp_ret = plan_cache_->ref_cache_obj(plan_id, guard); //plan引用计数加1 - ObPlanCacheObject *cache_obj = static_cast(guard.get_cache_obj()); + //如果当前plan_id对应的plan已被淘汰, 则忽略继续获取下一个plan if (OB_HASH_NOT_EXIST == tmp_ret) { //do nothing; } else if (OB_SUCCESS != tmp_ret) { ret = tmp_ret; - } else if (OB_ISNULL(cache_obj)) { + } else if (OB_ISNULL(guard.get_cache_obj())) { ret = OB_ERR_UNEXPECTED; //SERVER_LOG(WARN, "cache object is NULL", K(ret)); - } else if (OB_FAIL(fill_cells(cache_obj, *plan_cache_))) { //plan exist - SERVER_LOG(WARN, "fail to fill cells", K(cache_obj), K(tenant_id)); + } else if (OB_FAIL(fill_cells(guard.get_cache_obj(), *plan_cache_))) { //plan exist + SERVER_LOG(WARN, "fail to fill cells", KPC(guard.get_cache_obj()), K(tenant_id)); } else { is_filled = true; } @@ -153,7 +153,7 @@ int ObGVSql::get_row_from_specified_tenant(uint64_t tenant_id, bool &is_end) return ret; } -int ObGVSql::fill_cells(const ObPlanCacheObject *cache_obj, const ObPlanCache &plan_cache) +int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &plan_cache) { int ret = OB_SUCCESS; const int64_t col_count = output_column_ids_.count(); diff --git a/src/observer/virtual_table/ob_gv_sql.h b/src/observer/virtual_table/ob_gv_sql.h index fcb377469..0a6cf0a8a 100644 --- a/src/observer/virtual_table/ob_gv_sql.h +++ b/src/observer/virtual_table/ob_gv_sql.h @@ -31,7 +31,7 @@ public: int inner_get_next_row() { return get_row_from_tenants(); } protected: int get_row_from_tenants(); - int fill_cells(const sql::ObPlanCacheObject *cache_obj, const sql::ObPlanCache &plan_cache); + int fill_cells(const sql::ObILibCacheObject *cache_obj, const sql::ObPlanCache &plan_cache); int get_row_from_specified_tenant(uint64_t tenant_id, bool &is_end); private: common::ObSEArray plan_id_array_; diff --git a/src/pl/CMakeLists.txt b/src/pl/CMakeLists.txt index 4666d8abd..0da883ab3 100644 --- a/src/pl/CMakeLists.txt +++ b/src/pl/CMakeLists.txt @@ -36,6 +36,10 @@ ob_set_subtarget(ob_pl common ob_pl_user_type.cpp ) +ob_set_subtarget(ob_pl common_mixed + pl_cache/ob_pl_cache.cpp + pl_cache/ob_pl_cache_mgr.cpp +) ob_set_subtarget(ob_pl sys_package sys_package/ob_dbms_stats.cpp diff --git a/src/pl/ob_pl.cpp b/src/pl/ob_pl.cpp index 2c84f6d9d..ec212803a 100644 --- a/src/pl/ob_pl.cpp +++ b/src/pl/ob_pl.cpp @@ -42,7 +42,7 @@ #include "observer/ob_req_time_service.h" #include "sql/privilege_check/ob_ora_priv_check.h" #include "sql/engine/expr/ob_expr_pl_integer_checker.h" - +#include "pl/pl_cache/ob_pl_cache_mgr.h" namespace oceanbase { using namespace common; @@ -1241,6 +1241,206 @@ int ObPL::execute(ObExecContext &ctx, return ret; } +int ObPL::trans_sql(PlTransformTreeCtx &trans_ctx, ParseNode *root, ObExecContext &ctx) +{ + int ret = OB_SUCCESS; + int64_t param_unit_idx = 0; + int64_t param_num = trans_ctx.raw_param_num_; + ObPlanCacheCtx pc_ctx(trans_ctx.raw_sql_or_expr_, + PC_PL_MODE, // PL_MODE + ctx.get_allocator(), + *(ctx.get_sql_ctx()), + ctx, + ctx.get_my_session()->get_effective_tenant_id()); + pc_ctx.fp_result_.pc_key_.namespace_ = ObLibCacheNameSpace::NS_ANON; + pc_ctx.fp_result_.pc_key_.name_ = trans_ctx.no_param_sql_; + ObSEArray special_params; + ParamStore params((ObWrapperAllocator(trans_ctx.allocator_))); + ObMaxConcurrentParam::FixParamStore fix_param_store(OB_MALLOC_NORMAL_BLOCK_SIZE, + ObWrapperAllocator(trans_ctx.allocator_)); + if (param_num > 0) { + SqlInfo sql_info; + ObPCParam *pc_param = NULL; + char *ptr = (char *)trans_ctx.allocator_->alloc(param_num * sizeof(ObPCParam)); + pc_ctx.fp_result_.raw_params_.set_allocator(trans_ctx.allocator_); + pc_ctx.fp_result_.raw_params_.set_capacity(param_num); + if (OB_ISNULL(ptr)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc memory for pc param", K(ret), K(ptr)); + } + for (int64_t i = 0; + OB_SUCC(ret) && i < param_num && NULL != trans_ctx.p_list_;//p_list包含所有表达式和sql的raw param + ++i) { + pc_param = new(ptr)ObPCParam(); + ptr += sizeof(ObPCParam); + pc_param->node_ = trans_ctx.p_list_->node_; + if (OB_FAIL(pc_ctx.fp_result_.raw_params_.push_back(pc_param))) { + LOG_WARN("fail to push into params", K(ret)); + } else { + trans_ctx.p_list_ = trans_ctx.p_list_->next_; + } + } // for end + if (OB_FAIL(ret)) { + } else if (OB_FAIL(ObSqlParameterization::transform_syntax_tree(*trans_ctx.allocator_, + *ctx.get_my_session(), + &pc_ctx.fp_result_.raw_params_, + root, + sql_info, + params, + NULL, + fix_param_store, + false, + INVALID_MODE, + NULL, + true))) { + LOG_WARN("fail to exec transform_syntax_tree", K(ret)); + } else if (OB_FAIL(ObSqlParameterization::check_and_generate_param_info(pc_ctx.fp_result_.raw_params_, + sql_info, + special_params))) { + LOG_WARN("fail to check and generate param info", K(ret)); + } + if (OB_SUCC(ret)) { + char *buf = NULL; + int32_t pos = 0; + buf = (char *)trans_ctx.allocator_->alloc(pc_ctx.raw_sql_.length()); + if (NULL == buf) { + LOG_WARN("fail to alloc buf", K(pc_ctx.raw_sql_.length())); + ret = OB_ALLOCATE_MEMORY_FAILED; + } else if (OB_FAIL(ObSqlParameterization::construct_sql(pc_ctx.fp_result_.pc_key_.name_, special_params, buf, pc_ctx.raw_sql_.length(), pos))) { + LOG_WARN("fail to construct_sql", K(ret)); + } else if (OB_FAIL(ObSqlParameterization::transform_neg_param(pc_ctx.fp_result_.raw_params_))) { + LOG_WARN("fail to transform_neg_param", K(ret)); + } else { + if (trans_ctx.buf_size_ < trans_ctx.buf_len_ + pos) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error about trans_ctx.buf", K(ret)); + } else { + MEMCPY(trans_ctx.buf_ + trans_ctx.buf_len_, buf, pos); + trans_ctx.buf_len_ += pos; + } + CK (OB_NOT_NULL(trans_ctx.params_)); + for (int64_t i = 0; OB_SUCC(ret) && i < params.count(); ++i) { + OZ (trans_ctx.params_->push_back(params.at(i))); + } + } + } + } else { + if (trans_ctx.buf_size_ < trans_ctx.buf_len_ + trans_ctx.no_param_sql_.length()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error about trans_ctx.buf", K(ret)); + } else { + MEMCPY(trans_ctx.buf_ + trans_ctx.buf_len_, trans_ctx.no_param_sql_.ptr(), trans_ctx.no_param_sql_.length()); + trans_ctx.buf_len_ += trans_ctx.no_param_sql_.length(); + } + } + return ret; +} + +int ObPL::transform_tree(PlTransformTreeCtx &trans_ctx, ParseNode *root, ParseNode *no_param_root, ObExecContext &ctx, ParseResult &parse_result) +{ + int ret = OB_SUCCESS; + if (OB_NOT_NULL(root) && OB_NOT_NULL(no_param_root)) { + if (T_EXPR == no_param_root->type_) { + ParseNode *expr_node = NULL; + /* 调整语法树结构, 避免语法树分析阶段因为结构不同报错 */ + if (OB_ISNULL(expr_node = new_non_terminal_node(trans_ctx.allocator_, T_EXPR, 1, root))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc memory", K(ret)); + } else { + /* 语法树分析时会修改node上部分属性, 这里提前记录 */ + int64_t raw_pos = expr_node->children_[0]->pos_ - trans_ctx.raw_anonymous_off_; + int64_t raw_str_off = expr_node->children_[0]->str_off_; + trans_ctx.raw_sql_or_expr_.assign_ptr(expr_node->children_[0]->raw_text_, expr_node->children_[0]->text_len_); + trans_ctx.raw_param_num_ = no_param_root->children_[0]->param_num_; + trans_ctx.no_param_sql_.assign_ptr(parse_result.no_param_sql_ + no_param_root->children_[0]->pos_, no_param_root->children_[0]->str_len_); + if (trans_ctx.buf_size_ < trans_ctx.buf_len_ + raw_pos - trans_ctx.copied_idx_ || + raw_pos < trans_ctx.copied_idx_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error about trans_ctx.buf", K(ret), K(raw_pos), K(trans_ctx.copied_idx_)); + } else { + MEMCPY(trans_ctx.buf_ + trans_ctx.buf_len_, trans_ctx.raw_sql_.ptr() + trans_ctx.copied_idx_, raw_pos - trans_ctx.copied_idx_); + trans_ctx.buf_len_ += raw_pos - trans_ctx.copied_idx_; + OZ (trans_sql(trans_ctx, expr_node, ctx)); + trans_ctx.copied_idx_ = raw_pos + raw_str_off; + } + } + } else if (T_SQL_STMT == no_param_root->type_) { + int64_t raw_pos = root->children_[0]->pos_ - trans_ctx.raw_anonymous_off_; + int64_t raw_str_off = root->children_[0]->str_off_; + trans_ctx.raw_sql_or_expr_.assign_ptr(root->children_[0]->raw_text_, root->children_[0]->text_len_); + trans_ctx.raw_param_num_ = no_param_root->children_[0]->param_num_; + trans_ctx.no_param_sql_.assign_ptr(parse_result.no_param_sql_ + no_param_root->children_[0]->pos_, no_param_root->children_[0]->str_len_); + if (trans_ctx.buf_size_ < trans_ctx.buf_len_ + raw_pos - trans_ctx.copied_idx_ || + raw_pos < trans_ctx.copied_idx_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error about trans_ctx.buf", K(ret)); + } else { + MEMCPY(trans_ctx.buf_ + trans_ctx.buf_len_, trans_ctx.raw_sql_.ptr() + trans_ctx.copied_idx_, raw_pos - trans_ctx.copied_idx_); + trans_ctx.buf_len_ += raw_pos - trans_ctx.copied_idx_; + OZ (trans_sql(trans_ctx, root, ctx)); + trans_ctx.copied_idx_ = raw_pos + raw_str_off; + } + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < root->num_child_ && i < no_param_root->num_child_; ++i) { + OZ (SMART_CALL(transform_tree(trans_ctx, root->children_[i], no_param_root->children_[i], ctx, parse_result))); + } + } + } + return ret; +} + +int ObPL::parameter_anonymous_block(ObExecContext &ctx, + const ObStmtNodeTree *block, + ParamStore ¶ms, + ObIAllocator &allocator, + ObCacheObjGuard &cacheobj_guard) +{ + int ret = OB_SUCCESS; + CK (OB_NOT_NULL(ctx.get_my_session())); + CK (OB_NOT_NULL(block)); + if (OB_SUCC(ret)) { + ObString sql(static_cast(block->str_len_), block->str_value_); + ObString pc_key; + ParseResult parse_result; + ObPLParser pl_parser(allocator, + ctx.get_my_session()->get_dtc_params().connection_collation_); + OZ (pl_parser.fast_parse(sql, parse_result)); + if (OB_SUCC(ret)) { + PlTransformTreeCtx trans_ctx; + ParseNode *block_node = NULL; + memset(&trans_ctx, 0, sizeof(PlTransformTreeCtx)); + trans_ctx.allocator_ = &allocator; + trans_ctx.raw_sql_ = sql; + trans_ctx.raw_anonymous_off_ = block->str_off_; + trans_ctx.params_ = ¶ms; + trans_ctx.buf_ = (char *)trans_ctx.allocator_->alloc(sql.length()); + trans_ctx.buf_size_ = sql.length(); + trans_ctx.p_list_ = parse_result.param_nodes_; + CK (T_STMT_LIST == parse_result.result_tree_->type_ && 1 == parse_result.result_tree_->num_child_); + CK (OB_NOT_NULL(block_node = parse_result.result_tree_->children_[0])); + CK (T_SP_ANONYMOUS_BLOCK == block_node->type_); + CK (OB_NOT_NULL(block_node = block_node->children_[0])); + CK (T_SP_BLOCK_CONTENT == block_node->type_ || T_SP_LABELED_BLOCK == block_node->type_); + OZ (transform_tree(trans_ctx, const_cast(block), block_node, ctx, parse_result)); + if (OB_SUCC(ret)) { + if (trans_ctx.buf_size_ < trans_ctx.buf_len_ + trans_ctx.raw_sql_.length() - trans_ctx.copied_idx_ || + trans_ctx.raw_sql_.length() < trans_ctx.copied_idx_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error about trans_ctx.buf", K(ret)); + } else { + MEMCPY(trans_ctx.buf_ + trans_ctx.buf_len_, + trans_ctx.raw_sql_.ptr() + trans_ctx.copied_idx_, + trans_ctx.raw_sql_.length() - trans_ctx.copied_idx_); + trans_ctx.buf_len_ += trans_ctx.raw_sql_.length() - trans_ctx.copied_idx_; + } + } + pc_key.assign_ptr(trans_ctx.buf_, trans_ctx.buf_len_); + OZ (get_pl_function(ctx, params, OB_INVALID_ID, pc_key, cacheobj_guard)); + } + } + return ret; +} + // for execute anonymous int ObPL::execute(ObExecContext &ctx, const ObStmtNodeTree *block) { @@ -1249,7 +1449,8 @@ int ObPL::execute(ObExecContext &ctx, const ObStmtNodeTree *block) lib::MemoryContext mem_context = NULL; lib::ContextParam param; ObPLFunction *routine = NULL; - + ObCacheObjGuard cacheobj_guard(PL_ANON_HANDLE); + bool is_forbid_anony_parameter = block->is_forbid_anony_parameter_; /* !!! * PL,req_timeinfo_guard一定要在执行前定义 * !!! @@ -1265,61 +1466,72 @@ int ObPL::execute(ObExecContext &ctx, const ObStmtNodeTree *block) OZ (CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, param)); CK (OB_NOT_NULL(mem_context)); - // compile it. if (OB_SUCC(ret)) { - ObPLCompiler compiler(mem_context->get_arena_allocator(), - *(ctx.get_my_session()), - *(ctx.get_sql_ctx()->schema_guard_), - *(ctx.get_package_guard()), - *(ctx.get_sql_proxy())); - if (OB_ISNULL(routine = static_cast( - mem_context->get_arena_allocator().alloc(sizeof(ObPLFunction))))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate memory for anonymous pl function", - K(ret), K(sizeof(ObPLFunction))); + ParamStore exec_params((ObWrapperAllocator(ctx.get_allocator()))); + if (!is_forbid_anony_parameter && lib::is_oracle_mode()) { + OZ (parameter_anonymous_block(ctx, block, exec_params, ctx.get_allocator(), cacheobj_guard)); + OX (routine = static_cast(cacheobj_guard.get_cache_obj())); + CK (OB_NOT_NULL(routine)); + OX (routine->set_debug_priv()); + } else { + // compile it. + if (OB_SUCC(ret) && NULL == routine) { + ObPLCompiler compiler(mem_context->get_arena_allocator(), + *(ctx.get_my_session()), + *(ctx.get_sql_ctx()->schema_guard_), + *(ctx.get_package_guard()), + *(ctx.get_sql_proxy())); + if (OB_ISNULL(routine = static_cast( + mem_context->get_arena_allocator().alloc(sizeof(ObPLFunction))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory for anonymous pl function", + K(ret), K(sizeof(ObPLFunction))); + } + OX (routine = new(routine)ObPLFunction(mem_context)); + OZ (compiler.compile(block, *routine, NULL, false)); + OX (routine->set_debug_priv()); + } } - OX (routine = new(routine)ObPLFunction(mem_context)); - OZ (compiler.compile(block, *routine)); - OX (routine->set_debug_priv()); - } - // prepare it. - if (OB_SUCC(ret)) { - SMART_VAR(ObPLContext, stack_ctx) { - LinkPLStackGuard link_stack_guard(ctx, stack_ctx); - OZ (stack_ctx.init(*(ctx.get_my_session()), ctx, routine->is_autonomous(), false)); + // prepare it. + if (OB_SUCC(ret)) { + SMART_VAR(ObPLContext, stack_ctx) { + LinkPLStackGuard link_stack_guard(ctx, stack_ctx); + OZ (stack_ctx.init(*(ctx.get_my_session()), ctx, routine->is_autonomous(), false)); - try { - // execute it. - OZ (execute(ctx, - ctx.get_allocator(), - *(ctx.get_package_guard()), - *routine, - NULL, // params - NULL, // nocopy params - NULL, // result - NULL, // status - stack_ctx.is_top_stack(), - false, - false)); // in function + try { + // execute it. + OZ (execute(ctx, + ctx.get_allocator(), + *(ctx.get_package_guard()), + *routine, + is_forbid_anony_parameter ? NULL : &exec_params, // params + NULL, // nocopy params + NULL, // result + NULL, // status + stack_ctx.is_top_stack(), + false, // inner call + false, + true)); - // unprepare it. - if (stack_ctx.is_inited()) { - stack_ctx.destory(*(ctx.get_my_session()), ctx, ret); + // unprepare it. + if (stack_ctx.is_inited()) { + stack_ctx.destory(*(ctx.get_my_session()), ctx, ret); + } + } catch (...) { + // unprepare it. + if (stack_ctx.is_inited()) { + stack_ctx.destory(*(ctx.get_my_session()), ctx, ret); + } + if (is_forbid_anony_parameter && NULL != routine) { + routine->~ObPLFunction(); + } + if (NULL != mem_context) { + DESTROY_CONTEXT(mem_context); + mem_context = NULL; + } + throw; } - } catch (...) { - // unprepare it. - if (stack_ctx.is_inited()) { - stack_ctx.destory(*(ctx.get_my_session()), ctx, ret); - } - if (NULL != routine) { - routine->~ObPLFunction(); - } - if (NULL != mem_context) { - DESTROY_CONTEXT(mem_context); - mem_context = NULL; - } - throw; } } } @@ -1331,7 +1543,7 @@ int ObPL::execute(ObExecContext &ctx, const ObStmtNodeTree *block) } #endif - if (NULL != routine) { + if (is_forbid_anony_parameter && NULL != routine) { routine->~ObPLFunction(); } if (NULL != mem_context) { @@ -1563,62 +1775,67 @@ int ObPL::get_pl_function(ObExecContext &ctx, ObPLFunction* routine = NULL; OZ (ObPLContext::valid_execute_context(ctx)); if (OB_SUCC(ret)) { - ObPlanCache *plan_cache = ctx.get_my_session()->get_plan_cache(); ObPlanBaseKeyGuard guard(ctx.get_sql_ctx()->spm_ctx_.bl_key_); - ObPlanCacheCtx pc_ctx(sql, - true, // PS_MODE - ctx.get_allocator(), - *(ctx.get_sql_ctx()), - ctx, - ctx.get_my_session()->get_effective_tenant_id()); - // init pc key - pc_ctx.fp_result_.pc_key_.namespace_ = ObLibCacheNameSpace::NS_ANON; - pc_ctx.normal_parse_const_cnt_ = params.count(); - pc_ctx.fp_result_.cache_params_ = ¶ms; - CK (OB_NOT_NULL(plan_cache)); - OZ (sql::ObSql::construct_ps_param(params, pc_ctx)); + uint64_t database_id = OB_INVALID_ID; + ctx.get_my_session()->get_database_id(database_id); - // use stmt id as key - pc_ctx.fp_result_.pc_key_.key_id_ = stmt_id; - if (OB_FAIL(ret)) { - } else if (OB_FAIL(plan_cache->get_pl_function(cacheobj_guard, pc_ctx))) { - LOG_INFO("get pl function from plan cache failed", - K(ret), K(pc_ctx.fp_result_.pc_key_), K(stmt_id), K(sql), K(params)); - ret = OB_ERR_UNEXPECTED != ret ? OB_SUCCESS : ret; - } else if (FALSE_IT(routine = static_cast(cacheobj_guard.get_cache_obj()))) { - // do nothing - } else if (OB_NOT_NULL(routine)) { - LOG_DEBUG("get pl function from plan cache success", KPC(routine)); + ObPLCacheCtx pc_ctx; + pc_ctx.session_info_ = ctx.get_my_session(); + pc_ctx.schema_guard_ = ctx.get_sql_ctx()->schema_guard_; + pc_ctx.cache_params_ = ¶ms; + pc_ctx.raw_sql_ = sql; + MEMCPY(pc_ctx.sql_id_, ctx.get_sql_ctx()->sql_id_, (int32_t)sizeof(ctx.get_sql_ctx()->sql_id_)); + + pc_ctx.key_.namespace_ = ObLibCacheNameSpace::NS_ANON; + pc_ctx.key_.db_id_ = database_id; + pc_ctx.key_.sessid_ = ctx.get_my_session()->is_pl_debug_on() ? ctx.get_my_session()->get_sessid() : 0; + + if (OB_SUCC(ret)) { + if (stmt_id != OB_INVALID_ID) { + // use stmt id as key + pc_ctx.key_.key_id_ = stmt_id; + if (OB_FAIL(ObPLCacheMgr::get_pl_cache(ctx.get_my_session()->get_plan_cache(), cacheobj_guard, pc_ctx))) { + LOG_INFO("get pl function from plan cache failed", + K(ret), K(pc_ctx.key_), K(stmt_id), K(sql), K(params)); + ret = OB_ERR_UNEXPECTED != ret ? OB_SUCCESS : ret; + } else if (FALSE_IT(routine = static_cast(cacheobj_guard.get_cache_obj()))) { + // do nothing + } else if (OB_NOT_NULL(routine)) { + LOG_DEBUG("get pl function from plan cache success", KPC(routine)); + } + } } // use sql as key if (OB_SUCC(ret) && OB_ISNULL(routine)) { - pc_ctx.fp_result_.pc_key_.key_id_ = OB_INVALID_ID; - pc_ctx.fp_result_.pc_key_.name_ = sql; + pc_ctx.key_.key_id_ = OB_INVALID_ID; + pc_ctx.key_.name_ = sql; LOG_DEBUG("find plan by stmt_id failed, start to find plan by sql", - K(ret), K(sql), K(stmt_id), K(pc_ctx.fp_result_.pc_key_)); - if (OB_FAIL(plan_cache->get_pl_function(cacheobj_guard, pc_ctx))) { + K(ret), K(sql), K(stmt_id), K(pc_ctx.key_)); + if (OB_FAIL(ObPLCacheMgr::get_pl_cache(ctx.get_my_session()->get_plan_cache(), cacheobj_guard, pc_ctx))) { LOG_INFO("get pl function by sql failed, will ignore this error", - K(ret), K(pc_ctx.fp_result_.pc_key_), K(stmt_id), K(sql), K(params)); + K(ret), K(pc_ctx.key_), K(stmt_id), K(sql), K(params)); ret = OB_ERR_UNEXPECTED != ret ? OB_SUCCESS : ret; } else if (FALSE_IT(routine = static_cast(cacheobj_guard.get_cache_obj()))) { // do nothing - } else if (OB_NOT_NULL(routine)) { - pc_ctx.fp_result_.pc_key_.key_id_ = stmt_id; - pc_ctx.fp_result_.pc_key_.name_ = sql; - OZ (plan_cache->add_exists_cache_obj_by_stmt_id(pc_ctx, routine)); - LOG_DEBUG("plan added succeed", - K(ret), K(pc_ctx.fp_result_.pc_key_), K(stmt_id), K(sql), K(params)); + } else if (OB_NOT_NULL(routine) && stmt_id != OB_INVALID_ID) { + //pc_ctx.fp_result_.pc_key_.key_id_ = stmt_id; + //pc_ctx.fp_result_.pc_key_.name_ = sql; + //OZ (plan_cache->add_exists_cache_obj_by_stmt_id(pc_ctx, routine)); + //LOG_DEBUG("plan added succeed", + // K(ret), K(pc_ctx.fp_result_.pc_key_), K(stmt_id), K(sql), K(params)); } // reset pc_ctx - pc_ctx.fp_result_.pc_key_.key_id_ = stmt_id; - pc_ctx.fp_result_.pc_key_.name_.reset(); + if (stmt_id != OB_INVALID_ID) { + pc_ctx.key_.key_id_ = stmt_id; + pc_ctx.key_.name_.reset(); + } } LOG_DEBUG("get anonymous from cache by sql", K(ret), K(stmt_id), KPC(routine), - K(pc_ctx.fp_result_.pc_key_), + K(pc_ctx.key_), K(ctx.get_sql_ctx()->sql_id_), K(sql)); @@ -1627,9 +1844,9 @@ int ObPL::get_pl_function(ObExecContext &ctx, ParseNode root_node; ObBucketHashWLockGuard guard(codegen_lock_, stmt_id); // check cache again after get lock - if (OB_FAIL(plan_cache->get_pl_function(cacheobj_guard, pc_ctx))) { + if (OB_FAIL(ObPLCacheMgr::get_pl_cache(ctx.get_my_session()->get_plan_cache(), cacheobj_guard, pc_ctx))) { LOG_INFO("get pl function by sql failed, will ignore this error", - K(ret), K(pc_ctx.fp_result_.pc_key_), K(stmt_id), K(sql), K(params)); + K(ret), K(pc_ctx.key_), K(stmt_id), K(sql), K(params)); ret = OB_ERR_UNEXPECTED != ret ? OB_SUCCESS : ret; } OX (routine = static_cast(cacheobj_guard.get_cache_obj())); @@ -1638,15 +1855,15 @@ int ObPL::get_pl_function(ObExecContext &ctx, OX (routine = static_cast(cacheobj_guard.get_cache_obj())); CK (OB_NOT_NULL(routine)); if (OB_SUCC(ret) && routine->get_can_cached()) { - OZ (add_pl_function_cache(routine, pc_ctx)); + OZ (add_pl_lib_cache(routine, pc_ctx)); // add sql key to plan cache - OX (pc_ctx.fp_result_.pc_key_.name_ = sql); - OZ (plan_cache->add_exists_cache_obj_by_sql(pc_ctx, routine)); - OX (pc_ctx.fp_result_.pc_key_.name_.reset()) + //OX (pc_ctx.key_.name_ = sql); + //OZ (plan_cache->add_exists_cache_obj_by_sql(pc_ctx, routine)); + //OX (pc_ctx.key_.name_.reset()); } LOG_DEBUG("add anonymous to cache", - K(ret), K(stmt_id), K(routine->get_can_cached()), KPC(routine), - K(pc_ctx.fp_result_.pc_key_), K(ctx.get_sql_ctx()->sql_id_), K(sql)); + K(ret), K(stmt_id), KPC(routine), + K(pc_ctx.key_), K(ctx.get_sql_ctx()->sql_id_), K(sql)); } } } @@ -1692,24 +1909,26 @@ int ObPL::get_pl_function(ObExecContext &ctx, CK (OB_NOT_NULL(local_routine)); } else { // standalone routine static const ObString PLSQL = ObString("PL/SQL"); - ObPlanCache *plan_cache = ctx.get_my_session()->get_plan_cache(); ObPlanBaseKeyGuard guard(ctx.get_sql_ctx()->spm_ctx_.bl_key_); - ObPlanCacheCtx pc_ctx(PLSQL, - false, // ps mode - ctx.get_allocator(), - *ctx.get_sql_ctx(), - ctx, - ctx.get_my_session()->get_effective_tenant_id()); - pc_ctx.fp_result_.reset(); - pc_ctx.fp_result_.pc_key_.key_id_ = routine_id; - pc_ctx.fp_result_.pc_key_.namespace_ = ObLibCacheNameSpace::NS_PRCR; - pc_ctx.fp_result_.pc_key_.sessid_ - = ctx.get_my_session()->is_pl_debug_on() ? ctx.get_my_session()->get_sessid() : 0; - CK (OB_NOT_NULL(plan_cache)); + + uint64_t database_id = OB_INVALID_ID; + ctx.get_my_session()->get_database_id(database_id); + + ObPLCacheCtx pc_ctx; + pc_ctx.session_info_ = ctx.get_my_session(); + pc_ctx.schema_guard_ = ctx.get_sql_ctx()->schema_guard_; + pc_ctx.raw_sql_ = PLSQL; + MEMCPY(pc_ctx.sql_id_, ctx.get_sql_ctx()->sql_id_, (int32_t)sizeof(ctx.get_sql_ctx()->sql_id_)); + + pc_ctx.key_.namespace_ = ObLibCacheNameSpace::NS_PRCR; + pc_ctx.key_.db_id_ = database_id; + pc_ctx.key_.key_id_ = routine_id; + pc_ctx.key_.sessid_ = ctx.get_my_session()->is_pl_debug_on() ? ctx.get_my_session()->get_sessid() : 0; + if (OB_FAIL(ret)) { - } else if (OB_FAIL(plan_cache->get_pl_function(cacheobj_guard, pc_ctx))) { + } else if (OB_FAIL(ObPLCacheMgr::get_pl_cache(ctx.get_my_session()->get_plan_cache(), cacheobj_guard, pc_ctx))) { LOG_INFO("get pl function from plan cache failed", - K(ret), K(pc_ctx.fp_result_.pc_key_), K(package_id), K(routine_id)); + K(ret), K(pc_ctx.key_), K(package_id), K(routine_id)); ret = OB_ERR_UNEXPECTED != ret ? OB_SUCCESS : ret; } else if (FALSE_IT(routine = static_cast(cacheobj_guard.get_cache_obj()))) { // do nothing @@ -1720,9 +1939,9 @@ int ObPL::get_pl_function(ObExecContext &ctx, { ObBucketHashWLockGuard guard(codegen_lock_, routine_id); // check again after get lock. - if (OB_FAIL(plan_cache->get_pl_function(cacheobj_guard, pc_ctx))) { + if (OB_FAIL(ObPLCacheMgr::get_pl_cache(ctx.get_my_session()->get_plan_cache(), cacheobj_guard, pc_ctx))) { LOG_INFO("get pl function from plan cache failed", - K(ret), K(pc_ctx.fp_result_.pc_key_), K(package_id), K(routine_id)); + K(ret), K(pc_ctx.key_), K(package_id), K(routine_id)); ret = OB_ERR_UNEXPECTED != ret ? OB_SUCCESS : ret; } OX (routine = static_cast(cacheobj_guard.get_cache_obj())); @@ -1733,7 +1952,7 @@ int ObPL::get_pl_function(ObExecContext &ctx, CK (OB_NOT_NULL(routine)); if (OB_SUCC(ret) && routine->get_can_cached()) { - OZ (add_pl_function_cache(routine, pc_ctx)); + OZ (add_pl_lib_cache(routine, pc_ctx)); } LOG_DEBUG("get func by compile", K(package_id), K(routine_id), KPC(routine)); @@ -1752,25 +1971,25 @@ int ObPL::get_pl_function(ObExecContext &ctx, return ret; } -int ObPL::add_pl_function_cache(ObPLFunction *pl_func, ObPlanCacheCtx &pc_ctx) +int ObPL::add_pl_lib_cache(ObPLFunction *pl_func, ObPLCacheCtx &pc_ctx) { int ret = OB_SUCCESS; ObPlanCache *plan_cache = NULL; - ObSQLSessionInfo *session = pc_ctx.exec_ctx_.get_my_session(); + ObSQLSessionInfo *session = pc_ctx.session_info_; if (OB_ISNULL(session) || OB_ISNULL(pl_func)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info is null", K(session), K(pl_func)); } else if (OB_ISNULL(plan_cache = session->get_plan_cache())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("plan cache is null"); - } else if (OB_FAIL(plan_cache->add_pl_cache(pl_func, pc_ctx))) { + } else if (OB_FAIL(ObPLCacheMgr::add_pl_cache(plan_cache, pl_func, pc_ctx))) { if (OB_SQL_PC_PLAN_DUPLICATE == ret) { ret = OB_SUCCESS; LOG_DEBUG("this plan has been added by others, need not add again", KPC(pl_func)); } else if (OB_REACH_MEMORY_LIMIT == ret || OB_SQL_PC_PLAN_SIZE_LIMIT == ret) { if (REACH_TIME_INTERVAL(1000000)) { //1s, 当内存达到上限时, 该日志打印会比较频繁, 所以以1s为间隔打印 LOG_DEBUG("can't add plan to plan cache", - K(ret), K(pl_func->get_mem_size()), K(pc_ctx.fp_result_.pc_key_), + K(ret), K(pl_func->get_mem_size()), K(pc_ctx.key_), K(plan_cache->get_mem_used())); } ret = OB_SUCCESS; @@ -1784,7 +2003,7 @@ int ObPL::add_pl_function_cache(ObPLFunction *pl_func, ObPlanCacheCtx &pc_ctx) } } } else { - LOG_DEBUG("add pl function to plan cache success", K(pc_ctx.fp_result_.pc_key_)); + LOG_DEBUG("add pl function to plan cache success", K(pc_ctx.key_)); } return ret; } @@ -1794,7 +2013,8 @@ int ObPL::generate_pl_function(ObExecContext &ctx, const ObString &anonymouse_sql, ParamStore ¶ms, ParseNode &parse_node, - ObCacheObjGuard& cacheobj_guard) + ObCacheObjGuard& cacheobj_guard, + bool is_anonymous_text) { int ret = OB_SUCCESS; ParseNode *block_node = NULL; @@ -1867,7 +2087,9 @@ int ObPL::generate_pl_function(ObExecContext &ctx, *(ctx.get_sql_ctx()->schema_guard_), *(ctx.get_package_guard()), *(ctx.get_sql_proxy())); - OZ (compiler.compile(block_node, *routine, ¶ms)); + + OZ (compiler.compile( + block_node, *routine, ¶ms, ctx.get_sql_ctx()->is_prepare_protocol_)); OZ (routine->set_params_info(params)); } @@ -2415,7 +2637,7 @@ do { \ */ if (func_.get_in_args().has_member(i)) { const ObPLDataType &pl_type = func_.get_variables().at(i); - if (is_anonymous && !func_.get_params_info().at(i).flag_.need_to_check_type_) { + if (is_anonymous) { OX (get_params().at(i) = params->at(i)); } else if (params->at(i).is_pl_mock_default_param()) { // 使用参数默认值 ObObjParam result; @@ -2442,7 +2664,7 @@ do { \ ObObjMeta null_meta = get_params().at(i).get_meta(); get_params().at(i) = params->at(i); // 空值不做cast params->at(i).is_null() ? get_params().at(i).set_null_meta(null_meta) : (void)NULL; - } else if (params->at(i).get_meta() == get_params().at(i).get_meta() + } else if (params->at(i).get_meta().get_type() == get_params().at(i).get_meta().get_type() && params->at(i).get_meta().is_numeric_type()) { ObObj tmp; if (pl_type.is_pl_integer_type()) { @@ -2801,7 +3023,87 @@ int ObPL::check_exec_priv( return ret; } -/* 对外接口,check pl需要的type执行权限 */ +int ObPLSqlInfo::generate( + const ObPLSqlStmt &sql_stmt, ObIArray &exprs) +{ + int ret = OB_SUCCESS; + + OX (loc_ = sql_stmt.get_location()); + + // copy ObPLSQL + OX (forall_sql_ = sql_stmt.is_forall_sql()); + OX (for_update_ = sql_stmt.is_for_update()); + OX (has_hidden_rowid_ = sql_stmt.has_hidden_rowid()); + CK (OB_NOT_NULL(allocator_)); + OZ (ob_write_string(*allocator_, sql_stmt.get_sql(), sql_, true)); + OX (params_.set_capacity(sql_stmt.get_params().count())); + for (int64_t i = 0; OB_SUCC(ret) && i < sql_stmt.get_params().count(); ++i) { + OZ (params_.push_back(exprs.at(sql_stmt.get_params().at(i)))); + } + OX (array_binding_params_.set_capacity(sql_stmt.get_array_binding_params().count())); + for (int64_t i = 0; OB_SUCC(ret) && i < sql_stmt.get_array_binding_params().count(); ++i) { + OZ (array_binding_params_.push_back(exprs.at(sql_stmt.get_array_binding_params().at(i)))); + } + + OZ (ob_write_string(*allocator_, sql_stmt.get_ps_sql(), ps_sql_, true)); + OX (stmt_type_ = sql_stmt.get_stmt_type()); + OX (rowid_table_id_ = sql_stmt.get_rowid_table_id()); + + // copy ObPLInto + OX (into_.set_capacity(sql_stmt.get_into().count())); + for (int64_t i = 0; OB_SUCC(ret) && i < sql_stmt.get_into().count(); ++i) { + OZ (into_.push_back(exprs.at(sql_stmt.get_into().at(i)))); + } + OZ (not_null_flags_.assign(sql_stmt.get_not_null_flags())); + OZ (pl_integer_ranges_.assign(sql_stmt.get_pl_integer_ranges())); + OZ (data_type_.assign(sql_stmt.get_data_type())); + OX (bulk_ = sql_stmt.is_bulk()); + + return ret; +} + +int ObPL::simple_execute(ObPLExecCtx *ctx, int64_t argc, int64_t *argv) +{ + int ret = OB_SUCCESS; + ObPLFunction *func = NULL; + CK (OB_NOT_NULL(ctx)); + CK (OB_NOT_NULL(func = ctx->func_)); + CK (func->get_is_all_sql_stmt()); + if (OB_SUCC(ret)) { + ObIArray &sql_infos = func->get_sql_infos(); + for (int64_t i = 0; OB_SUCC(ret) && i < sql_infos.count(); ++i) { + ObPLSqlInfo &sql_info = sql_infos.at(i); + if (sql_info.params_.empty()) { + OZ (ObSPIService::spi_query( + ctx, sql_infos.at(i).sql_.ptr(), sql_infos.at(i).stmt_type_, + sql_info.into_.get_data(), sql_info.into_.count(), + sql_info.data_type_.get_data(), sql_info.data_type_.count(), + sql_info.not_null_flags_.get_data(), + sql_info.pl_integer_ranges_.get_data(), + sql_info.bulk_)); + } else { + OZ (ObSPIService::spi_execute( + ctx, sql_info.ps_sql_.ptr(), sql_info.stmt_type_, + sql_info.forall_sql_ ? sql_info.array_binding_params_.get_data() : sql_info.params_.get_data(), + sql_info.forall_sql_ ? sql_info.array_binding_params_.count() : sql_info.params_.count(), + sql_info.into_.get_data(), sql_info.into_.count(), + sql_info.data_type_.get_data(), sql_info.data_type_.count(), + sql_info.not_null_flags_.get_data(), + sql_info.pl_integer_ranges_.get_data(), + sql_info.bulk_, + sql_info.forall_sql_)); + } + if (OB_READ_NOTHING == ret && lib::is_mysql_mode()) { + //ignore OB_READ_NOTHING error in mysql mode + ret = OB_SUCCESS; + } + + + } + } + return ret; +} + int ObPLExecState::check_pl_udt_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, @@ -3000,6 +3302,59 @@ ObPLCompileUnit::~ObPLCompileUnit() } } +void ObPLCompileUnit::reset() +{ + ObILibCacheObject::reset(); + tenant_schema_version_ = OB_INVALID_VERSION; + sys_schema_version_ = OB_INVALID_VERSION; + dependency_tables_.reset(); + params_info_.reset(); +} + +int ObPLCompileUnit::set_params_info(const ParamStore ¶ms) +{ + int ret = OB_SUCCESS; + int64_t N = params.count(); + ObParamInfo param_info; + if (N > 0 && OB_FAIL(params_info_.reserve(N))) { + OB_LOG(WARN, "fail to reserve params info", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) { + param_info.flag_ = params.at(i).get_param_flag(); + param_info.type_ = params.at(i).get_param_meta().get_type(); + param_info.col_type_ = params.at(i).get_collation_type(); + if (ObSQLUtils::is_oracle_empty_string(params.at(i))) { + param_info.is_oracle_empty_string_ = true; + } + if (params.at(i).get_param_meta().get_type() != params.at(i).get_type()) { + LOG_TRACE("differ in set_params_info", + K(params.at(i).get_param_meta().get_type()), + K(params.at(i).get_type()), + K(common::lbt())); + } + //todo:it is for arraybinding check, not pl ext check + if (params.at(i).is_ext()) { + ObDataType data_type; + if (OB_FAIL(ObSQLUtils::get_ext_obj_data_type(params.at(i), data_type))) { + LOG_WARN("fail to get ext obj data type", K(ret)); + } else { + param_info.ext_real_type_ = data_type.get_obj_type(); + param_info.scale_ = data_type.get_meta_type().get_scale(); + } + LOG_DEBUG("ext params info", K(data_type), K(param_info), K(params.at(i))); + } else { + param_info.scale_ = params.at(i).get_scale(); + } + if (OB_SUCC(ret)) { + if (OB_FAIL(params_info_.push_back(param_info))) { + LOG_WARN("failed to push back param info", K(ret)); + } + } + param_info.reset(); + } + return ret; +} + int ObPLCompileUnit::add_routine(ObPLFunction *routine) { int ret = OB_SUCCESS; @@ -3022,6 +3377,64 @@ int ObPLCompileUnit::get_routine(int64_t routine_idx, ObPLFunction *&routine) co return ret; } + +int ObPLCompileUnit::check_need_add_cache_obj_stat(ObILibCacheCtx &ctx, bool &need_real_add) +{ + int ret = OB_SUCCESS; + + ObPLCacheCtx &pc_ctx = static_cast(ctx); + need_real_add = pc_ctx.need_add_obj_stat_; + + return ret; +} + +void ObPLCompileUnit::dump_deleted_log_info(const bool is_debug_log /* = true */) const +{ + ObString raw_sql; + if (is_anon()) { + const pl::ObPLFunction *pl_func = dynamic_cast(this); + if (OB_ISNULL(pl_func)) { + LOG_ERROR("the plan is null", K(object_id_), + K(tenant_id_), + K(added_to_lc_), + K(get_ref_count()), + K(log_del_time_), + K(routine_table_), + K(expr_op_size_), + K(can_cached_)); + } else { + raw_sql = ObTruncatedString(pl_func->get_stat().raw_sql_, OB_MAX_SQL_LENGTH).string(); + } + } else { + // do nothing + } + if (is_debug_log) { + LOG_DEBUG("Dumping Cache Deleted Info", + K(object_id_), + K(tenant_id_), + K(added_to_lc_), + K(ns_), + K(get_ref_count()), + K(log_del_time_), + K(raw_sql), + K(routine_table_), + K(expr_op_size_), + K(can_cached_)); + } else { + LOG_INFO("Dumping Cache Deleted Info", + K(object_id_), + K(tenant_id_), + K(added_to_lc_), + K(ns_), + K(get_ref_count()), + K(log_del_time_), + K(raw_sql), + K(routine_table_), + K(expr_op_size_), + K(can_cached_)); + } +} + ObPLFunction::~ObPLFunction() { int ret = OB_SUCCESS; @@ -3029,39 +3442,8 @@ ObPLFunction::~ObPLFunction() allocator_.free(di_buf_); di_buf_ = NULL; } - if (OB_NOT_NULL(ps_cache_)) { - if (OB_FAIL(ps_cache_->deref_all_ps_stmt(ps_stmt_ids_))) { - LOG_WARN("failed to close all pl ps stmt", K(ret)); - } - ps_cache_->dec_ref_count(); - ps_cache_ = NULL; - } } -void ObPLFunction::set_ps_cache(sql::ObPsCache* ps_cache) -{ - ps_cache_ = ps_cache; - if (OB_NOT_NULL(ps_cache_)) { - ps_cache_->inc_ref_count(); - } -} - -int ObPLFunction::add_ps_stmt_ids(const ObIArray& ids, - ObSQLSessionInfo *session_info) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(session_info)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("session_info is NULL", K(ret)); - } - for (int64_t i = 0; OB_SUCC(ret) && i < ids.count(); ++i) { - ObPsStmtId id = ids.at(i); - if (OB_FAIL(ps_stmt_ids_.push_back(id))) { - LOG_WARN("failed to push back", K(ret), K(id)); - } - } - return ret; -} int ObPLFunction::set_variables(const ObPLSymbolTable &symbol_table) { @@ -3207,23 +3589,23 @@ bool ObPLFunction::should_init_as_session_cursor() int ObPLFunction::update_cache_obj_stat(ObILibCacheCtx &ctx) { int ret = OB_SUCCESS; - ObPlanCacheCtx &pc_ctx = static_cast(ctx); - if (ObLibCacheNameSpace::NS_PKG != get_ns()) { - PLCacheObjStat &stat = get_stat_for_update(); - stat.pl_schema_id_ = pc_ctx.fp_result_.pc_key_.key_id_; - stat.gen_time_ = ObTimeUtility::current_time(); - stat.last_active_time_ = ObTimeUtility::current_time(); - stat.hit_count_ = 0; - MEMCPY(stat.sql_id_, pc_ctx.sql_ctx_.sql_id_, (int32_t)sizeof(pc_ctx.sql_ctx_.sql_id_)); - if (ObLibCacheNameSpace::NS_ANON == get_ns()) { // only anonymous block record raw sql - ObTruncatedString trunc_raw_sql(pc_ctx.raw_sql_, OB_MAX_SQL_LENGTH); - if (OB_FAIL(ob_write_string(get_allocator(), - trunc_raw_sql.string(), - stat.raw_sql_))) { - LOG_WARN("failed to write sql", K(ret)); - } else { - stat.sql_cs_type_ = pc_ctx.sql_ctx_.session_info_->get_local_collation_connection(); - } + ObPLCacheCtx &pc_ctx = static_cast(ctx); + + PLCacheObjStat &stat = get_stat_for_update(); + stat.pl_schema_id_ = pc_ctx.key_.key_id_; + stat.gen_time_ = ObTimeUtility::current_time(); + stat.last_active_time_ = ObTimeUtility::current_time(); + stat.hit_count_ = 0; + MEMCPY(stat.sql_id_, pc_ctx.sql_id_, (int32_t)sizeof(pc_ctx.sql_id_)); + + if (ObLibCacheNameSpace::NS_ANON == get_ns()) { + ObTruncatedString trunc_raw_sql(pc_ctx.raw_sql_, OB_MAX_SQL_LENGTH); + if (OB_FAIL(ob_write_string(get_allocator(), + trunc_raw_sql.string(), + stat.raw_sql_))) { + LOG_WARN("failed to write sql", K(ret)); + } else { + stat.sql_cs_type_ = pc_ctx.session_info_->get_local_collation_connection(); } } return ret; diff --git a/src/pl/ob_pl.h b/src/pl/ob_pl.h index 1f64d17e7..413b1f520 100644 --- a/src/pl/ob_pl.h +++ b/src/pl/ob_pl.h @@ -33,7 +33,12 @@ #include "pl/ob_pl_package_manager.h" #include "pl/ob_pl_interface_pragma.h" #include "sql/plan_cache/ob_cache_object_factory.h" +#include "pl/pl_cache/ob_pl_cache.h" +namespace test +{ +class MockCacheObjectFactory; +} namespace oceanbase { @@ -54,6 +59,7 @@ typedef void* ObPointer; typedef uint64_t ObFuncPtr; typedef common::ParamStore ParamStore; +class ObPLCacheCtx; enum ObProcType { @@ -268,11 +274,16 @@ private: DISALLOW_COPY_AND_ASSIGN(ObPLFunctionBase); }; -class ObPLCompileUnit : public sql::ObPlanCacheObject +class ObPLCompileUnit : public sql::ObILibCacheObject { + friend class ::test::MockCacheObjectFactory; public: ObPLCompileUnit(sql::ObLibCacheNameSpace ns, lib::MemoryContext &mem_context) - : ObPlanCacheObject(ns, mem_context), + : ObILibCacheObject(ns, mem_context), + tenant_schema_version_(OB_INVALID_VERSION), + sys_schema_version_(OB_INVALID_VERSION), + dependency_tables_(allocator_), + params_info_( (ObWrapperAllocator(allocator_)) ), routine_table_(allocator_), type_table_(), expr_factory_(allocator_), @@ -291,6 +302,20 @@ public: } virtual ~ObPLCompileUnit(); + inline int64_t get_dependency_table_size() const { return dependency_tables_.count(); } + inline const DependenyTableStore &get_dependency_table() const { return dependency_tables_; } + inline void set_sys_schema_version(int64_t schema_version) { sys_schema_version_ = schema_version; } + inline void set_tenant_schema_version(int64_t schema_version) { tenant_schema_version_ = schema_version; } + inline int64_t get_tenant_schema_version() const { return tenant_schema_version_; } + inline int64_t get_sys_schema_version() const { return sys_schema_version_; } + int init_dependency_table_store(int64_t dependency_table_cnt) { return dependency_tables_.init(dependency_table_cnt); } + inline DependenyTableStore &get_dependency_table() { return dependency_tables_; } + + int set_params_info(const ParamStore ¶ms); + const common::Ob2DArray &get_params_info() const { return params_info_; } + inline bool get_can_cached() { return can_cached_; } inline void set_can_cached(bool can_cached) { can_cached_ = can_cached; } inline const ObIArray &get_routine_table() const { return routine_table_; } @@ -318,9 +343,23 @@ public: inline sql::ObExprFrameInfo &get_frame_info() { return frame_info_; } jit::ObDIRawData get_debug_info() const { return helper_.get_debug_info(); } - TO_STRING_KV(K_(routine_table), K(expr_op_size_), K_(can_cached)); + virtual void reset(); + virtual void dump_deleted_log_info(const bool is_debug_log = true) const; + virtual int check_need_add_cache_obj_stat(ObILibCacheCtx &ctx, bool &need_real_add); + + TO_STRING_KV(K_(routine_table), K(expr_op_size_), K_(can_cached), + K_(tenant_schema_version), K_(sys_schema_version)); protected: + int64_t tenant_schema_version_; + int64_t sys_schema_version_; + DependenyTableStore dependency_tables_; + + //stored args information after paramalization + common::Ob2DArray params_info_; + common::ObFixedArray routine_table_; common::ObArray type_table_; sql::ObRawExprFactory expr_factory_; @@ -344,6 +383,49 @@ class ObPLSymbolTable; class ObPLSymbolDebugInfoTable; class ObPLFunctionAST; +class ObPLSqlStmt; +class ObPLSqlInfo +{ +public: + ObPLSqlInfo() {} + ObPLSqlInfo(common::ObIAllocator &allocator) + : loc_(0), forall_sql_(false), for_update_(false), has_hidden_rowid_(false), + sql_(), params_(allocator), array_binding_params_(allocator), ps_sql_(), + stmt_type_(sql::stmt::StmtType::T_NONE), rowid_table_id_(OB_INVALID_ID), + into_(allocator), not_null_flags_(allocator), pl_integer_ranges_(allocator), + data_type_(allocator), bulk_(false), allocator_(&allocator) {} + + virtual ~ObPLSqlInfo() {} + + int generate(const ObPLSqlStmt &sql, ObIArray &exprs); + + TO_STRING_KV(K(loc_), K(forall_sql_), K(for_update_), K(has_hidden_rowid_), K(sql_), + K(params_), K(array_binding_params_), K(ps_sql_), K(stmt_type_), + K(rowid_table_id_), K(into_), K(not_null_flags_), K(pl_integer_ranges_), + K(data_type_), K(bulk_)); + +public: + uint64_t loc_; + + bool forall_sql_; + bool for_update_; + bool has_hidden_rowid_; + common::ObString sql_; + ObFixedArray params_; + ObFixedArray array_binding_params_; + common::ObString ps_sql_; + sql::stmt::StmtType stmt_type_; + uint64_t rowid_table_id_; + + ObFixedArray into_; + ObFixedArray not_null_flags_; + ObFixedArray pl_integer_ranges_; + ObFixedArray data_type_; + bool bulk_; + + ObIAllocator *allocator_; +}; + class ObPLVarDebugInfo { public: @@ -411,13 +493,13 @@ public: variables_(allocator_), variables_debuginfo_(allocator_), default_idxs_(allocator_), + sql_infos_(allocator_), in_args_(), out_args_(), exec_env_(), action_(0), di_buf_(NULL), di_len_(0), - ps_cache_(NULL), is_all_sql_stmt_(true), is_invoker_right_(false), is_pipelined_(false), @@ -467,9 +549,6 @@ public: inline const PLCacheObjStat get_stat() const { return stat_; } inline PLCacheObjStat &get_stat_for_update() { return stat_; } - int add_ps_stmt_ids(const ObIArray& ids, - oceanbase::sql::ObSQLSessionInfo *session_info); - void set_ps_cache(sql::ObPsCache* ps_cache); int get_subprogram(const ObIArray &path, ObPLFunction *&routine) const; inline const common::ObString &get_function_name() const { return function_name_; } @@ -513,17 +592,18 @@ public: int is_special_pkg_invoke_right(ObSchemaGetterGuard &guard, bool &flag); virtual int update_cache_obj_stat(ObILibCacheCtx &ctx); + common::ObFixedArray& get_sql_infos() + { + return sql_infos_; + } + TO_STRING_KV(K_(ns), K_(ref_count), K_(tenant_schema_version), K_(sys_schema_version), K_(object_id), K_(dependency_tables), - K_(outline_state), K_(params_info), - K_(is_contain_virtual_table), - K_(is_contain_inner_table), - K_(fetch_cur_time), K_(variables), K_(default_idxs), K_(function_name), @@ -534,14 +614,13 @@ private: common::ObFixedArray variables_; //根据ObPLSymbolTable的全局符号表生成,所有输入输出参数和PL体内使用的所有变量 common::ObFixedArray variables_debuginfo_; common::ObFixedArray default_idxs_; + common::ObFixedArray sql_infos_; common::ObBitSet in_args_; common::ObBitSet out_args_; sql::ObExecEnv exec_env_; ObFuncPtr action_; char *di_buf_; int64_t di_len_; - common::ObArray ps_stmt_ids_; - sql::ObPsCache *ps_cache_; bool is_all_sql_stmt_; bool is_invoker_right_; bool is_pipelined_; @@ -1015,6 +1094,36 @@ private: uint64_t last_insert_id_; }; +struct PlTransformTreeCtx +{ + ObIAllocator *allocator_; + ParamStore *params_; + char *buf_; // 反拼后的参数化字符串 + int64_t buf_len_; + int64_t buf_size_; + ObString raw_sql_; // 原始匿名块字符串 + int64_t raw_anonymous_off_; // 原始匿名块相对于用户输入首字符的偏移, 解决单个分隔符内存在多个sql场景 + ObString raw_sql_or_expr_; // 匿名块内部单个expr或者sql原始字符串 + ObString no_param_sql_; // 匿名块内部单个expr或者sql对应的fast parser后字符串 + int64_t copied_idx_; + ParamList *p_list_; // 存储匿名块内部所有expr和sql语句fast parser后得到的raw param node + int64_t raw_param_num_; // 匿名块内部单个expr或者sql fast parser后raw param node的个数, 每个expr和sql fast parser后, 会将param num存储在node节点中 + PlTransformTreeCtx() : + allocator_(NULL), + params_(NULL), + buf_(NULL), + buf_len_(0), + buf_size_(0), + raw_sql_(), + raw_anonymous_off_(0), + raw_sql_or_expr_(), + no_param_sql_(), + copied_idx_(0), + p_list_(NULL), + raw_param_num_(0) + {} +}; + class ObPL { public: @@ -1035,7 +1144,13 @@ public: uint64_t stmt_id, const common::ObString &sql, ObBitSet &out_args); - + int parameter_anonymous_block(ObExecContext &ctx, + const ObStmtNodeTree *block, + ParamStore ¶ms, + ObIAllocator &allocator, + ObCacheObjGuard &cacheobj_guard); + int transform_tree(PlTransformTreeCtx &trans_ctx, ParseNode *block, ParseNode *no_param_root, ObExecContext &ctx, ParseResult &parse_result); + int trans_sql(PlTransformTreeCtx &trans_ctx, ParseNode *root, ObExecContext &ctx); // for anonymous int execute(sql::ObExecContext &ctx, const ObStmtNodeTree *block); @@ -1078,7 +1193,8 @@ private: const ObString &anonymouse_sql, ParamStore ¶ms, ParseNode &node, - ObCacheObjGuard& cacheobj_guard); + ObCacheObjGuard& cacheobj_guard, + bool is_anonymous_text = false); // for normal routine int generate_pl_function(sql::ObExecContext &ctx, @@ -1102,8 +1218,7 @@ private: bool is_called_from_sql = false); // add pl to cache - int add_pl_function_cache(ObPLFunction *pl_func, - sql::ObPlanCacheCtx &pc_ctx); + int add_pl_lib_cache(ObPLFunction *pl_func, ObPLCacheCtx &pc_ctx); public: static int execute_proc(ObPLExecCtx &ctx, @@ -1129,6 +1244,8 @@ public: inline const ObPLInterfaceService &get_interface_service() const { return interface_service_; } static int insert_error_msg(int errcode); + static int simple_execute(ObPLExecCtx *ctx, int64_t argc, int64_t *argv); + private: common::ObMySQLProxy *sql_proxy_; ObPLPackageManager package_manager_; diff --git a/src/pl/ob_pl_code_generator.cpp b/src/pl/ob_pl_code_generator.cpp index 586c7c1bf..1436caa39 100644 --- a/src/pl/ob_pl_code_generator.cpp +++ b/src/pl/ob_pl_code_generator.cpp @@ -283,8 +283,15 @@ int ObPLCodeGenerateVisitor::visit(const ObPLDeclareVarStmt &s) OZ (generator_.get_helper().create_store(result, dest_datum)); } else { ObLLVMValue allocator, src_datum; + const ObConstRawExpr *const_expr = static_cast(s.get_default_expr()); OZ (generator_.generate_null(ObIntType, allocator)); - if (T_NULL == s.get_default_expr()->get_expr_type()) { + CK (NULL != s.get_symbol_table()); + if (OB_FAIL(ret)) { + } else if (T_NULL == s.get_default_expr()->get_expr_type() || + (T_QUESTIONMARK == const_expr->get_expr_type() && + 0 == s.get_symbol_table()->get_symbol(const_expr->get_value().get_unknown())->get_name().case_compare(ObPLResolver::ANONYMOUS_ARG) && + NULL != s.get_symbol_table()->get_symbol(const_expr->get_value().get_unknown())->get_pl_data_type().get_data_type() && + ObNullType == s.get_symbol_table()->get_symbol(const_expr->get_value().get_unknown())->get_pl_data_type().get_data_type()->get_obj_type())) { /* * allocator可以是null,因为这儿只是修改原复杂类型的属性信息 * 对于record来说把内部的元素初始化成一个null, @@ -3395,7 +3402,7 @@ int ObPLCodeGenerator::init_spi_service() arg_types.reset(); if (OB_FAIL(arg_types.push_back(pl_exec_context_pointer_type))) { //函数第一个参数必须是基础环境信息隐藏参数 LOG_WARN("push_back error", K(ret)); - } else if (OB_FAIL(arg_types.push_back(int64_type))) { + } else if (OB_FAIL(arg_types.push_back(char_type))) { LOG_WARN("push_back error", K(ret)); } else if (OB_FAIL(arg_types.push_back(int64_type))) { LOG_WARN("push_back error", K(ret)); @@ -3564,7 +3571,7 @@ int ObPLCodeGenerator::init_spi_service() arg_types.reset(); OZ (arg_types.push_back(pl_exec_context_pointer_type)); //函数第一个参数必须是基础环境信息隐藏参数 OZ (arg_types.push_back(char_type)); //sql - OZ (arg_types.push_back(int64_type));//id + OZ (arg_types.push_back(char_type));//id OZ (arg_types.push_back(int64_type));//type OZ (arg_types.push_back(bool_type));//for_update OZ (arg_types.push_back(bool_type));//hidden_rowid @@ -4435,7 +4442,7 @@ int ObPLCodeGenerator::generate_open( //sql & ps_id & stmt_type & params & param count ObLLVMValue str; ObLLVMValue len; - ObLLVMValue id; + ObLLVMValue ps_sql; ObLLVMValue type; ObLLVMValue for_update; ObLLVMValue hidden_rowid; @@ -4449,10 +4456,10 @@ int ObPLCodeGenerator::generate_open( ObLLVMValue cursor_param_count; ObLLVMValue ret_err; OZ (args.push_back(get_vars().at(CTX_IDX))); - OZ (generate_sql(cursor_sql, str, len, id, type, for_update, hidden_rowid, sql_params, + OZ (generate_sql(cursor_sql, str, len, ps_sql, type, for_update, hidden_rowid, sql_params, sql_param_count)); OZ (args.push_back(str)); - OZ (args.push_back(id)); + OZ (args.push_back(ps_sql)); OZ (args.push_back(type)); OZ (args.push_back(for_update)); OZ (args.push_back(hidden_rowid)); @@ -5086,20 +5093,20 @@ int ObPLCodeGenerator::generate_sql(const ObPLSqlStmt &s, ObLLVMValue &ret_err) ObSEArray args; ObLLVMValue str; ObLLVMValue len; - ObLLVMValue id; + ObLLVMValue ps_sql; ObLLVMValue type; ObLLVMValue for_update; ObLLVMValue hidden_rowid; ObLLVMValue params; ObLLVMValue count; OZ (args.push_back(get_vars().at(CTX_IDX))); - OZ (generate_sql(s, str, len, id, type, for_update, hidden_rowid, params, count)); + OZ (generate_sql(s, str, len, ps_sql, type, for_update, hidden_rowid, params, count)); if (OB_SUCC(ret)) { if (s.get_params().empty()) { OZ (args.push_back(str)); OZ (args.push_back(type)); } else { - OZ (args.push_back(id)); + OZ (args.push_back(ps_sql)); OZ (args.push_back(type)); OZ (args.push_back(params)); OZ (args.push_back(count)); @@ -6299,7 +6306,7 @@ int ObPLCodeGenerator::generate_loop_control(const ObPLLoopControl &control) int ObPLCodeGenerator::generate_sql(const ObPLSql &sql, jit::ObLLVMValue &str, jit::ObLLVMValue &length, - jit::ObLLVMValue &id, + jit::ObLLVMValue &ps_sql, jit::ObLLVMValue &type, jit::ObLLVMValue &for_update, jit::ObLLVMValue &hidden_rowid, @@ -6319,8 +6326,8 @@ int ObPLCodeGenerator::generate_sql(const ObPLSql &sql, } if (OB_SUCC(ret)) { - if (OB_FAIL(helper_.get_int64(sql.get_ps_id(), id))) { - LOG_WARN("failed to get int64", K(ret)); + if (OB_FAIL(generate_global_string(sql.get_ps_sql(), ps_sql, length))) { + LOG_WARN("failed to get_string", K(ret)); } else if (OB_FAIL(helper_.get_int64(sql.get_stmt_type(), type))) { LOG_WARN("failed to get int64", K(ret)); } else if (OB_FAIL(helper_.get_int8(sql.is_for_update(), for_update))) { @@ -7735,6 +7742,51 @@ int ObPLCodeGenerator::generate(ObPLPackage &pl_package) } int ObPLCodeGenerator::generate(ObPLFunction &pl_func) +{ + int ret = OB_SUCCESS; + ObPLFunctionAST &ast = static_cast(ast_); + if (debug_mode_ + || !ast.get_is_all_sql_stmt() + || !ast_.get_obj_access_exprs().empty()) { + OZ (generate_normal(pl_func)); + } else { + OZ (generate_simple(pl_func)); + } + LOG_TRACE("generate pl function", + K(debug_mode_), K(ast.get_is_all_sql_stmt()), K(ast.get_obj_access_exprs().empty())); + return ret; +} + +int ObPLCodeGenerator::generate_simple(ObPLFunction &pl_func) +{ + int ret = OB_SUCCESS; + ObPLFunctionAST &ast = static_cast(ast_); + common::ObFixedArray &sql_infos = pl_func.get_sql_infos(); + CK (!debug_mode_); + CK (ast.get_is_all_sql_stmt()); + OZ (prepare_expression(pl_func)); + OZ (final_expression(pl_func)); + OZ (pl_func.set_variables(get_ast().get_symbol_table())); + OZ (pl_func.get_dependency_table().assign(get_ast().get_dependency_table())); + OX (pl_func.add_members(get_ast().get_flag())); + OX (pl_func.set_pipelined(get_ast().get_pipelined())); + OX (pl_func.set_action((uint64_t)(&ObPL::simple_execute))); + OX (pl_func.set_can_cached(get_ast().get_can_cached())); + OX (pl_func.set_is_all_sql_stmt(get_ast().get_is_all_sql_stmt())); + + OX (sql_infos.set_capacity(static_cast(ast.get_sql_stmts().count()))); + for (int64_t i = 0; OB_SUCC(ret) && i < ast.get_sql_stmts().count(); ++i) { + const ObPLSqlStmt *sql_stmt = ast.get_sql_stmts().at(i); + ObPLSqlInfo sql_info(pl_func.get_allocator()); + CK (OB_NOT_NULL(sql_stmt)); + OZ (sql_info.generate(*sql_stmt, pl_func.get_expressions())); + OZ (sql_infos.push_back(sql_info)); + } + + return ret; +} + +int ObPLCodeGenerator::generate_normal(ObPLFunction &pl_func) { int ret = OB_SUCCESS; // 初始化符号表 diff --git a/src/pl/ob_pl_code_generator.h b/src/pl/ob_pl_code_generator.h index a2e1c3979..2fa19086d 100644 --- a/src/pl/ob_pl_code_generator.h +++ b/src/pl/ob_pl_code_generator.h @@ -201,6 +201,9 @@ public: int generate(ObPLFunction &pl_func); int generate(ObPLPackage &pl_package); + int generate_normal(ObPLFunction &pl_func); + int generate_simple(ObPLFunction &pl_func); + int generate_global_string(const ObString &string, jit::ObLLVMValue &str, jit::ObLLVMValue &len); int generate_string(const ObString &string, jit::ObLLVMValue &str, jit::ObLLVMValue &len); int generate_empty_string(jit::ObLLVMValue &str, jit::ObLLVMValue &len); @@ -216,7 +219,7 @@ public: int generate_sql(const ObPLSql &sql, jit::ObLLVMValue &str, jit::ObLLVMValue &length, - jit::ObLLVMValue &id, + jit::ObLLVMValue &ps_sql, jit::ObLLVMValue &type, jit::ObLLVMValue &for_update, jit::ObLLVMValue &hidden_rowid, diff --git a/src/pl/ob_pl_compile.cpp b/src/pl/ob_pl_compile.cpp index 17cdcfdca..91762ffcf 100644 --- a/src/pl/ob_pl_compile.cpp +++ b/src/pl/ob_pl_compile.cpp @@ -38,7 +38,8 @@ int ObPLCompiler::init_anonymous_ast( ObMySQLProxy &sql_proxy, ObSchemaGetterGuard &schema_guard, ObPLPackageGuard &package_guard, - const ParamStore *params) + const ParamStore *params, + bool is_prepare_protocol) { int ret = OB_SUCCESS; ObPLDataType pl_type; @@ -77,7 +78,16 @@ int ObPLCompiler::init_anonymous_ast( data_type.set_accuracy(params->at(i).get_accuracy()); data_type.set_meta_type(params->at(i).get_meta()); pl_type.reset(); - pl_type.set_data_type(data_type); + int64_t int_value = 0; + // 参数化整型常量按照会按照numbger来生成param + if (!is_prepare_protocol + && (ObNumberType == param.get_type() || ObUNumberType == param.get_type()) + && param.get_number().is_valid_int64(int_value) + && int_value <= INT32_MAX && int_value >= INT32_MIN) { + pl_type.set_pl_integer_type(PL_SIMPLE_INTEGER, data_type); + } else { + pl_type.set_data_type(data_type); + } OZ (ObPLResolver::adjust_routine_param_type(pl_type)); } OZ (func_ast.add_argument(ObPLResolver::ANONYMOUS_ARG, pl_type, NULL, NULL, true)); @@ -87,18 +97,18 @@ int ObPLCompiler::init_anonymous_ast( //for anonymous int ObPLCompiler::compile( - const ObStmtNodeTree *block, ObPLFunction &func, ParamStore *params/*=NULL*/) + const ObStmtNodeTree *block, + ObPLFunction &func, + ParamStore *params/*=NULL*/, + bool is_prepare_protocol/*=false*/) { int ret = OB_SUCCESS; FLTSpanGuard(pl_compile); - bool is_prepare_protocol = false; bool use_jitted_expr = false; //Step 1:构造匿名块的ObPLFunctionAST HEAP_VAR(ObPLFunctionAST, func_ast, allocator_) { - is_prepare_protocol = params != NULL ? true : false; - func_ast.set_db_name(session_info_.get_database_name()); OZ (init_anonymous_ast(func_ast, allocator_, @@ -106,7 +116,8 @@ int ObPLCompiler::compile( sql_proxy_, schema_guard_, package_guard_, - params)); + params, + is_prepare_protocol)); //Step 2:Resolver if (OB_SUCC(ret)) { @@ -132,9 +143,7 @@ int ObPLCompiler::compile( if (OB_SUCC(ret)) { func.set_proc_type(STANDALONE_ANONYMOUS); func.set_ns(ObLibCacheNameSpace::NS_ANON); - func.set_ps_cache(session_info_.get_ps_cache()); OZ (func.get_exec_env().load(session_info_)); - OZ (func.add_ps_stmt_ids(func_ast.get_ps_stmt_ids(), &session_info_)); } //Step 3:Code Generator if (OB_SUCC(ret)) { @@ -359,13 +368,6 @@ int ObPLCompiler::compile(const uint64_t id, ObPLFunction &func) } } } - // Process Prepare SQL Ref - if (OB_SUCC(ret)) { - func.set_ps_cache(session_info_.get_ps_cache()); - if (OB_FAIL(func.add_ps_stmt_ids(func_ast.get_ps_stmt_ids(), &session_info_))) { - LOG_WARN("failed to add ps stmt ids", K(ret)); - } - } int64_t resolve_end = ObTimeUtility::current_time(); LOG_INFO(">>>>>>>>Resolve Time: ", K(id), K(resolve_end - parse_end)); @@ -445,56 +447,64 @@ int ObPLCompiler::update_schema_object_dep_info(ObPLCompileUnitAST &ast, int ret = OB_SUCCESS; ObMySQLProxy *sql_proxy = nullptr; ObMySQLTransaction trans; + bool skip = false; if (GCTX.is_standby_cluster()) { - // do nothing; + skip = true; } else if (ObTriggerInfo::is_trigger_package_id(dep_obj_id)) { - // do nothing; - // trigger mock package, but it not do package ddl - } else if (OB_ISNULL(sql_proxy = GCTX.sql_proxy_)) { - ret = OB_ERR_UNEXPECTED; - } else if (OB_FAIL(trans.start(sql_proxy, tenant_id))) { - LOG_WARN("failed to start trans", K(ret), K(tenant_id)); - } else { - OZ (ObDependencyInfo::delete_schema_object_dependency(trans, - tenant_id, dep_obj_id, - schema_version, - dep_obj_type)); - ObSArray dep_infos; - ObString dummy; - OZ (ObDependencyInfo::collect_dep_infos(ast.get_dependency_table(), - dep_infos, - dep_obj_type, - 0, dummy, dummy)); - if (OB_FAIL(ret)) { - LOG_WARN("delete failed", K(ret)); - } else if (OB_INVALID_ID == owner_id - || OB_INVALID_ID == dep_obj_id - || OB_INVALID_ID == tenant_id - || OB_INVALID_SCHEMA_VERSION == schema_version) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("illegal schema version or owner id", K(ret), K(schema_version), - K(owner_id), K(dep_obj_id)); + if (lib::is_oracle_mode()) { + dep_obj_id = ObTriggerInfo::get_package_trigger_id(dep_obj_id); + dep_obj_type = ObObjectType::TRIGGER; } else { - for (int64_t i = 0 ; OB_SUCC(ret) && i < dep_infos.count(); ++i) { - ObDependencyInfo & dep = dep_infos.at(i); - dep.set_tenant_id(tenant_id); - dep.set_dep_obj_id(dep_obj_id); - dep.set_dep_obj_owner_id(owner_id); - dep.set_schema_version(schema_version); - OZ (dep.insert_schema_object_dependency(trans)); - // 理论上pl是单线程编译的,但是如果把这个相同的pl在多个observer上同时编译,这个依赖关系可能会多次重建。 - // 发生这种情况下,简单的忽略错误码 - if (OB_ERR_PRIMARY_KEY_DUPLICATE == ret) { - ret = OB_SUCCESS; - } - } + skip = true; } } - if (trans.is_started()) { - int temp_ret = OB_SUCCESS; - if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) { - LOG_WARN("trans end failed", "is_commit", OB_SUCC(ret), K(ret), K(temp_ret)); - ret = OB_SUCC(ret) ? temp_ret : ret; + if (!skip) { + if (OB_ISNULL(sql_proxy = GCTX.sql_proxy_)) { + ret = OB_ERR_UNEXPECTED; + } else if (OB_FAIL(trans.start(sql_proxy, tenant_id))) { + LOG_WARN("failed to start trans", K(ret), K(tenant_id)); + } else { + OZ (ObDependencyInfo::delete_schema_object_dependency(trans, + tenant_id, dep_obj_id, + schema_version, + dep_obj_type)); + ObSArray dep_infos; + ObString dummy; + OZ (ObDependencyInfo::collect_dep_infos(ast.get_dependency_table(), + dep_infos, + dep_obj_type, + 0, dummy, dummy)); + if (OB_FAIL(ret)) { + LOG_WARN("delete failed", K(ret)); + } else if (OB_INVALID_ID == owner_id + || OB_INVALID_ID == dep_obj_id + || OB_INVALID_ID == tenant_id + || OB_INVALID_SCHEMA_VERSION == schema_version) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("illegal schema version or owner id", K(ret), K(schema_version), + K(owner_id), K(dep_obj_id)); + } else { + for (int64_t i = 0 ; OB_SUCC(ret) && i < dep_infos.count(); ++i) { + ObDependencyInfo & dep = dep_infos.at(i); + dep.set_tenant_id(tenant_id); + dep.set_dep_obj_id(dep_obj_id); + dep.set_dep_obj_owner_id(owner_id); + dep.set_schema_version(schema_version); + OZ (dep.insert_schema_object_dependency(trans)); + // 理论上pl是单线程编译的,但是如果把这个相同的pl在多个observer上同时编译,这个依赖关系可能会多次重建。 + // 发生这种情况下,简单的忽略错误码 + if (OB_ERR_PRIMARY_KEY_DUPLICATE == ret) { + ret = OB_SUCCESS; + } + } + } + } + if (trans.is_started()) { + int temp_ret = OB_SUCCESS; + if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) { + LOG_WARN("trans end failed", "is_commit", OB_SUCC(ret), K(ret), K(temp_ret)); + ret = OB_SUCC(ret) ? temp_ret : ret; + } } } return ret; @@ -636,8 +646,7 @@ int ObPLCompiler::compile_package(const ObPackageInfo &package_info, OX (package_ast.set_priv_user(trigger_info->get_trigger_priv_user())); } if (OB_SUCC(ret)) { - if (package_info.is_for_trigger() && lib::is_oracle_mode()) { - // oracle mode 的 trigger每次编译重新生成package source + if (package_info.is_for_trigger()) { OZ (ObTriggerInfo::gen_package_source(package_info.get_tenant_id(), package_info.get_package_id(), source, @@ -901,7 +910,7 @@ int ObPLCompiler::generate_package_cursors( ast_cursor->get_index(),//代表在Package符号表中的位置 sql,//Cursor Sql sql_params,//Cursor参数表达式 - ast_cursor->get_ps_id(), + ast_cursor->get_ps_sql(), ast_cursor->get_stmt_type(), ast_cursor->is_for_update(), ast_cursor->has_hidden_rowid(), @@ -1065,8 +1074,6 @@ int ObPLCompiler::compile_subprogram_table(common::ObIAllocator &allocator, LOG_WARN("allocate memory failed", K(ret)); } else { new (routine) ObPLFunction(compile_unit.get_mem_context()); - routine->set_ps_cache(session_info.get_ps_cache()); - OZ (routine->add_ps_stmt_ids(routine_ast->get_ps_stmt_ids(), &session_info)); OZ (init_function(schema_guard, exec_env, *routine_info, *routine)); if (OB_SUCC(ret)) { diff --git a/src/pl/ob_pl_compile.h b/src/pl/ob_pl_compile.h index 551fa2b8b..84812f22e 100644 --- a/src/pl/ob_pl_compile.h +++ b/src/pl/ob_pl_compile.h @@ -51,7 +51,9 @@ public: int compile(const ObStmtNodeTree *block, ObPLFunction &func, - ParamStore *params= NULL); //匿名块接口 + ParamStore *params, + bool is_prepare_protocol); //匿名块接口 + int compile(const uint64_t id, ObPLFunction &func); //Procedure/Function接口 int analyze_package(const ObString &source, const ObPLBlockNS *parent_ns, @@ -72,9 +74,15 @@ public: ObMySQLProxy &sql_proxy, share::schema::ObSchemaGetterGuard &schema_guard, pl::ObPLPackageGuard &package_guard, - const ParamStore *params); + const ParamStore *params, + bool is_prepare_protocol = true); int check_package_body_legal(const ObPLBlockNS *parent_ns, const ObPLPackageAST &package_ast); + static int update_schema_object_dep_info(pl::ObPLCompileUnitAST &ast, + uint64_t tenant_id, + uint64_t dep_obj_id, uint64_t schema_version, + uint64_t owner_id, + share::schema::ObObjectType dep_obj_type); private: int init_function(const share::schema::ObRoutineInfo *proc, ObPLFunction &func); @@ -95,11 +103,6 @@ private: int generate_package_routines(const ObString &exec_env, ObPLRoutineTable &routine_table, ObPLPackage &package); - int update_schema_object_dep_info(pl::ObPLCompileUnitAST &ast, - uint64_t tenant_id, - uint64_t dep_obj_id, uint64_t schema_version, - uint64_t owner_id, - share::schema::ObObjectType dep_obj_type); static int compile_types(const ObIArray &types, ObPLCompileUnit &unit); static int format_object_name(share::schema::ObSchemaGetterGuard &schema_guard, const uint64_t tenant_id, diff --git a/src/pl/ob_pl_exception_handling.cpp b/src/pl/ob_pl_exception_handling.cpp index 6be8e0fd0..35c2d8841 100644 --- a/src/pl/ob_pl_exception_handling.cpp +++ b/src/pl/ob_pl_exception_handling.cpp @@ -120,6 +120,7 @@ ObPLException::ObPLException(int64_t error_code) new(&type_)ObPLConditionValue(ERROR_CODE, error_code); } + ObUnwindException *ObPLEH::eh_create_exception(int64_t pl_context, int64_t pl_function, int64_t loc, @@ -171,6 +172,8 @@ ObUnwindException *ObPLEH::eh_create_exception(int64_t pl_context, } } tl_eptr = unwind; + + } return unwind; } diff --git a/src/pl/ob_pl_exception_handling.h b/src/pl/ob_pl_exception_handling.h index 4bf6b7569..994d96ae7 100644 --- a/src/pl/ob_pl_exception_handling.h +++ b/src/pl/ob_pl_exception_handling.h @@ -65,6 +65,7 @@ public: static int eh_convert_exception(bool oracle_mode, int oberr, ObPLConditionType *type, int64_t *error_code, const char **sql_state, int64_t *str_len); static ObPLConditionType eh_classify_exception(const char *sql_state); + public: static void eh_debug_int64(const char *name_ptr, int64_t name_len, int64_t object); diff --git a/src/pl/ob_pl_package_manager.cpp b/src/pl/ob_pl_package_manager.cpp index fd8da3b48..2ff4fa107 100644 --- a/src/pl/ob_pl_package_manager.cpp +++ b/src/pl/ob_pl_package_manager.cpp @@ -27,6 +27,7 @@ #include "observer/ob_server_struct.h" #include "observer/ob_req_time_service.h" #include "lib/file/file_directory_utils.h" +#include "pl/pl_cache/ob_pl_cache_mgr.h" namespace oceanbase { @@ -859,7 +860,7 @@ int ObPLPackageManager::load_package_body(const ObPLResolveCtx &resolve_ctx, HEAP_VARS_2((ObPLPackageAST, package_spec_ast, resolve_ctx.allocator_), (ObPLPackageAST, package_body_ast, resolve_ctx.allocator_)) { ObString source; - if (package_spec_info.is_for_trigger() && lib::is_oracle_mode()) { + if (package_spec_info.is_for_trigger()) { OZ (ObTriggerInfo::gen_package_source(package_spec_info.get_tenant_id(), package_spec_info.get_package_id(), source, @@ -1278,26 +1279,29 @@ int ObPLPackageManager::add_package_to_plan_cache(const ObPLResolveCtx &resolve_ int64_t tenant_id = resolve_ctx.session_info_.get_effective_tenant_id(); uint64_t package_id = package->get_id(); ObString sql("package"); - ObArenaAllocator allocator(ObModIds::OB_PL_TEMP); - // empty plan ctx - ObPhysicalPlanCtx phy_plan_ctx(resolve_ctx.allocator_); - HEAP_VAR(ObExecContext, exec_ctx, allocator) { - exec_ctx.set_physical_plan_ctx(&phy_plan_ctx); - exec_ctx.set_my_session(&resolve_ctx.session_info_); - ObSqlCtx sql_ctx; - sql_ctx.session_info_ = &resolve_ctx.session_info_; - sql_ctx.schema_guard_ = &resolve_ctx.schema_guard_; - (void)ObSQLUtils::md5(sql,sql_ctx.sql_id_, (int32_t)sizeof(sql_ctx.sql_id_)); - ObPlanCacheCtx pc_ctx(sql, false, resolve_ctx.allocator_, sql_ctx, exec_ctx, tenant_id); - pc_ctx.fp_result_.reset(); - pc_ctx.fp_result_.pc_key_.key_id_ = package_id; - pc_ctx.fp_result_.pc_key_.namespace_ = ObLibCacheNameSpace::NS_PKG; - pc_ctx.fp_result_.pc_key_.sessid_ = - (get_tenant_id_by_object_id(package_id) != OB_SYS_TENANT_ID && resolve_ctx.session_info_.is_pl_debug_on()) - ? resolve_ctx.session_info_.get_sessid() : 0; + //ObArenaAllocator allocator(ObModIds::OB_PL_TEMP); + + //HEAP_VAR(ObExecContext, exec_ctx, allocator) { + + uint64_t database_id = OB_INVALID_ID; + resolve_ctx.session_info_.get_database_id(database_id); + + ObPLCacheCtx pc_ctx; + pc_ctx.session_info_ = &resolve_ctx.session_info_; + pc_ctx.schema_guard_ = &resolve_ctx.schema_guard_; + (void)ObSQLUtils::md5(sql,pc_ctx.sql_id_, (int32_t)sizeof(pc_ctx.sql_id_)); int64_t sys_schema_version = OB_INVALID_VERSION; int64_t tenant_schema_version = OB_INVALID_VERSION; - if (OB_FAIL(resolve_ctx.schema_guard_.get_schema_version(tenant_id, tenant_schema_version)) + + pc_ctx.key_.namespace_ = ObLibCacheNameSpace::NS_PKG; + pc_ctx.key_.db_id_ = database_id; + pc_ctx.key_.key_id_ = package_id; + pc_ctx.key_.sessid_ = + (get_tenant_id_by_object_id(package_id) != OB_SYS_TENANT_ID && resolve_ctx.session_info_.is_pl_debug_on()) + ? resolve_ctx.session_info_.get_sessid() : 0; + + if (OB_FAIL(ret)) { + } else if (OB_FAIL(resolve_ctx.schema_guard_.get_schema_version(tenant_id, tenant_schema_version)) || OB_FAIL(resolve_ctx.schema_guard_.get_schema_version(OB_SYS_TENANT_ID, sys_schema_version))) { LOG_WARN("fail to get schema version", K(ret), K(tenant_id)); } else { @@ -1306,7 +1310,7 @@ int ObPLPackageManager::add_package_to_plan_cache(const ObPLResolveCtx &resolve_ } if (OB_FAIL(ret)) { // do nothing - } else if (OB_FAIL(plan_cache->add_pl_cache(package, pc_ctx))) { + } else if (OB_FAIL(ObPLCacheMgr::add_pl_cache(resolve_ctx.session_info_.get_plan_cache(), package, pc_ctx))) { if (OB_SQL_PC_PLAN_DUPLICATE == ret) { LOG_INFO("package has been added by others, need not add again", K(package_id), K(ret)); ret = OB_SUCCESS; @@ -1323,10 +1327,10 @@ int ObPLPackageManager::add_package_to_plan_cache(const ObPLResolveCtx &resolve_ } } else { LOG_INFO("add pl package to plan cache success", - K(ret), K(package_id), K(package->get_dependency_table()), K(pc_ctx.fp_result_)); + K(ret), K(package_id), K(package->get_dependency_table()), K(pc_ctx.key_)); } - exec_ctx.set_physical_plan_ctx(NULL); - } + //exec_ctx.set_physical_plan_ctx(NULL); + //} } return ret; } @@ -1337,7 +1341,6 @@ int ObPLPackageManager::get_package_from_plan_cache(const ObPLResolveCtx &resolv { int ret = OB_SUCCESS; package = NULL; - ObPlanCache *plan_cache = NULL; bool is_overflow = false; if (OB_FAIL(check_stack_overflow(is_overflow))) { LOG_WARN("failed to check stack overflow", K(ret)); @@ -1347,33 +1350,34 @@ int ObPLPackageManager::get_package_from_plan_cache(const ObPLResolveCtx &resolv } if (OB_FAIL(ret)) { // do nothing - } else if (OB_ISNULL(plan_cache = resolve_ctx.session_info_.get_plan_cache())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("plan cache is null", K(ret)); } else { ObString sql("package"); - SMART_VAR(ObExecContext, exec_ctx, resolve_ctx.allocator_) { - exec_ctx.set_my_session(&resolve_ctx.session_info_); - ObSqlCtx sql_ctx; - sql_ctx.session_info_ = &resolve_ctx.session_info_; - sql_ctx.schema_guard_ = &resolve_ctx.schema_guard_; - (void)ObSQLUtils::md5(sql,sql_ctx.sql_id_, (int32_t)sizeof(sql_ctx.sql_id_)); - ObPlanCacheCtx pc_ctx(sql, false, resolve_ctx.allocator_, sql_ctx, exec_ctx, resolve_ctx.session_info_.get_effective_tenant_id()); - pc_ctx.fp_result_.reset(); - pc_ctx.fp_result_.pc_key_.key_id_ = package_id; - pc_ctx.fp_result_.pc_key_.namespace_ = ObLibCacheNameSpace::NS_PKG; - pc_ctx.fp_result_.pc_key_.sessid_ = + //SMART_VAR(ObExecContext, exec_ctx, resolve_ctx.allocator_) { + + uint64_t database_id = OB_INVALID_ID; + resolve_ctx.session_info_.get_database_id(database_id); + + ObPLCacheCtx pc_ctx; + pc_ctx.session_info_ = &resolve_ctx.session_info_; + pc_ctx.schema_guard_ = &resolve_ctx.schema_guard_; + (void)ObSQLUtils::md5(sql,pc_ctx.sql_id_, (int32_t)sizeof(pc_ctx.sql_id_)); + pc_ctx.key_.namespace_ = ObLibCacheNameSpace::NS_PKG; + pc_ctx.key_.db_id_ = database_id; + pc_ctx.key_.key_id_ = package_id; + pc_ctx.key_.sessid_ = (get_tenant_id_by_object_id(package_id) != OB_SYS_TENANT_ID && resolve_ctx.session_info_.is_pl_debug_on()) ? resolve_ctx.session_info_.get_sessid() : 0; + // get package from plan cache ObCacheObjGuard* cacheobj_guard = NULL; void* buf = NULL; - if (OB_ISNULL(buf = resolve_ctx.package_guard_.alloc_.alloc(sizeof(ObCacheObjGuard)))) { + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(buf = resolve_ctx.package_guard_.alloc_.alloc(sizeof(ObCacheObjGuard)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory.", K(ret)); } else if (FALSE_IT(cacheobj_guard = new (buf)ObCacheObjGuard(GET_PKG_HANDLE))) { // do nothing - } else if (OB_FAIL(plan_cache->get_pl_package(*cacheobj_guard, pc_ctx))) { + } else if (OB_FAIL(ObPLCacheMgr::get_pl_cache(resolve_ctx.session_info_.get_plan_cache(), *cacheobj_guard, pc_ctx))) { LOG_INFO("get pl package from plan cache failed", K(ret), K(package_id)); if (OB_ERR_UNEXPECTED != ret) { ret = OB_SUCCESS; @@ -1390,7 +1394,7 @@ int ObPLPackageManager::get_package_from_plan_cache(const ObPLResolveCtx &resolv LOG_DEBUG("get package from plan cache success", K(ret), K(package_id)); } } else {} - } + //} } return ret; } diff --git a/src/pl/ob_pl_resolver.cpp b/src/pl/ob_pl_resolver.cpp index 4565d858a..ebf014f4f 100644 --- a/src/pl/ob_pl_resolver.cpp +++ b/src/pl/ob_pl_resolver.cpp @@ -646,6 +646,7 @@ int ObPLResolver::resolve(const ObStmtNodeTree *parse_tree, ObPLFunctionAST &fun signal_stmt->set_sql_state(ob_sqlstate(save_ret)); signal_stmt->set_str_len(STRLEN(ob_sqlstate(save_ret))); func.set_can_cached(false); + func.set_is_all_sql_stmt(false); } } @@ -2562,6 +2563,17 @@ int ObPLResolver::resolve_declare_var_comm(const ObStmtNodeTree *parse_tree, ret = OB_ERR_EXPRESSION_WRONG_TYPE; LOG_WARN("PLS-00382: expression is of wrong type", K(ret)); } + if (OB_SUCC(ret) && not_null && T_QUESTIONMARK == default_node->children_[0]->type_) { + int64_t idx = default_node->children_[0]->value_; + const ObPLVar* var = current_block_->get_symbol_table()->get_symbol(idx); + if (NULL != var && + 0 == var->get_name().case_compare(ObPLResolver::ANONYMOUS_ARG) && + NULL != var->get_pl_data_type().get_data_type() && + ObNullType == var->get_pl_data_type().get_data_type()->get_obj_type()) { + ret = OB_ERR_EXPRESSION_WRONG_TYPE; + LOG_WARN("PLS-00382: expression is of wrong type", K(ret)); + } + } OZ (resolve_expr(default_node->children_[0], unit_ast, default_expr, combine_line_and_col(default_node->children_[0]->stmt_loc_), @@ -4588,7 +4600,7 @@ int ObPLResolver::resolve_static_sql(const ObStmtNodeTree *parse_tree, ObPLSql & } } if (OB_SUCC(ret)) { - static_sql.set_ps(prepare_result.id_, prepare_result.type_); + static_sql.set_ps_sql(prepare_result.ps_sql_, prepare_result.type_); static_sql.set_sql(prepare_result.route_sql_); static_sql.set_for_update(prepare_result.for_update_); static_sql.set_hidden_rowid(prepare_result.has_hidden_rowid_); @@ -4612,9 +4624,7 @@ int ObPLResolver::resolve_static_sql(const ObStmtNodeTree *parse_tree, ObPLSql & } if (OB_SUCC(ret)) { - if (OB_FAIL(func.add_ps_stmt_id(prepare_result.id_))) { - LOG_WARN("add ps stmt id failed", K(ret), K(prepare_result.id_)); - } else if (OB_FAIL(func.add_dependency_objects(prepare_result.ref_objects_))) { + if (OB_FAIL(func.add_dependency_objects(prepare_result.ref_objects_))) { LOG_WARN("add dependency tables failed", K(ret)); } else if (OB_FAIL(static_sql.set_ref_objects(prepare_result.ref_objects_))) { LOG_WARN("set ref objects failed", K(ret)); @@ -4632,6 +4642,7 @@ int ObPLResolver::resolve_sql(const ObStmtNodeTree *parse_tree, ObPLSqlStmt *stm int ret = OB_SUCCESS; CK(OB_NOT_NULL(stmt)); OZ (resolve_static_sql(parse_tree, *stmt, *stmt, false/*not cursor*/, func)); + OZ (func.get_sql_stmts().push_back(stmt)); return ret; } @@ -5652,7 +5663,17 @@ int ObPLResolver::resolve_inout_param(ObRawExpr *param_expr, ObPLRoutineParamMod } } else if (param_expr->is_const_raw_expr()) { // 本地变量做出参 const ObConstRawExpr *const_expr = static_cast(param_expr); - if (T_QUESTIONMARK != const_expr->get_expr_type()) { + const ObPLSymbolTable *table = current_block_->get_symbol_table(); + const ObPLVar *var = NULL; + bool is_anonymos_const_var = false; + if (!resolve_ctx_.is_prepare_protocol_ && + T_QUESTIONMARK == const_expr->get_expr_type() && + OB_NOT_NULL(table) && + OB_NOT_NULL(var = table->get_symbol(const_expr->get_value().get_unknown())) && + 0 == var->get_name().case_compare(pl::ObPLResolver::ANONYMOUS_ARG)) { + is_anonymos_const_var = true; + } + if (T_QUESTIONMARK != const_expr->get_expr_type() || is_anonymos_const_var) { ret = OB_NOT_SUPPORTED; LOG_WARN("procedure parameter expr type is wrong", K(ret), K(const_expr->get_expr_type())); } else { @@ -6254,9 +6275,7 @@ int ObPLResolver::resolve_cursor_def(const ObString &cursor_name, } } if (OB_SUCC(ret)) { - if (OB_FAIL(func.add_ps_stmt_id(prepare_result.id_))) { - LOG_WARN("failed to add ps stmt id", K(prepare_result.id_), K(ret)); - } else if (OB_FAIL(func.add_dependency_objects(prepare_result.ref_objects_))) { + if (OB_FAIL(func.add_dependency_objects(prepare_result.ref_objects_))) { LOG_WARN("failed to set ref object", K(prepare_result.ref_objects_), K(ret)); } } @@ -6307,7 +6326,7 @@ int ObPLResolver::resolve_cursor_def(const ObString &cursor_name, type, prepare_result.route_sql_, expr_idxs, - prepare_result.id_, + prepare_result.ps_sql_, prepare_result.type_, prepare_result.for_update_, prepare_result.has_hidden_rowid_, @@ -6322,7 +6341,7 @@ int ObPLResolver::resolve_cursor_def(const ObString &cursor_name, K(cursor_name), K(sql_node->str_value_), K(prepare_result.exec_params_), - K(prepare_result.id_), + K(prepare_result.ps_sql_), K(prepare_result.type_), K(prepare_result.for_update_), K(ret)); @@ -6368,7 +6387,7 @@ int ObPLResolver::resolve_cursor_def(const ObString &cursor_name, //仅当原型和声明完全一致时,才是合法 OZ (cursor->set(prepare_result.route_sql_, expr_idxs, - prepare_result.id_, + prepare_result.ps_sql_, prepare_result.type_, prepare_result.for_update_, record_type, @@ -6394,7 +6413,7 @@ int ObPLResolver::resolve_cursor_def(const ObString &cursor_name, } else { OZ (const_cast(external_cursor)->set(prepare_result.route_sql_, expr_idxs, - prepare_result.id_, + prepare_result.ps_sql_, prepare_result.type_, prepare_result.for_update_, record_type, @@ -6492,7 +6511,7 @@ int ObPLResolver::resolve_declare_cursor( ObPLDataType(PL_CURSOR_TYPE), ObString(), ObArray(), - OB_INVALID_ID, + ObString(), stmt::T_NONE, false, //for update false, //hidden rowid @@ -7102,7 +7121,7 @@ int ObPLResolver::add_pl_integer_checker_expr(ObRawExprFactory &expr_factory, return ret; } -int ObPLResolver::check_expr_result_type(const ObRawExpr *expr, ObPLIntegerType &pl_integer_type) +int ObPLResolver::check_expr_result_type(const ObRawExpr *expr, ObPLIntegerType &pl_integer_type, bool &is_anonymos_arg) { int ret = OB_SUCCESS; CK(OB_NOT_NULL(expr)); @@ -7152,6 +7171,9 @@ int ObPLResolver::check_expr_result_type(const ObRawExpr *expr, ObPLIntegerType ret = OB_ERR_UNEXPECTED; LOG_WARN("get symble var is null", K(var), K(const_expr->get_value().get_unknown()), K(ret)); } else { + if (0 == var->get_name().case_compare(ObPLResolver::ANONYMOUS_ARG)) { + is_anonymos_arg = true; + } pl_integer_type = var->get_type().get_pl_integer_type(); } } else if (expr->is_udf_expr()) { @@ -7200,9 +7222,11 @@ int ObPLResolver::add_pl_integer_checker_expr(ObRawExprFactory &expr_factory, const ObRawExpr *left = ObRawExprUtils::skip_implicit_cast(expr->get_param_expr(0)); const ObRawExpr *right = ObRawExprUtils::skip_implicit_cast(expr->get_param_expr(1)); ObPLIntegerType left_pl_integer = PL_INTEGER_INVALID, right_pl_integer = PL_INTEGER_INVALID; - if (OB_FAIL(check_expr_result_type(left, left_pl_integer))) { + bool is_anonymos_arg_left = false; + bool is_anonymos_arg_right = false; + if (OB_FAIL(check_expr_result_type(left, left_pl_integer, is_anonymos_arg_left))) { LOG_WARN("failed to check expr result type", K(ret)); - } else if (OB_FAIL(check_expr_result_type(right, right_pl_integer))) { + } else if (OB_FAIL(check_expr_result_type(right, right_pl_integer, is_anonymos_arg_right))) { LOG_WARN("failed to check expr result type", K(ret)); } else if (PL_INTEGER_INVALID != left_pl_integer && PL_INTEGER_INVALID != right_pl_integer) { ObPLIntegerType type = PL_SIMPLE_INTEGER == left_pl_integer && PL_SIMPLE_INTEGER == right_pl_integer ? @@ -7212,7 +7236,9 @@ int ObPLResolver::add_pl_integer_checker_expr(ObRawExprFactory &expr_factory, However, to ensure backward compatibility, when all operands in an arithmetic expression are integer literals, PL/SQL treats the integer literals as if they were cast to PLS_INTEGER. */ - if (PL_SIMPLE_INTEGER == type && T_INT == left->get_expr_type() && T_INT == right->get_expr_type()) { + if (PL_SIMPLE_INTEGER == type && + ((T_INT == left->get_expr_type() && T_INT == right->get_expr_type()) || + (is_anonymos_arg_left && is_anonymos_arg_right))) { type = PL_PLS_INTEGER; } OZ (add_pl_integer_checker_expr(expr_factory, type, -2147483648, 2147483647, expr)); @@ -8208,6 +8234,9 @@ int ObPLResolver::resolve_expr(const ParseNode *node, || T_NULL == expr->get_expr_type() || ObTinyIntType == expr->get_result_type().get_type()) { // do nothing ... + } else if (T_QUESTIONMARK == expr->get_expr_type() && + ObNullType == expr->get_data_type()) { + // do nothing ... } else { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("PLS-00382: expression is of wrong type", @@ -8388,8 +8417,6 @@ int ObPLResolver::transform_subquery_expr(const ParseNode *node, LOG_WARN("unexpected into expr", K(ret)); } else if (OB_FAIL(func.add_sql_exprs(prepare_result.exec_params_))) { LOG_WARN("failed to set precalc exprs", K(prepare_result.exec_params_), K(ret)); - } else if (OB_FAIL(func.add_ps_stmt_id(prepare_result.id_))) { - LOG_WARN("failed to add ps stmt id", K(prepare_result.id_), K(ret)); } else if (OB_FAIL(func.add_dependency_objects(prepare_result.ref_objects_))) { LOG_WARN("failed to add dependency objects", K(prepare_result.ref_objects_), K(ret)); } @@ -8398,7 +8425,7 @@ int ObPLResolver::transform_subquery_expr(const ParseNode *node, ObPlQueryRefRawExpr *subquery_expr = nullptr; OZ (expr_factory_.create_raw_expr(T_FUN_SUBQUERY, subquery_expr)); - OX (subquery_expr->set_ps_id(prepare_result.id_)); + OX (subquery_expr->set_ps_sql(prepare_result.ps_sql_)); OX (subquery_expr->set_stmt_type(prepare_result.type_)); OX (subquery_expr->set_route_sql(prepare_result.route_sql_)); @@ -8612,7 +8639,10 @@ int ObPLResolver::resolve_raw_expr(const ParseNode &node, ns.get_external_ns()->get_resolve_ctx().sql_proxy_, expr_factory, ns.get_external_ns()->get_parent_ns(), - is_prepare_protocol); + is_prepare_protocol, + false, + false, + ns.get_external_ns()->get_resolve_ctx().params_.param_list_); HEAP_VAR(pl::ObPLFunctionAST, func_ast, allocator) { OC( (resolver.init)(func_ast) ); if (OB_SUCC(ret)) { @@ -12692,7 +12722,7 @@ int ObPLResolver::add_external_cursor(ObPLBlockNS &ns, cursor.get_index(), sql, sql_params, - cursor.get_ps_id(), + cursor.get_ps_sql(), cursor.get_stmt_type(), cursor.is_for_update(), cursor.has_hidden_rowid(), diff --git a/src/pl/ob_pl_resolver.h b/src/pl/ob_pl_resolver.h index 11814ab10..414e096ad 100644 --- a/src/pl/ob_pl_resolver.h +++ b/src/pl/ob_pl_resolver.h @@ -849,7 +849,7 @@ private: common::ObIArray &udf_info, common::ObIArray &op_exprs, bool is_prepare_protocol/*= false*/); - int check_expr_result_type(const ObRawExpr *expr, ObPLIntegerType &pl_integer_type); + int check_expr_result_type(const ObRawExpr *expr, ObPLIntegerType &pl_integer_type, bool &is_anonymos_arg); bool is_need_add_checker(const ObPLIntegerType &type, const ObRawExpr *expr); int add_pl_integer_checker_expr(ObRawExprFactory &expr_factory, const ObPLIntegerType &type, diff --git a/src/pl/ob_pl_stmt.cpp b/src/pl/ob_pl_stmt.cpp index c49dcae98..c08b8a565 100644 --- a/src/pl/ob_pl_stmt.cpp +++ b/src/pl/ob_pl_stmt.cpp @@ -259,7 +259,7 @@ int ObPLConditionTable::add_condition(const common::ObString &name, const ObPLCo int ObPLCursor::set(const ObString &sql, const ObIArray &expr_idxs, - ObPsStmtId id, + const ObString &ps_sql, sql::stmt::StmtType type, bool for_update, ObRecordType *record_type, @@ -272,7 +272,7 @@ int ObPLCursor::set(const ObString &sql, int ret = OB_SUCCESS; set_sql(sql); set_sql_params(expr_idxs); - set_ps(id, type); + set_ps_sql(ps_sql, type); set_for_update(for_update); set_row_desc(record_type); set_cursor_type(cursor_type); @@ -287,7 +287,7 @@ int ObPLCursorTable::add_cursor(uint64_t pkg_id, int64_t idx, const ObString &sql, const ObIArray &sql_params, - ObPsStmtId ps_id, + const ObString &ps_sql, sql::stmt::StmtType stmt_type, bool for_update, bool has_hidden_rowid, @@ -312,7 +312,7 @@ int ObPLCursorTable::add_cursor(uint64_t pkg_id, cursor->set_index(idx); cursor->set_sql(sql); cursor->set_sql_params(sql_params); - cursor->set_ps(ps_id, stmt_type); + cursor->set_ps_sql(ps_sql, stmt_type); cursor->set_for_update(for_update); cursor->set_hidden_rowid(has_hidden_rowid); cursor->set_row_desc(row_desc); @@ -1062,7 +1062,7 @@ int ObPLBlockNS::add_questionmark_cursor(const int64_t symbol_idx) { int ret = OB_SUCCESS; ObArray dummy_params; - ObPsStmtId dummy_ps_id = OB_INVALID_ID; + ObString dummy_sql; sql::stmt::StmtType dummy_stmt_type = sql::stmt::T_NONE; bool dummy_for_update = false; bool dummy_hidden_rowid = false; @@ -1076,7 +1076,7 @@ int ObPLBlockNS::add_questionmark_cursor(const int64_t symbol_idx) symbol_idx, "?", dummy_params, - dummy_ps_id, + dummy_sql, dummy_stmt_type, false, false, @@ -1095,7 +1095,7 @@ int ObPLBlockNS::add_cursor(const ObString &name, const ObPLDataType &type, const ObString &sql, const ObIArray &sql_params, - ObPsStmtId ps_id, + const ObString &ps_sql, sql::stmt::StmtType stmt_type, bool for_update, bool has_hidden_rowid, @@ -1127,7 +1127,7 @@ int ObPLBlockNS::add_cursor(const ObString &name, get_symbol_table()->get_count() - 1, sql, sql_params, - ps_id, + ps_sql, stmt_type, for_update, has_hidden_rowid, @@ -4042,7 +4042,6 @@ int ObPLFunctionAST::add_argument(const common::ObString &name, } else if (type.is_cursor_type()) { ObString dummy_sql; ObArray dummy_params; - ObPsStmtId dummy_ps_id = OB_INVALID_ID; sql::stmt::StmtType dummy_stmt_type = sql::stmt::T_NONE; bool dummy_for_update = false; bool dummy_hidden_rowid = false; @@ -4054,7 +4053,7 @@ int ObPLFunctionAST::add_argument(const common::ObString &name, get_symbol_table().get_count() -1, dummy_sql, dummy_params, - dummy_ps_id, + dummy_sql, dummy_stmt_type, dummy_for_update, dummy_hidden_rowid, diff --git a/src/pl/ob_pl_stmt.h b/src/pl/ob_pl_stmt.h index c1523c763..c55a931a6 100644 --- a/src/pl/ob_pl_stmt.h +++ b/src/pl/ob_pl_stmt.h @@ -453,11 +453,11 @@ public: sql_(), params_(allocator), array_binding_params_(allocator), - ps_id_(common::OB_INVALID_ID), stmt_type_(sql::stmt::T_NONE), ref_objects_(allocator), row_desc_(NULL), - rowid_table_id_(OB_INVALID_ID) {} + rowid_table_id_(OB_INVALID_ID), + ps_sql_() {} virtual ~ObPLSql() {} inline const common::ObString &get_sql() const { return sql_; } @@ -474,9 +474,9 @@ public: inline bool has_hidden_rowid() const { return has_hidden_rowid_; } inline const common::ObIArray &get_array_binding_params() const { return array_binding_params_; } inline common::ObIArray &get_array_binding_params() { return array_binding_params_; } - inline ObPsStmtId get_ps_id() const { return ps_id_; } + inline const common::ObString &get_ps_sql() const { return ps_sql_; } inline sql::stmt::StmtType get_stmt_type() const { return stmt_type_; } - inline void set_ps(const ObPsStmtId id, const sql::stmt::StmtType type) { ps_id_ = id; stmt_type_ = type; } + inline void set_ps_sql(const common::ObString &sql, const sql::stmt::StmtType type) { ps_sql_ = sql; stmt_type_ = type; } inline const common::ObIArray &get_ref_objects() const { return ref_objects_; } inline int set_ref_objects(const common::ObIArray &objects) { return append(ref_objects_, objects); } inline int add_ref_object(const share::schema::ObSchemaObjVersion &object) { return ref_objects_.push_back(object); } @@ -485,7 +485,7 @@ public: inline uint64_t get_rowid_table_id() const { return rowid_table_id_; } inline void set_rowid_table_id(uint64 table_id) { rowid_table_id_ = table_id; } - TO_STRING_KV(K_(sql), K_(params), K_(ps_id), K_(stmt_type), K_(ref_objects), K_(rowid_table_id)); + TO_STRING_KV(K_(sql), K_(params), K_(ps_sql), K_(stmt_type), K_(ref_objects), K_(rowid_table_id)); protected: bool forall_sql_; @@ -494,11 +494,11 @@ protected: common::ObString sql_; ObPLSEArray params_; ObPLSEArray array_binding_params_; - ObPsStmtId ps_id_; sql::stmt::StmtType stmt_type_; ObPLSEArray ref_objects_; const ObRecordType *row_desc_; uint64_t rowid_table_id_; + common::ObString ps_sql_; }; class ObPLCursor @@ -542,9 +542,9 @@ public: inline int64_t get_sql_param(int64_t i) const { return value_.get_param(i); } inline int set_sql_params(const common::ObIArray ¶ms) { return value_.set_params(params); } inline int add_sql_param(int64_t expr) { return value_.add_param(expr); } - inline ObPsStmtId get_ps_id() const { return value_.get_ps_id(); } + inline const common::ObString &get_ps_sql() const { return value_.get_ps_sql(); } inline sql::stmt::StmtType get_stmt_type() const { return value_.get_stmt_type(); } - inline void set_ps(const ObPsStmtId id, const sql::stmt::StmtType type) { value_.set_ps(id, type); } + inline void set_ps_sql(const common::ObString &sql, const sql::stmt::StmtType type) { value_.set_ps_sql(sql, type); } inline void set_for_update(bool for_update) { value_.set_for_update(for_update); } inline bool is_for_update() const { return value_.is_for_update(); } inline void set_hidden_rowid(bool has_hidden_rowid) { value_.set_hidden_rowid(has_hidden_rowid); } @@ -566,7 +566,7 @@ public: int set(const ObString &sql, const ObIArray &expr_idxs, - ObPsStmtId id, + const common::ObString &ps_sql, sql::stmt::StmtType type, bool for_update, ObRecordType *record_type, @@ -607,7 +607,7 @@ public: int64_t idx, const common::ObString &sql, const common::ObIArray &sql_params, - ObPsStmtId ps_id, + const common::ObString &ps_sql, sql::stmt::StmtType stmt_type, bool for_update, bool has_hidden_rowid, @@ -1259,7 +1259,7 @@ public: const ObPLDataType &type, const common::ObString &sql, const common::ObIArray &sql_params, - ObPsStmtId ps_id, + const common::ObString &ps_sql, sql::stmt::StmtType stmt_type, bool for_update, bool has_hidden_rowid, @@ -1453,6 +1453,7 @@ private: class ObPLStmtVisitor; class ObPLStmtBlock; +class ObPLSqlStmt; class ObPLCompileUnitAST { @@ -1470,7 +1471,7 @@ public: obj_access_exprs_(allocator), exprs_(allocator), simple_calc_bitset_(), - ps_stmt_ids_(allocator), + sql_stmts_(allocator), expr_factory_(allocator), symbol_table_(allocator), symbol_debuginfo_table_(allocator), @@ -1498,7 +1499,6 @@ public: inline const common::ObIArray &get_obj_access_exprs() const { return obj_access_exprs_; } inline common::ObIArray &get_obj_access_exprs() { return obj_access_exprs_; } inline int64_t get_obj_access_expr_count() { return obj_access_exprs_.count(); } - inline const common::ObIArray &get_ps_stmt_ids() const { return ps_stmt_ids_; } inline const sql::ObRawExpr* get_obj_access_expr(int64_t i) const { return obj_access_exprs_.at(i); } inline sql::ObRawExpr* get_obj_access_expr(int64_t i) { return obj_access_exprs_.at(i); } inline int set_obj_access_exprs(common::ObIArray &exprs) { return append(obj_access_exprs_, exprs); } @@ -1541,8 +1541,6 @@ public: const share::schema::ObSchemaObjVersion &obj_version); inline bool get_can_cached() const { return can_cached_; } inline void set_can_cached(bool can_cached) { can_cached_ = can_cached; } - inline int add_ps_stmt_id(const ObPsStmtId &id) - { return ps_stmt_ids_.push_back(id); } int add_sql_exprs(common::ObIArray &exprs); inline const ObPLCompileFlag &get_compile_flag() const { return compile_flag_; } @@ -1558,6 +1556,8 @@ public: priv_user_ = priv_user; } + inline ObIArray& get_sql_stmts() { return sql_stmts_; } + void process_default_compile_flag(); virtual const common::ObString &get_db_name() const = 0; @@ -1585,7 +1585,7 @@ protected: ObPLSEArray obj_access_exprs_; //使用的ObjAccessRawExpr ObPLSEArray exprs_; //使用的表达式,在AST里是ObRawExpr,在ObPLFunction里是ObISqlExpression ObBitSet<> simple_calc_bitset_; //可以使用LLVM进行计算的表达式下标 - ObPLSEArray ps_stmt_ids_; // 通过SpiPrepare的SQL RPEPARE ID + ObPLSEArray sql_stmts_; sql::ObRawExprFactory expr_factory_; ObPLSymbolTable symbol_table_; ObPLSymbolDebugInfoTable symbol_debuginfo_table_; @@ -2373,7 +2373,7 @@ public: int accept(ObPLStmtVisitor &visitor) const; - TO_STRING_KV(K_(type), K_(label), K_(sql), K_(params), K_(ps_id), K_(stmt_type), K_(into), K_(data_type), K_(bulk)); + TO_STRING_KV(K_(type), K_(label), K_(sql), K_(params), K_(ps_sql), K_(stmt_type), K_(into), K_(data_type), K_(bulk)); private: }; diff --git a/src/pl/ob_pl_type.cpp b/src/pl/ob_pl_type.cpp index ae766d76d..c6b938938 100644 --- a/src/pl/ob_pl_type.cpp +++ b/src/pl/ob_pl_type.cpp @@ -1778,14 +1778,14 @@ int ObPLCursorInfo::close(sql::ObSQLSessionInfo &session, bool is_reuse) if (is_streaming()) { ObSPIResultSet *spi_result = get_cursor_handler(); if (OB_NOT_NULL(spi_result)) { - if (OB_NOT_NULL(spi_result->get_mysql_result().get_result())) { + if (OB_NOT_NULL(spi_result->get_result_set())) { OZ (spi_result->set_cursor_env(session)); - int close_ret = spi_result->get_mysql_result().close(); + int close_ret = spi_result->close_result_set(); if (OB_SUCCESS != close_ret) { LOG_WARN("close mysql result set failed", K(ret), K(close_ret)); } ret = (OB_SUCCESS == ret ? close_ret : ret); - spi_result->get_mysql_result().reset(); + //spi_result->get_mysql_result().reset(); int reset_ret = spi_result->reset_cursor_env(session); ret = (OB_SUCCESS == ret ? reset_ret : ret); } @@ -1978,18 +1978,24 @@ int ObPLCursorInfo::prepare_entity(ObSQLSessionInfo &session, return ret; } -int ObPLCursorInfo::prepare_spi_result(ObSPIResultSet *&spi_result) +int ObPLCursorInfo::prepare_spi_result(ObPLExecCtx *ctx, ObSPIResultSet *&spi_result) { int ret = OB_SUCCESS; - if (OB_ISNULL(spi_cursor_)) { - OV (OB_NOT_NULL(entity_)); - if (OB_SUCC(ret)) { - ObIAllocator &alloc = entity_->get_arena_allocator(); - OX (spi_cursor_ = alloc.alloc(sizeof(ObSPIResultSet))); - OV (OB_NOT_NULL(spi_cursor_), OB_ALLOCATE_MEMORY_FAILED); + CK (OB_NOT_NULL(ctx)); + CK (OB_NOT_NULL(ctx->exec_ctx_)); + CK (OB_NOT_NULL(ctx->exec_ctx_->get_my_session())); + if (OB_SUCC(ret)) { + if (OB_ISNULL(spi_cursor_)) { + OV (OB_NOT_NULL(entity_)); + if (OB_SUCC(ret)) { + ObIAllocator &alloc = entity_->get_arena_allocator(); + OX (spi_cursor_ = alloc.alloc(sizeof(ObSPIResultSet))); + OV (OB_NOT_NULL(spi_cursor_), OB_ALLOCATE_MEMORY_FAILED); + } } } OX (spi_result = new (spi_cursor_) ObSPIResultSet()); + OZ (spi_result->init(*ctx->exec_ctx_->get_my_session())); return ret; } diff --git a/src/pl/ob_pl_type.h b/src/pl/ob_pl_type.h index 09929bb31..d49937651 100644 --- a/src/pl/ob_pl_type.h +++ b/src/pl/ob_pl_type.h @@ -938,7 +938,7 @@ public: static int prepare_entity(sql::ObSQLSessionInfo &session, lib::MemoryContext &entity); - int prepare_spi_result(sql::ObSPIResultSet *&spi_result); + int prepare_spi_result(ObPLExecCtx *ctx, sql::ObSPIResultSet *&spi_result); int prepare_spi_cursor(sql::ObSPICursor *&spi_cursor, uint64_t tenant_id, uint64_t mem_limit); diff --git a/src/pl/parser/ob_pl_parser.cpp b/src/pl/parser/ob_pl_parser.cpp index 94351094a..884700981 100644 --- a/src/pl/parser/ob_pl_parser.cpp +++ b/src/pl/parser/ob_pl_parser.cpp @@ -18,6 +18,7 @@ #include "lib/string/ob_string.h" #include "lib/charset/ob_charset.h" #include "lib/ash/ob_active_session_guard.h" +#include "sql/parser/parse_malloc.h" #ifdef __cplusplus extern "C" { @@ -41,6 +42,80 @@ namespace oceanbase using namespace common; namespace pl { + +#define ISSPACE(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t' || (c) == '\f' || (c) == '\v') +int ObPLParser::fast_parse(const ObString &query, + ParseResult &parse_result) +{ + ObActiveSessionGuard::get_stat().in_pl_parse_ = true; + int ret = OB_SUCCESS; + // 删除SQL语句末尾的空格 + int64_t len = query.length(); + while (len > 0 && ISSPACE(query[len - 1])) { + --len; + } + const ObString stmt_block(len, query.ptr()); + ObParseCtx parse_ctx; + memset(&parse_ctx, 0, sizeof(ObParseCtx)); + parse_ctx.global_errno_ = OB_SUCCESS; + parse_ctx.is_pl_fp_ = true; + parse_ctx.mem_pool_ = &allocator_; + parse_ctx.stmt_str_ = stmt_block.ptr(); + parse_ctx.stmt_len_ = stmt_block.length(); + parse_ctx.orig_stmt_str_ = query.ptr(); + parse_ctx.orig_stmt_len_ = query.length(); + parse_ctx.comp_mode_ = lib::is_oracle_mode(); + parse_ctx.is_for_trigger_ = 0; + parse_ctx.is_dynamic_ = 0; + parse_ctx.is_inner_parse_ = 1; + parse_ctx.charset_info_ = ObCharset::get_charset(connection_collation_); + parse_ctx.is_not_utf8_connection_ = ObCharset::is_valid_collation(connection_collation_) ? + (ObCharset::charset_type_by_coll(connection_collation_) != CHARSET_UTF8MB4) : false; + parse_ctx.connection_collation_ = connection_collation_; + parse_ctx.mysql_compatible_comment_ = false; + int64_t new_length = stmt_block.length() + 1; + char *buf = (char *)parse_malloc(new_length, parse_ctx.mem_pool_); + if (OB_UNLIKELY(NULL == buf)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("no memory for parser"); + } else { + parse_ctx.no_param_sql_ = buf; + parse_ctx.no_param_sql_buf_len_ = new_length; + } + ret = parse_stmt_block(parse_ctx, parse_result.result_tree_); + if (OB_ERR_PARSE_SQL == ret) { + int err_len = 0; + const char *err_str = "", *global_errmsg = ""; + int err_line = 0; + if (parse_ctx.cur_error_info_ != NULL) { + int first_column = parse_ctx.cur_error_info_->stmt_loc_.first_column_; + int last_column = parse_ctx.cur_error_info_->stmt_loc_.last_column_; + err_len = last_column - first_column + 1; + err_str = parse_ctx.stmt_str_ + first_column; + err_line = parse_ctx.cur_error_info_->stmt_loc_.last_line_ + 1; + global_errmsg = parse_ctx.global_errmsg_; + } + ObString stmt(parse_ctx.stmt_len_, parse_ctx.stmt_str_); + LOG_WARN("failed to parser pl stmt", + K(ret), K(err_line), K(global_errmsg), K(stmt)); + LOG_USER_ERROR(OB_ERR_PARSE_SQL, ob_errpkt_strerror(OB_ERR_PARSER_SYNTAX, false), + err_len, err_str, err_line); + } else { + memmove(parse_ctx.no_param_sql_ + parse_ctx.no_param_sql_len_, + parse_ctx.stmt_str_ + parse_ctx.copied_pos_, + parse_ctx.stmt_len_ - parse_ctx.copied_pos_); + parse_ctx.no_param_sql_len_ += parse_ctx.stmt_len_ - parse_ctx.copied_pos_; + parse_result.no_param_sql_ = parse_ctx.no_param_sql_; + parse_result.no_param_sql_len_ = parse_ctx.no_param_sql_len_; + parse_ctx.no_param_sql_buf_len_ = parse_ctx.no_param_sql_buf_len_; + parse_result.param_node_num_ = parse_ctx.param_node_num_; + parse_result.param_nodes_ = parse_ctx.param_nodes_; + parse_result.tail_param_node_ = parse_ctx.tail_param_node_; + } + ObActiveSessionGuard::get_stat().in_pl_parse_ = false; + return ret; +} + int ObPLParser::parse(const ObString &stmt_block, const ObString &orig_stmt_block, // for preprocess ParseResult &parse_result, diff --git a/src/pl/parser/ob_pl_parser.h b/src/pl/parser/ob_pl_parser.h index 89bce1c50..49a6e19af 100644 --- a/src/pl/parser/ob_pl_parser.h +++ b/src/pl/parser/ob_pl_parser.h @@ -38,7 +38,8 @@ public: : allocator_(allocator), connection_collation_(conn_collation) {} - + int fast_parse(const ObString &stmt_block, + ParseResult &parse_result); int parse(const common::ObString &stmt_block, const common::ObString &orig_stmt_block, ParseResult &parse_result, diff --git a/src/pl/parser/parse_stmt_item_type.h b/src/pl/parser/parse_stmt_item_type.h index a02e4d8aa..c22825df5 100644 --- a/src/pl/parser/parse_stmt_item_type.h +++ b/src/pl/parser/parse_stmt_item_type.h @@ -88,6 +88,14 @@ enum PackageAlterOptions PACKAGE_ALTER_NONEDITIONABLE }; +enum TriggerAlterOptions +{ + TRIGGER_ALTER_COMPILE = 0, + TRIGGER_ALTER_IF_ENABLE, + TRIGGER_ALTER_RENAME, + TRIGGER_ALTER_IF_EDITIONABLE +}; + #ifdef __cplusplus } #endif diff --git a/src/pl/parser/parse_stmt_node.h b/src/pl/parser/parse_stmt_node.h index 11dec8275..1203ed284 100644 --- a/src/pl/parser/parse_stmt_node.h +++ b/src/pl/parser/parse_stmt_node.h @@ -69,6 +69,13 @@ typedef struct _ObParseCtx int64_t last_escape_check_pos_; //解析quoted string时的一个临时变量,处理连接gbk字符集时遇到的转义字符问题 int connection_collation_; bool mysql_compatible_comment_; //whether the parser is parsing "/*! xxxx */" + int copied_pos_; + char *no_param_sql_; + int no_param_sql_len_; + int no_param_sql_buf_len_; + int param_node_num_; + ParamList *param_nodes_; + ParamList *tail_param_node_; struct { uint32_t is_inner_parse_:1; //is inner parser, not from the user's call @@ -77,7 +84,9 @@ typedef struct _ObParseCtx uint32_t is_for_preprocess_:1; uint32_t is_include_old_new_in_trigger_:1; // indicates whether include :old/:new/:parent in trigger body uint32_t in_q_quote_:1; - uint32_t reserved_:26; + uint32_t is_pl_fp_ :1; + uint32_t is_forbid_anony_parameter_ : 1; // 1 表示禁止匿名块参数化 + uint32_t reserved_:24; }; } ObParseCtx; diff --git a/src/pl/parser/pl_parser_mysql_mode.y b/src/pl/parser/pl_parser_mysql_mode.y index 28b8866de..16cd85035 100644 --- a/src/pl/parser/pl_parser_mysql_mode.y +++ b/src/pl/parser/pl_parser_mysql_mode.y @@ -626,10 +626,15 @@ sp_call_name: ; ident: - IDENT { $$ = $1; } + IDENT + { + $$ = $1; + $$->str_off_ = @1.first_column; + } | unreserved_keyword { get_non_reserved_node($$, parse_ctx->mem_pool_, @1.first_column, @1.last_column); + $$->str_off_ = @1.first_column; } ; diff --git a/src/pl/pl_cache/ob_pl_cache.cpp b/src/pl/pl_cache/ob_pl_cache.cpp new file mode 100644 index 000000000..13ea4d305 --- /dev/null +++ b/src/pl/pl_cache/ob_pl_cache.cpp @@ -0,0 +1,986 @@ +/** + * Copyright (c) 2022 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX PL_CACHE +#include "ob_pl_cache.h" +#include "lib/oblog/ob_log_module.h" +#include "share/rc/ob_tenant_base.h" //MTL +#include "pl/ob_pl_stmt.h" +namespace oceanbase +{ +namespace pl +{ + +int PCVPlSchemaObj::init(const ObTableSchema *schema) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(schema) || OB_ISNULL(inner_alloc_)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("unexpected null argument", K(ret), K(schema), K(inner_alloc_)); + } else { + tenant_id_ = schema->get_tenant_id(); + database_id_ = schema->get_database_id(); + schema_id_ = schema->get_table_id(); + schema_version_ = schema->get_schema_version(); + schema_type_ = TABLE_SCHEMA; + table_type_ = schema->get_table_type(); + is_tmp_table_ = schema->is_tmp_table(); + // copy table name + char *buf = nullptr; + const ObString &tname = schema->get_table_name_str(); + if (nullptr == (buf = static_cast(inner_alloc_->alloc(tname.length())))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret), K(tname.length())); + } else { + MEMCPY(buf, tname.ptr(), tname.length()); + table_name_.assign_ptr(buf, tname.length()); + } + } + return ret; +} + +bool PCVPlSchemaObj::operator==(const PCVPlSchemaObj &other) const +{ + bool ret = true; + if (schema_type_ != other.schema_type_) { + ret = false; + } else if (TABLE_SCHEMA == other.schema_type_) { + ret = tenant_id_ == other.tenant_id_ && + database_id_ == other.database_id_ && + schema_id_ == other.schema_id_ && + schema_version_ == other.schema_version_ && + table_type_ == other.table_type_; + } else { + ret = schema_id_ == other.schema_id_ && + schema_version_ == other.schema_version_; + } + return ret; +} + +int PCVPlSchemaObj::init_without_copy_name(const ObSimpleTableSchemaV2 *schema) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(schema)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("unexpected null argument", K(ret), K(schema)); + } else { + tenant_id_ = schema->get_tenant_id(); + database_id_ = schema->get_database_id(); + schema_id_ = schema->get_table_id(); + schema_version_ = schema->get_schema_version(); + schema_type_ = TABLE_SCHEMA; + table_type_ = schema->get_table_type(); + is_tmp_table_ = schema->is_tmp_table(); + + table_name_ = schema->get_table_name_str(); + } + return ret; +} + +int PCVPlSchemaObj::init_with_version_obj(const ObSchemaObjVersion &schema_obj_version) +{ + int ret = OB_SUCCESS; + schema_type_ = schema_obj_version.get_schema_type(); + schema_id_ = schema_obj_version.object_id_; + schema_version_ = schema_obj_version.version_; + return ret; +} + +void PCVPlSchemaObj::reset() +{ + tenant_id_ = common::OB_INVALID_ID; + database_id_ = common::OB_INVALID_ID; + schema_id_ = common::OB_INVALID_ID; + schema_type_ = OB_MAX_SCHEMA; + schema_version_ = 0; + table_type_ = MAX_TABLE_TYPE; + is_tmp_table_ = false; + if (inner_alloc_ != nullptr && table_name_.ptr() != nullptr) { + inner_alloc_->free(table_name_.ptr()); + table_name_.reset(); + inner_alloc_ = nullptr; + } +} + +PCVPlSchemaObj::~PCVPlSchemaObj() +{ + reset(); +} + +void ObPLObjectKey::reset() +{ + db_id_ = common::OB_INVALID_ID; + key_id_ = common::OB_INVALID_ID; + sessid_ = 0; + name_.reset(); + namespace_ = ObLibCacheNameSpace::NS_INVALID; +} + +int ObPLObjectKey::deep_copy(ObIAllocator &allocator, const ObILibCacheKey &other) +{ + int ret = OB_SUCCESS; + const ObPLObjectKey &key = static_cast(other); + if (OB_FAIL(common::ob_write_string(allocator, key.name_, name_))) { + LOG_WARN("failed to deep copy name", K(ret), K(name_)); + } else { + db_id_ = key.db_id_; + key_id_ = key.key_id_; + sessid_ = key.sessid_; + namespace_ = key.namespace_; + } + return ret; +} + +void ObPLObjectKey::destory(common::ObIAllocator &allocator) +{ + if (nullptr != name_.ptr()) { + allocator.free(const_cast(name_.ptr())); + } +} + +uint64_t ObPLObjectKey::hash() const +{ + uint64_t hash_ret = murmurhash(&db_id_, sizeof(uint64_t), 0); + hash_ret = murmurhash(&key_id_, sizeof(uint64_t), hash_ret); + hash_ret = murmurhash(&sessid_, sizeof(uint32_t), hash_ret); + hash_ret = name_.hash(hash_ret); + hash_ret = murmurhash(&namespace_, sizeof(ObLibCacheNameSpace), hash_ret); + return hash_ret; +} + +bool ObPLObjectKey::is_equal(const ObILibCacheKey &other) const +{ + const ObPLObjectKey &key = static_cast(other); + bool cmp_ret = db_id_ == key.db_id_ && + key_id_ == key.key_id_ && + sessid_ == key.sessid_ && + name_ == key.name_ && + namespace_ == key.namespace_; + return cmp_ret; +} + +int ObPLObjectValue::init(const ObILibCacheObject &cache_obj, ObPLCacheCtx &pc_ctx) +{ + int ret = OB_SUCCESS; + const pl::ObPLCompileUnit &pl_object = static_cast(cache_obj); + if (OB_FAIL(add_match_info(pc_ctx, &pc_ctx.key_, cache_obj))) { + LOG_WARN("failed to add_match_info", K(ret)); + } else { + params_info_.reset(); + if (OB_FAIL(params_info_.reserve(pl_object.get_params_info().count()))) { + LOG_WARN("failed to reserve 2d array", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < pl_object.get_params_info().count(); ++i) { + if (OB_FAIL(params_info_.push_back(pl_object.get_params_info().at(i)))) { + LOG_WARN("fail to push back param info", K(ret)); + } + } + } + return ret; +} + +void ObPLObjectValue::reset() +{ + ObDLinkBase::reset(); + for (int64_t i = 0; i < stored_schema_objs_.count(); i++) { + if (OB_ISNULL(stored_schema_objs_.at(i)) || OB_ISNULL(pc_alloc_)) { + // do nothing + } else { + stored_schema_objs_.at(i)->reset(); + pc_alloc_->free(stored_schema_objs_.at(i)); + } + } + stored_schema_objs_.reset(); + sys_schema_version_ = OB_INVALID_VERSION; + tenant_schema_version_ = OB_INVALID_VERSION; + sessid_ = 0; + sess_create_time_ = 0; + contain_sys_name_table_ = false; + contain_sys_pl_object_ = false; + contain_tmp_table_ = false; + params_info_.reset(); + + pl_routine_obj_ = nullptr; +} + +int64_t ObPLObjectValue::get_mem_size() +{ + int64_t value_mem_size = 0; + if (OB_ISNULL(pl_routine_obj_)) { + BACKTRACE(ERROR, true, "invalid routine obj"); + } else { + value_mem_size = pl_routine_obj_->get_mem_size(); + } + return value_mem_size; +} + +int ObPLObjectValue::lift_tenant_schema_version(int64_t new_schema_version) +{ + int ret = OB_SUCCESS; + if (new_schema_version <= tenant_schema_version_) { + // do nothing + } else { + ATOMIC_STORE(&(tenant_schema_version_), new_schema_version); + } + return ret; +} + +int ObPLObjectValue::check_value_version(share::schema::ObSchemaGetterGuard *schema_guard, + bool need_check_schema, + const ObIArray &schema_array, + bool &is_old_version) +{ + int ret = OB_SUCCESS; + is_old_version = false; + if (OB_ISNULL(schema_guard)) { + int ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret), K(schema_guard)); + } else if (0 == schema_array.count()) { + // do nothing + } else { + int64_t table_count = stored_schema_objs_.count(); + + if (schema_array.count() != table_count) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table count do not match", K(ret), K(schema_array.count()), K(table_count)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && !is_old_version && i < table_count; ++i) { + const PCVPlSchemaObj *schema_obj1 = stored_schema_objs_.at(i); + const PCVPlSchemaObj &schema_obj2 = schema_array.at(i); + if (nullptr == schema_obj1) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("got an unexpected null table schema", K(ret), K(schema_obj1)); + } else if (*schema_obj1 == schema_obj2) { // schema do match + LOG_DEBUG("matched schema objs", K(*schema_obj1), K(schema_obj2), K(i)); + // do nothing + } else { + LOG_DEBUG("mismatched schema objs", K(*schema_obj1), K(schema_obj2), K(i)); + is_old_version = true; + } + } + } + } + return ret; +} + + +int ObPLObjectValue::need_check_schema_version(ObPLCacheCtx &pc_ctx, + int64_t &new_schema_version, + bool &need_check) +{ + int ret = OB_SUCCESS; + need_check = false; + if (OB_FAIL(pc_ctx.schema_guard_->get_schema_version(pc_ctx.session_info_->get_effective_tenant_id(), + new_schema_version))) { + LOG_WARN("failed to get tenant schema version", K(ret)); + } else { + int64_t cached_tenant_schema_version = ATOMIC_LOAD(&tenant_schema_version_); + need_check = ((new_schema_version != cached_tenant_schema_version) + || contain_tmp_table_ + || contain_sys_pl_object_ + || contain_sys_name_table_); + if (need_check && REACH_TIME_INTERVAL(10000000)) { + LOG_INFO("need check schema", K(new_schema_version), K(cached_tenant_schema_version)); + } + } + return ret; +} + +int ObPLObjectValue::get_all_dep_schema(ObSchemaGetterGuard &schema_guard, + const DependenyTableStore &dep_schema_objs, + ObIArray &schema_array) +{ + int ret = OB_SUCCESS; + schema_array.reset(); + const ObSimpleTableSchemaV2 *table_schema = nullptr; + PCVPlSchemaObj tmp_schema_obj; + + for (int64_t i = 0; OB_SUCC(ret) && i < dep_schema_objs.count(); ++i) { + if (TABLE_SCHEMA != dep_schema_objs.at(i).get_schema_type()) { + if (OB_FAIL(tmp_schema_obj.init_with_version_obj(dep_schema_objs.at(i)))) { + LOG_WARN("failed to init pcv schema obj", K(ret)); + } else if (OB_FAIL(schema_array.push_back(tmp_schema_obj))) { + LOG_WARN("failed to push back pcv schema obj", K(ret)); + } else { + tmp_schema_obj.reset(); + } + } else if (OB_FAIL(schema_guard.get_simple_table_schema( + MTL_ID(), + dep_schema_objs.at(i).get_object_id(), + table_schema))) { + LOG_WARN("failed to get table schema", + K(ret), K(dep_schema_objs.at(i))); + } else if (nullptr == table_schema) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get an unexpected null table schema", K(ret)); + } else if (table_schema->is_index_table()) { + // do nothing + } else if (OB_FAIL(tmp_schema_obj.init_without_copy_name(table_schema))) { + LOG_WARN("failed to init pcv schema obj", K(ret)); + } else if (OB_FAIL(schema_array.push_back(tmp_schema_obj))) { + LOG_WARN("failed to push back pcv schema obj", K(ret)); + } else { + table_schema = nullptr; + tmp_schema_obj.reset(); + } + } + + if (OB_FAIL(ret)) { + schema_array.reset(); + } else { + LOG_DEBUG("get all dep schema", K(schema_array)); + } + return ret; +} + +int ObPLObjectValue::get_all_dep_schema(ObPLCacheCtx &pc_ctx, + const uint64_t database_id, + int64_t &new_schema_version, + bool &need_check_schema, + ObIArray &schema_array) +{ + int ret = OB_SUCCESS; + need_check_schema = false; + if (OB_FAIL(need_check_schema_version(pc_ctx, + new_schema_version, + need_check_schema))) { + LOG_WARN("failed to get need_check_schema flag", K(ret)); + } else if (!need_check_schema) { + // do nothing + } else if (OB_ISNULL(pc_ctx.schema_guard_)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret)); + } else { + schema_array.reset(); + const ObSimpleTableSchemaV2 *table_schema = nullptr; + PCVPlSchemaObj tmp_schema_obj; + uint64_t tenant_id = OB_INVALID_ID; + for (int64_t i = 0; OB_SUCC(ret) && i < stored_schema_objs_.count(); i++) { + tenant_id = MTL_ID(); + ObSchemaGetterGuard &schema_guard = *pc_ctx.schema_guard_; + PCVPlSchemaObj *pcv_schema = stored_schema_objs_.at(i); + if (OB_ISNULL(pcv_schema)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("got unexpected null", K(ret)); + } else if (TABLE_SCHEMA != pcv_schema->schema_type_) { + // if no table schema, get schema version is enough + int64_t new_version = 0; + if (PACKAGE_SCHEMA == stored_schema_objs_.at(i)->schema_type_ + || UDT_SCHEMA == stored_schema_objs_.at(i)->schema_type_) { + tenant_id = pl::get_tenant_id_by_object_id(stored_schema_objs_.at(i)->schema_id_); + } + if (OB_FAIL(schema_guard.get_schema_version(pcv_schema->schema_type_, + tenant_id, + pcv_schema->schema_id_, + new_version))) { + LOG_WARN("failed to get schema version", + K(ret), K(tenant_id), K(pcv_schema->schema_type_), K(pcv_schema->schema_id_)); + } else { + tmp_schema_obj.schema_id_ = pcv_schema->schema_id_; + tmp_schema_obj.schema_type_ = pcv_schema->schema_type_; + tmp_schema_obj.schema_version_ = new_version; + if (OB_FAIL(schema_array.push_back(tmp_schema_obj))) { + LOG_WARN("failed to push back array", K(ret)); + } else { + tmp_schema_obj.reset(); + } + } + } else if (lib::is_oracle_mode()) { + if (pcv_schema->is_explicit_db_name_) { + //In oracle mode, if mark database name,use table id search schema directly. + if (OB_FAIL(schema_guard.get_simple_table_schema(tenant_id, + pcv_schema->schema_id_, table_schema))) { + LOG_WARN("failed to get table schema", K(pcv_schema->schema_id_), K(ret)); + } else { /* do nothing */ } + } else if (OB_FAIL(schema_guard.get_simple_table_schema(tenant_id, //otherwise, use db id in session and table name search schema + database_id, + pcv_schema->table_name_, + false, + table_schema))) { + LOG_WARN("failed to get table schema", K(pcv_schema->schema_id_), K(ret)); + } else if (nullptr == table_schema && OB_FAIL(schema_guard.get_simple_table_schema(tenant_id, + common::OB_ORA_SYS_DATABASE_ID, + pcv_schema->table_name_, + false, + table_schema))) { // finaly,find sys tenand + LOG_WARN("failed to get table schema", K(ret), K(tenant_id), + K(pcv_schema->table_name_)); + } else { + // do nothing + } + } else if (OB_FAIL(schema_guard.get_simple_table_schema(tenant_id, + pcv_schema->database_id_, + pcv_schema->table_name_, + false, + table_schema))) { //In mysql mode, use db id cached by pcv schema to search + LOG_WARN("failed to get table schema", + K(ret), K(pcv_schema->tenant_id_), K(pcv_schema->database_id_), + K(pcv_schema->table_name_)); + } else { + // do nothing + } + + if (OB_FAIL(ret)) { + // do nothing + } else if (TABLE_SCHEMA != pcv_schema->schema_type_) { // not table schema + tmp_schema_obj.reset(); + } else if (nullptr == table_schema) { + ret = OB_OLD_SCHEMA_VERSION; + LOG_DEBUG("table not exist", K(ret), K(*pcv_schema), K(table_schema)); + } else if (OB_FAIL(tmp_schema_obj.init_without_copy_name(table_schema))) { + LOG_WARN("failed to init pcv schema obj", K(ret)); + } else if (OB_FAIL(schema_array.push_back(tmp_schema_obj))) { + LOG_WARN("failed to push back array", K(ret)); + } else { + table_schema = nullptr; + tmp_schema_obj.reset(); + } + } // for end + } + return ret; +} + + +int ObPLObjectValue::match_dep_schema(const ObPLCacheCtx &pc_ctx, + const ObIArray &schema_array, + bool &is_same) +{ + int ret = OB_SUCCESS; + is_same = true; + ObSQLSessionInfo *session_info = pc_ctx.session_info_; + if (OB_ISNULL(session_info)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret), K(session_info)); + } else if (schema_array.count() != stored_schema_objs_.count()) { + is_same = false; + } else { + for (int64_t i = 0; OB_SUCC(ret) && is_same && i < schema_array.count(); i++) { + if (OB_ISNULL(stored_schema_objs_.at(i))) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid null table schema", K(ret), K(i)); + } else if (schema_array.at(i).is_tmp_table_) { // check for tmp table + is_same = ((session_info->get_sessid_for_table() == sessid_) && + (session_info->get_sess_create_time() == sess_create_time_)); + } else if (lib::is_oracle_mode() + && TABLE_SCHEMA == stored_schema_objs_.at(i)->schema_type_ + && !stored_schema_objs_.at(i)->match_compare(schema_array.at(i))) { + // check whether common table name is same as system table in oracle mode + is_same = false; + } else { + // do nothing + } + } + } + return ret; +} + +int ObPLObjectValue::add_match_info(ObILibCacheCtx &ctx, + ObILibCacheKey *key, + const ObILibCacheObject &cache_obj) +{ + int ret = OB_SUCCESS; + + ObPLCacheCtx& pc_ctx = static_cast(ctx); + const pl::ObPLCompileUnit &cache_object = static_cast(cache_obj); + if (OB_UNLIKELY(!cache_object.is_prcr() && !cache_object.is_sfc() && !cache_object.is_pkg() && !cache_object.is_anon())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("cache object is invalid", K(cache_object)); + } else if (OB_UNLIKELY(pl_routine_obj_ != nullptr)) { + ret = OB_SQL_PC_PLAN_DUPLICATE; + } else if (OB_FAIL(set_stored_schema_objs(cache_object.get_dependency_table(), + pc_ctx.schema_guard_))) { + LOG_WARN("failed to set stored schema objs", + K(ret), K(cache_object.get_dependency_table())); + } else { + sys_schema_version_ = cache_object.get_sys_schema_version(); + tenant_schema_version_ = cache_object.get_tenant_schema_version(); + if (contain_tmp_table_) { + sessid_ = pc_ctx.session_info_->get_sessid_for_table(); + sess_create_time_ = pc_ctx.session_info_->get_sess_create_time(); + } + } + return ret; +} + + +int ObPLObjectValue::set_stored_schema_objs(const DependenyTableStore &dep_table_store, + share::schema::ObSchemaGetterGuard *schema_guard) +{ + int ret = OB_SUCCESS; + const ObTableSchema *table_schema = nullptr; + PCVPlSchemaObj *pcv_schema_obj = nullptr; + void *obj_buf = nullptr; + + stored_schema_objs_.reset(); + stored_schema_objs_.set_allocator(pc_alloc_); + + if (OB_ISNULL(schema_guard)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid null argument", K(ret), K(schema_guard)); + } else if (OB_FAIL(stored_schema_objs_.init(dep_table_store.count()))) { + LOG_WARN("failed to init stored_schema_objs", K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < dep_table_store.count(); i++) { + const ObSchemaObjVersion &table_version = dep_table_store.at(i); + table_schema = nullptr; + int hash_err = OB_SUCCESS; + if (table_version.get_schema_type() != TABLE_SCHEMA) { + // if not table schema, store schema id and version + if (nullptr == (obj_buf = pc_alloc_->alloc(sizeof(PCVPlSchemaObj)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret)); + } else if (FALSE_IT(pcv_schema_obj = new(obj_buf)PCVPlSchemaObj(pc_alloc_))) { + // do nothing + } else if (OB_FAIL(pcv_schema_obj->init_with_version_obj(table_version))) { + LOG_WARN("failed to init pcv schema obj", K(ret), K(table_version)); + } else if (OB_FAIL(stored_schema_objs_.push_back(pcv_schema_obj))) { + LOG_WARN("failed to push back array", K(ret)); + } else { + // do nothing + } + } else if (OB_FAIL(schema_guard->get_table_schema( + MTL_ID(), + table_version.get_object_id(), + table_schema))) { // now deal with table schema + LOG_WARN("failed to get table schema", K(ret), K(table_version), K(table_schema)); + } else if (nullptr == table_schema) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get an unexpected null schema", K(ret), K(table_schema)); + } else if (table_schema->is_index_table()) { + // do nothing + } else if (nullptr == (obj_buf = pc_alloc_->alloc(sizeof(PCVPlSchemaObj)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret)); + } else if (FALSE_IT(pcv_schema_obj = new(obj_buf)PCVPlSchemaObj(pc_alloc_))) { + // do nothing + } else if (OB_FAIL(pcv_schema_obj->init(table_schema))) { + LOG_WARN("failed to init pcv schema obj with table schema", K(ret)); + } else if (FALSE_IT(pcv_schema_obj->is_explicit_db_name_ = table_version.is_db_explicit_)) { + // do nothing + } else if (OB_FAIL(stored_schema_objs_.push_back(pcv_schema_obj))) { + LOG_WARN("failed to push back array", K(ret)); + } else if(!contain_sys_name_table_) { + /* Ordinary tables in oracle mode can have the same name as tables in sys, + and need to be distinguished when matching plans to match different plans + The table under sys contains system tables and views, so call is_sys_table_name + to check whether the table is under sys. + In addition, if SQL contains internal tables, the schema version changes of the + internal tables will not be reflected in the tenant schema version of ordinary tenants. + In order to be able to update the plan in time, you need to check the schema version number + of the corresponding internal table. The internal table of the oracle tenant is under sys, + and the mysql tenant Under oceanbase. */ + if (lib::is_oracle_mode()) { + if (OB_FAIL(share::schema::ObSysTableChecker::is_sys_table_name(MTL_ID(), + OB_ORA_SYS_DATABASE_ID, + table_schema->get_table_name(), + contain_sys_name_table_))) { + LOG_WARN("failed to check sys table", K(ret)); + } + } else if (OB_FAIL(share::schema::ObSysTableChecker::is_sys_table_name(MTL_ID(), + OB_SYS_DATABASE_ID, + table_schema->get_table_name(), + contain_sys_name_table_))) { + LOG_WARN("failed to check sys table", K(ret)); + } else { + // do nothing + } + LOG_DEBUG("check sys table", K(table_schema->get_table_name()), K(contain_sys_name_table_)); + } else { + // do nothing + } + if (OB_SUCC(ret) && OB_NOT_NULL(pcv_schema_obj)) { + if (pcv_schema_obj->is_tmp_table_ && !contain_tmp_table_) { + contain_tmp_table_ = true; + } + if (!contain_sys_pl_object_ && + (PACKAGE_SCHEMA == pcv_schema_obj->schema_type_ || + UDT_SCHEMA == pcv_schema_obj->schema_type_) && + OB_SYS_TENANT_ID == pl::get_tenant_id_by_object_id(pcv_schema_obj->schema_id_)) { + contain_sys_pl_object_ = true; + } + } + obj_buf = nullptr; + pcv_schema_obj = nullptr; + table_schema = nullptr; + } // for end + } + if (OB_FAIL(ret)) { + stored_schema_objs_.reset(); + } else { + // do nothing + } + return ret; +} + +bool ObPLObjectValue::match_params_info(const Ob2DArray &infos) +{ + bool is_same = true; + if (infos.count() != params_info_.count()) { + is_same = false; + } else { + int64_t N = infos.count(); + for (int64_t i = 0; is_same && i < N; ++i) { + if (true == is_same && params_info_.at(i).flag_.need_to_check_type_) { + if (infos.at(i).type_ != params_info_.at(i).type_ + || infos.at(i).scale_ != params_info_.at(i).scale_ + || infos.at(i).col_type_ != params_info_.at(i).col_type_ + || (params_info_.at(i).flag_.need_to_check_extend_type_ + && infos.at(i).ext_real_type_ != params_info_.at(i).ext_real_type_) + || (params_info_.at(i).flag_.is_boolean_ != infos.at(i).flag_.is_boolean_)) { + is_same = false; + } + } + if (true == is_same && params_info_.at(i).flag_.need_to_check_bool_value_) { + if (infos.at(i).flag_.expected_bool_value_ + != params_info_.at(i).flag_.expected_bool_value_) { + is_same = false; + } + } + } + } + return is_same; +} + +int ObPLObjectValue::match_param_info(const ObParamInfo ¶m_info, + const ObObjParam ¶m, + bool &is_same) const +{ + int ret = OB_SUCCESS; + is_same = true; + + if (param_info.flag_.need_to_check_type_) { + if (lib::is_oracle_mode() && + param.get_param_meta().get_type() == ObCharType && + param.get_type() == ObNullType) { + } else if (param.get_param_meta().get_type() != param.get_type()) { + LOG_TRACE("differ in match param info", + K(param.get_param_meta().get_type()), + K(param.get_type())); + } + + if (param.get_collation_type() != param_info.col_type_) { + is_same = false; + } else if (param.get_param_meta().get_type() != param_info.type_) { + is_same = false; + } else if (param.is_ext()) { + ObDataType data_type; + if (!param_info.flag_.need_to_check_extend_type_) { + // do nothing + } else if (OB_FAIL(ObSQLUtils::get_ext_obj_data_type(param, data_type))) { + LOG_WARN("fail to get obj data_type", K(ret), K(param)); + } else if (data_type.get_scale() == param_info.scale_ && + data_type.get_obj_type() == param_info.ext_real_type_) { + is_same = true; + } else { + is_same = false; + } + LOG_DEBUG("ext match param info", K(data_type), K(param_info), K(is_same), K(ret)); + } else if (param_info.is_oracle_empty_string_ && !param.is_null()) { //Plain strings do not match the scheme of the empty string + is_same = false; + } else if (ObSQLUtils::is_oracle_empty_string(param) + &&!param_info.is_oracle_empty_string_) { //Empty strings do not match the scheme of ordinary strings + is_same = false; + } else if (param_info.flag_.is_boolean_ != param.is_boolean()) { //bool type not match int type + is_same = false; + } else { + is_same = (param.get_scale() == param_info.scale_); + } + } + if (is_same && param_info.flag_.need_to_check_bool_value_) { + bool is_value_true = false; + if (OB_FAIL(ObObjEvaluator::is_true(param, is_value_true))) { + SQL_PC_LOG(WARN, "fail to get param info", K(ret)); + } else if (is_value_true != param_info.flag_.expected_bool_value_) { + is_same = false; + } + } + return ret; +} + +int ObPLObjectValue::match_params_info(const ParamStore *params, + bool &is_same) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(params)) { + is_same = true; + } else if (params->count() > params_info_.count()) { + is_same = false; + } else { + //match original param info + int64_t N = params->count(); + LOG_DEBUG("params info", K(params_info_), K(*params), K(this)); + for (int64_t i = 0; OB_SUCC(ret) && is_same && i < N; ++i) { + if (OB_FAIL(match_param_info(params_info_.at(i), + params->at(i), + is_same))) { + LOG_WARN("fail to match param info", K(ret), K(params_info_), K(*params)); + } + } + + if (OB_FAIL(ret)) { + is_same = false; + } + } + + return ret; +} + +int ObPLObjectSet::init(ObILibCacheCtx &ctx, const ObILibCacheObject *obj) +{ + int ret = OB_SUCCESS; + ObPLCacheCtx& pc_ctx = static_cast(ctx); + + if (is_inited_) { + ret = OB_INIT_TWICE; + LOG_WARN("init twice", K(ret)); + } else if (OB_FAIL(key_.deep_copy(allocator_, pc_ctx.key_))) { + LOG_WARN("fail to init plan cache key in pcv set", K(ret)); + } else { + is_inited_ = true; + } + return ret; +} + +int ObPLObjectSet::create_new_pl_object_value(ObPLObjectValue *&pl_object_value) +{ + int ret = OB_SUCCESS; + void *buff = nullptr; + pl_object_value = nullptr; + + if (nullptr == (buff = allocator_.alloc(sizeof(ObPLObjectValue)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory for ObPLObjectValue", K(ret)); + } else if (nullptr == (pl_object_value = new(buff)ObPLObjectValue(allocator_))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to construct ObPLObjectValue", K(ret)); + } else { + // do nothing + } + + if (OB_SUCC(ret)) { + // do nothing + } else if (nullptr != pl_object_value) { // cleanup + pl_object_value->~ObPLObjectValue(); + allocator_.free(pl_object_value); + pl_object_value = nullptr; + } + + return ret; +} + +void ObPLObjectSet::free_pl_object_value(ObPLObjectValue *pl_object_value) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(pl_object_value)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument",K(ret)); + } else { + pl_object_value->~ObPLObjectValue(); + allocator_.free(pl_object_value); + pl_object_value = nullptr; + } +} + +void ObPLObjectSet::destroy() +{ + if (is_inited_) { + while (!object_value_sets_.is_empty()) { + ObPLObjectValue *pl_object_value= object_value_sets_.get_first(); + if (OB_ISNULL(pl_object_value)) { + //do nothing; + } else { + object_value_sets_.remove(pl_object_value); + free_pl_object_value(pl_object_value); + pl_object_value = nullptr; + } + } + + key_.destory(allocator_); + key_.reset(); + + is_inited_ = false; + } +} + + +int ObPLObjectSet::inner_get_cache_obj(ObILibCacheCtx &ctx, + ObILibCacheKey *key, + ObILibCacheObject *&cache_obj) +{ + int ret = OB_SUCCESS; + + ObPLCacheCtx& pc_ctx = static_cast(ctx); + pc_ctx.schema_guard_->set_session_id(pc_ctx.session_info_->get_sessid_for_table()); + ObSEArray schema_array; + DLIST_FOREACH(pl_object_value, object_value_sets_) { + schema_array.reset(); + int64_t new_tenant_schema_version = OB_INVALID_VERSION; + bool need_check_schema = true; + bool is_old_version = false; + bool is_same = true; + bool match_params = true; + + if (OB_FAIL(pl_object_value->get_all_dep_schema(pc_ctx, + pc_ctx.session_info_->get_database_id(), + new_tenant_schema_version, + need_check_schema, + schema_array))) { + if (OB_OLD_SCHEMA_VERSION == ret) { + LOG_DEBUG("old schema version, to be delete", K(ret), K(pl_object_value->pl_routine_obj_->get_object_id())); + } else { + LOG_WARN("failed to get all table schema", K(ret)); + } + } else if (schema_array.count() != 0 && OB_FAIL(pl_object_value->match_dep_schema(pc_ctx, schema_array, is_same))) { + LOG_WARN("failed to match_dep_schema", K(ret)); + } else if (!is_same) { + ret = OB_OLD_SCHEMA_VERSION; + LOG_DEBUG("old schema version, to be delete", K(ret), K(pl_object_value->pl_routine_obj_->get_object_id())); + } else if (OB_FAIL(pl_object_value->check_value_version(pc_ctx.schema_guard_, + need_check_schema, + schema_array, + is_old_version))) { + LOG_WARN("fail to check table version", K(ret)); + } else if (true == is_old_version) { + ret = OB_OLD_SCHEMA_VERSION; + LOG_DEBUG("old schema version, to be delete", K(ret), K(pl_object_value->pl_routine_obj_->get_object_id())); + } else if (OB_FAIL(pl_object_value->match_params_info(pc_ctx.cache_params_, match_params))) { + LOG_DEBUG("failed to match params info", K(ret)); + } else if (!match_params) { + // do nothing + } else { + cache_obj = pl_object_value->pl_routine_obj_; + cache_obj->set_dynamic_ref_handle(pc_ctx.handle_id_); + if (OB_FAIL(pl_object_value->lift_tenant_schema_version(new_tenant_schema_version))) { + LOG_WARN("failed to lift pcv's tenant schema version", K(ret)); + } + break; + } + } + if (OB_SUCC(ret) && nullptr == cache_obj) { + ret = OB_SQL_PC_NOT_EXIST; + } + return ret; +} + +int ObPLObjectSet::inner_add_cache_obj(ObILibCacheCtx &ctx, + ObILibCacheKey *key, + ObILibCacheObject *cache_obj) +{ + int ret = OB_SUCCESS; + + ObPLCacheCtx& pc_ctx = static_cast(ctx); + pl::ObPLCompileUnit *cache_object = static_cast(cache_obj); + ObSEArray schema_array; + + if (OB_ISNULL(cache_object)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get null cache obj", K(ret)); + } else if (OB_UNLIKELY(!cache_object->is_prcr() && + !cache_object->is_sfc() && + !cache_object->is_pkg() && + !cache_object->is_anon())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("cache object is invalid", K(cache_object)); + } else if (OB_FAIL(ObPLObjectValue::get_all_dep_schema(*pc_ctx.schema_guard_, + cache_object->get_dependency_table(), + schema_array))) { + LOG_WARN("failed to get all dep schema", K(ret)); + } else { + DLIST_FOREACH(pl_object_value, object_value_sets_) { + bool is_same = true; + bool is_old_version = false; + if (schema_array.count() != 0) { + if (OB_FAIL(pl_object_value->match_dep_schema(pc_ctx, schema_array, is_same))) { + LOG_WARN("failed to match_dep_schema", K(ret)); + } else if (!is_same) { + ret = OB_OLD_SCHEMA_VERSION; + LOG_DEBUG("old schema version, to be delete", K(ret), K(pl_object_value->pl_routine_obj_->get_object_id())); + } else if (pl_object_value->check_value_version(pc_ctx.schema_guard_, + true, + schema_array, + is_old_version)) { + LOG_WARN("fail to check table version", K(ret)); + } else if (true == is_old_version) { + ret = OB_OLD_SCHEMA_VERSION; + LOG_DEBUG("old schema version, to be delete", K(ret), K(pl_object_value->pl_routine_obj_->get_object_id())); + } + } + if (OB_SUCC(ret)) { + if (true == pl_object_value->match_params_info(cache_object->get_params_info())) { + ret = OB_SQL_PC_PLAN_DUPLICATE; + } + } + } + } + + /* if object_value_sets_ has a value which has different schema and schema version but same param info, + it must report an error. + so, if ret is 0, need to create new pl object value. */ + if (OB_SUCC(ret)) { + ObPLObjectValue *pl_object_value = nullptr; + if (OB_FAIL(create_new_pl_object_value(pl_object_value))) { + LOG_WARN("fail to create new function value", K(ret)); + } else if (OB_UNLIKELY(nullptr == pl_object_value)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(pl_object_value->init(*cache_obj, pc_ctx))) { + LOG_WARN("failed to init pl function", K(ret)); + } else { + bool is_old_version = false; + if (pl_object_value->check_value_version(pc_ctx.schema_guard_, + true, + schema_array, + is_old_version)) { + LOG_WARN("fail to check table version", K(ret)); + } else if (true == is_old_version) { + ret = OB_OLD_SCHEMA_VERSION; + LOG_DEBUG("old schema version, to be delete", K(ret), K(pl_object_value->pl_routine_obj_->get_object_id())); + } else { + pl_object_value->pl_routine_obj_ = cache_object; + pl_object_value->pl_routine_obj_->set_dynamic_ref_handle(PC_REF_PL_HANDLE); + + if (!object_value_sets_.add_last(pl_object_value)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to add pcv to object_value_sets_", K(ret)); + free_pl_object_value(pl_object_value); + pl_object_value = nullptr; + } else { + // do nothing + } + } + } + } + + return ret; +} + + +int64_t ObPLObjectSet::get_mem_size() +{ + int64_t value_mem_size = 0; + + DLIST_FOREACH_NORET(pl_object_value, object_value_sets_) { + if (OB_ISNULL(pl_object_value)) { + BACKTRACE(ERROR, true, "invalid pl_object_value"); + } else { + value_mem_size += pl_object_value->get_mem_size(); + } + } // end for + return value_mem_size; +} + +} +} \ No newline at end of file diff --git a/src/pl/pl_cache/ob_pl_cache.h b/src/pl/pl_cache/ob_pl_cache.h new file mode 100644 index 000000000..339411b58 --- /dev/null +++ b/src/pl/pl_cache/ob_pl_cache.h @@ -0,0 +1,312 @@ +/** + * Copyright (c) 2022 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_PL_CACHE_H_ +#define OCEANBASE_PL_CACHE_H_ +#include "share/ob_define.h" +#include "sql/ob_sql_define.h" +#include "sql/plan_cache/ob_i_lib_cache_key.h" +#include "sql/plan_cache/ob_i_lib_cache_object.h" +#include "sql/plan_cache/ob_i_lib_cache_node.h" +#include "sql/plan_cache/ob_i_lib_cache_context.h" +#include "sql/plan_cache/ob_cache_object_factory.h" +#include "sql/plan_cache/ob_lib_cache_register.h" +#include "pl/ob_pl.h" + +namespace oceanbase +{ + + +namespace pl +{ + class ObPLCompileUnit; +} + +namespace pl +{ + +struct ObPLCacheCtx; +class ObPLObjectSet; +class ObPLCacheMgr; + +//todo:when PCVSchemaObj has been moved to appropriate header file, use PCVSchemaObj to instead of PCVPlSchemaObj +struct PCVPlSchemaObj +{ + uint64_t tenant_id_; + uint64_t database_id_; + int64_t schema_id_; + int64_t schema_version_; + share::schema::ObSchemaType schema_type_; + share::schema::ObTableType table_type_; + common::ObString table_name_; + bool is_tmp_table_; + bool is_explicit_db_name_; + common::ObIAllocator *inner_alloc_; + + PCVPlSchemaObj(): + tenant_id_(common::OB_INVALID_ID), + database_id_(common::OB_INVALID_ID), + schema_id_(common::OB_INVALID_ID), + schema_version_(0), + schema_type_(share::schema::OB_MAX_SCHEMA), + table_type_(share::schema::MAX_TABLE_TYPE), + is_tmp_table_(false), + is_explicit_db_name_(false), + inner_alloc_(nullptr) {} + + explicit PCVPlSchemaObj(ObIAllocator *alloc): + tenant_id_(common::OB_INVALID_ID), + database_id_(common::OB_INVALID_ID), + schema_id_(common::OB_INVALID_ID), + schema_version_(0), + schema_type_(share::schema::OB_MAX_SCHEMA), + table_type_(share::schema::MAX_TABLE_TYPE), + is_tmp_table_(false), + is_explicit_db_name_(false), + inner_alloc_(alloc) {} + + int init(const share::schema::ObTableSchema *schema); + int init_with_version_obj(const share::schema::ObSchemaObjVersion &schema_obj_version); + int init_without_copy_name(const share::schema::ObSimpleTableSchemaV2 *schema); + void set_allocator(common::ObIAllocator *alloc) + { + inner_alloc_ = alloc; + } + + bool compare_schema(const share::schema::ObTableSchema &schema) const + { + bool ret = false; + ret = tenant_id_ == schema.get_tenant_id() && + database_id_ == schema.get_database_id() && + schema_id_ == schema.get_table_id() && + schema_version_ == schema.get_schema_version() && + table_type_ == schema.get_table_type(); + return ret; + } + + bool match_compare(const PCVPlSchemaObj &other) const + { + bool ret = true; + ret = tenant_id_ == other.tenant_id_ + && database_id_ == other.database_id_ + && table_type_ == other.table_type_; + return ret; + } + + bool operator==(const PCVPlSchemaObj &other) const; + + bool operator!=(const PCVPlSchemaObj &other) const + { + return !operator==(other); + } + + void reset(); + ~PCVPlSchemaObj(); + + TO_STRING_KV(K_(tenant_id), + K_(database_id), + K_(schema_id), + K_(schema_version), + K_(schema_type), + K_(table_type), + K_(table_name), + K_(is_tmp_table), + K_(is_explicit_db_name)); +}; + +// standalone procedure/function & package +struct ObPLObjectKey : public ObILibCacheKey +{ + ObPLObjectKey() + : ObILibCacheKey(ObLibCacheNameSpace::NS_INVALID), + db_id_(common::OB_INVALID_ID), + key_id_(common::OB_INVALID_ID), + sessid_(0), + name_() {} + ObPLObjectKey(uint64_t db_id, uint64_t key_id) + : ObILibCacheKey(ObLibCacheNameSpace::NS_INVALID), + db_id_(db_id), + key_id_(key_id), + sessid_(0), + name_() {} + + void reset(); + virtual int deep_copy(common::ObIAllocator &allocator, const ObILibCacheKey &other) override; + void destory(common::ObIAllocator &allocator); + virtual uint64_t hash() const override; + virtual bool is_equal(const ObILibCacheKey &other) const; + + TO_STRING_KV(K_(db_id), + K_(key_id), + K_(namespace), + K_(name)); + + uint64_t db_id_; + uint64_t key_id_; // routine id or package id + uint32_t sessid_; + common::ObString name_; +}; + +class ObPLObjectValue : public common::ObDLinkBase +{ +public: + ObPLObjectValue(common::ObIAllocator &alloc) : + pc_alloc_(&alloc), + sys_schema_version_(OB_INVALID_VERSION), + tenant_schema_version_(OB_INVALID_VERSION), + sessid_(OB_INVALID_ID), + sess_create_time_(0), + contain_sys_name_table_(false), + contain_tmp_table_(false), + contain_sys_pl_object_(false), + stored_schema_objs_(pc_alloc_), + params_info_(ObWrapperAllocator(alloc)), + pl_routine_obj_(NULL) {} + + virtual ~ObPLObjectValue() { reset(); } + int init(const ObILibCacheObject &cache_obj, ObPLCacheCtx &pc_ctx); + int set_stored_schema_objs(const DependenyTableStore &dep_table_store, + share::schema::ObSchemaGetterGuard *schema_guard); + int lift_tenant_schema_version(int64_t new_schema_version); + int check_value_version(share::schema::ObSchemaGetterGuard *schema_guard, + bool need_check_schema, + const ObIArray &schema_array, + bool &is_old_version); + int need_check_schema_version(ObPLCacheCtx &pc_ctx, + int64_t &new_schema_version, + bool &need_check); + int get_all_dep_schema(ObPLCacheCtx &pc_ctx, + const uint64_t database_id, + int64_t &new_schema_version, + bool &need_check_schema, + ObIArray &schema_array); + // get all dependency schemas, used for add plan + static int get_all_dep_schema(share::schema::ObSchemaGetterGuard &schema_guard, + const DependenyTableStore &dep_schema_objs, + common::ObIArray &schema_array); + int match_dep_schema(const ObPLCacheCtx &pc_ctx, + const ObIArray &schema_array, + bool &is_same); + int add_match_info(ObILibCacheCtx &ctx, + ObILibCacheKey *key, + const ObILibCacheObject &cache_obj); + + bool match_params_info(const Ob2DArray &infos); + + int match_param_info(const ObParamInfo ¶m_info, + const ObObjParam ¶m, + bool &is_same) const; + + int match_params_info(const ParamStore *params, + bool &is_same); + + void reset(); + int64_t get_mem_size(); + + TO_STRING_KV(K_(sys_schema_version), + K_(tenant_schema_version), + K_(sessid), + K_(sess_create_time)); + +public: + common::ObIAllocator *pc_alloc_; + int64_t sys_schema_version_; + int64_t tenant_schema_version_; + uint64_t sessid_; // session id for temporary table + uint64_t sess_create_time_; // sess_create_time_ for temporary table + bool contain_sys_name_table_; + bool contain_tmp_table_; + /* The update of the system package/class will only push up the schema version of the system tenant. + If the object under the common tenant depends on the system package/class, + In the update scenario, since the schema_version of ordinary users is not pushed up, + it may miss checking whether the system package/type is out of date, + Causes routine objects that depend on system packages/classes to be unavailable after updating, + so schema checks are always performed on classes containing system packages/classes*/ + bool contain_sys_pl_object_; + common::ObFixedArray stored_schema_objs_; + common::Ob2DArray params_info_; + pl::ObPLCompileUnit *pl_routine_obj_; +private: + DISALLOW_COPY_AND_ASSIGN(ObPLObjectValue); +}; + + +struct ObPLCacheCtx : public ObILibCacheCtx +{ + ObPLCacheCtx() + : ObILibCacheCtx(), + handle_id_(MAX_HANDLE), + key_(), + session_info_(NULL), + schema_guard_(NULL), + need_add_obj_stat_(true), + cache_params_(NULL), + raw_sql_() + { + sql_id_[0] = '\0'; + sql_id_[common::OB_MAX_SQL_ID_LENGTH] = '\0'; + } + + CacheRefHandleID handle_id_; + ObPLObjectKey key_; + char sql_id_[common::OB_MAX_SQL_ID_LENGTH + 1]; + ObSQLSessionInfo *session_info_; + share::schema::ObSchemaGetterGuard *schema_guard_; + bool need_add_obj_stat_; + ParamStore *cache_params_; + ObString raw_sql_; +}; + + +class ObPLObjectSet : public ObILibCacheNode +{ +public: + ObPLObjectSet(ObPlanCache *lib_cache, lib::MemoryContext &mem_context) + : ObILibCacheNode(lib_cache, mem_context), + is_inited_(false), + key_() + { + } + virtual ~ObPLObjectSet() + { + destroy(); + }; + virtual int init(ObILibCacheCtx &ctx, const ObILibCacheObject *cache_obj) override; + virtual int inner_get_cache_obj(ObILibCacheCtx &ctx, + ObILibCacheKey *key, + ObILibCacheObject *&cache_obj) override; + virtual int inner_add_cache_obj(ObILibCacheCtx &ctx, + ObILibCacheKey *key, + ObILibCacheObject *cache_obj) override; + + void destroy(); + + int create_new_pl_object_value(ObPLObjectValue *&pl_object_value); + void free_pl_object_value(ObPLObjectValue *pl_object_value); + int64_t get_mem_size(); + + TO_STRING_KV(K_(is_inited)); +private: + bool is_inited_; + ObPLObjectKey key_; //used for manager key memory + // a list of plan sets with different param types combination + common::ObDList object_value_sets_; +}; + + +} // namespace pl end +} // namespace oceanbase end + +#endif \ No newline at end of file diff --git a/src/pl/pl_cache/ob_pl_cache_mgr.cpp b/src/pl/pl_cache/ob_pl_cache_mgr.cpp new file mode 100644 index 000000000..cbb9e62ef --- /dev/null +++ b/src/pl/pl_cache/ob_pl_cache_mgr.cpp @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2022 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX PL_CACHE +#include "ob_pl_cache_mgr.h" +#include "observer/ob_req_time_service.h" +#include "sql/plan_cache/ob_plan_cache.h" + +using namespace oceanbase::observer; + +namespace oceanbase +{ +namespace pl +{ + + +int ObPLCacheMgr::get_pl_object(ObPlanCache *lib_cache, ObILibCacheCtx &ctx, ObCacheObjGuard& guard) +{ + int ret = OB_SUCCESS; + FLTSpanGuard(pc_get_pl_object); + //guard.get_cache_obj() = NULL; + ObGlobalReqTimeService::check_req_timeinfo(); + if (OB_ISNULL(lib_cache)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("lib cache is null"); + } else { + ObPLCacheCtx &pc_ctx = static_cast(ctx); + if (OB_FAIL(lib_cache->get_cache_obj(ctx, &pc_ctx.key_, guard))) { + PL_CACHE_LOG(DEBUG, "failed to get plan", K(ret)); + // if schema expired, update pl cache; + if (OB_OLD_SCHEMA_VERSION == ret) { + PL_CACHE_LOG(WARN, "start to remove pl object", K(ret), K(pc_ctx.key_)); + if (OB_FAIL(lib_cache->remove_cache_node(&pc_ctx.key_))) { + PL_CACHE_LOG(WARN, "fail to remove pcv set when schema/plan expired", K(ret)); + } else { + ret = OB_SQL_PC_NOT_EXIST; + } + } + if (OB_FAIL(ret) && OB_NOT_NULL(guard.get_cache_obj())) { + ObILibCacheObject *cache_obj = guard.get_cache_obj(); + ObCacheObjectFactory::free(lib_cache, cache_obj, guard.get_ref_handle()); + //guard.get_cache_obj() = NULL; + } + } else if (OB_ISNULL(guard.get_cache_obj()) || + (!guard.get_cache_obj()->is_prcr() && + !guard.get_cache_obj()->is_sfc() && + !guard.get_cache_obj()->is_pkg() && + !guard.get_cache_obj()->is_anon())) { + ret = OB_ERR_UNEXPECTED; + PL_CACHE_LOG(WARN, "cache obj is invalid", KPC(guard.get_cache_obj())); + } + + if (OB_FAIL(ret) && OB_NOT_NULL(guard.get_cache_obj())) { + // TODO PL pc_ctx + ObILibCacheObject *cache_obj = guard.get_cache_obj(); + ObCacheObjectFactory::free(lib_cache, cache_obj, static_cast(pc_ctx).handle_id_); + //guard.get_cache_obj() = NULL; + } + if (OB_SUCC(ret) && OB_NOT_NULL(guard.get_cache_obj())) { + lib_cache->inc_hit_and_access_cnt(); + } else { + lib_cache->inc_access_cnt(); + } + } + + return ret; +} + +int ObPLCacheMgr::get_pl_cache(ObPlanCache *lib_cache, ObCacheObjGuard& guard, ObPLCacheCtx &pc_ctx) +{ + int ret = OB_SUCCESS; + ObGlobalReqTimeService::check_req_timeinfo(); + pc_ctx.handle_id_ = guard.get_ref_handle(); + if (OB_FAIL(get_pl_object(lib_cache, pc_ctx, guard))) { + PL_CACHE_LOG(DEBUG, "fail to get plan", K(ret)); + } else if (OB_ISNULL(guard.get_cache_obj())) { + ret = OB_ERR_UNEXPECTED; + PL_CACHE_LOG(WARN, "cache obj is invalid", KPC(guard.get_cache_obj())); + } else { + // update pl func/package stat + pl::PLCacheObjStat *stat = NULL; + int64_t current_time = ObTimeUtility::current_time(); + if (ObLibCacheNameSpace::NS_PKG != guard.get_cache_obj()->get_ns()) { + pl::ObPLFunction* pl_func = static_cast(guard.get_cache_obj()); + stat = &pl_func->get_stat_for_update(); + ATOMIC_INC(&(stat->hit_count_)); + ATOMIC_STORE(&(stat->last_active_time_), current_time); + } else { + //todo:support package + //pl::ObPLPackage* pl_pkg = static_cast(guard.get_cache_obj()); + //stat = &pl_pkg->get_stat_for_update(); + } + } + return ret; +} + +int ObPLCacheMgr::add_pl_object(ObPlanCache *lib_cache, + ObILibCacheCtx &ctx, + ObILibCacheObject *cache_obj) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(cache_obj)) { + ret = OB_INVALID_ARGUMENT; + PL_CACHE_LOG(WARN, "invalid cache obj", K(ret)); + } else if (OB_ISNULL(lib_cache)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("lib cache is null"); + } else { + ObPLCacheCtx &pc_ctx = static_cast(ctx); + do { + if (OB_FAIL(lib_cache->add_cache_obj(ctx, &pc_ctx.key_, cache_obj)) && OB_OLD_SCHEMA_VERSION == ret) { + PL_CACHE_LOG(INFO, "schema in pl cache value is old, start to remove pl object", K(ret), K(pc_ctx.key_)); + int tmp_ret = OB_SUCCESS; + if (OB_SUCCESS != (tmp_ret = lib_cache->remove_cache_node(&pc_ctx.key_))) { + ret = tmp_ret; + PL_CACHE_LOG(WARN, "fail to remove lib cache node", K(ret)); + } + } + } while (OB_OLD_SCHEMA_VERSION == ret); + } + return ret; +} + +int ObPLCacheMgr::add_pl_cache(ObPlanCache *lib_cache, ObILibCacheObject *pl_object, ObPLCacheCtx &pc_ctx) +{ + int ret = OB_SUCCESS; + FLTSpanGuard(pc_add_pl_object); + ObGlobalReqTimeService::check_req_timeinfo(); + if (OB_ISNULL(lib_cache)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("lib cache is null"); + } else if (OB_ISNULL(pl_object)) { + ret = OB_INVALID_ARGUMENT; + PL_CACHE_LOG(WARN, "invalid physical plan", K(ret)); + } else if (lib_cache->get_mem_hold() > lib_cache->get_mem_limit()) { + ret = OB_REACH_MEMORY_LIMIT; + PL_CACHE_LOG(DEBUG, "lib cache memory used reach the high water mark", + K(lib_cache->get_mem_used()), K(lib_cache->get_mem_limit()), K(ret)); + } else if (pl_object->get_mem_size() >= lib_cache->get_mem_high()) { + // do nothing + } else { + ObLibCacheNameSpace ns = NS_INVALID; + switch (pl_object->get_ns()) { + case NS_PRCR: + case NS_SFC: { + ns = NS_PRCR; + } + break; + case NS_PKG: + case NS_ANON: { + ns = pl_object->get_ns(); + } + break; + default: { + ret = OB_NOT_SUPPORTED; + PL_CACHE_LOG(WARN, "pl object to cache is not valid", K(pl_object->get_ns()), K(ret)); + } + break; + } + if (OB_FAIL(ret)) { + } else if (FALSE_IT(pc_ctx.key_.namespace_ = ns)) { + } else if (OB_FAIL(add_pl_object(lib_cache, pc_ctx, pl_object))) { + if (!is_not_supported_err(ret) + && OB_SQL_PC_PLAN_DUPLICATE != ret) { + PL_CACHE_LOG(WARN, "fail to add pl function", K(ret)); + } + } else { + (void)lib_cache->inc_mem_used(pl_object->get_mem_size()); + } + } + return ret; +} + + +// delete all pl cache obj +int ObPLCacheMgr::cache_evict_all_pl(ObPlanCache *lib_cache) +{ + int ret = OB_SUCCESS; + PL_CACHE_LOG(DEBUG, "cache evict all pl cache start"); + if (OB_ISNULL(lib_cache)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("lib cache is null"); + } else { + LCKeyValueArray to_evict_keys; + ObGetPLKVEntryOp get_ids_op(&to_evict_keys, PCV_GET_PL_KEY_HANDLE); + if (OB_FAIL(lib_cache->foreach_cache_evict(get_ids_op))) { + PL_CACHE_LOG(WARN, "failed to foreach cache evict", K(ret)); + } + PL_CACHE_LOG(DEBUG, "cache evict all pl end", K(to_evict_keys)); + } + + return ret; +} + +} +} \ No newline at end of file diff --git a/src/pl/pl_cache/ob_pl_cache_mgr.h b/src/pl/pl_cache/ob_pl_cache_mgr.h new file mode 100644 index 000000000..ee1493890 --- /dev/null +++ b/src/pl/pl_cache/ob_pl_cache_mgr.h @@ -0,0 +1,81 @@ + +/** + * Copyright (c) 2022 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_PL_CACHE_MGR_H_ +#define OCEANBASE_PL_CACHE_MGR_H_ +#include "share/ob_define.h" +#include "ob_pl_cache.h" +#include "sql/plan_cache/ob_i_lib_cache_key.h" +#include "sql/plan_cache/ob_i_lib_cache_node.h" +#include "sql/plan_cache/ob_plan_cache_manager.h" + +namespace oceanbase +{ + +namespace sql +{ + class ObPlanCache; + class ObKVEntryTraverseOp; +} + +namespace pl +{ + +struct ObGetPLKVEntryOp : public sql::ObKVEntryTraverseOp +{ + explicit ObGetPLKVEntryOp(LCKeyValueArray *key_val_list, + const CacheRefHandleID ref_handle) + : ObKVEntryTraverseOp(key_val_list, ref_handle) + { + } + virtual int check_entry_match(LibCacheKVEntry &entry, bool &is_match) + { + int ret = OB_SUCCESS; + is_match = false; + if (ObLibCacheNameSpace::NS_PRCR == entry.first->namespace_ || + ObLibCacheNameSpace::NS_SFC == entry.first->namespace_ || + ObLibCacheNameSpace::NS_ANON == entry.first->namespace_ || + ObLibCacheNameSpace::NS_PKG == entry.first->namespace_) { + is_match = true; + } + return ret; + } +}; + +class ObPLCacheMgr +{ +public: + ObPLCacheMgr() {} + + ~ObPLCacheMgr() {} + + static int add_pl_cache(ObPlanCache *lib_cache, ObILibCacheObject *pl_object, ObPLCacheCtx &pc_ctx); + static int get_pl_cache(ObPlanCache *lib_cache, + ObCacheObjGuard& guard, ObPLCacheCtx &pc_ctx); + + static int cache_evict_all_pl(ObPlanCache *lib_cache); + +private: + static int add_pl_object(ObPlanCache *lib_cache, + ObILibCacheCtx &ctx, + ObILibCacheObject *cache_obj); + static int get_pl_object(ObPlanCache *lib_cache, + ObILibCacheCtx &pc_ctx, ObCacheObjGuard& guard); + + DISALLOW_COPY_AND_ASSIGN(ObPLCacheMgr); +}; + +} // namespace pl end +} // namespace oceanbase end + +#endif \ No newline at end of file diff --git a/src/pl/sys_package/ob_dbms_sql.cpp b/src/pl/sys_package/ob_dbms_sql.cpp index 69b04bf3a..84de5e06d 100644 --- a/src/pl/sys_package/ob_dbms_sql.cpp +++ b/src/pl/sys_package/ob_dbms_sql.cpp @@ -88,19 +88,45 @@ int ObDbmsInfo::deep_copy_field_columns(ObIAllocator& allocator, return ret; } +int ObDbmsInfo::deep_copy_field_columns(ObIAllocator& allocator, + const common::ColumnsFieldArray src_fields, + common::ColumnsFieldArray &dst_fields) +{ + int ret = OB_SUCCESS; + dst_fields.reset(); + dst_fields.set_allocator(&allocator); + if (src_fields.count() <= 0) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("src fields is null.", K(ret), K(src_fields.count())); + } else if (OB_FAIL(dst_fields.reserve(src_fields.count()))) { + LOG_WARN("fail to reserve column fields", + K(ret), K(dst_fields.count()), K(src_fields.count())); + } else { + for (int64_t i = 0 ; OB_SUCC(ret) && i < src_fields.count(); ++i) { + ObField tmp_field; + if (OB_FAIL(tmp_field.deep_copy(src_fields.at(i), &allocator))) { + LOG_WARN("deep copy field failed", K(ret)); + } else if (OB_FAIL(dst_fields.push_back(tmp_field))) { + LOG_WARN("push back field param failed", K(ret)); + } else { } + } + } + return ret; +} + int ObDbmsInfo::init_params(int64_t param_count) { int ret = OB_SUCCESS; ObIAllocator *alloc = NULL; - OV (OB_NOT_NULL(entity_), OB_NOT_INIT, stmt_id_, param_count); + OV (OB_NOT_NULL(entity_), OB_NOT_INIT, ps_sql_, param_count); OX (alloc = &entity_->get_arena_allocator()); CK (OB_NOT_NULL(alloc)); OX (param_names_.reset()); OX (param_names_.set_allocator(alloc)); - OZ (param_names_.init(param_count), stmt_id_, param_count); + OZ (param_names_.init(param_count), ps_sql_, param_count); OX (bind_params_.reset()); OX (bind_params_.set_allocator(alloc)); - OZ (bind_params_.init(param_count), stmt_id_, param_count); + OZ (bind_params_.init(param_count), ps_sql_, param_count); OX (exec_params_.~Ob2DArray()); OX (new (&exec_params_) ParamStore(ObWrapperAllocator(alloc))); return ret; @@ -181,12 +207,12 @@ int ObDbmsInfo::add_param_name(ObString &clone_name) ObIAllocator *alloc = NULL; int64_t param_cnt = param_names_.count(); CK (into_cnt <= param_cnt); - OV (OB_NOT_NULL(entity_), OB_NOT_INIT, stmt_id_, param_cnt); + OV (OB_NOT_NULL(entity_), OB_NOT_INIT, ps_sql_, param_cnt); OX (alloc = &entity_->get_arena_allocator()); CK (OB_NOT_NULL(alloc)); OX (into_names_.reset()); OX (into_names_.set_allocator(alloc)); - OZ (into_names_.init(into_cnt), stmt_id_, into_cnt); + OZ (into_names_.init(into_cnt), ps_sql_, into_cnt); for (int64_t i = param_cnt - into_cnt; OB_SUCC(ret) && i < param_cnt; ++i) { OZ (into_names_.push_back(param_names_.at(i))); } diff --git a/src/pl/sys_package/ob_dbms_sql.h b/src/pl/sys_package/ob_dbms_sql.h index 204c2e757..319ff8382 100644 --- a/src/pl/sys_package/ob_dbms_sql.h +++ b/src/pl/sys_package/ob_dbms_sql.h @@ -45,7 +45,7 @@ public: : sql_stmt_(), stmt_type_(sql::stmt::T_NONE), entity_(nullptr), - stmt_id_(0), + ps_sql_(), param_names_(alloc), into_names_(alloc), bind_params_(alloc), @@ -59,8 +59,8 @@ public: inline lib::MemoryContext &get_dbms_entity() { return entity_; } inline const lib::MemoryContext get_dbms_entity() const { return entity_; } - inline int64_t get_stmt_id() const { return stmt_id_; } - inline void set_stmt_id(int64_t id) { stmt_id_ = id; } + inline common::ObString &get_ps_sql() { return ps_sql_; } + inline void set_ps_sql(ObString sql) { ps_sql_ = sql; } common::ObString &get_sql_stmt() { return sql_stmt_; } sql::stmt::StmtType get_stmt_type() const { return stmt_type_; } inline void set_stmt_type(sql::stmt::StmtType type) { stmt_type_ = type; } @@ -70,6 +70,10 @@ public: ObIAllocator& allocator, const common::ColumnsFieldIArray* src_fields, common::ColumnsFieldArray &dst_fields); + static int deep_copy_field_columns( + ObIAllocator& allocator, + const common::ColumnsFieldArray src_fields, + common::ColumnsFieldArray &dst_fields); int init_params(int64_t param_count); int get_param_name_count() const { return param_names_.count(); } @@ -152,7 +156,7 @@ protected: sql::stmt::StmtType stmt_type_; private: lib::MemoryContext entity_; - int64_t stmt_id_; + common::ObString ps_sql_; ParamNames param_names_; IntoNames into_names_; BindParams bind_params_; diff --git a/src/rootserver/ob_ddl_operator.cpp b/src/rootserver/ob_ddl_operator.cpp index ba41d1b93..daa655a5a 100644 --- a/src/rootserver/ob_ddl_operator.cpp +++ b/src/rootserver/ob_ddl_operator.cpp @@ -8478,6 +8478,7 @@ int ObDDLOperator::del_routines_in_package(const ObPackageInfo &package_info, int ObDDLOperator::create_trigger(ObTriggerInfo &trigger_info, ObMySQLTransaction &trans, ObErrorInfo &error_info, + ObIArray &dep_infos, const ObString *ddl_stmt_str, bool for_insert_errors, bool is_update_table_schema_version, @@ -8512,6 +8513,16 @@ int ObDDLOperator::create_trigger(ObTriggerInfo &trigger_info, trans, tenant_id, base_table_id, false/*in offline ddl white list*/), base_table_id, trigger_info.get_trigger_name()); } + } else if (0 == dep_infos.count()) { + // create trigger in mysql mode or create trigger when truncate table, dep_infos.count() is 0, + // no need to deal with dependencies. + } else { + OZ (ObDependencyInfo::delete_schema_object_dependency(trans, trigger_info.get_tenant_id(), + trigger_info.get_trigger_id(), + trigger_info.get_schema_version(), + trigger_info.get_object_type())); + OZ (insert_dependency_infos(trans, dep_infos, trigger_info.get_tenant_id(), trigger_info.get_trigger_id(), + trigger_info.get_schema_version(), trigger_info.get_owner_id())); } if (OB_SUCC(ret)) { if (OB_FAIL(error_info.handle_error_info(trans, &trigger_info))) { @@ -8538,6 +8549,10 @@ int ObDDLOperator::drop_trigger(const ObTriggerInfo &trigger_info, new_schema_version, trans, ddl_stmt_str), trigger_info.get_trigger_name()); + OZ (ObDependencyInfo::delete_schema_object_dependency(trans, tenant_id, + trigger_info.get_trigger_id(), + new_schema_version, + trigger_info.get_object_type())); if (OB_SUCC(ret) && !trigger_info.is_system_type() && is_update_table_schema_version) { uint64_t base_table_id = trigger_info.get_base_object_id(); OZ (schema_service->get_table_sql_service().update_data_table_schema_version(trans, diff --git a/src/rootserver/ob_ddl_operator.h b/src/rootserver/ob_ddl_operator.h index 20b73e9f8..a2d74cb99 100644 --- a/src/rootserver/ob_ddl_operator.h +++ b/src/rootserver/ob_ddl_operator.h @@ -781,6 +781,7 @@ public: int create_trigger(share::schema::ObTriggerInfo &new_trigger_info, common::ObMySQLTransaction &trans, share::schema::ObErrorInfo &error_info, + ObIArray &dep_infos, const common::ObString *ddl_stmt_str/*=NULL*/, bool for_insert_errors, bool is_update_table_schema_version = true, diff --git a/src/rootserver/ob_ddl_service.cpp b/src/rootserver/ob_ddl_service.cpp index b30e2a59c..d633d1d01 100644 --- a/src/rootserver/ob_ddl_service.cpp +++ b/src/rootserver/ob_ddl_service.cpp @@ -14309,8 +14309,11 @@ int ObDDLService::rebuild_triggers_on_hidden_table( OX (new_trigger_info.set_tenant_id(hidden_table_schema.get_tenant_id())); OZ (ddl_operator.drop_trigger(*trigger_info, trans, nullptr, false/*is_update_table_schema_version*/)); - OZ (ddl_operator.create_trigger(new_trigger_info, trans, error_info, - nullptr, false/*for_insert_errors*/, false/*is_update_table_schema_version*/)); + if (OB_SUCC(ret)) { + ObSEArray dep_infos; + OZ (ddl_operator.create_trigger(new_trigger_info, trans, error_info, dep_infos, + nullptr, false/*for_insert_errors*/, false/*is_update_table_schema_version*/)); + } } } return ret; @@ -26865,18 +26868,21 @@ int ObDDLService::create_trigger(const ObCreateTriggerArg &arg) { int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; - ObTriggerInfo new_trigger_info = arg.trigger_info_; + ObTriggerInfo new_trigger_info; //for_insert_errors_ is false, Indicates that the trigger is created normally //true Indicates that the error message is inserted into the system table after the trigger is created //So the following steps can be skipped - uint64_t tenant_id = new_trigger_info.get_tenant_id(); + uint64_t tenant_id = OB_INVALID_ID; uint64_t trigger_database_id = OB_INVALID_ID; uint64_t base_object_id = OB_INVALID_ID; ObSchemaType base_object_type = OB_MAX_SCHEMA; const ObString &trigger_database = arg.trigger_database_; const ObString &base_object_database = arg.base_object_database_; const ObString &base_object_name = arg.base_object_name_; - if (OB_FAIL(get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { + if (OB_FAIL(new_trigger_info.assign(arg.trigger_info_))) { + LOG_WARN("assign trigger_info failed", K(ret)); + } else if (FALSE_IT(tenant_id = new_trigger_info.get_tenant_id())) { + } else if (OB_FAIL(get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) { LOG_WARN("o get schema guard in inner table failed", KR(ret), K(tenant_id)); } else if (!arg.for_insert_errors_) { const ObTriggerInfo *old_trigger_info = NULL; @@ -26904,6 +26910,7 @@ int ObDDLService::create_trigger(const ObCreateTriggerArg &arg) if (OB_SUCC(ret) && OB_FAIL(create_trigger_in_trans(new_trigger_info, const_cast(arg.error_info_), + const_cast &>(arg.dependency_infos_), &arg.ddl_stmt_str_, arg.for_insert_errors_, schema_guard))) { @@ -26914,6 +26921,7 @@ int ObDDLService::create_trigger(const ObCreateTriggerArg &arg) int ObDDLService::create_trigger_in_trans(ObTriggerInfo &trigger_info, ObErrorInfo &error_info, + ObIArray &dep_infos, const ObString *ddl_stmt_str, bool for_insert_errors, share::schema::ObSchemaGetterGuard &schema_guard) @@ -26927,7 +26935,7 @@ int ObDDLService::create_trigger_in_trans(ObTriggerInfo &trigger_info, LOG_WARN("failed to get tenant schema version", KR(ret), K(tenant_id)); } else if (OB_FAIL(trans.start(sql_proxy_, tenant_id, refreshed_schema_version))) { LOG_WARN("start transaction failed", KR(ret), K(tenant_id), K(refreshed_schema_version)); - } else if (OB_FAIL(ddl_operator.create_trigger(trigger_info, trans, error_info, + } else if (OB_FAIL(ddl_operator.create_trigger(trigger_info, trans, error_info, dep_infos, ddl_stmt_str, for_insert_errors))) { LOG_WARN("create trigger failed", K(ret), K(trigger_info)); } @@ -27047,12 +27055,27 @@ int ObDDLService::alter_trigger(const ObAlterTriggerArg &arg) OZ (trans.start(sql_proxy_, tenant_id, refreshed_schema_version), refreshed_schema_version); for (int64_t i = 0; OB_SUCC(ret) && i < arg.trigger_infos_.count(); ++i) { const ObTriggerInfo *old_tg_info = NULL; - ObTriggerInfo new_tg_info = arg.trigger_infos_.at(i); + ObTriggerInfo new_tg_info; + OZ (new_tg_info.assign(arg.trigger_infos_.at(i))); OZ (schema_guard.get_trigger_info(tenant_id, new_tg_info.get_trigger_id(), old_tg_info)); CK (OB_NOT_NULL(old_tg_info), OB_ERR_TRIGGER_NOT_EXIST); - OZ (new_tg_info.deep_copy(*old_tg_info)); - OX (new_tg_info.set_is_enable(is_enable)); - OZ (ddl_operator.alter_trigger(new_tg_info, trans, &arg.ddl_stmt_str_)); + if (OB_SUCC(ret)) { + if (!arg.is_set_status_) { + const ObTriggerInfo *other_trg_info = NULL; + ObString new_trg_name = new_tg_info.get_trigger_name(); + ObString new_trg_body = new_tg_info.get_trigger_body(); + OZ (schema_guard.get_trigger_info(new_tg_info.get_tenant_id(), new_tg_info.get_database_id(), + new_trg_name, other_trg_info)); + OV (OB_ISNULL(other_trg_info), OB_OBJ_ALREADY_EXIST, new_tg_info); + OZ (new_tg_info.deep_copy(*old_tg_info)); + OZ (new_tg_info.set_trigger_name(new_trg_name)); + OZ (new_tg_info.set_trigger_body(new_trg_body)); + } else { + OZ (new_tg_info.deep_copy(*old_tg_info)); + OX (new_tg_info.set_is_enable(is_enable)); + } + OZ (ddl_operator.alter_trigger(new_tg_info, trans, &arg.ddl_stmt_str_)); + } } if (trans.is_started()) { int temp_ret = OB_SUCCESS; @@ -27166,16 +27189,15 @@ int ObDDLService::create_trigger_for_truncate_table(ObSchemaGetterGuard &schema_ new_trigger_info.set_trigger_id(new_trigger_id); new_trigger_info.set_base_object_id(new_table_schema.get_table_id()); new_table_schema.get_trigger_list().push_back(new_trigger_id); - OZ (ObTriggerInfo::gen_package_source(new_trigger_info, db_schema->get_database_name(), - new_table_schema.get_table_name(), - spec_source, body_source, inner_alloc)); - if (OB_SUCC(ret) && OB_FAIL(ddl_operator - .create_trigger(new_trigger_info, trans, error_info, - &origin_trigger_info->get_trigger_body(), - false, /* for_insert_error */ - is_update_table_schema_version, - true))) { - LOG_WARN("failed to create trigger for truncate table", K(ret)); + if (OB_SUCC(ret)) { + ObSEArray dep_infos; + if (OB_FAIL(ddl_operator.create_trigger(new_trigger_info, trans, error_info, dep_infos, + &origin_trigger_info->get_trigger_body(), + false, /* for_insert_error */ + is_update_table_schema_version, + true))) { + LOG_WARN("failed to create trigger for truncate table", K(ret)); + } } } } diff --git a/src/rootserver/ob_ddl_service.h b/src/rootserver/ob_ddl_service.h index 71299dfdd..5a37218c1 100644 --- a/src/rootserver/ob_ddl_service.h +++ b/src/rootserver/ob_ddl_service.h @@ -859,6 +859,7 @@ public: // trigger int create_trigger_in_trans(share::schema::ObTriggerInfo &new_trigger_info, share::schema::ObErrorInfo &error_info, + ObIArray &dep_infos, const common::ObString *ddl_stmt_str, bool for_insert_errors, share::schema::ObSchemaGetterGuard &schema_guard); diff --git a/src/share/ob_rpc_struct.cpp b/src/share/ob_rpc_struct.cpp index 8c4acd8d2..91b6e4752 100644 --- a/src/share/ob_rpc_struct.cpp +++ b/src/share/ob_rpc_struct.cpp @@ -4553,8 +4553,25 @@ bool ObAlterTriggerArg::is_valid() const return trigger_infos_.count() != 0; } +int ObAlterTriggerArg::assign(const ObAlterTriggerArg &other) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(ObDDLArg::assign(other))) { + LOG_WARN("fail to assign ddl arg", KR(ret)); + } else if (OB_FAIL(trigger_info_.assign(other.trigger_info_))) { + LOG_WARN("failed to copy trigger info", K(ret)); + } else if (OB_FAIL(trigger_infos_.assign(other.trigger_infos_))) { + LOG_WARN("failed to copy trigger infos", K(ret)); + } else { + trigger_database_ = other.trigger_database_; + is_set_status_ = other.is_set_status_; + is_alter_compile_ = other.is_alter_compile_; + } + return ret; +} + OB_SERIALIZE_MEMBER((ObAlterTriggerArg, ObDDLArg), trigger_database_, - trigger_info_, trigger_infos_); + trigger_info_, trigger_infos_, is_set_status_, is_alter_compile_); bool ObCreateUDTArg::is_valid() const { diff --git a/src/share/ob_rpc_struct.h b/src/share/ob_rpc_struct.h index 3d9108631..e2784ff84 100644 --- a/src/share/ob_rpc_struct.h +++ b/src/share/ob_rpc_struct.h @@ -5496,19 +5496,25 @@ OB_UNIS_VERSION(1); public: ObAlterTriggerArg() : - ObDDLArg(), trigger_database_(), trigger_info_() + ObDDLArg(), trigger_database_(), trigger_info_(), trigger_infos_(), + is_set_status_(false),is_alter_compile_(false) {} virtual ~ObAlterTriggerArg() {} bool is_valid() const; + int assign(const ObAlterTriggerArg &other); TO_STRING_KV(K(trigger_database_), K(trigger_info_), - K(trigger_infos_)) + K(trigger_infos_), + K(is_set_status_), + K(is_alter_compile_)) ; public: common::ObString trigger_database_; // 废弃 share::schema::ObTriggerInfo trigger_info_; // 废弃 common::ObSArray trigger_infos_; + bool is_set_status_; + bool is_alter_compile_; }; struct ObCreateUDTArg : public ObDDLArg diff --git a/src/share/schema/ob_dependency_info.cpp b/src/share/schema/ob_dependency_info.cpp index b7ef4d515..4447ba337 100644 --- a/src/share/schema/ob_dependency_info.cpp +++ b/src/share/schema/ob_dependency_info.cpp @@ -330,35 +330,38 @@ int ObDependencyInfo::collect_dep_infos(const ObIArray &sche int ret = OB_SUCCESS; int64_t order = 0; for (int64_t i = 0; OB_SUCC(ret) && i < schema_objs.count(); ++i) { - ObDependencyInfo dep; - const ObSchemaObjVersion &s_objs = schema_objs.at(i); - if (!s_objs.is_valid() - // object may depend on self - || (is_pl - && dep_obj_type == s_objs.get_schema_object_type())) { - continue; + // if (ObObjectType::TRIGGER == dep_obj_type), the schema_objs.at(0) is the trigger itself, need to skip. + if (!(ObObjectType::TRIGGER == dep_obj_type && 0 == i)) { + ObDependencyInfo dep; + const ObSchemaObjVersion &s_objs = schema_objs.at(i); + if (!s_objs.is_valid() + // object may depend on self + || (is_pl + && dep_obj_type == s_objs.get_schema_object_type())) { + continue; + } + dep.set_dep_obj_id(OB_INVALID_ID); + dep.set_dep_obj_type(dep_obj_type); + dep.set_dep_obj_owner_id(OB_INVALID_ID); + dep.set_ref_obj_id(s_objs.get_object_id()); + dep.set_ref_obj_type(s_objs.get_schema_object_type()); + dep.set_order(order); + ++order; + dep.set_dep_timestamp(-1); + dep.set_ref_timestamp(s_objs.get_version()); + dep.set_property(property); + if (dep_attrs.length() >= OB_MAX_ORACLE_RAW_SQL_COL_LENGTH + || dep_reason.length() >= OB_MAX_ORACLE_RAW_SQL_COL_LENGTH) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dep attrs or dep reason is too long", K(ret), + K(dep_attrs.length()), + K(dep_reason.length())); + } else { + if (!dep_attrs.empty()) OZ (dep.set_dep_attrs(dep_attrs)); + if (!dep_reason.empty()) OZ (dep.set_dep_reason(dep_reason)); + } + OZ (deps.push_back(dep)); } - dep.set_dep_obj_id(OB_INVALID_ID); - dep.set_dep_obj_type(dep_obj_type); - dep.set_dep_obj_owner_id(OB_INVALID_ID); - dep.set_ref_obj_id(s_objs.get_object_id()); - dep.set_ref_obj_type(s_objs.get_schema_object_type()); - dep.set_order(order); - ++order; - dep.set_dep_timestamp(-1); - dep.set_ref_timestamp(s_objs.get_version()); - dep.set_property(property); - if (dep_attrs.length() >= OB_MAX_ORACLE_RAW_SQL_COL_LENGTH - || dep_reason.length() >= OB_MAX_ORACLE_RAW_SQL_COL_LENGTH) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dep attrs or dep reason is too long", K(ret), - K(dep_attrs.length()), - K(dep_reason.length())); - } else { - if (!dep_attrs.empty()) OZ (dep.set_dep_attrs(dep_attrs)); - if (!dep_reason.empty()) OZ (dep.set_dep_reason(dep_reason)); - } - OZ (deps.push_back(dep)); } return ret; } diff --git a/src/share/schema/ob_error_info.cpp b/src/share/schema/ob_error_info.cpp index 3c80aec15..04b07615e 100644 --- a/src/share/schema/ob_error_info.cpp +++ b/src/share/schema/ob_error_info.cpp @@ -437,6 +437,27 @@ int ObErrorInfo::handle_error_info(ObMySQLTransaction &trans, const IObErrorInfo return ret; } +int ObErrorInfo::handle_error_info(const IObErrorInfo *info) +{ + int ret = OB_SUCCESS; + ObMySQLTransaction trans; + if (OB_FAIL(collect_error_info(info))) { + LOG_WARN("collect error info failed", K(ret)); + } else if (OB_FAIL(trans.start(GCTX.sql_proxy_, get_tenant_id(), true))) { + LOG_WARN("fail start trans", K(ret)); + } else if (OB_FAIL(handle_error_info(trans, info))) { + LOG_WARN("handle error info failed.", K(ret)); + } + if (trans.is_started()) { + int tmp_ret = OB_SUCCESS; + if (OB_SUCCESS != (tmp_ret = trans.end(OB_SUCCESS == ret))) { + LOG_WARN("trans end failed", K(ret), K(tmp_ret)); + ret = OB_SUCCESS == ret ? tmp_ret : ret; + } + } + return ret; +} + int ObErrorInfo::delete_error(const IObErrorInfo *info) { int ret = OB_SUCCESS; diff --git a/src/share/schema/ob_error_info.h b/src/share/schema/ob_error_info.h index 06994bb38..4738d5b14 100644 --- a/src/share/schema/ob_error_info.h +++ b/src/share/schema/ob_error_info.h @@ -109,6 +109,7 @@ public: int update_error_info(const IObErrorInfo *info); int get_error_info_from_table(common::ObISQLClient &sql_client, ObErrorInfo *old_err_info); int handle_error_info(common::ObMySQLTransaction &trans, const IObErrorInfo *info); + int handle_error_info(const IObErrorInfo *info); int del_error(common::ObISQLClient &sql_client); int del_error(common::ObMySQLProxy *sql_proxy); int add_error(common::ObISQLClient & sql_client, bool is_replace, bool only_history); diff --git a/src/share/schema/ob_trigger_info.cpp b/src/share/schema/ob_trigger_info.cpp index 044dd87ed..257dc20af 100644 --- a/src/share/schema/ob_trigger_info.cpp +++ b/src/share/schema/ob_trigger_info.cpp @@ -326,52 +326,6 @@ int64_t ObTriggerInfo::get_convert_size() const "%.*s \n" /************************* mysql mode procedure *************************/ -int ObTriggerInfo::gen_package_source(const ObTriggerInfo &trigger_info, - const ObString &base_object_database, - const ObString &base_object_name, - ObString &spec_source, - ObString &body_source, - ObIAllocator &alloc) -{ - int ret = OB_SUCCESS; - ObParser parser(alloc, trigger_info.get_sql_mode()); - ParseResult parse_result; - ParseNode *stmt_list_node = NULL; - ParseNode *trigger_source_node = NULL; - ParseNode *trigger_define_node = NULL; - ParseNode *anonymous_node = NULL; - ParseNode *trigger_body_node = NULL; - OZ (parser.parse(trigger_info.get_trigger_body(), parse_result, TRIGGER_MODE), - trigger_info.get_trigger_body()); - // stmt list node. - OV (OB_NOT_NULL(stmt_list_node = parse_result.result_tree_)); - OV (stmt_list_node->type_ == T_STMT_LIST, OB_ERR_UNEXPECTED, stmt_list_node->type_); - OV (stmt_list_node->num_child_ == 1, OB_ERR_UNEXPECTED, stmt_list_node->num_child_); - OV (OB_NOT_NULL(stmt_list_node->children_)); - // trigger source node. - OV (OB_NOT_NULL(trigger_source_node = stmt_list_node->children_[0])); - if (OB_FAIL(ret)) { - } else if (T_TG_SOURCE == trigger_source_node->type_) { - // trigger define node. - OV (OB_NOT_NULL(trigger_define_node = trigger_source_node->children_[1])); - OV (OB_NOT_NULL(trigger_body_node = - trigger_define_node->children_[lib::is_oracle_mode() ? 3 : 2])); - } - if (OB_SUCC(ret)) { - if (trigger_info.is_simple_dml_type() || trigger_info.is_instead_dml_type()) { - OZ (gen_package_source_simple(trigger_info, base_object_database, base_object_name, - *trigger_body_node, - ObDataTypeCastParams(), //trigger_body_node is from utf8 sql - spec_source, body_source, alloc)); - } else { - ret = OB_NOT_SUPPORTED; - LOG_WARN("only simple trigger is supported", K(ret)); - } - } - OV (!spec_source.empty() && !body_source.empty(), OB_ERR_UNEXPECTED, spec_source, body_source); - return ret; -} - int ObTriggerInfo::gen_package_source(const uint64_t tenant_id, const uint64_t tg_package_id, common::ObString &source, @@ -386,7 +340,6 @@ int ObTriggerInfo::gen_package_source(const uint64_t tenant_id, const ParseNode *trigger_define_node = NULL; const ParseNode *trigger_body_node = NULL; const ObTriggerInfo *trigger_info = NULL; - CK (lib::is_oracle_mode()); OZ (schema_guard.get_trigger_info(tenant_id, get_package_trigger_id(tg_package_id), trigger_info)); CK (OB_NOT_NULL(trigger_info)); if (OB_SUCC(ret)) { @@ -422,7 +375,11 @@ int ObTriggerInfo::gen_package_source(const uint64_t tenant_id, } OV (T_TG_SOURCE == trigger_source_node->type_, trigger_source_node->type_); OV (OB_NOT_NULL(trigger_define_node = trigger_source_node->children_[1])); - OV (OB_NOT_NULL(trigger_body_node = trigger_define_node->children_[3])); + if (OB_FAIL(ret)) { + } else { + OV (3 == trigger_define_node->num_child_); + OV (OB_NOT_NULL(trigger_body_node = trigger_define_node->children_[2])); + } OZ (schema_guard.get_simple_table_schema(tenant_id, trigger_info->get_base_object_id(), table_schema)); CK (OB_NOT_NULL(table_schema)); OZ (schema_guard.get_database_schema(tenant_id, table_schema->get_database_id(), base_db_schema)); @@ -441,6 +398,7 @@ int ObTriggerInfo::gen_package_source(const uint64_t tenant_id, OX (source = is_header ? spec_source : body_source); } } + LOG_INFO("generate trigger package end", K(source), K(ret)); return ret; } @@ -1030,6 +988,88 @@ int ObTriggerInfo::gen_procedure_source(const common::ObString &base_object_data return ret; } + +// for rebuild trigger body due to rename table +int ObTriggerInfo::replace_table_name_in_body(ObTriggerInfo &trigger_info, + common::ObIAllocator &alloc, + const common::ObString &base_object_database, + const common::ObString &base_object_name, + bool is_oracle_mode) +{ + UNUSED(base_object_database); + int ret = OB_SUCCESS; + char *buf = NULL; + int64_t buf_len = 0; + int64_t pos = 0; + ObParser parser(alloc, trigger_info.get_sql_mode()); + ParseResult parse_result; + ParseNode *stmt_list_node = NULL; + const ParseNode *trg_source_node = NULL; + + const ParseNode *trg_def_node = NULL; + const ParseNode *dml_event_node = NULL; + const ParseNode *base_schema_node = NULL; + const ParseNode *base_object_node = NULL; + + OZ (parser.parse(trigger_info.get_trigger_body(), parse_result, TRIGGER_MODE), trigger_info.get_trigger_body()); + // stmt list node + OV (OB_NOT_NULL(stmt_list_node = parse_result.result_tree_)); + OV (stmt_list_node->type_ == T_STMT_LIST, OB_ERR_UNEXPECTED, stmt_list_node->type_); + OV (stmt_list_node->num_child_ == 1, OB_ERR_UNEXPECTED, stmt_list_node->num_child_); + OV (OB_NOT_NULL(stmt_list_node->children_)); + // trigger source node + OV (OB_NOT_NULL(trg_source_node = stmt_list_node->children_[0])); + + OV (2 == trg_source_node->num_child_); + OV (OB_NOT_NULL(trg_def_node = trg_source_node->children_[1])); + if (OB_FAIL(ret)) { + // do nothing + } else if (is_oracle_mode) { + OV (4 == trg_def_node->num_child_); + OV (OB_NOT_NULL(dml_event_node = trg_def_node->children_[0])); + OV (3 == dml_event_node->num_child_); + OV (OB_NOT_NULL(base_schema_node = dml_event_node->children_[2])); + } else { + OV (3 == trg_def_node->num_child_); + OV (OB_NOT_NULL(base_schema_node = trg_def_node->children_[1])); + } + OV (2 == base_schema_node->num_child_); + OV (OB_NOT_NULL(base_object_node = base_schema_node->children_[1])); + + if (OB_SUCC(ret)) { + buf_len = trg_def_node->str_len_ - base_object_node->str_len_ + base_object_name.length() + 3; + buf = static_cast(alloc.alloc(buf_len)); + bool has_delimiter_already = false; + int trg_header_len = (int)base_object_node->str_off_; + const char *trg_tail_str = (trg_def_node->str_value_ + base_object_node->str_off_ + base_object_node->str_len_); + if (is_oracle_mode) { + // '\"' is included in base_object_node->str_value_ in oracle mode, + // but is not included in base_object_node->str_len_ + has_delimiter_already = ('\"' == trg_def_node->str_value_[base_object_node->str_off_]); + } else { + has_delimiter_already = ('`' == trg_def_node->str_value_[base_object_node->str_off_]); + } + if (has_delimiter_already) { + // base object database + if (NULL == base_schema_node->children_[0] && !is_oracle_mode) { + trg_header_len = trg_header_len - 1; + } + trg_tail_str = trg_tail_str + 2; + } + OV (OB_NOT_NULL(buf), OB_ALLOCATE_MEMORY_FAILED); + OZ (BUF_PRINTF(is_oracle_mode ? "%.*s\"%.*s\"%.*s" : "%.*s`%.*s`%.*s", + trg_header_len, + trg_def_node->str_value_, + base_object_name.length(), + base_object_name.ptr(), + int(trg_def_node->str_len_ - (base_object_node->str_off_ + base_object_node->str_len_)), + trg_tail_str)); + OZ (trigger_info.set_trigger_body(ObString(buf))); + } + LOG_INFO("rebuild trigger body end", K(trigger_info), K(base_object_name), K(lbt()), K(ret)); + return ret; +} + } // namespace schema } // namespace share } // namespace oceanbase diff --git a/src/share/schema/ob_trigger_info.h b/src/share/schema/ob_trigger_info.h index e0850fb6d..a67eb96b4 100644 --- a/src/share/schema/ob_trigger_info.h +++ b/src/share/schema/ob_trigger_info.h @@ -421,12 +421,6 @@ public: virtual int deep_copy(const ObTriggerInfo &other); virtual int64_t get_convert_size() const; - static int gen_package_source(const ObTriggerInfo &trigger_info, - const common::ObString &base_object_database, - const common::ObString &base_object_name, - common::ObString &spec_source, - common::ObString &body_source, - common::ObIAllocator &alloc); static int gen_package_source(const uint64_t tenant_id, const uint64_t tg_package_id, common::ObString &source, @@ -442,6 +436,11 @@ public: const ParseNode &parse_node, const ObDataTypeCastParams &dtc_params, ObString &procedure_source); + static int replace_table_name_in_body(ObTriggerInfo &trigger_info, + common::ObIAllocator &alloc, + const common::ObString &base_object_database, + const common::ObString &base_object_name, + bool is_oracle_mode); TO_STRING_KV(K(tenant_id_), K(trigger_id_), K(owner_id_), diff --git a/src/share/schema/ob_trigger_sql_service.cpp b/src/share/schema/ob_trigger_sql_service.cpp index 71b09bc2e..948f66852 100644 --- a/src/share/schema/ob_trigger_sql_service.cpp +++ b/src/share/schema/ob_trigger_sql_service.cpp @@ -144,26 +144,28 @@ int ObTriggerSqlService::rebuild_trigger_package(const ObTriggerInfo &trigger_in ObString spec_source; ObString body_source; ObArenaAllocator inner_alloc; - ObTriggerValues new_values; ObDMLExecHelper exec(sql_client, trigger_info.get_exec_tenant_id()); ObDMLSqlSplicer dml; int64_t affected_rows = 0; + bool is_oracle_mode = false; + ObTriggerInfo new_trigger_info(&inner_alloc); OV (trigger_info.is_valid(), OB_INVALID_ARGUMENT, trigger_info); - OX (new_values.set_database_id(trigger_info.get_database_id())); - OX (new_values.set_trigger_name(trigger_info.get_trigger_name())); - OZ (ObTriggerInfo::gen_package_source(trigger_info, base_object_database, base_object_name, - spec_source, body_source, inner_alloc)); - OX (new_values.set_spec_source(spec_source)); - OX (new_values.set_body_source(body_source)); + OZ (new_trigger_info.deep_copy(trigger_info)); + OZ (ObCompatModeGetter::check_is_oracle_mode_with_table_id(new_trigger_info.get_tenant_id(), + new_trigger_info.get_base_object_id(), + is_oracle_mode)); + OZ (ObTriggerInfo::replace_table_name_in_body(new_trigger_info, inner_alloc, base_object_database, + base_object_name, is_oracle_mode)); + // update all_trigger. - OZ (fill_dml_sql(trigger_info, new_values, new_schema_version, dml)); + OZ (fill_dml_sql(new_trigger_info, new_schema_version, dml)); OZ (exec.exec_update(OB_ALL_TENANT_TRIGGER_TNAME, dml, affected_rows)); OV (is_single_row(affected_rows), OB_ERR_UNEXPECTED, affected_rows); // insert all_trigger_history. OZ (dml.add_column("is_deleted", 0)); OZ (exec.exec_insert(OB_ALL_TENANT_TRIGGER_HISTORY_TNAME, dml, affected_rows)); OV (is_single_row(affected_rows), OB_ERR_UNEXPECTED, affected_rows); - OZ (log_trigger_operation(trigger_info, new_schema_version, + OZ (log_trigger_operation(new_trigger_info, new_schema_version, op_type, NULL, sql_client)); return ret; } diff --git a/src/sql/code_generator/ob_expr_generator_impl.cpp b/src/sql/code_generator/ob_expr_generator_impl.cpp index 2a748b8f0..e146abb07 100644 --- a/src/sql/code_generator/ob_expr_generator_impl.cpp +++ b/src/sql/code_generator/ob_expr_generator_impl.cpp @@ -449,7 +449,7 @@ int ObExprGeneratorImpl::visit(ObPlQueryRefRawExpr &expr) "expr type", get_type_name(expr.get_expr_type())); } else { ObExprOpSubQueryInPl *pl_subquery = static_cast(op); - OX (pl_subquery->set_ps_id(expr.get_ps_id())); + OZ (pl_subquery->deep_copy_ps_sql(expr.get_ps_sql())); OX (pl_subquery->set_stmt_type(expr.get_stmt_type())); OZ (pl_subquery->deep_copy_route_sql(expr.get_route_sql())); OX (pl_subquery->set_result_type(expr.get_subquery_result_type())); diff --git a/src/sql/das/ob_das_utils.cpp b/src/sql/das/ob_das_utils.cpp index 613552504..47ca24169 100644 --- a/src/sql/das/ob_das_utils.cpp +++ b/src/sql/das/ob_das_utils.cpp @@ -62,7 +62,7 @@ int ObDASUtils::store_warning_msg(const ObWarningBuffer &wb, obrpc::ObRpcResultC return ret; } -int ObDASUtils::check_nested_sql_mutating(ObTableID ref_table_id, ObExecContext &exec_ctx) +int ObDASUtils::check_nested_sql_mutating(ObTableID ref_table_id, ObExecContext &exec_ctx, bool is_reading) { int ret = OB_SUCCESS; ObExecContext *cur_parent_ctx = exec_ctx.get_parent_ctx(); @@ -87,7 +87,8 @@ int ObDASUtils::check_nested_sql_mutating(ObTableID ref_table_id, ObExecContext LOG_DEBUG("check nested sql mutating", K(cur_parent_ctx), K(parent_das_ctx), K(ref_table_id)); FOREACH_X(node, parent_das_ctx.get_table_loc_list(), OB_SUCC(ret)) { ObDASTableLoc *table_loc = *node; - if (table_loc->loc_meta_->ref_table_id_ == ref_table_id && table_loc->is_writing_) { + if (table_loc->loc_meta_->ref_table_id_ == ref_table_id + && (table_loc->is_writing_ || (table_loc->is_reading_ && !is_reading && lib::is_mysql_mode()))) { ObSchemaGetterGuard schema_guard; const ObTableSchema *table_schema = NULL; uint64_t tenant_id = exec_ctx.get_my_session()->get_effective_tenant_id(); diff --git a/src/sql/das/ob_das_utils.h b/src/sql/das/ob_das_utils.h index b5f00199a..e45a05067 100644 --- a/src/sql/das/ob_das_utils.h +++ b/src/sql/das/ob_das_utils.h @@ -33,7 +33,9 @@ public: static int get_tablet_loc_by_id(const ObTabletID &tablet_id, ObDASTableLoc &table_loc, ObDASTabletLoc *&tablet_loc); - static int check_nested_sql_mutating(common::ObTableID ref_table_id, ObExecContext &exec_ctx); + static int check_nested_sql_mutating(common::ObTableID ref_table_id, + ObExecContext &exec_ctx, + bool is_reading = false); static ObDASTabletLoc *get_related_tablet_loc(const ObDASTabletLoc &tablet_loc, common::ObTableID related_table_id); static int build_table_loc_meta(common::ObIAllocator &allocator, diff --git a/src/sql/engine/cmd/ob_trigger_executor.cpp b/src/sql/engine/cmd/ob_trigger_executor.cpp index 6f50175e3..79fe4c7b8 100644 --- a/src/sql/engine/cmd/ob_trigger_executor.cpp +++ b/src/sql/engine/cmd/ob_trigger_executor.cpp @@ -18,8 +18,8 @@ #include "share/ob_rpc_struct.h" #include "share/schema/ob_schema_getter_guard.h" #include "pl/ob_pl_package.h" -#include "pl/ob_pl_compile.h" #include "lib/mysqlclient/ob_mysql_proxy.h" +#include "sql/resolver/ddl/ob_trigger_resolver.h" namespace oceanbase { @@ -58,8 +58,11 @@ int ObCreateTriggerExecutor::execute(ObExecContext &ctx, ObCreateTriggerStmt &st ctx.get_sql_proxy(), ctx.get_allocator(), arg)); - if (OB_SUCC(ret) && arg.error_info_.get_error_status() != ERROR_STATUS_NO_ERROR) { - OZ (common_rpc_proxy->create_trigger(arg), common_rpc_proxy->get_server()); + if (OB_SUCC(ret)) { + if (lib::is_oracle_mode() || + (lib::is_mysql_mode() && arg.error_info_.get_error_status() != ERROR_STATUS_NO_ERROR)) { + OZ (common_rpc_proxy->create_trigger(arg), common_rpc_proxy->get_server()); + } } OZ (ctx.get_sql_ctx()->schema_guard_->reset()); return ret; @@ -93,7 +96,9 @@ int ObAlterTriggerExecutor::execute(ObExecContext &ctx, ObAlterTriggerStmt &stmt OV (OB_NOT_NULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx)), OB_NOT_INIT); OZ (task_exec_ctx->get_common_rpc(common_rpc_proxy)); OV (OB_NOT_NULL(common_rpc_proxy)); - OZ (common_rpc_proxy->alter_trigger(arg), common_rpc_proxy->get_server()); + if (OB_SUCC(ret) && !arg.is_alter_compile_) { + OZ (common_rpc_proxy->alter_trigger(arg), common_rpc_proxy->get_server()); + } return ret; } @@ -104,56 +109,32 @@ int ObCreateTriggerExecutor::analyze_dependencies(ObSchemaGetterGuard &schema_gu ObCreateTriggerArg &arg) { int ret = OB_SUCCESS; - uint64_t database_id = session_info->get_database_id(); uint64_t tenant_id = arg.trigger_info_.get_tenant_id(); - const ObString &trigger_name = arg.trigger_info_.get_trigger_name(); + const ObString &trigger_name = arg.trigger_info_.get_trigger_name();\ const ObString &db_name = arg.trigger_database_; const ObTriggerInfo *trigger_info = NULL; - if (OB_FAIL(schema_guard.get_trigger_info(tenant_id, database_id, trigger_name, trigger_info))) { + if (OB_FAIL(schema_guard.get_trigger_info(tenant_id, arg.trigger_info_.get_database_id(), + trigger_name, trigger_info))) { LOG_WARN("failed to get trigger info", K(ret)); - } else if (NULL != trigger_info) { - HEAP_VARS_2((ObPLPackageAST, package_spec_ast, allocator), - (ObPLPackageAST, package_body_ast, allocator)) { - ObPLPackageGuard package_guard(PACKAGE_RESV_HANDLE); - const ObString &pkg_name = trigger_info->get_package_body_info().get_package_name(); - ObPLCompiler compiler(allocator, - *session_info, - schema_guard, - package_guard, - *sql_proxy); - ObPackageInfo package_spec_info = trigger_info->get_package_spec_info(); - OZ (package_spec_ast.init(db_name, - package_spec_info.get_package_name(), - PL_PACKAGE_SPEC, - package_spec_info.get_database_id(), - package_spec_info.get_package_id(), - package_spec_info.get_schema_version(), - NULL)); - OZ (compiler.analyze_package(package_spec_info.get_source(), - NULL, package_spec_ast, true)); - OZ (package_body_ast.init(db_name, - pkg_name, - PL_PACKAGE_BODY, - trigger_info->get_package_body_info().get_database_id(), - trigger_info->get_package_body_info().get_package_id(), - trigger_info->get_package_body_info().get_schema_version(), - &package_spec_ast)); - OZ (compiler.analyze_package(trigger_info->get_package_body_source(), - &(package_spec_ast.get_body()->get_namespace()), - package_body_ast, - true)); - if (OB_FAIL(ret) && ret != OB_ERR_UNEXPECTED) { - LOG_USER_WARN(OB_ERR_TRIGGER_COMPILE_ERROR, "TRIGGER", - db_name.length(), db_name.ptr(), - trigger_name.length(), trigger_name.ptr()); - ObPL::insert_error_msg(ret); - ret = OB_SUCCESS; - } - if (OB_SUCC(ret)) { - arg.trigger_info_.deep_copy(*trigger_info); - arg.error_info_.collect_error_info(&arg.trigger_info_); - arg.for_insert_errors_ = true; - } + } else if (NULL == trigger_info) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("trigger info is null", K(db_name), K(trigger_name), K(ret)); + } else { + if (OB_FAIL(ObTriggerResolver::analyze_trigger(schema_guard, session_info, sql_proxy, + allocator, *trigger_info, db_name, arg.dependency_infos_, false))) { + LOG_WARN("analyze trigger failed", K(trigger_info), K(db_name), K(ret)); + } + if (OB_FAIL(ret) && ret != OB_ERR_UNEXPECTED) { + LOG_USER_WARN(OB_ERR_TRIGGER_COMPILE_ERROR, "TRIGGER", + db_name.length(), db_name.ptr(), + trigger_name.length(), trigger_name.ptr()); + ObPL::insert_error_msg(ret); + ret = OB_SUCCESS; + } + if (OB_SUCC(ret)) { + arg.trigger_info_.deep_copy(*trigger_info); + arg.error_info_.collect_error_info(&arg.trigger_info_); + arg.for_insert_errors_ = true; } } return ret; diff --git a/src/sql/engine/dml/ob_dml_service.cpp b/src/sql/engine/dml/ob_dml_service.cpp index f4c6bf77c..047a41a0f 100644 --- a/src/sql/engine/dml/ob_dml_service.cpp +++ b/src/sql/engine/dml/ob_dml_service.cpp @@ -1058,10 +1058,15 @@ int ObDMLService::init_ins_rtdef( int ret = OB_SUCCESS; dml_rtctx.get_exec_ctx().set_dml_event(ObDmlEventType::DE_INSERTING); const ObDASTableLocMeta *loc_meta = get_table_loc_meta(ins_ctdef.multi_ctdef_); - if (OB_FAIL(init_das_dml_rtdef(dml_rtctx, - ins_ctdef.das_ctdef_, - ins_rtdef.das_rtdef_, - loc_meta))) { + if (lib::is_mysql_mode() + && OB_FAIL(ObDASUtils::check_nested_sql_mutating(ins_ctdef.das_ctdef_.index_tid_, dml_rtctx.get_exec_ctx()))) { + // MySql returns error, trigger the insert statement through udf, + // even if there is no data that meets the where condition which in insert-select + LOG_WARN("failed to check stmt table", K(ret), K(ins_ctdef.das_ctdef_.index_tid_)); + } else if (OB_FAIL(init_das_dml_rtdef(dml_rtctx, + ins_ctdef.das_ctdef_, + ins_rtdef.das_rtdef_, + loc_meta))) { LOG_WARN("failed to init das dml rtdef", K(ret)); } else if (OB_FAIL(init_related_das_rtdef(dml_rtctx, ins_ctdef.related_ctdefs_, ins_rtdef.related_rtdefs_))) { LOG_WARN("init related das ctdef failed", K(ret)); @@ -1094,10 +1099,15 @@ int ObDMLService::init_del_rtdef(ObDMLRtCtx &dml_rtctx, int ret = OB_SUCCESS; dml_rtctx.get_exec_ctx().set_dml_event(ObDmlEventType::DE_DELETING); const ObDASTableLocMeta *loc_meta = get_table_loc_meta(del_ctdef.multi_ctdef_); - if (OB_FAIL(init_das_dml_rtdef(dml_rtctx, - del_ctdef.das_ctdef_, - del_rtdef.das_rtdef_, - loc_meta))) { + if (lib::is_mysql_mode() + && OB_FAIL(ObDASUtils::check_nested_sql_mutating(del_ctdef.das_ctdef_.index_tid_, dml_rtctx.get_exec_ctx()))) { + // MySql returns error, trigger the delete statement through udf, + // even if there is no data that meets the where condition + LOG_WARN("failed to check stmt table", K(ret), K(del_ctdef.das_ctdef_.index_tid_)); + } else if (OB_FAIL(init_das_dml_rtdef(dml_rtctx, + del_ctdef.das_ctdef_, + del_rtdef.das_rtdef_, + loc_meta))) { LOG_WARN("failed to init das dml rfdef", K(ret)); } else if (OB_FAIL(init_related_das_rtdef(dml_rtctx, del_ctdef.related_ctdefs_, del_rtdef.related_rtdefs_))) { LOG_WARN("init related das ctdef failed", K(ret)); @@ -1182,10 +1192,15 @@ int ObDMLService::init_upd_rtdef( int ret = OB_SUCCESS; const ObDASTableLocMeta *loc_meta = get_table_loc_meta(upd_ctdef.multi_ctdef_); dml_rtctx.get_exec_ctx().set_dml_event(ObDmlEventType::DE_UPDATING); - if (OB_FAIL(init_das_dml_rtdef(dml_rtctx, - upd_ctdef.dupd_ctdef_, - upd_rtdef.dupd_rtdef_, - loc_meta))) { + if (lib::is_mysql_mode() + && OB_FAIL(ObDASUtils::check_nested_sql_mutating(upd_ctdef.dupd_ctdef_.index_tid_, dml_rtctx.get_exec_ctx()))) { + // MySql returns error, trigger the update statement through udf, + // even if there is no data that meets the where condition + LOG_WARN("failed to check stmt table", K(ret), K(upd_ctdef.dupd_ctdef_.index_tid_)); + } else if (OB_FAIL(init_das_dml_rtdef(dml_rtctx, + upd_ctdef.dupd_ctdef_, + upd_rtdef.dupd_rtdef_, + loc_meta))) { LOG_WARN("failed to init das dml rfdef", K(ret)); } else if (OB_FAIL(init_related_das_rtdef(dml_rtctx, upd_ctdef.related_upd_ctdefs_, upd_rtdef.related_upd_rtdefs_))) { LOG_WARN("init related das ctdef failed", K(ret)); diff --git a/src/sql/engine/expr/ob_expr_statement_digest.cpp b/src/sql/engine/expr/ob_expr_statement_digest.cpp index f0afe0468..49ace5846 100644 --- a/src/sql/engine/expr/ob_expr_statement_digest.cpp +++ b/src/sql/engine/expr/ob_expr_statement_digest.cpp @@ -44,7 +44,7 @@ int calc_digest_text(ObIAllocator &allocator, ObSqlCtx sql_ctx; sql_ctx.session_info_ = session; sql_ctx.schema_guard_ = schema_guard; - ObPlanCacheCtx pc_ctx(sql_str, false, allocator, sql_ctx, exec_ctx, + ObPlanCacheCtx pc_ctx(sql_str, PC_TEXT_MODE, allocator, sql_ctx, exec_ctx, session->get_effective_tenant_id()); ObParser parser(allocator, session->get_sql_mode(), cs_type); ParseResult parse_result; diff --git a/src/sql/engine/expr/ob_pl_expr_subquery.cpp b/src/sql/engine/expr/ob_pl_expr_subquery.cpp index 134ef330d..2a2418fa2 100644 --- a/src/sql/engine/expr/ob_pl_expr_subquery.cpp +++ b/src/sql/engine/expr/ob_pl_expr_subquery.cpp @@ -30,7 +30,7 @@ namespace sql OB_SERIALIZE_MEMBER( (ObExprOpSubQueryInPl, ObFuncExprOperator), - id_, type_, route_sql_, result_type_, is_ignore_fail_); + id_, type_, route_sql_, result_type_, is_ignore_fail_, ps_sql_); ObExprOpSubQueryInPl::ObExprOpSubQueryInPl(common::ObIAllocator &alloc) @@ -38,6 +38,7 @@ ObExprOpSubQueryInPl::ObExprOpSubQueryInPl(common::ObIAllocator &alloc) alloc, T_FUN_SUBQUERY, N_PL_SUBQUERY_CONSTRUCT, PARAM_NUM_UNKNOWN, NOT_ROW_DIMENSION, INTERNAL_IN_MYSQL_MODE), id_(common::OB_INVALID_ID), + ps_sql_(ObString()), type_(stmt::T_NONE), route_sql_(ObString()), result_type_(), @@ -57,7 +58,7 @@ int ObExprOpSubQueryInPl::assign(const ObExprOperator &other) if (OB_FAIL(ObExprOperator::assign(other))) { LOG_WARN("copy in Base class ObExprOperator failed", K(other), K(ret)); } else { - OX (this->id_ = tmp_other->id_); + OZ (deep_copy_ps_sql(tmp_other->ps_sql_)); OX (this->type_ = tmp_other->type_); OX (this->result_type_ = tmp_other->result_type_); OZ (deep_copy_route_sql(tmp_other->route_sql_)); @@ -124,17 +125,21 @@ int ObExprOpSubQueryInPl::eval_subquery(const ObExpr &expr, CK(OB_NOT_NULL(session = ctx.exec_ctx_.get_my_session())); CK (OB_NOT_NULL(ctx.exec_ctx_.get_sql_ctx())); - share::schema::ObSchemaGetterGuard schema_guard; observer::ObQueryRetryCtrl retry_ctrl; int64_t tenant_version = 0; int64_t sys_version = 0; bool is_stack_overflow = false; + if (info->id_ != common::OB_INVALID_ID) { + ret = OB_NOT_SUPPORTED; + LOG_USER_ERROR(OB_NOT_SUPPORTED, "observer version need upate to 4.1 ver"); + } + OZ(check_stack_overflow(is_stack_overflow)); if (OB_SUCC(ret) && is_stack_overflow) { ret = OB_SIZE_OVERFLOW; LOG_WARN("too deep recursive", - K(ret), K(is_stack_overflow), K(info->id_), K(info->type_)); + K(ret), K(is_stack_overflow), K(info->ps_sql_), K(info->type_)); } if (OB_FAIL(ret)) { @@ -152,67 +157,66 @@ int ObExprOpSubQueryInPl::eval_subquery(const ObExpr &expr, pl::ObPLExecCtx pl_exec_ctx(&alloc, &ctx.exec_ctx_, params, nullptr, &ret, nullptr); SMART_VAR(ObSPIResultSet, spi_result) { + OZ (spi_result.init(*session)); OZ (spi_result.start_nested_stmt_if_need(&pl_exec_ctx, static_cast(info->type_))); if (OB_SUCC(ret)) { - ObMySQLProxy::MySQLResult &mysql_result = spi_result.get_mysql_result(); ObSPIOutParams out_params; int64_t old_query_start_time = session->get_query_start_time(); session->set_query_start_time(ObTimeUtility::current_time()); - + bool is_retry = false; do { + if (is_retry) { + out_params.reset(); + spi_result.reset_member_for_retry(*session); + } retry_ctrl.clear_state_before_each_retry(session->get_retry_info_for_update()); if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(session->get_effective_tenant_id(), - schema_guard))) { + spi_result.get_scheme_guard()))) { LOG_WARN("get schema guard failed", K(ret)); - } else if (OB_FAIL(schema_guard.get_schema_version(session->get_effective_tenant_id(), + } else if (OB_FAIL(spi_result.get_scheme_guard().get_schema_version(session->get_effective_tenant_id(), tenant_version))) { LOG_WARN("fail get schema version", K(ret)); - } else if (OB_FAIL(schema_guard.get_schema_version(OB_SYS_TENANT_ID, sys_version))) { + } else if (OB_FAIL(spi_result.get_scheme_guard().get_schema_version(OB_SYS_TENANT_ID, sys_version))) { LOG_WARN("fail get sys schema version", K(ret)); } else { retry_ctrl.set_tenant_local_schema_version(tenant_version); retry_ctrl.set_sys_local_schema_version(sys_version); - - mysql_result.reset(); - + spi_result.get_sql_ctx().schema_guard_ = &spi_result.get_scheme_guard(); OZ (ObSPIService::inner_open(&pl_exec_ctx, expr.arg_cnt_ == 0 ? info->route_sql_.ptr() : nullptr, - info->id_, + info->ps_sql_.ptr(), info->type_, *params, - mysql_result, + spi_result, out_params)); - observer::ObInnerSQLResult *result_set = - static_cast(mysql_result.get_result()); if (OB_FAIL(ret)) { LOG_WARN("inner open error", K(ret)); - } else if (OB_FAIL(get_result(result_set, result, alloc))) { + } else if (OB_FAIL(get_result(spi_result.get_result_set(), result, alloc))) { if (OB_ERR_TOO_MANY_ROWS != ret) { int cli_ret = OB_SUCCESS; retry_ctrl.test_and_save_retry_state(GCTX, *ctx.exec_ctx_.get_sql_ctx(), - result_set->result_set(), - ret, cli_ret, true); + *spi_result.get_result_set(), + ret, cli_ret, true, true, true); ret = cli_ret; } } session->set_session_in_retry(retry_ctrl.need_retry()); - int64_t close_ret = mysql_result.close(); + int64_t close_ret = spi_result.get_result_set()->close(); if (OB_SUCCESS != close_ret) { LOG_WARN("close spi result failed", K(ret), K(close_ret)); } ret = OB_SUCCESS == ret ? close_ret : ret; } - + is_retry = true; } while (observer::RETRY_TYPE_NONE != retry_ctrl.get_retry_type()); session->get_retry_info_for_update().clear(); session->set_query_start_time(old_query_start_time); } - spi_result.get_mysql_result().reset(); spi_result.end_nested_stmt_if_need(&pl_exec_ctx, ret); } } @@ -280,15 +284,12 @@ int ObExprOpSubQueryInPl::fetch_row(void *result_set, int64_t &row_count, ObNewR ret = OB_INVALID_ARGUMENT; LOG_WARN("Argument passed in is NULL", K(result_set), K(ret)); } else { - observer::ObInnerSQLResult *inner_result = - static_cast(result_set); - if (OB_FAIL(inner_result->next())) { + ObResultSet *ob_result_set = static_cast(result_set); + const ObNewRow *row = NULL; + if (OB_FAIL(ob_result_set->get_next_row(row))) { //上层判断返回值,这里不打印信息 - } else if (OB_ISNULL(inner_result->get_row())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get a invalid row", K(ret)); } else { - cur_row = *inner_result->get_row(); + cur_row = *row; ++row_count; } } @@ -336,7 +337,8 @@ OB_DEF_SERIALIZE(ObExprPlSubQueryInfo) type_, route_sql_, result_type_, - is_ignore_fail_); + is_ignore_fail_, + ps_sql_); return ret; } @@ -348,7 +350,8 @@ OB_DEF_DESERIALIZE(ObExprPlSubQueryInfo) type_, route_sql_, result_type_, - is_ignore_fail_); + is_ignore_fail_, + ps_sql_); return ret; } @@ -360,7 +363,8 @@ OB_DEF_SERIALIZE_SIZE(ObExprPlSubQueryInfo) type_, route_sql_, result_type_, - is_ignore_fail_); + is_ignore_fail_, + ps_sql_); return len; } @@ -371,13 +375,12 @@ int ObExprPlSubQueryInfo::deep_copy(common::ObIAllocator &allocator, int ret = common::OB_SUCCESS; OZ(ObExprExtraInfoFactory::alloc(allocator, type, copied_info)); ObExprPlSubQueryInfo &other = *static_cast(copied_info); - other.id_ = id_; other.type_ = type_; other.result_type_ = result_type_; other.is_ignore_fail_ = is_ignore_fail_; OZ(ob_write_string(allocator, route_sql_, other.route_sql_, true)); - + OZ(ob_write_string(allocator, ps_sql_, other.ps_sql_, true)); return ret; } @@ -388,12 +391,13 @@ int ObExprPlSubQueryInfo::from_raw_expr(RE &raw_expr, ObIAllocator &alloc) ObPlQueryRefRawExpr &subquery_expr = const_cast (static_cast(raw_expr)); - id_ = subquery_expr.get_ps_id(); + id_ = common::OB_INVALID_ID; type_ = subquery_expr.get_stmt_type(); result_type_ = subquery_expr.get_result_type(); is_ignore_fail_ = subquery_expr.is_ignore_fail(); OZ(ob_write_string(alloc, subquery_expr.get_route_sql(), route_sql_, true)); + OZ(ob_write_string(alloc, subquery_expr.get_route_sql(), ps_sql_, true)); return ret; } diff --git a/src/sql/engine/expr/ob_pl_expr_subquery.h b/src/sql/engine/expr/ob_pl_expr_subquery.h index a0c35b9c9..73521eded 100644 --- a/src/sql/engine/expr/ob_pl_expr_subquery.h +++ b/src/sql/engine/expr/ob_pl_expr_subquery.h @@ -30,6 +30,7 @@ public: ObExprPlSubQueryInfo(common::ObIAllocator &alloc, ObExprOperatorType type) : ObIExprExtraInfo(alloc, type), id_(common::OB_INVALID_ID), + ps_sql_(ObString()), type_(stmt::T_NONE), route_sql_(ObString()), result_type_(), @@ -42,7 +43,8 @@ public: template int from_raw_expr(RE &expr, ObIAllocator &alloc); - ObPsStmtId id_; //prepare的语句id + ObPsStmtId id_; //prepare的语句id, 保留id,兼容老版本 + common::ObString ps_sql_; stmt::StmtType type_; //prepare的语句类型 common::ObString route_sql_; @@ -73,8 +75,12 @@ public: { return ob_write_string(allocator_, v, route_sql_); } + int deep_copy_ps_sql(const common::ObString &v) + { + return ob_write_string(allocator_, v, ps_sql_); + } - inline void set_ps_id(ObPsStmtId id) { id_ = id; } + inline void set_ps_sql(common::ObString sql) { ps_sql_ = sql; } inline void set_stmt_type(stmt::StmtType type) { type_ = type; } inline void set_route_sql(common::ObString sql) { route_sql_ = sql; } inline void set_result_type(ObExprResType type) { result_type_ = type; } @@ -92,6 +98,7 @@ private: static int get_result(void *result_set, ObObj &result, ObIAllocator &alloc); ObPsStmtId id_; //prepare的语句id + common::ObString ps_sql_; stmt::StmtType type_; //prepare的语句类型 common::ObString route_sql_; diff --git a/src/sql/engine/ob_physical_plan.cpp b/src/sql/engine/ob_physical_plan.cpp index 1b28f5f90..80de8dd41 100644 --- a/src/sql/engine/ob_physical_plan.cpp +++ b/src/sql/engine/ob_physical_plan.cpp @@ -1076,7 +1076,7 @@ int ObPhysicalPlan::update_cache_obj_stat(ObILibCacheCtx &ctx) stat_.slow_count_ = 0; stat_.slowest_exec_time_ = 0; stat_.slowest_exec_usec_ = 0; - if (pc_ctx.is_ps_mode_) { + if (PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) { ObTruncatedString trunc_stmt(pc_ctx.raw_sql_, OB_MAX_SQL_LENGTH); if (OB_FAIL(ob_write_string(get_allocator(), trunc_stmt.string(), diff --git a/src/sql/engine/table/ob_table_scan_op.cpp b/src/sql/engine/table/ob_table_scan_op.cpp index 831bc47c2..496aae8c1 100644 --- a/src/sql/engine/table/ob_table_scan_op.cpp +++ b/src/sql/engine/table/ob_table_scan_op.cpp @@ -1202,7 +1202,7 @@ int ObTableScanOp::inner_open() if (OB_ISNULL(my_session = GET_MY_SESSION(ctx_))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to get my session", K(ret)); - } else if (OB_FAIL(ObDASUtils::check_nested_sql_mutating(MY_SPEC.ref_table_id_, ctx_))) { + } else if (OB_FAIL(ObDASUtils::check_nested_sql_mutating(MY_SPEC.ref_table_id_, ctx_, true))) { LOG_WARN("failed to check stmt table", K(ret), K(MY_SPEC.ref_table_id_)); } else if (OB_FAIL(init_table_scan_rtdef())) { LOG_WARN("prepare scan param failed", K(ret)); diff --git a/src/sql/ob_result_set.cpp b/src/sql/ob_result_set.cpp index 17b0f5baf..1c1f0554e 100644 --- a/src/sql/ob_result_set.cpp +++ b/src/sql/ob_result_set.cpp @@ -77,6 +77,7 @@ ObResultSet::~ObResultSet() } // Always called at the end of the ObResultSet destructor update_end_time(); + is_init_ = false; } int ObResultSet::open_cmd() @@ -920,7 +921,7 @@ int ObResultSet::from_plan(const ObPhysicalPlan &phy_plan, const ObIArrayset_field_columns(field_columns_))) { LOG_WARN("Failed to copy field info to plan", K(ret)); - } else if (is_ps_mode && OB_FAIL(phy_plan->set_param_fields(param_columns_))) { + } else if ((PC_PS_MODE == mode || PC_PL_MODE == mode) + && OB_FAIL(phy_plan->set_param_fields(param_columns_))) { // param fields is only needed ps mode LOG_WARN("failed to copy param field to plan", K(ret)); - } else if (is_ps_mode && OB_FAIL(phy_plan->set_returning_param_fields(returning_param_columns_))) { + } else if ((PC_PS_MODE == mode || PC_PL_MODE == mode) + && OB_FAIL(phy_plan->set_returning_param_fields(returning_param_columns_))) { // returning param fields is only needed ps mode LOG_WARN("failed to copy returning param field to plan", K(ret)); } diff --git a/src/sql/ob_result_set.h b/src/sql/ob_result_set.h index 5e6c74637..ebfb3e172 100644 --- a/src/sql/ob_result_set.h +++ b/src/sql/ob_result_set.h @@ -184,6 +184,8 @@ public: stmt::StmtType get_stmt_type() const; stmt::StmtType get_inner_stmt_type() const; stmt::StmtType get_literal_stmt_type() const; + const common::ObString& get_stmt_ps_sql() const { return ps_sql_; } + common::ObString& get_stmt_ps_sql() { return ps_sql_; } int64_t get_query_string_id() const; static void refresh_location_cache(ObTaskExecutorCtx &task_exec_ctx, bool is_nonblock, int err); int refresh_location_cache(bool is_nonblock); @@ -198,8 +200,10 @@ public: if (0 < my_session_.get_pl_exact_err_msg().length()) { my_session_.get_pl_exact_err_msg().reset(); } + is_init_ = true; return common::OB_SUCCESS; } + bool is_inited() const { return is_init_; } common::ObIAllocator& get_mem_pool() { return mem_pool_; } ObExecContext &get_exec_context() { return exec_ctx_ != nullptr ? *exec_ctx_ : *inner_exec_ctx_; } void set_exec_context(ObExecContext &exec_ctx) { exec_ctx_ = &exec_ctx; } @@ -213,7 +217,7 @@ public: int add_returning_param_column(const common::ObField ¶m); int from_plan(const ObPhysicalPlan &phy_plan, const common::ObIArray &raw_params); - int to_plan(const bool is_ps_mode, ObPhysicalPlan *phy_plan); + int to_plan(const PlanCacheMode mode, ObPhysicalPlan *phy_plan); const common::ObString &get_statement_name() const; void set_statement_id(const uint64_t stmt_id); void set_statement_name(const common::ObString name); @@ -420,6 +424,8 @@ private: bool is_returning_; bool is_com_filed_list_; //used to mark COM_FIELD_LIST common::ObString wild_str_;//uesd to save filed wildcard in COM_FIELD_LIST; + common::ObString ps_sql_; // for sql in pl + bool is_init_; }; @@ -490,7 +496,9 @@ inline ObResultSet::ObResultSet(ObSQLSessionInfo &session, common::ObIAllocator executor_(), is_returning_(false), is_com_filed_list_(false), - wild_str_() + wild_str_(), + ps_sql_(), + is_init_(false) { message_[0] = '\0'; // Always called in the ObResultSet constructor diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index 02cf9dfd4..c16bf88d5 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -12,6 +12,7 @@ #define USING_LOG_PREFIX SQL #include "ob_spi.h" +#include "ob_sql.h" #include "common/sql_mode/ob_sql_mode_utils.h" #include "ob_sql_utils.h" #include "observer/ob_inner_sql_connection_pool.h" @@ -83,11 +84,54 @@ namespace sql } \ } while (0) -ObResultSet *ObSPIResultSet::get_result_set() +int ObSPIService::PLPrepareResult::init(sql::ObSQLSessionInfo &session_info) { - return NULL == mysql_result_.get_result() - ? NULL : &reinterpret_cast(mysql_result_.get_result()) - ->result_set(); + int ret = OB_SUCCESS; + lib::ContextParam param; + param.set_mem_attr(session_info.get_effective_tenant_id(), + ObModIds::OB_PL_TEMP, + ObCtxIds::DEFAULT_CTX_ID) + .set_properties(lib::USE_TL_PAGE_OPTIONAL) + .set_page_size(OB_MALLOC_MIDDLE_BLOCK_SIZE) + .set_ablock_size(lib::INTACT_MIDDLE_AOBJECT_SIZE); + if (OB_FAIL(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context_, param))) { + LOG_WARN("create memory entity failed", K(ret)); + } else { + result_set_ = new (buf_) ObResultSet(session_info, mem_context_->get_arena_allocator()); + } + return ret; +} + +int ObSPIResultSet::init(sql::ObSQLSessionInfo &session_info) +{ + int ret = OB_SUCCESS; + lib::ContextParam param; + param.set_mem_attr(session_info.get_effective_tenant_id(), + ObModIds::OB_RESULT_SET, + ObCtxIds::DEFAULT_CTX_ID) + .set_properties(lib::USE_TL_PAGE_OPTIONAL) + .set_page_size(OB_MALLOC_MIDDLE_BLOCK_SIZE) + .set_ablock_size(lib::INTACT_MIDDLE_AOBJECT_SIZE); + if (OB_FAIL(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context_, param))) { + LOG_WARN("create memory entity failed", K(ret)); + } else { + result_set_ = new (buf_) ObResultSet(session_info, mem_context_->get_arena_allocator()); + is_inited_ = true; + } + return ret; +} + +int ObSPIResultSet::close_result_set() +{ + int ret = OB_SUCCESS; + if (is_inited_) { + WITH_CONTEXT(mem_context_) { + ret = result_set_->close(); + } + } else { + LOG_INFO("result set is not init", K(ret)); + } + return ret; } int ObSPIResultSet::destruct_exec_params(ObSQLSessionInfo &session) @@ -294,10 +338,10 @@ void ObSPIResultSet::end_cursor_stmt(ObPLExecCtx *pl_ctx, int &result) CK (OB_NOT_NULL(session = pl_ctx->exec_ctx_->get_my_session())); OZ (reset_cursor_env(*session)); if (OB_SUCC(ret) - && OB_NOT_NULL(get_mysql_result().get_result()) + && OB_NOT_NULL(get_result_set()) && get_out_params().has_out_param()) { OZ (ObSPIService::process_function_out_result( - pl_ctx, get_mysql_result(), get_out_params().get_out_params())); + pl_ctx, *get_result_set(), get_out_params().get_out_params())); } if (OB_FAIL(ret)) { result = OB_SUCCESS == result ? ret : result; @@ -365,6 +409,7 @@ void ObSPIResultSet::end_nested_stmt_if_need(ObPLExecCtx *pl_ctx, int &result) return; } + bool ObSPIService::can_obj_access_expr_fast_calc(const ObSqlExpression &expr, const ObExprObjAccess *&obj_access) { @@ -1228,9 +1273,10 @@ public: }; +//todo:@hr351303 确认sql 和 ps sql是否可以合一 int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, const char *sql, - uint64_t id, + const char *ps_sql, int64_t type, const ObSqlExpression **param_exprs, int64_t param_count, @@ -1268,7 +1314,7 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, HEAP_VAR(ObSPIResultSet, spi_result) { stmt::StmtType stmt_type = stmt::T_NONE; bool is_diagnostics_stmt = false; - + OZ (spi_result.init(*session)); OZ (spi_result.start_nested_stmt_if_need(ctx, static_cast(type))); if (OB_SUCC(ret)) { @@ -1276,12 +1322,13 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, ObQueryRetryCtrl retry_ctrl; int64_t tenant_version = 0; int64_t sys_version = 0; - share::schema::ObSchemaGetterGuard schema_guard; + ObSPIOutParams out_params; int64_t old_query_start_time = session->get_query_start_time(); HEAP_VAR(ObPLSqlCodeInfo, saved_sqlcode_info) { session->set_query_start_time(ObTimeUtility::current_time()); saved_sqlcode_info = *(ctx->exec_ctx_->get_my_session()->get_pl_sqlcode_info()); + bool is_retry = false; do { // SQL_AUDIT_START ObWaitEventDesc max_wait_desc; @@ -1301,35 +1348,39 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, wb->reset(); } row_count = 0; - spi_result.get_mysql_result().reset(); out_params.reset(); + if (is_retry) { + spi_result.reset_member_for_retry(*session); + } retry_ctrl.clear_state_before_each_retry(session->get_retry_info_for_update()); - if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(session->get_effective_tenant_id(), schema_guard))) { + if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(session->get_effective_tenant_id(), spi_result.get_scheme_guard()))) { LOG_WARN("get schema guard failed", K(ret)); - } else if (OB_FAIL(schema_guard.get_schema_version(session->get_effective_tenant_id(), tenant_version))) { + } else if (OB_FAIL(spi_result.get_scheme_guard().get_schema_version(session->get_effective_tenant_id(), tenant_version))) { LOG_WARN("fail get schema version", K(ret)); - } else if (OB_FAIL(schema_guard.get_schema_version(OB_SYS_TENANT_ID, sys_version))) { + } else if (OB_FAIL(spi_result.get_scheme_guard().get_schema_version(OB_SYS_TENANT_ID, sys_version))) { LOG_WARN("fail get sys schema version", K(ret)); } else { retry_ctrl.set_tenant_local_schema_version(tenant_version); retry_ctrl.set_sys_local_schema_version(sys_version); + spi_result.get_sql_ctx().schema_guard_ = &spi_result.get_scheme_guard(); ObArenaAllocator allocator; if (OB_FAIL(inner_open(ctx, allocator, sql, - id, + ps_sql, type, param_exprs, param_count, into_exprs, into_count, - spi_result.get_mysql_result(), + spi_result, out_params, + &retry_ctrl, is_forall))) { - LOG_WARN("failed to open", K(id), K(type), K(ret)); + LOG_WARN("failed to open", K(type), K(ret)); } else if (OB_FAIL(inner_fetch(ctx, retry_ctrl, - spi_result.get_mysql_result().get_result(), + spi_result, into_exprs, into_count, column_types, @@ -1340,21 +1391,18 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, row_count, is_bulk, is_forall))) { - LOG_WARN("failed to execute inner_fetch for pl/sql", K(ret), K(id), K(sql), K(type)); + LOG_WARN("failed to execute inner_fetch for pl/sql", K(ret), K(ps_sql), K(sql), K(type)); } else if (out_params.has_out_param()) { OZ (process_function_out_result( - ctx, spi_result.get_mysql_result(), out_params.get_out_params()), out_params); + ctx, *spi_result.get_result_set(), out_params.get_out_params()), out_params); } if (OB_SUCC(ret)) { // 如果成功记录下stmttype,用于DDL语句的schema刷新 - ObInnerSQLResult *inner_result = static_cast(spi_result.get_mysql_result().get_result()); - CK (OB_NOT_NULL(inner_result)); - CK (OB_NOT_NULL(inner_result->get_result_set())); - OX (stmt_type = inner_result->result_set().get_stmt_type()); - OX (is_diagnostics_stmt = ObStmt::is_diagnostic_stmt(inner_result->result_set().get_literal_stmt_type())); + OX (stmt_type = spi_result.get_result_set()->get_stmt_type()); + OX (is_diagnostics_stmt = ObStmt::is_diagnostic_stmt(spi_result.get_result_set()->get_literal_stmt_type())); } // 无论成功或者失败都在这里close result set // 原因是close函数里面会设置audit的sched info信息, audit会在ObInnerSQLConnection::process_record中处理audit信息 - int close_ret = spi_result.get_mysql_result().close(); + int close_ret = spi_result.close_result_set(); if (OB_SUCCESS != close_ret) { LOG_WARN("close spi result failed", K(ret), K(close_ret)); } @@ -1372,43 +1420,45 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, exec_record.record_end(); } } - LOG_DEBUG("start process record", K(ret), K(id), K(sql), K(type), K(enable_sql_audit)); + LOG_DEBUG("start process record", K(ret), K(ps_sql), K(sql), K(type), K(enable_sql_audit)); // 处理监控统计项 if (enable_sql_audit) { - observer::ObInnerSQLResult* result_set = static_cast(spi_result.get_mysql_result().get_result()); - if (OB_NOT_NULL(result_set) && OB_NOT_NULL(result_set->get_result_set())) { - if (result_set->is_inited()) { + if (OB_NOT_NULL(spi_result.get_result_set())) { + if (spi_result.get_result_set()->is_inited()) { ObSQLSessionInfo *session_info = ctx->exec_ctx_->get_my_session(); int64_t try_cnt = session_info->get_raw_audit_record().try_cnt_; ObExecRecord record_bk = session_info->get_raw_audit_record().exec_record_; session_info->get_raw_audit_record().try_cnt_ = retry_ctrl.get_retry_times(); - ObInnerSQLConnection::process_record(*(result_set), - *(ctx->exec_ctx_->get_my_session()), - time_record, - ret, - ctx->exec_ctx_->get_my_session()->get_current_execution_id(), // sql execute id - id, // ps stmt id - ctx->func_->get_object_id(), // routine id - max_wait_desc, - total_wait_desc, - exec_record, - exec_timestamp, - true); + ObInnerSQLConnection::process_record(*spi_result.get_result_set(), + spi_result.get_sql_ctx(), + *(ctx->exec_ctx_->get_my_session()), + time_record, + ret, + ctx->exec_ctx_->get_my_session()->get_current_execution_id(), // sql execute id + OB_INVALID_ID, + max_wait_desc, + total_wait_desc, + exec_record, + exec_timestamp, + true, + sql != NULL ? sql : ps_sql, + true); session_info->get_raw_audit_record().exec_record_ = record_bk; session_info->get_raw_audit_record().try_cnt_ = try_cnt; } else { LOG_DEBUG("result set is not inited, do not process record", - K(ret), K(id), K(sql), K(type)); + K(ret), K(ps_sql), K(sql), K(type)); } } else { if (OB_SUCC(ret)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected error, result_set is null", K(ret), K(id), K(sql), K(type)); + LOG_WARN("unexpected error, result_set is null", K(ret), K(ps_sql), K(sql), K(type)); } else { - LOG_WARN("result_set is null", K(ret), K(id), K(sql), K(type)); + LOG_WARN("result_set is null", K(ret), K(ps_sql), K(sql), K(type)); } } } + is_retry = true; } while (RETRY_TYPE_NONE != retry_ctrl.get_retry_type()); //SPI只做LOCAL重试 } session->get_retry_info_for_update().clear(); @@ -1431,16 +1481,11 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, } // 记录第一条SQL执行PartitionHit信息, 并对PartitionHit进行Freeze, 防止后续的SQL冲掉 if (OB_SUCC(ret)) { - ObInnerSQLResult *inner_result - = static_cast(spi_result.get_mysql_result().get_result()); - if (OB_NOT_NULL(inner_result) - && OB_NOT_NULL(inner_result->get_result_set()) - && OB_NOT_NULL(inner_result->result_set().get_physical_plan())) { + if (OB_NOT_NULL(spi_result.get_result_set()->get_physical_plan())) { session->partition_hit().freeze(); } } - spi_result.get_mysql_result().reset(); spi_result.end_nested_stmt_if_need(ctx, ret); if (OB_FAIL(ret) && !is_diagnostics_stmt) { // support `SHOW WARNINGS` in mysql PL @@ -1457,7 +1502,7 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, * 所以暂时还不方便将两个接口整理重构为一个接口,计划在dbms_sql支持读流程接口和returning语句后再重构。 */ int ObSPIService::dbms_cursor_execute(ObPLExecCtx *ctx, - uint64_t stmt_id, + const ObString ps_sql, stmt::StmtType stmt_type, ObDbmsCursorInfo &cursor) { @@ -1480,18 +1525,19 @@ int ObSPIService::dbms_cursor_execute(ObPLExecCtx *ctx, exec_timestamp.exec_type_ = sql::PLSql; HEAP_VAR(ObSPIResultSet, spi_result) { + OZ (spi_result.init(*session)); OZ (spi_result.start_nested_stmt_if_need(ctx, static_cast(stmt_type))); if (OB_SUCC(ret)) { int64_t row_count = 0; ObQueryRetryCtrl retry_ctrl; int64_t tenant_version = 0; int64_t sys_version = 0; - share::schema::ObSchemaGetterGuard schema_guard; ObSPIOutParams out_params; ObPLSqlCodeInfo saved_sqlcode_info; uint64_t eff_tenant_id = session->get_effective_tenant_id(); int64_t old_query_start_time = session->get_query_start_time(); session->set_query_start_time(ObTimeUtility::current_time()); + bool is_retry = false; do { // SQL_AUDIT_START ObWaitEventDesc max_wait_desc; @@ -1509,27 +1555,43 @@ int ObSPIService::dbms_cursor_execute(ObPLExecCtx *ctx, saved_sqlcode_info = *(session->get_pl_sqlcode_info()); session->get_pl_sqlcode_info()->set_sqlcode(OB_SUCCESS); row_count = 0; - spi_result.get_mysql_result().reset(); out_params.reset(); + if (is_retry) { + spi_result.reset_member_for_retry(*session); + } retry_ctrl.clear_state_before_each_retry(session->get_retry_info_for_update()); - if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(eff_tenant_id, schema_guard))) { + if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(eff_tenant_id, spi_result.get_scheme_guard()))) { LOG_WARN("get schema guard failed", K(ret)); - } else if (OB_FAIL(schema_guard.get_schema_version(eff_tenant_id, tenant_version))) { + } else if (OB_FAIL(spi_result.get_scheme_guard().get_schema_version(eff_tenant_id, tenant_version))) { LOG_WARN("fail get schema version", K(ret)); - } else if (OB_FAIL(schema_guard.get_schema_version(OB_SYS_TENANT_ID, sys_version))) { + } else if (OB_FAIL(spi_result.get_scheme_guard().get_schema_version(OB_SYS_TENANT_ID, sys_version))) { LOG_WARN("fail get sys schema version", K(ret)); } else { retry_ctrl.set_tenant_local_schema_version(tenant_version); retry_ctrl.set_sys_local_schema_version(sys_version); + spi_result.get_sql_ctx().schema_guard_ = &spi_result.get_scheme_guard(); if (OB_FAIL(inner_open(ctx, exec_params.count() > 0 ? NULL : sql_stmt.ptr(), - stmt_id, + ps_sql, stmt_type, exec_params, - spi_result.get_mysql_result(), + spi_result, out_params))) { - LOG_WARN("failed to open", K(ret), K(stmt_id), K(stmt_type), + LOG_WARN("failed to open", K(ret), K(ps_sql), K(stmt_type), K(exec_params), K(sql_stmt), K(sql_stmt.ptr()), K(sql_stmt.length())); + if (spi_result.get_result_set() != NULL) { + int cli_ret = OB_SUCCESS; + retry_ctrl.test_and_save_retry_state( + GCTX, + *ctx->exec_ctx_->get_sql_ctx(), + *spi_result.get_result_set(), + ret, cli_ret, true, true, true); + LOG_WARN("failed to get_result, check if need retry", + K(ret), K(cli_ret), K(retry_ctrl.need_retry())); + ret = cli_ret; + ctx->exec_ctx_->get_sql_ctx()->clear(); + ctx->exec_ctx_->get_my_session()->set_session_in_retry(retry_ctrl.need_retry()); + } } /* else if (OB_FAIL(inner_fetch(ctx, retry_ctrl, spi_result.get_mysql_result().get_result(), @@ -1546,10 +1608,7 @@ int ObSPIService::dbms_cursor_execute(ObPLExecCtx *ctx, ObInnerSQLResult *inner_result = NULL; ObPhysicalPlanCtx *plan_ctx = NULL; const ParamStore *param_store = NULL; - CK (OB_NOT_NULL(inner_result = - static_cast(spi_result.get_mysql_result().get_result()))); - CK (OB_NOT_NULL(inner_result->get_result_set())); - CK (OB_NOT_NULL(plan_ctx = inner_result->result_set().get_exec_context().get_physical_plan_ctx())); + CK (OB_NOT_NULL(plan_ctx = spi_result.get_result_set()->get_exec_context().get_physical_plan_ctx())); CK (OB_NOT_NULL(param_store = &(plan_ctx->get_param_store()))); OV (param_store->count() >= exec_params.count(), OB_ERR_UNEXPECTED, param_store->count()); for (int64_t i = 0; OB_SUCC(ret) && i < exec_params.count(); ++i) { @@ -1558,7 +1617,7 @@ int ObSPIService::dbms_cursor_execute(ObPLExecCtx *ctx, } if (OB_SUCC(ret) && out_params.has_out_param()) { OZ (process_function_out_result( - ctx, spi_result.get_mysql_result(), out_params.get_out_params()), out_params); + ctx, *spi_result.get_result_set(), out_params.get_out_params()), out_params); } // TODO: 先注掉,因为目前看参数传进来的stmt_type已经是有效的,不需要再生成。 // if (OB_SUCC(ret)) { // 如果成功记录下stmttype,用于DDL语句的schema刷新 @@ -1568,7 +1627,7 @@ int ObSPIService::dbms_cursor_execute(ObPLExecCtx *ctx, // } // 无论成功或者失败都在这里close result set // 原因是close函数里面会设置audit的sched info信息, audit会在ObInnerSQLConnection::process_record中处理audit信息 - int close_ret = spi_result.get_mysql_result().close(); + int close_ret = spi_result.close_result_set(); if (OB_SUCCESS != close_ret) { LOG_WARN("close spi result failed", K(ret), K(close_ret)); } @@ -1586,40 +1645,41 @@ int ObSPIService::dbms_cursor_execute(ObPLExecCtx *ctx, } } LOG_DEBUG("start process record", - K(ret), K(stmt_id), K(sql_stmt), K(stmt_type), K(enable_sql_audit)); + K(ret), K(sql_stmt), K(stmt_type), K(enable_sql_audit)); // 处理监控统计项 if (enable_sql_audit) { - observer::ObInnerSQLResult* result_set = static_cast( - spi_result.get_mysql_result().get_result()); - if (OB_NOT_NULL(result_set) && OB_NOT_NULL(result_set->get_result_set())) { - if (result_set->is_inited()) { - ObInnerSQLConnection::process_record(*result_set, - *session, - time_record, - ret, - session->get_current_execution_id(), - stmt_id, - OB_INVALID_ID, // routine id - max_wait_desc, - total_wait_desc, - exec_record, - exec_timestamp, - true); + if (OB_NOT_NULL(spi_result.get_result_set())) { + if (spi_result.get_result_set()->is_inited()) { + ObInnerSQLConnection::process_record(*spi_result.get_result_set(), + spi_result.get_sql_ctx(), + *session, + time_record, + ret, + session->get_current_execution_id(), + OB_INVALID_ID, //FIXME@hr351303 + max_wait_desc, + total_wait_desc, + exec_record, + exec_timestamp, + true, + ps_sql, + true); } else { LOG_DEBUG("result set is not inited, do not process record", - K(ret), K(stmt_id), K(sql_stmt), K(stmt_type)); + K(ret), K(ps_sql), K(sql_stmt), K(stmt_type)); } } else { if (OB_SUCC(ret)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected error, result_set is null", - K(ret), K(stmt_id), K(sql_stmt), K(stmt_type)); + K(ret), K(ps_sql), K(sql_stmt), K(stmt_type)); } else { LOG_WARN("result_set is null", - K(ret), K(stmt_id), K(sql_stmt), K(stmt_type)); + K(ret), K(ps_sql), K(sql_stmt), K(stmt_type)); } } } + is_retry = true; } while (RETRY_TYPE_NONE != retry_ctrl.get_retry_type()); //SPI只做LOCAL重试 session->get_retry_info_for_update().clear(); session->set_query_start_time(old_query_start_time); @@ -1640,16 +1700,11 @@ int ObSPIService::dbms_cursor_execute(ObPLExecCtx *ctx, } // 记录第一条SQL执行PartitionHit信息, 并对PartitionHit进行Freeze, 防止后续的SQL冲掉 if (OB_SUCC(ret)) { - ObInnerSQLResult *inner_result - = static_cast(spi_result.get_mysql_result().get_result()); - if (OB_NOT_NULL(inner_result) - && OB_NOT_NULL(inner_result->get_result_set()) - && OB_NOT_NULL(inner_result->result_set().get_physical_plan())) { + if (OB_NOT_NULL(spi_result.get_result_set()->get_physical_plan())) { session->partition_hit().freeze(); } } - spi_result.get_mysql_result().reset(); spi_result.end_nested_stmt_if_need(ctx, ret); SET_FORALL_BULK_EXCEPTION; @@ -1671,7 +1726,7 @@ int ObSPIService::spi_query(ObPLExecCtx *ctx, { int ret = OB_SUCCESS; FLTSpanGuard(pl_spi_query); - OZ (spi_inner_execute(ctx, sql, OB_INVALID_ID, type, NULL, 0, + OZ (spi_inner_execute(ctx, sql, "", type, NULL, 0, into_exprs, into_count, column_types, type_count, exprs_not_null_flag, @@ -1681,7 +1736,7 @@ int ObSPIService::spi_query(ObPLExecCtx *ctx, } int ObSPIService::spi_execute(ObPLExecCtx *ctx, - uint64_t id, + const char *ps_sql, int64_t type, const ObSqlExpression **param_exprs, int64_t param_count, @@ -1696,7 +1751,7 @@ int ObSPIService::spi_execute(ObPLExecCtx *ctx, { int ret = OB_SUCCESS; FLTSpanGuard(pl_spi_execute); - OZ (spi_inner_execute(ctx, NULL, id, type, param_exprs, param_count, + OZ (spi_inner_execute(ctx, NULL, ps_sql, type, param_exprs, param_count, into_exprs, into_count, column_types, type_count, exprs_not_null_flag, pl_integer_ranges, is_bulk, is_forall)); return ret; @@ -1757,59 +1812,44 @@ int ObSPIService::spi_parse_prepare(common::ObIAllocator &allocator, } else if (OB_FAIL(ob_write_string(allocator, ObString(parse_result.no_param_sql_len_, parse_result.no_param_sql_), prepare_result.route_sql_))) { LOG_WARN("failed to write string", K(sql), K(ret)); } else { - HEAP_VAR(ObMySQLProxy::MySQLResult, proxy_result) { - ObInnerSQLConnection *spi_conn = NULL; - proxy_result.reset(); - if (OB_FAIL(acquire_spi_conn(sql_proxy, session, spi_conn))) { - LOG_WARN("acquire connection failed", K(ret)); - } else { - if (OB_FAIL(spi_conn->prepare(session.get_priv_tenant_id(), - prepare_result.route_sql_, - NULL, //must be NULL to generate SIMPLE_PS_MODE - false, /*is_dynamic_sql*/ - false, /*is_dbms_sql*/ - false, /*is_cursor*/ - proxy_result))) { - LOG_WARN("query failed", K(ret), K(spi_conn), K(sql)); + PLPrepareCtx pl_prepare_ctx(session, NULL, false, false, false); + SMART_VAR(PLPrepareResult, pl_prepare_result) { + CK (OB_NOT_NULL(GCTX.sql_engine_)); + OZ (pl_prepare_result.init(session)); + CK (OB_NOT_NULL(pl_prepare_result.result_set_)); + if (OB_SUCC(ret)) { + if (OB_FAIL(GCTX.sql_engine_->handle_pl_prepare( + prepare_result.route_sql_, pl_prepare_ctx, pl_prepare_result))) { + LOG_WARN("query failed", K(ret), K(sql)); } - sql_proxy.close(spi_conn, OB_SUCCESS == ret); - spi_conn = NULL; } LOG_TRACE("execute sql", K(sql), K(ret)); if (OB_SUCC(ret)) { - sqlclient::ObMySQLResult *mysql_result = proxy_result.get_result(); - if (OB_ISNULL(mysql_result) - || OB_ISNULL(static_cast(mysql_result)->get_result_set())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("result is NULL", K(mysql_result), K(ret)); - } else { - ObInnerSQLResult *inner_result = static_cast(mysql_result); - prepare_result.id_ = inner_result->result_set().get_statement_id(); - prepare_result.type_ = inner_result->result_set().get_stmt_type(); - prepare_result.for_update_ = false; //Mysql模式不支持可更新游标 - prepare_result.has_hidden_rowid_ = false; - - if (OB_FAIL(resolve_exec_params(parse_result, - session, - expr_factory, - *secondary_namespace, - prepare_result, - allocator))) { //resolve PL exec变量 - LOG_WARN("failed to resolve_exec_params", K(ret)); - } else if (OB_FAIL(resolve_into_params(parse_result, - session, - expr_factory, - *secondary_namespace, - prepare_result))) { //resolve PL into变量 - LOG_WARN("failed to resolve_into_params", K(ret)); - } else if (OB_FAIL(resolve_ref_objects(parse_result, - session, - schema_guard, - prepare_result))) { //resolve ref object - LOG_WARN("failed to resolve_ref_objects", K(ret)); - } else { /*do nothing*/ } - } + OZ (ob_write_string(allocator, pl_prepare_result.result_set_->get_stmt_ps_sql(), prepare_result.ps_sql_)); + prepare_result.type_ = pl_prepare_result.result_set_->get_stmt_type(); + prepare_result.for_update_ = false; //Mysql模式不支持可更新游标 + prepare_result.has_hidden_rowid_ = false; + if (OB_FAIL(ret)) { + } else if (OB_FAIL(resolve_exec_params(parse_result, + session, + expr_factory, + *secondary_namespace, + prepare_result, + allocator))) { //resolve PL exec变量 + LOG_WARN("failed to resolve_exec_params", K(ret)); + } else if (OB_FAIL(resolve_into_params(parse_result, + session, + expr_factory, + *secondary_namespace, + prepare_result))) { //resolve PL into变量 + LOG_WARN("failed to resolve_into_params", K(ret)); + } else if (OB_FAIL(resolve_ref_objects(parse_result, + session, + schema_guard, + prepare_result))) { //resolve ref object + LOG_WARN("failed to resolve_ref_objects", K(ret)); + } else { /*do nothing*/ } } } } @@ -1817,14 +1857,14 @@ int ObSPIService::spi_parse_prepare(common::ObIAllocator &allocator, return ret; } -int ObSPIService::spi_build_record_type_by_result_set(common::ObIAllocator &allocator, - ObSQLSessionInfo &session, - share::schema::ObSchemaGetterGuard &schema_guard, - const sql::ObResultSet &result_set, - int64_t hidden_column_count, - ObRecordType *&record_type, - uint64_t &rowid_table_id, - pl::ObPLBlockNS *secondary_namespace) +int ObSPIService::spi_build_record_type(common::ObIAllocator &allocator, + ObSQLSessionInfo &session, + share::schema::ObSchemaGetterGuard &schema_guard, + const sql::ObResultSet &result_set, + int64_t hidden_column_count, + pl::ObRecordType *&record_type, + uint64_t &rowid_table_id, + pl::ObPLBlockNS *secondary_namespace) { int ret = OB_SUCCESS; const common::ColumnsFieldIArray *columns = result_set.get_field_columns(); @@ -1903,128 +1943,106 @@ int ObSPIService::spi_resolve_prepare(common::ObIAllocator &allocator, ret = OB_INVALID_ARGUMENT; LOG_WARN("Argument passed in is NULL", K(sql), K(ret)); } else { - HEAP_VAR(ObMySQLProxy::MySQLResult, proxy_result) { - ObInnerSQLConnection *spi_conn = NULL; - const int64_t start = ::oceanbase::common::ObTimeUtility::current_time(); - proxy_result.reset(); - if (OB_FAIL(acquire_spi_conn(sql_proxy, session, spi_conn))) { - LOG_WARN("acquire connection failed", K(ret)); - } else { - if (OB_FAIL(spi_conn->prepare(session.get_effective_tenant_id(), - sql, - secondary_namespace, - false, /*is_dynamic_sql*/ - false, /*is_dbms_sql*/ - is_cursor, - proxy_result))) { - LOG_WARN("query failed", K(ret), K(spi_conn), K(start), K(sql)); + PLPrepareCtx pl_prepare_ctx(session, secondary_namespace, false, false, is_cursor); + const int64_t start = ::oceanbase::common::ObTimeUtility::current_time(); + + SMART_VAR(PLPrepareResult, pl_prepare_result) { + CK (OB_NOT_NULL(GCTX.sql_engine_)); + OZ (pl_prepare_result.init(session)); + CK (OB_NOT_NULL(pl_prepare_result.result_set_)); + if (OB_SUCC(ret)) { + if (OB_FAIL(GCTX.sql_engine_->handle_pl_prepare(sql, pl_prepare_ctx, pl_prepare_result))) { + LOG_WARN("query failed", K(ret), K(start), K(sql)); } - sql_proxy.close(spi_conn, OB_SUCCESS == ret); } - //sql_proxy.close(conn, ret); LOG_TRACE("execute sql", K(sql), K(ret)); if (OB_SUCC(ret)) { - ObInnerSQLResult *inner_result = - static_cast(proxy_result.get_result()); - if (OB_ISNULL(inner_result) || OB_ISNULL(inner_result->get_result_set())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("result is NULL", K(inner_result), K(ret)); - } else { - prepare_result.id_ = inner_result->result_set().get_statement_id(); - prepare_result.type_ = inner_result->result_set().get_stmt_type(); - prepare_result.for_update_ = inner_result->result_set().get_is_select_for_update(); - prepare_result.has_hidden_rowid_ = inner_result->result_set().has_hidden_rowid(); - if (OB_NOT_NULL(prepare_result.record_type_)) { - if (stmt::T_SELECT != prepare_result.type_) { - ret = OB_NOT_SUPPORTED; - LOG_WARN("cursor only supported select stmt", K(ret)); - LOG_USER_ERROR(OB_NOT_SUPPORTED, "non-select stmt in cursor"); - } else if (OB_NOT_NULL(inner_result->result_set().get_field_columns()) - && inner_result->result_set().get_field_columns()->count() > 0) { - OZ (spi_build_record_type_by_result_set(allocator, - session, - schema_guard, - inner_result->result_set(), - prepare_result.has_hidden_rowid_ ? 1 : 0, - prepare_result.record_type_, - prepare_result.rowid_table_id_, - secondary_namespace)); - } else { - HEAP_VAR(ObMySQLProxy::MySQLResult, proxy_result) { - ObInnerSQLConnection *spi_conn = NULL; - ObInnerSQLResult *result = NULL; - // 当 stmt_sql不为空时,说明route_sql中的QUESTIONMARK有无效值,此时使用stmt_sql进行prepare - const ObString &route_sql = inner_result->result_set().get_stmt_sql().empty() ? - inner_result->result_set().get_route_sql() : - inner_result->result_set().get_stmt_sql(); - proxy_result.reset(); - // 如果当前语句含有INTO, 则resultset中没有输出列, 我们使用reconstruct的route_sql来构造recordtype - CK (!inner_result->result_set().get_route_sql().empty()); - OZ (acquire_spi_conn(sql_proxy, session, spi_conn)); - OZ (spi_conn->prepare(session.get_effective_tenant_id(), - route_sql, - secondary_namespace, - false, /*is_dynamic_sql*/ - false, /*is_dbms_sql*/ - is_cursor, - proxy_result)); - sql_proxy.close(spi_conn, OB_SUCCESS == ret); - CK (OB_NOT_NULL(result = static_cast(proxy_result.get_result()))); - OZ (spi_build_record_type_by_result_set(allocator, - session, - schema_guard, - result->result_set(), - prepare_result.has_hidden_rowid_ ? 1 : 0, - prepare_result.record_type_, - prepare_result.rowid_table_id_, - secondary_namespace)); - } + OZ (ob_write_string(allocator, pl_prepare_result.result_set_->get_stmt_ps_sql(), prepare_result.ps_sql_)); + prepare_result.type_ = pl_prepare_result.result_set_->get_stmt_type(); + prepare_result.for_update_ = pl_prepare_result.result_set_->get_is_select_for_update(); + prepare_result.has_hidden_rowid_ = pl_prepare_result.result_set_->has_hidden_rowid(); + if (OB_FAIL(ret)) { + } else if (OB_NOT_NULL(prepare_result.record_type_)) { + if (stmt::T_SELECT != prepare_result.type_) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("cursor only supported select stmt", K(ret)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "non-select stmt in cursor"); + } else if (OB_NOT_NULL(pl_prepare_result.result_set_->get_field_columns()) && + pl_prepare_result.result_set_->get_field_columns()->count() > 0) { + OZ (spi_build_record_type(allocator, + session, + schema_guard, + *pl_prepare_result.result_set_, + prepare_result.has_hidden_rowid_ ? 1 : 0, + prepare_result.record_type_, + prepare_result.rowid_table_id_, + secondary_namespace)); + } else { + PLPrepareCtx tmp_pl_prepare_ctx(session, secondary_namespace, false, false, is_cursor); + const ObString &route_sql = pl_prepare_result.result_set_->get_stmt_ps_sql().empty() ? + pl_prepare_result.result_set_->get_route_sql() : + pl_prepare_result.result_set_->get_stmt_ps_sql(); + + SMART_VAR(PLPrepareResult, tmp_pl_prepare_result) { + CK (OB_NOT_NULL(GCTX.sql_engine_)); + OZ (tmp_pl_prepare_result.init(session)); + CK (OB_NOT_NULL(tmp_pl_prepare_result.result_set_)); + // 如果当前语句含有INTO, 则resultset中没有输出列, 我们使用reconstruct的route_sql来构造recordtype + CK (!pl_prepare_result.result_set_->get_route_sql().empty()); + OZ(GCTX.sql_engine_->handle_pl_prepare(route_sql, tmp_pl_prepare_ctx, tmp_pl_prepare_result)); + CK (OB_NOT_NULL(tmp_pl_prepare_result.result_set_->get_field_columns())); + OZ (spi_build_record_type(allocator, + session, + schema_guard, + *tmp_pl_prepare_result.result_set_, + prepare_result.has_hidden_rowid_ ? 1 : 0, + prepare_result.record_type_, + prepare_result.rowid_table_id_, + secondary_namespace)); } } - OZ (append(prepare_result.ref_objects_, inner_result->result_set().get_ref_objects())); + } + OZ (append(prepare_result.ref_objects_, pl_prepare_result.result_set_->get_ref_objects())); + if (OB_SUCC(ret)) { + ObRawExpr *expr = NULL; + for (int64_t i = 0; OB_SUCC(ret) && i < pl_prepare_result.result_set_->get_external_params().count(); ++i) { + expr = NULL; + if (OB_FAIL(ObPLExprCopier::copy_expr(expr_factory, + pl_prepare_result.result_set_->get_external_params().at(i), + expr))) { + LOG_WARN("failed to copy expr", + K(i), K(pl_prepare_result.result_set_->get_external_params().at(i)), K(ret)); + } else if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to copy expr, expr is NULL", K(expr), K(ret)); + } else { /*do nothing*/ } + if (OB_SUCC(ret) && OB_FAIL(prepare_result.exec_params_.push_back(expr))) { + LOG_WARN("push_back error", K(ret)); + } + } + for (int64_t i = 0; OB_SUCC(ret) && i < pl_prepare_result.result_set_->get_into_exprs().count(); ++i) { + expr = NULL; + if (OB_FAIL(ObPLExprCopier::copy_expr(expr_factory, + pl_prepare_result.result_set_->get_into_exprs().at(i), + expr))) { + LOG_WARN("failed to copy expr", K(i), K(pl_prepare_result.result_set_->get_into_exprs().at(i)), K(ret)); + } else if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to copy expr", K(expr), K(ret)); + } else if (OB_FAIL(prepare_result.into_exprs_.push_back(expr))) { + LOG_WARN("push_back error", K(ret)); + } + } + // add debug info, for convinence of sql reconstruct debug + LOG_DEBUG("spi prepare, source sql and prepared reconstruct sql", K(sql), + K(pl_prepare_result.result_set_->get_route_sql())); if (OB_SUCC(ret)) { - ObRawExpr *expr = NULL; - for (int64_t i = 0; OB_SUCC(ret) && i < inner_result->result_set().get_external_params().count(); ++i) { - expr = NULL; - if (OB_FAIL(ObPLExprCopier::copy_expr(expr_factory, - inner_result->result_set().get_external_params().at(i), - expr))) { - LOG_WARN("failed to copy expr", - K(i), K(inner_result->result_set().get_external_params().at(i)), K(ret)); - } else if (OB_ISNULL(expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to copy expr, expr is NULL", K(expr), K(ret)); - } else { /*do nothing*/ } - OZ (expr->formalize(&session)); - if (OB_SUCC(ret) && OB_FAIL(prepare_result.exec_params_.push_back(expr))) { - LOG_WARN("push_back error", K(ret)); - } - } - for (int64_t i = 0; OB_SUCC(ret) && i < inner_result->result_set().get_into_exprs().count(); ++i) { - expr = NULL; - if (OB_FAIL(ObPLExprCopier::copy_expr(expr_factory, - inner_result->result_set().get_into_exprs().at(i), - expr))) { - LOG_WARN("failed to copy expr", - K(i), K(inner_result->result_set().get_into_exprs().at(i)), K(ret)); - } else if (OB_ISNULL(expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to copy expr", K(expr), K(ret)); - } else if (OB_FAIL(prepare_result.into_exprs_.push_back(expr))) { - LOG_WARN("push_back error", K(ret)); - } - } - // add debug info, for convinence of sql reconstruct debug - LOG_DEBUG("spi prepare, source sql and prepared reconstruct sql", K(sql), - K(inner_result->result_set().get_route_sql())); - if (OB_SUCC(ret)) { - if (inner_result->result_set().get_route_sql().empty()) { - prepare_result.route_sql_ = sql; - } else { - if (OB_FAIL(ob_write_string(allocator, inner_result->result_set().get_route_sql(), prepare_result.route_sql_))) { - LOG_WARN("failed to write string", K(sql), K(ret)); - } + if (pl_prepare_result.result_set_->get_route_sql().empty()) { + prepare_result.route_sql_ = sql; + } else { + if (OB_FAIL(ob_write_string(allocator, pl_prepare_result.result_set_->get_route_sql(), prepare_result.route_sql_))) { + LOG_WARN("failed to write string", K(sql), K(ret)); } } } @@ -2072,10 +2090,11 @@ int ObSPIService::calc_dynamic_sqlstr( int ObSPIService::prepare_dynamic(ObPLExecCtx *ctx, const ObSqlExpression *sql_expr, + ObIAllocator &allocator, bool is_returning, int64_t param_cnt, ObSqlString &sql_str, - ObPsStmtId &stmt_id, + ObString &ps_sql, stmt::StmtType &stmt_type, bool &for_update, bool &hidden_rowid, @@ -2083,17 +2102,18 @@ int ObSPIService::prepare_dynamic(ObPLExecCtx *ctx, { int ret = OB_SUCCESS; OZ (calc_dynamic_sqlstr(ctx, sql_expr, sql_str)); - OZ (prepare_dynamic(ctx, is_returning, false, param_cnt, sql_str, - stmt_id, stmt_type, for_update, hidden_rowid, into_cnt)); + OZ (prepare_dynamic(ctx, allocator, is_returning, false, param_cnt, sql_str, + ps_sql, stmt_type, for_update, hidden_rowid, into_cnt)); return ret; } int ObSPIService::prepare_dynamic(ObPLExecCtx *ctx, + ObIAllocator &allocator, bool is_returning, bool is_dbms_sql, int64_t param_cnt, ObSqlString &sql_str, - ObPsStmtId &stmt_id, + ObString &ps_sql, stmt::StmtType &stmt_type, bool &for_update, bool &hidden_rowid, @@ -2101,159 +2121,147 @@ int ObSPIService::prepare_dynamic(ObPLExecCtx *ctx, common::ColumnsFieldArray *field_list) { int ret = OB_SUCCESS; - HEAP_VAR(ObSPIResultSet, spi_result) { - ObMySQLProxy::MySQLResult &proxy_result = spi_result.get_mysql_result(); - ObInnerSQLConnection *spi_conn = NULL; - stmt_type = stmt::T_NONE; - stmt_id = OB_INVALID_ID; - ObInnerSQLResult *inner_result = NULL; - ObSQLSessionInfo *session = NULL; - ObMySQLProxy *sql_proxy = NULL; + ObSQLSessionInfo *session = NULL; + CK (OB_NOT_NULL(ctx), ctx->valid()); + CK (OB_NOT_NULL(ctx->allocator_)); + CK (OB_NOT_NULL(session = ctx->exec_ctx_->get_my_session())); + CK (OB_NOT_NULL(GCTX.sql_engine_)); + stmt_type = stmt::T_NONE; + OV ((is_dbms_sql && NULL != field_list) + || (!is_dbms_sql && NULL == field_list), + OB_ERR_UNEXPECTED, is_dbms_sql, field_list); + if (OB_SUCC(ret)) { + PLPrepareCtx pl_prepare_ctx(*session, NULL, true, is_dbms_sql, false); + SMART_VAR(PLPrepareResult, pl_prepare_result) { + OZ (pl_prepare_result.init(*session)); + CK (OB_NOT_NULL(pl_prepare_result.result_set_)); + OZ(GCTX.sql_engine_->handle_pl_prepare(sql_str.string(), pl_prepare_ctx, pl_prepare_result)); - CK (OB_NOT_NULL(ctx), ctx->valid()); - CK (OB_NOT_NULL(session = ctx->exec_ctx_->get_my_session())); - CK (OB_NOT_NULL(sql_proxy = ctx->exec_ctx_->get_sql_proxy())); - OV ((is_dbms_sql && NULL != field_list) - || (!is_dbms_sql && NULL == field_list), - OB_ERR_UNEXPECTED, is_dbms_sql, field_list); + OX (stmt_type = static_cast(pl_prepare_result.result_set_->get_stmt_type())); + OZ (ob_write_string(allocator, pl_prepare_result.result_set_->get_stmt_ps_sql(), ps_sql, true)); + OX (for_update = pl_prepare_result.result_set_->get_is_select_for_update()); + OX (hidden_rowid = pl_prepare_result.result_set_->has_hidden_rowid()); + OX (into_cnt = pl_prepare_result.result_set_->get_into_exprs().count()); - OZ (acquire_spi_conn(*sql_proxy, *session, spi_conn)); - OZ (spi_conn->prepare(session->get_effective_tenant_id(), - sql_str.string(), - NULL, - true, /*dynamic_sql*/ - is_dbms_sql, - false, /*not cursor*/ - proxy_result)); - sql_proxy->close(spi_conn, OB_SUCCESS == ret); - - OX (inner_result = - static_cast(proxy_result.get_result())); - CK (OB_NOT_NULL(inner_result->get_result_set())); - OX (stmt_type = static_cast(inner_result->result_set().get_stmt_type())); - OX (stmt_id = static_cast(inner_result->result_set().get_statement_id())); - OX (for_update = static_cast(inner_result->result_set().get_is_select_for_update())); - OX (hidden_rowid = static_cast(inner_result->result_set().has_hidden_rowid())); - OX (into_cnt = inner_result->result_set().get_into_exprs().count()); - - if (OB_SUCC(ret) && NULL != field_list) { - CK (OB_NOT_NULL(inner_result->result_set().get_field_columns())); - if (OB_SUCC(ret) && inner_result->result_set().get_field_columns()->count() > 0) { - OZ (ObDbmsInfo::deep_copy_field_columns(*field_list->get_allocator(), - inner_result->result_set().get_field_columns(), - *field_list)); + if (OB_SUCC(ret) && NULL != field_list) { + CK (OB_NOT_NULL(pl_prepare_result.result_set_->get_field_columns())); + if (OB_SUCC(ret) && pl_prepare_result.result_set_->get_field_columns()->count() > 0) { + OZ (ObDbmsInfo::deep_copy_field_columns( + *(field_list->get_allocator()), + pl_prepare_result.result_set_->get_field_columns(), + *field_list)); + } } - } - if (OB_SUCC(ret)) { - if (!ObStmt::is_dynamic_supported_stmt(stmt_type)) { - // Some stmt type is dangerous and not allowed in Oracle, so we must forbid it. - ret = OB_NOT_SUPPORTED; - LOG_WARN("Statement type not allowed in dynamic sql", K(ret), K(stmt_type), K(sql_str)); - LOG_USER_ERROR(OB_NOT_SUPPORTED, "Statement not allowed in dynamic sql,"); - } else { - int64_t exec_param_cnt = ObStmt::is_dml_stmt(stmt_type) - ? inner_result->result_set().get_external_params().count() - : inner_result->result_set().get_param_fields()->count(); - if (inner_result->result_set().is_returning() && 0 == into_cnt) { - ret = OB_ERR_MISSING_INTO_KEYWORD; - LOG_WARN("ORA-00925: missing INTO keyword", K(ret), - K(inner_result->result_set().is_returning()), K(into_cnt)); + if (OB_SUCC(ret)) { + if (!ObStmt::is_dynamic_supported_stmt(stmt_type)) { + // Some stmt type is dangerous and not allowed in Oracle, so we must forbid it. + ret = OB_NOT_SUPPORTED; + LOG_WARN("Statement type not allowed in dynamic sql", K(ret), K(stmt_type), K(sql_str)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "Statement not allowed in dynamic sql,"); } else { - /*! - * 1、select语句的INTO子句在动态语句里直接丢掉,所以select语句参数个数按传进来的入参个数检查 - * 2、dml语句如果有RETURNING INTO子句,需要去掉动态语句里RETURNING INTO的参数, - * 但是如果EXECUTE IMMEDIATE本身有RETURNING子句的话就不用去了 - */ - int64_t need_exec_param_cnt = exec_param_cnt; - if (ObStmt::is_dml_write_stmt(stmt_type)) { - need_exec_param_cnt = need_exec_param_cnt + (is_returning ? 0 : into_cnt); - } - if (param_cnt != need_exec_param_cnt) { - if (lib::is_mysql_mode()) { - ret = OB_ERR_WRONG_DYNAMIC_PARAM; - LOG_USER_ERROR(OB_ERR_WRONG_DYNAMIC_PARAM, exec_param_cnt, param_cnt); - } else if (param_cnt < need_exec_param_cnt) { - ret = OB_ERR_NOT_ALL_VARIABLE_BIND; - LOG_WARN("ORA-01008: not all variables bound", - K(ret), K(param_cnt), - K(need_exec_param_cnt), K(into_cnt), K(is_returning), K(stmt_type)); - } else { - ret = OB_ERR_BIND_VARIABLE_NOT_EXIST; - LOG_WARN("ORA-01006: bind variable does not exist", - K(ret), K(param_cnt), - K(need_exec_param_cnt), K(into_cnt), K(is_returning), K(stmt_type)); + int64_t exec_param_cnt = ObStmt::is_dml_stmt(stmt_type) + ? pl_prepare_result.result_set_->get_external_params().count() + : pl_prepare_result.result_set_->get_param_fields()->count(); + if (pl_prepare_result.result_set_->is_returning() && 0 == into_cnt) { + ret = OB_ERR_MISSING_INTO_KEYWORD; + LOG_WARN("ORA-00925: missing INTO keyword", K(ret), + K(pl_prepare_result.result_set_->is_returning()), K(into_cnt)); + } else { + /*! + * 1、select语句的INTO子句在动态语句里直接丢掉,所以select语句参数个数按传进来的入参个数检查 + * 2、dml语句如果有RETURNING INTO子句,需要去掉动态语句里RETURNING INTO的参数, + * 但是如果EXECUTE IMMEDIATE本身有RETURNING子句的话就不用去了 + */ + int64_t need_exec_param_cnt = exec_param_cnt; + if (ObStmt::is_dml_write_stmt(stmt_type)) { + need_exec_param_cnt = need_exec_param_cnt + (is_returning ? 0 : into_cnt); + } + if (param_cnt != need_exec_param_cnt) { + if (lib::is_mysql_mode()) { + ret = OB_ERR_WRONG_DYNAMIC_PARAM; + LOG_USER_ERROR(OB_ERR_WRONG_DYNAMIC_PARAM, exec_param_cnt, param_cnt); + } else if (param_cnt < need_exec_param_cnt) { + ret = OB_ERR_NOT_ALL_VARIABLE_BIND; + LOG_WARN("ORA-01008: not all variables bound", + K(ret), K(param_cnt), + K(need_exec_param_cnt), K(into_cnt), K(is_returning), K(stmt_type)); + } else { + ret = OB_ERR_BIND_VARIABLE_NOT_EXIST; + LOG_WARN("ORA-01006: bind variable does not exist", + K(ret), K(param_cnt), + K(need_exec_param_cnt), K(into_cnt), K(is_returning), K(stmt_type)); + } } } } } - } - if (OB_SUCC(ret)) { - bool remove_into = false; - if (is_returning) { - if (stmt_type != stmt::T_INSERT - && stmt_type != stmt::T_DELETE - && stmt_type != stmt::T_UPDATE) { - ret = OB_ERR_CLAUSE_RETURN_ILLEGAL; - LOG_WARN("ORA-06547: RETURNING clause must be used with " - "INSERT, UPDATE, or DELETE statements", K(ret), K(stmt_type)); - LOG_USER_ERROR(OB_NOT_SUPPORTED, "RETURNING clause used with not " - "INSERT, UPDATE, or DELETE statements"); - } else if (inner_result->result_set().get_into_exprs().empty()) { - ret = OB_ERR_MISSING_INTO_KEYWORD; - LOG_WARN("ORA-00925: missing INTO keyword", K(ret)); - LOG_USER_ERROR(OB_NOT_SUPPORTED, "missing INTO keyword"); - } else { - remove_into = true; + if (OB_SUCC(ret)) { + bool remove_into = false; + if (is_returning) { + if (stmt_type != stmt::T_INSERT + && stmt_type != stmt::T_DELETE + && stmt_type != stmt::T_UPDATE) { + ret = OB_ERR_CLAUSE_RETURN_ILLEGAL; + LOG_WARN("ORA-06547: RETURNING clause must be used with " + "INSERT, UPDATE, or DELETE statements", K(ret), K(stmt_type)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "RETURNING clause used with not " + "INSERT, UPDATE, or DELETE statements"); + } else if (pl_prepare_result.result_set_->get_into_exprs().empty()) { + ret = OB_ERR_MISSING_INTO_KEYWORD; + LOG_WARN("ORA-00925: missing INTO keyword", K(ret)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "missing INTO keyword"); + } else { + remove_into = true; + } + } else if (stmt::T_SELECT == stmt_type) { + /* + * 动态语句如果是select into,INTO子句会被忽略掉,INTO子句里面占位符的也不需要绑定实参 + * 例如: + * SQL> DECLARE + * x int; + * y int :=1; + * c SYS_REFCURSOR; + * BEGIN + * execute immediate 'select * into :a from t where a1 >1' using IN y; + * dbms_output.put_line(x); + * END; + * / 2 3 4 5 6 7 8 9 + * DECLARE + * * + * ERROR at line 1: + * ORA-01006: bind variable does not exist + * ORA-06512: at line 6 + * */ + remove_into = !pl_prepare_result.result_set_->get_into_exprs().empty(); + } else { /*do nothing*/ } + + if (OB_SUCC(ret) && remove_into) { + CK (!pl_prepare_result.result_set_->get_route_sql().empty()); + CK ((pl_prepare_result.result_set_->get_route_sql().length() + 1) < OB_MAX_SQL_LENGTH); + OX (sql_str.reset()); + OZ (sql_str.append(pl_prepare_result.result_set_->get_route_sql())); } - } else if (stmt::T_SELECT == stmt_type) { - /* - * 动态语句如果是select into,INTO子句会被忽略掉,INTO子句里面占位符的也不需要绑定实参 - * 例如: - * SQL> DECLARE - * x int; - * y int :=1; - * c SYS_REFCURSOR; - * BEGIN - * execute immediate 'select * into :a from t where a1 >1' using IN y; - * dbms_output.put_line(x); - * END; - * / 2 3 4 5 6 7 8 9 - * DECLARE - * * - * ERROR at line 1: - * ORA-01006: bind variable does not exist - * ORA-06512: at line 6 - * */ - remove_into = !inner_result->result_set().get_into_exprs().empty(); - } else { /*do nothing*/ } - - if (OB_SUCC(ret) && remove_into) { - CK (!inner_result->result_set().get_route_sql().empty()); - CK ((inner_result->result_set().get_route_sql().length() + 1) < OB_MAX_SQL_LENGTH); - OX (sql_str.reset()); - OZ (sql_str.append(inner_result->result_set().get_route_sql())); } } } + return ret; } int ObSPIService::dynamic_out_params( common::ObIAllocator &allocator, - ObMySQLResult *result, common::ObObjParam **params, int64_t param_count) + ObResultSet *result_set, common::ObObjParam **params, int64_t param_count) { int ret = OB_SUCCESS; - ObInnerSQLResult *inner_result = NULL; ObPhysicalPlanCtx *plan_ctx = NULL; const ParamStore *param_store = NULL; if (param_count > 0) { - CK (OB_NOT_NULL(inner_result = static_cast(result))); - CK (OB_NOT_NULL(inner_result->get_result_set())); CK (OB_NOT_NULL(params)); + CK (OB_NOT_NULL(result_set)); CK (OB_NOT_NULL( - plan_ctx = inner_result->result_set().get_exec_context().get_physical_plan_ctx())); + plan_ctx = result_set->get_exec_context().get_physical_plan_ctx())); CK (OB_NOT_NULL(param_store = &(plan_ctx->get_param_store()))); OV (param_store->count() >= param_count, OB_ERR_UNEXPECTED, param_store->count(), param_count); @@ -2289,99 +2297,115 @@ int ObSPIService::spi_execute_immediate(ObPLExecCtx *ctx, int ret = OB_SUCCESS; // HEAP_VAR(char[OB_MAX_SQL_LENGTH], sql_buffer) { bool need_execute_sql = true; + ObSQLSessionInfo *session = NULL; + ObMySQLProxy *sql_proxy = NULL; ObSqlString sql_str; + ObArenaAllocator allocator; HEAP_VAR(ObSPIResultSet, spi_result) { - ObMySQLProxy::MySQLResult &proxy_result = spi_result.get_mysql_result(); - ObInnerSQLConnection *spi_conn = NULL; stmt::StmtType stmt_type = stmt::T_NONE; - ObPsStmtId stmt_id = OB_INVALID_ID; + ObString ps_sql; bool for_update = false; bool hidden_rowid = false; ObQueryRetryCtrl retry_ctrl; int64_t tenant_version = 0; int64_t sys_version = 0; share::schema::ObSchemaGetterGuard schema_guard; - ObSQLSessionInfo *session = NULL; - ObMySQLProxy *sql_proxy = NULL; int64_t inner_into_cnt = 0; //动态语句里into子句的变量个数 ObArray out_using_params; int64_t exec_param_cnt = param_count; + stmt::StmtType saved_stmt_type = stmt::T_NONE; CK (OB_NOT_NULL(ctx), ctx->valid()); CK ((OB_NOT_NULL(params) && param_count > 0) || (OB_ISNULL(params) && 0 == param_count)); CK (OB_NOT_NULL(session = ctx->exec_ctx_->get_my_session())); CK (OB_NOT_NULL(sql_proxy = ctx->exec_ctx_->get_sql_proxy())); CK (OB_NOT_NULL(sql)); - stmt::StmtType saved_stmt_type = stmt::T_NONE; + CK (OB_NOT_NULL(GCTX.sql_engine_)); + OZ(spi_result.init(*session)); OX(saved_stmt_type = session->get_stmt_type()); - // Step1: Prepare dynamic SQL! Only prepare once! - OZ (prepare_dynamic(ctx, - sql, - is_returning, - param_count, - sql_str, - stmt_id, - stmt_type, - for_update, - hidden_rowid, - inner_into_cnt)); - if (OB_SUCC(ret)) { - if (ObStmt::is_ddl_stmt(stmt_type, false) - && (into_count > 0 || param_count > 0 || is_returning)) { - ret = OB_ERR_DDL_IN_ILLEGAL_CONTEXT; - LOG_WARN("DDL statement is executed in an illegal context", - K(ret), K(into_count), K(param_count), K(is_returning)); - } else if (ObStmt::is_select_stmt(stmt_type) && 0 >= into_count) { - /* If dynamic_sql_statement is a SELECT statement, and you omit both - * into_clause and bulk_collect_into_clause, then - * execute_immediate_statement never executes. - * For example, this statement never increments the sequence: - * EXECUTE IMMEDIATE 'SELECT S.NEXTVAL FROM DUAL' + // Step1: Prepare dynamic SQL! Only prepare once! + OZ (prepare_dynamic(ctx, + sql, + allocator, + is_returning, + param_count, + sql_str, + ps_sql, + stmt_type, + for_update, + hidden_rowid, + inner_into_cnt)); + if (OB_SUCC(ret)) { + if (ObStmt::is_ddl_stmt(stmt_type, false) + && (into_count > 0 || param_count > 0 || is_returning)) { + ret = OB_ERR_DDL_IN_ILLEGAL_CONTEXT; + LOG_WARN("DDL statement is executed in an illegal context", + K(ret), K(into_count), K(param_count), K(is_returning)); + } else if (ObStmt::is_select_stmt(stmt_type) && 0 >= into_count) { + /* If dynamic_sql_statement is a SELECT statement, and you omit both + * into_clause and bulk_collect_into_clause, then + * execute_immediate_statement never executes. + * For example, this statement never increments the sequence: + * EXECUTE IMMEDIATE 'SELECT S.NEXTVAL FROM DUAL' + */ + need_execute_sql = false; + } else if (ObStmt::is_dml_write_stmt(stmt_type) && inner_into_cnt > 0 && 0 == into_count) { + /* + * 处理https://work.aone.alibaba-inc.com/issue/28206174这种特殊的用法。 + * 仅当dml语句含returning变量,并且外部没有INTO变量时才允许使用USING OUT接收参数 */ - need_execute_sql = false; - } else if (ObStmt::is_dml_write_stmt(stmt_type) && inner_into_cnt > 0 && 0 == into_count) { - /* - * 处理https://work.aone.alibaba-inc.com/issue/28206174这种特殊的用法。 - * 仅当dml语句含returning变量,并且外部没有INTO变量时才允许使用USING OUT接收参数 - */ - CK (param_count >= inner_into_cnt); - OX (exec_param_cnt = param_count - inner_into_cnt); - for (int64_t i = exec_param_cnt; OB_SUCC(ret) && i < param_count; ++i) { - ObPLRoutineParamMode pm = static_cast(params_mode[i]); - if (PL_PARAM_INOUT == pm || PL_PARAM_OUT == pm) { - OZ (out_using_params.push_back(params[i])); - } else { - ret = OB_ERR_INOUT_PARAM_PLACEMENT_NOT_PROPERLY; - LOG_WARN("ORA-06536: IN bind variable bound to an OUT position", K(ret)); + CK (param_count >= inner_into_cnt); + OX (exec_param_cnt = param_count - inner_into_cnt); + for (int64_t i = exec_param_cnt; OB_SUCC(ret) && i < param_count; ++i) { + ObPLRoutineParamMode pm = static_cast(params_mode[i]); + if (PL_PARAM_INOUT == pm || PL_PARAM_OUT == pm) { + OZ (out_using_params.push_back(params[i])); + } else { + ret = OB_ERR_INOUT_PARAM_PLACEMENT_NOT_PROPERLY; + LOG_WARN("ORA-06536: IN bind variable bound to an OUT position", K(ret)); + } } + } else if (ObStmt::is_dml_write_stmt(stmt_type) && inner_into_cnt > 0 && into_count > 0 && !is_returning) { + CK (param_count >= inner_into_cnt); + for (int64_t i = param_count - inner_into_cnt; OB_SUCC(ret) && i < param_count; ++i) { + ObPLRoutineParamMode pm = static_cast(params_mode[i]); + if (PL_PARAM_IN == pm) { + ret = OB_ERR_INOUT_PARAM_PLACEMENT_NOT_PROPERLY; + LOG_WARN("ORA-06536: IN bind variable bound to an OUT position", K(ret)); + } + } + } else { /*do nothing*/ } + } + for (int i = 0; OB_SUCC(ret) && i < param_count; ++i) { + ObPLRoutineParamMode pm = static_cast(params_mode[i]); + if (ObStmt::is_select_stmt(stmt_type) && (PL_PARAM_INOUT == pm || PL_PARAM_OUT == pm)) { + ret = OB_ERR_INOUT_PARAM_PLACEMENT_NOT_PROPERLY; + LOG_WARN("select stmt with using out/inout param mode is not allowed", K(ret)); + } + if (ObStmt::is_dml_write_stmt(stmt_type) + && i < param_count - inner_into_cnt + && PL_PARAM_OUT == pm) { + ret = OB_ERR_INOUT_PARAM_PLACEMENT_NOT_PROPERLY; + LOG_WARN("using out/inout param mode is not allowed", K(ret)); + } else if (ObStmt::is_dml_write_stmt(stmt_type) && + into_count > 0 && !is_returning && + (PL_PARAM_INOUT == pm || PL_PARAM_OUT == pm)) { + ret = OB_ERR_INOUT_PARAM_PLACEMENT_NOT_PROPERLY; + LOG_WARN("using out/inout param mode is not allowed", K(ret)); } - } else { /*do nothing*/ } - } - for (int i = 0; OB_SUCC(ret) && i < param_count; ++i) { - ObPLRoutineParamMode pm = static_cast(params_mode[i]); - if (ObStmt::is_select_stmt(stmt_type) && (PL_PARAM_INOUT == pm || PL_PARAM_OUT == pm)) { - ret = OB_ERR_INOUT_PARAM_PLACEMENT_NOT_PROPERLY; - LOG_WARN("select stmt with using out/inout param mode is not allowed", K(ret)); } - if (ObStmt::is_dml_write_stmt(stmt_type) - && i < param_count - inner_into_cnt - && PL_PARAM_OUT == pm) { - ret = OB_ERR_INOUT_PARAM_PLACEMENT_NOT_PROPERLY; - LOG_WARN("using out/inout param mode is not allowed", K(ret)); + if (OB_SUCC(ret)) { + ObParser parser(*ctx->allocator_, STD_MODE); + ObMPParseStat parse_stat; + ObSEArray queries; + OZ (parser.split_multiple_stmt(sql_str.string(), queries, parse_stat)); + if (OB_SUCC(ret) && queries.count() > 1) { + ret = OB_ERR_CMD_NOT_PROPERLY_ENDED; + LOG_WARN("execute immdeidate only support one stmt", K(ret)); + } } - } - if (OB_SUCC(ret)) { - ObParser parser(*ctx->allocator_, STD_MODE); - ObMPParseStat parse_stat; - ObSEArray queries; - OZ (parser.split_multiple_stmt(sql_str.string(), queries, parse_stat)); - if (OB_SUCC(ret) && queries.count() > 1) { - ret = OB_ERR_CMD_NOT_PROPERLY_ENDED; - LOG_WARN("execute immdeidate only support one stmt", K(ret)); - } - } - OX (session->set_stmt_type(saved_stmt_type)); - OZ (spi_result.start_nested_stmt_if_need(ctx, stmt_type)); + OX (session->set_stmt_type(saved_stmt_type)); + OZ (spi_result.start_nested_stmt_if_need(ctx, stmt_type)); // Step2: execute dynamic SQL now! if (OB_FAIL(ret)) { @@ -2393,6 +2417,7 @@ int ObSPIService::spi_execute_immediate(ObPLExecCtx *ctx, int64_t old_query_start_time = session->get_query_start_time(); session->set_query_start_time(ObTimeUtility::current_time()); + bool is_retry = false; do { ObWaitEventDesc max_wait_desc; ObWaitEventStat total_wait_desc; @@ -2408,58 +2433,67 @@ int ObSPIService::spi_execute_immediate(ObPLExecCtx *ctx, } ret = OB_SUCCESS; + if (is_retry) { + spi_result.reset_member_for_retry(*session); + } retry_ctrl.clear_state_before_each_retry(session->get_retry_info_for_update()); OZ (GCTX.schema_service_->get_tenant_schema_guard(session->get_effective_tenant_id(), - schema_guard)); - OZ (schema_guard.get_schema_version(session->get_effective_tenant_id(), tenant_version)); - OZ (schema_guard.get_schema_version(OB_SYS_TENANT_ID, sys_version)); + spi_result.get_scheme_guard())); + OZ (spi_result.get_scheme_guard().get_schema_version(session->get_effective_tenant_id(), tenant_version)); + OZ (spi_result.get_scheme_guard().get_schema_version(OB_SYS_TENANT_ID, sys_version)); OX (retry_ctrl.set_tenant_local_schema_version(tenant_version)); OX (retry_ctrl.set_sys_local_schema_version(sys_version)); - - if (OB_NOT_NULL(spi_conn)) { - sql_proxy->close(spi_conn, OB_SUCCESS == ret); - spi_conn = NULL; - } - - OX (proxy_result.reset()); + OX (spi_result.get_sql_ctx().schema_guard_ = &spi_result.get_scheme_guard()); + ObArenaAllocator allocator; + ParamStore exec_params( (ObWrapperAllocator(allocator)) ); bool is_inner_session = session->is_inner(); ObSQLSessionInfo::SessionType old_session_type = session->get_session_type(); !is_inner_session ? session->set_inner_session() : (void)NULL; session->set_session_type(ObSQLSessionInfo::USER_SESSION); - - if (OB_FAIL(ret)) { - } else if (0 == param_count) { - OZ (acquire_spi_conn(*sql_proxy, *session, spi_conn)); - OZ (spi_conn->execute_read( - session->get_effective_tenant_id(), sql_str.ptr(), proxy_result, false, true)); - } else { - ObArenaAllocator allocator; - ParamStore exec_params( (ObWrapperAllocator(allocator)) ); - for (int64_t i = 0; OB_SUCC(ret) && i < exec_param_cnt; ++i) { - CK (OB_NOT_NULL(params[i])); - OZ (exec_params.push_back(*params[i]), *params[i]); + if (OB_SUCC(ret)) { + WITH_CONTEXT(spi_result.get_memory_ctx()) { + if (OB_FAIL(ret)) { + } else if (0 == param_count) { + spi_result.get_result_set()->set_user_sql(true); + OZ (GCTX.sql_engine_->handle_pl_execute( + sql_str.string(), *session, exec_params, *spi_result.get_result_set(), spi_result.get_sql_ctx(), + false /* is_prepare_protocol */, false /* is_dynamic_sql*/)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < exec_param_cnt; ++i) { + CK (OB_NOT_NULL(params[i])); + OZ (exec_params.push_back(*params[i]), *params[i]); + } + LOG_INFO("execute dynamic sql using", K(ps_sql), K(exec_params)); + OZ (GCTX.sql_engine_->handle_pl_execute( + ps_sql, *session, exec_params, *spi_result.get_result_set(), spi_result.get_sql_ctx(), + true /* is_prepare_protocol */, true /* is_dynamic_sql*/)); + } } - OZ (acquire_spi_conn(*sql_proxy, *session, spi_conn)); - LOG_INFO("execute dynamic sql using", K(sql_str), K(exec_params)); - OZ (spi_conn->execute( - session->get_effective_tenant_id(), stmt_id, stmt_type, - exec_params, proxy_result, true /*from pl*/, true /*dynamic*/)); } - - if (NULL != spi_conn) { - sql_proxy->close(spi_conn, OB_SUCCESS == ret); - spi_conn = NULL; + if (OB_FAIL(ret) && spi_result.get_result_set() != NULL) { + int cli_ret = OB_SUCCESS; + retry_ctrl.test_and_save_retry_state( + GCTX, + *ctx->exec_ctx_->get_sql_ctx(), + *spi_result.get_result_set(), + ret, cli_ret, true, true, true); + LOG_WARN("failed to get_result, check if need retry", + K(ret), K(cli_ret), K(retry_ctrl.need_retry())); + ret = cli_ret; + ctx->exec_ctx_->get_sql_ctx()->clear(); + ctx->exec_ctx_->get_my_session()->set_session_in_retry(retry_ctrl.need_retry()); } + // todo:@hr351303 确认session标记是否还需要 !is_inner_session ? session->set_user_session() : (void)NULL; session->set_session_type(old_session_type); - LOG_TRACE("execute dynamic sql", K(ret), K(sql), K(sql_str), K(stmt_id)); + LOG_TRACE("execute dynamic sql", K(ret), K(sql), K(sql_str), K(ps_sql)); int64_t row_count = 0; OZ (inner_fetch(ctx, retry_ctrl, - proxy_result.get_result(), + spi_result, into_exprs, into_count, column_types, @@ -2474,7 +2508,7 @@ int ObSPIService::spi_execute_immediate(ObPLExecCtx *ctx, //此处仅需要处理非DML RETURNING返回的USING OUT参数 OZ (dynamic_out_params( - *(ctx->allocator_), proxy_result.get_result(), params, exec_param_cnt)); + *(ctx->allocator_), spi_result.get_result_set(), params, exec_param_cnt)); if (enable_sql_audit) { time_record.set_exec_end_timestamp(ObTimeUtility::current_time()); exec_record.record_end(); @@ -2482,48 +2516,48 @@ int ObSPIService::spi_execute_immediate(ObPLExecCtx *ctx, } // 处理监控统计项 if (enable_sql_audit) { - observer::ObInnerSQLResult* result_set - = static_cast(proxy_result.get_result()); - if (OB_NOT_NULL(result_set)) { - if (result_set->is_inited()) { + if (OB_NOT_NULL(spi_result.get_result_set())) { + if (spi_result.get_result_set()->is_inited()) { int64_t try_cnt = session->get_raw_audit_record().try_cnt_; ObExecRecord record_bk = session->get_raw_audit_record().exec_record_; session->get_raw_audit_record().try_cnt_ = retry_ctrl.get_retry_times(); - ObInnerSQLConnection::process_record(*(result_set), - *session, - time_record, - ret, - session->get_current_execution_id(), // sql execute id - stmt_id, // ps stmt id - ctx->func_->get_object_id(), // routine id - max_wait_desc, - total_wait_desc, - exec_record, - exec_timestamp, - true); + ObInnerSQLConnection::process_record(*spi_result.get_result_set(), + spi_result.get_sql_ctx(), + *session, + time_record, + ret, + session->get_current_execution_id(), // sql execute id + OB_INVALID_ID, // ps stmt id FIXME@hr351303 + max_wait_desc, + total_wait_desc, + exec_record, + exec_timestamp, + true, + 0 == param_count ? sql_str.string() : ps_sql, + true); session->get_raw_audit_record().exec_record_ = record_bk; session->get_raw_audit_record().try_cnt_ = try_cnt; } else { LOG_DEBUG("result set is not inited, do not process record", - K(ret), K(stmt_id), K(sql_str), K(stmt_type)); + K(ret), K(ps_sql), K(sql_str), K(stmt_type)); } } else { if (OB_SUCC(ret)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected error, result_set is null", - K(ret), K(stmt_id), K(sql_str), K(stmt_type)); + K(ret), K(ps_sql), K(sql_str), K(stmt_type)); } else { LOG_WARN("result_set is null", - K(ret), K(stmt_id), K(sql_str), K(stmt_type)); + K(ret), K(ps_sql), K(sql_str), K(stmt_type)); } } } - if (OB_FAIL(ret)) { - int close_ret = proxy_result.close(); - if (OB_SUCCESS != close_ret) { - LOG_WARN("close result set failed", K(ret), K(close_ret)); - } + // 无论成功或者失败都在这里close result set + int close_ret = spi_result.close_result_set(); + if (OB_SUCCESS != close_ret) { + LOG_WARN("close result set failed", K(ret), K(close_ret)); } + is_retry = true; } while (RETRY_TYPE_NONE != retry_ctrl.get_retry_type()); //SPI只做LOCAL重试 session->get_retry_info_for_update().clear(); session->set_query_start_time(old_query_start_time); @@ -2550,19 +2584,8 @@ int ObSPIService::spi_execute_immediate(ObPLExecCtx *ctx, recreate_implicit_savapoint_if_need(ctx, ret); } - spi_result.get_mysql_result().reset(); spi_result.end_nested_stmt_if_need(ctx, ret); - if (stmt_id != OB_INVALID_ID - && OB_NOT_NULL(session) - && OB_NOT_NULL(session->get_ps_cache())) { - int tmp_ret = OB_SUCCESS; - if ((tmp_ret = session->get_ps_cache()->deref_ps_stmt(stmt_id)) != OB_SUCCESS) { - LOG_WARN("failed to close execute immediate ps stmt", K(tmp_ret), K(ret), K(stmt_id)); - ret = OB_SUCCESS == ret ? tmp_ret : ret; - } - } - SET_FORALL_BULK_EXCEPTION; SET_SPI_STATUS; } @@ -2922,24 +2945,26 @@ int ObSPIService::spi_dynamic_open(ObPLExecCtx *ctx, int ret = OB_SUCCESS; ObSqlString sql_str; stmt::StmtType stmt_type = stmt::T_NONE; - ObPsStmtId stmt_id = OB_INVALID_ID; + ObArenaAllocator allocator; + ObString ps_sql; bool for_update = false; bool hidden_rowid = false; int64_t inner_into_cnt = 0; OZ (prepare_dynamic(ctx, sql, + allocator, false/*not returning*/, sql_param_count, sql_str, - stmt_id, + ps_sql, stmt_type, for_update, hidden_rowid, inner_into_cnt)); OZ (spi_cursor_open(ctx, sql_param_count > 0 ? NULL : sql_str.ptr(), - stmt_id, + ps_sql.ptr(),//trans to c-stype stmt_type, for_update, hidden_rowid, @@ -2951,18 +2976,7 @@ int ObSPIService::spi_dynamic_open(ObPLExecCtx *ctx, NULL/*formal_param_idxs*/, NULL/*actual_param_exprs*/, 0/*cursor_param_count*/)); - if (stmt_id != OB_INVALID_ID - && OB_NOT_NULL(ctx) - && OB_NOT_NULL(ctx->exec_ctx_) - && OB_NOT_NULL(ctx->exec_ctx_->get_my_session()) - && OB_NOT_NULL(ctx->exec_ctx_->get_my_session()->get_ps_cache())) { - int tmp_ret = OB_SUCCESS; - if ((tmp_ret - = ctx->exec_ctx_->get_my_session()->get_ps_cache()->deref_ps_stmt(stmt_id)) != OB_SUCCESS){ - LOG_WARN("failed to close dynamic cursor ps stmt", K(tmp_ret), K(ret), K(stmt_id)); - } - ret = (OB_SUCCESS == ret) ? tmp_ret : ret; - } + return ret; } @@ -2973,7 +2987,7 @@ int ObSPIService::dbms_dynamic_open(ObPLExecCtx *pl_ctx, // ObString &sql_stmt = cursor.get_sql_stmt(); // ParamStore &exec_params = cursor.get_exec_params(); stmt::StmtType stmt_type = cursor.get_stmt_type(); - ObPsStmtId stmt_id = cursor.get_stmt_id(); + const ObString ps_sql = cursor.get_ps_sql(); bool for_update = cursor.is_for_update(); bool hidden_rowid = cursor.has_hidden_rowid(); // int64_t into_cnt = 0; @@ -2981,9 +2995,9 @@ int ObSPIService::dbms_dynamic_open(ObPLExecCtx *pl_ctx, OV (OB_NOT_NULL(pl_ctx->exec_ctx_->get_my_session())); if (ObStmt::is_select_stmt(stmt_type) || cursor.get_into_names().count() > 0) { // NOTICE: DML Returning also use cursor impl. - OZ (dbms_cursor_open(pl_ctx, cursor, stmt_id, stmt_type, for_update, hidden_rowid), cursor); + OZ (dbms_cursor_open(pl_ctx, cursor, ps_sql, stmt_type, for_update, hidden_rowid), cursor); } else { - OZ (dbms_cursor_execute(pl_ctx, stmt_id, stmt_type, cursor), cursor); + OZ (dbms_cursor_execute(pl_ctx, ps_sql, stmt_type, cursor), cursor); OX (cursor.set_affected_rows(pl_ctx->exec_ctx_->get_my_session()->get_affected_rows())); } return ret; @@ -2991,7 +3005,7 @@ int ObSPIService::dbms_dynamic_open(ObPLExecCtx *pl_ctx, int ObSPIService::spi_cursor_open(ObPLExecCtx *ctx, const char *sql, - uint64_t id, + const char *ps_sql, int64_t type, bool for_update, bool has_hidden_rowid, @@ -3016,7 +3030,7 @@ int ObSPIService::spi_cursor_open(ObPLExecCtx *ctx, || (NULL != sql && sql_param_count > 0) || (NULL == sql && 0 == sql_param_count)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("Argument passed in is NULL", K(ctx), K(sql), K(id), K(type), K(sql_param_exprs), K(sql_param_count), K(ret)); + LOG_WARN("Argument passed in is NULL", K(ctx), K(sql), K(ps_sql), K(type), K(sql_param_exprs), K(sql_param_count), K(ret)); } else if (OB_FAIL(spi_get_cursor_info(ctx, package_id, routine_id, cursor_index, cursor, cursor_var, loc))) { LOG_WARN("failed to get cursor info", K(ret), K(cursor_index)); // } else if (OB_ISNULL(cursor)) { @@ -3104,124 +3118,174 @@ int ObSPIService::spi_cursor_open(ObPLExecCtx *ctx, ret = OB_ERR_UNEXPECTED; LOG_WARN("Argument in pl context is NULL", K(cursor->get_allocator()), K(ret)); } else { - // 如果当前cursor已经有spi_result则复用,避免内存占用过多 - spi_result = (NULL == cursor->get_cursor_handler()) - ? static_cast(cursor->get_allocator()->alloc(sizeof(ObSPIResultSet))) - : cursor->get_cursor_handler(); - if (OB_ISNULL(spi_result)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to alloc mysql result"); - } - } - OX (new(spi_result)ObSPIResultSet()); - OX (cursor->set_spi_cursor(spi_result)); - OZ (spi_result->start_cursor_stmt(ctx, static_cast(type), false)); - if (OB_FAIL(ret)) { - // do nothing - } else if (is_server_cursor) { - WITH_CONTEXT(cursor->get_cursor_entity()) { - lib::ContextTLOptGuard guard(false); - OZ (inner_open(ctx, - spi_result->get_allocaor(), - sql, - id, - type, - sql_param_exprs, - sql_param_count, - NULL, - 0, - spi_result->get_mysql_result(), - spi_result->get_out_params())); - } - } else { - ret = inner_open(ctx, - spi_result->get_allocaor(), - sql, - id, - type, - sql_param_exprs, - sql_param_count, - NULL, - 0, - spi_result->get_mysql_result(), - spi_result->get_out_params()); - } - OX (cursor->open(spi_result)); - CK (OB_NOT_NULL(spi_result->get_result_set())); - if (OB_SUCC(ret) && OB_INVALID_ID != cursor->get_id()) { - //如果是客户端游标,设置结果集为二进制模式 - OX (spi_result->get_result_set()->set_ps_protocol()); - } + ObQueryRetryCtrl retry_ctrl; + int64_t tenant_version = 0; + int64_t sys_version = 0; + do { + ret = OB_SUCCESS; + // 如果当前cursor已经有spi_result则复用,避免内存占用过多 + spi_result = (NULL == cursor->get_cursor_handler()) + ? static_cast(cursor->get_allocator()->alloc(sizeof(ObSPIResultSet))) + : cursor->get_cursor_handler(); + if (OB_ISNULL(spi_result)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc mysql result"); + } + OX (new(spi_result)ObSPIResultSet()); + OZ (spi_result->init(*session_info)); + OX (cursor->set_spi_cursor(spi_result)); + OZ (spi_result->start_cursor_stmt(ctx, static_cast(type), false)); + OZ ((GCTX.schema_service_->get_tenant_schema_guard(session_info->get_effective_tenant_id(), spi_result->get_scheme_guard()))); + OX (spi_result->get_sql_ctx().schema_guard_ = &spi_result->get_scheme_guard()); + OZ (spi_result->get_scheme_guard().get_schema_version(session_info->get_effective_tenant_id(), tenant_version)); + OZ (spi_result->get_scheme_guard().get_schema_version(OB_SYS_TENANT_ID, sys_version)); + OX (retry_ctrl.set_tenant_local_schema_version(tenant_version)); + OX (retry_ctrl.set_sys_local_schema_version(sys_version)); + OX (retry_ctrl.clear_state_before_each_retry(session_info->get_retry_info_for_update())); + if (OB_FAIL(ret)) { + // do nothing + } else if (is_server_cursor) { + WITH_CONTEXT(cursor->get_cursor_entity()) { + lib::ContextTLOptGuard guard(false); + OZ (inner_open(ctx, + spi_result->get_allocaor(), + sql, + ps_sql, + type, + sql_param_exprs, + sql_param_count, + NULL, + 0, + *spi_result, + spi_result->get_out_params(), + &retry_ctrl)); + } + } else { + ret = inner_open(ctx, + spi_result->get_allocaor(), + sql, + ps_sql, + type, + sql_param_exprs, + sql_param_count, + NULL, + 0, + *spi_result, + spi_result->get_out_params(), + &retry_ctrl); + } + OX (cursor->open(spi_result)); + CK (OB_NOT_NULL(spi_result->get_result_set())); + if (OB_SUCC(ret) && OB_INVALID_ID != cursor->get_id()) { + //如果是客户端游标,设置结果集为二进制模式 + OX (spi_result->get_result_set()->set_ps_protocol()); + } - if (OB_NOT_NULL(spi_result)) { - spi_result->end_cursor_stmt(ctx, ret); - } - if (OB_SUCC(ret)) { - transaction::ObTxReadSnapshot &snapshot = - spi_result->get_result_set()->get_exec_context().get_das_ctx().get_snapshot(); - OZ (cursor->set_and_register_snapshot(snapshot)); - } - if (OB_FAIL(ret) && OB_NOT_NULL(spi_result)) { - spi_result->~ObSPIResultSet(); + if (OB_SUCC(ret)) { + transaction::ObTxReadSnapshot &snapshot = + spi_result->get_result_set()->get_exec_context().get_das_ctx().get_snapshot(); + OZ (cursor->set_and_register_snapshot(snapshot)); + } + if (OB_FAIL(ret) && OB_NOT_NULL(spi_result)) { + int tmp_ret = ret; + ret = OB_SUCCESS; + if (OB_NOT_NULL(spi_result->get_result_set())) { + // 此分支所有错误码都被吞掉,最终返回最初的错误码 + int close_ret = spi_result->close_result_set(); + if (OB_SUCCESS != close_ret) { + LOG_WARN("close mysql result set failed", K(ret), K(close_ret)); + } + } + ret = tmp_ret; + spi_result->~ObSPIResultSet(); + LOG_WARN("cursor open result failed.", K(ret)); + } + if (OB_NOT_NULL(spi_result)) { + spi_result->end_cursor_stmt(ctx, ret); + } + } while (RETRY_TYPE_NONE != retry_ctrl.get_retry_type()); } cursor->set_last_execute_time(ObTimeUtility::current_time()); } else { //MySQL Cursor/Updated Cursor/Server Cursor(REF_CURSOR, PACKAGE CURSOR) HEAP_VAR(ObSPIResultSet, spi_result) { + OZ (spi_result.init(*session_info)); OZ (spi_result.start_nested_stmt_if_need(ctx, static_cast(type))); int64_t old_query_start_time = session_info->get_query_start_time(); // query_start_time_ set to 0 in begin_nested_session, here we reset it. session_info->set_query_start_time(ObTimeUtility::current_time()); - OZ (inner_open(ctx, - spi_result.get_allocaor(), - sql, - id, - type, - sql_param_exprs, - sql_param_count, - NULL, - 0, - spi_result.get_mysql_result(), - spi_result.get_out_params())); if (OB_SUCC(ret)) { - ObSPICursor* spi_cursor = cursor->get_spi_cursor(); - uint64_t size = 0; - OZ (session_info->get_tmp_table_size(size)); - OZ (cursor->prepare_spi_cursor(spi_cursor, - session_info->get_effective_tenant_id(), - size), K(size)); - if (is_server_cursor) { - CK (OB_NOT_NULL(cursor->get_allocator())); + ObQueryRetryCtrl retry_ctrl; + int64_t tenant_version = 0; + int64_t sys_version = 0; + bool is_retry = false; + do { + ret = OB_SUCCESS; + if (is_retry) { + spi_result.get_out_params().reset(); + spi_result.reset_member_for_retry(*session_info); + } + OZ ((GCTX.schema_service_->get_tenant_schema_guard(session_info->get_effective_tenant_id(), spi_result.get_scheme_guard()))); + OX (spi_result.get_sql_ctx().schema_guard_ = &spi_result.get_scheme_guard()); + OZ (spi_result.get_scheme_guard().get_schema_version(session_info->get_effective_tenant_id(), tenant_version)); + OZ (spi_result.get_scheme_guard().get_schema_version(OB_SYS_TENANT_ID, sys_version)); + OX (retry_ctrl.set_tenant_local_schema_version(tenant_version)); + OX (retry_ctrl.set_sys_local_schema_version(sys_version)); + OX (retry_ctrl.clear_state_before_each_retry(session_info->get_retry_info_for_update())); + + OZ (inner_open(ctx, + spi_result.get_allocaor(), + sql, + ps_sql, + type, + sql_param_exprs, + sql_param_count, + NULL, + 0, + spi_result, + spi_result.get_out_params(), + &retry_ctrl)); + if (OB_SUCC(ret)) { + ObSPICursor* spi_cursor = cursor->get_spi_cursor(); + uint64_t size = 0; + OZ (session_info->get_tmp_table_size(size)); + OZ (cursor->prepare_spi_cursor(spi_cursor, + session_info->get_effective_tenant_id(), + size), K(size)); + if (is_server_cursor) { + CK (OB_NOT_NULL(cursor->get_allocator())); + CK (OB_NOT_NULL(spi_result.get_result_set())); + OZ (ObDbmsInfo::deep_copy_field_columns( + *cursor->get_allocator(), + spi_result.get_result_set()->get_field_columns(), + spi_cursor->fields_)); + } + OZ (fill_cursor(*spi_result.get_result_set(), spi_cursor)); + OX (spi_cursor->row_store_.finish_add_row()) + OX (cursor->open(spi_cursor)); + if (OB_FAIL(ret)) { + spi_cursor->~ObSPICursor(); + } + } + OX (for_update ? cursor->set_for_update() : (void)NULL); + OX (for_update ? cursor->set_trans_id(session_info->get_tx_id()) : (void)NULL); + OX (has_hidden_rowid ? cursor->set_hidden_rowid() : (void)NULL); + CK (OB_NOT_NULL(spi_result.get_result_set())); - OZ (ObDbmsInfo::deep_copy_field_columns( - *cursor->get_allocator(), - spi_result.get_result_set()->get_field_columns(), - spi_cursor->fields_)); - } - OZ (fill_cursor(spi_result.get_mysql_result().get_result(), spi_cursor)); - OX (spi_cursor->row_store_.finish_add_row()) - OX (cursor->open(spi_cursor)); - if (OB_FAIL(ret)) { - spi_cursor->~ObSPICursor(); - } - } - OX (for_update ? cursor->set_for_update() : (void)NULL); - OX (for_update ? cursor->set_trans_id(session_info->get_tx_id()) : (void)NULL); - OX (has_hidden_rowid ? cursor->set_hidden_rowid() : (void)NULL); + if (OB_SUCC(ret) && lib::is_oracle_mode()) { + transaction::ObTxReadSnapshot &snapshot = + spi_result.get_result_set()->get_exec_context().get_das_ctx().get_snapshot(); + OZ (cursor->set_and_register_snapshot(snapshot)); + } - CK (OB_NOT_NULL(spi_result.get_result_set())); - if (OB_SUCC(ret) && lib::is_oracle_mode()) { - transaction::ObTxReadSnapshot &snapshot = - spi_result.get_result_set()->get_exec_context().get_das_ctx().get_snapshot(); - OZ (cursor->set_and_register_snapshot(snapshot)); + int close_ret = spi_result.close_result_set(); + if (OB_SUCCESS != close_ret) { + LOG_WARN("close mysql result failed", K(ret), K(close_ret)); + } + ret = (OB_SUCCESS == ret ? close_ret : ret); + is_retry = true; + } while (RETRY_TYPE_NONE != retry_ctrl.get_retry_type()); } - - int close_ret = spi_result.get_mysql_result().close(); - if (OB_SUCCESS != close_ret) { - LOG_WARN("close mysql result failed", K(ret), K(close_ret)); - } - ret = (OB_SUCCESS == ret ? close_ret : ret); spi_result.destruct_exec_params(*session_info); - spi_result.get_mysql_result().reset(); spi_result.end_nested_stmt_if_need(ctx, ret); session_info->set_query_start_time(old_query_start_time); } @@ -3244,7 +3308,7 @@ int ObSPIService::spi_cursor_open(ObPLExecCtx *ctx, int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, ObDbmsCursorInfo &cursor, - uint64_t stmt_id, + const ObString &ps_sql, int64_t stmt_type, bool for_update, bool hidden_rowid) @@ -3253,7 +3317,8 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, ObSQLSessionInfo *session = NULL; ParamStore &exec_params = cursor.get_exec_params(); ObString &sql_stmt = cursor.get_sql_stmt(); - const char *sql_str = exec_params.count() > 0 ? NULL : sql_stmt.ptr(); + ObString sql_str = + (exec_params.count() > 0 || cursor.get_into_names().count() > 0) ? ObString() : sql_stmt; bool use_stream = false; ObExecRecord exec_record; ObExecTimestamp exec_timestamp; @@ -3268,7 +3333,8 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, OB_NOT_NULL(ctx->exec_ctx_) && OB_NOT_NULL(ctx->allocator_) && OB_NOT_NULL(session = ctx->exec_ctx_->get_my_session()), - OB_INVALID_ARGUMENT, ctx, stmt_id, stmt_type); + OB_INVALID_ARGUMENT, ctx, ps_sql, stmt_type); + OZ (session->ps_use_stream_result_set(use_stream)); if (enable_sql_audit) { time_record.set_send_timestamp(ObTimeUtility::current_time()); @@ -3297,143 +3363,165 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, LOG_USER_ERROR(OB_NOT_SUPPORTED, "non-select stmt in cursor"); } OX (cursor.set_streaming()); - OV (OB_NOT_NULL(cursor.get_dbms_entity()), OB_NOT_INIT, sql_stmt, stmt_id, exec_params); - OV (OB_NOT_NULL(cursor.get_cursor_entity()), OB_NOT_INIT, sql_stmt, stmt_id, exec_params); - OZ (cursor.prepare_spi_result(spi_result), sql_stmt, stmt_id, exec_params); - OV (OB_NOT_NULL(spi_result), OB_ERR_UNEXPECTED, sql_stmt, stmt_id, exec_params); - OZ (spi_result->start_cursor_stmt(ctx, static_cast(stmt_type)), - sql_stmt, stmt_id, exec_params); - WITH_CONTEXT(cursor.get_cursor_entity()) { - lib::ContextTLOptGuard guard(false); - OZ (inner_open(ctx, sql_str, stmt_id, stmt_type, exec_params, - spi_result->get_mysql_result(), spi_result->get_out_params()), - sql_stmt, stmt_id, exec_params); - } - OV (OB_NOT_NULL(spi_result->get_result_set()), - OB_ERR_UNEXPECTED, sql_stmt, stmt_id, exec_params); - CK (OB_NOT_NULL(spi_result->get_result_set()->get_field_columns())); - if (OB_SUCC(ret) && cursor.get_field_columns().empty()) { - const common::ColumnsFieldArray* field_column = - dynamic_cast - (spi_result->get_result_set()->get_field_columns()); - OX (cursor.get_field_columns().set_allocator(&cursor.get_dbms_entity()->get_arena_allocator())); - OZ (cursor.get_field_columns().assign(*field_column)); - } - OX (spi_result->get_result_set()->set_ps_protocol()); - if (OB_SUCCESS != ret && OB_NOT_NULL(spi_result)) { - int tmp_ret = ret; + OV (OB_NOT_NULL(cursor.get_dbms_entity()), OB_NOT_INIT, sql_stmt, ps_sql, exec_params); + OV (OB_NOT_NULL(cursor.get_cursor_entity()), OB_NOT_INIT, sql_stmt, ps_sql, exec_params); + ObQueryRetryCtrl retry_ctrl; + int64_t tenant_version = 0; + int64_t sys_version = 0; + int64_t retry_cnt = 0; + do { ret = OB_SUCCESS; - if (OB_NOT_NULL(spi_result->get_mysql_result().get_result())) { - // 此分支所有错误码都被吞掉,最终返回最初的错误码 - OZ (spi_result->set_cursor_env(*session)); - int close_ret = spi_result->get_mysql_result().close(); - if (OB_SUCCESS != close_ret) { - LOG_WARN("close mysql result set failed", K(ret), K(close_ret)); + OZ (cursor.prepare_spi_result(ctx, spi_result), sql_stmt, ps_sql, exec_params); + OV (OB_NOT_NULL(spi_result), OB_ERR_UNEXPECTED, sql_stmt, ps_sql, exec_params); + OZ (spi_result->start_cursor_stmt(ctx, static_cast(stmt_type)), + sql_stmt, ps_sql, exec_params); + OZ ((GCTX.schema_service_->get_tenant_schema_guard(session->get_effective_tenant_id(), spi_result->get_scheme_guard()))); + OZ (spi_result->get_scheme_guard().get_schema_version(session->get_effective_tenant_id(), tenant_version)); + OZ (spi_result->get_scheme_guard().get_schema_version(OB_SYS_TENANT_ID, sys_version)); + OX (retry_ctrl.set_tenant_local_schema_version(tenant_version)); + OX (retry_ctrl.set_sys_local_schema_version(sys_version)); + OX (retry_ctrl.clear_state_before_each_retry(session->get_retry_info_for_update())); + OX (spi_result->get_sql_ctx().schema_guard_ = &spi_result->get_scheme_guard()); + if (OB_SUCC(ret)) { + WITH_CONTEXT(cursor.get_cursor_entity()) { + lib::ContextTLOptGuard guard(false); + if (OB_FAIL(inner_open(ctx, sql_str, ps_sql, stmt_type, exec_params, + *spi_result, spi_result->get_out_params()))) { + if (spi_result->get_result_set() != NULL) { + int cli_ret = OB_SUCCESS; + retry_ctrl.test_and_save_retry_state(GCTX, + *ctx->exec_ctx_->get_sql_ctx(), + *spi_result->get_result_set(), + ret, cli_ret, true, true, true); + LOG_WARN("fail to open, check if need retry", K(ret), K(cli_ret), + K(retry_ctrl.need_retry()), K(sql_str), K(ps_sql), K(exec_params)); + ret = cli_ret; + ctx->exec_ctx_->get_sql_ctx()->clear(); + ctx->exec_ctx_->get_my_session()->set_session_in_retry(retry_ctrl.need_retry()); + } + } } - spi_result->get_mysql_result().reset(); - OZ (spi_result->reset_cursor_env(*session)); } - ret = tmp_ret; - spi_result->~ObSPIResultSet(); - LOG_WARN("cursor open result failed.", K(ret), K(sql_stmt), K(stmt_id), K(exec_params)); - } - OX (cursor.open(spi_result)); - if (OB_NOT_NULL(spi_result)) { - // no OX - spi_result->end_cursor_stmt(ctx, ret); - } - if (OB_SUCC(ret)) { - transaction::ObTxReadSnapshot &snapshot = - spi_result->get_result_set()->get_exec_context().get_das_ctx().get_snapshot(); - OZ (cursor.set_and_register_snapshot(snapshot)); - } - LOG_DEBUG("start process record", K(ret), K(stmt_id), K(sql_str), K(enable_sql_audit)); - if (enable_sql_audit) { - observer::ObInnerSQLResult* result_set = - static_cast(spi_result->get_mysql_result().get_result()); - time_record.set_exec_end_timestamp(ObTimeUtility::current_time()); - exec_record.record_end(); - if (OB_NOT_NULL(result_set) && result_set->is_inited()) { - ObSQLSessionInfo *session_info = ctx->exec_ctx_->get_my_session(); - int64_t try_cnt = session_info->get_raw_audit_record().try_cnt_; - ObExecRecord record_bk = session_info->get_raw_audit_record().exec_record_; - session_info->get_raw_audit_record().try_cnt_ = try_cnt; - // 会在inner_open的时候被改成了 inner ,所以这个地方需要重新设置一下 - exec_timestamp.exec_type_ = cursor.is_ps_cursor() ? sql::PSCursor : sql::DbmsCursor; - ObInnerSQLConnection::process_record(*(result_set), - *(ctx->exec_ctx_->get_my_session()), - time_record, - ret, - ctx->exec_ctx_->get_my_session() - ->get_current_execution_id(), - stmt_id, // ps stmt id - OB_INVALID, // routine id - max_wait_desc, - total_wait_desc, - exec_record, - exec_timestamp, - true); - session_info->get_raw_audit_record().exec_record_ = record_bk; - session_info->get_raw_audit_record().try_cnt_ = try_cnt; + OV (OB_NOT_NULL(spi_result->get_result_set()), + OB_ERR_UNEXPECTED, sql_stmt, ps_sql, exec_params); + CK (OB_NOT_NULL(spi_result->get_result_set()->get_field_columns())); + if (OB_SUCC(ret) && cursor.get_field_columns().empty()) { + const common::ColumnsFieldArray* field_column = + dynamic_cast + (spi_result->get_result_set()->get_field_columns()); + OX (cursor.get_field_columns().set_allocator(&cursor.get_dbms_entity()->get_arena_allocator())); + OZ (cursor.get_field_columns().assign(*field_column)); } - } + OX (spi_result->get_result_set()->set_ps_protocol()); + if (OB_SUCCESS != ret && OB_NOT_NULL(spi_result)) { + int tmp_ret = ret; + ret = OB_SUCCESS; + if (OB_NOT_NULL(spi_result->get_result_set())) { + // 此分支所有错误码都被吞掉,最终返回最初的错误码 + int close_ret = spi_result->close_result_set(); + if (OB_SUCCESS != close_ret) { + LOG_WARN("close mysql result set failed", K(ret), K(close_ret)); + } + } + ret = tmp_ret; + spi_result->~ObSPIResultSet(); + LOG_WARN("cursor open result failed.", K(ret), K(sql_stmt), K(ps_sql), K(exec_params)); + } + OX (cursor.open(spi_result)); + if (OB_NOT_NULL(spi_result)) { + // no OX + spi_result->end_cursor_stmt(ctx, ret); + } + if (OB_SUCC(ret)) { + transaction::ObTxReadSnapshot &snapshot = + spi_result->get_result_set()->get_exec_context().get_das_ctx().get_snapshot(); + OZ (cursor.set_and_register_snapshot(snapshot)); + } + LOG_DEBUG("start process record", K(ret), K(ps_sql), K(sql_str), K(enable_sql_audit)); + if (enable_sql_audit) { + time_record.set_exec_end_timestamp(ObTimeUtility::current_time()); + exec_record.record_end(); + if (OB_NOT_NULL(spi_result->get_result_set()) && spi_result->get_result_set()->is_inited()) { + ObSQLSessionInfo *session_info = ctx->exec_ctx_->get_my_session(); + int64_t try_cnt = session_info->get_raw_audit_record().try_cnt_; + ObExecRecord record_bk = session_info->get_raw_audit_record().exec_record_; + session_info->get_raw_audit_record().try_cnt_ = try_cnt; + // 会在inner_open的时候被改成了 inner ,所以这个地方需要重新设置一下 + exec_timestamp.exec_type_ = cursor.is_ps_cursor() ? sql::PSCursor : sql::DbmsCursor; + ObInnerSQLConnection::process_record(*spi_result->get_result_set(), + spi_result->get_sql_ctx(), + *(ctx->exec_ctx_->get_my_session()), + time_record, + ret, + ctx->exec_ctx_->get_my_session() + ->get_current_execution_id(), + OB_INVALID_ID, // ps stmt id FIXME@hr351303 + max_wait_desc, + total_wait_desc, + exec_record, + exec_timestamp, + true, + exec_params.count() > 0 ? ps_sql : sql_str, + true); + session_info->get_raw_audit_record().exec_record_ = record_bk; + session_info->get_raw_audit_record().try_cnt_ = try_cnt; + } + } + } while (RETRY_TYPE_NONE != retry_ctrl.get_retry_type()); } else { SMART_VAR(ObSPIResultSet, spi_result) { ObSPICursor *spi_cursor = NULL; uint64_t size = 0; OZ (session->get_tmp_table_size(size)); + OZ (spi_result.init(*ctx->exec_ctx_->get_my_session())); OZ (spi_result.start_nested_stmt_if_need(ctx, static_cast(stmt_type)), - sql_stmt, stmt_id, exec_params); + sql_stmt, ps_sql, exec_params); if (OB_SUCC(ret)) { ObQueryRetryCtrl retry_ctrl; int64_t tenant_version = 0; int64_t sys_version = 0; int64_t retry_cnt = 0; - share::schema::ObSchemaGetterGuard schema_guard; + int64_t old_query_start_time = session->get_query_start_time(); + session->set_query_start_time(ObTimeUtility::current_time()); do { ret = OB_SUCCESS; + if (retry_cnt > 0) { + spi_result.get_out_params().reset(); + spi_result.reset_member_for_retry(*session); + } retry_ctrl.clear_state_before_each_retry(session->get_retry_info_for_update()); OZ (cursor.prepare_spi_cursor(spi_cursor, session->get_effective_tenant_id(), size)); - OZ (GCTX.schema_service_->get_tenant_schema_guard(session->get_effective_tenant_id(), schema_guard)); - OZ (schema_guard.get_schema_version(session->get_effective_tenant_id(), tenant_version)); - OZ (schema_guard.get_schema_version(OB_SYS_TENANT_ID, sys_version)); + OZ (GCTX.schema_service_->get_tenant_schema_guard(session->get_effective_tenant_id(), spi_result.get_scheme_guard())); + OZ (spi_result.get_scheme_guard().get_schema_version(session->get_effective_tenant_id(), tenant_version)); + OZ (spi_result.get_scheme_guard().get_schema_version(OB_SYS_TENANT_ID, sys_version)); OX (retry_ctrl.set_tenant_local_schema_version(tenant_version)); OX (retry_ctrl.set_sys_local_schema_version(sys_version)); + OX (spi_result.get_sql_ctx().schema_guard_ = &spi_result.get_scheme_guard()); if (OB_SUCC(ret)) { - OZ (inner_open(ctx, sql_str, stmt_id, stmt_type, exec_params, - spi_result.get_mysql_result(), spi_result.get_out_params()), - sql_stmt, stmt_id, exec_params); + OZ (inner_open(ctx, sql_str, ps_sql, stmt_type, exec_params, + spi_result, spi_result.get_out_params()), + sql_stmt, ps_sql, exec_params); OZ (ObDbmsInfo::deep_copy_field_columns( cursor.get_dbms_entity()->get_arena_allocator(), spi_result.get_result_set()->get_field_columns(), cursor.get_field_columns())); - OZ (fill_cursor(spi_result.get_mysql_result().get_result(), spi_cursor)); + OZ (fill_cursor(*spi_result.get_result_set(), spi_cursor)); if (OB_FAIL(ret)) { int cli_ret = OB_SUCCESS; - sqlclient::ObMySQLResult *mysql_result = spi_result.get_mysql_result().get_result(); - // we only check fill_cursor for retry, - // do not check inner_open, because inner_open retry by itself. - // but we need inner_open in retry, because retry need to reopen resultset. - if (OB_ISNULL(mysql_result) || OB_ISNULL(ctx->exec_ctx_->get_sql_ctx()) - || OB_ISNULL((static_cast(mysql_result)) - ->get_result_set())) { - // it has failed, do not set the error code separately, keep the original error code - LOG_WARN("result set or sql ctx is null", K(ret)); - } else { - retry_ctrl.test_and_save_retry_state( - GCTX, - *ctx->exec_ctx_->get_sql_ctx(), - (static_cast(mysql_result))->result_set(), - ret, - cli_ret, - true); - LOG_WARN("failed to fill_cursor, check if need retry", - K(ret), K(cli_ret), K(retry_ctrl.need_retry()), - K(sql_stmt), K(stmt_id), K(exec_params)); - } + retry_ctrl.test_and_save_retry_state(GCTX, + *ctx->exec_ctx_->get_sql_ctx(), + *spi_result.get_result_set(), + ret, + cli_ret, + true, + true, + true); + LOG_WARN("failed to fill_cursor, check if need retry", + K(ret), K(cli_ret), K(retry_ctrl.need_retry()), + K(sql_stmt), K(ps_sql), K(exec_params)); } } OX (spi_cursor->row_store_.finish_add_row()); @@ -3442,10 +3530,9 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, spi_result.get_result_set()->get_exec_context().get_das_ctx().get_snapshot(); OZ (cursor.set_and_register_snapshot(snapshot)); } - LOG_DEBUG("start process record", K(ret), K(stmt_id), K(sql_str), K(enable_sql_audit)); + LOG_DEBUG("start process record", K(ret), K(ps_sql), K(sql_str), K(enable_sql_audit)); if (enable_sql_audit) { - observer::ObInnerSQLResult* result_set = - static_cast(spi_result.get_mysql_result().get_result()); + ObResultSet* result_set = spi_result.get_result_set(); time_record.set_exec_end_timestamp(ObTimeUtility::current_time()); exec_record.record_end(); if (OB_NOT_NULL(result_set) && result_set->is_inited()) { @@ -3455,18 +3542,20 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, session_info->get_raw_audit_record().try_cnt_ = retry_ctrl.get_retry_times(); // 会在inner_open的时候被改成了 inner ,所以这个地方需要重新设置一下 exec_timestamp.exec_type_ = cursor.is_ps_cursor() ? sql::PSCursor : sql::DbmsCursor; - ObInnerSQLConnection::process_record(*(result_set), + ObInnerSQLConnection::process_record(*result_set, + spi_result.get_sql_ctx(), *(ctx->exec_ctx_->get_my_session()), time_record, ret, ctx->exec_ctx_->get_my_session() ->get_current_execution_id(), - stmt_id, // ps stmt id - OB_INVALID, // routine id + OB_INVALID_ID, // ps stmt id FIXME@hr351303 max_wait_desc, total_wait_desc, exec_record, exec_timestamp, + true, + exec_params.count() > 0 ? ps_sql : sql_str, true); session_info->get_raw_audit_record().exec_record_ = record_bk; session_info->get_raw_audit_record().try_cnt_ = retry_cnt; @@ -3474,15 +3563,16 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, } if (OB_SUCCESS != ret && OB_NOT_NULL(spi_cursor)) { spi_cursor->~ObSPICursor(); - LOG_WARN("fill cursor failed.", K(ret), K(cursor.get_id()), K(sql_stmt), K(stmt_id), K(session->get_sessid())); + LOG_WARN("fill cursor failed.", K(ret), K(cursor.get_id()), K(sql_stmt), K(ps_sql), K(session->get_sessid())); } - int close_ret = spi_result.get_mysql_result().close(); + int close_ret = spi_result.close_result_set(); if (OB_SUCCESS != close_ret) { LOG_WARN("close mysql result failed", K(ret), K(close_ret)); } ret = OB_SUCCESS == ret ? close_ret : ret; retry_cnt++; } while (RETRY_TYPE_NONE != retry_ctrl.get_retry_type()); + session->set_query_start_time(old_query_start_time); } if (OB_SUCC(ret)) { @@ -3495,7 +3585,6 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, OX (cursor.set_hidden_rowid()); } } - spi_result.get_mysql_result().reset(); spi_result.end_nested_stmt_if_need(ctx, ret); } } @@ -3607,11 +3696,8 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx, } else if (!cursor->is_streaming()) { \ bool can_retry = true; \ ret = get_result(ctx, \ - cursor->is_streaming() \ - ? static_cast((cursor)->get_cursor_handler() \ - ->get_mysql_result().get_result()) \ - : static_cast((cursor)->get_spi_cursor()), \ - cursor->is_streaming(), \ + static_cast((cursor)->get_spi_cursor()), \ + false, \ into_exprs, \ into_count, \ column_types, \ @@ -3632,7 +3718,7 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx, return_type_count); \ } else { \ ret = inner_fetch_with_retry(ctx, \ - cursor->get_cursor_handler()->get_mysql_result().get_result(), \ + *cursor->get_cursor_handler(), \ into_exprs, \ into_count, \ column_types, \ @@ -3670,8 +3756,7 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx, } else { LOG_DEBUG("start process record", K(ret), K(cursor->get_id()), K(enable_sql_audit)); if (enable_sql_audit) { - observer::ObInnerSQLResult* result_set = - static_cast(spi_result->get_mysql_result().get_result()); + ObResultSet* result_set = spi_result->get_result_set(); time_record.set_exec_end_timestamp(ObTimeUtility::current_time()); exec_record.record_end(); if (OB_NOT_NULL(result_set) && result_set->is_inited()) { @@ -3680,17 +3765,19 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx, ObExecRecord record_bk = session_info->get_raw_audit_record().exec_record_; session_info->get_raw_audit_record().try_cnt_ = try_cnt; ObInnerSQLConnection::process_record(*(result_set), + spi_result->get_sql_ctx(), *(ctx->exec_ctx_->get_my_session()), time_record, ret, ctx->exec_ctx_->get_my_session() ->get_current_execution_id(), cursor->get_id(), // ps stmt id - OB_INVALID, // routine id max_wait_desc, total_wait_desc, exec_record, exec_timestamp, + true, + ObString(), true); session_info->get_raw_audit_record().exec_record_ = record_bk; session_info->get_raw_audit_record().try_cnt_ = try_cnt; @@ -4633,7 +4720,7 @@ OB_INLINE int ObSPIService::acquire_spi_conn(ObMySQLProxy &sql_proxy, } int ObSPIService::adjust_out_params( - ObMySQLProxy::MySQLResult &mysql_result, ObSPIOutParams &out_params) + ObResultSet &result_set, ObSPIOutParams &out_params) { int ret = OB_SUCCESS; /*observer::ObInnerSQLResult* inner_result = @@ -4657,7 +4744,7 @@ int ObSPIService::adjust_out_params( LOG_DEBUG("debug for adjust_out_params", K(ret), K(out_params), K(ref_objects)); }*/ // In Oracle: function with out parameter can not use in sql. - UNUSED(mysql_result); + UNUSED(result_set); out_params.set_has_out_param(false); return ret; } @@ -4809,18 +4896,14 @@ int ObSPIService::construct_exec_params(ObPLExecCtx *ctx, } int ObSPIService::process_function_out_result(ObPLExecCtx *ctx, - ObMySQLProxy::MySQLResult &mysql_result, + ObResultSet &result_set, ObIArray &out_params) { int ret = OB_SUCCESS; - ObInnerSQLResult *inner_result = static_cast(mysql_result.get_result()); - ObResultSet *result_set = NULL; ObExecContext *exec_ctx = NULL; ObPhysicalPlanCtx *pctx = NULL; ParamStore *exec_params = NULL; - CK (OB_NOT_NULL(inner_result)); - CK (OB_NOT_NULL(result_set = inner_result->get_result_set())); - CK (OB_NOT_NULL(exec_ctx = &(result_set->get_exec_context()))); + CK (OB_NOT_NULL(exec_ctx = &(result_set.get_exec_context()))); CK (OB_NOT_NULL(pctx = exec_ctx->get_physical_plan_ctx())); CK (OB_NOT_NULL(exec_params = &(pctx->get_param_store_for_update()))); @@ -4853,14 +4936,15 @@ int ObSPIService::process_function_out_result(ObPLExecCtx *ctx, int ObSPIService::inner_open(ObPLExecCtx *ctx, ObIAllocator ¶m_allocator, //用于拷贝执行期参数 const char *sql, - uint64_t id, + const char *ps_sql, int64_t type, const ObSqlExpression **param_exprs, int64_t param_count, const ObSqlExpression **into_exprs, int64_t into_count, - ObMySQLProxy::MySQLResult &mysql_result, + ObSPIResultSet &spi_result, ObSPIOutParams &out_params, + observer::ObQueryRetryCtrl *retry_ctrl, bool is_forall) { int ret = OB_SUCCESS; @@ -4873,7 +4957,7 @@ int ObSPIService::inner_open(ObPLExecCtx *ctx, if (NULL == sql) { OZ (construct_exec_params(ctx, param_allocator, param_exprs, param_count, into_exprs, into_count, exec_params, out_params, is_forall), - K(sql), K(id), K(type), K(param_count), K(out_params), K(exec_params)); + K(sql), K(type), K(param_count), K(out_params), K(exec_params)); } if (OB_SUCC(ret) && is_forall) { @@ -4899,12 +4983,29 @@ int ObSPIService::inner_open(ObPLExecCtx *ctx, LOG_WARN("unexpected null", K(ret)); } else { curr_params = batch_params; + spi_result.get_sql_ctx().multi_stmt_item_.set_ps_mode(true); + spi_result.get_sql_ctx().multi_stmt_item_.set_ab_cnt(array_binding_count); } } } - - OZ (inner_open(ctx, sql, id, type, *curr_params, mysql_result, out_params, is_forall, array_binding_count), - K(sql), K(id), K(type), K(param_count), K(out_params), K(exec_params), K(is_forall), K(array_binding_count)); + if (OB_FAIL(ret)) { + } else if (OB_FAIL(inner_open(ctx, sql, ps_sql, type, + *curr_params, spi_result, + out_params))) { + if (retry_ctrl != nullptr/*can_retry*/) { + int cli_ret = OB_SUCCESS; + retry_ctrl->test_and_save_retry_state( + GCTX, + *ctx->exec_ctx_->get_sql_ctx(), + *spi_result.get_result_set(), + ret, cli_ret, true, true, true); + LOG_WARN("failed to get_result, check if need retry", + K(ret), K(cli_ret), K(retry_ctrl->need_retry()), K(sql), K(ps_sql), K(type)); + ret = cli_ret; + ctx->exec_ctx_->get_sql_ctx()->clear(); + ctx->exec_ctx_->get_my_session()->set_session_in_retry(retry_ctrl->need_retry()); + } + } // if failed, we need release complex parameter memory in here if (OB_FAIL(ret) @@ -4921,19 +5022,17 @@ int ObSPIService::inner_open(ObPLExecCtx *ctx, } int ObSPIService::inner_open(ObPLExecCtx *ctx, - const char *sql, - uint64_t id, + const ObString &sql, + const ObString &ps_sql, int64_t type, ParamStore &exec_params, - ObMySQLProxy::MySQLResult &mysql_result, - ObSPIOutParams &out_params, - bool is_forall, - int32_t array_binding_count) + ObSPIResultSet &spi_result, + ObSPIOutParams &out_params) { int ret = OB_SUCCESS; // unconditional adjustment - OZ (adjust_out_params(mysql_result, out_params)); + OZ (adjust_out_params(*spi_result.get_result_set(), out_params)); if (OB_ISNULL(ctx) || OB_ISNULL(ctx->exec_ctx_) || (NULL == ctx->allocator_)) { @@ -4941,50 +5040,39 @@ int ObSPIService::inner_open(ObPLExecCtx *ctx, LOG_WARN("Argument passed in is NULL", K(ctx), K(sql), K(ret)); } else { #ifndef NDEBUG - LOG_INFO("spi_execute using", K(sql), K(id), K(exec_params)); + LOG_INFO("spi_execute using", K(sql), K(exec_params)); #else - LOG_DEBUG("spi_execute using", K(sql), K(id), K(exec_params)); + LOG_TRACE("spi_execute using", K(sql), K(exec_params)); #endif ObSQLSessionInfo *session = ctx->exec_ctx_->get_my_session(); - ObMySQLProxy *sql_proxy = ctx->exec_ctx_->get_sql_proxy(); - if (OB_ISNULL(session) || OB_ISNULL(sql_proxy)) { + if (OB_ISNULL(session) || OB_ISNULL(GCTX.sql_engine_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("Argument in pl context is NULL", K(session), K(sql_proxy), K(ret)); + LOG_WARN("Argument in pl context is NULL", K(session), K(ret)); } else { bool is_inner_session = session->is_inner(); ObSQLSessionInfo::SessionType old_session_type = session->get_session_type(); ObInnerSQLConnection *spi_conn = NULL; !is_inner_session ? session->set_inner_session() : (void)NULL; session->set_session_type(ObSQLSessionInfo::USER_SESSION); - mysql_result.reset(); - if (OB_FAIL(acquire_spi_conn(*sql_proxy, *session, spi_conn))) { - LOG_WARN("acquire connection failed", K(ret)); - } else { - if (OB_SUCC(ret)) { - if (NULL != sql) { - if (OB_FAIL(spi_conn->execute_read(session->get_effective_tenant_id(), - sql, - mysql_result, - true, - true))) { - LOG_WARN("query failed", K(ret), K(spi_conn), K(sql)); + if (OB_SUCC(ret)) { + WITH_CONTEXT(spi_result.get_memory_ctx()) { + if (NULL != sql.ptr()) { + spi_result.get_result_set()->set_user_sql(true); + if (OB_FAIL(GCTX.sql_engine_->handle_pl_execute( + sql, *session, exec_params, *spi_result.get_result_set(), spi_result.get_sql_ctx(), + false /* is_prepare_protocol */, false /* is_dynamic_sql*/))) { + LOG_WARN("query failed", K(ret), K(sql)); } } else { - OZ (spi_conn->execute(session->get_effective_tenant_id(), - static_cast(id), - static_cast(type), - exec_params, - mysql_result, - true, - false, - is_forall, - array_binding_count), spi_conn, id, exec_params); + spi_result.get_result_set()->set_stmt_type(static_cast(type)); + OZ (GCTX.sql_engine_->handle_pl_execute( + ps_sql, *session, exec_params, *spi_result.get_result_set(), spi_result.get_sql_ctx(), + true /* is_prepare_protocol */, false /* is_dynamic_sql */), exec_params); + OZ (adjust_out_params(*spi_result.get_result_set(), out_params)); } } } - if (NULL != spi_conn) { - sql_proxy->close(spi_conn, OB_SUCCESS == ret); - } + !is_inner_session ? session->set_user_session() : (void)NULL; session->set_session_type(old_session_type); } @@ -4994,7 +5082,7 @@ int ObSPIService::inner_open(ObPLExecCtx *ctx, int ObSPIService::inner_fetch(ObPLExecCtx *ctx, ObQueryRetryCtrl &retry_ctrl, - sqlclient::ObMySQLResult *result_set, + ObSPIResultSet &spi_result, const ObSqlExpression **into_exprs, int64_t into_count, const ObDataType *column_types, @@ -5014,46 +5102,49 @@ int ObSPIService::inner_fetch(ObPLExecCtx *ctx, int64_t return_type_count) { int ret = OB_SUCCESS; + ObResultSet *result_set = spi_result.get_result_set(); CK (OB_NOT_NULL(ctx)); CK (OB_NOT_NULL(ctx->exec_ctx_)); CK (OB_NOT_NULL(ctx->exec_ctx_->get_sql_ctx())); - CK (OB_NOT_NULL(static_cast(result_set)->get_result_set())); + CK (OB_NOT_NULL(result_set)); if (OB_SUCC(ret)) { ObNewRow dummy_row; bool can_retry = true; current_row = NULL != current_row ? current_row : &dummy_row; - if (OB_FAIL((get_result(ctx, - result_set, - true/*is streaming*/, - into_exprs, - into_count, - column_types, - type_count, - exprs_not_null_flag, - pl_integer_ranges, - out_using_params, - row_count, - *current_row, - can_retry, - has_hidden_rowid, - is_bulk, - is_dynamic_sql, - for_cursor, - is_forall, - limit, - return_types, - return_type_count)))) { - if (can_retry) { - int cli_ret = OB_SUCCESS; - retry_ctrl.test_and_save_retry_state( - GCTX, - *ctx->exec_ctx_->get_sql_ctx(), - static_cast(result_set)->result_set(), ret, cli_ret, true); - if (!for_cursor || (for_cursor && ret != OB_READ_NOTHING)) { - LOG_WARN("failed to get_result, check if need retry", - K(ret), K(cli_ret), K(retry_ctrl.need_retry())); + WITH_CONTEXT(spi_result.get_memory_ctx()) { + if (OB_FAIL((get_result(ctx, + result_set, + true/*is streaming*/, + into_exprs, + into_count, + column_types, + type_count, + exprs_not_null_flag, + pl_integer_ranges, + out_using_params, + row_count, + *current_row, + can_retry, + has_hidden_rowid, + is_bulk, + is_dynamic_sql, + for_cursor, + is_forall, + limit, + return_types, + return_type_count)))) { + if (can_retry) { + int cli_ret = OB_SUCCESS; + retry_ctrl.test_and_save_retry_state( + GCTX, + *ctx->exec_ctx_->get_sql_ctx(), + *result_set, ret, cli_ret, true, true, true); + if (!for_cursor || (for_cursor && ret != OB_READ_NOTHING)) { + LOG_WARN("failed to get_result, check if need retry", + K(ret), K(cli_ret), K(retry_ctrl.need_retry())); + } + ret = cli_ret; } - ret = cli_ret; } } ctx->exec_ctx_->get_sql_ctx()->clear(); @@ -5063,7 +5154,7 @@ int ObSPIService::inner_fetch(ObPLExecCtx *ctx, } int ObSPIService::inner_fetch_with_retry(ObPLExecCtx *ctx, - sqlclient::ObMySQLResult *result_set, + ObSPIResultSet &spi_result, const ObSqlExpression **into_exprs, int64_t into_count, const ObDataType *column_types, @@ -5086,25 +5177,25 @@ int ObSPIService::inner_fetch_with_retry(ObPLExecCtx *ctx, int64_t sys_version = 0; share::schema::ObSchemaGetterGuard schema_guard; ObSQLSessionInfo *session = NULL; + ObResultSet *result_set = spi_result.get_result_set(); int64_t query_timeout = 0; CK (OB_NOT_NULL(ctx)); CK (OB_NOT_NULL(ctx->exec_ctx_)); CK (OB_NOT_NULL(session = ctx->exec_ctx_->get_my_session())); OZ (session->get_query_timeout(query_timeout)); + CK (OB_NOT_NULL(result_set)); if (OB_SUCC(ret)) { int64_t time_gap = ObTimeUtility::current_time() - last_exec_time; int64_t old_query_start_time = session->get_query_start_time(); int64_t old_timeout_ts = THIS_WORKER.get_timeout_ts(); int64_t min_timeout_ts = old_timeout_ts; - observer::ObInnerSQLResult *inner_result=static_cast(result_set); - CK (OB_NOT_NULL(inner_result)); - CK (OB_NOT_NULL(inner_result->get_result_set())); - CK (inner_result->result_set().get_exec_context().get_physical_plan_ctx() != NULL); + + CK (result_set->get_exec_context().get_physical_plan_ctx() != NULL); OX (min_timeout_ts = MIN(old_timeout_ts, - inner_result->result_set().get_exec_context().get_physical_plan_ctx()->get_timeout_timestamp())); + result_set->get_exec_context().get_physical_plan_ctx()->get_timeout_timestamp())); OX (session->set_query_start_time(ObTimeUtility::current_time())); OX (THIS_WORKER.set_timeout_ts(min_timeout_ts + time_gap)); - OX (inner_result->result_set().get_exec_context().get_physical_plan_ctx()-> + OX (result_set->get_exec_context().get_physical_plan_ctx()-> set_timeout_timestamp(min_timeout_ts + time_gap)); if (OB_SUCC(ret)) { do { @@ -5125,12 +5216,10 @@ int ObSPIService::inner_fetch_with_retry(ObPLExecCtx *ctx, OZ (schema_guard.get_schema_version(OB_SYS_TENANT_ID, sys_version)); OX (retry_ctrl.set_tenant_local_schema_version(tenant_version)); OX (retry_ctrl.set_sys_local_schema_version(sys_version)); - CK (OB_NOT_NULL(result_set)); - CK (OB_NOT_NULL(static_cast(result_set)->get_result_set())); if (OB_SUCC(ret)) { ret = inner_fetch(ctx, retry_ctrl, - result_set, + spi_result, into_exprs, into_count, column_types, @@ -5306,10 +5395,7 @@ int ObSPIService::get_result(ObPLExecCtx *ctx, OZ (row_desc.push_back(static_cast(result_set)->row_desc_.at(i))); } } else { - ObResultSet* spi_result_set = static_cast(result_set)->get_result_set(); - const common::ColumnsFieldIArray *fields = NULL != spi_result_set - ? spi_result_set->get_field_columns() - : NULL; + const common::ColumnsFieldIArray *fields = static_cast(result_set)->get_field_columns(); if (OB_ISNULL(fields)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); @@ -5502,8 +5588,8 @@ int ObSPIService::get_result(ObPLExecCtx *ctx, if (lib::is_oracle_mode()) { // for not found, fetch into and bulk into and returning into not report error. if (!for_cursor && !is_bulk) { - if (ObStmt::is_dml_write_stmt(static_cast - (result_set)->result_set().get_stmt_type())) { + if (ObStmt::is_dml_write_stmt(static_cast + (result_set)->get_stmt_type())) { // dml returning with dynamic sql need set into value to null if (is_dynamic_sql && into_count > 0) { STORE_INTO_RESULT(ObObj(ObNullType)); @@ -5522,10 +5608,11 @@ int ObSPIService::get_result(ObPLExecCtx *ctx, } } } else if (!for_cursor) { //虽然不需要存储结果,但是也需要把get_next调一遍 - ObInnerSQLResult *inner_result = static_cast(result_set); - if (inner_result->result_set().is_with_rows()) { // SELECT或DML RETURNING + ObResultSet *ob_result_set = static_cast(result_set); + if (ob_result_set->is_with_rows()) { // SELECT或DML RETURNING if (lib::is_oracle_mode()) { // ORACLE Mode: only iterate to end - while (OB_SUCC(inner_result->next())) { + const ObNewRow *row = NULL; + while (OB_SUCC(ob_result_set->get_next_row(row))) { row_count++; } implicit_cursor->set_rowcount(row_count); @@ -5540,31 +5627,31 @@ int ObSPIService::get_result(ObPLExecCtx *ctx, CK (OB_NOT_NULL(session_info = exec_ctx->get_my_session())); CK (OB_NOT_NULL( query_sender = static_cast(session_info->get_pl_query_sender()))); - OZ (query_sender->response_query_result(inner_result->result_set(), + OZ (query_sender->response_query_result(*ob_result_set, session_info->is_ps_protocol(), true, can_retry)); OZ (query_sender->send_eof_packet(true)); } - } else if (stmt::T_ANONYMOUS_BLOCK != inner_result->result_set().get_stmt_type()) { + } else if (stmt::T_ANONYMOUS_BLOCK != ob_result_set->get_stmt_type()) { // 不带Returing的INSERT,DELETE,UPDATE - if (stmt::T_UPDATE == inner_result->result_set().get_stmt_type()) { + if (stmt::T_UPDATE == ob_result_set->get_stmt_type()) { ObPhysicalPlanCtx *phy_ctx - = GET_PHY_PLAN_CTX(inner_result->result_set().get_exec_context()); + = GET_PHY_PLAN_CTX(ob_result_set->get_exec_context()); CK (OB_NOT_NULL(phy_ctx)); OX (implicit_cursor->set_rowcount(phy_ctx->get_row_matched_count())); } else { - implicit_cursor->set_rowcount(inner_result->result_set().get_affected_rows()); + implicit_cursor->set_rowcount(ob_result_set->get_affected_rows()); } } } else { /*do nothing*/ } if (OB_SUCC(ret) && !for_cursor) { - ObInnerSQLResult *inner_result = static_cast(result_set); - ObPhysicalPlan *physical_plan = inner_result->result_set().get_physical_plan(); + ObResultSet *ob_result_set = static_cast(result_set); + ObPhysicalPlan *physical_plan = ob_result_set->get_physical_plan(); ObPhysicalPlanCtx *plan_ctx = nullptr; if (OB_NOT_NULL(physical_plan)) { - if (OB_NOT_NULL(plan_ctx = GET_PHY_PLAN_CTX(inner_result->result_set().get_exec_context()))) { + if (OB_NOT_NULL(plan_ctx = GET_PHY_PLAN_CTX(ob_result_set->get_exec_context()))) { physical_plan->update_cache_access_stat(plan_ctx->get_table_scan_stat()); plan_ctx->get_table_scan_stat().reset_cache_stat(); if (is_forall) { @@ -6070,18 +6157,15 @@ int ObSPIService::store_datum(int64_t ¤t_addr, const ObObj &obj) return ret; } -int ObSPIService::fill_cursor(sqlclient::ObMySQLResult *mysql_result, ObSPICursor *cursor) +int ObSPIService::fill_cursor(ObResultSet &result_set, ObSPICursor *cursor) { int ret = OB_SUCCESS; - if (OB_ISNULL(mysql_result) || OB_ISNULL(cursor) - || OB_ISNULL(cursor->allocator_) - || OB_ISNULL(static_cast(mysql_result)->get_result_set())) { + if (OB_ISNULL(cursor) || OB_ISNULL(cursor->allocator_)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("Argument passed in is NULL", K(mysql_result), K(cursor), K(ret)); + LOG_WARN("Argument passed in is NULL", K(cursor), K(ret)); } else { - ObInnerSQLResult *inner_result = static_cast(mysql_result); - const common::ColumnsFieldIArray *fields = NULL != inner_result->get_result_set() - ? inner_result->result_set().get_field_columns() : NULL; + const common::ObNewRow *row = NULL; + const common::ColumnsFieldIArray *fields = result_set.get_field_columns(); if (OB_ISNULL(fields)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); @@ -6096,15 +6180,15 @@ int ObSPIService::fill_cursor(sqlclient::ObMySQLResult *mysql_result, ObSPICurso } } while (OB_SUCC(ret)) { - if (OB_FAIL(mysql_result->next())) { + if (OB_FAIL(result_set.get_next_row(row))) { //break - } else if (OB_ISNULL(inner_result->get_row())) { + } else if (OB_ISNULL(row)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get a invalud row", K(ret)); } else { - ObNewRow row = *(inner_result->get_row()); - for (int64_t i = 0; OB_SUCC(ret) && i < row.get_count(); ++i) { - ObObj& obj = row.get_cell(i); + ObNewRow tmp_row = *row; + for (int64_t i = 0; OB_SUCC(ret) && i < tmp_row.get_count(); ++i) { + ObObj& obj = tmp_row.get_cell(i); ObObj tmp; if (obj.is_pl_extend()) { if (OB_FAIL(pl::ObUserDefinedType::deep_copy_obj(*(cursor->allocator_), obj, tmp))) { @@ -6114,7 +6198,7 @@ int ObSPIService::fill_cursor(sqlclient::ObMySQLResult *mysql_result, ObSPICurso } } } - if (OB_SUCC(ret) && OB_FAIL(cursor->row_store_.add_row(row))) { + if (OB_SUCC(ret) && OB_FAIL(cursor->row_store_.add_row(tmp_row))) { LOG_WARN("failed to add row to row store", K(ret)); } } @@ -6151,14 +6235,12 @@ int ObSPIService::fetch_row(void *result_set, ++row_count; } } else { - ObInnerSQLResult *inner_result = static_cast(result_set); - if (OB_FAIL(inner_result->next())) { + ObResultSet *ob_result_set = static_cast(result_set); + const ObNewRow *row = NULL; + if (OB_FAIL(ob_result_set->get_next_row(row))) { //上层判断返回值,这里不打印信息 - } else if (OB_ISNULL(inner_result->get_row())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get a invalid row", K(ret)); } else { - cur_row = *inner_result->get_row(); + cur_row = *row; ++row_count; } } diff --git a/src/sql/ob_spi.h b/src/sql/ob_spi.h index de953f25a..081328247 100644 --- a/src/sql/ob_spi.h +++ b/src/sql/ob_spi.h @@ -18,12 +18,13 @@ #include "ob_sql_utils.h" #include "sql/engine/basic/ob_ra_row_store.h" #include "sql/session/ob_sql_session_info.h" - +#include "sql/ob_result_set.h" namespace oceanbase { namespace observer { class ObInnerSQLConnection; +class ObITimeRecord; class ObQueryRetryCtrl; } using common::ObPsStmtId; @@ -79,23 +80,53 @@ private: ObSEArray out_params_; // 用于记录function的返回值 }; +class PlMemEntifyDestroyGuard + { + public: + PlMemEntifyDestroyGuard(lib::MemoryContext &entity) : ref_(entity) {} + ~PlMemEntifyDestroyGuard() + { + if (NULL != ref_) { + DESTROY_CONTEXT(ref_); + ref_ = NULL; + } + } + private: + lib::MemoryContext &ref_; + }; + class ObSPIResultSet { public: ObSPIResultSet() - : need_end_nested_stmt_(EST_NEED_NOT), + : is_inited_(false), + need_end_nested_stmt_(EST_NEED_NOT), + mem_context_(nullptr), + mem_context_destroy_guard_(mem_context_), allocator_(ObModIds::OB_PL_TEMP), - mysql_result_(), + result_set_(NULL), + sql_ctx_(), + schema_guard_(), orign_nested_count_(-1), cursor_nested_count_(-1), orign_session_value_(NULL), cursor_session_value_(NULL), nested_session_value_(NULL), - out_params_() {} + out_params_() { + } ~ObSPIResultSet() { reset(); } + int init(sql::ObSQLSessionInfo &session_info); + int close_result_set(); void reset() { - mysql_result_.reset(); + //result_set_.reset(); + if (is_inited_) { + if (result_set_ != NULL) { + result_set_->~ObResultSet(); + } + } + sql_ctx_.reset(); + schema_guard_.reset(); need_end_nested_stmt_ = EST_NEED_NOT; orign_nested_count_ = -1; cursor_nested_count_ = -1; @@ -113,10 +144,24 @@ public: nested_session_value_ = NULL; out_params_.reset(); allocator_.reset(); + + is_inited_ = false; + } + void reset_member_for_retry(sql::ObSQLSessionInfo &session_info) + { + if (result_set_ != NULL) { + result_set_->~ObResultSet(); + } + sql_ctx_.reset(); + //allocator_.reset(); + mem_context_->get_arena_allocator().reset(); + result_set_ = new (buf_) ObResultSet(session_info, mem_context_->get_arena_allocator()); } - ObMySQLProxy::MySQLResult &get_mysql_result() { return mysql_result_; } - ObResultSet *get_result_set(); + lib::MemoryContext &get_memory_ctx() { return mem_context_; } + share::schema::ObSchemaGetterGuard &get_scheme_guard() { return schema_guard_; } + sql::ObSqlCtx &get_sql_ctx() { return sql_ctx_; } + ObResultSet *get_result_set() { return result_set_; } ObSPIOutParams &get_out_params() { return out_params_; } ObIAllocator &get_allocaor() { return allocator_; } int destruct_exec_params(ObSQLSessionInfo &session); @@ -152,10 +197,19 @@ public: int start_nested_stmt_if_need(pl::ObPLExecCtx *pl_ctx, stmt::StmtType stmt_type); void end_nested_stmt_if_need(pl::ObPLExecCtx *pl_ctx, int &result); private: + bool is_inited_; EndStmtType need_end_nested_stmt_; + lib::MemoryContext mem_context_; + // Memory of memory entity may referenced by sql_ctx_, use the guard to make + // sure memory entity destroyed after sql_ctx_ destructed. + PlMemEntifyDestroyGuard mem_context_destroy_guard_; ObArenaAllocator allocator_; // ObIAllocator *allocator_; - ObMySQLProxy::MySQLResult mysql_result_; + //ObMySQLProxy::MySQLResult mysql_result_; + char buf_[sizeof(sql::ObResultSet)] __attribute__ ((aligned (16))); + sql::ObResultSet *result_set_; + sql::ObSqlCtx sql_ctx_; // life period follow result_set_ + share::schema::ObSchemaGetterGuard schema_guard_; int64_t orign_nested_count_; int64_t cursor_nested_count_; sql::ObSQLSessionInfo::StmtSavedValue *orign_session_value_; @@ -169,7 +223,6 @@ class ObSPIService public: struct ObSPIPrepareResult { - ObPsStmtId id_; //prepare的语句id stmt::StmtType type_; //prepare的语句类型 bool for_update_; bool has_hidden_rowid_; @@ -180,6 +233,66 @@ public: pl::ObRecordType *record_type_; TgTimingEvent tg_timing_event_; uint64_t rowid_table_id_; + ObString ps_sql_; // sql prepare过后的参数化sql + }; + + struct PLPrepareCtx + { + PLPrepareCtx(ObSQLSessionInfo &sess_info, + pl::ObPLBlockNS *secondary_ns, + bool is_dynamic_sql, + bool is_dbms_sql, + bool is_cursor) + : sess_info_(sess_info), + secondary_ns_(secondary_ns), + is_dynamic_sql_(is_dynamic_sql), + is_dbms_sql_(is_dbms_sql), + is_cursor_(is_cursor) + { + } + ObSQLSessionInfo &sess_info_; // pl执行用到的session + pl::ObPLBlockNS *secondary_ns_; // sql resolve过程中用来查找是否是pl变量的名称空间 + union { + uint16_t flag_; + struct { + uint16_t is_dynamic_sql_ : 1; // 标记当前执行的sql是否是动态sql + uint16_t is_dbms_sql_ : 1; // 标记当前执行的sql是否是dbms_sql + uint16_t is_cursor_ : 1; // 标记当前执行的sql是否是cursor + uint16_t reserved_ : 13; + }; + }; + TO_STRING_KV(KP_(secondary_ns), K_(is_dynamic_sql), K_(is_dbms_sql), K_(is_cursor)); + }; + + class PLPrepareResult + { + public: + PLPrepareResult() : + mem_context_(nullptr), + mem_context_destroy_guard_(mem_context_), + sql_ctx_(), + schema_guard_() {} + ~PLPrepareResult() { reset(); } + int init(sql::ObSQLSessionInfo &session_info); + void reset() + { + //result_set_.reset(); + if (result_set_ != NULL) { + result_set_->~ObResultSet(); + } + sql_ctx_.reset(); + schema_guard_.reset(); + } + common::ObIAllocator *get_allocator() { return &mem_context_->get_arena_allocator(); } + public: + lib::MemoryContext mem_context_; + // Memory of memory entity may referenced by sql_ctx_, use the guard to make + // sure memory entity destroyed after sql_ctx_ destructed. + PlMemEntifyDestroyGuard mem_context_destroy_guard_; + char buf_[sizeof(sql::ObResultSet)] __attribute__ ((aligned (16))); + sql::ObResultSet *result_set_; + sql::ObSqlCtx sql_ctx_; // life period follow result_set_ + share::schema::ObSchemaGetterGuard schema_guard_; }; enum ObCusorDeclareLoc { @@ -247,7 +360,7 @@ public: pl::ObPLBlockNS *secondary_namespace, ObSPIPrepareResult &prepare_result); static int spi_execute(pl::ObPLExecCtx *ctx, - uint64_t id, + const char* ps_sql, int64_t type, const ObSqlExpression **param_exprs, int64_t param_count, @@ -310,7 +423,7 @@ public: ObCusorDeclareLoc loc); static int spi_cursor_open(pl::ObPLExecCtx *ctx, const char *sql, - uint64_t id, + const char *ps_sql, int64_t type, bool for_update, bool has_hidden_rowid, @@ -324,7 +437,7 @@ public: int64_t cursor_param_count); static int dbms_cursor_open(pl::ObPLExecCtx *ctx, pl::ObDbmsCursorInfo &cursor, - uint64_t stmt_id, + const ObString &ps_sql, int64_t stmt_type, bool for_update, bool has_hidden_rowid); @@ -427,14 +540,14 @@ public: ObDataType *dest_type, uint64_t package_id = OB_INVALID_ID); - static int spi_build_record_type_by_result_set(common::ObIAllocator &allocator, - ObSQLSessionInfo &session, - share::schema::ObSchemaGetterGuard &schema_guard, - const sql::ObResultSet &result_set, - int64_t hidden_column_count, - pl::ObRecordType *&record_type, - uint64_t &rowid_table_id, - pl::ObPLBlockNS *secondary_namespace); + static int spi_build_record_type(common::ObIAllocator &allocator, + ObSQLSessionInfo &session, + share::schema::ObSchemaGetterGuard &schema_guard, + const sql::ObResultSet &result_set, + int64_t hidden_column_count, + pl::ObRecordType *&record_type, + uint64_t &rowid_table_id, + pl::ObPLBlockNS *secondary_namespace); static int spi_construct_collection( pl::ObPLExecCtx *ctx, uint64_t package_id, ObObjParam *result); @@ -469,7 +582,7 @@ public: static int spi_interface_impl(pl::ObPLExecCtx* ctx, int64_t func_addr); static int process_function_out_result(pl::ObPLExecCtx *ctx, - ObMySQLProxy::MySQLResult &mysql_result, + ObResultSet &result_set, ObIArray &out_params); static int spi_pipe_row_to_result(pl::ObPLExecCtx *ctx, ObObjParam *single_row); @@ -497,20 +610,22 @@ public: static int prepare_dynamic(pl::ObPLExecCtx *ctx, const ObSqlExpression *sql_expr, + ObIAllocator &allocator, bool is_returning, int64_t param_cnt, ObSqlString &sql_str, - ObPsStmtId &id, + common::ObString &ps_sql, stmt::StmtType &type, bool &for_update, bool &hidden_rowid, int64_t &into_cnt); static int prepare_dynamic(pl::ObPLExecCtx *ctx, + ObIAllocator &allocator, bool is_returning, bool is_dbms_sql, int64_t param_cnt, ObSqlString &sql_str, - ObPsStmtId &id, + common::ObString &ps_sql, stmt::StmtType &type, bool &for_update, bool &hidden_rowid, @@ -526,14 +641,12 @@ public: static int spi_update_location(pl::ObPLExecCtx *ctx, uint64_t location); static int inner_open(pl::ObPLExecCtx *pl_ctx, - const char *sql_str, - uint64_t stmt_id, + const common::ObString &sql, + const common::ObString &ps_sql, int64_t stmt_type, ParamStore &exec_params, - ObMySQLProxy::MySQLResult &mysql_result, - ObSPIOutParams &out_params, - bool is_forall = false, - int32_t array_binding_count = 0); + ObSPIResultSet &spi_result, + ObSPIOutParams &out_params); static void adjust_pl_status_for_xa(sql::ObExecContext &ctx, int &result); @@ -592,7 +705,7 @@ private: static int spi_inner_execute(pl::ObPLExecCtx *ctx, const char *sql, - uint64_t id, + const char *ps_sql, int64_t type, const ObSqlExpression **param_exprs, int64_t param_count, @@ -606,11 +719,11 @@ private: bool is_forall = false); static int dbms_cursor_execute(pl::ObPLExecCtx *ctx, - uint64_t stmt_id, + const ObString ps_sql, stmt::StmtType stmt_type, pl::ObDbmsCursorInfo &cursor); - static int adjust_out_params(ObMySQLProxy::MySQLResult &mysql_result, + static int adjust_out_params(ObResultSet &result_set, ObSPIOutParams &out_params); static int adjust_out_params(pl::ObPLExecCtx *ctx, @@ -637,19 +750,20 @@ private: static int inner_open(pl::ObPLExecCtx *ctx, ObIAllocator ¶m_allocator, //用于拷贝执行期参数 const char* sql, - uint64_t id, + const char* ps_sql, int64_t type, const ObSqlExpression **param_exprs, int64_t param_count, const ObSqlExpression **into_exprs, int64_t into_count, - ObMySQLProxy::MySQLResult &mysql_result, + ObSPIResultSet &spi_result, ObSPIOutParams &out_params, + observer::ObQueryRetryCtrl *retry_ctrl = nullptr, bool is_forall = false); static int inner_fetch(pl::ObPLExecCtx *ctx, observer::ObQueryRetryCtrl &retry_ctrl, - sqlclient::ObMySQLResult *result_set, + ObSPIResultSet &spi_result, const ObSqlExpression **into_exprs, int64_t into_count, const ObDataType *column_types, @@ -669,7 +783,7 @@ private: int64_t return_type_count = 0); static int inner_fetch_with_retry( pl::ObPLExecCtx *ctx, - sqlclient::ObMySQLResult *result_set, + ObSPIResultSet &spi_result, const ObSqlExpression **into_exprs, int64_t into_count, const ObDataType *column_types, @@ -754,7 +868,7 @@ private: static int store_datum(int64_t ¤t_addr, const ObObj &obj); - static int fill_cursor(sqlclient::ObMySQLResult *mysql_result, ObSPICursor *cursor); + static int fill_cursor(ObResultSet &result_set, ObSPICursor *cursor); static const ObPostExprItem &get_last_expr_item(const ObSqlExpression &expr); @@ -799,7 +913,7 @@ private: static int dynamic_out_params( common::ObIAllocator &allocator, - sqlclient::ObMySQLResult *result, common::ObObjParam **params, int64_t param_count); + ObResultSet *result, common::ObObjParam **params, int64_t param_count); static int cursor_close_impl(pl::ObPLExecCtx *ctx, pl::ObPLCursorInfo *cursor, @@ -822,6 +936,7 @@ private: const ObDataType *return_types = nullptr, int64_t return_type_count = 0); + static int check_package_dest_and_deep_copy(pl::ObPLExecCtx &ctx, const ObSqlExpression &expr, ObIArray &src_array, diff --git a/src/sql/ob_sql.cpp b/src/sql/ob_sql.cpp index 7327f8a43..80dc68741 100644 --- a/src/sql/ob_sql.cpp +++ b/src/sql/ob_sql.cpp @@ -237,7 +237,10 @@ int ObSql::stmt_list_field(const common::ObString &table_name, return OB_NOT_IMPLEMENT; } -int ObSql::fill_result_set(ObResultSet &result_set, ObSqlCtx *context, const bool is_ps_mode, ObStmt &basic_stmt) +int ObSql::fill_result_set(ObResultSet &result_set, + ObSqlCtx *context, + const PlanCacheMode mode, + ObStmt &basic_stmt) { int ret = OB_SUCCESS; @@ -265,7 +268,7 @@ int ObSql::fill_result_set(ObResultSet &result_set, ObSqlCtx *context, const boo ObCharset::get_default_collation_by_mode(result_charset, lib::is_oracle_mode()); switch (stmt->get_stmt_type()) { case stmt::T_SELECT: { - if (OB_FAIL(fill_select_result_set(result_set, context, is_ps_mode, collation_type, type_name, + if (OB_FAIL(fill_select_result_set(result_set, context, mode, collation_type, type_name, basic_stmt, field))) { LOG_WARN("fill select result set failed", K(ret)); } @@ -517,7 +520,9 @@ int ObSql::fill_result_set(ObResultSet &result_set, ObSqlCtx *context, const boo const int64_t question_marks_count = pctx->get_is_ps_rewrite_sql() ? pctx->get_orig_question_mark_cnt() : stmt->get_query_ctx()->get_prepare_param_count(); - if (OB_SUCC(ret) && is_ps_mode && question_marks_count > 0) { // param column is only needed in ps mode + // param column is only needed in ps mode + if (OB_SUCC(ret) && question_marks_count > 0 + && (PC_PS_MODE == mode || PC_PL_MODE == mode)) { if (OB_FAIL(result_set.reserve_param_columns(question_marks_count))) { LOG_WARN("reserve param columns failed", K(ret), K(question_marks_count)); } @@ -548,7 +553,8 @@ int ObSql::fill_result_set(ObResultSet &result_set, ObSqlCtx *context, const boo } // for resolve returning_params and only work for ps_mode // SQL: insert/update/delete ...returning expr1 ... into ?... - if (OB_SUCC(ret) && ObStmt::is_dml_write_stmt(stmt->get_stmt_type()) && is_ps_mode) { + if (OB_SUCC(ret) && ObStmt::is_dml_write_stmt(stmt->get_stmt_type()) + && (PC_PS_MODE == mode || PC_PL_MODE == mode)) { del_upd_stmt = static_cast(stmt); if (del_upd_stmt->is_returning()) { int64_t returning_param_num = del_upd_stmt->get_returning_exprs().count(); @@ -569,7 +575,7 @@ int ObSql::fill_result_set(ObResultSet &result_set, ObSqlCtx *context, const boo return ret; } -int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, const bool is_ps_mode, +int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, const PlanCacheMode mode, ObCollationType collation_type, const ObString &type_name, ObStmt &basic_stmt, ObField &field) { @@ -748,7 +754,7 @@ int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, co } } } - if (OB_SUCC(ret) && !is_ps_mode) { + if (OB_SUCC(ret) && !(PC_PS_MODE == mode || PC_PL_MODE == mode)) { void *buf = NULL; if (OB_ISNULL(buf = alloc.alloc(sizeof(ObParamedSelectItemCtx)))) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -913,8 +919,8 @@ int ObSql::do_real_prepare(const ObString &sql, bool is_from_pl = (NULL != context.secondary_namespace_ || result.is_simple_ps_protocol()); ObPsPrepareStatusGuard ps_status_guard(session, is_from_pl); - ObPlanCacheCtx pc_ctx(sql, true, /*is_ps_mode*/ - allocator, context, ectx, session.get_effective_tenant_id()); + ObPlanCacheCtx pc_ctx(sql, PC_PS_MODE, allocator, context, ectx, + session.get_effective_tenant_id()); ParamStore param_store( (ObWrapperAllocator(&allocator)) ); omt::ObTenantConfigGuard tenant_config(TENANT_CONF(session.get_effective_tenant_id())); pc_ctx.set_is_inner_sql(is_inner_sql); @@ -1005,7 +1011,7 @@ int ObSql::do_real_prepare(const ObString &sql, LOG_WARN("query ctx is null", K(ret)); } else if (stmt::T_CALL_PROCEDURE == basic_stmt->get_stmt_type() && FALSE_IT(result.set_cmd(dynamic_cast(basic_stmt)))) { - } else if (OB_FAIL(fill_result_set(result, &context, true, *basic_stmt))) { + } else if (OB_FAIL(fill_result_set(result, &context, PC_PS_MODE, *basic_stmt))) { LOG_WARN("Failed to fill result set", K(ret)); } else if (OB_ISNULL(result.get_param_fields())) { ret = OB_INVALID_ARGUMENT; @@ -1066,6 +1072,376 @@ int ObSql::do_real_prepare(const ObString &sql, return ret; } + +ObSql::TimeoutGuard::TimeoutGuard(ObSQLSessionInfo &session) + : session_(session) +{ + int ret = OB_SUCCESS; + worker_timeout_ = THIS_WORKER.get_timeout_ts(); + if (OB_FAIL(session_.get_query_timeout(query_timeout_)) + || OB_FAIL(session_.get_tx_timeout(trx_timeout_))) { + LOG_ERROR("get timeout failed", KR(ret), K(query_timeout_), K(trx_timeout_)); + } +} + +ObSql::TimeoutGuard::~TimeoutGuard() +{ + int ret = OB_SUCCESS; + if (THIS_WORKER.get_timeout_ts() != worker_timeout_) { + THIS_WORKER.set_timeout_ts(worker_timeout_); + } + int64_t query_timeout = 0; + int64_t trx_timeout = 0; + if (OB_FAIL(session_.get_query_timeout(query_timeout)) + || OB_FAIL(session_.get_tx_timeout(trx_timeout))) { + LOG_ERROR("get timeout failed", KR(ret), K(query_timeout), K(trx_timeout)); + } else { + if (query_timeout != query_timeout_ || trx_timeout != trx_timeout_) { + ObObj query_val, trx_val; + query_val.set_int(query_timeout_); + trx_val.set_int(trx_timeout_); + if (OB_FAIL(ret)) { + } else if (OB_FAIL(session_.update_sys_variable(SYS_VAR_OB_QUERY_TIMEOUT, query_val))) { + LOG_WARN("set sys variable failed", K(ret), K(OB_SV_QUERY_TIMEOUT), K(query_val)); + } else if (OB_FAIL(session_.update_sys_variable(SYS_VAR_OB_TRX_TIMEOUT, trx_val))) { + LOG_WARN("set sys variable failed", K(ret), K(OB_SV_TRX_TIMEOUT), K(trx_val)); + } + } + } +} + +int ObSql::set_timeout_for_pl(ObSQLSessionInfo &session_info, int64_t &abs_timeout_us) +{ + int ret = OB_SUCCESS; + int64_t query_timeout; + if (OB_FAIL(session_info.get_query_timeout(query_timeout))) { + // do nothing + } else { + OX (abs_timeout_us = session_info.get_query_start_time() > 0 + ? session_info.get_query_start_time() + query_timeout + : ObTimeUtility::current_time() + query_timeout); + if (THIS_WORKER.get_timeout_ts() > abs_timeout_us) { + OX (THIS_WORKER.set_timeout_ts(abs_timeout_us)); + } + } + return ret; +} + +/* + * sql: pl 中的 sql 语句 + * PLPrepareCtx: prepare 用到的相关信息 + * PLPrepareResult: prepare 后的输出结果 + */ + +int ObSql::handle_pl_prepare(const ObString &sql, + ObSPIService::PLPrepareCtx &pl_prepare_ctx, + ObSPIService::PLPrepareResult &pl_prepare_result) +{ + int ret = OB_SUCCESS; + ObString cur_query; + ObString trimed_stmt = const_cast(sql).trim(); + ObSqlCtx &context = pl_prepare_result.sql_ctx_; + int64_t param_cnt = 0; + ObString normalized_sql; + ParseResult parse_result; + ObStmt *basic_stmt = NULL; + int64_t cur_timeout_us = 0; + stmt::StmtType stmt_type = stmt::T_NONE; + ObSchemaGetterGuard &schema_guard = pl_prepare_result.schema_guard_; + ObSQLSessionInfo &sess = pl_prepare_ctx.sess_info_; + TimeoutGuard timeout_guard(sess); + int64_t old_query_start_time = sess.get_query_start_time(); + sess.set_query_start_time(ObTimeUtility::current_time()); + CK (OB_NOT_NULL(pl_prepare_result.get_allocator())); + CK (OB_NOT_NULL(pl_prepare_result.result_set_)); + if (OB_SUCC(ret)) { + ObIAllocator &allocator = *pl_prepare_result.get_allocator(); + ObParser parser(allocator, sess.get_sql_mode(), sess.get_local_collation_connection()); + ParseMode parse_mode = pl_prepare_ctx.is_dbms_sql_ ? DBMS_SQL_MODE : + pl_prepare_ctx.is_dynamic_sql_ ? DYNAMIC_SQL_MODE : + sess.is_for_trigger_package() ? TRIGGER_MODE : STD_MODE; + + if (OB_SUCC(ret)) { + context.is_dynamic_sql_ = pl_prepare_ctx.is_dynamic_sql_; + context.is_dbms_sql_ = pl_prepare_ctx.is_dbms_sql_; + context.is_cursor_ = pl_prepare_ctx.is_cursor_; + context.secondary_namespace_ = pl_prepare_ctx.secondary_ns_; + context.session_info_ = &sess; + context.disable_privilege_check_ = OB_SYS_TENANT_ID == sess.get_priv_tenant_id() + ? PRIV_CHECK_FLAG_DISABLE + : PRIV_CHECK_FLAG_IN_PL; + context.exec_type_ = PLSql; + context.is_prepare_protocol_ = true; + context.is_prepare_stage_ = true; + } + if (OB_SUCC(ret)) { + WITH_CONTEXT(pl_prepare_result.mem_context_) { + ObResultSet &result = *pl_prepare_result.result_set_; + LinkExecCtxGuard link_guard(result.get_session(), result.get_exec_context()); + if (trimed_stmt.empty()) { + ret = OB_ERR_EMPTY_QUERY; + LOG_WARN("query is empty", K(ret)); + } else if (OB_FAIL(set_timeout_for_pl(sess, cur_timeout_us))) { + LOG_WARN("failed to set timeout for pl", K(ret)); + } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard( + sess.get_effective_tenant_id(), schema_guard))) { + LOG_WARN("failed to get tenant schema guard", K(ret)); + } else if (FALSE_IT(context.schema_guard_ = &schema_guard)) { + } else if (OB_FAIL(init_result_set(context, result))) { + LOG_WARN("failed to init result set", K(ret)); + } else if (OB_FAIL(ob_write_string(allocator, sess.get_current_query_string(), cur_query))) { + LOG_WARN("failed to write string", K(ret)); + } else if (OB_FAIL(sess.store_query_string(trimed_stmt))) { + LOG_WARN("store query string fail", K(ret)); + } else if (OB_FAIL(parser.parse(sql, parse_result, parse_mode, false, false))) { + LOG_WARN("generate syntax tree failed", K(sql), K(ret)); + } else if (is_mysql_mode() && ObSQLUtils::is_mysql_ps_not_support_stmt(parse_result)) { + ret = OB_ER_UNSUPPORTED_PS; + LOG_WARN("This command is not supported in the prepared statement protocol yet", K(ret)); + } else if (NULL == pl_prepare_ctx.secondary_ns_ && !pl_prepare_ctx.is_dynamic_sql_) { + result.set_simple_ps_protocol(); + } + + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(ObResolverUtils::resolve_stmt_type(parse_result, stmt_type))) { + LOG_WARN("failed to resolve stmt type", K(ret)); + } else if (FALSE_IT(result.set_stmt_type(stmt_type))) { + } else if (result.is_simple_ps_protocol() + || (stmt::T_ANONYMOUS_BLOCK == stmt_type && 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; + if (stmt::T_ANONYMOUS_BLOCK == stmt_type && context.is_prepare_protocol_ + && context.is_prepare_stage_ && context.is_pre_execute_) { + OZ (result.reserve_param_columns(param_cnt)); + for (int64_t i = 0; OB_SUCC(ret) && i < param_cnt; ++i) { + ObField param_field; + param_field.type_.set_type(ObIntType); + param_field.cname_ = ObString::make_string("?"); + OZ (result.add_param_column(param_field), K(param_field), K(i), K(param_cnt)); + } + } + } 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_; + } + if (OB_FAIL(generate_stmt(parse_result, NULL, context, allocator, result, basic_stmt))) { + LOG_WARN("generate stmt failed", K(ret)); + } else if (OB_ISNULL(basic_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("generate stmt success, but stmt is NULL", K(ret)); + } else if (OB_ISNULL(basic_stmt->get_query_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("query ctx is null", K(ret)); + } else if (stmt::T_CALL_PROCEDURE == basic_stmt->get_stmt_type() + && FALSE_IT(result.set_cmd(dynamic_cast(basic_stmt)))) { + } else if (OB_FAIL(fill_result_set(result, &context, PC_PL_MODE, *basic_stmt))) { + LOG_WARN("Failed to fill result set", K(ret)); + } else if (OB_ISNULL(result.get_param_fields())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(result.get_param_fields()), K(ret)); + } else { + normalized_sql = basic_stmt->get_query_ctx()->get_sql_stmt(); + } + } + + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(ob_write_string(allocator, normalized_sql, result.get_stmt_ps_sql(), true))) { + LOG_WARN("failed to write string", K(trimed_stmt), K(ret)); + } else if (OB_FAIL(sess.store_query_string(cur_query))) { + LOG_WARN("failed to store query string", K(ret)); + } else { + // do nothing + } + } + } + } + sess.set_query_start_time(old_query_start_time); + return ret; +} + +int ObSql::handle_sql_execute(const ObString &sql, + ObSqlCtx &context, + ObResultSet &result, + ParamStore &org_params, + PlanCacheMode mode) +{ + int ret = OB_SUCCESS; + int get_plan_err = OB_SUCCESS; + bool use_plan_cache = false; + ObIAllocator &allocator = result.get_mem_pool(); + ObSQLSessionInfo *session = context.session_info_; + ObExecContext &ectx = result.get_exec_context(); + ObPhysicalPlanCtx *pctx = ectx.get_physical_plan_ctx(); + ParamStore params( (ObWrapperAllocator(allocator)) ); + ParamStore *ab_params = NULL; + + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(session) || OB_ISNULL(session->get_plan_cache())) { + ret = OB_INVALID_ARGUMENT; + } else if ((mode == PC_PS_MODE || mode == PC_PL_MODE) && OB_ISNULL(pctx)) { + ret = OB_INVALID_ARGUMENT; + } else { + use_plan_cache = session->get_local_ob_enable_plan_cache(); + } + + ObPlanCacheCtx pc_ctx(sql, mode, allocator, context, ectx, session->get_effective_tenant_id()); + + if (OB_FAIL(ret)) { + // do nothing + } else if (mode == PC_PL_MODE) { + if (OB_FAIL(reconstruct_pl_params_store(allocator, context, org_params, params, ab_params))) { + LOG_WARN("failed to reconstruct pl params", K(ret)); + } else if (context.multi_stmt_item_.is_batched_multi_stmt() && OB_ISNULL(ab_params)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("pl ab params is null", K(ret)); + } else if (OB_FAIL(construct_param_store(params, pctx->get_param_store_for_update()))) { + LOG_WARN("construct param store failed", K(ret)); + } else if (OB_FAIL(construct_parameterized_params(params, pc_ctx))) { + LOG_WARN("construct parameterized params failed", K(ret)); + } else { + pc_ctx.normal_parse_const_cnt_ = params.count(); + pc_ctx.set_is_parameterized_execute(); + pc_ctx.ab_params_ = ab_params; + } + } else if (mode == PC_PS_MODE) { + // TODO, not support ps now. + ret = OB_ERR_UNEXPECTED; + } + + if (OB_SUCC(ret)) { + if (!use_plan_cache) { + // do nothing + } else if (OB_FAIL(pc_get_plan_and_fill_result(pc_ctx, result, + get_plan_err, ectx.get_need_disconnect_for_update()))) { + LOG_WARN("failed to get plan", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (!result.get_is_from_plan_cache()) { + if (mode == PC_PS_MODE || mode == PC_PL_MODE) { + pctx->get_param_store_for_update().reset(); + } + if (OB_FAIL(handle_physical_plan(sql, context, result, pc_ctx, get_plan_err, mode))) { + if (OB_ERR_PROXY_REROUTE == ret) { + LOG_DEBUG("fail to handle physical plan", K(ret)); + } else { + LOG_WARN("fail to handle physical plan", K(ret)); + } + } + } + } + + if (OB_SUCC(ret) && !(org_params.count() == 0 && context.is_prepare_protocol_)) { + if (OB_FAIL(after_get_plan(pc_ctx, *session, result.get_physical_plan(), + result.get_is_from_plan_cache(), ¶ms))) { + LOG_WARN("fail to handle after get plan", K(ret)); + } + } + + return ret; +} + +/*! + * sql: 需要被执行的sql语句 + * params: 当前sql语句的参数列表 + * res: 直接结果集 + */ +// TODO baixian.zr/hr351303, remove is_prepare_protocol and is_dynamic_sql +int ObSql::handle_pl_execute(const ObString &sql, + ObSQLSessionInfo &session, + ParamStore ¶ms, + ObResultSet &result, + ObSqlCtx &context, + bool is_prepare_protocol, + bool is_dynamic_sql) +{ + int ret = OB_SUCCESS; + int get_plan_err = OB_SUCCESS; + TimeoutGuard timeout_guard(session); + LinkExecCtxGuard link_guard(result.get_session(), result.get_exec_context()); + int64_t cur_timeout_us = 0; + context.session_info_ = &session; + ObIAllocator &allocator = result.get_mem_pool(); + ObExecContext &ectx = result.get_exec_context(); + ObPhysicalPlanCtx *pctx = NULL; + + if (OB_FAIL(ret)) { + } else if (OB_FAIL(result.init())) { + LOG_WARN("failed to init result_set", K(ret)); + } else if (OB_FAIL(init_result_set(context, result))) { + LOG_WARN("failed to init result set", K(ret)); + } else { + context.cur_sql_ = sql; + context.is_dynamic_sql_ = is_dynamic_sql; + context.is_prepare_protocol_ = is_prepare_protocol; + context.disable_privilege_check_ = OB_SYS_TENANT_ID == session.get_priv_tenant_id() + ? PRIV_CHECK_FLAG_DISABLE + : PRIV_CHECK_FLAG_IN_PL; + pctx = ectx.get_physical_plan_ctx(); + ectx.get_das_ctx().get_schema_guard() = context.schema_guard_; + } + if (OB_SUCC(ret) && is_prepare_protocol && !is_dynamic_sql) { + result.set_simple_ps_protocol(); + } + if (OB_SUCC(ret) && params.count() == 0) { + context.is_prepare_protocol_ = false; // text protocol + } + + LOG_TRACE("arrive handle pl execute", K(ret), K(sql), K(is_prepare_protocol), K(is_dynamic_sql), K(lbt())); + + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(pctx)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguement", K(ret)); + } else if (OB_FAIL(set_timeout_for_pl(session, cur_timeout_us))) { + LOG_WARN("failed to set timeout for pl", K(ret)); + } else if (OB_FAIL(session.store_query_string(sql))) { + LOG_WARN("store query string fail", K(ret)); + } else if (OB_FAIL(handle_sql_execute(sql, context, result, params, PC_PL_MODE))) { + LOG_WARN("failed to handle sql execute", K(ret)); + } else { + result.get_session().set_exec_min_cluster_version(); + } + + if (OB_FAIL(ret) && OB_SUCCESS == result.get_errcode()) { + result.set_errcode(ret); + } + //todo:@hr351303下面的逻辑后续挪到spi层 + if (OB_SUCC(ret)) { + if (OB_ISNULL(context.schema_guard_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("schema guard is null"); + } else if (OB_FAIL(session.update_query_sensitive_system_variable(*(context.schema_guard_)))) { + LOG_WARN("update query affacted system variable failed", K(ret)); + } else if (OB_FAIL(result.open())) { + LOG_WARN("result set open failed", K(ret)); + } else { + // do nothing + } + } + + + if (session.get_in_transaction()) { + if (ObStmt::is_dml_write_stmt(result.get_stmt_type())) { + session.set_has_inner_dml_write(true); + } + } + FLT_SET_TAG(sql_id, context.sql_id_); + return ret; +} + int ObSql::handle_ps_prepare(const ObString &stmt, ObSqlCtx &context, ObResultSet &result, @@ -1240,15 +1616,15 @@ int ObSql::add_param_to_param_store(const ObObjParam ¶m, return ret; } -int ObSql::construct_param_store_from_ps_param(const ObPlanCacheCtx &phy_ctx, +int ObSql::construct_param_store_from_parameterized_params(const ObPlanCacheCtx &phy_ctx, ParamStore ¶m_store) { int ret = OB_SUCCESS; - if (OB_FAIL(param_store.reserve(phy_ctx.fp_result_.ps_params_.count()))) { + if (OB_FAIL(param_store.reserve(phy_ctx.fp_result_.parameterized_params_.count()))) { LOG_WARN("failed to reserve array", K(ret)); } - for (int i = 0; OB_SUCC(ret) && i < phy_ctx.fp_result_.ps_params_.count(); ++i) { - const common::ObObjParam *param = phy_ctx.fp_result_.ps_params_.at(i); + for (int i = 0; OB_SUCC(ret) && i < phy_ctx.fp_result_.parameterized_params_.count(); ++i) { + const common::ObObjParam *param = phy_ctx.fp_result_.parameterized_params_.at(i); if (OB_FAIL(add_param_to_param_store(*param, param_store))) { LOG_WARN("failed to add param to param store", K(ret)); } @@ -1328,15 +1704,15 @@ int ObSql::construct_param_store(const ParamStore ¶ms, return ret; } -int ObSql::construct_ps_param(const ParamStore ¶ms, - ObPlanCacheCtx &phy_ctx) +int ObSql::construct_parameterized_params(const ParamStore ¶ms, + ObPlanCacheCtx &phy_ctx) { int ret = OB_SUCCESS; - phy_ctx.fp_result_.ps_params_.reset(); - phy_ctx.fp_result_.ps_params_.set_allocator(&phy_ctx.allocator_); - phy_ctx.fp_result_.ps_params_.set_capacity(params.count()); + phy_ctx.fp_result_.parameterized_params_.reset(); + phy_ctx.fp_result_.parameterized_params_.set_allocator(&phy_ctx.allocator_); + phy_ctx.fp_result_.parameterized_params_.set_capacity(params.count()); for (int i = 0; OB_SUCC(ret) && i < params.count(); ++i) { - if (OB_FAIL(phy_ctx.fp_result_.ps_params_.push_back(¶ms.at(i)))) { + if (OB_FAIL(phy_ctx.fp_result_.parameterized_params_.push_back(¶ms.at(i)))) { LOG_WARN("add ps param failed", K(ret)); } } @@ -1405,10 +1781,14 @@ int ObSql::init_execute_params_for_ab(ObIAllocator &allocator, ParamStore *&first_group_params) { int ret = OB_SUCCESS; - if (OB_ISNULL(first_group_params = static_cast(allocator.alloc(sizeof(ParamStore))))) { + if (OB_NOT_NULL(first_group_params)) { + // do nothing + } else if (OB_ISNULL(first_group_params = static_cast(allocator.alloc(sizeof(ParamStore))))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else if (FALSE_IT(first_group_params = new(first_group_params)ParamStore(ObWrapperAllocator(allocator)))) { + } + if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(ObPlanCacheValue::get_one_group_params(0, params_store, *first_group_params))) { LOG_WARN("fail to get the first group paramsters", K(ret)); @@ -1422,6 +1802,34 @@ int ObSql::init_execute_params_for_ab(ObIAllocator &allocator, return ret; } +int ObSql::reconstruct_pl_params_store(ObIAllocator &allocator, + ObSqlCtx &context, + const ParamStore &origin_params, + ParamStore &pl_params, + ParamStore *&pl_ab_params) +{ + int ret = OB_SUCCESS; + if (context.multi_stmt_item_.is_batched_multi_stmt()) { + ParamStore *first_group_params = &pl_params; + if (OB_FAIL(init_execute_params_for_ab(allocator, origin_params, first_group_params))) { + LOG_WARN("fail to init first batch params", K(ret), K(origin_params)); + } else if (OB_ISNULL(pl_ab_params = static_cast(allocator.alloc(sizeof(ParamStore))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret)); + } else if (FALSE_IT(pl_ab_params = new(pl_ab_params)ParamStore(ObWrapperAllocator(allocator)))) { + // do nothing + } else if (OB_FAIL(construct_param_store(origin_params, + *pl_ab_params))) { + LOG_WARN("construct param store failed", K(ret)); + } + } else { + if (OB_FAIL(construct_param_store(origin_params, pl_params))) { + LOG_WARN("construct param store failed", K(ret)); + } + } + return ret; +} + int ObSql::reconstruct_ps_params_store(ObIAllocator &allocator, ObSqlCtx &context, const ParamStore &origin_params, @@ -1545,16 +1953,16 @@ int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id, } else if (FALSE_IT(generate_ps_sql_id(sql, context))) { } else if (OB_LIKELY(ObStmt::is_dml_stmt(stmt_type))) { //if plan not exist, generate plan - ObPlanCacheCtx pc_ctx(sql, true, /*is_ps_mode*/ - allocator, context, ectx, session.get_effective_tenant_id()); + ObPlanCacheCtx pc_ctx(sql, PC_PS_MODE, allocator, context, ectx, + session.get_effective_tenant_id()); pc_ctx.fp_result_.pc_key_.key_id_ = inner_stmt_id; pc_ctx.normal_parse_const_cnt_ = ps_params.count(); context.spm_ctx_.bl_key_.db_id_ = session.get_database_id(); - pc_ctx.set_is_ps_execute_stage(); + pc_ctx.set_is_parameterized_execute(); pc_ctx.set_is_inner_sql(is_inner_sql); pc_ctx.ab_params_ = ps_ab_params; - if (OB_FAIL(construct_ps_param(ps_params, pc_ctx))) { - LOG_WARN("construct_ps_param failed", K(ret)); + if (OB_FAIL(construct_parameterized_params(ps_params, pc_ctx))) { + LOG_WARN("construct parameterized params failed", K(ret)); } else { if (!use_plan_cache) { /*do nothing*/ @@ -1567,7 +1975,7 @@ int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id, } else if (!result.get_is_from_plan_cache()) { pctx->set_original_param_cnt(origin_params_count); pctx->get_param_store_for_update().reset(); - if (OB_FAIL(handle_physical_plan(sql, context, result, pc_ctx, get_plan_err, true))) { + if (OB_FAIL(handle_physical_plan(sql, context, result, pc_ctx, get_plan_err, PC_PS_MODE))) { if (OB_ERR_PROXY_REROUTE == ret) { LOG_DEBUG("fail to handle physical plan", K(ret)); } else { @@ -1587,7 +1995,7 @@ int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id, ParseResult parse_result; MEMSET(&parse_result, 0, SIZEOF(ParseResult)); if (OB_FAIL(generate_physical_plan(parse_result, NULL, context, result, - false/*is_begin_commit_stmt*/, true))) { + false/*is_begin_commit_stmt*/, PC_PS_MODE))) { LOG_WARN("generate physical plan failed", K(ret)); } else { const ObPsSqlMeta &sql_meta = ps_info->get_ps_sql_meta(); @@ -1625,7 +2033,7 @@ int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id, if (OB_FAIL(ret)) { } else if (OB_FAIL(generate_physical_plan( - parse_result, NULL, context, result, false /*is_begin_commit_stmt*/, true))) { + parse_result, NULL, context, result, false /*is_begin_commit_stmt*/, PC_PS_MODE))) { LOG_WARN("generate physical plan failed", K(ret), K(sql), K(stmt_type)); } // TODO 生成物理计划的路径可x需q区分 } @@ -1667,9 +2075,10 @@ int ObSql::handle_remote_query(const ObRemoteSqlInfo &remote_sql_info, const uint64_t tenant_id = session->get_effective_tenant_id(); bool use_plan_cache = session->get_local_ob_enable_plan_cache(); context.self_add_plan_ = false; + PlanCacheMode mode = remote_sql_info.use_ps_ ? PC_PS_MODE : PC_TEXT_MODE; context.cur_sql_ = trimed_stmt; pc_ctx = new (pc_ctx) ObPlanCacheCtx(trimed_stmt, - remote_sql_info.use_ps_, /*is_ps_mode*/ + mode, allocator, context, exec_ctx, @@ -1684,12 +2093,12 @@ int ObSql::handle_remote_query(const ObRemoteSqlInfo &remote_sql_info, pc_ctx->fp_result_.pc_key_.key_id_ = 0; pc_ctx->fp_result_.pc_key_.name_ = trimed_stmt; pc_ctx->normal_parse_const_cnt_ = remote_sql_info.ps_params_->count(); + pc_ctx->set_is_parameterized_execute(); pc_ctx->is_original_ps_mode_ = remote_sql_info.is_original_ps_mode_; - pc_ctx->set_is_ps_execute_stage(); if (OB_FAIL(construct_param_store(*remote_sql_info.ps_params_, param_store))) { LOG_WARN("construct param store failed", K(ret)); - } else if (OB_FAIL(construct_ps_param(param_store, *pc_ctx))) { - LOG_WARN("construct_ps_param failed", K(ret)); + } else if (OB_FAIL(construct_parameterized_params(param_store, *pc_ctx))) { + LOG_WARN("construct parameterized params failed", K(ret)); } } else if (remote_sql_info.is_batched_stmt_) { //这里保持跟控制端一致,如果是batched stmt,需要先做一次parser的切分 @@ -1743,11 +2152,12 @@ int ObSql::handle_remote_query(const ObRemoteSqlInfo &remote_sql_info, tmp_result.set_exec_context(exec_ctx); //经过plan cache的计算后,param_store里的值可能会增加,因为plan cache中会执行pre calculation //这里要再进行计划生成,需要把plan cache中pre calculation加入的param清除掉 - int64_t initial_param_count = pc_ctx->fp_result_.ps_params_.count(); + int64_t initial_param_count = pc_ctx->fp_result_.parameterized_params_.count(); for (int64_t i = remote_sql_info.ps_params_->count(); i > initial_param_count; --i) { remote_sql_info.ps_params_->pop_back(); } - if (OB_FAIL(handle_physical_plan(trimed_stmt, context, tmp_result, *pc_ctx, get_plan_err, remote_sql_info.use_ps_))) { + PlanCacheMode mode = remote_sql_info.use_ps_ ? PC_PS_MODE : PC_TEXT_MODE; + if (OB_FAIL(handle_physical_plan(trimed_stmt, context, tmp_result, *pc_ctx, get_plan_err, mode))) { if (OB_ERR_PROXY_REROUTE == ret) { LOG_DEBUG("fail to handle physical plan", K(ret)); } else { @@ -1861,7 +2271,7 @@ OB_INLINE int ObSql::handle_text_query(const ObString &stmt, ObSqlCtx &context, } else { context.cur_sql_ = trimed_stmt; pc_ctx = new (buf) ObPlanCacheCtx(trimed_stmt, - false, /*is_ps_mode*/ + PC_TEXT_MODE, allocator, context, ectx, @@ -2114,8 +2524,6 @@ int ObSql::generate_stmt(ParseResult &parse_result, KP(parse_result.result_tree_->children_[0])); } - - if (OB_SUCC(ret)) { // set # of question marks if (context.is_prepare_protocol_ && !context.is_prepare_stage_) { @@ -2286,7 +2694,7 @@ int ObSql::generate_physical_plan(ParseResult &parse_result, ObSqlCtx &sql_ctx, ObResultSet &result, const bool is_begin_commit_stmt, - const bool is_ps_mode /* false */, + const PlanCacheMode mode, ParseResult *outline_parse_result /* null */ ) { int ret = OB_SUCCESS; @@ -2349,7 +2757,7 @@ int ObSql::generate_physical_plan(ParseResult &parse_result, } else if (OB_ISNULL(result.get_exec_context().get_stmt_factory()->get_query_ctx())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("query ctx is null", K(ret)); - } else if (OB_FAIL(fill_result_set(result, &sql_ctx, is_ps_mode, *basic_stmt))) { + } else if (OB_FAIL(fill_result_set(result, &sql_ctx, mode, *basic_stmt))) { LOG_WARN("Failed to fill result set", K(ret)); } else if (OB_FAIL(sql_ctx.session_info_->get_sys_variable(share::SYS_VAR__AGGREGATION_OPTIMIZATION_SETTINGS, aggregate_setting))) { @@ -2509,7 +2917,7 @@ int ObSql::generate_physical_plan(ParseResult &parse_result, result.set_cmd(cmd); result.get_session().set_cur_sql_id(sql_ctx.sql_id_); if (!is_begin_commit_stmt - && OB_FAIL(fill_result_set(result, &sql_ctx, is_ps_mode, *basic_stmt))) { + && OB_FAIL(fill_result_set(result, &sql_ctx, mode, *basic_stmt))) { LOG_WARN("Failed to fill result set", K(ret)); } } @@ -2945,7 +3353,8 @@ int ObSql::execute_get_plan(ObPlanCache &plan_cache, if (OB_ISNULL(session) || OB_ISNULL(pctx)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is NULL", K(ret)); - } else if (pc_ctx.is_ps_mode_) { + } else if (PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) { + // TODO baixian.zr, change pl mode hit cache as text mode. ObPsStmtId stmt_id = pc_ctx.fp_result_.pc_key_.key_id_; guard.init(PS_EXEC_HANDLE); if (OB_FAIL(plan_cache.get_ps_plan(guard, stmt_id, pc_ctx))) { @@ -3021,7 +3430,7 @@ int ObSql::pc_get_plan(ObPlanCacheCtx &pc_ctx, || OB_BATCHED_MULTI_STMT_ROLLBACK == ret || OB_NEED_SWITCH_CONSUMER_GROUP == ret) { /*do nothing*/ - } else if (!pc_ctx.is_ps_mode_ + } else if (!(PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) && OB_PC_LOCK_CONFLICT == ret && !session->is_inner()) { //不是ps模式, 不是inner sql, 且plan cache锁超时, 后面会放入大查询队列列, @@ -3240,8 +3649,9 @@ int ObSql::parser_and_check(const ObString &outlined_stmt, pc_ctx.is_rewrite_sql_ ? UDR_SQL_MODE : STD_MODE, pc_ctx.sql_ctx_.handle_batched_multi_stmt()))) { LOG_WARN("Generate syntax tree failed", K(outlined_stmt), K(ret)); - } else if (pc_ctx.is_ps_mode_ - && OB_FAIL(construct_param_store_from_ps_param(pc_ctx, pctx->get_param_store_for_update()))) { + } else if ((PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) + && OB_FAIL(construct_param_store_from_parameterized_params( + pc_ctx, pctx->get_param_store_for_update()))) { LOG_WARN("construct param store failed", K(ret)); } if (OB_SUCC(ret)) { @@ -3299,8 +3709,8 @@ int ObSql::parser_and_check(const ObString &outlined_stmt, ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid args", K(ret), KP(children_node)); //除了普通的dml stmt,explain stmt中存在?也需要这里一起判断 - } else if (!pc_ctx.is_ps_mode_ && - (children_node->type_ == T_EXPLAIN || IS_DML_STMT(children_node->type_)) + } else if (!(PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) + && (children_node->type_ == T_EXPLAIN || IS_DML_STMT(children_node->type_)) && (children_node->value_ > 0)) { ret = OB_ERR_PARSE_SQL;//children_node->value_ > 0,说明具有question_mark const char *err_msg = "?"; @@ -3471,11 +3881,12 @@ int ObSql::pc_add_plan(ObPlanCacheCtx &pc_ctx, LOG_WARN("tenant config is invalid", K(ret)); } else if (OB_USE_PLAN_CACHE_NONE == phy_plan->get_phy_plan_hint().plan_cache_policy_) { LOG_DEBUG("Hint not use plan cache"); - } else if (OB_FAIL(result.to_plan(pc_ctx.is_ps_mode_, phy_plan))) { - LOG_WARN("Failed copy field to plan", K(ret)); + } else if (OB_FAIL(result.to_plan(pc_ctx.mode_, phy_plan))) { + LOG_WARN("Failed copy field to pplan", K(ret)); } else if (OB_FAIL(ob_write_string(phy_plan->get_allocator(), - pc_ctx.is_ps_mode_ ? pc_ctx.raw_sql_ : - pc_ctx.sql_ctx_.spm_ctx_.bl_key_.constructed_sql_, + (PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) + ? pc_ctx.raw_sql_ : + pc_ctx.sql_ctx_.spm_ctx_.bl_key_.constructed_sql_, phy_plan->stat_.constructed_sql_))) { LOG_WARN("failed to ob write string", K(ret)); } else if (OB_FAIL(ob_write_string(phy_plan->get_allocator(), @@ -3492,7 +3903,7 @@ int ObSql::pc_add_plan(ObPlanCacheCtx &pc_ctx, phy_plan->stat_.rule_version_ = rule_mgr->get_rule_version(); phy_plan->stat_.enable_udr_ = tenant_config->enable_user_defined_rewrite_rules; - if (pc_ctx.is_ps_mode_) { + if (PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) { //远程SQL第二次进入plan,将raw_sql作为pc_key存入plan cache中, //然后使用ps接口直接用参数化后的sql作为key来查plan cache,可以节省一次对SQL fast parse的代价 if (pc_ctx.sql_ctx_.is_remote_sql_) { @@ -3780,7 +4191,7 @@ int ObSql::pc_add_udr_plan(const ObUDRItemMgr::UDRItemRefGuard &item_guard, ObPhysicalPlanCtx *pctx = ectx.get_physical_plan_ctx(); ParamStore param_store( (ObWrapperAllocator(&allocator)) ); const ObString &raw_sql = pc_ctx.raw_sql_; - ObPlanCacheCtx tmp_pc_ctx(raw_sql, pc_ctx.is_ps_mode_, + ObPlanCacheCtx tmp_pc_ctx(raw_sql, pc_ctx.mode_, allocator, pc_ctx.sql_ctx_, ectx, session.get_effective_tenant_id()); tmp_pc_ctx.fp_result_ = pc_ctx.fp_result_; tmp_pc_ctx.normal_parse_const_cnt_ = pc_ctx.normal_parse_const_cnt_; @@ -3819,7 +4230,7 @@ OB_NOINLINE int ObSql::handle_physical_plan(const ObString &trimed_stmt, ObResultSet &result, ObPlanCacheCtx &pc_ctx, const int get_plan_err, - bool is_psmode) + PlanCacheMode mode) { int ret = OB_SUCCESS; FLTSpanGuard(hard_parse); @@ -3848,7 +4259,7 @@ OB_NOINLINE int ObSql::handle_physical_plan(const ObString &trimed_stmt, LOG_DEBUG("gen plan info", K(spm_ctx.bl_key_), K(get_plan_err)); // for batched multi stmt, we only parse and optimize the first statement // only in multi_query, need do this - if (!is_psmode && + if (!(PC_PS_MODE == mode || PC_PL_MODE == mode) && context.multi_stmt_item_.is_batched_multi_stmt() && OB_FAIL(get_first_batched_multi_stmt(context.multi_stmt_item_, outlined_stmt))) { LOG_WARN("failed to get first batched stmt item", K(ret)); @@ -3870,7 +4281,7 @@ OB_NOINLINE int ObSql::handle_physical_plan(const ObString &trimed_stmt, is_enable_transform_tree))) { LOG_WARN("fail to parser and check", K(ret)); } else if (context.multi_stmt_item_.is_batched_multi_stmt() && - !is_psmode && + !(PC_PS_MODE == mode || PC_PL_MODE == mode) && OB_FAIL(check_batched_multi_stmt_after_parser(pc_ctx, parse_result, add_plan_to_pc, @@ -3891,7 +4302,7 @@ OB_NOINLINE int ObSql::handle_physical_plan(const ObString &trimed_stmt, context, result, pc_ctx.is_begin_commit_stmt(), - is_psmode, + mode, &outline_parse_result))) { if (OB_ERR_PROXY_REROUTE == ret) { LOG_DEBUG("Failed to generate plan", K(ret)); @@ -4140,7 +4551,8 @@ void ObSql::generate_sql_id(ObPlanCacheCtx &pc_ctx, && parse_result.result_tree_->children_[0]->type_ == T_SP_CALL_STMT) { signature_sql = pc_ctx.sql_ctx_.spm_ctx_.bl_key_.constructed_sql_; } else if (add_plan_to_pc == false - || pc_ctx.is_ps_mode_ + || PC_PS_MODE == pc_ctx.mode_ + || PC_PL_MODE == pc_ctx.mode_ || OB_SUCCESS != err_code) { signature_sql = pc_ctx.raw_sql_; } else { diff --git a/src/sql/ob_sql.h b/src/sql/ob_sql.h index 34f53bc8d..f6aad5826 100644 --- a/src/sql/ob_sql.h +++ b/src/sql/ob_sql.h @@ -26,6 +26,7 @@ #include "sql/optimizer/ob_optimizer.h" #include "sql/rewrite/ob_transform_rule.h" #include "sql/executor/ob_maintain_dependency_info_task.h" +#include "sql/ob_spi.h" #include "sql/udr/ob_udr_item_mgr.h" namespace test @@ -55,6 +56,7 @@ class ObOptStatManager; namespace sql { struct ObStmtPrepareResult; +class ObSPIService; class ObIVirtualTableIteratorFactory; struct ObSqlCtx; class ObResultSet; @@ -208,6 +210,26 @@ public: int init_result_set(ObSqlCtx &context, ObResultSet &result_set); + int handle_sql_execute(const ObString &sql, + ObSqlCtx &context, + ObResultSet &result, + ParamStore ¶ms, + PlanCacheMode mode); + + int handle_pl_prepare(const ObString &sql, + ObSPIService::PLPrepareCtx &pl_prepare_ctx, + ObSPIService::PLPrepareResult &pl_prepare_result); + + int handle_pl_execute(const ObString &sql, + ObSQLSessionInfo &session_info, + ParamStore ¶ms, + ObResultSet &result, + ObSqlCtx &context, + bool is_prepare_protocol, + bool is_dynamic_sql); + static int construct_parameterized_params(const ParamStore ¶ms, + ObPlanCacheCtx &phy_ctx); + public: //for sql test only friend bool compare_stmt(const char *schema_file, const char *str1, const char *str2); @@ -229,23 +251,35 @@ public: } virtual ~ObSql() { destroy(); } - static int construct_ps_param(const ParamStore ¶ms, - ObPlanCacheCtx &phy_ctx); private: // disallow copy ObSql(const ObSql &other); ObSql &operator=(const ObSql &other); + class TimeoutGuard + { + public: + TimeoutGuard(ObSQLSessionInfo &session); + ~TimeoutGuard(); + private: + ObSQLSessionInfo &session_; + int64_t worker_timeout_; + int64_t query_timeout_; + int64_t trx_timeout_; + }; + private: + int set_timeout_for_pl(ObSQLSessionInfo &session_info, int64_t &abs_timeout_us); + int construct_param_store(const ParamStore ¶ms, ParamStore ¶m_store); int construct_ps_param_store(const ParamStore ¶ms, const ParamStore &fixed_params, const ObIArray &fixed_param_idx, ParamStore ¶m_store); - int construct_param_store_from_ps_param(const ObPlanCacheCtx &phy_ctx, - ParamStore ¶m_store); + int construct_param_store_from_parameterized_params(const ObPlanCacheCtx &phy_ctx, + ParamStore ¶m_store); bool is_exist_in_fixed_param_idx(const int64_t idx, const ObIArray &fixed_param_idx); int do_real_prepare(const ObString &stmt, @@ -255,8 +289,8 @@ private: int do_add_ps_cache(const PsCacheInfoCtx &info_ctx, share::schema::ObSchemaGetterGuard &schema_guard, ObResultSet &result); - int fill_result_set(ObResultSet &result, ObSqlCtx *context, const bool is_ps_mode, ObStmt &stmt); - int fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, const bool is_ps_mode, + int fill_result_set(ObResultSet &result, ObSqlCtx *context, const PlanCacheMode mode, ObStmt &stmt); + int fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, const PlanCacheMode mode, ObCollationType collation_type, const ObString &type_name, ObStmt &basic_stmt, ObField &field); int pc_add_udr_plan(const ObUDRItemMgr::UDRItemRefGuard &item_guard, @@ -280,6 +314,12 @@ private: const ParamStore ¶ms_store, ParamStore *¶ms); + int reconstruct_pl_params_store(ObIAllocator &allocator, + ObSqlCtx &context, + const ParamStore &origin_params, + ParamStore &pl_params, + ParamStore *&pl_ab_params); + int reconstruct_ps_params_store(ObIAllocator &allocator, ObSqlCtx &context, const ParamStore ¶ms, @@ -296,7 +336,7 @@ private: ObResultSet &result, ObPlanCacheCtx &pc_ctx, const int get_plan_err, - bool is_psmode = false); + PlanCacheMode mode = PC_INVALID_MODE); // @brief Generate 'stmt' from syntax tree // @param parse_result[in] syntax tree // @param select_item_param_infos select_item_param_infos from fast parser @@ -328,7 +368,7 @@ private: ObSqlCtx &context, ObResultSet &result, const bool is_begin_commit_stmt, - const bool is_ps_mode = false, + const PlanCacheMode mode = PC_INVALID_MODE, ParseResult *outline_parse_result = NULL); //generate physical_plan diff --git a/src/sql/ob_sql_utils.cpp b/src/sql/ob_sql_utils.cpp index a0d7043dc..451a94459 100644 --- a/src/sql/ob_sql_utils.cpp +++ b/src/sql/ob_sql_utils.cpp @@ -1795,6 +1795,7 @@ int ObSQLUtils::get_outline_key(ObIAllocator &allocator, char *buf = NULL; int32_t pos = 0; const bool is_transform_outline = true; + const bool is_parameterized_execute = false; ParseNode *type_node = NULL; if (OB_FAIL(parser.parse(query_sql, parse_result))) { LOG_WARN("Generate syntax tree failed", "sql", query_sql, K(ret)); diff --git a/src/sql/parser/parse_node.h b/src/sql/parser/parse_node.h index 4539a66cc..eb4f3ea26 100644 --- a/src/sql/parser/parse_node.h +++ b/src/sql/parser/parse_node.h @@ -127,23 +127,24 @@ typedef struct _ParseNode int32_t num_child_; /* attributes for non-terninal node, which has children */ int16_t param_num_; //记录该node对应的原始text中常量的个数, 暂时仅T_CAST_ARGUMENT使用 union { - uint16_t flag_; + uint32_t flag_; struct { - uint16_t is_neg_ : 1;// 记录常量节点的父节点是否为T_OP_NEG节点, 1表示是, 0 表示不是 - uint16_t is_hidden_const_ : 1; //1 表示某常量正常parse能识别但fast parse不能识别, 0 表示都能识别。 - uint16_t is_tree_not_param_ :1; //1 表示该节点及其子节点常量均不能参数化, 0表示没该限制 - uint16_t length_semantics_ :2; //2 for oralce [char|varbinary] (n b [bytes|char]) - uint16_t is_val_paramed_item_idx_ :1; // T_PROJECT_STRING的vlaues是否是select_item_param_infos数组的下标 - uint16_t is_copy_raw_text_ : 1; // 是否回填常量节点的raw_text_,用于select item常量参数化 - uint16_t is_column_varchar_ : 1; // 投影列是否是一个常量字符串,用于select item常量参数化 - uint16_t is_trans_from_minus_: 1; // 负数常量节点是否是从减号操作转换而来,比如1 - 2,词法阶段会生成一个-2 - uint16_t is_assigned_from_child_: 1; // 常量节点是否由子节点赋值得到,用于处理int64_min - uint16_t is_num_must_be_pos_: 1; // - uint16_t is_date_unit_ : 1; //1 表示是date unit常量,在反拼的时候需要反拼为字符串 - uint16_t is_literal_bool_ : 1; // indicate node is a literal TRUE/FALSE - uint16_t is_empty_ : 1; // 表示是否缺省该节点,1表示缺省,0表示没有缺省, opt_asc_desc节点中使用到 - uint16_t is_multiset_ : 1; // for cast(multiset(...) as ...) - uint16_t reserved_ : 1; + uint32_t is_neg_ : 1;// 记录常量节点的父节点是否为T_OP_NEG节点, 1表示是, 0 表示不是 + uint32_t is_hidden_const_ : 1; //1 表示某常量正常parse能识别但fast parse不能识别, 0 表示都能识别。 + uint32_t is_tree_not_param_ :1; //1 表示该节点及其子节点常量均不能参数化, 0表示没该限制 + uint32_t length_semantics_ :2; //2 for oralce [char|varbinary] (n b [bytes|char]) + uint32_t is_val_paramed_item_idx_ :1; // T_PROJECT_STRING的vlaues是否是select_item_param_infos数组的下标 + uint32_t is_copy_raw_text_ : 1; // 是否回填常量节点的raw_text_,用于select item常量参数化 + uint32_t is_column_varchar_ : 1; // 投影列是否是一个常量字符串,用于select item常量参数化 + uint32_t is_trans_from_minus_: 1; // 负数常量节点是否是从减号操作转换而来,比如1 - 2,词法阶段会生成一个-2 + uint32_t is_assigned_from_child_: 1; // 常量节点是否由子节点赋值得到,用于处理int64_min + uint32_t is_num_must_be_pos_: 1; // + uint32_t is_date_unit_ : 1; //1 表示是date unit常量,在反拼的时候需要反拼为字符串 + uint32_t is_literal_bool_ : 1; // indicate node is a literal TRUE/FALSE + uint32_t is_empty_ : 1; // 表示是否缺省该节点,1表示缺省,0表示没有缺省, opt_asc_desc节点中使用到 + uint32_t is_multiset_ : 1; // for cast(multiset(...) as ...) + uint32_t is_forbid_anony_parameter_ : 1; // 1 表示禁止匿名块参数化 + uint32_t reserved_; }; }; /* attributes for terminal node, it is real value */ @@ -211,6 +212,7 @@ typedef struct _PLParseInfo { bool is_pl_parse_;//用于标识当前parser逻辑是否为PLParse调用 bool is_pl_parse_expr_; //用于标识当前parser逻辑是否在解析PLParser的expr + bool is_forbid_pl_fp_; int last_pl_symbol_pos_; //上一个pl变量的结束位置 int plsql_line_; /*for mysql pl*/ diff --git a/src/sql/plan_cache/ob_cache_object.cpp b/src/sql/plan_cache/ob_cache_object.cpp index 72d71350d..321a18782 100644 --- a/src/sql/plan_cache/ob_cache_object.cpp +++ b/src/sql/plan_cache/ob_cache_object.cpp @@ -372,7 +372,11 @@ void ObPlanCacheObject::dump_deleted_log_info(const bool is_debug_log /* = true } } else if (is_anon()) { const pl::ObPLFunction *pl_func = dynamic_cast(this); - raw_sql = ObTruncatedString(pl_func->get_stat().raw_sql_, OB_MAX_SQL_LENGTH).string(); + if (OB_ISNULL(pl_func)) { + LOG_ERROR("the pl_func is null", K(this)); + } else { + raw_sql = ObTruncatedString(pl_func->get_stat().raw_sql_, OB_MAX_SQL_LENGTH).string(); + } } else { // do nothing } diff --git a/src/sql/plan_cache/ob_cache_object.h b/src/sql/plan_cache/ob_cache_object.h index a8b9292f9..b70a45697 100644 --- a/src/sql/plan_cache/ob_cache_object.h +++ b/src/sql/plan_cache/ob_cache_object.h @@ -140,11 +140,6 @@ public: ObPlanCacheObject(ObLibCacheNameSpace ns, lib::MemoryContext &mem_context); virtual ~ObPlanCacheObject() {} - inline bool is_sql_crsr() const { return ObLibCacheNameSpace::NS_CRSR == ns_; } - inline bool is_prcr() const { return ObLibCacheNameSpace::NS_PRCR == ns_; } - inline bool is_sfc() const { return ObLibCacheNameSpace::NS_SFC == ns_; } - inline bool is_pkg() const { return ObLibCacheNameSpace::NS_PKG == ns_; } - inline bool is_anon() const { return ObLibCacheNameSpace::NS_ANON == ns_; } inline int64_t get_dependency_table_size() const { return dependency_tables_.count(); } inline const DependenyTableStore &get_dependency_table() const { return dependency_tables_; } inline void set_sys_schema_version(int64_t schema_version) { sys_schema_version_ = schema_version; } diff --git a/src/sql/plan_cache/ob_cache_object_factory.h b/src/sql/plan_cache/ob_cache_object_factory.h index 0632c3313..28021362e 100644 --- a/src/sql/plan_cache/ob_cache_object_factory.h +++ b/src/sql/plan_cache/ob_cache_object_factory.h @@ -108,6 +108,11 @@ public: return cache_obj_; } + CacheRefHandleID get_ref_handle() const + { + return ref_handle_; + } + int force_early_release(ObPlanCache *pc); // this function may be somewhat dangerous and may cause some memory leak. diff --git a/src/sql/plan_cache/ob_i_lib_cache_object.h b/src/sql/plan_cache/ob_i_lib_cache_object.h index e04673c93..03a91a574 100644 --- a/src/sql/plan_cache/ob_i_lib_cache_object.h +++ b/src/sql/plan_cache/ob_i_lib_cache_object.h @@ -43,6 +43,11 @@ public: inline ObLibCacheNameSpace get_ns() const { return ns_; } inline void set_ns(ObLibCacheNameSpace ns) { ns_ = ns; } + inline bool is_sql_crsr() const { return ObLibCacheNameSpace::NS_CRSR == ns_; } + inline bool is_prcr() const { return ObLibCacheNameSpace::NS_PRCR == ns_; } + inline bool is_sfc() const { return ObLibCacheNameSpace::NS_SFC == ns_; } + inline bool is_pkg() const { return ObLibCacheNameSpace::NS_PKG == ns_; } + inline bool is_anon() const { return ObLibCacheNameSpace::NS_ANON == ns_; } inline bool is_valid_cache_obj() const { return ns_ > NS_INVALID && ns_ < NS_MAX; } inline uint64_t get_object_id() const { return object_id_; } inline int64_t get_mem_size() const { return allocator_.total(); } diff --git a/src/sql/plan_cache/ob_lib_cache_register.h b/src/sql/plan_cache/ob_lib_cache_register.h index 4b3701277..ed2e9cab5 100644 --- a/src/sql/plan_cache/ob_lib_cache_register.h +++ b/src/sql/plan_cache/ob_lib_cache_register.h @@ -12,11 +12,11 @@ #ifdef LIB_CACHE_OBJ_DEF LIB_CACHE_OBJ_DEF(NS_CRSR, "CRSR", ObPlanCacheKey, ObPCVSet, ObPhysicalPlan, ObNewModIds::OB_SQL_PHY_PLAN) // physical plan cache -LIB_CACHE_OBJ_DEF(NS_PRCR, "PRCR", ObPlanCacheKey, ObPCVSet, pl::ObPLFunction, ObNewModIds::OB_SQL_PHY_PL_OBJ) // procedure cache -LIB_CACHE_OBJ_DEF(NS_SFC, "SFC", ObPlanCacheKey, ObPCVSet, pl::ObPLFunction, ObNewModIds::OB_SQL_PHY_PL_OBJ) // function cache -LIB_CACHE_OBJ_DEF(NS_ANON, "ANON", ObPlanCacheKey, ObPCVSet, pl::ObPLFunction, ObNewModIds::OB_SQL_PHY_PL_OBJ) // anonymous cache -LIB_CACHE_OBJ_DEF(NS_TRGR, "TRGR", ObPlanCacheKey, ObPCVSet, pl::ObPLPackage, ObNewModIds::OB_SQL_PHY_PL_OBJ) // trigger cache -LIB_CACHE_OBJ_DEF(NS_PKG, "PKG", ObPlanCacheKey, ObPCVSet, pl::ObPLPackage, ObNewModIds::OB_SQL_PHY_PL_OBJ) // package cache +LIB_CACHE_OBJ_DEF(NS_PRCR, "PRCR", pl::ObPLObjectKey, pl::ObPLObjectSet, pl::ObPLFunction, ObNewModIds::OB_SQL_PHY_PL_OBJ) // procedure cache +LIB_CACHE_OBJ_DEF(NS_SFC, "SFC", pl::ObPLObjectKey, pl::ObPLObjectSet, pl::ObPLFunction, ObNewModIds::OB_SQL_PHY_PL_OBJ) // function cache +LIB_CACHE_OBJ_DEF(NS_ANON, "ANON", pl::ObPLObjectKey, pl::ObPLObjectSet, pl::ObPLFunction, ObNewModIds::OB_SQL_PHY_PL_OBJ) // anonymous cache +LIB_CACHE_OBJ_DEF(NS_TRGR, "TRGR", pl::ObPLObjectKey, pl::ObPLObjectSet, pl::ObPLPackage, ObNewModIds::OB_SQL_PHY_PL_OBJ) // trigger cache +LIB_CACHE_OBJ_DEF(NS_PKG, "PKG", pl::ObPLObjectKey, pl::ObPLObjectSet, pl::ObPLPackage, ObNewModIds::OB_SQL_PHY_PL_OBJ) // package cache #endif /*LIB_CACHE_OBJ_DEF*/ #ifndef OCEANBASE_SQL_PLAN_CACHE_OB_LIB_CACHE_REGISTER_ diff --git a/src/sql/plan_cache/ob_pcv_set.cpp b/src/sql/plan_cache/ob_pcv_set.cpp index 462c5fda1..5283c2f1c 100644 --- a/src/sql/plan_cache/ob_pcv_set.cpp +++ b/src/sql/plan_cache/ob_pcv_set.cpp @@ -107,11 +107,11 @@ int ObPCVSet::inner_get_cache_obj(ObILibCacheCtx &ctx, int ret = OB_SUCCESS; ObPlanCacheObject *plan = NULL; ObPlanCacheCtx &pc_ctx = static_cast(ctx); - if (pc_ctx.is_ps_mode_) { - if (normal_parse_const_cnt_ != pc_ctx.fp_result_.ps_params_.count()) { + if (PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) { + if (normal_parse_const_cnt_ != pc_ctx.fp_result_.parameterized_params_.count()) { ret = OB_NOT_SUPPORTED; LOG_WARN("param num is not equal", K_(normal_parse_const_cnt), - "ps_params_count", pc_ctx.fp_result_.ps_params_.count()); + "parameterized_params_count", pc_ctx.fp_result_.parameterized_params_.count()); } } else { if (normal_parse_const_cnt_ != pc_ctx.fp_result_.raw_params_.count()) { diff --git a/src/sql/plan_cache/ob_plan_cache.cpp b/src/sql/plan_cache/ob_plan_cache.cpp index 0e5aec724..9f0148f1a 100644 --- a/src/sql/plan_cache/ob_plan_cache.cpp +++ b/src/sql/plan_cache/ob_plan_cache.cpp @@ -36,6 +36,8 @@ #include "pl/ob_pl.h" #include "pl/ob_pl_package.h" #include "observer/ob_req_time_service.h" +#include "sql/plan_cache/ob_plan_cache_manager.h" +#include "pl/pl_cache/ob_pl_cache_mgr.h" using namespace oceanbase::common; using namespace oceanbase::common::hash; @@ -86,49 +88,6 @@ struct ObGetPlanIdBySqlIdOp uint64_t plan_hash_value_; }; -struct ObKVEntryTraverseOp -{ - typedef common::hash::HashMapPair LibCacheKVEntry; - explicit ObKVEntryTraverseOp(LCKeyValueArray *key_val_list, - const CacheRefHandleID ref_handle) - : ref_handle_(ref_handle), - key_value_list_(key_val_list) - { - } - - virtual int check_entry_match(LibCacheKVEntry &entry, bool &is_match) - { - UNUSED(entry); - int ret = OB_SUCCESS; - is_match = true; - return ret; - } - virtual int operator()(LibCacheKVEntry &entry) - { - int ret = common::OB_SUCCESS; - bool is_match = false; - if (OB_ISNULL(key_value_list_) || OB_ISNULL(entry.first) || OB_ISNULL(entry.second)) { - ret = common::OB_INVALID_ARGUMENT; - SQL_PC_LOG(WARN, "invalid argument", - K(key_value_list_), K(entry.first), K(entry.second), K(ret)); - } else if (OB_FAIL(check_entry_match(entry, is_match))) { - SQL_PC_LOG(WARN, "failed to check entry match", K(ret)); - } else if (is_match) { - if (OB_FAIL(key_value_list_->push_back(ObLCKeyValue(entry.first, entry.second)))) { - SQL_PC_LOG(WARN, "fail to push back key", K(ret)); - } else { - entry.second->inc_ref_count(ref_handle_); - } - } - return ret; - } - CacheRefHandleID get_ref_handle() { return ref_handle_; } const - LCKeyValueArray *get_key_value_list() { return key_value_list_; } - - const CacheRefHandleID ref_handle_; - LCKeyValueArray *key_value_list_; -}; - struct ObGetKVEntryByNsOp : public ObKVEntryTraverseOp { explicit ObGetKVEntryByNsOp(const ObLibCacheNameSpace ns, @@ -151,27 +110,6 @@ struct ObGetKVEntryByNsOp : public ObKVEntryTraverseOp ObLibCacheNameSpace namespace_; }; -struct ObGetPLKVEntryOp : public ObKVEntryTraverseOp -{ - explicit ObGetPLKVEntryOp(LCKeyValueArray *key_val_list, - const CacheRefHandleID ref_handle) - : ObKVEntryTraverseOp(key_val_list, ref_handle) - { - } - virtual int check_entry_match(LibCacheKVEntry &entry, bool &is_match) - { - int ret = OB_SUCCESS; - is_match = false; - if (ObLibCacheNameSpace::NS_PRCR == entry.first->namespace_ || - ObLibCacheNameSpace::NS_SFC == entry.first->namespace_ || - ObLibCacheNameSpace::NS_ANON == entry.first->namespace_ || - ObLibCacheNameSpace::NS_PKG == entry.first->namespace_) { - is_match = true; - } - return ret; - } -}; - struct ObGetKVEntryBySQLIDOp : public ObKVEntryTraverseOp { explicit ObGetKVEntryBySQLIDOp(uint64_t db_id, @@ -187,8 +125,7 @@ struct ObGetKVEntryBySQLIDOp : public ObKVEntryTraverseOp { int ret = OB_SUCCESS; is_match = false; - if (entry.first->namespace_ >= ObLibCacheNameSpace::NS_CRSR - && entry.first->namespace_ <= ObLibCacheNameSpace::NS_PKG) { + if (entry.first->namespace_ == ObLibCacheNameSpace::NS_CRSR) { ObPlanCacheKey *key = static_cast(entry.first); ObPCVSet *node = static_cast(entry.second); if (db_id_ != common::OB_INVALID_ID && db_id_ != key->db_id_) { @@ -658,83 +595,6 @@ int ObPlanCache::construct_fast_parser_result(common::ObIAllocator &allocator, return ret; } -int ObPlanCache::get_pl_cache(ObPlanCacheCtx &pc_ctx, ObCacheObjGuard& guard) -{ - int ret = OB_SUCCESS; - FLTSpanGuard(pc_get_pl_object); - guard.cache_obj_ = NULL; - ObGlobalReqTimeService::check_req_timeinfo(); - if (OB_ISNULL(pc_ctx.sql_ctx_.session_info_) - || OB_ISNULL(pc_ctx.sql_ctx_.schema_guard_)) { - ret = OB_INVALID_ARGUMENT; - SQL_PC_LOG(WARN, "invalid argument", - K(pc_ctx.sql_ctx_.session_info_), - K(pc_ctx.sql_ctx_.schema_guard_), - K(ret)); - } else if (OB_FAIL(construct_plan_cache_key(pc_ctx, pc_ctx.fp_result_.pc_key_.namespace_))) { - LOG_WARN("construct plan cache key failed", K(ret)); - } else { - if (OB_FAIL(get_plan_cache(pc_ctx, guard))) { - SQL_PC_LOG(DEBUG, "failed to get plan", K(ret)); - } else if (OB_ISNULL(guard.cache_obj_) || - (ObLibCacheNameSpace::NS_PRCR != guard.cache_obj_->get_ns() && - ObLibCacheNameSpace::NS_SFC != guard.cache_obj_->get_ns() && - ObLibCacheNameSpace::NS_PKG != guard.cache_obj_->get_ns() && - ObLibCacheNameSpace::NS_ANON != guard.cache_obj_->get_ns())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("cache obj is invalid", KPC(guard.cache_obj_)); - } - } - if (OB_FAIL(ret) && OB_NOT_NULL(guard.cache_obj_)) { - // TODO PL PC_CTX - co_mgr_.free(guard.cache_obj_, pc_ctx.handle_id_); - guard.cache_obj_ = NULL; - } - if (OB_SUCC(ret) && OB_NOT_NULL(guard.cache_obj_)) { - inc_hit_and_access_cnt(); - } else { - inc_access_cnt(); - } - - return ret; -} - -int ObPlanCache::get_pl_function(ObCacheObjGuard& guard, ObPlanCacheCtx &pc_ctx) -{ - int ret = OB_SUCCESS; - ObGlobalReqTimeService::check_req_timeinfo(); - pc_ctx.handle_id_ = guard.ref_handle_; - if (OB_FAIL(get_pl_cache(pc_ctx, guard))) { - SQL_PC_LOG(DEBUG, "fail to get plan", K(ret)); - } else if (OB_ISNULL(guard.cache_obj_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("cache obj is invalid", KPC(guard.cache_obj_)); - } else { - // update pl func stat - pl::ObPLFunction* pl_func = static_cast(guard.cache_obj_); - int64_t current_time = ObTimeUtility::current_time(); - PLCacheObjStat &stat = pl_func->get_stat_for_update(); - ATOMIC_INC(&(stat.hit_count_)); - ATOMIC_STORE(&(stat.last_active_time_), current_time); - } - return ret; -} - -int ObPlanCache::get_pl_package(ObCacheObjGuard& guard, ObPlanCacheCtx &pc_ctx) -{ - int ret = OB_SUCCESS; - ObGlobalReqTimeService::check_req_timeinfo(); - pc_ctx.handle_id_ = guard.ref_handle_; - if (OB_FAIL(get_pl_cache(pc_ctx, guard))) { - SQL_PC_LOG(DEBUG, "fail to get plan", K(ret)); - } else if (OB_ISNULL(guard.cache_obj_) - || ObLibCacheNameSpace::NS_PKG != guard.cache_obj_->get_ns()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("cache obj is invalid", KPC(guard.cache_obj_)); - } - return ret; -} - //plan cache中add plan 入口 //1.检查内存限制 //2.添加plan @@ -770,53 +630,6 @@ int ObPlanCache::add_plan(ObPhysicalPlan *plan, ObPlanCacheCtx &pc_ctx) return ret; } -int ObPlanCache::add_pl_cache(ObILibCacheObject *pl_object, ObPlanCacheCtx &pc_ctx) -{ - int ret = OB_SUCCESS; - FLTSpanGuard(pc_add_pl_object); - ObGlobalReqTimeService::check_req_timeinfo(); - if (OB_ISNULL(pl_object)) { - ret = OB_INVALID_ARGUMENT; - SQL_PC_LOG(WARN, "invalid physical plan", K(ret)); - } else if (is_reach_memory_limit()) { - ret = OB_REACH_MEMORY_LIMIT; - SQL_PC_LOG(DEBUG, "plan cache memory used reach the high water mark", - K(mem_used_), K(get_mem_limit()), K(ret)); - } else if (pl_object->get_mem_size() >= get_mem_high()) { - // do nothing - } else { - ObLibCacheNameSpace ns = NS_INVALID; - switch (pl_object->get_ns()) { - case NS_PRCR: - case NS_SFC: { - ns = NS_PRCR; - } - break; - case NS_PKG: - case NS_ANON: { - ns = pl_object->get_ns(); - } - break; - default: { - ret = OB_NOT_SUPPORTED; - LOG_WARN("pl object to cache is not valid", K(pl_object->get_ns()), K(ret)); - } - break; - } - if (OB_FAIL(ret)) { - } else if (OB_FAIL(construct_plan_cache_key(pc_ctx, ns))) { - LOG_WARN("construct plan cache key failed", K(ret)); - } else if (OB_FAIL(add_plan_cache(pc_ctx, pl_object))) { - if (!is_not_supported_err(ret) - && OB_SQL_PC_PLAN_DUPLICATE != ret) { - SQL_PC_LOG(WARN, "fail to add pl function", K(ret)); - } - } else { - (void)inc_mem_used(pl_object->get_mem_size()); - } - } - return ret; -} int ObPlanCache::add_plan_cache(ObILibCacheCtx &ctx, ObILibCacheObject *cache_obj) @@ -1095,6 +908,8 @@ int ObPlanCache::foreach_cache_evict(CallBack &cb) return ret; } +template int ObPlanCache::foreach_cache_evict(pl::ObGetPLKVEntryOp &); + // Remove all cache object in the lib cache int ObPlanCache::cache_evict_all_obj() { @@ -1132,20 +947,6 @@ int ObPlanCache::cache_evict_all_plan() return ret; } -// delete all pl cache obj -int ObPlanCache::cache_evict_all_pl() -{ - int ret = OB_SUCCESS; - SQL_PC_LOG(DEBUG, "cache evict all pl cache start"); - LCKeyValueArray to_evict_keys; - ObGetPLKVEntryOp get_ids_op(&to_evict_keys, PCV_GET_PL_KEY_HANDLE); - if (OB_FAIL(foreach_cache_evict(get_ids_op))) { - SQL_PC_LOG(WARN, "failed to foreach cache evict", K(ret)); - } - SQL_PC_LOG(DEBUG, "cache evict all pl end", K(to_evict_keys)); - return ret; -} - // delete plan by sql_id int ObPlanCache::cache_evict_plan_by_sql_id(uint64_t db_id, common::ObString sql_id) { @@ -1657,7 +1458,7 @@ int ObPlanCache::add_ps_plan(T *plan, ObPlanCacheCtx &pc_ctx) ret = OB_ERR_UNEXPECTED; SQL_PC_LOG(WARN, "pc_ctx.raw_sql_.ptr() is NULL, cannot add plan to plan cache by sql", K(ret)); } else { - pc_ctx.fp_result_.pc_key_.is_ps_mode_ = true; + pc_ctx.fp_result_.pc_key_.mode_ = PC_PS_MODE; pc_ctx.fp_result_.pc_key_.name_ = pc_ctx.raw_sql_; uint64_t old_stmt_id = pc_ctx.fp_result_.pc_key_.key_id_; // the remote plan uses key_id is 0 to distinguish, so if key_id is 0, it cannot be set to OB_INVALID_ID diff --git a/src/sql/plan_cache/ob_plan_cache.h b/src/sql/plan_cache/ob_plan_cache.h index fef42e35f..4ba9ccc76 100644 --- a/src/sql/plan_cache/ob_plan_cache.h +++ b/src/sql/plan_cache/ob_plan_cache.h @@ -24,7 +24,6 @@ #include "sql/plan_cache/ob_lib_cache_key_creator.h" #include "sql/plan_cache/ob_lib_cache_node_factory.h" #include "sql/plan_cache/ob_lib_cache_object_manager.h" - namespace oceanbase { namespace rpc @@ -35,6 +34,7 @@ namespace pl { class ObPLFunction; class ObPLPackage; +class ObGetPLKVEntryOp; } // namespace pl using common::ObPsStmtId; namespace sql @@ -168,9 +168,7 @@ public: uint64_t tenant_id, PlanCacheMap* pcm); bool is_inited() { return inited_; } - - //添加pl 对象到Cache - int add_pl_cache(ObILibCacheObject *pl_object, ObPlanCacheCtx &pc_ctx); + /** * Add new plan to PlanCache */ @@ -185,10 +183,6 @@ public: // cache object access functions /* 根据ObPlanCacheKey以及参数在plan cache中查询符合要求的执行计划 */ int get_plan(common::ObIAllocator &allocator, ObPlanCacheCtx &pc_ctx, ObCacheObjGuard& guard); - //根据ObPlanCacheKey以及参数在plan cache中查询缓存的pl function - int get_pl_function(ObCacheObjGuard& guard, ObPlanCacheCtx &pc_ctx); - //根据ObPlanCacheKey以及参数在plan cache中查询缓存的pl package - int get_pl_package(ObCacheObjGuard& cacheobj_guard, ObPlanCacheCtx &pc_ctx); /* 根据ObPlanCacheKey以及参数在plan cache中查询符合要求的执行计划 */ int get_ps_plan(ObCacheObjGuard& guard, const ObPsStmtId stmt_id, ObPlanCacheCtx &pc_ctx); int ref_cache_obj(const ObCacheObjID obj_id, ObCacheObjGuard& guard); @@ -266,7 +260,6 @@ public: * cache evict */ int cache_evict_all_plan(); - int cache_evict_all_pl(); int cache_evict_all_obj(); //evict plan, adjust mem between hwm and lwm int cache_evict(); @@ -293,6 +286,7 @@ public: ObPlanCacheStat &get_plan_cache_stat() { return pc_stat_; } const ObPlanCacheStat &get_plan_cache_stat() const { return pc_stat_; } int remove_cache_obj_stat_entry(const ObCacheObjID cache_obj_id); + int remove_cache_node(ObILibCacheKey *key); ObLCObjectManager &get_cache_obj_mgr() { return co_mgr_; } ObLCNodeFactory &get_cache_node_factory() { return cn_factory_; } int alloc_cache_obj(ObCacheObjGuard& guard, ObLibCacheNameSpace ns, uint64_t tenant_id); @@ -341,7 +335,7 @@ private: int add_cache_obj_stat(ObILibCacheCtx &ctx, ObILibCacheObject *cache_obj); bool calc_evict_num(int64_t &plan_cache_evict_num); - int remove_cache_node(ObILibCacheKey *key); + int batch_remove_cache_node(const LCKeyValueArray &to_evict); bool is_reach_memory_limit() { return get_mem_hold() > get_mem_limit(); } int construct_plan_cache_key(ObPlanCacheCtx &plan_ctx, ObLibCacheNameSpace ns); @@ -361,7 +355,6 @@ private: int deal_add_ps_plan_result(int add_plan_ret, ObPlanCacheCtx &pc_ctx, const ObILibCacheObject &cache_object); - int get_pl_cache(ObPlanCacheCtx &pc_ctx, ObCacheObjGuard& guard); int check_after_get_plan(int tmp_ret, ObILibCacheCtx &ctx, ObILibCacheObject *cache_obj); private: const static int64_t SLICE_SIZE = 1024; //1k diff --git a/src/sql/plan_cache/ob_plan_cache_manager.cpp b/src/sql/plan_cache/ob_plan_cache_manager.cpp index 65d5810d6..3ef5e291d 100644 --- a/src/sql/plan_cache/ob_plan_cache_manager.cpp +++ b/src/sql/plan_cache/ob_plan_cache_manager.cpp @@ -21,6 +21,7 @@ #include "observer/omt/ob_tenant_config_mgr.h" #include "pl/ob_pl.h" #include "sql/plan_cache/ob_cache_object_factory.h" +#include "pl/pl_cache/ob_pl_cache_mgr.h" namespace oceanbase { @@ -595,7 +596,7 @@ int ObPlanCacheManager::flush_pl_cache(const uint64_t tenant_id) int64_t safe_timestamp = INT64_MAX; ObArray deleted_objs; if (NULL != plan_cache) { - if (OB_FAIL(plan_cache->cache_evict_all_pl())) { + if (OB_FAIL(pl::ObPLCacheMgr::cache_evict_all_pl(plan_cache))) { SQL_PC_LOG(ERROR, "PL cache evict failed, please check", K(ret)); } else if (OB_FAIL(observer::ObGlobalReqTimeService::get_instance() .get_global_safe_timestamp(safe_timestamp))) { diff --git a/src/sql/plan_cache/ob_plan_cache_manager.h b/src/sql/plan_cache/ob_plan_cache_manager.h index f65ad0696..076c7d0cd 100644 --- a/src/sql/plan_cache/ob_plan_cache_manager.h +++ b/src/sql/plan_cache/ob_plan_cache_manager.h @@ -28,6 +28,49 @@ namespace sql { class ObPlanCache; +struct ObKVEntryTraverseOp +{ + typedef common::hash::HashMapPair LibCacheKVEntry; + explicit ObKVEntryTraverseOp(LCKeyValueArray *key_val_list, + const CacheRefHandleID ref_handle) + : ref_handle_(ref_handle), + key_value_list_(key_val_list) + { + } + + virtual int check_entry_match(LibCacheKVEntry &entry, bool &is_match) + { + UNUSED(entry); + int ret = OB_SUCCESS; + is_match = true; + return ret; + } + virtual int operator()(LibCacheKVEntry &entry) + { + int ret = common::OB_SUCCESS; + bool is_match = false; + if (OB_ISNULL(key_value_list_) || OB_ISNULL(entry.first) || OB_ISNULL(entry.second)) { + ret = common::OB_INVALID_ARGUMENT; + PL_CACHE_LOG(WARN, "invalid argument", + K(key_value_list_), K(entry.first), K(entry.second), K(ret)); + } else if (OB_FAIL(check_entry_match(entry, is_match))) { + PL_CACHE_LOG(WARN, "failed to check entry match", K(ret)); + } else if (is_match) { + if (OB_FAIL(key_value_list_->push_back(ObLCKeyValue(entry.first, entry.second)))) { + PL_CACHE_LOG(WARN, "fail to push back key", K(ret)); + } else { + entry.second->inc_ref_count(ref_handle_); + } + } + return ret; + } + CacheRefHandleID get_ref_handle() { return ref_handle_; } const + LCKeyValueArray *get_key_value_list() { return key_value_list_; } + + const CacheRefHandleID ref_handle_; + LCKeyValueArray *key_value_list_; +}; + class ObPlanCacheManager { public: diff --git a/src/sql/plan_cache/ob_plan_cache_struct.h b/src/sql/plan_cache/ob_plan_cache_struct.h index 2c39bc129..cbb56dcd3 100644 --- a/src/sql/plan_cache/ob_plan_cache_struct.h +++ b/src/sql/plan_cache/ob_plan_cache_struct.h @@ -40,18 +40,27 @@ namespace sql typedef common::ObSEArray TmpTableNameArray; +enum PlanCacheMode +{ + PC_INVALID_MODE = -1, + PC_TEXT_MODE = 0, + PC_PS_MODE = 1, + PC_PL_MODE = 2, + PC_MAX_MODE = 3 +}; + struct ObPlanCacheKey : public ObILibCacheKey { ObPlanCacheKey() : key_id_(common::OB_INVALID_ID), db_id_(common::OB_INVALID_ID), sessid_(0), - is_ps_mode_(false) {} + mode_(PC_INVALID_MODE) {} ObPlanCacheKey(const ObString &name, uint64_t key_id, uint64_t db_id, uint64_t sessid, - bool is_ps_mode, + PlanCacheMode mode, const ObString &sys_vars_str, const ObString &config_str, ObLibCacheNameSpace namespace_arg) @@ -60,7 +69,7 @@ struct ObPlanCacheKey : public ObILibCacheKey key_id_(key_id), db_id_(db_id), sessid_(sessid), - is_ps_mode_(is_ps_mode), + mode_(mode), sys_vars_str_(sys_vars_str), config_str_(config_str) {} @@ -70,7 +79,7 @@ struct ObPlanCacheKey : public ObILibCacheKey key_id_ = common::OB_INVALID_ID; db_id_ = common::OB_INVALID_ID; sessid_ = 0; - is_ps_mode_ = false; + mode_ = PC_INVALID_MODE; sys_vars_str_.reset(); config_str_.reset(); namespace_ = NS_INVALID; @@ -95,7 +104,7 @@ struct ObPlanCacheKey : public ObILibCacheKey db_id_ = pc_key.db_id_; key_id_ = pc_key.key_id_; sessid_ = pc_key.sessid_; - is_ps_mode_ = pc_key.is_ps_mode_; + mode_ = pc_key.mode_; namespace_ = pc_key.namespace_; } return ret; @@ -119,7 +128,7 @@ struct ObPlanCacheKey : public ObILibCacheKey hash_ret = common::murmurhash(&key_id_, sizeof(uint64_t), hash_ret); hash_ret = common::murmurhash(&db_id_, sizeof(uint64_t), hash_ret); hash_ret = common::murmurhash(&sessid_, sizeof(uint32_t), hash_ret); - hash_ret = common::murmurhash(&is_ps_mode_, sizeof(bool), hash_ret); + hash_ret = common::murmurhash(&mode_, sizeof(PlanCacheMode), hash_ret); hash_ret = sys_vars_str_.hash(hash_ret); hash_ret = config_str_.hash(hash_ret); hash_ret = common::murmurhash(&namespace_, sizeof(ObLibCacheNameSpace), hash_ret); @@ -134,7 +143,7 @@ struct ObPlanCacheKey : public ObILibCacheKey db_id_ == pc_key.db_id_ && key_id_ == pc_key.key_id_ && sessid_ == pc_key.sessid_ && - is_ps_mode_ == pc_key.is_ps_mode_ && + mode_ == pc_key.mode_ && sys_vars_str_ == pc_key.sys_vars_str_ && config_str_ == pc_key.config_str_ && namespace_ == pc_key.namespace_; @@ -145,7 +154,7 @@ struct ObPlanCacheKey : public ObILibCacheKey K_(key_id), K_(db_id), K_(sessid), - K_(is_ps_mode), + K_(mode), K_(sys_vars_str), K_(config_str), K_(namespace)); @@ -157,7 +166,7 @@ struct ObPlanCacheKey : public ObILibCacheKey uint64_t key_id_; //在ps中key_id_的含有为statement id uint64_t db_id_; uint32_t sessid_; - bool is_ps_mode_; + PlanCacheMode mode_; common::ObString sys_vars_str_; common::ObString config_str_; }; @@ -202,20 +211,20 @@ public: ObFastParserResult() : inner_alloc_("FastParserRes"), raw_params_(&inner_alloc_), - ps_params_(&inner_alloc_), + parameterized_params_(&inner_alloc_), cache_params_(NULL) { reset_question_mark_ctx(); } ObPlanCacheKey pc_key_; //plan cache key, parameterized by fast parser common::ObFixedArray raw_params_; - common::ObFixedArray ps_params_; + common::ObFixedArray parameterized_params_; ParamStore *cache_params_; ObQuestionMarkCtx question_mark_ctx_; void reset() { pc_key_.reset(); raw_params_.reuse(); - ps_params_.reuse(); + parameterized_params_.reuse(); cache_params_ = NULL; } void reset_question_mark_ctx() @@ -227,7 +236,7 @@ public: question_mark_ctx_.by_name_ = false; question_mark_ctx_.by_defined_name_ = false; } - TO_STRING_KV(K(pc_key_), K(raw_params_), K(ps_params_), K(cache_params_)); + TO_STRING_KV(K(pc_key_), K(raw_params_), K(parameterized_params_), K(cache_params_)); }; enum WayToGenPlan { @@ -283,12 +292,12 @@ typedef common::ObFixedArray SelectIt struct ObPlanCacheCtx : public ObILibCacheCtx { ObPlanCacheCtx(const common::ObString &sql, - const bool is_ps_mode, + const PlanCacheMode mode, common::ObIAllocator &allocator, ObSqlCtx &sql_ctx, ObExecContext &exec_ctx, uint64_t tenant_id) - : is_ps_mode_(is_ps_mode), + : mode_(mode), raw_sql_(sql), allocator_(allocator), sql_ctx_(sql_ctx), @@ -306,7 +315,7 @@ struct ObPlanCacheCtx : public ObILibCacheCtx multi_stmt_fp_results_(allocator), handle_id_(MAX_HANDLE), is_remote_executor_(false), - is_ps_execute_stage_(false), + is_parameterized_execute_(false), ps_need_parameterized_(false), fixed_param_idx_(allocator), need_add_obj_stat_(true), @@ -320,7 +329,7 @@ struct ObPlanCacheCtx : public ObILibCacheCtx dynamic_param_info_list_(allocator), tpl_sql_const_cons_(allocator) { - fp_result_.pc_key_.is_ps_mode_ = is_ps_mode_; + fp_result_.pc_key_.mode_ = mode_; } int get_not_param_info_str(common::ObIAllocator &allocator, common::ObString &str) @@ -356,7 +365,7 @@ struct ObPlanCacheCtx : public ObILibCacheCtx uint64_t get_normalized_pattern_digest() const { common::ObString normalized_pattern; - if (is_ps_mode_ || fp_result_.pc_key_.name_.empty()) { + if (mode_ == PC_PS_MODE || mode_ == PC_PL_MODE || fp_result_.pc_key_.name_.empty()) { normalized_pattern = raw_sql_; } else { normalized_pattern = fp_result_.pc_key_.name_; @@ -368,14 +377,14 @@ struct ObPlanCacheCtx : public ObILibCacheCtx int is_retry_for_dup_tbl(bool &v) const; //仅复制表原因的重试才会设置为true void set_begin_commit_stmt() { begin_commit_stmt_ = true; } bool is_begin_commit_stmt() const { return begin_commit_stmt_; } - void set_is_ps_execute_stage() { is_ps_execute_stage_ = true; } - bool is_ps_execute_stage() { return is_ps_execute_stage_; } + void set_is_parameterized_execute() { is_parameterized_execute_ = true; } + bool is_parameterized_execute() { return is_parameterized_execute_; } void set_is_inner_sql(bool v) { is_inner_sql_ = v; }; bool is_inner_sql() const { return is_inner_sql_; } void set_is_rewrite_sql(bool v) { is_rewrite_sql_ = v; } bool is_rewrite_sql() const { return is_rewrite_sql_; } TO_STRING_KV( - K(is_ps_mode_), + K(mode_), K(raw_sql_), K(not_param_info_), K(not_param_var_), @@ -385,7 +394,7 @@ struct ObPlanCacheCtx : public ObILibCacheCtx K(should_add_plan_), K(begin_commit_stmt_), K(is_remote_executor_), - K(is_ps_execute_stage_), + K(is_parameterized_execute_), K(ps_need_parameterized_), K(fixed_param_idx_), K(need_add_obj_stat_), @@ -398,7 +407,7 @@ struct ObPlanCacheCtx : public ObILibCacheCtx K(tpl_sql_const_cons_), K(is_original_ps_mode_) ); - bool is_ps_mode_; //control use which variables to do match + PlanCacheMode mode_; //control use which variables to do match const common::ObString &raw_sql_; //query sql common::ObIAllocator &allocator_; //result mem_pool @@ -438,7 +447,7 @@ struct ObPlanCacheCtx : public ObILibCacheCtx common::ObFixedArray multi_stmt_fp_results_; CacheRefHandleID handle_id_; bool is_remote_executor_; - bool is_ps_execute_stage_; + bool is_parameterized_execute_; bool ps_need_parameterized_; common::ObFixedArray fixed_param_idx_; bool need_add_obj_stat_; diff --git a/src/sql/plan_cache/ob_plan_cache_value.cpp b/src/sql/plan_cache/ob_plan_cache_value.cpp index 4598ad6e9..270e2744c 100644 --- a/src/sql/plan_cache/ob_plan_cache_value.cpp +++ b/src/sql/plan_cache/ob_plan_cache_value.cpp @@ -250,7 +250,7 @@ int ObPlanCacheValue::init(ObPCVSet *pcv_set, const ObILibCacheObject *cache_obj LOG_WARN("failed to assign user-defined rule infos", K(ret)); } else { //deep copy special param raw text - if (pc_ctx.is_ps_mode_) { + if (PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) { if (OB_FAIL(not_param_var_.assign(pc_ctx.not_param_var_))) { LOG_WARN("fail to assign not param var", K(ret)); } @@ -279,7 +279,7 @@ int ObPlanCacheValue::init(ObPCVSet *pcv_set, const ObILibCacheObject *cache_obj //deep copy constructed sql if (OB_SUCC(ret)) { ObString outline_signature_str; - if (pc_ctx.is_ps_mode_) { + if (PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) { outline_signature_str = pc_ctx.raw_sql_; } else { outline_signature_str = pc_ctx.sql_ctx_.spm_ctx_.bl_key_.constructed_sql_; @@ -302,13 +302,13 @@ int ObPlanCacheValue::init(ObPCVSet *pcv_set, const ObILibCacheObject *cache_obj } // deep copy constructed_sql_, used for baseline; if (OB_SUCC(ret)) { - if (pc_ctx.is_ps_mode_ && OB_FAIL(ob_write_string(*pc_alloc_, - pc_ctx.raw_sql_, - constructed_sql_))) { + if ((PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) + && OB_FAIL(ob_write_string(*pc_alloc_, pc_ctx.raw_sql_, constructed_sql_))) { LOG_WARN("fail to deep copy param raw text", K(ret)); - } else if (!pc_ctx.is_ps_mode_ && OB_FAIL(ob_write_string(*pc_alloc_, - pc_ctx.sql_ctx_.spm_ctx_.bl_key_.constructed_sql_, - constructed_sql_))) { + } else if (!(PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) + && OB_FAIL(ob_write_string(*pc_alloc_, + pc_ctx.sql_ctx_.spm_ctx_.bl_key_.constructed_sql_, + constructed_sql_))) { LOG_WARN("failed to write string", K(ret)); } } @@ -1494,11 +1494,11 @@ int ObPlanCacheValue::match(ObPlanCacheCtx &pc_ctx, } else if (!need_param_) { // not needs to param, compare raw_sql is_same = (pc_ctx.raw_sql_==raw_sql_); - } else if (pc_ctx.is_ps_mode_) { + } else if (PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) { const ObObjParam *ps_param = NULL; for (int64_t i = 0; OB_SUCC(ret) && is_same && i < not_param_var_.count(); ++i) { ps_param = NULL; - if (OB_FAIL(pc_ctx.fp_result_.ps_params_.at(not_param_var_[i].idx_, ps_param))) { + if (OB_FAIL(pc_ctx.fp_result_.parameterized_params_.at(not_param_var_[i].idx_, ps_param))) { LOG_WARN("fail to get ps param", K(not_param_info_[i].idx_), K(ret)); } else if (OB_ISNULL(ps_param)) { ret = OB_INVALID_ARGUMENT; @@ -1627,7 +1627,7 @@ int ObPlanCacheValue::create_new_plan_set(const ObPlanSetType plan_set_type, void *buff = nullptr; new_plan_set = nullptr; - int64_t mem_sz = plan_set_type == PST_SQL_CRSR ? sizeof(ObSqlPlanSet) : sizeof(ObPLPlanSet); + int64_t mem_sz = sizeof(ObSqlPlanSet); if (OB_ISNULL(pc_alloc) || (plan_set_type < PST_SQL_CRSR || plan_set_type >= PST_MAX)) { @@ -1637,11 +1637,7 @@ int ObPlanCacheValue::create_new_plan_set(const ObPlanSetType plan_set_type, ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory for ObPlanSet", K(ret)); } else { - if (PST_SQL_CRSR == plan_set_type) { - new_plan_set = new(buff)ObSqlPlanSet(); - } else { - new_plan_set = new(buff)ObPLPlanSet(); - } + new_plan_set = new(buff)ObSqlPlanSet(); } if (OB_SUCC(ret)) { diff --git a/src/sql/plan_cache/ob_plan_set.cpp b/src/sql/plan_cache/ob_plan_set.cpp index ebdb3ce3d..7672ca778 100644 --- a/src/sql/plan_cache/ob_plan_set.cpp +++ b/src/sql/plan_cache/ob_plan_set.cpp @@ -1912,65 +1912,7 @@ void ObSqlPlanSet::remove_all_plan() IGNORE_RETURN dist_plans_.remove_all_plan(); } -int ObPLPlanSet::add_cache_obj(ObPlanCacheObject &cache_object, - ObPlanCacheCtx &pc_ctx, - int64_t ol_param_idx, - int &add_ret) -{ - int ret = OB_SUCCESS; - UNUSED(pc_ctx); - UNUSED(ol_param_idx); - if (OB_UNLIKELY(!cache_object.is_prcr() && !cache_object.is_sfc() && !cache_object.is_pkg() && !cache_object.is_anon())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("cache object is invalid", K(cache_object)); - } else if (OB_UNLIKELY(pl_obj_ != NULL)) { - ret = OB_SQL_PC_PLAN_DUPLICATE; - } else { - pl_obj_ = &cache_object; - pl_obj_->set_dynamic_ref_handle(PC_REF_PL_HANDLE); - } - add_ret = ret; - return ret; -} -int ObPLPlanSet::select_plan(ObPlanCacheCtx &pc_ctx, ObPlanCacheObject *&cache_obj) -{ - int ret = OB_SUCCESS; - UNUSED(pc_ctx); - if (pl_obj_ != NULL) { - cache_obj = pl_obj_; - cache_obj->set_dynamic_ref_handle(pc_ctx.handle_id_); - } else { - cache_obj = NULL; - ret = OB_SQL_PC_NOT_EXIST; - } - return ret; -} - -void ObPLPlanSet::remove_all_plan() -{ - -} - -int64_t ObPLPlanSet::get_mem_size() -{ - int64_t plan_set_mem = 0; - if (pl_obj_ != NULL) { - plan_set_mem += pl_obj_->get_mem_size(); - } - return plan_set_mem; -} - -void ObPLPlanSet::reset() -{ - pl_obj_ = NULL; - ObPlanSet::reset(); -} - -bool ObPLPlanSet::is_sql_planset() -{ - return false; -} //add plan used int ObSqlPlanSet::get_phy_locations(const ObTablePartitionInfoArray &partition_infos, //ObIArray &table_locs, diff --git a/src/sql/plan_cache/ob_plan_set.h b/src/sql/plan_cache/ob_plan_set.h index 0ebbc1795..467950040 100644 --- a/src/sql/plan_cache/ob_plan_set.h +++ b/src/sql/plan_cache/ob_plan_set.h @@ -366,29 +366,6 @@ private: bool enable_inner_part_parallel_exec_; }; -class ObPLPlanSet : public ObPlanSet -{ -public: - ObPLPlanSet() - : ObPlanSet(PST_PRCD), - pl_obj_(NULL) - {} - virtual ~ObPLPlanSet() {} -public: - virtual int add_cache_obj(ObPlanCacheObject &cache_object, - ObPlanCacheCtx &pc_ctx, - int64_t ol_param_idx, - int &add_ret) override; - virtual int select_plan(ObPlanCacheCtx &pc_ctx, - ObPlanCacheObject *&cache_obj) override; - virtual void remove_all_plan() override; - virtual int64_t get_mem_size() override; - virtual void reset() override; - virtual bool is_sql_planset() override; -private: - sql::ObPlanCacheObject *pl_obj_; -}; - inline ObPlanSetType ObPlanSet::get_plan_set_type_by_cache_obj_type(ObLibCacheNameSpace ns) { ObPlanSetType ret = PST_MAX; diff --git a/src/sql/plan_cache/ob_sql_parameterization.cpp b/src/sql/plan_cache/ob_sql_parameterization.cpp index 495562483..1a63c26bc 100644 --- a/src/sql/plan_cache/ob_sql_parameterization.cpp +++ b/src/sql/plan_cache/ob_sql_parameterization.cpp @@ -65,6 +65,7 @@ struct TransformTreeCtx int64_t assign_father_level_; const ObIArray *udr_fixed_params_; bool ignore_scale_check_; + bool is_from_pl_; TransformTreeCtx(); }; @@ -125,7 +126,8 @@ TransformTreeCtx::TransformTreeCtx() : is_project_list_scope_(false), assign_father_level_(ObSqlParameterization::NO_VALUES), udr_fixed_params_(NULL), - ignore_scale_check_(false) + ignore_scale_check_(false), + is_from_pl_(false) { } @@ -141,7 +143,8 @@ int ObSqlParameterization::transform_syntax_tree(ObIAllocator &allocator, ObMaxConcurrentParam::FixParamStore &fixed_param_store, bool is_transform_outline, SQL_EXECUTION_MODE execution_mode, - const ObIArray *udr_fixed_params) + const ObIArray *udr_fixed_params, + bool is_from_pl) { int ret = OB_SUCCESS; ObCollationType collation_connection = CS_TYPE_INVALID; @@ -180,6 +183,7 @@ int ObSqlParameterization::transform_syntax_tree(ObIAllocator &allocator, ctx.is_project_list_scope_ = false; ctx.mode_ = execution_mode; ctx.assign_father_level_ = NO_VALUES; + ctx.is_from_pl_ = is_from_pl; if (OB_FAIL(transform_tree(ctx, session))) { if (OB_NOT_SUPPORTED != ret) { SQL_PC_LOG(WARN, "fail to transform syntax tree", K(ret)); @@ -352,11 +356,11 @@ bool ObSqlParameterization::is_tree_not_param(const ParseNode *tree) SQL_EXECUTION_MODE ObSqlParameterization::get_sql_execution_mode(ObPlanCacheCtx &pc_ctx) { SQL_EXECUTION_MODE mode = INVALID_MODE; - if (pc_ctx.is_ps_mode_) { - if (pc_ctx.is_ps_execute_stage_) { - mode = pc_ctx.is_inner_sql_ ? PL_EXECUTE_MODE : PS_EXECUTE_MODE; + if (PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) { + if (pc_ctx.is_parameterized_execute_) { + mode = (PC_PL_MODE == pc_ctx.mode_) ? PL_EXECUTE_MODE : PS_EXECUTE_MODE; } else { - mode = pc_ctx.is_inner_sql_ ? PL_PREPARE_MODE : PS_PREPARE_MODE; + mode = (PC_PL_MODE == pc_ctx.mode_) ? PL_PREPARE_MODE : PS_PREPARE_MODE; } } else { mode = TEXT_MODE; @@ -534,7 +538,7 @@ int ObSqlParameterization::transform_tree(TransformTreeCtx &ctx, literal_prefix, ctx.default_length_semantics_, static_cast(server_collation), - NULL, session_info.get_sql_mode()))) { + NULL, session_info.get_sql_mode(), ctx.is_from_pl_))) { SQL_PC_LOG(WARN, "fail to resolve const", K(ret)); } else { //对于字符串值,其T_VARCHAR型的parse node有一个T_VARCHAR类型的子node,该子node描述字符串的charset等信息。 @@ -653,7 +657,7 @@ int ObSqlParameterization::transform_tree(TransformTreeCtx &ctx, } // transform `operand - const_num_val` to `operand + (-const_num_val)` - if (OB_SUCC(ret) && OB_FAIL(transform_minus_op(*(ctx.allocator_), ctx.tree_))) { + if (OB_SUCC(ret) && OB_FAIL(transform_minus_op(*(ctx.allocator_), ctx.tree_, ctx.is_from_pl_))) { LOG_WARN("failed to transform minums operation", K(ret)); } else if (lib::is_oracle_mode()) { // in oracle mode, select +-1 from dual is prohibited, but with following orders, it can be executed successfully: @@ -964,7 +968,8 @@ int ObSqlParameterization::parameterize_syntax_tree(common::ObIAllocator &alloca SQL_PC_LOG(WARN, "fail to normal parameterized parser tree", K(ret)); } } else { - need_parameterized = (!pc_ctx.is_ps_mode_ || (is_prepare_mode(mode) && sql_info.ps_need_parameterized_)); + need_parameterized = (!(PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_) + || (is_prepare_mode(mode) && sql_info.ps_need_parameterized_)); } if (OB_FAIL(ret)) { } else if (is_execute_mode(mode)) { @@ -1006,8 +1011,8 @@ int ObSqlParameterization::parameterize_syntax_tree(common::ObIAllocator &alloca SQL_PC_LOG(WARN, "fail to transform_neg_param", K(ret)); } else { pc_ctx.sql_ctx_.spm_ctx_.bl_key_.constructed_sql_.assign_ptr(buf, pos); - pc_ctx.normal_parse_const_cnt_ = sql_info.total_; pc_ctx.ps_need_parameterized_ = sql_info.ps_need_parameterized_; + pc_ctx.normal_parse_const_cnt_ = sql_info.total_; } } } @@ -1833,7 +1838,7 @@ int ObSqlParameterization::resolve_paramed_const(SelectItemTraverseCtx &ctx) return ret; } -int ObSqlParameterization::transform_minus_op(ObIAllocator &alloc, ParseNode *tree) +int ObSqlParameterization::transform_minus_op(ObIAllocator &alloc, ParseNode *tree, bool is_from_pl) { int ret = OB_SUCCESS; if (T_OP_MINUS != tree->type_) { @@ -1852,28 +1857,31 @@ int ObSqlParameterization::transform_minus_op(ObIAllocator &alloc, ParseNode *tr tree->children_[1]->value_ >= 0) { ParseNode *child = tree->children_[1]; tree->type_ = T_OP_ADD; + if (!is_from_pl) { + if (T_INT == child->type_) { + child->value_ = -child->value_; + } - if (T_INT == child->type_) { - child->value_ = -child->value_; - } + char *new_str = static_cast(parse_malloc(child->str_len_ + 2, &alloc)); + char *new_raw_text = static_cast(parse_malloc(child->text_len_ + 2, &alloc)); + if (OB_ISNULL(new_str) || OB_ISNULL(new_raw_text)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret), K(new_raw_text), K(new_str)); + } else { + new_str[0] = '-'; + new_raw_text[0] = '-'; + MEMMOVE(new_str + 1, child->str_value_, child->str_len_); + MEMMOVE(new_raw_text + 1, child->raw_text_, child->text_len_); + new_str[child->str_len_ + 1] = '\0'; + new_raw_text[child->text_len_ + 1] = '\0'; - char *new_str = static_cast(parse_malloc(child->str_len_ + 2, &alloc)); - char *new_raw_text = static_cast(parse_malloc(child->text_len_ + 2, &alloc)); - if (OB_ISNULL(new_str) || OB_ISNULL(new_raw_text)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate memory", K(ret), K(new_raw_text), K(new_str)); + child->str_len_++; + child->text_len_ ++; + child->str_value_ = new_str; + child->raw_text_ = new_raw_text; + child->is_trans_from_minus_ = 1; + } } else { - new_str[0] = '-'; - new_raw_text[0] = '-'; - MEMMOVE(new_str + 1, child->str_value_, child->str_len_); - MEMMOVE(new_raw_text + 1, child->raw_text_, child->text_len_); - new_str[child->str_len_ + 1] = '\0'; - new_raw_text[child->text_len_ + 1] = '\0'; - - child->str_len_++; - child->text_len_ ++; - child->str_value_ = new_str; - child->raw_text_ = new_raw_text; child->is_trans_from_minus_ = 1; } } else if (T_OP_MUL == tree->children_[1]->type_ @@ -1914,27 +1922,31 @@ int ObSqlParameterization::transform_minus_op(ObIAllocator &alloc, ParseNode *tr // do nothing } else { tree->type_ = T_OP_ADD; - if (T_INT == const_node->type_) { - const_node->value_ = -const_node->value_; - } - char *new_str = static_cast(parse_malloc(const_node->str_len_ + 2, &alloc)); - char *new_raw_text = static_cast(parse_malloc(const_node->text_len_ + 2, &alloc)); + if (!is_from_pl) { + if (T_INT == const_node->type_) { + const_node->value_ = -const_node->value_; + } + char *new_str = static_cast(parse_malloc(const_node->str_len_ + 2, &alloc)); + char *new_raw_text = static_cast(parse_malloc(const_node->text_len_ + 2, &alloc)); - if (OB_ISNULL(new_str) || OB_ISNULL(new_raw_text)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to alloc memory", K(ret), K(new_str), K(new_raw_text)); + if (OB_ISNULL(new_str) || OB_ISNULL(new_raw_text)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc memory", K(ret), K(new_str), K(new_raw_text)); + } else { + new_str[0] = '-'; + new_raw_text[0] = '-'; + MEMMOVE(new_str + 1, const_node->str_value_, const_node->str_len_); + MEMMOVE(new_raw_text + 1, const_node->raw_text_, const_node->text_len_); + new_str[const_node->str_len_ + 1] = '\0'; + new_raw_text[const_node->text_len_]= '\0'; + + const_node->str_len_++; + const_node->text_len_++; + const_node->str_value_ = new_str; + const_node->raw_text_ = new_raw_text; + const_node->is_trans_from_minus_ = 1; + } } else { - new_str[0] = '-'; - new_raw_text[0] = '-'; - MEMMOVE(new_str + 1, const_node->str_value_, const_node->str_len_); - MEMMOVE(new_raw_text + 1, const_node->raw_text_, const_node->text_len_); - new_str[const_node->str_len_ + 1] = '\0'; - new_raw_text[const_node->text_len_]= '\0'; - - const_node->str_len_++; - const_node->text_len_++; - const_node->str_value_ = new_str; - const_node->raw_text_ = new_raw_text; const_node->is_trans_from_minus_ = 1; } } diff --git a/src/sql/plan_cache/ob_sql_parameterization.h b/src/sql/plan_cache/ob_sql_parameterization.h index d2c5f030a..11a078460 100644 --- a/src/sql/plan_cache/ob_sql_parameterization.h +++ b/src/sql/plan_cache/ob_sql_parameterization.h @@ -130,7 +130,8 @@ public: share::schema::ObMaxConcurrentParam::FixParamStore &fixed_param_store, bool is_transform_outline, SQL_EXECUTION_MODE execution_mode = INVALID_MODE, - const ObIArray *udr_fixed_params = NULL); + const ObIArray *udr_fixed_params = NULL, + bool is_from_pl = false); static int raw_fast_parameterize_sql(common::ObIAllocator &allocator, const ObSQLSessionInfo &session, const common::ObString &sql, @@ -188,7 +189,7 @@ private: static int parameterize_fields(SelectItemTraverseCtx &ctx); static int resolve_paramed_const(SelectItemTraverseCtx &ctx); - static int transform_minus_op(ObIAllocator &, ParseNode *); + static int transform_minus_op(ObIAllocator &, ParseNode *, bool is_from_pl=false); static int find_leftest_const_node(ParseNode &cur_node, ParseNode *&const_node); static bool need_fast_parser(const ObString &sql); diff --git a/src/sql/resolver/dcl/ob_dcl_resolver.cpp b/src/sql/resolver/dcl/ob_dcl_resolver.cpp index 14ef90279..0642e026c 100644 --- a/src/sql/resolver/dcl/ob_dcl_resolver.cpp +++ b/src/sql/resolver/dcl/ob_dcl_resolver.cpp @@ -155,7 +155,7 @@ int ObDCLResolver::check_oracle_password_strength(int64_t tenant_id, } else if (OB_FAIL(pool->acquire(session_info_, conn))) { LOG_WARN("failed to acquire inner connection", K(ret)); } else if (OB_FAIL(conn->execute_read(session_info_->get_effective_tenant_id(), - sql.ptr(), res, true, false))) { + sql.ptr(), res, true))) { LOG_WARN("execute sql failed", K(ret), K(sql)); } else if (OB_ISNULL(sql_result = res.get_result())) { ret = OB_ERR_UNEXPECTED; diff --git a/src/sql/resolver/ddl/ob_alter_table_resolver.cpp b/src/sql/resolver/ddl/ob_alter_table_resolver.cpp index 0f01c0ccf..efd01991e 100644 --- a/src/sql/resolver/ddl/ob_alter_table_resolver.cpp +++ b/src/sql/resolver/ddl/ob_alter_table_resolver.cpp @@ -5276,6 +5276,7 @@ int ObAlterTableResolver::resolve_modify_all_trigger(const ParseNode &node) CK (OB_NOT_NULL(alter_table_stmt) && OB_NOT_NULL(schema_checker_) && OB_NOT_NULL(allocator_)); CK (OB_NOT_NULL(schema_guard = schema_checker_->get_schema_guard())); if (OB_SUCC(ret)) { + alter_table_stmt->get_tg_arg().is_set_status_ = true; for (int64_t i = 0; OB_SUCC(ret) && i < table_schema_->get_trigger_list().count(); ++i) { ObTriggerInfo new_tg_arg; OX (new_tg_arg.set_is_enable(is_enable)); diff --git a/src/sql/resolver/ddl/ob_trigger_resolver.cpp b/src/sql/resolver/ddl/ob_trigger_resolver.cpp index 0d71c248c..06cb97d06 100644 --- a/src/sql/resolver/ddl/ob_trigger_resolver.cpp +++ b/src/sql/resolver/ddl/ob_trigger_resolver.cpp @@ -18,6 +18,9 @@ #include "pl/ob_pl_resolver.h" #include "sql/resolver/ob_stmt_resolver.h" #include "sql/resolver/ddl/ob_create_routine_resolver.h" +#include "pl/parser/parse_stmt_item_type.h" +#include "pl/ob_pl_package.h" +#include "pl/ob_pl_compile.h" namespace oceanbase { @@ -26,6 +29,7 @@ namespace sql using namespace common; using namespace obrpc; using namespace share::schema; +using namespace pl; int ObTriggerResolver::resolve(const ParseNode &parse_tree) { @@ -194,27 +198,28 @@ int ObTriggerResolver::resolve_alter_trigger_stmt(const ParseNode &parse_node, const ObTriggerInfo *old_tg_info = NULL; ObTriggerInfo new_tg_info; OV (parse_node.type_ == T_TG_ALTER, OB_ERR_UNEXPECTED, parse_node.type_); - OV (parse_node.num_child_ == 1, OB_ERR_UNEXPECTED, parse_node.num_child_); + OV (parse_node.num_child_ == 2, OB_ERR_UNEXPECTED, parse_node.num_child_); OV (OB_NOT_NULL(parse_node.children_)); OV (OB_NOT_NULL(parse_node.children_[0])); //trigger name. + OV (OB_NOT_NULL(parse_node.children_[1])); //alter clause. OV (OB_NOT_NULL(session_info_) && OB_NOT_NULL(schema_checker_)); OZ (resolve_schema_name(*parse_node.children_[0], trigger_db_name, trigger_name)); - OZ (new_tg_info.set_trigger_name(trigger_name), trigger_name); OZ (schema_checker_->get_trigger_info(session_info_->get_effective_tenant_id(), trigger_db_name, trigger_name, old_tg_info)); - if (OB_SUCC(ret) && OB_ISNULL(old_tg_info)) { - ret = OB_ERR_TRIGGER_NOT_EXIST; - LOG_ORACLE_USER_ERROR(OB_ERR_TRIGGER_NOT_EXIST, trigger_name.length(), trigger_name.ptr()); - } - OX (new_tg_info.set_trigger_id(old_tg_info->get_trigger_id())); - OZ (resolve_alter_clause(parse_node, new_tg_info)); - OZ (trigger_arg.trigger_infos_.push_back(new_tg_info)); if (OB_SUCC(ret) && ObSchemaChecker::is_ora_priv_check()) { OZ(schema_checker_->check_ora_ddl_priv(session_info_->get_effective_tenant_id(), session_info_->get_priv_user_id(), trigger_db_name, stmt::T_ALTER_TRIGGER, session_info_->get_enable_role_array())); } + if (OB_SUCC(ret) && OB_ISNULL(old_tg_info)) { + ret = OB_ERR_TRIGGER_NOT_EXIST; + LOG_ORACLE_USER_ERROR(OB_ERR_TRIGGER_NOT_EXIST, trigger_name.length(), trigger_name.ptr()); + } + OZ (new_tg_info.deep_copy(*old_tg_info)); + OZ (resolve_alter_clause(*parse_node.children_[1], new_tg_info, trigger_db_name, + trigger_arg.is_set_status_, trigger_arg.is_alter_compile_)); + OZ (trigger_arg.trigger_infos_.push_back(new_tg_info)); return ret; } @@ -783,16 +788,28 @@ int ObTriggerResolver::resolve_schema_name(const ParseNode &parse_node, } int ObTriggerResolver::resolve_alter_clause(const ParseNode &alter_clause, - ObTriggerInfo &tg_info) + ObTriggerInfo &tg_info, + const ObString &db_name, + bool &is_set_status, + bool &is_alter_compile) { int ret = OB_SUCCESS; - if (T_ENABLE == static_cast(alter_clause.value_)) { - tg_info.set_enable(); - } else if (T_DISABLE == static_cast(alter_clause.value_)) { - tg_info.set_disable(); - } else { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("alter clause must be ENABLE/DISABLE", K(ret)); + CK (OB_LIKELY(OB_NOT_NULL(schema_checker_))); + CK (OB_LIKELY(OB_NOT_NULL(schema_checker_->get_schema_guard()))); + CK (OB_LIKELY(OB_NOT_NULL(allocator_))); + CK (OB_LIKELY(T_TG_ALTER_OPTIONS == alter_clause.type_)); + if (FAILEDx(TRIGGER_ALTER_IF_EDITIONABLE == alter_clause.int16_values_[0])) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("alter editionable is not supported yet!", K(ret)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter editionable"); + } else if (TRIGGER_ALTER_IF_ENABLE == alter_clause.int16_values_[0]) { + is_set_status = true; + is_alter_compile = false; + if (T_ENABLE == static_cast(alter_clause.int16_values_[1])) { + tg_info.set_enable(); + } else { + tg_info.set_disable(); + } } return ret; } @@ -923,6 +940,66 @@ int ObTriggerResolver::resolve_base_object(ObCreateTriggerArg &tg_arg, return ret; } +int ObTriggerResolver::analyze_trigger(ObSchemaGetterGuard &schema_guard, + ObSQLSessionInfo *session_info, + ObMySQLProxy *sql_proxy, + ObIAllocator &allocator, + const ObTriggerInfo &trigger_info, + const ObString &db_name, + ObIArray &dep_infos, + bool is_alter_compile) +{ + int ret = OB_SUCCESS; + CK (OB_LIKELY(OB_NOT_NULL(session_info))); + CK (OB_LIKELY(OB_NOT_NULL(sql_proxy))); + if (OB_SUCC(ret)) { + HEAP_VARS_2((ObPLPackageAST, package_spec_ast, allocator), + (ObPLPackageAST, package_body_ast, allocator)) { + ObPLPackageGuard package_guard(PACKAGE_RESV_HANDLE); + const ObString &pkg_name = trigger_info.get_package_body_info().get_package_name(); + ObPLCompiler compiler(allocator, *session_info, schema_guard, package_guard, *sql_proxy); + const ObPackageInfo &package_spec_info = trigger_info.get_package_spec_info(); + OZ (package_spec_ast.init(db_name, + package_spec_info.get_package_name(), + PL_PACKAGE_SPEC, + package_spec_info.get_database_id(), + package_spec_info.get_package_id(), + package_spec_info.get_schema_version(), + NULL)); + OZ (compiler.analyze_package(trigger_info.get_package_spec_source(), NULL, package_spec_ast, true)); + OZ (package_body_ast.init(db_name, + pkg_name, + PL_PACKAGE_BODY, + trigger_info.get_package_body_info().get_database_id(), + trigger_info.get_package_body_info().get_package_id(), + trigger_info.get_package_body_info().get_schema_version(), + &package_spec_ast)); + OZ (compiler.analyze_package(trigger_info.get_package_body_source(), + &(package_spec_ast.get_body()->get_namespace()), + package_body_ast, + true)); + if (OB_SUCC(ret) && lib::is_oracle_mode()) { + if (is_alter_compile) { + OZ (ObPLCompiler::update_schema_object_dep_info(package_body_ast, + trigger_info.get_tenant_id(), + trigger_info.get_trigger_id(), + trigger_info.get_schema_version(), + trigger_info.get_owner_id(), + trigger_info.get_object_type())); + } else { + ObString dep_attr; + OZ (ObDependencyInfo::collect_dep_infos(package_body_ast.get_dependency_table(), + dep_infos, + trigger_info.get_object_type(), + 0, dep_attr, dep_attr)); + } + } + } + } + return ret; +} + + const ObString ObTriggerResolver::REF_OLD = "OLD"; const ObString ObTriggerResolver::REF_NEW = "NEW"; const ObString ObTriggerResolver::REF_PARENT = "PARENT"; diff --git a/src/sql/resolver/ddl/ob_trigger_resolver.h b/src/sql/resolver/ddl/ob_trigger_resolver.h index ded212e7b..5b60a024a 100644 --- a/src/sql/resolver/ddl/ob_trigger_resolver.h +++ b/src/sql/resolver/ddl/ob_trigger_resolver.h @@ -40,6 +40,14 @@ public: virtual ~ObTriggerResolver() {} virtual int resolve(const ParseNode &parse_tree); + static int analyze_trigger(ObSchemaGetterGuard &schema_guard, + ObSQLSessionInfo *session_info, + ObMySQLProxy *sql_proxy, + ObIAllocator &allocator, + const ObTriggerInfo &trigger_info, + const ObString &db_name, + ObIArray &dep_infos, + bool is_alter_compile); private: int resolve_create_trigger_stmt(const ParseNode &parse_node, obrpc::ObCreateTriggerArg &trigger_arg); @@ -79,10 +87,14 @@ private: common::ObString &database_name, common::ObString &schema_name); int resolve_alter_clause(const ParseNode &alter_clause, - share::schema::ObTriggerInfo &tg_info); + share::schema::ObTriggerInfo &tg_info, + const ObString &db_name, + bool &is_set_status, + bool &is_alter_compile); int fill_package_info(share::schema::ObTriggerInfo &trigger_info); int resolve_base_object(obrpc::ObCreateTriggerArg &trigger_arg, bool search_public_schema); + private: static const common::ObString REF_OLD; static const common::ObString REF_NEW; diff --git a/src/sql/resolver/expr/ob_raw_expr.cpp b/src/sql/resolver/expr/ob_raw_expr.cpp index 11e62e59d..3ed39177e 100644 --- a/src/sql/resolver/expr/ob_raw_expr.cpp +++ b/src/sql/resolver/expr/ob_raw_expr.cpp @@ -4242,7 +4242,7 @@ int ObPlQueryRefRawExpr::assign(const ObRawExpr &other) } else { const ObPlQueryRefRawExpr &tmp = static_cast(other); OZ (exprs_.assign(tmp.exprs_)); - OX (id_ = tmp.id_); + OX (ps_sql_ = tmp.ps_sql_); OX (type_ = tmp.type_); OX (route_sql_ = tmp.route_sql_); OX (subquery_result_type_ = tmp.subquery_result_type_); @@ -5691,7 +5691,7 @@ bool ObPlQueryRefRawExpr::inner_same_as( bool_ret = check_context->compare_query(*this, u_expr); } else { // very tricky, check the definition of ref_stmt_ and get_ref_stmt() - bool_ret = (get_ps_id() == u_expr.get_ps_id() && + bool_ret = (get_ps_sql() == u_expr.get_ps_sql() && get_stmt_type() == u_expr.get_stmt_type() && get_route_sql() == u_expr.get_route_sql() && get_subquery_result_type() == u_expr.get_subquery_result_type()); @@ -5703,7 +5703,7 @@ bool ObPlQueryRefRawExpr::inner_same_as( bool ObExprEqualCheckContext::compare_query(const ObPlQueryRefRawExpr &left, const ObPlQueryRefRawExpr &right) { - return left.get_ps_id() == right.get_ps_id() && + return left.get_ps_sql() == right.get_ps_sql() && left.get_stmt_type() == right.get_stmt_type() && left.get_route_sql() == right.get_route_sql() && left.get_subquery_result_type() == right.get_subquery_result_type(); @@ -5722,7 +5722,7 @@ int ObPlQueryRefRawExpr::get_name_internal(char *buf, const int64_t buf_len, int if (OB_FAIL(BUF_PRINTF("PL_SQ"))) { LOG_WARN("fail to BUF_PRINTF", K(ret)); } - } else if (OB_FAIL(BUF_PRINTF("subquery(%lu)", id_))) { + } else if (OB_FAIL(BUF_PRINTF("subquery(%.*s)", ps_sql_.length(), ps_sql_.ptr()))) { LOG_WARN("fail to BUF_PRINTF", K(ret)); } else if (EXPLAIN_EXTENDED == type) { if (OB_FAIL(BUF_PRINTF("("))) { diff --git a/src/sql/resolver/expr/ob_raw_expr.h b/src/sql/resolver/expr/ob_raw_expr.h index 5606895c8..01acd3623 100644 --- a/src/sql/resolver/expr/ob_raw_expr.h +++ b/src/sql/resolver/expr/ob_raw_expr.h @@ -4527,7 +4527,7 @@ class ObPlQueryRefRawExpr : public ObRawExpr public: ObPlQueryRefRawExpr() : ObRawExpr(), - id_(common::OB_INVALID_ID), + ps_sql_(ObString()), type_(stmt::T_NONE), route_sql_(ObString()), subquery_result_type_(), @@ -4539,7 +4539,7 @@ public: ObPlQueryRefRawExpr(common::ObIAllocator &alloc) : ObRawExpr(alloc), - id_(common::OB_INVALID_ID), + ps_sql_(ObString()), type_(stmt::T_NONE), route_sql_(ObString()), subquery_result_type_(), @@ -4558,14 +4558,14 @@ public: const ObRawExpr *get_param_expr(int64_t index) const; ObRawExpr *&get_param_expr(int64_t index); - inline void set_ps_id(ObPsStmtId id) { id_ = id; } + inline void set_ps_sql(const common::ObString &sql) { ps_sql_ = sql; } inline void set_stmt_type(stmt::StmtType type) { type_ = type; } inline void set_route_sql(const common::ObString &sql) { route_sql_ = sql; } inline void set_subquery_result_type(const sql::ObExprResType &type) { subquery_result_type_ = type; } - inline ObPsStmtId get_ps_id() const { return id_; } + inline const common::ObString &get_ps_sql() const { return ps_sql_; } inline stmt::StmtType get_stmt_type() const { return type_; } inline const common::ObString &get_route_sql() const { return route_sql_; } inline const sql::ObExprResType &get_subquery_result_type() const @@ -4593,7 +4593,7 @@ public: private: DISALLOW_COPY_AND_ASSIGN(ObPlQueryRefRawExpr); - ObPsStmtId id_; //prepare的语句id + common::ObString ps_sql_; //prepare后的参数化sql stmt::StmtType type_; //prepare的语句类型 common::ObString route_sql_; diff --git a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp index 9ed1f1e36..2bcdc7837 100644 --- a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp @@ -2346,12 +2346,22 @@ int ObRawExprResolverImpl::process_datatype_or_questionmark(const ParseNode &nod OX (ctx_.prepare_param_count_++); } } else { - /* - * 走到这里有三种情况: - * 1、PL里的sql语句,形如select * from t where a1=:a and a2=b,其中b是PL local变量 - * 2、普通ps过来的sql语句,形如select * from t where a1=:a and a2=1 - * */ //prepare stmt不需要type,只需要计算?的个数 + if (OB_SUCC(ret) && nullptr != ctx_.secondary_namespace_) { + const pl::ObPLSymbolTable* symbol_table = NULL; + const pl::ObPLVar* var = NULL; + CK (OB_NOT_NULL(symbol_table = ctx_.secondary_namespace_->get_symbol_table())); + CK (OB_NOT_NULL(var = symbol_table->get_symbol(val.get_unknown()))); + if (OB_SUCC(ret)) { + if (0 == var->get_name().case_compare(pl::ObPLResolver::ANONYMOUS_ARG)) { + CK (OB_NOT_NULL(var->get_type().get_meta_type())); + CK (OB_NOT_NULL(var->get_type().get_data_type())); + OX (c_expr->set_meta_type(*var->get_type().get_meta_type())); + OX (c_expr->set_expr_obj_meta(*var->get_type().get_meta_type())); + OX (c_expr->set_accuracy(var->get_type().get_data_type()->get_accuracy())); + } + } + } ObRawExpr *original_expr = c_expr; OZ (ObResolverUtils::resolve_external_param_info(*ctx_.external_param_info_, ctx_.expr_factory_, @@ -3339,6 +3349,17 @@ int ObRawExprResolverImpl::process_like_node(const ParseNode *node, ObRawExpr *& if (OB_ISNULL(ctx_.param_list_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("param_list_ is null", K(ret), K(ctx_.param_list_)); + } else if (ctx_.param_list_->empty() && nullptr != ctx_.secondary_namespace_) { + const pl::ObPLSymbolTable* symbol_table = NULL; + const pl::ObPLVar* var = NULL; + CK (OB_NOT_NULL(symbol_table = ctx_.secondary_namespace_->get_symbol_table())); + CK (OB_NOT_NULL(var = symbol_table->get_symbol(escape_node->value_))); + if (0 == var->get_name().case_compare(pl::ObPLResolver::ANONYMOUS_ARG) && + NULL != var->get_pl_data_type().get_data_type() && + ObNullType == var->get_pl_data_type().get_data_type()->get_obj_type()) { + ret = OB_ERR_INVALID_ESCAPE_CHAR_LENGTH; + LOG_WARN("invalid escape char length, expect 1, get 0", K(ret)); + } } else if (escape_node->value_ < 0 || escape_node->value_ >= ctx_.param_list_->count()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("index is out of range", K(escape_node->value_), K(ctx_.param_list_->count())); @@ -3607,6 +3628,10 @@ int ObRawExprResolverImpl::process_case_node(const ParseNode *node, ObRawExpr *& LOG_WARN("Add when expression failed", K(ret)); } else if (OB_FAIL(case_expr->add_then_param_expr(then_expr))) { LOG_WARN("Add then expression failed", K(ret)); + } else if(T_QUESTIONMARK == then_expr->get_expr_type()) { + if (then_expr->get_result_meta().get_type() != ObNullType) { + all_then_null = false; + } } else if (then_expr->get_expr_type() != T_NULL) { all_then_null = false; } @@ -3632,7 +3657,11 @@ int ObRawExprResolverImpl::process_case_node(const ParseNode *node, ObRawExpr *& LOG_WARN("fail to recursive resolve", K(ret), K(node->children_[2])); } if (OB_SUCC(ret)){ - if (default_expr->get_expr_type() != T_NULL) { + if (T_QUESTIONMARK == default_expr->get_expr_type()) { + if (default_expr->get_result_meta().get_type() != ObNullType) { + all_then_null = false; + } + } else if (default_expr->get_expr_type() != T_NULL) { all_then_null = false; } case_expr->set_default_param_expr(default_expr); diff --git a/src/sql/resolver/expr/ob_raw_expr_util.cpp b/src/sql/resolver/expr/ob_raw_expr_util.cpp index 6021bb37d..6fb9d73cf 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_util.cpp @@ -1015,7 +1015,19 @@ int ObRawExprUtils::resolve_udf_param_exprs(ObResolverParams ¶ms, } } if (OB_SUCC(ret)) { - if (T_QUESTIONMARK == iexpr->get_expr_type()) { + bool is_anonymos_const_var = false; + if (T_QUESTIONMARK == iexpr->get_expr_type() && nullptr != params.secondary_namespace_) { + ObConstRawExpr *c_expr = static_cast(iexpr); + const pl::ObPLVar* var = NULL; + const pl::ObPLSymbolTable* symbol_table = params.secondary_namespace_->get_symbol_table(); + if (!params.is_prepare_protocol_ && + OB_NOT_NULL(symbol_table) && + OB_NOT_NULL(var = symbol_table->get_symbol(c_expr->get_value().get_unknown())) && + 0 == var->get_name().case_compare(pl::ObPLResolver::ANONYMOUS_ARG)) { + OX (is_anonymos_const_var = true); + } + } + if (T_QUESTIONMARK == iexpr->get_expr_type() && !is_anonymos_const_var) { // 如果UDF出现在PL的DML语句中, 走到这里的ObjAccessRawExpr已经被替换为QuestionMark // 我们需要找到原始的ObjAccessRawExpr, 并设置fow_write属性 ObConstRawExpr *c_expr = static_cast(iexpr); @@ -1043,6 +1055,10 @@ int ObRawExprUtils::resolve_udf_param_exprs(ObResolverParams ¶ms, ret = OB_ER_SP_NOT_VAR_ARG; LOG_WARN("OUT or INOUT argument for routine is not a variable", K(iexpr->get_expr_type()), K(ret)); + } else if (T_QUESTIONMARK == iexpr->get_expr_type() && is_anonymos_const_var) { + ret = OB_ER_SP_NOT_VAR_ARG; + LOG_WARN("OUT or INOUT argument for routine is not a variable", + K(iexpr->get_expr_type()), K(ret)); } else if (T_OBJ_ACCESS_REF == iexpr->get_expr_type()) { ObObjAccessRawExpr* obj = static_cast(iexpr); CK (OB_NOT_NULL(obj)); diff --git a/src/sql/resolver/ob_resolver_utils.cpp b/src/sql/resolver/ob_resolver_utils.cpp index 0ab2cdc1a..b173d5b4a 100644 --- a/src/sql/resolver/ob_resolver_utils.cpp +++ b/src/sql/resolver/ob_resolver_utils.cpp @@ -1566,7 +1566,8 @@ int ObResolverUtils::resolve_sp_access_name(ObSchemaChecker &schema_checker, int ObResolverUtils::resolve_sp_name(ObSQLSessionInfo &session_info, const ParseNode &sp_name_node, ObString &db_name, - ObString &sp_name) + ObString &sp_name, + bool need_db_name) { int ret = OB_SUCCESS; const ParseNode *sp_node = NULL; @@ -1600,6 +1601,8 @@ int ObResolverUtils::resolve_sp_name(ObSQLSessionInfo &session_info, (lib::is_oracle_mode() ? OB_MAX_PL_IDENT_LENGTH : OB_MAX_MYSQL_PL_IDENT_LENGTH))) { ret = OB_ERR_TOO_LONG_IDENT; LOG_WARN("identifier is too long", K(sp_name), K(ret)); + } else if (!need_db_name && lib::is_oracle_mode()) { + // do nothing } else if (NULL == (db_node = sp_name_node.children_[0])) { if (session_info.get_database_name().empty()) { ret = OB_ERR_NO_DB_SELECTED; diff --git a/src/sql/resolver/ob_resolver_utils.h b/src/sql/resolver/ob_resolver_utils.h index c0a52178b..bf662d64c 100644 --- a/src/sql/resolver/ob_resolver_utils.h +++ b/src/sql/resolver/ob_resolver_utils.h @@ -258,7 +258,8 @@ public: static int resolve_sp_name(ObSQLSessionInfo &session_info, const ParseNode &sp_name_node, ObString &db_name, - ObString &sp_name); + ObString &sp_name, + bool need_db_name = true); static int resolve_synonym_object_recursively(ObSchemaChecker &schema_checker, ObSynonymChecker &synonym_checker, uint64_t tenant_id, diff --git a/src/sql/udr/ob_udr_mgr.cpp b/src/sql/udr/ob_udr_mgr.cpp index 0d072ea70..6c96b87db 100644 --- a/src/sql/udr/ob_udr_mgr.cpp +++ b/src/sql/udr/ob_udr_mgr.cpp @@ -37,10 +37,10 @@ void UDRBackupRecoveryGuard::recovery() pc_ctx_.is_rewrite_sql_ = false; pc_ctx_.def_name_ctx_ = nullptr; if (!is_prepare_protocol_) { - pc_ctx_.is_ps_mode_ = false; + pc_ctx_.mode_ = PC_INVALID_MODE; const_cast(pc_ctx_.raw_sql_) = cur_sql_; - pc_ctx_.is_ps_execute_stage_ = false; - pc_ctx_.fp_result_.ps_params_.reuse(); + pc_ctx_.is_parameterized_execute_ = false; + pc_ctx_.fp_result_.parameterized_params_.reuse(); } } diff --git a/src/sql/udr/ob_udr_utils.cpp b/src/sql/udr/ob_udr_utils.cpp index ee363a3af..5e0bd483a 100644 --- a/src/sql/udr/ob_udr_utils.cpp +++ b/src/sql/udr/ob_udr_utils.cpp @@ -89,13 +89,13 @@ int ObUDRUtils::refill_udr_exec_ctx(const ObUDRItemMgr::UDRItemRefGuard &item_gu OX (pc_ctx.rule_name_ = rule_item->get_rule_name()); OX (pc_ctx.def_name_ctx_ = const_cast(rule_item->get_question_mark_def_name_ctx())); OZ (cons_udr_param_store(dynamic_param_list, pc_ctx, param_store)); - OZ (ObSql::construct_ps_param(param_store, pc_ctx)); + OZ (ObSql::construct_parameterized_params(param_store, pc_ctx)); OX (pc_ctx.normal_parse_const_cnt_ = param_store.count()); - if (!pc_ctx.is_ps_mode_) { + if (pc_ctx.mode_ != PC_PS_MODE) { OX (context.is_prepare_protocol_ = true); OX (const_cast(pc_ctx.raw_sql_) = replacement); - OX (pc_ctx.is_ps_mode_ = true); - OX (pc_ctx.set_is_ps_execute_stage()); + OX (pc_ctx.mode_ = PC_PS_MODE); + OX (pc_ctx.set_is_parameterized_execute()); } } return ret; @@ -134,7 +134,7 @@ int ObUDRUtils::cons_udr_param_store(const DynamicParamInfoArray& dynamic_param_ if (OB_ISNULL(pc_ctx.sql_ctx_.session_info_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(pc_ctx.sql_ctx_.session_info_)); - } else if (pc_ctx.is_ps_mode_) { + } else if (PC_PS_MODE == pc_ctx.mode_) { ObSQLMode sql_mode = pc_ctx.sql_ctx_.session_info_->get_sql_mode(); ObCollationType conn_coll = pc_ctx.sql_ctx_.session_info_->get_local_collation_connection(); FPContext fp_ctx(conn_coll); @@ -196,11 +196,11 @@ int ObUDRUtils::clac_dynamic_param_store(const DynamicParamInfoArray& dynamic_pa ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null", K(ret)); } else if (T_QUESTIONMARK == raw_param->type_) { - if (!pc_ctx.is_ps_mode_ || raw_param->value_ >= pc_ctx.fp_result_.ps_params_.count()) { + if (pc_ctx.mode_ != PC_PS_MODE || raw_param->value_ >= pc_ctx.fp_result_.parameterized_params_.count()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid argument", K(ret), K(raw_param->value_), K(dynamic_param_info.raw_param_idx_), - K(pc_ctx.is_ps_mode_), K(pc_ctx.fp_result_.ps_params_.count())); - } else if (OB_FAIL(param_store.push_back(*pc_ctx.fp_result_.ps_params_.at(raw_param->value_)))) { + K(pc_ctx.mode_), K(pc_ctx.fp_result_.parameterized_params_.count())); + } else if (OB_FAIL(param_store.push_back(*pc_ctx.fp_result_.parameterized_params_.at(raw_param->value_)))) { LOG_WARN("pushback param failed", K(ret)); } } else if (OB_FAIL(ObResolverUtils::resolve_const(raw_param, diff --git a/unittest/sql/optimizer/test_optimizer_utils.cpp b/unittest/sql/optimizer/test_optimizer_utils.cpp index fdc4e48c4..e9279b2e6 100644 --- a/unittest/sql/optimizer/test_optimizer_utils.cpp +++ b/unittest/sql/optimizer/test_optimizer_utils.cpp @@ -491,10 +491,11 @@ int MockCacheObjectFactory::alloc(ObPhysicalPlan *&plan, uint64_t tenant_id) { int ret = OB_SUCCESS; - ObPlanCacheObject *cache_obj = NULL; + ObILibCacheObject *cache_obj = NULL; if (OB_FAIL(alloc(cache_obj, ObLibCacheNameSpace::NS_CRSR, tenant_id))) { LOG_WARN("alloc physical plan failed", K(ret), K(tenant_id)); - } else if (OB_ISNULL(cache_obj) || OB_UNLIKELY(!cache_obj->is_sql_crsr())) { + } else if (OB_ISNULL(cache_obj) || + OB_UNLIKELY(ObLibCacheNameSpace::NS_CRSR != cache_obj->get_ns())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("cache object is invalid", KPC(cache_obj)); } else { @@ -512,10 +513,11 @@ int MockCacheObjectFactory::alloc(ObPLFunction *&func, uint64_t tenant_id) { int ret = OB_SUCCESS; - ObPlanCacheObject *cache_obj = NULL; + ObILibCacheObject *cache_obj = NULL; if (OB_FAIL(alloc(cache_obj, ns, tenant_id))) { LOG_WARN("alloc cache object failed", K(ret), K(tenant_id)); - } else if (OB_ISNULL(cache_obj) || OB_UNLIKELY(!cache_obj->is_prcr())) { + } else if (OB_ISNULL(cache_obj) || + OB_UNLIKELY(ObLibCacheNameSpace::NS_PRCR != cache_obj->get_ns())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("cache object is invalid", KPC(cache_obj)); } else { @@ -532,10 +534,11 @@ int MockCacheObjectFactory::alloc(ObPLPackage *&package, uint64_t tenant_id) { int ret = OB_SUCCESS; - ObPlanCacheObject *cache_obj = NULL; + ObILibCacheObject *cache_obj = NULL; if (OB_FAIL(alloc(cache_obj, ObLibCacheNameSpace::NS_PKG, tenant_id))) { LOG_WARN("alloc cache object failed", K(ret), K(tenant_id)); - } else if (OB_ISNULL(cache_obj) || OB_UNLIKELY(!cache_obj->is_pkg())) { + } else if (OB_ISNULL(cache_obj) || + OB_UNLIKELY(ObLibCacheNameSpace::NS_PKG != cache_obj->get_ns())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("cache object is invalid", KPC(cache_obj)); } else { @@ -548,7 +551,7 @@ int MockCacheObjectFactory::alloc(ObPLPackage *&package, return ret; } -int MockCacheObjectFactory::alloc(ObPlanCacheObject *&cache_obj, +int MockCacheObjectFactory::alloc(ObILibCacheObject *&cache_obj, ObLibCacheNameSpace ns, uint64_t tenant_id) { int ret = OB_SUCCESS; @@ -619,7 +622,7 @@ int MockCacheObjectFactory::alloc(ObPlanCacheObject *&cache_obj, return ret; } -void MockCacheObjectFactory::free(ObPlanCacheObject *cache_obj) +void MockCacheObjectFactory::free(ObILibCacheObject *cache_obj) { int ret = OB_SUCCESS; if (OB_ISNULL(cache_obj)) { @@ -638,12 +641,12 @@ void MockCacheObjectFactory::free(ObPlanCacheObject *cache_obj) } } -void MockCacheObjectFactory::inner_free(ObPlanCacheObject *cache_obj) +void MockCacheObjectFactory::inner_free(ObILibCacheObject *cache_obj) { int ret = OB_SUCCESS; lib::MemoryContext entity = cache_obj->get_mem_context(); - WITH_CONTEXT(entity) { cache_obj->~ObPlanCacheObject(); } + WITH_CONTEXT(entity) { cache_obj->~ObILibCacheObject(); } cache_obj = NULL; DESTROY_CONTEXT(entity); } diff --git a/unittest/sql/optimizer/test_optimizer_utils.h b/unittest/sql/optimizer/test_optimizer_utils.h index df0c91747..676b03928 100644 --- a/unittest/sql/optimizer/test_optimizer_utils.h +++ b/unittest/sql/optimizer/test_optimizer_utils.h @@ -50,7 +50,7 @@ namespace test class MockCacheObjectFactory { public: - static int alloc(ObPlanCacheObject *&cache_obj, ObLibCacheNameSpace ns, + static int alloc(ObILibCacheObject *&cache_obj, ObLibCacheNameSpace ns, uint64_t tenant_id = common::OB_SERVER_TENANT_ID); static int alloc(ObPhysicalPlan *&plan, uint64_t tenant_id = common::OB_SERVER_TENANT_ID); @@ -58,10 +58,10 @@ public: uint64_t tenant_id = common::OB_SERVER_TENANT_ID); static int alloc(pl::ObPLPackage *&package, uint64_t tenant_id = common::OB_SERVER_TENANT_ID); - static void free(ObPlanCacheObject *cache_obj); + static void free(ObILibCacheObject *cache_obj); private: - static void inner_free(ObPlanCacheObject *); + static void inner_free(ObILibCacheObject *); }; class TestOptimizerUtils : public TestSqlUtils, public ::testing::Test {