[FEAT MERGE] 4.1 PL/SQL enhence & development

This commit is contained in:
obdev 2023-01-09 08:47:31 +00:00 committed by ob-robot
parent 322032b9ca
commit 08802d94f6
98 changed files with 5260 additions and 2676 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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...) \

View File

@ -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;

View File

@ -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());

View File

@ -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());

View File

@ -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 &params, 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 &params,
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 &params,
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;

View File

@ -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 &params,
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 &params,
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 &params, 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);

View File

@ -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();

View File

@ -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_;

View File

@ -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

View File

@ -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 &params,
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_ = &params;
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_;
/* !!!
* PLreq_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_ = &params;
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_ = &params;
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 &params,
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, &params));
OZ (compiler.compile(
block_node, *routine, &params, 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 &params)
{
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;

View File

@ -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 &params);
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 &params,
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 &params,
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_;

View File

@ -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;
// 初始化符号表

View File

@ -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,

View File

@ -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)) {

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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(),

View File

@ -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,

View File

@ -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,

View File

@ -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> &params) { 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:
};

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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;
}
;

View 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 &param_info,
const ObObjParam &param,
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;
}
}
}

View 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 &param_info,
const ObObjParam &param,
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

View 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;
}
}
}

View 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

View File

@ -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)));
}

View File

@ -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_;

View File

@ -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,

View File

@ -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,

View File

@ -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));
}
}
}
}

View File

@ -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);

View File

@ -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
{

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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_),

View File

@ -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;
}

View File

@ -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()));

View File

@ -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();

View File

@ -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,

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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;
}

View File

@ -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_;

View File

@ -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(),

View File

@ -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));

View File

@ -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));
}

View File

@ -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 &param);
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

File diff suppressed because it is too large Load Diff

View File

@ -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 &param_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 &current_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,

View File

@ -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(), &params))) {
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 &params,
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 &param,
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 &param_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 &params,
return ret;
}
int ObSql::construct_ps_param(const ParamStore &params,
ObPlanCacheCtx &phy_ctx)
int ObSql::construct_parameterized_params(const ParamStore &params,
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(&params.at(i)))) {
if (OB_FAIL(phy_ctx.fp_result_.parameterized_params_.push_back(&params.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 {

View File

@ -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 &params,
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 &params,
ObResultSet &result,
ObSqlCtx &context,
bool is_prepare_protocol,
bool is_dynamic_sql);
static int construct_parameterized_params(const ParamStore &params,
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 &params,
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 &params,
ParamStore &param_store);
int construct_ps_param_store(const ParamStore &params,
const ParamStore &fixed_params,
const ObIArray<int64_t> &fixed_param_idx,
ParamStore &param_store);
int construct_param_store_from_ps_param(const ObPlanCacheCtx &phy_ctx,
ParamStore &param_store);
int construct_param_store_from_parameterized_params(const ObPlanCacheCtx &phy_ctx,
ParamStore &param_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 &params_store,
ParamStore *&params);
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 &params,
@ -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

View File

@ -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));

View File

@ -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*/

View File

@ -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
}

View File

@ -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; }

View File

@ -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.

View File

@ -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(); }

View File

@ -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_

View File

@ -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()) {

View File

@ -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

View File

@ -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

View File

@ -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))) {

View File

@ -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:

View File

@ -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_;

View File

@ -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)) {

View File

@ -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,

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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));

View File

@ -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";

View File

@ -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;

View File

@ -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("("))) {

View File

@ -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_;

View File

@ -2346,12 +2346,22 @@ int ObRawExprResolverImpl::process_datatype_or_questionmark(const ParseNode &nod
OX (ctx_.prepare_param_count_++);
}
} else {
/*
*
* 1PL里的sql语句select * from t where a1=:a and a2=bb是PL local变量
* 2ps过来的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);

View File

@ -1015,7 +1015,19 @@ int ObRawExprUtils::resolve_udf_param_exprs(ObResolverParams &params,
}
}
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 &params,
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));

View File

@ -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;

View File

@ -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,

View File

@ -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();
}
}

View File

@ -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,

View File

@ -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);
}

View File

@ -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 {