summaryrefslogtreecommitdiff
path: root/sql/sql_admin.cc
diff options
context:
space:
mode:
authorJan Lindström <jplindst@mariadb.org>2013-09-03 17:50:36 +0300
committerJan Lindström <jplindst@mariadb.org>2013-09-03 17:50:36 +0300
commitba3ff50ab2bfabab6a4307282f92854f6efe6382 (patch)
tree904c9b94cc5f1dfa8727f17af56f50fba4155205 /sql/sql_admin.cc
parent81739d308fee0317e56bd70d97e3429ece83dd4b (diff)
parentc8b87ca16f05826c6801c70fb20a88a61959264e (diff)
downloadmariadb-git-ba3ff50ab2bfabab6a4307282f92854f6efe6382.tar.gz
Merge 10.0 to galera-10.0
Diffstat (limited to 'sql/sql_admin.cc')
-rw-r--r--sql/sql_admin.cc164
1 files changed, 91 insertions, 73 deletions
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index d08cd7915ab..b517c3b2d4d 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2012, 2013, Monty Program Ab.
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
@@ -42,9 +43,19 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
trans_rollback(thd);
close_thread_tables(thd);
thd->mdl_context.release_transactional_locks();
+
+ /*
+ table_list->table has been closed and freed. Do not reference
+ uninitialized data. open_tables() could fail.
+ */
+ table_list->table= NULL;
+ /* Same applies to MDL ticket. */
+ table_list->mdl_request.ticket= NULL;
+
DEBUG_SYNC(thd, "ha_admin_try_alter");
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
- result_code= mysql_recreate_table(thd, table_list);
+ result_code= (open_temporary_tables(thd, table_list) ||
+ mysql_recreate_table(thd, table_list));
reenable_binlog(thd);
/*
mysql_recreate_table() can push OK or ERROR.
@@ -52,8 +63,8 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
we will store the error message in a result set row
and then clear.
*/
- if (thd->stmt_da->is_ok())
- thd->stmt_da->reset_diagnostics_area();
+ if (thd->get_stmt_da()->is_ok())
+ thd->get_stmt_da()->reset_diagnostics_area();
table_list->table= NULL;
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
DBUG_RETURN(result_code);
@@ -89,7 +100,6 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
const char **ext;
MY_STAT stat_info;
Open_table_context ot_ctx(thd, (MYSQL_OPEN_IGNORE_FLUSH |
- MYSQL_OPEN_FOR_REPAIR |
MYSQL_OPEN_HAS_MDL_LOCK |
MYSQL_LOCK_IGNORE_TIMEOUT));
DBUG_ENTER("prepare_for_repair");
@@ -117,21 +127,17 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
MDL_EXCLUSIVE, MDL_TRANSACTION);
if (lock_table_names(thd, table_list, table_list->next_global,
- thd->variables.lock_wait_timeout,
- MYSQL_OPEN_SKIP_TEMPORARY))
+ thd->variables.lock_wait_timeout, 0))
DBUG_RETURN(0);
has_mdl_lock= TRUE;
- share= get_table_share(thd, table_list->db, table_list->table_name,
- GTS_TABLE);
+ share= tdc_acquire_share_shortlived(thd, table_list, GTS_TABLE);
if (share == NULL)
DBUG_RETURN(0); // Can't open frm file
if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, FALSE))
{
- mysql_mutex_lock(&LOCK_open);
- release_table_share(share);
- mysql_mutex_unlock(&LOCK_open);
+ tdc_release_share(share);
DBUG_RETURN(0); // Out of memory
}
table= &tmp_table;
@@ -192,13 +198,11 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
to close it, but leave it protected by exclusive metadata lock.
*/
pos_in_locked_tables= table->pos_in_locked_tables;
- if (wait_while_table_is_used(thd, table,
- HA_EXTRA_PREPARE_FOR_FORCED_CLOSE,
- TDC_RT_REMOVE_NOT_OWN_AND_MARK_NOT_USABLE))
+ if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_FORCED_CLOSE))
goto end;
/* Close table but don't remove from locked list */
close_all_tables_for_name(thd, table_list->table->s,
- HA_EXTRA_NOT_USED);
+ HA_EXTRA_NOT_USED, NULL);
table_list->table= 0;
}
/*
@@ -256,11 +260,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
end:
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
if (table == &tmp_table)
- {
- mysql_mutex_lock(&LOCK_open);
closefrm(table, 1); // Free allocated memory
- mysql_mutex_unlock(&LOCK_open);
- }
/* In case of a temporary table there will be no metadata lock. */
if (error && has_mdl_lock)
thd->mdl_context.release_transactional_locks();
@@ -338,6 +338,14 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
mysql_ha_rm_tables(thd, tables);
+ /*
+ Close all temporary tables which were pre-open to simplify
+ privilege checking. Clear all references to closed tables.
+ */
+ close_thread_tables(thd);
+ for (table= tables; table; table= table->next_local)
+ table->table= NULL;
+
for (table= tables; table; table= table->next_local)
{
char table_name[SAFE_NAME_LEN*2+2];
@@ -394,14 +402,15 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
because it's already known that the table is badly damaged.
*/
- Warning_info wi(thd->query_id, false);
- Warning_info *wi_saved= thd->warning_info;
+ Diagnostics_area *da= thd->get_stmt_da();
+ Warning_info tmp_wi(thd->query_id, false, true);
- thd->warning_info= &wi;
+ da->push_warning_info(&tmp_wi);
- open_error= open_and_lock_tables(thd, table, TRUE, 0);
+ open_error= (open_temporary_tables(thd, table) ||
+ open_and_lock_tables(thd, table, TRUE, 0));
- thd->warning_info= wi_saved;
+ da->pop_warning_info();
}
else
{
@@ -413,7 +422,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
mode. It does make sense for the user to see such errors.
*/
- open_error= open_and_lock_tables(thd, table, TRUE, 0);
+ open_error= (open_temporary_tables(thd, table) ||
+ open_and_lock_tables(thd, table, TRUE, 0));
}
thd->prepare_derived_at_open= FALSE;
@@ -448,7 +458,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
*/
Alter_info *alter_info= &lex->alter_info;
- if (alter_info->flags & ALTER_ADMIN_PARTITION)
+ if (alter_info->flags & Alter_info::ALTER_ADMIN_PARTITION)
{
if (!table->table->part_info)
{
@@ -512,16 +522,16 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (!table->table)
{
DBUG_PRINT("admin", ("open table failed"));
- if (thd->warning_info->is_empty())
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ if (thd->get_stmt_da()->is_warning_info_empty())
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
/* if it was a view will check md5 sum */
if (table->view &&
view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
- if (thd->stmt_da->is_error() &&
- table_not_corrupt_error(thd->stmt_da->sql_errno()))
+ if (thd->get_stmt_da()->is_error() &&
+ table_not_corrupt_error(thd->get_stmt_da()->sql_errno()))
result_code= HA_ADMIN_FAILED;
else
/* Default failure code is corrupt table */
@@ -569,7 +579,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
table->table=0; // For query cache
if (protocol->write())
goto err;
- thd->stmt_da->reset_diagnostics_area();
+ thd->get_stmt_da()->reset_diagnostics_area();
continue;
/* purecov: end */
}
@@ -589,10 +599,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
*/
if (lock_type == TL_WRITE && !table->table->s->tmp_table)
{
- table->table->s->protect_against_usage();
if (wait_while_table_is_used(thd, table->table,
- HA_EXTRA_PREPARE_FOR_RENAME,
- TDC_RT_REMOVE_NOT_OWN_AND_MARK_NOT_USABLE))
+ HA_EXTRA_PREPARE_FOR_RENAME))
goto err;
DEBUG_SYNC(thd, "after_admin_flush");
/* Flush entries in the query cache involving this table. */
@@ -742,8 +750,9 @@ send_result:
lex->cleanup_after_one_table_open();
thd->clear_error(); // these errors shouldn't get client
{
- List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
- MYSQL_ERROR *err;
+ Diagnostics_area::Sql_condition_iterator it=
+ thd->get_stmt_da()->sql_conditions();
+ const Sql_condition *err;
while ((err= it++))
{
protocol->prepare_for_resend();
@@ -756,7 +765,7 @@ send_result:
if (protocol->write())
goto err;
}
- thd->warning_info->clear_warning_info(thd->query_id);
+ thd->get_stmt_da()->clear_warning_info(thd->query_id);
}
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
@@ -824,19 +833,10 @@ send_result_message:
case HA_ADMIN_TRY_ALTER:
{
- uint save_flags;
Alter_info *alter_info= &lex->alter_info;
- /* Store the original value of alter_info->flags */
- save_flags= alter_info->flags;
- /*
- This is currently used only by InnoDB. ha_innobase::optimize() answers
- "try with alter", so here we close the table, do an ALTER TABLE,
- reopen the table and do ha_innobase::analyze() on it.
- We have to end the row, so analyze could return more rows.
- */
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
- if(alter_info->flags & ALTER_ADMIN_PARTITION)
+ if (alter_info->flags & Alter_info::ALTER_ADMIN_PARTITION)
{
protocol->store(STRING_WITH_LEN(
"Table does not support optimize on partitions. All partitions "
@@ -848,18 +848,23 @@ send_result_message:
"Table does not support optimize, doing recreate + analyze instead"),
system_charset_info);
}
- if (protocol->write())
+ if (protocol->write())
goto err;
+
DBUG_PRINT("info", ("HA_ADMIN_TRY_ALTER, trying analyze..."));
TABLE_LIST *save_next_local= table->next_local,
*save_next_global= table->next_global;
table->next_local= table->next_global= 0;
- result_code= admin_recreate_table(thd, table);
+ tmp_disable_binlog(thd); // binlogging is done by caller if wanted
+ result_code= admin_recreate_table(thd, table);
+ reenable_binlog(thd);
trans_commit_stmt(thd);
trans_commit(thd);
close_thread_tables(thd);
thd->mdl_context.release_transactional_locks();
+ /* Clear references to TABLE and MDL_ticket after releasing them. */
+ table->mdl_request.ticket= NULL;
if (!result_code) // recreation went ok
{
@@ -867,22 +872,27 @@ send_result_message:
table->mdl_request.ticket= NULL;
DEBUG_SYNC(thd, "ha_admin_open_ltable");
table->mdl_request.set_type(MDL_SHARED_WRITE);
- /*
- Reset the ALTER_ADMIN_PARTITION bit in alter_info->flags
- to force analyze on all partitions.
- */
- alter_info->flags &= ~(ALTER_ADMIN_PARTITION);
- if ((table->table= open_ltable(thd, table, lock_type, 0)))
+ if (!open_temporary_tables(thd, table) &&
+ (table->table= open_ltable(thd, table, lock_type, 0)))
{
+ uint save_flags;
+ /* Store the original value of alter_info->flags */
+ save_flags= alter_info->flags;
+
+ /*
+ Reset the ALTER_ADMIN_PARTITION bit in alter_info->flags
+ to force analyze on all partitions.
+ */
+ alter_info->flags &= ~(Alter_info::ALTER_ADMIN_PARTITION);
result_code= table->table->file->ha_analyze(thd, check_opt);
if (result_code == HA_ADMIN_ALREADY_DONE)
result_code= HA_ADMIN_OK;
else if (result_code) // analyze failed
table->table->file->print_error(result_code, MYF(0));
+ alter_info->flags= save_flags;
}
else
result_code= -1; // open failed
- alter_info->flags= save_flags;
}
/* Start a new row for the final status row */
protocol->prepare_for_resend();
@@ -893,7 +903,7 @@ send_result_message:
DBUG_ASSERT(thd->is_error() || thd->killed);
if (thd->is_error())
{
- const char *err_msg= thd->stmt_da->message();
+ const char *err_msg= thd->get_stmt_da()->message();
if (!thd->vio_ok())
{
sql_print_error("%s", err_msg);
@@ -912,6 +922,9 @@ send_result_message:
}
thd->clear_error();
}
+ /* Make sure this table instance is not reused after the operation. */
+ if (table->table)
+ table->table->m_needs_reopen= true;
}
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
table->next_local= save_next_local;
@@ -1010,14 +1023,15 @@ send_result_message:
err:
/* Make sure this table instance is not reused after the failure. */
- if (table && table->table)
- table->table->m_needs_reopen= true;
trans_rollback_stmt(thd);
trans_rollback(thd);
+ if (table && table->table)
+ {
+ table->table->m_needs_reopen= true;
+ table->table= 0;
+ }
close_thread_tables(thd); // Shouldn't be needed
thd->mdl_context.release_transactional_locks();
- if (table)
- table->table=0;
DBUG_RETURN(TRUE);
}
@@ -1090,12 +1104,13 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
}
-bool Analyze_table_statement::execute(THD *thd)
+bool Sql_cmd_analyze_table::execute(THD *thd)
{
+ LEX *m_lex= thd->lex;
TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
bool res= TRUE;
thr_lock_type lock_type = TL_READ_NO_INSERT;
- DBUG_ENTER("Analyze_table_statement::execute");
+ DBUG_ENTER("Sql_cmd_analyze_table::execute");
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))
@@ -1120,12 +1135,13 @@ error:
}
-bool Check_table_statement::execute(THD *thd)
+bool Sql_cmd_check_table::execute(THD *thd)
{
+ LEX *m_lex= thd->lex;
TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
thr_lock_type lock_type = TL_READ_NO_INSERT;
bool res= TRUE;
- DBUG_ENTER("Check_table_statement::execute");
+ DBUG_ENTER("Sql_cmd_check_table::execute");
if (check_table_access(thd, SELECT_ACL, first_table,
TRUE, UINT_MAX, FALSE))
@@ -1144,19 +1160,20 @@ error:
}
-bool Optimize_table_statement::execute(THD *thd)
+bool Sql_cmd_optimize_table::execute(THD *thd)
{
+ LEX *m_lex= thd->lex;
TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
bool res= TRUE;
- DBUG_ENTER("Optimize_table_statement::execute");
+ DBUG_ENTER("Sql_cmd_optimize_table::execute");
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
-
WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL)
- res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
+ res= (specialflag & SPECIAL_NO_NEW_FUNC) ?
+
mysql_recreate_table(thd, first_table) :
mysql_admin_table(thd, first_table, &m_lex->check_opt,
"optimize", TL_WRITE, 1, 0, 0, 0,
@@ -1177,11 +1194,12 @@ error:
}
-bool Repair_table_statement::execute(THD *thd)
+bool Sql_cmd_repair_table::execute(THD *thd)
{
+ LEX *m_lex= thd->lex;
TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
bool res= TRUE;
- DBUG_ENTER("Repair_table_statement::execute");
+ DBUG_ENTER("Sql_cmd_repair_table::execute");
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))