mirror of
https://github.com/MariaDB/server.git
synced 2025-01-21 06:22:28 +01:00
c1840ae157
git-svn-id: file:///svn/mysql/tokudb-engine/tokudb-engine@48871 c7de825b-a66e-492c-adef-691d508d4ae1
670 lines
23 KiB
C++
670 lines
23 KiB
C++
#if TOKU_INCLUDE_ALTER_51
|
|
|
|
volatile int ha_tokudb_add_index_wait = 0;
|
|
|
|
int
|
|
ha_tokudb::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys) {
|
|
TOKUDB_DBUG_ENTER("ha_tokudb::add_index");
|
|
DB_TXN* txn = NULL;
|
|
int error;
|
|
bool incremented_numDBs = false;
|
|
bool modified_DBs = false;
|
|
|
|
error = db_env->txn_begin(db_env, 0, &txn, 0);
|
|
if (error) { goto cleanup; }
|
|
|
|
error = tokudb_add_index(
|
|
table_arg,
|
|
key_info,
|
|
num_of_keys,
|
|
txn,
|
|
&incremented_numDBs,
|
|
&modified_DBs
|
|
);
|
|
if (error) { goto cleanup; }
|
|
|
|
cleanup:
|
|
if (error) {
|
|
if (txn) {
|
|
restore_add_index(table_arg, num_of_keys, incremented_numDBs, modified_DBs);
|
|
abort_txn(txn);
|
|
}
|
|
}
|
|
else {
|
|
commit_txn(txn, 0);
|
|
}
|
|
TOKUDB_DBUG_RETURN(error);
|
|
}
|
|
|
|
volatile int ha_tokudb_prepare_drop_index_wait = 0; //debug
|
|
|
|
//
|
|
// Prepares to drop indexes to the table. For each value, i, in the array key_num,
|
|
// table->key_info[i] is a key that is to be dropped.
|
|
// ***********NOTE*******************
|
|
// Although prepare_drop_index is supposed to just get the DB's ready for removal,
|
|
// and not actually do the removal, we are doing it here and not in final_drop_index
|
|
// For the flags we expose in alter_table_flags, namely xxx_NO_WRITES, this is allowed
|
|
// Changes for "future-proofing" this so that it works when we have the equivalent flags
|
|
// that are not NO_WRITES are not worth it at the moments
|
|
// Parameters:
|
|
// [in] table_arg - table that is being modified, seems to be identical to this->table
|
|
// [in] key_num - array of indexes that specify which keys of the array table->key_info
|
|
// are to be dropped
|
|
// num_of_keys - size of array, key_num
|
|
// Returns:
|
|
// 0 on success, error otherwise
|
|
//
|
|
int
|
|
ha_tokudb::prepare_drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys) {
|
|
TOKUDB_DBUG_ENTER("ha_tokudb::prepare_drop_index");
|
|
while (ha_tokudb_prepare_drop_index_wait) sleep(1); // debug
|
|
|
|
int error;
|
|
DB_TXN* txn = NULL;
|
|
|
|
error = db_env->txn_begin(db_env, 0, &txn, 0);
|
|
if (error) { goto cleanup; }
|
|
|
|
error = drop_indexes(table_arg, key_num, num_of_keys, table_arg->key_info, txn);
|
|
if (error) { goto cleanup; }
|
|
|
|
cleanup:
|
|
if (txn) {
|
|
if (error) {
|
|
abort_txn(txn);
|
|
restore_drop_indexes(table_arg, key_num, num_of_keys);
|
|
}
|
|
else {
|
|
commit_txn(txn,0);
|
|
}
|
|
}
|
|
|
|
TOKUDB_DBUG_RETURN(error);
|
|
}
|
|
|
|
volatile int ha_tokudb_final_drop_index_wait = 0; // debug
|
|
|
|
// ***********NOTE*******************
|
|
// Although prepare_drop_index is supposed to just get the DB's ready for removal,
|
|
// and not actually do the removal, we are doing it here and not in final_drop_index
|
|
// For the flags we expose in alter_table_flags, namely xxx_NO_WRITES, this is allowed
|
|
// Changes for "future-proofing" this so that it works when we have the equivalent flags
|
|
// that are not NO_WRITES are not worth it at the moments, therefore, we can make
|
|
// this function just return
|
|
int
|
|
ha_tokudb::final_drop_index(TABLE *table_arg) {
|
|
TOKUDB_DBUG_ENTER("ha_tokudb::final_drop_index");
|
|
while (ha_tokudb_final_drop_index_wait) sleep(1); // debug
|
|
|
|
int error = 0;
|
|
DBUG_EXECUTE_IF("final_drop_index_fail", {
|
|
error = 1;
|
|
});
|
|
TOKUDB_DBUG_RETURN(error);
|
|
}
|
|
|
|
#if defined(HA_GENERAL_ONLINE)
|
|
|
|
#include "ha_tokudb_alter_common.cc"
|
|
|
|
void
|
|
ha_tokudb::print_alter_info(
|
|
TABLE *altered_table,
|
|
HA_CREATE_INFO *create_info,
|
|
HA_ALTER_FLAGS *alter_flags,
|
|
uint table_changes
|
|
)
|
|
{
|
|
printf("***are keys of two tables same? %d\n", tables_have_same_keys(table,altered_table,false, false));
|
|
printf("***alter flags set ***\n");
|
|
for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) {
|
|
if (alter_flags->is_set(i)) {
|
|
printf("flag: %d\n", i);
|
|
}
|
|
}
|
|
//
|
|
// everyone calculates data by doing some default_values - record[0], but I do not see why
|
|
// that is necessary
|
|
//
|
|
printf("******\n");
|
|
printf("***orig table***\n");
|
|
for (uint i = 0; i < table->s->fields; i++) {
|
|
//
|
|
// make sure to use table->field, and NOT table->s->field
|
|
//
|
|
Field* curr_field = table->field[i];
|
|
uint null_offset = get_null_offset(table, curr_field);
|
|
printf(
|
|
"name: %s, nullable: %d, null_offset: %d, is_null_field: %d, is_null %d, \n",
|
|
curr_field->field_name,
|
|
curr_field->null_bit,
|
|
null_offset,
|
|
(curr_field->null_ptr != NULL),
|
|
(curr_field->null_ptr != NULL) ? table->s->default_values[null_offset] & curr_field->null_bit : 0xffffffff
|
|
);
|
|
}
|
|
printf("******\n");
|
|
printf("***altered table***\n");
|
|
for (uint i = 0; i < altered_table->s->fields; i++) {
|
|
Field* curr_field = altered_table->field[i];
|
|
uint null_offset = get_null_offset(altered_table, curr_field);
|
|
printf(
|
|
"name: %s, nullable: %d, null_offset: %d, is_null_field: %d, is_null %d, \n",
|
|
curr_field->field_name,
|
|
curr_field->null_bit,
|
|
null_offset,
|
|
(curr_field->null_ptr != NULL),
|
|
(curr_field->null_ptr != NULL) ? altered_table->s->default_values[null_offset] & curr_field->null_bit : 0xffffffff
|
|
);
|
|
}
|
|
printf("******\n");
|
|
}
|
|
|
|
static bool
|
|
alter_has_other_flag_set(HA_ALTER_FLAGS* alter_flags, uint flag) {
|
|
bool retval = false;
|
|
for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) {
|
|
if (i == flag)
|
|
{
|
|
continue;
|
|
}
|
|
if (alter_flags->is_set(i)) {
|
|
retval = true;
|
|
break;
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
int
|
|
ha_tokudb::check_if_supported_alter(TABLE *altered_table,
|
|
HA_CREATE_INFO *create_info,
|
|
HA_ALTER_FLAGS *alter_flags,
|
|
HA_ALTER_INFO *alter_info,
|
|
uint table_changes)
|
|
{
|
|
TOKUDB_DBUG_ENTER("check_if_supported_alter");
|
|
int retval;
|
|
THD* thd = ha_thd();
|
|
bool keys_same = tables_have_same_keys(table,altered_table, false, false);
|
|
|
|
|
|
if (tokudb_debug & TOKUDB_DEBUG_ALTER_TABLE_INFO) {
|
|
printf("has after or first %d\n", alter_info->contains_first_or_after);
|
|
print_alter_info(altered_table, create_info, alter_flags, table_changes);
|
|
}
|
|
bool has_added_columns = alter_flags->is_set(HA_ADD_COLUMN);
|
|
bool has_dropped_columns = alter_flags->is_set(HA_DROP_COLUMN);
|
|
bool has_column_rename = alter_flags->is_set(HA_CHANGE_COLUMN) &&
|
|
alter_flags->is_set(HA_ALTER_COLUMN_NAME);
|
|
bool has_auto_inc_change = alter_flags->is_set(HA_CHANGE_AUTOINCREMENT_VALUE);
|
|
//
|
|
// We do not check for changes to foreign keys or primary keys. They are not supported
|
|
// Changing the primary key implies changing keys in all dictionaries. that is why we don't
|
|
// try to make it fast
|
|
//
|
|
bool has_indexing_changes = alter_flags->is_set(HA_DROP_INDEX) ||
|
|
alter_flags->is_set(HA_DROP_UNIQUE_INDEX) ||
|
|
alter_flags->is_set(HA_ADD_INDEX) ||
|
|
alter_flags->is_set(HA_ADD_UNIQUE_INDEX);
|
|
|
|
// Check if the row format (read: compression) has
|
|
// changed as part of this alter statment.
|
|
bool has_row_format_changes = alter_flags->is_set(HA_ALTER_ROW_FORMAT);
|
|
bool has_non_indexing_changes = false;
|
|
bool has_non_dropped_changes = false;
|
|
bool has_non_added_changes = false;
|
|
bool has_non_column_rename_changes = false;
|
|
bool has_non_row_format_changes = false;
|
|
bool has_non_auto_inc_change = alter_has_other_flag_set(alter_flags, HA_CHANGE_AUTOINCREMENT_VALUE);
|
|
|
|
for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) {
|
|
if (i == HA_DROP_INDEX ||
|
|
i == HA_DROP_UNIQUE_INDEX ||
|
|
i == HA_ADD_INDEX ||
|
|
i == HA_ADD_UNIQUE_INDEX)
|
|
{
|
|
continue;
|
|
}
|
|
if (alter_flags->is_set(i)) {
|
|
has_non_indexing_changes = true;
|
|
break;
|
|
}
|
|
}
|
|
for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) {
|
|
if (i == HA_ALTER_COLUMN_NAME||
|
|
i == HA_CHANGE_COLUMN)
|
|
{
|
|
continue;
|
|
}
|
|
if (alter_flags->is_set(i)) {
|
|
has_non_column_rename_changes = true;
|
|
break;
|
|
}
|
|
}
|
|
for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) {
|
|
if (i == HA_DROP_COLUMN) {
|
|
continue;
|
|
}
|
|
if (keys_same &&
|
|
(i == HA_ALTER_INDEX || i == HA_ALTER_UNIQUE_INDEX || i == HA_ALTER_PK_INDEX)) {
|
|
continue;
|
|
}
|
|
if (alter_flags->is_set(i)) {
|
|
has_non_dropped_changes = true;
|
|
break;
|
|
}
|
|
}
|
|
for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) {
|
|
if (i == HA_ADD_COLUMN) {
|
|
continue;
|
|
}
|
|
if (keys_same &&
|
|
(i == HA_ALTER_INDEX || i == HA_ALTER_UNIQUE_INDEX || i == HA_ALTER_PK_INDEX)) {
|
|
continue;
|
|
}
|
|
if (alter_flags->is_set(i)) {
|
|
has_non_added_changes = true;
|
|
break;
|
|
}
|
|
}
|
|
// See if any flags other than row format have been set.
|
|
for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) {
|
|
if (i == HA_ALTER_ROW_FORMAT) {
|
|
continue;
|
|
}
|
|
if (alter_flags->is_set(i)) {
|
|
has_non_row_format_changes = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (tokudb_debug & TOKUDB_DEBUG_ALTER_TABLE_INFO) {
|
|
printf("has indexing changes %d, has non indexing changes %d\n", has_indexing_changes, has_non_indexing_changes);
|
|
}
|
|
#ifdef MARIADB_BASE_VERSION
|
|
#if MYSQL_VERSION_ID >= 50203
|
|
if (table->s->vfields || altered_table->s->vfields) {
|
|
retval = HA_ALTER_ERROR;
|
|
goto cleanup;
|
|
}
|
|
#endif
|
|
#endif
|
|
if (table->s->tmp_table != NO_TMP_TABLE) {
|
|
retval = (get_disable_slow_alter(thd)) ? HA_ALTER_ERROR : HA_ALTER_NOT_SUPPORTED;
|
|
goto cleanup;
|
|
}
|
|
if (!(are_null_bits_in_order(table) &&
|
|
are_null_bits_in_order(altered_table)
|
|
)
|
|
)
|
|
{
|
|
sql_print_error("Problems parsing null bits of the original and altered table");
|
|
retval = (get_disable_slow_alter(thd)) ? HA_ALTER_ERROR : HA_ALTER_NOT_SUPPORTED;
|
|
goto cleanup;
|
|
}
|
|
if (has_added_columns && !has_non_added_changes) {
|
|
uint32_t added_columns[altered_table->s->fields];
|
|
uint32_t num_added_columns = 0;
|
|
int r = find_changed_columns(
|
|
added_columns,
|
|
&num_added_columns,
|
|
table,
|
|
altered_table
|
|
);
|
|
if (r) {
|
|
retval = (get_disable_slow_alter(thd)) ? HA_ALTER_ERROR : HA_ALTER_NOT_SUPPORTED;
|
|
goto cleanup;
|
|
}
|
|
if (tokudb_debug & TOKUDB_DEBUG_ALTER_TABLE_INFO) {
|
|
for (uint32_t i = 0; i < num_added_columns; i++) {
|
|
uint32_t curr_added_index = added_columns[i];
|
|
Field* curr_added_field = altered_table->field[curr_added_index];
|
|
printf(
|
|
"Added column: index %d, name %s\n",
|
|
curr_added_index,
|
|
curr_added_field->field_name
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if (has_dropped_columns && !has_non_dropped_changes) {
|
|
uint32_t dropped_columns[table->s->fields];
|
|
uint32_t num_dropped_columns = 0;
|
|
int r = find_changed_columns(
|
|
dropped_columns,
|
|
&num_dropped_columns,
|
|
altered_table,
|
|
table
|
|
);
|
|
if (r) {
|
|
retval = (get_disable_slow_alter(thd)) ? HA_ALTER_ERROR : HA_ALTER_NOT_SUPPORTED;
|
|
goto cleanup;
|
|
}
|
|
if (tokudb_debug & TOKUDB_DEBUG_ALTER_TABLE_INFO) {
|
|
for (uint32_t i = 0; i < num_dropped_columns; i++) {
|
|
uint32_t curr_dropped_index = dropped_columns[i];
|
|
Field* curr_dropped_field = table->field[curr_dropped_index];
|
|
printf(
|
|
"Dropped column: index %d, name %s\n",
|
|
curr_dropped_index,
|
|
curr_dropped_field->field_name
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (has_indexing_changes && !has_non_indexing_changes) {
|
|
retval = HA_ALTER_SUPPORTED_WAIT_LOCK;
|
|
}
|
|
else if (has_dropped_columns && !has_non_dropped_changes) {
|
|
retval = HA_ALTER_SUPPORTED_WAIT_LOCK;
|
|
}
|
|
else if (has_added_columns && !has_non_added_changes) {
|
|
retval = HA_ALTER_SUPPORTED_WAIT_LOCK;
|
|
}
|
|
else if (has_row_format_changes && !has_non_row_format_changes && tables_have_same_keys_and_columns(table, altered_table, true)) {
|
|
retval = HA_ALTER_SUPPORTED_WAIT_LOCK;
|
|
}
|
|
else if (has_auto_inc_change && !has_non_auto_inc_change && tables_have_same_keys_and_columns(table, altered_table, true)) {
|
|
retval = HA_ALTER_SUPPORTED_WAIT_LOCK;
|
|
}
|
|
else if (has_column_rename && !has_non_column_rename_changes) {
|
|
// we have identified a possible column rename,
|
|
// but let's do some more checks
|
|
|
|
// we will only allow an hcr if there are no changes
|
|
// in column positions
|
|
if (alter_info->contains_first_or_after) {
|
|
retval = (get_disable_slow_alter(thd)) ? HA_ALTER_ERROR : HA_ALTER_NOT_SUPPORTED;
|
|
goto cleanup;
|
|
}
|
|
|
|
// now need to verify that one and only one column
|
|
// has changed only its name. If we find anything to
|
|
// the contrary, we don't allow it, also check indexes
|
|
|
|
bool cr_supported = column_rename_supported(table, altered_table, alter_info->contains_first_or_after);
|
|
if (cr_supported) {
|
|
retval = HA_ALTER_SUPPORTED_WAIT_LOCK;
|
|
}
|
|
else {
|
|
retval = (get_disable_slow_alter(thd)) ? HA_ALTER_ERROR : HA_ALTER_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
else {
|
|
retval = (get_disable_slow_alter(thd)) ? HA_ALTER_ERROR : HA_ALTER_NOT_SUPPORTED;
|
|
}
|
|
cleanup:
|
|
DBUG_RETURN(retval);
|
|
}
|
|
|
|
int
|
|
ha_tokudb::alter_table_phase2(
|
|
THD *thd,
|
|
TABLE *altered_table,
|
|
HA_CREATE_INFO *create_info,
|
|
HA_ALTER_INFO *alter_info,
|
|
HA_ALTER_FLAGS *alter_flags
|
|
)
|
|
{
|
|
TOKUDB_DBUG_ENTER("ha_tokudb::alter_table_phase2");
|
|
int error;
|
|
DB_TXN* txn = NULL;
|
|
bool incremented_numDBs = false;
|
|
bool modified_DBs = false;
|
|
bool has_dropped_columns = alter_flags->is_set(HA_DROP_COLUMN);
|
|
bool has_added_columns = alter_flags->is_set(HA_ADD_COLUMN);
|
|
bool has_row_format_changes = alter_flags->is_set(HA_ALTER_ROW_FORMAT);
|
|
KEY_AND_COL_INFO altered_kc_info;
|
|
memset(&altered_kc_info, 0, sizeof(altered_kc_info));
|
|
uint32_t max_new_desc_size = 0;
|
|
uchar* row_desc_buff = NULL;
|
|
uchar* column_extra = NULL;
|
|
bool dropping_indexes = alter_info->index_drop_count > 0 && !tables_have_same_keys(table,altered_table,false, false);
|
|
bool adding_indexes = alter_info->index_add_count > 0 && !tables_have_same_keys(table,altered_table,false, false);
|
|
bool change_autoinc = alter_flags->is_set(HA_CHANGE_AUTOINCREMENT_VALUE);
|
|
|
|
tokudb_trx_data* trx = (tokudb_trx_data *) thd_data_get(thd, tokudb_hton->slot);
|
|
|
|
is_fast_alter_running = true;
|
|
|
|
if (!trx ||
|
|
(trx->all != NULL) ||
|
|
(trx->sp_level != NULL) ||
|
|
(trx->stmt == NULL) ||
|
|
(trx->sub_sp_level != trx->stmt)
|
|
)
|
|
{
|
|
error = HA_ERR_UNSUPPORTED;
|
|
goto cleanup;
|
|
}
|
|
txn = trx->stmt;
|
|
|
|
error = allocate_key_and_col_info(altered_table->s, &altered_kc_info);
|
|
if (error) { goto cleanup; }
|
|
|
|
max_new_desc_size = get_max_desc_size(&altered_kc_info, altered_table);
|
|
row_desc_buff = (uchar *)my_malloc(max_new_desc_size, MYF(MY_WME));
|
|
if (row_desc_buff == NULL){ error = ENOMEM; goto cleanup;}
|
|
|
|
if (change_autoinc) {
|
|
error = write_auto_inc_create(share->status_block, create_info->auto_increment_value, txn);
|
|
if (error) { goto cleanup; }
|
|
}
|
|
|
|
// drop indexes
|
|
if (dropping_indexes) {
|
|
error = drop_indexes(table, alter_info->index_drop_buffer, alter_info->index_drop_count, table->key_info, txn);
|
|
if (error) { goto cleanup; }
|
|
}
|
|
|
|
// add indexes
|
|
if (adding_indexes) {
|
|
KEY *key_info;
|
|
KEY *key;
|
|
uint *idx_p;
|
|
uint *idx_end_p;
|
|
KEY_PART_INFO *key_part;
|
|
KEY_PART_INFO *part_end;
|
|
/* The add_index() method takes an array of KEY structs. */
|
|
key_info= (KEY*) thd->alloc(sizeof(KEY) * alter_info->index_add_count);
|
|
key= key_info;
|
|
for (idx_p= alter_info->index_add_buffer, idx_end_p= idx_p + alter_info->index_add_count;
|
|
idx_p < idx_end_p;
|
|
idx_p++, key++)
|
|
{
|
|
/* Copy the KEY struct. */
|
|
*key= alter_info->key_info_buffer[*idx_p];
|
|
/* Fix the key parts. */
|
|
part_end= key->key_part + key->key_parts;
|
|
for (key_part= key->key_part; key_part < part_end; key_part++)
|
|
key_part->field = table->field[key_part->fieldnr];
|
|
}
|
|
error = tokudb_add_index(
|
|
table,
|
|
key_info,
|
|
alter_info->index_add_count,
|
|
txn,
|
|
&incremented_numDBs,
|
|
&modified_DBs
|
|
);
|
|
if (error) {
|
|
// hack for now, in case of duplicate key error,
|
|
// because at the moment we cannot display the right key
|
|
// information to the user, so that he knows potentially what went
|
|
// wrong.
|
|
last_dup_key = MAX_KEY;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if (has_dropped_columns || has_added_columns) {
|
|
DBT column_dbt;
|
|
memset(&column_dbt, 0, sizeof(DBT));
|
|
uint32_t max_column_extra_size;
|
|
uint32_t num_column_extra;
|
|
uint32_t columns[table->s->fields + altered_table->s->fields]; // set size such that we know it is big enough for both cases
|
|
uint32_t num_columns = 0;
|
|
uint32_t curr_num_DBs = table->s->keys + test(hidden_primary_key);
|
|
memset(columns, 0, sizeof(columns));
|
|
|
|
if (has_added_columns && has_dropped_columns) {
|
|
error = HA_ERR_UNSUPPORTED;
|
|
goto cleanup;
|
|
}
|
|
if (!tables_have_same_keys(table, altered_table, true, false)) {
|
|
error = HA_ERR_UNSUPPORTED;
|
|
goto cleanup;
|
|
}
|
|
|
|
error = initialize_key_and_col_info(
|
|
altered_table->s,
|
|
altered_table,
|
|
&altered_kc_info,
|
|
hidden_primary_key,
|
|
primary_key
|
|
);
|
|
if (error) { goto cleanup; }
|
|
|
|
// generate the array of columns
|
|
if (has_dropped_columns) {
|
|
find_changed_columns(
|
|
columns,
|
|
&num_columns,
|
|
altered_table,
|
|
table
|
|
);
|
|
}
|
|
if (has_added_columns) {
|
|
find_changed_columns(
|
|
columns,
|
|
&num_columns,
|
|
table,
|
|
altered_table
|
|
);
|
|
}
|
|
max_column_extra_size =
|
|
STATIC_ROW_MUTATOR_SIZE + //max static row_mutator
|
|
4 + num_columns*(1+1+4+1+1+4) + altered_table->s->reclength + // max dynamic row_mutator
|
|
(4 + share->kc_info.num_blobs) + // max static blob size
|
|
(num_columns*(1+4+1+4)); // max dynamic blob size
|
|
column_extra = (uchar *)my_malloc(max_column_extra_size, MYF(MY_WME));
|
|
if (column_extra == NULL) { error = ENOMEM; goto cleanup; }
|
|
|
|
for (uint32_t i = 0; i < curr_num_DBs; i++) {
|
|
DBT row_descriptor;
|
|
memset(&row_descriptor, 0, sizeof(row_descriptor));
|
|
KEY* prim_key = (hidden_primary_key) ? NULL : &altered_table->s->key_info[primary_key];
|
|
KEY* key_info = &altered_table->key_info[i];
|
|
if (i == primary_key) {
|
|
row_descriptor.size = create_main_key_descriptor(
|
|
row_desc_buff,
|
|
prim_key,
|
|
hidden_primary_key,
|
|
primary_key,
|
|
altered_table,
|
|
&altered_kc_info
|
|
);
|
|
row_descriptor.data = row_desc_buff;
|
|
}
|
|
else {
|
|
row_descriptor.size = create_secondary_key_descriptor(
|
|
row_desc_buff,
|
|
key_info,
|
|
prim_key,
|
|
hidden_primary_key,
|
|
altered_table,
|
|
primary_key,
|
|
i,
|
|
&altered_kc_info
|
|
);
|
|
row_descriptor.data = row_desc_buff;
|
|
}
|
|
error = share->key_file[i]->change_descriptor(
|
|
share->key_file[i],
|
|
txn,
|
|
&row_descriptor,
|
|
0
|
|
);
|
|
if (error) { goto cleanup; }
|
|
|
|
if (i == primary_key || table_share->key_info[i].flags & HA_CLUSTERING) {
|
|
num_column_extra = fill_row_mutator(
|
|
column_extra,
|
|
columns,
|
|
num_columns,
|
|
altered_table,
|
|
&altered_kc_info,
|
|
i,
|
|
has_added_columns // true if adding columns, otherwise is a drop
|
|
);
|
|
|
|
column_dbt.data = column_extra;
|
|
column_dbt.size = num_column_extra;
|
|
DBUG_ASSERT(num_column_extra <= max_column_extra_size);
|
|
|
|
error = share->key_file[i]->update_broadcast(
|
|
share->key_file[i],
|
|
txn,
|
|
&column_dbt,
|
|
DB_IS_RESETTING_OP
|
|
);
|
|
if (error) { goto cleanup; }
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check if compression type has been altered.
|
|
if (has_row_format_changes) {
|
|
// Determine the new compression type.
|
|
enum toku_compression_method method = TOKU_NO_COMPRESSION;
|
|
method = row_type_to_compression_method(create_info->row_type);
|
|
|
|
// Set the new type.
|
|
uint32_t curr_num_DBs = table->s->keys + test(hidden_primary_key);
|
|
for (uint32_t i = 0; i < curr_num_DBs; ++i) {
|
|
DB *db = share->key_file[i];
|
|
error = db->change_compression_method(db, method);
|
|
if (error) {
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
// update frm file
|
|
// only for tables that are not partitioned
|
|
if (altered_table->part_info == NULL) {
|
|
error = write_frm_data(share->status_block, txn, altered_table->s->path.str);
|
|
if (error) { goto cleanup; }
|
|
}
|
|
if (thd->killed) {
|
|
error = ER_ABORTING_CONNECTION;
|
|
goto cleanup;
|
|
}
|
|
|
|
error = 0;
|
|
cleanup:
|
|
free_key_and_col_info(&altered_kc_info);
|
|
my_free(row_desc_buff, MYF(MY_ALLOW_ZERO_PTR));
|
|
my_free(column_extra, MYF(MY_ALLOW_ZERO_PTR));
|
|
if (txn) {
|
|
if (error) {
|
|
if (adding_indexes) {
|
|
restore_add_index(table, alter_info->index_add_count, incremented_numDBs, modified_DBs);
|
|
}
|
|
abort_txn(txn);
|
|
trx->stmt = NULL;
|
|
trx->sub_sp_level = NULL;
|
|
if (dropping_indexes) {
|
|
restore_drop_indexes(table, alter_info->index_drop_buffer, alter_info->index_drop_count);
|
|
}
|
|
}
|
|
}
|
|
TOKUDB_DBUG_RETURN(error);
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|