oceanbase

Форк
0
/
ob_index_builder.cpp 
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 RS
14
#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

50
namespace oceanbase
51
{
52
using namespace common;
53
using namespace common::sqlclient;
54
using namespace obrpc;
55
using namespace share;
56
using namespace share::schema;
57
using namespace sql;
58
using namespace palf;
59
namespace rootserver
60
{
61

62
ObIndexBuilder::ObIndexBuilder(ObDDLService &ddl_service)
63
  : ddl_service_(ddl_service)
64
{
65
}
66

67
ObIndexBuilder::~ObIndexBuilder()
68
{
69
}
70

71
int ObIndexBuilder::create_index(
72
    const ObCreateIndexArg &arg,
73
    obrpc::ObAlterTableRes &res)
74
{
75
  int ret = OB_SUCCESS;
76
  LOG_INFO("start create index", K(arg));
77
  if (!ddl_service_.is_inited()) {
78
    ret = OB_INNER_STAT_ERROR;
79
    LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));
80
  } else if (!arg.is_valid()) {
81
    ret = OB_INVALID_ARGUMENT;
82
    LOG_WARN("invalid arg", K(arg), K(ret));
83
  } else if (OB_FAIL(do_create_index(arg, res))) {
84
    LOG_WARN("generate_schema failed", K(arg), K(ret));
85
  }
86
  if (OB_ERR_TABLE_EXIST == ret) {
87
    if (true == arg.if_not_exist_) {
88
      ret = OB_SUCCESS;
89
      LOG_USER_WARN(OB_ERR_KEY_NAME_DUPLICATE, arg.index_name_.length(), arg.index_name_.ptr());
90
    } else {
91
      ret = OB_ERR_KEY_NAME_DUPLICATE;
92
      LOG_USER_ERROR(OB_ERR_KEY_NAME_DUPLICATE, arg.index_name_.length(), arg.index_name_.ptr());
93
    }
94
  }
95
  LOG_INFO("finish create index", K(arg), K(ret));
96
  return ret;
97
}
98

99
int ObIndexBuilder::drop_index(const ObDropIndexArg &arg, obrpc::ObDropIndexRes &res)
100
{
101
  int ret = OB_SUCCESS;
102
  const uint64_t tenant_id = arg.tenant_id_;
103
  const bool is_index = false;
104
  ObArenaAllocator allocator(ObModIds::OB_SCHEMA);
105
  const ObTableSchema *table_schema = NULL;
106
  ObSchemaGetterGuard schema_guard;
107
  bool is_db_in_recyclebin = false;
108
  bool need_rename_index = true;
109
  ObTableType drop_table_type = USER_INDEX;
110
  uint64_t compat_version = 0;
111
  const bool is_mlog = (obrpc::ObIndexArg::DROP_MLOG == arg.index_action_type_);
112
  if (is_mlog) {
113
    need_rename_index = false;
114
    drop_table_type = MATERIALIZED_VIEW_LOG;
115
  }
116
  if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) {
117
    LOG_WARN("failed to get data version", KR(ret), K(tenant_id));
118
  } else if (is_mlog && (compat_version < DATA_VERSION_4_3_0_0)) {
119
    ret = OB_NOT_SUPPORTED;
120
    LOG_WARN("materialized view log before version 4.3 is not supported", KR(ret), K(compat_version));
121
    LOG_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()) {
124
    ret = OB_INNER_STAT_ERROR;
125
    LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));
126
  } else if (!arg.is_valid()) {
127
    ret = OB_INVALID_ARGUMENT;
128
    LOG_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))) {
130
    LOG_WARN("get_schema_guard failed", K(ret));
131
  } else if (OB_FAIL(schema_guard.get_table_schema(
132
                         tenant_id, arg.database_name_, arg.table_name_,
133
                         is_index, table_schema, arg.is_hidden_))) {
134
    LOG_WARN("failed to get data table schema", K(arg), K(ret));
135
  } else if (NULL == table_schema) {
136
    ret = OB_TABLE_NOT_EXIST;
137
    LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(arg.database_name_), to_cstring(arg.table_name_));
138
    LOG_WARN("table not found", K(arg), K(ret));
139
  } else if (arg.is_in_recyclebin_) {
140
    // internal delete index
141
  } else if (table_schema->is_in_recyclebin()) {
142
    ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
143
    LOG_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,
145
            table_schema->get_database_id(), is_db_in_recyclebin))) {
146
    LOG_WARN("check database in recyclebin failed", K(ret), K(tenant_id));
147
  } else if (is_db_in_recyclebin) {
148
    ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
149
    LOG_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))) {
151
    LOG_WARN("check whether foreign key related table executes ddl failed", K(ret));
152
  }
