summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rwxr-xr-xclient/CMakeLists.txt1
-rw-r--r--client/Makefile.am5
-rw-r--r--client/client_priv.h2
-rw-r--r--client/mysql.cc61
-rw-r--r--client/mysqlbinlog.cc187
-rw-r--r--client/mysqldump.c118
-rw-r--r--client/mysqlslap.c18
-rw-r--r--client/mysqltest.cc78
-rw-r--r--client/readline.cc2
-rw-r--r--client/sql_string.cc6
-rw-r--r--client/sql_string.h2
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.",
&current_prompt, &current_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)
{