25 #include <mysqld_error.h>
28 #include <mysql/innodb_priv.h>
29 #include <sql_alter.h>
30 #include <sql_class.h>
50 #include "ha_innodb.h"
54 = Alter_inplace_info::ADD_INDEX
55 | Alter_inplace_info::ADD_UNIQUE_INDEX;
59 = Alter_inplace_info::ADD_PK_INDEX
60 | Alter_inplace_info::DROP_PK_INDEX
61 | Alter_inplace_info::CHANGE_CREATE_OPTION
63 | Alter_inplace_info::ALTER_COLUMN_NULLABLE
64 | Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE
65 | Alter_inplace_info::ALTER_COLUMN_ORDER
66 | Alter_inplace_info::DROP_COLUMN
67 | Alter_inplace_info::ADD_COLUMN
76 = INNOBASE_ONLINE_CREATE | INNOBASE_ALTER_REBUILD;
80 = Alter_inplace_info::ALTER_COLUMN_DEFAULT
81 | Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT
82 | Alter_inplace_info::ALTER_COLUMN_STORAGE_TYPE
83 | Alter_inplace_info::ALTER_RENAME;
87 = Alter_inplace_info::DROP_FOREIGN_KEY
88 | Alter_inplace_info::ADD_FOREIGN_KEY;
92 = INNOBASE_ONLINE_CREATE
93 | INNOBASE_FOREIGN_OPERATIONS
94 | Alter_inplace_info::DROP_INDEX
95 | Alter_inplace_info::DROP_UNIQUE_INDEX
96 | Alter_inplace_info::ALTER_COLUMN_NAME;
99 static UNIV_COLD __attribute__((nonnull))
109 my_error(ER_TABLE_DEF_CHANGED, MYF(0));
111 case DB_RECORD_NOT_FOUND:
112 my_error(ER_KEY_NOT_FOUND, MYF(0), table);
115 my_error(ER_LOCK_DEADLOCK, MYF(0));
118 my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
121 my_error(ER_QUERY_INTERRUPTED, MYF(0));
123 case DB_OUT_OF_MEMORY:
124 my_error(ER_OUT_OF_RESOURCES, MYF(0));
126 case DB_OUT_OF_FILE_SPACE:
127 my_error(ER_RECORD_FILE_FULL, MYF(0), table);
130 my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
131 DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
134 my_error(ER_TOO_MANY_CONCURRENT_TRXS, MYF(0));
137 my_error(ER_LOCK_TABLE_FULL, MYF(0));
140 my_error(ER_UNDO_RECORD_TOO_BIG, MYF(0));
143 my_error(ER_NOT_KEYFILE, MYF(0), table);
146 my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
152 my_error(ER_INVALID_USE_OF_NULL, MYF(0));
156 case DB_DUPLICATE_KEY:
163 my_error(ER_GET_ERRNO, MYF(0), error);
173 innobase_fulltext_exist(
177 for (uint
i = 0;
i < table->s->keys;
i++) {
178 if (table->key_info[
i].
flags & HA_FULLTEXT) {
190 static __attribute__((nonnull, warn_unused_result))
192 innobase_need_rebuild(
196 if (ha_alter_info->handler_flags
197 == Alter_inplace_info::CHANGE_CREATE_OPTION
198 && !(ha_alter_info->create_info->used_fields
199 & (HA_CREATE_USED_ROW_FORMAT
200 | HA_CREATE_USED_KEY_BLOCK_SIZE))) {
206 return(!!(ha_alter_info->handler_flags & INNOBASE_ALTER_REBUILD));
224 enum_alter_inplace_result
227 TABLE* altered_table,
230 DBUG_ENTER(
"check_if_supported_inplace_alter");
235 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
239 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
242 if (altered_table->s->fields > REC_MAX_N_USER_FIELDS) {
249 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
256 & ~(INNOBASE_INPLACE_IGNORE
257 | INNOBASE_ALTER_NOREBUILD
258 | INNOBASE_ALTER_REBUILD)) {
262 | Alter_inplace_info::ALTER_COLUMN_TYPE))
264 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE);
265 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
271 & Alter_inplace_info::ADD_FOREIGN_KEY)
274 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_CHECK);
275 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
278 if (!(ha_alter_info->
handler_flags & ~INNOBASE_INPLACE_IGNORE)) {
279 DBUG_RETURN(HA_ALTER_INPLACE_NO_LOCK);
287 & Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE)
288 && !thd_is_strict_mode(user_thd)) {
290 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL);
291 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
299 & (Alter_inplace_info::ADD_PK_INDEX
300 | Alter_inplace_info::ADD_UNIQUE_INDEX))) {
302 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_IGNORE);
303 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
309 & (Alter_inplace_info::ADD_PK_INDEX
310 | Alter_inplace_info::DROP_PK_INDEX))
311 == Alter_inplace_info::DROP_PK_INDEX) {
313 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOPK);
314 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
322 & Alter_inplace_info::ALTER_COLUMN_NULLABLE)) {
323 uint primary_key = altered_table->s->primary_key;
326 if (UNIV_UNLIKELY(primary_key >= MAX_KEY)
329 ER_PRIMARY_CANT_HAVE_NULL);
330 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
343 new_key < ha_alter_info->key_info_buffer
347 key_part < new_key->key_part + new_key->user_defined_key_parts;
351 DBUG_ASSERT(key_part->fieldnr
352 < altered_table->s->fields);
355 for (uint fieldnr = 0; (new_field = cf_it++);
357 if (fieldnr == key_part->fieldnr) {
362 DBUG_ASSERT(new_field);
364 key_part->field = altered_table->field[
370 key_part->null_offset = key_part->field->null_offset();
371 key_part->null_bit = key_part->field->null_bit;
373 if (new_field->field) {
380 & Alter_inplace_info::ADD_COLUMN);
384 if (prebuilt->
table->fts
385 && innobase_fulltext_exist(altered_table)
388 key_part->field->field_name,
391 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_HIDDEN_FTS);
392 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
395 DBUG_ASSERT((MTYP_TYPENR(key_part->field->unireg_check)
396 == Field::NEXT_NUMBER)
397 == !!(key_part->field->flags
398 & AUTO_INCREMENT_FLAG));
400 if (key_part->field->flags & AUTO_INCREMENT_FLAG) {
403 DBUG_ASSERT(key_part->field == altered_table
404 -> found_next_number_field);
406 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC);
413 <= table->s->fields);
417 if (prebuilt->
table->fts
418 && innobase_fulltext_exist(altered_table)) {
428 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS);
429 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
437 for (Field** fp = table->field; *fp; fp++) {
439 & (FIELD_IS_RENAMED | FIELD_IS_DROPPED))) {
448 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS);
449 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
460 & Alter_inplace_info::ADD_PK_INDEX)
461 || innobase_need_rebuild(ha_alter_info))
462 && (innobase_fulltext_exist(altered_table)
471 if (prebuilt->
table->fts) {
474 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
477 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS);
479 & Alter_inplace_info::ADD_INDEX)) {
489 if (key->
flags & HA_FULLTEXT) {
490 DBUG_ASSERT(!(key->
flags & HA_KEYFLAG_MASK
494 | HA_BINARY_PACK_KEY)));
496 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS);
504 ? HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE
505 : HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE);
511 static __attribute__((nonnull(1,3,5,7)))
513 innobase_init_foreign(
530 ulint referenced_num_field)
535 if (constraint_name) {
546 foreign->heap, db_len + strlen(constraint_name) + 2));
548 ut_memcpy(foreign->id, table->name, db_len);
549 foreign->id[db_len] =
'/';
550 strcpy(foreign->id + db_len + 1, constraint_name);
557 existing_foreign != 0;
559 foreign_list, existing_foreign)) {
561 if (
ut_strcmp(existing_foreign->id, foreign->id) == 0) {
567 foreign->foreign_table =
table;
569 foreign->heap, table->name);
572 foreign->foreign_index =
index;
573 foreign->
n_fields = (
unsigned int) num_field;
575 foreign->foreign_col_names =
static_cast<const char**
>(
578 for (ulint
i = 0;
i < foreign->n_fields;
i++) {
580 foreign->heap, column_names[
i]);
587 foreign->heap, referenced_table_name);
590 foreign->referenced_col_names =
static_cast<const char**
>(
592 referenced_num_field *
sizeof(
void*)));
594 for (ulint
i = 0;
i < foreign->n_fields;
i++) {
595 foreign->referenced_col_names[
i]
597 referenced_column_names[
i]);
606 static __attribute__((nonnull, warn_unused_result))
608 innobase_check_fk_option(
612 if (!foreign->foreign_index) {
619 for (ulint j = 0; j < foreign->n_fields; j++) {
621 foreign->foreign_index, j)->
prtype)
638 static __attribute__((nonnull, warn_unused_result))
640 innobase_set_foreign_key_option(
646 ut_ad(!foreign->type);
648 switch (fk_key->delete_opt) {
649 case Foreign_key::FK_OPTION_NO_ACTION:
650 case Foreign_key::FK_OPTION_RESTRICT:
651 case Foreign_key::FK_OPTION_DEFAULT:
654 case Foreign_key::FK_OPTION_CASCADE:
657 case Foreign_key::FK_OPTION_SET_NULL:
662 switch (fk_key->update_opt) {
663 case Foreign_key::FK_OPTION_NO_ACTION:
664 case Foreign_key::FK_OPTION_RESTRICT:
665 case Foreign_key::FK_OPTION_DEFAULT:
668 case Foreign_key::FK_OPTION_CASCADE:
671 case Foreign_key::FK_OPTION_SET_NULL:
676 return(innobase_check_fk_option(foreign));
683 static __attribute__((nonnull, warn_unused_result))
685 innobase_find_equiv_index(
687 const
char*const* col_names,
694 for (uint
i = 0;
i < n_add;
i++) {
695 const KEY* key = &keys[add[
i]];
702 for (uint j = 0; j < n_cols; j++) {
705 = key_part.field->pack_length();
710 if (key_part.field->type() == MYSQL_TYPE_VARCHAR) {
712 key_part.field)->length_bytes;
715 if (key_part.length < col_len) {
723 key_part.field->field_name)) {
739 static __attribute__((nonnull(1,2,6), warn_unused_result))
741 innobase_find_fk_index(
746 const
char** col_names,
753 const
char** columns,
758 index = dict_table_get_first_index(table);
760 while (index != NULL) {
761 if (!(index->
type & DICT_FTS)
763 table, col_names, columns, n_cols,
764 index, NULL,
true, 0)) {
765 for (ulint
i = 0;
i < n_drop_index;
i++) {
766 if (index == drop_index[
i]) {
776 index = dict_table_get_next_index(index);
786 static __attribute__((nonnull(1,2,3,7,8), warn_unused_result))
788 innobase_get_foreign_key_info(
795 const
char** col_names,
807 char* referenced_table_name = NULL;
809 Alter_info* alter_info = ha_alter_info->alter_info;
815 while ((key=key_iterator++)) {
816 if (key->type != Key::FOREIGN_KEY) {
825 ulint referenced_num_col = 0;
827 char* db_namep = NULL;
828 char* tbl_namep = NULL;
829 ulint db_name_len = 0;
830 ulint tbl_name_len = 0;
832 char db_name[MAX_DATABASE_NAME_LEN];
838 if (fk_key->columns.elements > 0) {
846 while ((column = key_part_iterator++)) {
847 column_names[
i] = column->field_name.str;
852 index = innobase_find_fk_index(
855 drop_index, n_drop_index,
862 DBUG_EXECUTE_IF(
"innodb_test_no_foreign_idx",
867 if (!index && !innobase_find_equiv_index(
869 ha_alter_info->key_info_buffer,
870 ha_alter_info->index_add_buffer,
871 ha_alter_info->index_add_count)) {
873 ER_FK_NO_INDEX_CHILD,
876 ? fk_key->name.str :
"",
877 table_share->table_name.str);
887 tbl_namep = fk_key->ref_table.str;
888 tbl_name_len = fk_key->ref_table.length;
889 db_namep = fk_key->ref_db.str;
890 db_name_len = fk_key->ref_db.length;
892 ut_ad(fk_key->ref_table.str);
894 memcpy(tbl_name, fk_key->ref_table.str,
895 fk_key->ref_table.length);
896 tbl_name[fk_key->ref_table.length] = 0;
898 tbl_name_len = strlen(tbl_name);
899 tbl_namep = &tbl_name[0];
901 if (fk_key->ref_db.str != NULL) {
902 memcpy(db_name, fk_key->ref_db.str,
903 fk_key->ref_db.length);
904 db_name[fk_key->ref_db.length] = 0;
906 db_name_len = strlen(db_name);
907 db_namep = &db_name[0];
919 add_fk[num_fk]->
heap);
924 DBUG_EXECUTE_IF(
"innodb_test_open_ref_fail",
925 referenced_table = NULL;);
927 if (!referenced_table && trx->check_foreigns) {
929 my_error(ER_FK_CANNOT_OPEN_PARENT,
935 if (fk_key->ref_columns.elements > 0) {
939 fk_key->ref_columns);
941 while ((column = key_part_iterator++)) {
942 referenced_column_names[
i] =
943 column->field_name.str;
948 if (referenced_table) {
952 referenced_column_names,
957 "innodb_test_no_reference_idx",
958 referenced_index = NULL;);
962 if (!referenced_index) {
964 my_error(ER_FK_NO_INDEX_PARENT, MYF(0),
966 ? fk_key->name.str :
"",
971 ut_a(!trx->check_foreigns);
974 referenced_num_col =
i;
977 if (!innobase_init_foreign(
978 add_fk[num_fk], fk_key->name.str,
979 table, index, column_names,
980 num_col, referenced_table_name,
981 referenced_table, referenced_index,
982 referenced_column_names, referenced_num_col)) {
993 correct_option = innobase_set_foreign_key_option(
994 add_fk[num_fk], fk_key);
996 DBUG_EXECUTE_IF(
"innodb_test_wrong_fk_option",
997 correct_option =
false;);
999 if (!correct_option) {
1000 my_error(ER_FK_INCORRECT_OPTION,
1002 table_share->table_name.str,
1003 add_fk[num_fk]->id);
1014 for (ulint i = 0; i <= num_fk; i++) {
1028 innobase_col_to_mysql(
1036 uchar* dest = field->ptr;
1037 ulint flen = field->pack_length();
1039 switch (col->
mtype) {
1046 for (ptr = dest + len; ptr != dest; ) {
1050 if (!(field->flags & UNSIGNED_FLAG)) {
1051 ((byte*) dest)[len - 1] ^= 0x80;
1061 if (field->type() == MYSQL_TYPE_VARCHAR) {
1067 dest, len, flen - field->key_length());
1071 memcpy(dest, data, len);
1085 memcpy(dest, data, len);
1089 case DATA_SYS_CHILD:
1094 case DATA_FIXBINARY:
1108 memcpy(dest, data, len);
1118 struct TABLE* table,
1124 uint n_fields = table->s->fields;
1127 - !!(DICT_TF2_FLAG_IS_SET(index->
table,
1130 for (uint i = 0; i < n_fields; i++) {
1131 Field* field = table->field[
i];
1134 const uchar* ifield;
1140 if (ipos == ULINT_UNDEFINED
1147 ifield = rec_get_nth_field(rec, offsets, ipos, &ilen);
1150 if (ilen == UNIV_SQL_NULL) {
1151 ut_ad(field->real_maybe_null());
1155 field->set_notnull();
1157 innobase_col_to_mysql(
1159 dict_index_get_nth_field(index, ipos)),
1160 ifield, ilen, field);
1170 struct TABLE* table,
1174 uint n_fields = table->s->fields;
1177 - !!(DICT_TF2_FLAG_IS_SET(index->
table,
1180 for (uint i = 0; i < n_fields; i++) {
1181 Field* field = table->field[
i];
1188 if (ipos == ULINT_UNDEFINED
1194 field->set_notnull();
1196 const dfield_t* df = &fields[ipos];
1198 innobase_col_to_mysql(
1200 dict_index_get_nth_field(index, ipos)),
1201 static_cast<const uchar*>(dfield_get_data(df)),
1213 struct TABLE* table,
1217 uint n_fields = table->s->fields;
1224 for (uint i = 0; i < n_fields; i++) {
1225 Field* field = table->field[
i];
1226 const dfield_t* df = dtuple_get_nth_field(row, i);
1233 field->set_notnull();
1235 innobase_col_to_mysql(
1236 dict_table_get_nth_col(itab, i),
1237 static_cast<const uchar*>(dfield_get_data(df)),
1251 uint n_fields = table->s->fields;
1254 for (i = 0; i < n_fields; i++) {
1255 table->field[
i]->set_default();
1262 static __attribute__((nonnull, warn_unused_result))
1264 innobase_check_index_keys(
1271 for (uint key_num = 0; key_num < info->index_add_count;
1273 const KEY& key = info->key_info_buffer[
1274 info->index_add_buffer[key_num]];
1279 for (ulint i = 0; i < key_num; i++) {
1280 const KEY& key2 = info->key_info_buffer[
1281 info->index_add_buffer[
i]];
1283 if (0 == strcmp(key.
name, key2.
name)) {
1284 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
1287 return(ER_WRONG_NAME_FOR_INDEX);
1295 for (index = dict_table_get_first_index(innodb_table);
1296 index; index = dict_table_get_next_index(index)) {
1298 if (!strcmp(key.
name, index->
name)) {
1306 for (uint i = 0; i < info->index_drop_count;
1309 = info->index_drop_buffer[
i];
1311 if (0 == strcmp(key.
name, drop_key->
name)) {
1316 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key.
name);
1318 return(ER_WRONG_NAME_FOR_INDEX);
1330 &is_unsigned, field)) {
1341 if (field->type() == MYSQL_TYPE_VARCHAR) {
1342 if (key_part1.length
1343 >= field->pack_length()
1349 if (key_part1.length
1350 >= field->pack_length()) {
1355 my_error(ER_WRONG_KEY_COLUMN, MYF(0),
1357 return(ER_WRONG_KEY_COLUMN);
1363 for (ulint j = 0; j <
i; j++) {
1367 if (key_part1.fieldnr != key_part2.fieldnr) {
1371 my_error(ER_WRONG_KEY_COLUMN, MYF(0),
1373 return(ER_WRONG_KEY_COLUMN);
1383 static __attribute__((nonnull(2,3)))
1385 innobase_create_index_field_def(
1387 const
TABLE* altered_table,
1399 DBUG_ENTER(
"innobase_create_index_field_def");
1404 field = altered_table
1405 ? altered_table->field[key_part->fieldnr]
1409 index_field->col_no = key_part->fieldnr;
1413 if (DATA_BLOB == col_type
1414 || (key_part->length < field->pack_length()
1415 && field->type() != MYSQL_TYPE_VARCHAR)
1416 || (field->type() == MYSQL_TYPE_VARCHAR
1417 && key_part->length < field->pack_length()
1420 index_field->prefix_len = key_part->length;
1422 index_field->prefix_len = 0;
1430 static __attribute__((nonnull))
1432 innobase_create_index_def(
1434 const
TABLE* altered_table,
1447 const KEY* key = &keys[key_number];
1453 DBUG_ENTER(
"innobase_create_index_def");
1454 DBUG_ASSERT(!key_clustered || new_clustered);
1459 index->ind_type = 0;
1460 index->key_number = key_number;
1461 index->n_fields = n_fields;
1462 len = strlen(key->
name) + 1;
1463 index->name = index_name =
static_cast<char*
>(
1466 if (!new_clustered) {
1470 memcpy(index_name, key->
name, len);
1472 if (key->
flags & HA_NOSAME) {
1476 if (key_clustered) {
1477 DBUG_ASSERT(!(key->
flags & HA_FULLTEXT));
1479 }
else if (key->
flags & HA_FULLTEXT) {
1480 DBUG_ASSERT(!(key->
flags & HA_KEYFLAG_MASK
1483 | HA_BINARY_PACK_KEY)));
1484 DBUG_ASSERT(!(key->
flags & HA_NOSAME));
1485 DBUG_ASSERT(!index->ind_type);
1486 index->ind_type |= DICT_FTS;
1489 if (!new_clustered) {
1490 altered_table = NULL;
1493 for (i = 0; i < n_fields; i++) {
1494 innobase_create_index_field_def(
1495 altered_table, &key->key_part[i], &index->fields[i]);
1506 innobase_fts_check_doc_id_col(
1510 const TABLE* altered_table,
1513 ulint* fts_doc_col_no)
1518 *fts_doc_col_no = ULINT_UNDEFINED;
1520 const uint n_cols = altered_table->s->fields;
1523 for (i = 0; i < n_cols; i++) {
1524 const Field* field = altered_table->field[
i];
1526 if (my_strcasecmp(system_charset_info,
1532 my_error(ER_WRONG_COLUMN_NAME, MYF(0),
1534 }
else if (field->type() != MYSQL_TYPE_LONGLONG
1535 || field->pack_length() != 8
1536 || field->real_maybe_null()
1537 || !(field->flags & UNSIGNED_FLAG)) {
1538 my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN, MYF(0),
1541 *fts_doc_col_no =
i;
1551 for (; i + DATA_N_SYS_COLS < (uint) table->
n_cols; i++) {
1558 col = dict_table_get_nth_col(table, i);
1568 *fts_doc_col_no =
i;
1581 enum fts_doc_id_index_enum
1582 innobase_fts_check_doc_id_index(
1585 const TABLE* altered_table,
1587 ulint* fts_doc_col_no)
1595 if (altered_table) {
1599 for (uint i = 0; i < altered_table->s->keys; i++) {
1600 const KEY& key = altered_table->key_info[
i];
1607 if ((key.
flags & HA_NOSAME)
1610 && !strcmp(key.key_part[0].field->field_name,
1612 if (fts_doc_col_no) {
1613 *fts_doc_col_no = ULINT_UNDEFINED;
1615 return(FTS_EXIST_DOC_ID_INDEX);
1617 return(FTS_INCORRECT_DOC_ID_INDEX);
1623 return(FTS_NOT_EXIST_DOC_ID_INDEX);
1626 for (index = dict_table_get_first_index(table);
1627 index; index = dict_table_get_next_index(index)) {
1638 return(FTS_INCORRECT_DOC_ID_INDEX);
1643 field = dict_index_get_nth_field(index, 0);
1649 && field->
col->
prtype & DATA_NOT_NULL) {
1650 if (fts_doc_col_no) {
1653 return(FTS_EXIST_DOC_ID_INDEX);
1655 return(FTS_INCORRECT_DOC_ID_INDEX);
1661 return(FTS_NOT_EXIST_DOC_ID_INDEX);
1669 enum fts_doc_id_index_enum
1670 innobase_fts_check_doc_id_index_in_def(
1673 const KEY* key_info)
1677 for (ulint j = 0; j < n_key; j++) {
1678 const KEY* key = &key_info[j];
1686 if (!(key->
flags & HA_NOSAME)
1689 || strcmp(key->key_part[0].field->field_name,
1691 return(FTS_INCORRECT_DOC_ID_INDEX);
1694 return(FTS_EXIST_DOC_ID_INDEX);
1697 return(FTS_NOT_EXIST_DOC_ID_INDEX);
1714 static __attribute__((nonnull, warn_unused_result, malloc))
1716 innobase_create_key_defs(
1723 const
TABLE* altered_table,
1729 bool got_default_clust,
1731 ulint& fts_doc_id_col,
1733 bool& add_fts_doc_id,
1736 bool& add_fts_doc_idx)
1743 const uint*
const add
1744 = ha_alter_info->index_add_buffer;
1745 const KEY*
const key_info
1746 = ha_alter_info->key_info_buffer;
1748 DBUG_ENTER(
"innobase_create_key_defs");
1749 DBUG_ASSERT(!add_fts_doc_id || add_fts_doc_idx);
1750 DBUG_ASSERT(ha_alter_info->index_add_count == n_add);
1755 new_primary = n_add > 0
1756 && !my_strcasecmp(system_charset_info,
1757 key_info[*add].name,
"PRIMARY");
1765 if (n_add > 0 && !new_primary && got_default_clust
1766 && (key_info[*add].flags & HA_NOSAME)
1767 && !(key_info[*add].flags & HA_KEY_HAS_PART_KEY_SEG)) {
1772 while (key_part--) {
1773 const uint maybe_null
1774 = key_info[*add].key_part[key_part].key_type
1775 & FIELDFLAG_MAYBE_NULL;
1776 DBUG_ASSERT(!maybe_null
1777 == !key_info[*add].key_part[key_part].
1778 field->real_maybe_null());
1781 new_primary =
false;
1787 const bool rebuild = new_primary || add_fts_doc_id
1788 || innobase_need_rebuild(ha_alter_info);
1793 heap,
sizeof *indexdef
1794 * (ha_alter_info->key_count
1796 + got_default_clust)));
1799 ulint primary_key_number;
1802 DBUG_ASSERT(n_add > 0);
1803 primary_key_number = *add;
1804 }
else if (got_default_clust) {
1814 primary_key_number = ULINT_UNDEFINED;
1815 goto created_clustered;
1817 primary_key_number = 0;
1821 innobase_create_index_def(
1822 altered_table, key_info, primary_key_number,
1823 TRUE, TRUE, indexdef++, heap);
1828 for (ulint i = 0; i < ha_alter_info->key_count; i++) {
1829 if (i == primary_key_number) {
1833 innobase_create_index_def(
1834 altered_table, key_info, i, TRUE, FALSE,
1837 if (indexdef->
ind_type & DICT_FTS) {
1845 if (n_fts_add > 0) {
1847 && !innobase_fts_check_doc_id_col(
1848 NULL, altered_table,
1850 fts_doc_id_col = altered_table->s->
fields;
1851 add_fts_doc_id =
true;
1854 if (!add_fts_doc_idx) {
1855 fts_doc_id_index_enum
ret;
1858 ret = innobase_fts_check_doc_id_index(
1859 NULL, altered_table, &doc_col_no);
1862 ut_ad(ret != FTS_INCORRECT_DOC_ID_INDEX);
1864 if (ret == FTS_NOT_EXIST_DOC_ID_INDEX) {
1865 add_fts_doc_idx =
true;
1867 ut_ad(ret == FTS_EXIST_DOC_ID_INDEX);
1868 ut_ad(doc_col_no == ULINT_UNDEFINED
1869 || doc_col_no == fts_doc_id_col);
1876 for (ulint i = 0; i < n_add; i++) {
1877 innobase_create_index_def(
1878 altered_table, key_info, add[i], FALSE, FALSE,
1881 if (indexdef->
ind_type & DICT_FTS) {
1889 DBUG_ASSERT(indexdefs + n_add == indexdef);
1891 if (add_fts_doc_idx) {
1904 ut_ad(!add_fts_doc_id
1905 || fts_doc_id_col == altered_table->s->fields);
1908 index->
name = index_name =
static_cast<char*
>(
1922 DBUG_ASSERT(indexdef > indexdefs);
1923 DBUG_ASSERT((ulint) (indexdef - indexdefs)
1924 <= ha_alter_info->key_count
1925 + add_fts_doc_idx + got_default_clust);
1926 DBUG_ASSERT(ha_alter_info->index_add_count <= n_add);
1927 DBUG_RETURN(indexdefs);
1933 static __attribute__((nonnull, warn_unused_result))
1935 innobase_check_column_length(
1938 const
KEY* key_info)
1940 for (ulint key_part = 0; key_part < key_info->user_defined_key_parts; key_part++) {
1941 if (key_info->key_part[key_part].length > max_col_len) {
1957 const ulint* add_key_numbers;
1959 ulint num_to_add_index;
1963 const ulint num_to_drop_index;
1967 const ulint num_to_drop_fk;
1971 const ulint num_to_add_fk;
1983 const ulint* col_map;
1985 const char** col_names;
1987 const ulint add_autoinc;
1993 ulonglong max_autoinc;
1995 const char* tmp_name;
1999 ulint num_to_drop_arg,
2001 ulint num_to_drop_fk_arg,
2003 ulint num_to_add_fk_arg,
2007 const char** col_names_arg,
2008 ulint add_autoinc_arg,
2009 ulonglong autoinc_col_min_value_arg,
2010 ulonglong autoinc_col_max_value_arg) :
2012 prebuilt (prebuilt_arg),
2013 add_index (0), add_key_numbers (0), num_to_add_index (0),
2014 drop_index (drop_arg), num_to_drop_index (num_to_drop_arg),
2015 drop_fk (drop_fk_arg), num_to_drop_fk (num_to_drop_fk_arg),
2016 add_fk (add_fk_arg), num_to_add_fk (num_to_add_fk_arg),
2017 online (online_arg), heap (heap_arg), trx (0),
2018 old_table (prebuilt_arg->table),
2019 new_table (new_table_arg),
2020 col_map (0), col_names (col_names_arg),
2021 add_autoinc (add_autoinc_arg),
2023 sequence(prebuilt->trx->mysql_thd,
2024 autoinc_col_min_value_arg, autoinc_col_max_value_arg),
2029 for (ulint i = 0; i < num_to_add_index; i++) {
2030 ut_ad(!add_index[i]->to_be_dropped);
2032 for (ulint i = 0; i < num_to_drop_index; i++) {
2033 ut_ad(drop_index[i]->to_be_dropped);
2040 ~ha_innobase_inplace_ctx()
2047 bool need_rebuild ()
const {
return(old_table != new_table); }
2051 ha_innobase_inplace_ctx(
const ha_innobase_inplace_ctx&);
2052 ha_innobase_inplace_ctx& operator=(
const ha_innobase_inplace_ctx&);
2060 online_retry_drop_indexes_low(
2083 static __attribute__((nonnull))
2085 online_retry_drop_indexes(
2090 if (table->drop_aborted) {
2095 row_mysql_lock_data_dictionary(trx);
2096 online_retry_drop_indexes_low(table, trx);
2104 dict_table_check_for_dup_indexes(table, CHECK_ALL_COMPLETE);
2106 ut_a(!table->drop_aborted);
2113 static __attribute__((nonnull))
2115 online_retry_drop_indexes_with_trx(
2121 ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
2126 if (table->drop_aborted) {
2132 online_retry_drop_indexes_low(table, trx);
2142 inline __attribute__((pure, nonnull, warn_unused_result))
2144 innobase_dropping_foreign(
2150 while (n_drop_fk--) {
2151 if (*drop_fk++ == foreign) {
2169 static __attribute__((pure, nonnull, warn_unused_result))
2171 innobase_check_foreigns_low(
2176 const
char* col_name,
2184 user_table->foreign_list);
2187 if (!drop && !(foreign->type
2193 if (innobase_dropping_foreign(foreign, drop_fk, n_drop_fk)) {
2197 for (
unsigned f = 0; f < foreign->n_fields; f++) {
2198 if (!strcmp(foreign->foreign_col_names[f],
2201 ? ER_FK_COLUMN_CANNOT_DROP
2202 : ER_FK_COLUMN_NOT_NULL, MYF(0),
2203 col_name, foreign->id);
2219 user_table->referenced_list);
2222 if (innobase_dropping_foreign(foreign, drop_fk, n_drop_fk)) {
2226 for (
unsigned f = 0; f < foreign->n_fields; f++) {
2227 char display_name[FN_REFLEN];
2229 if (strcmp(foreign->referenced_col_names[f],
2235 display_name, (
sizeof display_name) - 1,
2236 foreign->foreign_table_name,
2237 strlen(foreign->foreign_table_name),
2240 my_error(ER_FK_COLUMN_CANNOT_DROP_CHILD,
2241 MYF(0), col_name, foreign->id,
2262 static __attribute__((pure, nonnull, warn_unused_result))
2264 innobase_check_foreigns(
2267 const
TABLE* altered_table,
2268 const
TABLE* old_table,
2274 ha_alter_info->alter_info->create_list);
2276 for (Field** fp = old_table->field; *fp; fp++) {
2280 ut_ad(!(*fp)->real_maybe_null()
2281 == !!((*fp)->flags & NOT_NULL_FLAG));
2283 while ((new_field = cf_it++)) {
2284 if (new_field->field == *fp) {
2289 if (!new_field || (new_field->flags & NOT_NULL_FLAG)) {
2290 if (innobase_check_foreigns_low(
2291 user_table, drop_fk, n_drop_fk,
2292 (*fp)->field_name, !new_field)) {
2307 static __attribute__((nonnull))
2309 innobase_build_col_map_add(
2316 if (field->is_real_null()) {
2321 ulint
size = field->pack_length();
2326 dfield, buf, TRUE, field->ptr, size, comp);
2341 static __attribute__((nonnull(1,2,3,4,5,7), warn_unused_result))
2343 innobase_build_col_map(
2346 const
TABLE* altered_table,
2353 DBUG_ENTER(
"innobase_build_col_map");
2354 DBUG_ASSERT(altered_table != table);
2355 DBUG_ASSERT(new_table != old_table);
2357 >= altered_table->s->fields + DATA_N_SYS_COLS);
2359 >= table->s->fields + DATA_N_SYS_COLS);
2360 DBUG_ASSERT(!!add_cols == !!(ha_alter_info->handler_flags
2361 & Alter_inplace_info::ADD_COLUMN));
2365 ulint* col_map =
static_cast<ulint*
>(
2369 ha_alter_info->alter_info->create_list);
2373 for (uint old_i = 0; old_i + DATA_N_SYS_COLS < old_table->n_cols;
2375 col_map[old_i] = ULINT_UNDEFINED;
2379 for (uint old_i = 0; table->field[old_i]; old_i++) {
2380 const Field* field = table->field[old_i];
2381 if (new_field->field == field) {
2387 innobase_build_col_map_add(
2388 heap, dtuple_get_nth_field(add_cols, i),
2389 altered_table->field[i],
2395 DBUG_ASSERT(i == altered_table->s->fields);
2397 i = table->s->fields;
2400 if (i + DATA_N_SYS_COLS < old_table->n_cols) {
2403 DBUG_ASSERT(DICT_TF2_FLAG_IS_SET(old_table,
2405 DBUG_ASSERT(i + DATA_N_SYS_COLS + 1 == old_table->n_cols);
2407 old_table, table->s->fields),
2409 if (altered_table->s->fields + DATA_N_SYS_COLS
2410 < new_table->n_cols) {
2411 DBUG_ASSERT(DICT_TF2_FLAG_IS_SET(
2414 DBUG_ASSERT(altered_table->s->fields
2415 + DATA_N_SYS_COLS + 1
2416 == new_table->n_cols);
2417 col_map[
i] = altered_table->s->fields;
2419 DBUG_ASSERT(!DICT_TF2_FLAG_IS_SET(
2422 col_map[
i] = ULINT_UNDEFINED;
2427 DBUG_ASSERT(!DICT_TF2_FLAG_IS_SET(
2432 for (; i < old_table->n_cols; i++) {
2433 col_map[
i] = i + new_table->n_cols - old_table->n_cols;
2436 DBUG_RETURN(col_map);
2447 innobase_drop_fts_index_table(
2454 for (
dict_index_t* index = dict_table_get_first_index(table);
2456 index = dict_table_get_next_index(index)) {
2457 if (index->type & DICT_FTS) {
2462 if (err != DB_SUCCESS) {
2477 static __attribute__((nonnull, warn_unused_result))
2479 innobase_get_col_names(
2482 const
TABLE* altered_table,
2489 DBUG_ENTER(
"innobase_get_col_names");
2490 DBUG_ASSERT(user_table->n_def > altered_table->s->fields);
2491 DBUG_ASSERT(ha_alter_info->handler_flags
2492 & Alter_inplace_info::ALTER_COLUMN_NAME);
2494 cols =
static_cast<const char**
>(
2497 for (i = 0; i < altered_table->s->fields; i++) {
2498 const Field* field = altered_table->field[
i];
2499 cols[
i] = field->field_name;
2505 while (++i < user_table->n_def) {
2506 cols[
i] = cols[i - 1] + strlen(cols[i - 1]) + 1;
2528 static __attribute__((warn_unused_result, nonnull(1,2,3,4)))
2530 prepare_inplace_alter_table_dict(
2533 const
TABLE* altered_table,
2534 const
TABLE* old_table,
2538 ulint fts_doc_id_col,
2539 bool add_fts_doc_id,
2540 bool add_fts_doc_id_idx)
2542 bool dict_locked =
false;
2543 ulint* add_key_nums;
2547 ulint new_clustered = 0;
2549 ulint num_fts_index;
2550 ha_innobase_inplace_ctx*ctx;
2552 DBUG_ENTER(
"prepare_inplace_alter_table_dict");
2554 ctx =
static_cast<ha_innobase_inplace_ctx*
>
2555 (ha_alter_info->handler_ctx);
2557 DBUG_ASSERT((ctx->add_autoinc != ULINT_UNDEFINED)
2558 == (ctx->sequence.m_max_value > 0));
2559 DBUG_ASSERT(!ctx->num_to_drop_index == !ctx->drop_index);
2560 DBUG_ASSERT(!ctx->num_to_drop_fk == !ctx->drop_fk);
2561 DBUG_ASSERT(!add_fts_doc_id || add_fts_doc_id_idx);
2562 DBUG_ASSERT(!add_fts_doc_id_idx
2563 || innobase_fulltext_exist(altered_table));
2564 DBUG_ASSERT(!ctx->add_cols);
2565 DBUG_ASSERT(!ctx->add_index);
2566 DBUG_ASSERT(!ctx->add_key_numbers);
2567 DBUG_ASSERT(!ctx->num_to_add_index);
2569 user_table = ctx->new_table;
2571 trx_start_if_not_started_xa(ctx->prebuilt->trx);
2583 ctx->num_to_add_index = ha_alter_info->index_add_count;
2585 index_defs = innobase_create_key_defs(
2586 ctx->heap, ha_alter_info, altered_table, ctx->num_to_add_index,
2589 fts_doc_id_col, add_fts_doc_id, add_fts_doc_id_idx);
2593 if (num_fts_index > 1) {
2594 my_error(ER_INNODB_FT_LIMIT, MYF(0));
2600 }
else if (ctx->add_autoinc == ULINT_UNDEFINED
2601 && num_fts_index == 0
2602 && (!innobase_need_rebuild(ha_alter_info)
2603 || !innobase_fulltext_exist(altered_table))) {
2609 my_error(ER_NOT_SUPPORTED_YET, MYF(0),
2610 thd_query_string(ctx->prebuilt->trx->mysql_thd)->str);
2617 DBUG_ASSERT(!add_fts_doc_id || new_clustered);
2618 DBUG_ASSERT(!!new_clustered ==
2619 (innobase_need_rebuild(ha_alter_info)
2620 || add_fts_doc_id));
2626 *
sizeof *ctx->add_index));
2627 ctx->add_key_numbers = add_key_nums =
static_cast<ulint*
>(
2629 *
sizeof *ctx->add_key_numbers));
2642 ctx->prebuilt->trx, ctx->new_table, LOCK_S);
2644 if (error != DB_SUCCESS) {
2646 goto error_handling;
2653 row_mysql_lock_data_dictionary(ctx->trx);
2664 online_retry_drop_indexes_low(ctx->new_table, ctx->trx);
2666 ut_d(dict_table_check_for_dup_indexes(
2667 ctx->new_table, CHECK_ABORTED_OK));
2672 if (new_clustered) {
2673 const char* new_table_name
2674 = dict_mem_create_temporary_tablename(
2676 ctx->new_table->name,
2677 ctx->new_table->id);
2681 if (innobase_check_foreigns(
2682 ha_alter_info, altered_table, old_table,
2683 user_table, ctx->drop_fk, ctx->num_to_drop_fk)) {
2684 goto new_clustered_failed;
2687 n_cols = altered_table->s->
fields;
2689 if (add_fts_doc_id) {
2692 DBUG_ASSERT(add_fts_doc_id_idx);
2698 DBUG_ASSERT(!add_fts_doc_id_idx || (flags2 &
DICT_TF2_FTS));
2704 my_error(ER_TABLE_EXISTS_ERROR, MYF(0),
2706 goto new_clustered_failed;
2711 new_table_name, 0, n_cols, flags, flags2);
2714 ctx->col_names = NULL;
2717 ctx->new_table->data_dir_path =
2722 for (uint i = 0; i < altered_table->s->fields; i++) {
2723 const Field* field = altered_table->field[
i];
2726 = (ulint) field->type();
2729 &is_unsigned, field);
2735 ut_a(field_type <= MAX_CHAR_COLL_NUM);
2737 if (!field->real_maybe_null()) {
2738 field_type |= DATA_NOT_NULL;
2741 if (field->binary()) {
2742 field_type |= DATA_BINARY_TYPE;
2746 field_type |= DATA_UNSIGNED;
2750 charset_no = (ulint) field->charset()->number;
2752 if (charset_no > MAX_CHAR_COLL_NUM) {
2755 my_error(ER_WRONG_KEY_COLUMN, MYF(0),
2757 goto new_clustered_failed;
2763 col_len = field->pack_length();
2771 if (field->type() == MYSQL_TYPE_VARCHAR) {
2774 field)->length_bytes;
2776 col_len -= length_bytes;
2778 if (length_bytes == 2) {
2779 field_type |= DATA_LONG_TRUE_VARCHAR;
2785 my_error(ER_WRONG_COLUMN_NAME, MYF(0),
2787 goto new_clustered_failed;
2791 ctx->new_table, ctx->heap,
2798 if (add_fts_doc_id) {
2800 ctx->new_table->fts->doc_col = fts_doc_id_col;
2801 ut_ad(fts_doc_id_col == altered_table->s->fields);
2802 }
else if (ctx->new_table->fts) {
2803 ctx->new_table->fts->doc_col = fts_doc_id_col;
2807 ctx->new_table, ctx->trx,
false);
2819 ctx->new_table->name, TRUE, FALSE,
2821 ut_a(ctx->new_table == temp_table);
2825 DBUG_ASSERT(ctx->new_table->n_ref_count == 1);
2828 my_error(ER_TABLESPACE_EXISTS, MYF(0),
2830 goto new_clustered_failed;
2831 case DB_DUPLICATE_KEY:
2832 my_error(HA_ERR_TABLE_EXIST, MYF(0),
2833 altered_table->s->table_name.str);
2834 goto new_clustered_failed;
2836 my_error_innodb(error, table_name, flags);
2837 new_clustered_failed:
2838 DBUG_ASSERT(ctx->trx != ctx->prebuilt->trx);
2843 online_retry_drop_indexes_with_trx(
2844 user_table, ctx->trx);
2848 if (ha_alter_info->handler_flags
2849 & Alter_inplace_info::ADD_COLUMN) {
2859 ctx->col_map = innobase_build_col_map(
2860 ha_alter_info, altered_table, old_table,
2861 ctx->new_table, user_table,
2862 add_cols, ctx->heap);
2863 ctx->add_cols = add_cols;
2865 DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info));
2867 if (!ctx->new_table->fts
2868 && innobase_fulltext_exist(altered_table)) {
2871 ctx->new_table->fts->doc_col = fts_doc_id_col;
2877 DBUG_ASSERT(ctx->new_table->id != 0);
2878 ctx->trx->table_id = ctx->new_table->id;
2882 for (ulint a = 0; a < ctx->num_to_add_index; a++) {
2885 ctx->trx, ctx->new_table,
2890 if (!ctx->add_index[a]) {
2891 error = ctx->trx->error_state;
2892 DBUG_ASSERT(error != DB_SUCCESS);
2893 goto error_handling;
2896 if (ctx->add_index[a]->type & DICT_FTS) {
2897 DBUG_ASSERT(num_fts_index);
2898 DBUG_ASSERT(!fts_index);
2899 DBUG_ASSERT(ctx->add_index[a]->type == DICT_FTS);
2900 fts_index = ctx->add_index[a];
2914 ut_ad(!ctx->add_index[a]->online_log);
2915 }
else if (ctx->add_index[a]->type & DICT_FTS) {
2919 DBUG_EXECUTE_IF(
"innodb_OOM_prepare_inplace_alter",
2920 error = DB_OUT_OF_MEMORY;
2921 goto error_handling;);
2922 rw_lock_x_lock(&ctx->add_index[a]->lock);
2924 NULL,
true, NULL, NULL);
2925 rw_lock_x_unlock(&ctx->add_index[a]->lock);
2928 error = DB_OUT_OF_MEMORY;
2929 goto error_handling;
2934 ut_ad(new_clustered == ctx->need_rebuild());
2936 DBUG_EXECUTE_IF(
"innodb_OOM_prepare_inplace_alter",
2937 error = DB_OUT_OF_MEMORY;
2938 goto error_handling;);
2940 if (new_clustered && ctx->online) {
2942 dict_index_t* clust_index = dict_table_get_first_index(
2945 rw_lock_x_lock(&clust_index->
lock);
2947 clust_index, ctx->new_table,
2948 !(ha_alter_info->handler_flags
2949 & Alter_inplace_info::ADD_PK_INDEX),
2950 ctx->add_cols, ctx->col_map);
2951 rw_lock_x_unlock(&clust_index->
lock);
2954 error = DB_OUT_OF_MEMORY;
2955 goto error_handling;
2981 ut_ad(ctx->trx->dict_operation_lock_mode == RW_X_LATCH);
2983 #ifdef UNIV_SYNC_DEBUG
2994 DBUG_EXECUTE_IF(
"innodb_test_fail_after_fts_index_table",
2996 goto error_handling;);
2998 if (error != DB_SUCCESS) {
2999 goto error_handling;
3002 trx_start_for_ddl(ctx->trx, op);
3004 if (!ctx->new_table->fts
3005 || ib_vector_size(ctx->new_table->fts->indexes) == 0) {
3007 ctx->trx, ctx->new_table,
3008 user_table->
name, TRUE);
3011 "innodb_test_fail_after_fts_common_table",
3014 if (error != DB_SUCCESS) {
3015 goto error_handling;
3018 ctx->new_table->fts->fts_status
3021 error = innobase_fts_load_stopword(
3022 ctx->new_table, ctx->trx,
3023 ctx->prebuilt->trx->mysql_thd)
3024 ? DB_SUCCESS : DB_ERROR;
3025 ctx->new_table->fts->fts_status
3028 if (error != DB_SUCCESS) {
3029 goto error_handling;
3036 DBUG_ASSERT(error == DB_SUCCESS);
3047 dict_locked =
false;
3049 ut_a(ctx->trx->lock.n_active_thrs == 0);
3060 ut_d(dict_table_check_for_dup_indexes(
3061 user_table, CHECK_PARTIAL_OK));
3065 my_error(ER_TABLESPACE_EXISTS, MYF(0),
"(unknown)");
3067 case DB_DUPLICATE_KEY:
3068 my_error(ER_DUP_KEY, MYF(0),
"SYS_INDEXES");
3071 my_error_innodb(error, table_name, user_table->
flags);
3076 ctx->prebuilt->trx->error_info = NULL;
3077 ctx->trx->error_state = DB_SUCCESS;
3080 row_mysql_lock_data_dictionary(ctx->trx);
3083 if (new_clustered) {
3084 if (ctx->need_rebuild()) {
3086 if (DICT_TF2_FLAG_IS_SET(
3088 innobase_drop_fts_index_table(
3089 ctx->new_table, ctx->trx);
3094 #if defined UNIV_DEBUG || defined UNIV_DDL_DEBUG
3099 ut_a(!ctx->new_table->stat_initialized);
3107 dict_index_t* clust_index = dict_table_get_first_index(
3110 rw_lock_x_lock(&clust_index->
lock);
3119 rw_lock_x_unlock(&clust_index->
lock);
3126 DBUG_ASSERT(user_table->
n_ref_count == 1 || ctx->online);
3128 online_retry_drop_indexes_with_trx(user_table, ctx->trx);
3130 ut_ad(!ctx->need_rebuild());
3135 ut_d(dict_table_check_for_dup_indexes(user_table, CHECK_ALL_COMPLETE));
3140 for (ulint i = 0; i < ctx->num_to_drop_index; i++) {
3142 DBUG_ASSERT(ctx->drop_index[i]->to_be_dropped);
3143 ctx->drop_index[
i]->to_be_dropped = 0;
3152 ha_alter_info->handler_ctx = NULL;
3163 static __attribute__((nonnull(1,2,3,5), warn_unused_result))
3165 innobase_check_foreign_key_index(
3173 const
char** col_names,
3186 ut_ad(!foreign || indexed_table
3191 indexed_table, col_names,
3196 && !innobase_find_equiv_index(
3199 ha_alter_info->key_info_buffer,
3200 ha_alter_info->index_add_buffer,
3201 ha_alter_info->index_add_count)
3203 trx->error_info =
index;
3210 indexed_table, index);
3212 ut_ad(!foreign || indexed_table
3216 && !innobase_dropping_foreign(
3217 foreign, drop_fk, n_drop_fk)
3219 indexed_table, col_names,
3224 && !innobase_find_equiv_index(
3227 ha_alter_info->key_info_buffer,
3228 ha_alter_info->index_add_buffer,
3229 ha_alter_info->index_add_count)
3231 trx->error_info =
index;
3254 TABLE* altered_table,
3265 const char** col_names;
3270 ulint add_autoinc_col_no = ULINT_UNDEFINED;
3271 ulonglong autoinc_col_max_value = 0;
3272 ulint fts_doc_col_no = ULINT_UNDEFINED;
3273 bool add_fts_doc_id =
false;
3274 bool add_fts_doc_id_idx =
false;
3276 DBUG_ENTER(
"prepare_inplace_alter_table");
3286 index = dict_table_get_next_index(index)) {
3287 ut_ad(!index->to_be_dropped);
3292 ut_d(dict_table_check_for_dup_indexes(
3293 prebuilt->
table, CHECK_ABORTED_OK));
3296 if (!(ha_alter_info->
handler_flags & ~INNOBASE_INPLACE_IGNORE)) {
3302 & Alter_inplace_info::CHANGE_CREATE_OPTION) {
3303 if (
const char* invalid_opt = create_options_are_invalid(
3304 user_thd, altered_table,
3307 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
3309 goto err_exit_no_heap;
3314 if (innobase_index_name_is_reserved(
3320 if (ha_alter_info->
handler_flags & ~INNOBASE_INPLACE_IGNORE) {
3321 online_retry_drop_indexes(prebuilt->
table, user_thd);
3326 indexed_table = prebuilt->
table;
3329 error = innobase_check_index_keys(ha_alter_info, indexed_table);
3332 goto err_exit_no_heap;
3338 & Alter_inplace_info::ALTER_COLUMN_NAME) {
3342 for (Field** fp = table->field; *fp; fp++) {
3343 if (!((*fp)->flags & FIELD_IS_RENAMED)) {
3347 const char* name = 0;
3351 if (cf->field == *fp) {
3352 name = cf->field_name;
3353 goto check_if_ok_to_rename;
3358 check_if_ok_to_rename:
3361 if (!my_strcasecmp(system_charset_info,
3364 && innobase_fulltext_exist(altered_table)) {
3365 my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN,
3367 goto err_exit_no_heap;
3376 for (j = 0; j < table->s->fields; j++) {
3382 system_charset_info, name, s)) {
3383 my_error(ER_WRONG_COLUMN_NAME, MYF(0),
3385 goto err_exit_no_heap;
3393 if (!innobase_table_flags(altered_table,
3397 || indexed_table->
space != 0,
3399 goto err_exit_no_heap;
3402 max_col_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags);
3410 if (key->
flags & HA_FULLTEXT) {
3414 DBUG_ASSERT(!(key->
flags & HA_NOSAME));
3415 DBUG_ASSERT(!(key->
flags & HA_KEYFLAG_MASK
3418 | HA_BINARY_PACK_KEY)));
3422 if (innobase_check_column_length(max_col_len, key)) {
3423 my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
3425 goto err_exit_no_heap;
3432 = dict_table_get_first_index(indexed_table);
3434 index = dict_table_get_next_index(index)) {
3435 if (index->type & DICT_FTS) {
3436 DBUG_ASSERT(index->type == DICT_FTS
3443 = dict_index_get_nth_field(index, i);
3445 my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
3447 goto err_exit_no_heap;
3456 & (INNOBASE_ALTER_NOREBUILD | INNOBASE_ALTER_REBUILD)) {
3460 & Alter_inplace_info::ALTER_COLUMN_NAME) {
3461 col_names = innobase_get_col_names(
3462 ha_alter_info, altered_table, indexed_table,
3473 & Alter_inplace_info::DROP_FOREIGN_KEY) {
3474 DBUG_ASSERT(ha_alter_info->
alter_info->drop_list.elements > 0);
3479 ha_alter_info->
alter_info->drop_list.elements
3486 if (drop->type != Alter_drop::FOREIGN_KEY) {
3494 foreign_list, foreign)) {
3495 const char* fid = strchr(foreign->
id,
'/');
3501 fid = fid ? fid + 1 : foreign->
id;
3503 if (!my_strcasecmp(system_charset_info,
3505 drop_fk[n_drop_fk++] = foreign;
3510 my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
3517 DBUG_ASSERT(n_drop_fk > 0);
3518 DBUG_ASSERT(n_drop_fk
3519 == ha_alter_info->
alter_info->drop_list.elements);
3528 & (Alter_inplace_info::DROP_INDEX
3529 | Alter_inplace_info::DROP_UNIQUE_INDEX
3530 | Alter_inplace_info::DROP_PK_INDEX));
3535 *
sizeof *drop_index));
3542 indexed_table, key->
name);
3545 push_warning_printf(
3547 Sql_condition::WARN_LEVEL_WARN,
3549 "InnoDB could not find key "
3550 "with name %s", key->
name);
3554 drop_index[n_drop_index++] =
index;
3556 drop_primary =
index;
3565 if (innobase_fulltext_exist(table)
3566 && !innobase_fulltext_exist(altered_table)
3567 && !DICT_TF2_FLAG_IS_SET(
3574 if (fts_doc_index == NULL) {
3575 goto check_if_can_drop_indexes;
3580 for (uint i = 0; i < table->s->keys; i++) {
3582 system_charset_info,
3584 table->key_info[i].
name)) {
3589 goto check_if_can_drop_indexes;
3593 drop_index[n_drop_index++] = fts_doc_index;
3596 check_if_can_drop_indexes:
3601 row_mysql_lock_data_dictionary(prebuilt->
trx);
3603 if (!n_drop_index) {
3607 for (ulint i = 0; i < n_drop_index; i++) {
3608 ut_ad(!drop_index[i]->to_be_dropped);
3614 for (uint i = 0; i < n_drop_index; i++) {
3617 if (innobase_check_foreign_key_index(
3618 ha_alter_info, index,
3619 indexed_table, col_names,
3620 prebuilt->
trx, drop_fk, n_drop_fk)) {
3633 && innobase_check_foreign_key_index(
3634 ha_alter_info, drop_primary,
3635 indexed_table, col_names,
3636 prebuilt->
trx, drop_fk, n_drop_fk)) {
3651 & Alter_inplace_info::ADD_FOREIGN_KEY) {
3660 if (!innobase_get_foreign_key_info(
3661 ha_alter_info, table_share,
3662 prebuilt->
table, col_names,
3663 drop_index, n_drop_index,
3664 add_fk, &n_add_fk, prebuilt->
trx)) {
3667 row_mysql_lock_data_dictionary(prebuilt->
trx);
3671 for (ulint i = 0; i < n_drop_index; i++) {
3672 DBUG_ASSERT(*drop_index[i]->name
3684 goto err_exit_no_heap;
3690 == Alter_inplace_info::CHANGE_CREATE_OPTION
3691 && !innobase_need_rebuild(ha_alter_info))) {
3695 =
new ha_innobase_inplace_ctx(
3697 drop_index, n_drop_index,
3701 heap, indexed_table,
3702 col_names, ULINT_UNDEFINED, 0, 0);
3707 if (ha_alter_info->
handler_flags & ~INNOBASE_INPLACE_IGNORE) {
3708 online_retry_drop_indexes(prebuilt->
table, user_thd);
3716 if (innobase_fulltext_exist(altered_table)) {
3719 if (!innobase_fts_check_doc_id_col(
3720 prebuilt->
table, altered_table, &fts_doc_col_no)) {
3721 fts_doc_col_no = altered_table->s->fields;
3722 add_fts_doc_id =
true;
3723 add_fts_doc_id_idx =
true;
3725 push_warning_printf(
3727 Sql_condition::WARN_LEVEL_WARN,
3729 "InnoDB rebuilding table to add column "
3731 }
else if (fts_doc_col_no == ULINT_UNDEFINED) {
3735 switch (innobase_fts_check_doc_id_index(
3736 prebuilt->
table, altered_table, &doc_col_no)) {
3737 case FTS_NOT_EXIST_DOC_ID_INDEX:
3738 add_fts_doc_id_idx =
true;
3740 case FTS_INCORRECT_DOC_ID_INDEX:
3741 my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0),
3744 case FTS_EXIST_DOC_ID_INDEX:
3745 DBUG_ASSERT(doc_col_no == fts_doc_col_no
3746 || doc_col_no == ULINT_UNDEFINED
3748 & (Alter_inplace_info::ALTER_COLUMN_ORDER
3749 | Alter_inplace_info::DROP_COLUMN
3750 | Alter_inplace_info::ADD_COLUMN)));
3761 DBUG_ASSERT(i < altered_table->s->fields);
3763 for (uint old_i = 0; table->field[old_i]; old_i++) {
3764 if (new_field->field == table->field[old_i]) {
3770 DBUG_ASSERT(!new_field->field);
3772 & Alter_inplace_info::ADD_COLUMN);
3774 field = altered_table->field[
i];
3776 DBUG_ASSERT((MTYP_TYPENR(field->unireg_check)
3777 == Field::NEXT_NUMBER)
3778 == !!(field->flags & AUTO_INCREMENT_FLAG));
3780 if (field->flags & AUTO_INCREMENT_FLAG) {
3781 if (add_autoinc_col_no != ULINT_UNDEFINED) {
3784 my_error(ER_WRONG_AUTO_KEY, MYF(0));
3787 add_autoinc_col_no =
i;
3800 ha_alter_info->
handler_ctx =
new ha_innobase_inplace_ctx(
3802 drop_index, n_drop_index,
3803 drop_fk, n_drop_fk, add_fk, n_add_fk,
3805 heap, prebuilt->
table, col_names,
3808 autoinc_col_max_value);
3810 DBUG_RETURN(prepare_inplace_alter_table_dict(
3811 ha_alter_info, altered_table, table,
3812 table_share->table_name.str,
3814 fts_doc_col_no, add_fts_doc_id,
3815 add_fts_doc_id_idx));
3834 TABLE* altered_table,
3839 DBUG_ENTER(
"inplace_alter_table");
3842 #ifdef UNIV_SYNC_DEBUG
3847 DEBUG_SYNC(user_thd,
"innodb_inplace_alter_table_enter");
3849 if (!(ha_alter_info->
handler_flags & INNOBASE_ALTER_DATA)) {
3851 DEBUG_SYNC(user_thd,
"innodb_after_inplace_alter_table");
3856 == Alter_inplace_info::CHANGE_CREATE_OPTION
3857 && !innobase_need_rebuild(ha_alter_info)) {
3861 ha_innobase_inplace_ctx* ctx
3862 =
static_cast<ha_innobase_inplace_ctx*
>
3866 DBUG_ASSERT(ctx->trx);
3867 DBUG_ASSERT(ctx->prebuilt == prebuilt);
3877 DBUG_EXECUTE_IF(
"innodb_OOM_inplace_alter",
3878 error = DB_OUT_OF_MEMORY;
goto oom;);
3881 prebuilt->
table, ctx->new_table,
3883 ctx->add_index, ctx->add_key_numbers, ctx->num_to_add_index,
3884 altered_table, ctx->add_cols, ctx->col_map,
3885 ctx->add_autoinc, ctx->sequence);
3889 if (error == DB_SUCCESS && ctx->online && ctx->need_rebuild()) {
3890 DEBUG_SYNC_C(
"row_log_table_apply1_before");
3892 ctx->thr, prebuilt->
table, altered_table);
3895 DEBUG_SYNC_C(
"inplace_after_index_build");
3897 DBUG_EXECUTE_IF(
"create_index_fail",
3898 error = DB_DUPLICATE_KEY;);
3908 ut_d(dict_table_check_for_dup_indexes(
3909 prebuilt->
table, CHECK_PARTIAL_OK));
3914 case DB_DUPLICATE_KEY:
3931 DBUG_ASSERT(ctx->online);
3932 my_error(ER_INNODB_ONLINE_LOG_TOO_BIG, MYF(0),
3939 my_error(ER_INDEX_CORRUPT, MYF(0),
3946 my_error_innodb(error,
3947 table_share->table_name.str,
3954 ctx->trx->error_state = DB_SUCCESS;
3963 innobase_online_rebuild_log_free(
3967 dict_index_t* clust_index = dict_table_get_first_index(table);
3970 #ifdef UNIV_SYNC_DEBUG
3974 rw_lock_x_lock(&clust_index->
lock);
3981 DEBUG_SYNC_C(
"innodb_online_rebuild_log_free_aborted");
3986 rw_lock_x_unlock(&clust_index->
lock);
3996 static __attribute__((nonnull))
3998 innobase_rollback_sec_index(
4010 && !DICT_TF2_FLAG_IS_SET(user_table,
4012 && !innobase_fulltext_exist(table)) {
4030 inline __attribute__((nonnull, warn_unused_result))
4032 rollback_inplace_alter_table(
4040 ha_innobase_inplace_ctx* ctx
4041 =
static_cast<ha_innobase_inplace_ctx*
>
4042 (ha_alter_info->handler_ctx);
4044 DBUG_ENTER(
"rollback_inplace_alter_table");
4046 if (!ctx || !ctx->trx) {
4052 row_mysql_lock_data_dictionary(ctx->trx);
4054 if (ctx->need_rebuild()) {
4056 ulint flags = ctx->new_table->flags;
4060 innobase_online_rebuild_log_free(prebuilt->table);
4065 if (DICT_TF2_FLAG_IS_SET(ctx->new_table,
DICT_TF2_FTS)) {
4067 err = innobase_drop_fts_index_table(
4068 ctx->new_table, ctx->trx);
4070 if (err != DB_SUCCESS) {
4072 err, table->s->table_name.str,
4081 #if defined UNIV_DEBUG || defined UNIV_DDL_DEBUG
4086 ut_a(!ctx->new_table->stat_initialized);
4095 my_error_innodb(err, table->s->table_name.str,
4100 DBUG_ASSERT(!(ha_alter_info->handler_flags
4101 & Alter_inplace_info::ADD_PK_INDEX));
4102 DBUG_ASSERT(ctx->new_table == prebuilt->table);
4106 innobase_rollback_sec_index(
4107 prebuilt->table, table, FALSE, ctx->trx);
4116 dict_index_t* clust_index = dict_table_get_first_index(
4124 DBUG_ASSERT(ctx->prebuilt == prebuilt);
4126 if (ctx->num_to_add_fk) {
4127 for (ulint i = 0; i < ctx->num_to_add_fk; i++) {
4132 if (ctx->num_to_drop_index) {
4133 row_mysql_lock_data_dictionary(prebuilt->trx);
4140 for (ulint i = 0; i < ctx->num_to_drop_index; i++) {
4163 static __attribute__((nonnull, warn_unused_result))
4165 innobase_drop_foreign_try(
4168 const
char* table_name,
4169 const
char* foreign_id)
4171 DBUG_ENTER(
"innobase_drop_foreign_try");
4174 ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
4176 #ifdef UNIV_SYNC_DEBUG
4181 static const char sql[] =
4182 "PROCEDURE DROP_FOREIGN_PROC () IS\n"
4184 "DELETE FROM SYS_FOREIGN WHERE ID=:id;\n"
4185 "DELETE FROM SYS_FOREIGN_COLS WHERE ID=:id;\n"
4194 trx->op_info =
"dropping foreign key constraint from dictionary";
4198 DBUG_EXECUTE_IF(
"ib_drop_foreign_error",
4199 error = DB_OUT_OF_FILE_SPACE;);
4201 if (error != DB_SUCCESS) {
4202 my_error_innodb(error, table_name, 0);
4203 trx->error_state = DB_SUCCESS;
4220 static __attribute__((nonnull, warn_unused_result))
4222 innobase_rename_column_try(
4226 const
char* table_name,
4235 DBUG_ENTER(
"innobase_rename_column_try");
4238 ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
4240 #ifdef UNIV_SYNC_DEBUG
4244 if (new_clustered) {
4245 goto rename_foreign;
4255 trx->op_info =
"renaming column in SYS_COLUMNS";
4259 "PROCEDURE RENAME_SYS_COLUMNS_PROC () IS\n"
4261 "UPDATE SYS_COLUMNS SET NAME=:new\n"
4262 "WHERE TABLE_ID=:tableid AND NAME=:old\n"
4267 DBUG_EXECUTE_IF(
"ib_rename_column_error",
4268 error = DB_OUT_OF_FILE_SPACE;);
4270 if (error != DB_SUCCESS) {
4272 my_error_innodb(error, table_name, 0);
4273 trx->error_state = DB_SUCCESS;
4278 trx->op_info =
"renaming column in SYS_FIELDS";
4280 for (
const dict_index_t* index = dict_table_get_first_index(
4283 index = dict_table_get_next_index(index)) {
4286 if (strcmp(dict_index_get_nth_field(index, i)->name,
4300 "PROCEDURE RENAME_SYS_FIELDS_PROC () IS\n"
4303 "UPDATE SYS_FIELDS SET COL_NAME=:new\n"
4304 "WHERE INDEX_ID=:indexid AND COL_NAME=:old\n"
4310 "UPDATE SYS_FIELDS SET COL_NAME=:new\n"
4311 "WHERE INDEX_ID=:indexid AND COL_NAME=:old\n"
4312 "AND POS>=65536*:nth AND POS<65536*(:nth+1);\n"
4317 if (error != DB_SUCCESS) {
4324 trx->op_info =
"renaming column in SYS_FOREIGN_COLS";
4327 user_table->foreign_list);
4330 for (
unsigned i = 0; i < foreign->
n_fields; i++) {
4344 "PROCEDURE RENAME_SYS_FOREIGN_F_PROC () IS\n"
4346 "UPDATE SYS_FOREIGN_COLS\n"
4347 "SET FOR_COL_NAME=:new\n"
4348 "WHERE ID=:id AND POS=:nth\n"
4349 "AND FOR_COL_NAME=:old;\n"
4353 if (error != DB_SUCCESS) {
4360 user_table->referenced_list);
4363 for (
unsigned i = 0; i < foreign->
n_fields; i++) {
4377 "PROCEDURE RENAME_SYS_FOREIGN_R_PROC () IS\n"
4379 "UPDATE SYS_FOREIGN_COLS\n"
4380 "SET REF_COL_NAME=:new\n"
4381 "WHERE ID=:id AND POS=:nth\n"
4382 "AND REF_COL_NAME=:old;\n"
4386 if (error != DB_SUCCESS) {
4404 static __attribute__((nonnull, warn_unused_result))
4406 innobase_rename_columns_try(
4409 ha_innobase_inplace_ctx*ctx,
4412 const
char* table_name)
4415 ha_alter_info->alter_info->create_list);
4419 DBUG_ASSERT(ha_alter_info->handler_flags
4420 & Alter_inplace_info::ALTER_COLUMN_NAME);
4422 for (Field** fp = table->field; *fp; fp++, i++) {
4423 if (!((*fp)->flags & FIELD_IS_RENAMED)) {
4429 if (cf->field == *fp) {
4430 if (innobase_rename_column_try(
4431 ctx->old_table, trx, table_name, i,
4432 cf->field->field_name,
4434 ctx->need_rebuild())) {
4437 goto processed_field;
4454 static __attribute__((nonnull))
4456 innobase_rename_columns_cache(
4462 if (!(ha_alter_info->handler_flags
4463 & Alter_inplace_info::ALTER_COLUMN_NAME)) {
4468 ha_alter_info->alter_info->create_list);
4471 for (Field** fp = table->field; *fp; fp++, i++) {
4472 if (!((*fp)->flags & FIELD_IS_RENAMED)) {
4478 if (cf->field == *fp) {
4480 cf->field->field_name,
4482 goto processed_field;
4498 static __attribute__((nonnull, warn_unused_result))
4503 ha_innobase_inplace_ctx*ctx,
4504 const
TABLE* altered_table,
4505 const
TABLE* old_table)
4507 ulonglong max_autoinc;
4509 DBUG_ENTER(
"commit_get_autoinc");
4511 if (!altered_table->found_next_number_field) {
4515 }
else if (ctx->add_autoinc != ULINT_UNDEFINED) {
4519 max_autoinc = ctx->sequence.last();
4520 }
else if ((ha_alter_info->handler_flags
4521 & Alter_inplace_info::CHANGE_CREATE_OPTION)
4522 && (ha_alter_info->create_info->used_fields
4523 & HA_CREATE_USED_AUTO)) {
4527 ut_ad(old_table->found_next_number_field);
4529 max_autoinc = ha_alter_info->create_info->auto_increment_value;
4532 if (max_autoinc < ctx->old_table->autoinc) {
4533 max_autoinc = ctx->old_table->autoinc;
4539 ut_ad(old_table->found_next_number_field);
4541 max_autoinc = ctx->old_table->autoinc;
4545 DBUG_RETURN(max_autoinc);
4557 static __attribute__((nonnull, warn_unused_result))
4559 innobase_update_foreign_try(
4561 ha_innobase_inplace_ctx*ctx,
4563 const
char* table_name)
4568 DBUG_ENTER(
"innobase_update_foreign_try");
4575 for (i = 0; i < ctx->num_to_add_fk; i++) {
4582 &foreign_id, ctx->old_table->name, fk);
4584 if (error != DB_SUCCESS) {
4585 my_error(ER_TOO_LONG_IDENT, MYF(0),
4592 ctx->new_table, ctx->col_names,
4599 my_error(ER_FK_INCORRECT_OPTION,
4600 MYF(0), table_name, fk->
id);
4609 ctx->old_table->name, fk, trx);
4612 "innodb_test_cannot_add_fk_system",
4615 if (error != DB_SUCCESS) {
4616 my_error(ER_FK_FAIL_ADD_SYSTEM, MYF(0),
4622 for (i = 0; i < ctx->num_to_drop_fk; i++) {
4627 if (innobase_drop_foreign_try(trx, table_name, fk->
id)) {
4639 static __attribute__((nonnull, warn_unused_result))
4641 innobase_update_foreign_cache(
4643 ha_innobase_inplace_ctx* ctx)
4647 DBUG_ENTER(
"innobase_update_foreign_cache");
4649 user_table = ctx->old_table;
4653 for (ulint i = 0; i < ctx->num_to_add_fk; i++) {
4658 if (ctx->need_rebuild()) {
4662 DBUG_ASSERT(!ctx->col_names);
4665 user_table = ctx->new_table;
4671 for (ulint i = 0; i < ctx->num_to_drop_fk; i++) {
4681 ctx->col_names,
false,
true,
4697 inline __attribute__((nonnull, warn_unused_result))
4702 ha_innobase_inplace_ctx*ctx,
4703 TABLE* altered_table,
4704 const
TABLE* old_table,
4706 const
char* table_name)
4711 DBUG_ENTER(
"commit_try_rebuild");
4712 DBUG_ASSERT(ctx->need_rebuild());
4713 DBUG_ASSERT(trx->dict_operation_lock_mode == RW_X_LATCH);
4714 DBUG_ASSERT(!(ha_alter_info->handler_flags
4715 & Alter_inplace_info::DROP_FOREIGN_KEY)
4716 || ctx->num_to_drop_fk > 0);
4717 DBUG_ASSERT(ctx->num_to_drop_fk
4718 == ha_alter_info->alter_info->drop_list.elements);
4720 for (
dict_index_t* index = dict_table_get_first_index(rebuilt_table);
4722 index = dict_table_get_next_index(index)) {
4727 my_error(ER_INDEX_CORRUPT, MYF(0),
4733 if (innobase_update_foreign_try(ctx, trx, table_name)) {
4741 for (ulint i = 0; i < ctx->num_to_drop_index; i++) {
4743 DBUG_ASSERT(index->
table == user_table);
4754 DEBUG_SYNC_C(
"row_log_table_apply2_before");
4756 ctx->thr, user_table, altered_table);
4763 case DB_DUPLICATE_KEY:
4764 if (err_key == ULINT_UNDEFINED) {
4769 DBUG_ASSERT(err_key <
4770 ha_alter_info->key_count);
4771 dup_key = &ha_alter_info
4772 ->key_info_buffer[err_key];
4777 my_error(ER_INNODB_ONLINE_LOG_TOO_BIG, MYF(0),
4778 ha_alter_info->key_info_buffer[0].name);
4781 my_error(ER_INDEX_CORRUPT, MYF(0),
4782 (err_key == ULINT_UNDEFINED)
4784 : ha_alter_info->key_info_buffer[err_key]
4788 my_error_innodb(error, table_name, user_table->
flags);
4793 if ((ha_alter_info->handler_flags
4794 & Alter_inplace_info::ALTER_COLUMN_NAME)
4795 && innobase_rename_columns_try(ha_alter_info, ctx, old_table,
4800 DBUG_EXECUTE_IF(
"ib_ddl_crash_before_rename", DBUG_SUICIDE(););
4817 user_table, rebuilt_table, ctx->tmp_name, trx);
4822 DBUG_EXECUTE_IF(
"ib_ddl_crash_after_rename", DBUG_SUICIDE(););
4823 DBUG_EXECUTE_IF(
"ib_rebuild_cannot_rename", error = DB_ERROR;);
4844 my_error(ER_TABLESPACE_EXISTS, MYF(0), ctx->tmp_name);
4846 case DB_DUPLICATE_KEY:
4848 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), ctx->tmp_name);
4851 my_error_innodb(error, table_name, user_table->
flags);
4859 inline __attribute__((nonnull))
4861 commit_cache_rebuild(
4863 ha_innobase_inplace_ctx* ctx)
4867 DBUG_ENTER(
"commit_cache_rebuild");
4868 DBUG_ASSERT(ctx->need_rebuild());
4873 ctx->heap, ctx->old_table->name);
4878 ctx->old_table, ctx->tmp_name, FALSE);
4879 ut_a(error == DB_SUCCESS);
4882 ctx->new_table, old_name, FALSE);
4883 ut_a(error == DB_SUCCESS);
4899 inline __attribute__((nonnull, warn_unused_result))
4901 commit_try_norebuild(
4904 ha_innobase_inplace_ctx*ctx,
4905 const
TABLE* old_table,
4907 const
char* table_name)
4909 DBUG_ENTER(
"commit_try_norebuild");
4910 DBUG_ASSERT(!ctx->need_rebuild());
4911 DBUG_ASSERT(trx->dict_operation_lock_mode == RW_X_LATCH);
4912 DBUG_ASSERT(!(ha_alter_info->handler_flags
4913 & Alter_inplace_info::DROP_FOREIGN_KEY)
4914 || ctx->num_to_drop_fk > 0);
4915 DBUG_ASSERT(ctx->num_to_drop_fk
4916 == ha_alter_info->alter_info->drop_list.elements);
4918 for (ulint i = 0; i < ctx->num_to_add_index; i++) {
4935 my_error(ER_DUP_UNKNOWN_IN_INDEX,
4936 MYF(0), index->
name + 1);
4941 if (innobase_update_foreign_try(ctx, trx, table_name)) {
4949 for (ulint i = 0; i < ctx->num_to_add_index; i++) {
4953 DBUG_ASSERT(*index->
name
4956 trx, ctx->new_table->id, index->
id);
4957 if (error != DB_SUCCESS) {
4959 "InnoDB: rename index to add: %lu\n",
4962 my_error(ER_INTERNAL_ERROR, MYF(0),
4963 "rename index to add");
4974 for (ulint i = 0; i < ctx->num_to_drop_index; i++) {
4977 DBUG_ASSERT(index->
table == ctx->new_table);
4982 if (error != DB_SUCCESS) {
4984 "InnoDB: rename index to drop: %lu\n",
4987 my_error(ER_INTERNAL_ERROR, MYF(0),
4988 "rename index to drop");
4993 if (!(ha_alter_info->handler_flags
4994 & Alter_inplace_info::ALTER_COLUMN_NAME)) {
4998 DBUG_RETURN(innobase_rename_columns_try(ha_alter_info, ctx,
4999 old_table, trx, table_name));
5009 inline __attribute__((nonnull, warn_unused_result))
5011 commit_cache_norebuild(
5013 ha_innobase_inplace_ctx*ctx,
5017 DBUG_ENTER(
"commit_cache_norebuild");
5021 DBUG_ASSERT(!ctx->need_rebuild());
5023 for (ulint i = 0; i < ctx->num_to_add_index; i++) {
5031 if (ctx->num_to_drop_index) {
5041 for (ulint i = 0; i < ctx->num_to_drop_index; i++) {
5044 DBUG_ASSERT(index->
table == ctx->new_table);
5065 for (ulint i = 0; i < ctx->num_to_drop_index; i++) {
5068 DBUG_ASSERT(index->
table == ctx->new_table);
5070 if (index->
type & DICT_FTS) {
5071 DBUG_ASSERT(index->
type == DICT_FTS
5074 DBUG_ASSERT(index->
table->fts);
5098 alter_stats_norebuild(
5101 ha_innobase_inplace_ctx* ctx,
5102 TABLE* altered_table,
5103 const char* table_name,
5108 DBUG_ENTER(
"alter_stats_norebuild");
5109 DBUG_ASSERT(!ctx->need_rebuild());
5121 if (key->
flags & HA_FULLTEXT) {
5130 ctx->new_table->name, key->
name,
5131 errstr,
sizeof errstr) != DB_SUCCESS) {
5133 Sql_condition::WARN_LEVEL_WARN,
5134 ER_LOCK_WAIT_TIMEOUT, errstr);
5138 for (i = 0; i < ctx->num_to_add_index; i++) {
5140 DBUG_ASSERT(index->
table == ctx->new_table);
5142 if (!(index->
type & DICT_FTS)) {
5160 alter_stats_rebuild(
5163 const char* table_name,
5166 DBUG_ENTER(
"alter_stats_rebuild");
5177 if (ret != DB_SUCCESS) {
5178 push_warning_printf(
5180 Sql_condition::WARN_LEVEL_WARN,
5182 "Error updating stats for table '%s' "
5183 "after table rebuild: %s",
5191 # define DBUG_INJECT_CRASH(prefix, count) \
5194 ut_snprintf(buf, sizeof buf, prefix "_%u", count); \
5195 DBUG_EXECUTE_IF(buf, DBUG_SUICIDE();); \
5198 # define DBUG_INJECT_CRASH(prefix, count)
5219 TABLE* altered_table,
5223 ha_innobase_inplace_ctx* ctx0
5224 =
static_cast<ha_innobase_inplace_ctx*
>
5227 uint crash_inject_count = 1;
5228 uint crash_fail_inject_count = 1;
5229 uint failure_inject_count = 1;
5232 DBUG_ENTER(
"commit_inplace_alter_table");
5234 DBUG_ASSERT(!ctx0 || ctx0->prebuilt == prebuilt);
5235 DBUG_ASSERT(!ctx0 || ctx0->old_table == prebuilt->table);
5237 DEBUG_SYNC_C(
"innodb_commit_inplace_alter_table_enter");
5239 DEBUG_SYNC_C(
"innodb_commit_inplace_alter_table_wait");
5246 DBUG_RETURN(rollback_inplace_alter_table(
5247 ha_alter_info, table, prebuilt));
5250 if (!(ha_alter_info->
handler_flags & ~INNOBASE_INPLACE_IGNORE)) {
5265 ctx_single[0] = ctx0;
5266 ctx_single[1] = NULL;
5267 ctx_array = ctx_single;
5270 DBUG_ASSERT(ctx0 == ctx_array[0]);
5271 ut_ad(prebuilt->table == ctx0->old_table);
5280 ha_innobase_inplace_ctx* ctx
5281 =
static_cast<ha_innobase_inplace_ctx*
>(*pctx);
5289 trx_start_if_not_started_xa(prebuilt->trx);
5292 ha_innobase_inplace_ctx* ctx
5293 =
static_cast<ha_innobase_inplace_ctx*
>(*pctx);
5294 DBUG_ASSERT(ctx->prebuilt->trx == prebuilt->trx);
5305 prebuilt->trx, ctx->old_table, LOCK_X);
5307 if (error != DB_SUCCESS) {
5309 error, table_share->table_name.str, 0);
5314 DEBUG_SYNC(user_thd,
"innodb_alter_commit_after_lock_table");
5316 const bool new_clustered = ctx0->need_rebuild();
5317 trx_t* trx = ctx0->trx;
5320 if (new_clustered) {
5323 ha_innobase_inplace_ctx* ctx
5324 =
static_cast<ha_innobase_inplace_ctx*
>(*pctx);
5325 DBUG_ASSERT(ctx->need_rebuild());
5327 if (ctx->old_table->fts) {
5328 ut_ad(!ctx->old_table->fts->add_wq);
5333 if (ctx->new_table->fts) {
5334 ut_ad(!ctx->new_table->fts->add_wq);
5342 DBUG_ASSERT(!new_clustered);
5349 row_mysql_lock_data_dictionary(trx);
5358 ha_innobase_inplace_ctx* ctx
5359 =
static_cast<ha_innobase_inplace_ctx*
>(*pctx);
5361 DBUG_ASSERT(new_clustered == ctx->need_rebuild());
5384 *pctx && !fail; pctx++) {
5385 ha_innobase_inplace_ctx* ctx
5386 =
static_cast<ha_innobase_inplace_ctx*
>(*pctx);
5388 DBUG_ASSERT(new_clustered == ctx->need_rebuild());
5390 ctx->max_autoinc = commit_get_autoinc(
5391 ha_alter_info, ctx, altered_table, table);
5393 if (ctx->need_rebuild()) {
5394 ctx->tmp_name = dict_mem_create_temporary_tablename(
5395 ctx->heap, ctx->new_table->name,
5396 ctx->new_table->id);
5398 fail = commit_try_rebuild(
5399 ha_alter_info, ctx, altered_table, table,
5400 trx, table_share->table_name.str);
5402 fail = commit_try_norebuild(
5403 ha_alter_info, ctx, table, trx,
5404 table_share->table_name.str);
5406 DBUG_INJECT_CRASH(
"ib_commit_inplace_crash",
5407 crash_inject_count++);
5412 ut_snprintf(buf,
sizeof buf,
"ib_commit_inplace_fail_%u",
5413 failure_inject_count++);
5414 DBUG_EXECUTE_IF(buf,
5415 my_error(ER_INTERNAL_ERROR, MYF(0),
5427 }
else if (!new_clustered) {
5435 ha_innobase_inplace_ctx* ctx
5436 =
static_cast<ha_innobase_inplace_ctx*
>(*pctx);
5438 DBUG_ASSERT(ctx->need_rebuild());
5443 ctx->old_table->name,
5444 ctx->new_table->space,
5445 ctx->new_table->name,
5446 ctx->tmp_name, &mtr);
5447 DBUG_INJECT_CRASH(
"ib_commit_inplace_crash",
5448 crash_inject_count++);
5456 DBUG_EXECUTE_IF(
"innodb_alter_commit_crash_before_commit",
5476 DBUG_EXECUTE_IF(
"innodb_alter_commit_crash_after_commit",
5496 ha_innobase_inplace_ctx* ctx
5497 =
static_cast<ha_innobase_inplace_ctx*
>(*pctx);
5499 DBUG_ASSERT(ctx->need_rebuild() == new_clustered);
5501 if (new_clustered) {
5502 innobase_online_rebuild_log_free(ctx->old_table);
5506 if (new_clustered) {
5510 #if defined UNIV_DEBUG || defined UNIV_DDL_DEBUG
5516 ut_a(!ctx->new_table->stat_initialized);
5522 ctx->new_table = NULL;
5529 innobase_rollback_sec_index(
5530 ctx->new_table, table, TRUE, trx);
5533 DBUG_INJECT_CRASH(
"ib_commit_inplace_crash_fail",
5534 crash_fail_inject_count++);
5540 ctx->new_table, altered_table->s);
5542 if (new_clustered) {
5553 ctx->old_table->to_be_dropped =
true;
5556 commit_cache_rebuild(ctx);
5558 error = innobase_update_foreign_cache(ctx);
5559 if (error != DB_SUCCESS) {
5563 error = innobase_update_foreign_cache(ctx);
5565 if (error != DB_SUCCESS) {
5573 my_error(ER_CANNOT_ADD_FOREIGN,
5576 "InnoDB: dict_load_foreigns()"
5577 " returned %u for %s",
5579 thd_query_string(user_thd)
5583 if (!commit_cache_norebuild(
5585 ut_a(!prebuilt->trx->check_foreigns);
5588 innobase_rename_columns_cache(
5589 ha_alter_info, table,
5593 DBUG_INJECT_CRASH(
"ib_commit_inplace_crash",
5594 crash_inject_count++);
5602 if (trx == ctx0->trx) {
5614 ha_innobase_inplace_ctx* ctx
5615 =
static_cast<ha_innobase_inplace_ctx*
>
5617 DBUG_ASSERT(ctx->need_rebuild() == new_clustered);
5619 ut_d(dict_table_check_for_dup_indexes(
5623 DBUG_INJECT_CRASH(
"ib_commit_inplace_crash_fail",
5624 crash_fail_inject_count++);
5635 DBUG_EXECUTE_IF(
"ib_ddl_crash_after_user_trx_commit", DBUG_SUICIDE(););
5639 ha_innobase_inplace_ctx* ctx
5640 =
static_cast<ha_innobase_inplace_ctx*
>
5642 DBUG_ASSERT(ctx->need_rebuild() == new_clustered);
5644 if (altered_table->found_next_number_field) {
5652 bool add_fts =
false;
5659 for (ulint i = 0; i < ctx->num_to_add_index; i++) {
5662 if (index->
type & DICT_FTS) {
5663 DBUG_ASSERT(index->
type == DICT_FTS);
5669 ut_d(dict_table_check_for_dup_indexes(
5670 ctx->new_table, CHECK_ALL_COMPLETE));
5676 ut_d(dict_table_check_for_dup_indexes(
5677 ctx->new_table, CHECK_ABORTED_OK));
5680 if (new_clustered) {
5688 DBUG_ASSERT(0 == strcmp(ctx->old_table->name,
5692 ctx->new_table->name,
5693 errstr,
sizeof(errstr))
5695 push_warning_printf(
5697 Sql_condition::WARN_LEVEL_WARN,
5699 "Deleting persistent statistics"
5700 " for rebuilt table '%s' in"
5701 " InnoDB failed: %s",
5702 table->s->table_name.str,
5706 DBUG_EXECUTE_IF(
"ib_ddl_crash_before_commit",
5709 trx_t*
const user_trx = prebuilt->trx;
5724 ctx->new_table, altered_table->s->reclength);
5725 trx_start_if_not_started(user_trx);
5726 user_trx->will_lock++;
5727 prebuilt->trx = user_trx;
5729 DBUG_INJECT_CRASH(
"ib_commit_inplace_crash",
5730 crash_inject_count++);
5740 if (new_clustered) {
5743 ha_innobase_inplace_ctx* ctx
5744 =
static_cast<ha_innobase_inplace_ctx*
>
5746 DBUG_ASSERT(ctx->need_rebuild());
5748 alter_stats_rebuild(
5749 ctx->new_table, table->s->table_name.str,
5751 DBUG_INJECT_CRASH(
"ib_commit_inplace_crash",
5752 crash_inject_count++);
5757 ha_innobase_inplace_ctx* ctx
5758 =
static_cast<ha_innobase_inplace_ctx*
>
5760 DBUG_ASSERT(!ctx->need_rebuild());
5762 alter_stats_norebuild(
5763 ha_alter_info, ctx, altered_table,
5764 table->s->table_name.str, user_thd);
5765 DBUG_INJECT_CRASH(
"ib_commit_inplace_crash",
5766 crash_inject_count++);
5774 dict_index_t* clust_index = dict_table_get_first_index(
5783 index = dict_table_get_next_index(index)) {
5799 ulonglong start_value,
5800 ulonglong max_value)
5802 m_max_value(max_value),
5805 m_next_value(start_value),
5808 if (thd != 0 && m_max_value > 0) {
5810 thd_get_autoinc(thd, &m_offset, &m_increment);
5812 if (m_increment > 1 || m_offset > 1) {
5819 m_increment, m_offset, m_max_value);
5821 }
else if (start_value == 0) {