oceanbase
1117 строк · 56.7 Кб
1/**
2* Copyright (c) 2021 OceanBase
3* OceanBase CE is licensed under Mulan PubL v2.
4* You can use this software according to the terms and conditions of the Mulan PubL v2.
5* You may obtain a copy of Mulan PubL v2 at:
6* http://license.coscl.org.cn/MulanPubL-2.0
7* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10* See the Mulan PubL v2 for more details.
11*/
12
13#define USING_LOG_PREFIX RS14#include "ob_index_builder.h"15
16#include "share/ob_define.h"17#include "lib/allocator/page_arena.h"18#include "lib/mysqlclient/ob_mysql_result.h"19#include "lib/container/ob_array_iterator.h"20#include "share/ob_srv_rpc_proxy.h"21#include "lib/mysqlclient/ob_mysql_proxy.h"22#include "share/ob_ddl_common.h"23#include "share/ob_debug_sync.h"24#include "share/ob_common_rpc_proxy.h"25#include "share/schema/ob_table_schema.h"26#include "share/schema/ob_multi_version_schema_service.h"27#include "share/schema/ob_schema_struct.h"28#include "share/schema/ob_part_mgr_util.h"29#include "share/ob_common_rpc_proxy.h"30#include "share/config/ob_server_config.h"31#include "share/ob_index_builder_util.h"32#include "observer/ob_server_struct.h"33#include "sql/resolver/ddl/ob_ddl_resolver.h"34#include "ob_zone_manager.h"35#include "ob_ddl_service.h"36#include "ob_root_service.h"37#include "ob_snapshot_info_manager.h"38#include "share/ob_thread_mgr.h"39#include "sql/resolver/ob_resolver_utils.h"40#include "storage/ddl/ob_ddl_lock.h"41#include "storage/tx/ob_ts_mgr.h"42#include "storage/tx/ob_i_ts_source.h"43#include "storage/tx/ob_ts_mgr.h"44#include "storage/tx/ob_i_ts_source.h"45#include <map>46#include "rootserver/ddl_task/ob_ddl_scheduler.h"47#include "rootserver/ddl_task/ob_ddl_task.h"48#include "share/scn.h"49
50namespace oceanbase51{
52using namespace common;53using namespace common::sqlclient;54using namespace obrpc;55using namespace share;56using namespace share::schema;57using namespace sql;58using namespace palf;59namespace rootserver60{
61
62ObIndexBuilder::ObIndexBuilder(ObDDLService &ddl_service)63: ddl_service_(ddl_service)64{
65}
66
67ObIndexBuilder::~ObIndexBuilder()68{
69}
70
71int ObIndexBuilder::create_index(72const ObCreateIndexArg &arg,73obrpc::ObAlterTableRes &res)74{
75int ret = OB_SUCCESS;76LOG_INFO("start create index", K(arg));77if (!ddl_service_.is_inited()) {78ret = OB_INNER_STAT_ERROR;79LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));80} else if (!arg.is_valid()) {81ret = OB_INVALID_ARGUMENT;82LOG_WARN("invalid arg", K(arg), K(ret));83} else if (OB_FAIL(do_create_index(arg, res))) {84LOG_WARN("generate_schema failed", K(arg), K(ret));85}86if (OB_ERR_TABLE_EXIST == ret) {87if (true == arg.if_not_exist_) {88ret = OB_SUCCESS;89LOG_USER_WARN(OB_ERR_KEY_NAME_DUPLICATE, arg.index_name_.length(), arg.index_name_.ptr());90} else {91ret = OB_ERR_KEY_NAME_DUPLICATE;92LOG_USER_ERROR(OB_ERR_KEY_NAME_DUPLICATE, arg.index_name_.length(), arg.index_name_.ptr());93}94}95LOG_INFO("finish create index", K(arg), K(ret));96return ret;97}
98
99int ObIndexBuilder::drop_index(const ObDropIndexArg &arg, obrpc::ObDropIndexRes &res)100{
101int ret = OB_SUCCESS;102const uint64_t tenant_id = arg.tenant_id_;103const bool is_index = false;104ObArenaAllocator allocator(ObModIds::OB_SCHEMA);105const ObTableSchema *table_schema = NULL;106ObSchemaGetterGuard schema_guard;107bool is_db_in_recyclebin = false;108bool need_rename_index = true;109ObTableType drop_table_type = USER_INDEX;110uint64_t compat_version = 0;111const bool is_mlog = (obrpc::ObIndexArg::DROP_MLOG == arg.index_action_type_);112if (is_mlog) {113need_rename_index = false;114drop_table_type = MATERIALIZED_VIEW_LOG;115}116if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) {117LOG_WARN("failed to get data version", KR(ret), K(tenant_id));118} else if (is_mlog && (compat_version < DATA_VERSION_4_3_0_0)) {119ret = OB_NOT_SUPPORTED;120LOG_WARN("materialized view log before version 4.3 is not supported", KR(ret), K(compat_version));121LOG_USER_ERROR(OB_NOT_SUPPORTED, "materialized view log before version 4.3 is");122} else if (OB_FALSE_IT(schema_guard.set_session_id(arg.session_id_))) {123} else if (!ddl_service_.is_inited()) {124ret = OB_INNER_STAT_ERROR;125LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));126} else if (!arg.is_valid()) {127ret = OB_INVALID_ARGUMENT;128LOG_WARN("invalid arg", K(arg), K(ret));129} else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) {130LOG_WARN("get_schema_guard failed", K(ret));131} else if (OB_FAIL(schema_guard.get_table_schema(132tenant_id, arg.database_name_, arg.table_name_,133is_index, table_schema, arg.is_hidden_))) {134LOG_WARN("failed to get data table schema", K(arg), K(ret));135} else if (NULL == table_schema) {136ret = OB_TABLE_NOT_EXIST;137LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(arg.database_name_), to_cstring(arg.table_name_));138LOG_WARN("table not found", K(arg), K(ret));139} else if (arg.is_in_recyclebin_) {140// internal delete index141} else if (table_schema->is_in_recyclebin()) {142ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;143LOG_WARN("can not drop index of table in recyclebin.", K(ret), K(arg));144} else if (OB_FAIL(schema_guard.check_database_in_recyclebin(tenant_id,145table_schema->get_database_id(), is_db_in_recyclebin))) {146LOG_WARN("check database in recyclebin failed", K(ret), K(tenant_id));147} else if (is_db_in_recyclebin) {148ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;149LOG_WARN("Can not drop index of db in recyclebin", K(ret), K(arg));150} else if (OB_FAIL(ddl_service_.check_fk_related_table_ddl(*table_schema, ObDDLType::DDL_DROP_INDEX))) {151LOG_WARN("check whether foreign key related table executes ddl failed", K(ret));152}153if (OB_SUCC(ret)) {154const uint64_t data_table_id = table_schema->get_table_id();155const ObTableSchema *index_table_schema = NULL;156if (OB_INVALID_ID != arg.index_table_id_) {157LOG_DEBUG("drop index with index_table_id", K(arg.index_table_id_));158if (OB_FAIL(schema_guard.get_table_schema(tenant_id, arg.index_table_id_, index_table_schema))) {159LOG_WARN("fail to get index table schema", K(ret), K(tenant_id), K(arg.index_table_id_));160}161} else {162ObString index_table_name;163if (is_mlog) {164index_table_name = arg.index_name_;165} else if (OB_FAIL(ObTableSchema::build_index_table_name(166allocator, data_table_id, arg.index_name_, index_table_name))) {167LOG_WARN("build_index_table_name failed", K(arg), K(data_table_id), K(ret));168}169if (OB_SUCC(ret)) {170if (OB_FAIL(schema_guard.get_table_schema(tenant_id,171table_schema->get_database_id(),172index_table_name,173!is_mlog,/*is_index*/174index_table_schema))) {175LOG_WARN("fail to get table schema", K(ret), K(tenant_id), K(index_table_name), K(index_table_schema));176}177}178}179bool have_index = false;180const common::ObIArray<ObForeignKeyInfo> &foreign_key_infos = table_schema->get_foreign_key_infos();181if (OB_FAIL(ret)) {182} else if (OB_ISNULL(index_table_schema)) {183if (is_mlog) {184ret = OB_ERR_TABLE_NO_MLOG;185LOG_WARN("table does not have a materialized view log", KR(ret),186K(arg.database_name_), K(arg.index_name_));187LOG_USER_ERROR(OB_ERR_TABLE_NO_MLOG, to_cstring(arg.database_name_), to_cstring(arg.index_name_));188} else {189ret = OB_ERR_CANT_DROP_FIELD_OR_KEY;190LOG_WARN("index table schema should not be null", K(arg.index_name_), K(ret));191LOG_USER_ERROR(OB_ERR_CANT_DROP_FIELD_OR_KEY, arg.index_name_.length(), arg.index_name_.ptr());192}193} else if (OB_FAIL(ddl_service_.check_index_on_foreign_key(index_table_schema,194foreign_key_infos,195have_index))) {196LOG_WARN("fail to check index on foreign key", K(ret), K(foreign_key_infos), KPC(index_table_schema));197} else if (have_index) {198ret = OB_ERR_ATLER_TABLE_ILLEGAL_FK;199LOG_WARN("cannot delete index with foreign key dependency", K(ret));200} else if (!arg.is_inner_ && index_table_schema->is_unavailable_index()) {201ret = OB_NOT_SUPPORTED;202LOG_WARN("not support to drop a building index", K(ret), K(arg.is_inner_), KPC(index_table_schema));203LOG_USER_ERROR(OB_NOT_SUPPORTED, "dropping a building index is");204} else if (arg.is_add_to_scheduler_) {205ObDDLOperator ddl_operator(ddl_service_.get_schema_service(), ddl_service_.get_sql_proxy());206ObDDLSQLTransaction trans(&ddl_service_.get_schema_service());207int64_t refreshed_schema_version = 0;208ObArenaAllocator allocator(lib::ObLabel("DdlTaskTmp"));209ObDDLTaskRecord task_record;210bool has_index_task = false;211SMART_VAR(ObTableSchema, new_index_schema) {212if (OB_FAIL(schema_guard.get_schema_version(tenant_id, refreshed_schema_version))) {213LOG_WARN("failed to get tenant schema version", KR(ret), K(tenant_id));214} else if (OB_FAIL(trans.start(&ddl_service_.get_sql_proxy(), tenant_id, refreshed_schema_version))) {215LOG_WARN("start transaction failed", KR(ret), K(tenant_id), K(refreshed_schema_version));216} else if (!arg.is_inner_ && !index_table_schema->can_read_index() && OB_FAIL(ObDDLTaskRecordOperator::check_has_index_task(217trans, tenant_id, data_table_id, index_table_schema->get_table_id(), has_index_task))) {218LOG_WARN("failed to check ddl conflict", K(ret));219} else if (has_index_task) {220ret = OB_NOT_SUPPORTED;221LOG_WARN("not support to drop a building or dropping index", K(ret), K(arg.is_inner_), KPC(index_table_schema));222LOG_USER_ERROR(OB_NOT_SUPPORTED, "dropping a building or dropping index is");223} else if (need_rename_index && OB_FAIL(ddl_service_.rename_dropping_index_name(224table_schema->get_table_id(),225table_schema->get_database_id(),226arg,227schema_guard,228ddl_operator,229trans,230new_index_schema))) {231LOG_WARN("renmae index name failed", K(ret));232} else if (!need_rename_index && OB_FAIL(new_index_schema.assign(*index_table_schema))) {233LOG_WARN("failed to assign index table schema to new index schema", KR(ret));234} else if (OB_FAIL(submit_drop_index_task(trans, *table_schema, new_index_schema, new_index_schema.get_schema_version(), arg, allocator, task_record))) {235LOG_WARN("submit drop index task failed", K(ret));236} else {237res.tenant_id_ = new_index_schema.get_tenant_id();238res.index_table_id_ = new_index_schema.get_table_id();239res.schema_version_ = new_index_schema.get_schema_version();240res.task_id_ = task_record.task_id_;241}242}243if (trans.is_started()) {244int temp_ret = OB_SUCCESS;245if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) {246LOG_WARN_RET(temp_ret, "trans end failed", "is_commit", OB_SUCCESS == ret, K(temp_ret));247ret = (OB_SUCC(ret)) ? temp_ret : ret;248}249}250if (OB_SUCC(ret)) {251int tmp_ret = OB_SUCCESS;252if (OB_FAIL(ddl_service_.publish_schema(tenant_id))) {253LOG_WARN("fail to publish schema", K(ret), K(tenant_id));254} else if (OB_TMP_FAIL(GCTX.root_service_->get_ddl_task_scheduler().schedule_ddl_task(task_record))) {255LOG_WARN("fail to schedule ddl task", K(tmp_ret), K(task_record));256}257}258} else {259//construct an arg for drop table260ObTableItem table_item;261table_item.database_name_ = arg.database_name_;262table_item.table_name_ = index_table_schema->get_table_name();263table_item.is_hidden_ = index_table_schema->is_user_hidden_table();264obrpc::ObDDLRes ddl_res;265obrpc::ObDropTableArg drop_table_arg;266drop_table_arg.tenant_id_ = tenant_id;267drop_table_arg.if_exist_ = false;268drop_table_arg.table_type_ = drop_table_type;269drop_table_arg.ddl_stmt_str_ = arg.ddl_stmt_str_;270drop_table_arg.force_drop_ = arg.is_in_recyclebin_;271drop_table_arg.task_id_ = arg.task_id_;272if (OB_FAIL(drop_table_arg.tables_.push_back(table_item))) {273LOG_WARN("failed to add table item!", K(table_item), K(ret));274} else if (OB_FAIL(ddl_service_.drop_table(drop_table_arg, ddl_res))) {275if (OB_TABLE_NOT_EXIST == ret) {276ret = OB_ERR_CANT_DROP_FIELD_OR_KEY;277LOG_USER_ERROR(OB_ERR_CANT_DROP_FIELD_OR_KEY, arg.index_name_.length(), arg.index_name_.ptr());278LOG_WARN("index not exist, can't drop it", K(arg), K(ret));279} else {280LOG_WARN("drop_table failed", K(arg), K(drop_table_arg), K(ret));281}282}283}284}285
286LOG_INFO("finish drop index", K(arg), K(ret));287return ret;288}
289
290int ObIndexBuilder::do_create_global_index(291share::schema::ObSchemaGetterGuard &schema_guard,292const obrpc::ObCreateIndexArg &arg,293const share::schema::ObTableSchema &table_schema,294obrpc::ObAlterTableRes &res)295{
296int ret = OB_SUCCESS;297uint64_t tenant_data_version = 0;298ObArray<ObColumnSchemaV2 *> gen_columns;299const bool global_index_without_column_info = false;300ObDDLTaskRecord task_record;301ObArenaAllocator allocator(lib::ObLabel("DdlTaskTmp"));302HEAP_VARS_2((ObTableSchema, new_table_schema),303(obrpc::ObCreateIndexArg, new_arg)) {304ObTableSchema &index_schema = new_arg.index_schema_;305ObDDLSQLTransaction trans(&ddl_service_.get_schema_service());306int64_t refreshed_schema_version = 0;307const uint64_t tenant_id = table_schema.get_tenant_id();308if (OB_FAIL(schema_guard.get_schema_version(tenant_id, refreshed_schema_version))) {309LOG_WARN("failed to get tenant schema version", KR(ret), K(tenant_id));310} else if (OB_FAIL(trans.start(&ddl_service_.get_sql_proxy(), tenant_id, refreshed_schema_version))) {311LOG_WARN("start transaction failed", KR(ret), K(tenant_id), K(refreshed_schema_version));312} else if (OB_FAIL(new_table_schema.assign(table_schema))) {313LOG_WARN("fail to assign schema", K(ret));314} else if (!new_table_schema.is_valid()) {315ret = OB_ERR_UNEXPECTED;316LOG_WARN("fail to copy table schema", K(ret));317} else if (OB_FAIL(new_arg.assign(arg))) {318LOG_WARN("fail to assign arg", K(ret));319} else if (!new_arg.is_valid()) {320ret = OB_ERR_UNEXPECTED;321LOG_WARN("fail to copy create index arg", K(ret));322} else if (OB_FAIL(ObIndexBuilderUtil::adjust_expr_index_args(323new_arg, new_table_schema, allocator, gen_columns))) {324LOG_WARN("fail to adjust expr index args", K(ret));325} else if (OB_FAIL(generate_schema(326new_arg, new_table_schema, global_index_without_column_info,327true/*generate_id*/, index_schema))) {328LOG_WARN("fail to generate schema", K(ret), K(new_arg));329} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) {330LOG_WARN("get min data version failed", K(ret), K(tenant_id));331} else {332if (gen_columns.empty()) {333if (OB_FAIL(ddl_service_.create_global_index(334trans, new_arg, new_table_schema, tenant_data_version, index_schema))) {335LOG_WARN("fail to create global index", K(ret));336}337} else {338if (OB_FAIL(ddl_service_.create_global_inner_expr_index(339trans, table_schema, tenant_data_version, new_table_schema, gen_columns, index_schema))) {340LOG_WARN("fail to create global inner expr index", K(ret));341}342}343if (OB_FAIL(ret)) {344} else if (OB_FAIL(submit_build_index_task(trans,345new_arg,346&new_table_schema,347nullptr/*inc_data_tablet_ids*/,348nullptr/*del_data_tablet_ids*/,349&index_schema,350arg.parallelism_,351arg.consumer_group_id_,352tenant_data_version,353allocator,354task_record))) {355LOG_WARN("fail to submit build global index task", K(ret));356}357}358if (OB_SUCC(ret)) {359res.index_table_id_ = index_schema.get_table_id();360res.schema_version_ = index_schema.get_schema_version();361res.task_id_ = task_record.task_id_;362}363if (trans.is_started()) {364int temp_ret = OB_SUCCESS;365if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) {366LOG_WARN("trans end failed", "is_commit", OB_SUCCESS == ret, K(temp_ret));367ret = (OB_SUCC(ret)) ? temp_ret : ret;368}369}370if (OB_SUCC(ret)) {371int tmp_ret = OB_SUCCESS;372if (OB_FAIL(ddl_service_.publish_schema(tenant_id))) {373LOG_WARN("fail to publish schema", K(ret), K(tenant_id));374} else if (OB_TMP_FAIL(GCTX.root_service_->get_ddl_task_scheduler().schedule_ddl_task(task_record))) {375LOG_WARN("fail to schedule ddl task", K(tmp_ret), K(task_record));376}377}378}379return ret;380}
381
382int ObIndexBuilder::submit_build_index_task(383ObMySQLTransaction &trans,384const obrpc::ObCreateIndexArg &create_index_arg,385const ObTableSchema *data_schema,386const ObIArray<ObTabletID> *inc_data_tablet_ids,387const ObIArray<ObTabletID> *del_data_tablet_ids,388const ObTableSchema *index_schema,389const int64_t parallelism,390const int64_t group_id,391const uint64_t tenant_data_version,392common::ObIAllocator &allocator,393ObDDLTaskRecord &task_record)394{
395int ret = OB_SUCCESS;396ObCreateDDLTaskParam param(index_schema->get_tenant_id(),397ObDDLType::DDL_CREATE_INDEX,398data_schema,399index_schema,4000/*object_id*/,401index_schema->get_schema_version(),402parallelism,403group_id,404&allocator,405&create_index_arg);406param.tenant_data_version_ = tenant_data_version;407if (OB_UNLIKELY(nullptr == data_schema || nullptr == index_schema || tenant_data_version <= 0)) {408ret = OB_INVALID_ARGUMENT;409LOG_WARN("schema is invalid", K(ret), KP(data_schema), KP(index_schema), K(tenant_data_version));410} else if (OB_FAIL(GCTX.root_service_->get_ddl_task_scheduler().create_ddl_task(param, trans, task_record))) {411LOG_WARN("submit create index ddl task failed", K(ret));412} else if (OB_FAIL(ObDDLLock::lock_for_add_drop_index(413*data_schema, inc_data_tablet_ids, del_data_tablet_ids, *index_schema, ObTableLockOwnerID(task_record.task_id_), trans))) {414LOG_WARN("failed to lock online ddl lock", K(ret));415}416return ret;417}
418
419int ObIndexBuilder::submit_drop_index_task(ObMySQLTransaction &trans,420const ObTableSchema &data_schema,421const ObTableSchema &index_schema,422const int64_t schema_version,423const obrpc::ObDropIndexArg &arg,424common::ObIAllocator &allocator,425ObDDLTaskRecord &task_record)426{
427int ret = OB_SUCCESS;428if (OB_UNLIKELY(!index_schema.is_valid())) {429ret = OB_INVALID_ARGUMENT;430LOG_WARN("invalid arguments", K(ret));431} else {432int64_t refreshed_schema_version = 0;433const uint64_t tenant_id = index_schema.get_tenant_id();434const ObDDLType ddl_type = (ObIndexArg::DROP_MLOG == arg.index_action_type_) ?435ObDDLType::DDL_DROP_MLOG : ObDDLType::DDL_DROP_INDEX;436ObCreateDDLTaskParam param(tenant_id,437ddl_type,438&index_schema,439nullptr,4400/*object_id*/,441schema_version,4420/*parallelism*/,443arg.consumer_group_id_,444&allocator,445&arg);446if (OB_FAIL(GCTX.root_service_->get_ddl_task_scheduler().create_ddl_task(param, trans, task_record))) {447LOG_WARN("submit create index ddl task failed", K(ret));448} else if (OB_FAIL(ObDDLLock::lock_for_add_drop_index(449data_schema, nullptr/*inc_data_tablet_ids*/, nullptr/*del_data_tablet_ids*/, index_schema, ObTableLockOwnerID(task_record.task_id_), trans))) {450LOG_WARN("failed to lock online ddl lock", K(ret));451}452}453return ret;454}
455
456int ObIndexBuilder::do_create_local_index(457share::schema::ObSchemaGetterGuard &schema_guard,458const obrpc::ObCreateIndexArg &create_index_arg,459const share::schema::ObTableSchema &table_schema,460obrpc::ObAlterTableRes &res)461{
462int ret = OB_SUCCESS;463ObSEArray<ObColumnSchemaV2 *, 1> gen_columns;464ObDDLTaskRecord task_record;465ObArenaAllocator allocator(lib::ObLabel("DdlTaskTmp"));466HEAP_VARS_3((ObTableSchema, index_schema),467(ObTableSchema, new_table_schema),468(obrpc::ObCreateIndexArg, my_arg)) {469ObDDLSQLTransaction trans(&ddl_service_.get_schema_service());470int64_t refreshed_schema_version = 0;471const uint64_t tenant_id = table_schema.get_tenant_id();472uint64_t tenant_data_version = 0;473if (OB_FAIL(schema_guard.get_schema_version(tenant_id, refreshed_schema_version))) {474LOG_WARN("failed to get tenant schema version", KR(ret), K(tenant_id));475} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) {476LOG_WARN("get tenant data version failed", K(ret));477} else if (OB_FAIL(trans.start(&ddl_service_.get_sql_proxy(), tenant_id, refreshed_schema_version))) {478LOG_WARN("start transaction failed", KR(ret), K(tenant_id), K(refreshed_schema_version));479} else if (OB_FAIL(new_table_schema.assign(table_schema))) {480LOG_WARN("fail to assign schema", K(ret));481} else if (!new_table_schema.is_valid()) {482ret = OB_ERR_UNEXPECTED;483LOG_WARN("fail to copy table schema", K(ret));484} else if (OB_FAIL(my_arg.assign(create_index_arg))) {485LOG_WARN("fail to assign arg", K(ret));486} else if (!my_arg.is_valid()) {487ret = OB_ERR_UNEXPECTED;488LOG_WARN("fail to copy create index arg", K(ret));489} else {490const bool global_index_without_column_info = true;491// build a global index with local storage if both the data table and index table are non-partitioned492if (INDEX_TYPE_NORMAL_GLOBAL == my_arg.index_type_) {493my_arg.index_type_ = INDEX_TYPE_NORMAL_GLOBAL_LOCAL_STORAGE;494my_arg.index_schema_.set_index_type(INDEX_TYPE_NORMAL_GLOBAL_LOCAL_STORAGE);495} else if (INDEX_TYPE_UNIQUE_GLOBAL == my_arg.index_type_) {496my_arg.index_type_ = INDEX_TYPE_UNIQUE_GLOBAL_LOCAL_STORAGE;497my_arg.index_schema_.set_index_type(INDEX_TYPE_UNIQUE_GLOBAL_LOCAL_STORAGE);498} else if (INDEX_TYPE_SPATIAL_GLOBAL == my_arg.index_type_) {499if (tenant_data_version < DATA_VERSION_4_1_0_0) {500ret = OB_NOT_SUPPORTED;501LOG_WARN("tenant data version is less than 4.1, spatial index is not supported", K(ret), K(tenant_data_version));502LOG_USER_ERROR(OB_NOT_SUPPORTED, "tenant data version is less than 4.1, spatial index");503} else {504my_arg.index_type_ = INDEX_TYPE_SPATIAL_GLOBAL_LOCAL_STORAGE;505my_arg.index_schema_.set_index_type(INDEX_TYPE_SPATIAL_GLOBAL_LOCAL_STORAGE);506}507}508if (OB_FAIL(ObIndexBuilderUtil::adjust_expr_index_args(509my_arg, new_table_schema, allocator, gen_columns))) {510LOG_WARN("fail to adjust expr index args", K(ret));511} else if (OB_FAIL(generate_schema(512my_arg, new_table_schema, global_index_without_column_info,513true/*generate_id*/, index_schema))) {514LOG_WARN("fail to generate schema", K(ret), K(my_arg));515} else if (OB_FAIL(new_table_schema.check_create_index_on_hidden_primary_key(index_schema))) {516LOG_WARN("failed to check create index on table", K(ret), K(index_schema));517} else if (gen_columns.empty()) {518if (OB_FAIL(ddl_service_.create_index_table(my_arg, tenant_data_version, index_schema, trans))) {519LOG_WARN("fail to create index", K(ret), K(index_schema));520}521} else {522if (OB_FAIL(ddl_service_.create_inner_expr_index(trans,523table_schema,524tenant_data_version,525new_table_schema,526gen_columns,527index_schema))) {528LOG_WARN("fail to create inner expr index", K(ret));529}530}531if (OB_FAIL(ret)) {532} else if (OB_FAIL(submit_build_index_task(trans,533create_index_arg,534&new_table_schema,535nullptr/*inc_data_tablet_ids*/,536nullptr/*del_data_tablet_ids*/,537&index_schema,538create_index_arg.parallelism_,539create_index_arg.consumer_group_id_,540tenant_data_version,541allocator,542task_record))) {543LOG_WARN("failt to submit build local index task", K(ret));544} else {545res.index_table_id_ = index_schema.get_table_id();546res.schema_version_ = index_schema.get_schema_version();547res.task_id_ = task_record.task_id_;548}549}550if (trans.is_started()) {551int temp_ret = OB_SUCCESS;552if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) {553LOG_WARN("trans end failed", "is_commit", OB_SUCCESS == ret, K(temp_ret));554ret = (OB_SUCC(ret)) ? temp_ret : ret;555}556}557if (OB_SUCC(ret)) {558if (OB_FAIL(ddl_service_.publish_schema(tenant_id))) {559LOG_WARN("fail to publish schema", K(ret), K(tenant_id));560} else if (OB_FAIL(GCTX.root_service_->get_ddl_task_scheduler().schedule_ddl_task(task_record))) {561LOG_WARN("fail to schedule ddl task", K(ret), K(task_record));562}563}564}565return ret;566}
567
568// not generate table_id for index, caller will do that
569// if we pass the data_schema argument, the create_index_arg can not set database_name
570// and table_name, which will used for getting data table schema in generate_schema
571int ObIndexBuilder::do_create_index(572const ObCreateIndexArg &arg,573obrpc::ObAlterTableRes &res)574{
575int ret = OB_SUCCESS;576ObSchemaGetterGuard schema_guard;577const bool is_index = false;578const ObTableSchema *table_schema = NULL;579uint64_t table_id = OB_INVALID_ID;580bool in_tenant_space = true;581schema_guard.set_session_id(arg.session_id_);582const uint64_t tenant_id = arg.tenant_id_;583if (!ddl_service_.is_inited()) {584ret = OB_INNER_STAT_ERROR;585LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));586} else if (!arg.is_valid()) {587ret = OB_INVALID_ARGUMENT;588LOG_WARN("invalid argument", K(arg), K(ret));589} else if (OB_FAIL(ddl_service_.get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) {590LOG_WARN("get_schema_guard failed", K(ret));591} else if (OB_FAIL(schema_guard.get_table_schema(592tenant_id, arg.database_name_, arg.table_name_, is_index, table_schema))) {593LOG_WARN("get_table_schema failed", K(arg), K(ret));594} else if (NULL == table_schema) {595ret = OB_TABLE_NOT_EXIST;596LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(arg.database_name_), to_cstring(arg.table_name_));597LOG_WARN("table not exist", K(arg), K(ret));598} else if (FALSE_IT(table_id = table_schema->get_table_id())) {599} else if (OB_FAIL(ObSysTableChecker::is_tenant_space_table_id(table_id, in_tenant_space))) {600LOG_WARN("fail to check table in tenant space", K(ret), K(table_id));601} else if (is_inner_table(table_id)) {602// FIXME: create index for inner table is not supported yet.603ret = OB_NOT_SUPPORTED;604LOG_WARN("create index on inner table not supported", K(ret), K(table_id));605} else if (!arg.is_inner_ && table_schema->is_in_recyclebin()) {606ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;607LOG_WARN("can not add index on table in recyclebin", K(ret), K(arg));608} else if (table_schema->is_in_splitting()) {609ret = OB_OP_NOT_ALLOW;610LOG_WARN("can not create index during splitting", K(ret), K(arg));611} else if (OB_FAIL(ddl_service_.check_restore_point_allow(tenant_id, *table_schema))) {612LOG_WARN("failed to check restore point allow.", K(ret), K(tenant_id), K(table_id));613} else if (table_schema->get_index_tid_count() >= OB_MAX_INDEX_PER_TABLE) {614ret = OB_ERR_TOO_MANY_KEYS;615LOG_USER_ERROR(OB_ERR_TOO_MANY_KEYS, OB_MAX_INDEX_PER_TABLE);616int64_t index_count = table_schema->get_index_tid_count();617LOG_WARN("too many index for table", K(OB_MAX_INDEX_PER_TABLE), K(index_count), K(ret));618} else if (OB_FAIL(ddl_service_.check_fk_related_table_ddl(*table_schema, ObDDLType::DDL_CREATE_INDEX))) {619LOG_WARN("check whether the foreign key related table is executing ddl failed", K(ret));620} else if (INDEX_TYPE_NORMAL_LOCAL == arg.index_type_621|| INDEX_TYPE_UNIQUE_LOCAL == arg.index_type_622|| INDEX_TYPE_DOMAIN_CTXCAT == arg.index_type_623|| INDEX_TYPE_SPATIAL_LOCAL == arg.index_type_) {624if (OB_FAIL(do_create_local_index(schema_guard, arg, *table_schema, res))) {625LOG_WARN("fail to do create local index", K(ret), K(arg));626}627} else if (INDEX_TYPE_NORMAL_GLOBAL == arg.index_type_628|| INDEX_TYPE_UNIQUE_GLOBAL == arg.index_type_629|| INDEX_TYPE_SPATIAL_GLOBAL == arg.index_type_) {630if (!table_schema->is_partitioned_table() && !arg.index_schema_.is_partitioned_table()) {631// create a global index with local storage when both the data table and index table are non-partitioned632if (OB_FAIL(do_create_local_index(schema_guard, arg, *table_schema, res))) {633LOG_WARN("fail to do create local index", K(ret));634}635} else {636if (OB_FAIL(do_create_global_index(schema_guard, arg, *table_schema, res))) {637LOG_WARN("fail to do create global index", K(ret));638}639}640} else {641ret = OB_ERR_UNEXPECTED;642LOG_WARN("index type unexpected", K(ret), "index_type", arg.index_type_);643}644return ret;645}
646
647/* after global index is introducted, the arguments of this interface become complicated
648* if this interface is modified, please update this comments
649* modified by wenduo, 2018/5/15
650* ObIndexBuilder::generate_schema is invoked in thoe following three circumstances:
651* 1. invoked when Create index to build global index: this interface helps to specifiy partition columns,
652* the column information of index schema is generated during the resolve stage, no need to generate
653* column information of the index schema any more in this interface,
654* the argument global_index_without_column_info is false for this situation
655* 2. invoked when Create table with index: this interface helps to specify partition columns,
656* the column information of index schema is generated during the resolve stage, need to to generate
657* column information of the index schema any more in this interface,
658* the argument global_index_without_column_info is false for this situation
659* 3. invoked when Alter table with index, in this situation only non-partition global index can be build,
660* column information is not filled in the index schema and the global_index_without_column_info is true.
661* when generate_schema is invoked to build a local index or a global index with local storage,
662* global_index_without_column_info is false.
663*/
664int ObIndexBuilder::generate_schema(665const ObCreateIndexArg &arg,666ObTableSchema &data_schema,667const bool global_index_without_column_info,668const bool generate_id,669ObTableSchema &schema)670{
671int ret = OB_SUCCESS;672bool is_oracle_mode = false;673// some items in arg may be invalid, don't check arg here(when create table with index, alter674// table add index)675if (OB_UNLIKELY(!ddl_service_.is_inited())) {676ret = OB_INNER_STAT_ERROR;677LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));678} else if (OB_UNLIKELY(!data_schema.is_valid())) {679ret = OB_INVALID_ARGUMENT;680LOG_WARN("invalid argument", K(ret), K(data_schema));681} else if (OB_FAIL(data_schema.check_if_oracle_compat_mode(is_oracle_mode))) {682LOG_WARN("check_if_oracle_compat_mode failed", K(ret));683}684
685if (OB_SUCC(ret)) {686if (arg.index_columns_.count() <= 0) {687ret = OB_INVALID_ARGUMENT;688LOG_WARN("index columns can't be empty", "index columns", arg.index_columns_, K(ret));689} else {}690
691//do some check692if (OB_SUCC(ret)) {693if (!GCONF.enable_sys_table_ddl) {694if (!data_schema.is_user_table() && !data_schema.is_tmp_table()) {695ret = OB_ERR_WRONG_OBJECT;696LOG_USER_ERROR(OB_ERR_WRONG_OBJECT, to_cstring(arg.database_name_),697to_cstring(arg.table_name_), "BASE_TABLE");698ObTableType table_type = data_schema.get_table_type();699LOG_WARN("Not support to create index on non-normal table", K(table_type), K(arg), K(ret));700} else if (OB_INVALID_ID != arg.index_table_id_ || OB_INVALID_ID != arg.data_table_id_) {701char err_msg[number::ObNumber::MAX_PRINTABLE_SIZE];702MEMSET(err_msg, 0, sizeof(err_msg));703// create index specifying index_id can only be used when the configuration is on704ret = OB_OP_NOT_ALLOW;705(void)snprintf(err_msg, sizeof(err_msg),706"%s", "create index with index_table_id/data_table_id");707LOG_USER_ERROR(OB_OP_NOT_ALLOW, err_msg);708}709}710
711if (OB_SUCC(ret)712&& (INDEX_TYPE_NORMAL_LOCAL == arg.index_type_713|| INDEX_TYPE_UNIQUE_LOCAL == arg.index_type_714|| INDEX_TYPE_DOMAIN_CTXCAT == arg.index_type_)) {715if (OB_FAIL(sql::ObResolverUtils::check_unique_index_cover_partition_column(716data_schema, arg))) {717RS_LOG(WARN, "fail to check unique key cover partition column", K(ret));718}719}720int64_t index_data_length = 0;721bool is_ctxcat_added = false;722bool is_mysql_func_index = false;723for (int64_t i = 0; OB_SUCC(ret) && i < arg.index_columns_.count(); ++i) {724const ObColumnSchemaV2 *data_column = NULL;725const ObColumnSortItem &sort_item = arg.index_columns_.at(i);726if (NULL == (data_column = data_schema.get_column_schema(sort_item.column_name_))) {727ret = OB_ERR_KEY_COLUMN_DOES_NOT_EXITS;728LOG_USER_ERROR(OB_ERR_KEY_COLUMN_DOES_NOT_EXITS, sort_item.column_name_.length(), sort_item.column_name_.ptr());729LOG_WARN("get_column_schema failed", "tenant_id", data_schema.get_tenant_id(),730"database_id", data_schema.get_database_id(),731"table_name", data_schema.get_table_name(),732"column name", sort_item.column_name_, K(ret));733} else if (OB_INVALID_ID != sort_item.get_column_id()734&& data_column->get_column_id() != sort_item.get_column_id()) {735ret = OB_ERR_INVALID_COLUMN_ID;736LOG_USER_ERROR(OB_ERR_INVALID_COLUMN_ID, sort_item.column_name_.length(), sort_item.column_name_.ptr());737LOG_WARN("Column ID specified by create index mismatch with data table Column ID",738"data_table_column_id", data_column->get_column_id(),739"user_specidifed_column_id", sort_item.get_column_id(),740K(ret));741} else if (sort_item.prefix_len_ > 0) {742if ((index_data_length += sort_item.prefix_len_) > OB_MAX_USER_ROW_KEY_LENGTH) {743ret = OB_ERR_TOO_LONG_KEY_LENGTH;744LOG_USER_ERROR(OB_ERR_TOO_LONG_KEY_LENGTH, OB_MAX_USER_ROW_KEY_LENGTH);745LOG_WARN("index table rowkey length over max_user_row_key_length",746K(index_data_length), LITERAL_K(OB_MAX_USER_ROW_KEY_LENGTH), K(ret));747}748} else if (FALSE_IT(is_mysql_func_index |= !is_oracle_mode && data_column->is_func_idx_column())) {749} else if (!is_oracle_mode && data_column->is_func_idx_column() && ob_is_text_tc(data_column->get_data_type())) {750ret = OB_ERR_FUNCTIONAL_INDEX_ON_LOB;751LOG_WARN("Cannot create a functional index on an expression that returns a BLOB or TEXT.", K(ret));752} else if (ob_is_text_tc(data_column->get_data_type()) && !data_column->is_fulltext_column()) {753ret = OB_ERR_WRONG_KEY_COLUMN;754LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, sort_item.column_name_.length(), sort_item.column_name_.ptr());755LOG_WARN("index created direct on large text column should only be fulltext", K(arg.index_type_), K(ret));756} else if (ObTimestampTZType == data_column->get_data_type()757&& arg.is_unique_primary_index()) {758ret = OB_ERR_WRONG_KEY_COLUMN;759LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, sort_item.column_name_.length(), sort_item.column_name_.ptr());760LOG_WARN("TIMESTAMP WITH TIME ZONE column can't be primary/unique key", K(arg.index_type_), K(ret));761} else if (data_column->get_meta_type().is_blob()) {762ret = OB_ERR_WRONG_KEY_COLUMN;763LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, sort_item.column_name_.length(), sort_item.column_name_.ptr());764LOG_WARN("fulltext index created on blob column is not supported", K(arg.index_type_), K(ret));765} else if (data_column->get_meta_type().is_ext() || data_column->get_meta_type().is_user_defined_sql_type()) {766ret = OB_ERR_WRONG_KEY_COLUMN;767LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, sort_item.column_name_.length(), sort_item.column_name_.ptr());768LOG_WARN("index created on udt column is not supported", K(arg.index_type_), K(ret));769} else if (ob_is_json_tc(data_column->get_data_type())) {770if (!is_oracle_mode && data_column->is_func_idx_column()) {771ret = OB_ERR_FUNCTIONAL_INDEX_ON_JSON_OR_GEOMETRY_FUNCTION;772LOG_WARN("Cannot create a functional index on an expression that returns a JSON or GEOMETRY.",K(ret));773} else {774ret = OB_ERR_JSON_USED_AS_KEY;775LOG_USER_ERROR(OB_ERR_JSON_USED_AS_KEY, sort_item.column_name_.length(), sort_item.column_name_.ptr());776LOG_WARN("JSON column cannot be used in key specification.", K(arg.index_type_), K(ret));777}778} else if (data_column->is_string_type()) {779int64_t length = 0;780if (data_column->is_fulltext_column()) {781if (!is_ctxcat_added) {782length = OB_MAX_OBJECT_NAME_LENGTH;783is_ctxcat_added = true;784}785} else if (OB_FAIL(data_column->get_byte_length(length, is_oracle_mode, false))) {786LOG_WARN("fail to get byte length of column", K(ret));787} else if (length < 0) {788ret = OB_ERR_WRONG_KEY_COLUMN;789LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, sort_item.column_name_.length(), sort_item.column_name_.ptr());790LOG_WARN("byte_length of string type column is less than zero", K(length), K(ret));791} else { /*do nothing*/ }792
793if (OB_SUCC(ret)) {794index_data_length += length;795if (index_data_length > OB_MAX_USER_ROW_KEY_LENGTH) {796ret = OB_ERR_TOO_LONG_KEY_LENGTH;797LOG_USER_ERROR(OB_ERR_TOO_LONG_KEY_LENGTH, (OB_MAX_USER_ROW_KEY_LENGTH));798LOG_WARN("index table rowkey length over max_user_row_key_length",799K(index_data_length), LITERAL_K(OB_MAX_USER_ROW_KEY_LENGTH), K(ret));800}801}802}803}804if (OB_SUCC(ret) && is_mysql_func_index) {805uint64_t tenant_data_version = 0;806if (OB_FAIL(GET_MIN_DATA_VERSION(data_schema.get_tenant_id(), tenant_data_version))) {807LOG_WARN("get tenant data version failed", K(ret));808} else if (tenant_data_version < DATA_VERSION_4_2_0_0){809ret = OB_NOT_SUPPORTED;810LOG_WARN("tenant version is less than 4.2, functional index is not supported in mysql mode", K(ret), K(tenant_data_version));811LOG_USER_ERROR(OB_NOT_SUPPORTED, "version is less than 4.2, functional index in mysql mode not supported");812}813}814}815
816if (OB_SUCC(ret)) {817// column information of the global index is filled during the resolve stage818const bool is_index_local_storage = (INDEX_TYPE_NORMAL_LOCAL == arg.index_type_819|| INDEX_TYPE_UNIQUE_LOCAL == arg.index_type_820|| INDEX_TYPE_NORMAL_GLOBAL_LOCAL_STORAGE == arg.index_type_821|| INDEX_TYPE_UNIQUE_GLOBAL_LOCAL_STORAGE == arg.index_type_822|| INDEX_TYPE_DOMAIN_CTXCAT == arg.index_type_823|| INDEX_TYPE_SPATIAL_LOCAL == arg.index_type_824|| INDEX_TYPE_SPATIAL_GLOBAL_LOCAL_STORAGE == arg.index_type_);825const bool need_generate_index_schema_column = (is_index_local_storage || global_index_without_column_info);826schema.set_table_mode(data_schema.get_table_mode_flag());827schema.set_table_state_flag(data_schema.get_table_state_flag());828schema.set_duplicate_scope(data_schema.get_duplicate_scope());829if (OB_FAIL(set_basic_infos(arg, data_schema, schema))) {830LOG_WARN("set_basic_infos failed", K(arg), K(data_schema), K(ret));831} else if (need_generate_index_schema_column832&& OB_FAIL(set_index_table_columns(arg, data_schema, schema))) {833LOG_WARN("set_index_table_columns failed", K(arg), K(data_schema), K(ret));834} else if (OB_FAIL(set_index_table_options(arg, data_schema, schema))) {835LOG_WARN("set_index_table_options failed", K(arg), K(data_schema), K(ret));836} else {837schema.set_name_generated_type(arg.index_schema_.get_name_generated_type());838LOG_INFO("finish generate index schema", K(schema));839}840}841if (OB_FAIL(ret)) {842} else if (data_schema.get_part_level() > 0843&& is_index_local_storage(arg.index_type_)844&& OB_FAIL(schema.assign_partition_schema(data_schema))) {845LOG_WARN("fail to assign partition schema", K(schema), K(ret));846} else if (OB_FAIL(ddl_service_.try_format_partition_schema(schema))) {847LOG_WARN("fail to format partition schema", KR(ret), K(schema));848} else if (generate_id) {849if (OB_FAIL(ddl_service_.generate_object_id_for_partition_schema(schema))) {850LOG_WARN("fail to generate object_id for partition schema", KR(ret), K(schema));851} else if (OB_FAIL(ddl_service_.generate_tablet_id(schema))) {852LOG_WARN("fail to fetch new table id", KR(ret), K(schema));853}854}855}856
857if (OB_SUCC(ret)) {858// create index column_group after schema generate859if (OB_FAIL(create_index_column_group(arg, schema))) {860LOG_WARN("fail to create cg for index", K(ret));861}862}863return ret;864}
865
866int ObIndexBuilder::create_index_column_group(const obrpc::ObCreateIndexArg &arg, ObTableSchema &index_table_schema)867{
868int ret = OB_SUCCESS;869uint64_t compat_version = 0;870if (OB_FAIL(GET_MIN_DATA_VERSION(index_table_schema.get_tenant_id(), compat_version))) {871LOG_WARN("fail to get min data version", K(ret));872} else if (compat_version >= DATA_VERSION_4_3_0_0) {873ObArray<uint64_t> column_ids; // not include virtual column874index_table_schema.set_column_store(true);875if (arg.index_cgs_.count() > 0) {876index_table_schema.set_max_used_column_group_id(index_table_schema.get_max_used_column_group_id());877for (int64_t i = 0; OB_SUCC(ret) && i < arg.index_cgs_.count(); ++i) {878const obrpc::ObCreateIndexArg::ObIndexColumnGroupItem &cur_item = arg.index_cgs_.at(i);879if (!cur_item.is_valid()) {880ret = OB_INVALID_ARGUMENT;881LOG_WARN("invalid cg item", K(ret), K(cur_item));882} else if (cur_item.is_each_cg_) {883// handle all_type column_group & single_type column_group884ObColumnGroupSchema column_group_schema;885const int64_t column_cnt = index_table_schema.get_column_count();886if (OB_FAIL(column_ids.reserve(column_cnt))) {887LOG_WARN("fail to reserve", KR(ret), K(column_cnt));888} else {889ObTableSchema::const_column_iterator tmp_begin = index_table_schema.column_begin();890ObTableSchema::const_column_iterator tmp_end = index_table_schema.column_end();891for (; OB_SUCC(ret) && (tmp_begin != tmp_end); tmp_begin++) {892column_group_schema.reset();893ObColumnSchemaV2 *column = (*tmp_begin);894if (OB_FAIL(ObSchemaUtils::build_single_column_group(895index_table_schema, column, index_table_schema.get_tenant_id(),896index_table_schema.get_max_used_column_group_id() + 1, column_group_schema))) {897LOG_WARN("fail to build single column group");898} else if (column_group_schema.is_valid()) {899if (OB_FAIL(index_table_schema.add_column_group(column_group_schema))) {900LOG_WARN("fail to add single type column group", KR(ret), K(column_group_schema));901} else if (column->is_rowkey_column() || arg.exist_all_column_group_) {//if not exist all cg, build rowkey cg902if (OB_FAIL(column_ids.push_back(column->get_column_id()))) {903LOG_WARN("fail to push back", KR(ret), "column_id", column->get_column_id());904}905}906}907}908}909
910if (OB_SUCC(ret)) {911column_group_schema.reset();912const ObColumnGroupType cg_type = arg.exist_all_column_group_ ? ObColumnGroupType::ALL_COLUMN_GROUP913: ObColumnGroupType::ROWKEY_COLUMN_GROUP;914const ObString cg_name = arg.exist_all_column_group_ ? OB_ALL_COLUMN_GROUP_NAME : OB_ROWKEY_COLUMN_GROUP_NAME;915
916if (OB_FAIL(ObSchemaUtils::build_column_group(index_table_schema, index_table_schema.get_tenant_id(), cg_type, cg_name,917column_ids, index_table_schema.get_max_used_column_group_id() + 1, column_group_schema))) {918LOG_WARN("fail to build all type column_group", KR(ret), K(column_ids));919} else if (OB_FAIL(index_table_schema.add_column_group(column_group_schema))) {920LOG_WARN("fail to add all type column group", KR(ret), K(column_group_schema));921}922}923}924}925}926
927// add default column_group928if (OB_SUCC(ret)) {929ObColumnGroupSchema tmp_cg;930if (arg.index_cgs_.count() > 0) {931column_ids.reuse(); // if exists cg node, column_ids in default_type will be empty932} else {933ObTableSchema::const_column_iterator tmp_begin = index_table_schema.column_begin();934ObTableSchema::const_column_iterator tmp_end = index_table_schema.column_end();935for (; OB_SUCC(ret) && (tmp_begin != tmp_end); tmp_begin++) {936ObColumnSchemaV2 *column = (*tmp_begin);937if (OB_ISNULL(column)) {938ret = OB_ERR_UNEXPECTED;939LOG_WARN("column should not be null", KR(ret));940} else if (column->is_virtual_generated_column()) {941// skip virtual column942} else if (OB_FAIL(column_ids.push_back(column->get_column_id()))) {943LOG_WARN("fail to push back", KR(ret), "column_id", column->get_column_id());944}945}946}947
948if (FAILEDx(ObSchemaUtils::build_column_group(index_table_schema, index_table_schema.get_tenant_id(),949ObColumnGroupType::DEFAULT_COLUMN_GROUP, OB_DEFAULT_COLUMN_GROUP_NAME, column_ids,950DEFAULT_TYPE_COLUMN_GROUP_ID, tmp_cg))) {951LOG_WARN("fail to build default type column_group", KR(ret), "table_id", index_table_schema.get_table_id(), K(column_ids));952} else if (OB_FAIL(index_table_schema.add_column_group(tmp_cg))) {953LOG_WARN("fail to add default column group", KR(ret), "table_id", index_table_schema.get_table_id(),954K(arg.index_cgs_.count()), K(column_ids));955}956}957} else if (arg.index_cgs_.count() > 0) {958ret = OB_NOT_SUPPORTED;959LOG_WARN("data_version not support for create index with column group", K(ret), K(compat_version));960LOG_USER_ERROR(OB_NOT_SUPPORTED, "tenant data version is less than 4.3, create index with column group");961}962
963return ret;964}
965
966int ObIndexBuilder::set_basic_infos(const ObCreateIndexArg &arg,967const ObTableSchema &data_schema,968ObTableSchema &schema)969{
970int ret = OB_SUCCESS;971ObSchemaGetterGuard schema_guard;972const ObDatabaseSchema *database = NULL;973const uint64_t tenant_id = data_schema.get_tenant_id();974if (!ddl_service_.is_inited()) {975ret = OB_INNER_STAT_ERROR;976LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));977} else if (OB_FAIL(ddl_service_.get_schema_service().get_tenant_schema_guard(tenant_id, schema_guard))) {978LOG_WARN("fail to get schema_guard", K(ret), K(tenant_id));979} else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, data_schema.get_database_id(), database))) {980LOG_WARN("fail to get database_schema", K(ret), K(tenant_id), "database_id", data_schema.get_database_id());981} else if (OB_ISNULL(database)) {982ret = OB_ERR_UNEXPECTED;983LOG_WARN("database_schema is null", K(ret), "database_id", data_schema.get_database_id());984} else if (!data_schema.is_valid()) {985// some items in arg may be invalid, don't check arg986ret = OB_INVALID_ARGUMENT;987LOG_WARN("invalid argument", K(data_schema), K(ret));988} else {989ObString index_table_name = arg.index_name_;990ObArenaAllocator allocator(ObModIds::OB_SCHEMA);991const uint64_t table_schema_id = data_schema.get_table_id();992const ObTablespaceSchema *tablespace_schema = NULL;993if (table_schema_id != ((OB_INVALID_ID == arg.data_table_id_) ? table_schema_id : arg.data_table_id_)) {994// need to check if the data table ids are the same when data table id is specified995ret = OB_INVALID_ARGUMENT;996LOG_WARN("Invalid data table id", K(table_schema_id), K(arg.data_table_id_), K(ret));997} else if (OB_FAIL(ObTableSchema::build_index_table_name(998allocator, table_schema_id, arg.index_name_, index_table_name))) {999LOG_WARN("build_index_table_name failed", K(table_schema_id), K(arg), K(ret));1000} else if (OB_FAIL(schema.set_table_name(index_table_name))) {1001LOG_WARN("set_table_name failed", K(index_table_name), K(arg), K(ret));1002} else {1003schema.set_name_generated_type(arg.index_schema_.get_name_generated_type());1004schema.set_table_id(arg.index_table_id_);1005schema.set_table_type(USER_INDEX);1006schema.set_index_type(arg.index_type_);1007schema.set_index_status(arg.index_option_.index_status_);1008schema.set_data_table_id(table_schema_id);1009
1010// priority same with data table schema1011schema.set_tenant_id(tenant_id);1012schema.set_database_id(data_schema.get_database_id());1013schema.set_tablegroup_id(OB_INVALID_ID);1014schema.set_load_type(data_schema.get_load_type());1015schema.set_def_type(data_schema.get_def_type());1016if (INDEX_TYPE_NORMAL_LOCAL == arg.index_type_1017|| INDEX_TYPE_UNIQUE_LOCAL == arg.index_type_1018|| INDEX_TYPE_SPATIAL_LOCAL == arg.index_type_) {1019schema.set_part_level(data_schema.get_part_level());1020} else {} // partition level is filled during resolve stage for global index1021schema.set_charset_type(data_schema.get_charset_type());1022schema.set_collation_type(data_schema.get_collation_type());1023schema.set_row_store_type(data_schema.get_row_store_type());1024schema.set_store_format(data_schema.get_store_format());1025schema.set_storage_format_version(data_schema.get_storage_format_version());1026schema.set_tablespace_id(arg.index_schema_.get_tablespace_id());1027if (OB_FAIL(schema.set_encryption_str(arg.index_schema_.get_encryption_str()))) {1028LOG_WARN("fail to set set_encryption_str", K(ret), K(arg));1029}1030
1031if (data_schema.get_max_used_column_id() > schema.get_max_used_column_id()) {1032schema.set_max_used_column_id(data_schema.get_max_used_column_id());1033}1034//index table will not contain auto increment column1035schema.set_autoinc_column_id(0);1036schema.set_progressive_merge_num(data_schema.get_progressive_merge_num());1037schema.set_progressive_merge_round(data_schema.get_progressive_merge_round());1038if (OB_FAIL(ret)) {1039} else if (OB_FAIL(schema.set_compress_func_name(data_schema.get_compress_func_name()))) {1040LOG_WARN("set_compress_func_name failed", K(data_schema));1041} else if (OB_INVALID_ID != schema.get_tablespace_id()) {1042if (OB_FAIL(schema_guard.get_tablespace_schema(1043tenant_id, schema.get_tablespace_id(), tablespace_schema))) {1044LOG_WARN("fail to get tablespace schema", K(schema), K(ret));1045} else if (OB_UNLIKELY(NULL == tablespace_schema)) {1046ret = OB_ERR_UNEXPECTED;1047LOG_WARN("tablespace schema is null", K(ret), K(schema));1048} else if (OB_FAIL(schema.set_encrypt_key(tablespace_schema->get_encrypt_key()))) {1049LOG_WARN("fail to set encrypt key", K(ret), K(schema));1050} else {1051schema.set_master_key_id(tablespace_schema->get_master_key_id());1052}1053}1054}1055}1056return ret;1057}
1058
1059int ObIndexBuilder::set_index_table_columns(const ObCreateIndexArg &arg,1060const ObTableSchema &data_schema,1061ObTableSchema &schema)1062{
1063int ret = OB_SUCCESS;1064if (!ddl_service_.is_inited()) {1065ret = OB_INNER_STAT_ERROR;1066LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));1067} else if (OB_FAIL(ObIndexBuilderUtil::set_index_table_columns(arg, data_schema, schema))) {1068LOG_WARN("fail to set index table columns", K(ret));1069} else {} // no more to do1070return ret;1071}
1072
1073int ObIndexBuilder::set_index_table_options(const obrpc::ObCreateIndexArg &arg,1074const share::schema::ObTableSchema &data_schema,1075share::schema::ObTableSchema &schema)1076{
1077int ret = OB_SUCCESS;1078if (!ddl_service_.is_inited()) {1079ret = OB_INNER_STAT_ERROR;1080LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));1081} else if (!data_schema.is_valid()) {1082// some items in arg may be invalid, don't check arg1083ret = OB_INVALID_ARGUMENT;1084LOG_WARN("invalid argument", K(data_schema), K(ret));1085} else {1086schema.set_block_size(arg.index_option_.block_size_);1087schema.set_tablet_size(data_schema.get_tablet_size());1088schema.set_pctfree(data_schema.get_pctfree());1089schema.set_index_attributes_set(arg.index_option_.index_attributes_set_);1090schema.set_is_use_bloomfilter(arg.index_option_.use_bloom_filter_);1091//schema.set_progressive_merge_num(arg.index_option_.progressive_merge_num_);1092schema.set_index_using_type(arg.index_using_type_);1093schema.set_row_store_type(data_schema.get_row_store_type());1094schema.set_store_format(data_schema.get_store_format());1095// set dop for index table1096schema.set_dop(arg.index_schema_.get_dop());1097if (OB_FAIL(schema.set_compress_func_name(data_schema.get_compress_func_name()))) {1098LOG_WARN("set_compress_func_name failed", K(ret),1099"compress method", data_schema.get_compress_func_name());1100} else if (OB_FAIL(schema.set_comment(arg.index_option_.comment_))) {1101LOG_WARN("set_comment failed", "comment", arg.index_option_.comment_, K(ret));1102} else if (OB_FAIL(schema.set_parser_name(arg.index_option_.parser_name_))) {1103LOG_WARN("set parser name failed", K(ret), "parser_name", arg.index_option_.parser_name_);1104}1105}1106return ret;1107}
1108
1109bool ObIndexBuilder::is_final_index_status(const ObIndexStatus index_status) const1110{
1111return (INDEX_STATUS_AVAILABLE == index_status1112|| INDEX_STATUS_UNIQUE_INELIGIBLE == index_status1113|| is_error_index_status(index_status));1114}
1115
1116}//end namespace rootserver1117}//end namespace oceanbase1118