Fix prepared statement does not check read only privilege
This commit is contained in:
@ -1951,6 +1951,52 @@ int ObSql::reconstruct_ps_params_store(ObIAllocator &allocator,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ObSql::check_read_only_privilege(ParseResult &parse_result,
|
||||||
|
ObExecContext &exec_ctx,
|
||||||
|
ObSchemaGetterGuard &schema_guard,
|
||||||
|
ObSqlTraits &sql_traits)
|
||||||
|
{
|
||||||
|
int ret = OB_SUCCESS;
|
||||||
|
bool read_only = false;
|
||||||
|
ObPhysicalPlanCtx *pctx = exec_ctx.get_physical_plan_ctx();
|
||||||
|
ObSQLSessionInfo *session = exec_ctx.get_my_session();
|
||||||
|
sql_traits.is_readonly_stmt_ = ObSQLUtils::is_readonly_stmt(parse_result);
|
||||||
|
sql_traits.is_modify_tenant_stmt_
|
||||||
|
= ObSQLUtils::is_modify_tenant_stmt(parse_result);
|
||||||
|
sql_traits.is_cause_implicit_commit_
|
||||||
|
= ObSQLUtils::cause_implicit_commit(parse_result);
|
||||||
|
sql_traits.is_commit_stmt_ = ObSQLUtils::is_commit_stmt(parse_result);
|
||||||
|
sql_traits.stmt_type_ = ObSQLUtils::get_sql_item_type(parse_result);
|
||||||
|
if (OB_ISNULL(pctx) || OB_ISNULL(session)) {
|
||||||
|
ret = OB_INVALID_ARGUMENT;
|
||||||
|
LOG_WARN("invalid argument", K(ret));
|
||||||
|
} else if (OB_FAIL(schema_guard.get_tenant_read_only(MTL_ID(), read_only))) {
|
||||||
|
LOG_WARN("fail to get tenant read only attribute", K(ret), K(MTL_ID()));
|
||||||
|
} else if (OB_FAIL(session->check_read_only_privilege(read_only,
|
||||||
|
sql_traits))) {
|
||||||
|
LOG_WARN("failed to check read_only privilege", K(ret));
|
||||||
|
if (ObSQLUtils::is_end_trans_stmt(parse_result)) {
|
||||||
|
int et_ret = OB_SUCCESS;
|
||||||
|
exec_ctx.set_need_disconnect(false);
|
||||||
|
//FIXME qianfu NG_TRACE_EXT(set_need_disconnect, OB_ID(need_disconnect), false);
|
||||||
|
LOG_WARN("is commit or rollback stmt, but fail to check read_only privilege, "
|
||||||
|
"rollback", K(ret));
|
||||||
|
int64_t plan_timeout = 0;
|
||||||
|
if (OB_SUCCESS != (et_ret = session->get_query_timeout(plan_timeout))) {
|
||||||
|
LOG_ERROR("fail to get query timeout", K(ret), K(et_ret));
|
||||||
|
} else {
|
||||||
|
pctx->set_timeout_timestamp(session->get_query_start_time() + plan_timeout);
|
||||||
|
// explicitly rollback the transaction, if it fails, the connection will be disconnected
|
||||||
|
if (OB_SUCCESS != (et_ret = ObSqlTransControl::explicit_end_trans(
|
||||||
|
exec_ctx, true))) {
|
||||||
|
LOG_ERROR("fail explicit rollback trans", K(ret), K(et_ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id,
|
int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id,
|
||||||
const stmt::StmtType stmt_type,
|
const stmt::StmtType stmt_type,
|
||||||
const ParamStore ¶ms,
|
const ParamStore ¶ms,
|
||||||
@ -2111,16 +2157,16 @@ int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id,
|
|||||||
ObParser parser(allocator, session.get_sql_mode(),
|
ObParser parser(allocator, session.get_sql_mode(),
|
||||||
session.get_local_collation_connection());
|
session.get_local_collation_connection());
|
||||||
ParseResult parse_result;
|
ParseResult parse_result;
|
||||||
|
ObSqlTraits sql_traits;
|
||||||
ParseMode parse_mode = context.is_dbms_sql_ ? DBMS_SQL_MODE :
|
ParseMode parse_mode = context.is_dbms_sql_ ? DBMS_SQL_MODE :
|
||||||
context.is_dynamic_sql_ ? DYNAMIC_SQL_MODE :
|
context.is_dynamic_sql_ ? DYNAMIC_SQL_MODE :
|
||||||
(context.session_info_->is_for_trigger_package() ? TRIGGER_MODE : STD_MODE);
|
(context.session_info_->is_for_trigger_package() ? TRIGGER_MODE : STD_MODE);
|
||||||
if (OB_FAIL(parser.parse(sql, parse_result, parse_mode))) {
|
if (OB_FAIL(parser.parse(sql, parse_result, parse_mode))) {
|
||||||
LOG_WARN("failed to parse sql", K(ret), K(sql), K(stmt_type));
|
LOG_WARN("failed to parse sql", K(ret), K(sql), K(stmt_type));
|
||||||
}
|
} else if (OB_FAIL(check_read_only_privilege(parse_result, ectx, *schema_guard, sql_traits))) {
|
||||||
|
LOG_WARN("failed to check read only privilege", K(ret));
|
||||||
if (OB_FAIL(ret)) {
|
} else if (OB_FAIL(generate_physical_plan(parse_result, NULL, context, result,
|
||||||
} else if (OB_FAIL(generate_physical_plan(
|
false /*is_begin_commit_stmt*/, PC_PS_MODE))) {
|
||||||
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));
|
LOG_WARN("generate physical plan failed", K(ret), K(sql), K(stmt_type));
|
||||||
} // TODO 生成物理计划的路径可x需q区分
|
} // TODO 生成物理计划的路径可x需q区分
|
||||||
}
|
}
|
||||||
@ -4022,17 +4068,6 @@ int ObSql::parser_and_check(const ObString &outlined_stmt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (OB_SUCC(ret)) {
|
if (OB_SUCC(ret)) {
|
||||||
const uint64_t tenant_id = session->get_effective_tenant_id();
|
|
||||||
ObSqlTraits &sql_traits = pc_ctx.sql_traits_;
|
|
||||||
sql_traits.is_readonly_stmt_ = ObSQLUtils::is_readonly_stmt(parse_result);
|
|
||||||
sql_traits.is_modify_tenant_stmt_
|
|
||||||
= ObSQLUtils::is_modify_tenant_stmt(parse_result);
|
|
||||||
sql_traits.is_cause_implicit_commit_
|
|
||||||
= ObSQLUtils::cause_implicit_commit(parse_result);
|
|
||||||
sql_traits.is_commit_stmt_ = ObSQLUtils::is_commit_stmt(parse_result);
|
|
||||||
sql_traits.stmt_type_ = ObSQLUtils::get_sql_item_type(parse_result);
|
|
||||||
|
|
||||||
bool read_only = false;
|
|
||||||
//租户级别的read only检查
|
//租户级别的read only检查
|
||||||
if (session->is_inner() || pc_ctx.is_begin_commit_stmt()) {
|
if (session->is_inner() || pc_ctx.is_begin_commit_stmt()) {
|
||||||
// FIXME:
|
// FIXME:
|
||||||
@ -4041,30 +4076,9 @@ int ObSql::parser_and_check(const ObString &outlined_stmt,
|
|||||||
} else if (OB_ISNULL(pc_ctx.sql_ctx_.schema_guard_)) {
|
} else if (OB_ISNULL(pc_ctx.sql_ctx_.schema_guard_)) {
|
||||||
ret = OB_ERR_UNEXPECTED;
|
ret = OB_ERR_UNEXPECTED;
|
||||||
LOG_WARN("invalid argument", K(pc_ctx.sql_ctx_.schema_guard_));
|
LOG_WARN("invalid argument", K(pc_ctx.sql_ctx_.schema_guard_));
|
||||||
} else if (OB_FAIL(pc_ctx.sql_ctx_.schema_guard_->get_tenant_read_only(tenant_id, read_only))) {
|
} else if (OB_FAIL(check_read_only_privilege(parse_result, exec_ctx,
|
||||||
LOG_WARN("fail to get tenant read only attribute", K(ret), K(tenant_id));
|
*pc_ctx.sql_ctx_.schema_guard_, pc_ctx.sql_traits_))) {
|
||||||
} else if (OB_FAIL(session->check_read_only_privilege(read_only,
|
LOG_WARN("failed to check read only privilege", K(ret));
|
||||||
sql_traits))) {
|
|
||||||
LOG_WARN("failed to check read_only privilege", K(ret));
|
|
||||||
if (ObSQLUtils::is_end_trans_stmt(parse_result)) {
|
|
||||||
int et_ret = OB_SUCCESS;
|
|
||||||
// 是commit或者rollback语句检查read only权限失败,不断连接
|
|
||||||
exec_ctx.set_need_disconnect(false);
|
|
||||||
//FIXME qianfu NG_TRACE_EXT(set_need_disconnect, OB_ID(need_disconnect), false);
|
|
||||||
LOG_WARN("is commit or rollback stmt, but fail to check read_only privilege, "
|
|
||||||
"rollback", K(ret));
|
|
||||||
// 回滚事务
|
|
||||||
int64_t plan_timeout = 0;
|
|
||||||
if (OB_SUCCESS != (et_ret = session->get_query_timeout(plan_timeout))) {
|
|
||||||
LOG_ERROR("fail to get query timeout", K(ret), K(et_ret));
|
|
||||||
} else {
|
|
||||||
pctx->set_timeout_timestamp(session->get_query_start_time() + plan_timeout);
|
|
||||||
if (OB_SUCCESS != (et_ret = ObSqlTransControl::explicit_end_trans(
|
|
||||||
exec_ctx, true))) { // 这里是显式回滚事务,失败了是要断连接的
|
|
||||||
LOG_ERROR("fail explicit rollback trans", K(ret), K(et_ret));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -474,6 +474,10 @@ private:
|
|||||||
int handle_text_execute(const ObStmt *basic_stmt, ObSqlCtx &sql_ctx, ObResultSet &result);
|
int handle_text_execute(const ObStmt *basic_stmt, ObSqlCtx &sql_ctx, ObResultSet &result);
|
||||||
int check_need_reroute(ObPlanCacheCtx &pc_ctx, ObSQLSessionInfo &session, ObPhysicalPlan *plan, bool &need_reroute);
|
int check_need_reroute(ObPlanCacheCtx &pc_ctx, ObSQLSessionInfo &session, ObPhysicalPlan *plan, bool &need_reroute);
|
||||||
int get_first_batched_multi_stmt(ObMultiStmtItem& multi_stmt_item, ObString& sql);
|
int get_first_batched_multi_stmt(ObMultiStmtItem& multi_stmt_item, ObString& sql);
|
||||||
|
int check_read_only_privilege(ParseResult &parse_result,
|
||||||
|
ObExecContext &exec_ctx,
|
||||||
|
ObSchemaGetterGuard &schema_guard,
|
||||||
|
ObSqlTraits &sql_traits);
|
||||||
static int add_param_to_param_store(const ObObjParam ¶m,
|
static int add_param_to_param_store(const ObObjParam ¶m,
|
||||||
ParamStore ¶m_store);
|
ParamStore ¶m_store);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user