diff options
author | Nirbhay Choubey <nirbhay@skysql.com> | 2014-08-11 23:55:41 -0400 |
---|---|---|
committer | Nirbhay Choubey <nirbhay@skysql.com> | 2014-08-11 23:55:41 -0400 |
commit | 8358dd53b7406deaa9f50ad09b16a86b7e367632 (patch) | |
tree | ef8995ad0e400cb6a1842649c3c886c7b3474835 /client | |
parent | e06e12f5b8dfe0ab2e5976eec1b27b25d318441b (diff) | |
parent | 4105cbf4a230c82ea7dee31d4d2262b798fad9f4 (diff) | |
download | mariadb-git-8358dd53b7406deaa9f50ad09b16a86b7e367632.tar.gz |
bzr merge -r4346 maria/10.0 (maria-10.0.13)
Diffstat (limited to 'client')
-rw-r--r-- | client/client_priv.h | 1 | ||||
-rw-r--r-- | client/mysql_upgrade.c | 45 | ||||
-rw-r--r-- | client/mysqladmin.cc | 63 | ||||
-rw-r--r-- | client/mysqlcheck.c | 10 | ||||
-rw-r--r-- | client/mysqldump.c | 212 | ||||
-rw-r--r-- | client/mysqlslap.c | 2 | ||||
-rw-r--r-- | client/mysqltest.cc | 93 |
7 files changed, 320 insertions, 106 deletions
diff --git a/client/client_priv.h b/client/client_priv.h index ef93818829e..67a6e822ea3 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -92,6 +92,7 @@ enum options_client OPT_REPORT_PROGRESS, OPT_SKIP_ANNOTATE_ROWS_EVENTS, OPT_SSL_CRL, OPT_SSL_CRLPATH, + OPT_USE_GTID, OPT_GALERA_SST_MODE, OPT_MAX_CLIENT_OPTION /* should be always the last */ }; diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index bf33397efdb..9caeb37f61b 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -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; } @@ -741,20 +742,19 @@ 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 ? "--silent": "", opt_write_binlog ? "--write-binlog" : "--skip-write-binlog", + arg1, arg2, "2>&1", NULL); } @@ -762,7 +762,7 @@ static int run_mysqlcheck_upgrade(void) static int run_mysqlcheck_fixnames(void) { - verbose("Phase 1/3: Fixing table and database names"); + verbose("Phase 2/3: Fixing table and database names"); print_conn_args("mysqlcheck"); return run_tool(mysqlcheck_path, NULL, /* Send output from mysqlcheck directly to screen */ @@ -848,7 +848,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 @@ -995,16 +994,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 @@ -1024,16 +1019,16 @@ int main(int argc, char **argv) /* Run "mysqlcheck" and "mysql_fix_privilege_tables.sql" */ - if ((!opt_systables_only && - (run_mysqlcheck_fixnames() || run_mysqlcheck_upgrade())) || + verbose("Phase 1/3: Running 'mysql_fix_privilege_tables'..."); + if (run_mysqlcheck_upgrade("--databases", "mysql") || 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 - */ die("Upgrade failed" ); - } + if (!opt_systables_only && + (run_mysqlcheck_fixnames() || + verbose("Phase 3/3: 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 bd5d2eac4e5..88016d9563d 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); @@ -1216,6 +1228,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 f7ae0783e5e..5a1dffd4014 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -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}, @@ -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."); @@ -696,6 +703,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) diff --git a/client/mysqldump.c b/client/mysqldump.c index eba5bd93671..3adbe87a8bb 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", OPT_USE_GTID, "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, " @@ -1186,7 +1197,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))) @@ -1209,6 +1220,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, @@ -4844,12 +4939,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) ? "-- " : ""; @@ -4860,6 +4958,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 { @@ -4889,6 +4990,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 */ @@ -4897,7 +5001,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) @@ -4967,12 +5083,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 ? @@ -4990,8 +5110,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, @@ -5000,9 +5142,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) { @@ -5075,12 +5217,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") ); } @@ -5701,6 +5844,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 */ @@ -5741,7 +5885,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; @@ -5792,9 +5939,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; @@ -5811,19 +5960,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 ef339d17a42..41f1d074dd9 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -8990,6 +8990,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); @@ -9910,36 +9914,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. @@ -9951,10 +9953,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 */ @@ -9972,44 +9973,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*) ®)) |