153
  if (OB_SUCC(ret)) {
154
    const uint64_t data_table_id = table_schema->get_table_id();
155
    const ObTableSchema *index_table_schema = NULL;
156
    if (OB_INVALID_ID != arg.index_table_id_) {
157
      LOG_DEBUG("drop index with index_table_id", K(arg.index_table_id_));
158
      if (OB_FAIL(schema_guard.get_table_schema(tenant_id, arg.index_table_id_, index_table_schema))) {
159
        LOG_WARN("fail to get index table schema", K(ret), K(tenant_id), K(arg.index_table_id_));
160
      }
161
    } else {
162
      ObString index_table_name;
163
      if (is_mlog) {
164
        index_table_name = arg.index_name_;
165
      } else if (OB_FAIL(ObTableSchema::build_index_table_name(
166
          allocator, data_table_id, arg.index_name_, index_table_name))) {
167
        LOG_WARN("build_index_table_name failed", K(arg), K(data_table_id), K(ret));
168
      }
169
      if (OB_SUCC(ret)) {
170
        if (OB_FAIL(schema_guard.get_table_schema(tenant_id,
171
            table_schema->get_database_id(),
172
            index_table_name,
173
            !is_mlog,/*is_index*/
174
            index_table_schema))) {
175
          LOG_WARN("fail to get table schema", K(ret), K(tenant_id), K(index_table_name), K(index_table_schema));
176
        }
177
      }
178
    }
179
    bool have_index = false;
180
    const common::ObIArray<ObForeignKeyInfo> &foreign_key_infos = table_schema->get_foreign_key_infos();
181
    if (OB_FAIL(ret)) {
182
    } else if (OB_ISNULL(index_table_schema)) {
183
      if (is_mlog) {
184
        ret = OB_ERR_TABLE_NO_MLOG;
185
        LOG_WARN("table does not have a materialized view log", KR(ret),
186
            K(arg.database_name_), K(arg.index_name_));
187
        LOG_USER_ERROR(OB_ERR_TABLE_NO_MLOG, to_cstring(arg.database_name_), to_cstring(arg.index_name_));
188
      } else {
189
        ret = OB_ERR_CANT_DROP_FIELD_OR_KEY;
190
        LOG_WARN("index table schema should not be null", K(arg.index_name_), K(ret));
191
        LOG_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,
194
                                                               foreign_key_infos,
195
                                                               have_index))) {
196
      LOG_WARN("fail to check index on foreign key", K(ret), K(foreign_key_infos), KPC(index_table_schema));
197
    } else if (have_index) {
198
      ret = OB_ERR_ATLER_TABLE_ILLEGAL_FK;
199
      LOG_WARN("cannot delete index with foreign key dependency", K(ret));
200
    } else if (!arg.is_inner_ && index_table_schema->is_unavailable_index()) {
201
      ret = OB_NOT_SUPPORTED;
202
      LOG_WARN("not support to drop a building index", K(ret), K(arg.is_inner_), KPC(index_table_schema));
203
      LOG_USER_ERROR(OB_NOT_SUPPORTED, "dropping a building index is");
204
    } else if (arg.is_add_to_scheduler_) {
205
      ObDDLOperator ddl_operator(ddl_service_.get_schema_service(), ddl_service_.get_sql_proxy());
206
      ObDDLSQLTransaction trans(&ddl_service_.get_schema_service());
207
      int64_t refreshed_schema_version = 0;
208
      ObArenaAllocator allocator(lib::ObLabel("DdlTaskTmp"));
209
      ObDDLTaskRecord task_record;
210
      bool has_index_task = false;
211
      SMART_VAR(ObTableSchema, new_index_schema) {
212
        if (OB_FAIL(schema_guard.get_schema_version(tenant_id, refreshed_schema_version))) {
213
          LOG_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))) {
215
          LOG_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(
217
              trans, tenant_id, data_table_id, index_table_schema->get_table_id(), has_index_task))) {
218
          LOG_WARN("failed to check ddl conflict", K(ret));
219
        } else if (has_index_task) {
220
          ret = OB_NOT_SUPPORTED;
221
          LOG_WARN("not support to drop a building or dropping index", K(ret), K(arg.is_inner_), KPC(index_table_schema));
222
          LOG_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(
224
                                                      table_schema->get_table_id(),
225
                                                      table_schema->get_database_id(),
226
                                                      arg,
227
                                                      schema_guard,
228
                                                      ddl_operator,
229
                                                      trans,
230
                                                      new_index_schema))) {
231
          LOG_WARN("renmae index name failed", K(ret));
232
        } else if (!need_rename_index && OB_FAIL(new_index_schema.assign(*index_table_schema))) {
233
          LOG_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))) {
235
          LOG_WARN("submit drop index task failed", K(ret));
236
        } else {
237
          res.tenant_id_ = new_index_schema.get_tenant_id();
238
          res.index_table_id_ = new_index_schema.get_table_id();
239
          res.schema_version_ = new_index_schema.get_schema_version();
240
          res.task_id_ = task_record.task_id_;
241
        }
242
      }
243
      if (trans.is_started()) {
244
        int temp_ret = OB_SUCCESS;
245
        if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) {
246
          LOG_WARN_RET(temp_ret, "trans end failed", "is_commit", OB_SUCCESS == ret, K(temp_ret));
247
          ret = (OB_SUCC(ret)) ? temp_ret : ret;
248
        }
249
      }
250
      if (OB_SUCC(ret)) {
251
        int tmp_ret = OB_SUCCESS;
252
        if (OB_FAIL(ddl_service_.publish_schema(tenant_id))) {
253
          LOG_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))) {
255
          LOG_WARN("fail to schedule ddl task", K(tmp_ret), K(task_record));
256
        }
257
      }
258
    } else {
259
      //construct an arg for drop table
260
      ObTableItem table_item;
261
      table_item.database_name_ = arg.database_name_;
262
      table_item.table_name_ = index_table_schema->get_table_name();
263
      table_item.is_hidden_ = index_table_schema->is_user_hidden_table();
264
      obrpc::ObDDLRes ddl_res;
265
      obrpc::ObDropTableArg drop_table_arg;
266
      drop_table_arg.tenant_id_ = tenant_id;
267
      drop_table_arg.if_exist_ = false;
268
      drop_table_arg.table_type_ = drop_table_type;
269
      drop_table_arg.ddl_stmt_str_ = arg.ddl_stmt_str_;
270
      drop_table_arg.force_drop_ = arg.is_in_recyclebin_;
271
      drop_table_arg.task_id_ = arg.task_id_;
272
      if (OB_FAIL(drop_table_arg.tables_.push_back(table_item))) {
273
        LOG_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))) {
275
        if (OB_TABLE_NOT_EXIST == ret) {
276
          ret = OB_ERR_CANT_DROP_FIELD_OR_KEY;
277
          LOG_USER_ERROR(OB_ERR_CANT_DROP_FIELD_OR_KEY, arg.index_name_.length(), arg.index_name_.ptr());
278
          LOG_WARN("index not exist, can't drop it", K(arg), K(ret));
279
        } else {
280
          LOG_WARN("drop_table failed", K(arg), K(drop_table_arg), K(ret));
281
        }
282
      }
283
    }
284
  }
285

286
  LOG_INFO("finish drop index", K(arg), K(ret));
287
  return ret;
288
}
289

290
int ObIndexBuilder::do_create_global_index(
291
    share::schema::ObSchemaGetterGuard &schema_guard,
292
    const obrpc::ObCreateIndexArg &arg,
293
    const share::schema::ObTableSchema &table_schema,
294
    obrpc::ObAlterTableRes &res)
