diff options
Diffstat (limited to 'client/mysqlcheck.c')
-rw-r--r-- | client/mysqlcheck.c | 210 |
1 files changed, 151 insertions, 59 deletions
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index ec9ee50868b..e84cbdefbbc 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -15,7 +15,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define CHECK_VERSION "2.5.0" +#define CHECK_VERSION "2.5.1" #include "client_priv.h" #include <m_ctype.h> @@ -29,6 +29,10 @@ #define EX_USAGE 1 #define EX_MYSQLERR 2 +/* ALTER instead of repair. */ +#define MAX_ALTER_STR_SIZE 128 * 1024 +#define KEY_PARTITIONING_CHANGED_STR "KEY () partitioning changed" + static MYSQL mysql_connection, *sock = 0; static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0, opt_compress = 0, opt_databases = 0, opt_fast = 0, @@ -42,14 +46,15 @@ static int my_end_arg; static char * opt_mysql_unix_port = 0; static char *opt_password = 0, *current_user = 0, *default_charset= 0, *current_host= 0; +static char *opt_plugin_dir= 0, *opt_default_auth= 0; static int first_error = 0; -DYNAMIC_ARRAY tables4repair; +DYNAMIC_ARRAY tables4repair, tables4rebuild, alter_table_cmds; #ifdef HAVE_SMEM static char *shared_memory_base_name=0; #endif static uint opt_protocol=0; -enum operations { DO_CHECK, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE }; +enum operations { DO_CHECK=1, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE }; static struct my_option my_long_options[] = { @@ -63,10 +68,6 @@ static struct my_option my_long_options[] = "Instead of issuing one query for each table, use one query per database, naming all tables in the database in a comma-separated list.", &opt_all_in_1, &opt_all_in_1, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef __NETWARE__ - {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, -#endif {"auto-repair", OPT_AUTO_REPAIR, "If a checked table is corrupted, automatically fix it. Repairing will be done after all tables have been checked, if corrupted ones were found.", &opt_auto_repair, &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0, @@ -105,6 +106,10 @@ static struct my_option my_long_options[] = {"default-character-set", OPT_DEFAULT_CHARSET, "Set the default character set.", &default_charset, &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"default_auth", OPT_DEFAULT_AUTH, + "Default authentication client-side plugin to use.", + &opt_default_auth, &opt_default_auth, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"fast",'F', "Check only tables that haven't been closed properly.", &opt_fast, &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -129,7 +134,8 @@ static struct my_option my_long_options[] = "Faster than extended-check, but only finds 99.99 percent of all errors. Should be good enough for most cases.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"write-binlog", OPT_WRITE_BINLOG, - "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Enabled by default; use --skip-write-binlog when commands should not be sent to replication slaves.", + "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Use --skip-write-binlog " + "when commands should not be sent to replication slaves.", &opt_write_binlog, &opt_write_binlog, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"optimize", 'o', "Optimize table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, @@ -141,14 +147,16 @@ static struct my_option my_long_options[] = {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif + {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.", + &opt_plugin_dir, &opt_plugin_dir, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection or 0 for default to, in " "order of preference, my.cnf, $MYSQL_TCP_PORT, " #if MYSQL_PORT_DEFAULT == 0 "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - &opt_mysql_port, - &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, + &opt_mysql_port, &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -209,13 +217,11 @@ static uint fixed_name_length(const char *name); static char *fix_table_name(char *dest, char *src); int what_to_do = 0; -#include <help_start.h> static void print_version(void) { printf("%s Ver %s Distrib %s, for %s (%s)\n", my_progname, CHECK_VERSION, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); - NETWARE_SET_SCREEN_MODE(1); } /* print_version */ @@ -244,18 +250,14 @@ static void usage(void) my_print_variables(my_long_options); } /* usage */ -#include <help_end.h> static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { + int orig_what_to_do= what_to_do; + switch(optid) { -#ifdef __NETWARE__ - case OPT_AUTO_CLOSE: - setscreenmode(SCR_AUTOCLOSE_ON_EXIT); - break; -#endif case 'a': what_to_do = DO_ANALYZE; break; @@ -290,7 +292,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), if (argument) { char *start = argument; - my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); + my_free(opt_password); opt_password = my_strdup(argument, MYF(MY_FAE)); while (*argument) *argument++= 'x'; /* Destroy argument */ if (*start) @@ -329,6 +331,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt->name); break; } + + if (orig_what_to_do && (what_to_do != orig_what_to_do)) + { + fprintf(stderr, "Error: %s doesn't support multiple contradicting commands.\n", + my_progname); + return 1; + } return 0; } @@ -343,9 +352,8 @@ static int get_options(int *argc, char ***argv) exit(0); } - load_defaults("my", load_default_groups, argc, argv); - - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) + if ((ho_error= load_defaults("my", load_default_groups, argc, argv)) || + (ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); if (!what_to_do) @@ -368,12 +376,15 @@ static int get_options(int *argc, char ***argv) If there's no --default-character-set option given with --fix-table-name or --fix-db-name set the default character set to "utf8". */ - if (!default_charset && (opt_fix_db_names || opt_fix_table_names)) + if (!default_charset) { - default_charset= (char*) "utf8"; + if (opt_fix_db_names || opt_fix_table_names) + default_charset= (char*) "utf8"; + else + default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME; } - if (default_charset && !get_charset_by_csname(default_charset, MY_CS_PRIMARY, - MYF(MY_WME))) + if (strcmp(default_charset, MYSQL_AUTODETECT_CHARSET_NAME) && + !get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME))) { printf("Unsupported character set: %s\n", default_charset); return 1; @@ -467,7 +478,7 @@ static int process_selected_tables(char *db, char **table_names, int tables) } *--end = 0; handle_request_for_tables(table_names_comma_sep + 1, (uint) (tot_length - 1)); - my_free(table_names_comma_sep, MYF(0)); + my_free(table_names_comma_sep); } else for (; tables > 0; tables--, table_names++) @@ -566,7 +577,7 @@ static int process_all_tables_in_db(char *database) *--end = 0; if (tot_length) handle_request_for_tables(tables + 1, tot_length - 1); - my_free(tables, MYF(0)); + my_free(tables); } else { @@ -584,6 +595,17 @@ static int process_all_tables_in_db(char *database) } /* process_all_tables_in_db */ +static int run_query(const char *query) +{ + if (mysql_query(sock, query)) + { + fprintf(stderr, "Failed to %s\n", query); + fprintf(stderr, "Error: %s\n", mysql_error(sock)); + return 1; + } + return 0; +} + static int fix_table_storage_name(const char *name) { @@ -592,12 +614,7 @@ static int fix_table_storage_name(const char *name) if (strncmp(name, "#mysql50#", 9)) return 1; sprintf(qbuf, "RENAME TABLE `%s` TO `%s`", name, name + 9); - if (mysql_query(sock, qbuf)) - { - fprintf(stderr, "Failed to %s\n", qbuf); - fprintf(stderr, "Error: %s\n", mysql_error(sock)); - rc= 1; - } + rc= run_query(qbuf); if (verbose) printf("%-50s %s\n", name, rc ? "FAILED" : "OK"); return rc; @@ -610,14 +627,30 @@ static int fix_database_storage_name(const char *name) if (strncmp(name, "#mysql50#", 9)) return 1; sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name); - if (mysql_query(sock, qbuf)) + rc= run_query(qbuf); + if (verbose) + printf("%-50s %s\n", name, rc ? "FAILED" : "OK"); + return rc; +} + +static int rebuild_table(char *name) +{ + char *query, *ptr; + int rc= 0; + query= (char*)my_malloc(sizeof(char) * (12 + fixed_name_length(name) + 6 + 1), + MYF(MY_WME)); + if (!query) + return 1; + ptr= strmov(query, "ALTER TABLE "); + ptr= fix_table_name(ptr, name); + ptr= strxmov(ptr, " FORCE", NullS); + if (mysql_real_query(sock, query, (uint)(ptr - query))) { - fprintf(stderr, "Failed to %s\n", qbuf); + fprintf(stderr, "Failed to %s\n", query); fprintf(stderr, "Error: %s\n", mysql_error(sock)); rc= 1; } - if (verbose) - printf("%-50s %s\n", name, rc ? "FAILED" : "OK"); + my_free(query); return rc; } @@ -640,8 +673,11 @@ static int process_one_db(char *database) static int use_db(char *database) { - if (mysql_get_server_version(sock) >= 50003 && - !my_strcasecmp(&my_charset_latin1, database, "information_schema")) + if (mysql_get_server_version(sock) >= FIRST_INFORMATION_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, database, INFORMATION_SCHEMA_DB_NAME)) + return 1; + if (mysql_get_server_version(sock) >= FIRST_PERFORMANCE_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, database, PERFORMANCE_SCHEMA_DB_NAME)) return 1; if (mysql_select_db(sock, database)) { @@ -654,13 +690,7 @@ static int use_db(char *database) static int disable_binlog() { const char *stmt= "SET SQL_LOG_BIN=0"; - if (mysql_query(sock, stmt)) - { - fprintf(stderr, "Failed to %s\n", stmt); - fprintf(stderr, "Error: %s\n", mysql_error(sock)); - return 1; - } - return 0; + return run_query(stmt); } static int handle_request_for_tables(char *tables, uint length) @@ -720,7 +750,7 @@ static int handle_request_for_tables(char *tables, uint length) return 1; } print_result(); - my_free(query, MYF(0)); + my_free(query); return 0; } @@ -730,12 +760,14 @@ static void print_result() MYSQL_RES *res; MYSQL_ROW row; char prev[NAME_LEN*2+2]; + char prev_alter[MAX_ALTER_STR_SIZE]; uint i; - my_bool found_error=0; + my_bool found_error=0, table_rebuild=0; res = mysql_use_result(sock); prev[0] = '\0'; + prev_alter[0]= 0; for (i = 0; (row = mysql_fetch_row(res)); i++) { int changed = strcmp(prev, row[0]); @@ -750,8 +782,20 @@ static void print_result() */ if (found_error && opt_auto_repair && what_to_do != DO_REPAIR && strcmp(row[3],"OK")) - insert_dynamic(&tables4repair, (uchar*) prev); + { + if (table_rebuild) + { + if (prev_alter[0]) + insert_dynamic(&alter_table_cmds, (uchar*) prev_alter); + else + insert_dynamic(&tables4rebuild, (uchar*) prev); + } + else + insert_dynamic(&tables4repair, (uchar*) prev); + } found_error=0; + table_rebuild=0; + prev_alter[0]= 0; if (opt_silent) continue; } @@ -760,8 +804,31 @@ static void print_result() else if (!status && changed) { printf("%s\n%-9s: %s", row[0], row[2], row[3]); - if (strcmp(row[2],"note")) - found_error=1; + if (opt_auto_repair && strcmp(row[2],"note")) + { + const char *alter_txt= strstr(row[3], "ALTER TABLE"); + found_error=1; + if (alter_txt) + { + table_rebuild=1; + if (!strncmp(row[3], KEY_PARTITIONING_CHANGED_STR, + strlen(KEY_PARTITIONING_CHANGED_STR)) && + strstr(alter_txt, "PARTITION BY")) + { + if (strlen(alter_txt) >= MAX_ALTER_STR_SIZE) + { + printf("Error: Alter command too long (>= %d)," + " please do \"%s\" or dump/reload to fix it!\n", + MAX_ALTER_STR_SIZE, + alter_txt); + table_rebuild= 0; + prev_alter[0]= 0; + } + else + strcpy(prev_alter, alter_txt); + } + } + } } else printf("%-9s: %s", row[2], row[3]); @@ -770,7 +837,17 @@ static void print_result() } /* add the last table to be repaired to the list */ if (found_error && opt_auto_repair && what_to_do != DO_REPAIR) - insert_dynamic(&tables4repair, (uchar*) prev); + { + if (table_rebuild) + { + if (prev_alter[0]) + insert_dynamic(&alter_table_cmds, (uchar*) prev_alter); + else + insert_dynamic(&tables4rebuild, (uchar*) prev); + } + else + insert_dynamic(&tables4repair, (uchar*) prev); + } mysql_free_result(res); } @@ -796,8 +873,14 @@ static int dbConnect(char *host, char *user, char *passwd) if (shared_memory_base_name) mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); #endif - if (default_charset) - mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); + + if (opt_plugin_dir && *opt_plugin_dir) + mysql_options(&mysql_connection, MYSQL_PLUGIN_DIR, opt_plugin_dir); + + if (opt_default_auth && *opt_default_auth) + mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth); + + mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd, NULL, opt_mysql_port, opt_mysql_unix_port, 0))) { @@ -862,7 +945,9 @@ int main(int argc, char **argv) } if (opt_auto_repair && - my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64)) + (my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64) || + my_init_dynamic_array(&tables4rebuild, sizeof(char)*(NAME_LEN*2+2),16,64) || + my_init_dynamic_array(&alter_table_cmds, MAX_ALTER_STR_SIZE, 0, 1))) { first_error = 1; goto end; @@ -880,7 +965,7 @@ int main(int argc, char **argv) { uint i; - if (!opt_silent && tables4repair.elements) + if (!opt_silent && (tables4repair.elements || tables4rebuild.elements)) puts("\nRepairing tables"); what_to_do = DO_REPAIR; for (i = 0; i < tables4repair.elements ; i++) @@ -888,14 +973,21 @@ int main(int argc, char **argv) char *name= (char*) dynamic_array_ptr(&tables4repair, i); handle_request_for_tables(name, fixed_name_length(name)); } + for (i = 0; i < tables4rebuild.elements ; i++) + rebuild_table((char*) dynamic_array_ptr(&tables4rebuild, i)); + for (i = 0; i < alter_table_cmds.elements ; i++) + run_query((char*) dynamic_array_ptr(&alter_table_cmds, i)); } end: dbDisconnect(current_host); if (opt_auto_repair) + { delete_dynamic(&tables4repair); - my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); + delete_dynamic(&tables4rebuild); + } + my_free(opt_password); #ifdef HAVE_SMEM - my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); + my_free(shared_memory_base_name); #endif my_end(my_end_arg); return(first_error!=0); |