[FEAT MERGE] 4.1 PL/SQL enhence & development
This commit is contained in:
parent
322032b9ca
commit
08802d94f6
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
6
deps/oblib/src/lib/oblog/ob_log_module.h
vendored
6
deps/oblib/src/lib/oblog/ob_log_module.h
vendored
@ -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...) \
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
|
@ -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<char *>(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<ObTableRowCount> *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;
|
||||
|
@ -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 <typename T>
|
||||
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);
|
||||
|
@ -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<ObPlanCacheObject*>(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();
|
||||
|
@ -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<uint64_t, 1024> plan_id_array_;
|
||||
|
@ -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
|
||||
|
730
src/pl/ob_pl.cpp
730
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<ObPCParam *, OB_PC_SPECIAL_PARAM_COUNT> 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<int64_t>(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<ParseNode *>(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<ObPLFunction*>(
|
||||
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<ObPLFunction*>(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<ObPLFunction*>(
|
||||
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<ObPLFunction*>(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<ObPLFunction*>(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<ObPLFunction*>(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<ObPLFunction*>(cacheobj_guard.get_cache_obj()));
|
||||
@ -1638,15 +1855,15 @@ int ObPL::get_pl_function(ObExecContext &ctx,
|
||||
OX (routine = static_cast<ObPLFunction*>(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<ObPLFunction*>(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<ObPLFunction*>(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<sql::ObSqlExpression *> &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<ObPLSqlInfo> &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<ObPLCacheCtx&>(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<const pl::ObPLFunction *>(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<ObPsStmtId>& 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<ObPlanCacheCtx&>(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<ObPLCacheCtx&>(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;
|
||||
|
151
src/pl/ob_pl.h
151
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<ObParamInfo,
|
||||
common::OB_MALLOC_BIG_BLOCK_SIZE,
|
||||
common::ObWrapperAllocator, false> &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<ObPLFunction*> &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<ObParamInfo,
|
||||
common::OB_MALLOC_BIG_BLOCK_SIZE,
|
||||
common::ObWrapperAllocator, false> params_info_;
|
||||
|
||||
common::ObFixedArray<ObPLFunction*, common::ObIAllocator> routine_table_;
|
||||
common::ObArray<ObUserDefinedType *> 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<sql::ObSqlExpression *> &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<const sql::ObSqlExpression *, common::ObIAllocator> params_;
|
||||
ObFixedArray<const sql::ObSqlExpression *, common::ObIAllocator> array_binding_params_;
|
||||
common::ObString ps_sql_;
|
||||
sql::stmt::StmtType stmt_type_;
|
||||
uint64_t rowid_table_id_;
|
||||
|
||||
ObFixedArray<const sql::ObSqlExpression *, common::ObIAllocator> into_;
|
||||
ObFixedArray<bool, common::ObIAllocator> not_null_flags_;
|
||||
ObFixedArray<int64_t, common::ObIAllocator> pl_integer_ranges_;
|
||||
ObFixedArray<ObDataType, common::ObIAllocator> 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<ObPsStmtId>& ids,
|
||||
oceanbase::sql::ObSQLSessionInfo *session_info);
|
||||
void set_ps_cache(sql::ObPsCache* ps_cache);
|
||||
int get_subprogram(const ObIArray<int64_t> &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<ObPLSqlInfo, common::ObIAllocator>& 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<ObPLDataType, common::ObIAllocator> variables_; //根据ObPLSymbolTable的全局符号表生成,所有输入输出参数和PL体内使用的所有变量
|
||||
common::ObFixedArray<ObPLVarDebugInfo*, common::ObIAllocator> variables_debuginfo_;
|
||||
common::ObFixedArray<int64_t, common::ObIAllocator> default_idxs_;
|
||||
common::ObFixedArray<ObPLSqlInfo, common::ObIAllocator> sql_infos_;
|
||||
common::ObBitSet<common::OB_DEFAULT_BITSET_SIZE> in_args_;
|
||||
common::ObBitSet<common::OB_DEFAULT_BITSET_SIZE> out_args_;
|
||||
sql::ObExecEnv exec_env_;
|
||||
ObFuncPtr action_;
|
||||
char *di_buf_;
|
||||
int64_t di_len_;
|
||||
common::ObArray<ObPsStmtId> 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<OB_DEFAULT_BITSET_SIZE> &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_;
|
||||
|
@ -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<const ObConstRawExpr*>(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<ObLLVMValue, 16> 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<ObPLFunctionAST&>(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<ObPLFunctionAST&>(ast_);
|
||||
common::ObFixedArray<ObPLSqlInfo, common::ObIAllocator> &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<uint32_t>(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;
|
||||
// 初始化符号表
|
||||
|
@ -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,
|
||||
|
@ -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<ObDependencyInfo> 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<ObDependencyInfo> 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)) {
|
||||
|
||||
|
@ -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<const ObUserDefinedType*> &types, ObPLCompileUnit &unit);
|
||||
static int format_object_name(share::schema::ObSchemaGetterGuard &schema_guard,
|
||||
const uint64_t tenant_id,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<const ObConstRawExpr*>(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<ObPLCursor*>(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<int64_t>(),
|
||||
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(),
|
||||
|
@ -849,7 +849,7 @@ private:
|
||||
common::ObIArray<sql::ObUDFInfo> &udf_info,
|
||||
common::ObIArray<sql::ObOpRawExpr*> &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,
|
||||
|
@ -259,7 +259,7 @@ int ObPLConditionTable::add_condition(const common::ObString &name, const ObPLCo
|
||||
|
||||
int ObPLCursor::set(const ObString &sql,
|
||||
const ObIArray<int64_t> &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<int64_t> &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<int64_t> 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<int64_t> &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<int64_t> 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,
|
||||
|
@ -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<int64_t> &get_array_binding_params() const { return array_binding_params_; }
|
||||
inline common::ObIArray<int64_t> &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<share::schema::ObSchemaObjVersion> &get_ref_objects() const { return ref_objects_; }
|
||||
inline int set_ref_objects(const common::ObIArray<share::schema::ObSchemaObjVersion> &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<int64_t> params_;
|
||||
ObPLSEArray<int64_t> array_binding_params_;
|
||||
ObPsStmtId ps_id_;
|
||||
sql::stmt::StmtType stmt_type_;
|
||||
ObPLSEArray<share::schema::ObSchemaObjVersion> 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<int64_t> ¶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<int64_t> &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<int64_t> &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<int64_t> &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<sql::ObRawExpr*> &get_obj_access_exprs() const { return obj_access_exprs_; }
|
||||
inline common::ObIArray<sql::ObRawExpr*> &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<ObPsStmtId> &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<sql::ObRawExpr*> &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<sql::ObRawExpr*> &exprs);
|
||||
|
||||
inline const ObPLCompileFlag &get_compile_flag() const { return compile_flag_; }
|
||||
@ -1558,6 +1556,8 @@ public:
|
||||
priv_user_ = priv_user;
|
||||
}
|
||||
|
||||
inline ObIArray<ObPLSqlStmt *>& 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<sql::ObRawExpr*> obj_access_exprs_; //使用的ObjAccessRawExpr
|
||||
ObPLSEArray<sql::ObRawExpr*> exprs_; //使用的表达式,在AST里是ObRawExpr,在ObPLFunction里是ObISqlExpression
|
||||
ObBitSet<> simple_calc_bitset_; //可以使用LLVM进行计算的表达式下标
|
||||
ObPLSEArray<ObPsStmtId> ps_stmt_ids_; // 通过SpiPrepare的SQL RPEPARE ID
|
||||
ObPLSEArray<ObPLSqlStmt*> 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:
|
||||
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
;
|
||||
|
||||
|
986
src/pl/pl_cache/ob_pl_cache.cpp
Normal file
986
src/pl/pl_cache/ob_pl_cache.cpp
Normal file
@ -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<char *>(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<const ObPLObjectKey&>(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<char *>(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<const ObPLObjectKey&>(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<const pl::ObPLCompileUnit &>(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<ObPLObjectValue>::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<PCVPlSchemaObj> &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<PCVPlSchemaObj> &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<PCVPlSchemaObj> &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<PCVPlSchemaObj> &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<ObPLCacheCtx&>(ctx);
|
||||
const pl::ObPLCompileUnit &cache_object = static_cast<const pl::ObPLCompileUnit &>(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<ObParamInfo,
|
||||
OB_MALLOC_BIG_BLOCK_SIZE,
|
||||
ObWrapperAllocator, false> &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<ObPLCacheCtx&>(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<ObPLCacheCtx&>(ctx);
|
||||
pc_ctx.schema_guard_->set_session_id(pc_ctx.session_info_->get_sessid_for_table());
|
||||
ObSEArray<PCVPlSchemaObj, 4> 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<ObPLCacheCtx&>(ctx);
|
||||
pl::ObPLCompileUnit *cache_object = static_cast<pl::ObPLCompileUnit *>(cache_obj);
|
||||
ObSEArray<PCVPlSchemaObj, 4> 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
312
src/pl/pl_cache/ob_pl_cache.h
Normal file
312
src/pl/pl_cache/ob_pl_cache.h
Normal file
@ -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<ObPLObjectValue>
|
||||
{
|
||||
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<PCVPlSchemaObj> &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<PCVPlSchemaObj> &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<PCVPlSchemaObj> &schema_array);
|
||||
int match_dep_schema(const ObPLCacheCtx &pc_ctx,
|
||||
const ObIArray<PCVPlSchemaObj> &schema_array,
|
||||
bool &is_same);
|
||||
int add_match_info(ObILibCacheCtx &ctx,
|
||||
ObILibCacheKey *key,
|
||||
const ObILibCacheObject &cache_obj);
|
||||
|
||||
bool match_params_info(const Ob2DArray<ObParamInfo,
|
||||
OB_MALLOC_BIG_BLOCK_SIZE,
|
||||
ObWrapperAllocator, false> &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<PCVPlSchemaObj *, common::ObIAllocator> stored_schema_objs_;
|
||||
common::Ob2DArray<ObParamInfo, common::OB_MALLOC_BIG_BLOCK_SIZE,
|
||||
common::ObWrapperAllocator, false> 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<ObPLObjectValue> object_value_sets_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace pl end
|
||||
} // namespace oceanbase end
|
||||
|
||||
#endif
|
205
src/pl/pl_cache/ob_pl_cache_mgr.cpp
Normal file
205
src/pl/pl_cache/ob_pl_cache_mgr.cpp
Normal file
@ -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<ObPLCacheCtx&>(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<ObPLCacheCtx &>(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<pl::ObPLFunction*>(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<pl::ObPLPackage*>(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<ObPLCacheCtx&>(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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
81
src/pl/pl_cache/ob_pl_cache_mgr.h
Normal file
81
src/pl/pl_cache/ob_pl_cache_mgr.h
Normal file
@ -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
|
@ -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)));
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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<ObDependencyInfo> &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,
|
||||
|
@ -781,6 +781,7 @@ public:
|
||||
int create_trigger(share::schema::ObTriggerInfo &new_trigger_info,
|
||||
common::ObMySQLTransaction &trans,
|
||||
share::schema::ObErrorInfo &error_info,
|
||||
ObIArray<ObDependencyInfo> &dep_infos,
|
||||
const common::ObString *ddl_stmt_str/*=NULL*/,
|
||||
bool for_insert_errors,
|
||||
bool is_update_table_schema_version = true,
|
||||
|
@ -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<ObDependencyInfo, 1> 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<ObErrorInfo &>(arg.error_info_),
|
||||
const_cast<ObSArray<ObDependencyInfo> &>(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<ObDependencyInfo> &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<ObDependencyInfo, 1> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -859,6 +859,7 @@ public:
|
||||
// trigger
|
||||
int create_trigger_in_trans(share::schema::ObTriggerInfo &new_trigger_info,
|
||||
share::schema::ObErrorInfo &error_info,
|
||||
ObIArray<ObDependencyInfo> &dep_infos,
|
||||
const common::ObString *ddl_stmt_str,
|
||||
bool for_insert_errors,
|
||||
share::schema::ObSchemaGetterGuard &schema_guard);
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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<share::schema::ObTriggerInfo> trigger_infos_;
|
||||
bool is_set_status_;
|
||||
bool is_alter_compile_;
|
||||
};
|
||||
|
||||
struct ObCreateUDTArg : public ObDDLArg
|
||||
|
@ -330,35 +330,38 @@ int ObDependencyInfo::collect_dep_infos(const ObIArray<ObSchemaObjVersion> &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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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<char*>(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
|
||||
|
@ -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_),
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -449,7 +449,7 @@ int ObExprGeneratorImpl::visit(ObPlQueryRefRawExpr &expr)
|
||||
"expr type", get_type_name(expr.get_expr_type()));
|
||||
} else {
|
||||
ObExprOpSubQueryInPl *pl_subquery = static_cast<ObExprOpSubQueryInPl*>(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()));
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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<stmt::StmtType>(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<observer::ObInnerSQLResult*>(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<observer::ObInnerSQLResult*>(result_set);
|
||||
if (OB_FAIL(inner_result->next())) {
|
||||
ObResultSet *ob_result_set = static_cast<ObResultSet*>(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<ObExprPlSubQueryInfo *>(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<ObPlQueryRefRawExpr &> (static_cast<const ObPlQueryRefRawExpr&>(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;
|
||||
}
|
||||
|
||||
|
@ -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 <typename RE>
|
||||
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_;
|
||||
|
@ -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(),
|
||||
|
@ -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));
|
||||
|
@ -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 ObIArray<ObPCPa
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObResultSet::to_plan(const bool is_ps_mode, ObPhysicalPlan *phy_plan)
|
||||
int ObResultSet::to_plan(const PlanCacheMode mode, ObPhysicalPlan *phy_plan)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(phy_plan)) {
|
||||
@ -929,10 +930,12 @@ int ObResultSet::to_plan(const bool is_ps_mode, ObPhysicalPlan *phy_plan)
|
||||
} else {
|
||||
if (OB_FAIL(phy_plan->set_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));
|
||||
}
|
||||
|
@ -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<ObPCParam *> &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
|
||||
|
1910
src/sql/ob_spi.cpp
1910
src/sql/ob_spi.cpp
File diff suppressed because it is too large
Load Diff
191
src/sql/ob_spi.h
191
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<ObObj, OB_DEFAULT_SE_ARRAY_COUNT> 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<ObObj> &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<ObObj> &src_array,
|
||||
|
@ -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<ObDelUpdStmt *>(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<ObICmd*>(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<ObString &>(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<ObICmd*>(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<ParamStore *>(allocator.alloc(sizeof(ParamStore))))) {
|
||||
if (OB_NOT_NULL(first_group_params)) {
|
||||
// do nothing
|
||||
} else if (OB_ISNULL(first_group_params = static_cast<ParamStore *>(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<ParamStore *>(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 {
|
||||
|
@ -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<int64_t> &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<int64_t> &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
|
||||
|
@ -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));
|
||||
|
@ -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*/
|
||||
|
@ -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<const pl::ObPLFunction *>(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
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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.
|
||||
|
@ -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(); }
|
||||
|
@ -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_
|
||||
|
@ -107,11 +107,11 @@ int ObPCVSet::inner_get_cache_obj(ObILibCacheCtx &ctx,
|
||||
int ret = OB_SUCCESS;
|
||||
ObPlanCacheObject *plan = NULL;
|
||||
ObPlanCacheCtx &pc_ctx = static_cast<ObPlanCacheCtx&>(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()) {
|
||||
|
@ -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<ObILibCacheKey *, ObILibCacheNode *> 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<ObPlanCacheKey*>(entry.first);
|
||||
ObPCVSet *node = static_cast<ObPCVSet*>(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<pl::ObPLFunction*>(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>(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
|
||||
|
@ -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
|
||||
|
@ -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<AllocCacheObjInfo> 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))) {
|
||||
|
@ -28,6 +28,49 @@ namespace sql
|
||||
{
|
||||
class ObPlanCache;
|
||||
|
||||
struct ObKVEntryTraverseOp
|
||||
{
|
||||
typedef common::hash::HashMapPair<ObILibCacheKey *, ObILibCacheNode *> 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:
|
||||
|
@ -40,18 +40,27 @@ namespace sql
|
||||
|
||||
typedef common::ObSEArray<ObString, 1, common::ModulePageAllocator, true> 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<ObPCParam *, common::ObIAllocator> raw_params_;
|
||||
common::ObFixedArray<const common::ObObjParam *, common::ObIAllocator> ps_params_;
|
||||
common::ObFixedArray<const common::ObObjParam *, common::ObIAllocator> 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<SelectItemParamInfo, common::ObIAllocator> 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<ObFastParserResult, common::ObIAllocator> 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<int64_t, common::ObIAllocator> fixed_param_idx_;
|
||||
bool need_add_obj_stat_;
|
||||
|
@ -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)) {
|
||||
|
@ -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<ObDASTableLoc> &table_locs,
|
||||
|
@ -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;
|
||||
|
@ -65,6 +65,7 @@ struct TransformTreeCtx
|
||||
int64_t assign_father_level_;
|
||||
const ObIArray<FixedParamValue> *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<FixedParamValue> *udr_fixed_params)
|
||||
const ObIArray<FixedParamValue> *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<ObCollationType>(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<char *>(parse_malloc(child->str_len_ + 2, &alloc));
|
||||
char *new_raw_text = static_cast<char *>(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<char *>(parse_malloc(child->str_len_ + 2, &alloc));
|
||||
char *new_raw_text = static_cast<char *>(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<char *>(parse_malloc(const_node->str_len_ + 2, &alloc));
|
||||
char *new_raw_text = static_cast<char *>(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<char *>(parse_malloc(const_node->str_len_ + 2, &alloc));
|
||||
char *new_raw_text = static_cast<char *>(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;
|
||||
}
|
||||
}
|
||||
|
@ -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<FixedParamValue> *udr_fixed_params = NULL);
|
||||
const ObIArray<FixedParamValue> *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);
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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<ObItemType>(alter_clause.value_)) {
|
||||
tg_info.set_enable();
|
||||
} else if (T_DISABLE == static_cast<ObItemType>(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<ObItemType>(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<ObDependencyInfo> &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";
|
||||
|
@ -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<ObDependencyInfo> &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;
|
||||
|
@ -4242,7 +4242,7 @@ int ObPlQueryRefRawExpr::assign(const ObRawExpr &other)
|
||||
} else {
|
||||
const ObPlQueryRefRawExpr &tmp = static_cast<const ObPlQueryRefRawExpr &>(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("("))) {
|
||||
|
@ -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_;
|
||||
|
@ -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);
|
||||
|
@ -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<ObConstRawExpr*>(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<ObConstRawExpr*>(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<ObObjAccessRawExpr*>(iexpr);
|
||||
CK (OB_NOT_NULL(obj));
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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<ObString &>(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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<QuestionMarkDefNameCtx *>(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<ObString &>(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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user