summaryrefslogtreecommitdiff
path: root/sql/sql_admin.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_admin.cc')
-rw-r--r--sql/sql_admin.cc119
1 files changed, 74 insertions, 45 deletions
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 213d77f8237..060dcc059b5 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -26,13 +26,15 @@
#include "sql_view.h" // view_checksum
#include "sql_table.h" // mysql_recreate_table
#include "debug_sync.h" // DEBUG_SYNC
-#include "sql_acl.h" // *_ACL
#include "sp.h" // Sroutine_hash_entry
#include "sql_parse.h" // check_table_access
#include "strfunc.h"
#include "sql_admin.h"
#include "sql_statistics.h"
#include "wsrep_mysqld.h"
+
+const LEX_CSTRING msg_status= {STRING_WITH_LEN("status")};
+
/* Prepare, run and cleanup for mysql_recreate_table() */
static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
@@ -122,9 +124,9 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
Let us try to open at least a .FRM for this table.
*/
- table_list->mdl_request.init(MDL_key::TABLE,
- table_list->db.str, table_list->table_name.str,
- MDL_EXCLUSIVE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table_list->mdl_request, MDL_key::TABLE,
+ table_list->db.str, table_list->table_name.str,
+ MDL_EXCLUSIVE, MDL_TRANSACTION);
if (lock_table_names(thd, table_list, table_list->next_global,
thd->variables.lock_wait_timeout, 0))
@@ -213,15 +215,9 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
Table open failed, maybe because we run out of memory.
Close all open tables and relaese all MDL locks
*/
-#if MYSQL_VERSION < 100500
- tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
- table->s->db.str, table->s->table_name.str,
- TRUE);
-#else
tdc_release_share(share);
share->tdc->flush(thd, true);
share= 0;
-#endif
}
/*
@@ -437,6 +433,21 @@ dbug_err:
}
+
+static void send_read_only_warning(THD *thd, const LEX_CSTRING *msg_status,
+ const LEX_CSTRING *table_name)
+{
+ Protocol *protocol= thd->protocol;
+ char buf[MYSQL_ERRMSG_SIZE];
+ size_t length;
+ length= my_snprintf(buf, sizeof(buf),
+ ER_THD(thd, ER_OPEN_AS_READONLY),
+ table_name->str);
+ protocol->store(msg_status, system_charset_info);
+ protocol->store(buf, length, system_charset_info);
+}
+
+
/*
RETURN VALUES
FALSE Message sent to net (admin operation went ok)
@@ -510,7 +521,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
for (table= tables; table; table= table->next_local)
{
- char table_name[SAFE_NAME_LEN*2+2];
+ char table_name_buff[SAFE_NAME_LEN*2+2];
+ LEX_CSTRING table_name= { table_name_buff, 0};
const char *db= table->db.str;
bool fatal_error=0;
bool open_error;
@@ -520,7 +532,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
DBUG_PRINT("admin", ("table: '%s'.'%s'", db, table->table_name.str));
DEBUG_SYNC(thd, "admin_command_kill_before_modify");
- strxmov(table_name, db, ".", table->table_name.str, NullS);
+ table_name.length= strxmov(table_name_buff, db, ".", table->table_name.str,
+ NullS) - table_name_buff;
thd->open_options|= extra_open_options;
table->lock_type= lock_type;
/*
@@ -577,8 +590,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
close_thread_tables(thd);
table->table= NULL;
thd->release_transactional_locks();
- table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str,
- MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table->mdl_request, MDL_key::TABLE, table->db.str,
+ table->table_name.str, MDL_SHARED_NO_READ_WRITE,
+ MDL_TRANSACTION);
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
@@ -605,12 +619,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
size_t length;
DBUG_PRINT("admin", ("sending non existent partition error"));
protocol->prepare_for_resend();
- protocol->store(table_name, system_charset_info);
+ protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
length= my_snprintf(buff, sizeof(buff),
ER_THD(thd, ER_DROP_PARTITION_NON_EXISTENT),
- table_name);
+ table_name.str);
protocol->store(buff, length, system_charset_info);
if(protocol->write())
goto err;
@@ -686,20 +700,17 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
goto send_result;
}
- if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
+ if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify &&
+ operator_func != &handler::ha_analyze)
{
/* purecov: begin inspected */
- char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
- size_t length;
enum_sql_command save_sql_command= lex->sql_command;
+ LEX_CSTRING error_clex_str= { STRING_WITH_LEN("error") };
DBUG_PRINT("admin", ("sending error message"));
protocol->prepare_for_resend();
- protocol->store(table_name, system_charset_info);
+ protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
- protocol->store(STRING_WITH_LEN("error"), system_charset_info);
- length= my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_OPEN_AS_READONLY),
- table_name);
- protocol->store(buff, length, system_charset_info);
+ send_read_only_warning(thd, &error_clex_str, &table_name);
trans_commit_stmt(thd);
trans_commit(thd);
close_thread_tables(thd);
@@ -754,7 +765,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/* purecov: begin inspected */
DBUG_PRINT("admin", ("sending crashed warning"));
protocol->prepare_for_resend();
- protocol->store(table_name, system_charset_info);
+ protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
@@ -825,6 +836,15 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (compl_result_code == HA_ADMIN_OK && collect_eis)
{
+ if (result_code == HA_ERR_TABLE_READONLY)
+ {
+ protocol->prepare_for_resend();
+ protocol->store(&table_name, system_charset_info);
+ protocol->store(operator_name, system_charset_info);
+ send_read_only_warning(thd, &msg_status, &table_name);
+ (void) protocol->write();
+ result_code= HA_ADMIN_OK;
+ }
/*
Here we close and reopen table in read mode because operation of
collecting statistics is long and it will be better do not block
@@ -837,8 +857,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
close_thread_tables(thd);
table->table= NULL;
thd->release_transactional_locks();
- table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str,
- MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table->mdl_request, MDL_key::TABLE, table->db.str,
+ table->table_name.str, MDL_SHARED_NO_READ_WRITE,
+ MDL_TRANSACTION);
table->mdl_request.set_type(MDL_SHARED_READ);
table->lock_type= TL_READ;
@@ -931,9 +952,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
else
{
protocol->prepare_for_resend();
- protocol->store(table_name, system_charset_info);
+ protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
- protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+ protocol->store(&msg_status, system_charset_info);
protocol->store(STRING_WITH_LEN("Engine-independent statistics collected"),
system_charset_info);
if (protocol->write())
@@ -960,7 +981,7 @@ send_result:
while ((err= it++))
{
protocol->prepare_for_resend();
- protocol->store(table_name, system_charset_info);
+ protocol->store(&table_name, system_charset_info);
protocol->store((char*) operator_name, system_charset_info);
protocol->store(warning_level_names[err->get_level()].str,
warning_level_names[err->get_level()].length,
@@ -972,7 +993,7 @@ send_result:
thd->get_stmt_da()->clear_warning_info(thd->query_id);
}
protocol->prepare_for_resend();
- protocol->store(table_name, system_charset_info);
+ protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
send_result_message:
@@ -995,32 +1016,32 @@ send_result_message:
char buf[MYSQL_ERRMSG_SIZE];
size_t length= my_snprintf(buf, sizeof(buf),
ER_THD(thd, ER_BAD_TABLE_ERROR),
- table_name);
+ table_name.str);
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
protocol->store(buf, length, system_charset_info);
}
break;
case HA_ADMIN_OK:
- protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+ protocol->store(&msg_status, system_charset_info);
protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
break;
case HA_ADMIN_FAILED:
- protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+ protocol->store(&msg_status, system_charset_info);
protocol->store(STRING_WITH_LEN("Operation failed"),
system_charset_info);
break;
case HA_ADMIN_REJECT:
- protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+ protocol->store(&msg_status, system_charset_info);
protocol->store(STRING_WITH_LEN("Operation need committed state"),
system_charset_info);
open_for_modify= FALSE;
break;
case HA_ADMIN_ALREADY_DONE:
- protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+ protocol->store(&msg_status, system_charset_info);
protocol->store(STRING_WITH_LEN("Table is already up to date"),
system_charset_info);
break;
@@ -1062,9 +1083,7 @@ send_result_message:
*save_next_global= table->next_global;
table->next_local= table->next_global= 0;
- 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);
@@ -1102,7 +1121,7 @@ send_result_message:
}
/* Start a new row for the final status row */
protocol->prepare_for_resend();
- protocol->store(table_name, system_charset_info);
+ protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
if (result_code) // either mysql_recreate_table or analyze failed
{
@@ -1123,7 +1142,7 @@ send_result_message:
goto err;
/* Start off another row for HA_ADMIN_FAILED */
protocol->prepare_for_resend();
- protocol->store(table_name, system_charset_info);
+ protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
}
thd->clear_error();
@@ -1167,7 +1186,11 @@ send_result_message:
fatal_error=1;
break;
}
-
+ case HA_ERR_TABLE_READONLY:
+ {
+ send_read_only_warning(thd, &msg_status, &table_name);
+ break;
+ }
default: // Probably HA_ADMIN_INTERNAL_ERROR
{
char buf[MYSQL_ERRMSG_SIZE];
@@ -1186,9 +1209,16 @@ send_result_message:
they must be marked as DDL so that they are not scheduled in parallel
with conflicting DMLs resulting in deadlock.
*/
- thd->transaction.stmt.mark_executed_table_admin_cmd();
+ thd->transaction->stmt.mark_executed_table_admin_cmd();
if (table->table && !table->view)
{
+ /*
+ Don't skip flushing if we are collecting EITS statistics.
+ */
+ const bool skip_flush=
+ (operator_func == &handler::ha_analyze) &&
+ (table->table->file->ha_table_flags() & HA_ONLINE_ANALYZE) &&
+ !collect_eis;
if (table->table->s->tmp_table)
{
/*
@@ -1198,10 +1228,9 @@ send_result_message:
if (open_for_modify && !open_error)
table->table->file->info(HA_STATUS_CONST);
}
- else if (open_for_modify || fatal_error)
+ else if ((!skip_flush && open_for_modify) || fatal_error)
{
- tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
- table->db.str, table->table_name.str, FALSE);
+ table->table->s->tdc->flush_unused(true);
/*
May be something modified. Consequently, we have to
invalidate the query cache.