295
{
296
  int ret = OB_SUCCESS;
297
  uint64_t tenant_data_version = 0;
298
  ObArray<ObColumnSchemaV2 *> gen_columns;
299
  const bool global_index_without_column_info = false;
300
  ObDDLTaskRecord task_record;
301
  ObArenaAllocator allocator(lib::ObLabel("DdlTaskTmp"));
302
  HEAP_VARS_2((ObTableSchema, new_table_schema),
303
              (obrpc::ObCreateIndexArg, new_arg)) {
304
    ObTableSchema &index_schema = new_arg.index_schema_;
305
    ObDDLSQLTransaction trans(&ddl_service_.get_schema_service());
306
    int64_t refreshed_schema_version = 0;
307
    const uint64_t tenant_id = table_schema.get_tenant_id();
308
    if (OB_FAIL(schema_guard.get_schema_version(tenant_id, refreshed_schema_version))) {
309
      LOG_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))) {
311
      LOG_WARN("start transaction failed", KR(ret), K(tenant_id), K(refreshed_schema_version));
312
    } else if (OB_FAIL(new_table_schema.assign(table_schema))) {
313
      LOG_WARN("fail to assign schema", K(ret));
314
    } else if (!new_table_schema.is_valid()) {
315
      ret = OB_ERR_UNEXPECTED;
316
      LOG_WARN("fail to copy table schema", K(ret));
317
    } else if (OB_FAIL(new_arg.assign(arg))) {
318
      LOG_WARN("fail to assign arg", K(ret));
319
    } else if (!new_arg.is_valid()) {
320
      ret = OB_ERR_UNEXPECTED;
321
      LOG_WARN("fail to copy create index arg", K(ret));
322
    } else if (OB_FAIL(ObIndexBuilderUtil::adjust_expr_index_args(
323
            new_arg, new_table_schema, allocator, gen_columns))) {
324
      LOG_WARN("fail to adjust expr index args", K(ret));
325
    } else if (OB_FAIL(generate_schema(
326
        new_arg, new_table_schema, global_index_without_column_info,
327
        true/*generate_id*/, index_schema))) {
328
      LOG_WARN("fail to generate schema", K(ret), K(new_arg));
329
    } else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) {
330
      LOG_WARN("get min data version failed", K(ret), K(tenant_id));
331
    } else {
332
      if (gen_columns.empty()) {
333
        if (OB_FAIL(ddl_service_.create_global_index(
334
                trans, new_arg, new_table_schema, tenant_data_version, index_schema))) {
335
          LOG_WARN("fail to create global index", K(ret));
336
        }
337
      } else {
338
        if (OB_FAIL(ddl_service_.create_global_inner_expr_index(
339
              trans, table_schema, tenant_data_version, new_table_schema, gen_columns, index_schema))) {
340
          LOG_WARN("fail to create global inner expr index", K(ret));
341
        }
342
      }
343
      if (OB_FAIL(ret)) {
344
      } else if (OB_FAIL(submit_build_index_task(trans,
345
                                                 new_arg,
346
                                                 &new_table_schema,
347
                                                 nullptr/*inc_data_tablet_ids*/,
348
                                                 nullptr/*del_data_tablet_ids*/,
349
                                                 &index_schema,
350
                                                 arg.parallelism_,
351
                                                 arg.consumer_group_id_,
352
                                                 tenant_data_version,
353
                                                 allocator,
354
                                                 task_record))) {
355
        LOG_WARN("fail to submit build global index task", K(ret));
356
      }
357
    }
358
    if (OB_SUCC(ret)) {
359
      res.index_table_id_ = index_schema.get_table_id();
360
      res.schema_version_ = index_schema.get_schema_version();
361
      res.task_id_ = task_record.task_id_;
362
    }
363
    if (trans.is_started()) {
364
      int temp_ret = OB_SUCCESS;
365
      if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) {
366
        LOG_WARN("trans end failed", "is_commit", OB_SUCCESS == ret, K(temp_ret));
367
        ret = (OB_SUCC(ret)) ? temp_ret : ret;
368
      }
369
    }
370
    if (OB_SUCC(ret)) {
371
      int tmp_ret = OB_SUCCESS;
372
      if (OB_FAIL(ddl_service_.publish_schema(tenant_id))) {
373
        LOG_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))) {
375
        LOG_WARN("fail to schedule ddl task", K(tmp_ret), K(task_record));
376
      }
377
    }
378
  }
379
  return ret;
380
}
381

382
int ObIndexBuilder::submit_build_index_task(
383
    ObMySQLTransaction &trans,
384
    const obrpc::ObCreateIndexArg &create_index_arg,
385
    const ObTableSchema *data_schema,
386
    const ObIArray<ObTabletID> *inc_data_tablet_ids,
387
    const ObIArray<ObTabletID> *del_data_tablet_ids,
388
    const ObTableSchema *index_schema,
389
    const int64_t parallelism,
390
    const int64_t group_id,
391
    const uint64_t tenant_data_version,
392
    common::ObIAllocator &allocator,
393
    ObDDLTaskRecord &task_record)
394
{
395
  int ret = OB_SUCCESS;
396
  ObCreateDDLTaskParam param(index_schema->get_tenant_id(),
397
                             ObDDLType::DDL_CREATE_INDEX,
398
                             data_schema,
399
                             index_schema,
400
                             0/*object_id*/,
401
                             index_schema->get_schema_version(),
402
                             parallelism,
403
                             group_id,
404
                             &allocator,
405
                             &create_index_arg);
406
  param.tenant_data_version_ = tenant_data_version;
407
  if (OB_UNLIKELY(nullptr == data_schema || nullptr == index_schema || tenant_data_version <= 0)) {
408
    ret = OB_INVALID_ARGUMENT;
409
    LOG_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))) {
411
    LOG_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))) {
414
    LOG_WARN("failed to lock online ddl lock", K(ret));
415
  }
416
  return ret;
417
}
418

419
int ObIndexBuilder::submit_drop_index_task(ObMySQLTransaction &trans,
420
                                           const ObTableSchema &data_schema,
421
                                           const ObTableSchema &index_schema,
422
                                           const int64_t schema_version,
423
                                           const obrpc::ObDropIndexArg &arg,
424
                                           common::ObIAllocator &allocator,
425
                                           ObDDLTaskRecord &task_record)
426
{
427
  int ret = OB_SUCCESS;
428
  if (OB_UNLIKELY(!index_schema.is_valid())) {
429
    ret = OB_INVALID_ARGUMENT;
430
    LOG_WARN("invalid arguments", K(ret));
431
  } else {
432
    int64_t refreshed_schema_version = 0;
433
    const uint64_t tenant_id = index_schema.get_tenant_id();
434
    const ObDDLType ddl_type = (ObIndexArg::DROP_MLOG == arg.index_action_type_) ?
435
                               ObDDLType::DDL_DROP_MLOG : ObDDLType::DDL_DROP_INDEX;
436
    ObCreateDDLTaskParam param(tenant_id,
437
                               ddl_type,
438
                               &index_schema,
439
                               nullptr,
440
                               0/*object_id*/,
441
                               schema_version,
442
                               0/*parallelism*/,
443
                               arg.consumer_group_id_,
444
                               &allocator,
445
                               &arg);
446
    if (OB_FAIL(GCTX.root_service_->get_ddl_task_scheduler().create_ddl_task(param, trans, task_record))) {
447
      LOG_WARN("submit create index ddl task failed", K(ret));
448
    } else if (OB_FAIL(ObDDLLock::lock_for_add_drop_index(
449
        data_schema, nullptr/*inc_data_tablet_ids*/, nullptr/*del_data_tablet_ids*/, index_schema, ObTableLockOwnerID(task_record.task_id_), trans))) {
450
      LOG_WARN("failed to lock online ddl lock", K(ret));
451
    }
452
  }
453
  return ret;
454
}
455

