Files
oceanbase/src/sql/engine/cmd/ob_database_executor.cpp
wangzelin.wzl 93a1074b0c patch 4.0
2022-10-24 17:57:12 +08:00

309 lines
13 KiB
C++

/**
* Copyright (c) 2021 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.
*/
#include "sql/engine/cmd/ob_database_executor.h"
#include "sql/engine/cmd/ob_ddl_executor_util.h"
#include "sql/resolver/ddl/ob_create_database_stmt.h"
#include "sql/resolver/ddl/ob_use_database_stmt.h"
#include "sql/resolver/ddl/ob_alter_database_stmt.h"
#include "sql/resolver/ddl/ob_drop_database_stmt.h"
#include "sql/resolver/ddl/ob_flashback_stmt.h"
#include "sql/resolver/ddl/ob_purge_stmt.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/session/ob_sql_session_info.h"
#include "share/ob_common_rpc_proxy.h"
#include "lib/worker.h"
#include "share/ob_cluster_info_proxy.h"
#include "rootserver/ob_root_utils.h"
namespace oceanbase
{
using namespace common;
namespace sql
{
ObCreateDatabaseExecutor::ObCreateDatabaseExecutor()
{
}
ObCreateDatabaseExecutor::~ObCreateDatabaseExecutor()
{
}
int ObCreateDatabaseExecutor::execute(ObExecContext &ctx, ObCreateDatabaseStmt &stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx *task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy *common_rpc_proxy = NULL;
const obrpc::ObCreateDatabaseArg &create_database_arg = stmt.get_create_database_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
SQL_ENG_LOG(WARN, "fail to get first stmt" , K(ret));
} else {
const_cast<obrpc::ObCreateDatabaseArg&>(create_database_arg).ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
SQL_ENG_LOG(WARN, "get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)
|| OB_ISNULL(ctx.get_physical_plan_ctx())) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "fail to get physical plan ctx", K(ret), K(ctx), K(common_rpc_proxy));
} else {
//为什么create database的协议需要返回database_id,暂时没有用上。
obrpc::UInt64 database_id(0);
if (OB_FAIL(common_rpc_proxy->create_database(create_database_arg, database_id))) {
SQL_ENG_LOG(WARN, "rpc proxy create table failed", K(ret));
} else {
ctx.get_physical_plan_ctx()->set_affected_rows(1);
}
}
SQL_ENG_LOG(INFO, "finish execute create database.", K(ret), K(stmt));
return ret;
}
/////////////////////
ObUseDatabaseExecutor::ObUseDatabaseExecutor()
{
}
ObUseDatabaseExecutor::~ObUseDatabaseExecutor()
{
}
int ObUseDatabaseExecutor::execute(ObExecContext &ctx, ObUseDatabaseStmt &stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo *session = NULL;
if (OB_ISNULL(session = ctx.get_my_session())) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "session is NULL");
} else {
const bool is_oracle_mode = lib::is_oracle_mode();
const bool is_oceanbase_db = is_oceanbase_sys_database_id(stmt.get_db_id());
if (session->is_tenant_changed() && !is_oceanbase_db) {
ret = OB_OP_NOT_ALLOW;
SQL_ENG_LOG(WARN, "tenant changed, access non oceanbase database not allowed", K(ret), K(stmt),
"login_tenant_id", session->get_login_tenant_id(),
"effective_tenant_id", session->get_effective_tenant_id());
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "tenant changed, access non oceanbase database");
} else if (is_oracle_mode && is_oceanbase_db) {
ret = OB_OP_NOT_ALLOW;
SQL_ENG_LOG(WARN, "cannot access oceanbase database on tenant with oracle compatiblity", K(ret),
"effective_tenant_id", session->get_effective_tenant_id());
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "access oceanbase database");
} else {
ObCollationType db_coll_type = ObCharset::collation_type(stmt.get_db_collation());
if (OB_UNLIKELY(CS_TYPE_INVALID == db_coll_type)) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "invalid collation", K(ret), K(stmt.get_db_name()), K(stmt.get_db_collation()));
} else if (OB_FAIL(session->set_default_database(stmt.get_db_name(), db_coll_type))) {
SQL_ENG_LOG(WARN, "fail to set default database", K(ret), K(stmt.get_db_name()), K(stmt.get_db_collation()), K(db_coll_type));
} else {
session->set_db_priv_set(stmt.get_db_priv_set());
SQL_ENG_LOG(INFO, "use default database", "db", stmt.get_db_name());
session->set_database_id(stmt.get_db_id());
}
}
}
return ret;
}
//////////////////
ObAlterDatabaseExecutor::ObAlterDatabaseExecutor()
{
}
ObAlterDatabaseExecutor::~ObAlterDatabaseExecutor()
{
}
int ObAlterDatabaseExecutor::execute(ObExecContext &ctx, ObAlterDatabaseStmt &stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx *task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy *common_rpc_proxy = NULL;
const obrpc::ObAlterDatabaseArg &alter_database_arg = stmt.get_alter_database_arg();
ObString first_stmt;
ObSQLSessionInfo *session = NULL;
if (OB_ISNULL(session = ctx.get_my_session())) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "session is NULL");
} else if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
SQL_ENG_LOG(WARN, "fail to get first stmt" , K(ret));
} else {
const_cast<obrpc::ObAlterDatabaseArg&>(alter_database_arg).ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get common rpc proxy failed");
} else if (OB_FAIL(common_rpc_proxy->alter_database(alter_database_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy alter table failed", K(ret));
} else if (! stmt.get_alter_option_set().has_member(obrpc::ObAlterDatabaseArg::COLLATION_TYPE)) {
// do nothing
} else if (0 == stmt.get_database_name().compare(session->get_database_name())) {
const int64_t db_coll = static_cast<int64_t>(stmt.get_collation_type());
if (OB_FAIL(session->update_sys_variable(share::SYS_VAR_CHARACTER_SET_DATABASE, db_coll))) {
SQL_ENG_LOG(WARN, "failed to update sys variable", K(ret));
} else if (OB_FAIL(session->update_sys_variable(share::SYS_VAR_COLLATION_DATABASE, db_coll))) {
SQL_ENG_LOG(WARN, "failed to update sys variable", K(ret));
}
}
return ret;
}
//////////////////
ObDropDatabaseExecutor::ObDropDatabaseExecutor()
{
}
ObDropDatabaseExecutor::~ObDropDatabaseExecutor()
{
}
int ObDropDatabaseExecutor::execute(ObExecContext &ctx, ObDropDatabaseStmt &stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx *task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy *common_rpc_proxy = NULL;
const obrpc::ObDropDatabaseArg &drop_database_arg = stmt.get_drop_database_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
SQL_ENG_LOG(WARN, "fail to get first stmt" , K(ret));
} else {
const_cast<obrpc::ObDropDatabaseArg&>(drop_database_arg).ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
SQL_ENG_LOG(WARN, "get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy) || OB_ISNULL(ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "failt to get my session", K(ctx), K(common_rpc_proxy));
} else {
obrpc::UInt64 affected_row(0);
obrpc::ObDropDatabaseRes drop_database_res;
const_cast<obrpc::ObDropDatabaseArg&>(drop_database_arg).compat_mode_ = ORACLE_MODE == ctx.get_my_session()->get_compatibility_mode()
? lib::Worker::CompatMode::ORACLE : lib::Worker::CompatMode::MYSQL;
if (OB_FAIL(common_rpc_proxy->drop_database(drop_database_arg, drop_database_res))) {
SQL_ENG_LOG(WARN, "rpc proxy drop table failed",
"timeout", THIS_WORKER.get_timeout_remain(), K(ret));
} else if (OB_ISNULL(ctx.get_physical_plan_ctx())) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "fail to get physical plan ctx", K(ret), K(ctx));
} else {
ObString null_string;
ObNameCaseMode case_mode = OB_NAME_CASE_INVALID;
if (OB_FAIL(ctx.get_my_session()->get_name_case_mode(case_mode))) {
SQL_ENG_LOG(WARN, "fail to get name case mode from session", K(ret));
} else if (ObCharset::case_mode_equal(case_mode,
ctx.get_my_session()->get_database_name(),
drop_database_arg.database_name_)) {
ObCollationType server_coll_type = ObCharset::collation_type(stmt.get_server_collation());
if (OB_UNLIKELY(CS_TYPE_INVALID == server_coll_type)) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "invalid collation", K(ret), K(stmt.get_server_collation()));
} else if (OB_FAIL(ctx.get_my_session()->set_default_database(null_string, server_coll_type))) {
SQL_ENG_LOG(WARN, "fail to set default database", K(ret), K(stmt.get_server_collation()), K(server_coll_type));
} else {
ctx.get_physical_plan_ctx()->set_affected_rows(drop_database_res.affected_row_);
ctx.get_my_session()->set_database_id(OB_INVALID_ID);
}
}
}
if (OB_SUCC(ret) && drop_database_res.is_valid()) {
int64_t affected_rows = 0;
ObSQLSessionInfo *my_session = nullptr;
if (OB_ISNULL(my_session = ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "my_session is nullptr", K(ret));
} else if (drop_database_res.is_valid() &&
OB_FAIL(ObDDLExecutorUtil::wait_ddl_retry_task_finish(drop_database_res.ddl_res_.tenant_id_,
drop_database_res.ddl_res_.task_id_,
*my_session, common_rpc_proxy, affected_rows))) {
SQL_ENG_LOG(WARN, "wait ddl finish failed", K(ret));
} else {
ctx.get_physical_plan_ctx()->set_affected_rows(affected_rows);
}
}
}
SQL_ENG_LOG(INFO, "finish execute drop database.", K(ret), K(stmt));
return ret;
}
int ObFlashBackDatabaseExecutor::execute(ObExecContext &ctx, ObFlashBackDatabaseStmt &stmt)
{
int ret = OB_SUCCESS;
const obrpc::ObFlashBackDatabaseArg &flashback_database_arg = stmt.get_flashback_database_arg();
ObTaskExecutorCtx *task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy *common_rpc_proxy = NULL;
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
SQL_ENG_LOG(WARN, "fail to get first stmt" , K(ret));
} else {
const_cast<obrpc::ObFlashBackDatabaseArg&>(flashback_database_arg).ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
SQL_ENG_LOG(WARN, "get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)){
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->flashback_database(flashback_database_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy flashback database failed", K(ret));
}
return ret;
}
int ObPurgeDatabaseExecutor::execute(ObExecContext &ctx, ObPurgeDatabaseStmt &stmt)
{
int ret = OB_SUCCESS;
const obrpc::ObPurgeDatabaseArg &purge_database_arg = stmt.get_purge_database_arg();
ObTaskExecutorCtx *task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy *common_rpc_proxy = NULL;
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
SQL_ENG_LOG(WARN, "fail to get first stmt" , K(ret));
} else {
const_cast<obrpc::ObPurgeDatabaseArg&>(purge_database_arg).ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
SQL_ENG_LOG(WARN, "get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)){
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->purge_database(purge_database_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy purge database failed", K(ret));
}
return ret;
}
}
}