init push

This commit is contained in:
oceanbase-admin
2021-05-31 22:56:52 +08:00
commit cea7de1475
7020 changed files with 5689869 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,158 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_CMD_OB_ALTER_SYSTEM_EXECUTOR_
#define OCEANBASE_SQL_ENGINE_CMD_OB_ALTER_SYSTEM_EXECUTOR_
#include "share/ob_define.h"
#include "sql/resolver/cmd/ob_alter_system_stmt.h"
#include "sql/resolver/cmd/ob_clear_balance_task_stmt.h"
namespace oceanbase {
namespace sql {
class ObExecContext;
class ObAdminServerStmt;
class ObAdminZoneStmt;
class ObBootstrapStmt;
#define DEF_SIMPLE_EXECUTOR(name) \
class name##Executor { \
public: \
name##Executor() \
{} \
virtual ~name##Executor() \
{} \
int execute(ObExecContext& ctx, name##Stmt& stmt); \
\
private: \
DISALLOW_COPY_AND_ASSIGN(name##Executor); \
}
DEF_SIMPLE_EXECUTOR(ObAdminServer);
DEF_SIMPLE_EXECUTOR(ObAdminZone);
DEF_SIMPLE_EXECUTOR(ObFreeze);
DEF_SIMPLE_EXECUTOR(ObFlushCache);
DEF_SIMPLE_EXECUTOR(ObFlushKVCache);
DEF_SIMPLE_EXECUTOR(ObFlushIlogCache);
DEF_SIMPLE_EXECUTOR(ObFlushDagWarnings);
DEF_SIMPLE_EXECUTOR(ObLoadBaseline);
DEF_SIMPLE_EXECUTOR(ObSwitchReplicaRole);
DEF_SIMPLE_EXECUTOR(ObSwitchRSRole);
DEF_SIMPLE_EXECUTOR(ObDropReplica);
DEF_SIMPLE_EXECUTOR(ObChangeReplica);
DEF_SIMPLE_EXECUTOR(ObMigrateReplica);
DEF_SIMPLE_EXECUTOR(ObReportReplica);
DEF_SIMPLE_EXECUTOR(ObRecycleReplica);
DEF_SIMPLE_EXECUTOR(ObAdminMerge);
DEF_SIMPLE_EXECUTOR(ObClearRoottable);
DEF_SIMPLE_EXECUTOR(ObRefreshSchema);
DEF_SIMPLE_EXECUTOR(ObRefreshMemStat);
DEF_SIMPLE_EXECUTOR(ObSetConfig);
DEF_SIMPLE_EXECUTOR(ObClearLocationCache);
DEF_SIMPLE_EXECUTOR(ObReloadGts);
DEF_SIMPLE_EXECUTOR(ObReloadUnit);
DEF_SIMPLE_EXECUTOR(ObReloadServer);
DEF_SIMPLE_EXECUTOR(ObReloadZone);
DEF_SIMPLE_EXECUTOR(ObClearMergeError);
DEF_SIMPLE_EXECUTOR(ObMigrateUnit);
DEF_SIMPLE_EXECUTOR(ObUpgradeVirtualSchema);
DEF_SIMPLE_EXECUTOR(ObAdminUpgradeCmd);
DEF_SIMPLE_EXECUTOR(ObAdminRollingUpgradeCmd);
DEF_SIMPLE_EXECUTOR(ObRunJob);
DEF_SIMPLE_EXECUTOR(ObRunUpgradeJob);
DEF_SIMPLE_EXECUTOR(ObStopUpgradeJob);
DEF_SIMPLE_EXECUTOR(ObBootstrap);
DEF_SIMPLE_EXECUTOR(ObSetTP);
DEF_SIMPLE_EXECUTOR(ObRefreshTimeZoneInfo);
DEF_SIMPLE_EXECUTOR(ObEnableSqlThrottle);
DEF_SIMPLE_EXECUTOR(ObDisableSqlThrottle);
DEF_SIMPLE_EXECUTOR(ObSetDiskValid);
DEF_SIMPLE_EXECUTOR(ObClearBalanceTask);
DEF_SIMPLE_EXECUTOR(ObAddDisk);
DEF_SIMPLE_EXECUTOR(ObDropDisk);
DEF_SIMPLE_EXECUTOR(ObArchiveLog);
DEF_SIMPLE_EXECUTOR(ObBackupDatabase);
DEF_SIMPLE_EXECUTOR(ObBackupManage);
DEF_SIMPLE_EXECUTOR(ObBackupSetEncryption);
DEF_SIMPLE_EXECUTOR(ObBackupSetDecryption);
class ObCancelTaskExecutor {
public:
ObCancelTaskExecutor()
{}
virtual ~ObCancelTaskExecutor()
{}
int execute(ObExecContext& ctx, ObCancelTaskStmt& stmt);
private:
int parse_task_id(const common::ObString& task_id_str, share::ObTaskId& task_id);
int fetch_sys_task_info(ObExecContext& ctx, const common::ObString& task_id, common::ObAddr& task_server);
private:
DISALLOW_COPY_AND_ASSIGN(ObCancelTaskExecutor);
};
class ObChangeTenantExecutor {
public:
ObChangeTenantExecutor()
{}
virtual ~ObChangeTenantExecutor()
{}
int execute(ObExecContext& ctx, ObChangeTenantStmt& stmt);
private:
private:
DISALLOW_COPY_AND_ASSIGN(ObChangeTenantExecutor);
};
#undef DEF_SIMPLE_EXECUTOR
} // end namespace sql
} // end namespace oceanbase
#endif // OCEANBASE_SQL_ENGINE_CMD_OB_ALTER_SYSTEM_EXECUTOR_

View File

@ -0,0 +1,56 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_baseline_executor.h"
#include "lib/string/ob_string.h"
#include "share/ob_common_rpc_proxy.h"
#include "share/ob_rpc_struct.h"
#include "share/schema/ob_schema_getter_guard.h"
#include "share/schema/ob_schema_struct.h"
#include "observer/ob_server_struct.h"
#include "sql/resolver/ddl/ob_alter_baseline_stmt.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/resolver/ob_schema_checker.h"
#include "sql/plan_cache/ob_cache_object_factory.h"
namespace oceanbase {
using namespace common;
using namespace share::schema;
using namespace obrpc;
namespace sql {
int ObAlterBaselineExecutor::execute(ObExecContext& ctx, ObAlterBaselineStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
ObAlterPlanBaselineArg& arg = stmt.alter_baseline_arg_;
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->alter_plan_baseline(arg))) {
LOG_WARN("rpc proxy alter baseline failed", "dst", common_rpc_proxy->get_server(), K(ret));
} else { /*do nothing*/
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,47 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_OB_BASELINE_EXECUTOR_H_
#define OCEANBASE_SQL_OB_BASELINE_EXECUTOR_H_
#include "lib/container/ob_vector.h"
#include "sql/parser/parse_node.h"
#include "sql/resolver/ob_stmt_type.h"
namespace oceanbase {
namespace common {
class ObString;
}
namespace share {
namespace schema {}
} // namespace share
namespace sql {
class ObExecContext;
class ObAlterBaselineStmt;
class ObLogPlan;
class ObDMLStmt;
class ObOptimizerContext;
class ObAlterBaselineExecutor {
public:
ObAlterBaselineExecutor()
{}
virtual ~ObAlterBaselineExecutor()
{}
int execute(ObExecContext& ctx, ObAlterBaselineStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObAlterBaselineExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif // OCEANBASE_SQL_OB_BASELINE_EXECUTOR_H_

View File

@ -0,0 +1,259 @@
/**
* 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/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_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 "share/ob_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 {
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 = share::is_oracle_mode();
const bool is_oceanbase_db = OB_SYS_DATABASE_ID == extract_pure_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);
if (OB_FAIL(common_rpc_proxy->drop_database(drop_database_arg, affected_row))) {
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(affected_row);
ctx.get_my_session()->set_database_id(OB_INVALID_ID);
}
}
}
}
SQL_ENG_LOG(INFO, "finish execute drop database.", K(ret), K(stmt));
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;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,99 @@
/**
* 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.
*/
#ifndef OCEANBASE_SRC_SQL_ENGINE_CMD_OB_DATABASE_EXECUTOR_H_
#define OCEANBASE_SRC_SQL_ENGINE_CMD_OB_DATABASE_EXECUTOR_H_
#include "share/ob_define.h"
#include "share/schema/ob_schema_getter_guard.h"
namespace oceanbase {
namespace sql {
class ObExecContext;
class ObCreateDatabaseStmt;
class ObDropDatabaseStmt;
class ObUseDatabaseStmt;
class ObAlterDatabaseStmt;
class ObFlashBackDatabaseStmt;
class ObPurgeDatabaseStmt;
class ObCreateDatabaseExecutor {
public:
ObCreateDatabaseExecutor();
virtual ~ObCreateDatabaseExecutor();
int execute(ObExecContext& ctx, ObCreateDatabaseStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObCreateDatabaseExecutor);
};
///////////////////////
class ObUseDatabaseExecutor {
public:
ObUseDatabaseExecutor();
virtual ~ObUseDatabaseExecutor();
int execute(ObExecContext& ctx, ObUseDatabaseStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObUseDatabaseExecutor);
};
///////////////////////
class ObAlterDatabaseExecutor {
public:
ObAlterDatabaseExecutor();
virtual ~ObAlterDatabaseExecutor();
int execute(ObExecContext& ctx, ObAlterDatabaseStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObAlterDatabaseExecutor);
};
/////////////////////
class ObDropDatabaseExecutor {
public:
ObDropDatabaseExecutor();
virtual ~ObDropDatabaseExecutor();
int execute(ObExecContext& ctx, ObDropDatabaseStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObDropDatabaseExecutor);
};
/* *
*
* */
class ObFlashBackDatabaseExecutor {
public:
ObFlashBackDatabaseExecutor()
{}
virtual ~ObFlashBackDatabaseExecutor()
{}
int execute(ObExecContext& ctx, ObFlashBackDatabaseStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObFlashBackDatabaseExecutor);
};
class ObPurgeDatabaseExecutor {
public:
ObPurgeDatabaseExecutor()
{}
virtual ~ObPurgeDatabaseExecutor()
{}
int execute(ObExecContext& ctx, ObPurgeDatabaseStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObPurgeDatabaseExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif /* OCEANBASE_SRC_SQL_ENGINE_CMD_OB_DATABASE_EXECUTOR_H_ */

View File

@ -0,0 +1,76 @@
/**
* 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_dblink_executor.h"
#include "sql/resolver/ddl/ob_create_dblink_stmt.h"
#include "sql/resolver/ddl/ob_drop_dblink_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 "share/ob_worker.h"
namespace oceanbase {
using namespace common;
namespace sql {
int ObCreateDbLinkExecutor::execute(ObExecContext& ctx, ObCreateDbLinkStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObCreateDbLinkArg& create_dblink_arg = stmt.get_create_dblink_arg();
const_cast<obrpc::ObCreateDbLinkArg&>(create_dblink_arg).ddl_stmt_str_ = stmt.get_sql_stmt();
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 if (OB_FAIL(common_rpc_proxy->create_dblink(create_dblink_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy create dblink failed", K(ret));
} else {
ctx.get_physical_plan_ctx()->set_affected_rows(1);
}
SQL_ENG_LOG(INFO, "finish execute create dblink.", K(ret), K(stmt));
return ret;
}
int ObDropDbLinkExecutor::execute(ObExecContext& ctx, ObDropDbLinkStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObDropDbLinkArg& drop_dblink_arg = stmt.get_drop_dblink_arg();
const_cast<obrpc::ObDropDbLinkArg&>(drop_dblink_arg).ddl_stmt_str_ = stmt.get_sql_stmt();
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 if (OB_FAIL(common_rpc_proxy->drop_dblink(drop_dblink_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy drop dblink failed", K(ret));
} else {
ctx.get_physical_plan_ctx()->set_affected_rows(1);
}
SQL_ENG_LOG(INFO, "finish execute drop dblink.", K(ret), K(stmt));
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,49 @@
/**
* 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.
*/
#ifndef OCEANBASE_SRC_SQL_ENGINE_CMD_OB_DBLINK_EXECUTOR_H_
#define OCEANBASE_SRC_SQL_ENGINE_CMD_OB_DBLINK_EXECUTOR_H_
#include "share/ob_define.h"
namespace oceanbase {
namespace sql {
class ObExecContext;
class ObCreateDbLinkStmt;
class ObDropDbLinkStmt;
class ObCreateDbLinkExecutor {
public:
ObCreateDbLinkExecutor()
{}
virtual ~ObCreateDbLinkExecutor()
{}
int execute(ObExecContext& ctx, ObCreateDbLinkStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObCreateDbLinkExecutor);
};
class ObDropDbLinkExecutor {
public:
ObDropDbLinkExecutor()
{}
virtual ~ObDropDbLinkExecutor()
{}
int execute(ObExecContext& ctx, ObDropDbLinkStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObDropDbLinkExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif /* OCEANBASE_SRC_SQL_ENGINE_CMD_OB_DBLINK_EXECUTOR_H_ */

View File

@ -0,0 +1,298 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_dcl_executor.h"
#include "lib/encrypt/ob_encrypted_helper.h"
#include "share/ob_rpc_struct.h"
#include "share/schema/ob_schema_struct.h"
#include "share/ob_common_rpc_proxy.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/resolver/dcl/ob_grant_stmt.h"
#include "sql/resolver/dcl/ob_revoke_stmt.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/engine/cmd/ob_user_cmd_executor.h"
namespace oceanbase {
using namespace common;
using namespace share::schema;
namespace sql {
int ObGrantExecutor::execute(ObExecContext& ctx, ObGrantStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
ObSQLSessionInfo* session_info = NULL;
const uint64_t tenant_id = stmt.get_tenant_id();
const ObStrings& users = stmt.get_users();
ObIAllocator& allocator = ctx.get_allocator();
obrpc::ObGrantArg& arg = static_cast<obrpc::ObGrantArg&>(stmt.get_ddl_arg());
const bool is_role = arg.roles_.count() > 0;
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(session_info = ctx.get_my_session())) {
ret = OB_NOT_INIT;
LOG_WARN("Get my session error");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (!is_role) {
ObString user_name;
ObString host_name;
ObString pwd;
ObString need_enc;
// i += 4, each with user_name, pwd, need_enc
if (OB_UNLIKELY(users.count() <= 0) || OB_UNLIKELY(0 != users.count() % 4)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Resolve users error. Users should have user and pwd", "ObStrings count", users.count(), K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < users.count(); i += 4) {
if (OB_FAIL(users.get_string(i, user_name))) {
LOG_WARN("Get string from ObStrings error", "count", users.count(), K(i), K(ret));
} else if (OB_FAIL(users.get_string(i + 1, host_name))) {
LOG_WARN("Get string from ObStrings error", "count", users.count(), K(i), K(ret));
} else if (OB_FAIL(users.get_string(i + 2, pwd))) {
LOG_WARN("Get string from ObStrings error", "count", users.count(), K(i), K(ret));
} else if (OB_FAIL(users.get_string(i + 3, need_enc))) {
LOG_WARN("Get string from ObStrings error", "count", users.count(), K(i), K(ret));
} else {
if (OB_FAIL(arg.users_passwd_.push_back(user_name))) {
LOG_WARN("failed to add user", K(ret));
} else if (OB_FAIL(arg.hosts_.push_back(host_name))) {
LOG_WARN("failed to add user", K(ret));
} else if (ObString::make_string("YES") == need_enc) {
ObString pwd_enc;
if (pwd.length() > 0) {
char* enc_buf = NULL;
if (NULL == (enc_buf = static_cast<char*>(allocator.alloc(ENC_BUF_LEN)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("Failed to allocate memory", K(ret), K(ENC_BUF_LEN));
} else if (OB_FAIL(ObCreateUserExecutor::encrypt_passwd(pwd, pwd_enc, enc_buf, ENC_BUF_LEN))) {
LOG_WARN("Encrypt password failed", K(ret));
} else {
} // do nothing
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(arg.users_passwd_.push_back(pwd_enc))) {
LOG_WARN("failed to add password", K(ret));
} else {
} // do nothing
} else {
if (OB_FAIL(arg.users_passwd_.push_back(pwd))) {
LOG_WARN("failed to add password", K(ret));
}
}
}
}
}
if (OB_SUCC(ret)) {
arg.tenant_id_ = tenant_id;
arg.db_ = stmt.get_database_name();
arg.table_ = stmt.get_table_name();
arg.priv_set_ = stmt.get_priv_set();
arg.priv_level_ = stmt.get_grant_level();
arg.need_create_user_ = stmt.get_need_create_user();
arg.has_create_user_priv_ = session_info->get_user_priv_set() & OB_PRIV_CREATE_USER;
arg.ddl_stmt_str_ = stmt.get_sql_stmt();
arg.option_ = stmt.get_option();
arg.object_type_ = stmt.get_object_type();
arg.object_id_ = stmt.get_object_id();
arg.grantor_id_ = stmt.get_grantor_id();
arg.ins_col_ids_ = stmt.get_ins_col_ids();
arg.upd_col_ids_ = stmt.get_upd_col_ids();
arg.ref_col_ids_ = stmt.get_ref_col_ids();
arg.is_inner_ = session_info->is_inner();
if (OB_FAIL(common_rpc_proxy->grant(arg))) {
LOG_WARN("Grant privileges to user error", K(ret), K(arg));
}
}
return ret;
}
int ObRevokeExecutor::execute(ObExecContext& ctx, ObRevokeStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else {
switch (stmt.get_grant_level()) {
case OB_PRIV_USER_LEVEL: {
if (OB_FAIL(revoke_user(common_rpc_proxy, stmt))) {
LOG_WARN("grant_revoke_user error", K(ret));
}
break;
}
case OB_PRIV_DB_LEVEL: {
if (OB_FAIL(revoke_db(common_rpc_proxy, stmt))) {
LOG_WARN("grant_revoke_user error", K(ret));
}
break;
}
case OB_PRIV_TABLE_LEVEL: {
if (OB_FAIL(revoke_table(common_rpc_proxy, stmt))) {
LOG_WARN("grant_revoke_user error", K(ret));
}
break;
case OB_PRIV_SYS_ORACLE_LEVEL: {
if (OB_FAIL(revoke_sys_priv(common_rpc_proxy, stmt))) {
LOG_WARN("grant_revoke_user error", K(ret));
}
break;
}
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Resolver may be error, invalid grant_level",
"grant_level",
ob_priv_level_str(stmt.get_grant_level()),
K(ret));
break;
}
}
}
return ret;
}
int ObRevokeExecutor::revoke_user(obrpc::ObCommonRpcProxy* rpc_proxy, ObRevokeStmt& stmt)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(rpc_proxy)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Input argument error", K(rpc_proxy), K(ret));
} else {
obrpc::ObRevokeUserArg& arg = static_cast<obrpc::ObRevokeUserArg&>(stmt.get_ddl_arg());
arg.tenant_id_ = stmt.get_tenant_id();
const ObIArray<uint64_t>& user_ids = stmt.get_users();
const bool is_role = arg.role_ids_.count() > 0;
if (is_role) {
for (int i = 0; OB_SUCC(ret) && i < user_ids.count(); ++i) {
arg.user_id_ = user_ids.at(i);
if (OB_FAIL(rpc_proxy->revoke_user(arg))) {
LOG_WARN("revoke user error", K(arg), K(ret));
}
}
} else if (0 == user_ids.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("User ids is empty, resolver may be error", K(ret));
} else {
arg.revoke_all_ = stmt.get_revoke_all();
arg.priv_set_ = stmt.get_priv_set();
for (int i = 0; OB_SUCC(ret) && i < user_ids.count(); i++) {
arg.user_id_ = user_ids.at(i);
if (OB_FAIL(rpc_proxy->revoke_user(arg))) {
LOG_WARN("revoke user error", K(arg), K(ret));
}
}
}
}
return ret;
}
int ObRevokeExecutor::revoke_db(obrpc::ObCommonRpcProxy* rpc_proxy, ObRevokeStmt& stmt)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(rpc_proxy)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Input argument error", K(rpc_proxy), K(ret));
} else {
obrpc::ObRevokeDBArg& arg = static_cast<obrpc::ObRevokeDBArg&>(stmt.get_ddl_arg());
arg.tenant_id_ = stmt.get_tenant_id();
arg.priv_set_ = stmt.get_priv_set();
arg.db_ = stmt.get_database_name();
const ObIArray<uint64_t>& user_ids = stmt.get_users();
if (0 == user_ids.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("User ids is empty, resolver may be error", K(ret));
} else {
for (int i = 0; OB_SUCC(ret) && i < user_ids.count(); i++) {
arg.user_id_ = user_ids.at(i);
if (OB_FAIL(rpc_proxy->revoke_database(arg))) {
LOG_WARN("revoke user error", K(arg), K(ret));
}
}
}
}
return ret;
}
int ObRevokeExecutor::revoke_table(obrpc::ObCommonRpcProxy* rpc_proxy, ObRevokeStmt& stmt)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(rpc_proxy)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Input argument error", K(rpc_proxy), K(ret));
} else {
obrpc::ObRevokeTableArg& arg = static_cast<obrpc::ObRevokeTableArg&>(stmt.get_ddl_arg());
arg.tenant_id_ = stmt.get_tenant_id();
arg.priv_set_ = stmt.get_priv_set();
arg.db_ = stmt.get_database_name();
arg.table_ = stmt.get_table_name();
arg.obj_id_ = stmt.get_obj_id();
arg.obj_type_ = static_cast<uint64_t>(stmt.get_object_type());
arg.grantor_id_ = stmt.get_grantor_id();
arg.revoke_all_ora_ = stmt.get_revoke_all_ora();
const ObIArray<uint64_t>& user_ids = stmt.get_users();
if (0 == user_ids.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("User ids is empty, resolver may be error", K(ret));
} else {
for (int i = 0; OB_SUCC(ret) && i < user_ids.count(); i++) {
arg.user_id_ = user_ids.at(i);
if (OB_FAIL(rpc_proxy->revoke_table(arg))) {
LOG_WARN("revoke user error", K(arg), K(ret));
}
}
}
}
return ret;
}
int ObRevokeExecutor::revoke_sys_priv(obrpc::ObCommonRpcProxy* rpc_proxy, ObRevokeStmt& stmt)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(rpc_proxy)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Input argument error", K(rpc_proxy), K(ret));
} else {
obrpc::ObRevokeSysPrivArg& arg = static_cast<obrpc::ObRevokeSysPrivArg&>(stmt.get_ddl_arg());
arg.tenant_id_ = stmt.get_tenant_id();
const ObIArray<uint64_t>& user_ids = stmt.get_users();
if (0 == user_ids.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("User ids is empty, resolver may be error", K(ret));
} else {
arg.ddl_stmt_str_ = stmt.get_sql_stmt();
for (int i = 0; OB_SUCC(ret) && i < user_ids.count(); i++) {
arg.grantee_id_ = user_ids.at(i);
if (OB_FAIL(rpc_proxy->revoke_sys_priv(arg))) {
LOG_WARN("revoke user error", K(arg), K(ret));
}
}
}
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,61 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_CMD_OB_DCL_EXECUTOR_
#define OCEANBASE_SQL_ENGINE_CMD_OB_DCL_EXECUTOR_
#include "share/ob_define.h"
namespace oceanbase {
namespace common {
class ObString;
}
namespace obrpc {
class ObCommonRpcProxy;
}
namespace sql {
class ObExecContext;
class ObGrantStmt;
class ObGrantExecutor {
public:
ObGrantExecutor()
{}
virtual ~ObGrantExecutor()
{}
int execute(ObExecContext& ctx, ObGrantStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObGrantExecutor);
};
class ObRevokeStmt;
class ObRevokeExecutor {
public:
ObRevokeExecutor()
{}
virtual ~ObRevokeExecutor()
{}
int execute(ObExecContext& ctx, ObRevokeStmt& stmt);
private:
int revoke_user(obrpc::ObCommonRpcProxy* rpc_proxy, ObRevokeStmt& stmt);
int revoke_db(obrpc::ObCommonRpcProxy* rpc_proxy, ObRevokeStmt& stmt);
int revoke_table(obrpc::ObCommonRpcProxy* rpc_proxy, ObRevokeStmt& stmt);
int revoke_sys_priv(obrpc::ObCommonRpcProxy* rpc_proxy, ObRevokeStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObRevokeExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif // OCEANBASE_SQL_ENGINE_CMD_OB_DCL_EXECUTOR_

View File

@ -0,0 +1,29 @@
/**
* 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_empty_query_executor.h"
#include "sql/resolver/cmd/ob_empty_query_stmt.h"
#include "sql/engine/ob_exec_context.h"
namespace oceanbase {
using namespace common;
namespace sql {
int ObEmptyQueryExecutor::execute(ObExecContext& ctx, ObEmptyQueryStmt& stmt)
{
UNUSED(ctx);
UNUSED(stmt);
int ret = OB_SUCCESS;
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,35 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_EMPTY_QUERY_EXECUTOR_H__
#define OCEANBASE_SQL_ENGINE_EMPTY_QUERY_EXECUTOR_H__
#include "share/ob_define.h"
namespace oceanbase {
namespace sql {
class ObExecContext;
class ObEmptyQueryStmt;
class ObEmptyQueryExecutor {
public:
ObEmptyQueryExecutor()
{}
virtual ~ObEmptyQueryExecutor()
{}
int execute(ObExecContext& ctx, ObEmptyQueryStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObEmptyQueryExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif /* OCEANBASE_SQL_ENGINE_EMPTY_QUERY_EXECUTOR_H__ */

View File

@ -0,0 +1,377 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "ob_index_executor.h"
#include "share/ob_common_rpc_proxy.h"
#include "share/system_variable/ob_system_variable_alias.h"
#include "share/schema/ob_table_schema.h"
#include "sql/resolver/ddl/ob_create_index_stmt.h"
#include "sql/resolver/ddl/ob_drop_index_stmt.h"
#include "sql/resolver/ddl/ob_purge_stmt.h"
#include "sql/resolver/ob_resolver_utils.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/engine/cmd/ob_partition_executor_utils.h"
#include "observer/ob_server.h"
using namespace oceanbase::common;
namespace oceanbase {
using namespace oceanbase::share::schema;
namespace sql {
ObCreateIndexExecutor::ObCreateIndexExecutor()
{}
ObCreateIndexExecutor::~ObCreateIndexExecutor()
{}
int ObCreateIndexExecutor::execute(ObExecContext& ctx, ObCreateIndexStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
obrpc::ObCreateIndexArg& create_index_arg = stmt.get_create_index_arg();
ObSQLSessionInfo* my_session = ctx.get_my_session();
const bool is_sys_index = is_inner_table(create_index_arg.index_table_id_);
obrpc::ObAlterTableRes res;
ObString first_stmt;
bool is_sync_ddl_user = false;
ObArenaAllocator allocator(ObModIds::OB_SQL_EXECUTOR);
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
create_index_arg.ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (NULL == my_session) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get my session", K(ret), K(ctx));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_FAIL(ObPartitionExecutorUtils::calc_values_exprs(ctx, stmt))) {
LOG_WARN("fail to compare range partition expr", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_INVALID_ID == create_index_arg.session_id_ &&
FALSE_IT(create_index_arg.session_id_ = my_session->get_sessid_for_table())) {
// impossible
} else if (FALSE_IT(create_index_arg.is_inner_ = my_session->is_inner())) {
} else if (OB_FAIL(common_rpc_proxy->create_index(create_index_arg, res))) {
LOG_WARN("rpc proxy create index failed", K(create_index_arg), "dst", common_rpc_proxy->get_server(), K(ret));
} else if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(my_session, is_sync_ddl_user))) {
LOG_WARN("Failed to check sync_dll_user", K(ret));
} else if (!is_sys_index && !is_sync_ddl_user) {
// only check sync index status for non-sys table and when it's not backup or restore
create_index_arg.index_schema_.set_table_id(res.index_table_id_);
create_index_arg.index_schema_.set_schema_version(res.schema_version_);
if (OB_FAIL(sync_check_index_status(*my_session, *common_rpc_proxy, create_index_arg, allocator))) {
LOG_WARN("failed to sync_check_index_status", K(create_index_arg), K(ret));
}
}
return ret;
}
int ObCreateIndexExecutor::set_drop_index_stmt_str(
obrpc::ObDropIndexArg& drop_index_arg, common::ObIAllocator& allocator)
{
int ret = OB_SUCCESS;
char* buf = NULL;
int64_t buf_len = OB_MAX_SQL_LENGTH;
int64_t pos = 0;
if (OB_ISNULL(buf = static_cast<char*>(allocator.alloc(buf_len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to allocate memory", K(ret), K(OB_MAX_SQL_LENGTH));
} else if (is_mysql_mode() && OB_FAIL(databuff_printf(buf,
buf_len,
pos,
"ALTER TABLE `%.*s`.`%.*s` DROP INDEX `%.*s`",
drop_index_arg.database_name_.length(),
drop_index_arg.database_name_.ptr(),
drop_index_arg.table_name_.length(),
drop_index_arg.table_name_.ptr(),
drop_index_arg.index_name_.length(),
drop_index_arg.index_name_.ptr()))) {
LOG_WARN("fail to print ddl_stmt_str for rollback", K(ret));
} else if (is_oracle_mode() && OB_FAIL(databuff_printf(buf,
buf_len,
pos,
"DROP INDEX \"%.*s\"",
drop_index_arg.index_name_.length(),
drop_index_arg.index_name_.ptr()))) {
LOG_WARN("fail to print ddl_stmt_str for rollback", K(ret));
} else {
drop_index_arg.ddl_stmt_str_.assign_ptr(buf, static_cast<int32_t>(pos));
}
return ret;
}
// is_update_global_indexes = true: creating index caused by drop/truncate partition,don't need to drop failed index
// when reports error. is_update_global_indexes = false:creating index caused by create index/alter table add index,need
// to drop failed index when reports error.
int ObCreateIndexExecutor::sync_check_index_status(sql::ObSQLSessionInfo& my_session,
obrpc::ObCommonRpcProxy& common_rpc_proxy, const obrpc::ObCreateIndexArg& create_index_arg,
common::ObIAllocator& allocator, bool is_update_global_indexes)
{
int ret = OB_SUCCESS;
// force refresh schema version, make sure version of observer is latest
THIS_WORKER.set_timeout_ts(ObTimeUtility::current_time() + OB_MAX_USER_SPECIFIED_TIMEOUT);
bool is_finish = false;
const static int CHECK_INTERVAL = 100 * 1000; // 100ms
obrpc::ObDropIndexArg drop_index_arg;
int64_t refreshed_schema_version = OB_INVALID_VERSION;
const uint64_t tenant_id = my_session.get_effective_tenant_id();
const uint64_t index_table_id = create_index_arg.index_schema_.get_table_id();
ObSqlString drop_index_sql;
if (!is_update_global_indexes) {
if (share::is_oracle_mode()) {
ret = drop_index_sql.append_fmt(
"drop index \"%.*s\"", create_index_arg.index_name_.length(), create_index_arg.index_name_.ptr());
} else {
ret = drop_index_sql.append_fmt("drop index `%.*s` on `%.*s`",
create_index_arg.index_name_.length(),
create_index_arg.index_name_.ptr(),
create_index_arg.table_name_.length(),
create_index_arg.table_name_.ptr());
}
if (!OB_SUCC(ret)) {
OB_LOG(WARN, "fail to append drop index sql", KR(ret));
} else {
drop_index_arg.tenant_id_ = create_index_arg.tenant_id_;
drop_index_arg.exec_tenant_id_ = create_index_arg.tenant_id_;
drop_index_arg.index_table_id_ = index_table_id;
drop_index_arg.session_id_ = create_index_arg.session_id_;
drop_index_arg.index_name_ = create_index_arg.index_name_;
drop_index_arg.table_name_ = create_index_arg.table_name_;
drop_index_arg.database_name_ = create_index_arg.database_name_;
drop_index_arg.index_action_type_ = obrpc::ObIndexArg::DROP_INDEX;
drop_index_arg.to_recyclebin_ = false;
drop_index_arg.ddl_stmt_str_ = drop_index_sql.string();
}
}
while (OB_SUCC(ret) && !is_finish) {
// check whether index_table_id received from rs is valid.
if (OB_UNLIKELY(OB_INVALID_ID == index_table_id)) {
is_finish = true;
if (true == create_index_arg.if_not_exist_) {
// if not exist, ignore error code and exit check_index_status
// since the index is not created, don't need to rollback.
break;
} else {
ret = OB_ERR_ADD_INDEX;
LOG_WARN("index table id is invalid", KR(ret), K(index_table_id));
}
}
// handle session timeout or killed first.
if (OB_FAIL(ret)) {
} else if (OB_FAIL(handle_session_exception(my_session))) {
if (!is_update_global_indexes && (OB_ERR_QUERY_INTERRUPTED == ret || OB_SESSION_KILLED == ret)) {
LOG_WARN("handle_session_exception", KR(ret));
int tmp_ret = OB_SUCCESS;
if (OB_SUCCESS != (tmp_ret = common_rpc_proxy.drop_index(drop_index_arg))) {
LOG_WARN("rpc proxy drop index failed",
"dst",
common_rpc_proxy.get_server(),
K(tmp_ret),
K(drop_index_arg.table_name_),
K(drop_index_arg.index_name_));
}
} else {
LOG_WARN("failed to handle_session_exception", KR(ret));
}
}
// If switch to standby db when it start to work,
// return session killed, and the index is handled by standby.
if (OB_FAIL(ret)) {
} else if (OB_SYS_TENANT_ID == tenant_id) {
// no need to process sys tenant
} else if (OB_FAIL(handle_switchover())) {
if (OB_SESSION_KILLED != ret) {
LOG_WARN("fail to handle switchover status", KR(ret));
} else {
LOG_WARN("fail to add index while swithover", KR(ret));
}
}
share::schema::ObMultiVersionSchemaService* schema_service = GCTX.schema_service_;
const ObTableSchema* index_schema = NULL;
share::schema::ObSchemaGetterGuard schema_guard;
if (OB_FAIL(ret)) {
} else if (NULL == schema_service) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get schema servicie", KR(ret));
} else if (OB_FAIL(schema_service->get_tenant_refreshed_schema_version(tenant_id, refreshed_schema_version))) {
LOG_WARN("fail to get tenant refreshed schema version", KR(ret), K(tenant_id), K(refreshed_schema_version));
} else if (refreshed_schema_version < create_index_arg.index_schema_.get_schema_version()) {
// not refresh schema after the index is created, check again after sleep
usleep(CHECK_INTERVAL);
LOG_INFO("we have not gotten the index schema",
K(index_table_id),
K(refreshed_schema_version),
K(create_index_arg.index_schema_.get_schema_version()));
} else if (OB_FAIL(schema_service->get_tenant_schema_guard(tenant_id, schema_guard))) {
LOG_WARN("get schema guard failed", KR(ret), K(refreshed_schema_version));
} else if (OB_FAIL(schema_guard.get_table_schema(index_table_id, index_schema))) {
LOG_WARN("fail to get index table schema", KR(ret), K(refreshed_schema_version), K(index_table_id));
} else if (OB_ISNULL(index_schema)) {
// maybe ddl(drop index,drop table,truncate table) in another session has dropped this index.
if (!is_update_global_indexes) {
ret = OB_ERR_ADD_INDEX;
LOG_USER_ERROR(OB_ERR_ADD_INDEX);
} else {
ret = OB_ERR_UNEXPECTED;
}
LOG_WARN("index table schema is null",
KR(ret),
K(index_table_id),
K(refreshed_schema_version),
K(create_index_arg.index_schema_.get_schema_version()));
} else if (!is_final_index_status(index_schema->get_index_status(), index_schema->is_dropped_schema())) {
usleep(CHECK_INTERVAL);
LOG_INFO("index status is not final", K(index_table_id));
} else {
is_finish = true;
LOG_INFO("index status is final", K(index_table_id), K(index_schema->get_index_status()));
if (is_error_index_status(index_schema->get_index_status(), index_schema->is_dropped_schema())) {
// status of index is ERROR, need to rollback.
if (is_update_global_indexes) {
ret = OB_ERR_DROP_TRUNCATE_PARTITION_REBUILD_INDEX;
LOG_USER_ERROR(OB_ERR_DROP_TRUNCATE_PARTITION_REBUILD_INDEX,
create_index_arg.index_name_.length(),
create_index_arg.index_name_.ptr());
} else {
ret = OB_ERR_ADD_INDEX;
LOG_USER_ERROR(OB_ERR_ADD_INDEX);
int tmp_ret = OB_SUCCESS;
if (OB_SUCCESS != (tmp_ret = set_drop_index_stmt_str(drop_index_arg, allocator))) {
LOG_WARN("fail to set drop index ddl_stmt_str", K(tmp_ret));
} else if (OB_SUCCESS != (tmp_ret = common_rpc_proxy.drop_index(drop_index_arg))) {
LOG_WARN("rpc proxy drop index failed",
"dst",
common_rpc_proxy.get_server(),
K(tmp_ret),
K(drop_index_arg.table_name_),
K(drop_index_arg.index_name_));
}
}
}
}
}
return ret;
}
int ObCreateIndexExecutor::handle_session_exception(ObSQLSessionInfo& session)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(session.is_query_killed())) {
ret = OB_ERR_QUERY_INTERRUPTED;
LOG_WARN("query is killed", K(ret));
} else if (OB_UNLIKELY(session.is_zombie())) {
ret = OB_SESSION_KILLED;
LOG_WARN("session is killed", K(ret));
}
return ret;
}
int ObCreateIndexExecutor::handle_switchover()
{
int ret = OB_SUCCESS;
if (GCTX.is_standby_cluster()) {
ret = OB_SESSION_KILLED;
LOG_INFO("create index while switchoverd, kill session", KR(ret));
}
return ret;
}
ObDropIndexExecutor::ObDropIndexExecutor()
{}
ObDropIndexExecutor::~ObDropIndexExecutor()
{}
int ObDropIndexExecutor::execute(ObExecContext& ctx, ObDropIndexStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObDropIndexArg& drop_index_arg = stmt.get_drop_index_arg();
ObSQLSessionInfo* my_session = ctx.get_my_session();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObDropIndexArg&>(drop_index_arg).ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (NULL == my_session) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get my session", K(ret), K(ctx));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_INVALID_ID == drop_index_arg.session_id_ &&
FALSE_IT(
const_cast<obrpc::ObDropIndexArg&>(drop_index_arg).session_id_ = my_session->get_sessid_for_table())) {
// impossible
} else if (OB_FAIL(common_rpc_proxy->drop_index(drop_index_arg))) {
LOG_WARN("rpc proxy drop index failed", "dst", common_rpc_proxy->get_server(), K(ret));
}
return ret;
}
int ObPurgeIndexExecutor::execute(ObExecContext& ctx, ObPurgeIndexStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObPurgeIndexArg& purge_index_arg = stmt.get_purge_index_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObPurgeIndexArg&>(purge_index_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;
LOG_WARN("get task executor context failed");
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->purge_index(purge_index_arg))) {
LOG_WARN("rpc proxy purge index failed", "dst", common_rpc_proxy->get_server(), K(ret));
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,80 @@
/**
* 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.
*/
#ifndef OCEANBASE_SRC_SQL_ENGINE_CMD_OB_INDEX_EXECUTOR_H_
#define OCEANBASE_SRC_SQL_ENGINE_CMD_OB_INDEX_EXECUTOR_H_
#include "lib/allocator/ob_allocator.h"
namespace oceanbase {
namespace obrpc {
struct ObCreateIndexArg;
struct ObDropIndexArg;
class ObCommonRpcProxy;
} // namespace obrpc
namespace sql {
class ObExecContext;
class ObCreateIndexStmt;
class ObSQLSessionInfo;
class ObCreateIndexExecutor {
public:
friend class ObAlterTableExecutor;
ObCreateIndexExecutor();
virtual ~ObCreateIndexExecutor();
int execute(ObExecContext& ctx, ObCreateIndexStmt& stmt);
private:
int set_drop_index_stmt_str(obrpc::ObDropIndexArg& drop_index_arg, common::ObIAllocator& allocator);
int sync_check_index_status(sql::ObSQLSessionInfo& my_session, obrpc::ObCommonRpcProxy& common_rpc_proxy,
const obrpc::ObCreateIndexArg& create_index_arg, common::ObIAllocator& allocator,
bool is_update_global_indexes = false);
int handle_session_exception(ObSQLSessionInfo& session);
int handle_switchover();
};
class ObDropIndexStmt;
class ObDropIndexExecutor {
public:
ObDropIndexExecutor();
virtual ~ObDropIndexExecutor();
int execute(ObExecContext& ctx, ObDropIndexStmt& stmt);
};
class ObFlashBackIndexStmt;
class ObFlashBackIndexExecutor {
public:
ObFlashBackIndexExecutor()
{}
virtual ~ObFlashBackIndexExecutor()
{}
int execute(ObExecContext& ctx, ObFlashBackIndexStmt& stmt);
private:
};
class ObPurgeIndexStmt;
class ObPurgeIndexExecutor {
public:
ObPurgeIndexExecutor()
{}
virtual ~ObPurgeIndexExecutor()
{}
int execute(ObExecContext& ctx, ObPurgeIndexStmt& stmt);
private:
};
} // namespace sql
} // namespace oceanbase
#endif /* OCEANBASE_SRC_SQL_ENGINE_CMD_OB_INDEX_EXECUTOR_H_ */

View File

@ -0,0 +1,248 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/resolver/cmd/ob_kill_stmt.h"
#include "sql/engine/cmd/ob_kill_executor.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/session/ob_sql_session_mgr.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/engine/cmd/ob_kill_session_arg.h"
#include "lib/net/ob_addr.h"
#include "lib/string/ob_sql_string.h"
#include "lib/mysqlclient/ob_mysql_proxy.h"
#include "share/ob_srv_rpc_proxy.h"
#include "observer/ob_server_struct.h"
#include "share/ob_rpc_struct.h"
namespace oceanbase {
using namespace common;
using namespace obrpc;
namespace sql {
int ObKillExecutor::execute(ObExecContext& ctx, ObKillStmt& stmt)
{
int ret = OB_SUCCESS;
ObKillSessionArg arg;
ObAddr addr;
ObSQLSessionMgr* session_mgr = ctx.get_session_mgr();
if (OB_ISNULL(session_mgr)) {
ret = OB_SUCCESS;
LOG_WARN("data member from ObExeccontext is NULL", K(ret), K(session_mgr));
} else if (OB_FAIL(arg.init(ctx, stmt))) {
LOG_WARN("fail to init kill_session arg", K(ret), K(arg), K(ctx), K(stmt));
} else if (OB_FAIL(kill_session(arg, *session_mgr))) {
if (OB_ENTRY_NOT_EXIST == ret) { // doesn't find sessid in current server
if (OB_FAIL(get_remote_session_location(arg, ctx, addr))) {
LOG_WARN("fail to get remote session location", K(ret), K(arg), K(ctx), K(addr));
} else if (OB_FAIL(kill_remote_session(ctx, addr, arg))) {
LOG_WARN("fail to kill remote session", K(ret), K(ctx), K(addr), K(arg));
} else { /*do nothing*/
}
} else {
LOG_WARN("fail to kill session", K(ret), K(arg));
}
} else { /*do nothing*/
}
if (OB_UNKNOWN_CONNECTION == ret) {
LOG_USER_ERROR(OB_UNKNOWN_CONNECTION, static_cast<uint64_t>(arg.sess_id_));
} else if (OB_ERR_KILL_DENIED == ret) {
LOG_USER_ERROR(OB_ERR_KILL_DENIED, static_cast<uint64_t>(arg.sess_id_));
}
return ret;
}
// If you are in system tenant, you can kill all threads and statements in any tenant.
// If you have the SUPER privilege, you can kill all threads and statements at your Tenant.
// Otherwise, you can kill only your own threads and statements.
int ObKillSession::kill_session(const ObKillSessionArg& arg, ObSQLSessionMgr& sess_mgr)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObSQLSessionInfo* sess_info = NULL;
ObAddr addr;
uint32_t sess_id = arg.sess_id_;
if (OB_FAIL(get_session(sess_mgr, sess_id, sess_info))) {
LOG_WARN("fail to get session", K(ret), K(sess_id));
} else if (OB_ISNULL(sess_info)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session info is NULL", K(ret), K(arg));
} else if ((OB_SYS_TENANT_ID == arg.tenant_id_) ||
((arg.tenant_id_ == sess_info->get_priv_tenant_id()) &&
(arg.has_user_super_privilege_ || arg.user_id_ == sess_info->get_user_id()))) {
if (arg.is_query_) {
if (OB_FAIL(sess_mgr.kill_query(*sess_info))) {
LOG_WARN("fail to kill query", K(ret), K(arg));
}
} else {
if (OB_FAIL(sess_mgr.kill_session(*sess_info))) {
LOG_WARN("fail to kill session", K(ret), K(arg));
}
}
} else {
ret = OB_ERR_KILL_DENIED;
}
if (OB_UNLIKELY(sess_info != NULL && OB_SUCCESS != (tmp_ret = sess_mgr.revert_session(sess_info)))) {
// ignore tmp_ret, our monitor will find the error
LOG_ERROR("revert session fail", K(tmp_ret), K(arg));
}
return ret;
}
int ObKillSession::get_session(ObSQLSessionMgr& sess_mgr, uint32_t sess_id, ObSQLSessionInfo*& sess_info)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
sess_info = NULL;
ObSQLSessionInfo* sess = NULL;
uint32_t version = 0;
do {
sess = NULL;
if (OB_FAIL(sess_mgr.get_session(version, sess_id, sess))) {
LOG_WARN("fail to get_session", K(ret), K(version), K(sess_id));
} else if (OB_ISNULL(sess)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get session fail", K(ret), K(version), K(sess_id));
} else if (OB_UNLIKELY(sess->is_shadow())) {
ret = OB_ENTRY_NOT_EXIST;
if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = sess_mgr.revert_session(sess)))) {
LOG_ERROR(
"fail to revert session", K(sess_id), K(version), "proxy_sessid", sess->get_proxy_sessid(), K(tmp_ret));
}
} else { /*do nothing*/
}
++version;
} while (OB_UNLIKELY(OB_ENTRY_NOT_EXIST == ret && version <= ObSQLSessionMgr::MAX_VERSION));
if (OB_SUCC(ret)) {
sess_info = sess;
}
return ret;
}
int ObKillExecutor::get_remote_session_location(const ObKillSessionArg& arg, ObExecContext& ctx, ObAddr& addr)
{
int ret = OB_SUCCESS;
SMART_VAR(ObMySQLProxy::MySQLResult, res)
{
ObMySQLProxy* sql_proxy = ctx.get_sql_proxy();
sqlclient::ObMySQLResult* result_set = NULL;
ObSQLSessionInfo* cur_sess = ctx.get_my_session();
ObSqlString read_sql;
char svr_ip[OB_IP_STR_BUFF] = "";
int64_t svr_port = 0;
int64_t tmp_real_str_len = 0;
// execute sql
if (OB_ISNULL(sql_proxy) || OB_ISNULL(cur_sess)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("sql proxy or sesion from exec context is NULL", K(ret), K(sql_proxy), K(cur_sess));
} else if (OB_FAIL(generate_read_sql(arg.sess_id_, read_sql))) {
LOG_WARN("fail to generate sql", K(ret), K(read_sql), K(*cur_sess), K(arg));
} else if (OB_FAIL(sql_proxy->read(res, read_sql.ptr()))) {
LOG_WARN("fail to read by sql proxy", K(ret), K(read_sql));
} else if (OB_ISNULL(result_set = res.get_result())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("result set is NULL", K(ret), K(read_sql));
} else { /*do nothing*/
}
// read result_set
if (OB_FAIL(ret)) {
} else if (OB_FAIL(result_set->next())) {
if (OB_LIKELY(OB_ITER_END == ret)) {
ret = OB_UNKNOWN_CONNECTION;
}
LOG_WARN("fail to get next row", K(ret), K(result_set));
} else {
UNUSED(tmp_real_str_len);
EXTRACT_STRBUF_FIELD_MYSQL(*result_set, "svr_ip", svr_ip, OB_IP_STR_BUFF, tmp_real_str_len);
EXTRACT_INT_FIELD_MYSQL(*result_set, "svr_port", svr_port, int64_t);
}
// set addr
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(OB_ITER_END != result_set->next())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("more than one sessid record", K(ret), K(arg), K(read_sql));
} else if (OB_UNLIKELY(!addr.set_ip_addr(svr_ip, static_cast<int32_t>(svr_port)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to set ip_addr", K(ret), K(svr_ip), K(svr_port));
} else { /*do nothing*/
}
}
return ret;
}
int ObKillExecutor::generate_read_sql(uint32_t sess_id, ObSqlString& sql)
{
int ret = OB_SUCCESS;
const char* sql_str = "select svr_ip, svr_port from oceanbase.__all_virtual_processlist \
where id = %u";
if (OB_FAIL(sql.append_fmt(sql_str, sess_id))) {
LOG_WARN("fail to append sql", K(ret), K(sess_id));
}
return ret;
}
int ObKillExecutor::kill_remote_session(ObExecContext& ctx, const ObAddr& addr, const ObKillSessionArg& arg)
{
int ret = OB_SUCCESS;
ObSrvRpcProxy* rpc_proxy = GCTX.srv_rpc_proxy_;
ObSQLSessionInfo* session = ctx.get_my_session();
ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(ctx);
if (OB_ISNULL(rpc_proxy) || OB_ISNULL(session) || OB_ISNULL(plan_ctx)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("some params are NULL", K(ret), K(rpc_proxy), K(session), K(plan_ctx));
} else {
int64_t timeout = plan_ctx->get_timeout_timestamp() - ObTimeUtility::current_time();
uint64_t tenant_id = THIS_WORKER.get_rpc_tenant() > 0 ? THIS_WORKER.get_rpc_tenant() : session->get_rpc_tenant_id();
if (OB_UNLIKELY(timeout <= 0)) {
ret = OB_TIMEOUT;
LOG_WARN("task_execute timeout before rpc",
K(ret),
K(addr),
K(timeout),
K(arg),
K(tenant_id),
"timeout_ts",
plan_ctx->get_timeout_timestamp());
} else if (OB_FAIL(rpc_proxy->to(addr).by(tenant_id).as(OB_SYS_TENANT_ID).timeout(timeout).kill_session(arg))) {
LOG_WARN("fail to kill remote session", K(ret), K(addr), K(tenant_id), K(timeout), K(arg));
} else { /*do nothing*/
}
}
return ret;
}
int ObRpcKillSessionP::process()
{
int ret = OB_SUCCESS;
ObKillSessionArg& arg = arg_;
ObSQLSessionMgr* session_mgr = gctx_.session_mgr_;
if (OB_ISNULL(session_mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session mgr from gctx is NULL", K(ret));
} else if (OB_FAIL(kill_session(arg, *session_mgr))) {
LOG_WARN("fail to kill sessoin", K(ret), K(arg));
ret = OB_ENTRY_NOT_EXIST == ret ? OB_UNKNOWN_CONNECTION : ret;
} else { /*do nothing*/
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,79 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_CMD_OB_KILL_EXECUTOR_H__
#define OCEANBASE_SQL_ENGINE_CMD_OB_KILL_EXECUTOR_H__
#include "share/ob_srv_rpc_proxy.h"
namespace oceanbase {
namespace observer {
class ObGlobalContext;
}
namespace common {
class ObSqlString;
class ObAddr;
} // namespace common
namespace sql {
class ObExecContext;
class ObKillStmt;
class ObSQLSessionInfo;
class ObSQLSessionMgr;
class ObKillSessionArg;
class ObKillSession {
public:
ObKillSession()
{}
virtual ~ObKillSession()
{}
protected:
int kill_session(const ObKillSessionArg& arg, ObSQLSessionMgr& sess_mgr);
private:
int get_session(ObSQLSessionMgr& ses_mgr, uint32_t sessid, ObSQLSessionInfo*& sess_info);
DISALLOW_COPY_AND_ASSIGN(ObKillSession);
};
class ObKillExecutor : public ObKillSession {
public:
ObKillExecutor()
{}
virtual ~ObKillExecutor()
{}
int execute(ObExecContext& ctx, ObKillStmt& stmt);
private:
int get_remote_session_location(const ObKillSessionArg& arg, ObExecContext& ctx, common::ObAddr& addr);
int generate_read_sql(uint32_t sess_id, common::ObSqlString& sql);
int kill_remote_session(ObExecContext& ctx, const common::ObAddr& addr, const ObKillSessionArg& arg);
DISALLOW_COPY_AND_ASSIGN(ObKillExecutor);
};
class ObRpcKillSessionP : public obrpc::ObRpcProcessor<obrpc::ObSrvRpcProxy::ObRpc<obrpc::OB_KILL_SESSION> >,
public ObKillSession {
public:
explicit ObRpcKillSessionP(const observer::ObGlobalContext& gctx) : gctx_(gctx)
{}
~ObRpcKillSessionP()
{}
protected:
int process();
private:
const observer::ObGlobalContext& gctx_;
};
} // namespace sql
} // namespace oceanbase
#endif /* OCEANBASE_SQL_ENGINE_CMD_OB_KILL_EXECUTOR_H__ */
//// end of header file

View File

@ -0,0 +1,113 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/resolver/cmd/ob_kill_stmt.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/code_generator/ob_expr_generator_impl.h"
#include "sql/engine/ob_physical_plan.h"
namespace oceanbase {
using namespace common;
namespace sql {
OB_SERIALIZE_MEMBER(ObKillSessionArg, sess_id_, tenant_id_, user_id_, is_query_, has_user_super_privilege_);
int ObKillSessionArg::init(ObExecContext& ctx, const ObKillStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session = NULL;
if (OB_ISNULL(session = ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session is NULL", K(ret), K(ctx));
} else if (OB_FAIL(calculate_sessid(ctx, stmt))) {
LOG_WARN("fail to calculate sessid", K(ret), K(ctx), K(stmt));
} else {
tenant_id_ = session->get_priv_tenant_id();
user_id_ = session->get_user_id();
is_query_ = stmt.is_query();
has_user_super_privilege_ = session->has_user_super_privilege();
}
return ret;
}
int ObKillSessionArg::calculate_sessid(ObExecContext& ctx, const ObKillStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* my_session = ctx.get_my_session();
ObPhysicalPlanCtx* plan_ctx = ctx.get_physical_plan_ctx();
ObPhysicalPlan phy_plan;
ObPhysicalPlanCtx phy_plan_ctx(ctx.get_allocator());
ObExecContext* exec_ctx = NULL; // because ObExecContext is bigger than 10K, can't use it as local variable
ObExprCtx expr_ctx;
ObNewRow tmp_row;
RowDesc row_desc;
ObExprGeneratorImpl expr_gen(0, 0, NULL, row_desc);
ObObj value_obj;
ObRawExpr* value_expr = NULL;
void* tmp_ptr = NULL;
if (OB_ISNULL(my_session) || OB_ISNULL(plan_ctx)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("data member from ObExecContext is Null", K(ret), K(my_session), K(plan_ctx));
} else {
ObArenaAllocator allocator(
common::ObModIds::OB_SQL_EXPR_CALC, OB_MALLOC_NORMAL_BLOCK_SIZE, my_session->get_effective_tenant_id());
ObSqlExpression sql_expr(allocator, 0);
const int64_t cur_time =
plan_ctx->has_cur_time() ? plan_ctx->get_cur_time().get_timestamp() : ObTimeUtility::current_time();
phy_plan_ctx.set_cur_time(cur_time, *my_session);
if (OB_UNLIKELY(NULL == (tmp_ptr = allocator.alloc(sizeof(ObExecContext))))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("fail to alloc ObExecContext", K(ret));
} else {
exec_ctx = new (tmp_ptr) ObExecContext;
phy_plan_ctx.set_phy_plan(&phy_plan);
expr_ctx.phy_plan_ctx_ = &phy_plan_ctx;
expr_ctx.my_session_ = my_session;
expr_ctx.exec_ctx_ = exec_ctx;
expr_ctx.calc_buf_ = &allocator;
if (OB_ISNULL(value_expr = stmt.get_value_expr())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to get value expr", K(ret), K(value_expr));
} else if (OB_FAIL(expr_gen.generate(*value_expr, sql_expr))) {
LOG_WARN("fail to fill sql expression", K(ret));
} else if (FALSE_IT(phy_plan.set_regexp_op_count(expr_gen.get_cur_regexp_op_count()))) {
// will not reach here
} else if (FALSE_IT(phy_plan.set_like_op_count(expr_gen.get_cur_like_op_count()))) {
// will not reach here
} else if (OB_FAIL(sql_expr.calc(expr_ctx, tmp_row, value_obj))) {
LOG_WARN("fail to calc value", K(ret), K(stmt.get_value_expr()));
} else {
const ObObj* res_obj = NULL;
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_WARN_ON_FAIL);
EXPR_CAST_OBJ_V2(ObUInt32Type, value_obj, res_obj);
ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD == ret ? OB_SUCCESS : ret;
if (OB_FAIL(ret)) {
LOG_WARN(
"fail to cast expr", "orig type", value_obj.get_type(), "dest type", "ObUint32type", K(ret), K(res_obj));
} else if (OB_ISNULL(res_obj)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN(
"fail to cast expr", "orig type", value_obj.get_type(), "dest type", "ObUint32type", K(ret), K(res_obj));
} else {
sess_id_ = res_obj->get_uint32();
}
}
}
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,51 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_CMD_OB_KILL_SESSION_ARG_H__
#define OCEANBASE_SQL_ENGINE_CMD_OB_KILL_SESSION_ARG_H__
#include <cstdint>
#include "lib/utility/ob_unify_serialize.h"
#include "lib/utility/ob_print_utils.h"
namespace oceanbase {
namespace sql {
class ObExecContext;
class ObKillStmt;
class ObKillSessionArg {
OB_UNIS_VERSION(1);
public:
ObKillSessionArg()
: sess_id_(0),
tenant_id_(common::OB_INVALID_TENANT_ID),
user_id_(common::OB_INVALID_ID),
is_query_(false),
has_user_super_privilege_(false)
{}
~ObKillSessionArg()
{}
int init(ObExecContext& ctx, const ObKillStmt& stmt);
int calculate_sessid(ObExecContext& ctx, const ObKillStmt& stmt);
TO_STRING_KV(K(sess_id_), K(tenant_id_), K(user_id_), K(is_query_), K(has_user_super_privilege_));
public:
uint32_t sess_id_;
uint64_t tenant_id_;
uint64_t user_id_;
bool is_query_;
bool has_user_super_privilege_;
};
} // namespace sql
} // namespace oceanbase
#endif

View File

@ -0,0 +1,43 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_load_data_executor.h"
#include "lib/oblog/ob_log_module.h"
#include "sql/engine/cmd/ob_load_data_impl.h"
#include "sql/engine/ob_exec_context.h"
namespace oceanbase {
namespace sql {
int ObLoadDataExecutor::execute(ObExecContext& ctx, ObLoadDataStmt& stmt)
{
int ret = OB_SUCCESS;
ObLoadDataBase* load_impl = NULL;
if (stmt.get_load_arguments().is_csv_format_
? OB_ISNULL(load_impl = OB_NEWx(ObLoadDataSPImpl, (&ctx.get_allocator())))
: OB_ISNULL(load_impl = OB_NEWx(ObLoadDataImpl, (&ctx.get_allocator())))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate memory failed", K(ret));
} else {
if (OB_FAIL(load_impl->execute(ctx, stmt))) {
LOG_WARN("failed to execute load data stmt", K(ret));
}
load_impl->~ObLoadDataBase();
ctx.get_allocator().free(load_impl);
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,39 @@
/**
* 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.
*/
#ifndef OCEANBASE_LOAD_DATA_EXECUTOR_H_
#define OCEANBASE_LOAD_DATA_EXECUTOR_H_
#include "sql/resolver/cmd/ob_load_data_stmt.h"
namespace oceanbase {
namespace sql {
class ObLoadDataStmt;
class ObLoadDataExecutor {
public:
ObLoadDataExecutor()
{}
virtual ~ObLoadDataExecutor()
{}
int execute(ObExecContext& ctx, ObLoadDataStmt& stmt);
private:
// disallow copy
DISALLOW_COPY_AND_ASSIGN(ObLoadDataExecutor);
// function members
private:
// data members
};
} // end namespace sql
} // end namespace oceanbase
#endif /* OCEANBASE_LOAD_DATA_EXECUTOR_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,705 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_load_data_rpc.h"
#include "observer/ob_server_struct.h"
#include "lib/oblog/ob_log_module.h"
#include "lib/string/ob_sql_string.h"
#include "lib/utility/serialization.h"
#include "share/ob_tenant_mgr.h"
#include "storage/ob_partition_service.h"
#include "storage/ob_dml_param.h"
#include "sql/parser/ob_parser.h"
#include "sql/resolver/ob_resolver.h"
#include "sql/resolver/dml/ob_insert_stmt.h"
#include "sql/plan_cache/ob_sql_parameterization.h"
#include "sql/code_generator/ob_expr_generator_impl.h"
#include "sql/code_generator/ob_code_generator.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/engine/cmd/ob_load_data_impl.h"
using namespace oceanbase::sql;
using namespace oceanbase::common;
using namespace oceanbase::share;
using namespace oceanbase::share::schema;
using namespace oceanbase::storage;
namespace oceanbase {
namespace sql {
int ObLoadbuffer::deep_copy_str(const ObString& src, ObString& dest)
{
int ret = OB_SUCCESS;
char* buf = NULL;
int64_t len = src.length() + 1;
if (OB_UNLIKELY(len <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("src string length is invalid", K(ret), K(src), K(len));
} else if (NULL == (buf = static_cast<char*>(field_data_allocator_.alloc(len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("fail to allocate memory, ", K(ret), K(src), K(len));
} else {
MEMCPY(buf, src.ptr(), len - 1);
buf[len - 1] = '\0';
dest.assign_ptr(buf, static_cast<ObString::obstr_size_t>(len - 1));
}
return ret;
}
int ObLoadbuffer::store_row(const ObIArray<ObString>& row_strs, int64_t cur_line_number)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < insert_column_num_; ++i) {
const ObString& src_str = row_strs.at(i);
ObString& dst_str = insert_values_.at(stored_pos_);
if (OB_FAIL(deep_copy_str(src_str, dst_str))) {
LOG_WARN("deep copy string failed", K(ret));
}
stored_pos_++;
}
file_line_number_.at(stored_row_cnt_) = cur_line_number;
stored_row_cnt_++;
return ret;
}
int ObLoadbuffer::set_allocator_tenant()
{
int ret = OB_SUCCESS;
if (OB_INVALID_ID == tenant_id_) {
ret = OB_NOT_INIT;
LOG_WARN("tenant_id must be init first", K(tenant_id_));
} else {
field_data_allocator_.set_tenant_id(tenant_id_);
array_allocator_.set_tenant_id(tenant_id_);
}
return ret;
}
int ObLoadbuffer::prepare_insert_info(const ObIArray<ObString>& column_names, ObExprValueBitSet& expr_value_bitset)
{
int ret = OB_SUCCESS;
if (OB_FAIL(expr_bitset_.add_members(expr_value_bitset))) {
LOG_WARN("prepare expr bitset failed", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < column_names.count(); ++i) {
if (OB_FAIL(insert_column_names_.push_back(column_names.at(i)))) {
LOG_WARN("insert column names push failed", K(ret));
}
}
return ret;
}
int ObLoadbuffer::init_array()
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < LOAD_BUFFER_MAX_ROW_COUNT * insert_column_num_; ++i) {
if (OB_FAIL(insert_values_.push_back(ObString::make_empty_string()))) {
LOG_WARN("insert values push empty string failed", K(ret));
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < LOAD_BUFFER_MAX_ROW_COUNT; ++i) {
if (OB_FAIL(file_line_number_.push_back(-1))) {
LOG_WARN("insert values push empty string failed", K(ret));
}
}
return ret;
}
int ObRpcLoadDataShuffleTaskExecuteP::process()
{
int ret = OB_SUCCESS;
ObShuffleTask& task = arg_;
// ObShuffleResult &result = result_;
ObShuffleTaskHandle* handle = nullptr;
ObLoadDataStat* job_status = nullptr;
LOG_DEBUG("LOAD DATA receiving shuffle task", "task_id", task.task_id_);
if (OB_FAIL(ObGlobalLoadDataStatMap::getInstance()->get_job_status(task.gid_, job_status))) {
LOG_WARN("fail to get job, main thread has already quit", K(ret), K(task));
} else if (OB_ISNULL(job_status)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("job status is null", K(ret));
} else {
if (OB_UNLIKELY(THIS_WORKER.is_timeout())) {
ret = OB_TIMEOUT;
LOG_WARN("LOAD DATA shuffle task timeout", K(ret), K(task));
} else if (OB_FAIL(task.shuffle_task_handle_.get_arg(handle))) { // check identifier
LOG_ERROR("fail to get arg", K(ret));
} else if (OB_FAIL(ObLoadDataSPImpl::exec_shuffle(task.task_id_, handle))) {
LOG_WARN("fail to exec shuffle task", K(ret));
}
handle->result.exec_ret_ = ret;
MEM_BARRIER(); // use handle ptr before release job ref
job_status->release();
}
return OB_SUCCESS;
}
int ObRpcLoadDataShuffleTaskCallBack::release_resouce()
{
int ret = OB_SUCCESS;
int ret1 = complete_task_list_.push_back(handle_);
MEM_BARRIER();
int ret2 = task_controller_.on_task_finished();
if (OB_FAIL(ret1) || OB_FAIL(ret2)) {
LOG_ERROR("shuffle call back release resource failed", K(ret1), K(ret2));
}
return ret;
}
int ObRpcLoadDataShuffleTaskCallBack::process()
{
// int ret = OB_SUCCESS;
// ObShuffleResult &result = result_;
LOG_DEBUG("LOAD DATA shuffle task callback process");
handle_->result.process_us_ = ObTimeUtil::current_time() - get_send_ts();
// handle_->result = result;
release_resouce();
return OB_SUCCESS;
}
void ObRpcLoadDataShuffleTaskCallBack::on_timeout()
{
LOG_WARN("LOAD DATA main thread shuffle task rpc timeout");
if (OB_NOT_NULL(handle_)) {
handle_->result.flags_.set_bit(ObTaskResFlag::RPC_TIMEOUT);
}
release_resouce();
}
void ObRpcLoadDataShuffleTaskCallBack::set_args(const Request& arg)
{
UNUSED(arg);
}
int ObRpcLoadDataInsertTaskCallBack::release_resouce()
{
int ret = OB_SUCCESS;
int ret1 = complete_task_list_.push_back(insert_task_);
MEM_BARRIER();
int ret2 = task_controller_.on_task_finished();
if (OB_FAIL(ret1) || OB_FAIL(ret2)) {
LOG_ERROR("push back buffer failed", K(ret1), K(ret2));
}
return ret;
}
int ObRpcLoadDataInsertTaskCallBack::process()
{
int ret = OB_SUCCESS;
LOG_DEBUG("LOAD DATA insert task callback process");
if (OB_NOT_NULL(insert_task_)) {
if (OB_FAIL(insert_task_->result_.assign(result_))) {
LOG_WARN("fail to assign result", K(ret));
} else {
insert_task_->result_recv_ts_ = ObTimeUtil::current_time();
insert_task_->process_us_ = insert_task_->result_recv_ts_ - get_send_ts();
}
}
release_resouce();
return OB_SUCCESS;
}
void ObRpcLoadDataInsertTaskCallBack::set_args(const Request& arg)
{
UNUSED(arg);
}
void ObRpcLoadDataInsertTaskCallBack::on_timeout()
{
int64_t task_id = -2; // undefined
if (OB_ISNULL(insert_task_)) {
LOG_ERROR("insert task is null on timeout");
} else {
task_id = insert_task_->task_id_;
insert_task_->result_.flags_.set_bit(ObTaskResFlag::RPC_TIMEOUT);
}
LOG_WARN("LOAD DATA main thread insert task rpc timeout", K(task_id));
release_resouce();
}
int ObRpcLoadDataTaskExecuteP::process()
{
int ret = OB_SUCCESS;
ObLoadbuffer& buffer = arg_;
ObLoadResult& result = result_;
ObIArray<ObString>& column_names = buffer.get_insert_keys();
ObIArray<ObString>& values = buffer.get_insert_values();
ObString& table_name = buffer.get_table_name();
ObExprValueBitSet& expr_bitset = buffer.get_expr_bitset();
uint64_t tenant_id = buffer.get_tenant_id();
int64_t task_id = buffer.get_task_id();
int64_t part_id = buffer.get_part_id();
ObLoadDupActionType insert_mode = buffer.get_load_mode();
int64_t insert_column_number = column_names.count();
int64_t total_values_number = buffer.get_stored_pos(); // values.count() will always be 1000
int64_t total_row_number = buffer.get_stored_row_count();
int64_t succ_row_count = 0;
int need_wait_minor_freeze = false;
if (OB_UNLIKELY(total_values_number <= 0) || OB_UNLIKELY(insert_column_number <= 0) ||
OB_UNLIKELY(total_values_number != insert_column_number * (total_values_number / insert_column_number)) ||
OB_UNLIKELY(total_row_number != total_values_number / insert_column_number)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("insert values are invalid",
K(ret),
K(total_values_number),
K(insert_column_number),
K(total_row_number),
K(buffer));
} else if (!escape_data_buffer_.set_data(str_buf_, OB_MAX_DEFAULT_VALUE_LENGTH)) { // for escaped value
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid escape_buf", K(ret));
} else {
// 1. try insert as one stmt
ObSqlString batch_insert_sql;
int exec_ret = OB_SUCCESS;
int64_t affected_rows = 0;
if (OB_FAIL(
ObLoadDataUtils::build_insert_sql_string_head(insert_mode, table_name, column_names, batch_insert_sql))) {
LOG_WARN("gen insert sql column_names failed", K(ret));
} else if (OB_FAIL(ObLoadDataUtils::append_values_in_remote_process(insert_column_number,
total_values_number,
expr_bitset,
values,
batch_insert_sql,
escape_data_buffer_))) {
LOG_WARN("append values failed", K(ret));
} else if (OB_UNLIKELY(
OB_SUCCESS != (exec_ret = gctx_.sql_proxy_->write(
tenant_id, batch_insert_sql.ptr(), affected_rows, get_compatibility_mode())))) {
LOG_WARN("fail to execute insert sql in batch",
K(exec_ret),
K(affected_rows),
K(task_id),
K(get_compatibility_mode()));
} else {
// succ!
succ_row_count = affected_rows;
}
// 2. if failed, try insert seperately
if (OB_SUCC(ret) && OB_SUCCESS != exec_ret) {
ObSqlString seperate_insert_sql_head;
ObSqlString seperate_insert_sql;
if (OB_FAIL(ObLoadDataUtils::build_insert_sql_string_head(
insert_mode, table_name, column_names, seperate_insert_sql_head))) {
LOG_WARN("gen insert sql column_names failed", K(ret));
}
for (int64_t row_idx = 0; OB_SUCC(ret) && row_idx < total_row_number; ++row_idx) {
if (OB_FAIL(seperate_insert_sql.assign(seperate_insert_sql_head.string()))) {
LOG_WARN("assign insert column_names failed", K(ret));
} else if (OB_FAIL(ObLoadDataUtils::append_values_in_remote_process(insert_column_number,
insert_column_number,
expr_bitset,
values,
seperate_insert_sql,
escape_data_buffer_,
row_idx))) {
LOG_WARN("append values failed", K(ret));
} else {
exec_ret = OB_SUCCESS;
affected_rows = 0;
if (OB_UNLIKELY(
OB_SUCCESS != (exec_ret = gctx_.sql_proxy_->write(
tenant_id, seperate_insert_sql.ptr(), affected_rows, get_compatibility_mode())))) {
LOG_WARN("LOAD DATA row insert failed in remote process",
K(exec_ret),
K(seperate_insert_sql),
K(get_compatibility_mode()));
if (OB_FAIL(result.row_number_.push_back(static_cast<int16_t>(row_idx)))) {
LOG_WARN("push back row number failed", K(ret));
} else if (OB_FAIL(result.row_err_code_.push_back(exec_ret))) {
LOG_WARN("push back row err code failed", K(ret));
}
} else {
// succ!
succ_row_count++;
}
}
}
}
}
// check memory
int memory_check_ret = OB_SUCCESS;
ObTenantManager& tenant_mgr = ObTenantManager::get_instance();
if (OB_UNLIKELY(!tenant_mgr.has_tenant(tenant_id))) {
memory_check_ret = OB_ERR_UNEXPECTED;
LOG_ERROR("tenant no found", K(tenant_id), K(memory_check_ret));
} else {
int64_t active_memstore_used = 0;
int64_t total_memstore_used = 0;
int64_t major_freeze_trigger = 0;
int64_t memstore_limit = 0;
int64_t freeze_cnt = 0;
if (OB_UNLIKELY(OB_SUCCESS != (memory_check_ret = tenant_mgr.get_tenant_memstore_cond(tenant_id,
active_memstore_used,
total_memstore_used,
major_freeze_trigger,
memstore_limit,
freeze_cnt)))) {
LOG_WARN("fail to get memstore used", K(memory_check_ret));
} else {
if (static_cast<double>(total_memstore_used) > static_cast<double>(major_freeze_trigger) * 1.02) {
need_wait_minor_freeze = true;
}
}
LOG_DEBUG("load data check tenant memory usage",
K(active_memstore_used),
K(total_memstore_used),
K(major_freeze_trigger),
K(memstore_limit),
K(freeze_cnt));
}
if (OB_SUCC(ret) && OB_SUCCESS != memory_check_ret) {
ret = memory_check_ret; // cover ret
}
// sumarize return value
if (OB_FAIL(ret)) {
ObLoadDataUtils::set_flag(result.task_flags_, static_cast<int64_t>(ObLoadTaskResultFlag::RPC_REMOTE_PROCESS_ERROR));
}
if (need_wait_minor_freeze) {
ObLoadDataUtils::set_flag(result.task_flags_, static_cast<int64_t>(ObLoadTaskResultFlag::NEED_WAIT_MINOR_FREEZE));
}
if (succ_row_count != total_row_number) {
ObLoadDataUtils::set_flag(result.task_flags_, static_cast<int64_t>(ObLoadTaskResultFlag::HAS_FAILED_ROW));
}
if (succ_row_count == 0) {
ObLoadDataUtils::set_flag(result.task_flags_, static_cast<int64_t>(ObLoadTaskResultFlag::ALL_ROWS_FAILED));
}
result.affected_rows_ = succ_row_count;
result.failed_rows_ = total_row_number - succ_row_count;
result.task_id_ = task_id;
result.part_id_ = part_id;
LOG_DEBUG("load data in remote process!",
K(task_id),
K(succ_row_count),
K(total_row_number),
K(need_wait_minor_freeze),
K(share::is_oracle_mode()));
return OB_SUCCESS;
}
OB_INLINE void ObRpcLoadDataTaskCallBack::set_args(const Request& arg)
{
UNUSED(arg);
}
void ObRpcLoadDataTaskCallBack::on_timeout()
{
int ret = OB_SUCCESS;
ObLoadbuffer* buffer = static_cast<ObLoadbuffer*>(request_buffer_ptr_);
if (OB_ISNULL(buffer)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("buffer is null", K(ret));
} else {
buffer->set_returned_timestamp(ObTimeUtility::current_time());
ObLoadDataUtils::set_flag(buffer->get_task_status(), static_cast<int64_t>(ObLoadTaskResultFlag::TIMEOUT));
ObLoadDataUtils::set_flag(buffer->get_task_status(), static_cast<int64_t>(ObLoadTaskResultFlag::HAS_FAILED_ROW));
ObLoadDataUtils::set_flag(buffer->get_task_status(), static_cast<int64_t>(ObLoadTaskResultFlag::ALL_ROWS_FAILED));
// TODO: check task real status, is all rows truely failed?
if (OB_FAIL(complete_task_list_.push_back(buffer))) {
LOG_ERROR("push back buffer failed", K(ret));
}
MEM_BARRIER();
if (OB_FAIL(task_controller_.on_task_finished())) {
LOG_ERROR("error on task finish", K(ret));
}
LOG_WARN("load data task is timeout", K(ret), KPC(buffer));
}
}
int ObRpcLoadDataTaskCallBack::process()
{
int ret = OB_SUCCESS;
ObLoadResult& result = result_;
ObLoadbuffer* buffer = static_cast<ObLoadbuffer*>(request_buffer_ptr_);
if (OB_ISNULL(buffer)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("task buffer is null", K(ret));
} else {
buffer->set_returned_timestamp(ObTimeUtility::current_time());
buffer->set_task_status(result.task_flags_);
if (OB_UNLIKELY(ObLoadDataUtils::has_flag(
buffer->get_task_status(), static_cast<int64_t>(ObLoadTaskResultFlag::HAS_FAILED_ROW)))) {
if (OB_UNLIKELY(result.failed_rows_ != result.row_err_code_.count() ||
result.failed_rows_ != result.row_number_.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("size of failed rows is not the same, impossible");
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < result.failed_rows_; ++i) {
if (OB_FAIL(buffer->get_failed_row_idx().push_back(result.row_number_.at(i)))) {
LOG_WARN("push back failed", K(ret));
} else if (OB_FAIL(buffer->get_error_code_array().push_back(result.row_err_code_.at(i)))) {
LOG_WARN("push back failed", K(ret));
}
}
}
}
if (OB_FAIL(ret)) {
ObLoadDataUtils::set_flag(
buffer->get_task_status(), static_cast<int64_t>(ObLoadTaskResultFlag::RPC_CALLBACK_PROCESS_ERROR));
}
// whatever ret is, the task has finished
int second_ret = OB_SUCCESS;
if (OB_SUCCESS != (second_ret = complete_task_list_.push_back(buffer))) {
// buffer will be auto released by the allocator
if (OB_SUCCESS == ret) {
ret = second_ret;
}
LOG_ERROR("push to complete list failed", K(second_ret));
}
MEM_BARRIER();
if (OB_SUCCESS != (second_ret = task_controller_.on_task_finished())) {
// signal main thread failed, fetal error. TODO: handle this error
if (OB_SUCCESS == ret) {
ret = second_ret;
}
LOG_ERROR("on task finished failed", K(ret));
}
}
LOG_DEBUG("in local cb process!", K(result), K(ret));
return OB_SUCCESS;
}
int ObParallelTaskController::init(int64_t max_parallelism)
{
int ret = OB_SUCCESS;
max_parallelism_ = max_parallelism;
if (OB_FAIL(vacant_cond_.init(common::ObWaitEventIds::ASYNC_RPC_PROXY_COND_WAIT))) {
LOG_WARN("init vacant cond failed", K(ret));
}
return ret;
}
int ObParallelTaskController::on_next_task()
{
int ret = OB_SUCCESS;
ObThreadCondGuard guard(vacant_cond_);
if (ATOMIC_AAF(&processing_cnt_, 1) > max_parallelism_) {
ret = vacant_cond_.wait();
}
return ret;
}
void ObParallelTaskController::wait_all_task_finish(const char* task_name, int64_t until_ts)
{
int64_t wait_duration_ms = 0;
int64_t begin_ts = ObTimeUtil::current_time();
int64_t processing_count = 0;
bool is_too_long = false;
LOG_DEBUG("start wait_all_task_finish", K(task_name));
while ((processing_count = get_processing_task_cnt()) > 0) {
usleep(1000 * 10); // wait 10m
wait_duration_ms += 10;
if (0 == wait_duration_ms % 1000) {
int64_t current_ts = ObTimeUtil::current_time();
if (current_ts > until_ts) {
LOG_ERROR("waiting load data task too long and exceed max waiting timestamp",
K(begin_ts),
K(until_ts),
K(current_ts));
}
}
if (!is_too_long && wait_duration_ms > 10 * 1000) {
is_too_long = true;
LOG_WARN("LOAD DATA, waiting task finish too long",
K(task_name),
K(processing_count),
K(wait_duration_ms),
K(until_ts));
}
}
if (is_too_long) {
LOG_WARN("LOAD DATA finish waitting long task", K(wait_duration_ms));
}
}
int ObParallelTaskController::on_task_finished()
{
int ret = OB_SUCCESS;
if (max_parallelism_ == ATOMIC_AAF(&processing_cnt_, -1)) {
ObThreadCondGuard guard(vacant_cond_);
ret = vacant_cond_.signal();
}
return ret;
}
int ObRpcLoadDataInsertTaskExecuteP::process()
{
int ret = OB_SUCCESS;
ObInsertTask& task = arg_;
ObInsertResult& result = result_;
LOG_DEBUG("LOAD DATA receiving insert task", "task_id", task.task_id_);
bool need_wait_freeze = false;
if (OB_UNLIKELY(THIS_WORKER.is_timeout())) {
ret = OB_TIMEOUT;
LOG_WARN("LOAD DATA shuffle task timeout", K(ret), K(task));
} else if (OB_FAIL(ObLoadDataSPImpl::exec_insert(task, result))) {
LOG_WARN("fail to exec insert", K(ret));
}
result.exec_ret_ = ret;
int temp_ret = ObLoadDataBase::memory_check_remote(task.tenant_id_, need_wait_freeze);
if (OB_SUCCESS != temp_ret) {
LOG_WARN("LOAD DATA remote memory check failed", K(temp_ret), K(task.tenant_id_));
}
result.flags_.reset();
if (need_wait_freeze) {
result.flags_.set_bit(ObTaskResFlag::NEED_WAIT_MINOR_FREEZE);
}
return OB_SUCCESS;
}
int ObInsertResult::assign(const ObInsertResult& other)
{
int ret = OB_SUCCESS;
flags_ = other.flags_;
exec_ret_ = other.exec_ret_;
if (OB_FAIL(failed_row_offset_.add_members(other.failed_row_offset_))) {
LOG_WARN("fail to add members", K(ret));
} else if (OB_FAIL(row_errors_.assign(other.row_errors_))) {
LOG_WARN("fail to assign error rows", K(ret));
}
return ret;
}
OB_DEF_SERIALIZE(ObLoadbuffer)
{
int ret = OB_SUCCESS;
LST_DO_CODE(OB_UNIS_ENCODE,
task_id_,
part_id_,
table_id_,
tenant_id_,
stored_pos_,
stored_row_cnt_,
insert_mode_,
insert_column_num_);
if (OB_FAIL(ret)) {
} else if (OB_FAIL(table_name_.serialize(buf, buf_len, pos))) {
LOG_WARN("serialize error", K(ret));
} else if (OB_FAIL(insert_column_names_.serialize(buf, buf_len, pos))) {
LOG_WARN("serialize column names error", K(ret));
} else if (OB_FAIL(insert_values_.serialize(buf, buf_len, pos))) {
LOG_WARN("serialize row store error", K(ret));
} else if (OB_FAIL(expr_bitset_.serialize(buf, buf_len, pos))) {
LOG_WARN("serialize expr bitset error", K(ret));
}
return ret;
}
OB_DEF_DESERIALIZE(ObLoadbuffer)
{
int ret = OB_SUCCESS;
LST_DO_CODE(OB_UNIS_DECODE,
task_id_,
part_id_,
table_id_,
tenant_id_,
stored_pos_,
stored_row_cnt_,
insert_mode_,
insert_column_num_);
if (OB_FAIL(ret)) {
} else if (OB_FAIL(table_name_.deserialize(buf, data_len, pos))) {
LOG_WARN("deserialize error", K(ret));
} else if (OB_FAIL(insert_column_names_.deserialize(buf, data_len, pos))) {
LOG_WARN("deserialize row store error", K(ret));
} else if (OB_FAIL(insert_values_.deserialize(buf, data_len, pos))) {
LOG_WARN("deserialize row store error", K(ret));
} else if (OB_FAIL(expr_bitset_.deserialize(buf, data_len, pos))) {
LOG_WARN("deserialize expr bitset error", K(ret));
}
return ret;
}
OB_DEF_SERIALIZE_SIZE(ObLoadbuffer)
{
int64_t len = 0;
LST_DO_CODE(OB_UNIS_ADD_LEN,
task_id_,
part_id_,
table_id_,
tenant_id_,
stored_pos_,
stored_row_cnt_,
insert_mode_,
insert_column_num_);
len += table_name_.get_serialize_size();
len += insert_column_names_.get_serialize_size();
len += insert_values_.get_serialize_size();
len += expr_bitset_.get_serialize_size();
return len;
}
OB_DEF_SERIALIZE(ObLoadResult)
{
int ret = OB_SUCCESS;
LST_DO_CODE(OB_UNIS_ENCODE, task_id_, part_id_, affected_rows_, failed_rows_, task_flags_);
if (OB_FAIL(ret)) {
} else if (OB_FAIL(row_number_.serialize(buf, buf_len, pos))) {
LOG_WARN("serialize row_number_ error", K(ret));
} else if (OB_FAIL(row_err_code_.serialize(buf, buf_len, pos))) {
LOG_WARN("serialize row_err_code_ error", K(ret));
}
return ret;
}
OB_DEF_DESERIALIZE(ObLoadResult)
{
int ret = OB_SUCCESS;
LST_DO_CODE(OB_UNIS_DECODE, task_id_, part_id_, affected_rows_, failed_rows_, task_flags_);
if (OB_FAIL(ret)) {
} else if (OB_FAIL(row_number_.deserialize(buf, data_len, pos))) {
LOG_WARN("deserialize row_number_ error", K(ret));
} else if (OB_FAIL(row_err_code_.deserialize(buf, data_len, pos))) {
LOG_WARN("deserialize row_err_code_ error", K(ret));
}
return ret;
}
OB_DEF_SERIALIZE_SIZE(ObLoadResult)
{
int64_t len = 0;
LST_DO_CODE(OB_UNIS_ADD_LEN, task_id_, part_id_, affected_rows_, failed_rows_, task_flags_);
len += row_number_.get_serialize_size();
len += row_err_code_.get_serialize_size();
return len;
}
OB_SERIALIZE_MEMBER(ObShuffleTask, task_id_, shuffle_task_handle_, gid_);
OB_SERIALIZE_MEMBER(ObShuffleResult, task_id_, flags_, exec_ret_, row_cnt_);
OB_SERIALIZE_MEMBER(
ObInsertTask, tenant_id_, task_id_, row_count_, column_count_, insert_stmt_head_, insert_value_data_);
OB_SERIALIZE_MEMBER(ObInsertResult, flags_, exec_ret_, failed_row_offset_, row_errors_);
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,681 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_CMD_LOAD_DATA_RPC_H_
#define OCEANBASE_SQL_ENGINE_CMD_LOAD_DATA_RPC_H_
#include "share/ob_define.h"
#include "rpc/obrpc/ob_rpc_proxy.h"
#include "rpc/obrpc/ob_rpc_processor.h"
#include "lib/container/ob_bit_set.h"
#include "lib/lock/ob_thread_cond.h"
#include "sql/ob_sql_utils.h"
#include "sql/engine/cmd/ob_load_data_utils.h"
#include "share/config/ob_server_config.h"
#include "observer/ob_server_struct.h"
namespace oceanbase {
namespace observer {
class ObGlobalContext;
}
namespace sql {
class ObLoadbuffer;
class ObLoadResult;
class ObLoadFileBuffer;
class ObDesExecContext;
class ObShuffleTask;
class ObShuffleResult;
class ObInsertTask;
class ObInsertResult;
class ObDataFragMgr;
class ObDataFrag;
class ObShuffleTaskHandle;
class ObInsertValueGenerator;
class ObPartIdCalculator;
class ObPartDataFragMgr;
} // namespace sql
namespace obrpc {
class ObLoadDataRpcProxy : public obrpc::ObRpcProxy {
public:
DEFINE_TO(ObLoadDataRpcProxy);
RPC_AP(@PR5 ap_load_data_execute, obrpc::OB_LOAD_DATA_EXECUTE, (sql::ObLoadbuffer), sql::ObLoadResult);
RPC_AP(@PR5 ap_load_data_shuffle, obrpc::OB_LOAD_DATA_SHUFFLE, (sql::ObShuffleTask), sql::ObShuffleResult);
RPC_AP(@PR5 ap_load_data_insert, obrpc::OB_LOAD_DATA_INSERT, (sql::ObInsertTask), sql::ObInsertResult);
};
} // namespace obrpc
namespace sql {
static const int64_t DEFAULT_BUFFERRED_ROW_COUNT = 1000; // must < 2^15
static const int64_t DEFAULT_PARALLEL_THREAD_COUNT = 4;
static const int64_t EXPECTED_INSERT_COLUMN_NUM = 64;
static const int64_t RPC_BATCH_INSERT_TIMEOUT_US = 10 * 1000 * 1000; // 10s
enum class ObLoadTaskResultFlag {
HAS_FAILED_ROW = 0,
ALL_ROWS_FAILED,
NEED_WAIT_MINOR_FREEZE,
TIMEOUT,
RPC_CALLBACK_PROCESS_ERROR,
RPC_REMOTE_PROCESS_ERROR,
INVALID_MAX_FLAG
};
static_assert(static_cast<int64_t>(ObLoadTaskResultFlag::INVALID_MAX_FLAG) < 64,
"ObLoadTaskResultFlag max value should less than 64");
enum class ObTaskResFlag {
RPC_TIMEOUT = 0,
NEED_WAIT_MINOR_FREEZE,
HAS_FAILED_ROW,
ALL_ROW_FAILED,
// SHUTDOWN_WITH_INTERNAL_ERROR,
MAX_VALUE
};
typedef ObBitSet<32> ErrRowBitset;
class ObParallelTaskController {
public:
ObParallelTaskController() : max_parallelism_(0), task_cnt_(0), processing_cnt_(0)
{}
~ObParallelTaskController()
{}
int init(int64_t max_parallelism);
int on_next_task();
int on_task_finished();
int64_t get_next_task_id()
{
return task_cnt_++;
}
void wait_all_task_finish(const char* task_name = NULL, int64_t until_ts = INT64_MAX);
int64_t get_processing_task_cnt()
{
return ATOMIC_LOAD(&processing_cnt_);
}
int64_t get_total_task_cnt()
{
return task_cnt_;
}
int64_t get_max_parallelism()
{
return max_parallelism_;
}
private:
static const int64_t MAX_TIME_WAIT_MS = 2 * RPC_BATCH_INSERT_TIMEOUT_US / 1000;
int64_t max_parallelism_;
int64_t task_cnt_;
// multi-thread values:
volatile int64_t processing_cnt_;
common::ObThreadCond vacant_cond_; // wait on (processing_cnt_ > MaxConcurrentTaskNum)
};
struct ObInsertResult {
ObInsertResult() : exec_ret_(0)
{}
void reset()
{
flags_.reset();
exec_ret_ = 0;
}
int assign(const ObInsertResult& other);
ObEnumBitSet<ObTaskResFlag> flags_;
int exec_ret_;
ErrRowBitset failed_row_offset_;
common::Ob2DArray<int> row_errors_;
TO_STRING_KV(K(exec_ret_), K(flags_));
OB_UNIS_VERSION(1);
};
struct ObInsertTask {
static constexpr int64_t RETRY_LIMIT = 3;
static constexpr int64_t COMMON_SIZE = 10;
ObInsertTask()
{
reset();
}
void reuse()
{
task_id_ = common::OB_INVALID_ID;
row_count_ = 0;
insert_value_data_.reuse();
source_frag_.reuse();
result_.reset();
result_recv_ts_ = 0;
process_us_ = 0;
retry_times_ = 0;
part_mgr = NULL;
}
void reset()
{
tenant_id_ = common::OB_INVALID_TENANT_ID;
column_count_ = 0;
reuse();
token_server_idx_ = OB_INVALID_INDEX;
non_string_fields_.reset();
insert_stmt_head_.reset();
insert_value_data_.reset();
source_frag_.reset();
}
bool is_empty_task()
{
return task_id_ == OB_INVALID_ID;
}
TO_STRING_KV(K(tenant_id_), K(task_id_), K(row_count_), K(column_count_), K(insert_value_data_.count()));
// serialized data:
uint64_t tenant_id_;
int64_t task_id_;
int64_t row_count_;
int64_t column_count_;
ObBitSet<> non_string_fields_;
common::ObString insert_stmt_head_; // insert into xxx (xxx)
// serialized format:
// 1. length of 2 int64_t
// 2. values for one row ObSEArray<ObString> using string as buf
// + for serialize
common::ObSEArray<common::ObString, COMMON_SIZE> insert_value_data_;
// no serialized data
common::ObSEArray<void*, COMMON_SIZE> source_frag_;
ObPartDataFragMgr* part_mgr;
ObInsertResult result_;
int64_t result_recv_ts_;
int64_t process_us_;
int64_t retry_times_;
int64_t token_server_idx_;
OB_UNIS_VERSION(1);
};
template <class T>
class ObRpcPointerArg {
public:
ObRpcPointerArg() : ptr_value_(0)
{}
int set_arg(T* ptr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(ptr)) {
ret = OB_INVALID_ARGUMENT;
} else {
ptr_ = ptr;
}
return ret;
}
int get_arg(T*& ptr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(ptr = ptr_)) {
ret = OB_ERR_NULL_VALUE;
}
return ret;
}
private:
union {
uint64_t ptr_value_;
T* ptr_;
};
OB_UNIS_VERSION(1);
};
OB_SERIALIZE_MEMBER_TEMP(template <class T>, ObRpcPointerArg<T>, ptr_value_);
struct ObShuffleTask {
ObShuffleTask() : task_id_(OB_INVALID_INDEX_INT64)
{}
int64_t task_id_;
ObRpcPointerArg<ObShuffleTaskHandle> shuffle_task_handle_;
ObLoadDataGID gid_;
TO_STRING_KV(K(task_id_), K(gid_));
OB_UNIS_VERSION(1);
};
struct ObShuffleResult {
ObShuffleResult() : task_id_(OB_INVALID_INDEX_INT64), flags_(), exec_ret_(0), row_cnt_(0), process_us_(0)
{}
void reset()
{
task_id_ = OB_INVALID_INDEX_INT64;
flags_.reset();
exec_ret_ = 0;
row_cnt_ = 0;
process_us_ = 0;
}
int64_t task_id_;
ObEnumBitSet<ObTaskResFlag> flags_;
int exec_ret_;
int64_t row_cnt_;
int64_t process_us_;
OB_UNIS_VERSION(1);
};
template <typename T>
class ObConcurrentFixedCircularArray {
public:
ObConcurrentFixedCircularArray() : array_size_(0), data_(NULL), head_pos_(0), tail_pos_(0)
{}
~ObConcurrentFixedCircularArray()
{
if (data_ != NULL) {
ob_free_align(static_cast<void*>(data_));
}
}
int init(int64_t array_size)
{
int ret = common::OB_SUCCESS;
if (OB_ISNULL(data_ = static_cast<T*>(
ob_malloc_align(CACHE_ALIGN_SIZE, array_size * sizeof(T), common::ObModIds::OB_SQL_EXECUTOR)))) {
ret = common::OB_ALLOCATE_MEMORY_FAILED;
LIB_LOG(WARN, "alloc memory failed", K(ret));
} else {
array_size_ = array_size;
}
return ret;
}
OB_INLINE int push_back(const T& obj)
{
int ret = common::OB_SUCCESS;
// push optimistically
int64_t pos = ATOMIC_FAA(&head_pos_, 1);
// validate
if (OB_UNLIKELY(pos - ATOMIC_LOAD(&tail_pos_) >= array_size_)) {
ret = common::OB_SIZE_OVERFLOW;
} else {
ATOMIC_SET(&data_[pos % array_size_], obj);
}
return ret;
}
OB_INLINE int pop(T& output)
{
int ret = common::OB_SUCCESS;
// pop optimistically
int64_t pos = ATOMIC_FAA(&tail_pos_, 1);
// validate
if (OB_UNLIKELY(pos >= ATOMIC_LOAD(&head_pos_))) {
ret = common::OB_ARRAY_OUT_OF_RANGE;
} else {
output = ATOMIC_LOAD(&data_[pos % array_size_]);
}
return ret;
}
OB_INLINE int64_t count()
{
return ATOMIC_LOAD(&head_pos_) - ATOMIC_LOAD(&tail_pos_);
}
private:
// data members
int64_t array_size_;
T* volatile data_;
volatile int64_t head_pos_;
volatile int64_t tail_pos_;
};
typedef ObConcurrentFixedCircularArray<ObLoadbuffer*> CompleteTaskArray;
// load data task buffer
class ObLoadbuffer {
public:
const static int64_t LOAD_BUFFER_MAX_ROW_COUNT = DEFAULT_BUFFERRED_ROW_COUNT;
ObLoadbuffer()
: tenant_id_(common::OB_INVALID_ID),
table_id_(common::OB_INVALID_ID),
insert_column_num_(0),
stored_row_cnt_(0),
stored_pos_(0),
task_id_(common::OB_INVALID_ID),
part_id_(common::OB_INVALID_PARTITION_ID),
task_status_(0),
insert_mode_(false),
returned_timestamp_(0),
field_data_allocator_(common::ObModIds::OB_SQL_EXECUTOR),
array_allocator_(common::ObModIds::OB_SQL_EXECUTOR),
insert_column_names_(common::OB_MALLOC_NORMAL_BLOCK_SIZE, array_allocator_),
expr_bitset_(array_allocator_),
insert_values_(common::OB_MALLOC_NORMAL_BLOCK_SIZE, array_allocator_),
file_line_number_(common::OB_MALLOC_NORMAL_BLOCK_SIZE, array_allocator_),
failed_inserted_row_idx_(common::OB_MALLOC_NORMAL_BLOCK_SIZE, array_allocator_),
error_codes_(common::OB_MALLOC_NORMAL_BLOCK_SIZE, array_allocator_)
{}
~ObLoadbuffer()
{}
int init_array();
int deep_copy_str(const common::ObString& src, common::ObString& dest);
int store_row(const common::ObIArray<common::ObString>& row_strs, int64_t cur_line_number);
OB_INLINE bool is_full()
{
return LOAD_BUFFER_MAX_ROW_COUNT == stored_row_cnt_;
}
OB_INLINE bool is_empty()
{
return 0 == stored_row_cnt_ && 0 == stored_pos_;
}
OB_INLINE void reuse()
{
task_status_ = 0;
stored_row_cnt_ = 0;
stored_pos_ = 0;
task_id_ = common::OB_INVALID_ID;
returned_timestamp_ = 0;
ip_addr_.reset();
field_data_allocator_.reuse();
failed_inserted_row_idx_.reuse();
error_codes_.reuse();
}
OB_INLINE void set_addr(common::ObAddr addr)
{
ip_addr_ = addr;
}
OB_INLINE common::ObAddr get_addr()
{
return ip_addr_;
}
OB_INLINE void set_returned_timestamp(int64_t timestamp)
{
returned_timestamp_ = timestamp;
}
OB_INLINE int64_t get_returned_timestamp()
{
return returned_timestamp_;
}
OB_INLINE void set_task_status(int64_t status)
{
task_status_ = status;
}
OB_INLINE int64_t& get_task_status()
{
return task_status_;
}
OB_INLINE void set_task_id(int64_t task_id)
{
task_id_ = task_id;
}
OB_INLINE int64_t get_task_id()
{
return task_id_;
}
OB_INLINE void set_part_id(int64_t part_id)
{
part_id_ = part_id;
}
OB_INLINE int64_t get_part_id()
{
return part_id_;
}
OB_INLINE void set_table_id(uint64_t table_id)
{
table_id_ = table_id;
}
OB_INLINE uint64_t get_table_id()
{
return table_id_;
}
OB_INLINE void set_tenant_id(uint64_t tenant_id)
{
tenant_id_ = tenant_id;
}
OB_INLINE uint64_t get_tenant_id()
{
return tenant_id_;
}
OB_INLINE void set_column_num(int64_t insert_column_num)
{
insert_column_num_ = insert_column_num;
}
OB_INLINE int64_t get_column_num()
{
return insert_column_num_;
}
OB_INLINE int64_t get_stored_pos()
{
return stored_pos_;
}
OB_INLINE int64_t get_stored_row_count()
{
return stored_row_cnt_;
}
OB_INLINE void set_table_name(common::ObString& table_name)
{
table_name_ = table_name;
}
OB_INLINE common::ObString& get_table_name()
{
return table_name_;
}
OB_INLINE ObExprValueBitSet& get_expr_bitset()
{
return expr_bitset_;
}
OB_INLINE void set_load_mode(ObLoadDupActionType insert_mode)
{
insert_mode_ = static_cast<int64_t>(insert_mode);
}
OB_INLINE ObLoadDupActionType get_load_mode()
{
return static_cast<ObLoadDupActionType>(insert_mode_);
}
int set_allocator_tenant();
int prepare_insert_info(const common::ObIArray<common::ObString>& column_names, ObExprValueBitSet& expr_value_bitset);
common::ObIArray<common::ObString>& get_insert_values()
{
return insert_values_;
}
common::ObIArray<common::ObString>& get_insert_keys()
{
return insert_column_names_;
}
common::ObIArray<int64_t>& get_file_line_number()
{
return file_line_number_;
}
common::ObIArray<int16_t>& get_failed_row_idx()
{
return failed_inserted_row_idx_;
}
common::ObIArray<int>& get_error_code_array()
{
return error_codes_;
}
TO_STRING_KV(K_(tenant_id), K_(table_id), K_(insert_column_num), K_(stored_row_cnt), K_(stored_pos), K_(task_id),
K_(part_id), K_(task_status), K_(insert_mode), K_(returned_timestamp));
OB_UNIS_VERSION(1);
private:
// send params
uint64_t tenant_id_;
uint64_t table_id_;
common::ObString table_name_;
int64_t insert_column_num_;
int64_t stored_row_cnt_;
int64_t stored_pos_;
int64_t task_id_;
int64_t part_id_;
int64_t task_status_;
int64_t insert_mode_;
int64_t returned_timestamp_;
common::ObAddr ip_addr_;
// allocator
common::ObArenaAllocator field_data_allocator_;
common::ModulePageAllocator array_allocator_;
// data arrays
common::ObSEArray<common::ObString, EXPECTED_INSERT_COLUMN_NUM> insert_column_names_;
ObExprValueBitSet expr_bitset_; // true if the value is expr
common::ObSEArray<common::ObString, LOAD_BUFFER_MAX_ROW_COUNT> insert_values_;
// only used in host server
common::ObSEArray<int64_t, LOAD_BUFFER_MAX_ROW_COUNT> file_line_number_; // belongs to [0, file_total_line_number)
common::ObSEArray<int16_t, LOAD_BUFFER_MAX_ROW_COUNT> failed_inserted_row_idx_; // idx belongs to [0,
// LOAD_BUFFER_MAX_ROW_COUNT)
common::ObSEArray<int, LOAD_BUFFER_MAX_ROW_COUNT> error_codes_;
};
// load data task result
class ObLoadResult {
public:
ObLoadResult()
: task_id_(-1), part_id_(common::OB_INVALID_PARTITION_ID), affected_rows_(0), failed_rows_(0), task_flags_(false)
{}
TO_STRING_KV(K_(task_id), K_(part_id), K_(affected_rows), K_(failed_rows), K_(task_flags));
int64_t task_id_;
int64_t part_id_;
int64_t affected_rows_;
int64_t failed_rows_;
int64_t task_flags_;
common::ObSEArray<int16_t, DEFAULT_BUFFERRED_ROW_COUNT> row_number_;
common::ObSEArray<int, DEFAULT_BUFFERRED_ROW_COUNT> row_err_code_;
OB_UNIS_VERSION(1);
};
class ObRpcLoadDataTaskExecuteP
: public oceanbase::obrpc::ObRpcProcessor<obrpc::ObLoadDataRpcProxy::ObRpc<obrpc::OB_LOAD_DATA_EXECUTE> > {
public:
explicit ObRpcLoadDataTaskExecuteP(const observer::ObGlobalContext& gctx) : gctx_(gctx), escape_data_buffer_()
{}
virtual ~ObRpcLoadDataTaskExecuteP()
{}
protected:
int process();
private:
const observer::ObGlobalContext& gctx_;
common::ObDataBuffer escape_data_buffer_;
char str_buf_[common::OB_MAX_DEFAULT_VALUE_LENGTH]; // TODO: change this
};
class ObRpcLoadDataTaskCallBack : public obrpc::ObLoadDataRpcProxy::AsyncCB<obrpc::OB_LOAD_DATA_EXECUTE> {
public:
ObRpcLoadDataTaskCallBack(
ObParallelTaskController& task_controller, CompleteTaskArray& complete_task_list, Request* request)
: task_controller_(task_controller), complete_task_list_(complete_task_list), request_buffer_ptr_(request)
{}
virtual void on_timeout();
void set_args(const Request& arg);
oceanbase::rpc::frame::ObReqTransport::AsyncCB* clone(const oceanbase::rpc::frame::SPAlloc& alloc) const
{
void* buf = alloc(sizeof(*this));
ObRpcLoadDataTaskCallBack* newcb = NULL;
if (NULL != buf) {
newcb = new (buf) ObRpcLoadDataTaskCallBack(task_controller_, complete_task_list_, request_buffer_ptr_);
}
return newcb;
}
int process();
private:
ObParallelTaskController& task_controller_;
CompleteTaskArray& complete_task_list_;
Request* request_buffer_ptr_;
};
// load data V2
class ObRpcLoadDataShuffleTaskExecuteP
: public oceanbase::obrpc::ObRpcProcessor<obrpc::ObLoadDataRpcProxy::ObRpc<obrpc::OB_LOAD_DATA_SHUFFLE> > {
public:
explicit ObRpcLoadDataShuffleTaskExecuteP(const observer::ObGlobalContext& gctx) : gctx_(gctx)
{}
virtual ~ObRpcLoadDataShuffleTaskExecuteP()
{}
protected:
int process();
private:
const observer::ObGlobalContext& gctx_;
};
class ObRpcLoadDataShuffleTaskCallBack : public obrpc::ObLoadDataRpcProxy::AsyncCB<obrpc::OB_LOAD_DATA_SHUFFLE> {
public:
ObRpcLoadDataShuffleTaskCallBack(ObParallelTaskController& task_controller,
ObConcurrentFixedCircularArray<ObShuffleTaskHandle*>& complete_task_list, ObShuffleTaskHandle* handle)
: task_controller_(task_controller), complete_task_list_(complete_task_list), handle_(handle)
{}
virtual void on_timeout();
void set_args(const Request& arg);
oceanbase::rpc::frame::ObReqTransport::AsyncCB* clone(const oceanbase::rpc::frame::SPAlloc& alloc) const
{
void* buf = alloc(sizeof(*this));
ObRpcLoadDataShuffleTaskCallBack* newcb = NULL;
if (NULL != buf) {
newcb = new (buf) ObRpcLoadDataShuffleTaskCallBack(task_controller_, complete_task_list_, handle_);
}
return newcb;
}
int process();
int release_resouce();
private:
ObParallelTaskController& task_controller_;
ObConcurrentFixedCircularArray<ObShuffleTaskHandle*>& complete_task_list_;
ObShuffleTaskHandle* handle_;
};
class ObRpcLoadDataInsertTaskExecuteP
: public oceanbase::obrpc::ObRpcProcessor<obrpc::ObLoadDataRpcProxy::ObRpc<obrpc::OB_LOAD_DATA_INSERT> > {
public:
explicit ObRpcLoadDataInsertTaskExecuteP(const observer::ObGlobalContext& gctx) : gctx_(gctx)
{}
virtual ~ObRpcLoadDataInsertTaskExecuteP()
{}
protected:
int process();
private:
const observer::ObGlobalContext& gctx_;
};
class ObRpcLoadDataInsertTaskCallBack : public obrpc::ObLoadDataRpcProxy::AsyncCB<obrpc::OB_LOAD_DATA_INSERT> {
public:
ObRpcLoadDataInsertTaskCallBack(ObParallelTaskController& task_controller,
ObConcurrentFixedCircularArray<ObInsertTask*>& complete_task_list, ObInsertTask* insert_task)
: task_controller_(task_controller), complete_task_list_(complete_task_list), insert_task_(insert_task)
{}
virtual void on_timeout();
void set_args(const Request& arg);
oceanbase::rpc::frame::ObReqTransport::AsyncCB* clone(const oceanbase::rpc::frame::SPAlloc& alloc) const
{
void* buf = alloc(sizeof(*this));
ObRpcLoadDataInsertTaskCallBack* newcb = NULL;
if (NULL != buf) {
newcb = new (buf) ObRpcLoadDataInsertTaskCallBack(task_controller_, complete_task_list_, insert_task_);
}
return newcb;
}
int process();
int release_resouce();
private:
ObParallelTaskController& task_controller_;
ObConcurrentFixedCircularArray<ObInsertTask*>& complete_task_list_;
ObInsertTask* insert_task_;
};
} // namespace sql
} // namespace oceanbase
#endif // OCEANBASE_SQL_ENGINE_CMD_LOAD_DATA_RPC_H__

View File

@ -0,0 +1,410 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_load_data_utils.h"
#include "sql/resolver/cmd/ob_load_data_stmt.h"
#include "sql/session/ob_sql_session_info.h"
namespace oceanbase {
using namespace common;
namespace sql {
const char* ObLoadDataUtils::NULL_STRING = "NULL";
const char ObLoadDataUtils::NULL_VALUE_FLAG = '\xff';
int ObLoadDataUtils::build_insert_sql_string_head(ObLoadDupActionType insert_mode, const ObString& table_name,
const ObIArray<ObString>& insert_keys, ObSqlString& insertsql_keys)
{
int ret = OB_SUCCESS;
static const char* replace_stmt = "replace into ";
static const char* insert_stmt = "insert into ";
static const char* insert_ignore_stmt = "insert ignore into ";
const char* stmt_head = NULL;
switch (insert_mode) {
case ObLoadDupActionType::LOAD_REPLACE:
stmt_head = replace_stmt;
break;
case ObLoadDupActionType::LOAD_IGNORE:
stmt_head = insert_ignore_stmt;
break;
case ObLoadDupActionType::LOAD_STOP_ON_DUP:
stmt_head = insert_stmt;
break;
default:
ret = OB_NOT_SUPPORTED;
LOG_WARN("not suppport insert mode", K(insert_mode));
}
insertsql_keys.reuse();
OZ(insertsql_keys.reserve(OB_MEDIUM_SQL_LENGTH));
OZ(insertsql_keys.assign(stmt_head));
OZ(insertsql_keys.append(table_name));
OZ(insertsql_keys.append("("));
for (int64_t i = 0; i < insert_keys.count(); ++i) {
if (i != 0) {
OZ(insertsql_keys.append(","));
}
OZ(insertsql_keys.append_fmt(
share::is_oracle_mode() ? "\"%.*s\"" : "`%.*s`", insert_keys.at(i).length(), insert_keys.at(i).ptr()));
}
OZ(insertsql_keys.append(")"));
if (OB_FAIL(ret)) {
LOG_WARN("append failed", K(ret), K(insertsql_keys.length()));
}
return ret;
}
int ObLoadDataUtils::append_values_in_remote_process(int64_t table_column_count, int64_t append_values_count,
const ObExprValueBitSet& expr_bitset, const ObIArray<ObString>& insert_values, ObSqlString& insertsql,
ObDataBuffer& data_buffer, int64_t skipped_row_count)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!insertsql.is_valid()) ||
OB_UNLIKELY(append_values_count + skipped_row_count * table_column_count > insert_values.count()) ||
OB_UNLIKELY(0 == table_column_count)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("insert values are invalid", K(ret), K(insertsql), K(append_values_count), K(insert_values.count()));
} else {
int64_t row_count = append_values_count / table_column_count;
if (OB_FAIL(insertsql.append(" values "))) {
LOG_WARN("append failed", K(ret), K(insertsql.length()));
}
for (int64_t row_idx = 0; OB_SUCC(ret) && row_idx < row_count; ++row_idx) {
if (OB_FAIL(append_values_for_one_row(
table_column_count, expr_bitset, insert_values, insertsql, data_buffer, row_idx + skipped_row_count))) {
LOG_WARN("append values for one row in remote process failed", K(ret));
} else {
if (row_idx + 1 != row_count) {
if (OB_FAIL(insertsql.append(","))) {
LOG_WARN("append failed", K(ret), K(insertsql.length()));
}
}
}
}
}
return ret;
}
int ObLoadDataUtils::append_values_for_one_row(const int64_t table_column_count,
const ObExprValueBitSet& expr_value_bitset, const ObIArray<ObString>& insert_values, ObSqlString& insertsql,
ObDataBuffer& data_buffer, const int64_t skipped_row_count)
{
int ret = OB_SUCCESS;
int64_t value_offset = skipped_row_count * table_column_count;
if (OB_UNLIKELY(skipped_row_count * table_column_count + table_column_count > insert_values.count())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(skipped_row_count), K(table_column_count), K(insert_values.count()));
}
if (OB_SUCC(ret)) {
if (OB_FAIL(insertsql.append("("))) {
LOG_WARN("append failed", K(ret), K(insertsql.length()));
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < table_column_count; ++i) {
const ObString& value = insert_values.at(i + value_offset);
bool is_expr_value = expr_value_bitset.has_member(i);
ObString cur_column_str;
if (!is_expr_value) {
cur_column_str = escape_quotation(value, data_buffer);
remove_last_slash(cur_column_str);
} else {
cur_column_str = value;
}
if (i != 0) {
if (OB_FAIL(insertsql.append(","))) {
LOG_WARN("append failed", K(ret), K(insertsql.length()));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(append_value(cur_column_str, insertsql, is_expr_value))) {
LOG_WARN("append failed", K(ret), K(insertsql.length()), K(cur_column_str));
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(insertsql.append(")"))) {
LOG_WARN("append failed", K(ret), K(insertsql.length()));
}
}
return ret;
}
int ObLoadDataUtils::append_value(const ObString& cur_column_str, ObSqlString& sqlstr_values, bool is_expr_value)
{
int ret = OB_SUCCESS;
if (!is_expr_value) {
if (is_null_field(cur_column_str)) {
if (OB_FAIL(sqlstr_values.append(NULL_STRING))) {
LOG_WARN("append failed", K(ret));
}
} else {
if (OB_FAIL(sqlstr_values.append_fmt("'%.*s'", cur_column_str.length(), cur_column_str.ptr()))) {
LOG_WARN("append failed", K(ret));
}
}
} else {
if (OB_FAIL(sqlstr_values.append(cur_column_str))) {
LOG_WARN("append failed", K(ret));
}
}
return ret;
}
int ObLoadDataUtils::append_values_in_local_process(const int64_t key_columns, const int64_t values_count,
const ObIArray<ObString>& insert_values, const ObExprValueBitSet& expr_value_bitset, ObSqlString& insertsql,
ObDataBuffer& data_buffer)
{
int ret = OB_SUCCESS;
if (!insertsql.is_valid() || values_count > insert_values.count() || key_columns != values_count) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("insert values are invalid", K(ret), K(insertsql), K(values_count), K(insert_values.count()));
} else {
if (OB_FAIL(insertsql.append(" values "))) {
LOG_WARN("append failed", K(ret), K(insertsql.length()));
} else if (OB_FAIL(
append_values_for_one_row(values_count, expr_value_bitset, insert_values, insertsql, data_buffer))) {
LOG_WARN("append values for one row in local process failed", K(ret));
}
}
return ret;
}
ObString ObLoadDataUtils::escape_quotation(const ObString& value, ObDataBuffer& data_buf)
{
char* buf = data_buf.get_data();
ObString result;
if (OB_ISNULL(buf)) {
LOG_WARN("data buf is not inited");
} else {
// check if escape is needed
bool need_escape = false;
const char* src = value.ptr();
int64_t str_len = value.length();
ObLoadEscapeSM escape_sm;
escape_sm.set_escape_char(ObLoadEscapeSM::ESCAPE_CHAR_MYSQL);
for (int64_t i = 0; !need_escape && i < str_len; ++i) {
if (*(src + i) == '\'' && !escape_sm.is_escaping()) {
need_escape = true;
}
escape_sm.shift_by_input(*(src + i));
}
if (!need_escape) {
result = value;
} else {
int64_t pos = 0;
escape_sm.reset();
for (int64_t i = 0; i < str_len && pos < data_buf.get_capacity(); ++i) {
if (*(src + i) == '\'' && !escape_sm.is_escaping()) {
buf[pos++] = static_cast<char>(
share::is_oracle_mode() ? ObLoadEscapeSM::ESCAPE_CHAR_ORACLE : ObLoadEscapeSM::ESCAPE_CHAR_MYSQL);
}
buf[pos++] = src[i];
escape_sm.shift_by_input(*(src + i));
}
if (OB_UNLIKELY(pos >= data_buf.get_capacity())) {
LOG_ERROR("data is too long"); // this should never happened, just for protection
result.reset();
} else {
result.assign_ptr(buf, static_cast<int32_t>(pos));
}
}
}
return result;
}
int ObLoadDataUtils::init_empty_string_array(ObIArray<ObString>& new_array, int64_t array_size)
{
int ret = OB_SUCCESS;
new_array.reset();
for (int64_t i = 0; OB_SUCC(ret) && i < array_size; ++i) {
if (OB_FAIL(new_array.push_back(ObString::make_empty_string()))) {
LOG_WARN("push back empty string failed", K(ret));
}
}
return ret;
}
bool ObKMPStateMachine::scan_buf(char*& cur_pos, const char* buf_end)
{
bool matched = false;
if (OB_UNLIKELY(!is_inited_ || NULL == cur_pos)) {
LOG_ERROR("ObKmpStateMachine not inited.", K(cur_pos), K(buf_end));
} else {
for (; !matched && cur_pos < buf_end; cur_pos++) {
while (matched_pos_ > 0 && *cur_pos != str_[matched_pos_]) {
matched_pos_ = next_[matched_pos_];
}
if (*cur_pos == str_[matched_pos_]) {
matched_pos_++;
}
if (matched_pos_ == str_len_) {
matched_pos_ = 0;
matched = true;
}
}
}
return matched;
}
int ObKMPStateMachine::init(ObIAllocator& allocator, const ObString& str)
{
int ret = OB_SUCCESS;
void* next_buff = NULL;
void* str_buff = NULL;
int32_t str_len = str.length();
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
LOG_WARN("init failed, init twice.", K(ret));
} else if (OB_UNLIKELY(str_len > KEY_WORD_MAX_LENGTH) || OB_UNLIKELY(str_len <= 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("init failed, invalid argument.", K(ret));
} else if (OB_ISNULL(next_buff = allocator.alloc(str_len * sizeof(int32_t)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("init failed, no memory.", K(ret), K(str_len));
} else if (OB_ISNULL(str_buff = allocator.alloc(str_len * sizeof(char)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("init failed, no memory.", K(ret), K(str_len));
} else {
str_len_ = str_len;
next_ = static_cast<int32_t*>(next_buff);
str_ = static_cast<char*>(str_buff);
// copy string
MEMCPY(str_, str.ptr(), str.length());
matched_pos_ = 0;
// calc kmp next arr
int32_t k = 0;
next_[0] = 0;
for (int64_t i = 1; i < str_len_; ++i) {
while (k > 0 && str_[k] != str_[i]) {
k = next_[k];
}
if (str_[k] == str_[i]) {
k++;
}
next_[i] = k;
}
// check error
for (int64_t i = 0; OB_SUCC(ret) && i < str_len_; ++i) {
if (OB_UNLIKELY(next_[i] < 0) || OB_UNLIKELY(next_[i] >= str_len_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("check next value failed", K(ret));
}
}
if (OB_SUCC(ret)) {
is_inited_ = true;
}
}
return ret;
}
int ObLoadDataUtils::check_session_status(ObSQLSessionInfo& session, int64_t reserved_us)
{
int ret = OB_SUCCESS;
bool is_timeout = false;
int64_t query_timeout = 0;
int64_t query_start_time = session.get_query_start_time();
int64_t current_time = ObTimeUtil::current_time();
if (OB_FAIL(session.get_query_timeout(query_timeout))) {
LOG_WARN("fail to get query timeout", K(ret));
} else if (OB_FAIL(session.is_timeout(is_timeout))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get session timeout info failed", K(ret));
} else if (OB_UNLIKELY(query_start_time + query_timeout < current_time + reserved_us)) {
ret = OB_TIMEOUT;
LOG_WARN("query is timeout", K(ret));
} else if (OB_UNLIKELY(is_timeout)) {
ret = OB_TIMEOUT;
LOG_WARN("session is timeout", K(ret));
} else if (OB_UNLIKELY(session.is_query_killed())) {
ret = OB_ERR_QUERY_INTERRUPTED;
LOG_WARN("query is killed", K(ret));
} else if (OB_UNLIKELY(session.is_zombie())) {
ret = OB_SESSION_KILLED;
LOG_WARN("session is killed", K(ret));
}
if (OB_FAIL(ret)) {
LOG_WARN(
"LOAD DATA timeout", K(ret), K(session.get_sessid()), K(query_timeout), K(query_start_time), K(current_time));
}
return ret;
}
int ObGlobalLoadDataStatMap::init()
{
int ret = OB_SUCCESS;
if (IS_INIT) {
ret = OB_INIT_TWICE;
} else if (OB_FAIL(map_.create(bucket_num, ObModIds::OB_SQL_LOAD_DATA, ObModIds::OB_SQL_LOAD_DATA))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("create hash table failed", K(ret));
} else {
is_inited_ = true;
}
return ret;
}
int ObGlobalLoadDataStatMap::register_job(const ObLoadDataGID& id, ObLoadDataStat* job_status)
{
int ret = OB_SUCCESS;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
}
OZ(map_.set_refactored(id, job_status));
return ret;
}
int ObGlobalLoadDataStatMap::unregister_job(const ObLoadDataGID& id, ObLoadDataStat*& job_status)
{
int ret = OB_SUCCESS;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
}
OZ(map_.erase_refactored(id, &job_status));
return ret;
}
int ObGlobalLoadDataStatMap::get_job_status(const ObLoadDataGID& id, ObLoadDataStat*& job_status)
{
int ret = OB_SUCCESS;
auto get_and_add_ref = [&](hash::HashMapPair<ObLoadDataGID, ObLoadDataStat*>& entry) -> void {
entry.second->aquire();
job_status = entry.second;
};
OZ(map_.read_atomic(id, get_and_add_ref));
return ret;
}
ObGlobalLoadDataStatMap* ObGlobalLoadDataStatMap::getInstance()
{
return instance_;
}
ObGlobalLoadDataStatMap* ObGlobalLoadDataStatMap::instance_ = new ObGlobalLoadDataStatMap();
volatile int64_t ObLoadDataGID::GlobalLoadDataID = 0;
OB_SERIALIZE_MEMBER(ObLoadTaskStatus, task_status_);
OB_SERIALIZE_MEMBER(ObLoadDataGID, id);
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,360 @@
/**
* 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 "share/ob_define.h"
#include "lib/container/ob_se_array.h"
#include "lib/container/ob_bit_set.h"
#include "lib/string/ob_sql_string.h"
#include "lib/hash/ob_hashmap.h"
#include "common/object/ob_object.h"
#ifndef OCEANBASE_SQL_ENGINE_CMD_LOAD_DATA_UTILS_H_
#define OCEANBASE_SQL_ENGINE_CMD_LOAD_DATA_UTILS_H_
namespace oceanbase {
namespace sql {
enum class ObLoadTaskResultFlag;
enum class ObLoadDupActionType;
class ObSQLSessionInfo;
typedef common::ObBitSet<common::OB_DEFAULT_BITSET_SIZE_FOR_BASE_COLUMN> ObExprValueBitSet;
/* A state machine to handle backslash from a char stream */
class ObLoadEscapeSM {
public:
static const int64_t ESCAPE_CHAR_MYSQL = static_cast<int64_t>('\\');
static const int64_t ESCAPE_CHAR_ORACLE = static_cast<int64_t>('\'');
ObLoadEscapeSM() : is_escaped_flag_(false), escape_char_(INT64_MAX), escaped_char_count(0)
{}
OB_INLINE void shift_by_input(char c)
{
/* there are 4 situations:
* 1. STATE : c == \\ && is_escaped_flag_ == True Action: is_escaped_flag_ = False
* 2. STATE : c == \\ && is_escaped_flag_ == False Action: is_escaped_flag_ = True
* 3. STATE : c != \\ && is_escaped_flag_ == True Action: is_escaped_flag_ = False
* 4. STATE : c != \\ && is_escaped_flag_ == False Action: is_escaped_flag_ = False
* only state 1-3 need to change is_escaped_flag_, but usual case is state 4
*/
if (OB_LIKELY(static_cast<int64_t>(c) != escape_char_ && !is_escaped_flag_)) {
// situation 4, do nothing
} else {
// situation 1-3
is_escaped_flag_ = !is_escaped_flag_;
if (is_escaped_flag_) {
escaped_char_count++;
}
}
}
OB_INLINE bool is_escaping()
{
return is_escaped_flag_;
}
void set_escape_char(int64_t escape_char)
{
escape_char_ = escape_char;
}
void reset()
{
is_escaped_flag_ = false;
escaped_char_count = 0;
}
int64_t get_escaped_char_count()
{
return escaped_char_count;
}
private:
bool is_escaped_flag_;
int64_t escape_char_;
int64_t escaped_char_count;
};
class ObLoadDataUtils {
public:
static const char* NULL_STRING;
static const char NULL_VALUE_FLAG;
static inline void remove_last_slash(common::ObString& value)
{
const char* data = value.ptr();
int32_t data_len = value.length();
if (OB_LIKELY(data_len) > 0 && OB_UNLIKELY(data[data_len - 1] == '\\')) {
bool is_escaped = false;
for (int32_t i = data_len - 2; i >= 0 && data[i] == '\\'; --i) {
is_escaped = !is_escaped;
}
if (!is_escaped) {
value.assign_ptr(data, data_len - 1);
}
}
}
static inline int str_write_buf(const common::ObString& str, char*& buf, int64_t& buf_len)
{
int ret = common::OB_SUCCESS;
int64_t data_len = str.length();
if (OB_UNLIKELY(buf_len <= data_len)) {
ret = common::OB_SIZE_OVERFLOW;
} else {
MEMCPY(buf, str.ptr(), data_len);
buf += data_len;
buf_len -= data_len;
}
return ret;
}
static inline int char_write_buf(char c, char*& buf, int64_t& buf_len)
{
int ret = common::OB_SUCCESS;
if (OB_UNLIKELY(buf_len <= 1)) {
ret = common::OB_SIZE_OVERFLOW;
} else {
buf[0] = c;
buf++;
buf_len--;
}
return ret;
}
static inline int escape_str_write_buf(const common::ObHexEscapeSqlStr& str, char*& buf, int64_t& buf_len)
{
int ret = common::OB_SUCCESS;
int64_t data_len = str.to_string(buf, buf_len);
if (OB_UNLIKELY(buf_len <= data_len)) {
ret = common::OB_SIZE_OVERFLOW;
} else {
buf += data_len;
buf_len -= data_len;
}
return ret;
}
static inline bool is_null_field(const common::ObString& field_str)
{
int ret_bool = false;
if (field_str.length() == 1 && *field_str.ptr() == NULL_VALUE_FLAG) {
ret_bool = true;
}
return ret_bool;
}
static common::ObString escape_quotation(const common::ObString& value, common::ObDataBuffer& data_buf);
static int init_empty_string_array(common::ObIArray<common::ObString>& new_array, int64_t array_size);
static int build_insert_sql_string_head(ObLoadDupActionType insert_mode, const common::ObString& table_name,
const common::ObIArray<common::ObString>& insert_keys, common::ObSqlString& insertsql_keys);
static int append_values_in_remote_process(int64_t table_column_count, int64_t append_values_count,
const ObExprValueBitSet& expr_bitset, const common::ObIArray<common::ObString>& insert_values,
common::ObSqlString& insertsql, common::ObDataBuffer& data_buffer, int64_t skipped_row_count = 0);
static int append_values_for_one_row(const int64_t table_column_count, const ObExprValueBitSet& expr_value_bitset,
const common::ObIArray<common::ObString>& insert_values, common::ObSqlString& insertsql,
common::ObDataBuffer& data_buffer, const int64_t skipped_row_count = 0);
static int append_value(
const common::ObString& cur_column_str, common::ObSqlString& sqlstr_values, bool is_expr_value);
static int append_values_in_local_process(const int64_t key_columns, const int64_t values_count,
const common::ObIArray<common::ObString>& insert_values, const ObExprValueBitSet& expr_value_bitset,
common::ObSqlString& insertsql, common::ObDataBuffer& data_buffer);
static inline bool has_flag(int64_t& task_status, int64_t flag)
{
return 0 != (task_status & (1 << flag));
}
static inline void set_flag(int64_t& task_status, int64_t flag)
{
task_status |= (1 << flag);
}
static int check_session_status(ObSQLSessionInfo& session, int64_t reserved_us = 0);
};
class ObLoadTaskStatus {
public:
ObLoadTaskStatus() : task_status_(0)
{}
enum class ResFlag {
HAS_FAILED_ROW = 0,
ALL_ROWS_FAILED,
NEED_WAIT_MINOR_FREEZE,
TIMEOUT,
RPC_CALLBACK_PROCESS_ERROR,
RPC_REMOTE_PROCESS_ERROR,
INVALID_MAX_FLAG
};
static_assert(static_cast<int64_t>(ResFlag::INVALID_MAX_FLAG) < 64,
"ObLoadTaskResultFlag max value should less than bit size of int64_t");
OB_INLINE void set_flag(ResFlag flag)
{
task_status_ |= (1 << static_cast<int64_t>(flag));
}
OB_INLINE bool has_flag(ResFlag flag)
{
return 0 != (task_status_ & (1 << static_cast<int64_t>(flag)));
}
TO_STRING_KV(K_(task_status));
OB_UNIS_VERSION(1);
private:
int64_t task_status_;
};
class ObLoadDataTimer {
public:
ObLoadDataTimer() : total_time_us_(0), temp_start_time_us_(-1)
{}
OB_INLINE void start_stat()
{
#ifdef TIME_STAT_ON
temp_start_time_us_ = ObTimeUtility::current_time();
#endif
}
OB_INLINE void end_stat()
{
#ifdef TIME_STAT_ON
if (temp_start_time_us_ != -1) {
total_time_us_ += (ObTimeUtility::current_time() - temp_start_time_us_);
temp_start_time_us_ = -1;
}
#endif
}
int64_t get_wait_secs() const
{
return total_time_us_ / 1000000;
}
TO_STRING_KV("secs", get_wait_secs());
private:
int64_t total_time_us_;
int64_t temp_start_time_us_;
};
/*
* ObKMPStateMachine is a str matcher
* efficently implimented using KMP algorithem
* to detect a given str from a char stream
*/
class ObKMPStateMachine {
public:
ObKMPStateMachine() : is_inited_(false), str_(NULL), str_len_(0), matched_pos_(0), next_(NULL)
{}
int init(common::ObIAllocator& allocator, const common::ObString& str);
/*
* accept one char at a time, and update the state of the detector
* return true if succ matching target str ending with the current char
*/
OB_INLINE bool accept_char(const char c)
{
bool ret_bool = false;
if (OB_UNLIKELY(!is_inited_)) {
SQL_ENG_LOG(ERROR, "ObKmpSeparatorDetector not inited.");
} else {
while (matched_pos_ > 0 && c != str_[matched_pos_]) {
matched_pos_ = next_[matched_pos_];
}
if (c == str_[matched_pos_]) {
matched_pos_++;
}
if (matched_pos_ == str_len_) {
matched_pos_ = 0;
ret_bool = true;
}
}
return ret_bool;
}
OB_INLINE int32_t get_pattern_length()
{
return str_len_;
}
bool scan_buf(char*& cur_pos, const char* buf_end);
void reuse()
{
matched_pos_ = 0;
}
private:
static const int KEY_WORD_MAX_LENGTH = 2 * 1024;
bool is_inited_;
char* str_; // string pattern for matching
int32_t str_len_;
int32_t matched_pos_; // can opt to pointer
int32_t* next_; // next array of KMP algorithm
};
struct ObLoadDataGID {
static volatile int64_t GlobalLoadDataID;
static void generate_new_id(ObLoadDataGID& gid)
{
gid.id = ATOMIC_AAF(&GlobalLoadDataID, 1);
}
ObLoadDataGID() : id(-1)
{}
bool is_valid() const
{
return id > 0;
}
uint64_t hash() const
{
return common::murmurhash(&id, sizeof(id), 0);
}
bool operator==(const ObLoadDataGID& other) const
{
return id == other.id;
}
void operator=(const ObLoadDataGID& other)
{
id = other.id;
}
int64_t id;
TO_STRING_KV(K(id));
OB_UNIS_VERSION(1);
};
struct ObLoadDataStat {
ObLoadDataStat() : ref_cnt_(0)
{}
int64_t aquire()
{
return ATOMIC_AAF(&ref_cnt_, 1);
}
int64_t release()
{
return ATOMIC_AAF(&ref_cnt_, -1);
}
int64_t get_ref_cnt()
{
return ATOMIC_LOAD(&ref_cnt_);
}
volatile int64_t ref_cnt_;
};
class ObGlobalLoadDataStatMap {
public:
static ObGlobalLoadDataStatMap* getInstance();
ObGlobalLoadDataStatMap() : is_inited_(false)
{}
int init();
int register_job(const ObLoadDataGID& id, ObLoadDataStat* job_status);
int unregister_job(const ObLoadDataGID& id, ObLoadDataStat*& job_status);
int get_job_status(const ObLoadDataGID& id, ObLoadDataStat*& job_status);
private:
typedef common::hash::ObHashMap<ObLoadDataGID, ObLoadDataStat*, common::hash::SpinReadWriteDefendMode> HASH_MAP;
static const int64_t bucket_num = 1000;
static ObGlobalLoadDataStatMap* instance_;
HASH_MAP map_;
bool is_inited_;
};
} // namespace sql
} // namespace oceanbase
#endif // OCEANBASE_SQL_ENGINE_CMD_LOAD_DATA_UTILS_H_

View File

@ -0,0 +1,438 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_outline_executor.h"
#include "lib/string/ob_string.h"
#include "share/ob_common_rpc_proxy.h"
#include "share/ob_rpc_struct.h"
#include "share/schema/ob_schema_getter_guard.h"
#include "share/schema/ob_schema_struct.h"
#include "share/stat/ob_stat_manager.h"
#include "observer/ob_server_struct.h"
#include "sql/ob_sql.h"
#include "sql/resolver/ddl/ob_create_outline_stmt.h"
#include "sql/resolver/ddl/ob_alter_outline_stmt.h"
#include "sql/resolver/ddl/ob_drop_outline_stmt.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/parser/ob_parser.h"
#include "sql/optimizer/ob_log_plan.h"
#include "sql/engine/ob_physical_plan_ctx.h"
#include "sql/rewrite/ob_transformer_impl.h"
#include "sql/rewrite/ob_transform_simplify.h"
#include "sql/resolver/ob_schema_checker.h"
#include "sql/optimizer/ob_optimizer.h"
#include "sql/optimizer/ob_optimizer_context.h"
#include "sql/optimizer/ob_optimizer_partition_location_cache.h"
#include "sql/optimizer/ob_log_plan_factory.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/plan_cache/ob_cache_object_factory.h"
#include "sql/ob_sql_partition_location_cache.h"
namespace oceanbase {
using namespace common;
using namespace share::schema;
using namespace obrpc;
namespace sql {
int ObOutlineExecutor::generate_outline_info2(
ObExecContext& ctx, ObCreateOutlineStmt* create_outline_stmt, ObOutlineInfo& outline_info)
{
int ret = OB_SUCCESS;
outline_info.set_tenant_id(ctx.get_my_session()->get_effective_tenant_id());
outline_info.set_outline_content(create_outline_stmt->get_hint());
outline_info.set_sql_id(create_outline_stmt->get_sql_id());
if (create_outline_stmt->get_max_concurrent() >= 0) {
ObMaxConcurrentParam concurrent_param(&ctx.get_allocator());
concurrent_param.concurrent_num_ = create_outline_stmt->get_max_concurrent();
if (OB_FAIL(outline_info.add_param(concurrent_param))) {
LOG_WARN("fail to add param", K(ret));
}
}
return ret;
}
int ObOutlineExecutor::generate_outline_info(
ObExecContext& ctx, ObCreateOutlineStmt* outline_stmt, ObOutlineInfo& outline_info)
{
int ret = OB_SUCCESS;
ObCreateOutlineStmt* create_outline_stmt = reinterpret_cast<ObCreateOutlineStmt*>(outline_stmt);
if (create_outline_stmt->get_outline_stmt() == NULL) {
ret = generate_outline_info2(ctx, create_outline_stmt, outline_info);
} else {
ObDMLStmt* outline_stmt = static_cast<ObDMLStmt*>(create_outline_stmt->get_outline_stmt());
ret = generate_outline_info1(ctx, outline_stmt, outline_info);
}
return ret;
}
int ObOutlineExecutor::generate_outline_info1(ObExecContext& ctx, ObDMLStmt* outline_stmt, ObOutlineInfo& outline_info)
{
int ret = OB_SUCCESS;
bool has_questionmark_in_outline_sql = false;
ObString outline;
ObString outline_key;
ObString& outline_sql = outline_info.get_sql_text_str();
int64_t max_concurrent = -1;
;
ObMaxConcurrentParam concurrent_param(&ctx.get_allocator());
if (OB_ISNULL(ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid ctx", K(ret));
} else if (OB_ISNULL(outline_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid outline stmt is NULL", K(ret));
} else if (OB_FAIL(ObSQLUtils::get_outline_key(ctx.get_allocator(),
ctx.get_my_session(),
outline_sql,
outline_key,
concurrent_param.fixed_param_store_,
FP_PARAMERIZE_AND_FILTER_HINT_MODE,
has_questionmark_in_outline_sql))) {
LOG_WARN("fail to get outline key", "outline_sql", outline_sql, K(ret));
} else if (FALSE_IT(max_concurrent = outline_stmt->get_stmt_hint().max_concurrent_)) {
} else if (OB_UNLIKELY(has_questionmark_in_outline_sql && max_concurrent < 0)) {
ret = OB_INVALID_OUTLINE;
LOG_USER_ERROR(OB_INVALID_OUTLINE, "sql text should have no ? when there is no concurrent limit");
LOG_WARN("outline should have no ? when there is no concurrent limit", K(outline_sql), K(ret));
} else if (OB_UNLIKELY(max_concurrent >= 0 && outline_stmt->get_stmt_hint().has_hint_exclude_concurrent_)) {
ret = OB_INVALID_OUTLINE;
LOG_USER_ERROR(OB_INVALID_OUTLINE, "outline and sql concurrent limit can not be mixed");
LOG_WARN("outline and sql concurrent limit can not be mixed",
"outline_sql_text",
outline_info.get_sql_text_str(),
K(ret));
} else if (OB_FAIL(get_outline(ctx, outline_stmt, outline))) {
LOG_WARN("fail to get outline", K(ret));
} else {
// to check whether ok
outline_info.set_outline_content(outline);
outline_info.set_tenant_id(ctx.get_my_session()->get_effective_tenant_id());
outline_info.set_signature(outline_key);
ObString& target_sql = outline_info.get_outline_target_str();
if (!target_sql.empty()) {
ObString target_key;
ObString target_key_with_hint;
ObMaxConcurrentParam target_param(&ctx.get_allocator());
ObMaxConcurrentParam target_param_with_hint(&ctx.get_allocator());
bool has_questionmark_in_target_sql = false;
bool is_same_param = true;
// get signature derived from to_clause, then check if equal with signature derived from
// on_clause
if (OB_FAIL(ObSQLUtils::get_outline_key(ctx.get_allocator(),
ctx.get_my_session(),
target_sql,
target_key,
target_param.fixed_param_store_,
FP_PARAMERIZE_AND_FILTER_HINT_MODE,
has_questionmark_in_target_sql))) {
LOG_WARN("fail to get outline key", K(target_sql), K(ret));
} else if (target_key != outline_key || has_questionmark_in_target_sql != has_questionmark_in_outline_sql) {
ret = OB_INVALID_OUTLINE;
LOG_USER_ERROR(
OB_INVALID_OUTLINE, "signature derived from on_clause is not same as signature derived from to_clause");
LOG_WARN("outline key is not same with target key",
K(outline_sql),
K(target_sql),
K(has_questionmark_in_target_sql),
K(has_questionmark_in_outline_sql),
K(ret));
} else if (max_concurrent >= 0 &&
(OB_FAIL(concurrent_param.same_param_as(target_param, is_same_param)) || !is_same_param)) {
if (OB_FAIL(ret)) {
LOG_WARN("fail to check if param is same", K(outline_sql), K(target_sql), K(ret));
} else {
ret = OB_INVALID_OUTLINE;
LOG_USER_ERROR(OB_INVALID_OUTLINE,
"fixed_param derived from on_clause is not same as fixed_param derived from to_clause");
LOG_WARN("outline fixed_param is not same with target fixed_param", K(outline_sql), K(target_sql), K(ret));
}
} else if (OB_FAIL(ObSQLUtils::get_outline_key(ctx.get_allocator(),
ctx.get_my_session(),
target_sql,
target_key_with_hint,
target_param_with_hint.fixed_param_store_,
FP_MODE,
has_questionmark_in_target_sql))) {
LOG_WARN("fail to get outline key", K(target_sql), K(ret));
} else {
// replace outline_key with target_key derived from to_clause with index not filtered
outline_info.set_signature(target_key_with_hint);
}
}
if (OB_SUCC(ret)) {
// set concurrent limit info to ObOutlineInfo
if (max_concurrent < 0) {
// if concurrent num is negative, you should reset the max concurrent param store
} else {
concurrent_param.concurrent_num_ = max_concurrent;
if (OB_FAIL(outline_info.add_param(concurrent_param))) {
LOG_WARN("fail to add param", K(ret));
}
}
}
}
return ret;
}
int ObOutlineExecutor::generate_logical_plan(
ObExecContext& ctx, ObOptimizerContext& opt_ctx, ObDMLStmt* outline_stmt, ObLogPlan*& logical_plan)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session_info = ctx.get_my_session();
ObPhysicalPlan* phy_plan = NULL;
ObOptimizer optimizer(opt_ctx);
if (OB_ISNULL(session_info) || OB_ISNULL(outline_stmt) || OB_ISNULL(opt_ctx.get_location_cache())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid parameter", K(session_info), K(outline_stmt));
} else if (OB_FAIL(
ObCacheObjectFactory::alloc(phy_plan, OUTLINE_EXEC_HANDLE, session_info->get_effective_tenant_id()))) {
LOG_WARN("fail to alloc phy_plan", K(ret));
} else if (OB_ISNULL(phy_plan)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("Failed to alloc physical plan from tc factory", K(ret));
} else if (OB_FAIL(ObSql::calc_pre_calculable_exprs(
outline_stmt->get_calculable_exprs(), ctx, *outline_stmt, *phy_plan))) {
LOG_WARN("fail to calc pre calculable expr", K(ret));
} else if (OB_FAIL(ObSql::transform_stmt(opt_ctx.get_sql_schema_guard(),
static_cast<ObOptimizerPartitionLocationCache*>(opt_ctx.get_location_cache())->get_location_cache(),
opt_ctx.get_partition_service(),
opt_ctx.get_stat_manager(),
opt_ctx.get_opt_stat_manager(),
&opt_ctx.get_local_server_addr(),
opt_ctx.get_merged_version(),
phy_plan,
ctx,
outline_stmt))) {
LOG_WARN("fail to transform outline stmt", K(ret));
} else if (OB_FAIL(ObSql::optimize_stmt(optimizer, *session_info, *outline_stmt, logical_plan))) {
LOG_WARN("fail to optimize stmt", K(ret));
} else { /*do nothing*/
}
if (OB_LIKELY(phy_plan != NULL)) {
ObCacheObjectFactory::free(phy_plan, OUTLINE_EXEC_HANDLE);
phy_plan = NULL;
}
return ret;
}
bool ObOutlineExecutor::is_valid_outline_stmt_type(stmt::StmtType type)
{
return type == stmt::T_SELECT || type == stmt::T_INSERT || type == stmt::T_UPDATE || type == stmt::T_REPLACE ||
type == stmt::T_DELETE;
}
int ObOutlineExecutor::print_outline(ObExecContext& ctx, ObLogPlan* log_plan, ObString& outline)
{
void* tmp_ptr = NULL;
char* buf = NULL;
int64_t pos = 0;
int ret = OB_SUCCESS;
if (OB_ISNULL(log_plan)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to get log plan", K(ret), K(log_plan));
} else if (OB_UNLIKELY(NULL == (tmp_ptr = ctx.get_allocator().alloc(
OB_MAX_SQL_LENGTH)))) { // the same as __all_outline column outline_content
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("fail to alloc memory", K(ret));
} else if (FALSE_IT(buf = static_cast<char*>(tmp_ptr))) {
} else if (OB_FAIL(log_plan->print_outline_oneline(buf, OB_MAX_SQL_LENGTH, pos))) {
LOG_WARN("fail to print outline", K(ret), K(buf), K(pos));
} else {
outline.assign_ptr(buf, static_cast<ObString::obstr_size_t>(pos));
}
return ret;
}
int ObOutlineExecutor::get_outline(ObExecContext& ctx, ObDMLStmt* outline_stmt, ObString& outline)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session_info = ctx.get_my_session();
ObPhysicalPlanCtx* pctx = ctx.get_physical_plan_ctx();
ObLogPlan* log_plan = NULL;
if (OB_ISNULL(session_info) || OB_ISNULL(pctx) || OB_ISNULL(outline_stmt) || OB_ISNULL(GCTX.merged_version_) ||
OB_ISNULL(ctx.get_sql_ctx()) || OB_ISNULL(ctx.get_sql_ctx()->sql_schema_guard_.get_schema_guard())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid parameter", K(session_info), K(pctx), K(outline_stmt), K(GCTX.merged_version_));
} else if (!is_valid_outline_stmt_type(outline_stmt->get_stmt_type())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected outline stmt type", K(outline_stmt->get_stmt_type()), K(ret));
} else {
if (outline_stmt->get_stmt_hint().is_only_concurrent_hint()) {
// do not generate outline_content
} else if (OB_ISNULL(ctx.get_expr_factory())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(ctx.get_expr_factory()));
} else {
ObSqlPartitionLocationCache sql_partition_location_cache;
sql_partition_location_cache.init(
GCTX.location_cache_, GCTX.self_addr_, ctx.get_virtual_table_ctx().schema_guard_);
ObQueryHint query_hint = outline_stmt->get_stmt_hint().get_query_hint();
ObOptimizerPartitionLocationCache optimizer_location_cache(ctx.get_allocator(), &sql_partition_location_cache);
ObOptimizerContext optctx(session_info,
&ctx,
&ctx.get_sql_ctx()->sql_schema_guard_,
&ObStatManager::get_instance(),
&ObOptStatManager::get_instance(),
GCTX.par_ser_,
ctx.get_allocator(),
&optimizer_location_cache,
&pctx->get_param_store(),
GCTX.self_addr_,
GCTX.srv_rpc_proxy_,
*GCTX.merged_version_,
query_hint,
*ctx.get_expr_factory(),
outline_stmt);
if (OB_FAIL(generate_logical_plan(ctx, optctx, outline_stmt, log_plan))) {
LOG_WARN("fail to generate logical plan", K(ret));
} else if (OB_FAIL(print_outline(ctx, log_plan, outline))) {
LOG_WARN("fail to print outline", K(ret));
} else { /*do nothing*/
}
}
}
return ret;
}
int ObCreateOutlineExecutor::execute(ObExecContext& ctx, ObCreateOutlineStmt& stmt)
{
int ret = OB_SUCCESS;
ObString outline_key;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
ObCreateOutlineArg& arg = stmt.get_create_outline_arg();
ObOutlineInfo& outline_info = arg.outline_info_;
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
arg.ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(generate_outline_info(ctx, &stmt, outline_info))) {
LOG_WARN("generate_outline_info failed", K(ret));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed", K(ret));
} else if (OB_FAIL(ctx.get_sql_ctx()->schema_guard_->reset())) {
LOG_WARN("schema_guard reset failed", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->create_outline(arg))) {
LOG_WARN("rpc proxy create outline failed", "dst", common_rpc_proxy->get_server(), K(ret));
} else { /*do nothing*/
}
return ret;
}
int ObAlterOutlineExecutor::execute(ObExecContext& ctx, ObAlterOutlineStmt& stmt)
{
int ret = OB_SUCCESS;
ObString outline_key;
ObString outline;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
ObAlterOutlineArg& arg = stmt.get_alter_outline_arg();
ObOutlineInfo& outline_info = arg.alter_outline_info_;
ObDMLStmt* outline_stmt = static_cast<ObDMLStmt*>(stmt.get_outline_stmt());
ObString& outline_sql = stmt.get_outline_sql();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
arg.ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(outline_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("outline stmt is empty", K(ret));
} else if (OB_FAIL(generate_outline_info1(ctx, outline_stmt, outline_info))) {
LOG_WARN("generate_outline_info failed", K(outline_sql), K(ret));
} else {
ObAlterOutlineInfo& alter_outline_info = arg.alter_outline_info_;
int64_t index = OB_INVALID_INDEX;
bool has_limit_param = false;
if (OB_FAIL(alter_outline_info.has_concurrent_limit_param(has_limit_param))) {
LOG_WARN("fail to judge whether outline_info has concurrent_limit_param", K(ret));
} else if (has_limit_param) {
index = ObAlterOutlineArg::ADD_CONCURRENT_LIMIT;
} else if (!alter_outline_info.get_outline_content_str().empty()) {
index = ObAlterOutlineArg::ADD_OUTLINE_CONTENT;
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid alter outline info", K(alter_outline_info), K(ret));
}
if (OB_SUCC(ret) && OB_FAIL(alter_outline_info.get_alter_option_bitset().add_member(index))) {
LOG_WARN("failed to add member to alter_option_bitset", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_FAIL(ctx.get_sql_ctx()->schema_guard_->reset())) {
LOG_WARN("schema_guard reset failed", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->alter_outline(arg))) {
LOG_WARN("rpc proxy alter outline failed", "dst", common_rpc_proxy->get_server(), K(ret));
} else { /*do nothing*/
}
return ret;
}
int ObDropOutlineExecutor::execute(ObExecContext& ctx, ObDropOutlineStmt& stmt)
{
int ret = OB_SUCCESS;
ObDropOutlineArg arg = stmt.get_drop_outline_arg();
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
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;
LOG_WARN("get task executor context failed");
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->drop_outline(arg))) {
LOG_WARN("rpc proxy drop outline failed", K(ret), "dst", common_rpc_proxy->get_server());
} else { /*do nothing*/
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,98 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_OB_CREATE_OUTLINE_EXECUTOR_H_
#define OCEANBASE_SQL_OB_CREATE_OUTLINE_EXECUTOR_H_
#include "lib/container/ob_vector.h"
#include "sql/parser/parse_node.h"
#include "sql/resolver/ob_stmt_type.h"
namespace oceanbase {
namespace common {
class ObString;
}
namespace share {
namespace schema {
class ObOutlineInfo;
}
} // namespace share
namespace sql {
class ObExecContext;
class ObCreateOutlineStmt;
class ObAlterOutlineStmt;
class ObDropOutlineStmt;
class ObLogPlan;
class ObDMLStmt;
class ObOptimizerContext;
class ObOutlineExecutor {
public:
ObOutlineExecutor()
{}
virtual ~ObOutlineExecutor()
{}
protected:
int get_outline(ObExecContext& ctx, ObDMLStmt* outline_stmt, common::ObString& outline);
int generate_outline_info(
ObExecContext& ctx, ObCreateOutlineStmt* outline_stmt, share::schema::ObOutlineInfo& outline_info);
int generate_outline_info1(ObExecContext& ctx, ObDMLStmt* outline_stmt, share::schema::ObOutlineInfo& outline_info);
int generate_outline_info2(
ObExecContext& ctx, ObCreateOutlineStmt* outline_stmt, share::schema::ObOutlineInfo& outline_info);
int generate_logical_plan(
ObExecContext& ctx, ObOptimizerContext& opt_ctx, ObDMLStmt* outline_stmt, ObLogPlan*& logical_plan);
bool is_valid_outline_stmt_type(stmt::StmtType type);
int print_outline(ObExecContext& ctx, ObLogPlan* log_plan, common::ObString& outline);
private:
DISALLOW_COPY_AND_ASSIGN(ObOutlineExecutor);
};
class ObCreateOutlineExecutor : public ObOutlineExecutor {
public:
ObCreateOutlineExecutor()
{}
virtual ~ObCreateOutlineExecutor()
{}
int execute(ObExecContext& ctx, ObCreateOutlineStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObCreateOutlineExecutor);
};
class ObAlterOutlineExecutor : public ObOutlineExecutor {
public:
ObAlterOutlineExecutor()
{}
virtual ~ObAlterOutlineExecutor()
{}
int execute(ObExecContext& ctx, ObAlterOutlineStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObAlterOutlineExecutor);
};
class ObDropOutlineExecutor {
public:
ObDropOutlineExecutor()
{}
virtual ~ObDropOutlineExecutor()
{}
int execute(ObExecContext& ctx, ObDropOutlineStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObDropOutlineExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif // OCEANBASE_SQL_OB_CREATE_OUTLINE_EXECUTOR_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_OB_PARTITION_EXECUTOR_UTILS_
#define OCEANBASE_SQL_OB_PARTITION_EXECUTOR_UTILS_
#include "common/object/ob_object.h"
#include "lib/container/ob_se_array.h"
#include "common/sql_mode/ob_sql_mode.h"
#include "sql/resolver/ob_stmt_type.h"
#include "sql/engine/expr/ob_expr_res_type.h"
#include "sql/resolver/ddl/ob_table_stmt.h"
namespace oceanbase {
namespace share {
namespace schema {
class ObPartition;
class ObSubPartition;
} // namespace schema
} // namespace share
namespace sql {
class ObExecContext;
class ObRawExpr;
class ObCreateTableStmt;
class ObCreateTablegroupStmt;
class ObCreateIndexStmt;
class ObTableStmt;
class ObTablegroupStmt;
class ObPartitionExecutorUtils {
public:
const static int OB_DEFAULT_ARRAY_SIZE = 16;
static int calc_values_exprs(ObExecContext& ctx, ObCreateTableStmt& stmt);
static int calc_values_exprs(ObExecContext& ctx, ObCreateIndexStmt& stmt);
static int calc_values_exprs_for_alter_table(
ObExecContext& ctx, share::schema::ObTableSchema& table_schema, ObPartitionedStmt& stmt);
static int cast_list_expr_to_obj(ObExecContext& ctx, const stmt::StmtType stmt_type, const bool is_subpart,
const int64_t real_part_num, share::schema::ObPartition** partition_array,
share::schema::ObSubPartition** subpartition_array, common::ObIArray<ObRawExpr*>& list_fun_expr,
common::ObIArray<ObRawExpr*>& list_values_exprs);
static int cast_expr_to_obj(ObExecContext& ctx, const stmt::StmtType stmt_type, bool is_list_part,
common::ObIArray<ObRawExpr*>& partition_fun_expr, common::ObIArray<ObRawExpr*>& partition_value_exprs,
common::ObIArray<common::ObObj>& partition_value_objs);
static int set_range_part_high_bound(ObExecContext& ctx, const stmt::StmtType stmt_type,
share::schema::ObTableSchema& table_schema, ObPartitionedStmt& stmt, bool is_subpart);
/*--------------tablegroup related start------------------*/
static int calc_values_exprs(ObExecContext& ctx, ObCreateTablegroupStmt& stmt);
static int calc_values_exprs(ObExecContext& ctx, ObCreateTablegroupStmt& stmt, bool is_subpart);
static int cast_range_expr_to_obj(ObExecContext& ctx, ObCreateTablegroupStmt& stmt, bool is_subpart,
common::ObIArray<common::ObObj>& range_partition_obj);
static int cast_range_expr_to_obj(ObExecContext& ctx, common::ObIArray<ObRawExpr*>& range_values_exprs,
const int64_t fun_expr_num, const stmt::StmtType stmt_type, const bool is_subpart, const int64_t real_part_num,
share::schema::ObPartition** partition_array, share::schema::ObSubPartition** subpartition_array,
common::ObIArray<common::ObObj>& range_partition_obj);
static int cast_list_expr_to_obj(ObExecContext& ctx, ObCreateTablegroupStmt& stmt, bool is_subpar);
static int cast_list_expr_to_obj(ObExecContext& ctx, ObTablegroupStmt& stmt, const bool is_subpart,
share::schema::ObPartition** partition_array, share::schema::ObSubPartition** subpartition_array);
static int cast_expr_to_obj(ObExecContext& ctx, int64_t fun_expr_num,
common::ObIArray<ObRawExpr*>& range_values_exprs, common::ObIArray<common::ObObj>& range_partition_obj);
/*--------------tablegroup related end------------------*/
static int calc_range_values_exprs(ObExecContext& ctx, ObCreateIndexStmt& stmt);
template <typename T>
static int check_increasing_range_value(T** array, int64_t part_num, const stmt::StmtType stmt_type);
static int expr_cal_and_cast(const sql::stmt::StmtType& stmt_type, bool is_list_part, ObExecContext& ctx,
const common::ObObjType fun_expr_type, const common::ObCollationType fun_collation_type, ObRawExpr* expr,
common::ObObj& value_obj);
static int expr_cal_and_cast_with_check_varchar_len(const stmt::StmtType& stmt_type, bool is_list_part,
ObExecContext& ctx, const sql::ObExprResType& dst_res_type, ObRawExpr* expr, common::ObObj& value_obj);
static int set_list_part_rows(ObExecContext& ctx, const stmt::StmtType stmt_type,
share::schema::ObTableSchema& table_schema, ObIArray<ObRawExpr*>& list_fun_exprs,
ObIArray<ObRawExpr*>& list_values_exprs, bool is_subpart);
static int set_individual_range_part_high_bound(ObExecContext& ctx, const stmt::StmtType stmt_type,
share::schema::ObTableSchema& table_schema, ObPartitionedStmt& stmt);
static int set_individual_list_part_rows(ObExecContext& ctx, const stmt::StmtType stmt_type,
share::schema::ObTableSchema& table_schema, ObIArray<ObRawExpr*>& list_fun_exprs,
ObDDLStmt::array_array_t& list_values_exprs_array);
static int row_expr_to_array(ObRawExpr* row_expr, ObIArray<ObRawExpr*>& list_values_expr_array);
private:
static int calc_values_exprs(ObExecContext& ctx, const stmt::StmtType stmt_type,
share::schema::ObTableSchema& table_schema, ObPartitionedStmt& stmt, bool is_subpart);
static int sort_list_paritition_if_need(share::schema::ObTableSchema& table_schema);
};
} // end namespace sql
} // end namespace oceanbase
#endif // OCEANBASE_SQL_OB_PARTITION_EXECUTOR_UTILS_

View File

@ -0,0 +1,49 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_profile_cmd_executor.h"
#include "lib/encrypt/ob_encrypted_helper.h"
#include "lib/string/ob_sql_string.h"
#include "share/schema/ob_schema_struct.h"
#include "share/ob_rpc_struct.h"
#include "share/ob_common_rpc_proxy.h"
#include "sql/resolver/ddl/ob_create_profile_stmt.h"
#include "sql/engine/ob_exec_context.h"
namespace oceanbase {
using namespace common;
using namespace obrpc;
using namespace share::schema;
namespace sql {
int ObProfileDDLExecutor::execute(ObExecContext& ctx, ObUserProfileStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else if (OB_FAIL(common_rpc_proxy->do_profile_ddl(stmt.get_ddl_arg()))) {
LOG_WARN("Create profile error", K(ret));
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,43 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_CMD_PROFILE_CMD_EXECUTOR_
#define OCEANBASE_SQL_ENGINE_CMD_PROFILE_CMD_EXECUTOR_
#include "lib/string/ob_string.h"
#include "lib/container/ob_array_serialization.h"
#include "share/schema/ob_schema_struct.h"
namespace oceanbase {
namespace obrpc {
class ObCommonRpcProxy;
class ObUserProfileArg;
class ObDropUserArg;
} // namespace obrpc
namespace sql {
class ObExecContext;
class ObUserProfileStmt;
class ObProfileDDLExecutor {
public:
ObProfileDDLExecutor()
{}
virtual ~ObProfileDDLExecutor()
{}
int execute(ObExecContext& ctx, ObUserProfileStmt& stmt);
private:
private:
DISALLOW_COPY_AND_ASSIGN(ObProfileDDLExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif // OCEANBASE_SQL_ENGINE_CMD_PROFILE_CMD_EXECUTOR_

View File

@ -0,0 +1,223 @@
/**
* 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/ob_exec_context.h"
#include "sql/engine/cmd/ob_resource_executor.h"
#include "sql/resolver/cmd/ob_resource_stmt.h"
#include "share/ob_common_rpc_proxy.h"
using namespace oceanbase::common;
namespace oceanbase {
namespace sql {
ObCreateResourcePoolExecutor::ObCreateResourcePoolExecutor()
{}
ObCreateResourcePoolExecutor::~ObCreateResourcePoolExecutor()
{}
int ObCreateResourcePoolExecutor::execute(ObExecContext& ctx, ObCreateResourcePoolStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObCreateResourcePoolArg& create_resource_pool_arg = stmt.get_arg();
if (NULL == (task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (NULL == (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_SUCCESS != (ret = common_rpc_proxy->create_resource_pool(create_resource_pool_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy create resource_pool failed", K(ret));
}
return ret;
}
ObAlterResourcePoolExecutor::ObAlterResourcePoolExecutor()
{}
ObAlterResourcePoolExecutor::~ObAlterResourcePoolExecutor()
{}
int ObAlterResourcePoolExecutor::execute(ObExecContext& ctx, ObAlterResourcePoolStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObAlterResourcePoolArg& alter_resource_pool_arg = stmt.get_arg();
if (NULL == (task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (NULL == (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_SUCCESS != (ret = common_rpc_proxy->alter_resource_pool(alter_resource_pool_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy alter resource_pool failed", K(ret));
}
return ret;
}
ObSplitResourcePoolExecutor::ObSplitResourcePoolExecutor()
{}
ObSplitResourcePoolExecutor::~ObSplitResourcePoolExecutor()
{}
int ObSplitResourcePoolExecutor::execute(ObExecContext& ctx, ObSplitResourcePoolStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObSplitResourcePoolArg& split_resource_pool_arg = stmt.get_arg();
if (NULL == (task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed", K(ret));
} else if (NULL == (common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get common rpc proxy failed", K(ret));
} else if (OB_SUCCESS != (ret = common_rpc_proxy->split_resource_pool(split_resource_pool_arg))) {
SQL_ENG_LOG(WARN, "send split resource pool failed", K(ret));
}
return ret;
}
ObMergeResourcePoolExecutor::ObMergeResourcePoolExecutor()
{}
ObMergeResourcePoolExecutor::~ObMergeResourcePoolExecutor()
{}
int ObMergeResourcePoolExecutor::execute(ObExecContext& ctx, ObMergeResourcePoolStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObMergeResourcePoolArg& merge_resource_pool_arg = stmt.get_arg();
if (NULL == (task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (NULL == (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_SUCCESS != (ret = common_rpc_proxy->merge_resource_pool(merge_resource_pool_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy merge resource_pool failed", K(ret));
}
return ret;
}
ObDropResourcePoolExecutor::ObDropResourcePoolExecutor()
{}
ObDropResourcePoolExecutor::~ObDropResourcePoolExecutor()
{}
int ObDropResourcePoolExecutor::execute(ObExecContext& ctx, ObDropResourcePoolStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObDropResourcePoolArg& drop_resource_pool_arg = stmt.get_arg();
if (NULL == (task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (NULL == (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_SUCCESS != (ret = common_rpc_proxy->drop_resource_pool(drop_resource_pool_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy drop resource_pool failed", K(ret));
}
return ret;
}
ObCreateResourceUnitExecutor::ObCreateResourceUnitExecutor()
{}
ObCreateResourceUnitExecutor::~ObCreateResourceUnitExecutor()
{}
int ObCreateResourceUnitExecutor::execute(ObExecContext& ctx, ObCreateResourceUnitStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObCreateResourceUnitArg& create_resource_unit_arg = stmt.get_arg();
if (NULL == (task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (NULL == (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_SUCCESS != (ret = common_rpc_proxy->create_resource_unit(create_resource_unit_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy create resource_unit failed", K(ret));
}
return ret;
}
ObAlterResourceUnitExecutor::ObAlterResourceUnitExecutor()
{}
ObAlterResourceUnitExecutor::~ObAlterResourceUnitExecutor()
{}
int ObAlterResourceUnitExecutor::execute(ObExecContext& ctx, ObAlterResourceUnitStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObAlterResourceUnitArg& alter_resource_unit_arg = stmt.get_arg();
if (NULL == (task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (NULL == (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_SUCCESS != (ret = common_rpc_proxy->alter_resource_unit(alter_resource_unit_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy alter resource_unit failed", K(ret));
}
return ret;
}
ObDropResourceUnitExecutor::ObDropResourceUnitExecutor()
{}
ObDropResourceUnitExecutor::~ObDropResourceUnitExecutor()
{}
int ObDropResourceUnitExecutor::execute(ObExecContext& ctx, ObDropResourceUnitStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObDropResourceUnitArg& drop_resource_unit_arg = stmt.get_arg();
if (NULL == (task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
SQL_ENG_LOG(WARN, "get task executor context failed");
} else if (NULL == (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_SUCCESS != (ret = common_rpc_proxy->drop_resource_unit(drop_resource_unit_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy drop resource_unit failed", K(ret));
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,102 @@
/**
* 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.
*/
#ifndef __OB_SQL_RESOURCE_EXECUTOR_H__
#define __OB_SQL_RESOURCE_EXECUTOR_H__
namespace oceanbase {
namespace sql {
class ObExecContext;
class ObCreateResourcePoolStmt;
class ObDropResourcePoolStmt;
class ObSplitResourcePoolStmt;
class ObMergeResourcePoolStmt;
class ObAlterResourcePoolStmt;
class ObCreateResourceUnitStmt;
class ObAlterResourceUnitStmt;
class ObDropResourceUnitStmt;
class ObCreateResourcePoolExecutor {
public:
ObCreateResourcePoolExecutor();
virtual ~ObCreateResourcePoolExecutor();
int execute(ObExecContext& ctx, ObCreateResourcePoolStmt& stmt);
private:
};
class ObDropResourcePoolExecutor {
public:
ObDropResourcePoolExecutor();
virtual ~ObDropResourcePoolExecutor();
int execute(ObExecContext& ctx, ObDropResourcePoolStmt& stmt);
private:
};
class ObSplitResourcePoolExecutor {
public:
ObSplitResourcePoolExecutor();
virtual ~ObSplitResourcePoolExecutor();
int execute(ObExecContext& ctx, ObSplitResourcePoolStmt& stmt);
private:
};
class ObMergeResourcePoolExecutor {
public:
ObMergeResourcePoolExecutor();
virtual ~ObMergeResourcePoolExecutor();
int execute(ObExecContext& ctx, ObMergeResourcePoolStmt& stmt);
private:
};
class ObAlterResourcePoolExecutor {
public:
ObAlterResourcePoolExecutor();
virtual ~ObAlterResourcePoolExecutor();
int execute(ObExecContext& ctx, ObAlterResourcePoolStmt& stmt);
private:
};
class ObCreateResourceUnitExecutor {
public:
ObCreateResourceUnitExecutor();
virtual ~ObCreateResourceUnitExecutor();
int execute(ObExecContext& ctx, ObCreateResourceUnitStmt& stmt);
private:
};
class ObAlterResourceUnitExecutor {
public:
ObAlterResourceUnitExecutor();
virtual ~ObAlterResourceUnitExecutor();
int execute(ObExecContext& ctx, ObAlterResourceUnitStmt& stmt);
private:
};
class ObDropResourceUnitExecutor {
public:
ObDropResourceUnitExecutor();
virtual ~ObDropResourceUnitExecutor();
int execute(ObExecContext& ctx, ObDropResourceUnitStmt& stmt);
private:
};
} // namespace sql
} // namespace oceanbase
#endif /* __OB_SQL_RESOURCE_EXECUTOR_H__ */
//// end of header file

View File

@ -0,0 +1,91 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "share/ob_common_rpc_proxy.h"
#include "sql/resolver/cmd/ob_alter_system_stmt.h"
#include "sql/engine/cmd/ob_restore_executor.h"
#include "sql/engine/ob_exec_context.h"
namespace oceanbase {
using namespace common;
using namespace share::schema;
namespace sql {
ObRestoreTenantExecutor::ObRestoreTenantExecutor()
{}
ObRestoreTenantExecutor::~ObRestoreTenantExecutor()
{}
int ObRestoreTenantExecutor::execute(ObExecContext& ctx, ObRestoreTenantStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObRestoreTenantArg& restore_tenant_arg = stmt.get_rpc_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObRestoreTenantArg&>(restore_tenant_arg).sql_text_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->restore_tenant(restore_tenant_arg))) {
LOG_WARN("rpc proxy restore tenant failed", K(ret), "dst", common_rpc_proxy->get_server());
}
return ret;
}
ObPhysicalRestoreTenantExecutor::ObPhysicalRestoreTenantExecutor()
{}
ObPhysicalRestoreTenantExecutor::~ObPhysicalRestoreTenantExecutor()
{}
int ObPhysicalRestoreTenantExecutor::execute(ObExecContext& ctx, ObPhysicalRestoreTenantStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObPhysicalRestoreTenantArg& restore_tenant_arg = stmt.get_rpc_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObPhysicalRestoreTenantArg&>(restore_tenant_arg).sql_text_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->physical_restore_tenant(restore_tenant_arg))) {
LOG_WARN("rpc proxy restore tenant failed", K(ret), "dst", common_rpc_proxy->get_server());
}
return ret;
}
} // end namespace sql
} // end namespace oceanbase

View File

@ -0,0 +1,38 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_OB_RESTORE_EXECUTOR_
#define OCEANBASE_SQL_OB_RESTORE_EXECUTOR_
namespace oceanbase {
namespace sql {
class ObExecContext;
class ObRestoreTenantStmt;
class ObPhysicalRestoreTenantStmt;
class ObRestoreTenantExecutor {
public:
ObRestoreTenantExecutor();
virtual ~ObRestoreTenantExecutor();
int execute(ObExecContext& ctx, ObRestoreTenantStmt& stmt);
};
class ObPhysicalRestoreTenantExecutor {
public:
ObPhysicalRestoreTenantExecutor();
virtual ~ObPhysicalRestoreTenantExecutor();
int execute(ObExecContext& ctx, ObPhysicalRestoreTenantStmt& stmt);
};
} // end namespace sql
} // end namespace oceanbase
#endif // OCEANBASE_SQL_OB_RESTORE_EXECUTOR_

View File

@ -0,0 +1,125 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_role_cmd_executor.h"
#include "lib/encrypt/ob_encrypted_helper.h"
#include "lib/string/ob_sql_string.h"
#include "share/schema/ob_schema_struct.h"
#include "share/ob_rpc_struct.h"
#include "share/ob_common_rpc_proxy.h"
#include "sql/resolver/dcl/ob_create_role_stmt.h"
#include "sql/resolver/dcl/ob_drop_role_stmt.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/engine/cmd/ob_user_cmd_executor.h"
namespace oceanbase {
using namespace common;
using namespace obrpc;
using namespace share::schema;
namespace sql {
int ObCreateRoleExecutor::execute(ObExecContext& ctx, ObCreateRoleStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const uint64_t tenant_id = stmt.get_tenant_id();
const ObString& role_name = stmt.get_role_name();
const ObString& pwd = stmt.get_password();
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else {
ObCreateUserArg arg;
arg.tenant_id_ = tenant_id;
arg.exec_tenant_id_ = tenant_id;
ObSQLSessionInfo* mysession = ctx.get_my_session();
if (OB_ISNULL(mysession)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get myssion", K(ret));
} else {
arg.creator_id_ = mysession->get_user_id();
}
ObUserInfo user_info;
user_info.set_tenant_id(tenant_id);
user_info.set_type(OB_ROLE);
user_info.set_host(OB_DEFAULT_HOST_NAME);
ObSArray<int64_t> failed_index;
ObString pwd_enc;
if (pwd.length() > 0) {
char enc_buf[ENC_BUF_LEN] = {0};
// user general encrypt of ob
if (OB_FAIL(ObCreateUserExecutor::encrypt_passwd(pwd, pwd_enc, enc_buf, ENC_BUF_LEN))) {
LOG_WARN("Encrypt password failed", K(ret));
} else if (OB_FAIL(user_info.set_passwd(pwd_enc))) {
LOG_WARN("set password failed", K(ret));
}
} else if (OB_FAIL(user_info.set_passwd(pwd_enc))) {
LOG_WARN("Failed to set password", K(ret));
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(user_info.set_user_name(role_name))) {
LOG_WARN("set user name failed", K(ret));
} else if (OB_FAIL(arg.user_infos_.push_back(user_info))) {
LOG_WARN("Add user info to array error", K(ret));
} else if (OB_FAIL(common_rpc_proxy->create_user(arg, failed_index))) {
LOG_WARN("Create user error", K(ret));
}
}
return ret;
}
int ObDropRoleExecutor::execute(ObExecContext& ctx, ObDropRoleStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const uint64_t tenant_id = stmt.get_tenant_id();
if (OB_INVALID_ID == tenant_id) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("tenant is invalid", K(ret));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed", K(ret));
} else if (NULL == (common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed", K(ret));
} else {
ObDropUserArg& arg = static_cast<ObDropUserArg&>(stmt.get_ddl_arg());
arg.tenant_id_ = tenant_id;
arg.exec_tenant_id_ = tenant_id;
arg.is_role_ = true;
const ObString& role_name = stmt.get_role_name();
ObString host_name(OB_DEFAULT_HOST_NAME);
ObSArray<int64_t> failed_index;
if (OB_FAIL(arg.users_.push_back(role_name))) {
LOG_WARN("Add user name failed", K(ret));
} else if (OB_FAIL(arg.hosts_.push_back(host_name))) {
LOG_WARN("Add host name failed", K(ret));
} else if (OB_FAIL(common_rpc_proxy->drop_user(arg, failed_index)) || (0 != failed_index.count())) {
LOG_WARN("drop role failed", K(ret), K(role_name));
// ret = OB_CANNOT_USER;
// LOG_USER_ERROR(ret, strlen("DROP ROLE"), "DROP ROLE", role_name.length(), role_name.ptr());
}
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,66 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_CMD_ROLE_CMD_EXECUTOR_
#define OCEANBASE_SQL_ENGINE_CMD_ROLE_CMD_EXECUTOR_
#include "lib/string/ob_string.h"
#include "lib/container/ob_array_serialization.h"
#include "share/schema/ob_schema_struct.h"
namespace oceanbase {
namespace obrpc {
class ObCommonRpcProxy;
class ObCreateRoleArg;
class ObDropUserArg;
} // namespace obrpc
namespace sql {
class ObExecContext;
class ObCreateRoleStmt;
class ObDropRoleStmt;
class ObCreateRoleExecutor {
public:
ObCreateRoleExecutor()
{}
virtual ~ObCreateRoleExecutor()
{}
int execute(ObExecContext& ctx, ObCreateRoleStmt& stmt);
static int encrypt_passwd(
const common::ObString& passwd, common::ObString& encrypted_passwd, char* enc_buf, int64_t buf_len);
private:
int create_role(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObCreateRoleArg& arg) const;
int drop_role(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObDropUserArg& arg) const;
private:
DISALLOW_COPY_AND_ASSIGN(ObCreateRoleExecutor);
};
class ObDropRoleExecutor {
public:
ObDropRoleExecutor()
{}
virtual ~ObDropRoleExecutor()
{}
int execute(ObExecContext& ctx, ObDropRoleStmt& stmt);
static int encrypt_passwd(
const common::ObString& passwd, common::ObString& encrypted_passwd, char* enc_buf, int64_t buf_len);
private:
int drop_role(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObDropUserArg& arg) const;
private:
DISALLOW_COPY_AND_ASSIGN(ObDropRoleExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif // OCEANBASE_SQL_ENGINE_CMD_USER_CMD_EXECUTOR_

View File

@ -0,0 +1,57 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_sequence_executor.h"
#include "share/ob_common_rpc_proxy.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/resolver/ddl/ob_sequence_stmt.h"
#include "sql/engine/ob_exec_context.h"
namespace oceanbase {
using namespace common;
using namespace share;
namespace sql {
#define DEF_SIMPLE_EXECUTOR_IMPL(name, func) \
int name##Executor::execute(ObExecContext& ctx, name##Stmt& stmt) \
{ \
int ret = OB_SUCCESS; \
ObTaskExecutorCtx* task_exec_ctx = NULL; \
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL; \
const obrpc::ObSequenceDDLArg& sequence_arg = stmt.get_arg(); \
ObString first_stmt; \
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) { \
LOG_WARN("fail to get first stmt", K(ret)); \
} else { \
const_cast<obrpc::ObSequenceDDLArg&>(sequence_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; \
LOG_WARN("get task executor context failed"); \
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) { \
ret = OB_NOT_INIT; \
LOG_WARN("get common rpc proxy failed"); \
} else if (OB_FAIL(common_rpc_proxy->func(sequence_arg))) { \
LOG_WARN("rpc proxy failed", K(sequence_arg), K(ret)); \
} \
return ret; \
}
DEF_SIMPLE_EXECUTOR_IMPL(ObCreateSequence, do_sequence_ddl);
DEF_SIMPLE_EXECUTOR_IMPL(ObAlterSequence, do_sequence_ddl);
DEF_SIMPLE_EXECUTOR_IMPL(ObDropSequence, do_sequence_ddl);
#undef DEF_EXECUTOR_IMPL
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,44 @@
/**
* 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.
*/
#ifndef __OB_SQL_SEQUENCE_EXECUTOR_H__
#define __OB_SQL_SEQUENCE_EXECUTOR_H__
#include "share/ob_define.h"
namespace oceanbase {
namespace sql {
#define DEF_SIMPLE_EXECUTOR(name) \
class name##Executor { \
public: \
name##Executor() \
{} \
virtual ~name##Executor() \
{} \
int execute(ObExecContext& ctx, name##Stmt& stmt); \
\
private: \
DISALLOW_COPY_AND_ASSIGN(name##Executor); \
}
class ObExecContext;
class ObCreateSequenceStmt;
class ObDropSequenceStmt;
class ObAlterSequenceStmt;
DEF_SIMPLE_EXECUTOR(ObCreateSequence);
DEF_SIMPLE_EXECUTOR(ObDropSequence);
DEF_SIMPLE_EXECUTOR(ObAlterSequence);
#undef DEF_SIMPLE_EXECUTOR
} // namespace sql
} // namespace oceanbase
#endif /* __OB_SQL_SEQUENCE_EXECUTOR_H__ */
//// end of header file

View File

@ -0,0 +1,180 @@
/**
* 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_set_names_executor.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/engine/ob_exec_context.h"
#include "lib/string/ob_sql_string.h"
#include "share/inner_table/ob_inner_table_schema.h"
#include "observer/ob_server_struct.h"
using namespace oceanbase::sql;
using namespace oceanbase::common;
using namespace oceanbase::share;
using namespace oceanbase::share::schema;
int ObSetNamesExecutor::execute(ObExecContext& ctx, ObSetNamesStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session = NULL;
if (NULL == (session = ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "session is NULL", K(ret), K(ctx));
} else {
ObString charset;
if (stmt.is_default_charset()) {
// Compatible with mysql, take the global character_set_client value
if (OB_FAIL(get_global_sys_var_character_set_client(ctx, charset))) {
SQL_ENG_LOG(WARN, "fail to get global character_set_client", K(ret));
}
} else {
charset = stmt.get_charset();
}
if (OB_SUCC(ret)) {
ObString collation = stmt.get_collation();
ObCollationType collation_type = CS_TYPE_INVALID;
ObCharsetType cs_type = ObCharset::charset_type(charset);
if (CHARSET_INVALID == cs_type) {
ret = OB_ERR_UNKNOWN_CHARSET;
LOG_USER_ERROR(OB_ERR_UNKNOWN_CHARSET, charset.length(), charset.ptr());
} else {
charset = ObString::make_string(ObCharset::charset_name(cs_type));
if (stmt.is_default_collation() || !collation.empty()) {
collation_type = ObCharset::collation_type(collation);
if (CS_TYPE_INVALID == collation_type) {
ret = OB_ERR_UNKNOWN_COLLATION;
LOG_USER_ERROR(OB_ERR_UNKNOWN_COLLATION, collation.length(), collation.ptr());
} else if (!ObCharset::is_valid_collation(cs_type, collation_type)) {
ret = OB_ERR_COLLATION_MISMATCH;
LOG_USER_ERROR(
OB_ERR_COLLATION_MISMATCH, collation.length(), collation.ptr(), charset.length(), charset.ptr());
} else {
collation = ObString::make_string(ObCharset::collation_name(collation_type));
}
} else {
// the use default collation of this charset
collation_type = ObCharset::get_default_collation(cs_type);
collation = ObString::make_string(ObCharset::collation_name(collation_type));
}
}
if (OB_SUCC(ret)) {
if (!ObCharset::is_valid_connection_collation(collation_type)) {
ret = OB_NOT_SUPPORTED;
SQL_ENG_LOG(WARN,
"collation type not supported",
"charset type",
ObCharset::charset_name(cs_type),
"collation type",
ObCharset::collation_name(collation_type));
}
}
if (OB_SUCC(ret)) {
if (stmt.is_set_names()) {
// SET NAMES
ObCollationType cs_coll_type = ObCharset::get_default_collation(ObCharset::charset_type(charset));
ObCollationType coll_type = ObCharset::collation_type(collation);
if (CS_TYPE_INVALID == cs_coll_type || CS_TYPE_INVALID == coll_type) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "cs coll type or coll type is invalid", K(ret), K(cs_coll_type), K(coll_type));
} else if (OB_FAIL(session->update_sys_variable(
SYS_VAR_CHARACTER_SET_CLIENT, static_cast<int64_t>(cs_coll_type)))) {
SQL_ENG_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(
SYS_VAR_CHARACTER_SET_RESULTS, static_cast<int64_t>(cs_coll_type)))) {
SQL_ENG_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(
SYS_VAR_CHARACTER_SET_CONNECTION, static_cast<int64_t>(cs_coll_type)))) {
SQL_ENG_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(
session->update_sys_variable(SYS_VAR_COLLATION_CONNECTION, static_cast<int64_t>(coll_type)))) {
SQL_ENG_LOG(WARN, "failed to update sys var", K(ret));
}
} else {
// SET CHARACTER SET
ObObj database_charset;
ObObj database_collation;
ObCollationType cs_coll_type = ObCharset::get_default_collation(ObCharset::charset_type(charset));
if (OB_FAIL(session->get_sys_variable(SYS_VAR_CHARACTER_SET_DATABASE, database_charset))) {
} else if (OB_FAIL(session->get_sys_variable(SYS_VAR_COLLATION_DATABASE, database_collation))) {
} else {
ObCollationType collation_connection = static_cast<ObCollationType>(database_collation.get_int());
ObCharsetType charset_connection = ObCharset::charset_type_by_coll(collation_connection);
if (!ObCharset::is_valid_connection_collation(collation_connection)) {
ret = OB_NOT_SUPPORTED;
SQL_ENG_LOG(WARN,
"connection collation type not supported",
"charset type",
ObCharset::charset_name(charset_connection),
"collation type",
ObCharset::collation_name(collation_connection));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(
session->update_sys_variable(SYS_VAR_CHARACTER_SET_CLIENT, static_cast<int64_t>(cs_coll_type)))) {
SQL_EXE_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(
SYS_VAR_CHARACTER_SET_RESULTS, static_cast<int64_t>(cs_coll_type)))) {
SQL_EXE_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_CHARACTER_SET_CONNECTION, database_charset))) {
SQL_EXE_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_COLLATION_CONNECTION, database_collation))) {
SQL_EXE_LOG(WARN, "failed to update sys var", K(ret));
}
}
}
}
}
}
return ret;
}
int ObSetNamesExecutor::get_global_sys_var_character_set_client(
ObExecContext& ctx, ObString& character_set_client) const
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session = NULL;
ObIAllocator& allocator = ctx.get_allocator();
ObSchemaGetterGuard schema_guard;
const ObSysVarSchema* var_schema = NULL;
ObObj value;
if (NULL == (session = ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "session is NULL", K(ret), K(ctx));
} else if (OB_ISNULL(GCTX.schema_service_)) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "schema service is null");
} else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(session->get_effective_tenant_id(), schema_guard))) {
SQL_ENG_LOG(WARN, "get schema guard failed", K(ret));
} else if (OB_FAIL(schema_guard.get_tenant_system_variable(
session->get_effective_tenant_id(), SYS_VAR_CHARACTER_SET_CLIENT, var_schema))) {
SQL_ENG_LOG(WARN, "get tenant system variable failed", K(ret));
} else if (OB_ISNULL(var_schema)) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "var_schema is null");
} else if (OB_FAIL(var_schema->get_value(&allocator, ObBasicSessionInfo::create_dtc_params(session), value))) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "get value from var_schema failed", K(ret), K(*var_schema));
} else if (ObIntType != value.get_type()) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "sys var character_set_client's type must be ObIntType", K(ret), K(value));
} else {
ObCollationType coll_type = static_cast<ObCollationType>(value.get_int());
if (!ObCharset::is_valid_collation(coll_type)) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "invalid collation type", K(ret), K(coll_type));
} else {
const char* cs_name_ptr = ObCharset::charset_name(coll_type);
character_set_client = ObString(cs_name_ptr);
}
}
return ret;
}

View File

@ -0,0 +1,42 @@
/**
* 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.
*/
#ifndef _OB_SET_NAMES_EXECUTOR_H
#define _OB_SET_NAMES_EXECUTOR_H 1
#include "sql/resolver/cmd/ob_set_names_stmt.h"
namespace oceanbase {
namespace sql {
class ObExecContext;
class ObSetNamesExecutor {
public:
ObSetNamesExecutor()
{}
virtual ~ObSetNamesExecutor()
{}
int execute(ObExecContext& ctx, ObSetNamesStmt& stmt);
private:
int get_global_sys_var_character_set_client(ObExecContext& ctx, common::ObString& character_set_client) const;
private:
// disallow copy
DISALLOW_COPY_AND_ASSIGN(ObSetNamesExecutor);
// function members
private:
// data members
};
} // end namespace sql
} // end namespace oceanbase
#endif /* _OB_SET_NAMES_EXECUTOR_H */

View File

@ -0,0 +1,122 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_set_password_executor.h"
#include "lib/string/ob_sql_string.h"
#include "lib/encrypt/ob_encrypted_helper.h"
#include "share/ob_rpc_struct.h"
#include "share/ob_common_rpc_proxy.h"
#include "share/schema/ob_schema_struct.h"
#include "sql/resolver/dcl/ob_set_password_stmt.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/engine/cmd/ob_user_cmd_executor.h"
namespace oceanbase {
using namespace common;
using namespace obrpc;
using namespace share;
using namespace share::schema;
namespace sql {
ObSetPasswordExecutor::ObSetPasswordExecutor()
{}
ObSetPasswordExecutor::~ObSetPasswordExecutor()
{}
int ObSetPasswordExecutor::execute(ObExecContext& ctx, ObSetPasswordStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session = NULL;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const uint64_t tenant_id = stmt.get_tenant_id();
const common::ObStrings* user_passwd = NULL;
const int64_t FIX_MEMBER_CNT = 7;
if (OB_ISNULL(session = ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session is NULL", K(ret));
} else if (OB_UNLIKELY(OB_INVALID_ID == tenant_id)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("tenant is invalid", K(ret));
} else if (OB_ISNULL(user_passwd = stmt.get_user_password())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("user_passwd is null", K(ret));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("task_exec_ctx is null", K(ret));
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("common_rpc_proxy is null", K(ret));
} else if (OB_UNLIKELY(FIX_MEMBER_CNT != user_passwd->count())) {
ret = OB_ERR_UNEXPECTED;
;
LOG_WARN("invalid set pwd stmt, wrong user passwd count", K(ret));
} else {
ObString user_name;
ObString host_name;
ObString passwd;
ObString ssl_type;
ObString ssl_cipher;
ObString x509_issuer;
ObString x509_subject;
ObSSLType ssl_type_enum = ObSSLType::SSL_TYPE_NOT_SPECIFIED;
if (OB_FAIL(user_passwd->get_string(0, user_name))) {
LOG_WARN("Get user name failed", K(ret));
} else if (OB_FAIL(user_passwd->get_string(1, host_name))) {
LOG_WARN("Get passwd failed", K(ret));
} else if (OB_FAIL(user_passwd->get_string(2, passwd))) {
LOG_WARN("Get passwd failed", K(ret));
} else if (OB_FAIL(user_passwd->get_string(3, ssl_type))) {
LOG_WARN("Get string from ObStrings error", K(ret));
} else if (OB_FAIL(user_passwd->get_string(4, ssl_cipher))) {
LOG_WARN("Get string from ObStrings error", K(ret));
} else if (OB_FAIL(user_passwd->get_string(5, x509_issuer))) {
LOG_WARN("Get string from ObStrings error", K(ret));
} else if (OB_FAIL(user_passwd->get_string(6, x509_subject))) {
LOG_WARN("Get string from ObStrings error", K(ret));
} else if (OB_UNLIKELY(ObSSLType::SSL_TYPE_MAX == (ssl_type_enum = get_ssl_type_from_string(ssl_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("known ssl_type", K(ssl_type), K(ret));
} else {
char enc_buf[ENC_BUF_LEN] = {0};
ObSetPasswdArg arg;
arg.tenant_id_ = tenant_id;
arg.user_ = user_name;
arg.host_ = host_name;
arg.ssl_type_ = ssl_type_enum;
arg.ssl_cipher_ = ssl_cipher;
arg.x509_issuer_ = x509_issuer;
arg.x509_subject_ = x509_subject;
arg.exec_tenant_id_ = tenant_id;
if (stmt.get_need_enc()) {
if (OB_FAIL(ObCreateUserExecutor::encrypt_passwd(passwd, arg.passwd_, enc_buf, ENC_BUF_LEN))) {
LOG_WARN("Encrypt passwd failed", K(ret));
}
} else {
arg.passwd_ = passwd;
}
if (OB_SUCC(ret) && OB_FAIL(common_rpc_proxy->set_passwd(arg))) {
LOG_WARN("Set password failed", K(ret));
} else if (0 == user_name.case_compare(session->get_user_name())) {
session->set_password_expired(false);
}
}
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,39 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_SET_PASSWORD_EXECUTOR_
#define OCEANBASE_SQL_SET_PASSWORD_EXECUTOR_
namespace oceanbase {
namespace common {
class ObString;
class ObSqlString;
} // namespace common
namespace obrpc {
class ObCommonRpcProxy;
}
namespace sql {
class ObExecContext;
class ObSetPasswordStmt;
class ObSetPasswordExecutor {
public:
ObSetPasswordExecutor();
virtual ~ObSetPasswordExecutor();
int execute(ObExecContext& ctx, ObSetPasswordStmt& stmt);
};
} // namespace sql
} // namespace oceanbase
#endif /* __OB_SQL_SET_PASSWORD_EXECUTOR_H__ */
//// end of header file

View File

@ -0,0 +1,84 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_synonym_executor.h"
#include "share/object/ob_obj_cast.h"
#include "lib/mysqlclient/ob_mysql_proxy.h"
#include "share/ob_common_rpc_proxy.h"
#include "sql/resolver/ddl/ob_create_synonym_stmt.h"
#include "sql/resolver/ddl/ob_drop_synonym_stmt.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/engine/ob_physical_plan.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/code_generator/ob_expr_generator_impl.h"
namespace oceanbase {
using namespace common;
using namespace share::schema;
namespace sql {
int ObCreateSynonymExecutor::execute(ObExecContext& ctx, ObCreateSynonymStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObCreateSynonymArg& create_synonym_arg = stmt.get_create_synonym_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObCreateSynonymArg&>(create_synonym_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;
LOG_WARN("get task executor context failed", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->create_synonym(create_synonym_arg))) {
LOG_WARN("rpc proxy create synonym failed", K(ret), "dst", common_rpc_proxy->get_server());
}
return ret;
}
int ObDropSynonymExecutor::execute(ObExecContext& ctx, ObDropSynonymStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObDropSynonymArg& drop_synonym_arg = stmt.get_drop_synonym_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObDropSynonymArg&>(drop_synonym_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;
LOG_WARN("get task executor context failed", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->drop_synonym(drop_synonym_arg))) {
LOG_WARN("rpc proxy drop synonym failed", K(ret), "dst", common_rpc_proxy->get_server());
}
return ret;
}
} // end namespace sql
} // end namespace oceanbase

View File

@ -0,0 +1,58 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_OB_SYNONYM_EXECUTOR_
#define OCEANBASE_SQL_OB_SYNONYM_EXECUTOR_
#include "common/object/ob_object.h"
#include "lib/container/ob_se_array.h"
namespace oceanbase {
namespace common {
class ObIAllocator;
class ObExprCtx;
namespace sqlclient {
class ObMySQLProxy;
}
} // namespace common
namespace sql {
class ObExecContext;
class ObRawExpr;
class ObCreateSynonymStmt;
class ObCreateSynonymExecutor {
public:
const static int OB_DEFAULT_ARRAY_SIZE = 16;
ObCreateSynonymExecutor()
{}
virtual ~ObCreateSynonymExecutor()
{}
int execute(ObExecContext& ctx, ObCreateSynonymStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObCreateSynonymExecutor);
};
class ObDropSynonymStmt;
class ObDropSynonymExecutor {
public:
ObDropSynonymExecutor()
{}
virtual ~ObDropSynonymExecutor()
{}
int execute(ObExecContext& ctx, ObDropSynonymStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObDropSynonymExecutor);
};
} // end namespace sql
} // end namespace oceanbase
#endif // OCEANBASE_SQL_OB_SYNONYM_EXECUTOR_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,311 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_OB_TABLE_EXECUTOR_
#define OCEANBASE_SQL_OB_TABLE_EXECUTOR_
#include "common/object/ob_object.h"
#include "lib/container/ob_se_array.h"
#include "common/sql_mode/ob_sql_mode.h"
#include "lib/string/ob_sql_string.h"
#include "share/ob_rpc_struct.h"
namespace oceanbase {
namespace share {
namespace schema {
class ObPartition;
class ObSubPartition;
class ObBasePartition;
class ObMultiVersionSchemaService;
} // namespace schema
} // namespace share
namespace obrpc {
class ObAlterTableArg;
}
namespace common {
class ObIAllocator;
class ObExprCtx;
class ObNewRow;
namespace sqlclient {
class ObMySQLProxy;
}
} // namespace common
namespace sql {
class ObExecContext;
class ObRawExpr;
class ObCreateTableStmt;
class ObTableStmt;
class ObTableExecutorUtils {
public:
static int get_first_stmt(
const common::ObString& stmt, common::ObString& first_stmt, ObSQLMode sql_mode = DEFAULT_OCEANBASE_MODE);
};
class ObCreateTableExecutor {
public:
ObCreateTableExecutor();
virtual ~ObCreateTableExecutor();
int execute(ObExecContext& ctx, ObCreateTableStmt& stmt);
int set_index_arg_list(ObExecContext& ctx, ObCreateTableStmt& stmt);
int execute_ctas(ObExecContext& ctx, ObCreateTableStmt& stmt, obrpc::ObCommonRpcProxy* common_rpc_proxy);
private:
int prepare_ins_arg(ObCreateTableStmt& stmt, const ObSQLSessionInfo* my_session, ObSqlString& ins_sql);
int prepare_alter_arg(
ObCreateTableStmt& stmt, const ObSQLSessionInfo* my_session, obrpc::ObAlterTableArg& alter_table_arg);
int prepare_drop_arg(const ObCreateTableStmt& stmt, const ObSQLSessionInfo* my_session,
obrpc::ObTableItem& table_item, obrpc::ObDropTableArg& drop_table_arg);
};
class ObAlterTableStmt;
class ObAlterTableExecutor {
public:
ObAlterTableExecutor();
virtual ~ObAlterTableExecutor();
int execute(ObExecContext& ctx, ObAlterTableStmt& stmt);
private:
struct PartitionServer {
PartitionServer() : pkey_(), server_()
{}
void reset()
{
pkey_.reset();
server_.reset();
}
TO_STRING_KV(K(pkey_), K(server_));
int set_server(const common::ObAddr& server)
{
int ret = common::OB_SUCCESS;
if (!server.is_valid()) {
ret = common::OB_INVALID_ARGUMENT;
RS_LOG(WARN, "invalid argument", K(ret), K(server));
} else {
server_ = server;
}
return ret;
}
int set_partition_key(const common::ObPartitionKey& pkey)
{
int ret = common::OB_SUCCESS;
if (!pkey.is_valid()) {
ret = common::OB_INVALID_ARGUMENT;
RS_LOG(WARN, "invalid argument", K(ret), K(pkey));
} else {
pkey_ = pkey;
}
return ret;
}
int set(const common::ObAddr& server, common::ObPartitionKey& pkey)
{
int ret = common::OB_SUCCESS;
if (!server.is_valid() || !pkey.is_valid()) {
ret = common::OB_INVALID_ARGUMENT;
RS_LOG(WARN, "invalid argument", K(ret), K(server), K(pkey));
} else {
server_ = server;
pkey_ = pkey;
}
return ret;
}
int set(
const common::ObAddr& server, const uint64_t table_id, const int64_t partition_id, const int64_t partition_cnt)
{
int ret = common::OB_SUCCESS;
if (!server.is_valid()) {
ret = common::OB_INVALID_ARGUMENT;
RS_LOG(WARN, "invalid argument", K(ret), K(server));
} else if (OB_FAIL(pkey_.init(table_id, partition_id, partition_cnt))) {
RS_LOG(WARN, "fail to init pkey", K(ret), K(table_id), K(partition_id), K(partition_cnt));
} else {
server_ = server;
}
return ret;
}
common::ObPartitionKey pkey_;
common::ObAddr server_;
};
static const int64_t TIME_INTERVAL_PER_PART_US = 50 * 1000; // 50ms
static const int64_t MAX_WAIT_CHECK_SCHEMA_VERSION_INTERVAL_US = 120LL * 1000000LL; // 120s
static const int64_t MIN_WAIT_CHECK_SCHEMA_VERSION_INTERVAL_US = 20LL * 1000000LL; // 20s
static const int64_t WAIT_US = 500 * 1000; // 500ms
static const int64_t GET_ASSOCIATED_SNAPSHOT_TIMEOUT = 9000000LL; // 9s
int alter_table_rpc_v1(obrpc::ObAlterTableArg& alter_table_arg, obrpc::ObAlterTableRes& res,
common::ObIAllocator& allocator, obrpc::ObCommonRpcProxy* common_rpc_proxy, ObSQLSessionInfo* my_session,
const bool is_sync_ddl_user);
int alter_table_rpc_v2(obrpc::ObAlterTableArg& alter_table_arg, obrpc::ObAlterTableRes& res,
common::ObIAllocator& allocator, obrpc::ObCommonRpcProxy* common_rpc_proxy, ObSQLSessionInfo* my_session,
const bool is_sync_ddl_user);
int set_alter_col_nullable_ddl_stmt_str(obrpc::ObAlterTableArg& alter_table_arg, common::ObIAllocator& allocator);
int set_drop_constraint_ddl_stmt_str(obrpc::ObAlterTableArg& alter_table_arg, common::ObIAllocator& allocator);
int set_alter_constraint_ddl_stmt_str_for_check(
obrpc::ObAlterTableArg& alter_table_arg, common::ObIAllocator& allocator);
int set_alter_constraint_ddl_stmt_str_for_fk(
obrpc::ObAlterTableArg& alter_table_arg, common::ObIAllocator& allocator);
int init_build_snapshot_ctx(const common::ObIArray<PartitionServer>& partition_leader_array,
common::ObIArray<int64_t>& invalid_snapshot_id_array, common::ObIArray<int64_t>& snapshot_array);
int generate_original_table_partition_leader_array(ObExecContext& ctx,
share::schema::ObSchemaGetterGuard& schema_guard, const share::schema::ObTableSchema* data_schema,
common::ObIArray<PartitionServer>& partition_leader_array);
int update_partition_leader_array(common::ObIArray<PartitionServer>& partition_leader_array,
const common::ObIArray<int>& ret_code_array, const common::ObIArray<int64_t>& invalid_snapshot_id_array);
int pick_build_snapshot(const common::ObIArray<int64_t>& snapshot_array, int64_t& snapshot);
template <typename PROXY>
int update_build_snapshot_ctx(PROXY& proxy, const common::ObIArray<int>& ret_code_array,
common::ObIArray<int64_t>& invalid_snapshot_id_array, common::ObIArray<int64_t>& snapshot_array);
template <typename PROXY, typename ARG>
int do_get_associated_snapshot(PROXY& rpc_proxy, ARG& rpc_arg, int64_t schema_version,
const share::schema::ObTableSchema* data_schema, common::ObIArray<PartitionServer>& partition_leader_array,
int64_t& snapshot);
int get_constraint_check_snapshot(ObExecContext& ctx, int64_t schema_version,
share::schema::ObSchemaGetterGuard& schema_guard, const uint64_t table_id, int64_t& snapshot);
int check_data_validity_for_check_by_inner_sql(const share::schema::AlterTableSchema& alter_table_schema,
ObCommonSqlProxy* sql_proxy, const ObString& check_expr_str, bool& is_data_valid);
int check_check_constraint_data_validity(ObExecContext& ctx, const obrpc::ObAlterTableArg& alter_table_arg,
ObCommonSqlProxy* sql_proxy, int64_t schema_version, const ObString& check_expr_str, bool& is_data_valid);
int check_data_validity_for_fk_by_inner_sql(const share::schema::AlterTableSchema& alter_table_schema,
const obrpc::ObCreateForeignKeyArg& fk_arg, ObCommonSqlProxy* sql_proxy, bool& is_data_valid);
int check_fk_constraint_data_validity(ObExecContext& ctx, const obrpc::ObAlterTableArg& alter_table_arg,
ObCommonSqlProxy* sql_proxy, int64_t schema_version, bool& is_data_valid);
int check_alter_partition(ObExecContext& ctx, ObAlterTableStmt& stmt, const obrpc::ObAlterTableArg& arg);
int set_index_arg_list(ObExecContext& ctx, ObAlterTableStmt& stmt);
int refresh_schema_for_table(const uint64_t tenant_id);
private:
// DISALLOW_COPY_AND_ASSIGN(ObAlterTableExecutor);
};
class ObDropTableStmt;
class ObDropTableExecutor {
public:
ObDropTableExecutor();
virtual ~ObDropTableExecutor();
int execute(ObExecContext& ctx, ObDropTableStmt& stmt);
private:
};
class ObRenameTableStmt;
class ObRenameTableExecutor {
public:
ObRenameTableExecutor();
virtual ~ObRenameTableExecutor();
int execute(ObExecContext& ctx, ObRenameTableStmt& stmt);
private:
};
class ObTruncateTableStmt;
class ObTruncateTableExecutor {
public:
ObTruncateTableExecutor();
virtual ~ObTruncateTableExecutor();
int execute(ObExecContext& ctx, ObTruncateTableStmt& stmt);
private:
};
class ObCreateTableLikeStmt;
class ObCreateTableLikeExecutor {
public:
ObCreateTableLikeExecutor();
virtual ~ObCreateTableLikeExecutor();
int execute(ObExecContext& ctx, ObCreateTableLikeStmt& stmt);
private:
};
class ObFlashBackTableFromRecyclebinStmt;
class ObFlashBackTableFromRecyclebinExecutor {
public:
ObFlashBackTableFromRecyclebinExecutor()
{}
virtual ~ObFlashBackTableFromRecyclebinExecutor()
{}
int execute(ObExecContext& ctx, ObFlashBackTableFromRecyclebinStmt& stmt);
private:
};
class ObFlashBackTableToScnStmt;
class ObFlashBackTableToScnExecutor {
public:
ObFlashBackTableToScnExecutor()
{}
virtual ~ObFlashBackTableToScnExecutor()
{}
int execute(ObExecContext& ctx, ObFlashBackTableToScnStmt& stmt);
private:
};
class ObPurgeTableStmt;
class ObPurgeTableExecutor {
public:
ObPurgeTableExecutor()
{}
virtual ~ObPurgeTableExecutor()
{}
int execute(ObExecContext& ctx, ObPurgeTableStmt& stmt);
private:
};
class ObOptimizeTableStmt;
class ObOptimizeTableExecutor {
public:
ObOptimizeTableExecutor() = default;
virtual ~ObOptimizeTableExecutor() = default;
int execute(ObExecContext& ctx, ObOptimizeTableStmt& stmt);
};
class ObOptimizeTenantStmt;
class ObOptimizeTenantExecutor {
public:
ObOptimizeTenantExecutor() = default;
virtual ~ObOptimizeTenantExecutor() = default;
int execute(ObExecContext& ctx, ObOptimizeTenantStmt& stmt);
static int optimize_tenant(const obrpc::ObOptimizeTenantArg& arg, const uint64_t tenant_id,
share::schema::ObMultiVersionSchemaService& schema_service, obrpc::ObCommonRpcProxy* common_rpc_proxy);
};
class ObOptimizeAllStmt;
class ObOptimizeAllExecutor {
public:
ObOptimizeAllExecutor() = default;
virtual ~ObOptimizeAllExecutor() = default;
int execute(ObExecContext& ctx, ObOptimizeAllStmt& stmt);
};
} // end namespace sql
} // end namespace oceanbase
#endif // OCEANBASE_SQL_OB_TABLE_EXECUTOR_

View File

@ -0,0 +1,197 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "share/object/ob_obj_cast.h"
#include "sql/engine/cmd/ob_tablegroup_executor.h"
#include "share/ob_common_rpc_proxy.h"
#include "share/schema/ob_schema_struct.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/resolver/ddl/ob_create_tablegroup_stmt.h"
#include "sql/resolver/ddl/ob_alter_tablegroup_stmt.h"
#include "sql/resolver/ddl/ob_drop_tablegroup_stmt.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/code_generator/ob_expr_generator_impl.h"
#include "sql/engine/cmd/ob_partition_executor_utils.h"
namespace oceanbase {
using namespace common;
using namespace share::schema;
namespace sql {
int ObCreateTablegroupExecutor::execute(ObExecContext& ctx, ObCreateTablegroupStmt& stmt)
{
int ret = OB_SUCCESS;
obrpc::ObRpcOpts rpc_opt;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
obrpc::ObCreateTablegroupArg& create_tablegroup_arg = stmt.get_create_tablegroup_arg();
ObTablegroupSchema& tablegroup_schema = create_tablegroup_arg.tablegroup_schema_;
tablegroup_schema.set_part_func_expr_num(stmt.get_part_func_expr_num());
tablegroup_schema.set_sub_part_func_expr_num(stmt.get_sub_part_func_expr_num());
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObCreateTablegroupArg&>(create_tablegroup_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;
LOG_WARN("get task executor context failed");
} else if (OB_FAIL(ObPartitionExecutorUtils::calc_values_exprs(ctx, stmt))) {
LOG_WARN("compare range parition expr fail", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else {
obrpc::UInt64 tablegroup_id(0);
if (OB_FAIL(common_rpc_proxy->create_tablegroup(create_tablegroup_arg, tablegroup_id))) {
LOG_WARN("rpc proxy create tablegroup failed", K(ret));
}
}
LOG_INFO("finish execute create tablegroup.", K(stmt), K(ret));
return ret;
}
int ObDropTablegroupExecutor::execute(ObExecContext& ctx, ObDropTablegroupStmt& stmt)
{
int ret = OB_SUCCESS;
obrpc::ObRpcOpts rpc_opt;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObDropTablegroupArg& drop_tablegroup_arg = stmt.get_drop_tablegroup_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObDropTablegroupArg&>(drop_tablegroup_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;
LOG_WARN("get task executor context failed");
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->drop_tablegroup(drop_tablegroup_arg))) {
LOG_WARN("rpc proxy drop tablegroup failed", K(ret));
}
LOG_INFO("finish execute drop tablegroup.", K(stmt), K(ret));
return ret;
}
int ObAlterTablegroupExecutor::execute(ObExecContext& ctx, ObAlterTablegroupStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
obrpc::ObAlterTablegroupArg& alter_tablegroup_arg = stmt.get_alter_tablegroup_arg();
alter_tablegroup_arg.alter_tablegroup_schema_.set_part_func_expr_num(stmt.get_part_func_expr_num());
alter_tablegroup_arg.alter_tablegroup_schema_.set_sub_part_func_expr_num(stmt.get_sub_part_func_expr_num());
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObAlterTablegroupArg&>(alter_tablegroup_arg).ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(check_alter_partition(ctx, stmt, alter_tablegroup_arg))) {
LOG_WARN("check alter partition failed", K(ret));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->alter_tablegroup(alter_tablegroup_arg))) {
LOG_WARN(
"rpc proxy alter table group failed", "dst", common_rpc_proxy->get_server(), K(ret), K(alter_tablegroup_arg));
}
return ret;
}
int ObAlterTablegroupExecutor::check_alter_partition(
ObExecContext& ctx, ObAlterTablegroupStmt& stmt, const obrpc::ObAlterTablegroupArg& arg)
{
int ret = OB_SUCCESS;
if (arg.is_alter_partitions()) {
const ObTablegroupSchema& tablegroup_schema = arg.alter_tablegroup_schema_;
if (arg.alter_option_bitset_.has_member(obrpc::ObAlterTablegroupArg::ADD_PARTITION) ||
arg.alter_option_bitset_.has_member(obrpc::ObAlterTablegroupArg::PARTITIONED_TABLE) ||
arg.alter_option_bitset_.has_member(obrpc::ObAlterTablegroupArg::REORGANIZE_PARTITION) ||
arg.alter_option_bitset_.has_member(obrpc::ObAlterTablegroupArg::SPLIT_PARTITION)) {
ObPartition** partition_array = tablegroup_schema.get_part_array();
int64_t real_part_num = tablegroup_schema.get_partition_num();
const int64_t fun_expr_num = stmt.get_part_func_expr_num();
if (arg.alter_option_bitset_.has_member(obrpc::ObAlterTablegroupArg::SPLIT_PARTITION)) {
real_part_num = tablegroup_schema.get_part_option().get_part_num();
}
if (tablegroup_schema.is_range_part()) {
ObSEArray<ObObj, 8> range_partition_obj;
ObIArray<ObRawExpr*>& range_values_exprs = stmt.get_part_values_exprs();
if (OB_ISNULL(partition_array)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("partition_array is NULL", K(ret));
} else if (OB_FAIL(ObPartitionExecutorUtils::cast_range_expr_to_obj(ctx,
range_values_exprs,
fun_expr_num,
stmt::T_ALTER_TABLEGROUP,
false, // is_subpart
real_part_num,
partition_array,
NULL,
range_partition_obj))) {
LOG_WARN("partition_array is NULL", K(ret));
}
} else if (tablegroup_schema.is_list_part()) {
if (OB_ISNULL(partition_array)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("partition_array is NULL", K(ret));
} else if (OB_FAIL(ObPartitionExecutorUtils::cast_list_expr_to_obj(ctx, stmt, false, partition_array, NULL))) {
LOG_WARN("failed cast list to expr", K(ret));
}
} else if (!arg.alter_option_bitset_.has_member(obrpc::ObAlterTablegroupArg::PARTITIONED_TABLE)) {
ret = OB_ERR_ONLY_ON_RANGE_LIST_PARTITION;
LOG_WARN("unexpected partition type",
K(ret),
"partition type",
tablegroup_schema.get_part_option().get_part_func_type());
}
if (OB_FAIL(ret)) {
} else if (arg.alter_option_bitset_.has_member(obrpc::ObAlterTablegroupArg::SPLIT_PARTITION)) {
const_cast<ObTablegroupSchema&>(tablegroup_schema)
.get_part_option()
.set_part_num(tablegroup_schema.get_partition_num());
}
} else if (arg.alter_option_bitset_.has_member(obrpc::ObAlterTablegroupArg::DROP_PARTITION)) {
// do-nothing
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("no operation", K(arg), K(ret));
}
LOG_DEBUG("dump table schema", K(tablegroup_schema));
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,65 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_OB_TABLEGROUP_EXECUTOR_
#define OCEANBASE_SQL_OB_TABLEGROUP_EXECUTOR_
#include "share/ob_define.h"
#include "common/object/ob_object.h"
#include "lib/container/ob_se_array.h"
#include "share/ob_rpc_struct.h"
namespace oceanbase {
namespace share {
namespace schema {
class ObPartition;
class ObSubPartition;
} // namespace schema
} // namespace share
namespace sql {
class ObRawExpr;
#define DEF_SIMPLE_EXECUTOR(name) \
class name##Executor { \
public: \
name##Executor() \
{} \
virtual ~name##Executor() \
{} \
int execute(ObExecContext& ctx, name##Stmt& stmt); \
\
private: \
DISALLOW_COPY_AND_ASSIGN(name##Executor); \
}
class ObExecContext;
class ObCreateTablegroupStmt;
DEF_SIMPLE_EXECUTOR(ObCreateTablegroup);
class ObDropTablegroupStmt;
DEF_SIMPLE_EXECUTOR(ObDropTablegroup);
class ObAlterTablegroupStmt;
class ObAlterTablegroupExecutor {
public:
ObAlterTablegroupExecutor()
{}
virtual ~ObAlterTablegroupExecutor()
{}
int execute(ObExecContext& ctx, ObAlterTablegroupStmt& stmt);
private:
int check_alter_partition(ObExecContext& ctx, ObAlterTablegroupStmt& stmt, const obrpc::ObAlterTablegroupArg& arg);
DISALLOW_COPY_AND_ASSIGN(ObAlterTablegroupExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif /* OCEANBASE_SQL_OB_TABLEGROUP_EXECUTOR_ */

View File

@ -0,0 +1,123 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_tcl_executor.h"
#include "lib/encrypt/ob_encrypted_helper.h"
#include "share/ob_rpc_struct.h"
#include "share/schema/ob_schema_struct.h"
#include "share/ob_common_rpc_proxy.h"
#include "sql/ob_sql_trans_control.h"
#include "sql/resolver/tcl/ob_end_trans_stmt.h"
#include "sql/resolver/tcl/ob_start_trans_stmt.h"
#include "sql/resolver/tcl/ob_savepoint_stmt.h"
#include "sql/engine/ob_exec_context.h"
namespace oceanbase {
using namespace common;
using namespace share::schema;
namespace sql {
int ObEndTransExecutor::execute(ObExecContext& ctx, ObEndTransStmt& stmt)
{
return end_trans(ctx, stmt);
}
int ObEndTransExecutor::end_trans(ObExecContext& ctx, ObEndTransStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* my_session = GET_MY_SESSION(ctx);
if (OB_ISNULL(my_session)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("session ptr is null", K(ret));
} else if (my_session->is_in_transaction() && my_session->get_trans_desc().is_xa_local_trans()) {
transaction::ObXATransID xid = my_session->get_trans_desc().get_xid();
if (stmt.get_is_rollback()) {
// Rollback can be executed in the xa transaction,
// the role is to roll back all modifications, but does not end the xa transaction
} else {
// commit is prohibited in xa transaction
ret = OB_TRANS_XA_ERR_COMMIT;
LOG_WARN("COMMIT is not allowed in a xa trans", K(ret), K(xid));
}
ctx.set_need_disconnect(false);
} else if (OB_FAIL(ObSqlTransControl::explicit_end_trans(ctx, stmt.get_is_rollback()))) {
LOG_WARN("fail end trans", K(ret));
}
return ret;
}
int ObStartTransExecutor::execute(ObExecContext& ctx, ObStartTransStmt& stmt)
{
return start_trans(ctx, stmt);
}
int ObStartTransExecutor::start_trans(ObExecContext& ctx, ObStartTransStmt& stmt)
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObSqlTransControl::explicit_start_trans(ctx, stmt.get_read_only()))) {
LOG_WARN("fail start trans", K(ret));
}
return ret;
}
int ObCreateSavePointExecutor::execute(ObExecContext& ctx, ObCreateSavePointStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session = GET_MY_SESSION(ctx);
if (OB_ISNULL(session)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(session));
} else if (!session->is_in_transaction() && !session->get_local_autocommit() &&
OB_FAIL(ObSqlTransControl::explicit_start_trans(ctx, session->get_tx_read_only()))) {
LOG_WARN("fail start trans", K(ret));
} else if (OB_FAIL(ObSqlTransControl::create_savepoint(ctx, stmt.get_sp_name()))) {
LOG_WARN("fail create savepoint", K(ret), K(stmt.get_sp_name()));
}
return ret;
}
int ObRollbackSavePointExecutor::execute(ObExecContext& ctx, ObRollbackSavePointStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session = GET_MY_SESSION(ctx);
if (OB_ISNULL(session)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(session));
} else if (!session->is_in_transaction()) {
ret = OB_SAVEPOINT_NOT_EXIST;
LOG_WARN("savepoint is not exist", K(ret), K(stmt.get_sp_name()));
} else if (OB_FAIL(ObSqlTransControl::rollback_savepoint(ctx, stmt.get_sp_name()))) {
LOG_WARN("fail rollback to savepoint", K(ret), K(stmt.get_sp_name()));
}
return ret;
}
int ObReleaseSavePointExecutor::execute(ObExecContext& ctx, ObReleaseSavePointStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session = GET_MY_SESSION(ctx);
if (OB_ISNULL(session)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(session));
} else if (!session->is_in_transaction()) {
ret = OB_SAVEPOINT_NOT_EXIST;
LOG_WARN("savepoint is not exist", K(ret), K(stmt.get_sp_name()));
} else if (OB_FAIL(ObSqlTransControl::release_savepoint(ctx, stmt.get_sp_name()))) {
LOG_WARN("fail release savepoint", K(ret), K(stmt.get_sp_name()));
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,90 @@
/**
* 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.
*/
#ifndef OCRANBASE_SQL_ENGINE_CMD_OB_TCL_CMD_EXECUTOR_
#define OCRANBASE_SQL_ENGINE_CMD_OB_TCL_CMD_EXECUTOR_
#include "share/ob_define.h"
namespace oceanbase {
namespace sql {
class ObExecContext;
class ObEndTransStmt;
class ObEndTransExecutor {
public:
ObEndTransExecutor()
{}
virtual ~ObEndTransExecutor()
{}
int execute(ObExecContext& ctx, ObEndTransStmt& stmt);
private:
int end_trans(ObExecContext& ctx, ObEndTransStmt& stmt);
DISALLOW_COPY_AND_ASSIGN(ObEndTransExecutor);
};
class ObStartTransStmt;
class ObStartTransExecutor {
public:
ObStartTransExecutor()
{}
virtual ~ObStartTransExecutor()
{}
int execute(ObExecContext& ctx, ObStartTransStmt& stmt);
private:
int start_trans(ObExecContext& ctx, ObStartTransStmt& stmt);
DISALLOW_COPY_AND_ASSIGN(ObStartTransExecutor);
};
class ObCreateSavePointStmt;
class ObCreateSavePointExecutor {
public:
ObCreateSavePointExecutor()
{}
virtual ~ObCreateSavePointExecutor()
{}
int execute(ObExecContext& ctx, ObCreateSavePointStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObCreateSavePointExecutor);
};
class ObRollbackSavePointStmt;
class ObRollbackSavePointExecutor {
public:
ObRollbackSavePointExecutor()
{}
virtual ~ObRollbackSavePointExecutor()
{}
int execute(ObExecContext& ctx, ObRollbackSavePointStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObRollbackSavePointExecutor);
};
class ObReleaseSavePointStmt;
class ObReleaseSavePointExecutor {
public:
ObReleaseSavePointExecutor()
{}
virtual ~ObReleaseSavePointExecutor()
{}
int execute(ObExecContext& ctx, ObReleaseSavePointStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObReleaseSavePointExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif // OCRANBASE_SQL_ENGINE_CMD_OB_TCL_CMD_EXECUTOR_

View File

@ -0,0 +1,618 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_tenant_executor.h"
#include "lib/container/ob_se_array_iterator.h"
#include "common/sql_mode/ob_sql_mode_utils.h"
#include "share/ob_unit_getter.h"
#include "share/ob_common_rpc_proxy.h"
#include "share/config/ob_server_config.h"
#include "share/schema/ob_schema_getter_guard.h"
#include "share/schema/ob_multi_version_schema_service.h"
#include "share/ob_get_compat_mode.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/resolver/ddl/ob_create_tenant_stmt.h"
#include "sql/resolver/ddl/ob_drop_tenant_stmt.h"
#include "sql/resolver/ddl/ob_lock_tenant_stmt.h"
#include "sql/resolver/ddl/ob_modify_tenant_stmt.h"
#include "sql/resolver/ddl/ob_purge_stmt.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/engine/cmd/ob_variable_set_executor.h"
#include "sql/code_generator/ob_expr_generator_impl.h"
#include "sql/resolver/cmd/ob_create_restore_point_stmt.h"
#include "sql/resolver/cmd/ob_drop_restore_point_stmt.h"
#include "observer/ob_inner_sql_connection_pool.h"
namespace oceanbase {
using namespace common;
using namespace share;
using namespace share::schema;
namespace sql {
int check_sys_var_options(ObExecContext& ctx, const common::ObIArray<ObVariableSetStmt::VariableSetNode>& sys_var_nodes,
share::schema::ObTenantSchema& tenant_schema, common::ObIArray<obrpc::ObSysVarIdValue>& sys_var_list);
int ObCreateTenantExecutor::execute(ObExecContext& ctx, ObCreateTenantStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
obrpc::ObSrvRpcProxy* srv_rpc_proxy = NULL;
obrpc::UInt64 tenant_id;
const obrpc::ObCreateTenantArg& create_tenant_arg = stmt.get_create_tenant_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObCreateTenantArg&>(create_tenant_arg).ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(check_sys_var_options(ctx,
stmt.get_sys_var_nodes(),
stmt.get_create_tenant_arg().tenant_schema_,
stmt.get_create_tenant_arg().sys_var_list_))) {
LOG_WARN("check_sys_var_options failed", K(ret));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else if (OB_ISNULL(srv_rpc_proxy = task_exec_ctx->get_srv_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get server rpc proxy failed");
} else if (OB_FAIL(common_rpc_proxy->create_tenant(create_tenant_arg, tenant_id))) {
LOG_WARN("rpc proxy create tenant failed", K(ret));
} else if (!create_tenant_arg.if_not_exist_ && OB_INVALID_ID == tenant_id) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("if_not_exist not set and tenant_id invalid tenant_id", K(create_tenant_arg), K(tenant_id), K(ret));
} else if (OB_INVALID_ID != tenant_id) {
// In fact, create tenant is success when come here. But we need
// notify relating servers to ensure this tenant is created
// indeed. Thus, client may receive a error packet for this
// request, but the tenant is created perfectly.
ObMySQLProxy* proxy = ctx.get_sql_proxy();
ObUnitInfoGetter ui_getter;
typedef ObSEArray<ObUnitInfoGetter::ObServerConfig, 10> ServerUnits;
ServerUnits units;
if (OB_ISNULL(proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("proxy is null");
} else if (OB_FAIL(ui_getter.init(*proxy, &GCONF))) {
LOG_WARN("init unit getter fail", K(ret));
} else if (OB_FAIL(ui_getter.get_tenant_server_configs(tenant_id, units))) {
LOG_WARN("get tenant server configs fail", K(ret));
} else {
int rret = ret;
for (ServerUnits::iterator it = units.begin(); it != units.end(); ++it) {
if (OB_FAIL(srv_rpc_proxy->to(it->server_).add_tenant_tmp(tenant_id))) {
LOG_WARN("add tenant temp fail", K(ret));
}
// If it fails here, it does not mean that the create tenant process has failed.
// Later, the server will obtain tenant information from rs according to the normal
// process and timed tasks.
if (!OB_SUCC(ret) && OB_SUCCESS == rret) {
rret = ret;
}
}
ret = rret;
}
}
return ret;
}
int check_sys_var_options(ObExecContext& ctx, const common::ObIArray<ObVariableSetStmt::VariableSetNode>& sys_var_nodes,
share::schema::ObTenantSchema& tenant_schema, common::ObIArray<obrpc::ObSysVarIdValue>& sys_var_list)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session = NULL;
ObMySQLProxy* sql_proxy = NULL;
ObPhysicalPlanCtx* plan_ctx = NULL;
if (OB_ISNULL(session = ctx.get_my_session()) || OB_ISNULL(sql_proxy = ctx.get_sql_proxy()) ||
OB_ISNULL(plan_ctx = ctx.get_physical_plan_ctx())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session or sql proxy or plan_ctx is NULL", K(session), K(sql_proxy), K(plan_ctx), K(ret));
} else {
// construct expr_ctx
ObPhysicalPlan phy_plan;
ObPhysicalPlanCtx phy_plan_ctx(ctx.get_allocator());
SMART_VAR(ObExecContext, exec_ctx)
{
ObArenaAllocator allocator(
common::ObModIds::OB_SQL_EXPR_CALC, OB_MALLOC_NORMAL_BLOCK_SIZE, session->get_effective_tenant_id());
ObExprCtx expr_ctx;
expr_ctx.phy_plan_ctx_ = &phy_plan_ctx;
expr_ctx.my_session_ = session;
expr_ctx.exec_ctx_ = &exec_ctx;
expr_ctx.calc_buf_ = &allocator;
expr_ctx.exec_ctx_->set_sql_proxy(sql_proxy);
phy_plan_ctx.set_phy_plan(&phy_plan);
const int64_t cur_time =
plan_ctx->has_cur_time() ? plan_ctx->get_cur_time().get_timestamp() : ObTimeUtility::current_time();
phy_plan_ctx.set_cur_time(cur_time, *session);
ObVariableSetStmt::VariableSetNode tmp_node; // just for init node
for (int64_t i = 0; OB_SUCC(ret) && i < sys_var_nodes.count(); ++i) {
ObVariableSetStmt::VariableSetNode& cur_node = tmp_node;
ObBasicSysVar* sys_var = NULL;
if (OB_FAIL(sys_var_nodes.at(i, cur_node))) {
LOG_WARN("failed to access node from array", K(ret));
} else if (!cur_node.is_system_variable_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("create tenant can only set system variables", K(cur_node), K(ret));
} else if (OB_FAIL(session->get_sys_variable_by_name(cur_node.variable_name_, sys_var))) {
LOG_WARN("fail to get_sys_variable_by_name", K(ret));
} else if (OB_ISNULL(sys_var)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("got sys var is NULL", K(ret));
} else if (cur_node.is_set_default_) { // set default, then do nothing
} else {
ObObj value_obj;
// first:calculate value of expression
ObNewRow tmp_row;
RowDesc row_desc;
ObExprGeneratorImpl expr_gen(0, 0, NULL, row_desc);
ObSqlExpression sql_expr(ctx.get_allocator(), 0);
if (OB_ISNULL(cur_node.value_expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node.value_expr_ is NULL", K(ret));
} else {
if (!is_strict_mode(session->get_sql_mode())) {
expr_ctx.cast_mode_ = CM_WARN_ON_FAIL;
}
if (OB_FAIL(expr_gen.generate(*cur_node.value_expr_, sql_expr))) {
LOG_WARN("fail to fill sql expression", K(ret));
} else if (FALSE_IT(phy_plan.set_regexp_op_count(expr_gen.get_cur_regexp_op_count()))) {
} else if (FALSE_IT(phy_plan.set_like_op_count(expr_gen.get_cur_like_op_count()))) {
} else if (OB_FAIL(sql_expr.calc(expr_ctx, tmp_row, value_obj))) {
LOG_WARN("fail to calc value", K(*cur_node.value_expr_), K(ret));
} else { /*do nothing*/
}
}
// second:convert value to dest type
uint64_t fake_tenant_id = OB_INVALID_ID;
ObSetVar set_var(cur_node.variable_name_,
cur_node.set_scope_,
cur_node.is_set_default_,
fake_tenant_id,
*expr_ctx.calc_buf_,
*sql_proxy);
if (OB_SUCC(ret)) {
ObObj out_obj;
const bool is_set_stmt = false;
if (OB_FAIL(ObVariableSetExecutor::check_and_convert_sys_var(
ctx, set_var, *sys_var, value_obj, out_obj, is_set_stmt))) {
LOG_WARN("fail to check_and_convert_sys_var", K(cur_node), K(*sys_var), K(value_obj), K(ret));
} else if (FALSE_IT(value_obj = out_obj)) {
} else if (OB_FAIL(ObVariableSetExecutor::cast_value(
ctx, cur_node, fake_tenant_id, *expr_ctx.calc_buf_, *sys_var, value_obj, out_obj))) {
LOG_WARN("fail to cast value", K(cur_node), K(*sys_var), K(value_obj), K(ret));
} else if (FALSE_IT(value_obj = out_obj)) {
} else { /*do nothing*/
}
}
// add variable value into ObCreateTenantArg
if (OB_SUCC(ret)) {
if (set_var.var_name_ == OB_SV_COLLATION_SERVER || set_var.var_name_ == OB_SV_COLLATION_DATABASE ||
set_var.var_name_ == OB_SV_COLLATION_CONNECTION || set_var.var_name_ == OB_SV_CHARACTER_SET_SERVER ||
set_var.var_name_ == OB_SV_CHARACTER_SET_DATABASE ||
set_var.var_name_ == OB_SV_CHARACTER_SET_CONNECTION) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("collation or charset can not be modify temporarily", K(set_var), K(ret));
} else {
// read only should also modify tenant_schema
if (set_var.var_name_ == OB_SV_READ_ONLY) {
if (session->get_in_transaction()) {
ret = OB_ERR_LOCK_OR_ACTIVE_TRANSACTION;
LOG_WARN("Can't execute the given command because "
"you have active locked tables or an active transaction",
K(ret));
} else {
tenant_schema.set_read_only(value_obj.get_bool());
}
}
ObSysVarClassType sys_id = sys_var->get_type();
ObString val_str;
expr_ctx.calc_buf_ = &ctx.get_allocator(); // make sure use this allocator to keep ObString is valid
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_NONE);
EXPR_GET_VARCHAR_V2(value_obj, val_str);
if (OB_SUCC(ret)) {
if (OB_UNLIKELY(val_str.length() > OB_MAX_SYS_VAR_VAL_LENGTH)) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("set sysvar value is overflow",
"max length",
OB_MAX_SYS_VAR_VAL_LENGTH,
"value length",
val_str.length(),
K(sys_id),
K(val_str));
} else if (OB_FAIL(sys_var_list.push_back(obrpc::ObSysVarIdValue(sys_id, val_str)))) {
LOG_WARN("failed to push back", K(sys_id), K(val_str), K(ret));
}
}
}
}
}
} // end of for
}
}
return ret;
}
int ObLockTenantExecutor::execute(ObExecContext& ctx, ObLockTenantStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObLockTenantArg& lock_tenant_arg = stmt.get_lock_tenant_arg();
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else if (OB_FAIL(common_rpc_proxy->lock_tenant(lock_tenant_arg))) {
LOG_WARN("rpc proxy lock tenant failed", K(ret));
}
return ret;
}
int modify_progressive_merge_num_for_tenant(
ObExecContext& ctx, const int64_t tenant_id, const int64_t progressive_merge_num)
{
int ret = OB_SUCCESS;
ObMySQLProxy* sql_proxy = ctx.get_sql_proxy();
ObSchemaGetterGuard schema_guard;
common::ObCommonSqlProxy* user_sql_proxy;
common::ObOracleSqlProxy oracle_sql_proxy;
if (OB_SYS_TENANT_ID == tenant_id && !GCONF.enable_sys_table_ddl) {
ret = OB_NOT_SUPPORTED;
LOG_USER_ERROR(OB_NOT_SUPPORTED, "sys_table_ddl option");
LOG_WARN("sys_table_ddl option should be enabled", K(ret));
} else if (OB_INVALID_ID == tenant_id) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(tenant_id));
} else if (nullptr == sql_proxy) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, sql proxy must not be null", K(ret));
} else if (OB_FAIL(ObMultiVersionSchemaService::get_instance().get_tenant_schema_guard(tenant_id, schema_guard))) {
LOG_WARN("failed to get schema guard", K(ret));
} else {
observer::ObInnerSQLConnectionPool* pool = static_cast<observer::ObInnerSQLConnectionPool*>(sql_proxy->get_pool());
if (OB_ISNULL(pool)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, pool must not be null", K(ret));
} else if (OB_FAIL(oracle_sql_proxy.init(pool))) {
LOG_WARN("fail to init oracle sql proxy", K(ret));
} else {
ObArray<const ObDatabaseSchema*> dbs;
if (OB_FAIL(schema_guard.get_database_schemas_in_tenant(tenant_id, dbs))) {
LOG_WARN("fail to get db schemas", K(ret), K(tenant_id));
} else {
for (int64_t i = 0; i < dbs.count() && OB_SUCC(ret); i++) {
const ObDatabaseSchema* db = dbs.at(i);
const uint64_t database_id = db->get_database_id();
ObArray<const ObTableSchema*> tables;
if (OB_FAIL(schema_guard.get_table_schemas_in_database(tenant_id, database_id, tables))) {
LOG_WARN("fail to get table schemas", K(ret), K(tenant_id), K(database_id));
}
for (int64_t j = 0; j < tables.count() && OB_SUCC(ret); j++) {
if (OB_FAIL(ctx.check_status())) {
LOG_WARN("should stopped", K(ret));
} else {
const ObTableSchema* table = tables.at(j);
bool do_alter = true;
if (!table->has_partition()) {
do_alter = false;
}
if (table->is_index_table()) {
do_alter = false;
}
if (table->is_in_recyclebin()) {
do_alter = false;
}
if (table->is_tmp_table()) {
do_alter = false;
}
if (extract_pure_id(table->get_table_id()) == OB_ALL_CORE_TABLE_TID) {
do_alter = false;
}
if (table->get_progressive_merge_num() == progressive_merge_num) {
do_alter = false;
}
if (OB_SYS_TENANT_ID != tenant_id && table->is_sys_table()) {
do_alter = false;
}
if (table->is_tmp_table()) {
do_alter = false;
}
if (do_alter) {
ObSqlString sql;
int64_t affected_rows = 0;
ObWorker::CompatMode mode;
if (OB_FAIL(ObCompatModeGetter::get_tenant_mode(tenant_id, mode))) {
LOG_WARN("fail to get tenant mode", K(ret), K(tenant_id));
} else if (ObWorker::CompatMode::MYSQL == mode) {
if (OB_FAIL(sql.assign_fmt("ALTER TABLE `%.*s`.`%.*s` SET PROGRESSIVE_MERGE_NUM = %ld",
db->get_database_name_str().length(),
db->get_database_name_str().ptr(),
table->get_table_name_str().length(),
table->get_table_name_str().ptr(),
progressive_merge_num))) {
LOG_WARN("sql assign_fmt failed", K(ret));
} else {
user_sql_proxy = sql_proxy;
}
} else if (ObWorker::CompatMode::ORACLE == mode) {
if (OB_FAIL(sql.assign_fmt("ALTER TABLE \"%.*s\".\"%.*s\" SET PROGRESSIVE_MERGE_NUM = %ld",
db->get_database_name_str().length(),
db->get_database_name_str().ptr(),
table->get_table_name_str().length(),
table->get_table_name_str().ptr(),
progressive_merge_num))) {
LOG_WARN("sql assign_fmt failed", K(ret));
} else {
user_sql_proxy = &oracle_sql_proxy;
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, invalid tenant mode", K(ret), K(mode));
}
if (OB_SUCC(ret)) {
if (OB_FAIL(user_sql_proxy->write(tenant_id, sql.ptr(), affected_rows))) {
if (OB_ERR_OPERATION_ON_RECYCLE_OBJECT != ret) {
LOG_WARN("execute sql failed", K(ret));
} else {
ret = OB_SUCCESS;
}
}
}
}
}
}
} // table loop end
} // database loop end
}
}
return ret;
}
int modify_progressive_merge_num_for_all_tenants(ObExecContext& ctx, const int64_t progressive_merge_num)
{
int ret = OB_SUCCESS;
ObSchemaGetterGuard schema_guard;
ObSEArray<uint64_t, 32> tenant_ids;
if (OB_FAIL(ObMultiVersionSchemaService::get_instance().get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) {
LOG_WARN("fail to get tenant schema guard", K(ret));
} else if (OB_FAIL(schema_guard.get_tenant_ids(tenant_ids))) {
LOG_WARN("fail to get tenant ids", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < tenant_ids.count(); ++i) {
const int64_t tenant_id = tenant_ids.at(i);
if (OB_FAIL(modify_progressive_merge_num_for_tenant(ctx, tenant_id, progressive_merge_num))) {
LOG_WARN("fail to modify progressive merge num for tenant", K(ret), K(tenant_id));
}
}
}
return ret;
}
int ObModifyTenantExecutor::execute(ObExecContext& ctx, ObModifyTenantStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObModifyTenantArg& modify_tenant_arg = stmt.get_modify_tenant_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObModifyTenantArg&>(modify_tenant_arg).ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (-1 == stmt.get_progressive_merge_num()) {
if (OB_FAIL(check_sys_var_options(ctx,
stmt.get_sys_var_nodes(),
stmt.get_modify_tenant_arg().tenant_schema_,
stmt.get_modify_tenant_arg().sys_var_list_))) {
LOG_WARN("check_sys_var_options failed", K(ret));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else if (OB_FAIL(common_rpc_proxy->modify_tenant(modify_tenant_arg))) {
LOG_WARN("rpc proxy modify tenant failed", K(ret));
}
} else {
if (modify_tenant_arg.tenant_schema_.get_tenant_name_str().case_compare("all") == 0) {
ObSQLSessionInfo* session = NULL;
if (OB_ISNULL(session = ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session is NULL", K(ret));
} else if (session->get_tenant_name().case_compare(ObString::make_string(OB_SYS_TENANT_NAME)) != 0) {
ret = OB_ERR_NO_PRIVILEGE;
LOG_WARN("no privilege", K(ret));
} else if (OB_FAIL(modify_progressive_merge_num_for_all_tenants(ctx, stmt.get_progressive_merge_num()))) {
LOG_WARN("modify_progressive_merge_num_for_tables failed", K(ret));
}
} else {
ObSchemaGetterGuard schema_guard;
const ObTenantSchema* tenant_schema = nullptr;
if (OB_FAIL(
ObMultiVersionSchemaService::get_instance().get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) {
LOG_WARN("fail to get tenant schema guard", K(ret));
} else if (OB_FAIL(schema_guard.get_tenant_info(
modify_tenant_arg.tenant_schema_.get_tenant_name_str(), tenant_schema))) {
LOG_WARN("fail to get tenant info", K(ret));
} else if (OB_ISNULL(tenant_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, tenant schema must not be NULL", K(ret));
} else if (OB_FAIL(modify_progressive_merge_num_for_tenant(
ctx, tenant_schema->get_tenant_id(), stmt.get_progressive_merge_num()))) {
LOG_WARN(
"fail to modify progressive merge num for tenant", K(ret), "tenant_id", tenant_schema->get_tenant_id());
}
}
}
return ret;
}
int ObDropTenantExecutor::execute(ObExecContext& ctx, ObDropTenantStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObDropTenantArg& drop_tenant_arg = stmt.get_drop_tenant_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObDropTenantArg&>(drop_tenant_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;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else if (OB_FAIL(common_rpc_proxy->drop_tenant(drop_tenant_arg))) {
LOG_WARN("rpc proxy drop tenant failed", K(ret));
}
return ret;
}
int ObPurgeTenantExecutor::execute(ObExecContext& ctx, ObPurgeTenantStmt& stmt)
{
int ret = OB_SUCCESS;
const obrpc::ObPurgeTenantArg& purge_tenant_arg = stmt.get_purge_tenant_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::ObPurgeTenantArg&>(purge_tenant_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_tenant(purge_tenant_arg))) {
SQL_ENG_LOG(WARN, "rpc proxy purge tenant failed", K(ret));
}
return ret;
}
int ObPurgeRecycleBinExecutor::execute(ObExecContext& ctx, ObPurgeRecycleBinStmt& stmt)
{
int ret = OB_SUCCESS;
// use to test purge recyclebin objects
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObPurgeRecycleBinArg& purge_recyclebin_arg = stmt.get_purge_recyclebin_arg();
// int64_t current_time = ObTimeUtility::current_time();
// obrpc::Int64 expire_time = current_time - GCONF.schema_history_expire_time;
obrpc::Int64 affected_rows = 0;
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObPurgeRecycleBinArg&>(purge_recyclebin_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;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else {
bool is_tenant_finish = false;
int64_t total_purge_count = 0;
while (OB_SUCC(ret) && !is_tenant_finish) {
int64_t start_time = ObTimeUtility::current_time();
if (OB_FAIL(common_rpc_proxy->purge_expire_recycle_objects(purge_recyclebin_arg, affected_rows))) {
LOG_WARN("purge reyclebin objects failed", K(ret), K(affected_rows), K(purge_recyclebin_arg));
is_tenant_finish = false;
} else {
is_tenant_finish = obrpc::ObPurgeRecycleBinArg::DEFAULT_PURGE_EACH_TIME == affected_rows ? false : true;
total_purge_count += affected_rows;
}
int64_t cost_time = ObTimeUtility::current_time() - start_time;
LOG_INFO("purge recycle objects",
K(ret),
K(cost_time),
K(total_purge_count),
K(purge_recyclebin_arg),
K(affected_rows),
K(is_tenant_finish));
}
LOG_INFO("purge recyclebin success", K(purge_recyclebin_arg), K(total_purge_count), K(ret));
}
return ret;
}
int ObCreateRestorePointExecutor::execute(ObExecContext& ctx, ObCreateRestorePointStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const int64_t tenant_id = ctx.get_my_session()->get_effective_tenant_id();
stmt.set_tenant_id(tenant_id);
const obrpc::ObCreateRestorePointArg& create_restore_point_arg = stmt.get_create_restore_point_arg();
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else if (OB_FAIL(common_rpc_proxy->create_restore_point(create_restore_point_arg))) {
LOG_WARN("rpc proxy create restore point failed", K(ret));
}
return ret;
}
int ObDropRestorePointExecutor::execute(ObExecContext& ctx, ObDropRestorePointStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const int64_t tenant_id = ctx.get_my_session()->get_effective_tenant_id();
stmt.set_tenant_id(tenant_id);
const obrpc::ObDropRestorePointArg& drop_restore_point_arg = stmt.get_drop_restore_point_arg();
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else if (OB_FAIL(common_rpc_proxy->drop_restore_point(drop_restore_point_arg))) {
LOG_WARN("rpc proxy drop restore point failed", K(ret));
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,65 @@
/**
* 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.
*/
#ifndef __OB_SQL_TENANT_EXECUTOR_H__
#define __OB_SQL_TENANT_EXECUTOR_H__
#include "share/ob_define.h"
namespace oceanbase {
namespace sql {
#define DEF_SIMPLE_EXECUTOR(name) \
class name##Executor { \
public: \
name##Executor() \
{} \
virtual ~name##Executor() \
{} \
int execute(ObExecContext& ctx, name##Stmt& stmt); \
\
private: \
DISALLOW_COPY_AND_ASSIGN(name##Executor); \
}
class ObExecContext;
class ObCreateTenantStmt;
class ObDropTenantStmt;
class ObLockTenantStmt;
class ObModifyTenantStmt;
class ObChangeTenantStmt;
class ObFlashBackTenantStmt;
class ObPurgeTenantStmt;
class ObPurgeRecycleBinStmt;
class ObCreateRestorePointStmt;
class ObDropRestorePointStmt;
DEF_SIMPLE_EXECUTOR(ObCreateTenant);
DEF_SIMPLE_EXECUTOR(ObDropTenant);
DEF_SIMPLE_EXECUTOR(ObModifyTenant);
DEF_SIMPLE_EXECUTOR(ObLockTenant);
DEF_SIMPLE_EXECUTOR(ObFlashBackTenant);
DEF_SIMPLE_EXECUTOR(ObPurgeTenant);
DEF_SIMPLE_EXECUTOR(ObPurgeRecycleBin);
DEF_SIMPLE_EXECUTOR(ObCreateRestorePoint);
DEF_SIMPLE_EXECUTOR(ObDropRestorePoint);
#undef DEF_SIMPLE_EXECUTOR
} // namespace sql
} // namespace oceanbase
#endif /* __OB_SQL_TENANT_EXECUTOR_H__ */
//// end of header file

View File

@ -0,0 +1,83 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_udf_executor.h"
#include "lib/mysqlclient/ob_mysql_proxy.h"
#include "share/ob_common_rpc_proxy.h"
#include "sql/resolver/ddl/ob_create_func_stmt.h"
#include "sql/resolver/ddl/ob_drop_func_stmt.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/engine/ob_physical_plan.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/code_generator/ob_expr_generator_impl.h"
namespace oceanbase {
using namespace common;
using namespace share::schema;
namespace sql {
int ObCreateFuncExecutor::execute(ObExecContext& ctx, ObCreateFuncStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObCreateUserDefinedFunctionArg& create_udf_arg = stmt.get_create_func_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObCreateUserDefinedFunctionArg&>(create_udf_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;
LOG_WARN("get task executor context failed", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->create_udf(create_udf_arg))) {
LOG_WARN("rpc proxy create udf failed", K(ret), "dst", common_rpc_proxy->get_server());
}
return ret;
}
int ObDropFuncExecutor::execute(ObExecContext& ctx, ObDropFuncStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObDropUserDefinedFunctionArg& drop_func_arg = stmt.get_drop_func_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
const_cast<obrpc::ObDropUserDefinedFunctionArg&>(drop_func_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;
LOG_WARN("get task executor context failed", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common rpc proxy should not be null", K(ret));
} else if (OB_FAIL(common_rpc_proxy->drop_udf(drop_func_arg))) {
LOG_WARN("rpc proxy create udf failed", K(ret), "dst", common_rpc_proxy->get_server());
}
return ret;
}
} // end namespace sql
} // end namespace oceanbase

View File

@ -0,0 +1,58 @@
/**
* 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.
*/
#ifndef OB_UDF_EXECUTOR_H_
#define OB_UDF_EXECUTOR_H_
#include "common/object/ob_object.h"
#include "lib/container/ob_se_array.h"
namespace oceanbase {
namespace common {
class ObIAllocator;
class ObExprCtx;
namespace sqlclient {
class ObMySQLProxy;
}
} // namespace common
namespace sql {
class ObExecContext;
class ObRawExpr;
class ObCreateFuncStmt;
class ObCreateFuncExecutor {
public:
const static int OB_DEFAULT_ARRAY_SIZE = 16;
ObCreateFuncExecutor()
{}
virtual ~ObCreateFuncExecutor()
{}
int execute(ObExecContext& ctx, ObCreateFuncStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObCreateFuncExecutor);
};
class ObDropFuncStmt;
class ObDropFuncExecutor {
public:
ObDropFuncExecutor()
{}
virtual ~ObDropFuncExecutor()
{}
int execute(ObExecContext& ctx, ObDropFuncStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObDropFuncExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif

View File

@ -0,0 +1,670 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_user_cmd_executor.h"
#include "lib/encrypt/ob_encrypted_helper.h"
#include "lib/string/ob_sql_string.h"
#include "share/schema/ob_schema_struct.h"
#include "share/ob_rpc_struct.h"
#include "share/ob_common_rpc_proxy.h"
#include "sql/resolver/dcl/ob_create_user_stmt.h"
#include "sql/resolver/dcl/ob_drop_user_stmt.h"
#include "sql/resolver/dcl/ob_lock_user_stmt.h"
#include "sql/resolver/dcl/ob_rename_user_stmt.h"
#include "sql/resolver/dcl/ob_alter_user_profile_stmt.h"
#include "sql/resolver/dcl/ob_alter_user_primary_zone_stmt.h"
#include "sql/engine/ob_exec_context.h"
namespace oceanbase {
using namespace common;
using namespace obrpc;
using namespace share::schema;
namespace sql {
int ObCreateUserExecutor::encrypt_passwd(
const common::ObString& pwd, common::ObString& encrypted_pwd, char* enc_buf, int64_t buf_len)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(enc_buf)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("enc_buf is NULL", K(ret));
} else if (buf_len < SCRAMBLE_LENGTH * 2 + 1) {
ret = OB_BUF_NOT_ENOUGH;
LOG_WARN("Encrypt buf not enough");
} else {
encrypted_pwd.assign_ptr(enc_buf, SCRAMBLE_LENGTH * 2 + 1);
if (OB_FAIL(ObEncryptedHelper::encrypt_passwd_to_stage2(pwd, encrypted_pwd))) {
SQL_ENG_LOG(WARN, "failed to encrypt passwd", K(ret));
}
}
return ret;
}
int ObCreateUserExecutor::userinfo_extract_user_name(const common::ObIArray<share::schema::ObUserInfo>& user_infos,
const common::ObIArray<int64_t>& index, common::ObIArray<common::ObString>& users,
common::ObIArray<common::ObString>& hosts)
{
int ret = OB_SUCCESS;
users.reset();
hosts.reset();
for (int64_t i = 0; OB_SUCC(ret) && i < index.count(); ++i) {
int64_t in = index.at(i);
if (OB_UNLIKELY(in < 0) || OB_UNLIKELY(in >= user_infos.count())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Userinfo index out of range", K(user_infos), K(index), K(in));
} else if (OB_FAIL(users.push_back(user_infos.at(in).get_user_name_str()))) {
LOG_WARN("Failed to add username", K(user_infos), K(index));
} else if (OB_FAIL(hosts.push_back(user_infos.at(in).get_host_name_str()))) {
LOG_WARN("Failed to add username", K(user_infos), K(index));
}
}
return ret;
}
int ObCreateUserExecutor::execute(ObExecContext& ctx, ObCreateUserStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const uint64_t tenant_id = stmt.get_tenant_id();
const ObStrings& users = stmt.get_users();
const bool if_not_exist = stmt.get_if_not_exists();
const int64_t FIX_MEMBER_CNT = 4;
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed");
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed");
} else if (OB_UNLIKELY(users.count() <= FIX_MEMBER_CNT) || OB_UNLIKELY(0 != users.count() % FIX_MEMBER_CNT)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Resolve create user error. Users should have user and pwd", "ObStrings count", users.count());
} else {
ObString user_name;
ObString host_name;
ObString pwd;
ObString need_enc;
ObString ssl_type;
ObString ssl_cipher;
ObString x509_issuer;
ObString x509_subject;
ObSSLType ssl_type_enum = ObSSLType::SSL_TYPE_NOT_SPECIFIED;
ObCreateUserArg& arg = static_cast<ObCreateUserArg&>(stmt.get_ddl_arg());
arg.tenant_id_ = tenant_id;
arg.user_infos_.reset();
arg.if_not_exist_ = if_not_exist;
const int64_t users_cnt = users.count() - FIX_MEMBER_CNT;
if (OB_FAIL(users.get_string(users_cnt, ssl_type))) {
LOG_WARN("Get string from ObStrings error", K(ret));
} else if (OB_FAIL(users.get_string(users_cnt + 1, ssl_cipher))) {
LOG_WARN("Get string from ObStrings error", K(ret));
} else if (OB_FAIL(users.get_string(users_cnt + 2, x509_issuer))) {
LOG_WARN("Get string from ObStrings error", K(ret));
} else if (OB_FAIL(users.get_string(users_cnt + 3, x509_subject))) {
LOG_WARN("Get string from ObStrings error", K(ret));
} else if (OB_UNLIKELY(ObSSLType::SSL_TYPE_MAX == (ssl_type_enum = get_ssl_type_from_string(ssl_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("known ssl_type", K(ssl_type), K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < users_cnt; i += FIX_MEMBER_CNT) {
if (OB_FAIL(users.get_string(i, user_name))) {
LOG_WARN("Get string from ObStrings error", "count", users.count(), K(i), K(ret));
} else if (OB_FAIL(users.get_string(i + 1, host_name))) {
LOG_WARN("Get string from ObStrings error", "count", users.count(), K(i), K(ret));
} else if (OB_FAIL(users.get_string(i + 2, pwd))) {
LOG_WARN("Get string from ObStrings error", "count", users.count(), K(i), K(ret));
} else if (OB_FAIL(users.get_string(i + 3, need_enc))) {
LOG_WARN("Get string from ObStrings error", "count", users.count(), K(i), K(ret));
} else {
ObUserInfo user_info;
if (ObString::make_string("YES") == need_enc) {
if (pwd.length() > 0) {
ObString pwd_enc;
char enc_buf[ENC_BUF_LEN] = {0};
if (OB_FAIL(encrypt_passwd(pwd, pwd_enc, enc_buf, ENC_BUF_LEN))) {
LOG_WARN("Encrypt password failed", K(ret));
} else if (OB_FAIL(user_info.set_passwd(pwd_enc))) {
LOG_WARN("set password failed", K(ret));
}
}
} else {
if (OB_FAIL(user_info.set_passwd(pwd))) {
LOG_WARN("Failed to set password", K(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(user_info.set_user_name(user_name))) {
LOG_WARN("set user name failed", K(ret));
} else if (OB_FAIL(user_info.set_host(host_name))) {
LOG_WARN("set host name failed", K(ret));
} else if (FALSE_IT(user_info.set_ssl_type(ssl_type_enum))) {
LOG_WARN("set ssl_type failed", K(ret));
} else if (OB_FAIL(user_info.set_ssl_cipher(ssl_cipher))) {
LOG_WARN("set ssl_cipher failed", K(ret));
} else if (OB_FAIL(user_info.set_x509_issuer(x509_issuer))) {
LOG_WARN("set x509_issuer failed", K(ret));
} else if (OB_FAIL(user_info.set_x509_subject(x509_subject))) {
LOG_WARN("set x509_subject failed", K(ret));
} else if (FALSE_IT(user_info.set_password_last_changed(ObTimeUtility::current_time()))) {
LOG_WARN("set set_password_last_changed failed", K(ret));
} else {
user_info.set_tenant_id(tenant_id);
if (user_name.empty()) {
user_info.set_user_id(combine_id(tenant_id, OB_EMPTY_USER_ID));
}
user_info.set_profile_id(stmt.get_profile_id());
if (OB_FAIL(arg.user_infos_.push_back(user_info))) {
LOG_WARN("Add user info to array error", K(ret));
} else {
LOG_DEBUG("Add user info to array", K(user_info));
}
}
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(create_user(common_rpc_proxy, arg))) {
LOG_WARN("Create user rpc failed", K(ret));
}
}
}
return ret;
}
int ObCreateUserExecutor::create_user(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObCreateUserArg& arg) const
{
int ret = OB_SUCCESS;
ObSArray<int64_t> failed_index;
ObSqlString fail_msg;
if (OB_ISNULL(rpc_proxy)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Input argument error", K(rpc_proxy), K(ret));
} else if (OB_FAIL(rpc_proxy->create_user(arg, failed_index))) {
LOG_WARN("Create user error", K(ret));
} else if (0 != failed_index.count()) {
ObSArray<ObString> failed_users;
ObSArray<ObString> failed_hosts;
if (OB_FAIL(userinfo_extract_user_name(arg.user_infos_, failed_index, failed_users, failed_hosts))) {
LOG_WARN("Failed to extract user name", K(arg.user_infos_), K(failed_index), K(ret));
} else if (OB_FAIL(ObDropUserExecutor::build_fail_msg(failed_users, failed_hosts, fail_msg))) {
LOG_WARN("Build fail msg error", K(ret));
} else {
ret = OB_CANNOT_USER;
LOG_USER_ERROR(OB_CANNOT_USER, (int)strlen("CREATE USER"), "CREATE USER", (int)fail_msg.length(), fail_msg.ptr());
}
} else {
// Create user completely success
}
return ret;
}
int ObDropUserExecutor::build_fail_msg(const common::ObIArray<common::ObString>& users,
const common::ObIArray<common::ObString>& hosts, common::ObSqlString& msg)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(users.count() < 1) || OB_UNLIKELY(users.count() != hosts.count())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(users.count()), K(hosts.count()), K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < users.count(); ++i) {
if (0 != i && OB_FAIL(msg.append_fmt(","))) {
LOG_WARN("Build msg fail", K(ret));
}
if (OB_SUCC(ret)) {
const ObString& user = users.at(i);
const ObString& host = hosts.at(i);
if (OB_UNLIKELY(user.empty()) || OB_UNLIKELY(host.empty())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Username is invalid", K(ret), K(user), K(host));
} else {
if (OB_FAIL(msg.append_fmt("'%.*s'@'%.*s'", user.length(), user.ptr(), host.length(), host.ptr()))) {
LOG_WARN("Build msg fail", K(user), K(host), K(ret));
} else {
// do nothing
}
}
}
}
}
return ret;
}
int ObDropUserExecutor::string_array_index_extract(const common::ObIArray<common::ObString>& src_users,
const common::ObIArray<common::ObString>& src_hosts, const common::ObIArray<int64_t>& index,
common::ObIArray<common::ObString>& dst_users, common::ObIArray<common::ObString>& dst_hosts)
{
int ret = OB_SUCCESS;
dst_users.reset();
dst_hosts.reset();
int64_t in = 0;
for (int64_t i = 0; OB_SUCC(ret) && i < index.count(); ++i) {
in = index.at(i);
if (in >= src_users.count() || in < 0) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("String index out of range", K(ret), K(in), K(src_users.count()));
} else if (OB_FAIL(dst_users.push_back(src_users.at(in)))) {
LOG_WARN("Failed to push back user", K(ret));
} else if (OB_FAIL(dst_hosts.push_back(src_hosts.at(in)))) {
LOG_WARN("Failed to push back host", K(ret));
// do nothing
}
}
return ret;
}
int ObDropUserExecutor::execute(ObExecContext& ctx, ObDropUserStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const uint64_t tenant_id = stmt.get_tenant_id();
const ObStrings* user_names = NULL;
if (OB_INVALID_ID == tenant_id) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("tenant is invalid", K(ret));
} else if (OB_ISNULL(user_names = stmt.get_users())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("names is NULL", K(ret));
} else if (OB_UNLIKELY(user_names->count() % 2 != 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("user not specified", K(ret));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed", K(ret));
} else if (NULL == (common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed", K(ret));
} else {
ObString user_name;
ObString host_name;
ObDropUserArg& arg = static_cast<ObDropUserArg&>(stmt.get_ddl_arg());
arg.tenant_id_ = tenant_id;
for (int64_t i = 0; OB_SUCC(ret) && i < user_names->count(); i += 2) {
if (OB_FAIL(user_names->get_string(i, user_name))) {
LOG_WARN("Get user name failed", K(ret));
} else if (OB_FAIL(user_names->get_string(i + 1, host_name))) {
LOG_WARN("Get host name failed", K(ret));
} else if (OB_FAIL(arg.users_.push_back(user_name))) {
LOG_WARN("Add user name failed", K(ret));
} else if (OB_FAIL(arg.hosts_.push_back(host_name))) {
LOG_WARN("Add host name failed", K(ret));
} else {
// do nothing
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(drop_user(common_rpc_proxy, arg))) {
LOG_WARN("Drop user completely failed", K(ret));
} else {
// do nothing
}
}
}
return ret;
}
int ObDropUserExecutor::drop_user(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObDropUserArg& arg)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!arg.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("arg is invalid", K(arg), K(ret));
} else if (OB_UNLIKELY(arg.users_.count() < 1)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("user not specified", K(ret));
} else if (OB_ISNULL(rpc_proxy)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("rpc_proxy is null", K(ret));
} else {
ObSArray<int64_t> failed_index;
ObSqlString fail_msg;
if (OB_FAIL(rpc_proxy->drop_user(arg, failed_index))) {
LOG_WARN("Lock user failed", K(ret));
if (OB_FAIL(ObDropUserExecutor::build_fail_msg(arg.users_, arg.hosts_, fail_msg))) {
LOG_WARN("Build fail msg error", K(arg), K(ret));
} else {
ret = OB_CANNOT_USER;
LOG_USER_ERROR(OB_CANNOT_USER, (int)strlen("DROP USER"), "DROP USER", (int)fail_msg.length(), fail_msg.ptr());
}
} else if (0 != failed_index.count()) {
ObSArray<ObString> failed_users;
ObSArray<ObString> failed_hosts;
if (OB_FAIL(ObDropUserExecutor::string_array_index_extract(
arg.users_, arg.hosts_, failed_index, failed_users, failed_hosts))) {
LOG_WARN("Failed to extract user name", K(arg), K(ret));
} else if (OB_FAIL(ObDropUserExecutor::build_fail_msg(failed_users, failed_hosts, fail_msg))) {
LOG_WARN("Build fail msg error", K(arg), K(ret));
} else {
ret = OB_CANNOT_USER;
LOG_USER_ERROR(OB_CANNOT_USER, (int)strlen("DROP USER"), "DROP USER", (int)fail_msg.length(), fail_msg.ptr());
}
} else {
// do nothing
}
}
return ret;
}
int ObLockUserExecutor::execute(ObExecContext& ctx, ObLockUserStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const uint64_t tenant_id = stmt.get_tenant_id();
const ObStrings* user_names = NULL;
if (OB_UNLIKELY(OB_INVALID_ID == tenant_id)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("tenant is invalid", K(ret));
} else if (OB_ISNULL(user_names = stmt.get_users())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("names is NULL", K(ret));
} else if (OB_UNLIKELY(user_names->count() % 2 != 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("user not specified", K(ret));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed", K(ret));
} else {
ObString user_name;
ObString host_name;
ObLockUserArg& arg = static_cast<ObLockUserArg&>(stmt.get_ddl_arg());
arg.tenant_id_ = tenant_id;
arg.locked_ = stmt.is_locked();
for (int64_t i = 0; OB_SUCC(ret) && i < user_names->count(); i += 2) {
if (OB_FAIL(user_names->get_string(i, user_name))) {
LOG_WARN("Get user name failed", K(ret));
} else if (OB_FAIL(user_names->get_string(i + 1, host_name))) {
LOG_WARN("Get host name failed", K(ret));
} else if (OB_FAIL(arg.users_.push_back(user_name))) {
LOG_WARN("Add user name failed", K(ret));
} else if (OB_FAIL(arg.hosts_.push_back(host_name))) {
LOG_WARN("Add host name failed", K(ret));
} else {
// do nothing
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(lock_user(common_rpc_proxy, arg))) {
LOG_WARN("Rename user completely failed", K(arg), K(ret));
} else {
// do nothing
}
}
}
return ret;
}
int ObLockUserExecutor::lock_user(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObLockUserArg& arg)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!arg.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("arg is invalid", K(arg), K(ret));
} else if (OB_UNLIKELY(arg.users_.count() < 1)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("user not specified", K(ret));
} else if (OB_ISNULL(rpc_proxy)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("rpc_proxy is null", K(ret));
} else {
ObSArray<int64_t> failed_index;
ObSqlString fail_msg;
if (OB_FAIL(rpc_proxy->lock_user(arg, failed_index))) {
LOG_WARN("Lock user failed", K(ret));
if (OB_FAIL(ObDropUserExecutor::build_fail_msg(arg.users_, arg.hosts_, fail_msg))) {
LOG_WARN("Build fail msg error", K(arg), K(ret));
} else {
ret = OB_CANNOT_USER;
LOG_USER_ERROR(OB_CANNOT_USER, (int)strlen("LOCK USER"), "LOCK USER", (int)fail_msg.length(), fail_msg.ptr());
}
} else if (0 != failed_index.count()) {
ObSArray<ObString> failed_users;
ObSArray<ObString> failed_hosts;
if (OB_FAIL(ObDropUserExecutor::string_array_index_extract(
arg.users_, arg.hosts_, failed_index, failed_users, failed_hosts))) {
LOG_WARN("Failed to extract user name", K(arg), K(ret));
} else {
if (OB_FAIL(ObDropUserExecutor::build_fail_msg(failed_users, failed_hosts, fail_msg))) {
LOG_WARN("Build fail msg error", K(arg), K(ret));
} else {
ret = OB_CANNOT_USER;
LOG_USER_ERROR(OB_CANNOT_USER, (int)strlen("LOCK USER"), "LOCK USER", (int)fail_msg.length(), fail_msg.ptr());
}
}
} else {
// do nothing
}
}
return ret;
}
int ObAlterUserProfileExecutor::set_role_exec(ObExecContext& ctx, ObAlterUserProfileStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* session = NULL;
uint64_t role_id = OB_INVALID_ID;
CK(1 == stmt.get_set_role_flag());
if (OB_ISNULL(session = ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session is NULL", K(ret));
} else {
const uint64_t tenant_id = session->get_effective_tenant_id();
int disable_flag = 0;
const ObUserInfo* user_info = NULL;
common::ObSEArray<uint64_t, 8>& enable_role_id_array = session->get_enable_role_array();
ObSchemaGetterGuard schema_guard;
obrpc::ObAlterUserProfileArg& arg = static_cast<obrpc::ObAlterUserProfileArg&>(stmt.get_ddl_arg());
OZ(GCTX.schema_service_->get_tenant_schema_guard(tenant_id, schema_guard));
OZ(schema_guard.get_user_info(session->get_user_id(), user_info));
if (OB_SUCC(ret) && NULL == user_info) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("user info is null", K(ret));
}
if (OB_SUCC(ret)) {
switch (arg.default_role_flag_) {
case OB_DEFAULT_ROLE_ALL:
OZ(session->set_enable_role_array(user_info->get_role_id_array()));
break;
case OB_DEFAULT_ROLE_NONE:
OX(enable_role_id_array.reset());
break;
case OB_DEFAULT_ROLE_LIST:
OX(enable_role_id_array.reset());
for (int i = 0; OB_SUCC(ret) && i < arg.role_id_array_.count(); i++) {
OX(role_id = arg.role_id_array_.at(i));
OZ(enable_role_id_array.push_back(role_id));
}
break;
case OB_DEFAULT_ROLE_ALL_EXCEPT:
int64_t idx;
OX(enable_role_id_array.reset());
/* scan all role granted to the user */
for (int i = 0; OB_SUCC(ret) && i < user_info->get_role_id_array().count(); i++) {
OX(role_id = user_info->get_role_id_array().at(i));
/* if not in execpt set, then push back */
if (OB_SUCC(ret) && !has_exist_in_array(arg.role_id_array_, role_id)) {
OZ(enable_role_id_array.push_back(role_id));
}
}
break;
}
OZ(enable_role_id_array.push_back(combine_id(session->get_effective_tenant_id(), OB_ORA_PUBLIC_ROLE_ID)));
}
}
return ret;
}
int ObAlterUserProfileExecutor::execute(ObExecContext& ctx, ObAlterUserProfileStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed", K(ret));
} else if (1 == stmt.get_set_role_flag()) {
OZ(set_role_exec(ctx, stmt));
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_FAIL(common_rpc_proxy->alter_user_profile(stmt.get_ddl_arg()))) {
LOG_WARN("alter user profile failed", K(stmt.get_ddl_arg()), K(ret));
}
return ret;
}
int ObRenameUserExecutor::execute(ObExecContext& ctx, ObRenameUserStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const uint64_t tenant_id = stmt.get_tenant_id();
const ObStrings* rename_infos = NULL;
if (OB_INVALID_ID == tenant_id) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("tenant is invalid", K(ret));
} else if (OB_ISNULL(rename_infos = stmt.get_rename_infos())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("names is NULL", K(ret));
} else if (rename_infos->count() < 1) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("user not specified", K(ret));
} else if (rename_infos->count() % 4 != 0) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("old and new names count not match", K(ret));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed", K(ret));
} else {
ObString old_username;
ObString old_hostname;
ObString new_username;
ObString new_hostname;
ObRenameUserArg& arg = static_cast<ObRenameUserArg&>(stmt.get_ddl_arg());
arg.tenant_id_ = tenant_id;
// rename_infos arr contains old names and new names in pairs, so step is 2
for (int64_t i = 0; OB_SUCC(ret) && i < rename_infos->count(); i += 4) {
if (OB_FAIL(rename_infos->get_string(i, old_username))) {
LOG_WARN("Get origin name failed", K(ret));
} else if (OB_FAIL(rename_infos->get_string(i + 1, old_hostname))) {
LOG_WARN("Get to name failed", K(ret));
} else if (OB_FAIL(rename_infos->get_string(i + 2, new_username))) {
LOG_WARN("Get to name failed", K(ret));
} else if (OB_FAIL(rename_infos->get_string(i + 3, new_hostname))) {
LOG_WARN("Get to name failed", K(ret));
} else if (OB_FAIL(arg.old_users_.push_back(old_username))) {
LOG_WARN("Add origin user name failed", K(ret));
} else if (OB_FAIL(arg.old_hosts_.push_back(old_hostname))) {
LOG_WARN("Add origin host name failed", K(ret));
} else if (OB_FAIL(arg.new_users_.push_back(new_username))) {
LOG_WARN("Add new user name failed", K(ret));
} else if (OB_FAIL(arg.new_hosts_.push_back(new_hostname))) {
LOG_WARN("Add new host name failed", K(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(rename_user(common_rpc_proxy, arg))) {
LOG_WARN("Rename user completely failed", K(arg), K(ret));
}
}
}
return ret;
}
int ObRenameUserExecutor::rename_user(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObRenameUserArg& arg)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!arg.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Invalid arg", K(arg), K(ret));
} else if (OB_UNLIKELY(arg.old_users_.count() < 1)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("user not specified", K(arg), K(ret));
} else if (OB_ISNULL(rpc_proxy)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("rpc_proxy is null", K(ret));
} else {
ObSArray<int64_t> failed_index;
ObSqlString fail_msg;
if (OB_FAIL(rpc_proxy->rename_user(arg, failed_index))) {
LOG_WARN("Rename user failed", K(ret));
if (OB_FAIL(ObDropUserExecutor::build_fail_msg(arg.old_users_, arg.old_hosts_, fail_msg))) {
LOG_WARN("Build fail msg error", K(arg), K(ret));
} else {
ret = OB_CANNOT_USER;
LOG_USER_ERROR(
OB_CANNOT_USER, (int)strlen("RENAME USER"), "RENAME USER", (int)fail_msg.length(), fail_msg.ptr());
}
} else if (0 != failed_index.count()) {
ObSArray<ObString> failed_users;
ObSArray<ObString> failed_hosts;
if (OB_FAIL(ObDropUserExecutor::string_array_index_extract(
arg.old_users_, arg.old_hosts_, failed_index, failed_users, failed_hosts))) {
LOG_WARN("Failed to extract user name", K(arg), K(ret));
} else {
if (OB_FAIL(ObDropUserExecutor::build_fail_msg(failed_users, failed_hosts, fail_msg))) {
LOG_WARN("Build fail msg error", K(arg), K(ret));
} else {
ret = OB_CANNOT_USER;
LOG_USER_ERROR(
OB_CANNOT_USER, (int)strlen("RENAME USER"), "RENAME USER", (int)fail_msg.length(), fail_msg.ptr());
}
}
} else {
// Rename user completely success
}
}
return ret;
}
int ObAlterUserPrimaryZoneExecutor::execute(ObExecContext& ctx, ObAlterUserPrimaryZoneStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
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_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("get task executor context failed", K(ret));
} else if (OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("get common rpc proxy failed", K(ret));
} else if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
stmt.arg_.exec_tenant_id_ = session->get_effective_tenant_id();
stmt.arg_.ddl_stmt_str_ = first_stmt;
OZ(common_rpc_proxy->alter_database(stmt.arg_));
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,129 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_CMD_USER_CMD_EXECUTOR_
#define OCEANBASE_SQL_ENGINE_CMD_USER_CMD_EXECUTOR_
#include "share/ob_define.h"
#include "lib/string/ob_string.h"
#include "lib/container/ob_array_serialization.h"
#include "share/schema/ob_schema_struct.h"
namespace oceanbase {
namespace obrpc {
class ObCommonRpcProxy;
class ObCreateUserArg;
class ObLockUserArg;
class ObRenameUserArg;
class ObDropUserArg;
} // namespace obrpc
namespace sql {
class ObExecContext;
class ObCreateUserStmt;
class ObDropUserExecutor;
class ObCreateUserExecutor {
public:
ObCreateUserExecutor()
{}
virtual ~ObCreateUserExecutor()
{}
int execute(ObExecContext& ctx, ObCreateUserStmt& stmt);
static int encrypt_passwd(
const common::ObString& passwd, common::ObString& encrypted_passwd, char* enc_buf, int64_t buf_len);
static int userinfo_extract_user_name(const common::ObIArray<share::schema::ObUserInfo>& user_infos,
const common::ObIArray<int64_t>& index, common::ObIArray<common::ObString>& users,
common::ObIArray<common::ObString>& hosts);
private:
int create_user(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObCreateUserArg& arg) const;
private:
DISALLOW_COPY_AND_ASSIGN(ObCreateUserExecutor);
};
class ObDropUserStmt;
class ObDropUserExecutor {
public:
ObDropUserExecutor()
{}
virtual ~ObDropUserExecutor()
{}
static int build_fail_msg(const common::ObIArray<common::ObString>& users,
const common::ObIArray<common::ObString>& hosts, common::ObSqlString& msg);
static int string_array_index_extract(const common::ObIArray<common::ObString>& src_users,
const common::ObIArray<common::ObString>& src_hosts, const common::ObIArray<int64_t>& index,
common::ObIArray<common::ObString>& dst_users, common::ObIArray<common::ObString>& dst_hosts);
int execute(ObExecContext& ctx, ObDropUserStmt& stmt);
private:
int drop_user(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObDropUserArg& arg);
DISALLOW_COPY_AND_ASSIGN(ObDropUserExecutor);
};
class ObLockUserStmt;
class ObLockUserExecutor {
public:
ObLockUserExecutor()
{}
virtual ~ObLockUserExecutor()
{}
int execute(ObExecContext& ctx, ObLockUserStmt& stmt);
private:
int lock_user(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObLockUserArg& arg);
DISALLOW_COPY_AND_ASSIGN(ObLockUserExecutor);
};
class ObAlterUserProfileStmt;
class ObAlterUserProfileExecutor {
private:
int set_role_exec(ObExecContext& ctx, ObAlterUserProfileStmt& stmt);
public:
ObAlterUserProfileExecutor()
{}
virtual ~ObAlterUserProfileExecutor()
{}
int execute(ObExecContext& ctx, ObAlterUserProfileStmt& stmt);
DISALLOW_COPY_AND_ASSIGN(ObAlterUserProfileExecutor);
};
class ObRenameUserStmt;
class ObRenameUserExecutor {
public:
ObRenameUserExecutor()
{}
virtual ~ObRenameUserExecutor()
{}
int execute(ObExecContext& ctx, ObRenameUserStmt& stmt);
private:
int rename_user(obrpc::ObCommonRpcProxy* rpc_proxy, const obrpc::ObRenameUserArg& arg);
DISALLOW_COPY_AND_ASSIGN(ObRenameUserExecutor);
};
class ObAlterUserPrimaryZoneStmt;
class ObAlterUserPrimaryZoneExecutor {
public:
ObAlterUserPrimaryZoneExecutor()
{}
virtual ~ObAlterUserPrimaryZoneExecutor()
{}
int execute(ObExecContext& ctx, ObAlterUserPrimaryZoneStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObAlterUserPrimaryZoneExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif // OCEANBASE_SQL_ENGINE_CMD_USER_CMD_EXECUTOR_

View File

@ -0,0 +1,871 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "lib/string/ob_sql_string.h"
#include "lib/mysqlclient/ob_mysql_proxy.h"
#include "common/sql_mode/ob_sql_mode_utils.h"
#include "observer/ob_server_struct.h"
#include "observer/ob_sql_client_decorator.h"
#include "share/ob_i_sql_expression.h"
#include "share/ob_schema_status_proxy.h"
#include "share/ob_common_rpc_proxy.h"
#include "share/object/ob_obj_cast.h"
#include "share/inner_table/ob_inner_table_schema.h"
#include "share/schema/ob_schema_utils.h"
#include "sql/engine/cmd/ob_variable_set_executor.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/engine/ob_physical_plan.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/code_generator/ob_expr_generator_impl.h"
#include "sql/code_generator/ob_column_index_provider.h"
#include "sql/ob_sql_trans_control.h"
#include "sql/ob_end_trans_callback.h"
#include "lib/timezone/ob_oracle_format_models.h"
using namespace oceanbase::common;
using namespace oceanbase::share;
using namespace oceanbase::share::schema;
namespace oceanbase {
namespace sql {
#define DEFINE_CAST_CTX() \
ObCollationType cast_coll_type = CS_TYPE_INVALID; \
if (NULL != ctx.get_my_session()) { \
if (common::OB_SUCCESS != ctx.get_my_session()->get_collation_connection(cast_coll_type)) { \
LOG_WARN("fail to get collation_connection"); \
cast_coll_type = ObCharset::get_default_collation(ObCharset::get_default_charset()); \
} else { \
} \
} else { \
LOG_WARN("session is null"); \
cast_coll_type = ObCharset::get_system_collation(); \
} \
const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(ctx.get_my_session()); \
ObCastCtx cast_ctx( \
&calc_buf, &dtc_params, get_cur_time(ctx.get_physical_plan_ctx()), CM_NONE, cast_coll_type, (NULL));
ObVariableSetExecutor::ObVariableSetExecutor()
{}
ObVariableSetExecutor::~ObVariableSetExecutor()
{}
int ObVariableSetExecutor::execute(ObExecContext& ctx, ObVariableSetStmt& stmt)
{
int ret = OB_SUCCESS;
int ret_ac = OB_SUCCESS;
ObSQLSessionInfo* session = NULL;
ObMySQLProxy* sql_proxy = NULL;
ObPhysicalPlanCtx* plan_ctx = NULL;
if (OB_ISNULL(session = ctx.get_my_session()) || OB_ISNULL(sql_proxy = ctx.get_sql_proxy()) ||
OB_ISNULL(plan_ctx = ctx.get_physical_plan_ctx())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session or sql proxy or physical plan ctx is NULL", K(ret), K(session), K(sql_proxy), K(plan_ctx));
} else {
ObPhysicalPlan phy_plan;
ObPhysicalPlanCtx phy_plan_ctx(ctx.get_allocator());
ObExprCtx expr_ctx;
phy_plan_ctx.set_phy_plan(&phy_plan);
phy_plan_ctx.set_last_insert_id_session(session->get_local_last_insert_id());
const int64_t cur_time =
plan_ctx->has_cur_time() ? plan_ctx->get_cur_time().get_timestamp() : ObTimeUtility::current_time();
phy_plan_ctx.set_cur_time(cur_time, *session);
expr_ctx.phy_plan_ctx_ = &phy_plan_ctx;
expr_ctx.my_session_ = session;
expr_ctx.exec_ctx_ = &ctx;
expr_ctx.calc_buf_ = &ctx.get_allocator();
if (OB_ISNULL(expr_ctx.exec_ctx_)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("expr_ctx.exec_ctx_ is NULL", K(ret));
} else {
expr_ctx.exec_ctx_->set_sql_proxy(sql_proxy);
}
ObVariableSetStmt::VariableSetNode tmp_node; // just for init node
for (int64_t i = 0; OB_SUCC(ret) && i < stmt.get_variables_size(); ++i) {
ObVariableSetStmt::VariableSetNode& node = tmp_node;
if (OB_FAIL(stmt.get_variable_node(i, node))) {
LOG_WARN("fail to get variable node", K(i), K(ret));
} else {
ObNewRow tmp_row;
ObObj value_obj;
ObBasicSysVar* sys_var = NULL;
RowDesc row_desc;
ObExprGeneratorImpl expr_gen(0, 0, NULL, row_desc);
ObSqlExpression sql_expr(ctx.get_allocator(), 0);
if (true == node.is_set_default_) {
if (false == node.is_system_variable_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("when reach here, node.is_system_variable_ must be true", K(ret));
} else {
}
} else {
if (OB_ISNULL(node.value_expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node.value_expr_ is NULL", K(ret));
} else {
if ((!node.is_system_variable_) || (!is_strict_mode(session->get_sql_mode()))) {
expr_ctx.cast_mode_ = CM_WARN_ON_FAIL;
} else {
}
if (OB_FAIL(expr_gen.generate(*node.value_expr_, sql_expr))) {
LOG_WARN("fail to fill sql expression", K(ret));
} else if (FALSE_IT(phy_plan.set_regexp_op_count(expr_gen.get_cur_regexp_op_count()))) {
} else if (FALSE_IT(phy_plan.set_like_op_count(expr_gen.get_cur_like_op_count()))) {
} else if (OB_FAIL(sql_expr.calc(expr_ctx, tmp_row, value_obj))) {
LOG_WARN("fail to calc value", K(ret), K(*node.value_expr_));
} else {
}
}
}
if (OB_FAIL(ret)) {
} else if (false == node.is_system_variable_) {
if (OB_FAIL(set_user_variable(value_obj, node.variable_name_, expr_ctx))) {
LOG_WARN("set user variable failed", K(ret));
}
} else {
ObSetVar set_var(node.variable_name_,
node.set_scope_,
node.is_set_default_,
stmt.get_actual_tenant_id(),
*expr_ctx.calc_buf_,
*sql_proxy);
ObObj out_obj;
const bool is_set_stmt = true;
if (OB_FAIL(session->get_sys_variable_by_name(node.variable_name_, sys_var))) {
if (OB_ERR_SYS_VARIABLE_UNKNOWN == ret) {
// session system variable not found, maybe latest data from proxy,
// so search in __all_sys_variable first.
const uint64_t tenant_id = session->get_effective_tenant_id();
const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id);
ObSQLClientRetryWeak sql_client_retry_weak(sql_proxy, exec_tenant_id, OB_ALL_SYS_VARIABLE_TID);
ObObj tmp_val;
ObSqlString sql;
SMART_VAR(ObMySQLProxy::MySQLResult, res)
{
sqlclient::ObMySQLResult* result = NULL;
if (OB_FAIL(sql.assign_fmt("select 1 from %s where tenant_id=%lu and name='%.*s';",
OB_ALL_SYS_VARIABLE_TNAME,
ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id),
node.variable_name_.length(),
node.variable_name_.ptr()))) {
LOG_WARN("assign sql string failed", K(ret));
} else if (OB_FAIL(sql_client_retry_weak.read(res, exec_tenant_id, sql.ptr()))) {
LOG_WARN("execute sql failed", K(sql), K(ret));
} else if (OB_ISNULL(result = res.get_result())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to get sql result", K(ret));
} else if (OB_FAIL(result->next())) {
if (OB_ITER_END == ret) {
// not found in inner table, means it is not a system variable
ret = OB_ERR_SYS_VARIABLE_UNKNOWN;
LOG_USER_ERROR(
OB_ERR_SYS_VARIABLE_UNKNOWN, node.variable_name_.length(), node.variable_name_.ptr());
} else {
LOG_WARN("get result failed", K(ret));
}
} else {
// found in __all_sys_variable, means it's caused by version compatibility.
// return OB_SYS_VARS_MAYBE_DIFF_VERSION, set OB_SUCCESS later.
ret = OB_SYS_VARS_MAYBE_DIFF_VERSION;
LOG_INFO("try to set sys var from new version, ignore it", K(ret), K(node.variable_name_));
}
}
} else {
LOG_WARN("fail to get system variable", K(ret), K(node.variable_name_));
}
} else if (OB_ISNULL(sys_var)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("sys_var is NULL", K(ret), K(node.variable_name_));
} else if (!share::is_mysql_mode() && sys_var->is_mysql_only()) {
// ignore set mysql only variables in oracle mode
} else if (!share::is_oracle_mode() && sys_var->is_oracle_only()) {
// ignore set oracle only variables in mysql mode
} else {
if (OB_FAIL(check_and_convert_sys_var(ctx, set_var, *sys_var, value_obj, out_obj, is_set_stmt))) {
LOG_WARN("fail to check", K(ret), K(node), K(*sys_var), K(value_obj));
} else if (FALSE_IT(value_obj = out_obj)) {
} else if (OB_FAIL(cast_value(ctx,
node,
stmt.get_actual_tenant_id(),
*expr_ctx.calc_buf_,
*sys_var,
value_obj,
out_obj))) {
LOG_WARN("fail to cast value", K(ret), K(node), K(*sys_var), K(value_obj));
} else if (FALSE_IT(value_obj = out_obj)) {
} else if (node.variable_name_ == OB_SV_AUTO_INCREMENT_INCREMENT ||
node.variable_name_ == OB_SV_AUTO_INCREMENT_OFFSET) {
if (OB_FAIL(process_auto_increment_hook(session->get_sql_mode(), node.variable_name_, value_obj))) {
LOG_WARN("fail to process auto increment hook", K(ret));
} else {
}
} else if (node.variable_name_ == OB_SV_LAST_INSERT_ID) {
if (OB_FAIL(
process_last_insert_id_hook(plan_ctx, session->get_sql_mode(), node.variable_name_, value_obj))) {
LOG_WARN("fail to process auto increment hook", K(ret));
} else {
}
} else if (ObSetVar::SET_SCOPE_GLOBAL == node.set_scope_ &&
node.variable_name_ == OB_SV_STMT_PARALLEL_DEGREE) {
const static int64_t PARALLEL_DEGREE_VALID_VALUE = 1;
int64_t parallel_degree_set_val = -1;
if (OB_FAIL(value_obj.get_int(parallel_degree_set_val))) {
LOG_WARN("fail to get int64_t from value_obj", K(ret), K(value_obj));
} else if (PARALLEL_DEGREE_VALID_VALUE != parallel_degree_set_val) {
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
char buf[32];
(void)databuff_printf(buf, 32, "%ld", parallel_degree_set_val);
ObString value(buf);
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR,
node.variable_name_.length(),
node.variable_name_.ptr(),
value.length(),
value.ptr());
}
} else {
}
if (OB_FAIL(ret)) {
} else if (ObSetVar::SET_SCOPE_SESSION == node.set_scope_) {
// handle autocommit case, must call before update_sys_variable,
// because update_sys_variable will change value of ac.
if (node.variable_name_ == OB_SV_AUTOCOMMIT) {
if (OB_UNLIKELY(OB_SUCCESS != (ret_ac = process_session_autocommit_hook(ctx, value_obj)))) {
LOG_WARN("fail to process session autocommit", K(ret), K(ret_ac));
if (OB_ERR_WRONG_VALUE_FOR_VAR == ret_ac) {
ret = ret_ac;
}
} else {
}
} else {
}
}
if (OB_FAIL(ret)) {
} else if (set_var.var_name_ == OB_SV_READ_ONLY) {
if (session->get_in_transaction()) {
ret = OB_ERR_LOCK_OR_ACTIVE_TRANSACTION;
LOG_WARN("Can't execute the given command because "
"you have active locked tables or an active transaction",
K(ret));
} else {
}
} else {
}
if (OB_FAIL(ret)) {
} else if (set_var.var_name_ == OB_SV_COMPATIBILITY_MODE) {
if (!(OB_SYS_TENANT_ID == session->get_effective_tenant_id()) || !GCONF.in_upgrade_mode()) {
ret = OB_OP_NOT_ALLOW;
LOG_WARN("Compatibility mode can be changed only under upgrade mode and system tenant",
K(ret),
K(session->get_effective_tenant_id()));
LOG_USER_ERROR(
OB_OP_NOT_ALLOW, "Compatibility mode be changed not under upgrade mode and system tenant");
} else if (ObSetVar::SET_SCOPE_SESSION != set_var.set_scope_) {
ret = OB_OP_NOT_ALLOW;
LOG_WARN("Compatibility mode can be changed only under session scope",
K(ret),
K(session->get_effective_tenant_id()));
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "Compatibility mode be changed not in session scope");
}
} else {
}
if (OB_SUCC(ret) && set_var.set_scope_ == ObSetVar::SET_SCOPE_GLOBAL) {
if (OB_FAIL(update_global_variables(ctx, stmt, set_var, value_obj))) {
LOG_WARN("failed to update global variables", K(ret));
} else {
}
}
if (OB_SUCC(ret) && set_var.set_scope_ == ObSetVar::SET_SCOPE_SESSION) {
if (OB_FAIL(sys_var->session_update(ctx, set_var, value_obj))) {
LOG_WARN("fail to update", K(ret), K(*sys_var), K(set_var), K(value_obj));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(sys_var->update(ctx, set_var, value_obj))) {
LOG_WARN("update sys var state failed", K(ret), K(set_var));
}
}
}
}
}
if (OB_SYS_VARS_MAYBE_DIFF_VERSION == ret) {
ret = OB_SUCCESS;
}
}
}
if (OB_SUCCESS != ret_ac) {
ret = ret_ac;
}
return ret;
}
int ObVariableSetExecutor::set_user_variable(const ObObj& val, const ObString& variable_name, const ObExprCtx& expr_ctx)
{
int ret = OB_SUCCESS;
// user defined tmp variable
ObSQLSessionInfo* session = expr_ctx.my_session_;
ObSessionVariable sess_var;
if (OB_ISNULL(session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session is null", K(ret));
} else if (OB_FAIL(switch_to_session_variable(expr_ctx, val, sess_var))) {
LOG_WARN("fail to stiwch to session variablee", K(ret), K(val));
} else if (OB_FAIL(session->replace_user_variable(variable_name, sess_var))) {
LOG_WARN("set variable to session plan failed", K(ret), K(variable_name));
} else {
}
return ret;
}
int ObVariableSetExecutor::update_global_variables(
ObExecContext& ctx, ObDDLStmt& stmt, const ObSetVar& set_var, const ObObj& val)
{
int ret = OB_SUCCESS;
obrpc::ObRpcOpts rpc_opt;
ObSQLSessionInfo* session = NULL;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
obrpc::ObModifySysVarArg& arg = static_cast<obrpc::ObModifySysVarArg&>(stmt.get_ddl_arg());
ObString extra_var_name;
ObString extra_var_value;
ObString extra_val;
ObString val_str;
ObCollationType extra_coll_type = CS_TYPE_INVALID;
char extra_var_value_buf[32] = {'\0'};
int64_t pos = 0;
bool should_update_extra_var = false;
if (OB_ISNULL(session = ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session is NULL", K(ret));
} else {
arg.tenant_id_ = set_var.actual_tenant_id_;
arg.exec_tenant_id_ = set_var.actual_tenant_id_;
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else {
arg.ddl_stmt_str_ = first_stmt;
}
if (OB_FAIL(ret)) {
} else if (set_var.var_name_ == OB_SV_COLLATION_SERVER || set_var.var_name_ == OB_SV_COLLATION_DATABASE ||
set_var.var_name_ == OB_SV_COLLATION_CONNECTION) {
ObString coll_str;
int64_t coll_int64 = OB_INVALID_INDEX;
if (OB_FAIL(val.get_int(coll_int64))) {
LOG_WARN("get int from val failed", K(ret));
} else if (OB_UNLIKELY(!ObCharset::is_valid_collation(coll_int64))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid collation", K(ret), K(coll_int64), K(val));
} else if (FALSE_IT(coll_str = ObString::make_string(
ObCharset::collation_name(static_cast<ObCollationType>(coll_int64))))) {
// do nothing
} else if (OB_FAIL(ObBasicSysVar::get_charset_var_and_val_by_collation(
set_var.var_name_, coll_str, extra_var_name, extra_val, extra_coll_type))) {
LOG_ERROR(
"fail to get charset variable and value by collation", K(ret), K(set_var.var_name_), K(val), K(coll_str));
} else if (OB_FAIL(databuff_printf(extra_var_value_buf,
sizeof(extra_var_value_buf),
pos,
"%d",
static_cast<int32_t>(extra_coll_type)))) {
LOG_WARN("databuff printf failed", K(extra_coll_type), K(ret));
} else {
extra_var_value.assign(extra_var_value_buf, pos);
should_update_extra_var = true;
}
} else if (set_var.var_name_ == OB_SV_CHARACTER_SET_SERVER || set_var.var_name_ == OB_SV_CHARACTER_SET_DATABASE ||
set_var.var_name_ == OB_SV_CHARACTER_SET_CONNECTION) {
ObString cs_str;
int64_t coll_int64 = OB_INVALID_INDEX;
if (OB_FAIL(val.get_int(coll_int64))) {
LOG_WARN("get int from value failed", K(ret));
} else if (OB_UNLIKELY(!ObCharset::is_valid_collation(coll_int64))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid collation", K(ret), K(coll_int64));
} else if (FALSE_IT(cs_str = ObString::make_string(ObCharset::charset_name(
ObCharset::charset_type_by_coll(static_cast<ObCollationType>(coll_int64)))))) {
// do nothing
} else if (OB_FAIL(ObBasicSysVar::get_collation_var_and_val_by_charset(
set_var.var_name_, cs_str, extra_var_name, extra_val, extra_coll_type))) {
LOG_ERROR(
"fail to get collation variable and value by charset", K(ret), K(set_var.var_name_), K(val), K(cs_str));
} else if (OB_FAIL(databuff_printf(extra_var_value_buf,
sizeof(extra_var_value_buf),
pos,
"%d",
static_cast<int32_t>(extra_coll_type)))) {
LOG_WARN("databuff printf failed", K(extra_coll_type), K(ret));
} else {
extra_var_value.assign(extra_var_value_buf, pos);
should_update_extra_var = true;
}
} else if (set_var.var_name_ == OB_SV_NLS_DATE_FORMAT || set_var.var_name_ == OB_SV_NLS_TIMESTAMP_FORMAT ||
set_var.var_name_ == OB_SV_NLS_TIMESTAMP_TZ_FORMAT) {
ObString format;
if (OB_UNLIKELY(val.is_null_oracle())) {
ret = OB_INVALID_DATE_FORMAT;
LOG_WARN("date format not recognized", K(ret), K(set_var.var_name_), K(val));
} else if (OB_FAIL(val.get_varchar(format))) {
LOG_WARN("fail get varchar", K(val), K(ret));
} else {
int64_t nls_enum = ObNLSFormatEnum::NLS_DATE;
ObDTMode mode = DT_TYPE_DATETIME;
if (set_var.var_name_ == OB_SV_NLS_TIMESTAMP_FORMAT) {
mode |= DT_TYPE_ORACLE;
nls_enum = ObNLSFormatEnum::NLS_TIMESTAMP;
} else if (set_var.var_name_ == OB_SV_NLS_TIMESTAMP_TZ_FORMAT) {
mode |= DT_TYPE_ORACLE;
mode |= DT_TYPE_TIMEZONE;
nls_enum = ObNLSFormatEnum::NLS_TIMESTAMP_TZ;
}
ObSEArray<ObDFMElem, ObDFMUtil::COMMON_ELEMENT_NUMBER> dfm_elems;
ObBitSet<ObDFMFlag::MAX_FLAG_NUMBER> elem_flags;
// 1. parse and check semantic of format string
if (OB_FAIL(ObDFMUtil::parse_datetime_format_string(format, dfm_elems))) {
LOG_WARN("fail to parse oracle datetime format string", K(ret), K(format));
} else if (OB_FAIL(ObDFMUtil::check_semantic(dfm_elems, elem_flags, mode))) {
LOG_WARN("check semantic of format string failed", K(ret), K(format));
}
}
} else if (set_var.var_name_ == OB_SV_LOG_LEVEL) {
ObString log_level;
if (OB_FAIL(val.get_varchar(log_level))) {
LOG_WARN("fail get varchar", K(val), K(ret));
} else if (0 == log_level.case_compare("disabled")) {
// allowed for variables
} else if (OB_FAIL(OB_LOGGER.parse_check(log_level.ptr(), log_level.length()))) {
LOG_WARN("Log level parse check error", K(log_level), K(ret));
}
} else if (set_var.var_name_ == OB_SV_TRANSACTION_ISOLATION) {
extra_var_name = ObString::make_string(OB_SV_TX_ISOLATION);
should_update_extra_var = true;
if (OB_FAIL(val.get_varchar(extra_var_value))) {
LOG_WARN("fail get varchar", K(val), K(ret));
}
} else if (set_var.var_name_ == OB_SV_TX_ISOLATION) {
extra_var_name = ObString::make_string(OB_SV_TRANSACTION_ISOLATION);
should_update_extra_var = true;
if (OB_FAIL(val.get_varchar(extra_var_value))) {
LOG_WARN("fail get varchar", K(val), K(ret));
}
} else if (set_var.var_name_ == OB_SV_TX_READ_ONLY) {
int64_t extra_var_values = -1;
extra_var_name = ObString::make_string(OB_SV_TRANSACTION_READ_ONLY);
if (OB_FAIL(val.get_int(extra_var_values))) {
LOG_WARN("fail get int", K(val), K(ret));
} else if (OB_FAIL(databuff_printf(extra_var_value_buf,
sizeof(extra_var_value_buf),
pos,
"%d",
static_cast<int32_t>(extra_var_values)))) {
LOG_WARN("databuff printf failed", K(extra_var_values), K(ret));
} else {
extra_var_value.assign(extra_var_value_buf, pos);
should_update_extra_var = true;
}
} else if (set_var.var_name_ == OB_SV_TRANSACTION_READ_ONLY) {
extra_var_name = ObString::make_string(OB_SV_TX_READ_ONLY);
int64_t extra_var_values = -1;
if (OB_FAIL(val.get_int(extra_var_values))) {
LOG_WARN("fail get int", K(val), K(ret));
} else if (OB_FAIL(databuff_printf(extra_var_value_buf,
sizeof(extra_var_value_buf),
pos,
"%d",
static_cast<int32_t>(extra_var_values)))) {
LOG_WARN("databuff printf failed", K(extra_var_values), K(ret));
} else {
extra_var_value.assign(extra_var_value_buf, pos);
should_update_extra_var = true;
}
}
if (OB_SUCC(ret) && should_update_extra_var) {
ObSysVarSchema sysvar_schema;
if (OB_FAIL(sysvar_schema.set_name(extra_var_name))) {
LOG_WARN("set sysvar schema name failed", K(ret));
} else if (OB_FAIL(sysvar_schema.set_value(extra_var_value))) {
LOG_WARN("set sysvar schema value failed", K(ret));
} else {
sysvar_schema.set_tenant_id(arg.tenant_id_);
if (OB_FAIL(arg.sys_var_list_.push_back(sysvar_schema))) {
LOG_WARN("store sys var to array failed", K(ret));
}
}
}
}
if (OB_SUCC(ret)) {
ObExprCtx expr_ctx;
expr_ctx.exec_ctx_ = &ctx;
expr_ctx.calc_buf_ = &set_var.calc_buf_;
expr_ctx.my_session_ = ctx.get_my_session();
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_NONE);
EXPR_GET_VARCHAR_V2(val, val_str);
ObSysVarSchema sysvar_schema;
if (OB_UNLIKELY(val_str.length() > OB_MAX_SYS_VAR_VAL_LENGTH)) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("set sysvar value is overflow",
"max length",
OB_MAX_SYS_VAR_VAL_LENGTH,
"value length",
val_str.length(),
"name",
set_var.var_name_,
"value",
val_str);
} else if (OB_FAIL(sysvar_schema.set_name(set_var.var_name_))) {
LOG_WARN("set sysvar schema name failed", K(ret));
} else if (OB_FAIL(sysvar_schema.set_value(val_str))) {
LOG_WARN("set sysvar schema value failed", K(ret));
} else {
sysvar_schema.set_tenant_id(arg.tenant_id_);
if (OB_FAIL(arg.sys_var_list_.push_back(sysvar_schema))) {
LOG_WARN("store sys var to array failed", K(ret));
}
}
}
if (OB_SUCC(ret)) {
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx)) ||
OB_ISNULL(common_rpc_proxy = task_exec_ctx->get_common_rpc())) {
ret = OB_NOT_INIT;
LOG_WARN("task exec ctx or common rpc proxy is NULL", K(ret), K(task_exec_ctx), K(common_rpc_proxy));
} else if (OB_FAIL(common_rpc_proxy->modify_system_variable(arg))) {
LOG_WARN("rpc proxy alter system variable failed", K(ret));
} else {
}
}
return ret;
}
int ObVariableSetExecutor::check_and_convert_sys_var(ObExecContext& ctx, const ObSetVar& set_var,
ObBasicSysVar& sys_var, const ObObj& in_val, ObObj& out_val, bool is_set_stmt)
{
int ret = OB_SUCCESS;
// OB_ASSERT(true == var_node.is_system_variable_);
// can't set collation_connection to utf16
if (OB_SUCC(ret)) {
if ((0 == set_var.var_name_.case_compare(OB_SV_CHARACTER_SET_CLIENT) ||
0 == set_var.var_name_.case_compare(OB_SV_CHARACTER_SET_CONNECTION) ||
0 == set_var.var_name_.case_compare(OB_SV_CHARACTER_SET_RESULTS) ||
0 == set_var.var_name_.case_compare(OB_SV_COLLATION_CONNECTION)) &&
(in_val.get_string().prefix_match_ci("utf16"))) {
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR,
set_var.var_name_.length(),
set_var.var_name_.ptr(),
in_val.get_string().length(),
in_val.get_string().ptr());
}
}
// check readonly
if (is_set_stmt && sys_var.is_readonly()) {
if (sys_var.is_with_upgrade() && GCONF.in_upgrade_mode()) {
// do nothing ...
} else {
ret = OB_ERR_INCORRECT_GLOBAL_LOCAL_VAR;
LOG_USER_ERROR(OB_ERR_INCORRECT_GLOBAL_LOCAL_VAR,
set_var.var_name_.length(),
set_var.var_name_.ptr(),
(int)strlen("read only"),
"read only");
}
}
// check scope
if (OB_FAIL(ret)) {
} else if (ObSetVar::SET_SCOPE_GLOBAL == set_var.set_scope_ && !sys_var.is_global_scope()) {
ret = OB_ERR_LOCAL_VARIABLE;
LOG_USER_ERROR(OB_ERR_LOCAL_VARIABLE, set_var.var_name_.length(), set_var.var_name_.ptr());
} else if (ObSetVar::SET_SCOPE_SESSION == set_var.set_scope_ && !sys_var.is_session_scope()) {
ret = OB_ERR_GLOBAL_VARIABLE;
LOG_USER_ERROR(OB_ERR_GLOBAL_VARIABLE, set_var.var_name_.length(), set_var.var_name_.ptr());
}
// check update type and value
if (OB_FAIL(ret)) {
} else if (OB_SUCCESS != (ret = sys_var.check_update_type(set_var, in_val))) {
if (OB_ERR_WRONG_TYPE_FOR_VAR == ret) {
LOG_USER_ERROR(OB_ERR_WRONG_TYPE_FOR_VAR, set_var.var_name_.length(), set_var.var_name_.ptr());
} else {
LOG_WARN("fail to check update type", K(ret));
}
} else if (OB_FAIL(sys_var.check_and_convert(ctx, set_var, in_val, out_val))) {
if (OB_ERR_WRONG_TYPE_FOR_VAR == ret) {
LOG_USER_ERROR(OB_ERR_WRONG_TYPE_FOR_VAR, set_var.var_name_.length(), set_var.var_name_.ptr());
} else {
LOG_WARN("fail to check value", K(ret));
}
}
// do not support modify now
if (OB_FAIL(ret)) {
} else if (share::is_oracle_mode() && set_var.var_name_.prefix_match("nls_")) {
static const common::ObString DEFAULT_VALUE_LANGUAGE("AMERICAN");
static const common::ObString DEFAULT_VALUE_TERRITORY("AMERICA");
static const common::ObString DEFAULT_VALUE_SORT("BINARY");
static const common::ObString DEFAULT_VALUE_COMP("BINARY");
static const common::ObString DEFAULT_VALUE_NCHAR_CHARACTERSET("AL16UTF16");
static const common::ObString DEFAULT_VALUE_DATE_LANGUAGE("AMERICAN");
static const common::ObString DEFAULT_VALUE_NCHAR_CONV_EXCP("FALSE");
static const common::ObString DEFAULT_VALUE_CALENDAR("GREGORIAN");
static const common::ObString DEFAULT_VALUE_NUMERIC_CHARACTERS(".,");
static const common::ObString DEFAULT_VALUE_CURRENCY("$");
static const common::ObString DEFAULT_VALUE_ISO_CURRENCY("AMERICA");
static const common::ObString DEFAULT_VALUE_DUAL_CURRENCY("$");
const ObString new_value = out_val.get_string();
if ((set_var.var_name_ == OB_SV_NLS_LANGUAGE && new_value.case_compare(DEFAULT_VALUE_LANGUAGE) != 0) ||
(set_var.var_name_ == OB_SV_NLS_TERRITORY && new_value.case_compare(DEFAULT_VALUE_TERRITORY) != 0) ||
(set_var.var_name_ == OB_SV_NLS_SORT && new_value.case_compare(DEFAULT_VALUE_SORT) != 0) ||
(set_var.var_name_ == OB_SV_NLS_COMP && new_value.case_compare(DEFAULT_VALUE_COMP) != 0) ||
(set_var.var_name_ == OB_SV_NLS_CHARACTERSET) ||
(set_var.var_name_ == OB_SV_NLS_NCHAR_CHARACTERSET &&
new_value.case_compare(DEFAULT_VALUE_NCHAR_CHARACTERSET) != 0) ||
(set_var.var_name_ == OB_SV_NLS_DATE_LANGUAGE && new_value.case_compare(DEFAULT_VALUE_DATE_LANGUAGE) != 0) ||
(set_var.var_name_ == OB_SV_NLS_NCHAR_CONV_EXCP &&
new_value.case_compare(DEFAULT_VALUE_NCHAR_CONV_EXCP) != 0) ||
(set_var.var_name_ == OB_SV_NLS_CALENDAR && new_value.case_compare(DEFAULT_VALUE_CALENDAR) != 0) ||
(set_var.var_name_ == OB_SV_NLS_NUMERIC_CHARACTERS &&
new_value.case_compare(DEFAULT_VALUE_NUMERIC_CHARACTERS) != 0) ||
(set_var.var_name_ == OB_SV_NLS_CURRENCY && new_value.case_compare(DEFAULT_VALUE_CURRENCY) != 0) ||
(set_var.var_name_ == OB_SV_NLS_ISO_CURRENCY && new_value.case_compare(DEFAULT_VALUE_ISO_CURRENCY) != 0) ||
(set_var.var_name_ == OB_SV_NLS_DUAL_CURRENCY && new_value.case_compare(DEFAULT_VALUE_DUAL_CURRENCY) != 0)) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("not support modify this variables now", K(set_var), K(new_value), K(ret));
}
}
return ret;
}
int ObVariableSetExecutor::cast_value(ObExecContext& ctx, const ObVariableSetStmt::VariableSetNode& var_node,
uint64_t actual_tenant_id, ObIAllocator& calc_buf, const ObBasicSysVar& sys_var, const ObObj& in_val,
ObObj& out_val)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(GCTX.schema_service_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("schema_service_ is null");
} else if (OB_ISNULL(ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("my session is null");
} else if (var_node.is_set_default_) {
uint64_t tenant_id = actual_tenant_id;
if (ObSetVar::SET_SCOPE_SESSION == var_node.set_scope_) {
ObSchemaGetterGuard schema_guard;
const ObSysVarSchema* var_schema = NULL;
const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(ctx.get_my_session());
if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) {
LOG_WARN("get schema guard failed", K(ret));
} else if (OB_FAIL(schema_guard.get_tenant_system_variable(tenant_id, var_node.variable_name_, var_schema))) {
LOG_WARN("get tenant system variable failed", K(ret), K(tenant_id), K(var_node.variable_name_));
} else if (OB_FAIL(var_schema->get_value(&calc_buf, dtc_params, out_val))) {
LOG_WARN("get value from sysvar schema failed", K(ret));
}
} else if (ObSetVar::SET_SCOPE_GLOBAL == var_node.set_scope_) {
const ObObj& def_val = sys_var.get_global_default_value();
DEFINE_CAST_CTX();
if (OB_FAIL(ObObjCaster::to_type(sys_var.get_data_type(), cast_ctx, def_val, out_val))) {
LOG_ERROR("failed to cast object", K(ret), K(var_node.variable_name_), K(def_val), K(sys_var.get_data_type()));
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid set scope", K(ret), K(var_node.set_scope_));
}
} else if (ObNullType == in_val.get_type()) {
out_val = in_val;
} else {
DEFINE_CAST_CTX();
if (OB_FAIL(ObObjCaster::to_type(sys_var.get_data_type(), cast_ctx, in_val, out_val))) {
LOG_WARN("failed to cast object", K(ret), K(var_node.variable_name_), K(in_val), K(sys_var.get_data_type()));
} else {
}
}
return ret;
}
int ObVariableSetExecutor::process_session_autocommit_hook(ObExecContext& exec_ctx, const ObObj& val)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* my_session = GET_MY_SESSION(exec_ctx);
if (OB_ISNULL(my_session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session is NULL", K(ret));
} else {
int64_t autocommit = 0;
bool in_trans = my_session->get_in_transaction();
bool ac = true;
if (OB_FAIL(my_session->get_autocommit(ac))) {
LOG_WARN("fail to get autocommit", K(ret));
} else if (OB_FAIL(val.get_int(autocommit))) {
LOG_WARN("fail get commit val", K(val), K(ret));
} else if (0 != autocommit && 1 != autocommit) {
const char* autocommit_str = to_cstring(autocommit);
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR,
(int)strlen(OB_SV_AUTOCOMMIT),
OB_SV_AUTOCOMMIT,
(int)strlen(autocommit_str),
autocommit_str);
} else {
if (false == ac && true == in_trans && 1 == autocommit) {
ObEndTransSyncCallback callback;
const bool is_rollback = false;
if (OB_FAIL(callback.init(&(my_session->get_trans_desc()), my_session))) {
LOG_WARN("fail init callback", K(ret));
} else {
int wait_ret = OB_SUCCESS;
if (OB_FAIL(ObSqlTransControl::implicit_end_trans(
exec_ctx, is_rollback, callback))) { // implicit commit, no rollback
LOG_WARN("fail end implicit trans", K(is_rollback), K(ret));
}
if (OB_UNLIKELY(OB_SUCCESS != (wait_ret = callback.wait()))) {
LOG_WARN("sync end trans callback return an error!",
K(ret),
K(wait_ret),
K(is_rollback),
K(my_session->get_trans_desc()));
}
ret = OB_SUCCESS != ret ? ret : wait_ret;
}
} else {
}
}
}
return ret;
}
int ObVariableSetExecutor::process_auto_increment_hook(const ObSQLMode sql_mode, const ObString var_name, ObObj& val)
{
int ret = OB_SUCCESS;
uint64_t auto_increment = 0;
if (OB_FAIL(val.get_uint64(auto_increment))) {
LOG_WARN("fail get auto_increment value", K(ret), K(val));
} else {
if (SMO_STRICT_ALL_TABLES & sql_mode) {
if (auto_increment <= 0 || auto_increment > UINT16_MAX) {
char auto_increment_str[OB_CAST_TO_VARCHAR_MAX_LENGTH];
int length = snprintf(auto_increment_str, OB_CAST_TO_VARCHAR_MAX_LENGTH, "%lu", auto_increment);
if (length < 0 || length >= OB_CAST_TO_VARCHAR_MAX_LENGTH) {
length = OB_CAST_TO_VARCHAR_MAX_LENGTH - 1;
auto_increment_str[length] = '\0';
}
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, var_name.length(), var_name.ptr(), length, auto_increment_str);
}
} else {
if (auto_increment <= 0) {
auto_increment = 1;
// should generate warning message
// SQL_ENG_LOG(WARN, "Truncated incorrect value");
} else if (auto_increment > UINT16_MAX) {
auto_increment = UINT16_MAX;
// should generate warning message
// SQL_ENG_LOG(WARN, "Truncated incorrect value");
}
val.set_uint64(auto_increment);
}
}
return ret;
}
int ObVariableSetExecutor::process_last_insert_id_hook(
ObPhysicalPlanCtx* plan_ctx, const ObSQLMode sql_mode, const ObString var_name, ObObj& val)
{
int ret = OB_SUCCESS;
int64_t value = 0;
uint64_t unsigned_value = 0;
if (OB_ISNULL(plan_ctx)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("plan ctx is NULL", K(ret));
} else if (OB_FAIL(val.get_int(value))) {
if (OB_FAIL(val.get_uint64(unsigned_value))) {
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
LOG_WARN("failed to get value", K(val), K(ret));
}
} else {
if (SMO_STRICT_ALL_TABLES & sql_mode) {
if (value < 0) {
char auto_increment_str[OB_CAST_TO_VARCHAR_MAX_LENGTH];
int32_t length = snprintf(auto_increment_str, OB_CAST_TO_VARCHAR_MAX_LENGTH, "%ld", value);
if (length < 0 || length >= OB_CAST_TO_VARCHAR_MAX_LENGTH) {
length = OB_CAST_TO_VARCHAR_MAX_LENGTH - 1;
auto_increment_str[length] = '\0';
}
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, var_name.length(), var_name.ptr(), length, auto_increment_str);
}
} else {
if (value < 0) {
value = 0;
// should generate warning message
// SQL_ENG_LOG(WARN, "Truncated incorrect value");
}
val.set_int(value);
}
}
if (OB_SUCC(ret)) {
if (0 != unsigned_value) {
plan_ctx->set_last_insert_id_session(unsigned_value);
} else {
plan_ctx->set_last_insert_id_session(static_cast<uint64_t>(value));
}
}
return ret;
}
int ObVariableSetExecutor::switch_to_session_variable(
const ObExprCtx& expr_ctx, const ObObj& value, ObSessionVariable& sess_var)
{
int ret = OB_SUCCESS;
if (ob_is_temporal_type(value.get_type())) { // switch the meta type and value type
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_NONE);
ObObj obj_tmp;
const ObObj* res_obj_ptr = NULL;
if (OB_FAIL(ObObjCaster::to_type(ObVarcharType, cast_ctx, value, obj_tmp, res_obj_ptr))) {
LOG_WARN("failed to cast object to ObVarcharType ", K(ret), K(value));
} else if (OB_ISNULL(res_obj_ptr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("res_obj_ptr is NULL", K(ret));
} else {
sess_var.value_.set_varchar(res_obj_ptr->get_varchar());
sess_var.meta_.set_collation_level(CS_LEVEL_IMPLICIT);
sess_var.meta_.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
sess_var.meta_.set_varchar();
}
} else if (ObNullType == value.get_type()) { // switch the meta type only
sess_var.value_.set_null();
sess_var.meta_.set_collation_level(CS_LEVEL_IMPLICIT);
sess_var.meta_.set_collation_type(CS_TYPE_BINARY);
} else { // won't switch
sess_var.value_ = value;
sess_var.meta_.set_type(value.get_type());
sess_var.meta_.set_scale(value.get_scale());
sess_var.meta_.set_collation_level(CS_LEVEL_IMPLICIT);
sess_var.meta_.set_collation_type(value.get_collation_type());
}
return ret;
}
#undef DEFINE_CAST_CTX
} // namespace sql
} // namespace oceanbase

View File

@ -0,0 +1,60 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_CMD_OB_VARIABLE_SET_EXECUTOR_
#define OCEANBASE_SQL_ENGINE_CMD_OB_VARIABLE_SET_EXECUTOR_
#include "sql/resolver/cmd/ob_variable_set_stmt.h"
#include "share/ob_define.h"
#include "sql/session/ob_session_val_map.h"
namespace oceanbase {
namespace common {
class ObIAllocator;
class ObExprCtx;
namespace sqlclient {
class ObMySQLProxy;
}
} // namespace common
namespace sql {
class ObExecContext;
class ObSQLSessionInfo;
class ObPhysicalPlanCtx;
class ObVariableSetExecutor {
public:
ObVariableSetExecutor();
virtual ~ObVariableSetExecutor();
int execute(ObExecContext& ctx, ObVariableSetStmt& stmt);
static int check_and_convert_sys_var(ObExecContext& ctx, const share::ObSetVar& set_var,
share::ObBasicSysVar& sys_var, const common::ObObj& in_val, common::ObObj& out_val, bool is_set_stmt);
static int set_user_variable(
const common::ObObj& val, const common::ObString& name, const common::ObExprCtx& expr_ctx);
static int cast_value(ObExecContext& ctx, const ObVariableSetStmt::VariableSetNode& var_node,
uint64_t actual_tenant_id, common::ObIAllocator& calc_buf, const share::ObBasicSysVar& sys_val,
const common::ObObj& in_val, common::ObObj& out_val);
static int switch_to_session_variable(
const common::ObExprCtx& expr_ctx, const common::ObObj& value, ObSessionVariable& sess_var);
private:
int process_session_autocommit_hook(ObExecContext& exec_ctx, const common::ObObj& val);
int process_auto_increment_hook(const ObSQLMode sql_mode, const common::ObString var_name, common::ObObj& val);
int process_last_insert_id_hook(
ObPhysicalPlanCtx* plan_ctx, const ObSQLMode sql_mode, const common::ObString var_name, common::ObObj& val);
int update_global_variables(
ObExecContext& ctx, ObDDLStmt& stmt, const share::ObSetVar& set_var, const common::ObObj& value_obj);
private:
DISALLOW_COPY_AND_ASSIGN(ObVariableSetExecutor);
};
} // namespace sql
} // namespace oceanbase
#endif /* OCEANBASE_SQL_ENGINE_CMD_OB_VARIABLE_SET_EXECUTOR_ */

View File

@ -0,0 +1,364 @@
/**
* 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.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_xa_executor.h"
#include "share/ob_errno.h"
#include "share/ob_define.h"
#include "sql/resolver/xa/ob_xa_stmt.h"
#include "sql/ob_sql_trans_control.h"
#include "storage/transaction/ob_trans_define.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/executor/ob_task_executor_ctx.h"
#include "storage/ob_partition_service.h"
namespace oceanbase {
using namespace common;
using namespace transaction;
namespace sql {
static inline void init_start_trans_param(
ObSQLSessionInfo* session, ObTaskExecutorCtx& task_exec_ctx, transaction::ObStartTransParam& param)
{
param.set_access_mode(transaction::ObTransAccessMode::READ_WRITE);
param.set_type(session->get_trans_type());
param.set_isolation(session->get_tx_isolation());
param.set_cluster_version(task_exec_ctx.get_min_cluster_version());
param.set_inner_trans(session->is_inner());
}
int ObXaStartExecutor::execute(ObExecContext& ctx, ObXaStartStmt& stmt)
{
int ret = OB_NOT_SUPPORTED;
UNUSED(ctx);
UNUSED(stmt);
return ret;
/*
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx);
ObSQLSessionInfo *my_session = GET_MY_SESSION(ctx);
ObTaskExecutorCtx &task_exec_ctx = ctx.get_task_exec_ctx();
storage::ObPartitionService *ps = nullptr;
int32_t xa_trans_state = ObXATransState::NON_EXISTING;
ObTransDesc &trans_desc = my_session->get_trans_desc();
if (OB_ISNULL(plan_ctx) || OB_ISNULL(my_session)
|| OB_ISNULL(ps = task_exec_ctx.get_partition_service())) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(plan_ctx), K(my_session));
} else if (OB_FAIL(ps->get_xa_trans_state(xa_trans_state, trans_desc))) {
LOG_WARN("get xa trans state failed", K(ret));
} else if (ObXATransState::NON_EXISTING != xa_trans_state) {
ret = OB_TRANS_XA_RMFAIL;
LOG_USER_ERROR(OB_TRANS_XA_RMFAIL, ObXATransState::to_string(xa_trans_state));
LOG_WARN("invalid xa state", K(ret), K(xa_trans_state));
} else if (my_session->get_in_transaction()) {
ret = OB_TRANS_XA_OUTSIDE;
LOG_WARN("already start trans", K(ret));
} else {
transaction::ObStartTransParam &start_trans_param = plan_ctx->get_start_trans_param();
init_start_trans_param(my_session, task_exec_ctx, start_trans_param);
if (OB_FAIL(ObSqlTransControl::explicit_start_trans(ctx, start_trans_param))) {
LOG_WARN("explicit start trans failed", K(ret), K(start_trans_param));
} else if (OB_FAIL(ps->xa_start(stmt.get_xa_string(),
stmt.get_gtrid_string().length(),
stmt.get_bqual_string().length(),
stmt.get_format_id(),
stmt.get_flags(),
trans_desc))) {
LOG_WARN("xa start failed", K(ret), K(start_trans_param));
if (OB_SUCCESS != (tmp_ret = ObSqlTransControl::explicit_end_trans(ctx, true))) {
ret = tmp_ret;
LOG_WARN("explicit end trans failed", K(ret));
}
} else {
// do nothing
}
}
LOG_DEBUG("xa start execute", K(stmt.get_xa_string()));
return ret;
*/
}
int ObPlXaStartExecutor::execute(ObExecContext& ctx, ObXaStartStmt& stmt)
{
int ret = OB_SUCCESS;
ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(ctx);
ObSQLSessionInfo* my_session = GET_MY_SESSION(ctx);
ObTaskExecutorCtx& task_exec_ctx = ctx.get_task_exec_ctx();
storage::ObPartitionService* ps = nullptr;
ObTransDesc& trans_desc = my_session->get_trans_desc();
ObXATransID xid;
if (OB_ISNULL(plan_ctx) || OB_ISNULL(my_session) || OB_ISNULL(ps = task_exec_ctx.get_partition_service())) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(plan_ctx), K(my_session));
ret = OB_TRANS_XA_RMFAIL;
} else if (OB_FAIL(xid.set(stmt.get_gtrid_string(), stmt.get_bqual_string(), stmt.get_format_id()))) {
LOG_WARN("set xid error", K(ret), K(stmt));
} else if (my_session->get_in_transaction()) {
ret = OB_TRANS_XA_OUTSIDE;
LOG_WARN("already start trans", K(ret), K(stmt.get_xa_string()));
} else {
transaction::ObStartTransParam& start_trans_param = plan_ctx->get_start_trans_param();
init_start_trans_param(my_session, task_exec_ctx, start_trans_param);
if (OB_FAIL(ObSqlTransControl::explicit_start_trans(ctx, start_trans_param))) {
LOG_WARN("explicit start trans failed", K(ret), K(start_trans_param));
} else if (OB_FAIL(ps->xa_start(xid, stmt.get_flags(), my_session->get_xa_end_timeout_seconds(), trans_desc))) {
LOG_WARN("xa start failed", K(ret), K(start_trans_param));
// if (OB_SUCCESS != (tmp_ret = ObSqlTransControl::explicit_end_trans(ctx, true))) {
// ret = tmp_ret;
// LOG_WARN("explicit end trans failed", K(ret));
//}
my_session->reset_first_stmt_type();
my_session->reset_tx_variable();
my_session->set_early_lock_release(false);
ctx.set_need_disconnect(false);
my_session->get_trans_desc().get_standalone_stmt_desc().reset();
} else {
// do nothing
}
}
LOG_DEBUG("xa start execute", K(stmt));
return ret;
}
int ObXaEndExecutor::execute(ObExecContext& ctx, ObXaEndStmt& stmt)
{
int ret = OB_NOT_SUPPORTED;
UNUSED(ctx);
UNUSED(stmt);
return ret;
/*
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObSQLSessionInfo *my_session = GET_MY_SESSION(ctx);
ObTaskExecutorCtx &task_exec_ctx = ctx.get_task_exec_ctx();
storage::ObPartitionService *ps = nullptr;
if (OB_ISNULL(my_session) || OB_ISNULL(ps = task_exec_ctx.get_partition_service())) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(my_session));
} else if (OB_FAIL(ps->xa_end(stmt.get_xa_string(),
transaction::ObXAEndFlag::TMSUCCESS,
my_session->get_trans_desc()))) {
LOG_WARN("xa end failed", K(ret), K(stmt.get_xa_string()));
if (OB_TRANS_XA_RMFAIL != ret
&& OB_SUCCESS != (tmp_ret = ObSqlTransControl::explicit_end_trans(ctx, true))) {
ret = tmp_ret;
LOG_WARN("explicit end trans failed", K(ret));
}
} else {
my_session->reset_first_stmt_type();
my_session->reset_tx_variable();
my_session->set_early_lock_release(false);
ctx.set_need_disconnect(false);
my_session->get_trans_desc().get_standalone_stmt_desc().reset();
}
LOG_DEBUG("xa end execute", K(stmt.get_xa_string()));
return ret;
*/
}
int ObPlXaEndExecutor::execute(ObExecContext& ctx, ObXaEndStmt& stmt)
{
int ret = OB_SUCCESS;
// int tmp_ret = OB_SUCCESS;
ObSQLSessionInfo* my_session = GET_MY_SESSION(ctx);
ObTaskExecutorCtx& task_exec_ctx = ctx.get_task_exec_ctx();
storage::ObPartitionService* ps = nullptr;
ObXATransID xid;
if (OB_ISNULL(my_session) || OB_ISNULL(ps = task_exec_ctx.get_partition_service())) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(my_session));
} else if (OB_FAIL(xid.set(stmt.get_gtrid_string(), stmt.get_bqual_string(), stmt.get_format_id()))) {
LOG_WARN("set xid error", K(ret), K(stmt));
} else if (!my_session->get_in_transaction()) {
ret = OB_TRANS_XA_PROTO;
LOG_WARN("not in a trans", K(ret));
} else if (OB_FAIL(ps->xa_end(xid, stmt.get_flags(), my_session->get_trans_desc()))) {
LOG_WARN("xa end failed", K(ret), K(stmt.get_xa_string()));
// if (OB_TRANS_XA_RMFAIL != ret
// && OB_SUCCESS != (tmp_ret = ObSqlTransControl::explicit_end_trans(ctx, true))) {
// ret = tmp_ret;
// LOG_WARN("explicit end trans failed", K(ret));
// }
} else {
my_session->reset_first_stmt_type();
my_session->reset_tx_variable();
my_session->set_early_lock_release(false);
ctx.set_need_disconnect(false);
my_session->get_trans_desc().get_standalone_stmt_desc().reset();
}
LOG_DEBUG("xa end execute", K(stmt));
return ret;
}
int ObXaPrepareExecutor::execute(ObExecContext& ctx, ObXaPrepareStmt& stmt)
{
int ret = OB_NOT_SUPPORTED;
UNUSED(ctx);
UNUSED(stmt);
return ret;
/*
int ret = OB_SUCCESS;
//int tmp_ret = OB_SUCCESS;
ObSQLSessionInfo *my_session = GET_MY_SESSION(ctx);
ObTaskExecutorCtx &task_exec_ctx = ctx.get_task_exec_ctx();
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx);
storage::ObPartitionService *ps = nullptr;
if (OB_ISNULL(my_session) || OB_ISNULL(plan_ctx)
|| OB_ISNULL(ps = task_exec_ctx.get_partition_service())) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(my_session), K(plan_ctx), K(ps));
} else if (my_session->get_in_transaction()) {
ret = OB_TRANS_XA_OUTSIDE;
LOG_WARN("already start trans", K(ret));
} else {
const uint64_t tenant_id = my_session->get_effective_tenant_id();
int64_t timeout = plan_ctx->get_trans_timeout_timestamp();
transaction::ObStartTransParam &start_trans_param = plan_ctx->get_start_trans_param();
init_start_trans_param(my_session, task_exec_ctx, start_trans_param);
if (OB_FAIL(ps->xa_prepare(stmt.get_xa_string(), tenant_id, timeout))) {
LOG_WARN("xa prepare failed", K(ret), K(stmt.get_xa_string()));
// if (OB_TRANS_XA_RMFAIL != ret
// && OB_SUCCESS != (tmp_ret = ObSqlTransControl::explicit_end_trans(ctx, true))) {
// ret = tmp_ret;
// LOG_WARN("explicit end trans failed", K(ret));
// }
}
}
LOG_DEBUG("xa prepare execute", K(stmt.get_xa_string()));
return ret;
*/
}
int ObPlXaPrepareExecutor::execute(ObExecContext& ctx, ObXaPrepareStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* my_session = GET_MY_SESSION(ctx);
ObTaskExecutorCtx& task_exec_ctx = ctx.get_task_exec_ctx();
ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(ctx);
storage::ObPartitionService* ps = nullptr;
ObXATransID xid;
if (OB_ISNULL(my_session) || OB_ISNULL(plan_ctx) || OB_ISNULL(ps = task_exec_ctx.get_partition_service())) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(my_session), K(plan_ctx), K(ps));
} else if (OB_FAIL(xid.set(stmt.get_gtrid_string(), stmt.get_bqual_string(), stmt.get_format_id()))) {
LOG_WARN("set xid error", K(ret), K(stmt));
} else if (my_session->get_in_transaction()) {
ret = OB_TRANS_XA_RMERR;
LOG_WARN("already start trans", K(ret));
} else {
const uint64_t tenant_id = my_session->get_effective_tenant_id();
int64_t timeout = plan_ctx->get_trans_timeout_timestamp();
transaction::ObStartTransParam& start_trans_param = plan_ctx->get_start_trans_param();
init_start_trans_param(my_session, task_exec_ctx, start_trans_param);
if (OB_FAIL(ps->xa_prepare(xid, tenant_id, timeout))) {
if (OB_TRANS_XA_RDONLY != ret) {
LOG_WARN("xa prepare failed", K(ret), K(stmt));
}
}
}
LOG_DEBUG("xa prepare execute", K(stmt));
return ret;
}
int ObXaEndTransExecutor::execute_(const ObString& xid, const bool is_rollback, ObExecContext& ctx)
{
int ret = OB_NOT_SUPPORTED;
UNUSED(xid);
UNUSED(is_rollback);
UNUSED(ctx);
return ret;
/*
int ret = OB_SUCCESS;
ObSQLSessionInfo *my_session = GET_MY_SESSION(ctx);
ObTaskExecutorCtx &task_exec_ctx = ctx.get_task_exec_ctx();
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx);
ObTransDesc &trans_desc = my_session->get_trans_desc();
storage::ObPartitionService *ps = nullptr;
if (OB_ISNULL(plan_ctx) || OB_ISNULL(my_session)
|| OB_ISNULL(ps = task_exec_ctx.get_partition_service())) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(plan_ctx), K(my_session));
} else if (my_session->get_in_transaction()) {
ret = OB_TRANS_XA_OUTSIDE;
LOG_WARN("already start trans", K(ret));
} else {
transaction::ObStartTransParam &start_trans_param = plan_ctx->get_start_trans_param();
init_start_trans_param(my_session, task_exec_ctx, start_trans_param);
if (OB_FAIL(ObSqlTransControl::explicit_start_trans(ctx, start_trans_param))) {
LOG_WARN("explicit start trans failed", K(ret), K(start_trans_param));
} else if (OB_FAIL(ps->xa_end_trans(xid, is_rollback, 0, trans_desc))) {
LOG_WARN("fail to execute xa commit/rollback", K(xid), K(is_rollback));
} else {
LOG_DEBUG("succeed to execute xa commit/rollback", K(xid), K(is_rollback));
}
my_session->reset_first_stmt_type();
my_session->reset_tx_variable();
my_session->set_early_lock_release(false);
ctx.set_need_disconnect(false);
my_session->get_trans_desc().get_standalone_stmt_desc().reset();
}
LOG_DEBUG("xa end_trans execute", K(xid), K(is_rollback));
return ret;
*/
}
int ObPlXaEndTransExecutor::execute_(const ObString& gtrid_str, const ObString& bqual_str, const int64_t format_id,
const bool is_rollback, const int64_t flags, ObExecContext& ctx)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* my_session = GET_MY_SESSION(ctx);
ObTaskExecutorCtx& task_exec_ctx = ctx.get_task_exec_ctx();
ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(ctx);
ObTransDesc& trans_desc = my_session->get_trans_desc();
storage::ObPartitionService* ps = nullptr;
ObXATransID xid;
if (OB_ISNULL(plan_ctx) || OB_ISNULL(my_session) || OB_ISNULL(ps = task_exec_ctx.get_partition_service())) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid param", K(ret), K(plan_ctx), K(my_session));
} else if (OB_FAIL(xid.set(gtrid_str, bqual_str, format_id))) {
LOG_WARN("set xid error", K(ret), K(gtrid_str), K(bqual_str), K(format_id));
} else if (my_session->get_in_transaction()) {
ret = OB_TRANS_XA_RMFAIL;
LOG_WARN("already start trans", K(ret));
} else {
transaction::ObStartTransParam& start_trans_param = plan_ctx->get_start_trans_param();
init_start_trans_param(my_session, task_exec_ctx, start_trans_param);
if (OB_FAIL(ObSqlTransControl::explicit_start_trans(ctx, start_trans_param))) {
LOG_WARN("explicit start trans failed", K(ret), K(start_trans_param));
} else if (OB_FAIL(ps->xa_end_trans(xid, is_rollback, flags, trans_desc))) {
LOG_WARN("fail to execute xa commit/rollback", K(xid), K(is_rollback));
} else {
LOG_DEBUG("succeed to execute xa commit/rollback", K(xid), K(is_rollback));
}
my_session->reset_first_stmt_type();
my_session->reset_tx_variable();
my_session->set_early_lock_release(false);
ctx.set_need_disconnect(false);
my_session->get_trans_desc().get_standalone_stmt_desc().reset();
}
LOG_DEBUG("xa end_trans execute", K(gtrid_str), K(bqual_str), K(format_id), K(is_rollback), K(flags));
return ret;
}
} // end namespace sql
} // end namespace oceanbase

View File

@ -0,0 +1,146 @@
/**
* 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.
*/
#ifndef OCEANBASE_SQL_ENGINE_CMD_OB_XA_CMD_EXECUTOR_
#define OCEANBASE_SQL_ENGINE_CMD_OB_XA_CMD_EXECUTOR_
#include "lib/utility/ob_macro_utils.h"
#include "lib/string/ob_string.h"
#include "sql/resolver/xa/ob_xa_stmt.h"
namespace oceanbase {
namespace sql {
class ObExecContext;
class ObXaStartStmt;
class ObXaStartExecutor {
public:
ObXaStartExecutor()
{}
~ObXaStartExecutor()
{}
int execute(ObExecContext& ctx, ObXaStartStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObXaStartExecutor);
};
class ObPlXaStartExecutor {
public:
ObPlXaStartExecutor()
{}
~ObPlXaStartExecutor()
{}
int execute(ObExecContext& ctx, ObXaStartStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObPlXaStartExecutor);
};
class ObXaEndStmt;
class ObXaEndExecutor {
public:
ObXaEndExecutor()
{}
~ObXaEndExecutor()
{}
int execute(ObExecContext& ctx, ObXaEndStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObXaEndExecutor);
};
class ObPlXaEndExecutor {
public:
ObPlXaEndExecutor()
{}
~ObPlXaEndExecutor()
{}
int execute(ObExecContext& ctx, ObXaEndStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObPlXaEndExecutor);
};
class ObXaPrepareStmt;
class ObXaPrepareExecutor {
public:
ObXaPrepareExecutor()
{}
~ObXaPrepareExecutor()
{}
int execute(ObExecContext& ctx, ObXaPrepareStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObXaPrepareExecutor);
};
class ObPlXaPrepareExecutor {
public:
ObPlXaPrepareExecutor()
{}
~ObPlXaPrepareExecutor()
{}
int execute(ObExecContext& ctx, ObXaPrepareStmt& stmt);
private:
DISALLOW_COPY_AND_ASSIGN(ObPlXaPrepareExecutor);
};
class ObXaCommitStmt;
class ObXaRollBackStmt;
class ObXaEndTransExecutor {
public:
ObXaEndTransExecutor()
{}
~ObXaEndTransExecutor()
{}
int execute(ObExecContext& ctx, ObXaCommitStmt& stmt)
{
return execute_(stmt.get_xa_string(), false, ctx);
}
int execute(ObExecContext& ctx, ObXaRollBackStmt& stmt)
{
return execute_(stmt.get_xa_string(), true, ctx);
}
private:
int execute_(const common::ObString& xid, const bool is_rollback, ObExecContext& ctx);
DISALLOW_COPY_AND_ASSIGN(ObXaEndTransExecutor);
};
class ObPlXaEndTransExecutor {
public:
ObPlXaEndTransExecutor()
{}
~ObPlXaEndTransExecutor()
{}
int execute(ObExecContext& ctx, ObXaCommitStmt& stmt)
{
return execute_(
stmt.get_gtrid_string(), stmt.get_bqual_string(), stmt.get_format_id(), false, stmt.get_flags(), ctx);
}
int execute(ObExecContext& ctx, ObXaRollBackStmt& stmt)
{
return execute_(
stmt.get_gtrid_string(), stmt.get_bqual_string(), stmt.get_format_id(), true, stmt.get_flags(), ctx);
}
private:
int execute_(const common::ObString& gtrid_str, const common::ObString& bqual_str, const int64_t format_id,
const bool is_rollback, const int64_t flags, ObExecContext& ctx);
DISALLOW_COPY_AND_ASSIGN(ObPlXaEndTransExecutor);
};
} // end namespace sql
} // end namespace oceanbase
#endif