456
int ObIndexBuilder::do_create_local_index(
457
    share::schema::ObSchemaGetterGuard &schema_guard,
458
    const obrpc::ObCreateIndexArg &create_index_arg,
459
    const share::schema::ObTableSchema &table_schema,
460
    obrpc::ObAlterTableRes &res)
461
{
462
  int ret = OB_SUCCESS;
463
  ObSEArray<ObColumnSchemaV2 *, 1> gen_columns;
464
  ObDDLTaskRecord task_record;
465
  ObArenaAllocator allocator(lib::ObLabel("DdlTaskTmp"));
466
  HEAP_VARS_3((ObTableSchema, index_schema),
467
              (ObTableSchema, new_table_schema),
468
              (obrpc::ObCreateIndexArg, my_arg)) {
469
    ObDDLSQLTransaction trans(&ddl_service_.get_schema_service());
470
    int64_t refreshed_schema_version = 0;
471
    const uint64_t tenant_id = table_schema.get_tenant_id();
472
    uint64_t tenant_data_version = 0;
473
    if (OB_FAIL(schema_guard.get_schema_version(tenant_id, refreshed_schema_version))) {
474
      LOG_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))) {
476
    LOG_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))) {
478
      LOG_WARN("start transaction failed", KR(ret), K(tenant_id), K(refreshed_schema_version));
479
    } else if (OB_FAIL(new_table_schema.assign(table_schema))) {
480
      LOG_WARN("fail to assign schema", K(ret));
481
    } else if (!new_table_schema.is_valid()) {
482
      ret = OB_ERR_UNEXPECTED;
483
      LOG_WARN("fail to copy table schema", K(ret));
484
    } else if (OB_FAIL(my_arg.assign(create_index_arg))) {
485
      LOG_WARN("fail to assign arg", K(ret));
486
    } else if (!my_arg.is_valid()) {
487
      ret = OB_ERR_UNEXPECTED;
488
      LOG_WARN("fail to copy create index arg", K(ret));
489
    } else {
490
      const 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-partitioned
492
      if (INDEX_TYPE_NORMAL_GLOBAL == my_arg.index_type_) {
493
        my_arg.index_type_ = INDEX_TYPE_NORMAL_GLOBAL_LOCAL_STORAGE;
494
        my_arg.index_schema_.set_index_type(INDEX_TYPE_NORMAL_GLOBAL_LOCAL_STORAGE);
495
      } else if (INDEX_TYPE_UNIQUE_GLOBAL == my_arg.index_type_) {
496
        my_arg.index_type_ = INDEX_TYPE_UNIQUE_GLOBAL_LOCAL_STORAGE;
497
        my_arg.index_schema_.set_index_type(INDEX_TYPE_UNIQUE_GLOBAL_LOCAL_STORAGE);
498
      } else if (INDEX_TYPE_SPATIAL_GLOBAL == my_arg.index_type_) {
499
        if (tenant_data_version < DATA_VERSION_4_1_0_0) {
500
          ret = OB_NOT_SUPPORTED;
501
          LOG_WARN("tenant data version is less than 4.1, spatial index is not supported", K(ret), K(tenant_data_version));
502
          LOG_USER_ERROR(OB_NOT_SUPPORTED, "tenant data version is less than 4.1, spatial index");
503
        } else {
504
          my_arg.index_type_ = INDEX_TYPE_SPATIAL_GLOBAL_LOCAL_STORAGE;
505
          my_arg.index_schema_.set_index_type(INDEX_TYPE_SPATIAL_GLOBAL_LOCAL_STORAGE);
506
        }
507
      }
508
      if (OB_FAIL(ObIndexBuilderUtil::adjust_expr_index_args(
509
              my_arg, new_table_schema, allocator, gen_columns))) {
510
        LOG_WARN("fail to adjust expr index args", K(ret));
511
      } else if (OB_FAIL(generate_schema(
512
              my_arg, new_table_schema, global_index_without_column_info,
513
              true/*generate_id*/, index_schema))) {
514
        LOG_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))) {
516
        LOG_WARN("failed to check create index on table", K(ret), K(index_schema));
517
      } else if (gen_columns.empty()) {
518
        if (OB_FAIL(ddl_service_.create_index_table(my_arg, tenant_data_version, index_schema, trans))) {
519
          LOG_WARN("fail to create index", K(ret), K(index_schema));
520
        }
521
      } else {
522
        if (OB_FAIL(ddl_service_.create_inner_expr_index(trans,
523
                                                         table_schema,
524
                                                         tenant_data_version,
525
                                                         new_table_schema,
526
                                                         gen_columns,
527
                                                         index_schema))) {
528
          LOG_WARN("fail to create inner expr index", K(ret));
529
        }
530
      }
531
      if (OB_FAIL(ret)) {
532
      } else if (OB_FAIL(submit_build_index_task(trans,
533
                                                 create_index_arg,
534
                                                 &new_table_schema,
535
                                                 nullptr/*inc_data_tablet_ids*/,
536
                                                 nullptr/*del_data_tablet_ids*/,
537
                                                 &index_schema,
538
                                                 create_index_arg.parallelism_,
539
                                                 create_index_arg.consumer_group_id_,
540
                                                 tenant_data_version,
541
                                                 allocator,
542
                                                 task_record))) {
543
        LOG_WARN("failt to submit build local index task", K(ret));
544
      } else {
545
        res.index_table_id_ = index_schema.get_table_id();
546
        res.schema_version_ = index_schema.get_schema_version();
547
        res.task_id_ = task_record.task_id_;
548
      }
549
    }
550
    if (trans.is_started()) {
551
      int temp_ret = OB_SUCCESS;
552
      if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) {
553
        LOG_WARN("trans end failed", "is_commit", OB_SUCCESS == ret, K(temp_ret));
554
        ret = (OB_SUCC(ret)) ? temp_ret : ret;
555
      }
556
    }
557
    if (OB_SUCC(ret)) {
558
      if (OB_FAIL(ddl_service_.publish_schema(tenant_id))) {
559
        LOG_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))) {
561
        LOG_WARN("fail to schedule ddl task", K(ret), K(task_record));
562
      }
563
    }
564
  }
565
  return 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
571
int ObIndexBuilder::do_create_index(
572
    const ObCreateIndexArg &arg,
573
    obrpc::ObAlterTableRes &res)
