diff options
Diffstat (limited to 'client')
-rwxr-xr-x | client/CMakeLists.txt | 1 | ||||
-rw-r--r-- | client/Makefile.am | 5 | ||||
-rw-r--r-- | client/client_priv.h | 2 | ||||
-rw-r--r-- | client/mysql.cc | 61 | ||||
-rw-r--r-- | client/mysqlbinlog.cc | 187 | ||||
-rw-r--r-- | client/mysqldump.c | 118 | ||||
-rw-r--r-- | client/mysqlslap.c | 18 | ||||
-rw-r--r-- | client/mysqltest.cc | 78 | ||||
-rw-r--r-- | client/readline.cc | 2 | ||||
-rw-r--r-- | client/sql_string.cc | 6 | ||||
-rw-r--r-- | client/sql_string.h | 2 |
11 files changed, 395 insertions, 85 deletions
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 5780da71bef..2d51bc3fd0f 100755 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -59,6 +59,7 @@ MYSQL_ADD_EXECUTABLE(mysqlbinlog mysqlbinlog.cc ../mysys/my_bitmap.c ../mysys/my_vle.c ../mysys/base64.c + ../mysys/checksum.c DESTINATION bin) TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient wsock32) diff --git a/client/Makefile.am b/client/Makefile.am index 72540de0fe8..f8a0a3f7139 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -24,6 +24,7 @@ endif INCLUDES = -I$(top_builddir)/include \ -I$(top_srcdir)/include \ -I$(top_srcdir)/regex \ + @ZLIB_INCLUDES@ \ $(openssl_includes) LIBS = @CLIENT_LIBS@ @@ -63,7 +64,8 @@ mysqlbinlog_SOURCES = mysqlbinlog.cc \ $(top_srcdir)/mysys/my_bit.c \ $(top_srcdir)/mysys/my_bitmap.c \ $(top_srcdir)/mysys/my_vle.c \ - $(top_srcdir)/mysys/base64.c + $(top_srcdir)/mysys/base64.c \ + $(top_srcdir)/mysys/checksum.c mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS) mysqldump_SOURCES= mysqldump.c \ @@ -105,6 +107,7 @@ sql_src=log_event.h mysql_priv.h rpl_constants.h \ log_event.cc my_decimal.h my_decimal.cc \ log_event_old.h log_event_old.cc \ rpl_record_old.h rpl_record_old.cc \ + rpl_utility.h rpl_utility.cc \ sql_list.h rpl_filter.h sql_list.cc rpl_filter.cc strings_src=decimal.c strings_def.h diff --git a/client/client_priv.h b/client/client_priv.h index 9ad627f0832..d948fb7f98f 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -99,5 +99,7 @@ enum options_client OPT_REWRITE_DB, OPT_PLUGIN_DIR, OPT_DEFAULT_PLUGIN, + OPT_REPORT_PROGRESS, + OPT_SKIP_ANNOTATE_ROWS_EVENTS, OPT_MAX_CLIENT_OPTION /* should be always the last */ }; diff --git a/client/mysql.cc b/client/mysql.cc index 0ce28fa90c6..ecef2214848 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -49,7 +49,7 @@ and you are welcome to modify and redistribute it under the GPL v2 license\n" #include <locale.h> #endif -const char *VER= "14.16"; +const char *VER= "15.1"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -152,7 +152,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0, default_charset_used= 0, opt_secure_auth= 0, default_pager_set= 0, opt_sigint_ignore= 0, show_warnings= 0, executing_query= 0, - ignore_spaces= 0; + ignore_spaces= 0, opt_progress_reports; static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error; static my_bool column_types_flag; static my_bool preserve_comments= 0; @@ -248,6 +248,13 @@ static const char* construct_prompt(); static char *get_arg(char *line, my_bool get_next_arg); static void init_username(); static void add_int_to_prompt(int toadd); +#ifndef EMBEDDED_LIBRARY +static uint last_progress_report_length= 0; +static void report_progress(const MYSQL *mysql, uint stage, uint max_stage, + double progress, const char *proc_info, + uint proc_info_length); +#endif +static void report_progress_end(); /* A structure which contains information on the commands this program can understand. */ @@ -1498,6 +1505,10 @@ static struct my_option my_long_options[] = "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", &opt_mysql_port, &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"progress-reports", OPT_REPORT_PROGRESS, + "Get progress reports for long running commands (like ALTER TABLE)", + &opt_progress_reports, &opt_progress_reports, 0, GET_BOOL, NO_ARG, 1, 0, + 0, 0, 0, 0}, {"prompt", OPT_PROMPT, "Set the mysql prompt to this value.", ¤t_prompt, ¤t_prompt, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -1854,6 +1865,7 @@ static int get_options(int argc, char **argv) opt_outfile= 0; opt_reconnect= 0; connect_flag= 0; /* Not in interactive mode */ + opt_progress_reports= 0; } if (strcmp(default_charset, charset_info->csname) && @@ -1881,6 +1893,9 @@ static int get_options(int argc, char **argv) if (ignore_spaces) connect_flag|= CLIENT_IGNORE_SPACE; + if (opt_progress_reports) + connect_flag|= CLIENT_PROGRESS; + return(0); } @@ -2287,7 +2302,7 @@ static bool add_line(String &buffer,char *line,char *in_string, break; } else if (!*in_string && inchar == '/' && *(pos+1) == '*' && - *(pos+2) != '!') + !(*(pos+2) == '!' || (*(pos+2) == 'M' && *(pos+3) == '!'))) { if (preserve_comments) { @@ -2765,6 +2780,8 @@ static int reconnect(void) } if (!connected) return put_info("Can't connect to the server\n",INFO_ERROR); + my_free(server_version,MYF(MY_ALLOW_ZERO_PTR)); + server_version= 0; /* purecov: end */ return 0; } @@ -3058,6 +3075,7 @@ com_go(String *buffer,char *line __attribute__((unused))) timer=start_timer(); executing_query= 1; error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length()); + report_progress_end(); #ifdef HAVE_READLINE if (status.add_to_history) @@ -4414,9 +4432,17 @@ sql_real_connect(char *host,char *database,char *user,char *password, } return -1; // Retryable } + connected=1; #ifndef EMBEDDED_LIBRARY mysql.reconnect= debug_info_flag; // We want to know if this happens + + /* + CLIENT_PROGRESS is set only if we requsted it in mysql_real_connect() + and the server also supports it + */ + if (mysql.client_flag & CLIENT_PROGRESS) + mysql_options(&mysql, MYSQL_PROGRESS_CALLBACK, (void*) report_progress); #else mysql.reconnect= 1; #endif @@ -5064,4 +5090,31 @@ void sql_element_free(void *ptr) { my_free(ptr,MYF(0)); } -#endif /* EMBEDDED_LIBRARY */ + +static void report_progress(const MYSQL *mysql, uint stage, uint max_stage, + double progress, const char *proc_info, + uint proc_info_length) +{ + uint length= printf("Stage: %d of %d '%.*s' %6.3g%% of stage done", + stage, max_stage, proc_info_length, proc_info, + progress); + if (length < last_progress_report_length) + printf("%*s", last_progress_report_length - length, ""); + putc('\r', stdout); + fflush(stdout); + last_progress_report_length= length; +} + +static void report_progress_end() +{ + if (last_progress_report_length) + { + printf("%*s\r", last_progress_report_length, ""); + last_progress_report_length= 0; + } +} +#else +static void report_progress_end() +{ +} +#endif diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index c1473b18486..f562f30313c 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -86,6 +86,7 @@ static const char* database= 0; static my_bool force_opt= 0, short_form= 0, remote_opt= 0; static my_bool debug_info_flag, debug_check_flag; static my_bool force_if_open_opt= 1; +static my_bool opt_verify_binlog_checksum= 1; static ulonglong offset = 0; static const char* host = 0; static int port= 0; @@ -110,6 +111,7 @@ static ulonglong rec_count= 0; static short binlog_flags = 0; static MYSQL* mysql = NULL; static const char* dirname_for_local_load= 0; +static bool opt_skip_annotate_row_events= 0; /** Pointer to the Format_description_log_event of the currently active binlog. @@ -131,6 +133,71 @@ enum Exit_status { OK_STOP }; +/** + Pointer to the last read Annotate_rows_log_event. Having read an + Annotate_rows event, we should not print it immediatedly because all + subsequent rbr events can be filtered away, and have to keep it for a while. + Also because of that when reading a remote Annotate event we have to keep + its binary log representation in a separately allocated buffer. +*/ +static Annotate_rows_log_event *annotate_event= NULL; + +void free_annotate_event() +{ + if (annotate_event) + { + delete annotate_event; + annotate_event= 0; + } +} + +Log_event* read_remote_annotate_event(uchar* net_buf, ulong event_len, + const char **error_msg) +{ + uchar *event_buf; + Log_event* event; + + if (!(event_buf= (uchar*) my_malloc(event_len + 1, MYF(MY_WME)))) + { + error("Out of memory"); + return 0; + } + + memcpy(event_buf, net_buf, event_len); + event_buf[event_len]= 0; + + if (!(event= Log_event::read_log_event((const char*) event_buf, event_len, + error_msg, glob_description_event, + opt_verify_binlog_checksum))) + { + my_free(event_buf, MYF(0)); + return 0; + } + /* + Ensure the event->temp_buf is pointing to the allocated buffer. + (TRUE = free temp_buf on the event deletion) + */ + event->register_temp_buf((char*)event_buf, TRUE); + + return event; +} + +void keep_annotate_event(Annotate_rows_log_event* event) +{ + free_annotate_event(); + annotate_event= event; +} + +void print_annotate_event(PRINT_EVENT_INFO *print_event_info) +{ + if (annotate_event) + { + annotate_event->print(result_file, print_event_info); + delete annotate_event; // the event should not be printed more than once + annotate_event= 0; + } +} + static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, const char* logname); static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, @@ -746,7 +813,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, read them to be able to process the wanted events. */ if (((rec_count >= offset) && - ((my_time_t)(ev->when) >= start_datetime)) || + (ev->when >= start_datetime)) || (ev_type == FORMAT_DESCRIPTION_EVENT)) { if (ev_type != FORMAT_DESCRIPTION_EVENT) @@ -770,7 +837,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, server_id && (server_id != ev->server_id)) goto end; } - if (((my_time_t)(ev->when) >= stop_datetime) + if ((ev->when >= stop_datetime) || (pos >= stop_position_mot)) { /* end the program */ @@ -793,8 +860,19 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, case QUERY_EVENT: { Query_log_event *qe= (Query_log_event*)ev; - if (!qe->is_trans_keyword() && shall_skip_database(qe->db)) - goto end; + if (!qe->is_trans_keyword()) + { + if (shall_skip_database(qe->db)) + goto end; + } + else + { + /* + In case the event for one of these statements is obtained + from binary log 5.0, make it compatible with 5.1 + */ + qe->flags|= LOG_EVENT_SUPPRESS_USE_F; + } print_use_stmt(print_event_info, qe); if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS) { @@ -943,6 +1021,19 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, my_free(fname, MYF(MY_WME)); break; } + case ANNOTATE_ROWS_EVENT: + if (!opt_skip_annotate_row_events) + { + /* + We don't print Annotate event just now because all subsequent + rbr-events can be filtered away. Instead we'll keep the event + till it will be printed together with the first not filtered + away Table map or the last rbr will be processed. + */ + keep_annotate_event((Annotate_rows_log_event*) ev); + destroy_evt= FALSE; + } + break; case TABLE_MAP_EVENT: { Table_map_log_event *map= ((Table_map_log_event *)ev); @@ -952,6 +1043,13 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, destroy_evt= FALSE; goto end; } + /* + The Table map is to be printed, so it's just the time when we may + print the kept Annotate event (if there is any). + print_annotate_event() also deletes the kept Annotate event. + */ + print_annotate_event(print_event_info); + size_t len_to= 0; const char* db_to= binlog_filter->get_rewrite_db(map->get_db_name(), &len_to); if (len_to && map->rewrite_db(db_to, len_to, glob_description_event)) @@ -988,6 +1086,13 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, 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 @@ -1219,10 +1324,18 @@ that may lead to an endless loop.", "Used to reserve file descriptors for use by this program.", &open_files_limit, &open_files_limit, 0, GET_ULONG, REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0}, + {"verify-binlog-checksum", 'c', "Verify checksum binlog events.", + (uchar**) &opt_verify_binlog_checksum, (uchar**) &opt_verify_binlog_checksum, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"rewrite-db", OPT_REWRITE_DB, "Updates to a database with a different name than the original. \ Example: rewrite-db='from->to'.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"skip-annotate-row-events", OPT_SKIP_ANNOTATE_ROWS_EVENTS, + "Don't print Annotate_rows events stored in the binary log.", + (uchar**) &opt_skip_annotate_row_events, + (uchar**) &opt_skip_annotate_row_events, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -1335,7 +1448,7 @@ static my_time_t convert_str_to_timestamp(const char* str) int was_cut; MYSQL_TIME l_time; long dummy_my_timezone; - my_bool dummy_in_dst_time_gap; + uint dummy_in_dst_time_gap; /* We require a total specification (date AND time) */ if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &was_cut) != MYSQL_TIMESTAMP_DATETIME || was_cut) @@ -1612,7 +1725,18 @@ static Exit_status check_master_version() "Master reported NULL for the version."); goto err; } - + /* + Make a notice to the server that this client + is checksum-aware. It does not need the first fake Rotate + necessary checksummed. + That preference is specified below. + */ + if (mysql_query(mysql, "SET @master_binlog_checksum='NONE'")) + { + error("Could not notify master about checksum awareness." + "Master returned '%s'", mysql_error(mysql)); + goto err; + } delete glob_description_event; switch (*version) { case '3': @@ -1694,6 +1818,8 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, cast to uint32. */ int4store(buf, (uint32)start_position); + if (!opt_skip_annotate_row_events) + binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT; int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags); size_t tlen = strlen(logname); @@ -1726,18 +1852,31 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, break; // end of data DBUG_PRINT("info",( "len: %lu net->read_pos[5]: %d\n", len, net->read_pos[5])); - if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 , - len - 1, &error_msg, - glob_description_event))) + if (net->read_pos[5] == ANNOTATE_ROWS_EVENT) { - error("Could not construct log event object: %s", error_msg); - DBUG_RETURN(ERROR_STOP); - } - /* - If reading from a remote host, ensure the temp_buf for the - Log_event class is pointing to the incoming stream. - */ - ev->register_temp_buf((char *) net->read_pos + 1, FALSE); + if (!(ev= read_remote_annotate_event(net->read_pos + 1, len - 1, + &error_msg))) + { + error("Could not construct annotate event object: %s", error_msg); + DBUG_RETURN(ERROR_STOP); + } + } + else + { + if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 , + len - 1, &error_msg, + glob_description_event, + opt_verify_binlog_checksum))) + { + error("Could not construct log event object: %s", error_msg); + DBUG_RETURN(ERROR_STOP); + } + /* + If reading from a remote host, ensure the temp_buf for the + Log_event class is pointing to the incoming stream. + */ + ev->register_temp_buf((char *) net->read_pos + 1, FALSE); + } Log_event_type type= ev->get_type_code(); if (glob_description_event->binlog_version >= 3 || @@ -1955,7 +2094,8 @@ static Exit_status check_header(IO_CACHE* file, Format_description_log_event *new_description_event; my_b_seek(file, tmp_pos); /* seek back to event's start */ if (!(new_description_event= (Format_description_log_event*) - Log_event::read_log_event(file, glob_description_event))) + Log_event::read_log_event(file, glob_description_event, + opt_verify_binlog_checksum))) /* EOF can't be hit here normally, so it's a real error */ { error("Could not read a Format_description_log_event event at " @@ -1988,7 +2128,8 @@ static Exit_status check_header(IO_CACHE* file, { Log_event *ev; my_b_seek(file, tmp_pos); /* seek back to event's start */ - if (!(ev= Log_event::read_log_event(file, glob_description_event))) + if (!(ev= Log_event::read_log_event(file, glob_description_event, + opt_verify_binlog_checksum))) { /* EOF can't be hit here normally, so it's a real error */ error("Could not read a Rotate_log_event event at offset %llu;" @@ -2060,7 +2201,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, return ERROR_STOP; } #endif - if (init_io_cache(file, fileno(stdin), 0, READ_CACHE, (my_off_t) 0, + if (init_io_cache(file, my_fileno(stdin), 0, READ_CACHE, (my_off_t) 0, 0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE))) { error("Failed to init IO cache."); @@ -2101,7 +2242,8 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, char llbuff[21]; my_off_t old_off = my_b_tell(file); - Log_event* ev = Log_event::read_log_event(file, glob_description_event); + Log_event* ev = Log_event::read_log_event(file, glob_description_event, + opt_verify_binlog_checksum); if (!ev) { /* @@ -2247,6 +2389,7 @@ int main(int argc, char** argv) if (result_file != stdout) my_fclose(result_file, MYF(0)); cleanup(); + free_annotate_event(); delete binlog_filter; free_root(&s_mem_root, MYF(0)); free_defaults(defaults_argv); @@ -2279,4 +2422,4 @@ void *sql_alloc(size_t size) #include "sql_string.cc" #include "sql_list.cc" #include "rpl_filter.cc" - +#include "rpl_utility.cc" diff --git a/client/mysqldump.c b/client/mysqldump.c index f416c297215..27582260cb9 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -82,6 +82,9 @@ #define IGNORE_DATA 0x01 /* don't dump data for this table */ #define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */ +/* Chars needed to store LONGLONG, excluding trailing '\0'. */ +#define LONGLONG_LEN 20 + static void add_load_option(DYNAMIC_STRING *str, const char *option, const char *option_value); static ulong find_set(TYPELIB *lib, const char *x, uint length, @@ -349,9 +352,9 @@ static struct my_option my_long_options[] = "This causes the binary log position and filename to be appended to the " "output. If equal to 1, will print it as a CHANGE MASTER command; if equal" " to 2, that command will be prefixed with a comment symbol. " - "This option will turn --lock-all-tables on, unless " - "--single-transaction is specified too (in which case a " - "global read lock is only taken a short time at the beginning of the dump; " + "This option will turn --lock-all-tables on, unless --single-transaction " + "is specified too (on servers before MariaDB 5.3 this will still take a " + "global read lock for a short time at the beginning of the dump; " "don't forget to read about --single-transaction below). In all cases, " "any action on logs will happen at the exact moment of the dump. " "Option automatically turns --lock-tables off.", @@ -1128,6 +1131,44 @@ static int fetch_db_collation(const char *db_name, } +/* + Check if server supports non-blocking binlog position using the + binlog_snapshot_file and binlog_snapshot_position status variables. If it + does, also return the position obtained if output pointers are non-NULL. + Returns 1 if position available, 0 if not. +*/ +static int +check_consistent_binlog_pos(char *binlog_pos_file, char *binlog_pos_offset) +{ + MYSQL_RES *res; + MYSQL_ROW row; + int found; + + if (mysql_query_with_error_report(mysql, &res, + "SHOW STATUS LIKE 'binlog_snapshot_%'")) + return 1; + + found= 0; + while ((row= mysql_fetch_row(res))) + { + if (0 == strcmp(row[0], "binlog_snapshot_file")) + { + if (binlog_pos_file) + strmake(binlog_pos_file, row[1], FN_REFLEN-1); + found++; + } + else if (0 == strcmp(row[0], "binlog_snapshot_position")) + { + if (binlog_pos_offset) + strmake(binlog_pos_offset, row[1], LONGLONG_LEN); + found++; + } + } + mysql_free_result(res); + + return (found == 2); +} + static char *my_case_str(const char *str, uint str_len, const char *token, @@ -4580,41 +4621,65 @@ static int dump_selected_tables(char *db, char **table_names, int tables) } /* dump_selected_tables */ -static int do_show_master_status(MYSQL *mysql_con) +static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) { MYSQL_ROW row; MYSQL_RES *master; + char binlog_pos_file[FN_REFLEN]; + char binlog_pos_offset[LONGLONG_LEN+1]; + char *file, *offset; const char *comment_prefix= (opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : ""; - if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS")) + + if (consistent_binlog_pos) { - return 1; + if(!check_consistent_binlog_pos(binlog_pos_file, binlog_pos_offset)) + return 1; + file= binlog_pos_file; + offset= binlog_pos_offset; } else { + if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS")) + return 1; + row= mysql_fetch_row(master); if (row && row[0] && row[1]) { - /* SHOW MASTER STATUS reports file and position */ - print_comment(md_result_file, 0, - "\n--\n-- Position to start replication or point-in-time " - "recovery from\n--\n\n"); - fprintf(md_result_file, - "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", - comment_prefix, row[0], row[1]); - check_io(md_result_file); + file= row[0]; + offset= row[1]; } - else if (!ignore_errors) + else { - /* SHOW MASTER STATUS reports nothing and --force is not enabled */ - my_printf_error(0, "Error: Binlogging on server not active", - MYF(0)); mysql_free_result(master); - maybe_exit(EX_MYSQLERR); - return 1; + if (!ignore_errors) + { + /* SHOW MASTER STATUS reports nothing and --force is not enabled */ + my_printf_error(0, "Error: Binlogging on server not active", + MYF(0)); + maybe_exit(EX_MYSQLERR); + return 1; + } + else + { + return 0; + } } - mysql_free_result(master); } + + /* SHOW MASTER STATUS reports file and position */ + if (opt_comments) + print_comment(md_result_file, 0, + "\n--\n-- Position to start replication or point-in-time " + "recovery from\n--\n\n"); + fprintf(md_result_file, + "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", + comment_prefix, file, offset); + check_io(md_result_file); + + if (!consistent_binlog_pos) + mysql_free_result(master); + return 0; } @@ -5251,6 +5316,7 @@ int main(int argc, char **argv) { char bin_log_name[FN_REFLEN]; int exit_code; + int consistent_binlog_pos= 0; MY_INIT("mysqldump"); compatible_mode_normal_str[0]= 0; @@ -5287,7 +5353,13 @@ int main(int argc, char **argv) if (!path) write_header(md_result_file, *argv); - if ((opt_lock_all_tables || opt_master_data) && + if (opt_single_transaction && opt_master_data) + { + /* See if we can avoid FLUSH TABLES WITH READ LOCK (MariaDB 5.3+). */ + consistent_binlog_pos= check_consistent_binlog_pos(NULL, NULL); + } + + if ((opt_lock_all_tables || (opt_master_data && !consistent_binlog_pos)) && do_flush_tables_read_lock(mysql)) goto err; if (opt_single_transaction && start_transaction(mysql)) @@ -5305,7 +5377,7 @@ int main(int argc, char **argv) goto err; flush_logs= 0; /* not anymore; that would not be sensible */ } - if (opt_master_data && do_show_master_status(mysql)) + if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos)) goto err; if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */ goto err; diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 196cdc6f394..fa77a69ec81 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -1224,7 +1224,7 @@ get_options(int *argc,char ***argv) if (opt_csv_str[0] == '-') { - csv_file= fileno(stdout); + csv_file= my_fileno(stdout); } else { @@ -1383,9 +1383,9 @@ get_options(int *argc,char ***argv) fprintf(stderr,"%s: Could not open create file\n", my_progname); exit(1); } - tmp_string= (char *)my_malloc(sbuf.st_size + 1, + tmp_string= (char *)my_malloc((size_t)sbuf.st_size + 1, MYF(MY_ZEROFILL|MY_FAE|MY_WME)); - my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0)); + my_read(data_file, (uchar*) tmp_string, (size_t)sbuf.st_size, MYF(0)); tmp_string[sbuf.st_size]= '\0'; my_close(data_file,MYF(0)); parse_delimiter(tmp_string, &create_statements, delimiter[0]); @@ -1410,9 +1410,9 @@ get_options(int *argc,char ***argv) fprintf(stderr,"%s: Could not open query supplied file\n", my_progname); exit(1); } - tmp_string= (char *)my_malloc(sbuf.st_size + 1, + tmp_string= (char *)my_malloc((size_t)sbuf.st_size + 1, MYF(MY_ZEROFILL|MY_FAE|MY_WME)); - my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0)); + my_read(data_file, (uchar*) tmp_string, (size_t)sbuf.st_size, MYF(0)); tmp_string[sbuf.st_size]= '\0'; my_close(data_file,MYF(0)); if (user_supplied_query) @@ -1441,9 +1441,9 @@ get_options(int *argc,char ***argv) fprintf(stderr,"%s: Could not open query supplied file\n", my_progname); exit(1); } - tmp_string= (char *)my_malloc(sbuf.st_size + 1, + tmp_string= (char *)my_malloc((size_t)sbuf.st_size + 1, MYF(MY_ZEROFILL|MY_FAE|MY_WME)); - my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0)); + my_read(data_file, (uchar*) tmp_string, (size_t)sbuf.st_size, MYF(0)); tmp_string[sbuf.st_size]= '\0'; my_close(data_file,MYF(0)); if (user_supplied_pre_statements) @@ -1472,9 +1472,9 @@ get_options(int *argc,char ***argv) fprintf(stderr,"%s: Could not open query supplied file\n", my_progname); exit(1); } - tmp_string= (char *)my_malloc(sbuf.st_size + 1, + tmp_string= (char *)my_malloc((size_t)sbuf.st_size + 1, MYF(MY_ZEROFILL|MY_FAE|MY_WME)); - my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0)); + my_read(data_file, (uchar*) tmp_string, (size_t)sbuf.st_size, MYF(0)); tmp_string[sbuf.st_size]= '\0'; my_close(data_file,MYF(0)); if (user_supplied_post_statements) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 6cf9918e829..612a4885303 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009-2011 Monty Program Ab. + Copyright (c) 2009-2012 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 @@ -114,7 +114,7 @@ static my_bool display_result_vertically= FALSE, display_result_lower= FALSE, display_metadata= FALSE, display_result_sorted= FALSE; static my_bool disable_query_log= 0, disable_result_log= 0; static my_bool disable_connect_log= 1; -static my_bool disable_warnings= 0; +static my_bool disable_warnings= 0, disable_column_names= 0; static my_bool prepare_warnings_enabled= 0; static my_bool disable_info= 1; static char *opt_plugin_dir= 0, *opt_default_auth; @@ -301,6 +301,7 @@ enum enum_commands { Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS, Q_ENABLE_INFO, Q_DISABLE_INFO, Q_ENABLE_METADATA, Q_DISABLE_METADATA, + Q_ENABLE_COLUMN_NAMES, Q_DISABLE_COLUMN_NAMES, Q_EXEC, Q_DELIMITER, Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR, Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS, @@ -374,6 +375,8 @@ const char *command_names[]= "disable_info", "enable_metadata", "disable_metadata", + "enable_column_names", + "disable_column_names", "exec", "delimiter", "disable_abort_on_error", @@ -729,7 +732,8 @@ void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, int len); void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val); void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val); -void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input); +void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input, + bool keep_header); static int match_expected_error(struct st_command *command, unsigned int err_errno, @@ -2810,6 +2814,7 @@ void do_exec(struct st_command *command) FILE *res_file; char *cmd= command->first_argument; DYNAMIC_STRING ds_cmd; + DYNAMIC_STRING ds_sorted, *ds_result; DBUG_ENTER("do_exec"); DBUG_PRINT("enter", ("cmd: '%s'", cmd)); @@ -2855,6 +2860,13 @@ void do_exec(struct st_command *command) die("popen(\"%s\", \"r\") failed", command->first_argument); } + ds_result= &ds_res; + if (display_result_sorted) + { + init_dynamic_string(&ds_sorted, "", 1024, 1024); + ds_result= &ds_sorted; + } + while (fgets(buf, sizeof(buf), res_file)) { if (disable_result_log) @@ -2864,10 +2876,17 @@ void do_exec(struct st_command *command) } else { - replace_dynstr_append(&ds_res, buf); + replace_dynstr_append(ds_result, buf); } } error= pclose(res_file); + + if (display_result_sorted) + { + dynstr_append_sorted(&ds_res, &ds_sorted, 0); + dynstr_free(&ds_sorted); + } + if (error > 0) { uint status= WEXITSTATUS(error); @@ -6767,6 +6786,7 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, my_bool *is_null; ulong *length; uint i; + int error; /* Allocate array with bind structs, lengths and NULL flags */ my_bind= (MYSQL_BIND*) my_malloc(num_fields * sizeof(MYSQL_BIND), @@ -6794,7 +6814,7 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, die("mysql_stmt_bind_result failed: %d: %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); - while (mysql_stmt_fetch(stmt) == 0) + while ((error=mysql_stmt_fetch(stmt)) == 0) { for (i= 0; i < num_fields; i++) append_field(ds, i, &fields[i], (char*)my_bind[i].buffer, @@ -6803,8 +6823,11 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, dynstr_append_mem(ds, "\n", 1); } + if (error != MYSQL_NO_DATA) + die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: error: %d", + error); if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) - die("fetch didn't end with MYSQL_NO_DATA from statement: %d %s", + die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: %d %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); for (i= 0; i < num_fields; i++) @@ -6899,6 +6922,8 @@ void append_table_headings(DYNAMIC_STRING *ds, uint num_fields) { uint col_idx; + if (disable_column_names) + return; for (col_idx= 0; col_idx < num_fields; col_idx++) { if (col_idx) @@ -7556,7 +7581,8 @@ int util_query(MYSQL* org_mysql, const char* query){ cur_con->util_mysql= mysql; } - return mysql_query(mysql, query); + int ret= mysql_query(mysql, query); + DBUG_RETURN(ret); } @@ -7768,7 +7794,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) if (display_result_sorted) { /* Sort the result set and append it to result */ - dynstr_append_sorted(save_ds, &ds_sorted); + dynstr_append_sorted(save_ds, &ds_sorted, 1); ds= save_ds; dynstr_free(&ds_sorted); } @@ -8431,6 +8457,14 @@ int main(int argc, char **argv) display_metadata= 0; var_set_int("$ENABLED_METADATA", 0); break; + case Q_ENABLE_COLUMN_NAMES: + disable_column_names= 0; + var_set_int("$ENABLED_COLUMN_NAMES", 0); + break; + case Q_DISABLE_COLUMN_NAMES: + disable_column_names= 1; + var_set_int("$ENABLED_COLUMN_NAMES", 1); + break; case Q_SOURCE: do_source(command); break; case Q_SLEEP: do_sleep(command, 0); break; case Q_REAL_SLEEP: do_sleep(command, 1); break; @@ -8818,7 +8852,7 @@ void timer_output(void) ulonglong timer_now(void) { - return my_micro_time() / 1000; + return my_interval_timer() / 1000000; } @@ -10142,17 +10176,16 @@ void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val) } - /* Build a list of pointer to each line in ds_input, sort the list and use the sorted list to append the strings sorted to the output ds SYNOPSIS - dynstr_append_sorted - ds - string where the sorted output will be appended - ds_input - string to be sorted - + dynstr_append_sorted() + ds string where the sorted output will be appended + ds_input string to be sorted + keep_header If header should not be sorted */ static int comp_lines(const char **a, const char **b) @@ -10160,7 +10193,8 @@ static int comp_lines(const char **a, const char **b) return (strcmp(*a,*b)); } -void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input) +void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input, + bool keep_header) { unsigned i; char *start= ds_input->str; @@ -10172,11 +10206,14 @@ void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input) my_init_dynamic_array(&lines, sizeof(const char*), 32, 32); - /* First line is result header, skip past it */ - while (*start && *start != '\n') - start++; - start++; /* Skip past \n */ - dynstr_append_mem(ds, ds_input->str, start - ds_input->str); + if (keep_header) + { + /* First line is result header, skip past it */ + while (*start && *start != '\n') + start++; + start++; /* Skip past \n */ + dynstr_append_mem(ds, ds_input->str, start - ds_input->str); + } /* Insert line(s) in array */ while (*start) @@ -10254,4 +10291,3 @@ char *mysql_authentication_dialog_ask(MYSQL *mysql, int type, return buf; } - diff --git a/client/readline.cc b/client/readline.cc index cb020d62241..b44862062e1 100644 --- a/client/readline.cc +++ b/client/readline.cc @@ -45,7 +45,7 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file) if (!(line_buff=(LINE_BUFFER*) my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL)))) return 0; - if (init_line_buffer(line_buff,fileno(file),IO_SIZE,max_size)) + if (init_line_buffer(line_buff,my_fileno(file),IO_SIZE,max_size)) { my_free(line_buff,MYF(0)); return 0; diff --git a/client/sql_string.cc b/client/sql_string.cc index 720b0332411..57518423f4b 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -544,11 +544,11 @@ uint32 String::numchars() return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length); } -int String::charpos(int i,uint32 offset) +int String::charpos(longlong i,uint32 offset) { if (i <= 0) - return i; - return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i); + return (int)i; + return (int)str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,(size_t)i); } int String::strstr(const String &s,uint32 offset) diff --git a/client/sql_string.h b/client/sql_string.h index 6d8269a4b31..be5ae5071f8 100644 --- a/client/sql_string.h +++ b/client/sql_string.h @@ -274,7 +274,7 @@ public: friend int stringcmp(const String *a,const String *b); friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); uint32 numchars(); - int charpos(int i,uint32 offset=0); + int charpos(longlong i,uint32 offset=0); int reserve(uint32 space_needed) { |