summaryrefslogtreecommitdiff
path: root/storage/innobase/handler/handler0alter.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/handler/handler0alter.cc')
-rw-r--r--storage/innobase/handler/handler0alter.cc111
1 files changed, 91 insertions, 20 deletions
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index b5c421bc930..24eb37ee776 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -46,12 +46,12 @@ Smart ALTER TABLE
#include "srv0mon.h"
#include "fts0priv.h"
#include "pars0pars.h"
-
+#include "row0sel.h"
+#include "ha_innodb.h"
#ifdef WITH_WSREP
//#include "wsrep_api.h"
#include <sql_acl.h> // PROCESS_ACL
#endif
-#include "ha_innodb.h"
/** Operations for creating secondary indexes (no rebuild needed) */
static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_ONLINE_CREATE
@@ -69,6 +69,7 @@ static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_ALTER_REBUILD
| Alter_inplace_info::ALTER_COLUMN_ORDER
| Alter_inplace_info::DROP_COLUMN
| Alter_inplace_info::ADD_COLUMN
+ | Alter_inplace_info::RECREATE_TABLE
/*
| Alter_inplace_info::ALTER_COLUMN_TYPE
| Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH
@@ -82,6 +83,7 @@ static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_ALTER_DATA
/** Operations for altering a table that InnoDB does not care about */
static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_INPLACE_IGNORE
= Alter_inplace_info::ALTER_COLUMN_DEFAULT
+ | Alter_inplace_info::ALTER_PARTITIONED
| Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT
| Alter_inplace_info::ALTER_COLUMN_STORAGE_TYPE
| Alter_inplace_info::ALTER_RENAME;
@@ -244,6 +246,7 @@ ha_innobase::check_if_supported_inplace_alter(
innobase_get_err_msg(ER_READ_ONLY_MODE);
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
} else if (srv_created_new_raw || srv_force_recovery) {
+
ha_alter_info->unsupported_reason =
innobase_get_err_msg(ER_READ_ONLY_MODE);
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
@@ -900,7 +903,7 @@ innobase_get_foreign_key_info(
/* Check whether there exist such
index in the the index create clause */
if (!index && !innobase_find_equiv_index(
- column_names, i,
+ column_names, static_cast<uint>(i),
ha_alter_info->key_info_buffer,
ha_alter_info->index_add_buffer,
ha_alter_info->index_add_count)) {
@@ -1007,6 +1010,12 @@ innobase_get_foreign_key_info(
}
referenced_num_col = i;
+ } else {
+ /* Not possible to add a foreign key without a
+ referenced column */
+ mutex_exit(&dict_sys->mutex);
+ my_error(ER_CANNOT_ADD_FOREIGN, MYF(0), tbl_namep);
+ goto err_exit;
}
if (!innobase_init_foreign(
@@ -1126,16 +1135,16 @@ innobase_col_to_mysql(
/* These column types should never be shipped to MySQL. */
ut_ad(0);
- case DATA_FIXBINARY:
case DATA_FLOAT:
case DATA_DOUBLE:
case DATA_DECIMAL:
/* Above are the valid column types for MySQL data. */
ut_ad(flen == len);
/* fall through */
+ case DATA_FIXBINARY:
case DATA_CHAR:
/* We may have flen > len when there is a shorter
- prefix on a CHAR column. */
+ prefix on the CHAR and BINARY column. */
ut_ad(flen >= len);
#else /* UNIV_DEBUG */
default:
@@ -2535,15 +2544,16 @@ innobase_drop_fts_index_table(
/** Get the new column names if any columns were renamed
@param ha_alter_info Data used during in-place alter
@param altered_table MySQL table that is being altered
+@param table MySQL table as it is before the ALTER operation
@param user_table InnoDB table as it is before the ALTER operation
@param heap Memory heap for the allocation
@return array of new column names in rebuilt_table, or NULL if not renamed */
static __attribute__((nonnull, warn_unused_result))
const char**
innobase_get_col_names(
-/*===================*/
Alter_inplace_info* ha_alter_info,
const TABLE* altered_table,
+ const TABLE* table,
const dict_table_t* user_table,
mem_heap_t* heap)
{
@@ -2551,19 +2561,31 @@ innobase_get_col_names(
uint i;
DBUG_ENTER("innobase_get_col_names");
- DBUG_ASSERT(user_table->n_def > altered_table->s->fields);
+ DBUG_ASSERT(user_table->n_def > table->s->fields);
DBUG_ASSERT(ha_alter_info->handler_flags
& Alter_inplace_info::ALTER_COLUMN_NAME);
cols = static_cast<const char**>(
- mem_heap_alloc(heap, user_table->n_def * sizeof *cols));
+ mem_heap_zalloc(heap, user_table->n_def * sizeof *cols));
+
+ i = 0;
+ List_iterator_fast<Create_field> cf_it(
+ ha_alter_info->alter_info->create_list);
+ while (const Create_field* new_field = cf_it++) {
+ DBUG_ASSERT(i < altered_table->s->fields);
+
+ for (uint old_i = 0; table->field[old_i]; old_i++) {
+ if (new_field->field == table->field[old_i]) {
+ cols[old_i] = new_field->field_name;
+ break;
+ }
+ }
- for (i = 0; i < altered_table->s->fields; i++) {
- const Field* field = altered_table->field[i];
- cols[i] = field->field_name;
+ i++;
}
/* Copy the internal column names. */
+ i = table->s->fields;
cols[i] = dict_table_get_col_name(user_table, i);
while (++i < user_table->n_def) {
@@ -3341,6 +3363,9 @@ ha_innobase::prepare_inplace_alter_table(
ulint fts_doc_col_no = ULINT_UNDEFINED;
bool add_fts_doc_id = false;
bool add_fts_doc_id_idx = false;
+#ifdef _WIN32
+ bool add_fts_idx = false;
+#endif /* _WIN32 */
DBUG_ENTER("prepare_inplace_alter_table");
DBUG_ASSERT(!ha_alter_info->handler_ctx);
@@ -3485,6 +3510,9 @@ check_if_ok_to_rename:
& ~(HA_FULLTEXT
| HA_PACK_KEY
| HA_BINARY_PACK_KEY)));
+#ifdef _WIN32
+ add_fts_idx = true;
+#endif /* _WIN32 */
continue;
}
@@ -3495,6 +3523,20 @@ check_if_ok_to_rename:
}
}
+#ifdef _WIN32
+ /* We won't be allowed to add fts index to a table with
+ fts indexes already but without AUX_HEX_NAME set.
+ This means the aux tables of the table failed to
+ rename to hex format but new created aux tables
+ shall be in hex format, which is contradictory.
+ It's only for Windows. */
+ if (!DICT_TF2_FLAG_IS_SET(indexed_table, DICT_TF2_FTS_AUX_HEX_NAME)
+ && indexed_table->fts != NULL && add_fts_idx) {
+ my_error(ER_INNODB_FT_AUX_NOT_HEX_ID, MYF(0));
+ goto err_exit_no_heap;
+ }
+#endif /* _WIN32 */
+
/* Check existing index definitions for too-long column
prefixes as well, in case max_col_len shrunk. */
for (const dict_index_t* index
@@ -3528,8 +3570,8 @@ check_if_ok_to_rename:
if (ha_alter_info->handler_flags
& Alter_inplace_info::ALTER_COLUMN_NAME) {
col_names = innobase_get_col_names(
- ha_alter_info, altered_table, indexed_table,
- heap);
+ ha_alter_info, altered_table, table,
+ indexed_table, heap);
} else {
col_names = NULL;
}
@@ -4599,16 +4641,39 @@ commit_get_autoinc(
& Alter_inplace_info::CHANGE_CREATE_OPTION)
&& (ha_alter_info->create_info->used_fields
& HA_CREATE_USED_AUTO)) {
- /* An AUTO_INCREMENT value was supplied, but the table
- was not rebuilt. Get the user-supplied value or the
- last value from the sequence. */
- ut_ad(old_table->found_next_number_field);
+ /* An AUTO_INCREMENT value was supplied, but the table was not
+ rebuilt. Get the user-supplied value or the last value from the
+ sequence. */
+ ib_uint64_t max_value_table;
+ dberr_t err;
+
+ Field* autoinc_field =
+ old_table->found_next_number_field;
+
+ dict_index_t* index = dict_table_get_index_on_first_col(
+ ctx->old_table, autoinc_field->field_index);
max_autoinc = ha_alter_info->create_info->auto_increment_value;
dict_table_autoinc_lock(ctx->old_table);
- if (max_autoinc < ctx->old_table->autoinc) {
- max_autoinc = ctx->old_table->autoinc;
+
+ err = row_search_max_autoinc(
+ index, autoinc_field->field_name, &max_value_table);
+
+ if (err != DB_SUCCESS) {
+ ut_ad(0);
+ max_autoinc = 0;
+ } else if (max_autoinc <= max_value_table) {
+ ulonglong col_max_value;
+ ulonglong offset;
+
+ col_max_value = innobase_get_int_col_max_value(
+ old_table->found_next_number_field);
+
+ offset = ctx->prebuilt->autoinc_offset;
+ max_autoinc = innobase_next_autoinc(
+ max_value_table, 1, 1, offset,
+ col_max_value);
}
dict_table_autoinc_unlock(ctx->old_table);
} else {
@@ -5328,6 +5393,7 @@ ha_innobase::commit_inplace_alter_table(
if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) {
DBUG_ASSERT(!ctx0);
MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE);
+ ha_alter_info->group_commit_ctx = NULL;
DBUG_RETURN(false);
}
@@ -5336,12 +5402,17 @@ ha_innobase::commit_inplace_alter_table(
inplace_alter_handler_ctx** ctx_array;
inplace_alter_handler_ctx* ctx_single[2];
+ if (ha_alter_info->group_commit_ctx) {
+ ctx_array = ha_alter_info->group_commit_ctx;
+ } else {
ctx_single[0] = ctx0;
ctx_single[1] = NULL;
ctx_array = ctx_single;
+ }
DBUG_ASSERT(ctx0 == ctx_array[0]);
ut_ad(prebuilt->table == ctx0->old_table);
+ ha_alter_info->group_commit_ctx = NULL;
/* Free the ctx->trx of other partitions, if any. We will only
use the ctx0->trx here. Others may have been allocated in