16 #include "sql_class.h"
17 #include "keycaches.h"
20 #include "partition_element.h"
21 #include "sql_partition.h"
22 #include "transaction.h"
24 #include "sql_table.h"
28 #include "sql_parse.h"
29 #include "sql_admin.h"
32 const char* operator_name,
const char* errmsg)
36 protocol->prepare_for_resend();
37 protocol->
store(table->alias, system_charset_info);
38 protocol->
store((
char*) operator_name, system_charset_info);
39 protocol->
store(STRING_WITH_LEN(
"error"), system_charset_info);
40 protocol->
store(errmsg, system_charset_info);
42 if (protocol->write())
48 static int prepare_for_repair(THD *thd,
TABLE_LIST *table_list,
54 bool has_mdl_lock= FALSE;
55 char from[FN_REFLEN],tmp[FN_REFLEN+32];
59 MYSQL_OPEN_HAS_MDL_LOCK |
60 MYSQL_LOCK_IGNORE_TIMEOUT));
61 DBUG_ENTER(
"prepare_for_repair");
63 if (!(check_opt->sql_flags & TT_USEFRM))
66 if (!(table= table_list->table))
77 thd->mdl_context.release_transactional_locks();
82 my_hash_value_type hash_value;
84 table_list->mdl_request.
init(MDL_key::TABLE,
85 table_list->db, table_list->table_name,
86 MDL_EXCLUSIVE, MDL_TRANSACTION);
89 thd->variables.lock_wait_timeout, 0))
95 hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length);
97 share= get_table_share(thd, table_list, key, key_length, 0,
103 if (open_table_from_share(thd, share,
"", 0, 0, 0, &tmp_table, FALSE))
116 if (table->s->tmp_table)
118 error= send_check_errmsg(thd, table_list,
"repair",
119 "Cannot repair temporary table from .frm file");
133 if (table->s->frm_version != FRM_VER_TRUE_VARCHAR)
135 error= send_check_errmsg(thd, table_list,
"repair",
136 "Failed repairing incompatible .frm file");
147 if (!ext[0] || !ext[1])
151 DBUG_ASSERT(table->file->ht->db_type != DB_TYPE_MRG_MYISAM);
154 strxmov(from, table->s->normalized_path.str, ext[1], NullS);
158 my_snprintf(tmp,
sizeof(tmp),
"%s-%lx_%lx",
159 from, current_pid, thd->thread_id);
161 if (table_list->table)
170 table_list->table= 0;
178 if (my_rename(from, tmp, MYF(MY_WME)))
180 error= send_check_errmsg(thd, table_list,
"repair",
181 "Failed renaming data file");
184 if (dd_recreate_table(thd, table_list->db, table_list->table_name))
186 error= send_check_errmsg(thd, table_list,
"repair",
187 "Failed generating table from .frm file");
195 query_cache_invalidate3(thd, table_list, FALSE);
198 error= send_check_errmsg(thd, table_list,
"repair",
199 "Failed restoring .MYD file");
203 if (thd->locked_tables_list.reopen_tables(thd))
212 error= send_check_errmsg(thd, table_list,
"repair",
213 "Failed to open partially repaired table");
218 thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
219 if (table == &tmp_table)
226 if (error && has_mdl_lock)
227 thd->mdl_context.release_transactional_locks();
243 static inline bool table_not_corrupt_error(uint sql_errno)
245 return (sql_errno == ER_NO_SUCH_TABLE ||
246 sql_errno == ER_FILE_NOT_FOUND ||
247 sql_errno == ER_LOCK_WAIT_TIMEOUT ||
248 sql_errno == ER_LOCK_DEADLOCK ||
249 sql_errno == ER_CANT_LOCK_LOG_TABLE ||
250 sql_errno == ER_OPEN_AS_READONLY);
260 static bool mysql_admin_table(THD* thd,
TABLE_LIST* tables,
262 const char *operator_name,
263 thr_lock_type lock_type,
264 bool open_for_modify,
265 bool repair_table_use_frm,
266 uint extra_open_options,
269 int (
handler::*operator_func)(THD *,
274 SELECT_LEX *select= &thd->lex->select_lex;
280 DBUG_ENTER(
"mysql_admin_table");
283 item->maybe_null = 1;
285 item->maybe_null = 1;
287 item->maybe_null = 1;
289 SQL_ADMIN_MSG_TEXT_SIZE));
290 item->maybe_null = 1;
292 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
299 close_thread_tables(thd);
300 for (table= tables;
table; table= table->next_local)
303 for (table= tables;
table; table= table->next_local)
306 char* db = table->db;
310 DBUG_PRINT(
"admin", (
"table: '%s'.'%s'", table->db, table->table_name));
311 DBUG_PRINT(
"admin", (
"extra_open_options: %u", extra_open_options));
312 strxmov(table_name, db,
".", table->table_name, NullS);
313 thd->open_options|= extra_open_options;
314 table->lock_type= lock_type;
321 table->mdl_request.
set_type((lock_type >= TL_WRITE_ALLOW_WRITE) ?
322 MDL_SHARED_NO_READ_WRITE : MDL_SHARED_READ);
325 TABLE_LIST *save_next_global, *save_next_local;
326 save_next_global= table->next_global;
327 table->next_global= 0;
328 save_next_local= table->next_local;
329 table->next_local= 0;
330 select->table_list.first=
table;
337 lex->query_tables=
table;
338 lex->query_tables_last= &table->next_global;
339 lex->query_tables_own_last= 0;
341 if (view_operator_func == NULL)
342 table->required_type=FRMTYPE_TABLE;
344 if (!thd->locked_tables_mode && repair_table_use_frm)
358 da->push_warning_info(&tmp_wi);
365 da->pop_warning_info();
383 table->next_global= save_next_global;
384 table->next_local= save_next_local;
385 thd->open_options&= ~extra_open_options;
399 if (open_error && thd->locked_tables_mode)
401 result_code= HA_ADMIN_FAILED;
404 #ifdef WITH_PARTITION_STORAGE_ENGINE
414 if (alter_info->flags & Alter_info::ALTER_ADMIN_PARTITION)
416 if (!table->table->part_info)
418 my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
422 if (set_part_state(alter_info, table->table->part_info, PART_ADMIN))
424 char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
426 DBUG_PRINT(
"admin", (
"sending non existent partition error"));
427 protocol->prepare_for_resend();
428 protocol->
store(table_name, system_charset_info);
429 protocol->
store(operator_name, system_charset_info);
430 protocol->
store(STRING_WITH_LEN(
"error"), system_charset_info);
431 length= my_snprintf(buff,
sizeof(buff),
432 ER(ER_DROP_PARTITION_NON_EXISTENT),
434 protocol->
store(buff, length, system_charset_info);
435 if(protocol->write())
444 DBUG_PRINT(
"admin", (
"table: 0x%lx", (
long) table->table));
448 DBUG_PRINT(
"admin", (
"calling prepare_func"));
449 switch ((*prepare_func)(thd, table, check_opt)) {
451 trans_rollback_stmt(thd);
455 table->table->m_needs_reopen=
true;
456 close_thread_tables(thd);
457 thd->mdl_context.release_transactional_locks();
458 DBUG_PRINT(
"admin", (
"simple error, admin next table"));
462 DBUG_PRINT(
"admin", (
"severe error, stop"));
466 DBUG_PRINT(
"admin", (
"prepare_func succeeded"));
481 DBUG_PRINT(
"admin", (
"open table failed"));
482 if (thd->get_stmt_da()->is_warning_info_empty())
483 push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
484 ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
487 view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
488 push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
489 ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
490 if (thd->get_stmt_da()->is_error() &&
491 table_not_corrupt_error(thd->get_stmt_da()->sql_errno()))
492 result_code= HA_ADMIN_FAILED;
495 result_code= HA_ADMIN_CORRUPT;
501 DBUG_PRINT(
"admin", (
"calling view_operator_func"));
502 result_code= (*view_operator_func)(thd,
table);
506 if (table->schema_table)
508 result_code= HA_ADMIN_NOT_IMPLEMENTED;
512 if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
515 char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
517 enum_sql_command save_sql_command= lex->sql_command;
518 DBUG_PRINT(
"admin", (
"sending error message"));
519 protocol->prepare_for_resend();
520 protocol->
store(table_name, system_charset_info);
521 protocol->
store(operator_name, system_charset_info);
522 protocol->
store(STRING_WITH_LEN(
"error"), system_charset_info);
523 length= my_snprintf(buff,
sizeof(buff), ER(ER_OPEN_AS_READONLY),
525 protocol->
store(buff, length, system_charset_info);
526 trans_commit_stmt(thd);
530 table->table->m_needs_reopen=
true;
531 close_thread_tables(thd);
532 thd->mdl_context.release_transactional_locks();
533 lex->reset_query_tables_list(FALSE);
538 lex->sql_command= save_sql_command;
540 if (protocol->write())
542 thd->get_stmt_da()->reset_diagnostics_area();
560 if (lock_type == TL_WRITE && !table->table->s->tmp_table)
563 HA_EXTRA_PREPARE_FOR_RENAME))
565 DEBUG_SYNC(thd,
"after_admin_flush");
567 query_cache_invalidate3(thd, table->table, 0);
578 DBUG_PRINT(
"admin", (
"sending crashed warning"));
579 protocol->prepare_for_resend();
580 protocol->
store(table_name, system_charset_info);
581 protocol->
store(operator_name, system_charset_info);
582 protocol->
store(STRING_WITH_LEN(
"warning"), system_charset_info);
583 protocol->
store(STRING_WITH_LEN(
"Table is marked as crashed"),
584 system_charset_info);
585 if (protocol->write())
591 !(check_opt->sql_flags & TT_USEFRM))
593 if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
594 (table->table->file->ha_check_for_upgrade(check_opt) ==
595 HA_ADMIN_NEEDS_ALTER))
597 DBUG_PRINT(
"admin", (
"recreating table"));
603 DBUG_ASSERT(! table->table->s->tmp_table);
605 trans_rollback_stmt(thd);
609 table->table->m_needs_reopen=
true;
610 close_thread_tables(thd);
611 thd->mdl_context.release_transactional_locks();
619 table->mdl_request.
ticket= NULL;
621 tmp_disable_binlog(thd);
622 result_code= mysql_recreate_table(thd, table);
623 reenable_binlog(thd);
630 if (thd->get_stmt_da()->is_ok())
631 thd->get_stmt_da()->reset_diagnostics_area();
633 result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
638 DBUG_PRINT(
"admin", (
"calling operator_func '%s'", operator_name));
639 result_code = (table->table->file->*operator_func)(thd, check_opt);
640 DBUG_PRINT(
"admin", (
"operator_func returned: %d", result_code));
644 lex->cleanup_after_one_table_open();
648 thd->get_stmt_da()->sql_conditions();
652 protocol->prepare_for_resend();
653 protocol->
store(table_name, system_charset_info);
654 protocol->
store((
char*) operator_name, system_charset_info);
656 warning_level_names[err->
get_level()].length,
657 system_charset_info);
659 if (protocol->write())
662 thd->get_stmt_da()->clear_warning_info(thd->query_id);
664 protocol->prepare_for_resend();
665 protocol->
store(table_name, system_charset_info);
666 protocol->
store(operator_name, system_charset_info);
670 DBUG_PRINT(
"info", (
"result_code: %d", result_code));
671 switch (result_code) {
672 case HA_ADMIN_NOT_IMPLEMENTED:
674 char buf[MYSQL_ERRMSG_SIZE];
675 size_t length=my_snprintf(buf,
sizeof(buf),
676 ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
677 protocol->
store(STRING_WITH_LEN(
"note"), system_charset_info);
678 protocol->
store(buf, length, system_charset_info);
682 case HA_ADMIN_NOT_BASE_TABLE:
684 char buf[MYSQL_ERRMSG_SIZE];
687 tbl_name.append(
String(db,system_charset_info));
688 tbl_name.append(
'.');
689 tbl_name.append(
String(table_name,system_charset_info));
691 size_t length= my_snprintf(buf,
sizeof(buf),
692 ER(ER_BAD_TABLE_ERROR), tbl_name.c_ptr());
693 protocol->
store(STRING_WITH_LEN(
"note"), system_charset_info);
694 protocol->
store(buf, length, system_charset_info);
699 protocol->
store(STRING_WITH_LEN(
"status"), system_charset_info);
700 protocol->
store(STRING_WITH_LEN(
"OK"), system_charset_info);
703 case HA_ADMIN_FAILED:
704 protocol->
store(STRING_WITH_LEN(
"status"), system_charset_info);
705 protocol->
store(STRING_WITH_LEN(
"Operation failed"),
706 system_charset_info);
709 case HA_ADMIN_REJECT:
710 protocol->
store(STRING_WITH_LEN(
"status"), system_charset_info);
711 protocol->
store(STRING_WITH_LEN(
"Operation need committed state"),
712 system_charset_info);
713 open_for_modify= FALSE;
716 case HA_ADMIN_ALREADY_DONE:
717 protocol->
store(STRING_WITH_LEN(
"status"), system_charset_info);
718 protocol->
store(STRING_WITH_LEN(
"Table is already up to date"),
719 system_charset_info);
722 case HA_ADMIN_CORRUPT:
723 protocol->
store(STRING_WITH_LEN(
"error"), system_charset_info);
724 protocol->
store(STRING_WITH_LEN(
"Corrupt"), system_charset_info);
728 case HA_ADMIN_INVALID:
729 protocol->
store(STRING_WITH_LEN(
"error"), system_charset_info);
730 protocol->
store(STRING_WITH_LEN(
"Invalid argument"),
731 system_charset_info);
734 case HA_ADMIN_TRY_ALTER:
740 save_flags= alter_info->flags;
747 trans_commit_stmt(thd);
749 close_thread_tables(thd);
750 thd->mdl_context.release_transactional_locks();
758 table->mdl_request.
ticket= NULL;
760 DEBUG_SYNC(thd,
"ha_admin_try_alter");
761 protocol->
store(STRING_WITH_LEN(
"note"), system_charset_info);
762 if(alter_info->flags & Alter_info::ALTER_ADMIN_PARTITION)
764 protocol->
store(STRING_WITH_LEN(
765 "Table does not support optimize on partitions. All partitions "
766 "will be rebuilt and analyzed."),system_charset_info);
770 protocol->
store(STRING_WITH_LEN(
771 "Table does not support optimize, doing recreate + analyze instead"),
772 system_charset_info);
774 if (protocol->write())
776 DBUG_PRINT(
"info", (
"HA_ADMIN_TRY_ALTER, trying analyze..."));
777 TABLE_LIST *save_next_local= table->next_local,
778 *save_next_global= table->next_global;
779 table->next_local= table->next_global= 0;
780 tmp_disable_binlog(thd);
783 mysql_recreate_table(thd, table));
784 reenable_binlog(thd);
791 if (thd->get_stmt_da()->is_ok())
792 thd->get_stmt_da()->reset_diagnostics_area();
793 trans_commit_stmt(thd);
795 close_thread_tables(thd);
796 thd->mdl_context.release_transactional_locks();
799 table->mdl_request.
ticket= NULL;
802 DEBUG_SYNC(thd,
"ha_admin_open_ltable");
803 table->mdl_request.
set_type(MDL_SHARED_WRITE);
811 alter_info->flags &= ~(Alter_info::ALTER_ADMIN_PARTITION);
812 result_code= table->table->file->
ha_analyze(thd, check_opt);
813 if (result_code == HA_ADMIN_ALREADY_DONE)
814 result_code= HA_ADMIN_OK;
815 else if (result_code)
816 table->table->file->
print_error(result_code, MYF(0));
817 alter_info->flags= save_flags;
823 protocol->prepare_for_resend();
824 protocol->
store(table_name, system_charset_info);
825 protocol->
store(operator_name, system_charset_info);
828 DBUG_ASSERT(thd->is_error() || thd->killed);
831 const char *err_msg= thd->get_stmt_da()->message();
834 sql_print_error(
"%s", err_msg);
839 protocol->
store(STRING_WITH_LEN(
"error"), system_charset_info);
840 protocol->
store(err_msg, system_charset_info);
841 if (protocol->write())
844 protocol->prepare_for_resend();
845 protocol->
store(table_name, system_charset_info);
846 protocol->
store(operator_name, system_charset_info);
852 table->table->m_needs_reopen=
true;
854 result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
855 table->next_local= save_next_local;
856 table->next_global= save_next_global;
857 goto send_result_message;
859 case HA_ADMIN_WRONG_CHECKSUM:
861 protocol->
store(STRING_WITH_LEN(
"note"), system_charset_info);
862 protocol->
store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
863 system_charset_info);
867 case HA_ADMIN_NEEDS_UPGRADE:
868 case HA_ADMIN_NEEDS_ALTER:
870 char buf[MYSQL_ERRMSG_SIZE];
873 protocol->
store(STRING_WITH_LEN(
"error"), system_charset_info);
875 length= my_snprintf(buf,
sizeof(buf), ER(ER_TABLE_NEEDS_UPGRADE),
878 length= my_snprintf(buf,
sizeof(buf), ER(ER_TABLE_NEEDS_REBUILD),
880 protocol->
store(buf, length, system_charset_info);
887 char buf[MYSQL_ERRMSG_SIZE];
888 size_t length=my_snprintf(buf,
sizeof(buf),
889 "Unknown - internal error %d during operation",
891 protocol->
store(STRING_WITH_LEN(
"error"), system_charset_info);
892 protocol->
store(buf, length, system_charset_info);
899 if (table->table->s->tmp_table)
905 if (open_for_modify && !open_error)
906 table->table->file->info(HA_STATUS_CONST);
908 else if (open_for_modify || fatal_error)
911 table->db, table->table_name, FALSE);
917 query_cache_invalidate3(thd, table, 0);
921 if (thd->transaction_rollback_request)
927 if (trans_rollback_stmt(thd) || trans_rollback_implicit(thd))
932 if (trans_commit_stmt(thd) || trans_commit_implicit(thd))
935 close_thread_tables(thd);
936 thd->mdl_context.release_transactional_locks();
952 rt->mdl_request.ticket= NULL;
954 if (protocol->write())
962 trans_rollback_stmt(thd);
966 table->table->m_needs_reopen=
true;
967 close_thread_tables(thd);
968 thd->mdl_context.release_transactional_locks();
986 bool mysql_assign_to_keycache(THD* thd,
TABLE_LIST* tables,
991 DBUG_ENTER(
"mysql_assign_to_keycache");
995 if (!(key_cache= get_key_cache(key_cache_name)))
998 my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
1002 if (!key_cache->key_cache_inited)
1004 my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
1007 check_opt.key_cache= key_cache;
1008 DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
1009 "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
1010 0, 0, &handler::assign_to_keycache, 0));
1027 bool mysql_preload_keys(THD* thd,
TABLE_LIST* tables)
1029 DBUG_ENTER(
"mysql_preload_keys");
1035 DBUG_RETURN(mysql_admin_table(thd, tables, 0,
1036 "preload_keys", TL_READ_NO_INSERT, 0, 0, 0, 0,
1037 &handler::preload_keys, 0));
1043 TABLE_LIST *first_table= thd->lex->select_lex.table_list.first;
1045 thr_lock_type lock_type = TL_READ_NO_INSERT;
1046 DBUG_ENTER(
"Sql_cmd_analyze_table::execute");
1049 FALSE, UINT_MAX, FALSE))
1051 thd->enable_slow_log= opt_log_slow_admin_statements;
1052 res= mysql_admin_table(thd, first_table, &thd->lex->check_opt,
1053 "analyze", lock_type, 1, 0, 0, 0,
1056 if (!res && !thd->lex->no_write_to_binlog)
1061 res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
1063 thd->lex->select_lex.table_list.first= first_table;
1064 thd->lex->query_tables= first_table;
1073 TABLE_LIST *first_table= thd->lex->select_lex.table_list.first;
1074 thr_lock_type lock_type = TL_READ_NO_INSERT;
1076 DBUG_ENTER(
"Sql_cmd_check_table::execute");
1079 TRUE, UINT_MAX, FALSE))
1081 thd->enable_slow_log= opt_log_slow_admin_statements;
1083 res= mysql_admin_table(thd, first_table, &thd->lex->check_opt,
"check",
1084 lock_type, 0, 0, HA_OPEN_FOR_REPAIR, 0,
1087 thd->lex->select_lex.table_list.first= first_table;
1088 thd->lex->query_tables= first_table;
1097 TABLE_LIST *first_table= thd->lex->select_lex.table_list.first;
1099 DBUG_ENTER(
"Sql_cmd_optimize_table::execute");
1102 FALSE, UINT_MAX, FALSE))
1104 thd->enable_slow_log= opt_log_slow_admin_statements;
1105 res= (specialflag & SPECIAL_NO_NEW_FUNC) ?
1106 mysql_recreate_table(thd, first_table) :
1107 mysql_admin_table(thd, first_table, &thd->lex->check_opt,
1108 "optimize", TL_WRITE, 1, 0, 0, 0,
1111 if (!res && !thd->lex->no_write_to_binlog)
1116 res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
1118 thd->lex->select_lex.table_list.first= first_table;
1119 thd->lex->query_tables= first_table;
1128 TABLE_LIST *first_table= thd->lex->select_lex.table_list.first;
1130 DBUG_ENTER(
"Sql_cmd_repair_table::execute");
1133 FALSE, UINT_MAX, FALSE))
1135 thd->enable_slow_log= opt_log_slow_admin_statements;
1136 res= mysql_admin_table(thd, first_table, &thd->lex->check_opt,
"repair",
1138 test(thd->lex->check_opt.sql_flags & TT_USEFRM),
1139 HA_OPEN_FOR_REPAIR, &prepare_for_repair,
1143 if (!res && !thd->lex->no_write_to_binlog)
1148 res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
1150 thd->lex->select_lex.table_list.first= first_table;
1151 thd->lex->query_tables= first_table;