summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/CMakeLists.txt8
-rw-r--r--client/client_priv.h1
-rw-r--r--client/completion_hash.cc2
-rw-r--r--client/mysql.cc152
-rw-r--r--client/mysql_plugin.c15
-rw-r--r--client/mysql_upgrade.c236
-rw-r--r--client/mysqladmin.cc255
-rw-r--r--client/mysqlbinlog.cc722
-rw-r--r--client/mysqlcheck.c117
-rw-r--r--client/mysqldump.c806
-rw-r--r--client/mysqlimport.c26
-rw-r--r--client/mysqlshow.c26
-rw-r--r--client/mysqlslap.c54
-rw-r--r--client/mysqltest.cc817
-rw-r--r--client/readline.cc3
-rw-r--r--client/sql_string.cc.dontuse2
16 files changed, 2246 insertions, 996 deletions
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 56e891ea284..40df176c6e6 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -16,16 +16,20 @@
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/include
+ ${PCRE_INCLUDES}
+ ${CMAKE_SOURCE_DIR}/mysys_ssl
${ZLIB_INCLUDE_DIR}
${SSL_INCLUDE_DIRS}
${CMAKE_SOURCE_DIR}/libmysql
- ${CMAKE_SOURCE_DIR}/regex
${CMAKE_SOURCE_DIR}/sql
${CMAKE_SOURCE_DIR}/strings
${MY_READLINE_INCLUDE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
+## We will need libeay32.dll and ssleay32.dll when running client executables.
+COPY_OPENSSL_DLLS(copy_openssl_client)
+
ADD_DEFINITIONS(${SSL_DEFINES})
MYSQL_ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc
${CMAKE_SOURCE_DIR}/sql/sql_string.cc)
@@ -37,7 +41,7 @@ ENDIF(UNIX)
MYSQL_ADD_EXECUTABLE(mysqltest mysqltest.cc COMPONENT Test)
SET_SOURCE_FILES_PROPERTIES(mysqltest.cc PROPERTIES COMPILE_FLAGS "-DTHREADS")
-TARGET_LINK_LIBRARIES(mysqltest mysqlclient regex)
+TARGET_LINK_LIBRARIES(mysqltest mysqlclient pcreposix pcre)
SET_TARGET_PROPERTIES(mysqltest PROPERTIES ENABLE_EXPORTS TRUE)
diff --git a/client/client_priv.h b/client/client_priv.h
index b5c647fbd0c..1419d9dfad9 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -92,6 +92,7 @@ enum options_client
OPT_REWRITE_DB,
OPT_REPORT_PROGRESS,
OPT_SKIP_ANNOTATE_ROWS_EVENTS,
+ OPT_SSL_CRL, OPT_SSL_CRLPATH,
OPT_MAX_CLIENT_OPTION /* should be always the last */
};
diff --git a/client/completion_hash.cc b/client/completion_hash.cc
index 9ffb2082c06..c170b69de2d 100644
--- a/client/completion_hash.cc
+++ b/client/completion_hash.cc
@@ -49,7 +49,7 @@ int completion_hash_init(HashTable *ht, uint nSize)
ht->initialized = 0;
return FAILURE;
}
- init_alloc_root(&ht->mem_root, 8192, 0);
+ init_alloc_root(&ht->mem_root, 8192, 0, MYF(0));
ht->pHashFunction = hashpjw;
ht->nTableSize = nSize;
ht->initialized = 1;
diff --git a/client/mysql.cc b/client/mysql.cc
index 50d45696a5c..f938c8f00ff 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -597,8 +597,6 @@ static COMMANDS commands[] = {
{ "NAMES", 0, 0, 0, ""},
{ "NATIONAL", 0, 0, 0, ""},
{ "NATURAL", 0, 0, 0, ""},
- { "NDB", 0, 0, 0, ""},
- { "NDBCLUSTER", 0, 0, 0, ""},
{ "NCHAR", 0, 0, 0, ""},
{ "NEW", 0, 0, 0, ""},
{ "NEXT", 0, 0, 0, ""},
@@ -613,7 +611,6 @@ static COMMANDS commands[] = {
{ "OLD_PASSWORD", 0, 0, 0, ""},
{ "ON", 0, 0, 0, ""},
{ "ONE", 0, 0, 0, ""},
- { "ONE_SHOT", 0, 0, 0, ""},
{ "OPEN", 0, 0, 0, ""},
{ "OPTIMIZE", 0, 0, 0, ""},
{ "OPTION", 0, 0, 0, ""},
@@ -923,6 +920,7 @@ static COMMANDS commands[] = {
{ "MAKE_SET", 0, 0, 0, ""},
{ "MAKEDATE", 0, 0, 0, ""},
{ "MAKETIME", 0, 0, 0, ""},
+ { "MASTER_GTID_WAIT", 0, 0, 0, ""},
{ "MASTER_POS_WAIT", 0, 0, 0, ""},
{ "MAX", 0, 0, 0, ""},
{ "MBRCONTAINS", 0, 0, 0, ""},
@@ -1096,7 +1094,7 @@ inline bool is_delimiter_command(char *name, ulong len)
only name(first DELIMITER_NAME_LEN bytes) is checked.
*/
return (len >= DELIMITER_NAME_LEN &&
- !my_strnncoll(charset_info, (uchar*) name, DELIMITER_NAME_LEN,
+ !my_strnncoll(&my_charset_latin1, (uchar*) name, DELIMITER_NAME_LEN,
(uchar *) DELIMITER_NAME, DELIMITER_NAME_LEN));
}
@@ -1142,6 +1140,7 @@ int main(int argc,char *argv[])
current_prompt = my_strdup(default_prompt,MYF(MY_WME));
prompt_counter=0;
aborted= 0;
+ sf_leaking_memory= 1; /* no memory leak reports yet */
outfile[0]=0; // no (default) outfile
strmov(pager, "stdout"); // the default, if --pager wasn't given
@@ -1176,18 +1175,11 @@ int main(int argc,char *argv[])
close(stdout_fileno_copy); /* Clean up dup(). */
}
- if (load_defaults("my",load_default_groups,&argc,&argv))
- {
- my_end(0);
- exit(1);
- }
+ load_defaults_or_exit("my", load_default_groups, &argc, &argv);
defaults_argv=argv;
- if (get_options(argc, (char **) argv))
- {
- free_defaults(defaults_argv);
- my_end(0);
- exit(1);
- }
+ if ((status.exit_status= get_options(argc, (char **) argv)))
+ mysql_end(-1);
+
if (status.batch && !status.line_buff &&
!(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin)))
{
@@ -1205,9 +1197,10 @@ int main(int argc,char *argv[])
my_end(0);
exit(1);
}
+ sf_leaking_memory= 0;
glob_buffer.realloc(512);
completion_hash_init(&ht, 128);
- init_alloc_root(&hash_mem_root, 16384, 0);
+ init_alloc_root(&hash_mem_root, 16384, 0, MYF(0));
bzero((char*) &mysql, sizeof(mysql));
if (sql_connect(current_host,current_db,current_user,opt_password,
opt_silent))
@@ -1232,15 +1225,17 @@ int main(int argc,char *argv[])
window_resize(0);
#endif
- put_info("Welcome to the MariaDB monitor. Commands end with ; or \\g.",
- INFO_INFO);
- my_snprintf((char*) glob_buffer.ptr(), glob_buffer.alloced_length(),
- "Your %s connection id is %lu\nServer version: %s\n",
- mysql_get_server_name(&mysql),
- mysql_thread_id(&mysql), server_version_string(&mysql));
- put_info((char*) glob_buffer.ptr(),INFO_INFO);
-
- put_info(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"), INFO_INFO);
+ if (!status.batch)
+ {
+ put_info("Welcome to the MariaDB monitor. Commands end with ; or \\g.",
+ INFO_INFO);
+ my_snprintf((char*) glob_buffer.ptr(), glob_buffer.alloced_length(),
+ "Your %s connection id is %lu\nServer version: %s\n",
+ mysql_get_server_name(&mysql),
+ mysql_thread_id(&mysql), server_version_string(&mysql));
+ put_info((char*) glob_buffer.ptr(),INFO_INFO);
+ put_info(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"), INFO_INFO);
+ }
#ifdef HAVE_READLINE
initialize_readline((char*) my_progname);
@@ -1355,6 +1350,44 @@ sig_handler mysql_end(int sig)
exit(status.exit_status);
}
+/*
+ set connection-specific options and call mysql_real_connect
+*/
+static bool do_connect(MYSQL *mysql, const char *host, const char *user,
+ const char *password, const char *database, ulong flags)
+{
+ if (opt_secure_auth)
+ mysql_options(mysql, MYSQL_SECURE_AUTH, (char *) &opt_secure_auth);
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
+ if (opt_use_ssl)
+ {
+ mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
+ opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
+ }
+ mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ (char*)&opt_ssl_verify_server_cert);
+#endif
+ if (opt_protocol)
+ mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+#ifdef HAVE_SMEM
+ if (shared_memory_base_name)
+ mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
+#endif
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
+ mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
+ "program_name", "mysql");
+ return mysql_real_connect(mysql, host, user, password, database,
+ opt_mysql_port, opt_mysql_unix_port, flags);
+}
+
/*
This function handles sigint calls
@@ -1376,8 +1409,7 @@ sig_handler handle_sigint(int sig)
}
kill_mysql= mysql_init(kill_mysql);
- if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password,
- "", opt_mysql_port, opt_mysql_unix_port,0))
+ if (!do_connect(kill_mysql,current_host, current_user, opt_password, "", 0))
{
tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n");
goto err;
@@ -1761,8 +1793,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case OPT_MYSQL_PROTOCOL:
#ifndef EMBEDDED_LIBRARY
- opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
- opt->name);
+ if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
+ opt->name)) <= 0)
+ exit(1);
#endif
break;
case OPT_SERVER_ARG:
@@ -1892,7 +1925,7 @@ static int get_options(int argc, char **argv)
opt_net_buffer_length= *mysql_params->p_net_buffer_length;
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
- exit(ho_error);
+ return(ho_error);
*mysql_params->p_max_allowed_packet= opt_max_allowed_packet;
*mysql_params->p_net_buffer_length= opt_net_buffer_length;
@@ -3030,7 +3063,6 @@ static int com_server_help(String *buffer __attribute__((unused)),
{
unsigned int num_fields= mysql_num_fields(result);
my_ulonglong num_rows= mysql_num_rows(result);
- mysql_fetch_fields(result);
if (num_fields==3 && num_rows==1)
{
if (!(cur= mysql_fetch_row(result)))
@@ -3052,9 +3084,7 @@ static int com_server_help(String *buffer __attribute__((unused)),
init_pager();
char last_char= 0;
- int num_name= 0, num_cat= 0;
- LINT_INIT(num_name);
- LINT_INIT(num_cat);
+ int UNINIT_VAR(num_name), UNINIT_VAR(num_cat);
if (num_fields == 2)
{
@@ -3191,7 +3221,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
}
/* Remove garbage for nicer messages */
- LINT_INIT(buff[0]);
+ LINT_INIT_STRUCT(buff[0]);
remove_cntrl(*buffer);
if (buffer->is_empty())
@@ -3335,7 +3365,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
end:
- /* Show warnings if any or error occured */
+ /* Show warnings if any or error occurred */
if (show_warnings == 1 && (warnings >= 1 || error))
print_warnings();
@@ -3562,9 +3592,9 @@ print_table_data(MYSQL_RES *result)
{
uint length= column_names ? field->name_length : 0;
if (quick)
- length=max(length,field->length);
+ length= MY_MAX(length,field->length);
else
- length=max(length,field->max_length);
+ length= MY_MAX(length,field->max_length);
if (length < 4 && !IS_NOT_NULL(field->flags))
length=4; // Room for "NULL"
if (opt_binhex && is_binary_field(field))
@@ -3587,8 +3617,8 @@ print_table_data(MYSQL_RES *result)
field->name,
field->name + name_length);
uint display_length= field->max_length + name_length - numcells;
- tee_fprintf(PAGER, " %-*s |",(int) min(display_length,
- MAX_COLUMN_LENGTH),
+ tee_fprintf(PAGER, " %-*s |",(int) MY_MIN(display_length,
+ MAX_COLUMN_LENGTH),
field->name);
}
(void) tee_fputs("\n", PAGER);
@@ -3678,9 +3708,9 @@ static int get_field_disp_length(MYSQL_FIELD *field)
uint length= column_names ? field->name_length : 0;
if (quick)
- length= max(length, field->length);
+ length= MY_MAX(length, field->length);
else
- length= max(length, field->max_length);
+ length= MY_MAX(length, field->max_length);
if (length < 4 && !IS_NOT_NULL(field->flags))
length= 4; /* Room for "NULL" */
@@ -3696,6 +3726,7 @@ static int get_field_disp_length(MYSQL_FIELD *field)
@returns The max number of characters in any row of this result
*/
+
static int get_result_width(MYSQL_RES *result)
{
unsigned int len= 0;
@@ -4656,23 +4687,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
}
if (opt_compress)
mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
- if (opt_secure_auth)
- mysql_options(&mysql, MYSQL_SECURE_AUTH, (char *) &opt_secure_auth);
if (using_opt_local_infile)
mysql_options(&mysql,MYSQL_OPT_LOCAL_INFILE, (char*) &opt_local_infile);
-#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
- if (opt_use_ssl)
- mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
- opt_ssl_capath, opt_ssl_cipher);
- mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
- (char*)&opt_ssl_verify_server_cert);
-#endif
- if (opt_protocol)
- mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
-#ifdef HAVE_SMEM
- if (shared_memory_base_name)
- mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
-#endif
if (safe_updates)
{
char init_command[100];
@@ -4684,15 +4700,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
- if (opt_plugin_dir && *opt_plugin_dir)
- mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
-
- if (opt_default_auth && *opt_default_auth)
- mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
-
- if (!mysql_real_connect(&mysql, host, user, password,
- database, opt_mysql_port, opt_mysql_unix_port,
- connect_flag | CLIENT_MULTI_STATEMENTS))
+ if (!do_connect(&mysql, host, user, password, database,
+ connect_flag | CLIENT_MULTI_STATEMENTS))
{
if (!silent ||
(mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&
@@ -4769,8 +4778,7 @@ com_status(String *buffer __attribute__((unused)),
const char *status_str;
char buff[40];
ulonglong id;
- MYSQL_RES *result;
- LINT_INIT(result);
+ MYSQL_RES *UNINIT_VAR(result);
if (mysql_real_query_for_lazy(
C_STRING_WITH_LEN("select DATABASE(), USER() limit 1")))
@@ -4856,10 +4864,11 @@ com_status(String *buffer __attribute__((unused)),
tee_fprintf(stdout, "Protocol:\t\tCompressed\n");
#endif
- if ((status_str= mysql_stat(&mysql)) && !mysql_error(&mysql)[0])
+ const char *pos;
+ if ((status_str= mysql_stat(&mysql)) && !mysql_error(&mysql)[0] &&
+ (pos= strchr(status_str,' ')))
{
ulong sec;
- const char *pos= strchr(status_str,' ');
/* print label */
tee_fprintf(stdout, "%.*s\t\t\t", (int) (pos-status_str), status_str);
if ((status_str= str2int(pos,10,0,LONG_MAX,(long*) &sec)))
@@ -5330,8 +5339,7 @@ static void init_username()
my_free(full_username);
my_free(part_username);
- MYSQL_RES *result;
- LINT_INIT(result);
+ MYSQL_RES *UNINIT_VAR(result);
if (!mysql_query(&mysql,"select USER()") &&
(result=mysql_use_result(&mysql)))
{
diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c
index bc9969c9b66..c353fb039d6 100644
--- a/client/mysql_plugin.c
+++ b/client/mysql_plugin.c
@@ -15,14 +15,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <my_global.h>
#include <m_string.h>
#include <mysql.h>
#include <my_getopt.h>
#include <my_dir.h>
-#include <my_global.h>
-#include <stdio.h>
-#include <string.h>
-
#define SHOW_VERSION "1.0.0"
#define PRINT_VERSION do { printf("%s Ver %s Distrib %s\n", \
@@ -324,7 +321,7 @@ static int get_default_values()
int ret= 0;
FILE *file= 0;
- bzero(tool_path, FN_REFLEN);
+ memset(tool_path, 0, FN_REFLEN);
if ((error= find_tool("my_print_defaults" FN_EXEEXT, tool_path)))
goto exit;
else
@@ -337,9 +334,9 @@ static int get_default_values()
char *format_str= 0;
if (has_spaces(tool_path) || has_spaces(defaults_file))
- format_str = "\"%s mysqld > %s\"";
+ format_str = "\"%s --mysqld > %s\"";
else
- format_str = "%s mysqld > %s";
+ format_str = "%s --mysqld > %s";
snprintf(defaults_cmd, sizeof(defaults_cmd), format_str,
add_quotes(tool_path), add_quotes(defaults_file));
@@ -350,7 +347,7 @@ static int get_default_values()
}
#else
snprintf(defaults_cmd, sizeof(defaults_cmd),
- "%s mysqld > %s", tool_path, defaults_file);
+ "%s --mysqld > %s", tool_path, defaults_file);
#endif
/* Execute the command */
@@ -1005,7 +1002,7 @@ found:
static int find_plugin(char *tp_path)
{
- /* Check for existance of plugin */
+ /* Check for existence of plugin */
fn_format(tp_path, plugin_data.so_name, opt_plugin_dir, "", MYF(0));
if (!file_exists(tp_path))
{
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 836f2c1686b..5eb495774ce 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>
@@ -36,8 +36,8 @@
# endif
#endif
-static int phase = 1;
-static int phases_total = 4;
+static int phase = 0;
+static const int phases_total = 7;
static char mysql_path[FN_REFLEN];
static char mysqlcheck_path[FN_REFLEN];
@@ -47,6 +47,8 @@ static my_bool opt_not_used, opt_silent;
static uint my_end_arg= 0;
static char *opt_user= (char*)"root";
+static my_bool upgrade_from_mysql;
+
static DYNAMIC_STRING ds_args;
static DYNAMIC_STRING conn_args;
@@ -67,6 +69,8 @@ static char **defaults_argv;
static my_bool not_used; /* Can't use GET_BOOL without a value pointer */
+char upgrade_from_version[sizeof("10.20.456-MariaDB")+1];
+
static my_bool opt_write_binlog;
#define OPT_SILENT OPT_MAX_CLIENT_OPTION
@@ -145,25 +149,25 @@ 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},
#define USER_OPT (array_elements(my_long_options) - 6)
{"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.",
+ {"write-binlog", OPT_WRITE_BINLOG, "All commands including those "
+ "issued by mysqlcheck are written to the binary log.",
&opt_write_binlog, &opt_write_binlog, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
@@ -381,6 +385,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);
@@ -531,7 +538,21 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
int ret;
File fd;
char query_file_path[FN_REFLEN];
+#ifdef WITH_WSREP
+ /*
+ Strictly speaking, WITH_WSREP on the client only means that the
+ client was compiled with WSREP, it doesn't mean the server was,
+ so the server might not have WSREP_ON variable.
+
+ But mysql_upgrade is tightly bound to a specific server version
+ anyway - it was mysql_fix_privilege_tables_sql script embedded
+ into its binary - so even if it won't assume anything about server
+ wsrep-ness, it won't be any less server-dependent.
+ */
+ const uchar sql_log_bin[]= "SET SQL_LOG_BIN=0, WSREP_ON=OFF;";
+#else
const uchar sql_log_bin[]= "SET SQL_LOG_BIN=0;";
+#endif /* WITH_WSREP */
DBUG_ENTER("run_query");
DBUG_PRINT("enter", ("query: %s", query));
@@ -605,7 +626,7 @@ static int extract_variable_from_show(DYNAMIC_STRING* ds, char* value)
if ((value_end= strchr(value_start, '\n')) == NULL)
return 1; /* Unexpected result */
- len= (size_t) min(FN_REFLEN, value_end-value_start);
+ len= (size_t) MY_MIN(FN_REFLEN, value_end-value_start);
strncpy(value, value_start, len);
value[len]= '\0';
return 0;
@@ -639,7 +660,7 @@ static int get_upgrade_info_file_name(char* name)
/*
Read the content of mysql_upgrade_info file and
compare the version number form file against
- version number wich mysql_upgrade was compiled for
+ version number which mysql_upgrade was compiled for
NOTE
This is an optimization to avoid running mysql_upgrade
@@ -656,7 +677,6 @@ static int upgrade_already_done(void)
{
FILE *in;
char upgrade_info_file[FN_REFLEN]= {0};
- char buf[sizeof(MYSQL_SERVER_VERSION)+1];
if (get_upgrade_info_file_name(upgrade_info_file))
return 0; /* Could not get filename => not sure */
@@ -664,15 +684,15 @@ static int upgrade_already_done(void)
if (!(in= my_fopen(upgrade_info_file, O_RDONLY, MYF(0))))
return 0; /* Could not open file => not sure */
- bzero(buf, sizeof(buf));
- if (!fgets(buf, sizeof(buf), in))
+ bzero(upgrade_from_version, sizeof(upgrade_from_version));
+ if (!fgets(upgrade_from_version, sizeof(upgrade_from_version), in))
{
/* Ignore, will be detected by strncmp() below */
}
my_fclose(in, MYF(0));
- return (strncmp(buf, MYSQL_SERVER_VERSION,
+ return (strncmp(upgrade_from_version, MYSQL_SERVER_VERSION,
sizeof(MYSQL_SERVER_VERSION)-1)==0);
}
@@ -737,32 +757,36 @@ static void print_conn_args(const char *tool_name)
verbose("Running '%s with default connection arguments", tool_name);
}
-
/*
- Check and upgrade(if neccessary) all tables
+ Check and upgrade(if necessary) all tables
in the server using "mysqlcheck --check-upgrade .."
*/
-static int run_mysqlcheck_upgrade(void)
+static int run_mysqlcheck_upgrade(my_bool mysql_db_only)
{
+ const char *what= mysql_db_only ? "mysql database" : "tables";
+ const char *arg1= mysql_db_only ? "--databases" : "--all-databases";
+ const char *arg2= mysql_db_only ? "mysql" : "--skip-database=mysql";
int retch;
- if (opt_systables_only)
+ if (opt_systables_only && !mysql_db_only)
{
- verbose("Phase %d/%d: Checking and upgrading tables... Skipped",
- phase++, phases_total);
+ verbose("Phase %d/%d: Checking and upgrading %s... Skipped",
+ ++phase, phases_total, what);
return 0;
}
- verbose("Phase %d/%d: Checking and upgrading tables", phase++, phases_total);
+ verbose("Phase %d/%d: Checking and upgrading %s", ++phase, phases_total, what);
print_conn_args("mysqlcheck");
retch= run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
defaults_file,
"--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);
return retch;
@@ -793,18 +817,23 @@ static my_bool is_mysql()
static int run_mysqlcheck_views(void)
{
const char *upgrade_views="--process-views=YES";
- if (is_mysql())
+ if (upgrade_from_mysql)
{
+ /*
+ this has to ignore opt_systables_only, because upgrade_from_mysql
+ is determined by analyzing systables. if we honor opt_systables_only
+ here, views won't be fixed by subsequent mysql_upgrade runs
+ */
upgrade_views="--process-views=UPGRADE_FROM_MYSQL";
- verbose("Phase %d/%d: Fixing views from mysql", phase++, phases_total);
+ verbose("Phase %d/%d: Fixing views from mysql", ++phase, phases_total);
}
else if (opt_systables_only)
{
- verbose("Phase %d/%d: Fixing views... Skipped", phase++, phases_total);
+ verbose("Phase %d/%d: Fixing views... Skipped", ++phase, phases_total);
return 0;
}
else
- verbose("Phase %d/%d: Fixing views", phase++, phases_total);
+ verbose("Phase %d/%d: Fixing views", ++phase, phases_total);
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
@@ -825,11 +854,11 @@ static int run_mysqlcheck_fixnames(void)
if (opt_systables_only)
{
verbose("Phase %d/%d: Fixing table and database names ... Skipped",
- phase++, phases_total);
+ ++phase, phases_total);
return 0;
}
verbose("Phase %d/%d: Fixing table and database names",
- phase++, phases_total);
+ ++phase, phases_total);
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
@@ -837,7 +866,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",
@@ -850,6 +881,7 @@ static const char *expected_errors[]=
"ERROR 1060", /* Duplicate column name */
"ERROR 1061", /* Duplicate key name */
"ERROR 1054", /* Unknown column */
+ "ERROR 1290", /* RR_OPTION_PREVENTS_STATEMENT */
0
};
@@ -893,6 +925,80 @@ static void print_line(char* line)
fputc('\n', stderr);
}
+static my_bool from_before_10_1()
+{
+ my_bool ret= TRUE;
+ DYNAMIC_STRING ds_events_struct;
+
+ if (upgrade_from_version[0])
+ {
+ return upgrade_from_version[1] == '.' ||
+ strncmp(upgrade_from_version, "10.1.", 5) < 0;
+ }
+
+ if (init_dynamic_string(&ds_events_struct, NULL, 2048, 2048))
+ die("Out of memory");
+
+ if (run_query("show create table mysql.user", &ds_events_struct, FALSE) ||
+ strstr(ds_events_struct.str, "default_role") != NULL)
+ ret= FALSE;
+ else
+ verbose("Upgrading from a version before MariaDB-10.1");
+
+ dynstr_free(&ds_events_struct);
+ return ret;
+}
+
+
+/*
+ Check for entries with "Unknown storage engine" in I_S.TABLES,
+ try to load plugins for these tables if available (MDEV-11942)
+*/
+static int install_used_engines(void)
+{
+ char buf[512];
+ DYNAMIC_STRING ds_result;
+ const char *query = "SELECT DISTINCT LOWER(engine) FROM information_schema.tables"
+ " WHERE table_comment LIKE 'Unknown storage engine%'";
+
+ if (opt_systables_only || !from_before_10_1())
+ {
+ verbose("Phase %d/%d: Installing used storage engines... Skipped", ++phase, phases_total);
+ return 0;
+ }
+ verbose("Phase %d/%d: Installing used storage engines", ++phase, phases_total);
+
+ if (init_dynamic_string(&ds_result, "", 512, 512))
+ die("Out of memory");
+
+ verbose("Checking for tables with unknown storage engine");
+
+ run_query(query, &ds_result, TRUE);
+
+ if (ds_result.length)
+ {
+ char *line= ds_result.str, *next=get_line(line);
+ do
+ {
+ if (next[-1] == '\n')
+ next[-1]=0;
+
+ verbose("installing plugin for '%s' storage engine", line);
+
+ // we simply assume soname=ha_enginename
+ strxnmov(buf, sizeof(buf)-1, "install soname 'ha_", line, "'", NULL);
+
+
+ if (run_query(buf, NULL, TRUE))
+ fprintf(stderr, "... can't %s\n", buf);
+ line=next;
+ next=get_line(line);
+ } while (*line);
+ }
+ dynstr_free(&ds_result);
+ return 0;
+}
+
/*
Update all system tables in MySQL Server to current
@@ -903,15 +1009,35 @@ static void print_line(char* line)
static int run_sql_fix_privilege_tables(void)
{
int found_real_errors= 0;
+ const char **query_ptr;
+ DYNAMIC_STRING ds_script;
DYNAMIC_STRING ds_result;
DBUG_ENTER("run_sql_fix_privilege_tables");
+ if (init_dynamic_string(&ds_script, "", 65536, 1024))
+ die("Out of memory");
+
if (init_dynamic_string(&ds_result, "", 512, 512))
die("Out of memory");
verbose("Phase %d/%d: Running 'mysql_fix_privilege_tables'",
- phase++, phases_total);
- run_query(mysql_fix_privilege_tables,
+ ++phase, phases_total);
+
+ /*
+ Individual queries can not be executed independently by invoking
+ a forked mysql client, because the script uses session variables
+ and prepared statements.
+ */
+ for ( query_ptr= &mysql_fix_privilege_tables[0];
+ *query_ptr != NULL;
+ query_ptr++
+ )
+ {
+ if (strcasecmp(*query_ptr, "flush privileges;\n"))
+ dynstr_append(&ds_script, *query_ptr);
+ }
+
+ run_query(ds_script.str,
&ds_result, /* Collect result */
TRUE);
@@ -939,6 +1065,7 @@ static int run_sql_fix_privilege_tables(void)
}
dynstr_free(&ds_result);
+ dynstr_free(&ds_script);
DBUG_RETURN(found_real_errors);
}
@@ -1003,25 +1130,23 @@ static int check_version_match(void)
int main(int argc, char **argv)
{
- char self_name[FN_REFLEN];
+ char self_name[FN_REFLEN + 1];
MY_INIT(argv[0]);
+ load_defaults_or_exit("my", load_default_groups, &argc, &argv);
+ defaults_argv= argv; /* Must be freed by 'free_defaults' */
#if __WIN__
if (GetModuleFileName(NULL, self_name, FN_REFLEN) == 0)
#endif
{
- strncpy(self_name, argv[0], FN_REFLEN);
+ strmake_buf(self_name, argv[0]);
}
if (init_dynamic_string(&ds_args, "", 512, 256) ||
init_dynamic_string(&conn_args, "", 512, 256))
die("Out of memory");
- if (load_defaults("my", load_default_groups, &argc, &argv))
- die(NULL);
- defaults_argv= argv; /* Must be freed by 'free_defaults' */
-
if (handle_options(&argc, &argv, my_long_options, get_one_option))
die(NULL);
if (debug_info_flag)
@@ -1044,6 +1169,8 @@ int main(int argc, char **argv)
{
int fd= create_temp_file(cnf_file_path, opt_tmpdir[0] ? opt_tmpdir : NULL,
"mysql_upgrade-", O_CREAT | O_WRONLY, MYF(MY_FAE));
+ if (fd < 0)
+ die(NULL);
my_write(fd, USTRING_WITH_LEN( "[client]\n"), MYF(MY_FAE));
my_write(fd, (uchar*)ds_args.str, ds_args.length, MYF(MY_FAE));
my_close(fd, MYF(0));
@@ -1073,23 +1200,30 @@ int main(int argc, char **argv)
if (opt_version_check && check_version_match())
die("Upgrade failed");
+ upgrade_from_mysql= is_mysql();
+
/*
Run "mysqlcheck" and "mysql_fix_privilege_tables.sql"
*/
- if (run_mysqlcheck_views() || 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
- */
+ if (run_mysqlcheck_upgrade(TRUE) ||
+ install_used_engines() ||
+ run_mysqlcheck_views() ||
+ run_sql_fix_privilege_tables() ||
+ run_mysqlcheck_fixnames() ||
+ run_mysqlcheck_upgrade(FALSE))
die("Upgrade failed" );
- }
+
+ verbose("Phase %d/%d: Running 'FLUSH PRIVILEGES'", ++phase, phases_total);
+ if (run_query("FLUSH PRIVILEGES", NULL, TRUE))
+ die("Upgrade failed" );
+
verbose("OK");
/* Create a file indicating upgrade has been performed */
create_mysql_upgrade_info_file();
+ DBUG_ASSERT(phase == phases_total);
+
end:
free_used_memory();
my_end(my_end_arg);
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 105e195c269..d4d40b0a0f2 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2014, Oracle and/or its affiliates.
- Copyright (c) 2010, 2017, Monty Program Ab.
+ Copyright (c) 2010, 2017, MariaDB
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
@@ -23,9 +23,10 @@
#include <sys/stat.h>
#include <mysql.h>
#include <sql_common.h>
-#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
+#include <welcome_copyright_notice.h>
+#include <my_rnd.h>
-#define ADMIN_VERSION "9.0"
+#define ADMIN_VERSION "9.1"
#define MAX_MYSQL_VAR 512
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
#define MAX_TRUNC_LENGTH 3
@@ -37,14 +38,15 @@ char ex_var_names[MAX_MYSQL_VAR][FN_REFLEN];
ulonglong last_values[MAX_MYSQL_VAR];
static int interval=0;
static my_bool option_force=0,interrupted=0,new_line=0,
- opt_compress=0, opt_relative=0, opt_verbose=0, opt_vertical=0,
- tty_password= 0, opt_nobeep;
+ opt_compress= 0, opt_local= 0, opt_relative= 0, opt_verbose= 0,
+ opt_vertical= 0, tty_password= 0, opt_nobeep;
static my_bool debug_info_flag= 0, debug_check_flag= 0;
static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations;
static uint opt_count_iterations= 0, my_end_arg;
static ulong opt_connect_timeout, opt_shutdown_timeout;
static char * unix_port=0;
static char *opt_plugin_dir= 0, *opt_default_auth= 0;
+static bool sql_log_bin_off= false;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
@@ -100,9 +102,13 @@ enum commands {
ADMIN_FLUSH_HOSTS, ADMIN_FLUSH_TABLES, ADMIN_PASSWORD,
ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE,
- ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD, ADMIN_FLUSH_SLOW_LOG,
+ ADMIN_START_ALL_SLAVES, ADMIN_STOP_ALL_SLAVES,
+ ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD, ADMIN_FLUSH_BINARY_LOG,
+ ADMIN_FLUSH_ENGINE_LOG, ADMIN_FLUSH_ERROR_LOG, ADMIN_FLUSH_GENERAL_LOG,
+ ADMIN_FLUSH_RELAY_LOG, ADMIN_FLUSH_SLOW_LOG,
ADMIN_FLUSH_TABLE_STATISTICS, ADMIN_FLUSH_INDEX_STATISTICS,
ADMIN_FLUSH_USER_STATISTICS, ADMIN_FLUSH_CLIENT_STATISTICS,
+ ADMIN_FLUSH_USER_RESOURCES,
ADMIN_FLUSH_ALL_STATUS, ADMIN_FLUSH_ALL_STATISTICS
};
static const char *command_names[]= {
@@ -113,9 +119,11 @@ static const char *command_names[]= {
"flush-hosts", "flush-tables", "password",
"ping", "extended-status", "flush-status",
"flush-privileges", "start-slave", "stop-slave",
- "flush-threads", "old-password", "flush-slow-log",
+ "start-all-slaves", "stop-all-slaves",
+ "flush-threads", "old-password", "flush-binary-log", "flush-engine-log",
+ "flush-error-log", "flush-general-log", "flush-relay-log", "flush-slow-log",
"flush-table-statistics", "flush-index-statistics",
- "flush-user-statistics", "flush-client-statistics",
+ "flush-user-statistics", "flush-client-statistics", "flush-user-resources",
"flush-all-status", "flush-all-statistics",
NullS
};
@@ -157,6 +165,9 @@ static struct my_option my_long_options[] =
NO_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host.", &host, &host, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"local", 'l', "Local command, don't write to binlog.",
+ &opt_local, &opt_local, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ 0, 0, 0},
{"no-beep", 'b', "Turn off beep on error.", &opt_nobeep,
&opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p',
@@ -287,8 +298,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
#endif
break;
case OPT_MYSQL_PROTOCOL:
- opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
- opt->name);
+ if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
+ opt->name)) <= 0)
+ {
+ sf_leaking_memory= 1; /* no memory leak reports here */
+ exit(1);
+ }
break;
}
return 0;
@@ -304,8 +319,7 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]);
mysql_init(&mysql);
sf_leaking_memory=1; /* don't report memory leaks on early exits */
- if ((error= load_defaults("my",load_default_groups,&argc,&argv)))
- goto err1;
+ load_defaults_or_exit("my", load_default_groups, &argc, &argv);
save_argv = argv; /* Save for free_defaults */
if ((error=handle_options(&argc, &argv, my_long_options, get_one_option)))
@@ -341,8 +355,12 @@ int main(int argc,char *argv[])
}
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
+ {
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
+ }
mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(char*)&opt_ssl_verify_server_cert);
#endif
@@ -361,6 +379,9 @@ int main(int argc,char *argv[])
if (opt_default_auth && *opt_default_auth)
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+ mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
+ mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
+ "program_name", "mysqladmin");
if (sql_connect(&mysql, option_wait))
{
/*
@@ -478,10 +499,8 @@ err2:
my_free(shared_memory_base_name);
#endif
free_defaults(save_argv);
-err1:
my_end(my_end_arg);
- exit(error);
- return 0;
+ return error;
}
@@ -581,6 +600,31 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
}
+static int maybe_disable_binlog(MYSQL *mysql)
+{
+ if (opt_local && !sql_log_bin_off)
+ {
+ if (mysql_query(mysql, "set local sql_log_bin=0"))
+ {
+ my_printf_error(0, "SET LOCAL SQL_LOG_BIN=0 failed; error: '%-.200s'",
+ error_flags, mysql_error(mysql));
+ return -1;
+ }
+ }
+ sql_log_bin_off= true;
+ return 0;
+}
+
+
+int flush(MYSQL *mysql, const char *what)
+{
+ char buf[FN_REFLEN];
+ my_snprintf(buf, sizeof(buf), "flush %s%s",
+ (opt_local && !sql_log_bin_off ? "local " : ""), what);
+ return mysql_query(mysql, buf);
+}
+
+
/**
@brief Execute all commands
@@ -597,6 +641,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
+ int ret = 0;
const char *status;
/*
MySQL documentation relies on the fact that mysqladmin will
@@ -607,6 +652,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
*/
struct my_rnd_struct rand_st;
+ char buff[FN_REFLEN + 20];
for (; argc > 0 ; argv++,argc--)
{
@@ -614,12 +660,13 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
switch ((command= find_type(argv[0],&command_typelib,FIND_TYPE_BASIC))) {
case ADMIN_CREATE:
{
- char buff[FN_REFLEN+20];
if (argc < 2)
{
my_printf_error(0, "Too few arguments to create", error_flags);
return 1;
}
+ if (maybe_disable_binlog(mysql))
+ return -1;
sprintf(buff,"create database `%.*s`",FN_REFLEN,argv[1]);
if (mysql_query(mysql,buff))
{
@@ -637,6 +684,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
my_printf_error(0, "Too few arguments to drop", error_flags);
return 1;
}
+ if (maybe_disable_binlog(mysql))
+ return -1;
if (drop_db(mysql,argv[1]))
return -1;
argc--; argv++;
@@ -677,7 +726,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_PRIVILEGES:
case ADMIN_RELOAD:
- if (mysql_query(mysql,"flush privileges"))
+ if (flush(mysql, "privileges"))
{
my_printf_error(0, "reload failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -688,10 +737,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (mysql_refresh(mysql,
(uint) ~(REFRESH_GRANT | REFRESH_STATUS |
REFRESH_READ_LOCK | REFRESH_SLAVE |
- REFRESH_MASTER | REFRESH_TABLE_STATS |
- REFRESH_INDEX_STATS |
- REFRESH_USER_STATS |
- REFRESH_CLIENT_STATS)))
+ REFRESH_MASTER)))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -884,7 +930,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_LOGS:
{
- if (mysql_query(mysql,"flush logs"))
+ if (flush(mysql, "logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -892,9 +938,59 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
break;
}
+ case ADMIN_FLUSH_BINARY_LOG:
+ {
+ if (flush(mysql, "binary logs"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_ENGINE_LOG:
+ {
+ if (flush(mysql, "engine logs"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_ERROR_LOG:
+ {
+ if (flush(mysql, "error logs"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_GENERAL_LOG:
+ {
+ if (flush(mysql, "general logs"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_RELAY_LOG:
+ {
+ if (flush(mysql, "relay logs"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
case ADMIN_FLUSH_SLOW_LOG:
{
- if (mysql_query(mysql,"flush slow logs"))
+ if (flush(mysql, "slow logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -904,7 +1000,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_HOSTS:
{
- if (mysql_query(mysql,"flush hosts"))
+ if (flush(mysql, "hosts"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -914,7 +1010,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_TABLES:
{
- if (mysql_query(mysql,"flush tables"))
+ if (flush(mysql, "tables"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -924,7 +1020,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_STATUS:
{
- if (mysql_query(mysql,"flush status"))
+ if (flush(mysql, "status"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -934,7 +1030,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_TABLE_STATISTICS:
{
- if (mysql_query(mysql,"flush table_statistics"))
+ if (flush(mysql, "table_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -944,7 +1040,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_INDEX_STATISTICS:
{
- if (mysql_query(mysql,"flush index_statistics"))
+ if (flush(mysql, "index_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -954,7 +1050,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_USER_STATISTICS:
{
- if (mysql_query(mysql,"flush user_statistics"))
+ if (flush(mysql, "user_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -962,9 +1058,19 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
break;
}
+ case ADMIN_FLUSH_USER_RESOURCES:
+ {
+ if (flush(mysql, "user_resources"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
case ADMIN_FLUSH_CLIENT_STATISTICS:
{
- if (mysql_query(mysql,"flush client_statistics"))
+ if (flush(mysql, "client_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -974,9 +1080,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_ALL_STATISTICS:
{
- if (mysql_query(mysql,
- "flush table_statistics,index_statistics,"
- "user_statistics,client_statistics"))
+ if (flush(mysql, "table_statistics,index_statistics,"
+ "user_statistics,client_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -986,9 +1091,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_ALL_STATUS:
{
- if (mysql_query(mysql,
- "flush status,table_statistics,index_statistics,"
- "user_statistics,client_statistics"))
+ if (flush(mysql, "status,table_statistics,index_statistics,"
+ "user_statistics,client_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -1006,6 +1110,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
start_time=time((time_t*) 0);
my_rnd_init(&rand_st,(ulong) start_time,(ulong) start_time/2);
+ if (maybe_disable_binlog(mysql))
+ return -1;
if (argc < 1)
{
my_printf_error(0, "Too few arguments to change password", error_flags);
@@ -1019,7 +1125,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (strcmp(typed_password, verified) != 0)
{
my_printf_error(0,"Passwords don't match",MYF(ME_BELL));
- return -1;
+ ret = -1;
+ goto password_done;
}
}
else
@@ -1046,7 +1153,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
my_printf_error(0, "Could not determine old_passwords setting from server; error: '%s'",
error_flags, mysql_error(mysql));
- return -1;
+ ret = -1;
+ goto password_done;
}
else
{
@@ -1057,7 +1165,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
"Could not get old_passwords setting from "
"server; error: '%s'",
error_flags, mysql_error(mysql));
- return -1;
+ ret = -1;
+ goto password_done;
}
if (!mysql_num_rows(res))
old= 1;
@@ -1082,15 +1191,15 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
my_printf_error(0, "Can't turn off logging; error: '%s'",
error_flags, mysql_error(mysql));
- return -1;
+ ret = -1;
}
+ else
if (mysql_query(mysql,buff))
{
if (mysql_errno(mysql)!=1290)
{
my_printf_error(0,"unable to change password; error: '%s'",
error_flags, mysql_error(mysql));
- return -1;
}
else
{
@@ -1104,9 +1213,10 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
" --skip-grant-tables).\n"
"Use: \"mysqladmin flush-privileges password '*'\""
" instead", error_flags);
- return -1;
}
+ ret = -1;
}
+password_done:
/* free up memory from prompted password */
if (typed_password != argv[1])
{
@@ -1118,26 +1228,67 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_START_SLAVE:
- if (mysql_query(mysql, "START SLAVE"))
+ case ADMIN_START_ALL_SLAVES:
+ {
+ my_bool many_slaves= 0;
+ const char *query= "START SLAVE";
+ if (command == ADMIN_START_ALL_SLAVES && mariadb_connection(mysql) &&
+ mysql_get_server_version(mysql) >= 100000)
+ {
+ query="START ALL SLAVES";
+ many_slaves= 1;
+ }
+
+ if (mysql_query(mysql, query))
{
my_printf_error(0, "Error starting slave: %s", error_flags,
mysql_error(mysql));
return -1;
}
+ else if (!many_slaves || mysql_warning_count(mysql) > 0)
+ {
+ if (!option_silent)
+ puts("Slave('s) started");
+ }
else
- puts("Slave started");
+ {
+ if (!option_silent)
+ puts("No slaves to start");
+ }
break;
+ }
case ADMIN_STOP_SLAVE:
- if (mysql_query(mysql, "STOP SLAVE"))
+ case ADMIN_STOP_ALL_SLAVES:
+ {
+ const char *query= "STOP SLAVE";
+ my_bool many_slaves= 0;
+
+ if (command == ADMIN_STOP_ALL_SLAVES && mariadb_connection(mysql) &&
+ mysql_get_server_version(mysql) >= 100000)
+ {
+ query="STOP ALL SLAVES";
+ many_slaves= 1;
+ }
+
+ if (mysql_query(mysql, query))
{
my_printf_error(0, "Error stopping slave: %s", error_flags,
mysql_error(mysql));
return -1;
}
+ else if (!many_slaves || mysql_warning_count(mysql) > 0)
+ {
+ /* We can't detect if there was any slaves to stop with STOP SLAVE */
+ if (many_slaves && !option_silent)
+ puts("Slave('s) stopped");
+ }
else
- puts("Slave stopped");
+ {
+ if (!option_silent)
+ puts("All slaves was already stopped");
+ }
break;
-
+ }
case ADMIN_PING:
mysql->reconnect=0; /* We want to know of reconnects */
if (!mysql_ping(mysql))
@@ -1167,7 +1318,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return 1;
}
}
- return 0;
+ return ret;
}
/**
@@ -1244,12 +1395,18 @@ static void usage(void)
flush-index-statistics Flush index statistics\n\
flush-logs Flush all logs\n\
flush-privileges Reload grant tables (same as reload)\n\
+ flush-binary-log Flush binary log\n\
+ flush-engine-log Flush engine log(s)\n\
+ flush-error-log Flush error log\n\
+ flush-general-log Flush general log\n\
+ flush-relay-log Flush relay log\n\
flush-slow-log Flush slow query log\n\
- flush-status Clear status variables\n\
+ flush-status Clear status variables\n\
flush-table-statistics Clear table statistics\n\
flush-tables Flush all tables\n\
flush-threads Flush the thread cache\n\
flush-user-statistics Flush user statistics\n\
+ flush-user-resources Flush user resources\n\
kill id,id,... Kill mysql threads");
#if MYSQL_VERSION_ID >= 32200
puts("\
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 1a11e3e697b..4ba76cb3ba1 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -34,9 +34,11 @@
#define TABLE TABLE_CLIENT
#include "client_priv.h"
#include <my_time.h>
+#include <sslopt-vars.h>
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
#include "sql_priv.h"
#include "log_event.h"
+#include "compat56.h"
#include "sql_common.h"
#include "my_dir.h"
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
@@ -48,6 +50,8 @@
#include "mysqld.h"
+#include <algorithm>
+
Rpl_filter *binlog_filter= 0;
#define BIN_LOG_HEADER_SIZE 4
@@ -67,9 +71,12 @@ ulong bytes_sent = 0L, bytes_received = 0L;
ulong mysqld_net_retry_count = 10L;
ulong open_files_limit;
ulong opt_binlog_rows_event_max_size;
-uint test_flags = 0;
+ulonglong test_flags = 0;
+ulong opt_binlog_rows_event_max_encoded_size= MAX_MAX_ALLOWED_PACKET;
static uint opt_protocol= 0;
static FILE *result_file;
+static char *result_file_name= 0;
+static const char *output_prefix= "";
#ifndef DBUG_OFF
static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
@@ -93,6 +100,8 @@ static char* database= 0;
static my_bool force_opt= 0, short_form= 0, remote_opt= 0;
static my_bool debug_info_flag, debug_check_flag;
static my_bool force_if_open_opt= 1;
+static my_bool opt_raw_mode= 0, opt_stop_never= 0;
+static ulong opt_stop_never_slave_server_id= 0;
static my_bool opt_verify_binlog_checksum= 1;
static ulonglong offset = 0;
static char* host = 0;
@@ -102,7 +111,7 @@ static const char* sock= 0;
static char *opt_plugindir= 0, *opt_default_auth= 0;
#ifdef HAVE_SMEM
-static char *shared_memory_base_name= 0;
+static const char *shared_memory_base_name= 0;
#endif
static char* user = 0;
static char* pass = 0;
@@ -117,7 +126,6 @@ static ulonglong start_position, stop_position;
static char *start_datetime_str, *stop_datetime_str;
static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX;
static ulonglong rec_count= 0;
-static short binlog_flags = 0;
static MYSQL* mysql = NULL;
static const char* dirname_for_local_load= 0;
static bool opt_skip_annotate_row_events= 0;
@@ -139,7 +147,9 @@ enum Exit_status {
/** An error occurred and execution should stop. */
ERROR_STOP,
/** No error occurred but execution should stop. */
- OK_STOP
+ OK_STOP,
+ /** No error occurred - end of file reached. */
+ OK_EOF,
};
/**
@@ -277,8 +287,8 @@ public:
int init()
{
- return init_dynamic_array(&file_names, sizeof(File_name_record),
- 100, 100);
+ return my_init_dynamic_array(&file_names, sizeof(File_name_record),
+ 100, 100, MYF(0));
}
void init_by_dir_name(const char *dir)
@@ -804,7 +814,12 @@ write_event_header_and_base64(Log_event *ev, FILE *result_file,
/* Write header and base64 output to cache */
ev->print_header(head, print_event_info, FALSE);
- ev->print_base64(body, print_event_info, FALSE);
+
+ DBUG_ASSERT(print_event_info->base64_output_mode == BASE64_OUTPUT_ALWAYS);
+
+ ev->print_base64(body, print_event_info,
+ print_event_info->base64_output_mode !=
+ BASE64_OUTPUT_DECODE_ROWS);
/* Read data from cache and write to result file */
if (copy_event_cache_to_file_and_reinit(head, result_file) ||
@@ -843,7 +858,9 @@ static bool print_base64(PRINT_EVENT_INFO *print_event_info, Log_event *ev)
return 1;
}
ev->print(result_file, print_event_info);
- return print_event_info->head_cache.error == -1;
+ return
+ print_event_info->head_cache.error == -1 ||
+ print_event_info->body_cache.error == -1;
}
@@ -1228,6 +1245,9 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
case WRITE_ROWS_EVENT:
case DELETE_ROWS_EVENT:
case UPDATE_ROWS_EVENT:
+ case WRITE_ROWS_EVENT_V1:
+ case UPDATE_ROWS_EVENT_V1:
+ case DELETE_ROWS_EVENT_V1:
{
Rows_log_event *e= (Rows_log_event*) ev;
if (print_row_event(print_event_info, ev, e->get_table_id(),
@@ -1245,6 +1265,9 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
goto err;
break;
}
+ case START_ENCRYPTION_EVENT:
+ glob_description_event->start_decryption((Start_encryption_log_event*)ev);
+ /* fall through */
default:
print_skip_replication_statement(print_event_info, ev);
ev->print(result_file, print_event_info);
@@ -1362,8 +1385,14 @@ static struct my_option my_options[] =
{"read-from-remote-server", 'R', "Read binary logs from a MySQL server.",
&remote_opt, &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
- {"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR,
- REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"raw", 0, "Requires -R. Output raw binlog data instead of SQL "
+ "statements. Output files named after server logs.",
+ &opt_raw_mode, &opt_raw_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ 0, 0},
+ {"result-file", 'r', "Direct output to a given file. With --raw this is a "
+ "prefix for the file names.",
+ &result_file_name, &result_file_name, 0, GET_STR, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
{"server-id", 0,
"Extract only binlog entries created by the server having the given id.",
&server_id, &server_id, 0, GET_ULONG,
@@ -1386,6 +1415,7 @@ static struct my_option my_options[] =
{"socket", 'S', "The socket file to use for connection.",
&sock, &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
0, 0},
+#include <sslopt-longopts.h>
{"start-datetime", OPT_START_DATETIME,
"Start reading the binlog at first event having a datetime equal or "
"posterior to the argument; the argument must be a date and time "
@@ -1399,8 +1429,11 @@ static struct my_option my_options[] =
"passed on the command line.",
&start_position, &start_position, 0, GET_ULL,
REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
- /* COM_BINLOG_DUMP accepts only 4 bytes for the position */
- (ulonglong)(~(uint32)0), 0, 0, 0},
+ /*
+ COM_BINLOG_DUMP accepts only 4 bytes for the position
+ so remote log reading has lower limit.
+ */
+ (ulonglong)(0xffffffffffffffffULL), 0, 0, 0},
{"stop-datetime", OPT_STOP_DATETIME,
"Stop reading the binlog at first event having a datetime equal or "
"posterior to the argument; the argument must be a date and time "
@@ -1409,6 +1442,14 @@ static struct my_option my_options[] =
"(you should probably use quotes for your shell to set it properly).",
&stop_datetime_str, &stop_datetime_str,
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"stop-never", 0, "Wait for more data from the server "
+ "instead of stopping at the end of the last log. Implies --to-last-log.",
+ &opt_stop_never, &opt_stop_never, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"stop-never-slave-server-id", 0,
+ "The slave server_id used for --read-from-remote-server --stop-never.",
+ &opt_stop_never_slave_server_id, &opt_stop_never_slave_server_id, 0,
+ GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"stop-position", OPT_STOP_POSITION,
"Stop reading the binlog at position N. Applies to the last binlog "
"passed on the command line.",
@@ -1439,6 +1480,15 @@ that may lead to an endless loop.",
"This value must be a multiple of 256.",
&opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size, 0,
GET_ULONG, REQUIRED_ARG, UINT_MAX, 256, ULONG_MAX, 0, 256, 0},
+#ifndef DBUG_OFF
+ {"debug-binlog-row-event-max-encoded-size", 0,
+ "The maximum size of base64-encoded rows-event in one BINLOG pseudo-query "
+ "instance. When the computed actual size exceeds the limit "
+ "the BINLOG's argument string is fragmented in two.",
+ &opt_binlog_rows_event_max_encoded_size,
+ &opt_binlog_rows_event_max_encoded_size, 0,
+ GET_ULONG, REQUIRED_ARG, UINT_MAX/4, 256, ULONG_MAX, 0, 256, 0},
+#endif
{"verify-binlog-checksum", 'c', "Verify checksum binlog events.",
(uchar**) &opt_verify_binlog_checksum, (uchar**) &opt_verify_binlog_checksum,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -1527,6 +1577,8 @@ static void cleanup()
my_free(host);
my_free(user);
my_free(const_cast<char*>(dirname_for_local_load));
+ my_free(start_datetime_str);
+ my_free(stop_datetime_str);
delete binlog_filter;
delete glob_description_event;
@@ -1558,13 +1610,14 @@ the mysql command line client.\n\n");
static my_time_t convert_str_to_timestamp(const char* str)
{
- int was_cut;
+ MYSQL_TIME_STATUS status;
MYSQL_TIME l_time;
long dummy_my_timezone;
uint dummy_in_dst_time_gap;
+
/* We require a total specification (date AND time) */
- if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &was_cut) !=
- MYSQL_TIMESTAMP_DATETIME || was_cut)
+ if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &status) ||
+ l_time.time_type != MYSQL_TIMESTAMP_DATETIME || status.warnings)
{
error("Incorrect date and time argument: %s", str);
exit(1);
@@ -1590,6 +1643,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
DBUG_PUSH(argument ? argument : default_dbug_option);
break;
#endif
+#include <sslopt-case.h>
case 'd':
one_database = 1;
break;
@@ -1608,16 +1662,16 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
else
tty_password=1;
break;
- case 'r':
- if (!(result_file = my_fopen(argument, O_WRONLY | O_BINARY, MYF(MY_WME))))
- exit(1);
- break;
case 'R':
remote_opt= 1;
break;
case OPT_MYSQL_PROTOCOL:
- opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
- opt->name);
+ if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
+ opt->name)) <= 0)
+ {
+ sf_leaking_memory= 1; /* no memory leak reports here */
+ exit(1);
+ }
break;
case OPT_START_DATETIME:
start_datetime= convert_str_to_timestamp(start_datetime_str);
@@ -1630,8 +1684,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_base64_output_mode= BASE64_OUTPUT_ALWAYS;
else
{
- opt_base64_output_mode= (enum_base64_output_mode)
- (find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1);
+ int val;
+
+ if ((val= find_type_with_warning(argument, &base64_output_mode_typelib,
+ opt->name)) <= 0)
+ {
+ sf_leaking_memory= 1; /* no memory leak reports here */
+ exit(1);
+ }
+ opt_base64_output_mode= (enum_base64_output_mode) (val - 1);
}
break;
case OPT_REWRITE_DB: // db_from->db_to
@@ -1707,13 +1768,20 @@ static int parse_args(int *argc, char*** argv)
{
int ho_error;
- result_file = stdout;
if ((ho_error=handle_options(argc, argv, my_options, get_one_option)))
exit(ho_error);
if (debug_info_flag)
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
- if (debug_check_flag)
+ else if (debug_check_flag)
my_end_arg= MY_CHECK_ERROR;
+ if (start_position > UINT_MAX32 && remote_opt)
+ {
+ /* Here we just emulate old behaviour of option limit handling */
+ fprintf(stderr, "Warning: option 'start-position': unsigned value %llu "
+ "adjusted to 4294967295 (limitation of the client-server protocol)",
+ start_position);
+ start_position= UINT_MAX32;
+ }
return 0;
}
@@ -1739,6 +1807,18 @@ static Exit_status safe_connect()
return ERROR_STOP;
}
+#ifdef HAVE_OPENSSL
+ if (opt_use_ssl)
+ {
+ mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
+ opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
+ }
+ mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ (char*)&opt_ssl_verify_server_cert);
+#endif /*HAVE_OPENSSL*/
+
if (opt_plugindir && *opt_plugindir)
mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugindir);
@@ -1752,6 +1832,9 @@ static Exit_status safe_connect()
mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
shared_memory_base_name);
#endif
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
+ mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
+ "program_name", "mysqlbinlog");
if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, 0))
{
error("Failed on connect: %s", mysql_error(mysql));
@@ -1786,7 +1869,8 @@ static Exit_status dump_log_entries(const char* logname)
Set safe delimiter, to dump things
like CREATE PROCEDURE safely
*/
- fprintf(result_file, "DELIMITER /*!*/;\n");
+ if (!opt_raw_mode)
+ fprintf(result_file, "DELIMITER /*!*/;\n");
strmov(print_event_info.delimiter, "/*!*/;");
print_event_info.verbose= short_form ? 0 : verbose;
@@ -1795,7 +1879,8 @@ static Exit_status dump_log_entries(const char* logname)
dump_local_log_entries(&print_event_info, logname));
/* Set delimiter back to semicolon */
- fprintf(result_file, "DELIMITER ;\n");
+ if (!opt_raw_mode)
+ fprintf(result_file, "DELIMITER ;\n");
strmov(print_event_info.delimiter, ";");
return rc;
}
@@ -1815,7 +1900,7 @@ static Exit_status check_master_version()
{
MYSQL_RES* res = 0;
MYSQL_ROW row;
- const char* version;
+ uint version;
if (mysql_query(mysql, "SELECT VERSION()") ||
!(res = mysql_store_result(mysql)))
@@ -1831,7 +1916,7 @@ static Exit_status check_master_version()
goto err;
}
- if (!(version = row[0]))
+ if (!(version = atoi(row[0])))
{
error("Could not find server version: "
"Master reported NULL for the version.");
@@ -1849,15 +1934,29 @@ static Exit_status check_master_version()
"Master returned '%s'", mysql_error(mysql));
goto err;
}
+
+ /*
+ Announce our capabilities to the server, so it will send us all the events
+ that we know about.
+ */
+ if (mysql_query(mysql, "SET @mariadb_slave_capability="
+ STRINGIFY_ARG(MARIA_SLAVE_CAPABILITY_MINE)))
+ {
+ error("Could not inform master about capability. Master returned '%s'",
+ mysql_error(mysql));
+ goto err;
+ }
+
delete glob_description_event;
- switch (*version) {
- case '3':
+ switch (version) {
+ case 3:
glob_description_event= new Format_description_log_event(1);
break;
- case '4':
+ case 4:
glob_description_event= new Format_description_log_event(3);
break;
- case '5':
+ case 5:
+ case 10:
/*
The server is soon going to send us its Format_description log
event, unless it is a 5.0 server with 3.23 or 4.0 binlogs.
@@ -1869,7 +1968,7 @@ static Exit_status check_master_version()
default:
glob_description_event= NULL;
error("Could not find server version: "
- "Master reported unrecognized MySQL version '%s'.", version);
+ "Master reported unrecognized MySQL version '%s'.", row[0]);
goto err;
}
if (!glob_description_event || !glob_description_event->is_valid())
@@ -1887,6 +1986,247 @@ err:
}
+static Exit_status handle_event_text_mode(PRINT_EVENT_INFO *print_event_info,
+ ulong *len,
+ const char* logname,
+ uint logname_len, my_off_t old_off)
+{
+ const char *error_msg;
+ Log_event *ev;
+ NET *net= &mysql->net;
+ DBUG_ENTER("handle_event_text_mode");
+
+ if (net->read_pos[5] == ANNOTATE_ROWS_EVENT)
+ {
+ if (!(ev= read_remote_annotate_event(net->read_pos + 1, *len - 1,
+ &error_msg)))
+ {
+ error("Could not construct annotate event object: %s", error_msg);
+ DBUG_RETURN(ERROR_STOP);
+ }
+ }
+ else
+ {
+ if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
+ *len - 1, &error_msg,
+ glob_description_event,
+ opt_verify_binlog_checksum)))
+ {
+ error("Could not construct log event object: %s", error_msg);
+ DBUG_RETURN(ERROR_STOP);
+ }
+ /*
+ If reading from a remote host, ensure the temp_buf for the
+ Log_event class is pointing to the incoming stream.
+ */
+ ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
+ }
+
+ Log_event_type type= ev->get_type_code();
+ if (glob_description_event->binlog_version >= 3 ||
+ (type != LOAD_EVENT && type != CREATE_FILE_EVENT))
+ {
+ /*
+ If this is a Rotate event, maybe it's the end of the requested binlog;
+ in this case we are done (stop transfer).
+ This is suitable for binlogs, not relay logs (but for now we don't read
+ relay logs remotely because the server is not able to do that). If one
+ day we read relay logs remotely, then we will have a problem with the
+ detection below: relay logs contain Rotate events which are about the
+ binlogs, so which would trigger the end-detection below.
+ */
+ if (type == ROTATE_EVENT)
+ {
+ Rotate_log_event *rev= (Rotate_log_event *)ev;
+ /*
+ If this is a fake Rotate event, and not about our log, we can stop
+ transfer. If this a real Rotate event (so it's not about our log,
+ it's in our log describing the next log), we print it (because it's
+ part of our log) and then we will stop when we receive the fake one
+ soon.
+ */
+ if (rev->when == 0)
+ {
+ *len= 1; // fake Rotate, so don't increment old_off
+ if (!to_last_remote_log)
+ {
+ if ((rev->ident_len != logname_len) ||
+ memcmp(rev->new_log_ident, logname, logname_len))
+ {
+ delete ev;
+ DBUG_RETURN(OK_EOF);
+ }
+ /*
+ Otherwise, this is a fake Rotate for our log, at the very
+ beginning for sure. Skip it, because it was not in the original
+ log. If we are running with to_last_remote_log, we print it,
+ because it serves as a useful marker between binlogs then.
+ */
+ delete ev;
+ DBUG_RETURN(OK_CONTINUE);
+ }
+ }
+ }
+ else if (type == FORMAT_DESCRIPTION_EVENT)
+ {
+ /*
+ This could be an fake Format_description_log_event that server
+ (5.0+) automatically sends to a slave on connect, before sending
+ a first event at the requested position. If this is the case,
+ don't increment old_off. Real Format_description_log_event always
+ starts from BIN_LOG_HEADER_SIZE position.
+ */
+ if (old_off != BIN_LOG_HEADER_SIZE)
+ *len= 1; // fake event, don't increment old_off
+ }
+ Exit_status retval= process_event(print_event_info, ev, old_off, logname);
+ if (retval != OK_CONTINUE)
+ DBUG_RETURN(retval);
+ }
+ else
+ {
+ Load_log_event *le= (Load_log_event*)ev;
+ const char *old_fname= le->fname;
+ uint old_len= le->fname_len;
+ File file;
+ Exit_status retval;
+ char fname[FN_REFLEN+1];
+
+ if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
+ {
+ DBUG_RETURN(ERROR_STOP);
+ }
+
+ retval= process_event(print_event_info, ev, old_off, logname);
+ if (retval != OK_CONTINUE)
+ {
+ my_close(file,MYF(MY_WME));
+ DBUG_RETURN(retval);
+ }
+ retval= load_processor.load_old_format_file(net,old_fname,old_len,file);
+ my_close(file,MYF(MY_WME));
+ if (retval != OK_CONTINUE)
+ DBUG_RETURN(retval);
+ }
+
+ DBUG_RETURN(OK_CONTINUE);
+}
+
+
+static char out_file_name[FN_REFLEN + 1];
+
+static Exit_status handle_event_raw_mode(PRINT_EVENT_INFO *print_event_info,
+ ulong *len,
+ const char* logname, uint logname_len)
+{
+ const char *error_msg;
+ const unsigned char *read_pos= mysql->net.read_pos + 1;
+ Log_event_type type;
+ DBUG_ENTER("handle_event_raw_mode");
+ DBUG_ASSERT(opt_raw_mode && remote_opt);
+
+ type= (Log_event_type) read_pos[EVENT_TYPE_OFFSET];
+
+ if (type == HEARTBEAT_LOG_EVENT)
+ DBUG_RETURN(OK_CONTINUE);
+
+ if (type == ROTATE_EVENT || type == FORMAT_DESCRIPTION_EVENT)
+ {
+ Log_event *ev;
+ if (!(ev= Log_event::read_log_event((const char*) read_pos ,
+ *len - 1, &error_msg,
+ glob_description_event,
+ opt_verify_binlog_checksum)))
+ {
+ error("Could not construct %s event object: %s",
+ type == ROTATE_EVENT ? "rotate" : "format description", error_msg);
+ DBUG_RETURN(ERROR_STOP);
+ }
+ /*
+ If reading from a remote host, ensure the temp_buf for the
+ Log_event class is pointing to the incoming stream.
+ */
+ ev->register_temp_buf((char *) read_pos, FALSE);
+
+ if (type == ROTATE_EVENT)
+ {
+ Exit_status ret_val= OK_CONTINUE;
+ Rotate_log_event *rev= (Rotate_log_event *)ev;
+ char *pe= strmake(out_file_name, output_prefix, sizeof(out_file_name)-1);
+ strmake(pe, rev->new_log_ident, sizeof(out_file_name) - (pe-out_file_name));
+
+ /*
+ If this is a fake Rotate event, and not about our log, we can stop
+ transfer. If this a real Rotate event (so it's not about our log,
+ it's in our log describing the next log), we print it (because it's
+ part of our log) and then we will stop when we receive the fake one
+ soon.
+ */
+ if (rev->when == 0)
+ {
+ if (!to_last_remote_log)
+ {
+ if ((rev->ident_len != logname_len) ||
+ memcmp(rev->new_log_ident, logname, logname_len))
+ {
+ ret_val= OK_EOF;
+ }
+ /*
+ Otherwise, this is a fake Rotate for our log, at the very
+ beginning for sure. Skip it, because it was not in the original
+ log. If we are running with to_last_remote_log, we print it,
+ because it serves as a useful marker between binlogs then.
+ */
+ }
+ *len= 1; // fake Rotate, so don't increment old_off
+ ev->temp_buf= 0;
+ delete ev;
+ DBUG_RETURN(ret_val);
+ }
+ ev->temp_buf= 0;
+ delete ev;
+ }
+ else /* if (type == FORMAT_DESCRIPTION_EVENT) */
+ {
+ DBUG_ASSERT(type == FORMAT_DESCRIPTION_EVENT);
+
+ if (result_file)
+ my_fclose(result_file, MYF(0));
+
+ if (!(result_file= my_fopen(out_file_name,
+ O_WRONLY | O_BINARY, MYF(MY_WME))))
+ {
+ error("Could not create output log file: %s", out_file_name);
+ DBUG_RETURN(ERROR_STOP);
+ }
+ /* TODO - add write error simulation here */
+
+ if (my_fwrite(result_file, (const uchar *) BINLOG_MAGIC,
+ BIN_LOG_HEADER_SIZE, MYF(MY_NABP)))
+ {
+ error("Could not write into log file '%s'", out_file_name);
+ DBUG_RETURN(ERROR_STOP);
+ }
+
+ delete glob_description_event;
+ glob_description_event= (Format_description_log_event*) ev;
+ print_event_info->common_header_len=
+ glob_description_event->common_header_len;
+ ev->temp_buf= 0;
+ /* We do not want to delete the event here. */
+ }
+ }
+
+ if (my_fwrite(result_file, read_pos, *len - 1, MYF(MY_NABP)))
+ {
+ error("Could not write into log file '%s'", out_file_name);
+ DBUG_RETURN(ERROR_STOP);
+ }
+
+ DBUG_RETURN(OK_CONTINUE);
+}
+
+
/**
Requests binlog dump from a remote server and prints the events it
receives.
@@ -1909,8 +2249,9 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
uint logname_len;
NET* net;
my_off_t old_off= start_position_mot;
- char fname[FN_REFLEN+1];
Exit_status retval= OK_CONTINUE;
+ short binlog_flags = 0;
+ ulong slave_id;
DBUG_ENTER("dump_remote_log_entries");
/*
@@ -1929,19 +2270,31 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to
cast to uint32.
*/
+ DBUG_ASSERT(start_position <= UINT_MAX32);
int4store(buf, (uint32)start_position);
if (!opt_skip_annotate_row_events)
binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
+ if (!opt_stop_never)
+ binlog_flags|= BINLOG_DUMP_NON_BLOCK;
+
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
size_t tlen = strlen(logname);
- if (tlen > UINT_MAX)
+ if (tlen > sizeof(buf) - 10)
{
error("Log name too long.");
DBUG_RETURN(ERROR_STOP);
}
logname_len = (uint) tlen;
- int4store(buf + 6, 0);
+ if (opt_stop_never)
+ {
+ DBUG_ASSERT(to_last_remote_log);
+ slave_id= (opt_stop_never_slave_server_id == 0) ?
+ 1 : opt_stop_never_slave_server_id;
+ }
+ else
+ slave_id= 0;
+ int4store(buf + 6, slave_id);
memcpy(buf + 10, logname, logname_len);
if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
{
@@ -1951,9 +2304,6 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
for (;;)
{
- const char *error_msg;
- Log_event *ev;
-
len= cli_safe_read(mysql);
if (len == packet_error)
{
@@ -1964,115 +2314,23 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
break; // end of data
DBUG_PRINT("info",( "len: %lu net->read_pos[5]: %d\n",
len, net->read_pos[5]));
- if (net->read_pos[5] == ANNOTATE_ROWS_EVENT)
+ if (opt_raw_mode)
{
- if (!(ev= read_remote_annotate_event(net->read_pos + 1, len - 1,
- &error_msg)))
- {
- error("Could not construct annotate event object: %s", error_msg);
- DBUG_RETURN(ERROR_STOP);
- }
+ retval= handle_event_raw_mode(print_event_info, &len,
+ logname, logname_len);
}
else
{
- if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
- len - 1, &error_msg,
- glob_description_event,
- opt_verify_binlog_checksum)))
- {
- error("Could not construct log event object: %s", error_msg);
- DBUG_RETURN(ERROR_STOP);
- }
- /*
- If reading from a remote host, ensure the temp_buf for the
- Log_event class is pointing to the incoming stream.
- */
- ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
+ retval= handle_event_text_mode(print_event_info, &len,
+ logname, logname_len, old_off);
}
-
- Log_event_type type= ev->get_type_code();
- if (glob_description_event->binlog_version >= 3 ||
- (type != LOAD_EVENT && type != CREATE_FILE_EVENT))
+ if (retval != OK_CONTINUE)
{
- /*
- If this is a Rotate event, maybe it's the end of the requested binlog;
- in this case we are done (stop transfer).
- This is suitable for binlogs, not relay logs (but for now we don't read
- relay logs remotely because the server is not able to do that). If one
- day we read relay logs remotely, then we will have a problem with the
- detection below: relay logs contain Rotate events which are about the
- binlogs, so which would trigger the end-detection below.
- */
- if (type == ROTATE_EVENT)
- {
- Rotate_log_event *rev= (Rotate_log_event *)ev;
- /*
- If this is a fake Rotate event, and not about our log, we can stop
- transfer. If this a real Rotate event (so it's not about our log,
- it's in our log describing the next log), we print it (because it's
- part of our log) and then we will stop when we receive the fake one
- soon.
- */
- if (rev->when == 0)
- {
- if (!to_last_remote_log)
- {
- if ((rev->ident_len != logname_len) ||
- memcmp(rev->new_log_ident, logname, logname_len))
- {
- delete ev;
- DBUG_RETURN(OK_CONTINUE);
- }
- /*
- Otherwise, this is a fake Rotate for our log, at the very
- beginning for sure. Skip it, because it was not in the original
- log. If we are running with to_last_remote_log, we print it,
- because it serves as a useful marker between binlogs then.
- */
- delete ev;
- continue;
- }
- len= 1; // fake Rotate, so don't increment old_off
- }
- }
- else if (type == FORMAT_DESCRIPTION_EVENT)
- {
- /*
- This could be an fake Format_description_log_event that server
- (5.0+) automatically sends to a slave on connect, before sending
- a first event at the requested position. If this is the case,
- don't increment old_off. Real Format_description_log_event always
- starts from BIN_LOG_HEADER_SIZE position.
- */
- if (old_off != BIN_LOG_HEADER_SIZE)
- len= 1; // fake event, don't increment old_off
- }
- Exit_status retval= process_event(print_event_info, ev, old_off, logname);
- if (retval != OK_CONTINUE)
- DBUG_RETURN(retval);
+ if (retval == OK_EOF)
+ break;
+ DBUG_RETURN(retval);
}
- else
- {
- Load_log_event *le= (Load_log_event*)ev;
- const char *old_fname= le->fname;
- uint old_len= le->fname_len;
- File file;
- Exit_status retval;
-
- if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
- DBUG_RETURN(ERROR_STOP);
- retval= process_event(print_event_info, ev, old_off, logname);
- if (retval != OK_CONTINUE)
- {
- my_close(file,MYF(MY_WME));
- DBUG_RETURN(retval);
- }
- retval= load_processor.load_old_format_file(net,old_fname,old_len,file);
- my_close(file,MYF(MY_WME));
- if (retval != OK_CONTINUE)
- DBUG_RETURN(retval);
- }
/*
Let's adjust offset for remote log as for local log to produce
similar text and to have --stop-position to work identically.
@@ -2218,7 +2476,7 @@ static Exit_status check_header(IO_CACHE* file,
Format_description_log_event *new_description_event;
my_b_seek(file, tmp_pos); /* seek back to event's start */
if (!(new_description_event= (Format_description_log_event*)
- Log_event::read_log_event(file, glob_description_event,
+ Log_event::read_log_event(file, 0, glob_description_event,
opt_verify_binlog_checksum)))
/* EOF can't be hit here normally, so it's a real error */
{
@@ -2252,7 +2510,7 @@ static Exit_status check_header(IO_CACHE* file,
{
Log_event *ev;
my_b_seek(file, tmp_pos); /* seek back to event's start */
- if (!(ev= Log_event::read_log_event(file, glob_description_event,
+ if (!(ev= Log_event::read_log_event(file, 0, glob_description_event,
opt_verify_binlog_checksum)))
{
/* EOF can't be hit here normally, so it's a real error */
@@ -2312,7 +2570,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
/* read from stdin */
/*
Windows opens stdin in text mode by default. Certain characters
- such as CTRL-Z are interpeted as events and the read() method
+ such as CTRL-Z are interpreted as events and the read() method
will stop. CTRL-Z is the EOF marker in Windows. to get past this
you have to open stdin in binary mode. Setmode() is used to set
stdin in binary mode. Errors on setting this mode result in
@@ -2340,7 +2598,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
my_off_t length,tmp;
for (length= start_position_mot ; length > 0 ; length-=tmp)
{
- tmp=min(length,sizeof(buff));
+ tmp= MY_MIN(length,sizeof(buff));
if (my_b_read(file, buff, (uint) tmp))
{
error("Failed reading from file.");
@@ -2366,7 +2624,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
char llbuff[21];
my_off_t old_off = my_b_tell(file);
- Log_event* ev = Log_event::read_log_event(file, glob_description_event,
+ Log_event* ev = Log_event::read_log_event(file, 0, glob_description_event,
opt_verify_binlog_checksum);
if (!ev)
{
@@ -2424,27 +2682,26 @@ int main(int argc, char** argv)
my_init_time(); // for time functions
tzset(); // set tzname
- init_alloc_root(&s_mem_root, 16384, 0);
- if (load_defaults("my", load_groups, &argc, &argv))
- exit(1);
+ init_alloc_root(&s_mem_root, 16384, 0, MYF(0));
+ load_defaults_or_exit("my", load_groups, &argc, &argv);
+ defaults_argv= argv;
if (!(binlog_filter= new Rpl_filter))
{
error("Failed to create Rpl_filter");
- exit(1);
+ goto err;
}
- defaults_argv= argv;
parse_args(&argc, (char***)&argv);
if (!argc || opt_version)
{
- if (!argc)
+ if (!opt_version)
+ {
usage();
- cleanup();
- free_defaults(defaults_argv);
- my_end(my_end_arg);
- exit(!opt_version);
+ retval= ERROR_STOP;
+ }
+ goto err;
}
if (opt_base64_output_mode == BASE64_OUTPUT_UNSPEC)
@@ -2459,45 +2716,91 @@ int main(int argc, char** argv)
my_set_max_open_files(open_files_limit);
+ if (opt_stop_never)
+ to_last_remote_log= TRUE;
+
+ if (opt_raw_mode)
+ {
+ if (!remote_opt)
+ {
+ error("The --raw mode only works with --read-from-remote-server");
+ exit(1);
+ }
+ if (one_database)
+ warning("The --database option is ignored in raw mode");
+
+ if (stop_position != (ulonglong)(~(my_off_t)0))
+ warning("The --stop-position option is ignored in raw mode");
+
+ if (stop_datetime != MY_TIME_T_MAX)
+ warning("The --stop-datetime option is ignored in raw mode");
+ result_file= 0;
+ if (result_file_name)
+ output_prefix= result_file_name;
+ }
+ else
+ {
+ if (result_file_name)
+ {
+ if (!(result_file= my_fopen(result_file_name,
+ O_WRONLY | O_BINARY, MYF(MY_WME))))
+ {
+ error("Could not create log file '%s'", result_file_name);
+ exit(1);
+ }
+ }
+ else
+ result_file= stdout;
+ }
+
MY_TMPDIR tmpdir;
tmpdir.list= 0;
if (!dirname_for_local_load)
{
if (init_tmpdir(&tmpdir, 0))
- exit(1);
+ {
+ retval= ERROR_STOP;
+ goto err;
+ }
dirname_for_local_load= my_strdup(my_tmpdir(&tmpdir), MY_WME);
}
if (load_processor.init())
- exit(1);
+ {
+ retval= ERROR_STOP;
+ goto err;
+ }
if (dirname_for_local_load)
load_processor.init_by_dir_name(dirname_for_local_load);
else
load_processor.init_by_cur_dir();
- fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;\n");
-
- fprintf(result_file,
- "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
+ if (!opt_raw_mode)
+ {
+ fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;\n");
- if (disable_log_bin)
fprintf(result_file,
- "/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
+ "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
- /*
- In mysqlbinlog|mysql, don't want mysql to be disconnected after each
- transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
- */
- fprintf(result_file,
- "/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
- "COMPLETION_TYPE=0*/;\n");
+ if (disable_log_bin)
+ fprintf(result_file,
+ "/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
- if (charset)
+ /*
+ In mysqlbinlog|mysql, don't want mysql to be disconnected after each
+ transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
+ */
fprintf(result_file,
- "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
- "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
- "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
- "\n/*!40101 SET NAMES %s */;\n", charset);
+ "/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
+ "COMPLETION_TYPE=0*/;\n");
+
+ if (charset)
+ fprintf(result_file,
+ "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
+ "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
+ "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
+ "\n/*!40101 SET NAMES %s */;\n", charset);
+ }
for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
(--argc >= 0) ; )
@@ -2511,27 +2814,30 @@ int main(int argc, char** argv)
start_position= BIN_LOG_HEADER_SIZE;
}
- /*
- Issue a ROLLBACK in case the last printed binlog was crashed and had half
- of transaction.
- */
- fprintf(result_file,
- "# End of log file\nROLLBACK /* added by mysqlbinlog */;\n"
- "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
- if (disable_log_bin)
- fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
-
- if (charset)
+ if (!opt_raw_mode)
+ {
+ /*
+ Issue a ROLLBACK in case the last printed binlog was crashed and had half
+ of transaction.
+ */
fprintf(result_file,
- "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
- "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
- "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
-
- fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;\n");
+ "# End of log file\nROLLBACK /* added by mysqlbinlog */;\n"
+ "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
+ if (disable_log_bin)
+ fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
+
+ if (charset)
+ fprintf(result_file,
+ "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
+ "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
+ "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
+
+ fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;\n");
+ }
if (tmpdir.list)
free_tmpdir(&tmpdir);
- if (result_file != stdout)
+ if (result_file && result_file != stdout)
my_fclose(result_file, MYF(0));
cleanup();
free_annotate_event();
@@ -2539,12 +2845,20 @@ int main(int argc, char** argv)
free_defaults(defaults_argv);
my_free_open_file_info();
load_processor.destroy();
+ mysql_server_end();
/* We cannot free DBUG, it is used in global destructors after exit(). */
my_end(my_end_arg | MY_DONT_FREE_DBUG);
exit(retval == ERROR_STOP ? 1 : 0);
/* Keep compilers happy. */
DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
+
+err:
+ cleanup();
+ free_defaults(defaults_argv);
+ my_end(my_end_arg);
+ exit(retval == ERROR_STOP ? 1 : 0);
+ DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
}
@@ -2553,6 +2867,27 @@ void *sql_alloc(size_t size)
return alloc_root(&s_mem_root, size);
}
+uint e_key_get_latest_version_func(uint) { return 1; }
+uint e_key_get_func(uint, uint, uchar*, uint*) { return 1; }
+uint e_ctx_size_func(uint, uint) { return 1; }
+int e_ctx_init_func(void *, const uchar*, uint, const uchar*, uint,
+ int, uint, uint) { return 1; }
+int e_ctx_update_func(void *, const uchar*, uint, uchar*, uint*) { return 1; }
+int e_ctx_finish_func(void *, uchar*, uint*) { return 1; }
+uint e_encrypted_length_func(uint, uint, uint) { return 1; }
+
+uint dummy1() { return 1; }
+struct encryption_service_st encryption_handler=
+{
+ e_key_get_latest_version_func,
+ e_key_get_func,
+ e_ctx_size_func,
+ e_ctx_init_func,
+ e_ctx_update_func,
+ e_ctx_finish_func,
+ e_encrypted_length_func
+};
+
/*
We must include this here as it's compiled with different options for
the server
@@ -2569,3 +2904,4 @@ void *sql_alloc(size_t size)
#include "sql_string.cc"
#include "sql_list.cc"
#include "rpl_filter.cc"
+#include "compat56.cc"
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 8b938580679..eafd47132ad 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2001, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2001, 2013, Oracle and/or its affiliates.
Copyright (c) 2010, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -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.4-MariaDB"
#include "client_priv.h"
#include <m_ctype.h>
@@ -43,7 +43,7 @@ static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0,
tty_password= 0, opt_frm= 0, debug_info_flag= 0, debug_check_flag= 0,
opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0,
- opt_do_tables= 1;
+ opt_persistent_all= 0, opt_do_tables= 1;
static my_bool opt_write_binlog= 1, opt_flush_tables= 0;
static uint verbose = 0, opt_mysql_port=0;
static int my_end_arg;
@@ -52,6 +52,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;
DYNAMIC_ARRAY views4repair;
static char *shared_memory_base_name=0;
@@ -159,6 +160,10 @@ static struct my_option my_long_options[] =
{"password", 'p',
"Password to use when connecting to server. If password is not given, it's solicited on the tty.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"persistent", 'Z',
+ "When using ANALYZE TABLE use the PERSISTENT FOR ALL option.",
+ &opt_persistent_all, &opt_persistent_all, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
#ifdef __WIN__
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -190,6 +195,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},
@@ -204,8 +212,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},
{"process-views", 0,
@@ -266,8 +274,11 @@ 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");
- puts("Please consult the MariaDB/MySQL knowledgebase at");
- puts("http://kb.askmonty.org/v/mysqlcheck for latest information about");
+ 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 Knowledge Base at");
+ puts("https://mariadb.com/kb/en/mysqlcheck for latest information about");
puts("this program.");
print_defaults("my", load_default_groups);
puts("");
@@ -356,8 +367,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
print_version(); exit(0);
break;
case OPT_MYSQL_PROTOCOL:
- opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
- opt->name);
+ if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
+ opt->name)) <= 0)
+ {
+ sf_leaking_memory= 1; /* no memory leak reports here */
+ exit(1);
+ }
break;
}
@@ -732,8 +747,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);
@@ -755,7 +772,7 @@ static int fix_table_storage_name(const char *name)
my_snprintf(qbuf, sizeof(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);
@@ -771,7 +788,7 @@ static int fix_database_storage_name(const char *name)
DBUG_RETURN(1);
my_snprintf(qbuf, sizeof(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);
@@ -788,12 +805,16 @@ static int rebuild_table(char *name)
if (!query)
DBUG_RETURN(1);
ptr= strxmov(query, "ALTER TABLE ", name, " FORCE", NullS);
+ if (verbose >= 3)
+ puts(query);
if (mysql_real_query(sock, query, (ulong)(ptr - query)))
{
fprintf(stderr, "Failed to %s\n", query);
fprintf(stderr, "Error: %s\n", mysql_error(sock));
rc= 1;
}
+ if (verbose)
+ printf("%-50s %s\n", name, rc ? "FAILED" : "FIXED");
my_free(query);
DBUG_RETURN(rc);
}
@@ -802,6 +823,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_FIX_NAMES)
@@ -837,10 +861,11 @@ static int use_db(char *database)
DBUG_RETURN(0);
} /* use_db */
+/* Do not send commands to replication slaves. */
static int disable_binlog()
{
- const char *stmt= "SET SQL_LOG_BIN=0";
- return run_query(stmt);
+ mysql_query(sock, "SET WSREP_ON=0"); /* ignore the error, if any */
+ return run_query("SET SQL_LOG_BIN=0", 0);
}
static int handle_request_for_tables(char *tables, size_t length,
@@ -890,6 +915,7 @@ static int handle_request_for_tables(char *tables, size_t length,
case DO_ANALYZE:
DBUG_ASSERT(!view);
op= (opt_write_binlog) ? "ANALYZE" : "ANALYZE NO_WRITE_TO_BINLOG";
+ if (opt_persistent_all) end = strmov(end, " PERSISTENT FOR ALL");
break;
case DO_OPTIMIZE:
DBUG_ASSERT(!view);
@@ -917,15 +943,18 @@ static int handle_request_for_tables(char *tables, size_t length,
org= ptr= strmov(strmov(query, op), tab_view);
ptr= fix_table_name(ptr, tables);
- strmake(table_name_buff, org, min((int) sizeof(table_name_buff)-1,
- (int) (ptr - org)));
+ strmake(table_name_buff, org, MY_MIN((int) sizeof(table_name_buff)-1,
+ (int) (ptr - org)));
table_name= table_name_buff;
ptr= strxmov(ptr, " ", options, NullS);
query_length= (size_t) (ptr - query);
}
+ if (verbose >= 3)
+ puts(query);
if (mysql_real_query(sock, query, query_length))
{
- sprintf(message, "when executing '%s%s... %s'", op, tab_view, options);
+ my_snprintf(message, sizeof(message), "when executing '%s%s... %s'",
+ op, tab_view, options);
DBerror(sock, message);
my_free(query);
DBUG_RETURN(1);
@@ -1019,31 +1048,9 @@ static void print_result()
printf("%s\n%-9s: %s", row[0], row[2], row[3]);
if (opt_auto_repair && strcmp(row[2],"note"))
{
- const char *alter_txt= strstr(row[3], "ALTER TABLE");
found_error=1;
- if (alter_txt)
- {
+ if (opt_auto_repair && strstr(row[3], "ALTER TABLE") != NULL)
table_rebuild=1;
- if (!strncmp(row[3], KEY_PARTITIONING_CHANGED_STR,
- strlen(KEY_PARTITIONING_CHANGED_STR)) &&
- strstr(alter_txt, "PARTITION BY"))
- {
- if (strlen(alter_txt) >= MAX_ALTER_STR_SIZE)
- {
- printf("Error: Alter command too long (>= %d),"
- " please do \"%s\" or dump/reload to fix it!\n",
- MAX_ALTER_STR_SIZE,
- alter_txt);
- table_rebuild= 0;
- prev_alter[0]= 0;
- }
- else
- {
- strncpy(prev_alter, alter_txt, MAX_ALTER_STR_SIZE-1);
- prev_alter[MAX_ALTER_STR_SIZE-1]= 0;
- }
- }
- }
}
}
else
@@ -1057,7 +1064,7 @@ static void print_result()
if (table_rebuild)
{
if (prev_alter[0])
- insert_dynamic(&alter_table_cmds, (uchar*) prev_alter);
+ insert_dynamic(&alter_table_cmds, prev_alter);
else
insert_table_name(&tables4rebuild, prev, length_of_db);
}
@@ -1081,8 +1088,12 @@ static int dbConnect(char *host, char *user, char *passwd)
mysql_options(&mysql_connection, MYSQL_OPT_COMPRESS, NullS);
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
+ {
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
+ }
#endif
if (opt_protocol)
mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
@@ -1096,6 +1107,9 @@ static int dbConnect(char *host, char *user, char *passwd)
mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth);
mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
+ mysql_options(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
+ mysql_options4(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_ADD,
+ "program_name", "mysqlcheck");
if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd,
NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
{
@@ -1152,9 +1166,7 @@ int main(int argc, char **argv)
/*
** Check out the args
*/
- if (load_defaults("my", load_default_groups, &argc, &argv))
- goto end2;
-
+ load_defaults_or_exit("my", load_default_groups, &argc, &argv);
defaults_argv= argv;
if (get_options(&argc, &argv))
goto end1;
@@ -1172,10 +1184,14 @@ int main(int argc, char **argv)
}
if (opt_auto_repair &&
- (my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64) ||
- my_init_dynamic_array(&views4repair, sizeof(char)*(NAME_LEN*2+2),16,64) ||
- my_init_dynamic_array(&tables4rebuild, sizeof(char)*(NAME_LEN*2+2),16,64) ||
- my_init_dynamic_array(&alter_table_cmds, MAX_ALTER_STR_SIZE, 0, 1)))
+ (my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,
+ 64, MYF(0)) ||
+ my_init_dynamic_array(&views4repair, sizeof(char)*(NAME_LEN*2+2),16,
+ 64, MYF(0)) ||
+ my_init_dynamic_array(&tables4rebuild, sizeof(char)*(NAME_LEN*2+2),16,
+ 64, MYF(0)) ||
+ my_init_dynamic_array(&alter_table_cmds, MAX_ALTER_STR_SIZE, 0, 1,
+ MYF(0))))
goto end;
if (opt_alldbs)
@@ -1201,7 +1217,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);
if (!opt_silent && views4repair.elements)
puts("\nRepairing views");
for (i = 0; i < views4repair.elements ; i++)
@@ -1210,7 +1226,7 @@ int main(int argc, char **argv)
handle_request_for_tables(name, fixed_name_length(name), TRUE, TRUE);
}
}
- ret= test(first_error);
+ ret= MY_TEST(first_error);
end:
dbDisconnect(current_host);
@@ -1226,7 +1242,6 @@ int main(int argc, char **argv)
my_free(shared_memory_base_name);
mysql_library_end();
free_defaults(defaults_argv);
- end2:
my_end(my_end_arg);
return ret;
} /* main */
diff --git a/client/mysqldump.c b/client/mysqldump.c
index ad71a4dd0ce..f00d1188502 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -39,7 +39,7 @@
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
*/
-#define DUMP_VERSION "10.14"
+#define DUMP_VERSION "10.16"
#include <my_global.h>
#include <my_sys.h>
@@ -87,14 +87,16 @@
/* 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, size_t length,
- char **err_pos, uint *err_len);
+static ulong find_set(TYPELIB *, const char *, size_t, char **, uint *);
static char *alloc_query_str(ulong size);
static void field_escape(DYNAMIC_STRING* in, const char *from);
-static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
+static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_no_data_med= 1,
quick= 1, extended_insert= 1,
lock_tables=1,ignore_errors=0,flush_logs=0,flush_privileges=0,
opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
@@ -111,7 +113,7 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
opt_slave_apply= 0,
opt_include_master_host_port= 0,
opt_events= 0, opt_comments_used= 0,
- opt_alltspcs=0, opt_notspcs= 0;
+ opt_alltspcs=0, opt_notspcs= 0, opt_logging;
static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*mysql=0;
@@ -134,10 +136,23 @@ 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;
+/*
+ multi_source is 0 if old server or 2 if server that support multi source
+ This is choosen this was as multi_source has 2 extra columns first in
+ SHOW ALL SLAVES STATUS.
+*/
+static uint multi_source= 0;
static DYNAMIC_STRING extended_row;
+static DYNAMIC_STRING dynamic_where;
+static MYSQL_RES *get_table_name_result= NULL;
+static MEM_ROOT glob_root;
+static MYSQL_RES *routine_res, *routine_list_res;
+
+
#include <sslopt-vars.h>
FILE *md_result_file= 0;
FILE *stderror_file=0;
@@ -193,6 +208,8 @@ const char *compatible_mode_names[]=
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
"", compatible_mode_names, NULL};
+#define MED_ENGINES "MRG_MyISAM, MRG_ISAM, CONNECT, OQGRAPH, SPIDER, VP, FEDERATED"
+
HASH ignore_table;
static struct my_option my_long_options[] =
@@ -226,8 +243,8 @@ static struct my_option my_long_options[] =
&opt_slave_apply, &opt_slave_apply, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
- "Directory for character set files.", (char**) &charsets_dir,
- (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ "Directory for character set files.", &charsets_dir,
+ &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"comments", 'i', "Write additional information.",
&opt_comments, &opt_comments, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
@@ -264,8 +281,8 @@ static struct my_option my_long_options[] =
{"debug", '#', "This is a non-debug version. Catch this and exit.",
0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
#else
- {"debug", '#', "Output debug log.", (char**) &default_dbug_option,
- (char**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"debug", '#', "Output debug log.", &default_dbug_option,
+ &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
&debug_check_flag, &debug_check_flag, 0,
@@ -340,6 +357,13 @@ static struct my_option my_long_options[] =
{"force", 'f', "Continue even if we get an SQL error.",
&ignore_errors, &ignore_errors, 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, "
@@ -375,6 +399,8 @@ static struct my_option my_long_options[] =
{"log-error", OPT_ERROR_LOG_FILE, "Append warnings and errors to given file.",
&log_error_file, &log_error_file, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"log-queries", 0, "When restoring the dump, the server will, if logging turned on, log the queries to the general and slow query log.",
+ &opt_logging, &opt_logging, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"master-data", OPT_MASTER_DATA,
"This causes the binary log position and filename to be appended to the "
"output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
@@ -412,6 +438,9 @@ static struct my_option my_long_options[] =
NO_ARG, 0, 0, 0, 0, 0, 0},
{"no-data", 'd', "No row information.", &opt_no_data,
&opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"no-data-med", 0, "No row information for engines that "
+ "Manage External Data (" MED_ENGINES ").", &opt_no_data_med,
+ &opt_no_data_med, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"no-set-names", 'N', "Same as --skip-set-charset.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"opt", OPT_OPTIMIZE,
@@ -680,6 +709,10 @@ static void write_header(FILE *sql_file, char *db_name)
print_comment(sql_file, 0, "-- Server version\t%s\n",
mysql_get_server_info(&mysql_connection));
+ if (!opt_logging)
+ fprintf(sql_file,
+"\n/*M!100101 SET LOCAL SQL_LOG_OFF=0, LOCAL SLOW_QUERY_LOG=0 */;");
+
if (opt_set_charset)
fprintf(sql_file,
"\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
@@ -889,7 +922,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
&err_ptr, &err_len);
if (err_len)
{
- strmake(buff, err_ptr, min(sizeof(buff) - 1, err_len));
+ strmake(buff, err_ptr, MY_MIN(sizeof(buff) - 1, err_len));
fprintf(stderr, "Invalid mode to --compatible: %s\n", buff);
exit(1);
}
@@ -923,8 +956,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
}
case (int) OPT_MYSQL_PROTOCOL:
- opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
- opt->name);
+ if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
+ opt->name)) <= 0)
+ {
+ sf_leaking_memory= 1; /* no memory leak reports here */
+ exit(1);
+ }
break;
}
return 0;
@@ -939,8 +976,7 @@ static int get_options(int *argc, char ***argv)
opt_net_buffer_length= *mysql_params->p_net_buffer_length;
md_result_file= stdout;
- if (load_defaults("my",load_default_groups,argc,argv))
- return 1;
+ load_defaults_or_exit("my", load_default_groups, argc, argv);
defaults_argv= *argv;
if (my_hash_init(&ignore_table, charset_info, 16, 0, 0,
@@ -1215,6 +1251,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,
size_t str_len,
const char *token,
@@ -1500,14 +1620,26 @@ static void free_resources()
{
if (md_result_file && md_result_file != stdout)
my_fclose(md_result_file, MYF(0));
+ if (get_table_name_result)
+ mysql_free_result(get_table_name_result);
+ if (routine_res)
+ mysql_free_result(routine_res);
+ if (routine_list_res)
+ mysql_free_result(routine_list_res);
+ if (mysql)
+ {
+ mysql_close(mysql);
+ mysql= 0;
+ }
+ my_free(order_by);
my_free(opt_password);
my_free(current_host);
+ free_root(&glob_root, MYF(0));
if (my_hash_inited(&ignore_table))
my_hash_free(&ignore_table);
- if (extended_insert)
- dynstr_free(&extended_row);
- if (insert_pat_inited)
- dynstr_free(&insert_pat);
+ dynstr_free(&extended_row);
+ dynstr_free(&dynamic_where);
+ dynstr_free(&insert_pat);
if (defaults_argv)
free_defaults(defaults_argv);
mysql_library_end();
@@ -1524,8 +1656,6 @@ static void maybe_exit(int error)
ignore_errors= 1; /* don't want to recurse, if something fails below */
if (opt_slave_data)
do_start_slave_sql(mysql);
- if (mysql)
- mysql_close(mysql);
free_resources();
exit(error);
}
@@ -1546,8 +1676,12 @@ static int connect_to_db(char *host, char *user,char *passwd)
mysql_options(&mysql_connection,MYSQL_OPT_COMPRESS,NullS);
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
+ {
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
+ }
mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(char*)&opt_ssl_verify_server_cert);
#endif
@@ -1565,6 +1699,9 @@ static int connect_to_db(char *host, char *user,char *passwd)
if (opt_default_auth && *opt_default_auth)
mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth);
+ mysql_options(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
+ mysql_options4(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_ADD,
+ "program_name", "mysqldump");
mysql= &mysql_connection; /* So we can mysql_close() it properly */
if (!mysql_real_connect(&mysql_connection,host,user,passwd,
NULL,opt_mysql_port,opt_mysql_unix_port, 0))
@@ -1611,6 +1748,7 @@ static void dbDisconnect(char *host)
{
verbose_msg("-- Disconnecting from %s...\n", host ? host : "localhost");
mysql_close(mysql);
+ mysql= 0;
} /* dbDisconnect */
@@ -1642,11 +1780,11 @@ static my_bool test_if_special_chars(const char *str)
} /* test_if_special_chars */
-
/*
quote_name(name, buff, force)
- Quotes char string, taking into account compatible mode
+ Quotes a string, if it requires quoting. To force quoting regardless
+ of the characters within the string, the force flag can be set to true.
Args
@@ -1655,8 +1793,8 @@ static my_bool test_if_special_chars(const char *str)
force Flag to make it ignore 'test_if_special_chars'
Returns
-
- buff quoted string
+ A pointer to the quoted string, or the original string if nothing has
+ changed.
*/
static char *quote_name(const char *name, char *buff, my_bool force)
@@ -1722,6 +1860,26 @@ static char *quote_for_like(const char *name, char *buff)
return buff;
}
+static char *quote_for_equal(const char *name, char *buff)
+{
+ char *to= buff;
+ *to++= '\'';
+ while (*name)
+ {
+ if (*name == '\\')
+ {
+ *to++='\\';
+ }
+ if (*name == '\'')
+ *to++= '\\';
+ *to++= *name++;
+ }
+ to[0]= '\'';
+ to[1]= 0;
+ return buff;
+
+}
+
/**
Quote and print a string.
@@ -2318,7 +2476,6 @@ static uint dump_routines_for_db(char *db)
char *routine_name;
int i;
FILE *sql_file= md_result_file;
- MYSQL_RES *routine_res, *routine_list_res;
MYSQL_ROW row, routine_list_row;
char db_cl_name[MY_CS_NAME_SIZE];
@@ -2374,7 +2531,11 @@ static uint dump_routines_for_db(char *db)
routine_type[i], routine_name);
if (mysql_query_with_error_report(mysql, &routine_res, query_buff))
+ {
+ mysql_free_result(routine_list_res);
+ routine_list_res= 0;
DBUG_RETURN(1);
+ }
while ((row= mysql_fetch_row(routine_res)))
{
@@ -2392,7 +2553,8 @@ static uint dump_routines_for_db(char *db)
print_comment(sql_file, 1,
"-- does %s have permissions on mysql.proc?\n\n",
fix_for_comment(current_user));
- maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", current_user, query_buff);
+ maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!",
+ current_user, query_buff);
}
else if (strlen(row[2]))
{
@@ -2415,6 +2577,9 @@ static uint dump_routines_for_db(char *db)
if (switch_db_collation(sql_file, db, ";",
db_cl_name, row[5], &db_cl_altered))
{
+ mysql_free_result(routine_res);
+ mysql_free_result(routine_list_res);
+ routine_res= routine_list_res= 0;
DBUG_RETURN(1);
}
@@ -2460,17 +2625,24 @@ static uint dump_routines_for_db(char *db)
if (db_cl_altered)
{
if (restore_db_collation(sql_file, db, ";", db_cl_name))
+ {
+ mysql_free_result(routine_res);
+ mysql_free_result(routine_list_res);
+ routine_res= routine_list_res= 0;
DBUG_RETURN(1);
+ }
}
}
}
} /* end of routine printing */
mysql_free_result(routine_res);
+ routine_res= 0;
} /* end of list of routines */
}
mysql_free_result(routine_list_res);
+ routine_list_res= 0;
} /* end of for i (0 .. 1) */
if (opt_xml)
@@ -2520,6 +2692,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
const char *insert_option;
char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
char table_buff2[NAME_LEN*2+3], query_buff[QUERY_LENGTH];
+ char temp_buff[NAME_LEN*2 + 3], temp_buff2[NAME_LEN*2 + 3];
const char *show_fields_stmt= "SELECT `COLUMN_NAME` AS `Field`, "
"`COLUMN_TYPE` AS `Type`, "
"`IS_NULLABLE` AS `Null`, "
@@ -2528,7 +2701,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
"`EXTRA` AS `Extra`, "
"`COLUMN_COMMENT` AS `Comment` "
"FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE "
- "TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s'";
+ "TABLE_SCHEMA = %s AND TABLE_NAME = %s";
FILE *sql_file= md_result_file;
int len;
my_bool is_log_table;
@@ -2592,13 +2765,20 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (switch_character_set_results(mysql, "binary") ||
mysql_query_with_error_report(mysql, &result, buff) ||
switch_character_set_results(mysql, default_charset))
+ {
+ my_free(order_by);
+ order_by= 0;
DBUG_RETURN(0);
+ }
if (path)
{
if (!(sql_file= open_sql_file_for_table(table, O_WRONLY)))
+ {
+ my_free(order_by);
+ order_by= 0;
DBUG_RETURN(0);
-
+ }
write_header(sql_file, db);
}
@@ -2667,6 +2847,8 @@ static uint get_table_structure(char *table, char *db, char *table_type,
my_free(scv_buff);
+ if (path)
+ my_fclose(sql_file, MYF(MY_WME));
DBUG_RETURN(0);
}
else
@@ -2834,7 +3016,9 @@ static uint get_table_structure(char *table, char *db, char *table_type,
verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
my_progname_short, mysql_error(mysql));
- my_snprintf(query_buff, sizeof(query_buff), show_fields_stmt, db, table);
+ my_snprintf(query_buff, sizeof(query_buff), show_fields_stmt,
+ quote_for_equal(db, temp_buff),
+ quote_for_equal(table, temp_buff2));
if (mysql_query_with_error_report(mysql, &result, query_buff))
DBUG_RETURN(0);
@@ -3078,7 +3262,7 @@ static void dump_trigger_old(FILE *sql_file, MYSQL_RES *show_triggers_rs,
char name_buff[NAME_LEN * 4 + 3];
const char *xml_msg= "\nWarning! mysqldump being run against old server "
- "that does not\nsupport 'SHOW CREATE TRIGGERS' "
+ "that does not\nsupport 'SHOW CREATE TRIGGER' "
"statement. Skipping..\n";
DBUG_ENTER("dump_trigger_old");
@@ -3168,10 +3352,6 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs,
continue;
}
- query_str= cover_definer_clause(row[2], strlen(row[2]),
- C_STRING_WITH_LEN("50017"),
- C_STRING_WITH_LEN("50003"),
- C_STRING_WITH_LEN(" TRIGGER"));
if (switch_db_collation(sql_file, db_name, ";",
db_cl_name, row[5], &db_cl_altered))
DBUG_RETURN(TRUE);
@@ -3183,12 +3363,18 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs,
switch_sql_mode(sql_file, ";", row[1]);
+ query_str= cover_definer_clause(row[2], strlen(row[2]),
+ C_STRING_WITH_LEN("50017"),
+ C_STRING_WITH_LEN("50003"),
+ C_STRING_WITH_LEN(" TRIGGER"));
fprintf(sql_file,
"DELIMITER ;;\n"
"/*!50003 %s */;;\n"
"DELIMITER ;\n",
(const char *) (query_str != NULL ? query_str : row[2]));
+ my_free(query_str);
+
restore_sql_mode(sql_file, ";");
restore_cs_variables(sql_file, ";");
@@ -3197,8 +3383,6 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs,
if (restore_db_collation(sql_file, db_name, ";", db_cl_name))
DBUG_RETURN(TRUE);
}
-
- my_free(query_str);
}
DBUG_RETURN(FALSE);
@@ -3229,12 +3413,14 @@ static int dump_triggers_for_table(char *table_name, char *db_name)
char db_cl_name[MY_CS_NAME_SIZE];
int ret= TRUE;
+ /* Servers below 5.1.21 do not support SHOW CREATE TRIGGER */
+ const int use_show_create_trigger= mysql_get_server_version(mysql) >= 50121;
DBUG_ENTER("dump_triggers_for_table");
DBUG_PRINT("enter", ("db: %s, table_name: %s", db_name, table_name));
- if (path && !(sql_file= open_sql_file_for_table(table_name,
- O_WRONLY | O_APPEND)))
+ if (path &&
+ !(sql_file= open_sql_file_for_table(table_name, O_WRONLY | O_APPEND)))
DBUG_RETURN(1);
/* Do not use ANSI_QUOTES on triggers in dump */
@@ -3250,9 +3436,15 @@ static int dump_triggers_for_table(char *table_name, char *db_name)
/* Get list of triggers. */
- my_snprintf(query_buff, sizeof(query_buff),
- "SHOW TRIGGERS LIKE %s",
- quote_for_like(table_name, name_buff));
+ if (use_show_create_trigger)
+ my_snprintf(query_buff, sizeof(query_buff),
+ "SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS "
+ "WHERE EVENT_OBJECT_SCHEMA = DATABASE() AND "
+ "EVENT_OBJECT_TABLE = %s",
+ quote_for_equal(table_name, name_buff));
+ else
+ my_snprintf(query_buff, sizeof(query_buff), "SHOW TRIGGERS LIKE %s",
+ quote_for_like(table_name, name_buff));
if (mysql_query_with_error_report(mysql, &show_triggers_rs, query_buff))
goto done;
@@ -3268,34 +3460,28 @@ static int dump_triggers_for_table(char *table_name, char *db_name)
while ((row= mysql_fetch_row(show_triggers_rs)))
{
-
- my_snprintf(query_buff, sizeof (query_buff),
- "SHOW CREATE TRIGGER %s",
- quote_name(row[0], name_buff, TRUE));
-
- if (mysql_query(mysql, query_buff))
+ if (use_show_create_trigger)
{
- /*
- mysqldump is being run against old server, that does not support
- SHOW CREATE TRIGGER statement. We should use SHOW TRIGGERS output.
-
- NOTE: the dump may be incorrect, as old SHOW TRIGGERS does not
- provide all the necessary information to restore trigger properly.
- */
+ MYSQL_RES *show_create_trigger_rs;
- dump_trigger_old(sql_file, show_triggers_rs, &row, table_name);
- }
- else
- {
- MYSQL_RES *show_create_trigger_rs= mysql_store_result(mysql);
+ my_snprintf(query_buff, sizeof (query_buff), "SHOW CREATE TRIGGER %s",
+ quote_name(row[0], name_buff, TRUE));
- if (!show_create_trigger_rs ||
- dump_trigger(sql_file, show_create_trigger_rs, db_name, db_cl_name))
+ if (mysql_query_with_error_report(mysql, &show_create_trigger_rs,
+ query_buff))
goto done;
-
- mysql_free_result(show_create_trigger_rs);
+ else
+ {
+ int error= (!show_create_trigger_rs ||
+ dump_trigger(sql_file, show_create_trigger_rs, db_name,
+ db_cl_name));
+ mysql_free_result(show_create_trigger_rs);
+ if (error)
+ goto done;
+ }
}
-
+ else
+ dump_trigger_old(sql_file, show_triggers_rs, &row, table_name);
}
if (opt_xml)
@@ -3542,12 +3728,14 @@ static void dump_table(char *table, char *db)
{
dynstr_append_checked(&query_string, " ORDER BY ");
dynstr_append_checked(&query_string, order_by);
+ my_free(order_by);
+ order_by= 0;
}
if (mysql_real_query(mysql, query_string.str, query_string.length))
{
- DB_error(mysql, "when executing 'SELECT INTO OUTFILE'");
dynstr_free(&query_string);
+ DB_error(mysql, "when executing 'SELECT INTO OUTFILE'");
DBUG_VOID_RETURN;
}
}
@@ -3573,6 +3761,8 @@ static void dump_table(char *table, char *db)
dynstr_append_checked(&query_string, " ORDER BY ");
dynstr_append_checked(&query_string, order_by);
+ my_free(order_by);
+ order_by= 0;
}
if (!opt_xml && !opt_compact)
@@ -3582,6 +3772,7 @@ static void dump_table(char *table, char *db)
}
if (mysql_query_with_error_report(mysql, 0, query_string.str))
{
+ dynstr_free(&query_string);
DB_error(mysql, "when retrieving data from server");
goto err;
}
@@ -3591,6 +3782,7 @@ static void dump_table(char *table, char *db)
res=mysql_store_result(mysql);
if (!res)
{
+ dynstr_free(&query_string);
DB_error(mysql, "when retrieving data from server");
goto err;
}
@@ -3906,23 +4098,22 @@ err:
static char *getTableName(int reset)
{
- static MYSQL_RES *res= NULL;
- MYSQL_ROW row;
+ MYSQL_ROW row;
- if (!res)
+ if (!get_table_name_result)
{
- if (!(res= mysql_list_tables(mysql,NullS)))
+ if (!(get_table_name_result= mysql_list_tables(mysql,NullS)))
return(NULL);
}
- if ((row= mysql_fetch_row(res)))
+ if ((row= mysql_fetch_row(get_table_name_result)))
return((char*) row[0]);
if (reset)
- mysql_data_seek(res,0); /* We want to read again */
+ mysql_data_seek(get_table_name_result,0); /* We want to read again */
else
{
- mysql_free_result(res);
- res= NULL;
+ mysql_free_result(get_table_name_result);
+ get_table_name_result= NULL;
}
return(NULL);
} /* getTableName */
@@ -3939,46 +4130,44 @@ static int dump_all_tablespaces()
static int dump_tablespaces_for_tables(char *db, char **table_names, int tables)
{
- DYNAMIC_STRING where;
int r;
int i;
char name_buff[NAME_LEN*2+3];
mysql_real_escape_string(mysql, name_buff, db, (ulong)strlen(db));
- init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN ("
+ init_dynamic_string_checked(&dynamic_where, " AND TABLESPACE_NAME IN ("
"SELECT DISTINCT TABLESPACE_NAME FROM"
" INFORMATION_SCHEMA.PARTITIONS"
" WHERE"
" TABLE_SCHEMA='", 256, 1024);
- dynstr_append_checked(&where, name_buff);
- dynstr_append_checked(&where, "' AND TABLE_NAME IN (");
+ dynstr_append_checked(&dynamic_where, name_buff);
+ dynstr_append_checked(&dynamic_where, "' AND TABLE_NAME IN (");
for (i=0 ; i<tables ; i++)
{
mysql_real_escape_string(mysql, name_buff,
table_names[i], (ulong)strlen(table_names[i]));
- dynstr_append_checked(&where, "'");
- dynstr_append_checked(&where, name_buff);
- dynstr_append_checked(&where, "',");
+ dynstr_append_checked(&dynamic_where, "'");
+ dynstr_append_checked(&dynamic_where, name_buff);
+ dynstr_append_checked(&dynamic_where, "',");
}
- dynstr_trunc(&where, 1);
- dynstr_append_checked(&where,"))");
+ dynstr_trunc(&dynamic_where, 1);
+ dynstr_append_checked(&dynamic_where,"))");
- DBUG_PRINT("info",("Dump TS for Tables where: %s",where.str));
- r= dump_tablespaces(where.str);
- dynstr_free(&where);
+ DBUG_PRINT("info",("Dump TS for Tables where: %s",dynamic_where.str));
+ r= dump_tablespaces(dynamic_where.str);
+ dynstr_free(&dynamic_where);
return r;
}
static int dump_tablespaces_for_databases(char** databases)
{
- DYNAMIC_STRING where;
int r;
int i;
- init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN ("
+ init_dynamic_string_checked(&dynamic_where, " AND TABLESPACE_NAME IN ("
"SELECT DISTINCT TABLESPACE_NAME FROM"
" INFORMATION_SCHEMA.PARTITIONS"
" WHERE"
@@ -3989,16 +4178,16 @@ static int dump_tablespaces_for_databases(char** databases)
char db_name_buff[NAME_LEN*2+3];
mysql_real_escape_string(mysql, db_name_buff,
databases[i], (ulong)strlen(databases[i]));
- dynstr_append_checked(&where, "'");
- dynstr_append_checked(&where, db_name_buff);
- dynstr_append_checked(&where, "',");
+ dynstr_append_checked(&dynamic_where, "'");
+ dynstr_append_checked(&dynamic_where, db_name_buff);
+ dynstr_append_checked(&dynamic_where, "',");
}
- dynstr_trunc(&where, 1);
- dynstr_append_checked(&where,"))");
+ dynstr_trunc(&dynamic_where, 1);
+ dynstr_append_checked(&dynamic_where,"))");
- DBUG_PRINT("info",("Dump TS for DBs where: %s",where.str));
- r= dump_tablespaces(where.str);
- dynstr_free(&where);
+ DBUG_PRINT("info",("Dump TS for DBs where: %s",dynamic_where.str));
+ r= dump_tablespaces(dynamic_where.str);
+ dynstr_free(&dynamic_where);
return r;
}
@@ -4408,9 +4597,12 @@ static int dump_all_tables_in_db(char *database)
}
}
if (numrows && mysql_real_query(mysql, query.str, query.length-1))
+ {
+ dynstr_free(&query);
DB_error(mysql, "when using LOCK TABLES");
- /* We shall continue here, if --force was given */
- dynstr_free(&query);
+ /* We shall continue here, if --force was given */
+ }
+ dynstr_free(&query); /* Safe to call twice */
}
if (flush_logs)
{
@@ -4420,6 +4612,14 @@ static int dump_all_tables_in_db(char *database)
else
verbose_msg("-- dump_all_tables_in_db : logs flushed successfully!\n");
}
+ if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500)
+ {
+ verbose_msg("-- Setting savepoint...\n");
+ if (mysql_query_with_error_report(mysql, 0, "SAVEPOINT sp"))
+ {
+ DBUG_RETURN(1);
+ }
+ }
while ((table= getTableName(0)))
{
char *end= strmov(afterdot, table);
@@ -4437,6 +4637,23 @@ static int dump_all_tables_in_db(char *database)
maybe_exit(EX_MYSQLERR);
}
}
+
+ /**
+ ROLLBACK TO SAVEPOINT in --single-transaction mode to release metadata
+ lock on table which was already dumped. This allows to avoid blocking
+ concurrent DDL on this table without sacrificing correctness, as we
+ won't access table second time and dumps created by --single-transaction
+ mode have validity point at the start of transaction anyway.
+ Note that this doesn't make --single-transaction mode with concurrent
+ DDL safe in general case. It just improves situation for people for whom
+ it might be working.
+ */
+ if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500)
+ {
+ verbose_msg("-- Rolling back to savepoint sp...\n");
+ if (mysql_query_with_error_report(mysql, 0, "ROLLBACK TO SAVEPOINT sp"))
+ maybe_exit(EX_MYSQLERR);
+ }
}
else
{
@@ -4459,6 +4676,14 @@ static int dump_all_tables_in_db(char *database)
}
}
}
+
+ if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500)
+ {
+ verbose_msg("-- Releasing savepoint...\n");
+ if (mysql_query_with_error_report(mysql, 0, "RELEASE SAVEPOINT sp"))
+ DBUG_RETURN(1);
+ }
+
if (opt_events && mysql_get_server_version(mysql) >= 50106)
{
DBUG_PRINT("info", ("Dumping events for database %s", database));
@@ -4576,29 +4801,37 @@ static my_bool dump_all_views_in_db(char *database)
/*
- get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
- table name from the server for the table name given on the command line.
- we do this because the table name given on the command line may be a
- different case (e.g. T1 vs t1)
-
- RETURN
- pointer to the table name
- 0 if error
+ See get_actual_table_name. Used to retrieve the correct table name
+ from the database schema.
*/
-
-static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
+static char *get_actual_table_name_helper(const char *old_table_name,
+ my_bool case_sensitive,
+ MEM_ROOT *root)
{
char *name= 0;
MYSQL_RES *table_res;
MYSQL_ROW row;
char query[50 + 2*NAME_LEN];
char show_name_buff[FN_REFLEN];
- DBUG_ENTER("get_actual_table_name");
+ DBUG_ENTER("get_actual_table_name_helper");
/* Check memory for quote_for_like() */
DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff));
- my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
- quote_for_like(old_table_name, show_name_buff));
+
+ if (case_sensitive)
+ {
+ DBUG_PRINT("info", ("case sensitive search"));
+ my_snprintf(query, sizeof(query),
+ "SELECT table_name FROM INFORMATION_SCHEMA.TABLES "
+ "WHERE table_schema = DATABASE() AND table_name = %s",
+ quote_for_equal(old_table_name, show_name_buff));
+ }
+ else
+ {
+ DBUG_PRINT("info", ("case insensitive search"));
+ my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
+ quote_for_like(old_table_name, show_name_buff));
+ }
if (mysql_query_with_error_report(mysql, 0, query))
return NullS;
@@ -4623,27 +4856,86 @@ static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
DBUG_RETURN(name);
}
+/*
+ get_actual_table_name -- executes a SELECT .. FROM I_S.tables to check
+ if the table name given on the command line matches the one in the database.
+ If the table is not found, it falls back to a slower SHOW TABLES LIKE '%s' to
+ get the actual table name from the server.
+
+ We do this because the table name given on the command line may be a
+ different case (e.g. T1 vs t1), but checking this takes a long time
+ when there are many tables present.
+
+ RETURN
+ pointer to the table name
+ 0 if error
+*/
+
+static char *get_actual_table_name(const char *old_table_name,
+ int lower_case_table_names,
+ MEM_ROOT *root)
+{
+ char *name= 0;
+ DBUG_ENTER("get_actual_table_name");
+
+ name= get_actual_table_name_helper(old_table_name, TRUE, root);
+ if (!name && !lower_case_table_names)
+ name= get_actual_table_name_helper(old_table_name, FALSE, root);
+ DBUG_RETURN(name);
+}
+
+/*
+ Retrieve the value for the server system variable lower_case_table_names.
+
+ RETURN
+ 0 case sensitive.
+ > 0 case insensitive
+*/
+static int get_sys_var_lower_case_table_names()
+{
+ int lower_case_table_names = 0;
+ MYSQL_RES *table_res;
+ MYSQL_ROW row;
+ const char *show_var_query = "SHOW VARIABLES LIKE 'lower_case_table_names'";
+ if (mysql_query_with_error_report(mysql, &table_res, show_var_query))
+ return 0; /* In case of error, assume default value of 0 */
+
+ if ((row= mysql_fetch_row(table_res)))
+ {
+ lower_case_table_names= atoi(row[1]);
+ mysql_free_result(table_res);
+ }
+
+ return lower_case_table_names;
+}
+
+
static int dump_selected_tables(char *db, char **table_names, int tables)
{
char table_buff[NAME_LEN*2+3];
DYNAMIC_STRING lock_tables_query;
- MEM_ROOT root;
char **dump_tables, **pos, **end;
+ int lower_case_table_names;
DBUG_ENTER("dump_selected_tables");
if (init_dumping(db, init_dumping_tables))
DBUG_RETURN(1);
- init_alloc_root(&root, 8192, 0);
- if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
+ init_alloc_root(&glob_root, 8192, 0, MYF(0));
+ if (!(dump_tables= pos= (char**) alloc_root(&glob_root,
+ tables * sizeof(char *))))
die(EX_EOM, "alloc_root failure.");
+ /* Figure out how to compare table names. */
+ lower_case_table_names = get_sys_var_lower_case_table_names();
+
init_dynamic_string_checked(&lock_tables_query, "LOCK TABLES ", 256, 1024);
for (; tables > 0 ; tables-- , table_names++)
{
/* the table name passed on commandline may be wrong case */
- if ((*pos= get_actual_table_name(*table_names, &root)))
+ if ((*pos= get_actual_table_name(*table_names, lower_case_table_names,
+ &glob_root)))
{
/* Add found table name to lock_tables_query */
if (lock_tables)
@@ -4658,7 +4950,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
if (!ignore_errors)
{
dynstr_free(&lock_tables_query);
- free_root(&root, MYF(0));
+ free_root(&glob_root, MYF(0));
}
maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names);
/* We shall countinue here, if --force was given */
@@ -4679,7 +4971,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
if (!ignore_errors)
{
dynstr_free(&lock_tables_query);
- free_root(&root, MYF(0));
+ free_root(&glob_root, MYF(0));
}
DB_error(mysql, "when doing LOCK TABLES");
/* We shall countinue here, if --force was given */
@@ -4691,7 +4983,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
if (mysql_refresh(mysql, REFRESH_LOG))
{
if (!ignore_errors)
- free_root(&root, MYF(0));
+ free_root(&glob_root, MYF(0));
DB_error(mysql, "when doing refresh");
}
/* We shall countinue here, if --force was given */
@@ -4701,12 +4993,23 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
if (opt_xml)
print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NullS);
+
/* obtain dump of routines (procs/functions) */
if (opt_routines && mysql_get_server_version(mysql) >= 50009)
{
DBUG_PRINT("info", ("Dumping routines for database %s", db));
dump_routines_for_db(db);
}
+
+ if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500)
+ {
+ verbose_msg("-- Setting savepoint...\n");
+ if (mysql_query_with_error_report(mysql, 0, "SAVEPOINT sp"))
+ {
+ free_root(&glob_root, MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
/* Dump each selected table */
for (pos= dump_tables; pos < end; pos++)
{
@@ -4719,11 +5022,44 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
{
if (path)
my_fclose(md_result_file, MYF(MY_WME));
+ if (!ignore_errors)
+ free_root(&glob_root, MYF(0));
+ maybe_exit(EX_MYSQLERR);
+ }
+ }
+
+ /**
+ ROLLBACK TO SAVEPOINT in --single-transaction mode to release metadata
+ lock on table which was already dumped. This allows to avoid blocking
+ concurrent DDL on this table without sacrificing correctness, as we
+ won't access table second time and dumps created by --single-transaction
+ mode have validity point at the start of transaction anyway.
+ Note that this doesn't make --single-transaction mode with concurrent
+ DDL safe in general case. It just improves situation for people for whom
+ it might be working.
+ */
+ if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500)
+ {
+ verbose_msg("-- Rolling back to savepoint sp...\n");
+ if (mysql_query_with_error_report(mysql, 0, "ROLLBACK TO SAVEPOINT sp"))
+ {
+ if (!ignore_errors)
+ free_root(&glob_root, MYF(0));
maybe_exit(EX_MYSQLERR);
}
}
}
+ if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500)
+ {
+ verbose_msg("-- Releasing savepoint...\n");
+ if (mysql_query_with_error_report(mysql, 0, "RELEASE SAVEPOINT sp"))
+ {
+ free_root(&glob_root, MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
+
/* Dump each selected view */
if (seen_views)
{
@@ -4735,9 +5071,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
DBUG_PRINT("info", ("Dumping events for database %s", db));
dump_events_for_db(db);
}
- free_root(&root, MYF(0));
- my_free(order_by);
- order_by= 0;
+ free_root(&glob_root, MYF(0));
if (opt_xml)
{
fputs("</database>\n", md_result_file);
@@ -4749,12 +5083,14 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
} /* dump_selected_tables */
-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) ? "-- " : "";
@@ -4765,10 +5101,14 @@ 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
{
- if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS"))
+ if (mysql_query_with_error_report(mysql_con, &master,
+ "SHOW MASTER STATUS"))
return 1;
row= mysql_fetch_row(master);
@@ -4793,6 +5133,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 */
@@ -4801,7 +5144,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)
@@ -4813,29 +5168,37 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
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"))
+ MYSQL_ROW row;
+
+ if (mysql_query_with_error_report(mysql_con, &slave,
+ multi_source ?
+ "SHOW ALL SLAVES STATUS" :
+ "SHOW SLAVE STATUS"))
return(1);
- else
+
+ /* Loop over all slaves */
+ while ((row= mysql_fetch_row(slave)))
{
- MYSQL_ROW row= mysql_fetch_row(slave);
- if (row && row[11])
+ if (row[11 + multi_source])
{
/* if SLAVE SQL is not running, we don't stop it */
- if (!strcmp(row[11],"No"))
+ if (strcmp(row[11 + multi_source], "No"))
{
- mysql_free_result(slave);
- /* Silently assume that they don't have the slave running */
- return(0);
+ char query[160];
+ if (multi_source)
+ sprintf(query, "STOP SLAVE '%.80s' SQL_THREAD", row[0]);
+ else
+ strmov(query, "STOP SLAVE SQL_THREAD");
+
+ if (mysql_query_with_error_report(mysql_con, 0, query))
+ {
+ mysql_free_result(slave);
+ return 1;
+ }
}
}
}
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);
}
@@ -4844,7 +5207,10 @@ 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");
+ if (multi_source)
+ fprintf(md_result_file, "STOP ALL SLAVES;\n");
+ else
+ fprintf(md_result_file, "STOP SLAVE;\n");
return(0);
}
@@ -4853,16 +5219,28 @@ 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");
+ if (multi_source)
+ fprintf(md_result_file, "START ALL SLAVES;\n");
+ else
+ fprintf(md_result_file, "START SLAVE;\n");
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 *slave= 0;
+ MYSQL_RES *UNINIT_VAR(slave);
+ MYSQL_ROW row;
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"))
+ 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 ?
+ "SHOW ALL SLAVES STATUS" :
+ "SHOW SLAVE STATUS"))
{
if (!ignore_errors)
{
@@ -4872,65 +5250,103 @@ static int do_show_slave_status(MYSQL *mysql_con)
mysql_free_result(slave);
return 1;
}
- else
+
+ while ((row= mysql_fetch_row(slave)))
{
- MYSQL_ROW row= mysql_fetch_row(slave);
- if (row && row[9] && row[21])
+ 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,
"\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 (multi_source)
+ fprintf(md_result_file, "%sCHANGE MASTER '%.80s' TO ",
+ nogtid_comment_prefix, row[0]);
+ else
+ fprintf(md_result_file, "%sCHANGE MASTER TO ", nogtid_comment_prefix);
+
if (opt_include_master_host_port)
{
- if (row[1])
- fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
+ if (row[1 + multi_source])
+ fprintf(md_result_file, "MASTER_HOST='%s', ", row[1 + multi_source]);
if (row[3])
- fprintf(md_result_file, "MASTER_PORT=%s, ", row[3]);
+ fprintf(md_result_file, "MASTER_PORT=%s, ", row[3 + multi_source]);
}
fprintf(md_result_file,
- "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
+ "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
+ row[9 + multi_source], row[21 + multi_source]);
check_io(md_result_file);
}
- mysql_free_result(slave);
}
+ mysql_free_result(slave);
return 0;
}
static int do_start_slave_sql(MYSQL *mysql_con)
{
MYSQL_RES *slave;
+ MYSQL_ROW row;
+ int error= 0;
+ DBUG_ENTER("do_start_slave_sql");
+
/* 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
+ if (mysql_query_with_error_report(mysql_con, &slave,
+ multi_source ?
+ "SHOW ALL SLAVES STATUS" :
+ "SHOW SLAVE STATUS"))
+ DBUG_RETURN(1);
+
+ while ((row= mysql_fetch_row(slave)))
{
- MYSQL_ROW row= mysql_fetch_row(slave);
- if (row && row[11])
+ DBUG_PRINT("info", ("Connection: '%s' status: '%s'",
+ multi_source ? row[0] : "", row[11 + multi_source]));
+ if (row[11 + multi_source])
{
/* if SLAVE SQL is not running, we don't start it */
- if (!strcmp(row[11],"Yes"))
+ if (strcmp(row[11 + multi_source], "Yes"))
{
- mysql_free_result(slave);
- /* Silently assume that they don't have the slave running */
- return(0);
+ char query[160];
+ if (multi_source)
+ sprintf(query, "START SLAVE '%.80s'", row[0]);
+ else
+ strmov(query, "START SLAVE");
+
+ if (mysql_query_with_error_report(mysql_con, 0, query))
+ {
+ fprintf(stderr, "%s: Error: Unable to start slave '%s'\n",
+ my_progname_short, multi_source ? row[0] : "");
+ error= 1;
+ }
}
}
}
mysql_free_result(slave);
-
- /* now, start slave if stopped */
- if (mysql_query_with_error_report(mysql_con, 0, "START SLAVE"))
- {
- fprintf(stderr, "%s: Error: Unable to start slave\n", my_progname_short);
- return 1;
- }
- return(0);
+ DBUG_RETURN(error);
}
@@ -4944,12 +5360,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") );
}
@@ -5054,9 +5471,9 @@ static ulong find_set(TYPELIB *lib, const char *x, size_t length,
for (; pos != end && *pos != ','; pos++) ;
var_len= (uint) (pos - start);
- strmake(buff, start, min(sizeof(buff) - 1, var_len));
+ strmake(buff, start, MY_MIN(sizeof(buff) - 1, var_len));
find= find_type(buff, lib, FIND_TYPE_BASIC);
- if (!find)
+ if (find <= 0)
{
*err_pos= (char*) start;
*err_len= var_len;
@@ -5135,8 +5552,10 @@ char check_if_ignore_table(const char *table_name, char *table_type)
/* Check memory for quote_for_like() */
DBUG_ASSERT(2*sizeof(table_name) < sizeof(show_name_buff));
- my_snprintf(buff, sizeof(buff), "show table status like %s",
- quote_for_like(table_name, show_name_buff));
+ my_snprintf(buff, sizeof(buff),
+ "SELECT engine FROM INFORMATION_SCHEMA.TABLES "
+ "WHERE table_schema = DATABASE() AND table_name = %s",
+ quote_for_equal(table_name, show_name_buff));
if (mysql_query_with_error_report(mysql, &res, buff))
{
if (mysql_errno(mysql) != ER_PARSE_ERROR)
@@ -5154,7 +5573,7 @@ char check_if_ignore_table(const char *table_name, char *table_type)
mysql_free_result(res);
DBUG_RETURN(result); /* assume table is ok */
}
- if (!(row[1]))
+ if (!(row[0]))
strmake(table_type, "VIEW", NAME_LEN-1);
else
{
@@ -5164,7 +5583,7 @@ char check_if_ignore_table(const char *table_name, char *table_type)
these types, but we do want to use delayed inserts in the dump if
the table type is _NOT_ one of these types
*/
- strmake(table_type, row[1], NAME_LEN-1);
+ strmake(table_type, row[0], NAME_LEN-1);
if (opt_delayed)
{
if (strcmp(table_type,"MyISAM") &&
@@ -5178,11 +5597,12 @@ char check_if_ignore_table(const char *table_name, char *table_type)
/*
If these two types, we do want to skip dumping the table
*/
- if (!opt_no_data &&
- (!my_strcasecmp(&my_charset_latin1, table_type, "MRG_MyISAM") ||
- !strcmp(table_type,"MRG_ISAM") ||
- !strcmp(table_type,"FEDERATED")))
- result= IGNORE_DATA;
+ if (!opt_no_data && opt_no_data_med)
+ {
+ const char *found= strstr(" " MED_ENGINES ",", table_type);
+ if (found && found[-1] == ' ' && found[strlen(table_type)] == ',')
+ result= IGNORE_DATA;
+ }
}
mysql_free_result(res);
DBUG_RETURN(result);
@@ -5511,8 +5931,7 @@ static my_bool get_view_structure(char *table, char* db)
dynstr_free(&ds_view);
}
- if (switch_character_set_results(mysql, default_charset))
- DBUG_RETURN(1);
+ switch_character_set_results(mysql, default_charset);
/* If a separate .sql file was opened, close it now */
if (sql_file != md_result_file)
@@ -5569,6 +5988,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 */
@@ -5607,6 +6027,13 @@ int main(int argc, char **argv)
if (!path)
write_header(md_result_file, *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;
@@ -5652,9 +6079,12 @@ int main(int argc, char **argv)
/* 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, 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;
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 9fd96965213..a9c24e20b0a 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -249,8 +249,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
#endif
case OPT_MYSQL_PROTOCOL:
- opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
- opt->name);
+ if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
+ opt->name)) <= 0)
+ {
+ sf_leaking_memory= 1; /* no memory leak reports here */
+ exit(1);
+ }
break;
case '#':
DBUG_PUSH(argument ? argument : "d:t:o");
@@ -442,8 +446,12 @@ static MYSQL *db_connect(char *host, char *database,
(char*) &opt_local_file);
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
+ {
mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
+ }
mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(char*)&opt_ssl_verify_server_cert);
#endif
@@ -461,6 +469,9 @@ static MYSQL *db_connect(char *host, char *database,
mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
+ mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
+ "program_name", "mysqlimport");
if (!(mysql_real_connect(mysql,host,user,passwd,
database,opt_mysql_port,opt_mysql_unix_port,
0)))
@@ -489,7 +500,6 @@ static void db_disconnect(char *host, MYSQL *mysql)
}
-
static void safe_exit(int error, MYSQL *mysql)
{
if (error && ignore_errors)
@@ -508,7 +518,10 @@ static void safe_exit(int error, MYSQL *mysql)
free_defaults(argv_to_free);
mysql_library_end();
my_free(opt_password);
- my_end(my_end_arg);
+ if (error)
+ sf_leaking_memory= 1; /* dirty exit, some threads are still running */
+ else
+ my_end(my_end_arg); /* clean exit */
exit(error);
}
@@ -628,8 +641,7 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
sf_leaking_memory=1; /* don't report memory leaks on early exits */
- if (load_defaults("my",load_default_groups,&argc,&argv))
- return 1;
+ load_defaults_or_exit("my", load_default_groups, &argc, &argv);
/* argv is changed in the program */
argv_to_free= argv;
if (get_options(&argc, &argv))
@@ -666,7 +678,7 @@ int main(int argc, char **argv)
MYF(0))))
return -2;
- for (counter= 0; *argv != NULL; argv++) /* Loop through tables */
+ for (; *argv != NULL; argv++) /* Loop through tables */
{
pthread_mutex_lock(&counter_mutex);
while (counter == opt_use_threads)
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 8bfbd87aca6..95ee8d697f3 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -68,10 +68,11 @@ int main(int argc, char **argv)
my_bool first_argument_uses_wildcards=0;
char *wild;
MYSQL mysql;
+ static char **defaults_argv;
MY_INIT(argv[0]);
sf_leaking_memory=1; /* don't report memory leaks on early exits */
- if (load_defaults("my",load_default_groups,&argc,&argv))
- exit(1);
+ load_defaults_or_exit("my", load_default_groups, &argc, &argv);
+ defaults_argv=argv;
get_options(&argc,&argv);
@@ -118,8 +119,12 @@ int main(int argc, char **argv)
mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
+ {
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
+ }
mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(char*)&opt_ssl_verify_server_cert);
#endif
@@ -137,13 +142,17 @@ int main(int argc, char **argv)
if (opt_default_auth && *opt_default_auth)
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+ mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
+ mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
+ "program_name", "mysqlshow");
if (!(mysql_real_connect(&mysql,host,user,opt_password,
(first_argument_uses_wildcards) ? "" :
argv[0],opt_mysql_port,opt_mysql_unix_port,
0)))
{
fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
- exit(1);
+ error= 1;
+ goto error;
}
mysql.reconnect= 1;
@@ -162,11 +171,14 @@ int main(int argc, char **argv)
error=list_fields(&mysql,argv[0],argv[1],wild);
break;
}
+error:
mysql_close(&mysql); /* Close & free connection */
my_free(opt_password);
+ mysql_server_end();
#ifdef HAVE_SMEM
my_free(shared_memory_base_name);
#endif
+ free_defaults(defaults_argv);
my_end(my_end_arg);
exit(error ? 1 : 0);
return 0; /* No compiler warnings */
@@ -315,8 +327,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
#endif
break;
case OPT_MYSQL_PROTOCOL:
- opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
- opt->name);
+ if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
+ opt->name)) <= 0)
+ {
+ sf_leaking_memory= 1; /* no memory leak reports here */
+ exit(1);
+ }
break;
case '#':
DBUG_PUSH(argument ? argument : "d:t:o");
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index ba7b8cea6a9..fd30776446d 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -85,9 +85,7 @@ TODO:
#include <mysqld_error.h>
#include <my_dir.h>
#include <signal.h>
-#include <stdarg.h>
#include <sslopt-vars.h>
-#include <sys/types.h>
#ifndef __WIN__
#include <sys/wait.h>
#endif
@@ -170,6 +168,7 @@ static ulonglong auto_generate_sql_number;
const char *concurrency_str= NULL;
static char *create_string;
uint *concurrency;
+static char mysql_charsets_dir[FN_REFLEN+1];
const char *default_dbug_option="d:t:o,/tmp/mysqlslap.trace";
const char *opt_csv_str;
@@ -301,8 +300,12 @@ void set_mysql_connect_options(MYSQL *mysql)
mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS);
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
+ {
mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
+ }
#endif
if (opt_protocol)
mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
@@ -322,11 +325,7 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
sf_leaking_memory=1; /* don't report memory leaks on early exits */
- if (load_defaults("my",load_default_groups,&argc,&argv))
- {
- my_end(0);
- exit(1);
- }
+ load_defaults_or_exit("my", load_default_groups, &argc, &argv);
defaults_argv=argv;
if (get_options(&argc,&argv))
{
@@ -359,6 +358,9 @@ int main(int argc, char **argv)
if (opt_default_auth && *opt_default_auth)
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+ mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
+ mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
+ "program_name", "mysqlslap");
if (!opt_only_print)
{
if (!(mysql_real_connect(&mysql, host, user, opt_password,
@@ -367,6 +369,7 @@ int main(int argc, char **argv)
{
fprintf(stderr,"%s: Error when connecting to server: %s\n",
my_progname,mysql_error(&mysql));
+ mysql_close(&mysql);
free_defaults(defaults_argv);
my_end(0);
exit(1);
@@ -412,8 +415,7 @@ int main(int argc, char **argv)
pthread_mutex_destroy(&sleeper_mutex);
pthread_cond_destroy(&sleep_threshhold);
- if (!opt_only_print)
- mysql_close(&mysql); /* Close & free connection */
+ mysql_close(&mysql); /* Close & free connection */
/* now free all the strings we created */
my_free(opt_password);
@@ -580,6 +582,9 @@ static struct my_option my_long_options[] =
"Number of row inserts to perform for each thread (default is 100).",
&auto_generate_sql_number, &auto_generate_sql_number,
0, GET_ULL, REQUIRED_ARG, 100, 0, 0, 0, 0, 0},
+ {"character-sets-dir", OPT_CHARSETS_DIR,
+ "Directory for character set files.", &charsets_dir,
+ &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"commit", OPT_SLAP_COMMIT, "Commit records every X number of statements.",
&commit_rate, &commit_rate, 0, GET_UINT, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
@@ -770,13 +775,21 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
#endif
break;
case OPT_MYSQL_PROTOCOL:
- opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
- opt->name);
+ if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
+ opt->name)) <= 0)
+ {
+ sf_leaking_memory= 1; /* no memory leak reports here */
+ exit(1);
+ }
break;
case '#':
DBUG_PUSH(argument ? argument : default_dbug_option);
debug_check_flag= 1;
break;
+ case OPT_CHARSETS_DIR:
+ strmake_buf(mysql_charsets_dir, argument);
+ charsets_dir = mysql_charsets_dir;
+ break;
case OPT_SLAP_CSV:
if (!argument)
argument= (char *)"-"; /* use stdout */
@@ -1808,8 +1821,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);
@@ -1858,21 +1871,21 @@ pthread_handler_t run_task(void *p)
}
pthread_mutex_unlock(&sleeper_mutex);
- if (!(mysql= mysql_init(NULL)))
+ if (mysql_thread_init())
{
- fprintf(stderr,"%s: mysql_init() failed ERROR : %s\n",
- my_progname, mysql_error(mysql));
+ fprintf(stderr,"%s: mysql_thread_init() failed\n", my_progname);
exit(0);
}
- set_mysql_connect_options(mysql);
- if (mysql_thread_init())
+ if (!(mysql= mysql_init(NULL)))
{
- fprintf(stderr,"%s: mysql_thread_init() failed ERROR : %s\n",
- my_progname, mysql_error(mysql));
+ fprintf(stderr,"%s: mysql_init() failed\n", my_progname);
+ mysql_thread_end();
exit(0);
}
+ set_mysql_connect_options(mysql);
+
DBUG_PRINT("info", ("trying to connect to host %s as user %s", host, user));
if (!opt_only_print)
@@ -1990,8 +2003,7 @@ end:
if (commit_rate)
run_query(mysql, "COMMIT", strlen("COMMIT"));
- if (!opt_only_print)
- mysql_close(mysql);
+ mysql_close(mysql);
mysql_thread_end();
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 842bde3b99e..cc1d61e5d79 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -33,7 +33,7 @@
And many others
*/
-#define MTEST_VERSION "3.4"
+#define MTEST_VERSION "3.5"
#include "client_priv.h"
#include <mysql_version.h>
@@ -44,7 +44,8 @@
#include <hash.h>
#include <stdarg.h>
#include <violite.h>
-#include "my_regex.h" /* Our own version of regex */
+#define PCRE_STATIC 1 /* Important on Windows */
+#include "pcreposix.h" /* pcreposix regex library */
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
@@ -87,6 +88,8 @@ static my_bool non_blocking_api_enabled= 0;
#define QUERY_SEND_FLAG 1
#define QUERY_REAP_FLAG 2
+#define QUERY_PRINT_ORIGINAL_FLAG 4
+
#ifndef HAVE_SETENV
static int setenv(const char *name, const char *value, int overwrite);
#endif
@@ -178,6 +181,7 @@ static uint my_end_arg= 0;
static uint opt_tail_lines= 0;
static uint opt_connect_timeout= 0;
+static uint opt_wait_for_pos_timeout= 0;
static char delimiter[MAX_DELIMITER_LENGTH]= ";";
static uint delimiter_length= 1;
@@ -248,14 +252,16 @@ static const char *opt_suite_dir, *opt_overlay_dir;
static size_t suite_dir_len, overlay_dir_len;
/* Precompiled re's */
-static my_regex_t ps_re; /* the query can be run using PS protocol */
-static my_regex_t sp_re; /* the query can be run as a SP */
-static my_regex_t view_re; /* the query can be run as a view*/
+static regex_t ps_re; /* the query can be run using PS protocol */
+static regex_t sp_re; /* the query can be run as a SP */
+static regex_t view_re; /* the query can be run as a view*/
static void init_re(void);
-static int match_re(my_regex_t *, char *);
+static int match_re(regex_t *, char *);
static void free_re(void);
+static char *get_string(char **to_ptr, char **from_ptr,
+ struct st_command *command);
static int replace(DYNAMIC_STRING *ds_str,
const char *search_str, ulong search_len,
const char *replace_str, ulong replace_len);
@@ -345,7 +351,8 @@ enum enum_commands {
Q_ERROR,
Q_SEND, Q_REAP,
Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
- Q_PING, Q_EVAL,
+ Q_PING, Q_EVAL,
+ Q_EVALP,
Q_EVAL_RESULT,
Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
@@ -411,6 +418,7 @@ const char *command_names[]=
"replace_column",
"ping",
"eval",
+ "evalp",
"eval_result",
/* Enable/disable that the _query_ is logged to result file */
"enable_query_log",
@@ -512,7 +520,7 @@ struct st_match_err
struct st_expected_errors
{
- struct st_match_err err[10];
+ struct st_match_err err[12];
uint count;
};
static struct st_expected_errors saved_expected_errors;
@@ -592,7 +600,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
void str_to_file(const char *fname, char *str, int size);
void str_to_file2(const char *fname, char *str, int size, my_bool append);
-void fix_win_paths(const char *val, int len);
+void fix_win_paths(const char *val, size_t len);
const char *get_errname_from_code (uint error_code);
int multi_reg_replace(struct st_replace_regex* r,char* val);
@@ -806,8 +814,7 @@ public:
LogFile log_file;
LogFile progress_file;
-void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
- int len);
+void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, size_t len);
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val);
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input,
@@ -832,6 +839,7 @@ static void handle_no_active_connection(struct st_command* command,
#define EMB_END_CONNECTION 3
#define EMB_PREPARE_STMT 4
#define EMB_EXECUTE_STMT 5
+#define EMB_CLOSE_STMT 6
/* workaround for MySQL BUG#57491 */
#undef MY_WME
@@ -880,6 +888,9 @@ pthread_handler_t connection_thread(void *arg)
case EMB_EXECUTE_STMT:
cn->result= mysql_stmt_execute(cn->stmt);
break;
+ case EMB_CLOSE_STMT:
+ cn->result= mysql_stmt_close(cn->stmt);
+ break;
default:
DBUG_ASSERT(0);
}
@@ -892,6 +903,8 @@ pthread_handler_t connection_thread(void *arg)
end_thread:
cn->query_done= 1;
+ mysql_close(cn->mysql);
+ cn->mysql= 0;
mysql_thread_end();
pthread_exit(0);
return 0;
@@ -977,6 +990,17 @@ static int do_stmt_execute(struct st_connection *cn)
}
+static int do_stmt_close(struct st_connection *cn)
+{
+ /* The cn->stmt is already set. */
+ if (!cn->has_thread)
+ return mysql_stmt_close(cn->stmt);
+ signal_connection_thd(cn, EMB_CLOSE_STMT);
+ wait_query_thread_done(cn);
+ return cn->result;
+}
+
+
static void emb_close_connection(struct st_connection *cn)
{
if (!cn->has_thread)
@@ -1012,6 +1036,7 @@ static void init_connection_thd(struct st_connection *cn)
#define do_read_query_result(cn) mysql_read_query_result(cn->mysql)
#define do_stmt_prepare(cn, q, q_len) mysql_stmt_prepare(cn->stmt, q, q_len)
#define do_stmt_execute(cn) mysql_stmt_execute(cn->stmt)
+#define do_stmt_close(cn) mysql_stmt_close(cn->stmt)
#endif /*EMBEDDED_LIBRARY*/
@@ -1081,7 +1106,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
Run query and dump the result to stderr in vertical format
NOTE! This function should be safe to call when an error
- has occured and thus any further errors will be ignored(although logged)
+ has occurred and thus any further errors will be ignored (although logged)
SYNOPSIS
show_query
@@ -1147,7 +1172,7 @@ static void show_query(MYSQL* mysql, const char* query)
is added to the warning stack, only print @@warning_count-1 warnings.
NOTE! This function should be safe to call when an error
- has occured and this any further errors will be ignored(although logged)
+ has occurred and this any further errors will be ignored(although logged)
SYNOPSIS
show_warnings_before_error
@@ -1371,11 +1396,11 @@ void close_connections()
DBUG_ENTER("close_connections");
for (--next_con; next_con >= connections; --next_con)
{
+ if (next_con->stmt)
+ do_stmt_close(next_con);
#ifdef EMBEDDED_LIBRARY
emb_close_connection(next_con);
#endif
- if (next_con->stmt)
- mysql_stmt_close(next_con->stmt);
next_con->stmt= 0;
mysql_close(next_con->mysql);
next_con->mysql= 0;
@@ -1395,7 +1420,7 @@ void close_statements()
for (con= connections; con < next_con; con++)
{
if (con->stmt)
- mysql_stmt_close(con->stmt);
+ do_stmt_close(con);
con->stmt= 0;
}
DBUG_VOID_RETURN;
@@ -1500,7 +1525,6 @@ static void cleanup_and_exit(int exit_code)
}
}
- sf_leaking_memory= 0; /* all memory should be freed by now */
exit(exit_code);
}
@@ -2476,7 +2500,7 @@ VAR *var_obtain(const char *name, int len)
/*
- - if variable starts with a $ it is regarded as a local test varable
+ - if variable starts with a $ it is regarded as a local test variable
- if not it is treated as a environment variable, and the corresponding
environment variable will be updated
*/
@@ -2620,16 +2644,16 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
{
char *end = (char*)((query_end && *query_end) ?
*query_end : query + strlen(query));
- MYSQL_RES *res;
+ MYSQL_RES *UNINIT_VAR(res);
MYSQL_ROW row;
MYSQL* mysql = cur_con->mysql;
DYNAMIC_STRING ds_query;
DBUG_ENTER("var_query_set");
- LINT_INIT(res);
if (!mysql)
{
struct st_command command;
+ DBUG_ASSERT(query_end);
memset(&command, 0, sizeof(command));
command.query= (char*)query;
command.first_word_len= (*query_end - query);
@@ -2656,7 +2680,7 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
do_eval(&ds_query, query, end, FALSE);
- if (mysql_real_query(mysql, ds_query.str, ds_query.length))
+ if (mysql_real_query(mysql, ds_query.str, ds_query.length) || !(res= mysql_store_result(mysql)))
{
handle_error(curr_command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), &ds_res);
@@ -2666,13 +2690,6 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
DBUG_VOID_RETURN;
}
- if (!(res= mysql_store_result(mysql)))
- {
- report_or_die("Query '%s' didn't return a result set", ds_query.str);
- dynstr_free(&ds_query);
- eval_expr(var, "", 0);
- DBUG_VOID_RETURN;
- }
dynstr_free(&ds_query);
if ((row= mysql_fetch_row(res)) && row[0])
@@ -2804,7 +2821,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
{
long row_no;
int col_no= -1;
- MYSQL_RES* res;
+ MYSQL_RES* UNINIT_VAR(res);
MYSQL* mysql= cur_con->mysql;
static DYNAMIC_STRING ds_query;
@@ -2817,7 +2834,6 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
};
DBUG_ENTER("var_set_query_get_value");
- LINT_INIT(res);
if (!mysql)
{
@@ -3313,7 +3329,7 @@ static int replace(DYNAMIC_STRING *ds_str,
NOTE
Although mysqltest is executed from cygwin shell, the command will be
executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use
- mysqltest commmand(s) like "remove_file" for that
+ mysqltest command(s) like "remove_file" for that
*/
void do_exec(struct st_command *command)
@@ -3327,6 +3343,8 @@ void do_exec(struct st_command *command)
DBUG_ENTER("do_exec");
DBUG_PRINT("enter", ("cmd: '%s'", cmd));
+ var_set_int("$sys_errno",0);
+
/* Skip leading space */
while (*cmd && my_isspace(charset_info, *cmd))
cmd++;
@@ -3359,6 +3377,12 @@ void do_exec(struct st_command *command)
#endif
#endif
+ if (disable_result_log)
+ {
+ /* Collect stderr output as well, for the case app. crashes or returns error.*/
+ dynstr_append(&ds_cmd, " 2>&1");
+ }
+
DBUG_PRINT("info", ("Executing '%s' as '%s'",
command->first_argument, ds_cmd.str));
@@ -3394,16 +3418,7 @@ void do_exec(struct st_command *command)
len--;
}
#endif
- if (disable_result_log)
- {
- if (len)
- buf[len-1] = 0;
- DBUG_PRINT("exec_result",("%s", buf));
- }
- else
- {
- replace_dynstr_append_mem(ds_result, buf, len);
- }
+ replace_dynstr_append_mem(ds_result, buf, len);
}
error= pclose(res_file);
@@ -3413,7 +3428,7 @@ void do_exec(struct st_command *command)
dynstr_free(&ds_sorted);
}
- if (error > 0)
+ if (error)
{
uint status= WEXITSTATUS(error);
int i;
@@ -3443,6 +3458,7 @@ void do_exec(struct st_command *command)
report_or_die("command \"%s\" failed with wrong error: %d",
command->first_argument, status);
}
+ var_set_int("$sys_errno",status);
}
else if (command->expected_errors.err[0].type == ERR_ERRNO &&
command->expected_errors.err[0].code.errnum != 0)
@@ -3458,6 +3474,12 @@ void do_exec(struct st_command *command)
}
dynstr_free(&ds_cmd);
+
+ if (disable_result_log)
+ {
+ /* Disable output in case of successful exit.*/
+ dynstr_set(&ds_res,"");
+ }
DBUG_VOID_RETURN;
}
@@ -3595,6 +3617,37 @@ void do_system(struct st_command *command)
}
+/* returns TRUE if path is inside a sandbox */
+bool is_sub_path(const char *path, size_t plen, const char *sandbox)
+{
+ size_t len= strlen(sandbox);
+ if (!sandbox || !len || plen <= len || memcmp(path, sandbox, len - 1)
+ || path[len] != '/')
+ return false;
+ return true;
+}
+
+
+/* returns TRUE if path cannot be modified */
+bool bad_path(const char *path)
+{
+ size_t plen= strlen(path);
+
+ const char *vardir= getenv("MYSQLTEST_VARDIR");
+ if (is_sub_path(path, plen, vardir))
+ return false;
+
+ const char *tmpdir= getenv("MYSQL_TMP_DIR");
+ if (is_sub_path(path, plen, tmpdir))
+ return false;
+
+ report_or_die("Path '%s' is not a subdirectory of MYSQLTEST_VARDIR '%s'"
+ "or MYSQL_TMP_DIR '%s'",
+ path, vardir, tmpdir);
+ return true;
+}
+
+
/*
SYNOPSIS
set_wild_chars
@@ -3653,6 +3706,9 @@ void do_remove_file(struct st_command *command)
rm_args, sizeof(rm_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_filename.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
error= my_delete(ds_filename.str, MYF(disable_warnings ? 0 : MY_WME)) != 0;
handle_command_error(command, error, my_errno);
@@ -3696,8 +3752,10 @@ void do_remove_files_wildcard(struct st_command *command)
' ');
fn_format(dirname, ds_directory.str, "", "", MY_UNPACK_FILENAME);
+ if (bad_path(ds_directory.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("listing directory: %s", dirname));
- /* Note that my_dir sorts the list if not given any flags */
if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT | MY_WME))))
{
error= 1;
@@ -3712,7 +3770,7 @@ void do_remove_files_wildcard(struct st_command *command)
/* Set default wild chars for wild_compare, is changed in embedded mode */
set_wild_chars(1);
- for (i= 0; i < (uint) dir_info->number_off_files; i++)
+ for (i= 0; i < (uint) dir_info->number_of_files; i++)
{
file= dir_info->dir_entry + i;
/* Remove only regular files, i.e. no directories etc. */
@@ -3771,6 +3829,9 @@ void do_copy_file(struct st_command *command)
sizeof(copy_file_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_to_file.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
/* MY_HOLD_ORIGINAL_MODES prevents attempts to chown the file */
error= (my_copy(ds_from_file.str, ds_to_file.str,
@@ -3808,6 +3869,9 @@ void do_move_file(struct st_command *command)
sizeof(move_file_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_to_file.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("Move %s to %s", ds_from_file.str, ds_to_file.str));
error= (my_rename(ds_from_file.str, ds_to_file.str,
MYF(disable_warnings ? 0 : MY_WME)) != 0);
@@ -3846,6 +3910,9 @@ void do_chmod_file(struct st_command *command)
sizeof(chmod_file_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_file.str))
+ DBUG_VOID_RETURN;
+
/* Parse what mode to set */
if (ds_mode.length != 4 ||
str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
@@ -3917,6 +3984,9 @@ void do_mkdir(struct st_command *command)
mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_dirname.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("creating directory: %s", ds_dirname.str));
error= my_mkdir(ds_dirname.str, 0777, MYF(MY_WME)) != 0;
handle_command_error(command, error, my_errno);
@@ -3924,6 +3994,65 @@ void do_mkdir(struct st_command *command)
DBUG_VOID_RETURN;
}
+
+/*
+ Remove directory recursively.
+*/
+static int rmtree(const char *dir)
+{
+ char path[FN_REFLEN];
+ char sep[]={ FN_LIBCHAR, 0 };
+ int err=0;
+
+ MY_DIR *dir_info= my_dir(dir, MYF(MY_DONT_SORT | MY_WANT_STAT));
+ if (!dir_info)
+ return 1;
+
+ for (uint i= 0; i < dir_info->number_of_files; i++)
+ {
+ FILEINFO *file= dir_info->dir_entry + i;
+ /* Skip "." and ".." */
+ if (!strcmp(file->name, ".") || !strcmp(file->name, ".."))
+ continue;
+
+ strxnmov(path, sizeof(path), dir, sep, file->name, NULL);
+
+ if (!MY_S_ISDIR(file->mystat->st_mode))
+ {
+ err= my_delete(path, 0);
+#ifdef _WIN32
+ /*
+ On Windows, check and possible reset readonly attribute.
+ my_delete(), or DeleteFile does not remove theses files.
+ */
+ if (err)
+ {
+ DWORD attr= GetFileAttributes(path);
+ if (attr != INVALID_FILE_ATTRIBUTES &&
+ (attr & FILE_ATTRIBUTE_READONLY))
+ {
+ SetFileAttributes(path, attr &~ FILE_ATTRIBUTE_READONLY);
+ err= my_delete(path, 0);
+ }
+ }
+#endif
+ }
+ else
+ err= rmtree(path);
+
+ if(err)
+ break;
+ }
+
+ my_dirend(dir_info);
+
+ if (!err)
+ err= rmdir(dir);
+
+ return err;
+}
+
+
/*
SYNOPSIS
do_rmdir
@@ -3931,12 +4060,11 @@ void do_mkdir(struct st_command *command)
DESCRIPTION
rmdir <dir_name>
- Remove the empty directory <dir_name>
+ Remove the directory tree
*/
void do_rmdir(struct st_command *command)
{
- int error;
static DYNAMIC_STRING ds_dirname;
const struct command_arg rmdir_args[] = {
{ "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove" }
@@ -3947,9 +4075,13 @@ void do_rmdir(struct st_command *command)
rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_dirname.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("removing directory: %s", ds_dirname.str));
- error= rmdir(ds_dirname.str) != 0;
- handle_command_error(command, error, errno);
+ if (rmtree(ds_dirname.str))
+ handle_command_error(command, 1, errno);
+
dynstr_free(&ds_dirname);
DBUG_VOID_RETURN;
}
@@ -3975,17 +4107,12 @@ static int get_list_files(DYNAMIC_STRING *ds, const DYNAMIC_STRING *ds_dirname,
DBUG_ENTER("get_list_files");
DBUG_PRINT("info", ("listing directory: %s", ds_dirname->str));
- /* Note that my_dir sorts the list if not given any flags */
- if (!(dir_info= my_dir(ds_dirname->str, MYF(0))))
+ if (!(dir_info= my_dir(ds_dirname->str, MYF(MY_WANT_SORT))))
DBUG_RETURN(1);
set_wild_chars(1);
- for (i= 0; i < (uint) dir_info->number_off_files; i++)
+ for (i= 0; i < (uint) dir_info->number_of_files; i++)
{
file= dir_info->dir_entry + i;
- if (file->name[0] == '.' &&
- (file->name[1] == '\0' ||
- (file->name[1] == '.' && file->name[2] == '\0')))
- continue; /* . or .. */
if (ds_wild && ds_wild->length &&
wild_compare(file->name, ds_wild->str, 0))
continue;
@@ -4067,6 +4194,9 @@ static void do_list_files_write_file_command(struct st_command *command,
list_files_args,
sizeof(list_files_args)/sizeof(struct command_arg), ' ');
+ if (bad_path(ds_filename.str))
+ DBUG_VOID_RETURN;
+
init_dynamic_string(&ds_content, "", 1024, 1024);
error= get_list_files(&ds_content, &ds_dirname, &ds_wild);
handle_command_error(command, error, my_errno);
@@ -4118,7 +4248,8 @@ void read_until_delimiter(DYNAMIC_STRING *ds,
while (1)
{
c= my_getc(cur_file->file);
-
+ if (c == '\r')
+ c= my_getc(cur_file->file);
if (c == '\n')
{
cur_file->lineno++;
@@ -4169,6 +4300,9 @@ void do_write_file_command(struct st_command *command, my_bool append)
sizeof(write_file_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_filename.str))
+ DBUG_VOID_RETURN;
+
if (!append && access(ds_filename.str, F_OK) == 0)
{
/* The file should not be overwritten */
@@ -4657,19 +4791,21 @@ void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
}
-void do_sync_with_master2(struct st_command *command, long offset)
+void do_sync_with_master2(struct st_command *command, long offset,
+ const char *connection_name)
{
MYSQL_RES *res;
MYSQL_ROW row;
MYSQL *mysql= cur_con->mysql;
char query_buf[FN_REFLEN+128];
- int timeout= 300; /* seconds */
+ int timeout= opt_wait_for_pos_timeout;
if (!master_pos.file[0])
die("Calling 'sync_with_master' without calling 'save_master_pos'");
- sprintf(query_buf, "select master_pos_wait('%s', %ld, %d)",
- master_pos.file, master_pos.pos + offset, timeout);
+ sprintf(query_buf, "select master_pos_wait('%s', %ld, %d, '%s')",
+ master_pos.file, master_pos.pos + offset, timeout,
+ connection_name);
if (mysql_query(mysql, query_buf))
die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
@@ -4704,7 +4840,7 @@ void do_sync_with_master2(struct st_command *command, long offset)
master_pos_wait returned NULL. This indicates that
slave SQL thread is not started, the slave's master
information is not initialized, the arguments are
- incorrect, or an error has occured
+ incorrect, or an error has occurred
*/
die("%.*s failed: '%s' returned NULL " \
"indicating slave SQL thread failure",
@@ -4729,24 +4865,36 @@ void do_sync_with_master(struct st_command *command)
long offset= 0;
char *p= command->first_argument;
const char *offset_start= p;
+ char *start, *buff= 0;
+ start= (char*) "";
+
if (*offset_start)
{
for (; my_isdigit(charset_info, *p); p++)
offset = offset * 10 + *p - '0';
- if(*p && !my_isspace(charset_info, *p))
+ if (*p && !my_isspace(charset_info, *p) && *p != ',')
die("Invalid integer argument \"%s\"", offset_start);
+
+ while (*p && my_isspace(charset_info, *p))
+ p++;
+ if (*p == ',')
+ {
+ p++;
+ while (*p && my_isspace(charset_info, *p))
+ p++;
+ start= buff= (char*)my_malloc(strlen(p)+1,MYF(MY_WME | MY_FAE));
+ get_string(&buff, &p, command);
+ }
command->last_argument= p;
}
- do_sync_with_master2(command, offset);
+ do_sync_with_master2(command, offset, start);
+ if (buff)
+ my_free(start);
return;
}
-/*
- when ndb binlog is on, this call will wait until last updated epoch
- (locally in the mysqld) has been received into the binlog
-*/
int do_save_master_pos()
{
MYSQL_RES *res;
@@ -4755,144 +4903,6 @@ int do_save_master_pos()
const char *query;
DBUG_ENTER("do_save_master_pos");
-#ifdef HAVE_NDB_BINLOG
- /*
- Wait for ndb binlog to be up-to-date with all changes
- done on the local mysql server
- */
- {
- ulong have_ndbcluster;
- if (mysql_query(mysql, query= "show variables like 'have_ndbcluster'"))
- die("'%s' failed: %d %s", query,
- mysql_errno(mysql), mysql_error(mysql));
- if (!(res= mysql_store_result(mysql)))
- die("mysql_store_result() returned NULL for '%s'", query);
- if (!(row= mysql_fetch_row(res)))
- die("Query '%s' returned empty result", query);
-
- have_ndbcluster= strcmp("YES", row[1]) == 0;
- mysql_free_result(res);
-
- if (have_ndbcluster)
- {
- ulonglong start_epoch= 0, handled_epoch= 0,
- latest_epoch=0, latest_trans_epoch=0,
- latest_handled_binlog_epoch= 0, latest_received_binlog_epoch= 0,
- latest_applied_binlog_epoch= 0;
- int count= 0;
- int do_continue= 1;
- while (do_continue)
- {
- const char binlog[]= "binlog";
- const char latest_epoch_str[]=
- "latest_epoch=";
- const char latest_trans_epoch_str[]=
- "latest_trans_epoch=";
- const char latest_received_binlog_epoch_str[]=
- "latest_received_binlog_epoch";
- const char latest_handled_binlog_epoch_str[]=
- "latest_handled_binlog_epoch=";
- const char latest_applied_binlog_epoch_str[]=
- "latest_applied_binlog_epoch=";
- if (count)
- my_sleep(100*1000); /* 100ms */
- if (mysql_query(mysql, query= "show engine ndb status"))
- die("failed in '%s': %d %s", query,
- mysql_errno(mysql), mysql_error(mysql));
- if (!(res= mysql_store_result(mysql)))
- die("mysql_store_result() returned NULL for '%s'", query);
- while ((row= mysql_fetch_row(res)))
- {
- if (strcmp(row[1], binlog) == 0)
- {
- const char *status= row[2];
-
- /* latest_epoch */
- while (*status && strncmp(status, latest_epoch_str,
- sizeof(latest_epoch_str)-1))
- status++;
- if (*status)
- {
- status+= sizeof(latest_epoch_str)-1;
- latest_epoch= strtoull(status, (char**) 0, 10);
- }
- else
- die("result does not contain '%s' in '%s'",
- latest_epoch_str, query);
- /* latest_trans_epoch */
- while (*status && strncmp(status, latest_trans_epoch_str,
- sizeof(latest_trans_epoch_str)-1))
- status++;
- if (*status)
- {
- status+= sizeof(latest_trans_epoch_str)-1;
- latest_trans_epoch= strtoull(status, (char**) 0, 10);
- }
- else
- die("result does not contain '%s' in '%s'",
- latest_trans_epoch_str, query);
- /* latest_received_binlog_epoch */
- while (*status &&
- strncmp(status, latest_received_binlog_epoch_str,
- sizeof(latest_received_binlog_epoch_str)-1))
- status++;
- if (*status)
- {
- status+= sizeof(latest_received_binlog_epoch_str)-1;
- latest_received_binlog_epoch= strtoull(status, (char**) 0, 10);
- }
- else
- die("result does not contain '%s' in '%s'",
- latest_received_binlog_epoch_str, query);
- /* latest_handled_binlog */
- while (*status &&
- strncmp(status, latest_handled_binlog_epoch_str,
- sizeof(latest_handled_binlog_epoch_str)-1))
- status++;
- if (*status)
- {
- status+= sizeof(latest_handled_binlog_epoch_str)-1;
- latest_handled_binlog_epoch= strtoull(status, (char**) 0, 10);
- }
- else
- die("result does not contain '%s' in '%s'",
- latest_handled_binlog_epoch_str, query);
- /* latest_applied_binlog_epoch */
- while (*status &&
- strncmp(status, latest_applied_binlog_epoch_str,
- sizeof(latest_applied_binlog_epoch_str)-1))
- status++;
- if (*status)
- {
- status+= sizeof(latest_applied_binlog_epoch_str)-1;
- latest_applied_binlog_epoch= strtoull(status, (char**) 0, 10);
- }
- else
- die("result does not contain '%s' in '%s'",
- latest_applied_binlog_epoch_str, query);
- if (count == 0)
- start_epoch= latest_trans_epoch;
- break;
- }
- }
- if (!row)
- die("result does not contain '%s' in '%s'",
- binlog, query);
- if (latest_handled_binlog_epoch > handled_epoch)
- count= 0;
- handled_epoch= latest_handled_binlog_epoch;
- count++;
- if (latest_handled_binlog_epoch >= start_epoch)
- do_continue= 0;
- else if (count > 300) /* 30s */
- {
- break;
- }
- mysql_free_result(res);
- }
- }
- }
-#endif
if (mysql_query(mysql, query= "show master status"))
die("failed in 'show master status': %d %s",
mysql_errno(mysql), mysql_error(mysql));
@@ -5143,7 +5153,7 @@ static int my_kill(int pid, int sig)
void do_shutdown_server(struct st_command *command)
{
- long timeout=60;
+ long timeout= opt_wait_for_pos_timeout ? opt_wait_for_pos_timeout / 5 : 300;
int pid;
DYNAMIC_STRING ds_pidfile_name;
MYSQL* mysql = cur_con->mysql;
@@ -5212,7 +5222,6 @@ void do_shutdown_server(struct st_command *command)
(void)my_kill(pid, 9);
DBUG_VOID_RETURN;
-
}
@@ -5390,7 +5399,7 @@ void do_get_errcodes(struct st_command *command)
{
die("The sqlstate definition must start with an uppercase S");
}
- else if (*p == 'E' || *p == 'H')
+ else if (*p == 'E' || *p == 'W' || *p == 'H')
{
/* Error name string */
@@ -5399,9 +5408,9 @@ void do_get_errcodes(struct st_command *command)
to->type= ERR_ERRNO;
DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum));
}
- else if (*p == 'e' || *p == 'h')
+ else if (*p == 'e' || *p == 'w' || *p == 'h')
{
- die("The error name definition must start with an uppercase E or H");
+ die("The error name definition must start with an uppercase E or W or H");
}
else
{
@@ -5464,8 +5473,8 @@ void do_get_errcodes(struct st_command *command)
If string is a '$variable', return the value of the variable.
*/
-char *get_string(char **to_ptr, char **from_ptr,
- struct st_command *command)
+static char *get_string(char **to_ptr, char **from_ptr,
+ struct st_command *command)
{
char c, sep;
char *to= *to_ptr, *from= *from_ptr, *start=to;
@@ -5639,7 +5648,11 @@ void do_close_connection(struct st_command *command)
con->mysql->net.vio = 0;
}
}
-#else
+#endif /*!EMBEDDED_LIBRARY*/
+ if (con->stmt)
+ do_stmt_close(con);
+ con->stmt= 0;
+#ifdef EMBEDDED_LIBRARY
/*
As query could be still executed in a separate theread
we need to check if the query's thread was finished and probably wait
@@ -5647,9 +5660,6 @@ void do_close_connection(struct st_command *command)
*/
emb_close_connection(con);
#endif /*EMBEDDED_LIBRARY*/
- if (con->stmt)
- mysql_stmt_close(con->stmt);
- con->stmt= 0;
mysql_close(con->mysql);
con->mysql= 0;
@@ -5726,6 +5736,10 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host,
verbose_msg("Connecting to server %s:%d (socket %s) as '%s'"
", connection '%s', attempt %d ...",
host, port, sock, user, name, failed_attempts);
+
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
+ mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
+ "program_name", "mysqltest");
while(!mysql_real_connect(mysql, host,user, pass, db, port, sock,
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
{
@@ -5826,7 +5840,9 @@ int connect_n_handle_errors(struct st_command *command,
replace_dynstr_append(ds, command->query);
dynstr_append_mem(ds, ";\n", 2);
}
-
+
+ mysql_options(con, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
+ mysql_options4(con, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "mysqltest");
while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
CLIENT_MULTI_STATEMENTS))
{
@@ -5910,6 +5926,8 @@ void do_connect(struct st_command *command)
my_bool con_ssl= 0, con_compress= 0;
my_bool con_pipe= 0;
my_bool con_shm __attribute__ ((unused))= 0;
+ int read_timeout= 0;
+ int write_timeout= 0;
int connect_timeout= 0;
struct st_connection* con_slot;
@@ -6007,9 +6025,21 @@ void do_connect(struct st_command *command)
con_pipe= 1;
else if (length == 3 && !strncmp(con_options, "SHM", 3))
con_shm= 1;
+ else if (strncasecmp(con_options, "read_timeout=",
+ sizeof("read_timeout=")-1) == 0)
+ {
+ read_timeout= atoi(con_options + sizeof("read_timeout=")-1);
+ }
+ else if (strncasecmp(con_options, "write_timeout=",
+ sizeof("write_timeout=")-1) == 0)
+ {
+ write_timeout= atoi(con_options + sizeof("write_timeout=")-1);
+ }
else if (strncasecmp(con_options, "connect_timeout=",
sizeof("connect_timeout=")-1) == 0)
+ {
connect_timeout= atoi(con_options + sizeof("connect_timeout=")-1);
+ }
else
die("Illegal option to connect: %.*s",
(int) (end - con_options), con_options);
@@ -6060,6 +6090,8 @@ void do_connect(struct st_command *command)
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
mysql_ssl_set(con_slot->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, ssl_cipher ? ssl_cipher : opt_ssl_cipher);
+ mysql_options(con_slot->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(con_slot->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
#if MYSQL_VERSION_ID >= 50000
/* Turn on ssl_verify_server_cert only if host is "localhost" */
opt_ssl_verify_server_cert= !strcmp(ds_host.str, "localhost");
@@ -6079,9 +6111,23 @@ void do_connect(struct st_command *command)
if (opt_protocol)
mysql_options(con_slot->mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
+ if (read_timeout)
+ {
+ mysql_options(con_slot->mysql, MYSQL_OPT_READ_TIMEOUT,
+ (char*)&read_timeout);
+ }
+
+ if (write_timeout)
+ {
+ mysql_options(con_slot->mysql, MYSQL_OPT_WRITE_TIMEOUT,
+ (char*)&write_timeout);
+ }
+
if (connect_timeout)
+ {
mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
(char*)&connect_timeout);
+ }
#ifdef HAVE_SMEM
if (con_shm)
@@ -6603,9 +6649,9 @@ int read_line()
}
else if ((c == '{' &&
(!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
- (uchar*) read_command_buf, min(5, p - read_command_buf), 0) ||
+ (uchar*) read_command_buf, MY_MIN(5, p - read_command_buf), 0) ||
!my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
- (uchar*) read_command_buf, min(2, p - read_command_buf), 0))))
+ (uchar*) read_command_buf, MY_MIN(2, p - read_command_buf), 0))))
{
/* Only if and while commands can be terminated by { */
*p++= c;
@@ -6661,7 +6707,7 @@ int read_line()
start_lineno));
}
- /* Skip all space at begining of line */
+ /* Skip all space at beginning of line */
skip_char= 1;
}
else if (end_of_query(c))
@@ -6673,10 +6719,10 @@ int read_line()
}
else if (c == '}')
{
- /* A "}" need to be by itself in the begining of a line to terminate */
+ /* A "}" need to be by itself in the beginning of a line to terminate */
*p++= c;
*p= 0;
- DBUG_PRINT("exit", ("Found '}' in begining of a line at line: %d",
+ DBUG_PRINT("exit", ("Found '}' in beginning of a line at line: %d",
cur_file->lineno));
DBUG_RETURN(0);
}
@@ -7082,6 +7128,10 @@ static struct my_option my_long_options[] =
"Number of seconds before connection timeout.",
&opt_connect_timeout, &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG,
120, 0, 3600 * 12, 0, 0, 0},
+ {"wait_for_pos_timeout", 0,
+ "Number of seconds to wait for master_pos_wait",
+ &opt_wait_for_pos_timeout, &opt_wait_for_pos_timeout, 0, GET_UINT,
+ REQUIRED_ARG, 300, 0, 3600 * 12, 0, 0, 0},
{"plugin_dir", 0, "Directory for client-side plugins.",
&opt_plugin_dir, &opt_plugin_dir, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -7248,8 +7298,9 @@ get_one_option(int optid, const struct my_option *opt, char *argument)
exit(0);
case OPT_MYSQL_PROTOCOL:
#ifndef EMBEDDED_LIBRARY
- opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
- opt->name);
+ if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
+ opt->name)) <= 0)
+ exit(1);
#endif
break;
case '?':
@@ -7262,9 +7313,7 @@ get_one_option(int optid, const struct my_option *opt, char *argument)
int parse_args(int argc, char **argv)
{
- if (load_defaults("my",load_default_groups,&argc,&argv))
- exit(1);
-
+ load_defaults_or_exit("my", load_default_groups, &argc, &argv);
default_argv= argv;
if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
@@ -7361,13 +7410,13 @@ void str_to_file(const char *fname, char *str, int size)
}
-void check_regerr(my_regex_t* r, int err)
+void check_regerr(regex_t* r, int err)
{
char err_buf[1024];
if (err)
{
- my_regerror(err,r,err_buf,sizeof(err_buf));
+ regerror(err,r,err_buf,sizeof(err_buf));
die("Regex error: %s\n", err_buf);
}
}
@@ -7402,7 +7451,7 @@ void init_win_path_patterns()
DBUG_ENTER("init_win_path_patterns");
- my_init_dynamic_array(&patterns, sizeof(const char*), 16, 16);
+ my_init_dynamic_array(&patterns, sizeof(const char*), 16, 16, MYF(0));
/* Loop through all paths in the array */
for (i= 0; i < num_paths; i++)
@@ -7462,7 +7511,7 @@ void free_win_path_patterns()
=> all \ from c:\mysql\m... until next space is converted into /
*/
-void fix_win_paths(const char *val, int len)
+void fix_win_paths(const char *val, size_t len)
{
uint i;
char *p;
@@ -7751,6 +7800,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)))
@@ -7770,11 +7820,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);
}
@@ -8020,7 +8077,7 @@ void handle_error(struct st_command *command,
{
/*
The query after a "--require" failed. This is fine as long the server
- returned a valid reponse. Don't allow 2013 or 2006 to trigger an
+ returned a valid response. Don't allow 2013 or 2006 to trigger an
abort_not_supported_test
*/
if (err_errno == CR_SERVER_LOST ||
@@ -8162,6 +8219,12 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command,
DBUG_ENTER("run_query_stmt");
DBUG_PRINT("query", ("'%-.60s'", query));
+ if (!mysql)
+ {
+ handle_no_active_connection(command, cn, ds);
+ DBUG_VOID_RETURN;
+ }
+
/*
Init a new stmt if it's not already one created for this connection
*/
@@ -8438,7 +8501,8 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
/*
Evaluate query if this is an eval command
*/
- if (command->type == Q_EVAL || command->type == Q_SEND_EVAL)
+ if (command->type == Q_EVAL || command->type == Q_SEND_EVAL ||
+ command->type == Q_EVALP)
{
if (!command->eval_query.str)
init_dynamic_string(&command->eval_query, "", command->query_len + 256,
@@ -8474,10 +8538,20 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
*/
if (!disable_query_log && (flags & QUERY_SEND_FLAG))
{
- replace_dynstr_append_mem(ds, query, query_len);
+ char *print_query= query;
+ int print_len= query_len;
+ if (flags & QUERY_PRINT_ORIGINAL_FLAG)
+ {
+ print_query= command->query;
+ print_len= command->end - command->query;
+ }
+ replace_dynstr_append_mem(ds, print_query, print_len);
dynstr_append_mem(ds, delimiter, delimiter_length);
dynstr_append_mem(ds, "\n", 1);
}
+
+ /* We're done with this flag */
+ flags &= ~QUERY_PRINT_ORIGINAL_FLAG;
/*
Write the command to the result file before we execute the query
@@ -8651,19 +8725,18 @@ char *re_eprint(int err)
{
static char epbuf[100];
size_t len __attribute__((unused))=
- my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf));
+ regerror(err, (regex_t *)NULL, epbuf, sizeof(epbuf));
assert(len <= sizeof(epbuf));
return(epbuf);
}
-void init_re_comp(my_regex_t *re, const char* str)
+void init_re_comp(regex_t *re, const char* str)
{
- int err= my_regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB),
- &my_charset_latin1);
+ int err= regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB | REG_DOTALL));
if (err)
{
char erbuf[100];
- int len= my_regerror(err, re, erbuf, sizeof(erbuf));
+ int len= regerror(err, re, erbuf, sizeof(erbuf));
die("error %s, %d/%d `%s'\n",
re_eprint(err), (int)len, (int)sizeof(erbuf), erbuf);
}
@@ -8677,18 +8750,56 @@ void init_re(void)
*/
const char *ps_re_str =
"^("
- "[[:space:]]*REPLACE[[:space:]]|"
- "[[:space:]]*INSERT[[:space:]]|"
- "[[:space:]]*UPDATE[[:space:]]|"
- "[[:space:]]*DELETE[[:space:]]|"
- "[[:space:]]*SELECT[[:space:]]|"
+ "[[:space:]]*ALTER[[:space:]]+SEQUENCE[[:space:]]|"
+ "[[:space:]]*ALTER[[:space:]]+TABLE[[:space:]]|"
+ "[[:space:]]*ALTER[[:space:]]+USER[[:space:]]|"
+ "[[:space:]]*ANALYZE[[:space:]]|"
+ "[[:space:]]*ASSIGN[[:space:]]|"
+ //"[[:space:]]*CALL[[:space:]]|" // XXX run_query_stmt doesn't read multiple result sets
+ "[[:space:]]*CHANGE[[:space:]]|"
+ "[[:space:]]*CHECKSUM[[:space:]]|"
+ "[[:space:]]*COMMIT[[:space:]]|"
+ "[[:space:]]*COMPOUND[[:space:]]|"
+ "[[:space:]]*CREATE[[:space:]]+DATABASE[[:space:]]|"
+ "[[:space:]]*CREATE[[:space:]]+INDEX[[:space:]]|"
+ "[[:space:]]*CREATE[[:space:]]+ROLE[[:space:]]|"
+ "[[:space:]]*CREATE[[:space:]]+SEQUENCE[[:space:]]|"
"[[:space:]]*CREATE[[:space:]]+TABLE[[:space:]]|"
+ "[[:space:]]*CREATE[[:space:]]+USER[[:space:]]|"
+ "[[:space:]]*CREATE[[:space:]]+VIEW[[:space:]]|"
+ "[[:space:]]*DELETE[[:space:]]|"
"[[:space:]]*DO[[:space:]]|"
+ "[[:space:]]*DROP[[:space:]]+DATABASE[[:space:]]|"
+ "[[:space:]]*DROP[[:space:]]+INDEX[[:space:]]|"
+ "[[:space:]]*DROP[[:space:]]+ROLE[[:space:]]|"
+ "[[:space:]]*DROP[[:space:]]+SEQUENCE[[:space:]]|"
+ "[[:space:]]*DROP[[:space:]]+TABLE[[:space:]]|"
+ "[[:space:]]*DROP[[:space:]]+USER[[:space:]]|"
+ "[[:space:]]*DROP[[:space:]]+VIEW[[:space:]]|"
+ "[[:space:]]*FLUSH[[:space:]]|"
+ "[[:space:]]*GRANT[[:space:]]|"
"[[:space:]]*HANDLER[[:space:]]+.*[[:space:]]+READ[[:space:]]|"
+ "[[:space:]]*INSERT[[:space:]]|"
+ "[[:space:]]*INSTALL[[:space:]]+|"
+ "[[:space:]]*KILL[[:space:]]|"
+ "[[:space:]]*OPTIMIZE[[:space:]]|"
+ "[[:space:]]*PRELOAD[[:space:]]|"
+ "[[:space:]]*RENAME[[:space:]]+TABLE[[:space:]]|"
+ "[[:space:]]*RENAME[[:space:]]+USER[[:space:]]|"
+ "[[:space:]]*REPAIR[[:space:]]|"
+ "[[:space:]]*REPLACE[[:space:]]|"
+ "[[:space:]]*RESET[[:space:]]|"
+ "[[:space:]]*REVOKE[[:space:]]|"
+ "[[:space:]]*ROLLBACK[[:space:]]|"
+ "[[:space:]]*SELECT[[:space:]]|"
"[[:space:]]*SET[[:space:]]+OPTION[[:space:]]|"
- "[[:space:]]*DELETE[[:space:]]+MULTI[[:space:]]|"
- "[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|"
- "[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])";
+ "[[:space:]]*SHOW[[:space:]]|"
+ "[[:space:]]*SHUTDOWN[[:space:]]|"
+ "[[:space:]]*SLAVE[[:space:]]|"
+ "[[:space:]]*TRUNCATE[[:space:]]|"
+ "[[:space:]]*UNINSTALL[[:space:]]+|"
+ "[[:space:]]*UPDATE[[:space:]]"
+ ")";
/*
Filter for queries that can be run using the
@@ -8709,7 +8820,7 @@ void init_re(void)
}
-int match_re(my_regex_t *re, char *str)
+int match_re(regex_t *re, char *str)
{
while (my_isspace(charset_info, *str))
str++;
@@ -8721,7 +8832,7 @@ int match_re(my_regex_t *re, char *str)
str= comm_end + 2;
}
- int err= my_regexec(re, str, (size_t)0, NULL, 0);
+ int err= regexec(re, str, (size_t)0, NULL, 0);
if (err == 0)
return 1;
@@ -8730,7 +8841,7 @@ int match_re(my_regex_t *re, char *str)
{
char erbuf[100];
- int len= my_regerror(err, re, erbuf, sizeof(erbuf));
+ int len= regerror(err, re, erbuf, sizeof(erbuf));
die("error %s, %d/%d `%s'\n",
re_eprint(err), (int)len, (int)sizeof(erbuf), erbuf);
}
@@ -8739,10 +8850,9 @@ int match_re(my_regex_t *re, char *str)
void free_re(void)
{
- my_regfree(&ps_re);
- my_regfree(&sp_re);
- my_regfree(&view_re);
- my_regex_end();
+ regfree(&ps_re);
+ regfree(&sp_re);
+ regfree(&view_re);
}
/****************************************************************************/
@@ -9008,12 +9118,16 @@ int main(int argc, char **argv)
cur_block->ok= TRUE; /* Outer block should always be executed */
cur_block->cmd= cmd_none;
- my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
+ my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024, MYF(0));
if (my_hash_init2(&var_hash, 64, charset_info,
- 128, 0, 0, get_var_key, var_free, MYF(0)))
+ 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);
@@ -9040,7 +9154,7 @@ int main(int argc, char **argv)
read_command_buf= (char*)my_malloc(read_command_buflen= 65536, MYF(MY_FAE));
init_dynamic_string(&ds_res, "", 2048, 2048);
- init_alloc_root(&require_file_root, 1024, 1024);
+ init_alloc_root(&require_file_root, 1024, 1024, MYF(0));
parse_args(argc, argv);
@@ -9091,7 +9205,7 @@ int main(int argc, char **argv)
var_set_string("MYSQLTEST_FILE", cur_file->file_name);
init_re();
- /* Cursor protcol implies ps protocol */
+ /* Cursor protocol implies ps protocol */
if (cursor_protocol)
ps_protocol= 1;
@@ -9127,6 +9241,8 @@ int main(int argc, char **argv)
{
mysql_ssl_set(con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(con->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(con->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
#if MYSQL_VERSION_ID >= 50000
/* Turn on ssl_verify_server_cert only if host is "localhost" */
opt_ssl_verify_server_cert= opt_host && !strcmp(opt_host, "localhost");
@@ -9186,7 +9302,7 @@ int main(int argc, char **argv)
abort_on_error);
/*
- some commmands need to be executed or at least parsed unconditionally,
+ some commands need to be executed or at least parsed unconditionally,
because they change the grammar.
*/
ok_to_do= cur_block->ok || command->type == Q_DELIMITER
@@ -9338,6 +9454,7 @@ int main(int argc, char **argv)
case Q_EVAL_RESULT:
die("'eval_result' command is deprecated");
case Q_EVAL:
+ case Q_EVALP:
case Q_QUERY_VERTICAL:
case Q_QUERY_HORIZONTAL:
if (command->query == command->query_buf)
@@ -9365,6 +9482,9 @@ int main(int argc, char **argv)
flags= QUERY_REAP_FLAG;
}
+ if (command->type == Q_EVALP)
+ flags |= QUERY_PRINT_ORIGINAL_FLAG;
+
/* Check for special property for this query */
display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
@@ -9434,7 +9554,7 @@ int main(int argc, char **argv)
select_connection(command);
else
select_connection_name("slave");
- do_sync_with_master2(command, 0);
+ do_sync_with_master2(command, 0, "");
break;
}
case Q_COMMENT:
@@ -9614,7 +9734,7 @@ int main(int argc, char **argv)
die("Test ended with parsing disabled");
/*
- The whole test has been executed _sucessfully_.
+ The whole test has been executed _successfully_.
Time to compare result or save it to record file.
The entire output from test is in the log file
*/
@@ -9660,7 +9780,7 @@ int main(int argc, char **argv)
verbose_msg("Test has succeeded!");
timer_output();
- /* Yes, if we got this far the test has suceeded! Sakila smiles */
+ /* Yes, if we got this far the test has succeeded! Sakila smiles */
cleanup_and_exit(0);
return 0; /* Keep compiler happy too */
}
@@ -9929,122 +10049,137 @@ 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.
Returns: st_replace_regex struct with pairs of substitutions
*/
+void append_replace_regex(char*, char*, struct st_replace_regex*, char**);
struct st_replace_regex* init_replace_regex(char* expr)
{
+ char *expr_end, *buf_p;
struct st_replace_regex* res;
- char* buf,*expr_end;
- char* p;
- 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 */
res=(struct st_replace_regex*)my_malloc(
- sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME));
- my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
+ sizeof(*res)+8192 ,MYF(MY_FAE+MY_WME));
+ my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex), 128, 128, MYF(0));
- buf= (char*)res + sizeof(*res);
expr_end= expr + expr_len;
+ buf_p= (char*)res + sizeof(*res);
+ append_replace_regex(expr, expr_end, res, &buf_p);
+
+ res->odd_buf_len= res->even_buf_len= 8192;
+ res->even_buf= (char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
+ res->odd_buf= (char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
+ res->buf= res->even_buf;
+
+ return res;
+}
+
+
+void append_replace_regex(char* expr, char *expr_end, struct st_replace_regex* res,
+ char **buf_p)
+{
+ char* p, start_re, end_re= 1;
+ struct st_regex reg;
+
p= expr;
- buf_p= buf;
/* for each regexp substitution statement */
while (p < expr_end)
{
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;
- /* buf_p now points to the replacement pattern terminated with \0 */
- reg.replace= buf_p;
+ /* Allow variable for the *entire* list of replacements */
+ if (*p == '$')
+ {
+ const char *v_end;
+ VAR *val= var_get(p, &v_end, 0, 1);
- /* Find second argument -- replace string to replace pattern */
- PARSE_REGEX_ARG
+ if (val)
+ {
+ char *expr, *expr_end;
+ expr= val->str_val;
+ expr_end= expr + val->str_val_len;
+ append_replace_regex(expr, expr_end, res, buf_p);
+ }
- if (p == expr_end)
+ p= (char *) v_end + 1;
+ continue;
+ }
+ else
+ {
+ if (parse_re_part(&start_re, &end_re, &p, expr_end, buf_p))
goto err;
- /* skip the ending '/' in the statement */
- p++;
+ reg.replace= *buf_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))
die("Out of memory");
}
- res->odd_buf_len= res->even_buf_len= 8192;
- res->even_buf= (char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
- res->odd_buf= (char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
- res->buf= res->even_buf;
- return res;
+ return;
err:
my_free(res);
die("Error parsing replace_regex \"%s\"", expr);
- return 0;
}
/*
@@ -10124,12 +10259,6 @@ void do_get_replace_regex(struct st_command *command)
{
char *expr= command->first_argument;
free_replace_regex();
- /* Allow variable for the *entire* list of replacements */
- if (*expr == '$')
- {
- VAR *val= var_get(expr, NULL, 0, 1);
- expr= val ? val->str_val : NULL;
- }
if (expr && *expr && !(glob_replace_regex=init_replace_regex(expr)))
die("Could not init replace_regex");
command->last_argument= command->end;
@@ -10170,19 +10299,19 @@ void free_replace_regex()
buf_len_p - result buffer length. Will change if the buffer is reallocated
pattern - regexp pattern to match
replace - replacement expression
- string - the string to perform substituions in
+ string - the string to perform substitutions in
icase - flag, if set to 1 the match is case insensitive
*/
int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
char *replace, char *string, int icase)
{
- my_regex_t r;
- my_regmatch_t *subs;
+ regex_t r;
+ regmatch_t *subs;
char *replace_end;
char *buf= *buf_p;
int len;
int buf_len, need_buf_len;
- int cflags= REG_EXTENDED;
+ int cflags= REG_EXTENDED | REG_DOTALL;
int err_code;
char *res_p,*str_p,*str_end;
@@ -10201,13 +10330,13 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
if (icase)
cflags|= REG_ICASE;
- if ((err_code= my_regcomp(&r,pattern,cflags,&my_charset_latin1)))
+ if ((err_code= regcomp(&r,pattern,cflags)))
{
check_regerr(&r,err_code);
return 1;
}
- subs= (my_regmatch_t*)my_malloc(sizeof(my_regmatch_t) * (r.re_nsub+1),
+ subs= (regmatch_t*)my_malloc(sizeof(regmatch_t) * (r.re_nsub+1),
MYF(MY_WME+MY_FAE));
*res_p= 0;
@@ -10218,14 +10347,14 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
while (!err_code)
{
/* find the match */
- err_code= my_regexec(&r,str_p, r.re_nsub+1, subs,
- (str_p == string) ? REG_NOTBOL : 0);
+ err_code= regexec(&r,str_p, r.re_nsub+1, subs,
+ (str_p == string) ? 0 : REG_NOTBOL);
/* if regular expression error (eg. bad syntax, or out of memory) */
if (err_code && err_code != REG_NOMATCH)
{
check_regerr(&r,err_code);
- my_regfree(&r);
+ regfree(&r);
return 1;
}
@@ -10338,7 +10467,7 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
}
}
my_free(subs);
- my_regfree(&r);
+ regfree(&r);
*res_p= 0;
*buf_p= buf;
*buf_len_p= buf_len;
@@ -10953,7 +11082,7 @@ void free_pointer_array(POINTER_ARRAY *pa)
/* Append the string to ds, with optional replace */
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
- const char *val, int len)
+ const char *val, size_t len)
{
char lower[512];
#ifdef __WIN__
@@ -11034,7 +11163,7 @@ void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input,
if (!*start)
DBUG_VOID_RETURN; /* No input */
- my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
+ my_init_dynamic_array(&lines, sizeof(const char*), 32, 32, MYF(0));
if (keep_header)
{
diff --git a/client/readline.cc b/client/readline.cc
index b6643b86356..23b1f8d7ac7 100644
--- a/client/readline.cc
+++ b/client/readline.cc
@@ -57,8 +57,7 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
char *batch_readline(LINE_BUFFER *line_buff, bool binary_mode)
{
char *pos;
- ulong out_length;
- LINT_INIT(out_length);
+ ulong UNINIT_VAR(out_length);
if (!(pos=intern_read_line(line_buff, &out_length)))
return 0;
diff --git a/client/sql_string.cc.dontuse b/client/sql_string.cc.dontuse
index 9679197b207..65b14e36cd1 100644
--- a/client/sql_string.cc.dontuse
+++ b/client/sql_string.cc.dontuse
@@ -267,7 +267,7 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
return copy_aligned(str, arg_length, offset, cs);
}
- /* Copy with charset convertion */
+ /* Copy with charset conversion */
bool String::copy(const char *str, uint32 arg_length,
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)