summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2014-10-15 12:59:13 +0200
committerSergei Golubchik <serg@mariadb.org>2014-10-15 12:59:13 +0200
commitf62c12b405ba7ec80b8e2490856b83c6f5899211 (patch)
tree010605c7f145da6ea6ac14b39abc4cf700d619b1 /client
parentf947f73b2b6d2bd246b81a9038224d2a85777520 (diff)
parentf1afc003eefe0aafd3e070c7453d9e029d8445a8 (diff)
downloadmariadb-git-f62c12b405ba7ec80b8e2490856b83c6f5899211.tar.gz
Merge 10.0.14 into 10.1
Diffstat (limited to 'client')
-rw-r--r--client/mysql.cc2
-rw-r--r--client/mysql_upgrade.c79
-rw-r--r--client/mysqladmin.cc63
-rw-r--r--client/mysqlcheck.c32
-rw-r--r--client/mysqldump.c212
-rw-r--r--client/mysqlslap.c2
-rw-r--r--client/mysqltest.cc105
7 files changed, 366 insertions, 129 deletions
diff --git a/client/mysql.cc b/client/mysql.cc
index 510bceecac2..25e6c0255c6 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -90,7 +90,7 @@ extern "C" {
#if defined(__WIN__)
#include <conio.h>
#else
-#include <readline/readline.h>
+#include <readline.h>
#define HAVE_READLINE
#define USE_POPEN
#endif
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 65ea586c672..cef5e22647d 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -22,7 +22,7 @@
#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
-#define VER "1.3a"
+#define VER "1.4"
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
@@ -140,21 +140,21 @@ static struct my_option my_long_options[]=
#include <sslopt-longopts.h>
{"tmpdir", 't', "Directory for temporary files.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"upgrade-system-tables", 's', "Only upgrade the system tables "
- "do not try to upgrade the data.",
+ {"upgrade-system-tables", 's', "Only upgrade the system tables in the mysql database. Tables in other databases are not checked or touched.",
&opt_systables_only, &opt_systables_only, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"user", 'u', "User for login if not current user.", &opt_user,
&opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"verbose", 'v', "Display more output about the process.",
+ {"verbose", 'v', "Display more output about the process; Using it twice will print connection argument; Using it 3 times will print out all CHECK, RENAME and ALTER TABLE during the check phase.",
&opt_not_used, &opt_not_used, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"version-check", 'k', "Run this program only if its \'server version\' "
- "matches the version of the server to which it's connecting, (enabled by "
- "default); use --skip-version-check to avoid this check. Note: the \'server "
- "version\' of the program is the version of the MySQL server with which it "
- "was built/distributed.", &opt_version_check, &opt_version_check, 0,
+ {"version-check", 'k',
+ "Run this program only if its \'server version\' "
+ "matches the version of the server to which it's connecting. "
+ "Note: the \'server version\' of the program is the version of the MariaDB "
+ "server with which it was built/distributed.",
+ &opt_version_check, &opt_version_check, 0,
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"write-binlog", OPT_WRITE_BINLOG, "All commands including those, "
"issued by mysqlcheck, are written to the binary log.",
@@ -206,12 +206,12 @@ static void die(const char *fmt, ...)
}
-static void verbose(const char *fmt, ...)
+static int verbose(const char *fmt, ...)
{
va_list args;
if (opt_silent)
- return;
+ return 0;
/* Print the verbose message */
va_start(args, fmt);
@@ -222,6 +222,7 @@ static void verbose(const char *fmt, ...)
fflush(stdout);
}
va_end(args);
+ return 0;
}
@@ -370,6 +371,9 @@ static int run_command(char* cmd,
FILE *res_file;
int error;
+ if (opt_verbose >= 4)
+ puts(cmd);
+
if (!(res_file= popen(cmd, "r")))
die("popen(\"%s\", \"r\") failed", cmd);
@@ -750,20 +754,21 @@ static void print_conn_args(const char *tool_name)
in the server using "mysqlcheck --check-upgrade .."
*/
-static int run_mysqlcheck_upgrade(void)
+static int run_mysqlcheck_upgrade(const char *arg1, const char *arg2)
{
- verbose("Phase 2/3: Checking and upgrading tables");
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
"--no-defaults",
ds_args.str,
"--check-upgrade",
- "--all-databases",
"--auto-repair",
- !opt_silent || opt_verbose ? "--verbose": "",
+ !opt_silent || opt_verbose >= 1 ? "--verbose" : "",
+ opt_verbose >= 2 ? "--verbose" : "",
+ opt_verbose >= 3 ? "--verbose" : "",
opt_silent ? "--silent": "",
opt_write_binlog ? "--write-binlog" : "--skip-write-binlog",
+ arg1, arg2,
"2>&1",
NULL);
}
@@ -771,7 +776,7 @@ static int run_mysqlcheck_upgrade(void)
static int run_mysqlcheck_fixnames(void)
{
- verbose("Phase 1/3: Fixing table and database names");
+ verbose("Phase 3/4: Fixing table and database names");
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
@@ -780,7 +785,9 @@ static int run_mysqlcheck_fixnames(void)
"--all-databases",
"--fix-db-names",
"--fix-table-names",
- opt_verbose ? "--verbose": "",
+ opt_verbose >= 1 ? "--verbose" : "",
+ opt_verbose >= 2 ? "--verbose" : "",
+ opt_verbose >= 3 ? "--verbose" : "",
opt_silent ? "--silent": "",
opt_write_binlog ? "--write-binlog" : "--skip-write-binlog",
"2>&1",
@@ -857,7 +864,6 @@ static int run_sql_fix_privilege_tables(void)
if (init_dynamic_string(&ds_result, "", 512, 512))
die("Out of memory");
- verbose("Phase 3/3: Running 'mysql_fix_privilege_tables'...");
/*
Individual queries can not be executed independently by invoking
a forked mysql client, because the script uses session variables
@@ -1004,16 +1010,12 @@ int main(int argc, char **argv)
/* Find mysql */
find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"), self_name);
- if (!opt_systables_only)
- {
- /* Find mysqlcheck */
- find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name);
- }
- else
- {
- if (!opt_silent)
- printf("The --upgrade-system-tables option was used, databases won't be touched.\n");
- }
+ /* Find mysqlcheck */
+ find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name);
+
+ if (opt_systables_only && !opt_silent)
+ printf("The --upgrade-system-tables option was used, user tables won't be touched.\n");
+
/*
Read the mysql_upgrade_info file to check if mysql_upgrade
@@ -1033,16 +1035,19 @@ int main(int argc, char **argv)
/*
Run "mysqlcheck" and "mysql_fix_privilege_tables.sql"
*/
- if ((!opt_systables_only &&
- (run_mysqlcheck_fixnames() || run_mysqlcheck_upgrade())) ||
- run_sql_fix_privilege_tables())
- {
- /*
- The upgrade failed to complete in some way or another,
- significant error message should have been printed to the screen
- */
+ verbose("Phase 1/4: Checking mysql database");
+ if (run_mysqlcheck_upgrade("--databases", "mysql"))
die("Upgrade failed" );
- }
+ verbose("Phase 2/4: Running 'mysql_fix_privilege_tables'...");
+ if (run_sql_fix_privilege_tables())
+ die("Upgrade failed" );
+
+ if (!opt_systables_only &&
+ (run_mysqlcheck_fixnames() ||
+ verbose("Phase 4/4: Checking and upgrading tables") ||
+ run_mysqlcheck_upgrade("--all-databases","--skip-database=mysql")))
+ die("Upgrade failed" );
+
verbose("OK");
/* Create a file indicating upgrade has been performed */
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 5ba463f8d6f..ee3ab7f0864 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates.
- Copyright (c) 2010, 2012, Monty Program Ab.
+ Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2014, 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
@@ -71,6 +71,7 @@ extern "C" my_bool get_one_option(int optid, const struct my_option *opt,
char *argument);
static my_bool sql_connect(MYSQL *mysql, uint wait);
static int execute_commands(MYSQL *mysql,int argc, char **argv);
+static char **mask_password(int argc, char ***argv);
static int drop_db(MYSQL *mysql,const char *db);
extern "C" sig_handler endprog(int signal_number);
static void nice_time(ulong sec,char *buff);
@@ -306,9 +307,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
int main(int argc,char *argv[])
{
- int error= 0;
+ int error= 0, temp_argc;
MYSQL mysql;
- char **commands, **save_argv;
+ char **commands, **save_argv, **temp_argv;
MY_INIT(argv[0]);
mysql_init(&mysql);
@@ -316,8 +317,12 @@ int main(int argc,char *argv[])
if ((error= load_defaults("my",load_default_groups,&argc,&argv)))
goto err1;
save_argv = argv; /* Save for free_defaults */
+
if ((error=handle_options(&argc, &argv, my_long_options, get_one_option)))
goto err2;
+ temp_argv= mask_password(argc, &argv);
+ temp_argc= argc;
+
if (debug_info_flag)
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
if (debug_check_flag)
@@ -328,7 +333,7 @@ int main(int argc,char *argv[])
usage();
exit(1);
}
- commands = argv;
+ commands = temp_argv;
if (tty_password)
opt_password = get_tty_password(NullS);
@@ -475,6 +480,13 @@ int main(int argc,char *argv[])
} /* got connection */
mysql_close(&mysql);
+ temp_argc--;
+ while(temp_argc >= 0)
+ {
+ my_free(temp_argv[temp_argc]);
+ temp_argc--;
+ }
+ my_free(temp_argv);
err2:
mysql_library_end();
my_free(opt_password);
@@ -1213,6 +1225,47 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return 0;
}
+/**
+ @brief Masking the password if it is passed as command line argument.
+
+ @details It works in Linux and changes cmdline in ps and /proc/pid/cmdline,
+ but it won't work for history file of shell.
+ The command line arguments are copied to another array and the
+ password in the argv is masked. This function is called just after
+ "handle_options" because in "handle_options", the agrv pointers
+ are altered which makes freeing of dynamically allocated memory
+ difficult. The password masking is done before all other operations
+ in order to minimise the time frame of password visibility via cmdline.
+
+ @param argc command line options (count)
+ @param argv command line options (values)
+
+ @return temp_argv copy of argv
+*/
+
+static char **mask_password(int argc, char ***argv)
+{
+ char **temp_argv;
+ temp_argv= (char **)(my_malloc(sizeof(char *) * argc, MYF(MY_WME)));
+ argc--;
+ while (argc > 0)
+ {
+ temp_argv[argc]= my_strdup((*argv)[argc], MYF(MY_FAE));
+ if (find_type((*argv)[argc - 1],&command_typelib, FIND_TYPE_BASIC) == ADMIN_PASSWORD ||
+ find_type((*argv)[argc - 1],&command_typelib, FIND_TYPE_BASIC) == ADMIN_OLD_PASSWORD)
+ {
+ char *start= (*argv)[argc];
+ while (*start)
+ *start++= 'x';
+ start= (*argv)[argc];
+ if (*start)
+ start[1]= 0; /* Cut length of argument */
+ }
+ argc--;
+ }
+ temp_argv[argc]= my_strdup((*argv)[argc], MYF(MY_FAE));
+ return(temp_argv);
+}
static void print_version(void)
{
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index fc196d2f27a..295affe9b1a 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.2-MariaDB"
+#define CHECK_VERSION "2.7.3-MariaDB"
#include "client_priv.h"
#include <m_ctype.h>
@@ -51,6 +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;
+static char *opt_skip_database;
DYNAMIC_ARRAY tables4repair, tables4rebuild, alter_table_cmds;
static char *shared_memory_base_name=0;
static uint opt_protocol=0;
@@ -178,6 +179,9 @@ static struct my_option my_long_options[] =
#endif
{"silent", 's', "Print only error messages.", &opt_silent,
&opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"skip_database", 0, "Don't process the database specified as argument",
+ &opt_skip_database, &opt_skip_database, 0, GET_STR, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
{"socket", 'S', "The socket file to use for connection.",
&opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -192,8 +196,8 @@ static struct my_option my_long_options[] =
{"user", 'u', "User for login if not current user.", &current_user,
&current_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"verbose", 'v', "Print info about the various stages.", 0, 0, 0, GET_NO_ARG,
- NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"verbose", 'v', "Print info about the various stages; Using it 3 times will print out all CHECK, RENAME and ALTER TABLE during the check phase.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
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}
@@ -246,6 +250,9 @@ static void usage(void)
puts("mysqlrepair: The default option will be -r");
puts("mysqlanalyze: The default option will be -a");
puts("mysqloptimize: The default option will be -o\n");
+ printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
+ printf("OR %s [OPTIONS] --databases DB1 [DB2 DB3...]\n",
+ my_progname);
puts("Please consult the MariaDB/MySQL knowledgebase at");
puts("http://kb.askmonty.org/v/mysqlcheck for latest information about");
puts("this program.");
@@ -625,8 +632,10 @@ static int process_all_tables_in_db(char *database)
} /* process_all_tables_in_db */
-static int run_query(const char *query)
+static int run_query(const char *query, my_bool log_query)
{
+ if (verbose >=3 && log_query)
+ puts(query);
if (mysql_query(sock, query))
{
fprintf(stderr, "Failed to %s\n", query);
@@ -646,7 +655,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);
- rc= run_query(qbuf);
+ rc= run_query(qbuf, 1);
if (verbose)
printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
DBUG_RETURN(rc);
@@ -661,7 +670,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);
- rc= run_query(qbuf);
+ rc= run_query(qbuf, 1);
if (verbose)
printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
DBUG_RETURN(rc);
@@ -680,6 +689,8 @@ static int rebuild_table(char *name)
ptr= strmov(query, "ALTER TABLE ");
ptr= fix_table_name(ptr, name);
ptr= strxmov(ptr, " FORCE", NullS);
+ if (verbose >= 3)
+ puts(query);
if (mysql_real_query(sock, query, (uint)(ptr - query)))
{
fprintf(stderr, "Failed to %s\n", query);
@@ -696,6 +707,9 @@ static int process_one_db(char *database)
{
DBUG_ENTER("process_one_db");
+ if (opt_skip_database && !strcmp(database, opt_skip_database))
+ DBUG_RETURN(0);
+
if (verbose)
puts(database);
if (what_to_do == DO_UPGRADE)
@@ -735,7 +749,7 @@ static int use_db(char *database)
static int disable_binlog()
{
mysql_query(sock, "SET WSREP_ON=0"); /* ignore the error, if any */
- return run_query("SET SQL_LOG_BIN=0");
+ return run_query("SET SQL_LOG_BIN=0", 0);
}
static int handle_request_for_tables(char *tables, uint length)
@@ -794,6 +808,8 @@ static int handle_request_for_tables(char *tables, uint length)
ptr= strxmov(ptr, " ", options, NullS);
query_length= (uint) (ptr - query);
}
+ if (verbose >= 3)
+ puts(query);
if (mysql_real_query(sock, query, query_length))
{
sprintf(message, "when executing '%s TABLE ... %s'", op, options);
@@ -1046,7 +1062,7 @@ 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));
+ run_query((char*) dynamic_array_ptr(&alter_table_cmds, i), 1);
}
ret= MY_TEST(first_error);
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 98f6f15b46e..dfda2f35f71 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -87,6 +87,9 @@
/* Chars needed to store LONGLONG, excluding trailing '\0'. */
#define LONGLONG_LEN 20
+/* Max length GTID position that we will output. */
+#define MAX_GTID_LENGTH 1024
+
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,
@@ -135,6 +138,7 @@ static ulong opt_compatible_mode= 0;
#define MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL 2
static uint opt_mysql_port= 0, opt_master_data;
static uint opt_slave_data;
+static uint opt_use_gtid;
static uint my_end_arg;
static char * opt_mysql_unix_port=0;
static int first_error=0;
@@ -355,6 +359,13 @@ static struct my_option my_long_options[] =
"server receiving the resulting dump.",
&opt_galera_sst_mode, &opt_galera_sst_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
+ {"gtid", 0, "Used together with --master-data=1 or --dump-slave=1."
+ "When enabled, the output from those options will set the GTID position "
+ "instead of the binlog file and offset; the file/offset will appear only as "
+ "a comment. When disabled, the GTID position will still appear in the "
+ "output, but only commented.",
+ &opt_use_gtid, &opt_use_gtid, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
@@ -1192,7 +1203,7 @@ check_consistent_binlog_pos(char *binlog_pos_file, char *binlog_pos_offset)
if (mysql_query_with_error_report(mysql, &res,
"SHOW STATUS LIKE 'binlog_snapshot_%'"))
- return 1;
+ return 0;
found= 0;
while ((row= mysql_fetch_row(res)))
@@ -1215,6 +1226,90 @@ check_consistent_binlog_pos(char *binlog_pos_file, char *binlog_pos_offset)
return (found == 2);
}
+
+/*
+ Get the GTID position corresponding to a given old-style binlog position.
+ This uses BINLOG_GTID_POS(). The advantage is that the GTID position can
+ be obtained completely non-blocking in this way (without the need for
+ FLUSH TABLES WITH READ LOCK), as the old-style position can be obtained
+ with START TRANSACTION WITH CONSISTENT SNAPSHOT.
+
+ Returns 0 if ok, non-zero if error.
+*/
+static int
+get_binlog_gtid_pos(char *binlog_pos_file, char *binlog_pos_offset,
+ char *out_gtid_pos)
+{
+ DYNAMIC_STRING query;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int err;
+ char file_buf[FN_REFLEN*2+1], offset_buf[LONGLONG_LEN*2+1];
+ size_t len_pos_file= strlen(binlog_pos_file);
+ size_t len_pos_offset= strlen(binlog_pos_offset);
+
+ if (len_pos_file >= FN_REFLEN || len_pos_offset > LONGLONG_LEN)
+ return 0;
+ mysql_real_escape_string(mysql, file_buf, binlog_pos_file, len_pos_file);
+ mysql_real_escape_string(mysql, offset_buf, binlog_pos_offset, len_pos_offset);
+ init_dynamic_string_checked(&query, "SELECT BINLOG_GTID_POS('", 256, 1024);
+ dynstr_append_checked(&query, file_buf);
+ dynstr_append_checked(&query, "', '");
+ dynstr_append_checked(&query, offset_buf);
+ dynstr_append_checked(&query, "')");
+
+ err= mysql_query_with_error_report(mysql, &res, query.str);
+ dynstr_free(&query);
+ if (err)
+ return err;
+
+ err= 1;
+ if ((row= mysql_fetch_row(res)))
+ {
+ strmake(out_gtid_pos, row[0], MAX_GTID_LENGTH-1);
+ err= 0;
+ }
+ mysql_free_result(res);
+
+ return err;
+}
+
+
+/*
+ Get the GTID position on a master or slave.
+ The parameter MASTER is non-zero to get the position on a master
+ (@@gtid_binlog_pos) or zero for a slave (@@gtid_slave_pos).
+
+ This uses the @@gtid_binlog_pos or @@gtid_slave_pos, so requires FLUSH TABLES
+ WITH READ LOCK or similar to be consistent.
+
+ Returns 0 if ok, non-zero for error.
+*/
+static int
+get_gtid_pos(char *out_gtid_pos, int master)
+{
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int found;
+
+ if (mysql_query_with_error_report(mysql, &res,
+ (master ?
+ "SELECT @@GLOBAL.gtid_binlog_pos" :
+ "SELECT @@GLOBAL.gtid_slave_pos")))
+ return 1;
+
+ found= 0;
+ if ((row= mysql_fetch_row(res)))
+ {
+ strmake(out_gtid_pos, row[0], MAX_GTID_LENGTH-1);
+ found++;
+ }
+ mysql_free_result(res);
+
+ return (found != 1);
+}
+
+
static char *my_case_str(const char *str,
uint str_len,
const char *token,
@@ -4850,12 +4945,15 @@ static int wsrep_set_sst_cmds(MYSQL *mysql) {
return 0;
}
-static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
+
+static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos,
+ int have_mariadb_gtid, int use_gtid)
{
MYSQL_ROW row;
MYSQL_RES *UNINIT_VAR(master);
char binlog_pos_file[FN_REFLEN];
char binlog_pos_offset[LONGLONG_LEN+1];
+ char gtid_pos[MAX_GTID_LENGTH];
char *file, *offset;
const char *comment_prefix=
(opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
@@ -4866,6 +4964,9 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
return 1;
file= binlog_pos_file;
offset= binlog_pos_offset;
+ if (have_mariadb_gtid &&
+ get_binlog_gtid_pos(binlog_pos_file, binlog_pos_offset, gtid_pos))
+ return 1;
}
else
{
@@ -4895,6 +4996,9 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
return 0;
}
}
+
+ if (have_mariadb_gtid && get_gtid_pos(gtid_pos, 1))
+ return 1;
}
/* SHOW MASTER STATUS reports file and position */
@@ -4903,7 +5007,19 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
"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);
+ (use_gtid ? "-- " : comment_prefix), file, offset);
+ if (have_mariadb_gtid)
+ {
+ print_comment(md_result_file, 0,
+ "\n--\n-- GTID to start replication from\n--\n\n");
+ if (use_gtid)
+ fprintf(md_result_file,
+ "%sCHANGE MASTER TO MASTER_USE_GTID=slave_pos;\n",
+ comment_prefix);
+ fprintf(md_result_file,
+ "%sSET GLOBAL gtid_slave_pos='%s';\n",
+ (!use_gtid ? "-- " : comment_prefix), gtid_pos);
+ }
check_io(md_result_file);
if (!consistent_binlog_pos)
@@ -4973,12 +5089,16 @@ static int add_slave_statements(void)
return(0);
}
-static int do_show_slave_status(MYSQL *mysql_con)
+static int do_show_slave_status(MYSQL *mysql_con, int use_gtid,
+ int have_mariadb_gtid)
{
MYSQL_RES *UNINIT_VAR(slave);
MYSQL_ROW row;
const char *comment_prefix=
(opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
+ const char *gtid_comment_prefix= (use_gtid ? comment_prefix : "-- ");
+ const char *nogtid_comment_prefix= (!use_gtid ? comment_prefix : "-- ");
+ int set_gtid_done= 0;
if (mysql_query_with_error_report(mysql_con, &slave,
multi_source ?
@@ -4996,8 +5116,30 @@ static int do_show_slave_status(MYSQL *mysql_con)
while ((row= mysql_fetch_row(slave)))
{
+ if (multi_source && !set_gtid_done)
+ {
+ char gtid_pos[MAX_GTID_LENGTH];
+ if (have_mariadb_gtid && get_gtid_pos(gtid_pos, 0))
+ return 1;
+ if (opt_comments)
+ fprintf(md_result_file, "\n--\n-- Gtid position to start replication "
+ "from\n--\n\n");
+ fprintf(md_result_file, "%sSET GLOBAL gtid_slave_pos='%s';\n",
+ gtid_comment_prefix, gtid_pos);
+ set_gtid_done= 1;
+ }
if (row[9 + multi_source] && row[21 + multi_source])
{
+ if (use_gtid)
+ {
+ if (multi_source)
+ fprintf(md_result_file, "%sCHANGE MASTER '%.80s' TO "
+ "MASTER_USE_GTID=slave_pos;\n", gtid_comment_prefix, row[0]);
+ else
+ fprintf(md_result_file, "%sCHANGE MASTER TO "
+ "MASTER_USE_GTID=slave_pos;\n", gtid_comment_prefix);
+ }
+
/* SHOW MASTER STATUS reports file and position */
if (opt_comments)
fprintf(md_result_file,
@@ -5006,9 +5148,9 @@ static int do_show_slave_status(MYSQL *mysql_con)
if (multi_source)
fprintf(md_result_file, "%sCHANGE MASTER '%.80s' TO ",
- comment_prefix, row[0]);
+ nogtid_comment_prefix, row[0]);
else
- fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix);
+ fprintf(md_result_file, "%sCHANGE MASTER TO ", nogtid_comment_prefix);
if (opt_include_master_host_port)
{
@@ -5081,12 +5223,13 @@ static int do_flush_tables_read_lock(MYSQL *mysql_con)
FLUSH TABLES is to lower the probability of a stage where both mysqldump
and most client connections are stalled. Of course, if a second long
update starts between the two FLUSHes, we have that bad stall.
+
+ We use the LOCAL option, as we do not want the FLUSH TABLES replicated to
+ other servers.
*/
return
- ( mysql_query_with_error_report(mysql_con, 0,
- ((opt_master_data != 0) ?
- "FLUSH /*!40101 LOCAL */ TABLES" :
- "FLUSH TABLES")) ||
+ ( mysql_query_with_error_report(mysql_con, 0,
+ "FLUSH /*!40101 LOCAL */ TABLES") ||
mysql_query_with_error_report(mysql_con, 0,
"FLUSH TABLES WITH READ LOCK") );
}
@@ -5707,6 +5850,7 @@ int main(int argc, char **argv)
char bin_log_name[FN_REFLEN];
int exit_code;
int consistent_binlog_pos= 0;
+ int have_mariadb_gtid= 0;
MY_INIT(argv[0]);
sf_leaking_memory=1; /* don't report memory leaks on early exits */
@@ -5747,7 +5891,10 @@ int main(int argc, char **argv)
/* Check if the server support multi source */
if (mysql_get_server_version(mysql) >= 100000)
+ {
multi_source= 2;
+ have_mariadb_gtid= 1;
+ }
if (opt_slave_data && do_stop_slave_sql(mysql))
goto err;
@@ -5798,9 +5945,11 @@ int main(int argc, char **argv)
if (opt_galera_sst_mode && wsrep_set_sst_cmds(mysql))
goto err;
- if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos))
+ if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos,
+ have_mariadb_gtid, opt_use_gtid))
goto err;
- if (opt_slave_data && do_show_slave_status(mysql))
+ if (opt_slave_data && do_show_slave_status(mysql, opt_use_gtid,
+ have_mariadb_gtid))
goto err;
if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */
goto err;
@@ -5817,19 +5966,36 @@ int main(int argc, char **argv)
dump_all_tablespaces();
dump_all_databases();
}
- else if (argc > 1 && !opt_databases)
- {
- /* Only one database and selected table(s) */
- if (!opt_alltspcs && !opt_notspcs)
- dump_tablespaces_for_tables(*argv, (argv + 1), (argc -1));
- dump_selected_tables(*argv, (argv + 1), (argc - 1));
- }
else
{
- /* One or more databases, all tables */
- if (!opt_alltspcs && !opt_notspcs)
- dump_tablespaces_for_databases(argv);
- dump_databases(argv);
+ // Check all arguments meet length condition. Currently database and table
+ // names are limited to NAME_LEN bytes and stack-based buffers assumes
+ // that escaped name will be not longer than NAME_LEN*2 + 2 bytes long.
+ int argument;
+ for (argument= 0; argument < argc; argument++)
+ {
+ size_t argument_length= strlen(argv[argument]);
+ if (argument_length > NAME_LEN)
+ {
+ die(EX_CONSCHECK, "[ERROR] Argument '%s' is too long, it cannot be "
+ "name for any table or database.\n", argv[argument]);
+ }
+ }
+
+ if (argc > 1 && !opt_databases)
+ {
+ /* Only one database and selected table(s) */
+ if (!opt_alltspcs && !opt_notspcs)
+ dump_tablespaces_for_tables(*argv, (argv + 1), (argc - 1));
+ dump_selected_tables(*argv, (argv + 1), (argc - 1));
+ }
+ else
+ {
+ /* One or more databases, all tables */
+ if (!opt_alltspcs && !opt_notspcs)
+ dump_tablespaces_for_databases(argv);
+ dump_databases(argv);
+ }
}
/* add 'START SLAVE' to end of dump */
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index 3ba5eb80a07..01064f74261 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -1796,8 +1796,8 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit)
pthread_mutex_lock(&sleeper_mutex);
master_wakeup= 0;
- pthread_mutex_unlock(&sleeper_mutex);
pthread_cond_broadcast(&sleep_threshhold);
+ pthread_mutex_unlock(&sleeper_mutex);
gettimeofday(&start_time, NULL);
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 635b9b51cda..6c11cd234a9 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -7577,6 +7577,7 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
{
uint count;
MYSQL_RES *warn_res;
+ DYNAMIC_STRING res;
DBUG_ENTER("append_warnings");
if (!(count= mysql_warning_count(mysql)))
@@ -7596,11 +7597,18 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
die("Warning count is %u but didn't get any warnings",
count);
- append_result(ds, warn_res);
+ init_dynamic_string(&res, "", 1024, 1024);
+
+ append_result(&res, warn_res);
mysql_free_result(warn_res);
- DBUG_PRINT("warnings", ("%s", ds->str));
+ DBUG_PRINT("warnings", ("%s", res.str));
+ if (display_result_sorted)
+ dynstr_append_sorted(ds, &res, 0);
+ else
+ dynstr_append_mem(ds, res.str, res.length);
+ dynstr_free(&res);
DBUG_RETURN(count);
}
@@ -8848,6 +8856,10 @@ int main(int argc, char **argv)
128, 0, 0, get_var_key, 0, var_free, MYF(0)))
die("Variable hash initialization failed");
+ {
+ char path_separator[]= { FN_LIBCHAR, 0 };
+ var_set_string("SYSTEM_PATH_SEPARATOR", path_separator);
+ }
var_set_string("MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
var_set_string("MYSQL_SYSTEM_TYPE", SYSTEM_TYPE);
var_set_string("MYSQL_MACHINE_TYPE", MACHINE_TYPE);
@@ -9768,36 +9780,34 @@ struct st_regex
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
char *string, int icase);
+bool parse_re_part(char *start_re, char *end_re,
+ char **p, char *end, char **buf)
+{
+ if (*start_re != *end_re)
+ {
+ switch ((*start_re= *(*p)++)) {
+ case '(': *end_re= ')'; break;
+ case '[': *end_re= ']'; break;
+ case '{': *end_re= '}'; break;
+ case '<': *end_re= '>'; break;
+ default: *end_re= *start_re;
+ }
+ }
+ while (*p < end && **p != *end_re)
+ {
+ if ((*p)[0] == '\\' && *p + 1 < end && (*p)[1] == *end_re)
+ (*p)++;
-/*
- Finds the next (non-escaped) '/' in the expression.
- (If the character '/' is needed, it can be escaped using '\'.)
-*/
+ *(*buf)++= *(*p)++;
+ }
+ *(*buf)++= 0;
+
+ (*p)++;
+
+ return *p > end;
+}
-#define PARSE_REGEX_ARG \
- while (p < expr_end) \
- { \
- char c= *p; \
- if (c == '/') \
- { \
- if (last_c == '\\') \
- { \
- buf_p[-1]= '/'; \
- } \
- else \
- { \
- *buf_p++ = 0; \
- break; \
- } \
- } \
- else \
- *buf_p++ = c; \
- \
- last_c= c; \
- p++; \
- } \
- \
/*
Initializes the regular substitution expression to be used in the
result output of test.
@@ -9809,10 +9819,9 @@ struct st_replace_regex* init_replace_regex(char* expr)
{
struct st_replace_regex* res;
char* buf,*expr_end;
- char* p;
+ char* p, start_re, end_re= 1;
char* buf_p;
uint expr_len= strlen(expr);
- char last_c = 0;
struct st_regex reg;
/* my_malloc() will die on fail with MY_FAE */
@@ -9830,44 +9839,32 @@ struct st_replace_regex* init_replace_regex(char* expr)
{
bzero(&reg,sizeof(reg));
/* find the start of the statement */
- while (p < expr_end)
- {
- if (*p == '/')
- break;
+ while (my_isspace(charset_info, *p) && p < expr_end)
p++;
- }
- if (p == expr_end || ++p == expr_end)
+ if (p >= expr_end)
{
if (res->regex_arr.elements)
break;
else
goto err;
}
- /* we found the start */
- reg.pattern= buf_p;
-
- /* Find first argument -- pattern string to be removed */
- PARSE_REGEX_ARG
- if (p == expr_end || ++p == expr_end)
- goto err;
+ start_re= 0;
+ reg.pattern= buf_p;
+ if (parse_re_part(&start_re, &end_re, &p, expr_end, &buf_p))
+ goto err;
- /* buf_p now points to the replacement pattern terminated with \0 */
reg.replace= buf_p;
-
- /* Find second argument -- replace string to replace pattern */
- PARSE_REGEX_ARG
-
- if (p == expr_end)
- goto err;
-
- /* skip the ending '/' in the statement */
- p++;
+ if (parse_re_part(&start_re, &end_re, &p, expr_end, &buf_p))
+ goto err;
/* Check if we should do matching case insensitive */
if (p < expr_end && *p == 'i')
+ {
+ p++;
reg.icase= 1;
+ }
/* done parsing the statement, now place it in regex_arr */
if (insert_dynamic(&res->regex_arr,(uchar*) &reg))