summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc356
1 files changed, 174 insertions, 182 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 448d095c876..648e05a4116 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2010, 2017, MariaDB Corporation.
+ Copyright (c) 2010, 2018, MariaDB
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
@@ -29,8 +29,7 @@
#include "lock.h" // mysql_unlock_tables
#include "strfunc.h" // find_type2, find_set
#include "sql_truncate.h" // regenerate_locked_table
-#include "sql_partition.h" // mem_alloc_error,
- // generate_partition_syntax,
+#include "sql_partition.h" // generate_partition_syntax,
// partition_info
// NOT_A_PARTITION_ID
#include "sql_db.h" // load_db_opt_by_name
@@ -115,7 +114,7 @@ static char* add_identifier(THD* thd, char *to_p, const char * end_p,
res= strconvert(&my_charset_filename, conv_name, name_len,
system_charset_info,
conv_string, FN_REFLEN, &errors);
- if (!res || errors)
+ if (unlikely(!res || errors))
{
DBUG_PRINT("error", ("strconvert of '%s' failed with %u (errors: %u)", conv_name, res, errors));
conv_name= name;
@@ -128,7 +127,9 @@ static char* add_identifier(THD* thd, char *to_p, const char * end_p,
conv_name_end= conv_string + res;
}
- quote = thd ? get_quote_char_for_identifier(thd, conv_name, res - 1) : '`';
+ quote= (likely(thd) ?
+ get_quote_char_for_identifier(thd, conv_name, res - 1) :
+ '`');
if (quote != EOF && (end_p - to_p > 2))
{
@@ -390,7 +391,7 @@ uint filename_to_tablename(const char *from, char *to, size_t to_length,
res= strconvert(&my_charset_filename, from, FN_REFLEN,
system_charset_info, to, to_length, &errors);
- if (errors) // Old 5.0 name
+ if (unlikely(errors)) // Old 5.0 name
{
res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX, from, NullS) -
to);
@@ -1144,11 +1145,8 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
}
hton= plugin_data(plugin, handlerton*);
file= get_new_handler((TABLE_SHARE*)0, &mem_root, hton);
- if (!file)
- {
- mem_alloc_error(sizeof(handler));
+ if (unlikely(!file))
goto error;
- }
}
switch (ddl_log_entry->action_type)
{
@@ -1160,7 +1158,8 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
if (frm_action)
{
strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
- if ((error= mysql_file_delete(key_file_frm, to_path, MYF(MY_WME))))
+ if (unlikely((error= mysql_file_delete(key_file_frm, to_path,
+ MYF(MY_WME)))))
{
if (my_errno != ENOENT)
break;
@@ -1172,7 +1171,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
}
else
{
- if ((error= file->ha_delete_table(ddl_log_entry->name)))
+ if (unlikely((error= file->ha_delete_table(ddl_log_entry->name))))
{
if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE)
break;
@@ -1425,19 +1424,19 @@ bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
+ (2*FN_REFLEN)],
(char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS
+ (3*FN_REFLEN)]));
- if (write_ddl_log_file_entry((*active_entry)->entry_pos))
+ if (unlikely(write_ddl_log_file_entry((*active_entry)->entry_pos)))
{
error= TRUE;
sql_print_error("Failed to write entry_no = %u",
(*active_entry)->entry_pos);
}
- if (write_header && !error)
+ if (write_header && likely(!error))
{
(void) sync_ddl_log_no_lock();
if (write_ddl_log_header())
error= TRUE;
}
- if (error)
+ if (unlikely(error))
release_ddl_log_memory_entry(*active_entry);
DBUG_RETURN(error);
}
@@ -1868,8 +1867,10 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
lpt->create_info->tmp_table(), frm.str, frm.length);
my_free(const_cast<uchar*>(frm.str));
- if (error || lpt->table->file->ha_create_partitioning_metadata(shadow_path,
- NULL, CHF_CREATE_FLAG))
+ if (unlikely(error) ||
+ unlikely(lpt->table->file->
+ ha_create_partitioning_metadata(shadow_path,
+ NULL, CHF_CREATE_FLAG)))
{
mysql_file_delete(key_file_frm, shadow_frm_name, MYF(0));
error= 1;
@@ -2127,7 +2128,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists,
false, drop_sequence, false, false);
thd->pop_internal_handler();
- if (error)
+ if (unlikely(error))
DBUG_RETURN(TRUE);
my_ok(thd);
DBUG_RETURN(FALSE);
@@ -2524,26 +2525,26 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
*/
(void) mysql_file_delete(key_file_frm, path, MYF(0));
}
- else if (mysql_file_delete(key_file_frm, path,
- MYF(MY_WME)))
+ else if (unlikely(mysql_file_delete(key_file_frm, path,
+ MYF(MY_WME))))
{
frm_delete_error= my_errno;
DBUG_ASSERT(frm_delete_error);
}
}
- if (!error)
+ if (likely(!error))
{
int trigger_drop_error= 0;
- if (!frm_delete_error)
+ if (likely(!frm_delete_error))
{
non_tmp_table_deleted= TRUE;
trigger_drop_error=
Table_triggers_list::drop_all_triggers(thd, &db, &table->table_name);
}
- if (trigger_drop_error ||
+ if (unlikely(trigger_drop_error) ||
(frm_delete_error && frm_delete_error != ENOENT))
error= 1;
else if (frm_delete_error && if_exists)
@@ -3190,8 +3191,10 @@ bool Column_definition::prepare_stage1_string(THD *thd,
Convert the default value from client character
set into the column character set if necessary.
We can only do this for constants as we have not yet run fix_fields.
+ But not for blobs, as they will be stored as SQL expressions, not
+ written down into the record image.
*/
- if (default_value &&
+ if (!(flags & BLOB_FLAG) && default_value &&
default_value->expr->basic_const_item() &&
charset != default_value->expr->collation.collation)
{
@@ -4487,12 +4490,10 @@ handler *mysql_create_frm_image(THD *thd,
db_options= create_info->table_options_with_row_type();
- if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
- create_info->db_type)))
- {
- mem_alloc_error(sizeof(handler));
+ if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
+ create_info->db_type))))
DBUG_RETURN(NULL);
- }
+
#ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *part_info= thd->work_part_info;
@@ -4505,11 +4506,9 @@ handler *mysql_create_frm_image(THD *thd,
object with the default settings.
*/
thd->work_part_info= part_info= new partition_info();
- if (!part_info)
- {
- mem_alloc_error(sizeof(partition_info));
+ if (unlikely(!part_info))
goto err;
- }
+
file->set_auto_partitions(part_info);
part_info->default_engine_type= create_info->db_type;
part_info->is_auto_partitioned= TRUE;
@@ -4680,12 +4679,9 @@ handler *mysql_create_frm_image(THD *thd,
engines in partition clauses.
*/
delete file;
- if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
- engine_type)))
- {
- mem_alloc_error(sizeof(handler));
+ if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
+ engine_type))))
DBUG_RETURN(NULL);
- }
}
}
/*
@@ -4809,10 +4805,14 @@ int create_table_impl(THD *thd,
create_info->data_file_name= create_info->index_file_name= 0;
}
else
- if (error_if_data_home_dir(create_info->data_file_name, "DATA DIRECTORY") ||
- error_if_data_home_dir(create_info->index_file_name, "INDEX DIRECTORY")||
- check_partition_dirs(thd->lex->part_info))
- goto err;
+ {
+ if (unlikely(error_if_data_home_dir(create_info->data_file_name,
+ "DATA DIRECTORY")) ||
+ unlikely(error_if_data_home_dir(create_info->index_file_name,
+ "INDEX DIRECTORY")) ||
+ unlikely(check_partition_dirs(thd->lex->part_info)))
+ goto err;
+ }
alias= const_cast<LEX_CSTRING*>(table_case_name(create_info, table_name));
@@ -5173,7 +5173,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
This should always work as we have a meta lock on the table.
*/
thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables);
- if (thd->locked_tables_list.reopen_tables(thd))
+ if (thd->locked_tables_list.reopen_tables(thd, false))
{
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
result= 1;
@@ -5195,9 +5195,10 @@ err:
thd->transaction.stmt.mark_created_temp_table();
/* Write log if no error or if we already deleted a table */
- if (!result || thd->log_current_statement)
+ if (likely(!result) || thd->log_current_statement)
{
- if (result && create_info->table_was_deleted && pos_in_locked_tables)
+ if (unlikely(result) && create_info->table_was_deleted &&
+ pos_in_locked_tables)
{
/*
Possible locked table was dropped. We should remove meta data locks
@@ -5205,7 +5206,7 @@ err:
*/
thd->locked_tables_list.unlock_locked_table(thd, mdl_ticket);
}
- else if (!result && create_info->tmp_table() && create_info->table)
+ else if (likely(!result) && create_info->tmp_table() && create_info->table)
{
/*
Remember that tmp table creation was logged so that we know if
@@ -5213,8 +5214,8 @@ err:
*/
create_info->table->s->table_creation_was_logged= 1;
}
- if (write_bin_log(thd, result ? FALSE : TRUE, thd->query(),
- thd->query_length(), is_trans))
+ if (unlikely(write_bin_log(thd, result ? FALSE : TRUE, thd->query(),
+ thd->query_length(), is_trans)))
result= 1;
}
DBUG_RETURN(result);
@@ -5439,9 +5440,9 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
error= my_errno;
(void) file->ha_create_partitioning_metadata(to, from, CHF_RENAME_FLAG);
}
- else if (!file || !(error=file->ha_rename_table(from_base, to_base)))
+ else if (!file || likely(!(error=file->ha_rename_table(from_base, to_base))))
{
- if (!(flags & NO_FRM_RENAME) && rename_file_ext(from,to,reg_ext))
+ if (!(flags & NO_FRM_RENAME) && unlikely(rename_file_ext(from,to,reg_ext)))
{
error=my_errno;
if (file)
@@ -5454,10 +5455,14 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
}
}
delete file;
- if (error == HA_ERR_WRONG_COMMAND)
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
- else if (error)
- my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
+
+ if (unlikely(error))
+ {
+ if (error == HA_ERR_WRONG_COMMAND)
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
+ else
+ my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
+ }
else if (!(flags & FN_IS_TMP))
mysql_audit_rename_table(thd, old_db, old_name, new_db, new_name);
@@ -5625,7 +5630,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
This should always work as we have a meta lock on the table.
*/
thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables);
- if (thd->locked_tables_list.reopen_tables(thd))
+ if (thd->locked_tables_list.reopen_tables(thd, false))
{
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
res= 1; // We got an error
@@ -5859,7 +5864,7 @@ int mysql_discard_or_import_tablespace(THD *thd,
THD_STAGE_INFO(thd, stage_end);
- if (error)
+ if (unlikely(error))
goto err;
/*
@@ -5870,15 +5875,15 @@ int mysql_discard_or_import_tablespace(THD *thd,
/* The ALTER TABLE is always in its own transaction */
error= trans_commit_stmt(thd);
- if (trans_commit_implicit(thd))
+ if (unlikely(trans_commit_implicit(thd)))
error=1;
- if (!error)
+ if (likely(!error))
error= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
err:
thd->tablespace_op=FALSE;
- if (error == 0)
+ if (likely(error == 0))
{
my_ok(thd);
DBUG_RETURN(0);
@@ -6007,7 +6012,7 @@ drop_create_field:
break;
}
}
- if (*f_ptr == NULL)
+ if (unlikely(*f_ptr == NULL))
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_BAD_FIELD_ERROR,
@@ -6043,7 +6048,7 @@ drop_create_field:
acol->name, (*f_ptr)->field_name.str) == 0)
break;
}
- if (*f_ptr == NULL)
+ if (unlikely(*f_ptr == NULL))
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_BAD_FIELD_ERROR,
@@ -7216,18 +7221,20 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
}
- if (error == HA_ERR_WRONG_COMMAND)
+ if (unlikely(error))
{
- THD *thd= table->in_use;
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
- ER_ILLEGAL_HA, ER_THD(thd, ER_ILLEGAL_HA),
- table->file->table_type(),
- table->s->db.str, table->s->table_name.str);
- error= 0;
+ if (error == HA_ERR_WRONG_COMMAND)
+ {
+ THD *thd= table->in_use;
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_ILLEGAL_HA, ER_THD(thd, ER_ILLEGAL_HA),
+ table->file->table_type(),
+ table->s->db.str, table->s->table_name.str);
+ error= 0;
+ }
+ else
+ table->file->print_error(error, MYF(0));
}
- else if (error)
- table->file->print_error(error, MYF(0));
-
DBUG_RETURN(error);
}
@@ -7365,8 +7372,11 @@ static bool mysql_inplace_alter_table(THD *thd,
exclusive lock is required for duration of the whole statement.
*/
if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
- ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
- inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) &&
+ ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_INSTANT) &&
(thd->locked_tables_mode == LTM_LOCK_TABLES ||
thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) ||
alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)
@@ -7390,8 +7400,11 @@ static bool mysql_inplace_alter_table(THD *thd,
*/
reopen_tables= true;
}
- else if (inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
- inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE)
+ else if (inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_INSTANT)
{
/*
Storage engine has requested exclusive lock only for prepare phase
@@ -7436,7 +7449,9 @@ static bool mysql_inplace_alter_table(THD *thd,
DBUG_ASSERT(0);
// fall through
case HA_ALTER_INPLACE_NO_LOCK:
- case HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE:
+ case HA_ALTER_INPLACE_INSTANT:
+ case HA_ALTER_INPLACE_COPY_NO_LOCK:
+ case HA_ALTER_INPLACE_NOCOPY_NO_LOCK:
switch (alter_info->requested_lock) {
case Alter_info::ALTER_TABLE_LOCK_DEFAULT:
case Alter_info::ALTER_TABLE_LOCK_NONE:
@@ -7448,8 +7463,9 @@ static bool mysql_inplace_alter_table(THD *thd,
}
break;
case HA_ALTER_INPLACE_EXCLUSIVE_LOCK:
- case HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE:
case HA_ALTER_INPLACE_SHARED_LOCK:
+ case HA_ALTER_INPLACE_COPY_LOCK:
+ case HA_ALTER_INPLACE_NOCOPY_LOCK:
break;
}
@@ -7464,19 +7480,23 @@ static bool mysql_inplace_alter_table(THD *thd,
necessary only for prepare phase (unless we are not under LOCK TABLES) and
user has not explicitly requested exclusive lock.
*/
- if ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
- inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) &&
+ if ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK) &&
!(thd->locked_tables_mode == LTM_LOCK_TABLES ||
thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) &&
(alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE))
{
/* If storage engine or user requested shared lock downgrade to SNW. */
- if (inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
+ if (inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED)
table->mdl_ticket->downgrade_lock(MDL_SHARED_NO_WRITE);
else
{
- DBUG_ASSERT(inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE);
+ DBUG_ASSERT(inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
+ inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK);
table->mdl_ticket->downgrade_lock(MDL_SHARED_UPGRADABLE);
}
}
@@ -7633,7 +7653,7 @@ static bool mysql_inplace_alter_table(THD *thd,
HA_EXTRA_PREPARE_FOR_RENAME :
HA_EXTRA_NOT_USED,
NULL);
- if (thd->locked_tables_list.reopen_tables(thd))
+ if (thd->locked_tables_list.reopen_tables(thd, false))
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
/* QQ; do something about metadata locks ? */
}
@@ -7888,6 +7908,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (field->default_value)
field->default_value->expr->walk(&Item::rename_fields_processor, 1,
&column_rename_param);
+ table->m_needs_reopen= 1; // because new column name is on thd->mem_root
}
/* Check if field is changed */
@@ -8007,7 +8028,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
break;
}
- if (find && !find->field)
+ if (likely(find && !find->field))
find_it.remove();
else
{
@@ -8078,7 +8099,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
&find->field_name))
break;
}
- if (!find)
+ if (unlikely(!find))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after.str,
table->s->table_name.str);
@@ -8112,13 +8133,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
alter_it.remove();
}
}
- if (alter_info->alter_list.elements)
+ if (unlikely(alter_info->alter_list.elements))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0),
alter_info->alter_list.head()->name, table->s->table_name.str);
goto err;
}
- if (!new_create_list.elements)
+ if (unlikely(!new_create_list.elements))
{
my_message(ER_CANT_REMOVE_ALL_FIELDS,
ER_THD(thd, ER_CANT_REMOVE_ALL_FIELDS),
@@ -8594,7 +8615,7 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
table->file->get_parent_foreign_key_list(thd, &fk_parent_key_list);
/* OOM when building list. */
- if (thd->is_error())
+ if (unlikely(thd->is_error()))
DBUG_RETURN(true);
/*
@@ -8689,7 +8710,7 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
table->file->get_foreign_key_list(thd, &fk_child_key_list);
/* OOM when building list. */
- if (thd->is_error())
+ if (unlikely(thd->is_error()))
DBUG_RETURN(true);
/*
@@ -8783,7 +8804,7 @@ simple_tmp_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
keys_onoff);
}
- if (!error && alter_ctx->is_table_renamed())
+ if (likely(!error) && alter_ctx->is_table_renamed())
{
THD_STAGE_INFO(thd, stage_rename);
@@ -8796,20 +8817,17 @@ simple_tmp_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
&alter_ctx->new_alias);
}
- if (!error)
+ if (likely(!error))
{
- int res= 0;
/*
We do not replicate alter table statement on temporary tables under
ROW-based replication.
*/
if (!thd->is_current_stmt_binlog_format_row())
{
- res= write_bin_log(thd, true, thd->query(), thd->query_length());
+ error= write_bin_log(thd, true, thd->query(), thd->query_length()) != 0;
}
- if (res != 0)
- error= true;
- else
+ if (likely(!error))
my_ok(thd);
}
@@ -8858,7 +8876,7 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
keys_onoff);
}
- if (!error && alter_ctx->is_table_renamed())
+ if (likely(!error) && alter_ctx->is_table_renamed())
{
THD_STAGE_INFO(thd, stage_rename);
handlerton *old_db_type= table->s->db_type();
@@ -8898,11 +8916,11 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
}
}
- if (!error)
+ if (likely(!error))
{
error= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
- if (!error)
+ if (likely(!error))
my_ok(thd);
}
table_list->table= NULL; // For query cache
@@ -8963,7 +8981,8 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
based on information about the table changes from fill_alter_inplace_info().
*/
-bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, const LEX_CSTRING *new_name,
+bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
+ const LEX_CSTRING *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
Alter_info *alter_info,
@@ -9065,7 +9084,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, const LEX_CSTRING *n
};);
#endif // WITH_WSREP
- if (error)
+ if (unlikely(error))
DBUG_RETURN(true);
table->use_all_columns();
@@ -9386,7 +9405,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, const LEX_CSTRING *n
supports auto-partitioning as such engines can do some changes
using in-place API.
*/
- if ((thd->variables.old_alter_table &&
+ if ((thd->variables.alter_algorithm == Alter_info::ALTER_TABLE_ALGORITHM_COPY &&
alter_info->requested_algorithm !=
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
|| is_inplace_alter_impossible(table, create_info, alter_info)
@@ -9511,7 +9530,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, const LEX_CSTRING *n
&key_info, &key_count, &frm);
reenable_binlog(thd);
thd->abort_on_warning= false;
- if (error)
+ if (unlikely(error))
{
my_free(const_cast<uchar*>(frm.str));
DBUG_RETURN(true);
@@ -9594,74 +9613,32 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, const LEX_CSTRING *n
goto err_new_table_cleanup;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
+ if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE)
+ ha_alter_info.online= true;
// Ask storage engine whether to use copy or in-place
enum_alter_inplace_result inplace_supported=
table->file->check_if_supported_inplace_alter(altered_table,
&ha_alter_info);
- switch (inplace_supported) {
- case HA_ALTER_INPLACE_EXCLUSIVE_LOCK:
- // If SHARED lock and no particular algorithm was requested, use COPY.
- if (alter_info->requested_lock ==
- Alter_info::ALTER_TABLE_LOCK_SHARED &&
- alter_info->requested_algorithm ==
- Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT)
- {
- use_inplace= false;
- }
- // Otherwise, if weaker lock was requested, report errror.
- else if (alter_info->requested_lock ==
- Alter_info::ALTER_TABLE_LOCK_NONE ||
- alter_info->requested_lock ==
- Alter_info::ALTER_TABLE_LOCK_SHARED)
- {
- ha_alter_info.report_unsupported_error("LOCK=NONE/SHARED",
- "LOCK=EXCLUSIVE");
- thd->drop_temporary_table(altered_table, NULL, false);
- goto err_new_table_cleanup;
- }
- break;
- case HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE:
- case HA_ALTER_INPLACE_SHARED_LOCK:
- // If weaker lock was requested, report errror.
- if (alter_info->requested_lock ==
- Alter_info::ALTER_TABLE_LOCK_NONE)
- {
- ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
- thd->drop_temporary_table(altered_table, NULL, false);
- goto err_new_table_cleanup;
- }
- break;
- case HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE:
- case HA_ALTER_INPLACE_NO_LOCK:
- break;
- case HA_ALTER_INPLACE_NOT_SUPPORTED:
- // If INPLACE was requested, report error.
- if (alter_info->requested_algorithm ==
- Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
- {
- ha_alter_info.report_unsupported_error("ALGORITHM=INPLACE",
- "ALGORITHM=COPY");
- thd->drop_temporary_table(altered_table, NULL, false);
- goto err_new_table_cleanup;
- }
- // COPY with LOCK=NONE is not supported, no point in trying.
- if (alter_info->requested_lock ==
- Alter_info::ALTER_TABLE_LOCK_NONE)
- {
- ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
- thd->drop_temporary_table(altered_table, NULL, false);
- goto err_new_table_cleanup;
- }
- // Otherwise use COPY
- use_inplace= false;
- break;
- case HA_ALTER_ERROR:
- default:
+ if (alter_info->supports_algorithm(thd, inplace_supported, &ha_alter_info) ||
+ alter_info->supports_lock(thd, inplace_supported, &ha_alter_info))
+ {
thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup;
}
+ // If SHARED lock and no particular algorithm was requested, use COPY.
+ if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK &&
+ alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED &&
+ alter_info->requested_algorithm ==
+ Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT &&
+ thd->variables.alter_algorithm ==
+ Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT)
+ use_inplace= false;
+
+ if (inplace_supported == HA_ALTER_INPLACE_NOT_SUPPORTED)
+ use_inplace= false;
+
if (use_inplace)
{
table->s->frm_image= &frm;
@@ -9967,7 +9944,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, const LEX_CSTRING *n
end_inplace:
- if (thd->locked_tables_list.reopen_tables(thd))
+ if (thd->locked_tables_list.reopen_tables(thd, false))
goto err_with_mdl_after_alter;
THD_STAGE_INFO(thd, stage_end);
@@ -10018,8 +9995,8 @@ err_new_table_cleanup:
the table to be altered isn't empty.
Report error here.
*/
- if (alter_ctx.error_if_not_empty &&
- thd->get_stmt_da()->current_row_for_warning())
+ if (unlikely(alter_ctx.error_if_not_empty &&
+ thd->get_stmt_da()->current_row_for_warning()))
{
const char *f_val= 0;
enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
@@ -10083,9 +10060,7 @@ bool mysql_trans_prepare_alter_copy_data(THD *thd)
This needs to be done before external_lock.
*/
- if (ha_enable_transaction(thd, FALSE))
- DBUG_RETURN(TRUE);
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(ha_enable_transaction(thd, FALSE) != 0);
}
@@ -10138,6 +10113,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
List<Item> fields;
List<Item> all_fields;
bool auto_increment_field_copied= 0;
+ bool cleanup_done= 0;
bool init_read_record_done= 0;
sql_mode_t save_sql_mode= thd->variables.sql_mode;
ulonglong prev_insert_id, time_to_report_progress;
@@ -10153,15 +10129,23 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
/* Two or 3 stages; Sorting, copying data and update indexes */
thd_progress_init(thd, 2 + MY_TEST(order));
- if (mysql_trans_prepare_alter_copy_data(thd))
+ if (!(copy= new (thd->mem_root) Copy_field[to->s->fields]))
DBUG_RETURN(-1);
- if (!(copy= new (thd->mem_root) Copy_field[to->s->fields]))
- DBUG_RETURN(-1); /* purecov: inspected */
+ if (mysql_trans_prepare_alter_copy_data(thd))
+ {
+ delete [] copy;
+ DBUG_RETURN(-1);
+ }
/* We need external lock before we can disable/enable keys */
if (to->file->ha_external_lock(thd, F_WRLCK))
+ {
+ /* Undo call to mysql_trans_prepare_alter_copy_data() */
+ ha_enable_transaction(thd, TRUE);
+ delete [] copy;
DBUG_RETURN(-1);
+ }
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
@@ -10172,7 +10156,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
to->file->extra(HA_EXTRA_PREPARE_FOR_ALTER_TABLE);
to->file->ha_start_bulk_insert(from->file->stats.records,
ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT);
-
List_iterator<Create_field> it(create);
Create_field *def;
copy_end=copy;
@@ -10285,15 +10268,15 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
if (!ignore) /* for now, InnoDB needs the undo log for ALTER IGNORE */
to->file->extra(HA_EXTRA_BEGIN_ALTER_COPY);
- while (!(error= info.read_record()))
+ while (likely(!(error= info.read_record())))
{
- if (thd->killed)
+ if (unlikely(thd->killed))
{
thd->send_kill_message();
error= 1;
break;
}
- if (++thd->progress.counter >= time_to_report_progress)
+ if (unlikely(++thd->progress.counter >= time_to_report_progress))
{
time_to_report_progress+= MY_HOW_OFTEN_TO_WRITE/10;
thd_progress_report(thd, thd->progress.counter,
@@ -10301,7 +10284,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
}
/* Return error if source table isn't empty. */
- if (alter_ctx->error_if_not_empty)
+ if (unlikely(alter_ctx->error_if_not_empty))
{
error= 1;
break;
@@ -10343,7 +10326,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
/* This will set thd->is_error() if fatal failure */
if (to->verify_constraints(ignore) == VIEW_CHECK_SKIP)
continue;
- if (thd->is_error())
+ if (unlikely(thd->is_error()))
{
error= 1;
break;
@@ -10353,7 +10336,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
error= to->file->ha_write_row(to->record[0]);
to->auto_increment_field_not_null= FALSE;
- if (error)
+ if (unlikely(error))
{
if (to->file->is_fatal_error(error, HA_CHECK_DUP))
{
@@ -10365,7 +10348,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
else
{
/* Duplicate key error. */
- if (alter_ctx->fk_error_if_delete_row)
+ if (unlikely(alter_ctx->fk_error_if_delete_row))
{
/*
We are trying to omit a row from the table which serves as parent
@@ -10421,7 +10404,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
/* We are going to drop the temporary table */
to->file->extra(HA_EXTRA_PREPARE_FOR_DROP);
}
- if (to->file->ha_end_bulk_insert() && error <= 0)
+ if (unlikely(to->file->ha_end_bulk_insert()) && error <= 0)
{
/* Give error, if not already given */
if (!thd->is_error())
@@ -10430,9 +10413,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
}
if (!ignore)
to->file->extra(HA_EXTRA_END_ALTER_COPY);
+
+ cleanup_done= 1;
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
- if (mysql_trans_commit_alter_copy_data(thd))
+ if (unlikely(mysql_trans_commit_alter_copy_data(thd)))
error= 1;
err:
@@ -10447,6 +10432,15 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
*copied= found_count;
*deleted=delete_count;
to->file->ha_release_auto_increment();
+
+ if (!cleanup_done)
+ {
+ /* This happens if we get an error during initialzation of data */
+ DBUG_ASSERT(error);
+ to->file->ha_end_bulk_insert();
+ ha_enable_transaction(thd, TRUE);
+ }
+
if (to->file->ha_external_lock(thd,F_UNLCK))
error=1;
if (error < 0 && !from->s->tmp_table &&
@@ -10623,8 +10617,6 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
int error= t->file->ha_rnd_next(t->record[0]);
if (unlikely(error))
{
- if (error == HA_ERR_RECORD_DELETED)
- continue;
break;
}
if (t->s->null_bytes)