diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/client_priv.h | 2 | ||||
-rw-r--r-- | client/completion_hash.h | 3 | ||||
-rw-r--r-- | client/echo.c | 3 | ||||
-rw-r--r-- | client/get_password.c | 3 | ||||
-rw-r--r-- | client/mysql.cc | 22 | ||||
-rw-r--r-- | client/mysqlbinlog.cc | 167 | ||||
-rw-r--r-- | client/mysqlcheck.c | 90 | ||||
-rw-r--r-- | client/mysqldump.c | 6 | ||||
-rw-r--r-- | client/mysqltest.cc | 3 | ||||
-rw-r--r-- | client/sql_string.cc.dontuse | 4 |
10 files changed, 180 insertions, 123 deletions
diff --git a/client/client_priv.h b/client/client_priv.h index 607bd3997c1..70a9d129433 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. 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 diff --git a/client/completion_hash.h b/client/completion_hash.h index 8e1b2d6e453..50098e436b9 100644 --- a/client/completion_hash.h +++ b/client/completion_hash.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2000-2002 MySQL AB +/* Copyright (c) 2000-2002, 2006 MySQL AB + Use is subject to license terms This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff --git a/client/echo.c b/client/echo.c index e3d22edb3ae..cd61b23a826 100644 --- a/client/echo.c +++ b/client/echo.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 2007 MySQL AB + Use is subject to license terms 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 diff --git a/client/get_password.c b/client/get_password.c index 09d307b5553..a73771b00d4 100644 --- a/client/get_password.c +++ b/client/get_password.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 2001, 2003, 2006, 2008 MySQL AB + Use is subject to license terms 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 diff --git a/client/mysql.cc b/client/mysql.cc index ad792abc23f..3cd078ac1ce 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1635,7 +1635,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), { switch(optid) { case OPT_CHARSETS_DIR: - strmake(mysql_charsets_dir, argument, sizeof(mysql_charsets_dir) - 1); + strmake_buf(mysql_charsets_dir, argument); charsets_dir = mysql_charsets_dir; break; case OPT_DELIMITER: @@ -1648,7 +1648,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), /* Check that delimiter does not contain a backslash */ if (!strstr(argument, "\\")) { - strmake(delimiter, argument, sizeof(delimiter) - 1); + strmake_buf(delimiter, argument); } else { @@ -1680,7 +1680,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), if (argument && strlen(argument)) { default_pager_set= 1; - strmake(pager, argument, sizeof(pager) - 1); + strmake_buf(pager, argument); strmov(default_pager, pager); } else if (default_pager_set) @@ -2961,7 +2961,7 @@ com_charset(String *buffer __attribute__((unused)), char *line) { char buff[256], *param; CHARSET_INFO * new_cs; - strmake(buff, line, sizeof(buff) - 1); + strmake_buf(buff, line); param= get_arg(buff, 0); if (!param || !*param) { @@ -3198,7 +3198,7 @@ static void init_tee(const char *file_name) return; } OUTFILE = new_outfile; - strmake(outfile, file_name, FN_REFLEN-1); + strmake_buf(outfile, file_name); tee_fprintf(stdout, "Logging to file '%s'\n", file_name); opt_outfile= 1; return; @@ -3827,7 +3827,7 @@ com_tee(String *buffer __attribute__((unused)), /* eliminate the spaces before the parameters */ while (my_isspace(charset_info,*param)) param++; - end= strmake(file_name, param, sizeof(file_name) - 1); + end= strmake_buf(file_name, param); /* remove end space from command line */ while (end > file_name && (my_isspace(charset_info,end[-1]) || my_iscntrl(charset_info,end[-1]))) @@ -3888,7 +3888,7 @@ com_pager(String *buffer __attribute__((unused)), } else { - end= strmake(pager_name, param, sizeof(pager_name)-1); + end= strmake_buf(pager_name, param); while (end > pager_name && (my_isspace(charset_info,end[-1]) || my_iscntrl(charset_info,end[-1]))) end--; @@ -4101,7 +4101,7 @@ static int com_source(String *buffer __attribute__((unused)), INFO_ERROR, 0); while (my_isspace(charset_info,*param)) param++; - end=strmake(source_name,param,sizeof(source_name)-1); + end=strmake_buf(source_name, param); while (end > source_name && (my_isspace(charset_info,end[-1]) || my_iscntrl(charset_info,end[-1]))) end--; @@ -4154,7 +4154,7 @@ com_delimiter(String *buffer __attribute__((unused)), char *line) { char buff[256], *tmp; - strmake(buff, line, sizeof(buff) - 1); + strmake_buf(buff, line); tmp= get_arg(buff, 0); if (!tmp || !*tmp) @@ -4171,7 +4171,7 @@ com_delimiter(String *buffer __attribute__((unused)), char *line) return 0; } } - strmake(delimiter, tmp, sizeof(delimiter) - 1); + strmake_buf(delimiter, tmp); delimiter_length= (int)strlen(delimiter); delimiter_str= delimiter; return 0; @@ -4185,7 +4185,7 @@ com_use(String *buffer __attribute__((unused)), char *line) int select_db; bzero(buff, sizeof(buff)); - strmake(buff, line, sizeof(buff) - 1); + strmake_buf(buff, line); tmp= get_arg(buff, 0); if (!tmp || !*tmp) { diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 2dae59af9ea..387413cc5aa 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -818,6 +818,88 @@ write_event_header_and_base64(Log_event *ev, FILE *result_file, } +static bool print_base64(PRINT_EVENT_INFO *print_event_info, Log_event *ev) +{ + /* + These events must be printed in base64 format, if printed. + base64 format requires a FD event to be safe, so if no FD + event has been printed, we give an error. Except if user + passed --short-form, because --short-form disables printing + row events. + */ + if (!print_event_info->printed_fd_event && !short_form && + opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS) + { + const char* type_str= ev->get_type_str(); + if (opt_base64_output_mode == BASE64_OUTPUT_NEVER) + error("--base64-output=never specified, but binlog contains a " + "%s event which must be printed in base64.", + type_str); + else + error("malformed binlog: it does not contain any " + "Format_description_log_event. I now found a %s event, which " + "is not safe to process without a " + "Format_description_log_event.", + type_str); + return 1; + } + ev->print(result_file, print_event_info); + return print_event_info->head_cache.error == -1; +} + + +static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, + ulong table_id, bool is_stmt_end) +{ + Table_map_log_event *ignored_map= + print_event_info->m_table_map_ignored.get_table(table_id); + bool skip_event= (ignored_map != NULL); + + /* + end of statement check: + i) destroy/free ignored maps + ii) if skip event, flush cache now + */ + if (is_stmt_end) + { + /* + Now is safe to clear ignored map (clear_tables will also + delete original table map events stored in the map). + */ + if (print_event_info->m_table_map_ignored.count() > 0) + print_event_info->m_table_map_ignored.clear_tables(); + + /* + If there is a kept Annotate event and all corresponding + rbr-events were filtered away, the Annotate event was not + freed and it is just the time to do it. + */ + free_annotate_event(); + + /* + One needs to take into account an event that gets + filtered but was last event in the statement. If this is + the case, previous rows events that were written into + IO_CACHEs still need to be copied from cache to + result_file (as it would happen in ev->print(...) if + event was not skipped). + */ + if (skip_event) + { + if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, result_file) || + copy_event_cache_to_file_and_reinit(&print_event_info->body_cache, result_file))) + return 1; + } + } + + /* skip the event check */ + if (skip_event) + return 0; + + return print_base64(print_event_info, ev); +} + + /** Print the given event, and either delete it or delegate the deletion to someone else. @@ -1130,86 +1212,29 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, error("Could not rewrite database name"); goto err; } + if (print_base64(print_event_info, ev)) + goto err; + break; } case WRITE_ROWS_EVENT: case DELETE_ROWS_EVENT: case UPDATE_ROWS_EVENT: + { + Rows_log_event *e= (Rows_log_event*) ev; + if (print_row_event(print_event_info, ev, e->get_table_id(), + e->get_flags(Rows_log_event::STMT_END_F))) + goto err; + break; + } case PRE_GA_WRITE_ROWS_EVENT: case PRE_GA_DELETE_ROWS_EVENT: case PRE_GA_UPDATE_ROWS_EVENT: { - if (ev_type != TABLE_MAP_EVENT) - { - Rows_log_event *e= (Rows_log_event*) ev; - Table_map_log_event *ignored_map= - print_event_info->m_table_map_ignored.get_table(e->get_table_id()); - bool skip_event= (ignored_map != NULL); - - /* - end of statement check: - i) destroy/free ignored maps - ii) if skip event, flush cache now - */ - if (e->get_flags(Rows_log_event::STMT_END_F)) - { - /* - Now is safe to clear ignored map (clear_tables will also - delete original table map events stored in the map). - */ - if (print_event_info->m_table_map_ignored.count() > 0) - print_event_info->m_table_map_ignored.clear_tables(); - - /* - If there is a kept Annotate event and all corresponding - rbr-events were filtered away, the Annotate event was not - freed and it is just the time to do it. - */ - free_annotate_event(); - - /* - One needs to take into account an event that gets - filtered but was last event in the statement. If this is - the case, previous rows events that were written into - IO_CACHEs still need to be copied from cache to - result_file (as it would happen in ev->print(...) if - event was not skipped). - */ - if (skip_event) - { - if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, result_file) || - copy_event_cache_to_file_and_reinit(&print_event_info->body_cache, result_file))) - goto err; - } - } - - /* skip the event check */ - if (skip_event) - goto end; - } - /* - These events must be printed in base64 format, if printed. - base64 format requires a FD event to be safe, so if no FD - event has been printed, we give an error. Except if user - passed --short-form, because --short-form disables printing - row events. - */ - if (!print_event_info->printed_fd_event && !short_form && - opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS) - { - const char* type_str= ev->get_type_str(); - if (opt_base64_output_mode == BASE64_OUTPUT_NEVER) - error("--base64-output=never specified, but binlog contains a " - "%s event which must be printed in base64.", - type_str); - else - error("malformed binlog: it does not contain any " - "Format_description_log_event. I now found a %s event, which " - "is not safe to process without a " - "Format_description_log_event.", - type_str); + Old_rows_log_event *e= (Old_rows_log_event*) ev; + if (print_row_event(print_event_info, ev, e->get_table_id(), + e->get_flags(Old_rows_log_event::STMT_END_F))) goto err; - } - /* FALL THROUGH */ + break; } default: print_skip_replication_statement(print_event_info, ev); diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 4218f2da62c..7462c7561f6 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -18,7 +18,7 @@ /* By Jani Tolonen, 2001-04-20, MySQL Development Team */ -#define CHECK_VERSION "2.7.0" +#define CHECK_VERSION "2.7.1" #include "client_priv.h" #include <m_ctype.h> @@ -32,6 +32,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, @@ -47,7 +51,7 @@ 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, tables4rebuild; +DYNAMIC_ARRAY tables4repair, tables4rebuild, alter_table_cmds; static char *shared_memory_base_name=0; static uint opt_protocol=0; @@ -620,6 +624,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) { @@ -630,12 +645,7 @@ static int fix_table_storage_name(const char *name) if (strncmp(name, "#mysql50#", 9)) DBUG_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"); DBUG_RETURN(rc); @@ -650,12 +660,7 @@ static int fix_database_storage_name(const char *name) if (strncmp(name, "#mysql50#", 9)) DBUG_RETURN(1); sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name); - 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"); DBUG_RETURN(rc); @@ -726,15 +731,7 @@ static int use_db(char *database) static int disable_binlog() { const char *stmt= "SET SQL_LOG_BIN=0"; - DBUG_ENTER("disable_binlog"); - - if (mysql_query(sock, stmt)) - { - fprintf(stderr, "Failed to %s\n", stmt); - fprintf(stderr, "Error: %s\n", mysql_error(sock)); - DBUG_RETURN(1); - } - DBUG_RETURN(0); + return run_query(stmt); } static int handle_request_for_tables(char *tables, uint length) @@ -821,6 +818,7 @@ static void print_result() MYSQL_RES *res; MYSQL_ROW row; char prev[(NAME_LEN+9)*2+2]; + char prev_alter[MAX_ALTER_STR_SIZE]; uint i; my_bool found_error=0, table_rebuild=0; DBUG_ENTER("print_result"); @@ -828,6 +826,7 @@ static void print_result() 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]); @@ -844,12 +843,18 @@ static void print_result() strcmp(row[3],"OK")) { if (table_rebuild) - insert_dynamic(&tables4rebuild, (uchar*) prev); + { + 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; } @@ -866,11 +871,30 @@ static void print_result() printf("%-50s %s", row[0], "Needs upgrade"); else printf("%s\n%-9s: %s", row[0], row[2], row[3]); - if (strcmp(row[2],"note")) + if (opt_auto_repair && strcmp(row[2],"note")) { - found_error=1; - if (opt_auto_repair && strstr(row[3], "ALTER TABLE") != NULL) + 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 @@ -882,7 +906,12 @@ static void print_result() if (found_error && opt_auto_repair && what_to_do != DO_REPAIR) { if (table_rebuild) - insert_dynamic(&tables4rebuild, (uchar*) prev); + { + if (prev_alter[0]) + insert_dynamic(&alter_table_cmds, (uchar*) prev_alter); + else + insert_dynamic(&tables4rebuild, (uchar*) prev); + } else insert_dynamic(&tables4repair, (uchar*) prev); } @@ -995,7 +1024,8 @@ 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(&tables4rebuild, 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))) goto end; if (opt_alldbs) @@ -1020,6 +1050,8 @@ int main(int argc, char **argv) } 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)); } ret= test(first_error); diff --git a/client/mysqldump.c b/client/mysqldump.c index 11bb74ae1d7..63e0dc04096 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2000, 2013, Oracle and/or its affiliates. Copyright (c) 2010, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify @@ -1914,9 +1914,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name, const char *str_create) { uint i; -#ifndef DBUG_OFF - my_bool body_found= 0; -#endif + my_bool body_found __attribute__((unused)) = 0; char *create_stmt_ptr= NULL; ulong create_stmt_len= 0; MYSQL_FIELD *field; diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 8c6c1cb3408..2dde607a016 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6335,8 +6335,7 @@ void do_delimiter(struct st_command* command) if (!(*p)) die("Can't set empty delimiter"); - strmake(delimiter, p, sizeof(delimiter) - 1); - delimiter_length= strlen(delimiter); + delimiter_length= strmake_buf(delimiter, p) - delimiter; DBUG_PRINT("exit", ("delimiter: %s", delimiter)); command->last_argument= p + delimiter_length; diff --git a/client/sql_string.cc.dontuse b/client/sql_string.cc.dontuse index 64219886dd0..9679197b207 100644 --- a/client/sql_string.cc.dontuse +++ b/client/sql_string.cc.dontuse @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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 @@ -691,7 +691,7 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) { if (from->Alloced_length >= from_length) return from; - if (from->alloced || !to || from == to) + if ((from->alloced && (from->Alloced_length != 0)) || !to || from == to) { (void) from->realloc(from_length); return from; |