summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorKonstantin Osipov <kostja@sun.com>2009-11-20 17:18:37 +0300
committerKonstantin Osipov <kostja@sun.com>2009-11-20 17:18:37 +0300
commitd51a4fae328044f6b796ad8405dbb0dc3c653762 (patch)
tree126efa7bce0c3c70a1d3c3cb0099c6615f951e39 /client
parentca595821498d6a547fa1780df86cdf127b0019b3 (diff)
parentecb6228c623cc2b239bf297e107225eaa4455d19 (diff)
downloadmariadb-git-d51a4fae328044f6b796ad8405dbb0dc3c653762.tar.gz
Merge with next-mr
Diffstat (limited to 'client')
-rw-r--r--client/client_priv.h4
-rw-r--r--client/mysql.cc93
-rw-r--r--client/mysqladmin.cc39
-rw-r--r--client/mysqlcheck.c2
-rw-r--r--client/mysqldump.c185
-rw-r--r--client/mysqltest.cc128
-rw-r--r--client/sql_string.cc1
-rw-r--r--client/sql_string.h4
8 files changed, 430 insertions, 26 deletions
diff --git a/client/client_priv.h b/client/client_priv.h
index e99d34ffa97..53027465771 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -62,6 +62,9 @@ enum options_client
OPT_MYSQL_NUMBER_OF_QUERY,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_CREATE_SLAP_SCHEMA,
+ OPT_MYSQLDUMP_SLAVE_APPLY,
+ OPT_MYSQLDUMP_SLAVE_DATA,
+ OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT,
OPT_SLAP_CSV, OPT_SLAP_CREATE_STRING,
OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE, OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
@@ -78,6 +81,7 @@ enum options_client
OPT_SLAP_DETACH,
OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT_MODE, OPT_SERVER_ID,
OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT,
+ OPT_AUTO_VERTICAL_OUTPUT,
OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE,
OPT_WRITE_BINLOG, OPT_DUMP_DATE,
OPT_INIT_COMMAND,
diff --git a/client/mysql.cc b/client/mysql.cc
index 04cca1a2615..5e3260e486b 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -143,6 +143,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
tty_password= 0, opt_nobeep=0, opt_reconnect=1,
opt_secure_auth= 0,
default_pager_set= 0, opt_sigint_ignore= 0,
+ auto_vertical_output= 0,
show_warnings= 0, executing_query= 0, interrupted_query= 0,
ignore_spaces= 0;
static my_bool debug_info_flag, debug_check_flag;
@@ -185,6 +186,7 @@ static MEM_ROOT hash_mem_root;
static uint prompt_counter;
static char delimiter[16]= DEFAULT_DELIMITER;
static uint delimiter_length= 1;
+unsigned short terminal_width= 80;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
@@ -238,6 +240,8 @@ 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);
+static int get_result_width(MYSQL_RES *res);
+static int get_field_disp_length(MYSQL_FIELD * field);
/* A structure which contains information on the commands this program
can understand. */
@@ -1065,6 +1069,10 @@ static void mysql_end_timer(ulong start_time,char *buff);
static void nice_time(double sec,char *buff,bool part_second);
extern "C" sig_handler mysql_end(int sig);
extern "C" sig_handler handle_sigint(int sig);
+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
+static sig_handler window_resize(int sig);
+#endif
+
int main(int argc,char *argv[])
{
@@ -1148,8 +1156,8 @@ int main(int argc,char *argv[])
if (sql_connect(current_host,current_db,current_user,opt_password,
opt_silent))
{
- quick=1; // Avoid history
- status.exit_status=1;
+ quick= 1; // Avoid history
+ status.exit_status= 1;
mysql_end(-1);
}
if (!status.batch)
@@ -1161,6 +1169,13 @@ int main(int argc,char *argv[])
signal(SIGINT, handle_sigint); // Catch SIGINT to clean up
signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up
+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
+ /* Readline will call this if it installs a handler */
+ signal(SIGWINCH, window_resize);
+ /* call the SIGWINCH handler to get the default term width */
+ window_resize(0);
+#endif
+
put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.",
INFO_INFO);
sprintf((char*) glob_buffer.ptr(),
@@ -1333,6 +1348,16 @@ err:
}
+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
+sig_handler window_resize(int sig)
+{
+ struct winsize window_size;
+
+ if (ioctl(fileno(stdin), TIOCGWINSZ, &window_size) == 0)
+ terminal_width= window_size.ws_col;
+}
+#endif
+
static struct my_option my_long_options[] =
{
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
@@ -1350,6 +1375,9 @@ static struct my_option my_long_options[] =
{"no-auto-rehash", 'A',
"No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of mysql and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
+ "Automatically switch to vertical output mode if the result is wider than the terminal width.",
+ (uchar**) &auto_vertical_output, (uchar**) &auto_vertical_output, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"batch", 'B',
"Don't use history file. Disable interactive behavior. (Enables --silent)", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
@@ -3056,7 +3084,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
print_table_data_html(result);
else if (opt_xml)
print_table_data_xml(result);
- else if (vertical)
+ else if (vertical || (auto_vertical_output && (terminal_width < get_result_width(result))))
print_table_data_vertically(result);
else if (opt_silent && verbose <= 2 && !output_tables)
print_tab_data(result);
@@ -3387,6 +3415,65 @@ print_table_data(MYSQL_RES *result)
my_afree((uchar*) num_flag);
}
+/**
+ Return the length of a field after it would be rendered into text.
+
+ This doesn't know or care about multibyte characters. Assume we're
+ using such a charset. We can't know that all of the upcoming rows
+ for this column will have bytes that each render into some fraction
+ of a character. It's at least possible that a row has bytes that
+ all render into one character each, and so the maximum length is
+ still the number of bytes. (Assumption 1: This can't be better
+ because we can never know the number of characters that the DB is
+ going to send -- only the number of bytes. 2: Chars <= Bytes.)
+
+ @param field Pointer to a field to be inspected
+
+ @returns number of character positions to be used, at most
+*/
+static int get_field_disp_length(MYSQL_FIELD *field)
+{
+ uint length= column_names ? field->name_length : 0;
+
+ if (quick)
+ length= max(length, field->length);
+ else
+ length= max(length, field->max_length);
+
+ if (length < 4 && !IS_NOT_NULL(field->flags))
+ length= 4; /* Room for "NULL" */
+
+ return length;
+}
+
+/**
+ For a new result, return the max number of characters that any
+ upcoming row may return.
+
+ @param result Pointer to the result to judge
+
+ @returns The max number of characters in any row of this result
+*/
+static int get_result_width(MYSQL_RES *result)
+{
+ unsigned int len= 0;
+ MYSQL_FIELD *field;
+ MYSQL_FIELD_OFFSET offset;
+
+#ifndef DBUG_OFF
+ offset= mysql_field_tell(result);
+ DBUG_ASSERT(offset == 0);
+#else
+ offset= 0;
+#endif
+
+ while ((field= mysql_fetch_field(result)) != NULL)
+ len+= get_field_disp_length(field) + 3; /* plus bar, space, & final space */
+
+ (void) mysql_field_seek(result, offset);
+
+ return len + 1; /* plus final bar. */
+}
static void
tee_print_sized_data(const char *data, unsigned int data_length, unsigned int total_bytes_to_send, bool right_justified)
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index c8cbafe72d9..3484cf08713 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -901,23 +901,38 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
char buff[128],crypted_pw[64];
time_t start_time;
+ char *typed_password= NULL, *verified= NULL;
/* Do initialization the same way as we do in mysqld */
start_time=time((time_t*) 0);
randominit(&rand_st,(ulong) start_time,(ulong) start_time/2);
- if (argc < 2)
+ if (argc < 1)
{
my_printf_error(0, "Too few arguments to change password", error_flags);
return 1;
}
- if (argv[1][0])
+ else if (argc == 1)
+ {
+ /* prompt for password */
+ typed_password= get_tty_password("New password: ");
+ verified= get_tty_password("Confirm new password: ");
+ if (strcmp(typed_password, verified) != 0)
+ {
+ my_printf_error(0,"Passwords don't match",MYF(ME_BELL));
+ return -1;
+ }
+ }
+ else
+ typed_password= argv[1];
+
+ if (typed_password[0])
{
- char *pw= argv[1];
bool old= (find_type(argv[0], &command_typelib, 2) ==
ADMIN_OLD_PASSWORD);
#ifdef __WIN__
- uint pw_len= (uint) strlen(pw);
- if (pw_len > 1 && pw[0] == '\'' && pw[pw_len-1] == '\'')
+ size_t pw_len= strlen(typed_password);
+ if (pw_len > 1 && typed_password[0] == '\'' &&
+ typed_password[pw_len-1] == '\'')
printf("Warning: single quotes were not trimmed from the password by"
" your command\nline client, as you might have expected.\n");
#endif
@@ -955,9 +970,9 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
}
if (old)
- make_scrambled_password_323(crypted_pw, pw);
+ make_scrambled_password_323(crypted_pw, typed_password);
else
- make_scrambled_password(crypted_pw, pw);
+ make_scrambled_password(crypted_pw, typed_password);
}
else
crypted_pw[0]=0; /* No password */
@@ -992,6 +1007,12 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return -1;
}
}
+ /* free up memory from prompted password */
+ if (typed_password != argv[1])
+ {
+ my_free(typed_password,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(verified,MYF(MY_ALLOW_ZERO_PTR));
+ }
argc--; argv++;
break;
}
@@ -1083,8 +1104,8 @@ static void usage(void)
kill id,id,... Kill mysql threads");
#if MYSQL_VERSION_ID >= 32200
puts("\
- password new-password Change old password to new-password, MySQL 4.1 hashing.\n\
- old-password new-password Change old password to new-password in old format.\n");
+ password [new-password] Change old password to new-password in current format\n\
+ old-password [new-password] Change old password to new-password in old format");
#endif
puts("\
ping Check if mysqld is alive\n\
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 252ee500cf6..980cfd9b3ea 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -128,7 +128,7 @@ static struct my_option my_long_options[] =
"Faster than extended-check, but only finds 99.99 percent of all errors. Should be good enough for most cases.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"write-binlog", OPT_WRITE_BINLOG,
- "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Enabled by default; use --skip-write-binlog when commands should not be sent to replication slaves.",
+ "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Use --skip-write-binlog when commands should not be sent to replication slaves.",
(uchar**) &opt_write_binlog, (uchar**) &opt_write_binlog, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
{"optimize", 'o', "Optimize table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 54e7d68e191..4a714690687 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -98,6 +98,8 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
opt_complete_insert= 0, opt_drop_database= 0,
opt_replace_into= 0,
opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1,
+ opt_slave_apply= 0,
+ opt_include_master_host_port= 0,
opt_events= 0,
opt_alltspcs=0, opt_notspcs= 0;
static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
@@ -118,7 +120,10 @@ static my_bool server_supports_switching_charsets= TRUE;
static ulong opt_compatible_mode= 0;
#define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1
#define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2
+#define MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL 1
+#define MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL 2
static uint opt_mysql_port= 0, opt_master_data;
+static uint opt_slave_data;
static uint my_end_arg;
static char * opt_mysql_unix_port=0;
static int first_error=0;
@@ -206,6 +211,10 @@ static struct my_option my_long_options[] =
{"allow-keywords", OPT_KEYWORDS,
"Allow creation of column names that are keywords.", (uchar**) &opt_keywords,
(uchar**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"apply-slave-statements", OPT_MYSQLDUMP_SLAVE_APPLY,
+ "Adds 'STOP SLAVE' prior to 'CHANGE MASTER' and 'START SLAVE' to bottom of dump.",
+ (uchar**) &opt_slave_apply, (uchar**) &opt_slave_apply, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
#ifdef __NETWARE__
{"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -264,6 +273,19 @@ static struct my_option my_long_options[] =
{"disable-keys", 'K',
"'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (uchar**) &opt_disable_keys,
(uchar**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"dump-slave", OPT_MYSQLDUMP_SLAVE_DATA,
+ "This causes the binary log position and filename of the master to be "
+ "appended to the dumped data output. Setting the value to 1, will print"
+ "it as a CHANGE MASTER command in the dumped data output; 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 "
+ "- 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.",
+ (uchar**) &opt_slave_data, (uchar**) &opt_slave_data, 0,
+ GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL, 0, 0, 0},
{"events", 'E', "Dump events.",
(uchar**) &opt_events, (uchar**) &opt_events, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -317,6 +339,12 @@ static struct my_option my_long_options[] =
"use the directive multiple times, once for each table. Each table must "
"be specified with both database and table names, e.g. --ignore-table=database.table",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"include-master-host-port", OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT,
+ "Adds 'MASTER_HOST=<host>, MASTER_PORT=<port>' to 'CHANGE MASTER TO..' in dump produced with --dump-slave.",
+ (uchar**) &opt_include_master_host_port,
+ (uchar**) &opt_include_master_host_port,
+ 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
(uchar**) &opt_ignore, (uchar**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
@@ -402,7 +430,7 @@ static struct my_option my_long_options[] =
(uchar**) &opt_routines, (uchar**) &opt_routines, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"set-charset", OPT_SET_CHARSET,
- "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.",
+ "Add 'SET NAMES default_character_set' to the output.",
(uchar**) &opt_set_charset, (uchar**) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
0, 0, 0, 0, 0},
{"set-variable", 'O',
@@ -764,6 +792,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (!argument) /* work like in old versions */
opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL;
break;
+ case (int) OPT_MYSQLDUMP_SLAVE_DATA:
+ if (!argument) /* work like in old versions */
+ opt_slave_data= MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL;
+ break;
case (int) OPT_OPTIMIZE:
extended_insert= opt_drop= opt_lock= quick= create_options=
opt_disable_keys= lock_tables= opt_set_charset= 1;
@@ -897,6 +929,14 @@ static int get_options(int *argc, char ***argv)
return(EX_USAGE);
}
+ /* We don't delete master logs if slave data option */
+ if (opt_slave_data)
+ {
+ opt_lock_all_tables= !opt_single_transaction;
+ opt_master_data= 0;
+ opt_delete_master_logs= 0;
+ }
+
/* Ensure consistency of the set of binlog & locking options */
if (opt_delete_master_logs && !opt_master_data)
opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL;
@@ -907,7 +947,10 @@ static int get_options(int *argc, char ***argv)
return(EX_USAGE);
}
if (opt_master_data)
+ {
opt_lock_all_tables= !opt_single_transaction;
+ opt_slave_data= 0;
+ }
if (opt_single_transaction || opt_lock_all_tables)
lock_tables= 0;
if (enclosed && opt_enclosed)
@@ -4334,6 +4377,130 @@ static int do_show_master_status(MYSQL *mysql_con)
return 0;
}
+static int do_stop_slave_sql(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ /* We need to check if the slave sql is running in the first place */
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ return(1);
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[11])
+ {
+ /* if SLAVE SQL is not running, we don't stop it */
+ if (!strcmp(row[11],"No"))
+ {
+ mysql_free_result(slave);
+ /* Silently assume that they don't have the slave running */
+ return(0);
+ }
+ }
+ }
+ mysql_free_result(slave);
+
+ /* now, stop slave if running */
+ if (mysql_query_with_error_report(mysql_con, 0, "STOP SLAVE SQL_THREAD"))
+ return(1);
+
+ return(0);
+}
+
+static int add_stop_slave(void)
+{
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- stop slave statement to make a recovery dump)\n--\n\n");
+ fprintf(md_result_file, "STOP SLAVE;\n");
+ return(0);
+}
+
+static int add_slave_statements(void)
+{
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- start slave statement to make a recovery dump)\n--\n\n");
+ fprintf(md_result_file, "START SLAVE;\n");
+ return(0);
+}
+
+static int do_show_slave_status(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ const char *comment_prefix=
+ (opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ {
+ if (!ignore_errors)
+ {
+ /* SHOW SLAVE STATUS reports nothing and --force is not enabled */
+ my_printf_error(0, "Error: Slave not set up", MYF(0));
+ }
+ mysql_free_result(slave);
+ return 1;
+ }
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[9] && row[21])
+ {
+ /* SHOW MASTER STATUS reports file and position */
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- Position to start replication or point-in-time "
+ "recovery from (the master of this slave)\n--\n\n");
+
+ fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix);
+
+ if (opt_include_master_host_port)
+ {
+ if (row[1])
+ fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
+ if (row[3])
+ fprintf(md_result_file, "MASTER_PORT='%s', ", row[3]);
+ }
+ fprintf(md_result_file,
+ "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
+
+ check_io(md_result_file);
+ }
+ mysql_free_result(slave);
+ }
+ return 0;
+}
+
+static int do_start_slave_sql(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ /* We need to check if the slave sql is stopped in the first place */
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ return(1);
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[11])
+ {
+ /* if SLAVE SQL is not running, we don't start it */
+ if (!strcmp(row[11],"Yes"))
+ {
+ mysql_free_result(slave);
+ /* Silently assume that they don't have the slave running */
+ return(0);
+ }
+ }
+ }
+ mysql_free_result(slave);
+
+ /* now, start slave if stopped */
+ if (mysql_query_with_error_report(mysql_con, 0, "START SLAVE"))
+ {
+ my_printf_error(0, "Error: Unable to start slave", MYF(0));
+ return 1;
+ }
+ return(0);
+}
+
+
static int do_flush_tables_read_lock(MYSQL *mysql_con)
{
@@ -4996,6 +5163,9 @@ int main(int argc, char **argv)
if (!path)
write_header(md_result_file, *argv);
+ if (opt_slave_data && do_stop_slave_sql(mysql))
+ goto err;
+
if ((opt_lock_all_tables || opt_master_data) &&
do_flush_tables_read_lock(mysql))
goto err;
@@ -5014,8 +5184,13 @@ int main(int argc, char **argv)
goto err;
flush_logs= 0; /* not anymore; that would not be sensible */
}
+ /* Add 'STOP SLAVE to beginning of dump */
+ if (opt_slave_apply && add_stop_slave())
+ goto err;
if (opt_master_data && do_show_master_status(mysql))
goto err;
+ if (opt_slave_data && do_show_slave_status(mysql))
+ goto err;
if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */
goto err;
@@ -5043,6 +5218,14 @@ int main(int argc, char **argv)
dump_databases(argv);
}
+ /* if --dump-slave , start the slave sql thread */
+ if (opt_slave_data && do_start_slave_sql(mysql))
+ goto err;
+
+ /* add 'START SLAVE' to end of dump */
+ if (opt_slave_apply && add_slave_statements())
+ goto err;
+
/* ensure dumped data flushed */
if (md_result_file && fflush(md_result_file))
{
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 89330b0e31d..4d104704c56 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -75,7 +75,8 @@
enum {
OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
- OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
+ OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
+ OPT_RESULT_FORMAT_VERSION
};
static int record= 0, opt_sleep= -1;
@@ -88,6 +89,7 @@ const char *opt_logdir= "";
const char *opt_include= 0, *opt_charsets_dir;
static int opt_port= 0;
static int opt_max_connect_retries;
+static int opt_result_format_version;
static my_bool opt_compress= 0, silent= 0, verbose= 0;
static my_bool debug_info_flag= 0, debug_check_flag= 0;
static my_bool tty_password= 0;
@@ -284,11 +286,12 @@ enum enum_commands {
Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
Q_LIST_FILES, Q_LIST_FILES_WRITE_FILE, Q_LIST_FILES_APPEND_FILE,
Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER,
+ Q_RESULT_FORMAT_VERSION,
Q_MOVE_FILE, Q_SEND_EVAL,
-
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
- Q_COMMENT_WITH_COMMAND
+ Q_COMMENT_WITH_COMMAND,
+ Q_EMPTY_LINE
};
@@ -378,6 +381,7 @@ const char *command_names[]=
"list_files_append_file",
"send_shutdown",
"shutdown_server",
+ "result_format",
"move_file",
"send_eval",
@@ -2193,6 +2197,59 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
}
+static void
+set_result_format_version(ulong new_version)
+{
+ switch (new_version){
+ case 1:
+ /* The first format */
+ break;
+ case 2:
+ /* New format that also writes comments and empty lines
+ from test file to result */
+ break;
+ default:
+ die("Version format %lu has not yet been implemented", new_version);
+ break;
+ }
+ opt_result_format_version= new_version;
+}
+
+
+/*
+ Set the result format version to use when generating
+ the .result file
+*/
+
+static void
+do_result_format_version(struct st_command *command)
+{
+ long version;
+ static DYNAMIC_STRING ds_version;
+ const struct command_arg result_format_args[] = {
+ "version", ARG_STRING, TRUE, &ds_version, "Version to use",
+ };
+
+ DBUG_ENTER("do_result_format_version");
+
+ check_command_args(command, command->first_argument,
+ result_format_args,
+ sizeof(result_format_args)/sizeof(struct command_arg),
+ ',');
+
+ /* Convert version number to int */
+ if (!str2int(ds_version.str, 10, (long) 0, (long) INT_MAX, &version))
+ die("Invalid version number: '%s'", ds_version.str);
+
+ set_result_format_version(version);
+
+ dynstr_append(&ds_res, "result_format: ");
+ dynstr_append_mem(&ds_res, ds_version.str, ds_version.length);
+ dynstr_append(&ds_res, "\n");
+ dynstr_free(&ds_version);
+}
+
+
/*
Set variable from the result of a field in a query
@@ -5273,7 +5330,7 @@ my_bool end_of_query(int c)
int read_line(char *buf, int size)
{
- char c, UNINIT_VAR(last_quote);
+ char c, UNINIT_VAR(last_quote), last_char= 0;
char *p= buf, *buf_end= buf + size - 1;
int skip_char= 0;
enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
@@ -5371,14 +5428,24 @@ int read_line(char *buf, int size)
}
else if (my_isspace(charset_info, c))
{
- /* Skip all space at begining of line */
if (c == '\n')
{
+ if (last_char == '\n')
+ {
+ /* Two new lines in a row, return empty line */
+ DBUG_PRINT("info", ("Found two new lines in a row"));
+ *p++= c;
+ *p= 0;
+ DBUG_RETURN(0);
+ }
+
/* Query hasn't started yet */
start_lineno= cur_file->lineno;
DBUG_PRINT("info", ("Query hasn't started yet, start_lineno: %d",
start_lineno));
}
+
+ /* Skip all space at begining of line */
skip_char= 1;
}
else if (end_of_query(c))
@@ -5419,6 +5486,8 @@ int read_line(char *buf, int size)
}
+ last_char= c;
+
if (!skip_char)
{
/* Could be a multibyte character */
@@ -5628,9 +5697,10 @@ int read_command(struct st_command** command_ptr)
DBUG_RETURN(1);
}
- convert_to_format_v1(read_command_buf);
+ if (opt_result_format_version == 1)
+ convert_to_format_v1(read_command_buf);
- DBUG_PRINT("info", ("query: %s", read_command_buf));
+ DBUG_PRINT("info", ("query: '%s'", read_command_buf));
if (*p == '#')
{
command->type= Q_COMMENT;
@@ -5640,6 +5710,10 @@ int read_command(struct st_command** command_ptr)
command->type= Q_COMMENT_WITH_COMMAND;
p+= 2; /* Skip past -- */
}
+ else if (*p == '\n')
+ {
+ command->type= Q_EMPTY_LINE;
+ }
/* Skip leading spaces */
while (*p && my_isspace(charset_info, *p))
@@ -5734,6 +5808,11 @@ static struct my_option my_long_options[] =
{"result-file", 'R', "Read/Store result from/in this file.",
(uchar**) &result_file_name, (uchar**) &result_file_name, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"result-format-version", OPT_RESULT_FORMAT_VERSION,
+ "Version of the result file format to use",
+ (uchar**) &opt_result_format_version,
+ (uchar**) &opt_result_format_version, 0,
+ GET_INT, REQUIRED_ARG, 1, 1, 2, 0, 0, 0},
{"server-arg", 'A', "Send option value to embedded server as a parameter.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-file", 'F', "Read embedded server arguments from file.",
@@ -5943,6 +6022,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
sf_malloc_quick=1;
#endif
break;
+ case OPT_RESULT_FORMAT_VERSION:
+ set_result_format_version(opt_result_format_version);
+ break;
case 'V':
print_version();
exit(0);
@@ -7818,6 +7900,7 @@ int main(int argc, char **argv)
case Q_MOVE_FILE: do_move_file(command); break;
case Q_CHMOD_FILE: do_chmod_file(command); break;
case Q_PERL: do_perl(command); break;
+ case Q_RESULT_FORMAT_VERSION: do_result_format_version(command); break;
case Q_DELIMITER:
do_delimiter(command);
break;
@@ -7935,9 +8018,38 @@ int main(int argc, char **argv)
do_sync_with_master2(command, 0);
break;
}
- case Q_COMMENT: /* Ignore row */
+ case Q_COMMENT:
+ {
command->last_argument= command->end;
+
+ /* Don't output comments in v1 */
+ if (opt_result_format_version == 1)
+ break;
+
+ /* Don't output comments if query logging is off */
+ if (disable_query_log)
+ break;
+
+ /* Write comment's with two starting #'s to result file */
+ const char* p= command->query;
+ if (p && *p == '#' && *(p+1) == '#')
+ {
+ dynstr_append_mem(&ds_res, command->query, command->query_len);
+ dynstr_append(&ds_res, "\n");
+ }
break;
+ }
+ case Q_EMPTY_LINE:
+ /* Don't output newline in v1 */
+ if (opt_result_format_version == 1)
+ break;
+
+ /* Don't output newline if query logging is off */
+ if (disable_query_log)
+ break;
+
+ dynstr_append(&ds_res, "\n");
+ break;
case Q_PING:
handle_command_error(command, mysql_ping(&cur_con->mysql));
break;
diff --git a/client/sql_string.cc b/client/sql_string.cc
index dc6147b563f..46fd1cb0012 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc
@@ -23,6 +23,7 @@
#include <my_sys.h>
#include <m_string.h>
#include <m_ctype.h>
+#include <mysql_com.h>
#ifdef HAVE_FCONVERT
#include <floatingpoint.h>
#endif
diff --git a/client/sql_string.h b/client/sql_string.h
index 0e6d6da4476..1a3ac5d33c5 100644
--- a/client/sql_string.h
+++ b/client/sql_string.h
@@ -22,10 +22,6 @@
#pragma interface /* gcc class implementation */
#endif
-#ifndef NOT_FIXED_DEC
-#define NOT_FIXED_DEC 31
-#endif
-
class String;
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);