574
{
575
  int ret = OB_SUCCESS;
576
  ObSchemaGetterGuard schema_guard;
577
  const bool is_index = false;
578
  const ObTableSchema *table_schema = NULL;
579
  uint64_t table_id = OB_INVALID_ID;
580
  bool in_tenant_space = true;
581
  schema_guard.set_session_id(arg.session_id_);
582
  const uint64_t tenant_id = arg.tenant_id_;
583
  if (!ddl_service_.is_inited()) {
584
    ret = OB_INNER_STAT_ERROR;
585
    LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));
586
  } else if (!arg.is_valid()) {
587
    ret = OB_INVALID_ARGUMENT;
588
    LOG_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))) {
590
    LOG_WARN("get_schema_guard failed", K(ret));
591
  } else if (OB_FAIL(schema_guard.get_table_schema(
592
             tenant_id, arg.database_name_, arg.table_name_, is_index, table_schema))) {
593
    LOG_WARN("get_table_schema failed", K(arg), K(ret));
594
  } else if (NULL == table_schema) {
595
    ret = OB_TABLE_NOT_EXIST;
596
    LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(arg.database_name_), to_cstring(arg.table_name_));
597
    LOG_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))) {
600
    LOG_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.
603
    ret = OB_NOT_SUPPORTED;
604
    LOG_WARN("create index on inner table not supported", K(ret), K(table_id));
605
  } else if (!arg.is_inner_ && table_schema->is_in_recyclebin()) {
606
    ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
607
    LOG_WARN("can not add index on table in recyclebin", K(ret), K(arg));
608
  } else if (table_schema->is_in_splitting()) {
609
    ret = OB_OP_NOT_ALLOW;
610
    LOG_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))) {
612
    LOG_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) {
614
    ret = OB_ERR_TOO_MANY_KEYS;
615
    LOG_USER_ERROR(OB_ERR_TOO_MANY_KEYS, OB_MAX_INDEX_PER_TABLE);
616
    int64_t index_count = table_schema->get_index_tid_count();
617
    LOG_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))) {
619
    LOG_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_) {
624
    if (OB_FAIL(do_create_local_index(schema_guard, arg, *table_schema, res))) {
625
      LOG_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_) {
630
    if (!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-partitioned
632
      if (OB_FAIL(do_create_local_index(schema_guard, arg, *table_schema, res))) {
633
        LOG_WARN("fail to do create local index", K(ret));
634
      }
635
    } else {
636
      if (OB_FAIL(do_create_global_index(schema_guard, arg, *table_schema, res))) {
637
        LOG_WARN("fail to do create global index", K(ret));
638
      }
639
    }
640
  } else {
641
    ret = OB_ERR_UNEXPECTED;
642
    LOG_WARN("index type unexpected", K(ret), "index_type", arg.index_type_);
643
  }
644
  return 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
 */
664
int ObIndexBuilder::generate_schema(
665
    const ObCreateIndexArg &arg,
666
    ObTableSchema &data_schema,
667
    const bool global_index_without_column_info,
668
    const bool generate_id,
669
    ObTableSchema &schema)
670
{
671
  int ret = OB_SUCCESS;
672
  bool is_oracle_mode = false;
673
  // some items in arg may be invalid, don't check arg here(when create table with index, alter
674
  // table add index)
675
  if (OB_UNLIKELY(!ddl_service_.is_inited())) {
676
    ret = OB_INNER_STAT_ERROR;
677
    LOG_WARN("ddl_service not init", "ddl_service inited", ddl_service_.is_inited(), K(ret));
678
  } else if (OB_UNLIKELY(!data_schema.is_valid())) {
679
    ret = OB_INVALID_ARGUMENT;
680
    LOG_WARN("invalid argument",  K(ret), K(data_schema));
681
  } else if (OB_FAIL(data_schema.check_if_oracle_compat_mode(is_oracle_mode))) {
682
    LOG_WARN("check_if_oracle_compat_mode failed", K(ret));
683
  }
684

685
  if (OB_SUCC(ret)) {
686
    if (arg.index_columns_.count() <= 0) {
687
      ret = OB_INVALID_ARGUMENT;
688
      LOG_WARN("index columns can't be empty", "index columns", arg.index_columns_, K(ret));
689
    } else {}
690

691
    //do some check
692
    if (OB_SUCC(ret)) {
693
      if (!GCONF.enable_sys_table_ddl) {
694
        if (!data_schema.is_user_table() && !data_schema.is_tmp_table()) {
695
          ret = OB_ERR_WRONG_OBJECT;
696
          LOG_USER_ERROR(OB_ERR_WRONG_OBJECT, to_cstring(arg.database_name_),
697
                         to_cstring(arg.table_name_), "BASE_TABLE");
698
          ObTableType table_type = data_schema.get_table_type();
699
          LOG_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_) {
701
          char err_msg[number::ObNumber::MAX_PRINTABLE_SIZE];
702
          MEMSET(err_msg, 0, sizeof(err_msg));
703
          // create index specifying index_id can only be used when the configuration is on
704
          ret = OB_OP_NOT_ALLOW;
705
          (void)snprintf(err_msg, sizeof(err_msg),
706
                   "%s", "create index with index_table_id/data_table_id");
707
          LOG_USER_ERROR(OB_OP_NOT_ALLOW, err_msg);
708
        }
709
      }
710

711
      if (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_)) {
715
        if (OB_FAIL(sql::ObResolverUtils::check_unique_index_cover_partition_column(
716
                data_schema, arg))) {
717
          RS_LOG(WARN, "fail to check unique key cover partition column", K(ret));
718
        }
719
      }
720
      int64_t index_data_length = 0;
721
      bool is_ctxcat_added = false;
722
      bool is_mysql_func_index = false;
723
      for (int64_t i = 0; OB_SUCC(ret) && i < arg.index_columns_.count(); ++i) {
724
        const ObColumnSchemaV2 *data_column = NULL;
725
        const ObColumnSortItem &sort_item = arg.index_columns_.at(i);
726
        if (NULL == (data_column = data_schema.get_column_schema(sort_item.column_name_))) {
727
          ret = OB_ERR_KEY_COLUMN_DOES_NOT_EXITS;
728
          LOG_USER_ERROR(OB_ERR_KEY_COLUMN_DOES_NOT_EXITS, sort_item.column_name_.length(), sort_item.column_name_.ptr());
729
          LOG_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()) {
735
          ret = OB_ERR_INVALID_COLUMN_ID;
736
          LOG_USER_ERROR(OB_ERR_INVALID_COLUMN_ID, sort_item.column_name_.length(), sort_item.column_name_.ptr());
737
          LOG_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(),
740
                   K(ret));
741
        } else if (sort_item.prefix_len_ > 0) {
742
          if ((index_data_length += sort_item.prefix_len_) > OB_MAX_USER_ROW_KEY_LENGTH) {
743
            ret = OB_ERR_TOO_LONG_KEY_LENGTH;
744
            LOG_USER_ERROR(OB_ERR_TOO_LONG_KEY_LENGTH, OB_MAX_USER_ROW_KEY_LENGTH);
745
            LOG_WARN("index table rowkey length over max_user_row_key_length",
746
                K(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())) {
750
          ret = OB_ERR_FUNCTIONAL_INDEX_ON_LOB;
751
          LOG_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()) {
753
          ret = OB_ERR_WRONG_KEY_COLUMN;
754
          LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, sort_item.column_name_.length(), sort_item.column_name_.ptr());
755
          LOG_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()) {
758
          ret = OB_ERR_WRONG_KEY_COLUMN;
759
          LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, sort_item.column_name_.length(), sort_item.column_name_.ptr());
760
          LOG_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()) {
762
          ret = OB_ERR_WRONG_KEY_COLUMN;
763
          LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, sort_item.column_name_.length(), sort_item.column_name_.ptr());
764
          LOG_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()) {
766
          ret = OB_ERR_WRONG_KEY_COLUMN;
767
          LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, sort_item.column_name_.length(), sort_item.column_name_.ptr());
768
          LOG_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())) {
770
          if (!is_oracle_mode && data_column->is_func_idx_column()) {
771
            ret = OB_ERR_FUNCTIONAL_INDEX_ON_JSON_OR_GEOMETRY_FUNCTION;
772
            LOG_WARN("Cannot create a functional index on an expression that returns a JSON or GEOMETRY.",K(ret));
773
          } else {
774
            ret = OB_ERR_JSON_USED_AS_KEY;
775
            LOG_USER_ERROR(OB_ERR_JSON_USED_AS_KEY, sort_item.column_name_.length(), sort_item.column_name_.ptr());
776
            LOG_WARN("JSON column cannot be used in key specification.", K(arg.index_type_), K(ret));
777
          }
778
        } else if (data_column->is_string_type()) {
779
          int64_t length = 0;
780
          if (data_column->is_fulltext_column()) {
781
            if (!is_ctxcat_added) {
782
              length = OB_MAX_OBJECT_NAME_LENGTH;
783
              is_ctxcat_added = true;
784
            }
785
          } else if (OB_FAIL(data_column->get_byte_length(length, is_oracle_mode, false))) {
786
            LOG_WARN("fail to get byte length of column", K(ret));
787
          } else if (length < 0) {
788
            ret = OB_ERR_WRONG_KEY_COLUMN;
789
            LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, sort_item.column_name_.length(), sort_item.column_name_.ptr());
790
            LOG_WARN("byte_length of string type column is less than zero", K(length), K(ret));
791
          } else { /*do nothing*/ }
