Co-authored-by: AnimationFan <30674773338@qq.com> Co-authored-by: simonjoylet <simonjoylet@gmail.com> Co-authored-by: Monk-Liu <1152761042@qq.com>
688 lines
30 KiB
C++
688 lines
30 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 RS
|
|
#include "rootserver/ob_mlog_builder.h"
|
|
#include "rootserver/ob_ddl_service.h"
|
|
#include "rootserver/ob_root_service.h"
|
|
#include "storage/ddl/ob_ddl_lock.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace obrpc;
|
|
using namespace share;
|
|
using namespace share::schema;
|
|
using namespace transaction::tablelock;
|
|
|
|
namespace rootserver
|
|
{
|
|
int ObMLogBuilder::MLogColumnUtils::check_column_type(
|
|
const ObColumnSchemaV2 &column_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (column_schema.get_meta_type().is_lob()) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED,
|
|
"create materialized view log on lob columns is");
|
|
LOG_WARN("create materialized view log on lob columns is not supported",
|
|
KR(ret), K(column_schema.get_column_name_str()));
|
|
} else if (column_schema.is_generated_column()) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED,
|
|
"create materialized view log on generated columns is");
|
|
LOG_WARN("create materialized view log on generated columns is not supported",
|
|
KR(ret), K(column_schema.get_column_name_str()));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::MLogColumnUtils::add_special_columns(
|
|
ObTableSchema &mlog_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(add_pk_column(mlog_schema))) {
|
|
LOG_WARN("failed to add sequence column", KR(ret));
|
|
} else if (OB_FAIL(add_dmltype_column())) {
|
|
LOG_WARN("failed to add dmltype column", KR(ret));
|
|
} else if (OB_FAIL(add_old_new_column())) {
|
|
LOG_WARN("failed to add old new column", KR(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// sequence column is mlog's rowkey
|
|
int ObMLogBuilder::MLogColumnUtils::add_pk_column(
|
|
ObTableSchema &mlog_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObColumnSchemaV2 rowkey_column;
|
|
rowkey_column.set_autoincrement(false);
|
|
rowkey_column.set_is_hidden(false);
|
|
rowkey_column.set_nullable(false);
|
|
rowkey_column.set_rowkey_position(1);
|
|
rowkey_column.set_order_in_rowkey(ObOrderType::ASC);
|
|
rowkey_column.set_column_id(OB_MLOG_SEQ_NO_COLUMN_ID);
|
|
rowkey_column.set_data_type(ObIntType);
|
|
rowkey_column.set_charset_type(CHARSET_BINARY);
|
|
rowkey_column.set_collation_type(CS_TYPE_BINARY);
|
|
mlog_schema.set_rowkey_column_num(1);
|
|
if (OB_FAIL(rowkey_column.set_column_name(OB_MLOG_SEQ_NO_COLUMN_NAME))) {
|
|
LOG_WARN("failed to set column name", KR(ret));
|
|
} else if (OB_FAIL(mlog_schema.add_column(rowkey_column))) {
|
|
LOG_WARN("failed to add rowkey column to mlog schema", KR(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::MLogColumnUtils::add_dmltype_column()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObColumnSchemaV2 column;
|
|
column.set_autoincrement(false);
|
|
column.set_is_hidden(false);
|
|
column.set_rowkey_position(0);
|
|
column.set_index_position(0);
|
|
column.set_collation_type(ObCollationType::CS_TYPE_UTF8MB4_GENERAL_CI);
|
|
column.set_data_type(ColumnType::ObVarcharType);
|
|
column.set_data_length(1);
|
|
column.set_column_id(OB_MLOG_DML_TYPE_COLUMN_ID);
|
|
if (OB_FAIL(column.set_column_name(OB_MLOG_DML_TYPE_COLUMN_NAME))) {
|
|
LOG_WARN("failed to set column name", KR(ret));
|
|
} else if (OB_FAIL(mlog_table_column_array_.push_back(column))) {
|
|
LOG_WARN("failed to push back column to mlog table column array", KR(ret), K(column));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::MLogColumnUtils::add_old_new_column()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObColumnSchemaV2 column;
|
|
column.set_autoincrement(false);
|
|
column.set_is_hidden(false);
|
|
column.set_rowkey_position(0);
|
|
column.set_index_position(0);
|
|
column.set_collation_type(ObCollationType::CS_TYPE_UTF8MB4_GENERAL_CI);
|
|
column.set_data_type(ColumnType::ObVarcharType);
|
|
column.set_data_length(1);
|
|
column.set_column_id(OB_MLOG_OLD_NEW_COLUMN_ID);
|
|
if (OB_FAIL(column.set_column_name(OB_MLOG_OLD_NEW_COLUMN_NAME))) {
|
|
LOG_WARN("failed to set column name", KR(ret));
|
|
} else if (OB_FAIL(mlog_table_column_array_.push_back(column))) {
|
|
LOG_WARN("failed to push back column to mlog table column array", KR(ret), K(column));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::MLogColumnUtils::add_base_table_pk_columns(
|
|
ObRowDesc &row_desc,
|
|
const ObTableSchema &base_table_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObArray<ObColDesc> column_ids;
|
|
if (OB_FAIL(base_table_schema.get_rowkey_column_ids(column_ids))) {
|
|
LOG_WARN("failed to get rowkey column ids", KR(ret));
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && (i < column_ids.count()); ++i) {
|
|
ObColumnSchemaV2 ref_column;
|
|
const ObColumnSchemaV2 *rowkey_column = base_table_schema.get_column_schema(
|
|
column_ids.at(i).col_id_);
|
|
if (OB_ISNULL(rowkey_column)) {
|
|
ret = OB_ERR_COLUMN_NOT_FOUND;
|
|
LOG_WARN("column not exist", KR(ret));
|
|
} else if (OB_FAIL(row_desc.add_column_desc(rowkey_column->get_table_id(),
|
|
rowkey_column->get_column_id()))) {
|
|
LOG_WARN("failed to add column desc to row desc", KR(ret),
|
|
K(rowkey_column->get_table_id()), K(rowkey_column->get_column_id()));
|
|
} else if (OB_FAIL(ref_column.assign(*rowkey_column))) {
|
|
LOG_WARN("failed to assign rowkey_column to ref_column",
|
|
KR(ret), KPC(rowkey_column));
|
|
} else {
|
|
ref_column.set_autoincrement(false);
|
|
ref_column.set_is_hidden(false);
|
|
ref_column.set_rowkey_position(0);
|
|
ref_column.set_index_position(0);
|
|
ref_column.set_prev_column_id(UINT64_MAX);
|
|
ref_column.set_next_column_id(UINT64_MAX);
|
|
ref_column.set_column_id(ObTableSchema::gen_mlog_col_id_from_ref_col_id(
|
|
rowkey_column->get_column_id()));
|
|
if (base_table_schema.is_heap_table()
|
|
&& OB_FAIL(ref_column.set_column_name(OB_MLOG_ROWID_COLUMN_NAME))) {
|
|
LOG_WARN("failed to set column name", KR(ret));
|
|
} else if (OB_FAIL(mlog_table_column_array_.push_back(ref_column))) {
|
|
LOG_WARN("failed to push back column to mlog table column array",
|
|
KR(ret), K(ref_column));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::MLogColumnUtils::add_base_table_columns(
|
|
const ObCreateMLogArg &create_mlog_arg,
|
|
ObRowDesc &row_desc,
|
|
const ObTableSchema &base_table_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
for (int64_t i = 0; OB_SUCC(ret) && (i < create_mlog_arg.store_columns_.count()); ++i) {
|
|
ObColumnSchemaV2 ref_column;
|
|
const ObString &column_name = create_mlog_arg.store_columns_.at(i);
|
|
const ObColumnSchemaV2 *data_column = nullptr;
|
|
if (OB_ISNULL(data_column = base_table_schema.get_column_schema(column_name))) {
|
|
ret = OB_ERR_COLUMN_NOT_FOUND;
|
|
LOG_WARN("failed to get column schema", KR(ret), K(column_name));
|
|
} else if (OB_FAIL(check_column_type(*data_column))) {
|
|
LOG_WARN("failed to check column type", KR(ret), KPC(data_column));
|
|
} else if (OB_INVALID_INDEX != row_desc.get_idx(
|
|
data_column->get_table_id(),
|
|
data_column->get_column_id())) {
|
|
ret = OB_ERR_COLUMN_DUPLICATE;
|
|
LOG_USER_ERROR(OB_ERR_COLUMN_DUPLICATE, column_name.length(), column_name.ptr());
|
|
} else if (OB_FAIL(row_desc.add_column_desc(data_column->get_table_id(),
|
|
data_column->get_column_id()))) {
|
|
LOG_WARN("failed to add column desc to row desc", KR(ret),
|
|
K(data_column->get_table_id()), K(data_column->get_column_id()));
|
|
} else if (OB_FAIL(ref_column.assign(*data_column))) {
|
|
LOG_WARN("failed to assign rowkey_column to ref_column",
|
|
KR(ret), KPC(data_column));
|
|
} else {
|
|
ref_column.set_autoincrement(false);
|
|
ref_column.set_is_hidden(false);
|
|
ref_column.set_rowkey_position(0);
|
|
ref_column.set_index_position(0);
|
|
ref_column.set_prev_column_id(UINT64_MAX);
|
|
ref_column.set_next_column_id(UINT64_MAX);
|
|
ref_column.set_column_id(ObTableSchema::gen_mlog_col_id_from_ref_col_id(
|
|
data_column->get_column_id()));
|
|
if (OB_FAIL(mlog_table_column_array_.push_back(ref_column))) {
|
|
LOG_WARN("failed to push back column to mlog table column array",
|
|
KR(ret), K(ref_column));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::MLogColumnUtils::add_base_table_part_key_columns(
|
|
const ObPartitionKeyInfo &part_key_info,
|
|
ObRowDesc &row_desc,
|
|
const ObTableSchema &base_table_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
for (int64_t i = 0; OB_SUCC(ret) && (i < part_key_info.get_size()); ++i) {
|
|
ObColumnSchemaV2 ref_column;
|
|
const ObRowkeyColumn *rowkey_column = part_key_info.get_column(i);
|
|
if (OB_ISNULL(rowkey_column)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("rowkey column is null", KR(ret));
|
|
} else {
|
|
const uint64_t column_id = rowkey_column->column_id_;
|
|
const ObColumnSchemaV2 *part_key_column = nullptr;
|
|
if (OB_ISNULL(part_key_column = base_table_schema.get_column_schema(column_id))) {
|
|
ret = OB_ERR_COLUMN_NOT_FOUND;
|
|
LOG_WARN("failed to get column schema", KR(ret), K(column_id));
|
|
} else if (OB_FAIL(check_column_type(*part_key_column))) {
|
|
LOG_WARN("failed to check column type", KR(ret), KPC(part_key_column));
|
|
} else if (OB_INVALID_INDEX != row_desc.get_idx(
|
|
part_key_column->get_table_id(), part_key_column->get_column_id())) {
|
|
// bypass
|
|
} else if (OB_FAIL(row_desc.add_column_desc(
|
|
part_key_column->get_table_id(), part_key_column->get_column_id()))) {
|
|
LOG_WARN("failed to add column desc to row desc", KR(ret),
|
|
K(part_key_column->get_table_id()), K(part_key_column->get_column_id()));
|
|
} else if (OB_FAIL(ref_column.assign(*part_key_column))) {
|
|
LOG_WARN("failed to assign rowkey_column to ref_column",
|
|
KR(ret), KPC(part_key_column));
|
|
} else {
|
|
ref_column.set_autoincrement(false);
|
|
ref_column.set_is_hidden(false);
|
|
ref_column.set_rowkey_position(0);
|
|
ref_column.set_index_position(0);
|
|
ref_column.set_prev_column_id(UINT64_MAX);
|
|
ref_column.set_next_column_id(UINT64_MAX);
|
|
ref_column.set_column_id(ObTableSchema::gen_mlog_col_id_from_ref_col_id(
|
|
part_key_column->get_column_id()));
|
|
if (OB_FAIL(mlog_table_column_array_.push_back(ref_column))) {
|
|
LOG_WARN("failed to push back column to mlog table column array",
|
|
KR(ret), K(ref_column));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::MLogColumnUtils::add_base_table_part_key_columns(
|
|
ObRowDesc &row_desc,
|
|
const ObTableSchema &base_table_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObPartitionKeyInfo &part_key_info = base_table_schema.get_partition_key_info();
|
|
const ObPartitionKeyInfo &sub_part_key_info = base_table_schema.get_subpartition_key_info();
|
|
if (OB_FAIL(add_base_table_part_key_columns(
|
|
part_key_info, row_desc, base_table_schema))) {
|
|
LOG_WARN("failed to add base table part key columns", KR(ret));
|
|
} else if (OB_FAIL(add_base_table_part_key_columns(
|
|
sub_part_key_info, row_desc, base_table_schema))) {
|
|
LOG_WARN("failed to add base table sub part key columns", KR(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::MLogColumnUtils::construct_mlog_table_columns(
|
|
ObTableSchema &mlog_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t rowkey_pos = 1; // the first rowkey is seq_no
|
|
// sort mlog_table_column_array first
|
|
struct ColumnSchemaCmp {
|
|
inline bool operator()(const ObColumnSchemaV2 &a, const ObColumnSchemaV2 &b) {
|
|
return (a.get_column_id() < b.get_column_id());
|
|
}
|
|
};
|
|
std::sort(mlog_table_column_array_.begin(), mlog_table_column_array_.end(), ColumnSchemaCmp());
|
|
|
|
for (int64_t i = 0; OB_SUCC(ret) && (i < mlog_table_column_array_.count()); ++i) {
|
|
ObColumnSchemaV2 &column = mlog_table_column_array_.at(i);
|
|
if ( column.is_part_key_column() || column.is_subpart_key_column()) {
|
|
column.set_rowkey_position(++rowkey_pos);
|
|
}
|
|
if (OB_FAIL(mlog_schema.add_column(column))) {
|
|
LOG_WARN("failed to add column to mlog schema", KR(ret), K(column));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ObMLogBuilder::ObMLogBuilder(ObDDLService &ddl_service)
|
|
: ddl_service_(ddl_service),
|
|
mlog_column_utils_(),
|
|
is_inited_(false)
|
|
{
|
|
|
|
}
|
|
|
|
ObMLogBuilder::~ObMLogBuilder()
|
|
{
|
|
|
|
}
|
|
|
|
int ObMLogBuilder::init()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_INIT) {
|
|
ret = OB_INIT_TWICE;
|
|
LOG_WARN("ObMLogBuilder init twice", KR(ret));
|
|
} else if (!ddl_service_.is_inited()) {
|
|
ret = OB_INNER_STAT_ERROR;
|
|
LOG_WARN("ddl service not init", KR(ret));
|
|
} else {
|
|
is_inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::create_mlog(
|
|
ObSchemaGetterGuard &schema_guard,
|
|
const ObCreateMLogArg &create_mlog_arg,
|
|
ObCreateMLogRes &create_mlog_res)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
uint64_t tenant_id = create_mlog_arg.tenant_id_;
|
|
uint64_t compat_version = 0;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("ObMLogBuilder not init", KR(ret));
|
|
} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) {
|
|
LOG_WARN("failed to get data version", KR(ret), K(tenant_id));
|
|
} else if (compat_version < DATA_VERSION_4_3_0_0) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_WARN("materialized view log before version 4.3 is not supported", KR(ret), K(compat_version));
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "materialized view log before version 4.3 is");
|
|
} else if (!create_mlog_arg.is_valid()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", KR(ret), K(create_mlog_arg));
|
|
} else {
|
|
uint64_t base_table_id = OB_INVALID_ID;
|
|
bool in_tenant_space = true;
|
|
const ObTableSchema *base_table_schema = nullptr;
|
|
schema_guard.set_session_id(create_mlog_arg.session_id_);
|
|
if (OB_FAIL(schema_guard.get_table_schema(tenant_id,
|
|
create_mlog_arg.database_name_,
|
|
create_mlog_arg.table_name_,
|
|
false /* is_index */,
|
|
base_table_schema))) {
|
|
LOG_WARN("failed to get table schema", KR(ret), K(create_mlog_arg));
|
|
} else if (OB_ISNULL(base_table_schema)) {
|
|
ret = OB_TABLE_NOT_EXIST;
|
|
LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(create_mlog_arg.database_name_),
|
|
to_cstring(create_mlog_arg.table_name_));
|
|
LOG_WARN("table not exist", KR(ret), K(create_mlog_arg));
|
|
} else if(!base_table_schema->is_user_table()) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_WARN("create materialized view log on a non-user table is not supported",
|
|
KR(ret), K(base_table_schema->get_table_type()));
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "create materialized view log on a non-user table is");
|
|
} else if (base_table_schema->has_mlog_table()) {
|
|
ret = OB_ERR_MLOG_EXIST;
|
|
LOG_WARN("a materialized view log already exists on table",
|
|
K(create_mlog_arg.table_name_), K(base_table_schema->get_mlog_tid()));
|
|
LOG_USER_ERROR(OB_ERR_MLOG_EXIST, to_cstring(create_mlog_arg.table_name_));
|
|
} else if (FALSE_IT(base_table_id = base_table_schema->get_table_id())) {
|
|
} else if (OB_FAIL(ObSysTableChecker::is_tenant_space_table_id(base_table_id, in_tenant_space))) {
|
|
LOG_WARN("failed to check table in tenant space", KR(ret), K(base_table_id));
|
|
} else if (is_inner_table(base_table_id)) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_WARN("create mlog on inner table is not supported", KR(ret), K(base_table_id));
|
|
} else if (base_table_schema->is_in_splitting()) {
|
|
ret = OB_OP_NOT_ALLOW;
|
|
LOG_WARN("can not create mlog during splitting", KR(ret), K(create_mlog_arg));
|
|
} else if (OB_FAIL(ddl_service_.check_restore_point_allow(
|
|
tenant_id, *base_table_schema))) {
|
|
LOG_WARN("failed to check restore point allow", KR(ret), K(tenant_id), K(base_table_id));
|
|
} else if (OB_FAIL(ddl_service_.check_fk_related_table_ddl(
|
|
*base_table_schema, ObDDLType::DDL_CREATE_INDEX))) {
|
|
LOG_WARN("check whether the foreign key related table is executing ddl failed", KR(ret));
|
|
} else if (OB_FAIL(do_create_mlog(schema_guard,
|
|
create_mlog_arg,
|
|
*base_table_schema,
|
|
compat_version,
|
|
create_mlog_res))) {
|
|
LOG_WARN("failed to do create mlog", KR(ret), K(create_mlog_arg));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::do_create_mlog(
|
|
ObSchemaGetterGuard &schema_guard,
|
|
const ObCreateMLogArg &create_mlog_arg,
|
|
const ObTableSchema &base_table_schema,
|
|
const uint64_t tenant_data_version,
|
|
ObCreateMLogRes &create_mlog_res)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
HEAP_VARS_3((ObTableSchema, mlog_schema),
|
|
(ObTableSchema, src_table_schema),
|
|
(obrpc::ObCreateIndexArg, create_index_arg)) {
|
|
ObDDLTaskRecord task_record;
|
|
ObArenaAllocator allocator("DdlTaskTmp");
|
|
ObDDLSQLTransaction trans(&ddl_service_.get_schema_service());
|
|
int64_t refreshed_schema_version = 0;
|
|
const uint64_t tenant_id = base_table_schema.get_tenant_id();
|
|
if (OB_FAIL(schema_guard.get_schema_version(tenant_id, refreshed_schema_version))) {
|
|
LOG_WARN("failed to get tenant schema version", KR(ret), K(tenant_id));
|
|
} else if (OB_FAIL(trans.start(&ddl_service_.get_sql_proxy(),
|
|
tenant_id,
|
|
refreshed_schema_version))) {
|
|
LOG_WARN("failed to start trans", KR(ret), K(tenant_id), K(refreshed_schema_version));
|
|
} else if (OB_FAIL(src_table_schema.assign(base_table_schema))) {
|
|
LOG_WARN("failed to assign table schema", KR(ret));
|
|
} else if (!src_table_schema.is_valid()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("failed to copy table schema", KR(ret));
|
|
} else if (OB_FAIL(generate_mlog_schema(schema_guard, create_mlog_arg, src_table_schema, mlog_schema))) {
|
|
LOG_WARN("failed to generate schema", KR(ret), K(create_mlog_arg), K(src_table_schema));
|
|
} else if (OB_FAIL(ddl_service_.create_mlog_table(trans, create_mlog_arg, tenant_data_version, schema_guard, mlog_schema))) {
|
|
LOG_WARN("failed to create mlog table", KR(ret), K(create_mlog_arg), K(mlog_schema));
|
|
} else {
|
|
// submit build mlog task
|
|
// creating mlog reuses create_index ddl task
|
|
create_index_arg.tenant_id_ = create_mlog_arg.tenant_id_;
|
|
create_index_arg.data_table_id_ = create_mlog_arg.base_table_id_;
|
|
create_index_arg.index_table_id_ = OB_INVALID_ID;
|
|
create_index_arg.session_id_ = create_mlog_arg.session_id_;
|
|
create_index_arg.index_action_type_ = ObIndexArg::ADD_MLOG;
|
|
ObCreateDDLTaskParam param(mlog_schema.get_tenant_id(),
|
|
ObDDLType::DDL_CREATE_MLOG,
|
|
&src_table_schema,
|
|
&mlog_schema,
|
|
0 /*object_id*/,
|
|
mlog_schema.get_schema_version(),
|
|
create_mlog_arg.parallelism_,
|
|
create_mlog_arg.consumer_group_id_,
|
|
&allocator,
|
|
&create_index_arg);
|
|
param.tenant_data_version_ = tenant_data_version;
|
|
if (OB_FAIL(GCTX.root_service_->get_ddl_task_scheduler().create_ddl_task(param, trans, task_record))) {
|
|
LOG_WARN("failed to submit create mlog task", KR(ret));
|
|
} else if (OB_FAIL(ObDDLLock::lock_for_add_drop_index(
|
|
src_table_schema,
|
|
nullptr/*inc_data_tablet_ids*/,
|
|
nullptr/*del_data_tablet_ids*/,
|
|
mlog_schema,
|
|
ObTableLockOwnerID(task_record.task_id_), trans))) {
|
|
LOG_WARN("failed to lock online ddl lock", KR(ret));
|
|
} else {
|
|
create_mlog_res.mlog_table_id_ = mlog_schema.get_table_id();
|
|
create_mlog_res.schema_version_ = mlog_schema.get_schema_version();
|
|
create_mlog_res.task_id_ = task_record.task_id_;
|
|
}
|
|
}
|
|
|
|
if (trans.is_started()) {
|
|
int tmp_ret = OB_SUCCESS;
|
|
if (OB_TMP_FAIL(trans.end(OB_SUCC(ret)))) {
|
|
LOG_WARN("failed to end trans", "is_commit", OB_SUCCESS == ret, KR(tmp_ret));
|
|
ret = (OB_SUCC(ret)) ? tmp_ret : ret;
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(ddl_service_.publish_schema(tenant_id))) {
|
|
LOG_WARN("failed to publish schema", KR(ret));
|
|
} else if (OB_FAIL(GCTX.root_service_->get_ddl_task_scheduler().schedule_ddl_task(task_record))) {
|
|
LOG_WARN("failed to schedule ddl task", KR(ret), K(task_record));
|
|
}
|
|
}
|
|
} // end HEAP_VAR()
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::generate_mlog_schema(
|
|
ObSchemaGetterGuard &schema_guard,
|
|
const ObCreateMLogArg &create_mlog_arg,
|
|
const ObTableSchema &base_table_schema,
|
|
ObTableSchema &mlog_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("ObMLogBuilder not init", KR(ret));
|
|
} else if (OB_UNLIKELY(!base_table_schema.is_valid())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid data schema", KR(ret), K(base_table_schema));
|
|
} else {
|
|
if (OB_FAIL(set_basic_infos(schema_guard, create_mlog_arg, base_table_schema, mlog_schema))) {
|
|
LOG_WARN("failed to set basic infos", KR(ret));
|
|
} else if (OB_FAIL(set_table_columns(create_mlog_arg, base_table_schema, mlog_schema))) {
|
|
LOG_WARN("failed to set table columns", KR(ret));
|
|
} else if (OB_FAIL(set_table_options(create_mlog_arg, base_table_schema, mlog_schema))) {
|
|
LOG_WARN("failed to set table options", KR(ret));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if ((base_table_schema.get_part_level() > 0)
|
|
&& OB_FAIL(mlog_schema.assign_partition_schema(base_table_schema))) {
|
|
LOG_WARN("failed to assign partition schema", KR(ret), K(mlog_schema));
|
|
} else if (OB_FAIL(ddl_service_.try_format_partition_schema(mlog_schema))) {
|
|
LOG_WARN("failed to format partitionn schema", KR(ret));
|
|
} else if (OB_FAIL(ddl_service_.generate_object_id_for_partition_schema(mlog_schema))) {
|
|
LOG_WARN("failed to generate object id for patition schema", KR(ret), K(mlog_schema));
|
|
} else if (OB_FAIL(ddl_service_.generate_tablet_id(mlog_schema))) {
|
|
LOG_WARN("failed to generate new tablet id", KR(ret), K(mlog_schema));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::set_basic_infos(
|
|
ObSchemaGetterGuard &schema_guard,
|
|
const ObCreateMLogArg &create_mlog_arg,
|
|
const ObTableSchema &base_table_schema,
|
|
ObTableSchema &mlog_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObDatabaseSchema *database = NULL;
|
|
const uint64_t tenant_id = base_table_schema.get_tenant_id();
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("ObMLogBuilder not init", KR(ret));
|
|
} else if (OB_FAIL(schema_guard.get_database_schema(
|
|
tenant_id, base_table_schema.get_database_id(), database))) {
|
|
LOG_WARN("failed to get database_schema", K(ret), K(tenant_id),
|
|
"database_id", base_table_schema.get_database_id());
|
|
} else if (OB_ISNULL(database)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("database_schema is null", K(ret), "database_id", base_table_schema.get_database_id());
|
|
} else if (OB_UNLIKELY(!base_table_schema.is_valid())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid data schema", KR(ret), K(base_table_schema));
|
|
} else {
|
|
ObString mlog_table_name;
|
|
ObArenaAllocator allocator(ObModIds::OB_SCHEMA);
|
|
bool is_oracle_mode = false;
|
|
if (OB_FAIL(base_table_schema.check_if_oracle_compat_mode(is_oracle_mode))) {
|
|
LOG_WARN("failed to check if oracle compat mode", KR(ret));
|
|
} else if (OB_FAIL(ObTableSchema::build_mlog_table_name(allocator,
|
|
create_mlog_arg.table_name_, mlog_table_name, is_oracle_mode))) {
|
|
LOG_WARN("failed to build mlog table name", KR(ret), K(create_mlog_arg.table_name_));
|
|
} else if (OB_FAIL(mlog_schema.set_table_name(mlog_table_name))) {
|
|
LOG_WARN("failed to set table name", KR(ret), K(mlog_table_name));
|
|
} else {
|
|
mlog_schema.set_table_mode(base_table_schema.get_table_mode_flag());
|
|
mlog_schema.set_table_type(MATERIALIZED_VIEW_LOG);
|
|
mlog_schema.set_index_status(ObIndexStatus::INDEX_STATUS_UNAVAILABLE);
|
|
mlog_schema.set_duplicate_scope(base_table_schema.get_duplicate_scope());
|
|
mlog_schema.set_table_state_flag(base_table_schema.get_table_state_flag());
|
|
mlog_schema.set_table_id(create_mlog_arg.mlog_table_id_);
|
|
mlog_schema.set_data_table_id(base_table_schema.get_table_id());
|
|
mlog_schema.set_tenant_id(base_table_schema.get_tenant_id());
|
|
mlog_schema.set_database_id(base_table_schema.get_database_id());
|
|
mlog_schema.set_tablegroup_id(OB_INVALID_ID);
|
|
mlog_schema.set_def_type(base_table_schema.get_def_type());
|
|
mlog_schema.set_part_level(base_table_schema.get_part_level());
|
|
mlog_schema.set_charset_type(base_table_schema.get_charset_type());
|
|
mlog_schema.set_collation_type(base_table_schema.get_collation_type());
|
|
mlog_schema.set_row_store_type(base_table_schema.get_row_store_type());
|
|
mlog_schema.set_store_format(base_table_schema.get_store_format());
|
|
mlog_schema.set_storage_format_version(base_table_schema.get_storage_format_version());
|
|
mlog_schema.set_tablet_size(base_table_schema.get_tablet_size());
|
|
mlog_schema.set_autoinc_column_id(0);
|
|
mlog_schema.set_progressive_merge_num(base_table_schema.get_progressive_merge_num());
|
|
mlog_schema.set_progressive_merge_round(base_table_schema.get_progressive_merge_round());
|
|
if (OB_FAIL(mlog_schema.set_compress_func_name(base_table_schema.get_compress_func_name()))) {
|
|
LOG_WARN("failed to set compress func name", KR(ret));
|
|
} else if (OB_INVALID_ID != mlog_schema.get_tablespace_id()) {
|
|
const ObTablespaceSchema *tablespace_schema = nullptr;
|
|
if (OB_FAIL(schema_guard.get_tablespace_schema(
|
|
mlog_schema.get_tenant_id(), mlog_schema.get_tablespace_id(), tablespace_schema))) {
|
|
LOG_WARN("failed to get tablespace schema", KR(ret));
|
|
} else if (OB_UNLIKELY(OB_ISNULL(tablespace_schema))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("tablespace schema is null", KR(ret));
|
|
} else if (OB_FAIL(mlog_schema.set_encrypt_key(tablespace_schema->get_encrypt_key()))) {
|
|
LOG_WARN("failed to set encrypt key", KR(ret));
|
|
} else {
|
|
mlog_schema.set_master_key_id(tablespace_schema->get_master_key_id());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::set_table_columns(
|
|
const ObCreateMLogArg &create_mlog_arg,
|
|
const ObTableSchema &base_table_schema,
|
|
ObTableSchema &mlog_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("ObMLogBuilder not init", KR(ret));
|
|
} else {
|
|
HEAP_VAR(ObRowDesc, row_desc) {
|
|
if (OB_FAIL(mlog_column_utils_.add_special_columns(mlog_schema))) {
|
|
LOG_WARN("failed to add special columns", KR(ret));
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (base_table_schema.is_heap_table()) {
|
|
if (create_mlog_arg.with_primary_key_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("create mlog on heap table cannot use with primary key option",
|
|
KR(ret), K(base_table_schema.is_heap_table()), K(create_mlog_arg.with_primary_key_));
|
|
} else if (!create_mlog_arg.with_rowid_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("create mlog on heap table should use with rowid option",
|
|
KR(ret), K(base_table_schema.is_heap_table()), K(create_mlog_arg.with_rowid_));
|
|
}
|
|
} else {
|
|
if (create_mlog_arg.with_rowid_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("create mlog on non-heap table cannot use with rowid option",
|
|
KR(ret), K(base_table_schema.is_heap_table()), K(create_mlog_arg.with_rowid_));
|
|
} else if (!create_mlog_arg.with_primary_key_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("create mlog on non-heap table should use with primary key option",
|
|
KR(ret), K(base_table_schema.is_heap_table()), K(create_mlog_arg.with_primary_key_));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(mlog_column_utils_.add_base_table_pk_columns(
|
|
row_desc, base_table_schema))) {
|
|
LOG_WARN("failed to add base table pk columns", KR(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(mlog_column_utils_.add_base_table_columns(
|
|
create_mlog_arg, row_desc, base_table_schema))) {
|
|
LOG_WARN("failed to add base table columns", KR(ret));
|
|
} else if (OB_FAIL(mlog_column_utils_.add_base_table_part_key_columns(
|
|
row_desc, base_table_schema))) {
|
|
LOG_WARN("failed to add base table part key columns", KR(ret));
|
|
} else if (OB_FAIL(mlog_column_utils_.construct_mlog_table_columns(mlog_schema))) {
|
|
LOG_WARN("failed to construct mlog table columns", KR(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObMLogBuilder::set_table_options(
|
|
const ObCreateMLogArg &create_mlog_arg,
|
|
const ObTableSchema &base_table_schema,
|
|
ObTableSchema &mlog_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("ObMLogBuilder not init", KR(ret));
|
|
} else {
|
|
mlog_schema.set_block_size(create_mlog_arg.mlog_schema_.get_block_size());
|
|
mlog_schema.set_pctfree(create_mlog_arg.mlog_schema_.get_pctfree());
|
|
mlog_schema.set_dop(create_mlog_arg.mlog_schema_.get_dop());
|
|
mlog_schema.set_tablespace_id(create_mlog_arg.mlog_schema_.get_tablespace_id());
|
|
mlog_schema.set_comment(create_mlog_arg.mlog_schema_.get_comment());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
} // namespace rootserver
|
|
} // namespace oceanbase
|