diff options
author | Sergei Golubchik <serg@mariadb.org> | 2014-10-15 12:59:13 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2014-10-15 12:59:13 +0200 |
commit | f62c12b405ba7ec80b8e2490856b83c6f5899211 (patch) | |
tree | 010605c7f145da6ea6ac14b39abc4cf700d619b1 /client | |
parent | f947f73b2b6d2bd246b81a9038224d2a85777520 (diff) | |
parent | f1afc003eefe0aafd3e070c7453d9e029d8445a8 (diff) | |
download | mariadb-git-f62c12b405ba7ec80b8e2490856b83c6f5899211.tar.gz |
Merge 10.0.14 into 10.1
Diffstat (limited to 'client')
-rw-r--r-- | client/mysql.cc | 2 | ||||
-rw-r--r-- | client/mysql_upgrade.c | 79 | ||||
-rw-r--r-- | client/mysqladmin.cc | 63 | ||||
-rw-r--r-- | client/mysqlcheck.c | 32 | ||||
-rw-r--r-- | client/mysqldump.c | 212 | ||||
-rw-r--r-- | client/mysqlslap.c | 2 | ||||
-rw-r--r-- | client/mysqltest.cc | 105 |
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.", ¤t_user, ¤t_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(®,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*) ®)) |