792

793
          if (OB_SUCC(ret)) {
794
            index_data_length += length;
795
            if (index_data_length > OB_MAX_USER_ROW_KEY_LENGTH) {
796
              ret = OB_ERR_TOO_LONG_KEY_LENGTH;
797
              LOG_USER_ERROR(OB_ERR_TOO_LONG_KEY_LENGTH, (OB_MAX_USER_ROW_KEY_LENGTH));
798
              LOG_WARN("index table rowkey length over max_user_row_key_length",
799
                       K(index_data_length), LITERAL_K(OB_MAX_USER_ROW_KEY_LENGTH), K(ret));
800
            }
801
          }
802
        }
803
      }
804
      if (OB_SUCC(ret) && is_mysql_func_index) {
805
        uint64_t tenant_data_version = 0;
806
        if (OB_FAIL(GET_MIN_DATA_VERSION(data_schema.get_tenant_id(), tenant_data_version))) {
807
          LOG_WARN("get tenant data version failed", K(ret));
808
        } else if (tenant_data_version < DATA_VERSION_4_2_0_0){
809
          ret = OB_NOT_SUPPORTED;
810
          LOG_WARN("tenant version is less than 4.2, functional index is not supported in mysql mode", K(ret), K(tenant_data_version));
811
          LOG_USER_ERROR(OB_NOT_SUPPORTED, "version is less than 4.2, functional index in mysql mode not supported");
812
        }
813
      }
814
    }
815

816
    if (OB_SUCC(ret)) {
817
      // column information of the global index is filled during the resolve stage
818
      const 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_);
825
      const bool need_generate_index_schema_column = (is_index_local_storage || global_index_without_column_info);
826
      schema.set_table_mode(data_schema.get_table_mode_flag());
827
      schema.set_table_state_flag(data_schema.get_table_state_flag());
828
      schema.set_duplicate_scope(data_schema.get_duplicate_scope());
829
      if (OB_FAIL(set_basic_infos(arg, data_schema, schema))) {
830
        LOG_WARN("set_basic_infos failed", K(arg), K(data_schema), K(ret));
831
      } else if (need_generate_index_schema_column
832
                 && OB_FAIL(set_index_table_columns(arg, data_schema, schema))) {
833
        LOG_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))) {
835
        LOG_WARN("set_index_table_options failed", K(arg), K(data_schema), K(ret));
836
      } else {
837
        schema.set_name_generated_type(arg.index_schema_.get_name_generated_type());
838
        LOG_INFO("finish generate index schema", K(schema));
839
      }
840
    }
841
    if (OB_FAIL(ret)) {
842
    } else if (data_schema.get_part_level() > 0
843
               && is_index_local_storage(arg.index_type_)
844
               && OB_FAIL(schema.assign_partition_schema(data_schema))) {
845
      LOG_WARN("fail to assign partition schema", K(schema), K(ret));
846
    } else if (OB_FAIL(ddl_service_.try_format_partition_schema(schema))) {
847
      LOG_WARN("fail to format partition schema", KR(ret), K(schema));
848
    } else if (generate_id) {
849
      if (OB_FAIL(ddl_service_.generate_object_id_for_partition_schema(schema))) {
850
        LOG_WARN("fail to generate object_id for partition schema", KR(ret), K(schema));
851
      } else if (OB_FAIL(ddl_service_.generate_tablet_id(schema))) {
852
        LOG_WARN("fail to fetch new table id", KR(ret), K(schema));
853
      }
854
    }
855
  }
856

857
  if (OB_SUCC(ret)) {
858
    // create index column_group after schema generate
859
    if (OB_FAIL(create_index_column_group(arg, schema))) {
860
      LOG_WARN("fail to create cg for index", K(ret));
861
    }
862
  }
863
  return ret;
864
}
865

