oceanbase
2440 строк · 115.5 Кб
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 "rootserver/parallel_ddl/ob_create_table_helper.h"
15#include "rootserver/parallel_ddl/ob_index_name_checker.h"
16#include "rootserver/ob_index_builder.h"
17#include "rootserver/ob_lob_meta_builder.h"
18#include "rootserver/ob_lob_piece_builder.h"
19#include "rootserver/ob_table_creator.h"
20#include "rootserver/ob_balance_group_ls_stat_operator.h"
21#include "rootserver/freeze/ob_major_freeze_helper.h"
22#include "share/ob_rpc_struct.h"
23#include "share/ob_index_builder_util.h"
24#include "share/ob_debug_sync_point.h"
25#include "share/sequence/ob_sequence_option_builder.h" // ObSequenceOptionBuilder
26#include "share/schema/ob_table_sql_service.h"
27#include "share/schema/ob_security_audit_sql_service.h"
28#include "share/schema/ob_sequence_sql_service.h"
29#include "share/schema/ob_multi_version_schema_service.h"
30#include "sql/resolver/ob_resolver_utils.h"
31
32using namespace oceanbase::lib;
33using namespace oceanbase::common;
34using namespace oceanbase::share;
35using namespace oceanbase::share::schema;
36using namespace oceanbase::rootserver;
37
38uint64_t ObCreateTableHelper::MockFKParentTableNameWrapper::hash() const
39{
40uint64_t hash_ret = 0;
41common::ObCollationType cs_type = ObSchema::get_cs_type_with_cmp_mode(OB_ORIGIN_AND_INSENSITIVE);
42hash_ret = common::ObCharset::hash(cs_type, parent_database_, hash_ret);
43hash_ret = common::ObCharset::hash(cs_type, parent_table_, hash_ret);
44return hash_ret;
45}
46
47int ObCreateTableHelper::MockFKParentTableNameWrapper::hash(uint64_t &hash_val) const
48{
49hash_val = hash();
50return OB_SUCCESS;
51}
52
53bool ObCreateTableHelper::MockFKParentTableNameWrapper::operator==(const MockFKParentTableNameWrapper &rv) const
54{
55return 0 == parent_database_.case_compare(rv.parent_database_)
56&& 0 == parent_table_.case_compare(rv.parent_table_);
57}
58
59ObCreateTableHelper::ObCreateTableHelper(
60share::schema::ObMultiVersionSchemaService *schema_service,
61const uint64_t tenant_id,
62const obrpc::ObCreateTableArg &arg,
63obrpc::ObCreateTableRes &res)
64: ObDDLHelper(schema_service, tenant_id),
65arg_(arg),
66res_(res),
67replace_mock_fk_parent_table_id_(common::OB_INVALID_ID),
68new_tables_(),
69new_mock_fk_parent_tables_(),
70new_mock_fk_parent_table_map_(),
71new_audits_(),
72new_sequences_(),
73has_index_(false)
74{}
75
76ObCreateTableHelper::~ObCreateTableHelper()
77{
78}
79
80int ObCreateTableHelper::init_()
81{
82int ret = OB_SUCCESS;
83const int64_t BUCKET_NUM = 100;
84if (OB_FAIL(new_mock_fk_parent_table_map_.create(BUCKET_NUM, "MockFkPMap", "MockFkPMap"))) {
85LOG_WARN("fail to init mock fk parent table map", KR(ret));
86}
87return ret;
88}
89
90int ObCreateTableHelper::execute()
91{
92RS_TRACE(create_table_begin);
93int ret = OB_SUCCESS;
94if (OB_FAIL(check_inner_stat_())) {
95LOG_WARN("fail to check inner stat", KR(ret));
96} else if (OB_FAIL(init_())) {
97LOG_WARN("fail to init struct", KR(ret));
98} else if (OB_FAIL(start_ddl_trans_())) {
99LOG_WARN("fail to start ddl trans", KR(ret));
100} else if (OB_FAIL(lock_objects_())) {
101LOG_WARN("fail to lock objects", KR(ret));
102} else if (OB_FAIL(generate_schemas_())) {
103LOG_WARN("fail to generate schemas", KR(ret));
104} else if (OB_FAIL(calc_schema_version_cnt_())) {
105LOG_WARN("fail to calc schema version cnt", KR(ret));
106} else if (OB_FAIL(gen_task_id_and_schema_versions_())) {
107LOG_WARN("fail to gen task id and schema versions", KR(ret));
108} else if (OB_FAIL(create_schemas_())) {
109LOG_WARN("fail create schemas", KR(ret));
110} else if (OB_FAIL(create_tablets_())) {
111LOG_WARN("fail create schemas", KR(ret));
112} else if (OB_FAIL(serialize_inc_schema_dict_())) {
113LOG_WARN("fail to serialize inc schema dict", KR(ret));
114} else if (OB_FAIL(wait_ddl_trans_())) {
115LOG_WARN("fail to wait ddl trans", KR(ret));
116} else if (OB_FAIL(add_index_name_to_cache_())) {
117LOG_WARN("fail to add index name to cache", KR(ret));
118}
119
120const bool commit = OB_SUCC(ret);
121if (OB_FAIL(end_ddl_trans_(ret))) { // won't overwrite ret
122LOG_WARN("fail to end ddl trans", KR(ret));
123if (commit && has_index_) {
124// Because index name is added to cache before trans commit,
125// it will remain garbage in cache when trans commit failed and false alarm will occur.
126//
127// To solve this problem:
128// 1. check_index_name_exist() will double check by inner_sql and erase garbage if index name conflicts.
129// 2. (Fully unnecessary) clean up index name cache when trans commit failed.
130int tmp_ret = OB_SUCCESS;
131if (OB_ISNULL(ddl_service_)) {
132tmp_ret = OB_ERR_UNEXPECTED;
133LOG_WARN("ddl_service_ is null", KR(tmp_ret));
134} else if (OB_TMP_FAIL(ddl_service_->get_index_name_checker().reset_cache(tenant_id_))) {
135LOG_ERROR("fail to reset cache", K(ret), KR(tmp_ret), K_(tenant_id));
136}
137}
138}
139
140if (OB_SUCC(ret)) {
141auto *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
142int64_t last_schema_version = OB_INVALID_VERSION;
143int64_t end_schema_version = OB_INVALID_VERSION;
144if (OB_UNLIKELY(new_tables_.count() <= 0)) {
145ret = OB_ERR_UNEXPECTED;
146LOG_WARN("table cnt is invalid", KR(ret));
147} else if (OB_ISNULL(tsi_generator)) {
148ret = OB_ERR_UNEXPECTED;
149LOG_WARN("tsi schema version generator is null", KR(ret));
150} else if (OB_FAIL(tsi_generator->get_current_version(last_schema_version))) {
151LOG_WARN("fail to get end version", KR(ret), K_(tenant_id), K_(arg));
152} else if (OB_FAIL(tsi_generator->get_end_version(end_schema_version))) {
153LOG_WARN("fail to get end version", KR(ret), K_(tenant_id), K_(arg));
154} else if (OB_UNLIKELY(last_schema_version != end_schema_version)) {
155ret = OB_ERR_UNEXPECTED;
156LOG_WARN("too much schema versions may be allocated", KR(ret), KPC(tsi_generator));
157} else {
158res_.table_id_ = new_tables_.at(0).get_table_id();
159res_.schema_version_ = last_schema_version;
160}
161}
162
163if (OB_ERR_TABLE_EXIST == ret) {
164const ObTableSchema &table = arg_.schema_;
165//create table xx if not exist (...)
166if (arg_.if_not_exist_) {
167ret = OB_SUCCESS;
168LOG_INFO("table is exist, no need to create again",
169"tenant_id", table.get_tenant_id(),
170"database_id", table.get_database_id(),
171"table_name", table.get_table_name());
172} else {
173LOG_WARN("table is exist, cannot create it twice", KR(ret),
174"tenant_id", table.get_tenant_id(),
175"database_id", table.get_database_id(),
176"table_name", table.get_table_name());
177LOG_USER_ERROR(OB_ERR_TABLE_EXIST,
178table.get_table_name_str().length(),
179table.get_table_name_str().ptr());
180}
181}
182
183RS_TRACE(create_table_end);
184FORCE_PRINT_TRACE(THE_RS_TRACE, "[parallel create table]");
185return ret;
186}
187
188int ObCreateTableHelper::lock_objects_()
189{
190int ret = OB_SUCCESS;
191if (OB_FAIL(check_inner_stat_())) {
192LOG_WARN("fail to check inner stat", KR(ret));
193}
194// 1. lock database name first
195if (FAILEDx(lock_database_by_obj_name_())) {
196LOG_WARN("fail to lock databases by obj name", KR(ret), K_(tenant_id));
197}
198// 2. lock objects by name
199if (FAILEDx(lock_objects_by_name_())) {
200LOG_WARN("fail to lock objects by name", KR(ret), K_(tenant_id));
201}
202DEBUG_SYNC(AFTER_PARALLEL_DDL_LOCK_OBJ_BY_NAME);
203// 3. prefetch schemas
204if (FAILEDx(prefetch_schemas_())) {
205LOG_WARN("fail to prefech schemas", KR(ret), K_(tenant_id));
206}
207// 4. lock objects by id
208if (FAILEDx(lock_objects_by_id_())) {
209LOG_WARN("fail to lock objects by name", KR(ret), K_(tenant_id));
210}
211// 5. lock objects by id after related objects are locked.
212if (FAILEDx(post_lock_objects_by_id_())) {
213LOG_WARN("fail to lock objects by id in post", KR(ret));
214}
215// 6. check ddl conflict
216if (FAILEDx(check_ddl_conflict_())) {
217LOG_WARN("fail to check ddl confict", KR(ret));
218}
219RS_TRACE(lock_objects);
220return ret;
221}
222
223// Lock ddl related database by name
224// 1. database (S)
225// - to create table
226// 2. parent database (S)
227// - in foreign key
228int ObCreateTableHelper::lock_database_by_obj_name_()
229{
230int ret = OB_SUCCESS;
231const int64_t start_ts = ObTimeUtility::current_time();
232if (OB_FAIL(check_inner_stat_())) {
233LOG_WARN("fail to check inner stat", KR(ret));
234} else {
235const ObString &database_name = arg_.db_name_;
236if (OB_FAIL(add_lock_object_by_database_name_(database_name, transaction::tablelock::SHARE))) {
237LOG_WARN("fail to lock database by name", KR(ret), K_(tenant_id), K(database_name));
238}
239
240for (int64_t i = 0; OB_SUCC(ret) && i < arg_.foreign_key_arg_list_.count(); i++) {
241const obrpc::ObCreateForeignKeyArg &foreign_key_arg = arg_.foreign_key_arg_list_.at(i);
242const ObString &parent_database_name = foreign_key_arg.parent_database_;
243if (OB_FAIL(add_lock_object_by_database_name_(parent_database_name, transaction::tablelock::SHARE))) {
244LOG_WARN("fail to lock database by name", KR(ret), K_(tenant_id), K(parent_database_name));
245}
246} // end for
247
248if (FAILEDx(lock_databases_by_name_())) {
249LOG_WARN("fail to lock databases by name", KR(ret), K_(tenant_id));
250}
251}
252const int64_t cost_ts = ObTimeUtility::current_time() - start_ts;
253LOG_INFO("lock databases", KR(ret), K_(tenant_id), K(cost_ts));
254return ret;
255}
256
257// Lock related objects' name for create table (`X` for EXCLUSIVE, `S` for SHARE):
258// 1. table (X)
259// 2. index (X)
260// - in oracle mode
261// 3. constraint (X)
262// 4. foreign key (X)
263// 5. tablegroup (S)
264// 6. sequence (X)
265// - Operation to lock sequence name will be delayed to generate_schemas_() stage.
266// 7. parent table (X)
267// 8. mock fk parent table(X)
268int ObCreateTableHelper::lock_objects_by_name_()
269{
270int ret = OB_SUCCESS;
271bool is_oracle_mode = false;
272const int64_t start_ts = ObTimeUtility::current_time();
273if (OB_FAIL(check_inner_stat_())) {
274LOG_WARN("fail to check inner stat", KR(ret));
275} else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id(
276tenant_id_, is_oracle_mode))) {
277LOG_WARN("fail to check is oracle mode", KR(ret));
278} else {
279const ObString &database_name = arg_.db_name_;
280const ObTableSchema &table = arg_.schema_;
281
282// 1. table
283const ObString &table_name = table.get_table_name();
284if (OB_FAIL(add_lock_object_by_name_(database_name, table_name,
285share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
286LOG_WARN("fail to lock object by table name", KR(ret), K_(tenant_id), K(database_name), K(table_name));
287}
288
289// 2. index (oracle) :
290// 1) oracle mode: index name is unique in user(database)
291// 2) mysql mode: index name is unique in table
292if (OB_SUCC(ret) && is_oracle_mode) {
293for (int64_t i = 0; OB_SUCC(ret) && i < arg_.index_arg_list_.size(); i++) {
294const ObString &index_name = arg_.index_arg_list_.at(i).index_name_; // original index name
295if (OB_FAIL(add_lock_object_by_name_(database_name, index_name,
296share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
297LOG_WARN("fail to lock object by index name", KR(ret), K_(tenant_id), K(database_name), K(index_name));
298}
299} // end for
300}
301
302// 3. constraint
303for (int64_t i = 0; OB_SUCC(ret) && i < arg_.constraint_list_.count(); i++) {
304const ObString &cst_name = arg_.constraint_list_.at(i).get_constraint_name_str();
305if (OB_FAIL(add_lock_object_by_name_(database_name, cst_name,
306share::schema::CONSTRAINT_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
307LOG_WARN("fail to lock object by constraint name", KR(ret), K_(tenant_id), K(database_name), K(cst_name));
308}
309} // end for
310
311// 4. foreign key
312for (int64_t i = 0; OB_SUCC(ret) && i < arg_.foreign_key_arg_list_.count(); i++) {
313const ObString &fk_name = arg_.foreign_key_arg_list_.at(i).foreign_key_name_;
314if (OB_FAIL(add_lock_object_by_name_(database_name, fk_name,
315share::schema::FOREIGN_KEY_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
316LOG_WARN("fail to lock object by foreign key name", KR(ret), K_(tenant_id), K(database_name), K(fk_name));
317}
318} // end for
319
320// 5. tablegroup
321const ObString &tablegroup_name = arg_.schema_.get_tablegroup_name();
322if (OB_SUCC(ret) && !tablegroup_name.empty()) {
323ObString mock_database_name(OB_SYS_DATABASE_NAME); // consider that tablegroup may across databases.
324if (OB_FAIL(add_lock_object_by_name_(mock_database_name, tablegroup_name,
325share::schema::TABLEGROUP_SCHEMA, transaction::tablelock::SHARE))) {
326LOG_WARN("fail to lock object by tablegroup name", KR(ret), K_(tenant_id), K(database_name), K(tablegroup_name));
327}
328}
329
330// 6. sequence
331// - will be delayed to generate_schemas_() stage.
332
333// 7. parent table/mock fk parent table
334// - here we don't distinguish between table and mocked table.
335for (int64_t i = 0; OB_SUCC(ret) && i < arg_.foreign_key_arg_list_.count(); i++) {
336const obrpc::ObCreateForeignKeyArg &foreign_key_arg = arg_.foreign_key_arg_list_.at(i);
337const ObString &parent_database_name = foreign_key_arg.parent_database_;
338const ObString &parent_table_name = foreign_key_arg.parent_table_;
339if (OB_FAIL(add_lock_object_by_name_(parent_database_name, parent_table_name,
340share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
341LOG_WARN("fail to lock object by parent table", KR(ret),
342K_(tenant_id), K(parent_database_name), K(parent_table_name));
343}
344} // end for
345
346if (FAILEDx(lock_existed_objects_by_name_())) {
347LOG_WARN("fail to lock objects by name", KR(ret), K_(tenant_id));
348}
349}
350const int64_t cost_ts = ObTimeUtility::current_time() - start_ts;
351LOG_INFO("lock objects by name", KR(ret), K_(tenant_id), K(cost_ts));
352return ret;
353}
354
355// lock related objects' id for create table (`X` for EXCLUSIVE, `S` for SHARE):
356// 1. tablegroup (S)
357// 2. audit (S)
358// - add share lock for OB_AUDIT_MOCK_USER_ID
359// 3. tablespace (S)
360// 4. parent table (X)
361// 5. mock fk parent table(X)
362// 6. udt (S)
363
364// Specially, when table name is duplicated with existed mock fk parent table name,
365// we may replace mock fk parent table with new table and modified related foreign key/child table.
366// So after lock table/mock fk parent table by name, we should lock all foreign keys/child tables
367// from mock fk parent table by id.
368//
369// 6. mock fk parent table for replacement (X)
370int ObCreateTableHelper::lock_objects_by_id_()
371{
372int ret = OB_SUCCESS;
373const int64_t start_ts = ObTimeUtility::current_time();
374const ObTableSchema &table = arg_.schema_;
375if (OB_FAIL(check_inner_stat_())) {
376LOG_WARN("fail to check inner stat", KR(ret));
377}
378// 1. tablegroup
379const uint64_t tablegroup_id = table.get_tablegroup_id();
380if (OB_SUCC(ret) && OB_INVALID_ID != tablegroup_id) {
381if (OB_FAIL(add_lock_object_by_id_(tablegroup_id, // filled in set_tablegroup_id_()
382share::schema::TABLEGROUP_SCHEMA, transaction::tablelock::SHARE))) {
383LOG_WARN("fail to lock tablegroup_id", KR(ret), K_(tenant_id), K(tablegroup_id));
384}
385}
386// 2. audit (lock by user_id)
387if (OB_SUCC(ret)) {
388if (OB_FAIL(add_lock_object_by_id_(OB_AUDIT_MOCK_USER_ID,
389share::schema::USER_SCHEMA, transaction::tablelock::SHARE))) {
390LOG_WARN("fail to lock user_id", KR(ret), K_(tenant_id), "user_id", OB_AUDIT_MOCK_USER_ID);
391}
392}
393// 3. tablespace
394const uint64_t tablespace_id = arg_.schema_.get_tablespace_id();
395if (OB_SUCC(ret) && OB_INVALID_ID != tablespace_id) {
396if (OB_FAIL(add_lock_object_by_id_(tablespace_id,
397share::schema::TABLESPACE_SCHEMA, transaction::tablelock::SHARE))) {
398LOG_WARN("fail to lock tablespace_id", KR(ret), K_(tenant_id), K(tablespace_id));
399}
400}
401// 4. parent table/mock fk parent table
402for (int64_t i = 0; OB_SUCC(ret) && i < arg_.foreign_key_arg_list_.count(); i++) {
403const obrpc::ObCreateForeignKeyArg &foreign_key_arg = arg_.foreign_key_arg_list_.at(i);
404if (OB_INVALID_ID != foreign_key_arg.parent_table_id_) { // filled in check_and_set_parent_table_id_()
405if (OB_FAIL(add_lock_object_by_id_(foreign_key_arg.parent_table_id_,
406share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
407LOG_WARN("fail to lock parent table id",
408KR(ret), K_(tenant_id), "parent_table_id", foreign_key_arg.parent_table_id_);
409}
410}
411} // end for
412// 5. lock mock fk parent table for replacement
413if (OB_SUCC(ret)) {
414const ObString &table_name = table.get_table_name();
415const uint64_t database_id = table.get_database_id();
416//TODO(yanmu.ztl): this interface has poor performance.
417if (OB_FAIL(latest_schema_guard_.get_mock_fk_parent_table_id(
418database_id, table_name, replace_mock_fk_parent_table_id_))) {
419LOG_WARN("fail to ge mock fk parent table id",
420KR(ret), K_(tenant_id), K(database_id), K(table_name));
421} else if (OB_INVALID_ID != replace_mock_fk_parent_table_id_) {
422// has existed mock fk parent table
423if (OB_FAIL(add_lock_object_by_id_(replace_mock_fk_parent_table_id_,
424share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
425LOG_WARN("fail to lock mock fk parent table id",
426KR(ret), K_(tenant_id), K_(replace_mock_fk_parent_table_id));
427}
428}
429}
430// 6. udt
431if (OB_SUCC(ret)) {
432ObTableSchema::const_column_iterator begin = table.column_begin();
433ObTableSchema::const_column_iterator end = table.column_end();
434ObSchemaGetterGuard guard;
435if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, guard))) {
436LOG_WARN("fail to get schema guard", KR(ret));
437}
438for (; OB_SUCC(ret) && begin != end; begin++) {
439ObColumnSchemaV2 *col = (*begin);
440if (OB_ISNULL(col)) {
441ret = OB_ERR_UNEXPECTED;
442LOG_WARN("get column schema failed", KR(ret));
443} else if (col->is_extend()) {
444const uint64_t udt_id = col->get_sub_data_type();
445if (is_inner_object_id(udt_id) && !is_sys_tenant(tenant_id_)) {
446// can't add object lock across tenant, assumed that sys inner udt won't be changed.
447const ObUDTTypeInfo *udt_info = NULL;
448if (OB_FAIL(guard.get_udt_info(OB_SYS_TENANT_ID, udt_id, udt_info))) {
449LOG_WARN("fail to get udt info", KR(ret), K(udt_id));
450} else if (OB_ISNULL(udt_info)) {
451ret = OB_ERR_PARALLEL_DDL_CONFLICT;
452LOG_WARN("inner udt not found", KR(ret), K(udt_id));
453}
454} else if (OB_FAIL(add_lock_object_by_id_(udt_id,
455share::schema::UDT_SCHEMA, transaction::tablelock::SHARE))) {
456LOG_WARN("fail to lock udt id", KR(ret), K_(tenant_id), K(udt_id));
457}
458}
459} // end for
460}
461
462if (FAILEDx(lock_existed_objects_by_id_())) {
463LOG_WARN("fail to lock objects by id", KR(ret));
464}
465const int64_t cost_ts = ObTimeUtility::current_time() - start_ts;
466LOG_INFO("lock objects by id", KR(ret), K_(tenant_id), K(cost_ts));
467return ret;
468}
469
470// tablegroup/mock fk parent table for replacement are locked by id in lock_objects_by_id_() first.
471// 1. foreign key (X)
472// - from mock fk parent table
473// 2. child table (X)
474// - from mock fk parent table
475// 3. primary table (S)
476// - in tablegroup
477//
478// TODO:(yanmu.ztl)
479// small timeout should be used here to avoid deadlock problem
480// since we have already locked some objects by id.
481int ObCreateTableHelper::post_lock_objects_by_id_()
482{
483int ret = OB_SUCCESS;
484const int64_t start_ts = ObTimeUtility::current_time();
485if (OB_FAIL(check_inner_stat_())) {
486LOG_WARN("fail to check inner stat", KR(ret));
487}
488// lock foreign key/child table if need replace existed mock fk parent table.
489if (OB_SUCC(ret) && OB_INVALID_ID != replace_mock_fk_parent_table_id_) {
490const ObMockFKParentTableSchema *mock_fk_parent_table = NULL;
491if (OB_FAIL(latest_schema_guard_.get_mock_fk_parent_table_schema(
492replace_mock_fk_parent_table_id_, mock_fk_parent_table))) {
493LOG_WARN("fail to get mock fk parent table schema",
494KR(ret), K_(tenant_id), K_(replace_mock_fk_parent_table_id));
495} else if (OB_ISNULL(mock_fk_parent_table)) {
496ret = OB_ERR_PARALLEL_DDL_CONFLICT;
497LOG_WARN("mock fk parent table not exist, ddl need retry",
498KR(ret), K_(tenant_id), K_(replace_mock_fk_parent_table_id));
499} else {
500for (int64_t i = 0; OB_SUCC(ret) && i < mock_fk_parent_table->get_foreign_key_infos().count(); i++) {
501const ObForeignKeyInfo &foreign_key = mock_fk_parent_table->get_foreign_key_infos().at(i);
502const uint64_t foreign_key_id = foreign_key.foreign_key_id_;
503const uint64_t child_table_id = foreign_key.child_table_id_;
504if (OB_FAIL(add_lock_object_by_id_(child_table_id,
505share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
506LOG_WARN("fail to lock child table",
507KR(ret), K_(tenant_id), K(child_table_id));
508} else if (OB_FAIL(add_lock_object_by_id_(foreign_key_id,
509share::schema::FOREIGN_KEY_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
510LOG_WARN("fail to lock foreign key",
511KR(ret), K_(tenant_id), K(foreign_key_id));
512}
513} // end for
514}
515}
516
517// TODO:(yanmu.ztl) lock primary table in tablegroup
518if (OB_SUCC(ret) && OB_INVALID_ID != arg_.schema_.get_tablegroup_id()) {
519}
520
521if (FAILEDx(lock_existed_objects_by_id_())) {
522LOG_WARN("fail to lock objects by id", KR(ret));
523}
524const int64_t cost_ts = ObTimeUtility::current_time() - start_ts;
525LOG_INFO("lock objects by id in post", KR(ret), K_(tenant_id), K(cost_ts));
526return ret;
527}
528
529int ObCreateTableHelper::check_ddl_conflict_()
530{
531int ret = OB_SUCCESS;
532const int64_t start_ts = ObTimeUtility::current_time();
533if (OB_FAIL(check_inner_stat_())) {
534LOG_WARN("fail to check inner stat", KR(ret));
535} else if (!arg_.is_need_check_based_schema_objects()) {
536// skip
537} else {
538ObArray<uint64_t> parent_table_ids;
539ObArray<uint64_t> mock_fk_parent_table_ids;
540// check schema object infos are all existed.
541for (int64_t i = 0; OB_SUCC(ret) && (i < arg_.based_schema_object_infos_.count()); ++i) {
542const ObBasedSchemaObjectInfo &info = arg_.based_schema_object_infos_.at(i);
543if (MOCK_FK_PARENT_TABLE_SCHEMA == info.schema_type_
544|| TABLE_SCHEMA == info.schema_type_) {
545bool find = false;
546for (int64_t j = 0; OB_SUCC(ret) && !find && j < arg_.foreign_key_arg_list_.count(); j++) {
547const obrpc::ObCreateForeignKeyArg &foreign_key_arg = arg_.foreign_key_arg_list_.at(j);
548if (MOCK_FK_PARENT_TABLE_SCHEMA == info.schema_type_
549&& foreign_key_arg.is_parent_table_mock_
550&& info.schema_id_ == foreign_key_arg.parent_table_id_) {
551find = true;
552} else if (TABLE_SCHEMA == info.schema_type_
553&& !foreign_key_arg.is_parent_table_mock_
554&& info.schema_id_ == foreign_key_arg.parent_table_id_) {
555find = true;
556}
557} // end for
558if (OB_SUCC(ret) && !find) {
559ret = OB_ERR_PARALLEL_DDL_CONFLICT;
560LOG_WARN("parent table may change, ddl need retry",
561KR(ret), K_(tenant_id), K(info));
562}
563if (OB_FAIL(ret)) {
564} else if (MOCK_FK_PARENT_TABLE_SCHEMA == info.schema_type_) {
565if (!has_exist_in_array(mock_fk_parent_table_ids, info.schema_id_)
566&& OB_FAIL(mock_fk_parent_table_ids.push_back(info.schema_id_))) {
567LOG_WARN("fail to push back mock fk parent table id", KR(ret), K(info));
568}
569} else if (TABLE_SCHEMA == info.schema_type_) {
570if (!has_exist_in_array(parent_table_ids, info.schema_id_)
571&& OB_FAIL(parent_table_ids.push_back(info.schema_id_))) {
572LOG_WARN("fail to push back parent table id", KR(ret), K(info));
573}
574}
575}
576} // end for
577
578ObArray<ObSchemaIdVersion> parent_table_versions;
579if (OB_SUCC(ret) && parent_table_ids.count() > 0) {
580if (OB_FAIL(parent_table_versions.reserve(parent_table_ids.count()))) {
581LOG_WARN("fail to reserve array", KR(ret));
582} else if (OB_FAIL(latest_schema_guard_.get_table_schema_versions(
583parent_table_ids, parent_table_versions))) {
584LOG_WARN("fail to get table schema versions", KR(ret));
585} else if (parent_table_ids.count() != parent_table_versions.count()) {
586ret = OB_ERR_PARALLEL_DDL_CONFLICT;
587LOG_WARN("parent table may be deleted, ddl need retry",
588KR(ret), K_(tenant_id), "base_objs_cnt", parent_table_ids.count(),
589"fetch_cnt", parent_table_versions.count());
590}
591}
592
593ObArray<ObSchemaIdVersion> mock_fk_parent_table_versions;
594if (OB_SUCC(ret) && mock_fk_parent_table_ids.count() > 0) {
595if (OB_FAIL(mock_fk_parent_table_versions.reserve(mock_fk_parent_table_ids.count()))) {
596LOG_WARN("fail to reserve array", KR(ret));
597} else if (OB_FAIL(latest_schema_guard_.get_mock_fk_parent_table_schema_versions(
598mock_fk_parent_table_ids, mock_fk_parent_table_versions))) {
599LOG_WARN("fail to get table schema versions", KR(ret));
600} else if (mock_fk_parent_table_ids.count() != mock_fk_parent_table_versions.count()) {
601ret = OB_ERR_PARALLEL_DDL_CONFLICT;
602LOG_WARN("mock fk parent table may be deleted, ddl need retry",
603KR(ret), K_(tenant_id), "base_objs_cnt", mock_fk_parent_table_ids.count(),
604"fetch_cnt", mock_fk_parent_table_versions.count());
605}
606}
607
608if (OB_SUCC(ret)) {
609for (int64_t i = 0; OB_SUCC(ret) && (i < arg_.based_schema_object_infos_.count()); ++i) {
610const ObBasedSchemaObjectInfo &info = arg_.based_schema_object_infos_.at(i);
611if (MOCK_FK_PARENT_TABLE_SCHEMA == info.schema_type_
612|| TABLE_SCHEMA == info.schema_type_) {
613bool find = false;
614for (int64_t j = 0; OB_SUCC(ret) && !find && j < parent_table_versions.count(); j++) {
615const ObSchemaIdVersion &version = parent_table_versions.at(j);
616if (version.get_schema_id() == info.schema_id_) {
617find = true;
618if (version.get_schema_version() != info.schema_version_) {
619ret = OB_ERR_PARALLEL_DDL_CONFLICT;
620LOG_WARN("parent table may be changed, ddl need retry",
621KR(ret), K_(tenant_id), K(info), K(version));
622}
623}
624} // end for
625for (int64_t j = 0; OB_SUCC(ret) && !find && j < mock_fk_parent_table_versions.count(); j++) {
626const ObSchemaIdVersion &version = mock_fk_parent_table_versions.at(j);
627if (version.get_schema_id() == info.schema_id_) {
628find = true;
629if (version.get_schema_version() != info.schema_version_) {
630ret = OB_ERR_PARALLEL_DDL_CONFLICT;
631LOG_WARN("mock fk parent table may be changed, ddl need retry",
632KR(ret), K_(tenant_id), K(info), K(version));
633}
634}
635} // end for
636if (OB_SUCC(ret) && !find) {
637ret = OB_ERR_PARALLEL_DDL_CONFLICT;
638LOG_WARN("parent table may be deleted, ddl need retry",
639KR(ret), K_(tenant_id), K(info));
640}
641}
642} // end for
643}
644
645// for replace mock fk parent table:
646// 1. check child tables still exist.
647// 2. cache child tables' schema before gen_task_id_and_schema_versions_() to increase throughput.
648if (OB_SUCC(ret) && OB_INVALID_ID != replace_mock_fk_parent_table_id_) {
649const ObMockFKParentTableSchema *mock_fk_parent_table = NULL;
650if (OB_FAIL(latest_schema_guard_.get_mock_fk_parent_table_schema(
651replace_mock_fk_parent_table_id_, mock_fk_parent_table))) {
652LOG_WARN("fail to get mock fk parent table schema",
653KR(ret), K_(tenant_id), K_(replace_mock_fk_parent_table_id));
654} else if (OB_ISNULL(mock_fk_parent_table)) {
655ret = OB_ERR_UNEXPECTED;
656LOG_WARN("mock fk parent table not exist after lock obj",
657KR(ret), K_(tenant_id), K_(replace_mock_fk_parent_table_id));
658}
659for (int64_t i = 0; OB_SUCC(ret) && i < mock_fk_parent_table->get_foreign_key_infos().count(); i++) {
660const ObForeignKeyInfo &foreign_key = mock_fk_parent_table->get_foreign_key_infos().at(i);
661const uint64_t child_table_id = foreign_key.child_table_id_;
662const ObTableSchema *child_table = NULL;
663if (OB_FAIL(latest_schema_guard_.get_table_schema(child_table_id, child_table))) {
664LOG_WARN("fail to get table schema", KR(ret), K_(tenant_id), K(child_table_id));
665} else if (OB_ISNULL(child_table)) {
666ret = OB_ERR_PARALLEL_DDL_CONFLICT;
667LOG_WARN("child table is not exist", KR(ret), K_(tenant_id), K(child_table_id));
668}
669} // end for
670}
671
672// check udt exist & not changed
673for (int64_t i = 0; OB_SUCC(ret) && (i < arg_.based_schema_object_infos_.count()); ++i) {
674const ObBasedSchemaObjectInfo &info = arg_.based_schema_object_infos_.at(i);
675if (UDT_SCHEMA == info.schema_type_) {
676const uint64_t udt_id = info.schema_id_;
677const ObUDTTypeInfo *udt_info = NULL;
678if (is_inner_object_id(udt_id) && !is_sys_tenant(tenant_id_)) {
679// can't add object lock across tenant, assumed that sys inner udt won't be changed.
680} else if (OB_FAIL(latest_schema_guard_.get_udt_info(udt_id, udt_info))) {
681LOG_WARN("fail to get udt info", KR(ret), K_(tenant_id), K(udt_id), K(info));
682} else if (OB_ISNULL(udt_info)) {
683ret = OB_ERR_PARALLEL_DDL_CONFLICT;
684LOG_WARN("udt doesn't exist", KR(ret), K_(tenant_id), K(udt_id));
685} else if (udt_info->get_schema_version() != info.schema_version_) {
686ret = OB_ERR_PARALLEL_DDL_CONFLICT;
687LOG_WARN("udt changed", KR(ret), K(info), KPC(udt_info));
688}
689}
690} // end for
691}
692const int64_t cost_ts = ObTimeUtility::current_time() - start_ts;
693LOG_INFO("check ddl confict", KR(ret), K_(tenant_id), K(cost_ts));
694return ret;
695}
696
697int ObCreateTableHelper::prefetch_schemas_()
698{
699int ret = OB_SUCCESS;
700const int64_t start_ts = ObTimeUtility::current_time();
701if (OB_FAIL(check_inner_stat_())) {
702LOG_WARN("fail to check inner stat", KR(ret));
703} else if (OB_FAIL(check_and_set_database_id_())) {
704LOG_WARN("fail to check and set database id", KR(ret));
705} else if (OB_FAIL(check_table_name_())) {
706LOG_WARN("fail to check table name", KR(ret));
707} else if (OB_FAIL(set_tablegroup_id_())) {
708LOG_WARN("fail to set tablegroup id", KR(ret));
709} else if (OB_FAIL(check_and_set_parent_table_id_())) {
710LOG_WARN("fail to check and set parent table id", KR(ret));
711}
712const int64_t cost_ts = ObTimeUtility::current_time() - start_ts;
713LOG_INFO("prefetch schemas", KR(ret), K_(tenant_id), K(cost_ts));
714return ret;
715}
716
717int ObCreateTableHelper::check_and_set_database_id_()
718{
719int ret = OB_SUCCESS;
720const ObString &database_name = arg_.db_name_;
721uint64_t database_id = OB_INVALID_ID;
722const ObDatabaseSchema *database_schema = NULL;
723if (OB_FAIL(check_inner_stat_())) {
724LOG_WARN("fail to check inner stat", KR(ret));
725} else if (OB_FAIL(latest_schema_guard_.get_database_id(database_name, database_id))) {
726LOG_WARN("fail to get database id", KR(ret), K_(tenant_id), K(database_name));
727} else if (OB_UNLIKELY(OB_INVALID_ID == database_id)) {
728ret = OB_ERR_BAD_DATABASE;
729LOG_WARN("database not exist", KR(ret), K_(tenant_id), K(database_name));
730LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr());
731} else if (OB_FAIL(latest_schema_guard_.get_database_schema(database_id, database_schema))) {
732LOG_WARN("fail to get database schema", KR(ret), K_(tenant_id), K(database_id), K(database_name));
733} else if (OB_ISNULL(database_schema)) {
734ret = OB_ERR_BAD_DATABASE;
735LOG_WARN("database not exist", KR(ret), K_(tenant_id), K(database_id), K(database_name));
736LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr());
737} else if (!arg_.is_inner_ && database_schema->is_in_recyclebin()) {
738ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
739LOG_WARN("Can't not create table in database which is in recyclebin",
740KR(ret), K_(tenant_id), K(database_id), K(database_name));
741} else {
742(void) const_cast<ObTableSchema&>(arg_.schema_).set_database_id(database_id);
743}
744return ret;
745}
746
747int ObCreateTableHelper::check_table_name_()
748{
749int ret = OB_SUCCESS;
750bool is_oracle_mode = false;
751const ObTableSchema &table = arg_.schema_;
752const uint64_t database_id = table.get_database_id();
753const ObString &table_name = table.get_table_name();
754// session_id is > 0 when table is mysql tmp table or creating ctas table.
755const uint64_t session_id = table.get_session_id();
756bool if_not_exist = arg_.if_not_exist_;
757if (OB_FAIL(check_inner_stat_())) {
758LOG_WARN("fail to check inner stat", KR(ret));
759} else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id(tenant_id_, is_oracle_mode))) {
760LOG_WARN("fail to check is oracle mode", KR(ret));
761} else if (is_oracle_mode) {
762if (OB_FAIL(latest_schema_guard_.check_oracle_object_exist(
763database_id, session_id, table_name, TABLE_SCHEMA,
764INVALID_ROUTINE_TYPE, if_not_exist))) {
765LOG_WARN("fail to check oracle object exist", KR(ret),
766K(database_id), K(session_id), K(table_name), K(if_not_exist));
767}
768} else {
769uint64_t synonym_id = OB_INVALID_ID;
770uint64_t table_id = OB_INVALID_ID;
771ObTableType table_type = MAX_TABLE_TYPE;
772int64_t schema_version = OB_INVALID_VERSION;
773if (OB_FAIL(latest_schema_guard_.get_synonym_id(database_id, table_name, synonym_id))) {
774LOG_WARN("fail to get synonymn_id", KR(ret), K_(tenant_id), K(database_id), K(table_name));
775} else if (OB_UNLIKELY(OB_INVALID_ID != synonym_id)) {
776ret = OB_ERR_EXIST_OBJECT;
777LOG_WARN("Name is already used by an existing object",
778KR(ret), K_(tenant_id), K(database_id), K(table_name), K(synonym_id));
779} else if (OB_FAIL(latest_schema_guard_.get_table_id(
780database_id, session_id, table_name, table_id, table_type, schema_version))) {
781LOG_WARN("fail to get table_id", KR(ret), K_(tenant_id), K(database_id), K(session_id), K(table_name));
782} else if (OB_UNLIKELY(OB_INVALID_ID != table_id)) {
783if (table.is_mysql_tmp_table()
784&& !(is_inner_table(table_id) || is_mysql_tmp_table(table_type))) {
785// mysql tmp table name is only duplicated in the same session.
786} else {
787// Raise error here to skip the following steps,
788// ret will be overwrite if if_not_exist_ is true before rpc returns.
789ret = OB_ERR_TABLE_EXIST;
790res_.table_id_ = table_id;
791res_.schema_version_ = schema_version;
792LOG_WARN("table exist", KR(ret), K_(tenant_id), K(database_id),
793K(session_id), K(table_name), K(table_id), K(schema_version),
794K(arg_.if_not_exist_));
795}
796}
797}
798return ret;
799}
800
801int ObCreateTableHelper::set_tablegroup_id_()
802{
803int ret = OB_SUCCESS;
804const ObTableSchema &table = arg_.schema_;
805const ObString &tablegroup_name = table.get_tablegroup_name();
806uint64_t tablegroup_id = OB_INVALID_ID;
807if (OB_FAIL(check_inner_stat_())) {
808LOG_WARN("fail to check inner stat", KR(ret));
809} else if (tablegroup_name.empty()) {
810if (table.has_partition()) {
811// try use default tablegroup id
812const uint64_t database_id = table.get_database_id();
813const ObDatabaseSchema *database_schema = NULL;
814if (OB_FAIL(latest_schema_guard_.get_database_schema(database_id, database_schema))) {
815LOG_WARN("fail to get database schema", KR(ret), K_(tenant_id), K(database_id));
816} else if (OB_ISNULL(database_schema)) {
817ret = OB_ERR_BAD_DATABASE;
818LOG_WARN("database not exist", KR(ret), K_(tenant_id), K(database_id));
819} else {
820tablegroup_id = database_schema->get_default_tablegroup_id();
821}
822
823if (OB_SUCC(ret) && OB_INVALID_ID == tablegroup_id) {
824const ObTenantSchema *tenant_schema = NULL;
825if (OB_FAIL(latest_schema_guard_.get_tenant_schema(tenant_id_, tenant_schema))) {
826LOG_WARN("fail to get tenant schema", KR(ret), K_(tenant_id));
827} else if (OB_ISNULL(tenant_schema)) {
828ret = OB_TENANT_NOT_EXIST;
829LOG_WARN("tenant not exist", KR(ret), K_(tenant_id));
830} else {
831tablegroup_id = tenant_schema->get_default_tablegroup_id();
832}
833}
834}
835} else {
836if (!table.has_partition()) {
837ret = OB_NOT_SUPPORTED;
838LOG_WARN("table which has no partitions with tablegroup", KR(ret), K(table));
839} else if (OB_FAIL(latest_schema_guard_.get_tablegroup_id(
840tablegroup_name, tablegroup_id))) {
841LOG_WARN("fail to get tablegroup id", KR(ret), K_(tenant_id), K(tablegroup_name));
842} else if (OB_UNLIKELY(OB_INVALID_ID == tablegroup_id)) {
843ret = OB_TABLEGROUP_NOT_EXIST;
844LOG_WARN("tabelgroup not exist ", KR(ret), K_(tenant_id), K(tablegroup_name));
845} else {}
846}
847
848if (OB_SUCC(ret) && OB_INVALID_ID != tablegroup_id) {
849// TODO:(yanmu.ztl) after 4.2, we can use ObSimpleTableSchema instead of ObTablegroupSchema
850const ObTablegroupSchema *tablegroup_schema = NULL;
851if (OB_FAIL(latest_schema_guard_.get_tablegroup_schema(tablegroup_id, tablegroup_schema))) {
852LOG_WARN("fail to get tablegroup schema", KR(ret), K_(tenant_id), K(tablegroup_id));
853} else if (OB_ISNULL(tablegroup_schema)) {
854ret = OB_TABLEGROUP_NOT_EXIST;
855LOG_WARN("tabelgroup not exist ", KR(ret), K_(tenant_id), K(tablegroup_id));
856} else if (OB_UNLIKELY(ObDuplicateScope::DUPLICATE_SCOPE_NONE != table.get_duplicate_scope()
857&& OB_INVALID_ID != tablegroup_id)) {
858ret = OB_NOT_SUPPORTED;
859LOG_WARN("duplicated table in tablegroup is not supported", K(ret),
860"table_id", table.get_table_id(),
861"tablegroup_id", table.get_tablegroup_id());
862LOG_USER_ERROR(OB_NOT_SUPPORTED, "duplicated table in tablegroup");
863}
864}
865
866if (OB_SUCC(ret)) {
867(void) const_cast<ObTableSchema&>(table).set_tablegroup_id(tablegroup_id);
868}
869return ret;
870}
871
872// parent table id won't change after parent table name is locked.
873int ObCreateTableHelper::check_and_set_parent_table_id_()
874{
875int ret = OB_SUCCESS;
876const ObTableSchema &table = arg_.schema_;
877const ObString &database_name = arg_.db_name_;
878const ObString &table_name = table.get_table_name();
879const uint64_t session_id = table.get_session_id();
880if (OB_FAIL(check_inner_stat_())) {
881LOG_WARN("fail to check inner stat", KR(ret));
882} else {
883for (int64_t i = 0; OB_SUCC(ret) && i < arg_.foreign_key_arg_list_.count(); i++) {
884const obrpc::ObCreateForeignKeyArg &foreign_key_arg = arg_.foreign_key_arg_list_.at(i);
885const ObString &parent_database_name = foreign_key_arg.parent_database_;
886const ObString &parent_table_name = foreign_key_arg.parent_table_;
887if (0 == parent_database_name.case_compare(database_name)
888&& 0 == parent_table_name.case_compare(table_name)) {
889// self reference
890} else {
891uint64_t parent_database_id = OB_INVALID_ID;
892const ObDatabaseSchema *parent_database = NULL;
893if (0 == parent_database_name.case_compare(database_name)) {
894parent_database_id = table.get_database_id();
895} else if (OB_FAIL(latest_schema_guard_.get_database_id(parent_database_name, parent_database_id))) {
896LOG_WARN("fail to get database id", KR(ret), K_(tenant_id), K(parent_database_name));
897} else if (OB_UNLIKELY(OB_INVALID_ID == parent_database_id)) {
898ret = OB_ERR_BAD_DATABASE;
899LOG_WARN("parent database not exist", KR(ret), K_(tenant_id), K(parent_database_name));
900LOG_USER_ERROR(OB_ERR_BAD_DATABASE, parent_database_name.length(), parent_database_name.ptr());
901} else if (OB_FAIL(latest_schema_guard_.get_database_schema(parent_database_id, parent_database))) {
902LOG_WARN("fail to get database schema", KR(ret), K_(tenant_id), K(parent_database_id));
903} else if (OB_ISNULL(parent_database)) {
904ret = OB_ERR_UNEXPECTED;
905LOG_WARN("database schema is null", KR(ret), K_(tenant_id), K(parent_database_id));
906} else if (parent_database->is_in_recyclebin()) {
907ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
908LOG_WARN("Can't not do ddl on db in recyclebin", KR(ret), K_(tenant_id), K(parent_database_id));
909}
910
911uint64_t parent_table_id = OB_INVALID_ID;
912ObTableType parent_table_type = ObTableType::MAX_TABLE_TYPE;
913int64_t parent_table_schema_version = OB_INVALID_VERSION; // not used
914if (FAILEDx(latest_schema_guard_.get_table_id(
915parent_database_id, session_id, parent_table_name,
916parent_table_id, parent_table_type, parent_table_schema_version))) {
917LOG_WARN("fail to get parent table id", KR(ret), K_(tenant_id),
918K(session_id), K(parent_database_id), K(parent_table_name));
919} else if (OB_UNLIKELY(OB_INVALID_ID == parent_table_id)) {
920if (!foreign_key_arg.is_parent_table_mock_) {
921ret = OB_TABLE_NOT_EXIST;
922LOG_WARN("parent table not exist", KR(ret), K_(tenant_id),
923K(session_id), K(parent_database_id), K(parent_table_name));
924LOG_USER_ERROR(OB_TABLE_NOT_EXIST,
925to_cstring(parent_database_name),
926to_cstring(parent_table_name));
927} else {
928//TODO(yanmu.ztl): this interface has poor performance.
929if (OB_FAIL(latest_schema_guard_.get_mock_fk_parent_table_id(
930parent_database_id, parent_table_name, parent_table_id))) {
931LOG_WARN("fail to get mock fk parent table id", KR(ret),
932K_(tenant_id), K(parent_database_id), K(parent_table_name));
933} else if (OB_UNLIKELY(OB_INVALID_ID == parent_table_id)) {
934LOG_INFO("mock fk parent table not exist", KR(ret), K_(tenant_id),
935K(parent_database_id), K(parent_table_name));
936}
937}
938} else {
939if (foreign_key_arg.is_parent_table_mock_) {
940ret = OB_ERR_PARALLEL_DDL_CONFLICT;
941LOG_WARN("parenet table already exist, should retry",
942KR(ret), K_(tenant_id), K(parent_table_id), K(foreign_key_arg));
943}
944}
945// parent_table_id will be OB_INVALID_ID in the following cases:
946// 1. foreign key is self reference.
947// 2. mock fk parent table doesn't exist.
948if (OB_SUCC(ret)) {
949const_cast<obrpc::ObCreateForeignKeyArg&>(foreign_key_arg).parent_database_id_ = parent_database_id;
950const_cast<obrpc::ObCreateForeignKeyArg&>(foreign_key_arg).parent_table_id_ = parent_table_id;
951}
952}
953} // end for
954}
955return ret;
956}
957
958int ObCreateTableHelper::generate_schemas_()
959{
960int ret = OB_SUCCESS;
961if (OB_FAIL(check_inner_stat_())) {
962LOG_WARN("fail to check inner stat", KR(ret));
963} else if (OB_FAIL(generate_table_schema_())) {
964LOG_WARN("fail to generate table schema", KR(ret));
965} else if (OB_FAIL(generate_aux_table_schemas_())) {
966LOG_WARN("fail to generate aux table schemas", KR(ret));
967} else if (OB_FAIL(gen_partition_object_and_tablet_ids_(new_tables_))) {
968LOG_WARN("fail to gen partition object/tablet ids", KR(ret));
969} else if (OB_FAIL(generate_foreign_keys_())) {
970LOG_WARN("fail to generate foreign keys", KR(ret));
971} else if (OB_FAIL(generate_sequence_object_())) {
972LOG_WARN("fail to generate sequence object", KR(ret));
973} else if (OB_FAIL(generate_audit_schema_())) {
974LOG_WARN("fail to generate audit schema", KR(ret));
975}
976RS_TRACE(generate_schemas);
977return ret;
978}
979
980int ObCreateTableHelper::generate_table_schema_()
981{
982int ret = OB_SUCCESS;
983HEAP_VAR(ObTableSchema, new_table) {
984
985// to make try_format_partition_schema() passed
986const uint64_t mock_table_id = OB_MIN_USER_OBJECT_ID + 1;
987bool is_oracle_mode = false;
988if (OB_FAIL(check_inner_stat_())) {
989LOG_WARN("fail to check inner stat", KR(ret));
990} else if (OB_UNLIKELY(OB_INVALID_ID != arg_.schema_.get_table_id())) {
991ret = OB_NOT_SUPPORTED;
992LOG_WARN("create table with table_id in 4.x is not supported",
993KR(ret), K_(tenant_id), "table_id", arg_.schema_.get_table_id());
994LOG_USER_ERROR(OB_NOT_SUPPORTED, "create table with id is");
995} else if (OB_FAIL(new_table.assign(arg_.schema_))) {
996LOG_WARN("fail to assign table schema", KR(ret), K_(tenant_id));
997} else if (FALSE_IT(new_table.set_table_id(mock_table_id))) {
998} else if (OB_FAIL(ddl_service_->try_format_partition_schema(new_table))) {
999LOG_WARN("fail to format partition schema", KR(ret), K_(tenant_id));
1000} else if (OB_FAIL(new_table.check_if_oracle_compat_mode(is_oracle_mode))) {
1001LOG_WARN("failed to get compat mode", KR(ret), K_(tenant_id));
1002}
1003
1004const uint64_t tablespace_id = new_table.get_tablespace_id();
1005if (OB_SUCC(ret) && OB_INVALID_ID != tablespace_id) {
1006const ObTablespaceSchema *tablespace = NULL;
1007if (OB_FAIL(latest_schema_guard_.get_tablespace_schema(
1008tablespace_id, tablespace))) {
1009LOG_WARN("fail to get tablespace schema", KR(ret), K_(tenant_id), K(tablespace_id));
1010} else if (OB_ISNULL(tablespace)) {
1011ret = OB_ERR_PARALLEL_DDL_CONFLICT;
1012LOG_WARN("tablespace not exist, need retry", KR(ret), K_(tenant_id), K(tablespace_id));
1013} else if (OB_FAIL(new_table.set_encrypt_key(tablespace->get_encrypt_key()))) {
1014LOG_WARN("fail to set encrypt key", KR(ret), K_(tenant_id), KPC(tablespace));
1015} else {
1016new_table.set_master_key_id(tablespace->get_master_key_id());
1017}
1018}
1019
1020const uint64_t tablegroup_id = new_table.get_tablegroup_id();
1021if (OB_SUCC(ret) && OB_INVALID_ID != tablegroup_id) {
1022//TODO:(yanmu.ztl) local schema maybe too old for concurrent create table
1023// to check partition options with the primary table in tablegroup.
1024ObSchemaGetterGuard guard;
1025if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id_, guard))) {
1026LOG_WARN("fail to get tenant schema guard", KR(ret), K_(tenant_id));
1027} else if (OB_FAIL(ddl_service_->try_check_and_set_table_schema_in_tablegroup(guard, new_table))) {
1028LOG_WARN("fail to check table in tablegorup", KR(ret), K(new_table));
1029}
1030}
1031
1032if (OB_SUCC(ret)) {
1033ObTableSchema::const_column_iterator begin = new_table.column_begin();
1034ObTableSchema::const_column_iterator end = new_table.column_end();
1035ObSchemaGetterGuard guard;
1036if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, guard))) {
1037LOG_WARN("fail to get schema guard", KR(ret));
1038}
1039for (; OB_SUCC(ret) && begin != end; begin++) {
1040ObColumnSchemaV2 *col = (*begin);
1041if (OB_ISNULL(col)) {
1042ret = OB_ERR_UNEXPECTED;
1043LOG_WARN("get column schema failed", KR(ret));
1044} else if (col->is_extend()) {
1045const uint64_t udt_id = col->get_sub_data_type();
1046const ObUDTTypeInfo *udt_info = NULL;
1047if (is_inner_object_id(udt_id) && !is_sys_tenant(tenant_id_)) {
1048// can't add object lock across tenant, assumed that sys inner udt won't be changed.
1049if (OB_FAIL(guard.get_udt_info(OB_SYS_TENANT_ID, udt_id, udt_info))) {
1050LOG_WARN("fail to get udt info", KR(ret), K(udt_id));
1051} else if (OB_ISNULL(udt_info)) {
1052ret = OB_ERR_UNEXPECTED;
1053LOG_WARN("inner udt not found", KR(ret), K(udt_id));
1054}
1055} else if (OB_FAIL(latest_schema_guard_.get_udt_info(udt_id, udt_info))) {
1056LOG_WARN("fail to get udt info", KR(ret), K_(tenant_id), K(udt_id));
1057} else if (OB_ISNULL(udt_info)) {
1058ret = OB_ERR_UNEXPECTED;
1059LOG_WARN("udt doesn't exist", KR(ret), K_(tenant_id), K(udt_id));
1060}
1061}
1062} // end for
1063}
1064
1065// check if constraint name duplicated
1066const uint64_t database_id = new_table.get_database_id();
1067bool cst_exist = false;
1068const ObIArray<ObConstraint> &constraints = arg_.constraint_list_;
1069const int64_t cst_cnt = constraints.count();
1070for (int64_t i = 0; OB_SUCC(ret) && i < cst_cnt; i++) {
1071const ObConstraint &cst = constraints.at(i);
1072const ObString &cst_name = cst.get_constraint_name_str();
1073if (OB_UNLIKELY(cst.get_constraint_name_str().empty())) {
1074ret = OB_ERR_UNEXPECTED;
1075LOG_WARN("cst name is empty", KR(ret), K_(tenant_id), K(database_id), K(cst_name));
1076} else if (OB_FAIL(check_constraint_name_exist_(new_table, cst_name, false /*is_foreign_key*/, cst_exist))) {
1077LOG_WARN("fail to check constraint name exist", KR(ret), K_(tenant_id), K(database_id), K(cst_name));
1078} else if (cst_exist) {
1079ret = OB_ERR_CONSTRAINT_NAME_DUPLICATE;
1080if (!is_oracle_mode) {
1081LOG_USER_ERROR(OB_ERR_CONSTRAINT_NAME_DUPLICATE, cst_name.length(), cst_name.ptr());
1082}
1083LOG_WARN("cst name is duplicate", KR(ret), K_(tenant_id), K(database_id), K(cst_name));
1084}
1085} // end for
1086
1087// fetch object_ids (data table + constraints)
1088ObIDGenerator id_generator;
1089const uint64_t object_cnt = cst_cnt + 1;
1090uint64_t object_id = OB_INVALID_ID;
1091if (FAILEDx(gen_object_ids_(object_cnt, id_generator))) {
1092LOG_WARN("fail to gen object ids", KR(ret), K_(tenant_id), K(object_cnt));
1093} else if (OB_FAIL(id_generator.next(object_id))) {
1094LOG_WARN("fail to get next object_id", KR(ret));
1095} else {
1096(void) new_table.set_table_id(object_id);
1097}
1098
1099// generate constraints
1100for (int64_t i = 0; OB_SUCC(ret) && i < cst_cnt; i++) {
1101ObConstraint &cst = const_cast<ObConstraint &>(constraints.at(i));
1102cst.set_tenant_id(tenant_id_);
1103cst.set_table_id(new_table.get_table_id());
1104if (OB_FAIL(id_generator.next(object_id))) {
1105LOG_WARN("fail to get next object_id", KR(ret));
1106} else if (FALSE_IT(cst.set_constraint_id(object_id))) {
1107} else if (OB_FAIL(new_table.add_constraint(cst))) {
1108LOG_WARN("fail to add constraint", KR(ret), K(cst));
1109}
1110} // end for
1111
1112// fill table schema for interval part
1113if (OB_SUCC(ret)
1114&& new_table.has_partition()
1115&& new_table.is_interval_part()) {
1116int64_t part_num = new_table.get_part_option().get_part_num();
1117ObPartition **part_array = new_table.get_part_array();
1118const ObRowkey *transition_point = NULL;
1119if (OB_UNLIKELY(PARTITION_LEVEL_TWO == new_table.get_part_level()
1120&& !new_table.has_sub_part_template_def())) {
1121ret = OB_NOT_SUPPORTED;
1122LOG_WARN("interval part of composited-partitioned table not support", KR(ret), K(new_table));
1123LOG_USER_ERROR(OB_NOT_SUPPORTED, "interval part of composited-partitioned table without template");
1124} else if (OB_UNLIKELY(1 != new_table.get_partition_key_column_num())) {
1125ret = OB_OP_NOT_ALLOW;
1126LOG_WARN("more than one partition key not support", KR(ret), K(new_table));
1127LOG_USER_ERROR(OB_OP_NOT_ALLOW, "more than one partition key");
1128} else if (OB_ISNULL(part_array)
1129|| OB_UNLIKELY(0 == part_num)) {
1130ret = OB_ERR_UNEXPECTED;
1131LOG_WARN("range part array is null or part_num is 0", KR(ret), K(new_table));
1132} else if (OB_ISNULL(transition_point = &part_array[part_num - 1]->get_high_bound_val())) {
1133ret = OB_ERR_UNEXPECTED;
1134LOG_WARN("transition_point is null", KR(ret), KP(transition_point));
1135} else if (OB_FAIL(ObPartitionUtils::check_interval_partition_table(
1136*transition_point, new_table.get_interval_range()))) {
1137LOG_WARN("fail to check_interval_partition_table", KR(ret), K(new_table));
1138} else if (OB_FAIL(new_table.set_transition_point(*transition_point))) {
1139LOG_WARN("fail to set transition point", KR(ret), K(new_table));
1140}
1141}
1142
1143if (FAILEDx(new_tables_.push_back(new_table))) {
1144LOG_WARN("fail to push back table", KR(ret));
1145}
1146
1147} // end HEAP_VAR
1148return ret;
1149}
1150
1151int ObCreateTableHelper::generate_aux_table_schemas_()
1152{
1153int ret = OB_SUCCESS;
1154HEAP_VAR(ObTableSchema, index_schema) {
1155
1156if (OB_FAIL(check_inner_stat_())) {
1157LOG_WARN("fail to check inner stat", KR(ret));
1158} else if (OB_UNLIKELY(new_tables_.count() <= 0)) {
1159ret = OB_ERR_UNEXPECTED;
1160LOG_WARN("table cnt not match", KR(ret), "table_cnt", new_tables_.count());
1161} else {
1162ObTableSchema *data_table = &(new_tables_.at(0));
1163
1164// 0. fetch object_ids
1165ObIDGenerator id_generator;
1166int64_t object_cnt = arg_.index_arg_list_.size();
1167bool has_lob_table = false;
1168uint64_t object_id = OB_INVALID_ID;
1169if (!data_table->is_external_table()) {
1170for (int64_t i = 0; OB_SUCC(ret) && !has_lob_table && i < data_table->get_column_count(); i++) {
1171const ObColumnSchemaV2 *column = data_table->get_column_schema_by_idx(i);
1172if (OB_ISNULL(column)) {
1173ret = OB_ERR_UNEXPECTED;
1174LOG_WARN("column is null", KR(ret), K(i), KPC(data_table));
1175} else if (is_lob_storage(column->get_data_type())) {
1176has_lob_table = true;
1177object_cnt += 2;
1178}
1179} // end for
1180}
1181if (FAILEDx(gen_object_ids_(object_cnt, id_generator))) {
1182LOG_WARN("fail to gen object ids", KR(ret), K_(tenant_id), K(object_cnt));
1183}
1184
1185// 1. build index table
1186ObIndexBuilder index_builder(*ddl_service_);
1187for (int64_t i = 0; OB_SUCC(ret) && i < arg_.index_arg_list_.size(); ++i) {
1188index_schema.reset();
1189obrpc::ObCreateIndexArg &index_arg = const_cast<obrpc::ObCreateIndexArg&>(arg_.index_arg_list_.at(i));
1190if (!index_arg.index_schema_.is_partitioned_table()
1191&& !data_table->is_partitioned_table()) {
1192if (INDEX_TYPE_NORMAL_GLOBAL == index_arg.index_type_) {
1193index_arg.index_type_ = INDEX_TYPE_NORMAL_GLOBAL_LOCAL_STORAGE;
1194} else if (INDEX_TYPE_UNIQUE_GLOBAL == index_arg.index_type_) {
1195index_arg.index_type_ = INDEX_TYPE_UNIQUE_GLOBAL_LOCAL_STORAGE;
1196} else if (INDEX_TYPE_SPATIAL_GLOBAL == index_arg.index_type_) {
1197index_arg.index_type_ = INDEX_TYPE_SPATIAL_GLOBAL_LOCAL_STORAGE;
1198}
1199}
1200// the global index has generated column schema during resolve, RS no need to generate index schema,
1201// just assign column schema
1202if (INDEX_TYPE_NORMAL_GLOBAL == index_arg.index_type_
1203|| INDEX_TYPE_UNIQUE_GLOBAL == index_arg.index_type_
1204|| INDEX_TYPE_SPATIAL_GLOBAL == index_arg.index_type_) {
1205if (OB_FAIL(index_schema.assign(index_arg.index_schema_))) {
1206LOG_WARN("fail to assign schema", KR(ret), K(index_arg));
1207}
1208}
1209// TODO(yanmu.ztl): should check if index name is duplicated in oracle mode.
1210const bool global_index_without_column_info = false;
1211ObSEArray<ObColumnSchemaV2 *, 1> gen_columns;
1212ObIAllocator *allocator = index_arg.index_schema_.get_allocator();
1213bool index_exist = false;
1214if (OB_FAIL(ret)) {
1215} else if (OB_ISNULL(allocator)) {
1216ret = OB_ERR_UNEXPECTED;
1217LOG_WARN("invalid allocator", K(ret));
1218} else if (OB_FAIL(ObIndexBuilderUtil::adjust_expr_index_args(
1219index_arg, *data_table, *allocator, gen_columns))) {
1220LOG_WARN("fail to adjust expr index args", KR(ret), K(index_arg), KPC(data_table));
1221} else if (OB_FAIL(index_builder.generate_schema(index_arg,
1222*data_table,
1223global_index_without_column_info,
1224false, /*generate_id*/
1225index_schema))) {
1226LOG_WARN("generate_schema for index failed", KR(ret), K(index_arg), KPC(data_table));
1227} else if (OB_FAIL(id_generator.next(object_id))) {
1228LOG_WARN("fail to get next object_id", KR(ret));
1229} else if (FALSE_IT(index_schema.set_table_id(object_id))) {
1230} else if (OB_FAIL(index_schema.generate_origin_index_name())) {
1231// For the later operation ObIndexNameChecker::add_index_name()
1232LOG_WARN("fail to generate origin index name", KR(ret), K(index_schema));
1233} else if (OB_FAIL(ddl_service_->get_index_name_checker().check_index_name_exist(
1234index_schema.get_tenant_id(),
1235index_schema.get_database_id(),
1236index_schema.get_table_name_str(),
1237index_exist))) {
1238} else if (index_exist) {
1239// actually, only index name in oracle tenant will be checked.
1240ret = OB_ERR_KEY_NAME_DUPLICATE;
1241LOG_WARN("duplicate index name", KR(ret), K_(tenant_id),
1242"database_id", index_schema.get_database_id(),
1243"index_name", index_schema.get_origin_index_name_str());
1244LOG_USER_ERROR(OB_ERR_KEY_NAME_DUPLICATE,
1245index_schema.get_origin_index_name_str().length(),
1246index_schema.get_origin_index_name_str().ptr());
1247} else if (OB_FAIL(new_tables_.push_back(index_schema))) {
1248LOG_WARN("push_back failed", KR(ret));
1249} else {
1250data_table = &(new_tables_.at(0)); // memory of data table may change after add table to new_tables_
1251}
1252} // end for
1253
1254// 2. build lob table
1255if (OB_SUCC(ret) && has_lob_table) {
1256HEAP_VARS_2((ObTableSchema, lob_meta_schema), (ObTableSchema, lob_piece_schema)) {
1257ObLobMetaBuilder lob_meta_builder(*ddl_service_);
1258ObLobPieceBuilder lob_piece_builder(*ddl_service_);
1259bool need_object_id = false;
1260if (OB_FAIL(id_generator.next(object_id))) {
1261LOG_WARN("fail to get next object_id", KR(ret));
1262} else if (OB_FAIL(lob_meta_builder.generate_aux_lob_meta_schema(
1263schema_service_->get_schema_service(), *data_table, object_id, lob_meta_schema, need_object_id))) {
1264LOG_WARN("generate lob meta table failed", KR(ret), KPC(data_table));
1265} else if (OB_FAIL(id_generator.next(object_id))) {
1266LOG_WARN("fail to get next object_id", KR(ret));
1267} else if (OB_FAIL(lob_piece_builder.generate_aux_lob_piece_schema(
1268schema_service_->get_schema_service(), *data_table, object_id, lob_piece_schema, need_object_id))) {
1269LOG_WARN("generate_schema for lob data table failed", KR(ret), KPC(data_table));
1270} else if (OB_FAIL(new_tables_.push_back(lob_meta_schema))) {
1271LOG_WARN("push_back lob meta table failed", KR(ret));
1272} else if (OB_FAIL(new_tables_.push_back(lob_piece_schema))) {
1273LOG_WARN("push_back lob piece table failed", KR(ret));
1274} else {
1275data_table = &(new_tables_.at(0)); // memory of data table may change after add table to new_tables_
1276data_table->set_aux_lob_meta_tid(lob_meta_schema.get_table_id());
1277data_table->set_aux_lob_piece_tid(lob_piece_schema.get_table_id());
1278}
1279
1280} // end HEAP_VARS_2
1281}
1282}
1283
1284} // end HEAP_VAR
1285return ret;
1286}
1287
1288int ObCreateTableHelper::generate_foreign_keys_()
1289{
1290int ret = OB_SUCCESS;
1291if (OB_FAIL(check_inner_stat_())) {
1292LOG_WARN("fail to check inner stat", KR(ret));
1293} else if (OB_UNLIKELY(new_tables_.count() <= 0)) {
1294ret = OB_ERR_UNEXPECTED;
1295LOG_WARN("invalid table cnt", KR(ret), "table_cnt", new_tables_.count());
1296} else {
1297bool is_oracle_mode = false;
1298ObTableSchema &data_table = new_tables_.at(0);
1299const uint64_t session_id = data_table.get_session_id();
1300ObIDGenerator id_generator; // for foreign key
1301const uint64_t object_cnt = arg_.foreign_key_arg_list_.count();
1302if (OB_FAIL(gen_object_ids_(object_cnt, id_generator))) {
1303LOG_WARN("fail to gen object ids", KR(ret), K_(tenant_id), K(object_cnt));
1304} else if (OB_FAIL(data_table.check_if_oracle_compat_mode(is_oracle_mode))) {
1305LOG_WARN("fail to check oracle mode", KR(ret));
1306}
1307// genernate foreign keys
1308for (int64_t i = 0; OB_SUCC(ret) && i < arg_.foreign_key_arg_list_.count(); i++) {
1309const obrpc::ObCreateForeignKeyArg &foreign_key_arg = arg_.foreign_key_arg_list_.at(i);
1310const ObString &foreign_key_name = foreign_key_arg.foreign_key_name_;
1311bool fk_exist = false;
1312ObForeignKeyInfo foreign_key_info;
1313// check if foreign key name is duplicated
1314if (OB_UNLIKELY(foreign_key_name.empty())) {
1315ret = OB_ERR_UNEXPECTED;
1316LOG_WARN("fk name is empty", KR(ret), K(foreign_key_arg));
1317} else if (OB_FAIL(check_constraint_name_exist_(data_table, foreign_key_name, true /*is_foreign_key*/, fk_exist))) {
1318LOG_WARN("fail to check foreign key name exist", KR(ret), K_(tenant_id), K(foreign_key_name));
1319} else if (fk_exist) {
1320if (is_oracle_mode) {
1321ret = OB_ERR_CONSTRAINT_NAME_DUPLICATE;
1322LOG_WARN("fk name is duplicate", KR(ret), K(foreign_key_name));
1323} else { // mysql mode
1324ret = OB_ERR_DUP_KEY;
1325LOG_USER_ERROR(OB_ERR_DUP_KEY,
1326data_table.get_table_name_str().length(),
1327data_table.get_table_name_str().ptr());
1328}
1329} else {
1330const ObTableSchema *parent_table = NULL;
1331ObMockFKParentTableSchema *new_mock_fk_parent_table = NULL;
1332const ObString &parent_database_name = foreign_key_arg.parent_database_;
1333const ObString &parent_table_name = foreign_key_arg.parent_table_;
1334const bool self_reference = (0 == parent_table_name.case_compare(data_table.get_table_name_str())
1335&& 0 == parent_database_name.case_compare(arg_.db_name_));
1336// 1. fill ref_cst_type_/ref_cst_id_
1337if (self_reference) {
1338// TODO: is it necessory to determine whether it is case sensitive by check sys variable
1339// check whether it belongs to self reference, if so, the parent schema is child schema.
1340parent_table = &data_table;
1341if (CONSTRAINT_TYPE_PRIMARY_KEY == foreign_key_arg.ref_cst_type_) {
1342if (is_oracle_mode) {
1343ObTableSchema::const_constraint_iterator iter = parent_table->constraint_begin();
1344for ( ; iter != parent_table->constraint_end(); ++iter) {
1345if (CONSTRAINT_TYPE_PRIMARY_KEY == (*iter)->get_constraint_type()) {
1346foreign_key_info.ref_cst_type_ = CONSTRAINT_TYPE_PRIMARY_KEY;
1347foreign_key_info.ref_cst_id_ = (*iter)->get_constraint_id();
1348break;
1349}
1350} // end for
1351} else {
1352foreign_key_info.ref_cst_type_ = CONSTRAINT_TYPE_PRIMARY_KEY;
1353foreign_key_info.ref_cst_id_ = common::OB_INVALID_ID;
1354}
1355} else if (CONSTRAINT_TYPE_UNIQUE_KEY == foreign_key_arg.ref_cst_type_) {
1356if (OB_FAIL(ddl_service_->get_uk_cst_id_for_self_ref(new_tables_, foreign_key_arg, foreign_key_info))) {
1357LOG_WARN("failed to get uk cst id for self ref", KR(ret), K(foreign_key_arg));
1358}
1359} else {
1360ret = OB_ERR_UNEXPECTED;
1361LOG_WARN("invalid foreign key ref cst type", KR(ret), K(foreign_key_arg));
1362}
1363} else {
1364foreign_key_info.ref_cst_type_ = foreign_key_arg.ref_cst_type_;
1365foreign_key_info.ref_cst_id_ = foreign_key_arg.ref_cst_id_;
1366if (foreign_key_arg.is_parent_table_mock_) {
1367// skip
1368} else {
1369const uint64_t parent_table_id = foreign_key_arg.parent_table_id_;
1370if (OB_FAIL(latest_schema_guard_.get_table_schema(parent_table_id, parent_table))) {
1371LOG_WARN("fail to get table schema", KR(ret), K_(tenant_id), K(parent_table_id));
1372} else if (OB_ISNULL(parent_table)) {
1373ret = OB_TABLE_NOT_EXIST;
1374LOG_WARN("parent table is not exist", KR(ret), K(foreign_key_arg));
1375}
1376}
1377}
1378
1379// 2. fill parent columns
1380if (OB_FAIL(ret)) {
1381} else if (foreign_key_arg.is_parent_table_mock_) {
1382if (OB_FAIL(get_mock_fk_parent_table_info_(foreign_key_arg, foreign_key_info, new_mock_fk_parent_table))) {
1383LOG_WARN("fail to get mock fk parent table info", KR(ret), K(foreign_key_arg));
1384}
1385} else {
1386if (false == parent_table->is_tmp_table()
1387&& 0 != parent_table->get_session_id()
1388&& OB_INVALID_ID != arg_.schema_.get_session_id()) {
1389ret = OB_TABLE_NOT_EXIST;
1390LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(parent_database_name), to_cstring(parent_table_name));
1391} else if (!arg_.is_inner_ && parent_table->is_in_recyclebin()) {
1392ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
1393LOG_WARN("parent table is in recyclebin", KR(ret), K(foreign_key_arg));
1394}
1395for (int64_t j = 0; OB_SUCC(ret) && j < foreign_key_arg.parent_columns_.count(); j++) {
1396const ObString &column_name = foreign_key_arg.parent_columns_.at(j);
1397const ObColumnSchemaV2 *column_schema = parent_table ->get_column_schema(column_name);
1398if (OB_ISNULL(column_schema)) {
1399ret = OB_ERR_COLUMN_NOT_FOUND;
1400LOG_WARN("parent column is not exist", KR(ret), K(column_name));
1401} else if (OB_FAIL(foreign_key_info.parent_column_ids_.push_back(column_schema->get_column_id()))) {
1402LOG_WARN("failed to push parent column id", KR(ret), K(column_name));
1403}
1404} // end for
1405}
1406
1407// 3. fill child columns
1408if (OB_SUCC(ret)) {
1409foreign_key_info.child_table_id_ = data_table.get_table_id();
1410foreign_key_info.parent_table_id_ = foreign_key_arg.is_parent_table_mock_ ?
1411new_mock_fk_parent_table->get_mock_fk_parent_table_id() :
1412parent_table->get_table_id();
1413for (int64_t j = 0; OB_SUCC(ret) && j < foreign_key_arg.child_columns_.count(); j++) {
1414const ObString &column_name = foreign_key_arg.child_columns_.at(j);
1415const ObColumnSchemaV2 *column_schema = data_table.get_column_schema(column_name);
1416if (OB_ISNULL(column_schema)) {
1417ret = OB_ERR_COLUMN_NOT_FOUND;
1418LOG_WARN("child column is not exist", KR(ret), K(column_name));
1419} else if (OB_FAIL(foreign_key_info.child_column_ids_.push_back(column_schema->get_column_id()))) {
1420LOG_WARN("failed to push child column id", KR(ret), K(column_name));
1421}
1422} // end for
1423}
1424
1425// 4. get reference option and foreign key name.
1426if (OB_SUCC(ret)) {
1427foreign_key_info.update_action_ = foreign_key_arg.update_action_;
1428foreign_key_info.delete_action_ = foreign_key_arg.delete_action_;
1429foreign_key_info.foreign_key_name_ = foreign_key_arg.foreign_key_name_;
1430foreign_key_info.enable_flag_ = foreign_key_arg.enable_flag_;
1431foreign_key_info.validate_flag_ = foreign_key_arg.validate_flag_;
1432foreign_key_info.rely_flag_ = foreign_key_arg.rely_flag_;
1433foreign_key_info.is_parent_table_mock_ = foreign_key_arg.is_parent_table_mock_;
1434foreign_key_info.name_generated_type_ = foreign_key_arg.name_generated_type_;
1435}
1436
1437// 5. add foreign key info
1438if (OB_SUCC(ret)) {
1439uint64_t object_id = OB_INVALID_ID;
1440if (OB_FAIL(id_generator.next(object_id))) {
1441LOG_WARN("fail to get next object_id", KR(ret));
1442} else if (FALSE_IT(foreign_key_info.foreign_key_id_ = object_id)) {
1443} else if (OB_FAIL(data_table.add_foreign_key_info(foreign_key_info))) {
1444LOG_WARN("fail to add foreign key info", KR(ret), K(foreign_key_info));
1445} else if (foreign_key_arg.is_parent_table_mock_) {
1446if (OB_FAIL(new_mock_fk_parent_table->add_foreign_key_info(foreign_key_info))) {
1447LOG_WARN("fail to add foreign key info", KR(ret), K(foreign_key_info));
1448}
1449} else {
1450// this logic is duplicated because of add_foreign_key() will also update data table's schema_version.
1451//if (parent_table->get_table_id() != data_table.get_table_id()) {
1452// // no need to update sync_versin_for_cascade_table while the refrence table is itself
1453// if (OB_FAIL(data_table.add_depend_table_id(parent_table->get_table_id()))) {
1454// LOG_WARN("failed to add depend table id", KR(ret), K(foreign_key_info));
1455// }
1456//}
1457}
1458}
1459}
1460} // end for
1461
1462FOREACH_X(iter, new_mock_fk_parent_table_map_, OB_SUCC(ret)) {
1463ObMockFKParentTableSchema *&new_mock_fk_parent_table = iter->second;
1464if (OB_ISNULL(new_mock_fk_parent_table)) {
1465ret = OB_ERR_UNEXPECTED;
1466LOG_WARN("mock fk parent table is null", KR(ret));
1467} else if (OB_FAIL(new_mock_fk_parent_tables_.push_back(new_mock_fk_parent_table))) {
1468LOG_WARN("fail to push back mock fk parent table", KR(ret), KPC(new_mock_fk_parent_table));
1469}
1470} // end foreach
1471
1472// check & replace existed mock fk parent table with data table
1473if (OB_SUCC(ret)) {
1474ObMockFKParentTableSchema *new_mock_fk_parent_table = NULL;
1475if (OB_FAIL(try_replace_mock_fk_parent_table_(new_mock_fk_parent_table))) {
1476LOG_WARN("replace mock fk parent table failed", KR(ret));
1477} else if (OB_NOT_NULL(new_mock_fk_parent_table)
1478&& OB_FAIL(new_mock_fk_parent_tables_.push_back(new_mock_fk_parent_table))) {
1479LOG_WARN("fail to push back mock fk parent table", KR(ret), K(new_mock_fk_parent_table));
1480}
1481}
1482}
1483return ret;
1484}
1485
1486int ObCreateTableHelper::get_mock_fk_parent_table_info_(
1487const obrpc::ObCreateForeignKeyArg &foreign_key_arg,
1488ObForeignKeyInfo &foreign_key_info,
1489ObMockFKParentTableSchema *&new_mock_fk_parent_table_schema)
1490{
1491int ret = OB_SUCCESS;
1492new_mock_fk_parent_table_schema = NULL;
1493if (OB_FAIL(check_inner_stat_())) {
1494LOG_WARN("fail to check inner stat", KR(ret));
1495} else if (OB_UNLIKELY(!foreign_key_arg.is_parent_table_mock_)) {
1496ret = OB_ERR_UNEXPECTED;
1497LOG_WARN("foreign_key_arg shoud be parent_table_mock", KR(ret), K(foreign_key_arg));
1498} else {
1499const ObMockFKParentTableSchema *ori_mock_fk_parent_table_schema = NULL;
1500if (OB_INVALID_ID != foreign_key_arg.parent_table_id_) {
1501// mock fk parent table already exist
1502if (OB_FAIL(latest_schema_guard_.get_mock_fk_parent_table_schema(
1503foreign_key_arg.parent_table_id_, ori_mock_fk_parent_table_schema))) {
1504LOG_WARN("fail to get mock fk parent table", KR(ret), K_(tenant_id), K(foreign_key_arg));
1505} else if (OB_ISNULL(ori_mock_fk_parent_table_schema)) {
1506ret = OB_ERR_PARALLEL_DDL_CONFLICT;
1507LOG_WARN("mock fk parent table may be dropped, ddl need retry", KR(ret), K_(tenant_id), K(foreign_key_arg));
1508}
1509}
1510
1511if (OB_SUCC(ret)) {
1512MockFKParentTableNameWrapper name_wrapper(foreign_key_arg.parent_database_,
1513foreign_key_arg.parent_table_);
1514int hash_ret = new_mock_fk_parent_table_map_.get_refactored(name_wrapper, new_mock_fk_parent_table_schema);
1515if (OB_SUCCESS == hash_ret) {
1516// skip
1517} else if (OB_HASH_NOT_EXIST != hash_ret) {
1518ret = hash_ret;
1519LOG_WARN("fail to get new mock fk parent table from map", KR(ret), K_(tenant_id), K(name_wrapper));
1520} else {
1521// 1. try init new mock fk parent table schema
1522if (OB_FAIL(ObSchemaUtils::alloc_schema(allocator_, new_mock_fk_parent_table_schema))) {
1523LOG_WARN("fail to new ObMockFKParentTableSchema", KR(ret), K_(tenant_id));
1524} else if (OB_INVALID_ID != foreign_key_arg.parent_table_id_) {
1525// mock fk parent table already exist
1526if (OB_ISNULL(ori_mock_fk_parent_table_schema)) {
1527ret = OB_ERR_UNEXPECTED;
1528LOG_WARN("ori mock fk parent table not exist", KR(ret), K(foreign_key_arg.parent_table_id_));
1529} else if (OB_FAIL(new_mock_fk_parent_table_schema->assign(*ori_mock_fk_parent_table_schema))) {
1530LOG_WARN("fail to assign mock fk parent table schema", KR(ret), KPC(ori_mock_fk_parent_table_schema));
1531} else {
1532(void) new_mock_fk_parent_table_schema->reset_column_array();
1533(void) new_mock_fk_parent_table_schema->set_operation_type(
1534ObMockFKParentTableOperationType::MOCK_FK_PARENT_TABLE_OP_UPDATE_SCHEMA_VERSION);
1535}
1536} else {
1537// mock fk parent table not exist
1538ObIDGenerator id_generator;
1539const uint64_t object_cnt = 1;
1540uint64_t object_id = OB_INVALID_ID;
1541if (OB_FAIL(gen_object_ids_(object_cnt, id_generator))) {
1542LOG_WARN("fail to gen object ids", KR(ret), K_(tenant_id), K(object_cnt));
1543} else if (OB_FAIL(id_generator.next(object_id))) {
1544LOG_WARN("fail to get next object_id", KR(ret));
1545} else if (OB_FAIL(new_mock_fk_parent_table_schema->set_mock_fk_parent_table_name(foreign_key_arg.parent_table_))) {
1546LOG_WARN("fail to set mock fk parent table name", KR(ret), K(foreign_key_arg));
1547} else {
1548(void) new_mock_fk_parent_table_schema->set_tenant_id(tenant_id_);
1549(void) new_mock_fk_parent_table_schema->set_database_id(foreign_key_arg.parent_database_id_);
1550(void) new_mock_fk_parent_table_schema->set_mock_fk_parent_table_id(object_id);
1551(void) new_mock_fk_parent_table_schema->set_operation_type(
1552ObMockFKParentTableOperationType::MOCK_FK_PARENT_TABLE_OP_CREATE_TABLE_BY_ADD_FK_IN_CHILD_TBALE);
1553}
1554}
1555
1556if (FAILEDx(new_mock_fk_parent_table_map_.set_refactored(name_wrapper, new_mock_fk_parent_table_schema))) {
1557LOG_WARN("fail to set mock fk parent table to map", KR(ret), KPC(new_mock_fk_parent_table_schema));
1558}
1559}
1560}
1561
1562// 2. try add new column to mock fk parent table
1563if (OB_FAIL(ret)) {
1564} else if (OB_ISNULL(new_mock_fk_parent_table_schema)) {
1565ret = OB_ERR_UNEXPECTED;
1566LOG_WARN("mock fk parent table should not be null", KR(ret), K(foreign_key_arg));
1567} else {
1568bool is_alter_table = ObMockFKParentTableOperationType::MOCK_FK_PARENT_TABLE_OP_CREATE_TABLE_BY_ADD_FK_IN_CHILD_TBALE
1569!= new_mock_fk_parent_table_schema->get_operation_type();
1570
1571uint64_t max_used_column_id = 0;
1572if (new_mock_fk_parent_table_schema->get_column_array().count() > 0) {
1573// 1. new mock fk parent table : update schema_version/add column
1574// 2. existed mock fk parent table: update schema_version/add column
1575max_used_column_id = new_mock_fk_parent_table_schema->get_column_array()
1576.at(new_mock_fk_parent_table_schema->get_column_array().count() - 1).first;
1577} else if (!is_alter_table) {
1578// 1. new mock fk parent table: create
1579max_used_column_id = 0;
1580} else {
1581// 1. update schema_version of existed mock fk parent table
1582// 2. add new column to mock fk parent table at the first time.
1583if (OB_ISNULL(ori_mock_fk_parent_table_schema)) {
1584ret = OB_ERR_UNEXPECTED;
1585LOG_WARN("mock fk parent table doesn't exist", KR(ret), K_(tenant_id), K(foreign_key_arg));
1586} else if (OB_UNLIKELY(ori_mock_fk_parent_table_schema->get_column_array().count() <= 0)) {
1587ret = OB_ERR_UNEXPECTED;
1588LOG_WARN("column cnt unexpected", KR(ret), KPC(ori_mock_fk_parent_table_schema));
1589} else {
1590max_used_column_id = ori_mock_fk_parent_table_schema->get_column_array()
1591.at(ori_mock_fk_parent_table_schema->get_column_array().count() - 1).first;
1592}
1593}
1594
1595for (int64_t i = 0; OB_SUCC(ret) && i < foreign_key_arg.parent_columns_.count(); ++i) {
1596uint64_t column_id = OB_INVALID_ID;
1597bool is_column_exist = false;
1598const ObString &column_name = foreign_key_arg.parent_columns_.at(i);
1599(void) new_mock_fk_parent_table_schema->get_column_id_by_column_name(column_name, column_id, is_column_exist);
1600
1601if (!is_column_exist && is_alter_table) {
1602if (OB_ISNULL(ori_mock_fk_parent_table_schema)) {
1603ret = OB_ERR_UNEXPECTED;
1604LOG_WARN("mock fk parent table doesn't exist", KR(ret), K_(tenant_id), K(foreign_key_arg));
1605} else {
1606(void) ori_mock_fk_parent_table_schema->get_column_id_by_column_name(column_name, column_id, is_column_exist);
1607}
1608}
1609
1610if (OB_FAIL(ret)) {
1611} else if (!is_column_exist) {
1612if (OB_FAIL(new_mock_fk_parent_table_schema->add_column_info_to_column_array(
1613std::make_pair(++max_used_column_id, column_name)))) {
1614LOG_WARN("fail to add_column_info_to_column_array for mock_fk_parent_table_schema",
1615KR(ret), K(max_used_column_id), K(column_name));
1616} else if (OB_FAIL(foreign_key_info.parent_column_ids_.push_back(max_used_column_id))) {
1617LOG_WARN("failed to push parent column id", KR(ret), K(max_used_column_id));
1618}
1619} else {
1620if (OB_FAIL(foreign_key_info.parent_column_ids_.push_back(column_id))) {
1621LOG_WARN("failed to push parent column id", KR(ret), K(column_id));
1622}
1623}
1624} // end for
1625}
1626
1627if (OB_SUCC(ret)
1628&& ObMockFKParentTableOperationType::MOCK_FK_PARENT_TABLE_OP_UPDATE_SCHEMA_VERSION
1629== new_mock_fk_parent_table_schema->get_operation_type()
1630&& new_mock_fk_parent_table_schema->get_column_array().count() > 0) {
1631(void) new_mock_fk_parent_table_schema->set_operation_type(
1632ObMockFKParentTableOperationType::MOCK_FK_PARENT_TABLE_OP_ADD_COLUMN);
1633}
1634}
1635return ret;
1636}
1637
1638int ObCreateTableHelper::try_replace_mock_fk_parent_table_(
1639ObMockFKParentTableSchema *&new_mock_fk_parent_table)
1640{
1641int ret = OB_SUCCESS;
1642new_mock_fk_parent_table = NULL;
1643if (OB_FAIL(check_inner_stat_())) {
1644LOG_WARN("fail to check inner stat", KR(ret));
1645} else if (OB_INVALID_ID == replace_mock_fk_parent_table_id_) {
1646// do nothing
1647} else if (OB_UNLIKELY(new_tables_.count() <= 0)) {
1648ret = OB_ERR_UNEXPECTED;
1649LOG_WARN("unexpected table cnt", KR(ret), K(new_tables_.count()));
1650} else {
1651// check if data table's columns are matched with existed mock fk parent table
1652const ObTableSchema &data_table = new_tables_.at(0);
1653
1654ObArray<const share::schema::ObTableSchema*> index_schemas;
1655for (int64_t i = 1; OB_SUCC(ret) && i < new_tables_.count(); ++i) {
1656if (new_tables_.at(i).is_unique_index()
1657&& OB_FAIL(index_schemas.push_back(&new_tables_.at(i)))) {
1658LOG_WARN("failed to push back to index_schemas", KR(ret));
1659}
1660} // end for
1661
1662const ObMockFKParentTableSchema *mock_fk_parent_table = NULL;
1663if (FAILEDx(latest_schema_guard_.get_mock_fk_parent_table_schema(
1664replace_mock_fk_parent_table_id_, mock_fk_parent_table))) {
1665LOG_WARN("fail to get mock fk parent table schema",
1666KR(ret), K_(tenant_id), K_(replace_mock_fk_parent_table_id));
1667} else if (OB_ISNULL(mock_fk_parent_table)) {
1668ret = OB_ERR_UNEXPECTED;
1669LOG_WARN("mock fk parent table not exist",
1670KR(ret), K_(tenant_id), K_(replace_mock_fk_parent_table_id));
1671} else if (OB_FAIL(check_fk_columns_type_for_replacing_mock_fk_parent_table_(
1672data_table, *mock_fk_parent_table))) {
1673LOG_WARN("fail to check if data table is matched with mock_fk_parent_table", KR(ret));
1674} else if (OB_FAIL(ObSchemaUtils::alloc_schema(
1675allocator_, *mock_fk_parent_table, new_mock_fk_parent_table))) {
1676LOG_WARN("fail to alloc schema", KR(ret), KPC(mock_fk_parent_table));
1677} else {
1678(void) new_mock_fk_parent_table->set_operation_type(
1679ObMockFKParentTableOperationType::MOCK_FK_PARENT_TABLE_OP_REPLACED_BY_REAL_PREANT_TABLE);
1680const ObIArray<ObForeignKeyInfo> &ori_mock_fk_infos_array = mock_fk_parent_table->get_foreign_key_infos();
1681// modify the parent column id of fk,make it fit with real parent table
1682// mock_column_id -> column_name -> real_column_id
1683for (int64_t i = 0; OB_SUCC(ret) && i < ori_mock_fk_infos_array.count(); ++i) {
1684const ObForeignKeyInfo &ori_foreign_key_info = mock_fk_parent_table->get_foreign_key_infos().at(i);
1685ObForeignKeyInfo &new_foreign_key_info = new_mock_fk_parent_table->get_foreign_key_infos().at(i);
1686new_foreign_key_info.parent_column_ids_.reuse();
1687new_foreign_key_info.ref_cst_type_ = CONSTRAINT_TYPE_INVALID;
1688new_foreign_key_info.is_parent_table_mock_ = false;
1689new_foreign_key_info.parent_table_id_ = data_table.get_table_id();
1690// replace parent table columns
1691for (int64_t j = 0; OB_SUCC(ret) && j < ori_foreign_key_info.parent_column_ids_.count(); ++j) {
1692bool is_column_exist = false;
1693uint64_t mock_parent_table_column_id = ori_foreign_key_info.parent_column_ids_.at(j);
1694ObString column_name;
1695const ObColumnSchemaV2 *col_schema = NULL;
1696(void) mock_fk_parent_table->get_column_name_by_column_id(
1697mock_parent_table_column_id, column_name, is_column_exist);
1698if (!is_column_exist) {
1699ret = OB_ERR_UNEXPECTED;
1700LOG_WARN("column is not exist", KR(ret), K(mock_parent_table_column_id), KPC(mock_fk_parent_table));
1701} else if (OB_ISNULL(col_schema = data_table.get_column_schema(column_name))) {
1702ret = OB_ERR_UNEXPECTED;
1703LOG_WARN("get column schema failed", KR(ret), K(column_name));
1704} else if (OB_FAIL(new_foreign_key_info.parent_column_ids_.push_back(col_schema->get_column_id()))) {
1705LOG_WARN("push_back to parent_column_ids failed", KR(ret), K(col_schema->get_column_id()));
1706}
1707} // end for
1708// check and mofidy ref cst type and ref cst id of fk
1709const ObRowkeyInfo &rowkey_info = data_table.get_rowkey_info();
1710common::ObArray<uint64_t> pk_column_ids;
1711for (int64_t j = 0; OB_SUCC(ret) && j < rowkey_info.get_size(); ++j) {
1712uint64_t column_id = 0;
1713const ObColumnSchemaV2 *col_schema = NULL;
1714if (OB_FAIL(rowkey_info.get_column_id(j, column_id))) {
1715LOG_WARN("fail to get rowkey info", KR(ret), K(j), K(rowkey_info));
1716} else if (OB_ISNULL(col_schema = data_table.get_column_schema(column_id))) {
1717ret = OB_ERR_UNEXPECTED;
1718LOG_WARN("get index column schema failed", K(ret));
1719} else if (col_schema->is_hidden() || col_schema->is_shadow_column()) {
1720// do nothing
1721} else if (OB_FAIL(pk_column_ids.push_back(col_schema->get_column_id()))) {
1722LOG_WARN("push back column_id failed", KR(ret), K(col_schema->get_column_id()));
1723}
1724} // end for
1725bool is_match = false;
1726if (FAILEDx(sql::ObResolverUtils::check_match_columns(
1727pk_column_ids, new_foreign_key_info.parent_column_ids_, is_match))) {
1728LOG_WARN("check_match_columns failed", KR(ret));
1729} else if (is_match) {
1730new_foreign_key_info.ref_cst_type_ = CONSTRAINT_TYPE_PRIMARY_KEY;
1731} else { // pk is not match, check if uk match
1732if (OB_FAIL(ddl_service_->get_uk_cst_id_for_replacing_mock_fk_parent_table(
1733index_schemas, new_foreign_key_info))) {
1734LOG_WARN("fail to get_uk_cst_id_for_replacing_mock_fk_parent_table", KR(ret));
1735} else if (CONSTRAINT_TYPE_INVALID == new_foreign_key_info.ref_cst_type_) {
1736ret = OB_ERR_CANNOT_ADD_FOREIGN;
1737LOG_WARN("ref_cst_type is invalid", KR(ret), KPC(mock_fk_parent_table));
1738}
1739}
1740}
1741}
1742}
1743return ret;
1744}
1745
1746int ObCreateTableHelper::check_fk_columns_type_for_replacing_mock_fk_parent_table_(
1747const ObTableSchema &parent_table_schema,
1748const ObMockFKParentTableSchema &mock_parent_table_schema)
1749{
1750int ret = OB_SUCCESS;
1751bool is_oracle_mode = false;
1752if (OB_FAIL(check_inner_stat_())) {
1753LOG_WARN("fail to check inner stat", KR(ret));
1754} else if (OB_FAIL(parent_table_schema.check_if_oracle_compat_mode(is_oracle_mode))) {
1755LOG_WARN("check if oracle compat mode failed", K(ret));
1756}
1757for (int64_t i = 0; OB_SUCC(ret) && i < mock_parent_table_schema.get_foreign_key_infos().count(); ++i) {
1758const ObTableSchema *child_table_schema = NULL;
1759const ObForeignKeyInfo &fk_info = mock_parent_table_schema.get_foreign_key_infos().at(i);
1760if (OB_FAIL(latest_schema_guard_.get_table_schema(fk_info.child_table_id_, child_table_schema))) {
1761LOG_WARN("table is not exist", KR(ret), K(fk_info));
1762} else if (OB_ISNULL(child_table_schema)) {
1763ret = OB_ERR_PARALLEL_DDL_CONFLICT;
1764LOG_WARN("child table schema is null, need retry", KR(ret), K(fk_info));
1765} else {
1766// prepare params for check_foreign_key_columns_type
1767ObArray<ObString> child_columns;
1768ObArray<ObString> parent_columns;
1769bool is_column_exist = false;
1770for (int64_t j = 0; OB_SUCC(ret) && j < fk_info.child_column_ids_.count(); ++j) {
1771ObString child_column_name;
1772const ObColumnSchemaV2 *child_col = child_table_schema->get_column_schema(fk_info.child_column_ids_.at(j));
1773if (OB_ISNULL(child_col)) {
1774ret = OB_ERR_UNEXPECTED;
1775LOG_WARN("column is not exist", KR(ret), K(fk_info));
1776} else if (OB_FAIL(child_columns.push_back(child_col->get_column_name_str()))) {
1777LOG_WARN("fail to push_back to child_columns", KR(ret), KPC(child_col));
1778}
1779} // end for
1780for (int64_t j = 0; OB_SUCC(ret) && j < fk_info.parent_column_ids_.count(); ++j) {
1781ObString parent_column_name;
1782(void) mock_parent_table_schema.get_column_name_by_column_id(
1783fk_info.parent_column_ids_.at(j), parent_column_name, is_column_exist);
1784if (!is_column_exist) {
1785ret = OB_ERR_UNEXPECTED;
1786LOG_WARN("column is not exist", KR(ret), K(fk_info));
1787} else if (OB_FAIL(parent_columns.push_back(parent_column_name))) {
1788LOG_WARN("fail to push_back to real_parent_table_schema_columns", KR(ret), K(fk_info));
1789}
1790} // end for
1791if (FAILEDx(sql::ObResolverUtils::check_foreign_key_columns_type(
1792!is_oracle_mode/*is_mysql_compat_mode*/,
1793*child_table_schema,
1794parent_table_schema,
1795child_columns,
1796parent_columns,
1797NULL))) {
1798ret = OB_ERR_CANNOT_ADD_FOREIGN;
1799LOG_WARN("Failed to check_foreign_key_columns_type", KR(ret));
1800}
1801}
1802} // end for
1803return ret;
1804}
1805
1806int ObCreateTableHelper::generate_sequence_object_()
1807{
1808int ret = OB_SUCCESS;
1809bool is_oracle_mode = false;
1810if (OB_FAIL(check_inner_stat_())) {
1811LOG_WARN("fail to check inner stat", KR(ret));
1812} else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id(tenant_id_, is_oracle_mode))) {
1813LOG_WARN("fail to check is oracle mode", KR(ret));
1814} else if (!is_oracle_mode) {
1815// skip
1816} else if (OB_UNLIKELY(new_tables_.count() <= 0)) {
1817ret = OB_ERR_UNEXPECTED;
1818LOG_WARN("unexpected table cnt", KR(ret), K(new_tables_.count()));
1819} else if (!(new_tables_.at(0).is_user_table()
1820|| new_tables_.at(0).is_oracle_tmp_table())) {
1821// skip
1822} else {
1823// 1. lock object name
1824// - Sequence object name for table is encoded with table_id which is determinated in generate_schemas_() stage,
1825// - so lock_objects_() stage will be delayed. And sequence_name won't be conficted for most cases since it's encoded.
1826const obrpc::ObSequenceDDLArg &sequence_ddl_arg = arg_.sequence_ddl_arg_;
1827const ObTableSchema &data_table = new_tables_.at(0);
1828const uint64_t tenant_id = data_table.get_tenant_id();
1829const uint64_t database_id = data_table.get_database_id();
1830const uint64_t session_id = arg_.schema_.get_session_id();
1831const ObString &database_name = arg_.db_name_;
1832ObSequenceSchema *new_sequence = NULL;
1833char sequence_name[OB_MAX_SEQUENCE_NAME_LENGTH + 1] = { 0 };
1834const bool is_or_replace = false;
1835for (ObTableSchema::const_column_iterator iter = data_table.column_begin();
1836OB_SUCC(ret) && iter != data_table.column_end(); ++iter) {
1837ObColumnSchemaV2 *column_schema = *iter;
1838if (OB_ISNULL(column_schema)) {
1839ret = OB_ERR_UNEXPECTED;
1840LOG_WARN("column is null", KR(ret));
1841} else if (!column_schema->is_identity_column()) {
1842continue;
1843} else if (OB_FAIL(ObSchemaUtils::alloc_schema(allocator_, new_sequence))) {
1844LOG_WARN("fail to alloc schema", KR(ret));
1845} else if (OB_FAIL(new_sequence->assign(sequence_ddl_arg.seq_schema_))) {
1846LOG_WARN("fail to assign sequence schema", KR(ret), K(sequence_ddl_arg));
1847} else {
1848ObSequenceOptionBuilder opt_builder;
1849int32_t len = snprintf(sequence_name, sizeof(sequence_name),
1850"%s%lu%c%lu", IDENTITY_COLUMN_SEQUENCE_OBJECT_NAME_PREFIX,
1851data_table.get_table_id(), '_', column_schema->get_column_id());
1852new_sequence->set_tenant_id(tenant_id);
1853new_sequence->set_database_id(database_id);
1854if (OB_UNLIKELY(len < 0)) {
1855ret = OB_ERR_UNEXPECTED;
1856LOG_WARN("create sequence name fail", KR(ret), KPC(column_schema));
1857} else if (OB_FAIL(new_sequence->set_sequence_name(sequence_name))) {
1858LOG_WARN("fail to set sequence name", KR(ret), K(sequence_name));
1859} else if (OB_FAIL(opt_builder.build_create_sequence_option(
1860sequence_ddl_arg.option_bitset_, new_sequence->get_sequence_option()))) {
1861LOG_WARN("fail to build sequence_option", KR(ret), K(sequence_ddl_arg));
1862} else if (OB_FAIL(add_lock_object_by_name_(
1863database_name, new_sequence->get_sequence_name(),
1864share::schema::SEQUENCE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
1865LOG_WARN("fail to lock object by sequence name prefix", KR(ret), K_(tenant_id),
1866K(database_name), KPC(new_sequence));
1867} else if (OB_FAIL(latest_schema_guard_.check_oracle_object_exist(
1868new_sequence->get_database_id(), session_id,
1869new_sequence->get_sequence_name(), SEQUENCE_SCHEMA,
1870INVALID_ROUTINE_TYPE, is_or_replace))) {
1871LOG_WARN("fail to check oracle object exist", KR(ret), KPC(new_sequence));
1872} else if (OB_FAIL(new_sequences_.push_back(new_sequence))) {
1873LOG_WARN("fail to push back new sequence ptr", KR(ret));
1874}
1875}
1876} // end for
1877
1878if (FAILEDx(lock_existed_objects_by_name_())) {
1879LOG_WARN("fail to lock objects by name", KR(ret), K_(tenant_id));
1880}
1881
1882// 2. generate object ids
1883ObIDGenerator id_generator;
1884const uint64_t object_cnt = new_sequences_.count();
1885if (FAILEDx(gen_object_ids_(object_cnt, id_generator))) {
1886LOG_WARN("fail to gen object ids", KR(ret), K_(tenant_id), K(object_cnt));
1887}
1888
1889// 3. generate schema
1890int64_t idx = 0;
1891uint64_t sequence_id = OB_INVALID_ID;
1892char sequence_string[OB_MAX_SEQUENCE_NAME_LENGTH + 1] = { 0 };
1893for (ObTableSchema::const_column_iterator iter = data_table.column_begin();
1894OB_SUCC(ret) && iter != data_table.column_end(); ++iter) {
1895ObColumnSchemaV2 *column_schema = *iter;
1896if (OB_ISNULL(column_schema)) {
1897ret = OB_ERR_UNEXPECTED;
1898LOG_WARN("column is null", KR(ret));
1899} else if (!column_schema->is_identity_column()) {
1900continue;
1901} else if (OB_UNLIKELY(idx >= new_sequences_.count())) {
1902ret = OB_ERR_UNEXPECTED;
1903LOG_WARN("invalid idx", KR(ret), K(idx), K(new_sequences_.count()));
1904} else if (OB_ISNULL(new_sequence = new_sequences_.at(idx++))) {
1905ret = OB_ERR_UNEXPECTED;
1906LOG_WARN("sequence is null", KR(ret));
1907} else if (OB_FAIL(id_generator.next(sequence_id))) {
1908LOG_WARN("fail to get next object_id", KR(ret));
1909} else {
1910// 3.1. generate sequence id
1911new_sequence->set_sequence_id(sequence_id);
1912// 3.2. modify column schema
1913column_schema->set_sequence_id(sequence_id);
1914int32_t len = snprintf(sequence_string, sizeof(sequence_string), "%lu", sequence_id);
1915if (OB_UNLIKELY(len < 0)) {
1916ret = OB_ERR_UNEXPECTED;
1917LOG_WARN("create sequence string fail", KR(ret), K(sequence_id));
1918} else {
1919ObObjParam cur_default_value; // for desc table
1920ObObjParam orig_default_value; // for store pure_sequence_id
1921cur_default_value.set_varchar("SEQUENCE.NEXTVAL");
1922cur_default_value.set_collation_type(ObCharset::get_system_collation());
1923cur_default_value.set_collation_level(CS_LEVEL_IMPLICIT);
1924cur_default_value.set_param_meta();
1925orig_default_value.set_varchar(sequence_string);
1926orig_default_value.set_collation_type(ObCharset::get_system_collation());
1927orig_default_value.set_collation_level(CS_LEVEL_IMPLICIT);
1928orig_default_value.set_param_meta();
1929if (OB_FAIL(column_schema->set_cur_default_value(cur_default_value))) {
1930LOG_WARN("set current default value fail", KR(ret));
1931} else if (OB_FAIL(column_schema->set_orig_default_value(orig_default_value))) {
1932LOG_WARN("set origin default value fail", KR(ret), K(column_schema));
1933}
1934}
1935}
1936} // end for
1937}
1938return ret;
1939}
1940
1941// create audit schema for table/sequence
1942int ObCreateTableHelper::generate_audit_schema_()
1943{
1944int ret = OB_SUCCESS;
1945if (OB_FAIL(check_inner_stat_())) {
1946LOG_WARN("fail to check inner stat", KR(ret));
1947} else if (OB_UNLIKELY(new_tables_.count() <= 0)) {
1948ret = OB_ERR_UNEXPECTED;
1949LOG_WARN("unexpected table cnt", KR(ret), K(new_tables_.count()));
1950} else {
1951// check if data table's columns are matched with existed mock fk parent table
1952const ObTableSchema &data_table = new_tables_.at(0);
1953ObArray<ObSAuditSchema> audits;
1954if (OB_FAIL(latest_schema_guard_.get_default_audit_schemas(audits))) {
1955LOG_WARN("fail to get audits", KR(ret));
1956} else if (!audits.empty()) {
1957ObSAuditSchema *new_audit_schema = NULL;
1958for (int64_t i = 0; OB_SUCC(ret) && i < audits.count(); i++) {
1959const ObSAuditSchema &audit = audits.at(i);
1960if (audit.is_access_operation_for_sequence()) {
1961for (int64_t j = 0; OB_SUCC(ret) && j < new_sequences_.count(); j++) {
1962const ObSequenceSchema *new_sequence = new_sequences_.at(j);
1963if (OB_ISNULL(new_sequence)) {
1964ret = OB_ERR_UNEXPECTED;
1965LOG_WARN("new sequence is null", KR(ret));
1966} else if (OB_FAIL(ObSchemaUtils::alloc_schema(allocator_, new_audit_schema))) {
1967LOG_WARN("fail to alloc schema", KR(ret));
1968} else if (OB_FAIL(new_audit_schema->assign(audit))) {
1969LOG_WARN("fail to assign audit", KR(ret));
1970} else {
1971new_audit_schema->set_audit_type(AUDIT_SEQUENCE);
1972new_audit_schema->set_owner_id(new_sequence->get_sequence_id());
1973if (OB_FAIL(new_audits_.push_back(new_audit_schema))) {
1974LOG_WARN("fail to push back audit", KR(ret), KPC(new_audit_schema));
1975}
1976}
1977} // end for
1978}
1979if (OB_FAIL(ret)) {
1980} else if (audit.is_access_operation_for_table()) {
1981if (OB_FAIL(ObSchemaUtils::alloc_schema(allocator_, new_audit_schema))) {
1982LOG_WARN("fail to alloc schema", KR(ret));
1983} else if (OB_FAIL(new_audit_schema->assign(audit))) {
1984LOG_WARN("fail to assign audit", KR(ret));
1985} else {
1986new_audit_schema->set_audit_type(AUDIT_TABLE);
1987new_audit_schema->set_owner_id(data_table.get_table_id());
1988if (OB_FAIL(new_audits_.push_back(new_audit_schema))) {
1989LOG_WARN("fail to push back audit", KR(ret), KPC(new_audit_schema));
1990}
1991}
1992}
1993} // end for
1994
1995if (OB_SUCC(ret) && !new_audits_.empty()) {
1996ObIDGenerator id_generator;
1997const uint64_t object_cnt = new_audits_.count();
1998uint64_t object_id = OB_INVALID_ID;
1999if (OB_FAIL(gen_object_ids_(object_cnt, id_generator))) {
2000LOG_WARN("fail to gen object ids", KR(ret), K_(tenant_id), K(object_cnt));
2001}
2002for (int64_t i = 0; OB_SUCC(ret) && i < new_audits_.count(); i++) {
2003ObSAuditSchema *audit = new_audits_.at(i);
2004if (OB_ISNULL(audit)) {
2005ret = OB_ERR_UNEXPECTED;
2006LOG_WARN("audit is null", KR(ret));
2007} else if (OB_FAIL(id_generator.next(object_id))) {
2008LOG_WARN("fail to get next object_id", KR(ret));
2009} else {
2010audit->set_audit_id(object_id);
2011}
2012} // end for
2013}
2014}
2015}
2016return ret;
2017}
2018
2019int ObCreateTableHelper::calc_schema_version_cnt_()
2020{
2021int ret = OB_SUCCESS;
2022if (OB_FAIL(check_inner_stat_())) {
2023LOG_WARN("fail to check inner stat", KR(ret));
2024} else if (OB_UNLIKELY(new_tables_.count() <= 0)) {
2025ret = OB_ERR_UNEXPECTED;
2026LOG_WARN("unexpected table cnt", KR(ret), K(new_tables_.count()));
2027} else {
2028const ObTableSchema &data_table = new_tables_.at(0);
2029// 0. data table
2030schema_version_cnt_ = 1; // init
2031
2032// 1. sequence
2033schema_version_cnt_ += new_sequences_.count();
2034
2035// 2. audit
2036schema_version_cnt_ += new_audits_.count();
2037
2038// 3. create index/lob table
2039if (OB_SUCC(ret) && new_tables_.count() > 1) {
2040schema_version_cnt_ += (new_tables_.count() - 1);
2041// update data table schema version
2042schema_version_cnt_++;
2043}
2044
2045// 4. foreign key (without mock fk parent table)
2046if (OB_SUCC(ret)) {
2047// this logic is duplicated because of add_foreign_key() will also update data table's schema_version.
2048//schema_version_cnt_ += data_table.get_depend_table_ids();
2049const ObIArray<ObForeignKeyInfo> &foreign_key_infos = data_table.get_foreign_key_infos();
2050for (int64_t i = 0; OB_SUCC(ret) && i < foreign_key_infos.count(); i++) {
2051const ObForeignKeyInfo &foreign_key_info = foreign_key_infos.at(i);
2052if (foreign_key_info.is_modify_fk_state_) {
2053continue;
2054} else if (!foreign_key_info.is_parent_table_mock_) {
2055schema_version_cnt_++;
2056// TODO(yanmu.ztl): can be optimized in the following cases:
2057// - self reference
2058// - foreign keys has same parent table.
2059}
2060} // end for
2061}
2062
2063// 5. mock fk parent table
2064if (OB_SUCC(ret)) {
2065// schema version for new mock fk parent tables
2066schema_version_cnt_ += new_mock_fk_parent_tables_.count();
2067for (int64_t i = 0; OB_SUCC(ret) && i < new_mock_fk_parent_tables_.count(); i++) {
2068const ObMockFKParentTableSchema *new_mock_fk_parent_table = new_mock_fk_parent_tables_.at(i);
2069if (OB_ISNULL(new_mock_fk_parent_table)) {
2070ret = OB_ERR_UNEXPECTED;
2071LOG_WARN("mock fk parent table is null", KR(ret));
2072} else if (MOCK_FK_PARENT_TABLE_OP_CREATE_TABLE_BY_ADD_FK_IN_CHILD_TBALE
2073== new_mock_fk_parent_table->get_operation_type()) {
2074// skip
2075} else if (MOCK_FK_PARENT_TABLE_OP_UPDATE_SCHEMA_VERSION
2076== new_mock_fk_parent_table->get_operation_type()
2077|| MOCK_FK_PARENT_TABLE_OP_ADD_COLUMN
2078== new_mock_fk_parent_table->get_operation_type()) {
2079// update new mock fk parent table(is useless here, just to be compatible with other logic)
2080schema_version_cnt_++;
2081} else if (MOCK_FK_PARENT_TABLE_OP_REPLACED_BY_REAL_PREANT_TABLE
2082== new_mock_fk_parent_table->get_operation_type()) {
2083// update foreign keys' schema version.
2084schema_version_cnt_++;
2085// update child tables' schema version.
2086// TODO(yanmu.ztl): can be optimized when child table is duplicated.
2087schema_version_cnt_ += (new_mock_fk_parent_table->get_foreign_key_infos().count());
2088// update data table's schema version at last.
2089schema_version_cnt_++;
2090} else {
2091ret = OB_NOT_SUPPORTED;
2092LOG_WARN("not supported operation type", KR(ret), KPC(new_mock_fk_parent_table));
2093}
2094} // end for
2095}
2096
2097// 6. for 1503 boundary ddl operation
2098schema_version_cnt_++;
2099}
2100return ret;
2101}
2102
2103int ObCreateTableHelper::create_schemas_()
2104{
2105int ret = OB_SUCCESS;
2106if (OB_FAIL(check_inner_stat_())) {
2107LOG_WARN("fail to check inner stat", KR(ret));
2108} else if (OB_FAIL(create_sequence_())) {
2109LOG_WARN("fail to create sequences", KR(ret));
2110} else if (OB_FAIL(create_tables_())) {
2111LOG_WARN("fail to create tables", KR(ret));
2112} else if (OB_FAIL(create_audits_())) {
2113LOG_WARN("fail to create tables", KR(ret));
2114} else if (OB_FAIL(deal_with_mock_fk_parent_tables_())) {
2115LOG_WARN("fail to deal with mock fk parent tables", KR(ret));
2116}
2117RS_TRACE(create_schemas);
2118return ret;
2119}
2120
2121int ObCreateTableHelper::create_sequence_()
2122{
2123int ret = OB_SUCCESS;
2124ObSchemaService *schema_service_impl = NULL;
2125if (OB_FAIL(check_inner_stat_())) {
2126LOG_WARN("fail to check inner stat", KR(ret));
2127} else if (new_sequences_.count() <= 0) {
2128// skip
2129} else if (OB_ISNULL(schema_service_impl = schema_service_->get_schema_service())) {
2130ret = OB_ERR_UNEXPECTED;
2131LOG_WARN("schema_service impl is null", KR(ret));
2132} else {
2133ObString *ddl_stmt_str = NULL;
2134uint64_t *old_sequence_id = NULL; // means don't sync sequence value
2135int64_t new_schema_version = OB_INVALID_VERSION;
2136for (int64_t i = 0; OB_SUCC(ret) && i < new_sequences_.count(); i++) {
2137ObSequenceSchema *new_sequence = new_sequences_.at(i);
2138if (OB_ISNULL(new_sequence)) {
2139ret = OB_ERR_UNEXPECTED;
2140LOG_WARN("new sequence is null", KR(ret));
2141} else if (OB_FAIL(schema_service_->gen_new_schema_version(tenant_id_, new_schema_version))) {
2142LOG_WARN("fail to gen new schema_version", KR(ret), K_(tenant_id));
2143} else if (FALSE_IT(new_sequence->set_schema_version(new_schema_version))) {
2144} else if (OB_FAIL(schema_service_impl->get_sequence_sql_service().insert_sequence(
2145*new_sequence, &trans_, ddl_stmt_str, old_sequence_id))) {
2146LOG_WARN("fail to create sequence", KR(ret), KPC(new_sequence));
2147}
2148} // end for
2149}
2150return ret;
2151}
2152
2153int ObCreateTableHelper::create_audits_()
2154{
2155int ret = OB_SUCCESS;
2156ObSchemaService *schema_service_impl = NULL;
2157if (OB_FAIL(check_inner_stat_())) {
2158LOG_WARN("fail to check inner stat", KR(ret));
2159} else if (OB_ISNULL(schema_service_impl = schema_service_->get_schema_service())) {
2160ret = OB_ERR_UNEXPECTED;
2161LOG_WARN("schema_service impl is null", KR(ret));
2162} else {
2163common::ObSqlString public_sql_string;
2164int64_t new_schema_version = OB_INVALID_VERSION;
2165for (int64_t i = 0; OB_SUCC(ret) && i < new_audits_.count(); i++) {
2166ObSAuditSchema *new_audit = new_audits_.at(i);
2167if (OB_ISNULL(new_audit)) {
2168ret = OB_ERR_UNEXPECTED;
2169LOG_WARN("audit is null", KR(ret));
2170} else if (OB_FAIL(schema_service_->gen_new_schema_version(tenant_id_, new_schema_version))) {
2171LOG_WARN("fail to gen new schema_version", KR(ret), K_(tenant_id));
2172} else if (FALSE_IT(new_audit->set_schema_version(new_schema_version))) {
2173} else if (OB_FAIL(schema_service_impl->get_audit_sql_service().handle_audit_metainfo(
2174*new_audit,
2175AUDIT_MT_ADD,
2176false,
2177new_schema_version,
2178NULL,
2179trans_,
2180public_sql_string))) {
2181LOG_WARN("fail to add audit", KR(ret), K_(tenant_id), K(new_audit));
2182}
2183} // end for
2184}
2185return ret;
2186}
2187
2188int ObCreateTableHelper::create_tables_()
2189{
2190int ret = OB_SUCCESS;
2191ObSchemaService *schema_service_impl = NULL;
2192if (OB_FAIL(check_inner_stat_())) {
2193LOG_WARN("fail to check inner stat", KR(ret));
2194} else if (OB_ISNULL(schema_service_impl = schema_service_->get_schema_service())) {
2195ret = OB_ERR_UNEXPECTED;
2196LOG_WARN("schema_service impl is null", KR(ret));
2197} else {
2198int64_t new_schema_version = OB_INVALID_VERSION;
2199for (int64_t i = 0; OB_SUCC(ret) && i < new_tables_.count(); i++) {
2200ObTableSchema &new_table = new_tables_.at(i);
2201const ObString *ddl_stmt_str = (0 == i) ? &arg_.ddl_stmt_str_ : NULL;
2202const bool need_sync_schema_version = (new_tables_.count() - 1 == i);
2203if (OB_FAIL(schema_service_->gen_new_schema_version(tenant_id_, new_schema_version))) {
2204LOG_WARN("fail to gen new schema_version", KR(ret), K_(tenant_id));
2205} else if (FALSE_IT(new_table.set_schema_version(new_schema_version))) {
2206} else if (OB_FAIL(schema_service_impl->get_table_sql_service().create_table(
2207new_table,
2208trans_,
2209ddl_stmt_str,
2210need_sync_schema_version,
2211false/*is_truncate_table*/))) {
2212LOG_WARN("fail to create table", KR(ret), K(new_table));
2213} else if (OB_FAIL(schema_service_impl->get_table_sql_service().insert_temp_table_info(
2214trans_, new_table))) {
2215LOG_WARN("insert_temp_table_info failed", KR(ret), K(new_table));
2216}
2217} // end for
2218}
2219return ret;
2220}
2221
2222int ObCreateTableHelper::deal_with_mock_fk_parent_tables_()
2223{
2224int ret = OB_SUCCESS;
2225ObSchemaService *schema_service_impl = NULL;
2226if (OB_FAIL(check_inner_stat_())) {
2227LOG_WARN("fail to check inner stat", KR(ret));
2228} else if (OB_ISNULL(schema_service_impl = schema_service_->get_schema_service())) {
2229ret = OB_ERR_UNEXPECTED;
2230LOG_WARN("schema_service impl is null", KR(ret));
2231} else if (OB_UNLIKELY(new_tables_.count() <= 0)) {
2232ret = OB_ERR_UNEXPECTED;
2233LOG_WARN("unexpected table cnt", KR(ret), K(new_tables_.count()));
2234} else {
2235const ObTableSchema &data_table = new_tables_.at(0);
2236const uint64_t data_table_id = data_table.get_table_id();
2237int64_t new_schema_version = OB_INVALID_VERSION;
2238for (int64_t i = 0; OB_SUCC(ret) && i < new_mock_fk_parent_tables_.count(); i++) {
2239ObMockFKParentTableSchema *new_mock_fk_parent_table = new_mock_fk_parent_tables_.at(i);
2240if (OB_ISNULL(new_mock_fk_parent_table)) {
2241ret = OB_ERR_UNEXPECTED;
2242LOG_WARN("mock fk parent table is null", KR(ret));
2243} else if (OB_FAIL(schema_service_->gen_new_schema_version(tenant_id_, new_schema_version))) {
2244LOG_WARN("fail to gen new schema_version", KR(ret), K_(tenant_id));
2245} else {
2246new_mock_fk_parent_table->set_schema_version(new_schema_version);
2247ObMockFKParentTableOperationType operation_type = new_mock_fk_parent_table->get_operation_type();
2248if (MOCK_FK_PARENT_TABLE_OP_CREATE_TABLE_BY_ADD_FK_IN_CHILD_TBALE == operation_type) {
2249// 1. create table: mock fk parent table doesn't exist.
2250if (OB_FAIL(schema_service_impl->get_table_sql_service().add_mock_fk_parent_table(
2251&trans_, *new_mock_fk_parent_table, false /*need_update_foreign_key*/))) {
2252LOG_WARN("fail to add mock fk parent table", KR(ret), KPC(new_mock_fk_parent_table));
2253}
2254} else if (MOCK_FK_PARENT_TABLE_OP_UPDATE_SCHEMA_VERSION == operation_type
2255|| MOCK_FK_PARENT_TABLE_OP_ADD_COLUMN == operation_type) {
2256// 2. alter table: mock fk parent table has new child table.
2257if (OB_FAIL(schema_service_impl->get_table_sql_service().alter_mock_fk_parent_table(
2258&trans_, *new_mock_fk_parent_table))) {
2259LOG_WARN("fail to alter mock fk parent table", KR(ret), KPC(new_mock_fk_parent_table));
2260}
2261} else if (MOCK_FK_PARENT_TABLE_OP_REPLACED_BY_REAL_PREANT_TABLE == operation_type) {
2262// 3. replace table: replace existed mock fk parent table with data table
2263const ObMockFKParentTableSchema *ori_mock_fk_parent_table = NULL;
2264if (OB_UNLIKELY(OB_INVALID_ID == replace_mock_fk_parent_table_id_)) {
2265ret = OB_ERR_UNEXPECTED;
2266LOG_WARN("invalid replace mock fk parent table id", KR(ret), K_(replace_mock_fk_parent_table_id));
2267} else if (OB_FAIL(latest_schema_guard_.get_mock_fk_parent_table_schema(
2268replace_mock_fk_parent_table_id_, ori_mock_fk_parent_table))) {
2269LOG_WARN("fail to get mock fk parent table schema",
2270KR(ret), K_(tenant_id), K_(replace_mock_fk_parent_table_id));
2271} else if (OB_ISNULL(ori_mock_fk_parent_table)) {
2272ret = OB_ERR_UNEXPECTED;
2273LOG_WARN("mock fk parent table not exist, unexpected",
2274KR(ret), K_(tenant_id), K_(replace_mock_fk_parent_table_id));
2275} else {
2276// 3.1. drop mock fk parent table.
2277// 3.2. update foreign keys from mock fk parent table.
2278if (OB_FAIL(schema_service_impl->get_table_sql_service().replace_mock_fk_parent_table(
2279&trans_, *new_mock_fk_parent_table, ori_mock_fk_parent_table))) {
2280LOG_WARN("fail to replace mock fk parent table", KR(ret), KPC(new_mock_fk_parent_table));
2281}
2282
2283// 3.3. update child tables' schema version.
2284for (int64_t j = 0; OB_SUCC(ret) && j < new_mock_fk_parent_table->get_foreign_key_infos().count(); j++) {
2285const ObForeignKeyInfo &foreign_key = new_mock_fk_parent_table->get_foreign_key_infos().at(j);
2286const uint64_t child_table_id = foreign_key.child_table_id_;
2287const ObTableSchema *child_table = NULL;
2288if (OB_FAIL(latest_schema_guard_.get_table_schema(child_table_id, child_table))) {
2289LOG_WARN("fail to get table schema", KR(ret), K_(tenant_id), K(child_table_id));
2290} else if (OB_ISNULL(child_table)) {
2291ret = OB_ERR_UNEXPECTED;
2292LOG_WARN("child table is not exist", KR(ret), K_(tenant_id), K(child_table_id));
2293} else if (OB_FAIL(schema_service_impl->get_table_sql_service().update_data_table_schema_version(
2294trans_, tenant_id_, child_table_id, child_table->get_in_offline_ddl_white_list()))) {
2295LOG_WARN("fail to update child table's schema version", KR(ret), K_(tenant_id), K(child_table_id));
2296}
2297} // end for
2298
2299// 3.4. update data table's schema version at last.
2300if (FAILEDx(schema_service_impl->get_table_sql_service().update_data_table_schema_version(
2301trans_, tenant_id_, data_table_id, false/*in_offline_ddl_white_list*/))) {
2302LOG_WARN("fail to update data table's schema version", KR(ret), K_(tenant_id), K(data_table_id));
2303}
2304}
2305} else {
2306ret = OB_NOT_SUPPORTED;
2307LOG_WARN("mock fk parent table operation type is not supported", KR(ret), K(operation_type));
2308}
2309}
2310} // end for
2311}
2312return ret;
2313}
2314
2315int ObCreateTableHelper::create_tablets_()
2316{
2317int ret = OB_SUCCESS;
2318SCN frozen_scn;
2319ObSchemaGetterGuard schema_guard;
2320ObSchemaService *schema_service_impl = NULL;
2321uint64_t tenant_data_version = 0;
2322
2323if (OB_FAIL(check_inner_stat_())) {
2324LOG_WARN("fail to check inner stat", KR(ret));
2325} else if (OB_ISNULL(schema_service_impl = schema_service_->get_schema_service())) {
2326ret = OB_ERR_UNEXPECTED;
2327LOG_WARN("schema_service impl is null", KR(ret));
2328} else if (OB_FAIL(ObMajorFreezeHelper::get_frozen_scn(tenant_id_, frozen_scn))) {
2329LOG_WARN("failed to get frozen status for create tablet", KR(ret), K_(tenant_id));
2330} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id_, schema_guard))) {
2331LOG_WARN("fail to get tenant schema guard", KR(ret), K_(tenant_id));
2332} else if (OB_UNLIKELY(new_tables_.count() <= 0)) {
2333ret = OB_ERR_UNEXPECTED;
2334LOG_WARN("unexpected table cnt", KR(ret), K(new_tables_.count()));
2335} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id_, tenant_data_version))) {
2336LOG_WARN("get min data version failed", K(ret), K_(tenant_id));
2337} else {
2338ObTableCreator table_creator(
2339tenant_id_,
2340frozen_scn,
2341trans_);
2342// TODO:(yanmu.ztl)
2343// schema_guard is used to get primary table in tablegroup or data table for local index.
2344// - primary table may be incorrect when ddl execute concurrently.
2345ObNewTableTabletAllocator new_table_tablet_allocator(
2346tenant_id_,
2347schema_guard,
2348sql_proxy_,
2349true /*use parallel ddl*/);
2350int64_t last_schema_version = OB_INVALID_VERSION;
2351auto *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
2352if (OB_FAIL(table_creator.init(true/*need_tablet_cnt_check*/))) {
2353LOG_WARN("fail to init table creator", KR(ret));
2354} else if (OB_FAIL(new_table_tablet_allocator.init())) {
2355LOG_WARN("fail to init new table tablet allocator", KR(ret));
2356} else if (OB_ISNULL(tsi_generator)) {
2357ret = OB_ERR_UNEXPECTED;
2358LOG_WARN("tsi schema version generator is null", KR(ret));
2359} else if (OB_FAIL(tsi_generator->get_current_version(last_schema_version))) {
2360LOG_WARN("fail to get end version", KR(ret), K_(tenant_id), K_(arg));
2361} else if (OB_UNLIKELY(last_schema_version <= 0)) {
2362ret = OB_ERR_UNEXPECTED;
2363LOG_WARN("last schema version is invalid", KR(ret), K_(tenant_id), K(last_schema_version));
2364} else {
2365ObArray<const ObTableSchema*> schemas;
2366common::ObArray<share::ObLSID> ls_id_array;
2367ObArray<bool> need_create_empty_majors;
2368for (int64_t i = 0; OB_SUCC(ret) && i < new_tables_.count(); i++) {
2369const ObTableSchema &new_table = new_tables_.at(i);
2370const uint64_t table_id = new_table.get_table_id();
2371if (!new_table.has_tablet()) {
2372// eg. external table ...
2373} else if (!new_table.is_global_index_table()) {
2374if (OB_FAIL(schemas.push_back(&new_table))) {
2375LOG_WARN("fail to push back new table", KR(ret));
2376} else if (OB_FAIL(need_create_empty_majors.push_back(true))) {
2377LOG_WARN("fail to push back need create empty major", KR(ret));
2378}
2379} else {
2380if (OB_FAIL(new_table_tablet_allocator.prepare(trans_, new_table))) {
2381LOG_WARN("fail to prepare ls for global index", KR(ret), K(new_table));
2382} else if (OB_FAIL(new_table_tablet_allocator.get_ls_id_array(ls_id_array))) {
2383LOG_WARN("fail to get ls id array", KR(ret));
2384} else if (OB_FAIL(table_creator.add_create_tablets_of_table_arg(
2385new_table, ls_id_array, tenant_data_version, true/*need create major sstable*/))) {
2386LOG_WARN("create table partitions failed", KR(ret), K(new_table));
2387}
2388}
2389//TODO:(yanmu.ztl) can be optimized into one sql
2390if (FAILEDx(schema_service_impl->get_table_sql_service().insert_ori_schema_version(
2391trans_, tenant_id_, table_id, last_schema_version))) {
2392LOG_WARN("fail to get insert ori schema version",
2393KR(ret), K_(tenant_id), K(table_id), K(last_schema_version));
2394}
2395} // end for
2396
2397if (OB_FAIL(ret)) {
2398} else if (schemas.count() > 0) {
2399const ObTableSchema &data_table = new_tables_.at(0);
2400if (OB_FAIL(new_table_tablet_allocator.prepare(trans_, data_table))) {
2401LOG_WARN("fail to prepare ls for data table", KR(ret));
2402} else if (OB_FAIL(new_table_tablet_allocator.get_ls_id_array(ls_id_array))) {
2403LOG_WARN("fail to get ls id array", KR(ret));
2404} else if (OB_FAIL(table_creator.add_create_tablets_of_tables_arg(
2405schemas, ls_id_array, tenant_data_version, need_create_empty_majors /*need create major sstable*/))) {
2406LOG_WARN("create table partitions failed", KR(ret), K(data_table));
2407} else if (OB_FAIL(table_creator.execute())) {
2408LOG_WARN("execute create partition failed", KR(ret));
2409}
2410}
2411}
2412// finish() will do nothing here, can be removed
2413int tmp_ret = OB_SUCCESS;
2414if (OB_SUCCESS != (tmp_ret = new_table_tablet_allocator.finish(OB_SUCCESS == ret))) {
2415LOG_WARN("fail to finish new table tablet allocator", KR(tmp_ret));
2416}
2417}
2418RS_TRACE(create_tablets);
2419return ret;
2420}
2421
2422int ObCreateTableHelper::add_index_name_to_cache_()
2423{
2424int ret = OB_SUCCESS;
2425if (OB_FAIL(check_inner_stat_())) {
2426LOG_WARN("fail to check inner stat", KR(ret));
2427} else {
2428ObIndexNameChecker &checker = ddl_service_->get_index_name_checker();
2429for (int64_t i = 0; OB_SUCC(ret) && i < new_tables_.count(); i++) {
2430const ObTableSchema &table = new_tables_.at(i);
2431if (table.is_index_table()) {
2432has_index_ = true;
2433if (OB_FAIL(checker.add_index_name(table))) {
2434LOG_WARN("fail to add index name", KR(ret), K(table));
2435}
2436}
2437} // end for
2438}
2439return ret;
2440}
2441