2258 lines
100 KiB
C++
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
|