866
int ObIndexBuilder::create_index_column_group(const obrpc::ObCreateIndexArg &arg, ObTableSchema &index_table_schema)
867
{
868
  int ret = OB_SUCCESS;
869
  uint64_t compat_version = 0;
870
  if (OB_FAIL(GET_MIN_DATA_VERSION(index_table_schema.get_tenant_id(), compat_version))) {
871
    LOG_WARN("fail to get min data version", K(ret));
872
  } else if (compat_version >= DATA_VERSION_4_3_0_0) {
873
    ObArray<uint64_t> column_ids; // not include virtual column
874
    index_table_schema.set_column_store(true);
875
    if (arg.index_cgs_.count() > 0) {
876
      index_table_schema.set_max_used_column_group_id(index_table_schema.get_max_used_column_group_id());
877
      for (int64_t i = 0; OB_SUCC(ret) && i < arg.index_cgs_.count(); ++i) {
878
        const obrpc::ObCreateIndexArg::ObIndexColumnGroupItem &cur_item = arg.index_cgs_.at(i);
879
        if (!cur_item.is_valid()) {
880
          ret = OB_INVALID_ARGUMENT;
881
          LOG_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_group
884
          ObColumnGroupSchema column_group_schema;
885
          const int64_t column_cnt = index_table_schema.get_column_count();
886
          if (OB_FAIL(column_ids.reserve(column_cnt))) {
887
            LOG_WARN("fail to reserve", KR(ret), K(column_cnt));
888
          } else {
889
            ObTableSchema::const_column_iterator tmp_begin = index_table_schema.column_begin();
890
            ObTableSchema::const_column_iterator tmp_end = index_table_schema.column_end();
891
            for (; OB_SUCC(ret) && (tmp_begin != tmp_end); tmp_begin++) {
892
              column_group_schema.reset();
893
              ObColumnSchemaV2 *column = (*tmp_begin);
894
              if (OB_FAIL(ObSchemaUtils::build_single_column_group(
895
                                          index_table_schema, column, index_table_schema.get_tenant_id(),
896
                                          index_table_schema.get_max_used_column_group_id() + 1, column_group_schema))) {
897
                LOG_WARN("fail to build single column group");
898
              } else if (column_group_schema.is_valid()) {
899
                if (OB_FAIL(index_table_schema.add_column_group(column_group_schema))) {
900
                  LOG_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 cg
902
                  if (OB_FAIL(column_ids.push_back(column->get_column_id()))) {
903
                    LOG_WARN("fail to push back", KR(ret), "column_id", column->get_column_id());
904
                  }
905
                }
906
              }
907
            }
908
          }
909

910
          if (OB_SUCC(ret)) {
911
            column_group_schema.reset();
912
            const ObColumnGroupType cg_type = arg.exist_all_column_group_ ? ObColumnGroupType::ALL_COLUMN_GROUP
913
                                              : ObColumnGroupType::ROWKEY_COLUMN_GROUP;
914
            const ObString cg_name = arg.exist_all_column_group_ ? OB_ALL_COLUMN_GROUP_NAME : OB_ROWKEY_COLUMN_GROUP_NAME;
915

916
            if (OB_FAIL(ObSchemaUtils::build_column_group(index_table_schema, index_table_schema.get_tenant_id(), cg_type, cg_name,
917
                column_ids, index_table_schema.get_max_used_column_group_id() + 1, column_group_schema))) {
918
              LOG_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))) {
920
              LOG_WARN("fail to add all type column group", KR(ret), K(column_group_schema));
921
            }
922
          }
923
        }
924
      }
925
    }
926

927
    // add default column_group
928
    if (OB_SUCC(ret)) {
929
      ObColumnGroupSchema tmp_cg;
930
      if (arg.index_cgs_.count() > 0) {
931
        column_ids.reuse(); // if exists cg node, column_ids in default_type will be empty
932
      } else {
933
        ObTableSchema::const_column_iterator tmp_begin = index_table_schema.column_begin();
934
        ObTableSchema::const_column_iterator tmp_end = index_table_schema.column_end();
935
        for (; OB_SUCC(ret) && (tmp_begin != tmp_end); tmp_begin++) {
936
          ObColumnSchemaV2 *column = (*tmp_begin);
937
          if (OB_ISNULL(column)) {
938
            ret = OB_ERR_UNEXPECTED;
939
            LOG_WARN("column should not be null", KR(ret));
940
          } else if (column->is_virtual_generated_column()) {
941
            // skip virtual column
942
          } else if (OB_FAIL(column_ids.push_back(column->get_column_id()))) {
943
            LOG_WARN("fail to push back", KR(ret), "column_id", column->get_column_id());
944
          }
945
        }
946
      }
947

948
      if (FAILEDx(ObSchemaUtils::build_column_group(index_table_schema, index_table_schema.get_tenant_id(),
949
          ObColumnGroupType::DEFAULT_COLUMN_GROUP, OB_DEFAULT_COLUMN_GROUP_NAME, column_ids,
950
          DEFAULT_TYPE_COLUMN_GROUP_ID, tmp_cg))) {
951
        LOG_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))) {
953
        LOG_WARN("fail to add default column group", KR(ret), "table_id", index_table_schema.get_table_id(),
954
                 K(arg.index_cgs_.count()), K(column_ids));
955
      }
956
    }
957
  } else if (arg.index_cgs_.count() > 0) {
958
    ret = OB_NOT_SUPPORTED;
959
    LOG_WARN("data_version not support for create index with column group", K(ret), K(compat_version));
960
    LOG_USER_ERROR(OB_NOT_SUPPORTED, "tenant data version is less than 4.3, create index with column group");
961
  }
962

963
  return ret;
964
}
965

966
int ObIndexBuilder::set_basic_infos(const ObCreateIndexArg &arg,
967
                                    const ObTableSchema &data_schema,
968
                                    ObTableSchema &schema)
