Files
oceanbase/src/sql/engine/cmd/ob_table_executor.cpp
oceanbase-admin cea7de1475 init push
2021-05-31 22:56:52 +08:00

2258 lines
100 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/cmd/ob_table_executor.h"
#include "sql/engine/cmd/ob_index_executor.h"
#include "share/object/ob_obj_cast.h"
#include "lib/mysqlclient/ob_mysql_proxy.h"
#include "lib/utility/ob_tracepoint.h"
#include "share/ob_common_rpc_proxy.h"
#include "sql/resolver/ddl/ob_create_table_stmt.h"
#include "sql/resolver/ddl/ob_alter_table_stmt.h"
#include "sql/resolver/ddl/ob_drop_table_stmt.h"
#include "sql/resolver/ddl/ob_rename_table_stmt.h"
#include "sql/resolver/ddl/ob_truncate_table_stmt.h"
#include "sql/resolver/ddl/ob_create_table_like_stmt.h"
#include "sql/resolver/ddl/ob_purge_stmt.h"
#include "sql/resolver/ddl/ob_optimize_stmt.h"
#include "sql/resolver/ob_resolver_utils.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/engine/cmd/ob_partition_executor_utils.h"
#include "sql/parser/ob_parser.h"
#include "sql/ob_select_stmt_printer.h"
#include "observer/ob_server_struct.h"
#include "observer/ob_server.h"
#include "share/ob_worker.h"
namespace oceanbase {
using namespace common;
using namespace share;
using namespace share::schema;
using namespace observer;
namespace sql {
ObCreateTableExecutor::ObCreateTableExecutor()
{}
ObCreateTableExecutor::~ObCreateTableExecutor()
{}
int ObCreateTableExecutor::prepare_ins_arg(
ObCreateTableStmt& stmt, const ObSQLSessionInfo* my_session, ObSqlString& ins_sql)
{
int ret = OB_SUCCESS;
ObArenaAllocator allocator(ObModIds::OB_SQL_EXECUTOR);
char* buf = static_cast<char*>(allocator.alloc(OB_MAX_SQL_LENGTH));
int64_t buf_len = OB_MAX_SQL_LENGTH;
int64_t pos1 = 0;
bool is_set_subquery = false;
bool is_oracle_mode = share::is_oracle_mode();
const ObString& db_name = stmt.get_database_name();
const ObString& tab_name = stmt.get_table_name();
const char sep_char = is_oracle_mode ? '"' : '`';
ObSelectStmt* select_stmt = stmt.get_sub_select();
ObSelectStmtPrinter select_stmt_printer(buf,
buf_len,
&pos1,
select_stmt,
select_stmt->tz_info_,
NULL, // column_list is null here
is_set_subquery);
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("allocate memory failed");
} else if (OB_ISNULL(select_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("select stmt should not be null", K(ret));
} else {
const ObStmtHint& hint = select_stmt->get_stmt_hint();
const char* use_px = "";
if (hint.has_px_hint_) {
if (hint.enable_use_px()) {
use_px = "/*+ USE_PX */";
} else if (hint.disable_use_px()) {
use_px = "/*+ NO_USE_PX */";
}
}
// 1, generate insert into string
if (OB_FAIL(databuff_printf(buf,
buf_len,
pos1,
"insert %s into %c%.*s%c.%c%.*s%c",
use_px,
sep_char,
db_name.length(),
db_name.ptr(),
sep_char,
sep_char,
tab_name.length(),
tab_name.ptr(),
sep_char))) {
LOG_WARN("fail to print insert into string", K(ret), K(db_name), K(tab_name));
}
}
if (OB_SUCC(ret)) {
if (share::is_oracle_mode()) {
ObTableSchema& table_schema = stmt.get_create_table_arg().schema_;
int64_t used_column_count = 0;
for (int64_t i = 0; OB_SUCC(ret) && i < table_schema.get_column_count(); ++i) {
const ObColumnSchemaV2* column_schema = table_schema.get_column_schema_by_idx(i);
if (OB_ISNULL(column_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get null column shcmea", K(ret));
} else if (column_schema->get_column_id() < OB_END_RESERVED_COLUMN_ID_NUM) {
// do nothing
} else if (OB_FAIL(databuff_printf(buf, buf_len, pos1, (0 == used_column_count) ? "(" : ", "))) {
LOG_WARN("failed to print insert into string", K(ret), K(i));
} else if (OB_FAIL(databuff_printf(buf,
buf_len,
pos1,
"%c%.*s%c",
sep_char,
LEN_AND_PTR(column_schema->get_column_name_str()),
sep_char))) {
LOG_WARN("failed to print insert into string", K(ret));
} else {
++used_column_count;
}
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < select_stmt->get_select_item_size(); ++i) {
const SelectItem& select_item = select_stmt->get_select_item(i);
if (OB_FAIL(databuff_printf(buf, buf_len, pos1, (0 == i) ? "(" : ", "))) {
LOG_WARN("failed to print insert into string", K(ret), K(i));
} else { /* do nothing */
}
if (OB_SUCC(ret)) {
if (!select_item.alias_name_.empty()) {
if (OB_FAIL(databuff_printf(
buf, buf_len, pos1, "%c%.*s%c", sep_char, LEN_AND_PTR(select_item.alias_name_), sep_char))) {
LOG_WARN("failed to print insert into string", K(ret));
} else { /* do nothing */
}
} else {
if (OB_FAIL(databuff_printf(
buf, buf_len, pos1, "%c%.*s%c", sep_char, LEN_AND_PTR(select_item.expr_name_), sep_char))) {
LOG_WARN("failed to print insert into string", K(ret));
} else { /* do nothing */
}
}
} else { /* do nothing */
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(databuff_printf(buf, buf_len, pos1, ") "))) {
LOG_WARN("fail to append ')'", K(ret));
} else if (OB_FAIL(select_stmt_printer.do_print())) {
LOG_WARN("fail to print select stmt", K(ret));
} else if (OB_FAIL(ins_sql.append(buf, pos1))) {
LOG_WARN("fail to append insert into string", K(ret));
}
}
}
if (OB_SUCC(ret)) {
ObCollationType client_cs_type = my_session->get_local_collation_connection();
ObString converted_sql;
if (OB_FAIL(ObSQLUtils::copy_and_convert_string_charset(
allocator, ins_sql.string(), converted_sql, CS_TYPE_UTF8MB4_BIN, client_cs_type))) {
LOG_WARN("fail to convert insert into string to client_cs_type", K(ret));
} else if (OB_FAIL(ins_sql.assign(converted_sql))) {
LOG_WARN("fail to assign converted insert into string", K(ret));
}
}
LOG_DEBUG("ins str preparation complete!", K(ins_sql), K(ret), K(share::is_oracle_mode()));
return ret;
}
int ObCreateTableExecutor::prepare_alter_arg(
ObCreateTableStmt& stmt, const ObSQLSessionInfo* my_session, obrpc::ObAlterTableArg& alter_table_arg)
{
int ret = OB_SUCCESS;
const obrpc::ObCreateTableArg& create_table_arg = stmt.get_create_table_arg();
ObTableSchema& table_schema = const_cast<obrpc::ObCreateTableArg&>(create_table_arg).schema_;
AlterTableSchema* alter_table_schema = &alter_table_arg.alter_table_schema_;
table_schema.set_session_id(my_session->get_sessid_for_table());
alter_table_arg.session_id_ = my_session->get_sessid_for_table();
alter_table_schema->alter_type_ = OB_DDL_ALTER_TABLE;
// compat for old server
alter_table_arg.tz_info_ = my_session->get_tz_info_wrap().get_tz_info_offset();
alter_table_arg.is_inner_ = my_session->is_inner();
alter_table_arg.exec_tenant_id_ = my_session->get_effective_tenant_id();
if (OB_FAIL(alter_table_arg.tz_info_wrap_.deep_copy(my_session->get_tz_info_wrap()))) {
LOG_WARN("failed to deep_copy tz info wrap", "tz_info_wrap", my_session->get_tz_info_wrap(), K(ret));
} else if (OB_FAIL(alter_table_arg.set_nls_formats(my_session->get_local_nls_formats()))) {
LOG_WARN("failed to set_nls_formats", K(ret));
} else if (OB_FAIL(alter_table_schema->assign(table_schema))) {
LOG_WARN("failed to assign alter table schema", K(ret));
} else if (FALSE_IT(alter_table_schema->set_session_id(0))) {
// impossible
} else if (OB_FAIL(alter_table_schema->set_origin_table_name(stmt.get_table_name()))) {
LOG_WARN("failed to set origin table name", K(ret));
} else if (OB_FAIL(alter_table_schema->set_origin_database_name(stmt.get_database_name()))) {
LOG_WARN("failed to set origin database name", K(ret));
} else if (OB_FAIL(alter_table_schema->set_table_name(stmt.get_table_name()))) {
LOG_WARN("failed to set table name", K(ret));
} else if (OB_FAIL(alter_table_schema->set_database_name(stmt.get_database_name()))) {
LOG_WARN("failed to set database name", K(ret));
} else if (OB_FAIL(alter_table_schema->alter_option_bitset_.add_member(obrpc::ObAlterTableArg::SESSION_ID))) {
LOG_WARN("failed to add member SESSION_ID for alter table schema", K(ret), K(alter_table_arg));
}
LOG_DEBUG("alter table arg preparation complete!", K(*alter_table_schema), K(ret));
return ret;
}
int ObCreateTableExecutor::prepare_drop_arg(const ObCreateTableStmt& stmt, const ObSQLSessionInfo* my_session,
obrpc::ObTableItem& table_item, obrpc::ObDropTableArg& drop_table_arg)
{
int ret = OB_SUCCESS;
const ObString& db_name = stmt.get_database_name();
const ObString& tab_name = stmt.get_table_name();
drop_table_arg.if_exist_ = true;
drop_table_arg.tenant_id_ = my_session->get_login_tenant_id();
drop_table_arg.to_recyclebin_ = false;
drop_table_arg.table_type_ = USER_TABLE;
drop_table_arg.session_id_ = my_session->get_sessid_for_table();
drop_table_arg.exec_tenant_id_ = my_session->get_effective_tenant_id();
table_item.database_name_ = db_name;
table_item.table_name_ = tab_name;
if (OB_FAIL(my_session->get_name_case_mode(table_item.mode_))) {
LOG_WARN("failed to get name case mode!", K(ret));
} else if (OB_FAIL(drop_table_arg.tables_.push_back(table_item))) {
LOG_WARN("failed to add table item!", K(table_item), K(ret));
}
LOG_DEBUG("drop table arg preparation complete!", K(drop_table_arg), K(table_item), K(ret));
return ret;
}
int ObCreateTableExecutor::execute_ctas(
ObExecContext& ctx, ObCreateTableStmt& stmt, obrpc::ObCommonRpcProxy* common_rpc_proxy)
{
int ret = OB_SUCCESS;
int64_t affected_rows = 0;
int64_t dummy = 0;
ObMySQLProxy* sql_proxy = ctx.get_sql_proxy();
common::ObCommonSqlProxy* user_sql_proxy;
common::ObOracleSqlProxy oracle_sql_proxy;
ObSQLSessionInfo* my_session = ctx.get_my_session();
ObPhysicalPlanCtx* plan_ctx = ctx.get_physical_plan_ctx();
ObSchemaGetterGuard schema_guard;
obrpc::ObAlterTableArg alter_table_arg;
obrpc::ObDropTableArg drop_table_arg;
obrpc::ObTableItem table_item;
ObSqlString ins_sql;
bool is_auto_commit = false;
bool need_clean_up = false;
int first_err_code = OB_SUCCESS;
const observer::ObGlobalContext& gctx = observer::ObServer::get_instance().get_gctx();
const ObTableSchema* table_schema = NULL;
obrpc::UInt64 table_id;
common::sqlclient::ObISQLConnection* conn = NULL;
obrpc::ObCreateTableArg& create_table_arg = stmt.get_create_table_arg();
create_table_arg.is_inner_ = my_session->is_inner();
CK(OB_NOT_NULL(sql_proxy),
OB_NOT_NULL(my_session),
OB_NOT_NULL(gctx.schema_service_),
OB_NOT_NULL(plan_ctx),
OB_NOT_NULL(common_rpc_proxy));
if (OB_SUCC(ret)) {
ObInnerSQLConnectionPool* pool = static_cast<observer::ObInnerSQLConnectionPool*>(sql_proxy->get_pool());
if (OB_ISNULL(pool)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("pool is null", K(ret));
} else if (OB_FAIL(oracle_sql_proxy.init(pool))) {
LOG_WARN("init oracle sql proxy failed", K(ret));
} else if (OB_FAIL(prepare_ins_arg(stmt, my_session, ins_sql))) {
LOG_WARN("failed to prepare insert table arg", K(ret));
} else if (OB_FAIL(prepare_alter_arg(stmt, my_session, alter_table_arg))) {
LOG_WARN("failed to prepare alter table arg", K(ret));
} else if (OB_FAIL(prepare_drop_arg(stmt, my_session, table_item, drop_table_arg))) {
LOG_WARN("failed to prepare drop table arg", K(ret));
} else if (OB_FAIL(common_rpc_proxy->create_table(create_table_arg, table_id))) {
LOG_WARN("rpc proxy create table failed", K(ret), "dst", common_rpc_proxy->get_server());
} else if (OB_INVALID_ID != table_id) {
const int64_t s1 = ObTimeUtility::current_time();
int64_t s2 = 0;
const int64_t DDL_WAIT_TIME = 1 * 1000 * 1000; // 1s
const int64_t SLEEP_ON_NEED_RETRY = 10 * 1000; // 10ms
obrpc::ObAlterTableRes res;
while (true) {
if (OB_FAIL(
gctx.schema_service_->get_tenant_schema_guard(my_session->get_effective_tenant_id(), schema_guard))) {
LOG_WARN("failed to get schema guard", K(ret));
break;
}
if (OB_FAIL(schema_guard.get_table_schema(table_id, table_schema))) {
LOG_WARN("failed to get table schema", K(ret), K(table_id));
break;
}
s2 = ObTimeUtility::current_time();
if (OB_NOT_NULL(table_schema)) {
LOG_DEBUG("CTAS refresh table schema succeed!", K(ret), K(s2 - s1));
break;
}
if (s2 - s1 < DDL_WAIT_TIME) {
ret = OB_SUCCESS;
usleep(SLEEP_ON_NEED_RETRY);
LOG_DEBUG("CTAS refresh table schema failed, try again", K(ret), K(table_id), K(s2 - s1));
} else {
LOG_DEBUG("CTAS refresh table schema timeout!", K(ret), K(table_id), K(s2 - s1));
break;
}
}
if (share::is_oracle_mode()) {
user_sql_proxy = &oracle_sql_proxy;
} else {
user_sql_proxy = sql_proxy;
}
if (OB_FAIL(ret)) {
// do nothing
} else if (OB_FAIL(pool->acquire(my_session, conn))) {
need_clean_up = true;
first_err_code = ret;
LOG_WARN("failed to acquire inner connection", K(ret));
} else if (OB_FAIL(
conn->execute_write(my_session->get_effective_tenant_id(), ins_sql.ptr(), affected_rows, true))) {
need_clean_up = true;
first_err_code = ret;
LOG_WARN("failed to exec sql", K(ins_sql), K(ret));
} else if (OB_FAIL(my_session->get_autocommit(is_auto_commit))) {
need_clean_up = true;
first_err_code = ret;
LOG_WARN("failed to get auto commit", K(ret));
} else if (!is_auto_commit &&
OB_FAIL(conn->execute_write(my_session->get_effective_tenant_id(), "commit;", dummy, true))) {
need_clean_up = true;
first_err_code = ret;
LOG_WARN("failed to exec commit", K(ins_sql), K(ret));
} else if (OB_FAIL(common_rpc_proxy->alter_table(alter_table_arg, res))) {
need_clean_up = true;
first_err_code = ret;
LOG_WARN("failed to update table session", K(ret), K(alter_table_arg));
} else {
plan_ctx->set_affected_rows(affected_rows);
LOG_DEBUG("CTAS all done", K(ins_sql), K(affected_rows), K(share::is_oracle_mode()));
}
#ifdef ERRSIM
{
int test_used_ret = OB_SUCCESS;
test_used_ret = E(EventTable::EN_CTAS_FAIL_NO_DROP_ERROR) OB_SUCCESS;
if (OB_FAIL(test_used_ret)) {
need_clean_up = false;
}
}
#else
// do nothing...
#endif
if (need_clean_up) {
if (OB_FAIL(common_rpc_proxy->drop_table(drop_table_arg))) {
LOG_WARN("failed to drop table", K(drop_table_arg), K(ret));
} else {
ret = first_err_code;
LOG_INFO("table is created and dropped due to error ", K(ret));
}
}
if (OB_NOT_NULL(conn)) {
user_sql_proxy->close(conn, true);
}
} else {
LOG_DEBUG("table exists, no need to CTAS", K(table_id));
}
}
return ret;
}
int ObCreateTableExecutor::execute(ObExecContext& ctx, ObCreateTableStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
obrpc::UInt64 table_id;
obrpc::ObCreateTableArg& create_table_arg = stmt.get_create_table_arg();
ObString first_stmt;
ObSelectStmt* select_stmt = stmt.get_sub_select();
ObTableSchema& table_schema = create_table_arg.schema_;
ObSQLSessionInfo* my_session = ctx.get_my_session();
if (OB_ISNULL(my_session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session is null", K(ret));
} else if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("get first statement failed", K(ret));
} else {
create_table_arg.is_inner_ = my_session->is_inner();
const_cast<obrpc::ObCreateTableArg&>(create_table_arg).ddl_stmt_str_ = first_stmt;
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(ObPartitionExecutorUtils::calc_values_exprs(ctx, stmt))) {
LOG_WARN("compare range parition expr fail", K(ret));
} else if (OB_FAIL(set_index_arg_list(ctx, stmt))) {
LOG_WARN("fail to set index_arg_list", 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_ISNULL(select_stmt)) {
if (OB_FAIL(common_rpc_proxy->create_table(create_table_arg, table_id))) {
LOG_WARN("rpc proxy create table failed", K(ret), "dst", common_rpc_proxy->get_server());
} else { /* do nothing */
}
} else if (OB_FAIL(execute_ctas(ctx, stmt, common_rpc_proxy))) {
LOG_WARN("execute create table as select failed", K(ret));
}
if (OB_SUCC(ret) && 0 != table_schema.get_session_id()) {
LOG_DEBUG("CTAS or temporary table create detected", K(table_schema));
ATOMIC_STORE(&OBSERVER.need_ctas_cleanup_, true);
}
}
return ret;
}
int ObCreateTableExecutor::set_index_arg_list(ObExecContext& ctx, ObCreateTableStmt& stmt)
{
int ret = OB_SUCCESS;
obrpc::ObCreateTableArg& create_table_arg = const_cast<obrpc::ObCreateTableArg&>(stmt.get_create_table_arg());
if (stmt.get_index_partition_resolve_results().count() != stmt.get_index_arg_list().count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid index resolve result", K(ret), K(stmt));
}
for (int64_t i = 0; OB_SUCC(ret) && i < stmt.get_index_arg_list().count(); i++) {
ObCreateIndexStmt index_stmt;
ObPartitionResolveResult& resolve_result = stmt.get_index_partition_resolve_results().at(i);
index_stmt.get_part_fun_exprs() = resolve_result.get_part_fun_exprs();
index_stmt.get_part_values_exprs() = resolve_result.get_part_values_exprs();
index_stmt.get_subpart_fun_exprs() = resolve_result.get_subpart_fun_exprs();
index_stmt.get_template_subpart_values_exprs() = resolve_result.get_template_subpart_values_exprs();
index_stmt.get_individual_subpart_values_exprs() = resolve_result.get_individual_subpart_values_exprs();
if (OB_FAIL(index_stmt.get_create_index_arg().assign(stmt.get_index_arg_list().at(i)))) {
LOG_WARN("fail to assign index arg", K(ret));
} else if (OB_FAIL(ObPartitionExecutorUtils::calc_values_exprs(ctx, index_stmt))) {
LOG_WARN("fail to compare range partition expr", K(ret));
} else if (OB_FAIL(create_table_arg.index_arg_list_.push_back(index_stmt.get_create_index_arg()))) {
LOG_WARN("fail to push back index_arg", K(ret));
}
}
return ret;
}
int ObTableExecutorUtils::get_first_stmt(const common::ObString& stmt, common::ObString& first_stmt, ObSQLMode sql_mode)
{
int ret = OB_SUCCESS;
ObArenaAllocator allocator(ObModIds::OB_SQL_PARSER);
ObSEArray<ObString, 1> queries;
ObMPParseStat parse_stat;
ObParser parser(allocator, sql_mode);
if (OB_FAIL(parser.split_multiple_stmt(stmt, queries, parse_stat, true /*return the first stmt*/))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("Get first statement from multiple statements failed", K(ret));
} else if (0 == queries.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("Get non-statement from multiple statements", K(ret));
} else {
first_stmt = queries.at(0);
}
return ret;
}
/**
*
*/
ObAlterTableExecutor::ObAlterTableExecutor()
{}
ObAlterTableExecutor::~ObAlterTableExecutor()
{}
int ObAlterTableExecutor::refresh_schema_for_table(const uint64_t tenant_id)
{
int ret = OB_SUCCESS;
share::schema::ObSchemaGetterGuard schema_guard;
const observer::ObGlobalContext& gctx = observer::ObServer::get_instance().get_gctx();
ObMultiVersionSchemaService* schema_service = gctx.schema_service_;
int64_t local_version = OB_INVALID_VERSION;
int64_t global_version = OB_INVALID_VERSION;
if (OB_ISNULL(schema_service)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, schema service must not be NULL", K(ret));
} else if (OB_FAIL(schema_service->get_tenant_refreshed_schema_version(tenant_id, local_version))) {
LOG_WARN("fail to get local version", K(ret), "tenant_id", tenant_id);
} else if (OB_FAIL(schema_service->get_tenant_received_broadcast_version(tenant_id, global_version))) {
LOG_WARN("fail to get global version", K(ret), "tenant_id", tenant_id);
} else if (local_version < global_version) {
LOG_INFO("try to refresh schema", K(local_version), K(global_version));
ObSEArray<uint64_t, 1> tenant_ids;
if (OB_FAIL(tenant_ids.push_back(tenant_id))) {
LOG_WARN("fail to push back tenant_id", K(ret), "tenant_id", tenant_id);
} else if (OB_FAIL(schema_service->refresh_and_add_schema(tenant_ids))) {
LOG_WARN("failed to refresh schema", K(ret));
}
}
return ret;
}
int ObAlterTableExecutor::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 ret = OB_SUCCESS;
bool alter_table_add_index = false;
const ObSArray<obrpc::ObIndexArg*> index_arg_list = alter_table_arg.index_arg_list_;
for (int64_t i = 0; OB_SUCC(ret) && i < index_arg_list.size(); ++i) {
obrpc::ObIndexArg* index_arg = index_arg_list.at(i);
if (OB_ISNULL(index_arg)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("index arg should not be null", K(ret));
} else if (obrpc::ObIndexArg::ADD_INDEX == index_arg->index_action_type_) {
alter_table_add_index = true;
break;
}
}
if (!alter_table_add_index) {
if (OB_FAIL(common_rpc_proxy->alter_table(alter_table_arg, res))) {
LOG_WARN("rpc proxy alter table failed", K(ret), "dst", common_rpc_proxy->get_server(), K(alter_table_arg));
}
} else {
ObSArray<obrpc::ObIndexArg*> add_index_arg_list;
alter_table_arg.index_arg_list_.reset();
for (int64_t i = 0; OB_SUCC(ret) && i < index_arg_list.size(); ++i) {
obrpc::ObIndexArg* index_arg = index_arg_list.at(i);
if (OB_ISNULL(index_arg)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("index arg should not be null", K(ret));
} else if (obrpc::ObIndexArg::ADD_INDEX == index_arg->index_action_type_) {
if (OB_FAIL(add_index_arg_list.push_back(index_arg))) {
LOG_WARN("fail to push back to arg_for_adding_index_list", K(ret));
}
} else { // not for adding index
if (OB_FAIL(alter_table_arg.index_arg_list_.push_back(index_arg))) {
LOG_WARN("fail to push back to arg_for_adding_index_list", K(ret));
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(common_rpc_proxy->alter_table(alter_table_arg, res))) {
LOG_WARN("rpc proxy alter table for not adding index failed",
K(ret),
"dst",
common_rpc_proxy->get_server(),
K(alter_table_arg));
}
}
if (OB_SUCC(ret)) {
ObString empty_stmt;
alter_table_arg.is_alter_columns_ = false;
alter_table_arg.is_alter_options_ = false;
alter_table_arg.is_alter_partitions_ = false;
alter_table_arg.ddl_stmt_str_ = empty_stmt;
alter_table_arg.ddl_id_str_ = empty_stmt;
alter_table_arg.alter_constraint_type_ = obrpc::ObAlterTableArg::CONSTRAINT_NO_OPERATION;
ObSArray<uint64_t> added_index_table_ids;
ObCreateIndexExecutor create_index_executor;
for (int64_t i = 0; OB_SUCC(ret) && i < add_index_arg_list.size(); ++i) {
alter_table_arg.index_arg_list_.reset();
if (OB_FAIL(alter_table_arg.index_arg_list_.push_back(add_index_arg_list.at(i)))) {
LOG_WARN("fail to push back to arg_for_adding_index_list", K(ret));
} else if (OB_FAIL(common_rpc_proxy->alter_table(alter_table_arg, res))) {
LOG_WARN("rpc proxy alter table for adding index failed",
K(ret),
"dst",
common_rpc_proxy->get_server(),
K(alter_table_arg));
} else {
obrpc::ObIndexArg* index_arg = alter_table_arg.index_arg_list_.at(0);
obrpc::ObCreateIndexArg* create_index_arg = NULL;
if (OB_ISNULL(index_arg)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index arg is null", K(ret), K(i));
} else if (obrpc::ObIndexArg::ADD_INDEX != index_arg->index_action_type_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index action type should be add index", K(ret), K(i));
} else if (OB_ISNULL(create_index_arg = static_cast<obrpc::ObCreateIndexArg*>(index_arg))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("create index arg is null", K(ret), K(i));
} else if (!is_sync_ddl_user) {
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(create_index_executor.sync_check_index_status(
*my_session, *common_rpc_proxy, *create_index_arg, allocator))) {
LOG_WARN("failed to sync_check_index_status", K(ret), K(*create_index_arg), K(i));
} else {
added_index_table_ids.push_back(res.index_table_id_);
}
}
}
}
if (OB_FAIL(ret)) {
int tmp_ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCCESS == tmp_ret && i < added_index_table_ids.size(); ++i) {
obrpc::ObDropIndexArg drop_index_arg;
obrpc::ObCreateIndexArg* create_index_arg = static_cast<obrpc::ObCreateIndexArg*>(add_index_arg_list.at(i));
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_ = added_index_table_ids.at(i);
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;
if (OB_SUCCESS != (tmp_ret = create_index_executor.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_));
}
}
LOG_INFO("added indexes failed, we rolled back all indexes added in this same alter table sql. But we didn't "
"roll back other actions in this same alter table sql");
}
}
}
return ret;
}
int ObAlterTableExecutor::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 ret = OB_SUCCESS;
const ObSArray<obrpc::ObIndexArg*> index_arg_list = alter_table_arg.index_arg_list_;
ObSArray<obrpc::ObIndexArg*> add_index_arg_list;
alter_table_arg.index_arg_list_.reset();
for (int64_t i = 0; OB_SUCC(ret) && i < index_arg_list.size(); ++i) {
obrpc::ObIndexArg* index_arg = index_arg_list.at(i);
if (OB_ISNULL(index_arg)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("index arg should not be null", KR(ret));
} else if (obrpc::ObIndexArg::ADD_INDEX == index_arg->index_action_type_) {
if (OB_FAIL(add_index_arg_list.push_back(index_arg))) {
LOG_WARN("fail to push back to arg_for_adding_index_list", KR(ret));
}
} else { // for rename/drop index action
if (OB_FAIL(alter_table_arg.index_arg_list_.push_back(index_arg))) {
LOG_WARN("fail to push back to arg_for_adding_index_list", KR(ret));
}
}
}
// for add index action
for (int64_t i = 0; OB_SUCC(ret) && i < add_index_arg_list.size(); ++i) {
if (OB_FAIL(alter_table_arg.index_arg_list_.push_back(add_index_arg_list.at(i)))) {
LOG_WARN("fail to push back to arg_for_adding_index_list", KR(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(common_rpc_proxy->alter_table(alter_table_arg, res))) {
LOG_WARN("rpc proxy alter table failed", KR(ret), "dst", common_rpc_proxy->get_server(), K(alter_table_arg));
} else {
alter_table_arg.based_schema_object_infos_.reset();
}
}
if (OB_SUCC(ret)) {
ObCreateIndexExecutor create_index_executor;
uint64_t failed_index_no = OB_INVALID_ID;
if (!is_sync_ddl_user && alter_table_arg.is_update_global_indexes_ &&
(obrpc::ObAlterTableArg::DROP_PARTITION == alter_table_arg.alter_part_type_ ||
obrpc::ObAlterTableArg::DROP_SUB_PARTITION == alter_table_arg.alter_part_type_ ||
obrpc::ObAlterTableArg::TRUNCATE_PARTITION == alter_table_arg.alter_part_type_ ||
obrpc::ObAlterTableArg::TRUNCATE_SUB_PARTITION == alter_table_arg.alter_part_type_)) {
common::ObSArray<ObAlterTableResArg>& res_array = res.res_arg_array_;
for (int64_t i = 0; OB_SUCC(ret) && i < res_array.size(); ++i) {
obrpc::ObCreateIndexArg create_index_arg;
create_index_arg.index_schema_.set_table_id(res_array.at(i).schema_id_);
create_index_arg.index_schema_.set_schema_version(res_array.at(i).schema_version_);
if (OB_FAIL(create_index_executor.sync_check_index_status(
*my_session, *common_rpc_proxy, create_index_arg, allocator))) {
LOG_WARN("failed to sync_check_index_status", KR(ret), K(create_index_arg), K(i));
}
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < add_index_arg_list.size(); ++i) {
obrpc::ObIndexArg* index_arg = add_index_arg_list.at(i);
obrpc::ObCreateIndexArg* create_index_arg = NULL;
if (OB_ISNULL(index_arg)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index arg is null", KR(ret), K(i));
} else if (obrpc::ObIndexArg::ADD_INDEX != index_arg->index_action_type_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index action type should be add index", KR(ret), K(i), K(*index_arg));
} else if (OB_ISNULL(create_index_arg = static_cast<obrpc::ObCreateIndexArg*>(index_arg))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("create index arg is null", KR(ret), K(i));
} else if (!is_sync_ddl_user) {
create_index_arg->index_schema_.set_table_id(res.res_arg_array_.at(i).schema_id_);
create_index_arg->index_schema_.set_schema_version(res.res_arg_array_.at(i).schema_version_);
if (OB_FAIL(create_index_executor.sync_check_index_status(
*my_session, *common_rpc_proxy, *create_index_arg, allocator))) {
failed_index_no = i;
LOG_WARN("failed to sync_check_index_status", KR(ret), K(*create_index_arg), K(i));
}
}
}
if (OB_FAIL(ret)) {
int tmp_ret = OB_SUCCESS;
for (int64_t i = 0; (OB_SUCCESS == tmp_ret) && (i < add_index_arg_list.size()); ++i) {
if (failed_index_no == i) {
continue;
} else {
obrpc::ObDropIndexArg drop_index_arg;
obrpc::ObCreateIndexArg* create_index_arg = static_cast<obrpc::ObCreateIndexArg*>(add_index_arg_list.at(i));
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_ = res.res_arg_array_.at(i).schema_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;
if (OB_SUCCESS != (tmp_ret = create_index_executor.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_));
}
}
}
LOG_INFO("added indexes failed, we rolled back all indexes added in this same alter table sql. But we didn't "
"roll back other actions in this same alter table sql");
}
}
}
return ret;
}
int ObAlterTableExecutor::execute(ObExecContext& ctx, ObAlterTableStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
ObMySQLProxy* sql_proxy = ctx.get_sql_proxy();
obrpc::ObAlterTableArg& alter_table_arg = stmt.get_alter_table_arg();
ObString first_stmt;
ObSQLSessionInfo* my_session = NULL;
obrpc::ObAlterTableRes res;
bool is_sync_ddl_user = false;
bool need_modify_fk_validate = false;
ObArenaAllocator allocator(ObModIds::OB_SQL_EXECUTOR);
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("get first statement failed", K(ret));
} else {
alter_table_arg.ddl_stmt_str_ = first_stmt;
my_session = ctx.get_my_session();
if (NULL == my_session) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get my session", K(ret), K(ctx));
} else if (OB_FAIL(check_alter_partition(ctx, stmt, alter_table_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(set_index_arg_list(ctx, stmt))) {
LOG_WARN("fail to set index_arg_list", 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_ISNULL(sql_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("sql_proxy is null", 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 (OB_INVALID_ID == alter_table_arg.session_id_ && 0 != my_session->get_sessid_for_table() &&
FALSE_IT(alter_table_arg.session_id_ = my_session->get_sessid_for_table())) {
// impossible
} else {
if (OB_SUCC(ret) && !is_sync_ddl_user && 1 == alter_table_arg.foreign_key_arg_list_.count()) {
if ((!alter_table_arg.foreign_key_arg_list_.at(0).is_modify_fk_state_ &&
alter_table_arg.foreign_key_arg_list_.at(0).validate_flag_) ||
(alter_table_arg.foreign_key_arg_list_.at(0).is_modify_validate_flag_ &&
alter_table_arg.foreign_key_arg_list_.at(0).validate_flag_)) {
need_modify_fk_validate = true;
ObString empty_stmt;
alter_table_arg.ddl_stmt_str_ = empty_stmt;
alter_table_arg.foreign_key_arg_list_.at(0).validate_flag_ = false;
}
}
if (OB_SUCC(ret) && (GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_3100)) {
if (OB_FAIL(
alter_table_rpc_v2(alter_table_arg, res, allocator, common_rpc_proxy, my_session, is_sync_ddl_user))) {
LOG_WARN("Failed to alter table rpc v2", K(ret));
}
} else if (OB_SUCC(ret) && (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_3100)) {
if (OB_FAIL(
alter_table_rpc_v1(alter_table_arg, res, allocator, common_rpc_proxy, my_session, is_sync_ddl_user))) {
LOG_WARN("Failed to alter table rpc v1", K(ret));
}
}
}
}
bool is_oracle_mode = false;
if (OB_SUCC(ret)) {
if (OB_FAIL(alter_table_arg.alter_table_schema_.check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("fail to check if tenant mode is oracle mode", K(ret));
}
}
if (OB_SUCC(ret) && is_oracle_mode && !is_sync_ddl_user &&
(obrpc::ObAlterTableArg::ADD_CONSTRAINT == alter_table_arg.alter_constraint_type_ ||
(obrpc::ObAlterTableArg::ALTER_CONSTRAINT_STATE == alter_table_arg.alter_constraint_type_))) {
common::ObCommonSqlProxy* user_sql_proxy;
ObOracleSqlProxy oracle_sql_proxy;
ObTableSchema::const_constraint_iterator iter = alter_table_arg.alter_table_schema_.constraint_begin();
bool is_data_valid = false;
if (OB_ISNULL(ctx.get_sql_proxy())) {
LOG_WARN("sql_proxy is null", K(ret), K(ctx.get_sql_proxy()));
} else if (OB_FAIL(oracle_sql_proxy.init(ctx.get_sql_proxy()->get_pool()))) {
LOG_WARN("init oracle sql proxy failed", K(ret));
} else if (CONSTRAINT_TYPE_CHECK != (*iter)->get_constraint_type()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("only alter table add check constraint can come here now", K(ret), K((*iter)->get_constraint_type()));
} else if ((obrpc::ObAlterTableArg::ADD_CONSTRAINT == alter_table_arg.alter_constraint_type_ &&
!(*iter)->get_validate_flag()) ||
(obrpc::ObAlterTableArg::ALTER_CONSTRAINT_STATE == alter_table_arg.alter_constraint_type_ &&
!(*iter)->get_is_modify_validate_flag()) ||
(obrpc::ObAlterTableArg::ALTER_CONSTRAINT_STATE == alter_table_arg.alter_constraint_type_ &&
(*iter)->get_is_modify_validate_flag() && !(*iter)->get_validate_flag())) {
// do nothing, don't check if data is valid
} else if (OB_FAIL(refresh_schema_for_table(alter_table_arg.alter_table_schema_.get_tenant_id()))) {
LOG_WARN("refresh_schema_for_table failed", K(ret));
} else {
user_sql_proxy = &oracle_sql_proxy;
if (OB_FAIL(check_check_constraint_data_validity(ctx,
alter_table_arg,
user_sql_proxy,
res.schema_version_,
(*iter)->get_check_expr_str(),
is_data_valid))) {
LOG_WARN("failed to check check constraint data validity", K(ret), K(alter_table_arg), K(res.schema_version_));
} else if (!is_data_valid) {
const ObString& origin_database_name = alter_table_arg.alter_table_schema_.get_origin_database_name();
if (origin_database_name.empty() || (*iter)->get_check_expr_str().empty()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("database name or cst name is null",
K(ret),
K(origin_database_name),
K((*iter)->get_check_expr_str().empty()));
} else {
ret = OB_ERR_ADD_CHECK_CONSTRAINT_VIOLATED;
LOG_USER_ERROR(OB_ERR_ADD_CHECK_CONSTRAINT_VIOLATED,
origin_database_name.length(),
origin_database_name.ptr(),
(*iter)->get_constraint_name_str().length(),
(*iter)->get_constraint_name_str().ptr());
}
}
}
if (OB_FAIL(ret) && !is_data_valid) {
int tmp_ret = ret;
obrpc::ObAlterTableRes tmp_res;
ret = OB_SUCCESS;
if (obrpc::ObAlterTableArg::ADD_CONSTRAINT == alter_table_arg.alter_constraint_type_) {
(*iter)->set_constraint_id(res.constriant_id_);
if (OB_FAIL(set_drop_constraint_ddl_stmt_str(alter_table_arg, allocator))) {
LOG_WARN("fail to set drop constraint ddl_stmt_str", K(ret));
} else {
alter_table_arg.alter_constraint_type_ = obrpc::ObAlterTableArg::DROP_CONSTRAINT;
}
} else {
if ((*iter)->get_is_modify_enable_flag()) {
(*iter)->set_enable_flag(!(*iter)->get_enable_flag());
}
if ((*iter)->get_is_modify_rely_flag()) {
(*iter)->set_rely_flag(!(*iter)->get_rely_flag());
}
if ((*iter)->get_is_modify_validate_flag()) {
(*iter)->set_validate_flag(!(*iter)->get_validate_flag());
}
alter_table_arg.alter_constraint_type_ = obrpc::ObAlterTableArg::ALTER_CONSTRAINT_STATE;
if (OB_FAIL(set_alter_constraint_ddl_stmt_str_for_check(alter_table_arg, allocator))) {
LOG_WARN("fail to set alter constraint ddl_stmt_str", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(common_rpc_proxy->alter_table(alter_table_arg, tmp_res))) {
LOG_WARN("rpc proxy alter table failed", K(ret), "dst", common_rpc_proxy->get_server());
} else {
ret = tmp_ret;
}
}
}
if (OB_SUCC(ret) && !is_sync_ddl_user && 1 == alter_table_arg.foreign_key_arg_list_.count()) {
if (!need_modify_fk_validate) {
// do nothing, don't check if data is valid
} else {
common::ObCommonSqlProxy* user_sql_proxy;
ObOracleSqlProxy oracle_sql_proxy;
obrpc::ObCreateForeignKeyArg fk_arg = alter_table_arg.foreign_key_arg_list_.at(0);
bool is_data_valid = false;
if (OB_ISNULL(ctx.get_sql_proxy())) {
LOG_WARN("sql_proxy is null", K(ret), K(ctx.get_sql_proxy()));
} else if (OB_FAIL(oracle_sql_proxy.init(ctx.get_sql_proxy()->get_pool()))) {
LOG_WARN("init oracle sql proxy failed", K(ret));
} else if (OB_FAIL(refresh_schema_for_table(alter_table_arg.alter_table_schema_.get_tenant_id()))) {
LOG_WARN("refresh_schema_for_table failed", K(ret));
} else {
if (is_oracle_mode) {
user_sql_proxy = &oracle_sql_proxy;
} else {
user_sql_proxy = sql_proxy; // mysql mode
}
if (OB_FAIL(check_fk_constraint_data_validity(
ctx, alter_table_arg, user_sql_proxy, res.schema_version_, is_data_valid))) {
LOG_WARN("failed to check fk constraint data validity", K(ret), K(alter_table_arg), K(res.schema_version_));
} else if (!is_data_valid) {
ret = OB_ERR_ORPHANED_CHILD_RECORD_EXISTS;
LOG_USER_ERROR(OB_ERR_ORPHANED_CHILD_RECORD_EXISTS,
alter_table_arg.alter_table_schema_.get_origin_database_name().length(),
alter_table_arg.alter_table_schema_.get_origin_database_name().ptr(),
fk_arg.foreign_key_name_.length(),
fk_arg.foreign_key_name_.ptr());
}
}
if (OB_FAIL(ret) && !is_data_valid) {
int tmp_ret = ret;
ret = OB_SUCCESS;
obrpc::ObAlterTableRes tmp_res;
obrpc::ObDropForeignKeyArg drop_foreign_key_arg;
if (!alter_table_arg.foreign_key_arg_list_.at(0).is_modify_fk_state_) {
drop_foreign_key_arg.index_action_type_ = obrpc::ObIndexArg::DROP_FOREIGN_KEY;
drop_foreign_key_arg.foreign_key_name_ = fk_arg.foreign_key_name_;
if (OB_FAIL(alter_table_arg.index_arg_list_.push_back(&drop_foreign_key_arg))) {
LOG_WARN("fail to push back arg to index_arg_list", K(ret));
} else if (OB_FAIL(set_drop_constraint_ddl_stmt_str(alter_table_arg, allocator))) {
LOG_WARN("fail to set drop constraint ddl_stmt_str", K(ret));
} else {
alter_table_arg.foreign_key_arg_list_.reset();
}
} else {
if (alter_table_arg.foreign_key_arg_list_.at(0).is_modify_rely_flag_) {
alter_table_arg.foreign_key_arg_list_.at(0).rely_flag_ =
!alter_table_arg.foreign_key_arg_list_.at(0).rely_flag_;
}
if (alter_table_arg.foreign_key_arg_list_.at(0).is_modify_enable_flag_) {
alter_table_arg.foreign_key_arg_list_.at(0).enable_flag_ =
!alter_table_arg.foreign_key_arg_list_.at(0).enable_flag_;
}
if (alter_table_arg.foreign_key_arg_list_.at(0).is_modify_validate_flag_) {
alter_table_arg.foreign_key_arg_list_.at(0).validate_flag_ =
!alter_table_arg.foreign_key_arg_list_.at(0).validate_flag_;
}
if (OB_FAIL(set_alter_constraint_ddl_stmt_str_for_fk(alter_table_arg, allocator))) {
LOG_WARN("fail to set alter constraint ddl_stmt_str", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(common_rpc_proxy->alter_table(alter_table_arg, tmp_res))) {
LOG_WARN("alter table failed", K(ret));
}
alter_table_arg.index_arg_list_.reset();
ret = tmp_ret;
} else if (OB_SUCC(ret) && need_modify_fk_validate) {
obrpc::ObAlterTableRes tmp_res;
alter_table_arg.ddl_stmt_str_ = first_stmt;
alter_table_arg.foreign_key_arg_list_.at(0).is_modify_fk_state_ = true;
alter_table_arg.foreign_key_arg_list_.at(0).is_modify_validate_flag_ = true;
alter_table_arg.foreign_key_arg_list_.at(0).validate_flag_ = true;
if (OB_FAIL(common_rpc_proxy->alter_table(alter_table_arg, tmp_res))) {
LOG_WARN("alter table modify fk validate failed", K(ret), K(alter_table_arg));
}
}
}
}
return ret;
}
int ObAlterTableExecutor::set_alter_col_nullable_ddl_stmt_str(
obrpc::ObAlterTableArg& alter_table_arg, common::ObIAllocator& allocator)
{
int ret = OB_SUCCESS;
AlterTableSchema& alter_table_schema = alter_table_arg.alter_table_schema_;
ObString column_name;
const ObColumnSchemaV2* col_schema = NULL;
char* buf = NULL;
int64_t buf_len = OB_MAX_SQL_LENGTH;
int64_t pos = 0;
if (alter_table_schema.get_column_count() != 1) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("column count != 1", K(ret), K(alter_table_schema.get_column_count()));
} else if (OB_ISNULL(col_schema = alter_table_schema.get_column_schema_by_idx(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("col_schema is null", K(ret));
} else {
column_name = col_schema->get_column_name_str();
}
if (OB_FAIL(ret)) {
} else if (column_name.empty()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cst_name is empty", K(ret), K(column_name));
} else 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 (OB_FAIL(databuff_printf(buf,
buf_len,
pos,
"ALTER TABLE \"%.*s\".\"%.*s\" MODIFY COLUMN %.*s NULL",
alter_table_schema.get_origin_database_name().length(),
alter_table_schema.get_origin_database_name().ptr(),
alter_table_schema.get_origin_table_name().length(),
alter_table_schema.get_origin_table_name().ptr(),
column_name.length(),
column_name.ptr()))) {
LOG_WARN("fail to print ddl_stmt_str for rollback", K(ret));
} else {
alter_table_arg.ddl_stmt_str_.assign_ptr(buf, static_cast<int32_t>(pos));
}
return ret;
}
int ObAlterTableExecutor::set_alter_constraint_ddl_stmt_str_for_fk(
obrpc::ObAlterTableArg& alter_table_arg, common::ObIAllocator& allocator)
{
int ret = OB_SUCCESS;
AlterTableSchema& alter_table_schema = alter_table_arg.alter_table_schema_;
ObString cst_name;
char* buf = NULL;
int64_t buf_len = OB_MAX_SQL_LENGTH;
int64_t pos = 0;
obrpc::ObCreateForeignKeyArg fk_arg = alter_table_arg.foreign_key_arg_list_.at(0);
cst_name = fk_arg.foreign_key_name_;
if (OB_FAIL(ret)) {
} else if (cst_name.empty()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cst_name is empty", K(ret), K(cst_name));
} else 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 (OB_FAIL(databuff_printf(buf,
buf_len,
pos,
"ALTER TABLE \"%.*s\".\"%.*s\" MODIFY CONSTRAINT %.*s ",
alter_table_schema.get_origin_database_name().length(),
alter_table_schema.get_origin_database_name().ptr(),
alter_table_schema.get_origin_table_name().length(),
alter_table_schema.get_origin_table_name().ptr(),
cst_name.length(),
cst_name.ptr()))) {
LOG_WARN("fail to print ddl_stmt_str for rollback", K(ret));
} else if (fk_arg.is_modify_rely_flag_ &&
OB_FAIL(databuff_printf(buf, buf_len, pos, fk_arg.rely_flag_ ? "RELY " : "NORELY "))) {
LOG_WARN("fail to print rely flag for rollback", K(ret));
} else if (fk_arg.is_modify_enable_flag_ &&
OB_FAIL(databuff_printf(buf, buf_len, pos, fk_arg.enable_flag_ ? "ENABLE " : "DISABLE "))) {
LOG_WARN("fail to print enable flag for rollback", K(ret));
} else if (fk_arg.is_modify_validate_flag_ &&
OB_FAIL(databuff_printf(buf, buf_len, pos, fk_arg.validate_flag_ ? "VALIDATE " : "NOVALIDATE "))) {
LOG_WARN("fail to print enable flag for rollback", K(ret));
} else {
alter_table_arg.ddl_stmt_str_.assign_ptr(buf, static_cast<int32_t>(pos));
}
return ret;
}
int ObAlterTableExecutor::set_alter_constraint_ddl_stmt_str_for_check(
obrpc::ObAlterTableArg& alter_table_arg, common::ObIAllocator& allocator)
{
int ret = OB_SUCCESS;
AlterTableSchema& alter_table_schema = alter_table_arg.alter_table_schema_;
ObString cst_name;
char* buf = NULL;
int64_t buf_len = OB_MAX_SQL_LENGTH;
int64_t pos = 0;
ObTableSchema::const_constraint_iterator iter = alter_table_arg.alter_table_schema_.constraint_begin();
cst_name = (*iter)->get_constraint_name_str();
if (OB_FAIL(ret)) {
} else if (cst_name.empty()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cst_name is empty", K(ret), K(cst_name));
} else 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 (OB_FAIL(databuff_printf(buf,
buf_len,
pos,
"ALTER TABLE \"%.*s\".\"%.*s\" MODIFY CONSTRAINT %.*s ",
alter_table_schema.get_origin_database_name().length(),
alter_table_schema.get_origin_database_name().ptr(),
alter_table_schema.get_origin_table_name().length(),
alter_table_schema.get_origin_table_name().ptr(),
cst_name.length(),
cst_name.ptr()))) {
LOG_WARN("fail to print ddl_stmt_str for rollback", K(ret));
} else if ((*iter)->get_is_modify_rely_flag() &&
OB_FAIL(databuff_printf(buf, buf_len, pos, (*iter)->get_rely_flag() ? "RELY " : "NORELY "))) {
LOG_WARN("fail to print rely flag for rollback", K(ret));
} else if ((*iter)->get_is_modify_enable_flag() &&
OB_FAIL(databuff_printf(buf, buf_len, pos, (*iter)->get_enable_flag() ? "ENABLE " : "DISABLE "))) {
LOG_WARN("fail to print enable flag for rollback", K(ret));
} else if ((*iter)->get_is_modify_validate_flag() &&
OB_FAIL(databuff_printf(buf, buf_len, pos, (*iter)->get_validate_flag() ? "VALIDATE " : "NOVALIDATE "))) {
LOG_WARN("fail to print enable flag for rollback", K(ret));
} else {
alter_table_arg.ddl_stmt_str_.assign_ptr(buf, static_cast<int32_t>(pos));
}
return ret;
}
int ObAlterTableExecutor::set_drop_constraint_ddl_stmt_str(
obrpc::ObAlterTableArg& alter_table_arg, common::ObIAllocator& allocator)
{
int ret = OB_SUCCESS;
AlterTableSchema& alter_table_schema = alter_table_arg.alter_table_schema_;
ObString cst_name;
char* buf = NULL;
int64_t buf_len = OB_MAX_SQL_LENGTH;
int64_t pos = 0;
if (obrpc::ObAlterTableArg::ADD_CONSTRAINT == alter_table_arg.alter_constraint_type_) {
ObTableSchema::const_constraint_iterator iter = alter_table_arg.alter_table_schema_.constraint_begin();
cst_name = (*iter)->get_constraint_name_str();
} else if (1 == alter_table_arg.foreign_key_arg_list_.count() &&
!alter_table_arg.foreign_key_arg_list_.at(0).is_modify_enable_flag_) {
obrpc::ObCreateForeignKeyArg fk_arg = alter_table_arg.foreign_key_arg_list_.at(0);
cst_name = fk_arg.foreign_key_name_;
}
if (OB_FAIL(ret)) {
} else if (cst_name.empty()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cst_name is empty", K(ret), K(cst_name));
} else 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 (OB_FAIL(databuff_printf(buf,
buf_len,
pos,
share::is_oracle_mode() ? "ALTER TABLE \"%.*s\".\"%.*s\" DROP CONSTRAINT \"%.*s\""
: "ALTER TABLE `%.*s`.`%.*s` DROP FOREIGN KEY `%.*s`",
alter_table_schema.get_origin_database_name().length(),
alter_table_schema.get_origin_database_name().ptr(),
alter_table_schema.get_origin_table_name().length(),
alter_table_schema.get_origin_table_name().ptr(),
cst_name.length(),
cst_name.ptr()))) {
LOG_WARN("fail to print ddl_stmt_str for rollback", K(ret));
} else {
alter_table_arg.ddl_stmt_str_.assign_ptr(buf, static_cast<int32_t>(pos));
}
return ret;
}
int ObAlterTableExecutor::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 ret = OB_SUCCESS;
if (OB_UNLIKELY(partition_leader_array.count() <= 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret));
} else {
invalid_snapshot_id_array.reset();
snapshot_array.reset();
const int64_t array_count = partition_leader_array.count();
for (int64_t index = 0; OB_SUCC(ret) && index < array_count; ++index) {
if (OB_FAIL(invalid_snapshot_id_array.push_back(index))) {
LOG_WARN("fail to push back", K(ret));
} else if (OB_FAIL(snapshot_array.push_back(0))) {
LOG_WARN("fail to push back", K(ret));
}
}
}
return ret;
}
int ObAlterTableExecutor::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 ret = OB_SUCCESS;
ObPartitionTableOperator* pt_operator;
UNUSED(schema_guard);
if (OB_ISNULL(data_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("data table schema is null", K(ret));
} else if (OB_ISNULL(ctx.get_sql_ctx())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("sql ctx is null", K(ret));
} else if (OB_ISNULL(
pt_operator = const_cast<ObPartitionTableOperator*>(ctx.get_sql_ctx()->partition_table_operator_))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("partition_table_operator is null", K(ret));
} else {
bool check_dropped_schema = false;
ObTablePartitionKeyIter partition_key_iter(*data_schema, check_dropped_schema);
ObPartitionKey pkey;
ObPartitionKey phy_pkey;
while (OB_SUCC(ret) && OB_SUCC(partition_key_iter.next_partition_key_v2(pkey))) {
ObArenaAllocator allocator(ObModIds::OB_RS_PARTITION_TABLE_TEMP);
ObPartitionInfo info;
info.set_allocator(&allocator);
PartitionServer partition_leader;
const ObPartitionReplica* leader_replica = NULL;
if (OB_UNLIKELY(!pkey.is_valid())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("pkey is invalid", K(ret));
} else if (data_schema->is_binding_table()) {
if (OB_FAIL(data_schema->get_pg_key(pkey, phy_pkey))) {
LOG_WARN("fail to get pg key", K(ret), K(pkey));
}
} else {
phy_pkey = pkey;
}
if (OB_FAIL(ret)) {
// failed
} else if (OB_FAIL(pt_operator->get(phy_pkey.get_table_id(), phy_pkey.get_partition_id(), info))) {
LOG_WARN("fail to get partition info", K(phy_pkey));
} else if (OB_FAIL(info.find_leader_v2(leader_replica))) {
LOG_WARN("fail to find leader", K(ret));
} else if (OB_UNLIKELY(NULL == leader_replica)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("leader replica ptr is null", K(ret));
} else if (partition_leader.set(
leader_replica->server_, pkey.get_table_id(), pkey.get_partition_id(), pkey.get_partition_cnt())) {
LOG_WARN("fail to set partition leader", K(ret), K(*leader_replica));
} else if (OB_FAIL(partition_leader_array.push_back(partition_leader))) {
LOG_WARN("fail to push back", K(ret));
}
}
if (OB_ITER_END == ret) {
ret = OB_SUCCESS;
} else {
LOG_WARN("fail to get leader array", K(ret));
}
if (OB_SUCC(ret)) {
if (partition_leader_array.count() != data_schema->get_all_part_num()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("part num and leader cnt not match",
K(ret),
"table_id",
data_schema->get_table_id(),
"left_cnt",
partition_leader_array.count(),
"right_cnt",
data_schema->get_all_part_num());
}
}
}
return ret;
}
int ObAlterTableExecutor::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 ret = OB_SUCCESS;
if (OB_UNLIKELY(ret_code_array.count() != invalid_snapshot_id_array.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("array count not match",
K(ret),
"left array count",
ret_code_array.count(),
"right array count",
invalid_snapshot_id_array.count());
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < ret_code_array.count(); ++i) {
int ret_code = ret_code_array.at(i);
if (OB_SUCCESS == ret_code) {
// already got snapshot
} else if (OB_EAGAIN == ret_code || OB_TIMEOUT == ret_code) {
// transaction on the partition not finish, wait and retry
} else if (OB_NOT_MASTER == ret_code || OB_PARTITION_NOT_EXIST == ret_code) {
int64_t part_array_idx = invalid_snapshot_id_array.at(i);
if (part_array_idx >= invalid_snapshot_id_array.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("part array id unexpected",
K(ret),
K(part_array_idx),
"invalid snapshot id array count",
invalid_snapshot_id_array.count());
} else {
const ObPartitionKey& pkey = partition_leader_array.at(part_array_idx).pkey_;
ObArenaAllocator allocator(ObModIds::OB_RS_PARTITION_TABLE_TEMP);
ObPartitionInfo info;
const ObPartitionReplica* leader_replica = NULL;
ObReplicaFilterHolder filter;
info.set_allocator(&allocator);
if (OB_FAIL(GCTX.pt_operator_->get(pkey.get_table_id(), pkey.get_partition_id(), info))) {
LOG_WARN("fail to get partition info", K(ret), K(pkey));
} else if (OB_FAIL(filter.set_replica_status(REPLICA_STATUS_NORMAL))) {
LOG_WARN("fail to set replica status", K(ret));
} else if (OB_FAIL(filter.set_in_member_list())) {
LOG_WARN("fail to set in member list", K(ret));
} else if (OB_FAIL(info.filter(filter))) {
LOG_WARN("fail to do filter", K(ret));
} else if (OB_FAIL(info.find_leader_v2(leader_replica))) {
if (OB_ENTRY_NOT_EXIST == ret) {
ret = OB_SUCCESS;
} else {
LOG_WARN("fail to get leader", K(ret));
}
} else if (OB_UNLIKELY(NULL == leader_replica)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("leader replica ptr is null", K(ret));
} else if (OB_FAIL(partition_leader_array.at(part_array_idx).set_server(leader_replica->server_))) {
LOG_WARN("fail to set server", K(ret));
} else {
} // no more to do
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected ret code", K(ret));
}
}
}
return ret;
}
int ObAlterTableExecutor::pick_build_snapshot(const common::ObIArray<int64_t>& snapshot_array, int64_t& snapshot)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(snapshot_array.count() <= 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret));
} else {
snapshot = 0;
for (int64_t i = 0; OB_SUCC(ret) && i < snapshot_array.count(); ++i) {
const int64_t this_snapshot = snapshot_array.at(i);
if (this_snapshot > snapshot) {
snapshot = this_snapshot;
}
}
}
return ret;
}
template <typename PROXY>
int ObAlterTableExecutor::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)
{
int ret = OB_SUCCESS;
if (invalid_snapshot_id_array.count() != ret_code_array.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("array count not match",
K(ret),
"left array count",
invalid_snapshot_id_array.count(),
"right array count",
ret_code_array.count());
} else if (proxy.get_results().count() != ret_code_array.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("array count not match",
K(ret),
"left array count",
proxy.get_results().count(),
"right array count",
ret_code_array.count());
} else {
common::ObArray<int64_t> tmp_invalid_snapshot_id_array;
for (int64_t i = 0; OB_SUCC(ret) && i < ret_code_array.count(); ++i) {
int ret_code = ret_code_array.at(i);
int64_t snapshot_array_idx = invalid_snapshot_id_array.at(i);
if (OB_SUCCESS == ret_code) {
if (snapshot_array_idx >= snapshot_array.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("snapshot array idx unexpected",
K(ret),
K(snapshot_array_idx),
"snapshot_array count",
snapshot_array.count());
} else if (NULL == proxy.get_results().at(i)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("result ptr is null", K(ret));
} else {
snapshot_array.at(snapshot_array_idx) = proxy.get_results().at(i)->snapshot_;
}
} else if (OB_EAGAIN == ret_code || OB_NOT_MASTER == ret_code || OB_PARTITION_NOT_EXIST == ret_code ||
OB_TIMEOUT == ret_code) {
if (OB_FAIL(tmp_invalid_snapshot_id_array.push_back(snapshot_array_idx))) {
LOG_WARN("fail to push back", K(ret));
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("rpc invoking failed", K(ret), K(ret_code));
}
}
if (OB_FAIL(ret)) {
} else {
invalid_snapshot_id_array.reset();
if (OB_FAIL(invalid_snapshot_id_array.assign(tmp_invalid_snapshot_id_array))) {
LOG_WARN("fail to assign array", K(ret));
}
}
}
return ret;
}
template <typename PROXY, typename ARG>
int ObAlterTableExecutor::do_get_associated_snapshot(PROXY& rpc_proxy, ARG& rpc_arg, int64_t schema_version,
const share::schema::ObTableSchema* table_schema, common::ObIArray<PartitionServer>& partition_leader_array,
int64_t& snapshot)
{
int ret = OB_SUCCESS;
common::ObArray<int64_t> snapshot_array;
common::ObArray<int64_t> invalid_snapshot_id_array;
if (OB_UNLIKELY(NULL == table_schema || partition_leader_array.count() <= 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), KP(table_schema), "array_cnt", partition_leader_array.count());
} else if (OB_FAIL(init_build_snapshot_ctx(partition_leader_array, invalid_snapshot_id_array, snapshot_array))) {
LOG_WARN("fail to init invalid snapshot id array", K(ret));
} else {
bool got_snapshot = false;
common::ObArray<int> ret_code_array;
int64_t timeout = table_schema->get_all_part_num() * TIME_INTERVAL_PER_PART_US;
const int64_t max_timeout = MAX_WAIT_CHECK_SCHEMA_VERSION_INTERVAL_US;
const int64_t min_timeout = MIN_WAIT_CHECK_SCHEMA_VERSION_INTERVAL_US;
timeout = std::min(timeout, max_timeout);
timeout = std::max(timeout, min_timeout);
int64_t timeout_ts = timeout + ObTimeUtility::current_time();
rootserver::ObGlobalIndexTask task;
task.schema_version_ = schema_version;
while (OB_SUCC(ret) && !got_snapshot && ObTimeUtility::current_time() < timeout_ts) {
rpc_proxy.reuse();
ret_code_array.reset();
for (int64_t i = 0; OB_SUCC(ret) && i < invalid_snapshot_id_array.count(); ++i) {
int64_t index = invalid_snapshot_id_array.at(i);
rpc_arg.reuse();
if (index >= partition_leader_array.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index unexpected", K(ret), K(index), "array count", partition_leader_array.count());
} else if (OB_FAIL(rpc_arg.build(&task, partition_leader_array.at(index).pkey_))) {
LOG_WARN("fail to build rpc arg", K(ret));
} else if (OB_FAIL(rpc_proxy.call(
partition_leader_array.at(index).server_, GET_ASSOCIATED_SNAPSHOT_TIMEOUT, rpc_arg))) {
LOG_WARN("fail to call rpc", K(ret));
}
}
int tmp_ret = OB_SUCCESS;
if (OB_SUCCESS != (tmp_ret = rpc_proxy.wait_all(ret_code_array))) {
LOG_WARN("rpc_proxy wait failed", K(ret), K(tmp_ret));
ret = (OB_SUCCESS == ret) ? tmp_ret : ret;
} else if (OB_SUCC(ret)) { // wait_all SUCC and the above process SUCC
common::ObArray<int64_t> pre_invalid_snapshot_id_array;
if (OB_FAIL(pre_invalid_snapshot_id_array.assign(invalid_snapshot_id_array))) {
LOG_WARN("fail to assign invalid snapshot id array", K(ret));
} else if (OB_FAIL(update_build_snapshot_ctx(
rpc_proxy, ret_code_array, invalid_snapshot_id_array, snapshot_array))) {
LOG_WARN("fail to update build snapshot ctx", K(ret));
} else if (invalid_snapshot_id_array.count() <= 0) {
if (OB_FAIL(pick_build_snapshot(snapshot_array, snapshot))) {
LOG_WARN("fail to pick snapshot array", K(ret));
} else {
LOG_INFO("get snapshot", K(ret));
got_snapshot = true;
}
} else {
int64_t regular_wait_us = WAIT_US;
int64_t sleep_us = timeout_ts - ObTimeUtility::current_time();
sleep_us = std::max(sleep_us, 1L);
sleep_us = std::min(sleep_us, regular_wait_us);
usleep(static_cast<uint32_t>(sleep_us));
if (OB_FAIL(update_partition_leader_array(
partition_leader_array, ret_code_array, pre_invalid_snapshot_id_array))) {
LOG_WARN("fail to update partition leader array", K(ret));
}
}
}
}
if (OB_FAIL(ret)) {
} else if (!got_snapshot) {
ret = OB_TIMEOUT;
LOG_WARN("get snapshot timeout", K(ret));
}
}
return ret;
}
int ObAlterTableExecutor::get_constraint_check_snapshot(ObExecContext& ctx, int64_t schema_version,
share::schema::ObSchemaGetterGuard& schema_guard, const uint64_t table_id, int64_t& snapshot)
{
int ret = OB_SUCCESS;
common::ObArray<PartitionServer> partition_leader_array;
const share::schema::ObTableSchema* data_schema = NULL;
if (OB_UNLIKELY(NULL == GCTX.srv_rpc_proxy_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("rpc_proxy_ ptr is null", K(ret));
} else if (OB_FAIL(schema_guard.get_table_schema(table_id, data_schema))) {
LOG_WARN("fail to get table schema", K(ret), "table_id", table_id);
} else if (OB_UNLIKELY(NULL == data_schema)) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("data schema not exist", K(ret), "table_id", table_id);
} else if (OB_FAIL(generate_original_table_partition_leader_array(
ctx, schema_guard, data_schema, partition_leader_array))) {
LOG_WARN("fail to generate original leader array", K(ret));
} else {
rootserver::ObCheckSchemaVersionElapsedProxy proxy(
*GCTX.srv_rpc_proxy_, &obrpc::ObSrvRpcProxy::check_schema_version_elapsed);
obrpc::ObCheckSchemaVersionElapsedArg arg;
if (OB_FAIL(
do_get_associated_snapshot(proxy, arg, schema_version, data_schema, partition_leader_array, snapshot))) {
LOG_WARN("fail to do get snapshot", K(ret));
} else {
} // no more to do
}
return ret;
}
int ObAlterTableExecutor::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 ret = OB_SUCCESS;
is_data_valid = false;
ObSqlString sql_string;
SMART_VAR(ObMySQLProxy::MySQLResult, res)
{
common::sqlclient::ObMySQLResult* result = NULL;
if (OB_SUCC(ret)) {
if (check_expr_str.empty()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("check_expr_str is empty", K(ret));
} else if (OB_FAIL(sql_string.assign_fmt("SELECT 1 FROM \"%.*s\".\"%.*s\" WHERE NOT (%.*s) AND ROWNUM = 1",
static_cast<int>(alter_table_schema.get_origin_database_name().length()),
alter_table_schema.get_origin_database_name().ptr(),
static_cast<int>(alter_table_schema.get_origin_table_name().length()),
alter_table_schema.get_origin_table_name().ptr(),
static_cast<int>(check_expr_str.length()),
check_expr_str.ptr()))) {
LOG_WARN("fail to assign format", K(ret));
} else if (OB_FAIL(sql_proxy->read(res, alter_table_schema.get_tenant_id(), sql_string.ptr()))) {
LOG_WARN("execute sql failed", K(ret), K(sql_string.ptr()));
} else if (OB_ISNULL(result = res.get_result())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("execute sql failed", K(ret), K(alter_table_schema.get_tenant_id()), K(sql_string));
} else if (OB_FAIL(result->next())) {
if (OB_ITER_END == ret) {
ret = OB_SUCCESS;
is_data_valid = true;
} else {
LOG_WARN("iterate next result fail", K(ret), K(sql_string));
}
} else {
LOG_WARN("old data is not valid for this new check constraint", K(ret), K(is_data_valid), K(sql_string));
}
}
}
return ret;
}
int ObAlterTableExecutor::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 ret = OB_SUCCESS;
is_data_valid = false;
int64_t snapshot = 0;
ObSchemaGetterGuard schema_guard;
const AlterTableSchema& alter_table_schema = alter_table_arg.alter_table_schema_;
const uint64_t tenant_id = alter_table_schema.get_tenant_id();
const observer::ObGlobalContext& gctx = observer::ObServer::get_instance().get_gctx();
const ObString& origin_database_name = alter_table_schema.get_origin_database_name();
const ObString& origin_table_name = alter_table_schema.get_origin_table_name();
const ObTableSchema* orig_table_schema = NULL;
if (OB_ISNULL(gctx.schema_service_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, schema service must not be NULL", K(ret));
} else if (OB_FAIL(gctx.schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) {
LOG_WARN("fail to get tenant schema guard", K(ret));
}
if (OB_SUCC(ret)) {
if (origin_database_name.empty() || origin_table_name.empty()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("database name or table name is null",
K(ret),
K(alter_table_schema),
K(origin_database_name),
K(origin_table_name));
} else {
if (OB_FAIL(schema_guard.get_table_schema(
tenant_id, origin_database_name, origin_table_name, false, orig_table_schema))) {
LOG_WARN("fail to get table schema", K(ret), K(tenant_id), K(origin_database_name), K(origin_table_name));
} else if (OB_ISNULL(orig_table_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("NULL ptr", K(ret), K(orig_table_schema));
} else {
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(get_constraint_check_snapshot(
ctx, schema_version, schema_guard, orig_table_schema->get_table_id(), snapshot))) {
LOG_WARN("fail to get global index build snapshot", K(ret));
} else if (OB_FAIL(check_data_validity_for_check_by_inner_sql(
alter_table_schema, sql_proxy, check_expr_str, is_data_valid))) {
LOG_WARN("fail to check data validity by inner sql", K(ret));
}
}
return ret;
}
int ObAlterTableExecutor::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 ret = OB_SUCCESS;
is_data_valid = false;
ObSqlString sql_string;
int64_t i = 0;
SMART_VAR(ObMySQLProxy::MySQLResult, res)
{
common::sqlclient::ObMySQLResult* result = NULL;
// print str like "select c1, c2 from db.t2 where c1 is not null and c2 is not null minus select c3, c4 from db.t1"
if (OB_SUCC(ret)) {
// print "select "
if (OB_FAIL(sql_string.assign_fmt("SELECT "))) {
LOG_WARN("fail to assign format", K(ret));
}
// print "c1, "
for (i = 0; OB_SUCC(ret) && i < fk_arg.child_columns_.count() - 1; ++i) {
if (OB_FAIL(sql_string.append_fmt(share::is_oracle_mode() ? "\"%.*s\", " : "`%.*s`, ",
static_cast<int>(fk_arg.child_columns_.at(i).length()),
fk_arg.child_columns_.at(i).ptr()))) {
LOG_WARN("fail to append format", K(ret));
}
}
// print "c2 from db.t2 where "
if (OB_SUCC(ret)) {
if (OB_FAIL(sql_string.append_fmt(
share::is_oracle_mode() ? "\"%.*s\" FROM \"%.*s\".\"%.*s\" WHERE " : "`%.*s` FROM `%.*s`.`%.*s` WHERE ",
static_cast<int>(fk_arg.child_columns_.at(i).length()),
fk_arg.child_columns_.at(i).ptr(),
static_cast<int>(alter_table_schema.get_origin_database_name().length()),
alter_table_schema.get_origin_database_name().ptr(),
static_cast<int>(alter_table_schema.get_origin_table_name().length()),
alter_table_schema.get_origin_table_name().ptr()))) {
LOG_WARN("fail to append format", K(ret));
}
}
// print "c1 is not null and "
for (i = 0; OB_SUCC(ret) && i < fk_arg.child_columns_.count() - 1; ++i) {
if (OB_FAIL(
sql_string.append_fmt(share::is_oracle_mode() ? "\"%.*s\" IS NOT NULL AND " : "`%.*s` IS NOT NULL AND ",
static_cast<int>(fk_arg.child_columns_.at(i).length()),
fk_arg.child_columns_.at(i).ptr()))) {
LOG_WARN("fail to append format", K(ret));
}
}
// print "c2 is not null minus select "
if (OB_SUCC(ret)) {
if (OB_FAIL(sql_string.append_fmt(
share::is_oracle_mode() ? "\"%.*s\" IS NOT NULL MINUS SELECT " : "`%.*s` IS NOT NULL MINUS SELECT ",
static_cast<int>(fk_arg.child_columns_.at(i).length()),
fk_arg.child_columns_.at(i).ptr()))) {
LOG_WARN("fail to append format", K(ret));
}
}
// print "c3, "
for (i = 0; OB_SUCC(ret) && i < fk_arg.parent_columns_.count() - 1; ++i) {
if (OB_FAIL(sql_string.append_fmt(share::is_oracle_mode() ? "\"%.*s\", " : "`%.*s`, ",
static_cast<int>(fk_arg.parent_columns_.at(i).length()),
fk_arg.parent_columns_.at(i).ptr()))) {
LOG_WARN("fail to append format", K(ret));
}
}
// print "c4 from db.t1"
if (OB_SUCC(ret)) {
if (OB_FAIL(sql_string.append_fmt(
share::is_oracle_mode() ? "\"%.*s\" FROM \"%.*s\".\"%.*s\"" : "`%.*s` FROM `%.*s`.`%.*s`",
static_cast<int>(fk_arg.parent_columns_.at(i).length()),
fk_arg.parent_columns_.at(i).ptr(),
static_cast<int>(fk_arg.parent_database_.length()),
fk_arg.parent_database_.ptr(),
static_cast<int>(fk_arg.parent_table_.length()),
fk_arg.parent_table_.ptr()))) {
LOG_WARN("fail to append format", K(ret));
}
}
}
// check data valid
if (OB_FAIL(ret)) {
} else if (OB_FAIL(sql_proxy->read(res, alter_table_schema.get_tenant_id(), sql_string.ptr()))) {
LOG_WARN("execute sql failed", K(ret), K(sql_string.ptr()));
} else if (OB_ISNULL(result = res.get_result())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("execute sql failed", K(ret), K(alter_table_schema.get_tenant_id()), K(sql_string));
} else if (OB_FAIL(result->next())) {
if (OB_ITER_END == ret) {
ret = OB_SUCCESS;
is_data_valid = true;
} else {
LOG_WARN("iterate next result fail", K(ret), K(sql_string));
}
} else {
LOG_WARN("add fk failed, because the table has orphaned child records", K(ret), K(is_data_valid), K(sql_string));
}
}
return ret;
}
int ObAlterTableExecutor::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 ret = OB_SUCCESS;
is_data_valid = false;
int64_t snapshot = 0;
ObSchemaGetterGuard schema_guard;
const AlterTableSchema& alter_table_schema = alter_table_arg.alter_table_schema_;
const uint64_t tenant_id = alter_table_schema.get_tenant_id();
const observer::ObGlobalContext& gctx = observer::ObServer::get_instance().get_gctx();
const ObString& origin_database_name = alter_table_schema.get_origin_database_name();
const ObString& origin_table_name = alter_table_schema.get_origin_table_name();
const ObTableSchema* orig_table_schema = NULL;
if (OB_ISNULL(gctx.schema_service_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, schema service must not be NULL", K(ret));
} else if (OB_FAIL(gctx.schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) {
LOG_WARN("fail to get tenant schema guard", K(ret));
}
if (OB_SUCC(ret)) {
if (origin_database_name.empty() || origin_table_name.empty()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("database name or table name is null",
K(ret),
K(alter_table_schema),
K(origin_database_name),
K(origin_table_name));
} else {
if (OB_FAIL(schema_guard.get_table_schema(
tenant_id, origin_database_name, origin_table_name, false, orig_table_schema))) {
LOG_WARN("fail to get table schema", K(ret), K(tenant_id), K(origin_database_name), K(origin_table_name));
} else if (OB_ISNULL(orig_table_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("NULL ptr", K(ret), K(orig_table_schema));
} else {
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(get_constraint_check_snapshot(
ctx, schema_version, schema_guard, orig_table_schema->get_table_id(), snapshot))) {
LOG_WARN("fail to get snapshot", K(ret));
} else if (OB_FAIL(check_data_validity_for_fk_by_inner_sql(
alter_table_schema, alter_table_arg.foreign_key_arg_list_.at(0), sql_proxy, is_data_valid))) {
LOG_WARN("fail to check data validity by inner sql", K(ret));
}
}
return ret;
}
int ObAlterTableExecutor::check_alter_partition(
ObExecContext& ctx, ObAlterTableStmt& stmt, const obrpc::ObAlterTableArg& arg)
{
int ret = OB_SUCCESS;
if (arg.is_alter_partitions_) {
AlterTableSchema& table_schema = const_cast<AlterTableSchema&>(arg.alter_table_schema_);
if (obrpc::ObAlterTableArg::PARTITIONED_TABLE == arg.alter_part_type_ ||
obrpc::ObAlterTableArg::REORGANIZE_PARTITION == arg.alter_part_type_ ||
obrpc::ObAlterTableArg::SPLIT_PARTITION == arg.alter_part_type_) {
ObPartition** partition_array = table_schema.get_part_array();
int64_t realy_part_num = OB_INVALID_PARTITION_ID;
if (obrpc::ObAlterTableArg::SPLIT_PARTITION == arg.alter_part_type_) {
realy_part_num = table_schema.get_part_option().get_part_num();
} else {
realy_part_num = table_schema.get_partition_num();
}
if (table_schema.is_range_part()) {
if (OB_FAIL(ObPartitionExecutorUtils::set_range_part_high_bound(
ctx, stmt::T_CREATE_TABLE, table_schema, stmt, false /*is_subpart*/))) {
LOG_WARN("partition_array is NULL", K(ret));
}
} else if (table_schema.is_list_part()) {
if (OB_ISNULL(partition_array)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("NULL ptr", K(ret));
} else if (OB_FAIL(ObPartitionExecutorUtils::cast_list_expr_to_obj(ctx,
stmt::T_CREATE_TABLE,
false, // is_subpart
realy_part_num,
partition_array,
NULL,
stmt.get_part_fun_exprs(),
stmt.get_part_values_exprs()))) {
LOG_WARN("partition_array is NULL", K(ret));
}
} else if (obrpc::ObAlterTableArg::PARTITIONED_TABLE != arg.alter_part_type_) {
ret = OB_ERR_ONLY_ON_RANGE_LIST_PARTITION;
LOG_WARN("only support range or list part",
K(ret),
K(arg.alter_part_type_),
"partition type",
table_schema.get_part_option().get_part_func_type());
}
if (OB_FAIL(ret)) {
} else if (obrpc::ObAlterTableArg::SPLIT_PARTITION == arg.alter_part_type_) {
const_cast<AlterTableSchema&>(table_schema).get_part_option().set_part_num(table_schema.get_partition_num());
}
} else if (obrpc::ObAlterTableArg::ADD_PARTITION == arg.alter_part_type_) {
if (table_schema.is_range_part() || table_schema.is_list_part()) {
if (OB_FAIL(ObPartitionExecutorUtils::calc_values_exprs_for_alter_table(ctx, table_schema, stmt))) {
LOG_WARN("failed to calc values exprs for alter table", K(ret));
}
} else {
ret = OB_NOT_SUPPORTED;
LOG_USER_WARN(OB_NOT_SUPPORTED, "add hash partition");
}
} else if (obrpc::ObAlterTableArg::ADD_SUB_PARTITION == arg.alter_part_type_) {
if (table_schema.is_range_subpart()) {
if (OB_FAIL(ObPartitionExecutorUtils::set_individual_range_part_high_bound(
ctx, stmt::T_CREATE_TABLE, table_schema, stmt))) {
LOG_WARN("failed to set individual range part high bound", K(ret));
}
} else if (table_schema.is_list_subpart()) {
if (OB_FAIL(ObPartitionExecutorUtils::set_individual_list_part_rows(ctx,
stmt::T_CREATE_TABLE,
table_schema,
stmt.get_subpart_fun_exprs(),
stmt.get_individual_subpart_values_exprs()))) {
LOG_WARN("failed to set individual list part rows", K(ret));
}
} else {
ret = OB_NOT_SUPPORTED;
LOG_USER_WARN(OB_NOT_SUPPORTED, "add hash subpartition");
}
} else if (obrpc::ObAlterTableArg::DROP_PARTITION == arg.alter_part_type_ ||
obrpc::ObAlterTableArg::DROP_SUB_PARTITION == arg.alter_part_type_ ||
obrpc::ObAlterTableArg::TRUNCATE_PARTITION == arg.alter_part_type_ ||
obrpc::ObAlterTableArg::TRUNCATE_SUB_PARTITION == arg.alter_part_type_) {
// do-nothing
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("no operation", K(arg.alter_part_type_), K(ret));
}
LOG_DEBUG("dump table schema", K(table_schema));
}
return ret;
}
int ObAlterTableExecutor::set_index_arg_list(ObExecContext& ctx, ObAlterTableStmt& stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo* my_session = ctx.get_my_session();
obrpc::ObAlterTableArg& alter_table_arg = const_cast<obrpc::ObAlterTableArg&>(stmt.get_alter_table_arg());
if (OB_ISNULL(my_session)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("session is null", K(ret));
} else if (stmt.get_index_partition_resolve_results().count() != stmt.get_index_arg_list().count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid index resolve result", K(ret), K(stmt));
}
for (int64_t i = 0; OB_SUCC(ret) && i < stmt.get_index_arg_list().count(); i++) {
ObCreateIndexStmt index_stmt;
obrpc::ObCreateIndexArg& create_index_arg = *(stmt.get_index_arg_list().at(i));
ObPartitionResolveResult& resolve_result = stmt.get_index_partition_resolve_results().at(i);
index_stmt.get_part_fun_exprs() = resolve_result.get_part_fun_exprs();
index_stmt.get_part_values_exprs() = resolve_result.get_part_values_exprs();
index_stmt.get_subpart_fun_exprs() = resolve_result.get_subpart_fun_exprs();
index_stmt.get_template_subpart_values_exprs() = resolve_result.get_template_subpart_values_exprs();
index_stmt.get_individual_subpart_values_exprs() = resolve_result.get_individual_subpart_values_exprs();
if (OB_FAIL(index_stmt.get_create_index_arg().assign(create_index_arg))) {
LOG_WARN("fail to assign create index arg", K(ret));
} else if (OB_FAIL(ObPartitionExecutorUtils::calc_values_exprs(ctx, index_stmt))) {
LOG_WARN("fail to compare range partition expr", K(ret));
} else {
create_index_arg.is_inner_ = my_session->is_inner();
if (OB_FAIL(create_index_arg.assign(index_stmt.get_create_index_arg()))) {
LOG_WARN("fail to assign create index arg", K(ret));
} else if (OB_FAIL(alter_table_arg.index_arg_list_.push_back(&create_index_arg))) {
LOG_WARN("fail to push back index_arg", K(ret));
}
}
}
return ret;
}
/**
*
*/
ObDropTableExecutor::ObDropTableExecutor()
{}
ObDropTableExecutor::~ObDropTableExecutor()
{}
int ObDropTableExecutor::execute(ObExecContext& ctx, ObDropTableStmt& stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx* task_exec_ctx = NULL;
obrpc::ObCommonRpcProxy* common_rpc_proxy = NULL;
const obrpc::ObDropTableArg& drop_table_arg = stmt.get_drop_table_arg();
ObString first_stmt;
ObSQLSessionInfo* my_session = NULL;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("get first statement failed", K(ret));
} else {
const_cast<obrpc::ObDropTableArg&>(drop_table_arg).ddl_stmt_str_ = first_stmt;
my_session = ctx.get_my_session();
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_table_arg.session_id_ &&
FALSE_IT(const_cast<obrpc::ObDropTableArg&>(drop_table_arg).session_id_ =
my_session->get_sessid_for_table())) {
// impossible
} else if (OB_FAIL(common_rpc_proxy->drop_table(drop_table_arg))) {
LOG_WARN("rpc proxy drop table failed", K(ret), "dst", common_rpc_proxy->get_server());
}
}
return ret;
}
/**
*
*/
ObRenameTableExecutor::ObRenameTableExecutor()
{}
ObRenameTableExecutor::~ObRenameTableExecutor()
{}
int ObRenameTableExecutor::execute(ObExecContext& ctx, ObRenameTableStmt& stmt)
{
int ret = OB_SUCCESS;
const obrpc::ObRenameTableArg& rename_table_arg = stmt.get_rename_table_arg();
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_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->rename_table(rename_table_arg))) {
LOG_WARN("rpc proxy rename table failed", K(ret));
}
return ret;
}
/**
*
*/
ObTruncateTableExecutor::ObTruncateTableExecutor()
{}
ObTruncateTableExecutor::~ObTruncateTableExecutor()
{}
int ObTruncateTableExecutor::execute(ObExecContext& ctx, ObTruncateTableStmt& stmt)
{
int ret = OB_SUCCESS;
const obrpc::ObTruncateTableArg& truncate_table_arg = stmt.get_truncate_table_arg();
ObString first_stmt;
ObSQLSessionInfo* my_session = ctx.get_my_session();
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("get first statement failed", K(ret));
} else {
const_cast<obrpc::ObTruncateTableArg&>(truncate_table_arg).ddl_stmt_str_ = first_stmt;
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_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_ISNULL(my_session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get my session", K(ret), K(ctx));
} else if (OB_INVALID_ID == truncate_table_arg.session_id_ &&
FALSE_IT(const_cast<obrpc::ObTruncateTableArg&>(truncate_table_arg).session_id_ =
my_session->get_sessid_for_table())) {
// impossible
} else if (OB_FAIL(common_rpc_proxy->truncate_table(truncate_table_arg))) {
LOG_WARN("rpc proxy alter table failed", K(ret));
}
}
return ret;
}
ObCreateTableLikeExecutor::ObCreateTableLikeExecutor()
{}
ObCreateTableLikeExecutor::~ObCreateTableLikeExecutor()
{}
int ObCreateTableLikeExecutor::execute(ObExecContext& ctx, ObCreateTableLikeStmt& stmt)
{
int ret = OB_SUCCESS;
const obrpc::ObCreateTableLikeArg& create_table_like_arg = stmt.get_create_table_like_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("get first statement failed", K(ret));
} else {
const_cast<obrpc::ObCreateTableLikeArg&>(create_table_like_arg).ddl_stmt_str_ = first_stmt;
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_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_table_like(create_table_like_arg))) {
LOG_WARN("rpc proxy create table like failed", K(ret));
}
}
return ret;
}
int ObPurgeTableExecutor::execute(ObExecContext& ctx, ObPurgeTableStmt& stmt)
{
int ret = OB_SUCCESS;
const obrpc::ObPurgeTableArg& purge_table_arg = stmt.get_purge_table_arg();
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("get first statement failed", K(ret));
} else {
const_cast<obrpc::ObPurgeTableArg&>(purge_table_arg).ddl_stmt_str_ = first_stmt;
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_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_table(purge_table_arg))) {
LOG_WARN("rpc proxy purge table failed", K(ret));
}
}
return ret;
}
int ObOptimizeTableExecutor::execute(ObExecContext& ctx, ObOptimizeTableStmt& stmt)
{
int ret = OB_SUCCESS;
obrpc::ObOptimizeTableArg& arg = stmt.get_optimize_table_arg();
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;
ObTaskExecutorCtx* task_exec_ctx = nullptr;
obrpc::ObCommonRpcProxy* common_rpc_proxy = nullptr;
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, task executor must not be NULL", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("fail to get common rpc", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, common rpc proxy must not be NULL", K(ret));
} else if (OB_FAIL(common_rpc_proxy->optimize_table(arg))) {
LOG_WARN("fail to optimize table", K(ret));
}
}
return ret;
}
int ObOptimizeTenantExecutor::execute(ObExecContext& ctx, ObOptimizeTenantStmt& stmt)
{
int ret = OB_SUCCESS;
obrpc::ObOptimizeTenantArg& arg = stmt.get_optimize_tenant_arg();
ObString first_stmt;
ObSQLSessionInfo* my_session = ctx.get_my_session();
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", K(ret));
} else if (OB_ISNULL(my_session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, my session must not be NULL", K(ret));
} else {
arg.ddl_stmt_str_ = first_stmt;
ObTaskExecutorCtx* task_exec_ctx = nullptr;
obrpc::ObCommonRpcProxy* common_rpc_proxy = nullptr;
const observer::ObGlobalContext& gctx = observer::ObServer::get_instance().get_gctx();
const int64_t effective_tenant_id = my_session->get_effective_tenant_id();
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, task executor must not be NULL", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("fail to get common rpc", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, common rpc proxy must not be NULL", K(ret));
} else if (OB_ISNULL(gctx.schema_service_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, schema service must not be NULL", K(ret));
} else if (OB_FAIL(optimize_tenant(arg, effective_tenant_id, *gctx.schema_service_, common_rpc_proxy))) {
LOG_WARN("fail to optimize tenant", K(ret));
}
}
return ret;
}
int ObOptimizeTenantExecutor::optimize_tenant(const obrpc::ObOptimizeTenantArg& arg, const uint64_t effective_tenant_id,
ObMultiVersionSchemaService& schema_service, obrpc::ObCommonRpcProxy* common_rpc_proxy)
{
int ret = OB_SUCCESS;
uint64_t tenant_id = OB_INVALID_ID;
ObSchemaGetterGuard schema_guard;
LOG_INFO("receive optimize tenant request", K(arg));
if (!arg.is_valid() || NULL == common_rpc_proxy) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(arg), KP(common_rpc_proxy));
} else if (OB_FAIL(schema_service.get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) {
LOG_WARN("fail to get schema guard", K(ret));
} else if (OB_FAIL(schema_guard.get_tenant_id(arg.tenant_name_, tenant_id))) {
LOG_WARN("fail to get tenant id", K(ret));
} else if (OB_SYS_TENANT_ID != effective_tenant_id && tenant_id != effective_tenant_id) {
ret = OB_OP_NOT_ALLOW;
LOG_WARN("tenant id mismatch", K(tenant_id), K(effective_tenant_id));
} else {
ObArray<const ObTableSchema*> table_schemas;
if (OB_FAIL(schema_service.get_tenant_schema_guard(tenant_id, schema_guard))) {
LOG_WARN("fail to get tenant schema guard", K(ret));
} else if (OB_FAIL(schema_guard.get_table_schemas_in_tenant(tenant_id, table_schemas))) {
LOG_WARN("fail to get table schemas in tenant", K(ret));
} else {
LOG_INFO("optimize tenant, table schema count", K(table_schemas.count()));
for (int64_t i = 0; OB_SUCC(ret) && i < table_schemas.count(); ++i) {
const ObTableSchema* table_schema = table_schemas.at(i);
const ObDatabaseSchema* database_schema = nullptr;
obrpc::ObOptimizeTableArg optimize_table_arg;
if (OB_ISNULL(table_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, table schema must not be NULL", K(ret));
} else if (table_schema->is_index_table() || table_schema->is_vir_table() || table_schema->is_view_table()) {
// do nothing
} else if (OB_FAIL(schema_guard.get_database_schema(table_schema->get_database_id(), database_schema))) {
LOG_WARN("fail to get database schema", K(ret));
} else {
obrpc::ObTableItem table_item;
optimize_table_arg.tenant_id_ = tenant_id;
optimize_table_arg.exec_tenant_id_ = tenant_id;
table_item.database_name_ = database_schema->get_database_name();
table_item.table_name_ = table_schema->get_table_name();
if (OB_FAIL(optimize_table_arg.tables_.push_back(table_item))) {
LOG_WARN("fail to push back optimize table arg", K(ret));
} else if (OB_FAIL(common_rpc_proxy->optimize_table(optimize_table_arg))) {
LOG_WARN("fail to optimize table", K(ret));
}
}
}
}
}
return ret;
}
int ObOptimizeAllExecutor::execute(ObExecContext& ctx, ObOptimizeAllStmt& stmt)
{
int ret = OB_SUCCESS;
obrpc::ObOptimizeAllArg& arg = stmt.get_optimize_all_arg();
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;
ObTaskExecutorCtx* task_exec_ctx = nullptr;
obrpc::ObCommonRpcProxy* common_rpc_proxy = nullptr;
ObSchemaGetterGuard schema_guard;
ObArray<uint64_t> tenant_ids;
const observer::ObGlobalContext& gctx = observer::ObServer::get_instance().get_gctx();
ObSQLSessionInfo* my_session = ctx.get_my_session();
if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, task executor must not be NULL", K(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("fail to get common rpc", K(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, common rpc proxy must not be NULL", K(ret));
} else if (OB_ISNULL(my_session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, my session must not be NULL", K(ret));
} else if (OB_ISNULL(gctx.schema_service_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("error unexpected, schema service must not be NULL", K(ret));
} else if (OB_FAIL(gctx.schema_service_->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) {
obrpc::ObOptimizeTenantArg tenant_arg;
const ObTenantSchema* tenant_schema = nullptr;
if (OB_FAIL(schema_guard.get_tenant_info(tenant_ids.at(i), tenant_schema))) {
LOG_WARN("fail to get tenant name", K(ret));
} else {
tenant_arg.tenant_name_ = tenant_schema->get_tenant_name();
if (OB_FAIL(ObOptimizeTenantExecutor::optimize_tenant(
tenant_arg, my_session->get_effective_tenant_id(), *gctx.schema_service_, common_rpc_proxy))) {
LOG_WARN("fail to optimize tenant", K(ret));
}
}
}
}
}
return ret;
}
} // end namespace sql
} // end namespace oceanbase