969
{
970
  int ret = OB_SUCCESS;
971
  ObSchemaGetterGuard schema_guard;
972
  const ObDatabaseSchema *database = NULL;
973
  const uint64_t tenant_id = data_schema.get_tenant_id();
974
  if (!ddl_service_.is_inited()) {
975
    ret = OB_INNER_STAT_ERROR;
976
    LOG_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))) {
978
    LOG_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))) {
980
    LOG_WARN("fail to get database_schema", K(ret), K(tenant_id), "database_id", data_schema.get_database_id());
981
  } else if (OB_ISNULL(database)) {
982
    ret = OB_ERR_UNEXPECTED;
983
    LOG_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 arg
986
    ret = OB_INVALID_ARGUMENT;
987
    LOG_WARN("invalid argument", K(data_schema), K(ret));
988
  } else {
989
    ObString index_table_name = arg.index_name_;
990
    ObArenaAllocator allocator(ObModIds::OB_SCHEMA);
991
    const uint64_t table_schema_id = data_schema.get_table_id();
992
    const ObTablespaceSchema *tablespace_schema = NULL;
993
    if (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 specified
995
      ret = OB_INVALID_ARGUMENT;
996
      LOG_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(
998
               allocator, table_schema_id, arg.index_name_, index_table_name))) {
999
      LOG_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))) {
1001
      LOG_WARN("set_table_name failed", K(index_table_name), K(arg), K(ret));
1002
    } else {
1003
      schema.set_name_generated_type(arg.index_schema_.get_name_generated_type());
1004
      schema.set_table_id(arg.index_table_id_);
1005
      schema.set_table_type(USER_INDEX);
1006
      schema.set_index_type(arg.index_type_);
1007
      schema.set_index_status(arg.index_option_.index_status_);
1008
      schema.set_data_table_id(table_schema_id);
1009

1010
      // priority same with data table schema
1011
      schema.set_tenant_id(tenant_id);
1012
      schema.set_database_id(data_schema.get_database_id());
1013
      schema.set_tablegroup_id(OB_INVALID_ID);
1014
      schema.set_load_type(data_schema.get_load_type());
1015
      schema.set_def_type(data_schema.get_def_type());
1016
      if (INDEX_TYPE_NORMAL_LOCAL == arg.index_type_
1017
          || INDEX_TYPE_UNIQUE_LOCAL == arg.index_type_
1018
          || INDEX_TYPE_SPATIAL_LOCAL == arg.index_type_) {
1019
        schema.set_part_level(data_schema.get_part_level());
1020
      } else {} // partition level is filled during resolve stage for global index
1021
      schema.set_charset_type(data_schema.get_charset_type());
1022
      schema.set_collation_type(data_schema.get_collation_type());
1023
      schema.set_row_store_type(data_schema.get_row_store_type());
1024
      schema.set_store_format(data_schema.get_store_format());
1025
      schema.set_storage_format_version(data_schema.get_storage_format_version());
1026
      schema.set_tablespace_id(arg.index_schema_.get_tablespace_id());
1027
      if (OB_FAIL(schema.set_encryption_str(arg.index_schema_.get_encryption_str()))) {
1028
        LOG_WARN("fail to set set_encryption_str", K(ret), K(arg));
1029
      }
1030

1031
      if (data_schema.get_max_used_column_id() > schema.get_max_used_column_id()) {
1032
        schema.set_max_used_column_id(data_schema.get_max_used_column_id());
1033
      }
1034
      //index table will not contain auto increment column
1035
      schema.set_autoinc_column_id(0);
1036
      schema.set_progressive_merge_num(data_schema.get_progressive_merge_num());
1037
      schema.set_progressive_merge_round(data_schema.get_progressive_merge_round());
1038
      if (OB_FAIL(ret)) {
1039
      } else if (OB_FAIL(schema.set_compress_func_name(data_schema.get_compress_func_name()))) {
1040
        LOG_WARN("set_compress_func_name failed", K(data_schema));
1041
      } else if (OB_INVALID_ID != schema.get_tablespace_id()) {
1042
        if (OB_FAIL(schema_guard.get_tablespace_schema(
1043
            tenant_id, schema.get_tablespace_id(), tablespace_schema))) {
1044
          LOG_WARN("fail to get tablespace schema", K(schema), K(ret));
1045
        } else if (OB_UNLIKELY(NULL == tablespace_schema)) {
1046
          ret = OB_ERR_UNEXPECTED;
1047
          LOG_WARN("tablespace schema is null", K(ret), K(schema));
1048
        } else if (OB_FAIL(schema.set_encrypt_key(tablespace_schema->get_encrypt_key()))) {
1049
          LOG_WARN("fail to set encrypt key", K(ret), K(schema));
1050
        } else {
1051
          schema.set_master_key_id(tablespace_schema->get_master_key_id());
1052
        }
1053
      }
1054
    }
1055
  }
1056
  return ret;
1057
}
1058

1059
int ObIndexBuilder::set_index_table_columns(const ObCreateIndexArg &arg,
1060
                                            const ObTableSchema &data_schema,
1061
                                            ObTableSchema &schema)
1062
{
1063
  int ret = OB_SUCCESS;
1064
  if (!ddl_service_.is_inited()) {
1065
    ret = OB_INNER_STAT_ERROR;
1066
    LOG_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))) {
1068
    LOG_WARN("fail to set index table columns", K(ret));
1069
  } else {} // no more to do
1070
  return ret;
1071
}
1072

1073
int ObIndexBuilder::set_index_table_options(const obrpc::ObCreateIndexArg &arg,
1074
                                            const share::schema::ObTableSchema &data_schema,
1075
                                            share::schema::ObTableSchema &schema)
1076
{
1077
  int ret = OB_SUCCESS;
1078
  if (!ddl_service_.is_inited()) {
1079
    ret = OB_INNER_STAT_ERROR;
1080
    LOG_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 arg
1083
    ret = OB_INVALID_ARGUMENT;
1084
    LOG_WARN("invalid argument", K(data_schema), K(ret));
1085
  } else {
1086
    schema.set_block_size(arg.index_option_.block_size_);
1087
    schema.set_tablet_size(data_schema.get_tablet_size());
1088
    schema.set_pctfree(data_schema.get_pctfree());
1089
    schema.set_index_attributes_set(arg.index_option_.index_attributes_set_);
1090
    schema.set_is_use_bloomfilter(arg.index_option_.use_bloom_filter_);
1091
    //schema.set_progressive_merge_num(arg.index_option_.progressive_merge_num_);
1092
    schema.set_index_using_type(arg.index_using_type_);
1093
    schema.set_row_store_type(data_schema.get_row_store_type());
1094
    schema.set_store_format(data_schema.get_store_format());
1095
    // set dop for index table
1096
    schema.set_dop(arg.index_schema_.get_dop());
1097
    if (OB_FAIL(schema.set_compress_func_name(data_schema.get_compress_func_name()))) {
1098
      LOG_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_))) {
1101
      LOG_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_))) {
1103
      LOG_WARN("set parser name failed", K(ret), "parser_name", arg.index_option_.parser_name_);
1104
    }
1105
  }
1106
  return ret;
1107
}
1108

1109
bool ObIndexBuilder::is_final_index_status(const ObIndexStatus index_status) const
1110
{
1111
  return (INDEX_STATUS_AVAILABLE == index_status
1112
          || INDEX_STATUS_UNIQUE_INELIGIBLE == index_status
1113
          || is_error_index_status(index_status));
1114
}
1115

1116
}//end namespace rootserver
1117
}//end namespace oceanbase
1118

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.