summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/CMakeLists.txt18
-rw-r--r--client/async_example.c216
-rw-r--r--client/client_priv.h9
-rw-r--r--client/get_password.c8
-rw-r--r--client/my_readline.h2
-rw-r--r--client/mysql.cc288
-rw-r--r--client/mysql_plugin.c1
-rw-r--r--client/mysql_upgrade.c92
-rw-r--r--client/mysqladmin.cc177
-rw-r--r--client/mysqlbinlog.cc414
-rw-r--r--client/mysqlcheck.c249
-rw-r--r--client/mysqldump.c222
-rw-r--r--client/mysqlimport.c41
-rw-r--r--client/mysqlshow.c9
-rw-r--r--client/mysqlslap.c191
-rw-r--r--client/mysqltest.cc1281
-rw-r--r--client/readline.cc5
-rw-r--r--client/sql_string.cc.dontuse (renamed from client/sql_string.cc)8
-rw-r--r--client/sql_string.h.dontuse (renamed from client/sql_string.h)21
19 files changed, 2383 insertions, 869 deletions
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 4d8fab3f4b9..e4507f9c8ba 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -21,21 +21,23 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/regex
${CMAKE_SOURCE_DIR}/sql
${CMAKE_SOURCE_DIR}/strings
- ${READLINE_INCLUDE_DIR}
+ ${MY_READLINE_INCLUDE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
-ADD_DEFINITIONS(${READLINE_DEFINES})
ADD_DEFINITIONS(${SSL_DEFINES})
-MYSQL_ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc)
+MYSQL_ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc
+ ${CMAKE_SOURCE_DIR}/sql/sql_string.cc)
TARGET_LINK_LIBRARIES(mysql mysqlclient)
IF(UNIX)
- TARGET_LINK_LIBRARIES(mysql ${READLINE_LIBRARY})
+ TARGET_LINK_LIBRARIES(mysql ${MY_READLINE_LIBRARY})
+ SET_TARGET_PROPERTIES(mysql PROPERTIES ENABLE_EXPORTS TRUE)
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)
+SET_TARGET_PROPERTIES(mysqltest PROPERTIES ENABLE_EXPORTS TRUE)
MYSQL_ADD_EXECUTABLE(mysqlcheck mysqlcheck.c)
@@ -47,7 +49,7 @@ TARGET_LINK_LIBRARIES(mysqldump mysqlclient)
MYSQL_ADD_EXECUTABLE(mysqlimport mysqlimport.c)
TARGET_LINK_LIBRARIES(mysqlimport mysqlclient)
-MYSQL_ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c)
+MYSQL_ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c COMPONENT Server)
TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient)
ADD_DEPENDENCIES(mysql_upgrade GenFixPrivs)
@@ -69,9 +71,13 @@ TARGET_LINK_LIBRARIES(mysqlslap mysqlclient)
# "WIN32" also covers 64 bit. "echo" is used in some files below "mysql-test/".
IF(WIN32)
- MYSQL_ADD_EXECUTABLE(echo echo.c)
+ MYSQL_ADD_EXECUTABLE(echo echo.c COMPONENT Junk)
ENDIF(WIN32)
+# async_example is just a code example, do not install it.
+ADD_EXECUTABLE(async_example async_example.c)
+TARGET_LINK_LIBRARIES(async_example mysqlclient)
+
SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap mysql_plugin
PROPERTIES HAS_CXX TRUE)
diff --git a/client/async_example.c b/client/async_example.c
new file mode 100644
index 00000000000..ccb60950904
--- /dev/null
+++ b/client/async_example.c
@@ -0,0 +1,216 @@
+/*
+ Copyright 2011 Kristian Nielsen and Monty Program Ab.
+
+ This file is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef __WIN__
+#include <poll.h>
+#else
+#include <WinSock2.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <mysql.h>
+
+#define SL(s) (s), sizeof(s)
+
+static const char *my_groups[]= { "client", NULL };
+
+static int
+wait_for_mysql(MYSQL *mysql, int status)
+{
+#ifdef __WIN__
+ fd_set rs, ws, es;
+ int res;
+ struct timeval tv, *timeout;
+ my_socket s= mysql_get_socket(mysql);
+ FD_ZERO(&rs);
+ FD_ZERO(&ws);
+ FD_ZERO(&es);
+ if (status & MYSQL_WAIT_READ)
+ FD_SET(s, &rs);
+ if (status & MYSQL_WAIT_WRITE)
+ FD_SET(s, &ws);
+ if (status & MYSQL_WAIT_EXCEPT)
+ FD_SET(s, &es);
+ if (status & MYSQL_WAIT_TIMEOUT)
+ {
+ tv.tv_sec= mysql_get_timeout_value(mysql);
+ tv.tv_usec= 0;
+ timeout= &tv;
+ }
+ else
+ timeout= NULL;
+ res= select(1, &rs, &ws, &es, timeout);
+ if (res == 0)
+ return MYSQL_WAIT_TIMEOUT;
+ else if (res == SOCKET_ERROR)
+ {
+ /*
+ In a real event framework, we should handle errors and re-try the select.
+ */
+ return MYSQL_WAIT_TIMEOUT;
+ }
+ else
+ {
+ int status= 0;
+ if (FD_ISSET(s, &rs))
+ status|= MYSQL_WAIT_READ;
+ if (FD_ISSET(s, &ws))
+ status|= MYSQL_WAIT_WRITE;
+ if (FD_ISSET(s, &es))
+ status|= MYSQL_WAIT_EXCEPT;
+ return status;
+ }
+#else
+ struct pollfd pfd;
+ int timeout;
+ int res;
+
+ pfd.fd= mysql_get_socket(mysql);
+ pfd.events=
+ (status & MYSQL_WAIT_READ ? POLLIN : 0) |
+ (status & MYSQL_WAIT_WRITE ? POLLOUT : 0) |
+ (status & MYSQL_WAIT_EXCEPT ? POLLPRI : 0);
+ if (status & MYSQL_WAIT_TIMEOUT)
+ timeout= 1000*mysql_get_timeout_value(mysql);
+ else
+ timeout= -1;
+ res= poll(&pfd, 1, timeout);
+ if (res == 0)
+ return MYSQL_WAIT_TIMEOUT;
+ else if (res < 0)
+ {
+ /*
+ In a real event framework, we should handle EINTR and re-try the poll.
+ */
+ return MYSQL_WAIT_TIMEOUT;
+ }
+ else
+ {
+ int status= 0;
+ if (pfd.revents & POLLIN)
+ status|= MYSQL_WAIT_READ;
+ if (pfd.revents & POLLOUT)
+ status|= MYSQL_WAIT_WRITE;
+ if (pfd.revents & POLLPRI)
+ status|= MYSQL_WAIT_EXCEPT;
+ return status;
+ }
+#endif
+}
+
+static void
+fatal(MYSQL *mysql, const char *msg)
+{
+ fprintf(stderr, "%s: %s\n", msg, mysql_error(mysql));
+ exit(1);
+}
+
+static void
+doit(const char *host, const char *user, const char *password)
+{
+ int err;
+ MYSQL mysql, *ret;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int status;
+
+ mysql_init(&mysql);
+ mysql_options(&mysql, MYSQL_OPT_NONBLOCK, 0);
+ mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "myapp");
+
+ /* Returns 0 when done, else flag for what to wait for when need to block. */
+ status= mysql_real_connect_start(&ret, &mysql, host, user, password, NULL,
+ 0, NULL, 0);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_real_connect_cont(&ret, &mysql, status);
+ }
+
+ if (!ret)
+ fatal(&mysql, "Failed to mysql_real_connect()");
+
+ status= mysql_real_query_start(&err, &mysql, SL("SHOW STATUS"));
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_real_query_cont(&err, &mysql, status);
+ }
+ if (err)
+ fatal(&mysql, "mysql_real_query() returns error");
+
+ /* This method cannot block. */
+ res= mysql_use_result(&mysql);
+ if (!res)
+ fatal(&mysql, "mysql_use_result() returns error");
+
+ for (;;)
+ {
+ status= mysql_fetch_row_start(&row, res);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_fetch_row_cont(&row, res, status);
+ }
+ if (!row)
+ break;
+ printf("%s: %s\n", row[0], row[1]);
+ }
+ if (mysql_errno(&mysql))
+ fatal(&mysql, "Got error while retrieving rows");
+ mysql_free_result(res);
+
+ /*
+ mysql_close() sends a COM_QUIT packet, and so in principle could block
+ waiting for the socket to accept the data.
+ In practise, for many applications it will probably be fine to use the
+ blocking mysql_close().
+ */
+ status= mysql_close_start(&mysql);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_close_cont(&mysql, status);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ int err;
+
+ if (argc != 4)
+ {
+ fprintf(stderr, "Usage: %s <host> <user> <password>\n", argv[0]);
+ exit(1);
+ }
+
+ err= mysql_library_init(argc, argv, (char **)my_groups);
+ if (err)
+ {
+ fprintf(stderr, "Fatal: mysql_library_init() returns error: %d\n", err);
+ exit(1);
+ }
+
+ doit(argv[1], argv[2], argv[3]);
+
+ mysql_library_end();
+
+ return 0;
+}
diff --git a/client/client_priv.h b/client/client_priv.h
index 2362811d2b3..607bd3997c1 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -52,6 +52,7 @@ enum options_client
OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_SERVER_ARG,
OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME,
OPT_SIGINT_IGNORE, OPT_HEXBLOB, OPT_ORDER_BY_PRIMARY, OPT_COUNT,
+ OPT_FLUSH_TABLES,
OPT_TRIGGERS,
OPT_MYSQL_ONLY_PRINT,
OPT_MYSQL_LOCK_DIRECTORY,
@@ -86,9 +87,11 @@ enum options_client
OPT_INIT_COMMAND,
OPT_PLUGIN_DIR,
OPT_DEFAULT_AUTH,
- OPT_DEFAULT_PLUGIN,
- OPT_ENABLE_CLEARTEXT_PLUGIN,
- OPT_MAX_CLIENT_OPTION
+ OPT_ABORT_SOURCE_ON_ERROR,
+ OPT_REWRITE_DB,
+ OPT_REPORT_PROGRESS,
+ OPT_SKIP_ANNOTATE_ROWS_EVENTS,
+ OPT_MAX_CLIENT_OPTION /* should be always the last */
};
/**
diff --git a/client/get_password.c b/client/get_password.c
index ea024f76fb6..09d307b5553 100644
--- a/client/get_password.c
+++ b/client/get_password.c
@@ -23,10 +23,6 @@
#include <m_string.h>
#include <m_ctype.h>
-#if defined(HAVE_BROKEN_GETPASS) && !defined(HAVE_GETPASSPHRASE)
-#undef HAVE_GETPASS
-#endif
-
#ifdef HAVE_GETPASS
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -113,7 +109,7 @@ static void get_password(char *to,uint length,int fd, my_bool echo)
for (;;)
{
- char tmp;
+ uchar tmp;
if (my_read(fd,&tmp,1,MYF(0)) != 1)
break;
if (tmp == '\b' || (int) tmp == 127)
@@ -138,7 +134,7 @@ static void get_password(char *to,uint length,int fd, my_bool echo)
fputc('*',stderr);
fflush(stderr);
}
- *(pos++) = tmp;
+ *(pos++)= (char) tmp;
}
while (pos != to && isspace(pos[-1]) == ' ')
pos--; /* Allow dummy space at end */
diff --git a/client/my_readline.h b/client/my_readline.h
index d288a33e1cc..11ace987b44 100644
--- a/client/my_readline.h
+++ b/client/my_readline.h
@@ -2,7 +2,7 @@
#define CLIENT_MY_READLINE_INCLUDED
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
diff --git a/client/mysql.cc b/client/mysql.cc
index 73787ea5eeb..67878b36227 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2012, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -12,8 +13,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* mysql command tool
* Commands compatible with mSQL by David J. Hughes
@@ -45,7 +45,7 @@
#include <locale.h>
#endif
-const char *VER= "14.14";
+const char *VER= "15.1";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
@@ -83,8 +83,9 @@ extern "C" {
#include <term.h>
#endif
#endif
-#endif
+#endif /* defined(HAVE_CURSES_H) && defined(HAVE_TERM_H) */
+#undef bcmp // Fix problem with new readline
#if defined(__WIN__)
#include <conio.h>
#else
@@ -92,7 +93,6 @@ extern "C" {
#define HAVE_READLINE
#define USE_POPEN
#endif
- //int vidattr(long unsigned int attrs); // Was missing in sun curses
}
#if !defined(HAVE_VIDATTR)
@@ -141,18 +141,18 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
opt_secure_auth= 0,
default_pager_set= 0, opt_sigint_ignore= 0,
auto_vertical_output= 0,
- show_warnings= 0, executing_query= 0, interrupted_query= 0,
- ignore_spaces= 0;
-static my_bool debug_info_flag, debug_check_flag;
+ show_warnings= 0, executing_query= 0,
+ ignore_spaces= 0, opt_progress_reports;
+static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error;
static my_bool column_types_flag;
static my_bool preserve_comments= 0;
+static my_bool in_com_source, aborted= 0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
-static uint opt_enable_cleartext_plugin= 0;
-static my_bool using_opt_enable_cleartext_plugin= 0;
static uint my_end_arg;
static char * opt_mysql_unix_port=0;
static int connect_flag=CLIENT_INTERACTIVE;
+static int interrupted_query= 0;
static char *current_host,*current_db,*current_user=0,*opt_password=0,
*current_prompt=0, *delimiter_str= 0,
*default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME,
@@ -242,6 +242,13 @@ static void init_username();
static void add_int_to_prompt(int toadd);
static int get_result_width(MYSQL_RES *res);
static int get_field_disp_length(MYSQL_FIELD * field);
+#ifndef EMBEDDED_LIBRARY
+static uint last_progress_report_length= 0;
+static void report_progress(const MYSQL *mysql, uint stage, uint max_stage,
+ double progress, const char *proc_info,
+ uint proc_info_length);
+#endif
+static void report_progress_end();
/* A structure which contains information on the commands this program
can understand. */
@@ -887,6 +894,7 @@ static COMMANDS commands[] = {
{ "LAST_INSERT_ID", 0, 0, 0, ""},
{ "ISSIMPLE", 0, 0, 0, ""},
{ "LAST_DAY", 0, 0, 0, ""},
+ { "LAST_VALUE", 0, 0, 0, ""},
{ "LCASE", 0, 0, 0, ""},
{ "LEAST", 0, 0, 0, ""},
{ "LENGTH", 0, 0, 0, ""},
@@ -1018,12 +1026,13 @@ static COMMANDS commands[] = {
{ (char *)NULL, 0, 0, 0, ""}
};
-static const char *load_default_groups[]= { "mysql","client",0 };
+static const char *load_default_groups[]=
+{ "mysql", "client", "client-server", "client-mariadb", 0 };
static int embedded_server_arg_count= 0;
static char *embedded_server_args[MAX_SERVER_ARGS];
static const char *embedded_server_groups[]=
-{ "server", "embedded", "mysql_SERVER", 0 };
+{ "server", "embedded", "mysql_SERVER", "mariadb_SERVER", 0 };
#ifdef HAVE_READLINE
/*
@@ -1079,9 +1088,10 @@ int main(int argc,char *argv[])
delimiter_str= delimiter;
default_prompt = my_strdup(getenv("MYSQL_PS1") ?
getenv("MYSQL_PS1") :
- "mysql> ",MYF(MY_WME));
+ "\\N [\\d]> ",MYF(MY_WME));
current_prompt = my_strdup(default_prompt,MYF(MY_WME));
prompt_counter=0;
+ aborted= 0;
outfile[0]=0; // no (default) outfile
strmov(pager, "stdout"); // the default, if --pager wasn't given
@@ -1172,10 +1182,11 @@ int main(int argc,char *argv[])
window_resize(0);
#endif
- put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.",
+ put_info("Welcome to the MariaDB monitor. Commands end with ; or \\g.",
INFO_INFO);
sprintf((char*) glob_buffer.ptr(),
- "Your MySQL connection id is %lu\nServer version: %s\n",
+ "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);
@@ -1288,15 +1299,16 @@ sig_handler mysql_end(int sig)
/*
This function handles sigint calls
If query is in process, kill query
+ If 'source' is executed, abort source command
no query in process, terminate like previous behavior
*/
+
sig_handler handle_sigint(int sig)
{
char kill_buffer[40];
MYSQL *kill_mysql= NULL;
/* terminate if no query being executed, or we already tried interrupting */
- /* terminate if no query being executed, or we already tried interrupting */
if (!executing_query || (interrupted_query == 2))
{
tee_fprintf(stdout, "Ctrl-C -- exit!\n");
@@ -1311,6 +1323,7 @@ sig_handler handle_sigint(int sig)
goto err;
}
+ /* First time try to kill the query, second time the connection */
interrupted_query++;
/* mysqld < 5 does not understand KILL QUERY, skip to KILL CONNECTION */
@@ -1321,11 +1334,15 @@ sig_handler handle_sigint(int sig)
sprintf(kill_buffer, "KILL %s%lu",
(interrupted_query == 1) ? "QUERY " : "",
mysql_thread_id(&mysql));
- tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n", kill_buffer);
+ if (verbose)
+ tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n",
+ kill_buffer);
mysql_real_query(kill_mysql, kill_buffer, (uint) strlen(kill_buffer));
mysql_close(kill_mysql);
- tee_fprintf(stdout, "Ctrl-C -- query aborted.\n");
-
+ tee_fprintf(stdout, "Ctrl-C -- query killed. Continuing normally.\n");
+ interrupted_query= 0;
+ if (in_com_source)
+ aborted= 1; // Abort source command
return;
err:
@@ -1337,7 +1354,6 @@ err:
handler called mysql_end().
*/
mysql_thread_end();
- return;
#else
mysql_end(sig);
#endif
@@ -1360,6 +1376,10 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0},
{"help", 'I', "Synonym for -?", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
+ {"abort-source-on-error", OPT_ABORT_SOURCE_ON_ERROR,
+ "Abort 'source filename' operations in case of errors",
+ &batch_abort_on_error, &batch_abort_on_error, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"auto-rehash", OPT_AUTO_REHASH,
"Enable automatic rehashing. One doesn't need to use 'rehash' to get table "
"and field completion, but startup and reconnecting may take a longer time. "
@@ -1411,16 +1431,12 @@ static struct my_option my_long_options[] =
&default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"delimiter", OPT_DELIMITER, "Delimiter to be used.", &delimiter_str,
&delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
- "Enable/disable the clear text authentication plugin.",
- &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin,
- 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"execute", 'e', "Execute command and quit. (Disables --force and history file.)", 0,
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"vertical", 'E', "Print the output of a query (rows) vertically.",
&vertical, &vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
0},
- {"force", 'f', "Continue even if we get an SQL error.",
+ {"force", 'f', "Continue even if we get an SQL error. Sets abort-source-on-error to 0",
&ignore_errors, &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
{"named-commands", 'G',
@@ -1493,6 +1509,10 @@ static struct my_option my_long_options[] =
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
&opt_mysql_port,
&opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"progress-reports", OPT_REPORT_PROGRESS,
+ "Get progress reports for long running commands (like ALTER TABLE)",
+ &opt_progress_reports, &opt_progress_reports, 0, GET_BOOL, NO_ARG, 1, 0,
+ 0, 0, 0, 0},
{"prompt", OPT_PROMPT, "Set the mysql prompt to this value.",
&current_prompt, &current_prompt, 0, GET_STR_ALLOC,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -1642,9 +1662,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case OPT_LOCAL_INFILE:
using_opt_local_infile=1;
break;
- case OPT_ENABLE_CLEARTEXT_PLUGIN:
- using_opt_enable_cleartext_plugin= TRUE;
- break;
case OPT_TEE:
if (argument == disabled_my_option)
{
@@ -1764,13 +1781,18 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
#endif
break;
#include <sslopt-case.h>
+ case 'f':
+ batch_abort_on_error= 0;
+ break;
case 'V':
usage(1);
- exit(0);
+ status.exit_status= 0;
+ mysql_end(-1);
case 'I':
case '?':
usage(0);
- exit(0);
+ status.exit_status= 0;
+ mysql_end(-1);
}
return 0;
}
@@ -1814,6 +1836,7 @@ static int get_options(int argc, char **argv)
opt_outfile= 0;
opt_reconnect= 0;
connect_flag= 0; /* Not in interactive mode */
+ opt_progress_reports= 0;
}
if (argc > 1)
@@ -1837,6 +1860,9 @@ static int get_options(int argc, char **argv)
if (ignore_spaces)
connect_flag|= CLIENT_IGNORE_SPACE;
+ if (opt_progress_reports)
+ connect_flag|= CLIENT_PROGRESS;
+
return(0);
}
@@ -1847,14 +1873,14 @@ static int read_and_execute(bool interactive)
String buffer;
#endif
- char *line;
+ char *line= 0;
char in_string=0;
ulong line_number=0;
bool ml_comment= 0;
COMMANDS *com;
status.exit_status=1;
-
- for (;;)
+
+ while (!aborted)
{
if (!interactive)
{
@@ -2017,12 +2043,12 @@ static COMMANDS *find_command(char *name,char cmd_char)
for (uint i= 0; commands[i].name; i++)
{
if (commands[i].func &&
- ((name &&
- !my_strnncoll(&my_charset_latin1, (uchar*)name, len,
- (uchar*)commands[i].name,len) &&
- !commands[i].name[len] &&
- (!end || (end && commands[i].takes_params))) ||
- (!name && commands[i].cmd_char == cmd_char)))
+ (((name &&
+ !my_strnncoll(&my_charset_latin1, (uchar*) name, len,
+ (uchar*) commands[i].name, len) &&
+ !commands[i].name[len] &&
+ (!end || (end && commands[i].takes_params)))) ||
+ (!name && commands[i].cmd_char == cmd_char)))
{
DBUG_PRINT("exit",("found command: %s", commands[i].name));
DBUG_RETURN(&commands[i]);
@@ -2180,16 +2206,21 @@ static bool add_line(String &buffer,char *line,char *in_string,
}
buffer.length(0);
}
- else if (!*ml_comment && (!*in_string && (inchar == '#' ||
- (inchar == '-' && pos[1] == '-' &&
- /*
- The third byte is either whitespace or is the
- end of the line -- which would occur only
- because of the user sending newline -- which is
- itself whitespace and should also match.
- */
- (my_isspace(charset_info,pos[2]) ||
- !pos[2])))))
+ else if (!*ml_comment &&
+ (!*in_string &&
+ (inchar == '#' ||
+ (inchar == '-' && pos[1] == '-' &&
+ /*
+ The third byte is either whitespace or is the end of
+ the line -- which would occur only because of the
+ user sending newline -- which is itself whitespace
+ and should also match.
+ We also ignore lines starting with '--', even if there
+ isn't a whitespace after. (This makes it easier to run
+ mysql-test-run cases through the client)
+ */
+ ((my_isspace(charset_info,pos[2]) || !pos[2]) ||
+ (buffer.is_empty() && out == line))))))
{
// Flush previously accepted characters
if (out != line)
@@ -2221,7 +2252,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
break;
}
else if (!*in_string && inchar == '/' && *(pos+1) == '*' &&
- *(pos+2) != '!')
+ !(*(pos+2) == '!' || (*(pos+2) == 'M' && *(pos+3) == '!')))
{
if (preserve_comments)
{
@@ -2701,6 +2732,8 @@ static int reconnect(void)
}
if (!connected)
return put_info("Can't connect to the server\n",INFO_ERROR);
+ my_free(server_version);
+ server_version= 0;
/* purecov: end */
return 0;
}
@@ -2888,13 +2921,8 @@ com_help(String *buffer __attribute__((unused)),
return com_server_help(buffer,line,help_arg);
}
- put_info("\nFor information about MySQL products and services, visit:\n"
- " http://www.mysql.com/\n"
- "For developer information, including the MySQL Reference Manual, "
- "visit:\n"
- " http://dev.mysql.com/\n"
- "To buy MySQL Enterprise support, training, or other products, visit:\n"
- " https://shop.mysql.com/\n", INFO_INFO);
+ put_info("\nGeneral information about MariaDB can be found at\n"
+ "http://mariadb.org\n", INFO_INFO);
put_info("List of all MySQL commands:", INFO_INFO);
if (!named_cmds)
put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO);
@@ -3006,6 +3034,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
timer=start_timer();
executing_query= 1;
error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length());
+ report_progress_end();
#ifdef HAVE_READLINE
if (status.add_to_history)
@@ -3893,8 +3922,9 @@ static int
com_edit(String *buffer,char *line __attribute__((unused)))
{
char filename[FN_REFLEN],buff[160];
- int fd,tmp;
+ int fd,tmp,error;
const char *editor;
+ MY_STAT stat_arg;
if ((fd=create_temp_file(filename,NullS,"sql", O_CREAT | O_WRONLY,
MYF(MY_WME))) < 0)
@@ -3910,10 +3940,14 @@ com_edit(String *buffer,char *line __attribute__((unused)))
!(editor = (char *)getenv("VISUAL")))
editor = "vi";
strxmov(buff,editor," ",filename,NullS);
- if(system(buff) == -1)
+ if ((error= system(buff)))
+ {
+ char errmsg[100];
+ sprintf(errmsg, "Command '%.40s' failed", buff);
+ put_info(errmsg, INFO_ERROR, 0, NullS);
goto err;
+ }
- MY_STAT stat_arg;
if (!my_stat(filename,&stat_arg,MYF(MY_WME)))
goto err;
if ((fd = my_open(filename,O_RDONLY, MYF(MY_WME))) < 0)
@@ -3997,7 +4031,7 @@ static int
com_connect(String *buffer, char *line)
{
char *tmp, buff[256];
- bool save_rehash= opt_rehash;
+ my_bool save_rehash= opt_rehash;
int error;
bzero(buff, sizeof(buff));
@@ -4055,6 +4089,7 @@ static int com_source(String *buffer __attribute__((unused)),
int error;
STATUS old_status;
FILE *sql_file;
+ my_bool save_ignore_errors;
/* Skip space from file name */
while (my_isspace(charset_info,*line))
@@ -4086,16 +4121,27 @@ static int com_source(String *buffer __attribute__((unused)),
/* Save old status */
old_status=status;
+ save_ignore_errors= ignore_errors;
bfill((char*) &status,sizeof(status),(char) 0);
status.batch=old_status.batch; // Run in batch mode
status.line_buff=line_buff;
status.file_name=source_name;
glob_buffer.length(0); // Empty command buffer
+ ignore_errors= !batch_abort_on_error;
+ in_com_source= 1;
error= read_and_execute(false);
+ ignore_errors= save_ignore_errors;
status=old_status; // Continue as before
+ in_com_source= aborted= 0;
my_fclose(sql_file,MYF(0));
batch_readline_end(line_buff);
+ /*
+ If we got an error during source operation, don't abort the client
+ if ignore_errors is set
+ */
+ if (error && ignore_errors)
+ error= -1; // Ignore error
return error;
}
@@ -4284,6 +4330,58 @@ char *get_arg(char *line, my_bool get_next_arg)
}
+/**
+ An example of mysql_authentication_dialog_ask callback.
+
+ The C function with the name "mysql_authentication_dialog_ask", if exists,
+ will be used by the "dialog" client authentication plugin when user
+ input is needed. This function should be of mysql_authentication_dialog_ask_t
+ type. If the function does not exists, a built-in implementation will be
+ used.
+
+ @param mysql mysql
+ @param type type of the input
+ 1 - normal string input
+ 2 - password string
+ @param prompt prompt
+ @param buf a buffer to store the use input
+ @param buf_len the length of the buffer
+
+ @retval a pointer to the user input string.
+ It may be equal to 'buf' or to 'mysql->password'.
+ In all other cases it is assumed to be an allocated
+ string, and the "dialog" plugin will free() it.
+*/
+
+MYSQL_PLUGIN_EXPORT
+char *mysql_authentication_dialog_ask(MYSQL *mysql, int type,
+ const char *prompt,
+ char *buf, int buf_len)
+{
+ char *s=buf;
+
+ fputs("[mariadb] ", stdout);
+ fputs(prompt, stdout);
+ fputs(" ", stdout);
+
+ if (type == 2) /* password */
+ {
+ s= get_tty_password("");
+ strnmov(buf, s, buf_len);
+ buf[buf_len-1]= 0;
+ my_free(s);
+ }
+ else
+ {
+ if (!fgets(buf, buf_len-1, stdin))
+ buf[0]= 0;
+ else if (buf[0] && (s= strend(buf))[-1] == '\n')
+ s[-1]= 0;
+ }
+
+ return buf;
+}
+
static int
sql_real_connect(char *host,char *database,char *user,char *password,
uint silent)
@@ -4331,17 +4429,13 @@ 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 (using_opt_enable_cleartext_plugin)
- mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
- (char*) &opt_enable_cleartext_plugin);
-
if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port,
connect_flag | CLIENT_MULTI_STATEMENTS))
@@ -4362,6 +4456,13 @@ sql_real_connect(char *host,char *database,char *user,char *password,
connected=1;
#ifndef EMBEDDED_LIBRARY
mysql.reconnect= debug_info_flag; // We want to know if this happens
+
+ /*
+ CLIENT_PROGRESS is set only if we requsted it in mysql_real_connect()
+ and the server also supports it
+ */
+ if (mysql.client_flag & CLIENT_PROGRESS)
+ mysql_options(&mysql, MYSQL_PROGRESS_CALLBACK, (void*) report_progress);
#else
mysql.reconnect= 1;
#endif
@@ -4458,6 +4559,7 @@ com_status(String *buffer __attribute__((unused)),
tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : "");
#endif
tee_fprintf(stdout, "Using delimiter:\t%s\n", delimiter);
+ tee_fprintf(stdout, "Server:\t\t\t%s\n", mysql_get_server_name(&mysql));
tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&mysql));
tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql));
tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql));
@@ -4626,12 +4728,19 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
if (error)
{
if (sqlstate)
- (void) tee_fprintf(file, "ERROR %d (%s): ", error, sqlstate);
+ (void) tee_fprintf(file, "ERROR %d (%s)", error, sqlstate);
else
- (void) tee_fprintf(file, "ERROR %d: ", error);
+ (void) tee_fprintf(file, "ERROR %d", error);
}
else
- tee_puts("ERROR: ", file);
+ tee_fputs("ERROR", file);
+ if (status.query_start_line && line_numbers)
+ {
+ (void) fprintf(file," at line %lu",status.query_start_line);
+ if (status.file_name)
+ (void) fprintf(file," in file: '%s'", status.file_name);
+ }
+ tee_fputs(": ", file);
}
else
vidattr(A_BOLD);
@@ -4640,7 +4749,7 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
}
if (unbuffered)
fflush(file);
- return info_type == INFO_ERROR ? -1 : 0;
+ return info_type == INFO_ERROR ? (ignore_errors ? -1 : 1): 0;
}
@@ -4777,7 +4886,7 @@ static void mysql_end_timer(ulong start_time,char *buff)
strmov(strend(buff),")");
}
-static const char* construct_prompt()
+static const char *construct_prompt()
{
processed_prompt.free(); // Erase the old prompt
time_t lclock = time(NULL); // Get the date struct
@@ -4806,6 +4915,12 @@ static const char* construct_prompt()
case 'd':
processed_prompt.append(current_db ? current_db : "(none)");
break;
+ case 'N':
+ if (connected)
+ processed_prompt.append(mysql_get_server_name(&mysql));
+ else
+ processed_prompt.append("unknown");
+ break;
case 'h':
{
const char *prompt;
@@ -4979,3 +5094,32 @@ static int com_prompt(String *buffer __attribute__((unused)),
tee_fprintf(stdout, "PROMPT set to '%s'\n", current_prompt);
return 0;
}
+
+#ifndef EMBEDDED_LIBRARY
+static void report_progress(const MYSQL *mysql, uint stage, uint max_stage,
+ double progress, const char *proc_info,
+ uint proc_info_length)
+{
+ uint length= printf("Stage: %d of %d '%.*s' %6.3g%% of stage done",
+ stage, max_stage, proc_info_length, proc_info,
+ progress);
+ if (length < last_progress_report_length)
+ printf("%*s", last_progress_report_length - length, "");
+ putc('\r', stdout);
+ fflush(stdout);
+ last_progress_report_length= length;
+}
+
+static void report_progress_end()
+{
+ if (last_progress_report_length)
+ {
+ printf("%*s\r", last_progress_report_length, "");
+ last_progress_report_length= 0;
+ }
+}
+#else
+static void report_progress_end()
+{
+}
+#endif
diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c
index bbb44678f51..f4e3111b7b7 100644
--- a/client/mysql_plugin.c
+++ b/client/mysql_plugin.c
@@ -100,6 +100,7 @@ int main(int argc,char *argv[])
char operation[16];
MY_INIT(argv[0]);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
plugin_data.name= 0; // initialize name
/*
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 8bbb8864afd..71bc936cfe6 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2006, 2012, Oracle and/or its affiliates.
+ Copyright (C) 2010, 2012, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,7 +22,7 @@
#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
-#define VER "1.1"
+#define VER "1.2"
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
@@ -40,6 +41,7 @@ static char mysqlcheck_path[FN_REFLEN];
static my_bool opt_force, opt_verbose, debug_info_flag, debug_check_flag,
opt_systables_only;
+static my_bool opt_not_used, opt_silent;
static uint my_end_arg= 0;
static char *opt_user= (char*)"root";
@@ -63,16 +65,20 @@ static my_bool not_used; /* Can't use GET_BOOL without a value pointer */
static my_bool opt_write_binlog;
+#define OPT_SILENT OPT_MAX_CLIENT_OPTION
+
static struct my_option my_long_options[]=
{
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
- {"basedir", 'b', "Not used by mysql_upgrade. Only for backward compatibility.",
+ {"basedir", 'b',
+ "Not used by mysql_upgrade. Only for backward compatibility.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
- "Directory for character set files.", 0,
- 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"compress", OPT_COMPRESS, "Use compression in server/client protocol.",
+ "Not used by mysql_upgrade. Only for backward compatibility.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ {"compress", OPT_COMPRESS,
+ "Not used by mysql_upgrade. Only for backward compatibility.",
&not_used, &not_used, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"datadir", 'd',
"Not used by mysql_upgrade. Only for backward compatibility.",
@@ -85,22 +91,21 @@ static struct my_option my_long_options[]=
&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,
- GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ &debug_check_flag, &debug_check_flag,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"debug-info", 'T', "Print some debug info at exit.", &debug_info_flag,
&debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"default-character-set", OPT_DEFAULT_CHARSET,
- "Set the default character set.", 0,
- 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ "Not used by mysql_upgrade. Only for backward compatibility.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"default_auth", OPT_DEFAULT_AUTH,
"Default authentication client-side plugin to use.",
&opt_default_auth, &opt_default_auth, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade "
"has already been executed for the current version of MySQL.",
- &opt_force, &opt_force, 0,
- GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"host",'h', "Connect to host.", 0,
+ &opt_force, &opt_force, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"host", 'h', "Connect to host.", 0,
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p',
"Password to use when connecting to server. If password is not given,"
@@ -128,6 +133,8 @@ static struct my_option my_long_options[]=
"Base name of shared memory.", 0,
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"silent", OPT_SILENT, "Print less information", &opt_silent,
+ &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"socket", 'S', "The socket file to use for connection.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#include <sslopt-longopts.h>
@@ -140,8 +147,7 @@ static struct my_option my_long_options[]=
{"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.",
- &opt_verbose, &opt_verbose, 0,
- GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ &opt_not_used, &opt_not_used, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"write-binlog", OPT_WRITE_BINLOG,
"All commands including mysqlcheck are binlogged. Enabled by default;"
"use --skip-write-binlog when commands should not be sent to replication slaves.",
@@ -187,7 +193,7 @@ static void verbose(const char *fmt, ...)
{
va_list args;
- if (!opt_verbose)
+ if (opt_silent)
return;
/* Print the verbose message */
@@ -246,9 +252,9 @@ get_one_option(int optid, const struct my_option *opt,
printf("%s Ver %s Distrib %s, for %s (%s)\n",
my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
- puts("MySQL utility for upgrading databases to new MySQL versions.\n");
+ puts("MariaDB utility for upgrading databases to new MariaDB versions.\n");
my_print_help(my_long_options);
- exit(0);
+ die(0);
break;
case '#':
@@ -284,6 +290,18 @@ get_one_option(int optid, const struct my_option *opt,
/* FALLTHROUGH */
case 'v': /* --verbose */
+ opt_verbose++;
+ if (argument == disabled_my_option)
+ {
+ opt_verbose= 0;
+ opt_silent= 1;
+ }
+ add_option= 0;
+ break;
+ case OPT_SILENT:
+ opt_verbose= 0;
+ add_option= 0;
+ break;
case 'f': /* --force */
case 's': /* --upgrade-system-tables */
case OPT_WRITE_BINLOG: /* --write-binlog */
@@ -448,7 +466,8 @@ static void find_tool(char *tool_executable_name, const char *tool_name,
len, self_name, FN_LIBCHAR, tool_name);
}
- verbose("Looking for '%s' as: %s", tool_name, tool_executable_name);
+ if (opt_verbose)
+ verbose("Looking for '%s' as: %s", tool_name, tool_executable_name);
/*
Make sure it can be executed
@@ -518,7 +537,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
"--database=mysql",
"--batch", /* Turns off pager etc. */
force ? "--force": "--skip-force",
- ds_res ? "--silent": "",
+ ds_res || opt_silent ? "--silent": "",
"<",
query_file_path,
"2>&1",
@@ -600,7 +619,6 @@ static int upgrade_already_done(void)
FILE *in;
char upgrade_info_file[FN_REFLEN]= {0};
char buf[sizeof(MYSQL_SERVER_VERSION)+1];
- char *res;
if (get_upgrade_info_file_name(upgrade_info_file))
return 0; /* Could not get filename => not sure */
@@ -608,19 +626,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 */
- /*
- Read from file, don't care if it fails since it
- will be detected by the strncmp
- */
bzero(buf, sizeof(buf));
- res= fgets(buf, sizeof(buf), in);
+ if (!fgets(buf, sizeof(buf), in))
+ {
+ /* Ignore, will be detected by strncmp() below */
+ }
my_fclose(in, MYF(0));
- if (!res)
- return 0; /* Could not read from file => not sure */
-
- return (strncmp(res, MYSQL_SERVER_VERSION,
+ return (strncmp(buf, MYSQL_SERVER_VERSION,
sizeof(MYSQL_SERVER_VERSION)-1)==0);
}
@@ -676,6 +690,8 @@ static void create_mysql_upgrade_info_file(void)
static void print_conn_args(const char *tool_name)
{
+ if (opt_verbose < 2)
+ return;
if (conn_args.str[0])
verbose("Running '%s' with connection arguments: %s", tool_name,
conn_args.str);
@@ -691,6 +707,7 @@ static void print_conn_args(const char *tool_name)
static int run_mysqlcheck_upgrade(void)
{
+ verbose("Phase 2/3: Checking and upgrading tables");
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
@@ -699,6 +716,8 @@ static int run_mysqlcheck_upgrade(void)
"--check-upgrade",
"--all-databases",
"--auto-repair",
+ !opt_silent || opt_verbose ? "--verbose": "",
+ opt_silent ? "--silent": "",
opt_write_binlog ? "--write-binlog" : "--skip-write-binlog",
NULL);
}
@@ -706,6 +725,7 @@ static int run_mysqlcheck_upgrade(void)
static int run_mysqlcheck_fixnames(void)
{
+ verbose("Phase 1/3: Fixing table and database names");
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
@@ -714,6 +734,8 @@ static int run_mysqlcheck_fixnames(void)
"--all-databases",
"--fix-db-names",
"--fix-table-names",
+ opt_verbose ? "--verbose": "",
+ opt_silent ? "--silent": "",
opt_write_binlog ? "--write-binlog" : "--skip-write-binlog",
NULL);
}
@@ -783,7 +805,7 @@ static int run_sql_fix_privilege_tables(void)
if (init_dynamic_string(&ds_result, "", 512, 512))
die("Out of memory");
- verbose("Running 'mysql_fix_privilege_tables'...");
+ verbose("Phase 3/3: Running 'mysql_fix_privilege_tables'...");
run_query(mysql_fix_privilege_tables,
&ds_result, /* Collect result */
TRUE);
@@ -812,14 +834,16 @@ static int run_sql_fix_privilege_tables(void)
}
dynstr_free(&ds_result);
- return found_real_errors;
+ DBUG_RETURN(found_real_errors);
}
static const char *load_default_groups[]=
{
- "client", /* Read settings how to connect to server */
- "mysql_upgrade", /* Read special settings for mysql_upgrade*/
+ "client", /* Read settings how to connect to server */
+ "mysql_upgrade", /* Read special settings for mysql_upgrade */
+ "client-server", /* Reads settings common between client & server */
+ "client-mariadb", /* Read mariadb unique client settings */
0
};
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 2a1d61395e2..e2ebb883f77 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2012, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,7 +25,7 @@
#include <sql_common.h>
#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
-#define ADMIN_VERSION "8.42"
+#define ADMIN_VERSION "9.0"
#define MAX_MYSQL_VAR 512
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
#define MAX_TRUNC_LENGTH 3
@@ -44,8 +45,6 @@ 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 uint opt_enable_cleartext_plugin= 0;
-static my_bool using_opt_enable_cleartext_plugin= 0;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
@@ -100,7 +99,10 @@ 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_THREADS, ADMIN_OLD_PASSWORD, ADMIN_FLUSH_SLOW_LOG,
+ ADMIN_FLUSH_TABLE_STATISTICS, ADMIN_FLUSH_INDEX_STATISTICS,
+ ADMIN_FLUSH_USER_STATISTICS, ADMIN_FLUSH_CLIENT_STATISTICS,
+ ADMIN_FLUSH_ALL_STATUS, ADMIN_FLUSH_ALL_STATISTICS
};
static const char *command_names[]= {
"create", "drop", "shutdown",
@@ -110,7 +112,10 @@ 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-threads", "old-password", "flush-slow-log",
+ "flush-table-statistics", "flush-index-statistics",
+ "flush-user-statistics", "flush-client-statistics",
+ "flush-all-status", "flush-all-statistics",
NullS
};
@@ -215,15 +220,12 @@ static struct my_option my_long_options[] =
"Default authentication client-side plugin to use.",
&opt_default_auth, &opt_default_auth, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
- "Enable/disable the clear text authentication plugin.",
- &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin,
- 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-static const char *load_default_groups[]= { "mysqladmin","client",0 };
+static const char *load_default_groups[]=
+{ "mysqladmin", "client", "client-server", "client-mariadb", 0 };
my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
@@ -289,9 +291,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
opt->name);
break;
- case OPT_ENABLE_CLEARTEXT_PLUGIN:
- using_opt_enable_cleartext_plugin= TRUE;
- break;
}
if (error)
{
@@ -304,20 +303,18 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
int main(int argc,char *argv[])
{
- int error= 0, ho_error;
+ int error= 0;
MYSQL mysql;
char **commands, **save_argv;
MY_INIT(argv[0]);
mysql_init(&mysql);
- if (load_defaults("my",load_default_groups,&argc,&argv))
- exit(1);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
+ if ((error= load_defaults("my",load_default_groups,&argc,&argv)))
+ goto err1;
save_argv = argv; /* Save for free_defaults */
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
- {
- free_defaults(save_argv);
- exit(ho_error);
- }
+ if ((error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ goto err2;
if (debug_info_flag)
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
if (debug_check_flag)
@@ -335,6 +332,8 @@ int main(int argc,char *argv[])
(void) signal(SIGINT,endprog); /* Here if abort */
(void) signal(SIGTERM,endprog); /* Here if abort */
+ sf_leaking_memory=0; /* from now on we cleanup properly */
+
if (opt_compress)
mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
if (opt_connect_timeout)
@@ -364,10 +363,6 @@ int main(int argc,char *argv[])
if (opt_default_auth && *opt_default_auth)
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
- if (using_opt_enable_cleartext_plugin)
- mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
- (char*) &opt_enable_cleartext_plugin);
-
if (sql_connect(&mysql, option_wait))
{
/*
@@ -470,14 +465,17 @@ int main(int argc,char *argv[])
} /* got connection */
mysql_close(&mysql);
+err2:
+ mysql_library_end();
my_free(opt_password);
my_free(user);
#ifdef HAVE_SMEM
my_free(shared_memory_base_name);
#endif
free_defaults(save_argv);
+err1:
my_end(my_end_arg);
- exit(error ? 1 : 0);
+ exit(error);
return 0;
}
@@ -603,11 +601,12 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
If this behaviour is ever changed, Docs should be notified.
*/
- struct rand_struct rand_st;
+ struct my_rnd_struct rand_st;
for (; argc > 0 ; argv++,argc--)
{
- switch (find_type(argv[0],&command_typelib, FIND_TYPE_BASIC)) {
+ int command;
+ switch ((command= find_type(argv[0],&command_typelib,FIND_TYPE_BASIC))) {
case ADMIN_CREATE:
{
char buff[FN_REFLEN+20];
@@ -684,7 +683,10 @@ 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_MASTER | REFRESH_TABLE_STATS |
+ REFRESH_INDEX_STATS |
+ REFRESH_USER_STATS |
+ REFRESH_CLIENT_STATS)))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -877,9 +879,19 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_LOGS:
{
- if (mysql_refresh(mysql,REFRESH_LOG))
+ if (mysql_query(mysql,"flush logs"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ 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"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -889,7 +901,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_query(mysql,"flush hosts"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -899,7 +911,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_query(mysql,"flush tables"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -909,7 +921,71 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_query(mysql,"flush status"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_TABLE_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush table_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_INDEX_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush index_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_USER_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush user_statistics"))
+ {
+ 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"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_ALL_STATISTICS:
+ {
+ if (mysql_query(mysql,
+ "flush table_statistics,index_statistics,"
+ "user_statistics,client_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_ALL_STATUS:
+ {
+ if (mysql_query(mysql,
+ "flush status,table_statistics,index_statistics,"
+ "user_statistics,client_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -923,7 +999,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
char *typed_password= NULL, *verified= NULL;
/* Do initialization the same way as we do in mysqld */
start_time=time((time_t*) 0);
- randominit(&rand_st,(ulong) start_time,(ulong) start_time/2);
+ my_rnd_init(&rand_st,(ulong) start_time,(ulong) start_time/2);
if (argc < 1)
{
@@ -1107,16 +1183,23 @@ static void usage(void)
my_print_variables(my_long_options);
print_defaults("my",load_default_groups);
puts("\nWhere command is a one or more of: (Commands may be shortened)\n\
- create databasename Create a new database\n\
- debug Instruct server to write debug information to log\n\
- drop databasename Delete a database and all its tables\n\
- extended-status Gives an extended status message from the server\n\
- flush-hosts Flush all cached hosts\n\
- flush-logs Flush all logs\n\
- flush-status Clear status variables\n\
- flush-tables Flush all tables\n\
- flush-threads Flush the thread cache\n\
- flush-privileges Reload grant tables (same as reload)\n\
+ create databasename Create a new database\n\
+ debug Instruct server to write debug information to log\n\
+ drop databasename Delete a database and all its tables\n\
+ extended-status Gives an extended status message from the server\n\
+ flush-all-statistics Flush all statistics tables\n\
+ flush-all-status Flush status and statistics\n\
+ flush-client-statistics Flush client statistics\n\
+ flush-hosts Flush all cached hosts\n\
+ flush-index-statistics Flush index statistics\n\
+ flush-logs Flush all logs\n\
+ flush-privileges Reload grant tables (same as reload)\n\
+ flush-slow-log Flush slow query log\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\
kill id,id,... Kill mysql threads");
#if MYSQL_VERSION_ID >= 32200
puts("\
@@ -1406,7 +1489,7 @@ static my_bool wait_pidfile(char *pidfile, time_t last_modified,
struct stat *pidfile_status)
{
char buff[FN_REFLEN];
- int error= 1;
+ my_bool error= 1;
uint count= 0;
DBUG_ENTER("wait_pidfile");
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index a58aa65207d..777e68902dd 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2012, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,6 +31,7 @@
#define MYSQL_CLIENT
#undef MYSQL_SERVER
+#define TABLE TABLE_CLIENT
#include "client_priv.h"
#include <my_time.h>
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
@@ -39,12 +41,24 @@
#include "my_dir.h"
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
+
+#include "sql_string.h" // needed for Rpl_filter
+#include "sql_list.h" // needed for Rpl_filter
+#include "rpl_filter.h"
+
+#include "mysqld.h"
+
+Rpl_filter *binlog_filter= 0;
+
#define BIN_LOG_HEADER_SIZE 4
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
+/* Needed for Rpl_filter */
+CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
+
char server_version[SERVER_VERSION_LENGTH];
ulong server_id = 0;
@@ -59,13 +73,14 @@ static FILE *result_file;
#ifndef DBUG_OFF
static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
#endif
-static const char *load_default_groups[]= { "mysqlbinlog","client",0 };
+static const char *load_groups[]=
+{ "mysqlbinlog", "client", "client-server", "client-mariadb", 0 };
static void error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
static void warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0;
-static bool opt_hexdump= 0;
+static bool opt_hexdump= 0, opt_version= 0;
const char *base64_output_mode_names[]=
{"NEVER", "AUTO", "ALWAYS", "UNSPEC", "DECODE-ROWS", NullS};
TYPELIB base64_output_mode_typelib=
@@ -77,12 +92,13 @@ 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_verify_binlog_checksum= 1;
static ulonglong offset = 0;
static char* host = 0;
static int port= 0;
static uint my_end_arg;
static const char* sock= 0;
-static char *opt_plugin_dir= 0, *opt_default_auth= 0;
+static char *opt_plugindir= 0, *opt_default_auth= 0;
#ifdef HAVE_SMEM
static char *shared_memory_base_name= 0;
@@ -102,7 +118,8 @@ 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 char* dirname_for_local_load= 0;
+static const char* dirname_for_local_load= 0;
+static bool opt_skip_annotate_row_events= 0;
/**
Pointer to the Format_description_log_event of the currently active binlog.
@@ -124,6 +141,71 @@ enum Exit_status {
OK_STOP
};
+/**
+ Pointer to the last read Annotate_rows_log_event. Having read an
+ Annotate_rows event, we should not print it immediatedly because all
+ subsequent rbr events can be filtered away, and have to keep it for a while.
+ Also because of that when reading a remote Annotate event we have to keep
+ its binary log representation in a separately allocated buffer.
+*/
+static Annotate_rows_log_event *annotate_event= NULL;
+
+void free_annotate_event()
+{
+ if (annotate_event)
+ {
+ delete annotate_event;
+ annotate_event= 0;
+ }
+}
+
+Log_event* read_remote_annotate_event(uchar* net_buf, ulong event_len,
+ const char **error_msg)
+{
+ uchar *event_buf;
+ Log_event* event;
+
+ if (!(event_buf= (uchar*) my_malloc(event_len + 1, MYF(MY_WME))))
+ {
+ error("Out of memory");
+ return 0;
+ }
+
+ memcpy(event_buf, net_buf, event_len);
+ event_buf[event_len]= 0;
+
+ if (!(event= Log_event::read_log_event((const char*) event_buf, event_len,
+ error_msg, glob_description_event,
+ opt_verify_binlog_checksum)))
+ {
+ my_free(event_buf);
+ return 0;
+ }
+ /*
+ Ensure the event->temp_buf is pointing to the allocated buffer.
+ (TRUE = free temp_buf on the event deletion)
+ */
+ event->register_temp_buf((char*)event_buf, TRUE);
+
+ return event;
+}
+
+void keep_annotate_event(Annotate_rows_log_event* event)
+{
+ free_annotate_event();
+ annotate_event= event;
+}
+
+void print_annotate_event(PRINT_EVENT_INFO *print_event_info)
+{
+ if (annotate_event)
+ {
+ annotate_event->print(result_file, print_event_info);
+ delete annotate_event; // the event should not be printed more than once
+ annotate_event= 0;
+ }
+}
+
static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
const char* logname);
static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
@@ -632,6 +714,72 @@ static bool shall_skip_database(const char *log_dbname)
/**
+ Print "use <db>" statement when current db is to be changed.
+
+ We have to control emiting USE statements according to rewrite-db options.
+ We have to do it here (see process_event() below) and to suppress
+ producing USE statements by corresponding log event print-functions.
+*/
+
+static void
+print_use_stmt(PRINT_EVENT_INFO* pinfo, const Query_log_event *ev)
+{
+ const char* db= ev->db;
+ const size_t db_len= ev->db_len;
+
+ // pinfo->db is the current db.
+ // If current db is the same as required db, do nothing.
+ if ((ev->flags & LOG_EVENT_SUPPRESS_USE_F) || !db ||
+ !memcmp(pinfo->db, db, db_len + 1))
+ return;
+
+ // Current db and required db are different.
+ // Check for rewrite rule for required db. (Note that in a rewrite rule
+ // neither db_from nor db_to part can be empty).
+ size_t len_to= 0;
+ const char *db_to= binlog_filter->get_rewrite_db(db, &len_to);
+
+ // If there is no rewrite rule for db (in this case len_to is left = 0),
+ // printing of the corresponding USE statement is left for log event
+ // print-function.
+ if (!len_to)
+ return;
+
+ // In case of rewrite rule print USE statement for db_to
+ my_fprintf(result_file, "use %`s%s\n", db_to, pinfo->delimiter);
+
+ // Copy the *original* db to pinfo to suppress emiting
+ // of USE stmts by log_event print-functions.
+ memcpy(pinfo->db, db, db_len + 1);
+}
+
+
+/**
+ Print "SET skip_replication=..." statement when needed.
+
+ Not all servers support this (only MariaDB from some version on). So we
+ mark the SET to only execute from the version of MariaDB that supports it,
+ and also only output it if we actually see events with the flag set, to not
+ get spurious errors on MySQL@Oracle servers of higher version that do not
+ support the flag.
+
+ So we start out assuming @@skip_replication is 0, and only output a SET
+ statement when it changes.
+*/
+static void
+print_skip_replication_statement(PRINT_EVENT_INFO *pinfo, const Log_event *ev)
+{
+ int cur_val;
+
+ cur_val= (ev->flags & LOG_EVENT_SKIP_REPLICATION_F) != 0;
+ if (cur_val == pinfo->skip_replication)
+ return; /* Not changed. */
+ fprintf(result_file, "/*!50521 SET skip_replication=%d*/%s\n",
+ cur_val, pinfo->delimiter);
+ pinfo->skip_replication= cur_val;
+}
+
+/**
Prints the given event in base64 format.
The header is printed to the head cache and the body is printed to
@@ -706,7 +854,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
read them to be able to process the wanted events.
*/
if (((rec_count >= offset) &&
- ((my_time_t)(ev->when) >= start_datetime)) ||
+ (ev->when >= start_datetime)) ||
(ev_type == FORMAT_DESCRIPTION_EVENT))
{
if (ev_type != FORMAT_DESCRIPTION_EVENT)
@@ -730,7 +878,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
server_id && (server_id != ev->server_id))
goto end;
}
- if (((my_time_t)(ev->when) >= stop_datetime)
+ if ((ev->when >= stop_datetime)
|| (pos >= stop_position_mot))
{
/* end the program */
@@ -751,9 +899,22 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
switch (ev_type) {
case QUERY_EVENT:
- if (!((Query_log_event*)ev)->is_trans_keyword() &&
- shall_skip_database(((Query_log_event*)ev)->db))
- goto end;
+ {
+ Query_log_event *qe= (Query_log_event*)ev;
+ if (!qe->is_trans_keyword())
+ {
+ if (shall_skip_database(qe->db))
+ goto end;
+ }
+ else
+ {
+ /*
+ In case the event for one of these statements is obtained
+ from binary log 5.0, make it compatible with 5.1
+ */
+ qe->flags|= LOG_EVENT_SUPPRESS_USE_F;
+ }
+ print_use_stmt(print_event_info, qe);
if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
{
if ((retval= write_event_header_and_base64(ev, result_file,
@@ -762,10 +923,14 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
goto end;
}
else
+ {
+ print_skip_replication_statement(print_event_info, ev);
ev->print(result_file, print_event_info);
+ }
if (head->error == -1)
goto err;
break;
+ }
case CREATE_FILE_EVENT:
{
@@ -794,6 +959,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
}
else
{
+ print_skip_replication_statement(print_event_info, ev);
ce->print(result_file, print_event_info, TRUE);
if (head->error == -1)
goto err;
@@ -906,9 +1072,11 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
if (!shall_skip_database(exlq->db))
{
+ print_use_stmt(print_event_info, exlq);
if (fname)
{
convert_path_to_forward_slashes(fname);
+ print_skip_replication_statement(print_event_info, ev);
exlq->print(result_file, print_event_info, fname);
if (head->error == -1)
{
@@ -926,6 +1094,19 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
my_free(fname);
break;
}
+ case ANNOTATE_ROWS_EVENT:
+ if (!opt_skip_annotate_row_events)
+ {
+ /*
+ We don't print Annotate event just now because all subsequent
+ rbr-events can be filtered away. Instead we'll keep the event
+ till it will be printed together with the first not filtered
+ away Table map or the last rbr will be processed.
+ */
+ keep_annotate_event((Annotate_rows_log_event*) ev);
+ destroy_evt= FALSE;
+ }
+ break;
case TABLE_MAP_EVENT:
{
Table_map_log_event *map= ((Table_map_log_event *)ev);
@@ -935,6 +1116,20 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
destroy_evt= FALSE;
goto end;
}
+ /*
+ The Table map is to be printed, so it's just the time when we may
+ print the kept Annotate event (if there is any).
+ print_annotate_event() also deletes the kept Annotate event.
+ */
+ print_annotate_event(print_event_info);
+
+ size_t len_to= 0;
+ const char* db_to= binlog_filter->get_rewrite_db(map->get_db_name(), &len_to);
+ if (len_to && map->rewrite_db(db_to, len_to, glob_description_event))
+ {
+ error("Could not rewrite database name");
+ goto err;
+ }
}
case WRITE_ROWS_EVENT:
case DELETE_ROWS_EVENT:
@@ -964,6 +1159,13 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
if (print_event_info->m_table_map_ignored.count() > 0)
print_event_info->m_table_map_ignored.clear_tables();
+ /*
+ If there is a kept Annotate event and all corresponding
+ rbr-events were filtered away, the Annotate event was not
+ freed and it is just the time to do it.
+ */
+ free_annotate_event();
+
/*
One needs to take into account an event that gets
filtered but was last event in the statement. If this is
@@ -1010,6 +1212,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
/* FALL THROUGH */
}
default:
+ print_skip_replication_statement(print_event_info, ev);
ev->print(result_file, print_event_info);
if (head->error == -1)
goto err;
@@ -1022,14 +1225,16 @@ err:
retval= ERROR_STOP;
end:
rec_count++;
+
/*
- Destroy the log_event object. If reading from a remote host,
- set the temp_buf to NULL so that memory isn't freed twice.
+ Destroy the log_event object.
+ MariaDB MWL#36: mainline does this:
+ If reading from a remote host,
+ set the temp_buf to NULL so that memory isn't freed twice.
+ We no longer do that, we use Rpl_filter::event_owns_temp_buf instead.
*/
if (ev)
{
- if (remote_opt)
- ev->temp_buf= 0;
if (destroy_evt) /* destroy it later if not set (ignored table map) */
delete ev;
}
@@ -1037,7 +1242,7 @@ end:
}
-static struct my_option my_long_options[] =
+static struct my_option my_options[] =
{
{"help", '?', "Display this help and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -1107,7 +1312,7 @@ static struct my_option my_long_options[] =
{"password", 'p', "Password to connect to remote server.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
- &opt_plugin_dir, &opt_plugin_dir, 0,
+ &opt_plugindir, &opt_plugindir, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection or 0 for default to, in "
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
@@ -1125,7 +1330,7 @@ static struct my_option my_long_options[] =
0, 0},
{"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"server-id", OPT_SERVER_ID,
+ {"server-id", 0,
"Extract only binlog entries created by the server having the given id.",
&server_id, &server_id, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -1194,6 +1399,18 @@ that may lead to an endless loop.",
"Used to reserve file descriptors for use by this program.",
&open_files_limit, &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
+ {"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},
+ {"rewrite-db", OPT_REWRITE_DB,
+ "Updates to a database with a different name than the original. \
+Example: rewrite-db='from->to'.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"skip-annotate-row-events", OPT_SKIP_ANNOTATE_ROWS_EVENTS,
+ "Don't print Annotate_rows events stored in the binary log.",
+ (uchar**) &opt_skip_annotate_row_events,
+ (uchar**) &opt_skip_annotate_row_events,
+ 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}
};
@@ -1269,8 +1486,9 @@ static void cleanup()
my_free(database);
my_free(host);
my_free(user);
- my_free(dirname_for_local_load);
+ my_free(const_cast<char*>(dirname_for_local_load));
+ delete binlog_filter;
delete glob_description_event;
if (mysql)
mysql_close(mysql);
@@ -1291,8 +1509,8 @@ static void usage()
Dumps a MySQL binary log in a format usable for viewing or for piping to\n\
the mysql command line client.\n\n");
printf("Usage: %s [options] log-files\n", my_progname);
- my_print_help(my_long_options);
- my_print_variables(my_long_options);
+ my_print_help(my_options);
+ my_print_variables(my_options);
}
@@ -1301,7 +1519,7 @@ static my_time_t convert_str_to_timestamp(const char* str)
int was_cut;
MYSQL_TIME l_time;
long dummy_my_timezone;
- my_bool dummy_in_dst_time_gap;
+ 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)
@@ -1374,6 +1592,53 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
(find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1);
}
break;
+ case OPT_REWRITE_DB: // db_from->db_to
+ {
+ /* See also handling of OPT_REPLICATE_REWRITE_DB in sql/mysqld.cc */
+ char* ptr;
+ char* key= argument; // db-from
+ char* val; // db-to
+
+ // Where key begins
+ while (*key && my_isspace(&my_charset_latin1, *key))
+ key++;
+
+ // Where val begins
+ if (!(ptr= strstr(argument, "->")))
+ {
+ sql_print_error("Bad syntax in rewrite-db: missing '->'!\n");
+ return 1;
+ }
+ val= ptr + 2;
+ while (*val && my_isspace(&my_charset_latin1, *val))
+ val++;
+
+ // Write \0 and skip blanks at the end of key
+ *ptr-- = 0;
+ while (my_isspace(&my_charset_latin1, *ptr) && ptr > argument)
+ *ptr-- = 0;
+
+ if (!*key)
+ {
+ sql_print_error("Bad syntax in rewrite-db: empty db-from!\n");
+ return 1;
+ }
+
+ // Skip blanks at the end of val
+ ptr= val;
+ while (*ptr && !my_isspace(&my_charset_latin1, *ptr))
+ ptr++;
+ *ptr= 0;
+
+ if (!*val)
+ {
+ sql_print_error("Bad syntax in rewrite-db: empty db-to!\n");
+ return 1;
+ }
+
+ binlog_filter->add_db_rewrite(key, val);
+ break;
+ }
case 'v':
if (argument == disabled_my_option)
verbose= 0;
@@ -1382,10 +1647,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case 'V':
print_version();
- exit(0);
+ opt_version= 1;
+ break;
case '?':
usage();
- exit(0);
+ opt_version= 1;
+ break;
}
if (tty_password)
pass= get_tty_password(NullS);
@@ -1399,7 +1666,7 @@ static int parse_args(int *argc, char*** argv)
int ho_error;
result_file = stdout;
- if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
+ 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;
@@ -1418,6 +1685,10 @@ static int parse_args(int *argc, char*** argv)
*/
static Exit_status safe_connect()
{
+ /* Close any old connections to MySQL */
+ if (mysql)
+ mysql_close(mysql);
+
mysql= mysql_init(NULL);
if (!mysql)
@@ -1426,8 +1697,8 @@ static Exit_status safe_connect()
return ERROR_STOP;
}
- if (opt_plugin_dir && *opt_plugin_dir)
- mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+ if (opt_plugindir && *opt_plugindir)
+ mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugindir);
if (opt_default_auth && *opt_default_auth)
mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
@@ -1524,7 +1795,18 @@ static Exit_status check_master_version()
"Master reported NULL for the version.");
goto err;
}
-
+ /*
+ Make a notice to the server that this client
+ is checksum-aware. It does not need the first fake Rotate
+ necessary checksummed.
+ That preference is specified below.
+ */
+ if (mysql_query(mysql, "SET @master_binlog_checksum='NONE'"))
+ {
+ error("Could not notify master about checksum awareness."
+ "Master returned '%s'", mysql_error(mysql));
+ goto err;
+ }
delete glob_description_event;
switch (*version) {
case '3':
@@ -1606,6 +1888,8 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
cast to uint32.
*/
int4store(buf, (uint32)start_position);
+ if (!opt_skip_annotate_row_events)
+ binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
size_t tlen = strlen(logname);
@@ -1638,18 +1922,31 @@ 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 (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
- len - 1, &error_msg,
- glob_description_event)))
+ if (net->read_pos[5] == ANNOTATE_ROWS_EVENT)
{
- 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);
+ 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 ||
@@ -1877,7 +2174,8 @@ 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, glob_description_event,
+ opt_verify_binlog_checksum)))
/* EOF can't be hit here normally, so it's a real error */
{
error("Could not read a Format_description_log_event event at "
@@ -1910,7 +2208,8 @@ 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, glob_description_event,
+ opt_verify_binlog_checksum)))
{
/* EOF can't be hit here normally, so it's a real error */
error("Could not read a Rotate_log_event event at offset %llu;"
@@ -2023,7 +2322,8 @@ 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, glob_description_event,
+ opt_verify_binlog_checksum);
if (!ev)
{
/*
@@ -2065,6 +2365,8 @@ end:
return retval;
}
+/* Used in sql_alloc(). Inited and freed in main() */
+MEM_ROOT s_mem_root;
int main(int argc, char** argv)
{
@@ -2077,17 +2379,27 @@ int main(int argc, char** argv)
my_init_time(); // for time functions
- if (load_defaults("my", load_default_groups, &argc, &argv))
+ init_alloc_root(&s_mem_root, 16384, 0);
+ if (load_defaults("my", load_groups, &argc, &argv))
+ exit(1);
+
+ if (!(binlog_filter= new Rpl_filter))
+ {
+ error("Failed to create Rpl_filter");
exit(1);
+ }
+
defaults_argv= argv;
parse_args(&argc, (char***)&argv);
- if (!argc)
+ if (!argc || opt_version)
{
- usage();
+ if (!argc)
+ usage();
+ cleanup();
free_defaults(defaults_argv);
my_end(my_end_arg);
- exit(1);
+ exit(!opt_version);
}
if (opt_base64_output_mode == BASE64_OUTPUT_UNSPEC)
@@ -2173,6 +2485,8 @@ int main(int argc, char** argv)
if (result_file != stdout)
my_fclose(result_file, MYF(0));
cleanup();
+ free_annotate_event();
+ free_root(&s_mem_root, MYF(0));
free_defaults(defaults_argv);
my_free_open_file_info();
load_processor.destroy();
@@ -2184,14 +2498,24 @@ int main(int argc, char** argv)
DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
}
+
+void *sql_alloc(size_t size)
+{
+ return alloc_root(&s_mem_root, size);
+}
+
/*
We must include this here as it's compiled with different options for
the server
*/
+#undef TABLE
#include "my_decimal.h"
#include "decimal.c"
#include "my_decimal.cc"
#include "log_event.cc"
#include "log_event_old.cc"
#include "rpl_utility.cc"
+#include "sql_string.cc"
+#include "sql_list.cc"
+#include "rpl_filter.cc"
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 8a9711fffae..4218f2da62c 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2001, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2011, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,7 +16,9 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define CHECK_VERSION "2.5.0"
+/* By Jani Tolonen, 2001-04-20, MySQL Development Team */
+
+#define CHECK_VERSION "2.7.0"
#include "client_priv.h"
#include <m_ctype.h>
@@ -35,8 +38,8 @@ static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 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_write_binlog= 1;
+ opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0;
+static my_bool opt_write_binlog= 1, opt_flush_tables= 0;
static uint verbose = 0, opt_mysql_port=0;
static int my_end_arg;
static char * opt_mysql_unix_port = 0;
@@ -45,9 +48,7 @@ static char *opt_password = 0, *current_user = 0,
static char *opt_plugin_dir= 0, *opt_default_auth= 0;
static int first_error = 0;
DYNAMIC_ARRAY tables4repair, tables4rebuild;
-#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
-#endif
static uint opt_protocol=0;
enum operations { DO_CHECK=1, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE };
@@ -69,8 +70,8 @@ static struct my_option my_long_options[] =
&opt_auto_repair, &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0,
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},
+ "Directory for character set files.", (char**) &charsets_dir,
+ (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"check", 'c', "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
0, 0, 0, 0},
{"check-only-changed", 'C',
@@ -122,10 +123,13 @@ static struct my_option my_long_options[] =
"If you are using this option with CHECK TABLE, it will ensure that the table is 100 percent consistent, but will take a long time. If you are using this option with REPAIR TABLE, it will force using old slow repair with keycache method, instead of much faster repair by sorting.",
&opt_extended, &opt_extended, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
+ {"flush", OPT_FLUSH_TABLES, "Flush each table after check. This is useful if you don't want to have the checked tables take up space in the caches after the check",
+ &opt_flush_tables, &opt_flush_tables, 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},
{"host",'h', "Connect to host.", &current_host,
- &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ &current_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"medium-check", 'm',
"Faster than extended-check, but only finds 99.99 percent of all errors. Should be good enough for most cases.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -191,7 +195,8 @@ static struct my_option my_long_options[] =
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-static const char *load_default_groups[] = { "mysqlcheck", "client", 0 };
+static const char *load_default_groups[]=
+{ "mysqlcheck", "client", "client-server", "client-mariadb", 0 };
static void print_version(void);
@@ -223,27 +228,27 @@ static void print_version(void)
static void usage(void)
{
+ DBUG_ENTER("usage");
print_version();
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
puts("This program can be used to CHECK (-c, -m, -C), REPAIR (-r), ANALYZE (-a),");
puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be");
puts("used at the same time. Not all options are supported by all storage engines.");
- puts("Please consult the MySQL manual for latest information about the");
- puts("above. The options -c, -r, -a, and -o are exclusive to each other, which");
+ puts("The options -c, -r, -a, and -o are exclusive to each other, which");
puts("means that the last option will be used, if several was specified.\n");
- puts("The option -c will be used by default, if none was specified. You");
- puts("can change the default behavior by making a symbolic link, or");
+ puts("The option -c (--check) will be used by default, if none was specified.");
+ puts("You can change the default behavior by making a symbolic link, or");
puts("copying this file somewhere with another name, the alternatives are:");
puts("mysqlrepair: The default option will be -r");
puts("mysqlanalyze: The default option will be -a");
puts("mysqloptimize: The default option will be -o\n");
- printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
- printf("OR %s [OPTIONS] --databases DB1 [DB2 DB3...]\n",
- my_progname);
- printf("OR %s [OPTIONS] --all-databases\n", my_progname);
+ puts("Please consult the MariaDB/MySQL knowledgebase at");
+ puts("http://kb.askmonty.org/v/mysqlcheck for latest information about");
+ puts("this program.");
print_defaults("my", load_default_groups);
my_print_help(my_long_options);
my_print_variables(my_long_options);
+ DBUG_VOID_RETURN;
} /* usage */
@@ -252,6 +257,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
int orig_what_to_do= what_to_do;
+ DBUG_ENTER("get_one_option");
switch(optid) {
case 'a':
@@ -332,15 +338,16 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
{
fprintf(stderr, "Error: %s doesn't support multiple contradicting commands.\n",
my_progname);
- return 1;
+ DBUG_RETURN(1);
}
- return 0;
+ DBUG_RETURN(0);
}
static int get_options(int *argc, char ***argv)
{
int ho_error;
+ DBUG_ENTER("get_options");
if (*argc == 1)
{
@@ -348,8 +355,7 @@ static int get_options(int *argc, char ***argv)
exit(0);
}
- if ((ho_error= load_defaults("my", load_default_groups, argc, argv)) ||
- (ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
+ if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
exit(ho_error);
if (!what_to_do)
@@ -383,21 +389,21 @@ static int get_options(int *argc, char ***argv)
!get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME)))
{
printf("Unsupported character set: %s\n", default_charset);
- return 1;
+ DBUG_RETURN(1);
}
if (*argc > 0 && opt_alldbs)
{
printf("You should give only options, no arguments at all, with option\n");
printf("--all-databases. Please see %s --help for more information.\n",
my_progname);
- return 1;
+ DBUG_RETURN(1);
}
if (*argc < 1 && !opt_alldbs)
{
printf("You forgot to give the arguments! Please see %s --help\n",
my_progname);
printf("for more information.\n");
- return 1;
+ DBUG_RETURN(1);
}
if (tty_password)
opt_password = get_tty_password(NullS);
@@ -405,7 +411,7 @@ static int get_options(int *argc, char ***argv)
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
if (debug_check_flag)
my_end_arg= MY_CHECK_ERROR;
- return(0);
+ DBUG_RETURN((0));
} /* get_options */
@@ -414,20 +420,24 @@ static int process_all_databases()
MYSQL_ROW row;
MYSQL_RES *tableres;
int result = 0;
+ DBUG_ENTER("process_all_databases");
if (mysql_query(sock, "SHOW DATABASES") ||
!(tableres = mysql_store_result(sock)))
{
my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
MYF(0), mysql_error(sock));
- return 1;
+ DBUG_RETURN(1);
}
+ if (verbose)
+ printf("Processing databases\n");
while ((row = mysql_fetch_row(tableres)))
{
if (process_one_db(row[0]))
result = 1;
}
- return result;
+ mysql_free_result(tableres);
+ DBUG_RETURN(result);
}
/* process_all_databases */
@@ -435,19 +445,25 @@ static int process_all_databases()
static int process_databases(char **db_names)
{
int result = 0;
+ DBUG_ENTER("process_databases");
+
+ if (verbose)
+ printf("Processing databases\n");
for ( ; *db_names ; db_names++)
{
if (process_one_db(*db_names))
result = 1;
}
- return result;
+ DBUG_RETURN(result);
} /* process_databases */
static int process_selected_tables(char *db, char **table_names, int tables)
{
+ DBUG_ENTER("process_selected_tables");
+
if (use_db(db))
- return 1;
+ DBUG_RETURN(1);
if (opt_all_in_1 && what_to_do != DO_UPGRADE)
{
/*
@@ -464,7 +480,7 @@ static int process_selected_tables(char *db, char **table_names, int tables)
if (!(table_names_comma_sep = (char *)
my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
- return 1;
+ DBUG_RETURN(1);
for (end = table_names_comma_sep + 1; tables > 0;
tables--, table_names++)
@@ -479,7 +495,7 @@ static int process_selected_tables(char *db, char **table_names, int tables)
else
for (; tables > 0; tables--, table_names++)
handle_request_for_tables(*table_names, fixed_name_length(*table_names));
- return 0;
+ DBUG_RETURN(0);
} /* process_selected_tables */
@@ -487,20 +503,24 @@ static uint fixed_name_length(const char *name)
{
const char *p;
uint extra_length= 2; /* count the first/last backticks */
-
+ DBUG_ENTER("fixed_name_length");
+
for (p= name; *p; p++)
{
if (*p == '`')
extra_length++;
else if (*p == '.')
extra_length+= 2;
+
}
- return (uint) ((p - name) + extra_length);
+ DBUG_RETURN((uint) ((p - name) + extra_length));
}
static char *fix_table_name(char *dest, char *src)
{
+ DBUG_ENTER("fix_table_name");
+
*dest++= '`';
for (; *src; src++)
{
@@ -518,28 +538,33 @@ static char *fix_table_name(char *dest, char *src)
}
}
*dest++= '`';
- return dest;
+
+ DBUG_RETURN(dest);
}
static int process_all_tables_in_db(char *database)
{
- MYSQL_RES *res;
+ MYSQL_RES *UNINIT_VAR(res);
MYSQL_ROW row;
uint num_columns;
+ my_bool system_database= 0;
+ DBUG_ENTER("process_all_tables_in_db");
- LINT_INIT(res);
if (use_db(database))
- return 1;
+ DBUG_RETURN(1);
if ((mysql_query(sock, "SHOW /*!50002 FULL*/ TABLES") &&
mysql_query(sock, "SHOW TABLES")) ||
!(res= mysql_store_result(sock)))
{
my_printf_error(0, "Error: Couldn't get table list for database %s: %s",
MYF(0), database, mysql_error(sock));
- return 1;
+ DBUG_RETURN(1);
}
+ if (!strcmp(database, "mysql") || !strcmp(database, "MYSQL"))
+ system_database= 1;
+
num_columns= mysql_num_fields(res);
if (opt_all_in_1 && what_to_do != DO_UPGRADE)
@@ -560,7 +585,7 @@ static int process_all_tables_in_db(char *database)
if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
{
mysql_free_result(res);
- return 1;
+ DBUG_RETURN(1);
}
for (end = tables + 1; (row = mysql_fetch_row(res)) ;)
{
@@ -582,12 +607,16 @@ static int process_all_tables_in_db(char *database)
/* Skip views if we don't perform renaming. */
if ((what_to_do != DO_UPGRADE) && (num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
continue;
+ if (system_database &&
+ (!strcmp(row[0], "general_log") ||
+ !strcmp(row[0], "slow_log")))
+ continue; /* Skip logging tables */
handle_request_for_tables(row[0], fixed_name_length(row[0]));
}
}
mysql_free_result(res);
- return 0;
+ DBUG_RETURN(0);
} /* process_all_tables_in_db */
@@ -596,8 +625,10 @@ static int fix_table_storage_name(const char *name)
{
char qbuf[100 + NAME_LEN*4];
int rc= 0;
+ DBUG_ENTER("fix_table_storage_name");
+
if (strncmp(name, "#mysql50#", 9))
- return 1;
+ DBUG_RETURN(1);
sprintf(qbuf, "RENAME TABLE `%s` TO `%s`", name, name + 9);
if (mysql_query(sock, qbuf))
{
@@ -607,15 +638,17 @@ static int fix_table_storage_name(const char *name)
}
if (verbose)
printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
- return rc;
+ DBUG_RETURN(rc);
}
static int fix_database_storage_name(const char *name)
{
char qbuf[100 + NAME_LEN*4];
int rc= 0;
+ DBUG_ENTER("fix_database_storage_name");
+
if (strncmp(name, "#mysql50#", 9))
- return 1;
+ DBUG_RETURN(1);
sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name);
if (mysql_query(sock, qbuf))
{
@@ -625,17 +658,19 @@ static int fix_database_storage_name(const char *name)
}
if (verbose)
printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
- return rc;
+ DBUG_RETURN(rc);
}
static int rebuild_table(char *name)
{
char *query, *ptr;
int rc= 0;
+ DBUG_ENTER("rebuild_table");
+
query= (char*)my_malloc(sizeof(char) * (12 + fixed_name_length(name) + 6 + 1),
MYF(MY_WME));
if (!query)
- return 1;
+ DBUG_RETURN(1);
ptr= strmov(query, "ALTER TABLE ");
ptr= fix_table_name(ptr, name);
ptr= strxmov(ptr, " FORCE", NullS);
@@ -646,11 +681,15 @@ static int rebuild_table(char *name)
rc= 1;
}
my_free(query);
- return rc;
+ DBUG_RETURN(rc);
}
static int process_one_db(char *database)
{
+ DBUG_ENTER("process_one_db");
+
+ if (verbose)
+ puts(database);
if (what_to_do == DO_UPGRADE)
{
int rc= 0;
@@ -660,45 +699,51 @@ static int process_one_db(char *database)
database+= 9;
}
if (rc || !opt_fix_table_names)
- return rc;
+ DBUG_RETURN(rc);
}
- return process_all_tables_in_db(database);
+ DBUG_RETURN(process_all_tables_in_db(database));
}
static int use_db(char *database)
{
+ DBUG_ENTER("use_db");
+
if (mysql_get_server_version(sock) >= FIRST_INFORMATION_SCHEMA_VERSION &&
!my_strcasecmp(&my_charset_latin1, database, INFORMATION_SCHEMA_DB_NAME))
- return 1;
+ DBUG_RETURN(1);
if (mysql_get_server_version(sock) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
!my_strcasecmp(&my_charset_latin1, database, PERFORMANCE_SCHEMA_DB_NAME))
- return 1;
+ DBUG_RETURN(1);
if (mysql_select_db(sock, database))
{
DBerror(sock, "when selecting the database");
- return 1;
+ DBUG_RETURN(1);
}
- return 0;
+ DBUG_RETURN(0);
} /* use_db */
static int disable_binlog()
{
const char *stmt= "SET SQL_LOG_BIN=0";
+ DBUG_ENTER("disable_binlog");
+
if (mysql_query(sock, stmt))
{
fprintf(stderr, "Failed to %s\n", stmt);
fprintf(stderr, "Error: %s\n", mysql_error(sock));
- return 1;
+ DBUG_RETURN(1);
}
- return 0;
+ DBUG_RETURN(0);
}
static int handle_request_for_tables(char *tables, uint length)
{
char *query, *end, options[100], message[100];
+ char table_name_buff[NAME_CHAR_LEN*2*2+1], *table_name;
uint query_length= 0;
const char *op = 0;
+ DBUG_ENTER("handle_request_for_tables");
options[0] = 0;
end = options;
@@ -725,22 +770,26 @@ static int handle_request_for_tables(char *tables, uint length)
op= (opt_write_binlog) ? "OPTIMIZE" : "OPTIMIZE NO_WRITE_TO_BINLOG";
break;
case DO_UPGRADE:
- return fix_table_storage_name(tables);
+ DBUG_RETURN(fix_table_storage_name(tables));
}
if (!(query =(char *) my_malloc((sizeof(char)*(length+110)), MYF(MY_WME))))
- return 1;
+ DBUG_RETURN(1);
if (opt_all_in_1)
{
/* No backticks here as we added them before */
query_length= sprintf(query, "%s TABLE %s %s", op, tables, options);
+ table_name= tables;
}
else
{
- char *ptr;
+ char *ptr, *org;
- ptr= strmov(strmov(query, op), " TABLE ");
+ org= ptr= strmov(strmov(query, op), " TABLE ");
ptr= fix_table_name(ptr, tables);
+ strmake(table_name_buff, org, min((int) sizeof(table_name_buff)-1,
+ (int) (ptr - org)));
+ table_name= table_name_buff;
ptr= strxmov(ptr, " ", options, NullS);
query_length= (uint) (ptr - query);
}
@@ -748,11 +797,22 @@ static int handle_request_for_tables(char *tables, uint length)
{
sprintf(message, "when executing '%s TABLE ... %s'", op, options);
DBerror(sock, message);
- return 1;
+ my_free(query);
+ DBUG_RETURN(1);
}
print_result();
+ if (opt_flush_tables)
+ {
+ query_length= sprintf(query, "FLUSH TABLES %s", table_name);
+ if (mysql_real_query(sock, query, query_length))
+ {
+ DBerror(sock, query);
+ my_free(query);
+ DBUG_RETURN(1);
+ }
+ }
my_free(query);
- return 0;
+ DBUG_RETURN(0);
}
@@ -760,9 +820,10 @@ static void print_result()
{
MYSQL_RES *res;
MYSQL_ROW row;
- char prev[NAME_LEN*2+2];
+ char prev[(NAME_LEN+9)*2+2];
uint i;
my_bool found_error=0, table_rebuild=0;
+ DBUG_ENTER("print_result");
res = mysql_use_result(sock);
@@ -796,7 +857,15 @@ static void print_result()
printf("%-50s %s", row[0], row[3]);
else if (!status && changed)
{
- printf("%s\n%-9s: %s", row[0], row[2], row[3]);
+ /*
+ If the error message includes REPAIR TABLE, we assume it means
+ we have to run upgrade on it. In this case we write a nicer message
+ than "Please do "REPAIR TABLE""...
+ */
+ if (!strcmp(row[2],"error") && strstr(row[3],"REPAIR TABLE"))
+ printf("%-50s %s", row[0], "Needs upgrade");
+ else
+ printf("%s\n%-9s: %s", row[0], row[2], row[3]);
if (strcmp(row[2],"note"))
{
found_error=1;
@@ -818,13 +887,14 @@ static void print_result()
insert_dynamic(&tables4repair, (uchar*) prev);
}
mysql_free_result(res);
+ DBUG_VOID_RETURN;
}
static int dbConnect(char *host, char *user, char *passwd)
{
DBUG_ENTER("dbConnect");
- if (verbose)
+ if (verbose > 1)
{
fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
}
@@ -838,10 +908,8 @@ static int dbConnect(char *host, char *user, char *passwd)
#endif
if (opt_protocol)
mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
-#ifdef HAVE_SMEM
if (shared_memory_base_name)
mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
-#endif
if (opt_plugin_dir && *opt_plugin_dir)
mysql_options(&mysql_connection, MYSQL_PLUGIN_DIR, opt_plugin_dir);
@@ -854,18 +922,20 @@ static int dbConnect(char *host, char *user, char *passwd)
NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
{
DBerror(&mysql_connection, "when trying to connect");
- return 1;
+ DBUG_RETURN(1);
}
mysql_connection.reconnect= 1;
- return 0;
+ DBUG_RETURN(0);
} /* dbConnect */
static void dbDisconnect(char *host)
{
- if (verbose)
+ DBUG_ENTER("dbDisconnect");
+ if (verbose > 1)
fprintf(stderr, "# Disconnecting from %s...\n", host ? host : "localhost");
mysql_close(sock);
+ DBUG_VOID_RETURN;
} /* dbDisconnect */
@@ -881,45 +951,52 @@ static void DBerror(MYSQL *mysql, const char *when)
static void safe_exit(int error)
{
+ DBUG_ENTER("safe_exit");
if (!first_error)
first_error= error;
if (ignore_errors)
- return;
+ DBUG_VOID_RETURN;
if (sock)
mysql_close(sock);
+ sf_leaking_memory= 1; /* don't check for memory leaks */
exit(error);
+ DBUG_VOID_RETURN;
}
int main(int argc, char **argv)
{
+ int ret= EX_USAGE;
+ char **defaults_argv;
+
MY_INIT(argv[0]);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
/*
** Check out the args
*/
+ if (load_defaults("my", load_default_groups, &argc, &argv))
+ goto end2;
+
+ defaults_argv= argv;
if (get_options(&argc, &argv))
- {
- my_end(my_end_arg);
- exit(EX_USAGE);
- }
+ goto end1;
+ sf_leaking_memory=0; /* from now on we cleanup properly */
+
+ ret= EX_MYSQLERR;
if (dbConnect(current_host, current_user, opt_password))
- exit(EX_MYSQLERR);
+ goto end1;
+ ret= 1;
if (!opt_write_binlog)
{
- if (disable_binlog()) {
- first_error= 1;
+ if (disable_binlog())
goto end;
- }
}
if (opt_auto_repair &&
(my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64) ||
my_init_dynamic_array(&tables4rebuild, sizeof(char)*(NAME_LEN*2+2),16,64)))
- {
- first_error = 1;
goto end;
- }
if (opt_alldbs)
process_all_databases();
@@ -944,6 +1021,8 @@ int main(int argc, char **argv)
for (i = 0; i < tables4rebuild.elements ; i++)
rebuild_table((char*) dynamic_array_ptr(&tables4rebuild, i));
}
+ ret= test(first_error);
+
end:
dbDisconnect(current_host);
if (opt_auto_repair)
@@ -951,10 +1030,12 @@ int main(int argc, char **argv)
delete_dynamic(&tables4repair);
delete_dynamic(&tables4rebuild);
}
+ end1:
my_free(opt_password);
-#ifdef HAVE_SMEM
my_free(shared_memory_base_name);
-#endif
+ mysql_library_end();
+ free_defaults(defaults_argv);
+ end2:
my_end(my_end_arg);
- return(first_error!=0);
+ return ret;
} /* main */
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 4fcf309b22b..284ea1e760a 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2012, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -38,7 +39,7 @@
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
*/
-#define DUMP_VERSION "10.13"
+#define DUMP_VERSION "10.14"
#include <my_global.h>
#include <my_sys.h>
@@ -83,6 +84,9 @@
#define IGNORE_DATA 0x01 /* don't dump data for this table */
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
+/* Chars needed to store LONGLONG, excluding trailing '\0'. */
+#define LONGLONG_LEN 20
+
/* general_log or slow_log tables under mysql database */
static inline my_bool general_log_or_slow_log_tables(const char *db,
const char *table)
@@ -229,8 +233,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.", &charsets_dir,
- &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ "Directory for character set files.", (char**) &charsets_dir,
+ (char**) &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},
@@ -267,8 +271,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.", &default_dbug_option,
- &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"debug", '#', "Output debug log.", (char**) &default_dbug_option,
+ (char**) &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,
@@ -382,9 +386,9 @@ static struct my_option my_long_options[] =
"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"
" to 2, that command will be prefixed with a comment symbol. "
- "This option will turn --lock-all-tables on, unless "
- "--single-transaction is specified too (in which case a "
- "global read lock is only taken a short time at the beginning of the dump; "
+ "This option will turn --lock-all-tables on, unless --single-transaction "
+ "is specified too (on servers before MariaDB 5.3 this will still take a "
+ "global read lock for a short time at the beginning of the dump; "
"don't forget to read about --single-transaction below). In all cases, "
"any action on logs will happen at the exact moment of the dump. "
"Option automatically turns --lock-tables off.",
@@ -524,7 +528,8 @@ static struct my_option my_long_options[] =
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-static const char *load_default_groups[]= { "mysqldump","client",0 };
+static const char *load_default_groups[]=
+{ "mysqldump", "client", "client-server", "client-mariadb", 0 };
static void maybe_exit(int error);
static void die(int error, const char* reason, ...);
@@ -595,17 +600,17 @@ void check_io(FILE *file)
static void print_version(void)
{
- printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
+ printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname_short,DUMP_VERSION,
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
} /* print_version */
static void short_usage_sub(void)
{
- printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
+ printf("Usage: %s [OPTIONS] database [tables]\n", my_progname_short);
printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n",
- my_progname);
- printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname);
+ my_progname_short);
+ printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname_short);
}
@@ -624,7 +629,7 @@ static void usage(void)
static void short_usage(void)
{
short_usage_sub();
- printf("For more options, use %s --help\n", my_progname);
+ printf("For more options, use %s --help\n", my_progname_short);
}
@@ -673,8 +678,13 @@ static void write_header(FILE *sql_file, char *db_name)
if (!path)
{
+ if (!opt_no_create_info)
+ {
+ /* We don't need unique checks as the table is created just before */
+ fprintf(md_result_file,"\
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n");
+ }
fprintf(md_result_file,"\
-/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n\
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n\
");
}
@@ -704,8 +714,12 @@ static void write_footer(FILE *sql_file)
if (!path)
{
fprintf(md_result_file,"\
-/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n");
+ if (!opt_no_create_info)
+ {
+ fprintf(md_result_file,"\
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n");
+ }
}
if (opt_set_charset)
fprintf(sql_file,
@@ -942,7 +956,7 @@ static int get_options(int *argc, char ***argv)
fields_terminated))
{
fprintf(stderr,
- "%s: You must use option --tab with --fields-...\n", my_progname);
+ "%s: You must use option --tab with --fields-...\n", my_progname_short);
return(EX_USAGE);
}
@@ -960,7 +974,7 @@ static int get_options(int *argc, char ***argv)
if (opt_single_transaction && opt_lock_all_tables)
{
fprintf(stderr, "%s: You can't use --single-transaction and "
- "--lock-all-tables at the same time.\n", my_progname);
+ "--lock-all-tables at the same time.\n", my_progname_short);
return(EX_USAGE);
}
if (opt_master_data)
@@ -972,14 +986,14 @@ static int get_options(int *argc, char ***argv)
lock_tables= 0;
if (enclosed && opt_enclosed)
{
- fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
+ fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname_short);
return(EX_USAGE);
}
if ((opt_databases || opt_alldbs) && path)
{
fprintf(stderr,
"%s: --databases or --all-databases can't be used with --tab.\n",
- my_progname);
+ my_progname_short);
return(EX_USAGE);
}
if (strcmp(default_charset, charset_info->csname) &&
@@ -1003,7 +1017,7 @@ static int get_options(int *argc, char ***argv)
static void DB_error(MYSQL *mysql_arg, const char *when)
{
DBUG_ENTER("DB_error");
- maybe_die(EX_MYSQLERR, "Got error: %d: %s %s",
+ maybe_die(EX_MYSQLERR, "Got error: %d: \"%s\" %s",
mysql_errno(mysql_arg), mysql_error(mysql_arg), when);
DBUG_VOID_RETURN;
}
@@ -1031,7 +1045,7 @@ static void die(int error_num, const char* fmt_reason, ...)
my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
va_end(args);
- fprintf(stderr, "%s: %s\n", my_progname, buffer);
+ fprintf(stderr, "%s: %s\n", my_progname_short, buffer);
fflush(stderr);
ignore_errors= 0; /* force the exit */
@@ -1065,7 +1079,7 @@ static void maybe_die(int error_num, const char* fmt_reason, ...)
my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
va_end(args);
- fprintf(stderr, "%s: %s\n", my_progname, buffer);
+ fprintf(stderr, "%s: %s\n", my_progname_short, buffer);
fflush(stderr);
maybe_exit(error_num);
@@ -1148,6 +1162,44 @@ static int fetch_db_collation(const char *db_name,
}
+/*
+ Check if server supports non-blocking binlog position using the
+ binlog_snapshot_file and binlog_snapshot_position status variables. If it
+ does, also return the position obtained if output pointers are non-NULL.
+ Returns 1 if position available, 0 if not.
+*/
+static int
+check_consistent_binlog_pos(char *binlog_pos_file, char *binlog_pos_offset)
+{
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int found;
+
+ if (mysql_query_with_error_report(mysql, &res,
+ "SHOW STATUS LIKE 'binlog_snapshot_%'"))
+ return 1;
+
+ found= 0;
+ while ((row= mysql_fetch_row(res)))
+ {
+ if (0 == strcmp(row[0], "binlog_snapshot_file"))
+ {
+ if (binlog_pos_file)
+ strmake(binlog_pos_file, row[1], FN_REFLEN-1);
+ found++;
+ }
+ else if (0 == strcmp(row[0], "binlog_snapshot_position"))
+ {
+ if (binlog_pos_offset)
+ strmake(binlog_pos_offset, row[1], LONGLONG_LEN);
+ found++;
+ }
+ }
+ mysql_free_result(res);
+
+ return (found == 2);
+}
+
static char *my_case_str(const char *str,
uint str_len,
const char *token,
@@ -1434,6 +1486,7 @@ static void free_resources()
if (md_result_file && md_result_file != stdout)
my_fclose(md_result_file, MYF(0));
my_free(opt_password);
+ my_free(current_host);
if (my_hash_inited(&ignore_table))
my_hash_free(&ignore_table);
if (extended_insert)
@@ -1442,6 +1495,7 @@ static void free_resources()
dynstr_free(&insert_pat);
if (defaults_argv)
free_defaults(defaults_argv);
+ mysql_library_end();
my_end(my_end_arg);
}
@@ -1493,9 +1547,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);
- if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd,
- NULL,opt_mysql_port,opt_mysql_unix_port,
- 0)))
+ 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))
{
DB_error(&mysql_connection, "when trying to connect");
DBUG_RETURN(1);
@@ -2107,7 +2161,7 @@ static uint dump_events_for_db(char *db)
if (create_delimiter(row[3], delimiter, sizeof(delimiter)) == NULL)
{
fprintf(stderr, "%s: Warning: Can't create delimiter for event '%s'\n",
- my_progname, event_name);
+ my_progname_short, event_name);
DBUG_RETURN(1);
}
@@ -2759,7 +2813,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
else
{
verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
- my_progname, mysql_error(mysql));
+ my_progname_short, mysql_error(mysql));
my_snprintf(query_buff, sizeof(query_buff), show_fields_stmt, db, table);
@@ -2870,7 +2924,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
goto continue_xml;
}
fprintf(stderr, "%s: Can't get keys for table %s (%s)\n",
- my_progname, result_table, mysql_error(mysql));
+ my_progname_short, result_table, mysql_error(mysql));
if (path)
my_fclose(sql_file, MYF(MY_WME));
DBUG_RETURN(0);
@@ -3526,7 +3580,7 @@ static void dump_table(char *table, char *db)
if (mysql_num_fields(res) != num_fields)
{
fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n",
- my_progname, result_table);
+ my_progname_short, result_table);
error= EX_CONSCHECK;
goto err;
}
@@ -3791,7 +3845,7 @@ static void dump_table(char *table, char *db)
{
my_snprintf(buf, sizeof(buf),
"%s: Error %d: %s when dumping table %s at row: %ld\n",
- my_progname,
+ my_progname_short,
mysql_errno(mysql),
mysql_error(mysql),
result_table,
@@ -3985,8 +4039,8 @@ static int dump_tablespaces(char* ts_where)
DBUG_RETURN(0);
}
- my_printf_error(0, "Error: '%s' when trying to dump tablespaces",
- MYF(0), mysql_error(mysql));
+ fprintf(stderr, "%s: Error: '%s' when trying to dump tablespaces\n",
+ my_progname_short, mysql_error(mysql));
DBUG_RETURN(1);
}
@@ -4126,13 +4180,14 @@ static int dump_all_databases()
if (dump_all_tables_in_db(row[0]))
result=1;
}
+ mysql_free_result(tableres);
if (seen_views)
{
if (mysql_query(mysql, "SHOW DATABASES") ||
!(tableres= mysql_store_result(mysql)))
{
- my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
- MYF(0), mysql_error(mysql));
+ fprintf(stderr, "%s: Error: Couldn't execute 'SHOW DATABASES': %s\n",
+ my_progname_short, mysql_error(mysql));
return 1;
}
while ((row= mysql_fetch_row(tableres)))
@@ -4148,6 +4203,7 @@ static int dump_all_databases()
if (dump_all_views_in_db(row[0]))
result=1;
}
+ mysql_free_result(tableres);
}
return result;
}
@@ -4276,8 +4332,6 @@ static int init_dumping(char *database, int init_func(char*))
check_io(md_result_file);
}
}
- if (extended_insert)
- init_dynamic_string_checked(&extended_row, "", 1024, 1024);
return 0;
} /* init_dumping */
@@ -4641,41 +4695,64 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
} /* dump_selected_tables */
-static int do_show_master_status(MYSQL *mysql_con)
+static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
{
MYSQL_ROW row;
- MYSQL_RES *master;
+ MYSQL_RES *UNINIT_VAR(master);
+ char binlog_pos_file[FN_REFLEN];
+ char binlog_pos_offset[LONGLONG_LEN+1];
+ char *file, *offset;
const char *comment_prefix=
(opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
- if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS"))
+
+ if (consistent_binlog_pos)
{
- return 1;
+ if(!check_consistent_binlog_pos(binlog_pos_file, binlog_pos_offset))
+ return 1;
+ file= binlog_pos_file;
+ offset= binlog_pos_offset;
}
else
{
+ if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS"))
+ return 1;
+
row= mysql_fetch_row(master);
if (row && row[0] && row[1])
{
- /* SHOW MASTER STATUS reports file and position */
- print_comment(md_result_file, 0,
- "\n--\n-- Position to start replication or point-in-time "
- "recovery from\n--\n\n");
- fprintf(md_result_file,
- "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
- comment_prefix, row[0], row[1]);
- check_io(md_result_file);
+ file= row[0];
+ offset= row[1];
}
- else if (!ignore_errors)
+ else
{
- /* SHOW MASTER STATUS reports nothing and --force is not enabled */
- my_printf_error(0, "Error: Binlogging on server not active",
- MYF(0));
mysql_free_result(master);
- maybe_exit(EX_MYSQLERR);
- return 1;
+ if (!ignore_errors)
+ {
+ /* SHOW MASTER STATUS reports nothing and --force is not enabled */
+ fprintf(stderr, "%s: Error: Binlogging on server not active\n",
+ my_progname_short);
+ maybe_exit(EX_MYSQLERR);
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
}
- mysql_free_result(master);
}
+
+ /* SHOW MASTER STATUS reports file and position */
+ print_comment(md_result_file, 0,
+ "\n--\n-- Position to start replication or point-in-time "
+ "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);
+ check_io(md_result_file);
+
+ if (!consistent_binlog_pos)
+ mysql_free_result(master);
+
return 0;
}
@@ -4728,7 +4805,7 @@ static int add_slave_statements(void)
static int do_show_slave_status(MYSQL *mysql_con)
{
- MYSQL_RES *slave;
+ MYSQL_RES *slave= 0;
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"))
@@ -4736,7 +4813,7 @@ static int do_show_slave_status(MYSQL *mysql_con)
if (!ignore_errors)
{
/* SHOW SLAVE STATUS reports nothing and --force is not enabled */
- my_printf_error(0, "Error: Slave not set up", MYF(0));
+ fprintf(stderr, "%s: Error: Slave not set up\n", my_progname_short);
}
mysql_free_result(slave);
return 1;
@@ -4759,7 +4836,7 @@ static int do_show_slave_status(MYSQL *mysql_con)
if (row[1])
fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
if (row[3])
- fprintf(md_result_file, "MASTER_PORT='%s', ", row[3]);
+ fprintf(md_result_file, "MASTER_PORT=%s, ", row[3]);
}
fprintf(md_result_file,
"MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
@@ -4796,7 +4873,7 @@ static int do_start_slave_sql(MYSQL *mysql_con)
/* now, start slave if stopped */
if (mysql_query_with_error_report(mysql_con, 0, "START SLAVE"))
{
- my_printf_error(0, "Error: Unable to start slave", MYF(0));
+ fprintf(stderr, "%s: Error: Unable to start slave\n", my_progname_short);
return 1;
}
return(0);
@@ -5233,6 +5310,7 @@ static my_bool get_view_structure(char *table, char* db)
field= mysql_fetch_field_direct(table_res, 0);
if (strcmp(field->name, "View") != 0)
{
+ mysql_free_result(table_res);
switch_character_set_results(mysql, default_charset);
verbose_msg("-- It's base table, skipped\n");
DBUG_RETURN(0);
@@ -5242,8 +5320,10 @@ static my_bool get_view_structure(char *table, char* db)
if (path)
{
if (!(sql_file= open_sql_file_for_table(table, O_WRONLY)))
+ {
+ mysql_free_result(table_res);
DBUG_RETURN(1);
-
+ }
write_header(sql_file, db);
}
@@ -5434,8 +5514,10 @@ int main(int argc, char **argv)
{
char bin_log_name[FN_REFLEN];
int exit_code;
- MY_INIT("mysqldump");
+ int consistent_binlog_pos= 0;
+ MY_INIT(argv[0]);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
compatible_mode_normal_str[0]= 0;
default_charset= (char *)mysql_universal_client_charset;
bzero((char*) &ignore_table, sizeof(ignore_table));
@@ -5446,6 +5528,7 @@ int main(int argc, char **argv)
free_resources();
exit(exit_code);
}
+ sf_leaking_memory=0; /* from now on we cleanup properly */
/*
Disable comments in xml mode if 'comments' option is not explicitly used.
@@ -5473,7 +5556,13 @@ int main(int argc, char **argv)
if (opt_slave_data && do_stop_slave_sql(mysql))
goto err;
- if ((opt_lock_all_tables || opt_master_data ||
+ if (opt_single_transaction && opt_master_data)
+ {
+ /* See if we can avoid FLUSH TABLES WITH READ LOCK (MariaDB 5.3+). */
+ consistent_binlog_pos= check_consistent_binlog_pos(NULL, NULL);
+ }
+
+ if ((opt_lock_all_tables || (opt_master_data && !consistent_binlog_pos) ||
(opt_single_transaction && flush_logs)) &&
do_flush_tables_read_lock(mysql))
goto err;
@@ -5509,7 +5598,7 @@ 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))
+ if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos))
goto err;
if (opt_slave_data && do_show_slave_status(mysql))
goto err;
@@ -5519,6 +5608,9 @@ int main(int argc, char **argv)
if (opt_alltspcs)
dump_all_tablespaces();
+ if (extended_insert)
+ init_dynamic_string_checked(&extended_row, "", 1024, 1024);
+
if (opt_alldbs)
{
if (!opt_alltspcs && !opt_notspcs)
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 2045c94619b..77d0cd0a7d3 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
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
@@ -18,8 +18,14 @@
/*
** mysqlimport.c - Imports all given files
** into a table(s).
+**
+** *************************
+** * *
+** * AUTHOR: Monty & Jani *
+** * DATE: June 24, 1997 *
+** * *
+** *************************
*/
-
#define IMPORT_VERSION "3.7"
#include "client_priv.h"
@@ -60,6 +66,8 @@ static char *opt_plugin_dir= 0, *opt_default_auth= 0;
static longlong opt_ignore_lines= -1;
#include <sslopt-vars.h>
+static char **argv_to_free;
+
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
#endif
@@ -67,8 +75,8 @@ static char *shared_memory_base_name=0;
static struct my_option my_long_options[] =
{
{"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},
+ "Directory for character set files.", (char**) &charsets_dir,
+ (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"default-character-set", OPT_DEFAULT_CHARSET,
"Set the default character set.", &default_charset,
&default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -184,7 +192,8 @@ static struct my_option my_long_options[] =
};
-static const char *load_default_groups[]= { "mysqlimport","client",0 };
+static const char *load_default_groups[]=
+{ "mysqlimport","client", "client-server", "client-mariadb", 0 };
static void print_version(void)
@@ -196,6 +205,8 @@ static void print_version(void)
static void usage(void)
{
+ puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.");
+ puts("Copyright 2008-2011 Oracle and Monty Program Ab.");
print_version();
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
printf("\
@@ -472,10 +483,18 @@ static void db_disconnect(char *host, MYSQL *mysql)
static void safe_exit(int error, MYSQL *mysql)
{
- if (ignore_errors)
+ if (error && ignore_errors)
return;
if (mysql)
mysql_close(mysql);
+
+#ifdef HAVE_SMEM
+ my_free(shared_memory_base_name);
+#endif
+ free_defaults(argv_to_free);
+ mysql_library_end();
+ my_free(opt_password);
+ my_end(my_end_arg);
exit(error);
}
@@ -594,8 +613,8 @@ error:
int main(int argc, char **argv)
{
int error=0;
- char **argv_to_free;
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;
@@ -606,6 +625,7 @@ int main(int argc, char **argv)
free_defaults(argv_to_free);
return(1);
}
+ sf_leaking_memory=0; /* from now on we cleanup properly */
#ifdef HAVE_LIBPTHREAD
if (opt_use_threads && !lock_tables)
@@ -684,11 +704,6 @@ int main(int argc, char **argv)
exitcode= error;
db_disconnect(current_host, mysql);
}
- my_free(opt_password);
-#ifdef HAVE_SMEM
- my_free(shared_memory_base_name);
-#endif
- free_defaults(argv_to_free);
- my_end(my_end_arg);
+ safe_exit(0, 0);
return(exitcode);
}
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 5677681541b..5cf2be1160c 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates.
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
@@ -57,7 +57,8 @@ static void print_res_header(MYSQL_RES *result);
static void print_res_top(MYSQL_RES *result);
static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur);
-static const char *load_default_groups[]= { "mysqlshow","client",0 };
+static const char *load_default_groups[]=
+{ "mysqlshow","client", "client-server", "client-mariadb", 0 };
static char * opt_mysql_unix_port=0;
int main(int argc, char **argv)
@@ -67,11 +68,13 @@ int main(int argc, char **argv)
char *wild;
MYSQL mysql;
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);
get_options(&argc,&argv);
+ sf_leaking_memory=0; /* from now on we cleanup properly */
wild=0;
if (argc)
{
@@ -171,7 +174,7 @@ int main(int argc, char **argv)
static struct my_option my_long_options[] =
{
{"character-sets-dir", 'c', "Directory for character set files.",
- &charsets_dir, &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
+ (char**) &charsets_dir, (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
0, 0, 0, 0, 0},
{"default-character-set", OPT_DEFAULT_CHARSET,
"Set the default character set.", &default_charset,
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index ff5d2ddaf26..8e70a2609c3 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2005, 2012, Oracle and/or its affiliates.
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
@@ -125,8 +125,6 @@ static char *host= NULL, *opt_password= NULL, *user= NULL,
*post_system= NULL,
*opt_mysql_unix_port= NULL;
static char *opt_plugin_dir= 0, *opt_default_auth= 0;
-static uint opt_enable_cleartext_plugin= 0;
-static my_bool using_opt_enable_cleartext_plugin= 0;
const char *delimiter= "\n";
@@ -180,7 +178,8 @@ static uint opt_protocol= 0;
static int get_options(int *argc,char ***argv);
static uint opt_mysql_port= 0;
-static const char *load_default_groups[]= { "mysqlslap","client",0 };
+static const char *load_default_groups[]=
+{ "mysqlslap", "client", "client-server", "client-mariadb", 0 };
typedef struct statement statement;
@@ -294,12 +293,32 @@ static int gettimeofday(struct timeval *tp, void *tzp)
}
#endif
+void set_mysql_connect_options(MYSQL *mysql)
+{
+ if (opt_compress)
+ 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);
+#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
+ mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+}
+
+
int main(int argc, char **argv)
{
MYSQL mysql;
option_string *eptr;
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))
{
@@ -313,6 +332,7 @@ int main(int argc, char **argv)
my_end(0);
exit(1);
}
+ sf_leaking_memory=0; /* from now on we cleanup properly */
/* Seed the random number generator if we will be using it. */
if (auto_generate_sql)
@@ -329,20 +349,7 @@ int main(int argc, char **argv)
exit(1);
}
mysql_init(&mysql);
- if (opt_compress)
- 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);
-#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
- mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+ set_mysql_connect_options(&mysql);
if (opt_plugin_dir && *opt_plugin_dir)
mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
@@ -350,9 +357,6 @@ int main(int argc, char **argv)
if (opt_default_auth && *opt_default_auth)
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
- if (using_opt_enable_cleartext_plugin)
- mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
- (char*) &opt_enable_cleartext_plugin);
if (!opt_only_print)
{
if (!(mysql_real_connect(&mysql, host, user, opt_password,
@@ -423,6 +427,7 @@ int main(int argc, char **argv)
my_free(shared_memory_base_name);
#endif
free_defaults(defaults_argv);
+ mysql_library_end();
my_end(my_end_arg);
return 0;
@@ -461,7 +466,16 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
/* First we create */
if (create_statements)
+ {
+ /*
+ If we have an --engine option, then we indicate
+ create_schema() to add the engine type to the DDL.
+ */
+ if (eptr)
+ create_statements->type= CREATE_TABLE_TYPE;
+
create_schema(mysql, create_schema_string, create_statements, eptr);
+ }
/*
If we generated GUID we need to build a list of them from creation that
@@ -475,10 +489,10 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
if (commit_rate)
run_query(mysql, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
- if (pre_system)
- if ((sysret= system(pre_system)) != 0)
- fprintf(stderr, "Warning: Execution of pre_system option returned %d.\n",
- sysret);
+ if (pre_system && (sysret= system(pre_system)) != 0)
+ fprintf(stderr,
+ "Warning: Execution of pre_system option returned %d.\n",
+ sysret);
/*
Pre statements are always run after all other logic so they can
@@ -492,11 +506,10 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
if (post_statements)
run_statements(mysql, post_statements);
- if (post_system)
- if ((sysret= system(post_system)) != 0)
- fprintf(stderr, "Warning: Execution of post_system option returned %d.\n",
- sysret);
-
+ if (post_system && (sysret= system(post_system)) != 0)
+ fprintf(stderr,
+ "Warning: Execution of post_system option returned %d.\n",
+ sysret);
/* We are finished with this run */
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
drop_primary_key_list();
@@ -541,7 +554,7 @@ static struct my_option my_long_options[] =
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-load-type", OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE,
"Specify test load type: mixed, update, write, key, or read; default is mixed.",
- &auto_generate_sql_type, &auto_generate_sql_type,
+ (char**) &auto_generate_sql_type, (char**) &auto_generate_sql_type,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-secondary-indexes",
OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES,
@@ -572,13 +585,13 @@ static struct my_option my_long_options[] =
&opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
{"concurrency", 'c', "Number of clients to simulate for query to run.",
- &concurrency_str, &concurrency_str, 0, GET_STR,
+ (char**) &concurrency_str, (char**) &concurrency_str, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"create", OPT_SLAP_CREATE_STRING, "File or string to use create tables.",
&create_string, &create_string, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"create-schema", OPT_CREATE_SLAP_SCHEMA, "Schema to run tests in.",
- &create_schema_string, &create_schema_string, 0, GET_STR,
+ (char**) &create_schema_string, (char**) &create_schema_string, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"csv", OPT_SLAP_CSV,
"Generate CSV output to named file or to stdout if no file is named.",
@@ -588,7 +601,7 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
#else
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
- &default_dbug_option, &default_dbug_option, 0, GET_STR,
+ (char**) &default_dbug_option, (char**) &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.",
@@ -602,18 +615,17 @@ static struct my_option my_long_options[] =
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"delimiter", 'F',
"Delimiter to use in SQL statements supplied in file or command line.",
- &delimiter, &delimiter, 0, GET_STR, REQUIRED_ARG,
+ (char**) &delimiter, (char**) &delimiter, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"detach", OPT_SLAP_DETACH,
"Detach (close and reopen) connections after X number of requests.",
&detach_rate, &detach_rate, 0, GET_UINT, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
- {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
- "Enable/disable the clear text authentication plugin.",
- &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin,
- 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
- {"engine", 'e', "Storage engine to use for creating the table.",
- &default_engine, &default_engine, 0,
+ {"engine", 'e',
+ "Comma separated list of storage engines to use for creating the table."
+ " The test is run for each engine. You can also specify an option for an "
+ "engine after a `:', like memory:max_row=2300",
+ &default_engine, &default_engine, 0,
GET_STR, REQUIRED_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},
@@ -623,11 +635,11 @@ static struct my_option my_long_options[] =
&opt_no_drop, &opt_no_drop, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"number-char-cols", 'x',
"Number of VARCHAR columns to create in table if specifying --auto-generate-sql.",
- &num_char_cols_opt, &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG,
+ (char**) &num_char_cols_opt, (char**) &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"number-int-cols", 'y',
"Number of INT columns to create in table if specifying --auto-generate-sql.",
- &num_int_cols_opt, &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG,
+ (char**) &num_int_cols_opt, (char**) &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"number-of-queries", OPT_MYSQL_NUMBER_OF_QUERY,
"Limit each client to this number of queries (this is not exact).",
@@ -770,9 +782,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'I': /* Info */
usage();
exit(0);
- case OPT_ENABLE_CLEARTEXT_PLUGIN:
- using_opt_enable_cleartext_plugin= TRUE;
- break;
}
DBUG_RETURN(0);
}
@@ -984,6 +993,7 @@ build_update_string(void)
ptr->type= UPDATE_TYPE_REQUIRES_PREFIX ;
else
ptr->type= UPDATE_TYPE;
+
strmov(ptr->string, update_string.str);
dynstr_free(&update_string);
DBUG_RETURN(ptr);
@@ -999,8 +1009,8 @@ build_update_string(void)
static statement *
build_insert_string(void)
{
- char buf[HUGE_STRING_LENGTH];
- unsigned int col_count;
+ char buf[HUGE_STRING_LENGTH];
+ unsigned int col_count;
statement *ptr;
DYNAMIC_STRING insert_string;
DBUG_ENTER("build_insert_string");
@@ -1090,8 +1100,8 @@ build_insert_string(void)
static statement *
build_select_string(my_bool key)
{
- char buf[HUGE_STRING_LENGTH];
- unsigned int col_count;
+ char buf[HUGE_STRING_LENGTH];
+ unsigned int col_count;
statement *ptr;
static DYNAMIC_STRING query_string;
DBUG_ENTER("build_select_string");
@@ -1143,6 +1153,7 @@ build_select_string(my_bool key)
ptr->type= SELECT_TYPE_REQUIRES_PREFIX;
else
ptr->type= SELECT_TYPE;
+
strmov(ptr->string, query_string.str);
dynstr_free(&query_string);
DBUG_RETURN(ptr);
@@ -1204,8 +1215,6 @@ get_options(int *argc,char ***argv)
exit(1);
}
-
-
if (auto_generate_sql && num_of_query && auto_actual_queries)
{
fprintf(stderr,
@@ -1246,6 +1255,7 @@ get_options(int *argc,char ***argv)
num_int_cols= atoi(str->string);
if (str->option)
num_int_cols_index= atoi(str->option);
+
option_cleanup(str);
}
@@ -1258,6 +1268,7 @@ get_options(int *argc,char ***argv)
num_char_cols_index= atoi(str->option);
else
num_char_cols_index= 0;
+
option_cleanup(str);
}
@@ -1379,9 +1390,9 @@ get_options(int *argc,char ***argv)
fprintf(stderr,"%s: Could not open create file\n", my_progname);
exit(1);
}
- tmp_string= (char *)my_malloc(sbuf.st_size + 1,
+ tmp_string= (char *)my_malloc((size_t)sbuf.st_size + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
- my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0));
+ my_read(data_file, (uchar*) tmp_string, (size_t)sbuf.st_size, MYF(0));
tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0));
parse_delimiter(tmp_string, &create_statements, delimiter[0]);
@@ -1406,9 +1417,9 @@ get_options(int *argc,char ***argv)
fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
exit(1);
}
- tmp_string= (char *)my_malloc(sbuf.st_size + 1,
+ tmp_string= (char *)my_malloc((size_t)sbuf.st_size + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
- my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0));
+ my_read(data_file, (uchar*) tmp_string, (size_t)sbuf.st_size, MYF(0));
tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0));
if (user_supplied_query)
@@ -1437,9 +1448,9 @@ get_options(int *argc,char ***argv)
fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
exit(1);
}
- tmp_string= (char *)my_malloc(sbuf.st_size + 1,
+ tmp_string= (char *)my_malloc((size_t)sbuf.st_size + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
- my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0));
+ my_read(data_file, (uchar*) tmp_string, (size_t)sbuf.st_size, MYF(0));
tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0));
if (user_supplied_pre_statements)
@@ -1468,9 +1479,9 @@ get_options(int *argc,char ***argv)
fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
exit(1);
}
- tmp_string= (char *)my_malloc(sbuf.st_size + 1,
+ tmp_string= (char *)my_malloc((size_t)sbuf.st_size + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
- my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0));
+ my_read(data_file, (uchar*) tmp_string, (size_t)sbuf.st_size, MYF(0));
tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0));
if (user_supplied_post_statements)
@@ -1492,6 +1503,7 @@ get_options(int *argc,char ***argv)
if (tty_password)
opt_password= get_tty_password(NullS);
+
DBUG_RETURN(0);
}
@@ -1506,6 +1518,7 @@ static int run_query(MYSQL *mysql, const char *query, int len)
if (verbose >= 3)
printf("%.*s;\n", len, query);
+
return mysql_real_query(mysql, query, len);
}
@@ -1626,18 +1639,6 @@ create_schema(MYSQL *mysql, const char *db, statement *stmt,
}
}
- if (engine_stmt)
- {
- len= snprintf(query, HUGE_STRING_LENGTH, "set storage_engine=`%s`",
- engine_stmt->string);
- if (run_query(mysql, query, len))
- {
- fprintf(stderr,"%s: Cannot set default engine: %s\n", my_progname,
- mysql_error(mysql));
- exit(1);
- }
- }
-
count= 0;
after_create= stmt;
@@ -1651,8 +1652,21 @@ limit_not_met:
{
char buffer[HUGE_STRING_LENGTH];
- snprintf(buffer, HUGE_STRING_LENGTH, "%s %s", ptr->string,
- engine_stmt->option);
+ snprintf(buffer, HUGE_STRING_LENGTH, "%s Engine = %s %s",
+ ptr->string, engine_stmt->string, engine_stmt->option);
+ if (run_query(mysql, buffer, strlen(buffer)))
+ {
+ fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
+ my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
+ exit(1);
+ }
+ }
+ else if (engine_stmt && engine_stmt->string && ptr->type == CREATE_TABLE_TYPE)
+ {
+ char buffer[HUGE_STRING_LENGTH];
+
+ snprintf(buffer, HUGE_STRING_LENGTH, "%s Engine = %s",
+ ptr->string, engine_stmt->string);
if (run_query(mysql, buffer, strlen(buffer)))
{
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
@@ -1686,6 +1700,7 @@ drop_schema(MYSQL *mysql, const char *db)
{
char query[HUGE_STRING_LENGTH];
int len;
+
DBUG_ENTER("drop_schema");
len= snprintf(query, HUGE_STRING_LENGTH, "DROP SCHEMA IF EXISTS `%s`", db);
@@ -1822,6 +1837,7 @@ pthread_handler_t run_task(void *p)
my_progname, mysql_error(mysql));
exit(0);
}
+ set_mysql_connect_options(mysql);
if (mysql_thread_init())
{
@@ -1862,7 +1878,6 @@ limit_not_met:
my_progname, mysql_error(mysql));
exit(0);
}
-
if (slap_connect(mysql))
goto end;
}
@@ -1972,17 +1987,27 @@ parse_option(const char *origin, option_string **stmt, char delm)
uint count= 0; /* We know that there is always one */
for (tmp= *sptr= (option_string *)my_malloc(sizeof(option_string),
- MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
(retstr= strchr(ptr, delm));
tmp->next= (option_string *)my_malloc(sizeof(option_string),
- MYF(MY_ZEROFILL|MY_FAE|MY_WME)),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME)),
tmp= tmp->next)
{
- char buffer[HUGE_STRING_LENGTH];
+ /*
+ Initialize buffer, because otherwise an
+ --engine=<storage_engine>:<option>,<eng1>,<eng2>
+ will crash.
+ */
+ char buffer[HUGE_STRING_LENGTH]= "";
char *buffer_ptr;
count++;
strncpy(buffer, ptr, (size_t)(retstr - ptr));
+ /*
+ Handle --engine=memory:max_row=200 cases, or more general speaking
+ --engine=<storage_engine>:<options>, which will be translated to
+ Engine = storage_engine option.
+ */
if ((buffer_ptr= strchr(buffer, ':')))
{
char *option_ptr;
@@ -2003,13 +2028,15 @@ parse_option(const char *origin, option_string **stmt, char delm)
tmp->length= (size_t)(retstr - ptr);
}
+ /* Skip delimiter delm */
ptr+= retstr - ptr + 1;
if (isspace(*ptr))
ptr++;
+
count++;
}
- if (ptr != origin+length)
+ if (ptr != origin + length)
{
char *origin_ptr;
@@ -2018,7 +2045,7 @@ parse_option(const char *origin, option_string **stmt, char delm)
char *option_ptr;
tmp->length= (size_t)(origin_ptr - ptr);
- tmp->string= my_strndup(origin, tmp->length, MYF(MY_FAE));
+ tmp->string= my_strndup(ptr, tmp->length, MYF(MY_FAE));
option_ptr= (char *)ptr + 1 + tmp->length;
@@ -2068,7 +2095,7 @@ parse_delimiter(const char *script, statement **stmt, char delm)
if (ptr != script+length)
{
tmp->string= my_strndup(ptr, (uint)((script + length) - ptr),
- MYF(MY_FAE));
+ MYF(MY_FAE));
tmp->length= (size_t)((script + length) - ptr);
count++;
}
@@ -2126,6 +2153,7 @@ print_conclusions_csv(conclusions *con)
{
char buffer[HUGE_STRING_LENGTH];
const char *ptr= auto_generate_sql_type ? auto_generate_sql_type : "query";
+
snprintf(buffer, HUGE_STRING_LENGTH,
"%s,%s,%ld.%03ld,%ld.%03ld,%ld.%03ld,%d,%llu\n",
con->engine ? con->engine : "", /* Storage engine we ran against */
@@ -2212,6 +2240,7 @@ slap_connect(MYSQL *mysql)
int x, connect_error= 1;
for (x= 0; x < 10; x++)
{
+ set_mysql_connect_options(mysql);
if (mysql_real_connect(mysql, host, user, opt_password,
create_schema_string,
opt_mysql_port,
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 22155005112..5415b653615 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2012, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,9 +23,17 @@
http://dev.mysql.com/doc/mysqltest/en/index.html
Please keep the test framework tools identical in all versions!
+
+ Written by:
+ Sasha Pachev <sasha@mysql.com>
+ Matt Wagner <matt@mysql.com>
+ Monty
+ Jani
+ Holyfoot
+ And many others
*/
-#define MTEST_VERSION "3.3"
+#define MTEST_VERSION "3.4"
#include "client_priv.h"
#include <mysql_version.h>
@@ -54,6 +63,12 @@
#define SIGNAL_FMT "signal %d"
#endif
+static my_bool non_blocking_api_enabled= 0;
+#if !defined(EMBEDDED_LIBRARY)
+#define WRAP_NONBLOCK_ENABLED non_blocking_api_enabled
+#include "../tests/nonblock-wrappers.h"
+#endif
+
/* Use cygwin for --exec and --system before 5.0 */
#if MYSQL_VERSION_ID < 50000
#define USE_CYGWIN
@@ -63,7 +78,9 @@
#define MAX_COLUMNS 256
#define MAX_EMBEDDED_SERVER_ARGS 64
#define MAX_DELIMITER_LENGTH 16
-#define DEFAULT_MAX_CONN 128
+#define DEFAULT_MAX_CONN 64
+
+#define DIE_BUFF_SIZE 8192
/* Flags controlling send and reap */
#define QUERY_SEND_FLAG 1
@@ -80,10 +97,7 @@ static my_bool get_one_option(int optid, const struct my_option *,
C_MODE_END
enum {
- OPT_PS_PROTOCOL=OPT_MAX_CLIENT_OPTION, OPT_SP_PROTOCOL,
- OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL, OPT_MAX_CONNECT_RETRIES,
- OPT_MAX_CONNECTIONS, OPT_MARK_PROGRESS, OPT_LOG_DIR,
- OPT_TAIL_LINES, OPT_RESULT_FORMAT_VERSION
+ OPT_LOG_DIR=OPT_MAX_CLIENT_OPTION, OPT_RESULT_FORMAT_VERSION
};
static int record= 0, opt_sleep= -1;
@@ -91,11 +105,12 @@ static char *opt_db= 0, *opt_pass= 0;
const char *opt_user= 0, *opt_host= 0, *unix_sock= 0, *opt_basedir= "./";
static char *shared_memory_base_name=0;
const char *opt_logdir= "";
-const char *opt_include= 0, *opt_charsets_dir;
+const char *opt_prologue= 0, *opt_charsets_dir;
static int opt_port= 0;
static int opt_max_connect_retries;
static int opt_result_format_version;
static int opt_max_connections= DEFAULT_MAX_CONN;
+static int error_count= 0;
static my_bool opt_compress= 0, silent= 0, verbose= 0;
static my_bool debug_info_flag= 0, debug_check_flag= 0;
static my_bool tty_password= 0;
@@ -109,13 +124,15 @@ static my_bool display_result_vertically= FALSE, display_result_lower= FALSE,
display_metadata= FALSE, display_result_sorted= FALSE;
static my_bool disable_query_log= 0, disable_result_log= 0;
static my_bool disable_connect_log= 1;
-static my_bool disable_warnings= 0;
+static my_bool disable_warnings= 0, disable_column_names= 0;
+static my_bool prepare_warnings_enabled= 0;
static my_bool disable_info= 1;
-static my_bool abort_on_error= 1;
+static my_bool abort_on_error= 1, opt_continue_on_error= 0;
static my_bool server_initialized= 0;
static my_bool is_windows= 0;
static char **default_argv;
-static const char *load_default_groups[]= { "mysqltest", "client", 0 };
+static const char *load_default_groups[]=
+{ "mysqltest", "client", "client-server", "client-mariadb", 0 };
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
/* Info on properties that can be set with --enable_X and --disable_X */
@@ -165,6 +182,10 @@ static char delimiter[MAX_DELIMITER_LENGTH]= ";";
static uint delimiter_length= 1;
static char TMPDIR[FN_REFLEN];
+static char global_subst_from[200];
+static char global_subst_to[200];
+static char *global_subst= NULL;
+static MEM_ROOT require_file_root;
/* Block stack */
enum block_cmd {
@@ -196,7 +217,6 @@ static struct st_test_file file_stack[16];
static struct st_test_file* cur_file;
static struct st_test_file* file_stack_end;
-
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
static const char *embedded_server_groups[]=
@@ -222,7 +242,9 @@ static ulonglong timer_now(void);
static ulong connection_retry_sleep= 100000; /* Microseconds */
-static char *opt_plugin_dir= 0;
+static const char *opt_plugin_dir;
+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 */
@@ -233,6 +255,10 @@ static void init_re(void);
static int match_re(my_regex_t *, char *);
static void free_re(void);
+static int replace(DYNAMIC_STRING *ds_str,
+ const char *search_str, ulong search_len,
+ const char *replace_str, ulong replace_len);
+
static uint opt_protocol=0;
DYNAMIC_ARRAY q_lines;
@@ -273,7 +299,7 @@ HASH var_hash;
struct st_connection
{
- MYSQL mysql;
+ MYSQL *mysql;
/* Used when creating views and sp, to avoid implicit commit */
MYSQL* util_mysql;
char *name;
@@ -327,6 +353,7 @@ enum enum_commands {
Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
Q_ENABLE_INFO, Q_DISABLE_INFO,
Q_ENABLE_METADATA, Q_DISABLE_METADATA,
+ Q_ENABLE_COLUMN_NAMES, Q_DISABLE_COLUMN_NAMES,
Q_EXEC, Q_DELIMITER,
Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
@@ -334,6 +361,7 @@ enum enum_commands {
Q_LOWERCASE,
Q_START_TIMER, Q_END_TIMER,
Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
+ Q_ENABLE_NON_BLOCKING_API, Q_DISABLE_NON_BLOCKING_API,
Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
Q_IF,
Q_DISABLE_PARSING, Q_ENABLE_PARSING,
@@ -345,6 +373,7 @@ enum enum_commands {
Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER,
Q_RESULT_FORMAT_VERSION,
Q_MOVE_FILE, Q_REMOVE_FILES_WILDCARD, Q_SEND_EVAL,
+ Q_ENABLE_PREPARE_WARNINGS, Q_DISABLE_PREPARE_WARNINGS,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
Q_COMMENT_WITH_COMMAND,
@@ -397,6 +426,8 @@ const char *command_names[]=
"disable_info",
"enable_metadata",
"disable_metadata",
+ "enable_column_names",
+ "disable_column_names",
"exec",
"delimiter",
"disable_abort_on_error",
@@ -412,6 +443,8 @@ const char *command_names[]=
"character_set",
"disable_ps_protocol",
"enable_ps_protocol",
+ "enable_non_blocking_api",
+ "disable_non_blocking_api",
"disable_reconnect",
"enable_reconnect",
"if",
@@ -445,6 +478,8 @@ const char *command_names[]=
"move_file",
"remove_files_wildcard",
"send_eval",
+ "enable_prepare_warnings",
+ "disable_prepare_warnings",
0
};
@@ -488,7 +523,7 @@ struct st_command
int first_word_len, query_len;
my_bool abort_on_error, used_replace;
struct st_expected_errors expected_errors;
- char require_file[FN_REFLEN];
+ char *require_file;
enum enum_commands type;
};
@@ -529,14 +564,15 @@ const char *from, int len);
static void cleanup_and_exit(int exit_code) __attribute__((noreturn));
-void die(const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2) __attribute__((noreturn));
-void abort_not_supported_test(const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2) __attribute__((noreturn));
-void verbose_msg(const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2);
-void log_msg(const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2);
+void really_die(const char *msg) __attribute__((noreturn));
+void report_or_die(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
+void die(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2)
+ __attribute__((noreturn));
+static void make_error_message(char *buf, size_t len, const char *fmt, va_list args);
+void abort_not_supported_test(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2)
+ __attribute__((noreturn));
+void verbose_msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
+void log_msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
VAR* var_from_env(const char *, const char *);
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
@@ -587,6 +623,8 @@ void free_all_replace(){
free_replace_column();
}
+void var_set_int(const char* name, int value);
+
class LogFile {
FILE* m_file;
@@ -607,8 +645,7 @@ public:
void open(const char* dir, const char* name, const char* ext)
{
DBUG_ENTER("LogFile::open");
- DBUG_PRINT("enter", ("dir: '%s', name: '%s'",
- dir, name));
+ DBUG_PRINT("enter", ("dir: '%s', name: '%s'", dir, name));
if (!name)
{
m_file= stdout;
@@ -656,6 +693,10 @@ public:
DBUG_VOID_RETURN;
DBUG_ASSERT(ds->str);
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("QQ", ("str: %*s", (int) ds->length, ds->str));
+#endif
+
if (fwrite(ds->str, 1, ds->length, m_file) != ds->length)
die("Failed to write %lu bytes to '%s', errno: %d",
(unsigned long)ds->length, m_file_name, errno);
@@ -674,14 +715,14 @@ public:
lines++;
int show_offset= 0;
- char buf[256];
+ char buf[256+1]; /* + zero termination for DBUG_PRINT */
size_t bytes;
bool found_bof= false;
/* Search backward in file until "lines" newline has been found */
while (lines && !found_bof)
{
- show_offset-= sizeof(buf);
+ show_offset-= sizeof(buf)-1;
while(fseek(m_file, show_offset, SEEK_END) != 0 && show_offset < 0)
{
found_bof= true;
@@ -689,7 +730,7 @@ public:
show_offset++;
}
- if ((bytes= fread(buf, 1, sizeof(buf), m_file)) <= 0)
+ if ((bytes= fread(buf, 1, sizeof(buf)-1, m_file)) <= 0)
{
// ferror=0 will happen here if no queries executed yet
if (ferror(m_file))
@@ -699,8 +740,8 @@ public:
DBUG_VOID_RETURN;
}
- DBUG_PRINT("info", ("Read %lu bytes from file, buf: %s",
- (unsigned long)bytes, buf));
+ DBUG_PRINT("info", ("Read %zu bytes from file, buf: %.*s",
+ bytes, (int)bytes, buf));
char* show_from= buf + bytes;
while(show_from > buf && lines > 0 )
@@ -743,8 +784,10 @@ public:
}
}
- while ((bytes= fread(buf, 1, sizeof(buf), m_file)) > 0)
- fwrite(buf, 1, bytes, stderr);
+ while ((bytes= fread(buf, 1, sizeof(buf)-1, m_file)) > 0)
+ if (bytes != fwrite(buf, 1, bytes, stderr))
+ die("Failed to write to '%s', errno: %d",
+ m_file_name, errno);
if (!lines)
{
@@ -765,7 +808,8 @@ void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int 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);
+void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input,
+ bool keep_header);
static int match_expected_error(struct st_command *command,
unsigned int err_errno,
@@ -776,12 +820,19 @@ void handle_error(struct st_command*,
void handle_no_error(struct st_command*);
void revert_properties();
+static void handle_no_active_connection(struct st_command* command,
+ struct st_connection *cn, DYNAMIC_STRING *ds);
+
#ifdef EMBEDDED_LIBRARY
#define EMB_SEND_QUERY 1
#define EMB_READ_QUERY_RESULT 2
#define EMB_END_CONNECTION 3
+/* workaround for MySQL BUG#57491 */
+#undef MY_WME
+#define MY_WME 0
+
/* attributes of the query thread */
pthread_attr_t cn_thd_attrib;
@@ -812,10 +863,10 @@ pthread_handler_t connection_thread(void *arg)
case EMB_END_CONNECTION:
goto end_thread;
case EMB_SEND_QUERY:
- cn->result= mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len);
+ cn->result= mysql_send_query(cn->mysql, cn->cur_query, cn->cur_query_len);
break;
case EMB_READ_QUERY_RESULT:
- cn->result= mysql_read_query_result(&cn->mysql);
+ cn->result= mysql_read_query_result(cn->mysql);
break;
default:
DBUG_ASSERT(0);
@@ -868,7 +919,7 @@ static void signal_connection_thd(struct st_connection *cn, int command)
static int do_send_query(struct st_connection *cn, const char *q, int q_len)
{
if (!cn->has_thread)
- return mysql_send_query(&cn->mysql, q, q_len);
+ return mysql_send_query(cn->mysql, q, q_len);
cn->cur_query= q;
cn->cur_query_len= q_len;
signal_connection_thd(cn, EMB_SEND_QUERY);
@@ -916,8 +967,9 @@ static void init_connection_thd(struct st_connection *cn)
#else /*EMBEDDED_LIBRARY*/
-#define do_send_query(cn,q,q_len) mysql_send_query(&cn->mysql, q, q_len)
-#define do_read_query_result(cn) mysql_read_query_result(&cn->mysql)
+#define init_connection_thd(X) do { } while(0)
+#define do_send_query(cn,q,q_len) mysql_send_query(cn->mysql, q, q_len)
+#define do_read_query_result(cn) mysql_read_query_result(cn->mysql)
#endif /*EMBEDDED_LIBRARY*/
@@ -942,7 +994,10 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
else
{
if (!(v= var_get(p, &p, 0, 0)))
- die("Bad variable in eval");
+ {
+ report_or_die( "Bad variable in eval");
+ return;
+ }
dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
}
break;
@@ -1219,36 +1274,48 @@ void check_command_args(struct st_command *command,
DBUG_VOID_RETURN;
}
-void handle_command_error(struct st_command *command, uint error)
+void handle_command_error(struct st_command *command, uint error,
+ int sys_errno)
{
DBUG_ENTER("handle_command_error");
DBUG_PRINT("enter", ("error: %d", error));
+ var_set_int("$sys_errno",sys_errno);
+ var_set_int("$errno",error);
if (error != 0)
{
int i;
if (command->abort_on_error)
- die("command \"%.*s\" failed with error %d. my_errno=%d",
- command->first_word_len, command->query, error, my_errno);
+ {
+ report_or_die("command \"%.*s\" failed with error: %u my_errno: %d "
+ "errno: %d",
+ command->first_word_len, command->query, error, my_errno,
+ sys_errno);
+ DBUG_VOID_RETURN;
+ }
i= match_expected_error(command, error, NULL);
if (i >= 0)
{
- DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %d",
- command->first_word_len, command->query, error));
+ DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %u, errno: %d",
+ command->first_word_len, command->query, error,
+ sys_errno));
revert_properties();
DBUG_VOID_RETURN;
}
if (command->expected_errors.count > 0)
- die("command \"%.*s\" failed with wrong error: %d. my_errno=%d",
- command->first_word_len, command->query, error, my_errno);
+ report_or_die("command \"%.*s\" failed with wrong error: %u "
+ "my_errno: %d errno: %d",
+ command->first_word_len, command->query, error, my_errno,
+ sys_errno);
}
else if (command->expected_errors.err[0].type == ERR_ERRNO &&
command->expected_errors.err[0].code.errnum != 0)
{
/* Error code we wanted was != 0, i.e. not an expected success */
- die("command \"%.*s\" succeeded - should have failed with errno %d...",
+ report_or_die("command \"%.*s\" succeeded - should have failed with "
+ "errno %d...",
command->first_word_len, command->query,
command->expected_errors.err[0].code.errnum);
}
@@ -1268,7 +1335,8 @@ void close_connections()
if (next_con->stmt)
mysql_stmt_close(next_con->stmt);
next_con->stmt= 0;
- mysql_close(&next_con->mysql);
+ mysql_close(next_con->mysql);
+ next_con->mysql= 0;
if (next_con->util_mysql)
mysql_close(next_con->util_mysql);
my_free(next_con->name);
@@ -1341,24 +1409,34 @@ void free_used_memory()
free_all_replace();
my_free(opt_pass);
free_defaults(default_argv);
+ free_root(&require_file_root, MYF(0));
free_re();
#ifdef __WIN__
free_tmp_sh_file();
free_win_path_patterns();
#endif
+ DBUG_VOID_RETURN;
+}
+
+
+static void cleanup_and_exit(int exit_code)
+{
+ free_used_memory();
/* Only call mysql_server_end if mysql_server_init has been called */
if (server_initialized)
mysql_server_end();
- /* Don't use DBUG after mysql_server_end() */
- return;
-}
+ /*
+ mysqltest is fundamentally written in a way that makes impossible
+ to free all memory before exit (consider memory allocated
+ for frame local DYNAMIC_STRING's and die() invoked down the stack.
+ We close stderr here to stop unavoidable safemalloc reports
+ from polluting the output.
+ */
+ fclose(stderr);
-static void cleanup_and_exit(int exit_code)
-{
- free_used_memory();
my_end(my_end_arg);
if (!silent) {
@@ -1378,26 +1456,64 @@ static void cleanup_and_exit(int exit_code)
}
}
+ sf_leaking_memory= 0; /* all memory should be freed by now */
exit(exit_code);
}
-void print_file_stack()
+size_t print_file_stack(char *s, const char *end)
+{
+ char *start= s;
+ struct st_test_file* err_file= cur_file;
+ if (err_file == file_stack)
+ return 0;
+
+ for (;;)
+ {
+ err_file--;
+ s+= my_snprintf(s, end - s, "included from %s at line %d:\n",
+ err_file->file_name, err_file->lineno);
+ if (err_file == file_stack)
+ break;
+ }
+ return s - start;
+}
+
+
+static void make_error_message(char *buf, size_t len, const char *fmt, va_list args)
{
- for (struct st_test_file* err_file= cur_file;
- err_file != file_stack;
- err_file--)
+ char *s= buf, *end= buf + len;
+ s+= my_snprintf(s, end - s, "mysqltest: ");
+ if (cur_file && cur_file != file_stack)
{
- fprintf(stderr, "included from %s at line %d:\n",
- err_file->file_name, err_file->lineno);
+ s+= my_snprintf(s, end - s, "In included file \"%s\": \n",
+ cur_file->file_name);
+ s+= print_file_stack(s, end);
}
+
+ if (start_lineno > 0)
+ s+= my_snprintf(s, end -s, "At line %u: ", start_lineno);
+ if (!fmt)
+ fmt= "unknown error";
+
+ s+= my_vsnprintf(s, end - s, fmt, args);
+ s+= my_snprintf(s, end -s, "\n", start_lineno);
}
void die(const char *fmt, ...)
{
- static int dying= 0;
+ char buff[DIE_BUFF_SIZE];
va_list args;
- DBUG_ENTER("die");
- DBUG_PRINT("enter", ("start_lineno: %d", start_lineno));
+ va_start(args, fmt);
+ make_error_message(buff, sizeof(buff), fmt, args);
+ really_die(buff);
+}
+
+void really_die(const char *msg)
+{
+ static int dying= 0;
+ fflush(stdout);
+ fprintf(stderr, "%s", msg);
+ fflush(stderr);
/*
Protect against dying twice
@@ -1408,28 +1524,6 @@ void die(const char *fmt, ...)
cleanup_and_exit(1);
dying= 1;
- /* Print the error message */
- fprintf(stderr, "mysqltest: ");
- if (cur_file && cur_file != file_stack)
- {
- fprintf(stderr, "In included file \"%s\": \n",
- cur_file->file_name);
- print_file_stack();
- }
-
- if (start_lineno > 0)
- fprintf(stderr, "At line %u: ", start_lineno);
- if (fmt)
- {
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- }
- else
- fprintf(stderr, "unknown error");
- fprintf(stderr, "\n");
- fflush(stderr);
-
log_file.show_tail(opt_tail_lines);
/*
@@ -1437,11 +1531,33 @@ void die(const char *fmt, ...)
been produced prior to the error
*/
if (cur_con && !cur_con->pending)
- show_warnings_before_error(&cur_con->mysql);
+ show_warnings_before_error(cur_con->mysql);
cleanup_and_exit(1);
}
+void report_or_die(const char *fmt, ...)
+{
+ va_list args;
+ DBUG_ENTER("report_or_die");
+
+ char buff[DIE_BUFF_SIZE];
+
+ va_start(args, fmt);
+ make_error_message(buff, sizeof(buff), fmt, args);
+ va_end(args);
+
+ if (opt_continue_on_error)
+ {
+ /* Just log the error and continue */
+ replace_dynstr_append(&ds_res, buff);
+ error_count++;
+ DBUG_VOID_RETURN;
+ }
+
+ really_die(buff);
+}
+
void abort_not_supported_test(const char *fmt, ...)
{
@@ -1449,11 +1565,15 @@ void abort_not_supported_test(const char *fmt, ...)
DBUG_ENTER("abort_not_supported_test");
/* Print include filestack */
+ fflush(stdout);
fprintf(stderr, "The test '%s' is not supported by this installation\n",
file_stack->file_name);
fprintf(stderr, "Detected in file %s at line %d\n",
cur_file->file_name, cur_file->lineno);
- print_file_stack();
+
+ char buff[DIE_BUFF_SIZE];
+ print_file_stack(buff, buff + sizeof(buff));
+ fprintf(stderr, "%s", buff);
/* Print error message */
va_start(args, fmt);
@@ -1480,9 +1600,12 @@ void verbose_msg(const char *fmt, ...)
{
va_list args;
DBUG_ENTER("verbose_msg");
+ DBUG_PRINT("enter", ("format: %s", fmt));
+
if (!verbose)
DBUG_VOID_RETURN;
+ fflush(stdout);
va_start(args, fmt);
fprintf(stderr, "mysqltest: ");
if (cur_file && cur_file != file_stack)
@@ -1493,6 +1616,7 @@ void verbose_msg(const char *fmt, ...)
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
+ fflush(stderr);
DBUG_VOID_RETURN;
}
@@ -1577,9 +1701,14 @@ static int run_command(char* cmd,
char buf[512]= {0};
FILE *res_file;
int error;
+ DBUG_ENTER("run_command");
+ DBUG_PRINT("enter", ("cmd: %s", cmd));
if (!(res_file= popen(cmd, "r")))
- die("popen(\"%s\", \"r\") failed", cmd);
+ {
+ report_or_die("popen(\"%s\", \"r\") failed", cmd);
+ return -1;
+ }
while (fgets(buf, sizeof(buf), res_file))
{
@@ -1597,7 +1726,7 @@ static int run_command(char* cmd,
}
error= pclose(res_file);
- return WEXITSTATUS(error);
+ DBUG_RETURN(WEXITSTATUS(error));
}
@@ -1679,7 +1808,10 @@ static int diff_check(const char *diff_name)
if (!(res_file= popen(buf, "r")))
die("popen(\"%s\", \"r\") failed", buf);
- /* if diff is not present, nothing will be in stdout to increment have_diff */
+ /*
+ if diff is not present, nothing will be in stdout to increment
+ have_diff
+ */
if (fgets(buf, sizeof(buf), res_file))
have_diff= 1;
@@ -1835,49 +1967,69 @@ enum compare_files_result_enum {
*/
-int compare_files2(File fd, const char* filename2)
+int compare_files2(File fd1, const char* filename2)
{
int error= RESULT_OK;
File fd2;
- size_t len, len2;
- char buff[512], buff2[512];
+ size_t fd1_length, fd2_length;
+ DYNAMIC_STRING fd1_result, fd2_result;
if ((fd2= my_open(filename2, O_RDONLY, MYF(0))) < 0)
{
- my_close(fd, MYF(0));
+ my_close(fd1, MYF(0));
die("Failed to open second file: '%s'", filename2);
}
- while((len= my_read(fd, (uchar*)&buff,
- sizeof(buff), MYF(0))) > 0)
- {
- if ((len2= my_read(fd2, (uchar*)&buff2,
- sizeof(buff2), MYF(0))) < len)
- {
- /* File 2 was smaller */
- error= RESULT_LENGTH_MISMATCH;
- break;
- }
- if (len2 > len)
- {
- /* File 1 was smaller */
- error= RESULT_LENGTH_MISMATCH;
- break;
- }
- if ((memcmp(buff, buff2, len)))
- {
- /* Content of this part differed */
- error= RESULT_CONTENT_MISMATCH;
- break;
- }
+
+ fd1_length= (size_t) my_seek(fd1, 0, SEEK_END, MYF(0));
+ fd2_length= (size_t) my_seek(fd2, 0, SEEK_END, MYF(0));
+
+ if (init_dynamic_string(&fd1_result, 0, fd1_length, 0) ||
+ init_dynamic_string(&fd2_result, 0, fd2_length, 0))
+ die("Out of memory when allocating data for result");
+
+ fd1_result.length= fd1_length;
+ fd2_result.length= fd2_length;
+
+ (void) my_seek(fd1, 0, SEEK_SET, MYF(0));
+ (void) my_seek(fd2, 0, SEEK_SET, MYF(0));
+ if (my_read(fd1, (uchar*) fd1_result.str, fd1_length, MYF(MY_WME | MY_NABP)))
+ die("Error when reading data from result file");
+ if (my_read(fd2, (uchar*) fd2_result.str, fd2_length, MYF(MY_WME | MY_NABP)))
+ die("Error when reading data from result file");
+
+ if (global_subst &&
+ (fd1_length != fd2_length ||
+ memcmp(fd1_result.str, fd2_result.str, fd1_length)))
+ {
+ /**
+ @todo MARIA_HACK
+ This serves for when a test is run with --default-storage-engine=X
+ where X is not MyISAM: tests using SHOW CREATE TABLE will always fail
+ because SHOW CREATE TABLE prints X instead of MyISAM. With
+ --global-subst=X,MyISAM , such trivial differences are eliminated and
+ test may be reported as passing.
+ --global-subst is only a quick way to run a lot of existing tests
+ with Maria and find bugs; it is not good enough for reaching the main
+ trees when Maria is merged into them.
+ --global-subst should be removed.
+ */
+ uint global_subst_from_len= strlen(global_subst_from);
+ uint global_subst_to_len= strlen(global_subst_to);
+ while (replace(&fd1_result,
+ global_subst_from, global_subst_from_len,
+ global_subst_to, global_subst_to_len) == 0)
+ /* do nothing */ ;
+ /* let's compare again to see if it is ok now */
}
- if (!error && my_read(fd2, (uchar*)&buff2,
- sizeof(buff2), MYF(0)) > 0)
- {
- /* File 1 was smaller */
+
+ if (fd1_result.length != fd2_result.length)
error= RESULT_LENGTH_MISMATCH;
- }
+ else if ((memcmp(fd1_result.str, fd2_result.str, fd1_result.length)))
+ error= RESULT_CONTENT_MISMATCH;
my_close(fd2, MYF(0));
+ dynstr_free(&fd1_result);
+ dynstr_free(&fd2_result);
return error;
}
@@ -1945,7 +2097,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
{
my_close(fd, MYF(0));
/* Remove the temporary file */
- my_delete(temp_file_path, MYF(0));
+ my_delete(temp_file_path, MYF(MY_WME));
die("Failed to write file '%s'", temp_file_path);
}
@@ -1953,7 +2105,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
my_close(fd, MYF(0));
/* Remove the temporary file */
- my_delete(temp_file_path, MYF(0));
+ my_delete(temp_file_path, MYF(MY_WME));
DBUG_RETURN(error);
}
@@ -1972,7 +2124,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
void check_result()
{
- const char* mess= "Result content mismatch\n";
+ const char *mess= 0;
DBUG_ENTER("check_result");
DBUG_ASSERT(result_file_name);
@@ -1980,9 +2132,13 @@ void check_result()
switch (compare_files(log_file.file_name(), result_file_name)) {
case RESULT_OK:
- break; /* ok */
+ if (!error_count)
+ break; /* ok */
+ mess= "Got errors while running test";
+ /* Fallthrough */
case RESULT_LENGTH_MISMATCH:
- mess= "Result length mismatch\n";
+ if (!mess)
+ mess= "Result length mismatch\n";
/* Fallthrough */
case RESULT_CONTENT_MISMATCH:
{
@@ -1992,12 +2148,16 @@ void check_result()
*/
char reject_file[FN_REFLEN];
size_t reject_length;
+
+ if (!mess)
+ mess= "Result content mismatch\n";
+
dirname_part(reject_file, result_file_name, &reject_length);
if (access(reject_file, W_OK) == 0)
{
/* Result file directory is writable, save reject file there */
- fn_format(reject_file, result_file_name, NULL,
+ fn_format(reject_file, result_file_name, "",
".reject", MY_REPLACE_EXT);
}
else
@@ -2091,8 +2251,8 @@ static int strip_surrounding(char* str, char c1, char c2)
static void strip_parentheses(struct st_command *command)
{
if (strip_surrounding(command->first_argument, '(', ')'))
- die("%.*s - argument list started with '%c' must be ended with '%c'",
- command->first_word_len, command->query, '(', ')');
+ die("%.*s - argument list started with '%c' must be ended with '%c'",
+ command->first_word_len, command->query, '(', ')');
}
@@ -2406,11 +2566,24 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
*query_end : query + strlen(query));
MYSQL_RES *res;
MYSQL_ROW row;
- MYSQL* mysql = &cur_con->mysql;
+ MYSQL* mysql = cur_con->mysql;
DYNAMIC_STRING ds_query;
DBUG_ENTER("var_query_set");
LINT_INIT(res);
+ if (!mysql)
+ {
+ struct st_command command;
+ memset(&command, 0, sizeof(command));
+ command.query= (char*)query;
+ command.first_word_len= (*query_end - query);
+ command.first_argument= command.query + command.first_word_len;
+ command.end= (char*)*query_end;
+ command.abort_on_error= 1; /* avoid uninitialized variables */
+ handle_no_active_connection(&command, cur_con, &ds_res);
+ DBUG_VOID_RETURN;
+ }
+
/* Only white space or ) allowed past ending ` */
while (end > query && *end != '`')
{
@@ -2429,8 +2602,8 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
if (mysql_real_query(mysql, ds_query.str, ds_query.length))
{
- handle_error (curr_command, mysql_errno(mysql), mysql_error(mysql),
- mysql_sqlstate(mysql), &ds_res);
+ handle_error(curr_command, mysql_errno(mysql), mysql_error(mysql),
+ mysql_sqlstate(mysql), &ds_res);
/* If error was acceptable, return empty string */
dynstr_free(&ds_query);
eval_expr(var, "", 0);
@@ -2438,7 +2611,12 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
}
if (!(res= mysql_store_result(mysql)))
- die("Query '%s' didn't return a result set", ds_query.str);
+ {
+ report_or_die("Query '%s' didn't return a result set", ds_query.str);
+ dynstr_free(&ds_query);
+ eval_expr(var, "", 0);
+ return;
+ }
dynstr_free(&ds_query);
if ((row= mysql_fetch_row(res)) && row[0])
@@ -2571,7 +2749,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
long row_no;
int col_no= -1;
MYSQL_RES* res;
- MYSQL* mysql= &cur_con->mysql;
+ MYSQL* mysql= cur_con->mysql;
static DYNAMIC_STRING ds_query;
static DYNAMIC_STRING ds_col;
@@ -2585,6 +2763,12 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
DBUG_ENTER("var_set_query_get_value");
LINT_INIT(res);
+ if (!mysql)
+ {
+ handle_no_active_connection(command, cur_con, &ds_res);
+ DBUG_VOID_RETURN;
+ }
+
strip_parentheses(command);
DBUG_PRINT("info", ("query: %s", command->query));
check_command_args(command, command->first_argument, query_get_value_args,
@@ -2607,16 +2791,23 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
/* Run the query */
if (mysql_real_query(mysql, ds_query.str, ds_query.length))
{
- handle_error (curr_command, mysql_errno(mysql), mysql_error(mysql),
- mysql_sqlstate(mysql), &ds_res);
+ handle_error(curr_command, mysql_errno(mysql), mysql_error(mysql),
+ mysql_sqlstate(mysql), &ds_res);
/* If error was acceptable, return empty string */
dynstr_free(&ds_query);
+ dynstr_free(&ds_col);
eval_expr(var, "", 0);
DBUG_VOID_RETURN;
}
if (!(res= mysql_store_result(mysql)))
- die("Query '%s' didn't return a result set", ds_query.str);
+ {
+ report_or_die("Query '%s' didn't return a result set", ds_query.str);
+ dynstr_free(&ds_query);
+ dynstr_free(&ds_col);
+ eval_expr(var, "", 0);
+ return;
+ }
{
/* Find column number from the given column name */
@@ -2636,8 +2827,11 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
if (col_no == -1)
{
mysql_free_result(res);
- die("Could not find column '%s' in the result of '%s'",
- ds_col.str, ds_query.str);
+ report_or_die("Could not find column '%s' in the result of '%s'",
+ ds_col.str, ds_query.str);
+ dynstr_free(&ds_query);
+ dynstr_free(&ds_col);
+ return;
}
DBUG_PRINT("info", ("Found column %d with name '%s'",
i, fields[i].name));
@@ -2745,6 +2939,7 @@ void eval_expr(VAR *v, const char *p, const char **p_end,
command.first_word_len= len;
command.first_argument= command.query + len;
command.end= (char*)*p_end;
+ command.abort_on_error= 1; /* avoid uninitialized variables */
var_set_query_get_value(&command, v);
DBUG_VOID_RETURN;
}
@@ -2774,40 +2969,128 @@ void eval_expr(VAR *v, const char *p, const char **p_end,
}
-int open_file(const char *name)
+bool open_and_set_current(const char *name)
+{
+ FILE *opened= fopen(name, "rb");
+
+ if (!opened)
+ return false;
+
+ cur_file++;
+ cur_file->file= opened;
+ cur_file->file_name= my_strdup(name, MYF(MY_FAE));
+ cur_file->lineno=1;
+ return true;
+}
+
+
+void open_file(const char *name)
{
char buff[FN_REFLEN];
size_t length;
+ const char *curname= cur_file->file_name;
DBUG_ENTER("open_file");
DBUG_PRINT("enter", ("name: %s", name));
- /* Extract path from current file and try it as base first */
- if (dirname_part(buff, cur_file->file_name, &length))
+ if (cur_file == file_stack_end)
+ die("Source directives are nesting too deep");
+
+ if (test_if_hard_path(name))
{
- strxmov(buff, buff, name, NullS);
- if (access(buff, F_OK) == 0){
- DBUG_PRINT("info", ("The file exists"));
- name= buff;
- }
+ if (open_and_set_current(name))
+ DBUG_VOID_RETURN;
}
- if (!test_if_hard_path(name))
+ else
{
- strxmov(buff, opt_basedir, name, NullS);
- name=buff;
- }
- fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
+ /*
+ if overlay-dir is specified, and the file is located somewhere
+ under overlay-dir or under suite-dir, the search works as follows:
+
+ 0.let suffix be current file dirname relative to siute-dir or overlay-dir
+ 1.try in overlay-dir/suffix
+ 2.try in suite-dir/suffix
+ 3.try in overlay-dir
+ 4.try in suite-dir
+ 5.try in basedir
+
+ consider an example: 'rty' overlay of the 'qwe' suite,
+ file qwe/include/some.inc contains the line
+ --source thing.inc
+ we look for it in this order:
+ 0.suffix is "include/"
+ 1.try in rty/include/thing.inc
+ 2.try in qwe/include/thing.inc
+ 3.try in try/thing.inc | this is useful when t/a.test has
+ 4.try in qwe/thing.inc | source include/b.inc;
+ 5.try in mysql-test/include/thing.inc
+
+ otherwise the search is as follows
+ 1.try in current file dirname
+ 3.try in overlay-dir (if any)
+ 4.try in suite-dir
+ 5.try in basedir
+ */
- if (cur_file == file_stack_end)
- die("Source directives are nesting too deep");
- cur_file++;
- if (!(cur_file->file = fopen(buff, "rb")))
- {
- cur_file--;
- die("Could not open '%s' for reading, errno: %d", buff, errno);
+ bool in_overlay= opt_overlay_dir &&
+ !strncmp(curname, opt_overlay_dir, overlay_dir_len);
+ bool in_suiteir= opt_overlay_dir && !in_overlay &&
+ !strncmp(curname, opt_suite_dir, suite_dir_len);
+ if (in_overlay || in_suiteir)
+ {
+ size_t prefix_len = in_overlay ? overlay_dir_len : suite_dir_len;
+ char buf2[FN_REFLEN], *suffix= buf2 + prefix_len;
+ dirname_part(buf2, curname, &length);
+
+ /* 1. first we look in the overlay dir */
+ strxnmov(buff, sizeof(buff), opt_overlay_dir, suffix, name, NullS);
+
+ /*
+ Overlayed rty/include/thing.inc can contain the line
+ --source thing.inc
+ which would mean to include qwe/include/thing.inc.
+ But it looks like including "itself", so don't try to open the file,
+ if buff contains the same file name as curname.
+ */
+ if (strcmp(buff, curname) && open_and_set_current(buff))
+ DBUG_VOID_RETURN;
+
+ /* 2. if that failed, we look in the suite dir */
+ strxnmov(buff, sizeof(buff), opt_suite_dir, suffix, name, NullS);
+
+ /* buff can not be equal to curname, as a file can never include itself */
+ if (open_and_set_current(buff))
+ DBUG_VOID_RETURN;
+ }
+ else
+ {
+ /* 1. try in current file dirname */
+ dirname_part(buff, curname, &length);
+ strxnmov(buff, sizeof(buff), buff, name, NullS);
+ if (open_and_set_current(buff))
+ DBUG_VOID_RETURN;
+ }
+
+ /* 3. now, look in the overlay dir */
+ if (opt_overlay_dir)
+ {
+ strxmov(buff, opt_overlay_dir, name, NullS);
+ if (open_and_set_current(buff))
+ DBUG_VOID_RETURN;
+ }
+
+ /* 4. if that failed - look in the suite dir */
+ strxmov(buff, opt_suite_dir, name, NullS);
+ if (open_and_set_current(buff))
+ DBUG_VOID_RETURN;
+
+ /* 5. the last resort - look in the base dir */
+ strxnmov(buff, sizeof(buff), opt_basedir, name, NullS);
+ if (open_and_set_current(buff))
+ DBUG_VOID_RETURN;
}
- cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
- cur_file->lineno=1;
- DBUG_RETURN(0);
+
+ die("Could not open '%s' for reading, errno: %d", name, errno);
+ DBUG_VOID_RETURN;
}
@@ -2980,6 +3263,7 @@ void do_exec(struct st_command *command)
FILE *res_file;
char *cmd= command->first_argument;
DYNAMIC_STRING ds_cmd;
+ DYNAMIC_STRING ds_sorted, *ds_result;
DBUG_ENTER("do_exec");
DBUG_PRINT("enter", ("cmd: '%s'", cmd));
@@ -2987,7 +3271,10 @@ void do_exec(struct st_command *command)
while (*cmd && my_isspace(charset_info, *cmd))
cmd++;
if (!*cmd)
- die("Missing argument in exec");
+ {
+ report_or_die("Missing argument in exec");
+ return;
+ }
command->last_argument= command->end;
init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
@@ -3019,10 +3306,19 @@ void do_exec(struct st_command *command)
DBUG_PRINT("info", ("Executing '%s' as '%s'",
command->first_argument, ds_cmd.str));
- if (!(res_file= my_popen(&ds_cmd, "r")) && command->abort_on_error)
+ if (!(res_file= my_popen(&ds_cmd, "r")))
{
dynstr_free(&ds_cmd);
- die("popen(\"%s\", \"r\") failed", command->first_argument);
+ if (command->abort_on_error)
+ report_or_die("popen(\"%s\", \"r\") failed", command->first_argument);
+ return;
+ }
+
+ ds_result= &ds_res;
+ if (display_result_sorted)
+ {
+ init_dynamic_string(&ds_sorted, "", 1024, 1024);
+ ds_result= &ds_sorted;
}
while (fgets(buf, sizeof(buf), res_file))
@@ -3034,10 +3330,17 @@ void do_exec(struct st_command *command)
}
else
{
- replace_dynstr_append(&ds_res, buf);
+ replace_dynstr_append(ds_result, buf);
}
}
error= pclose(res_file);
+
+ if (display_result_sorted)
+ {
+ dynstr_append_sorted(&ds_res, &ds_sorted, 0);
+ dynstr_free(&ds_sorted);
+ }
+
if (error > 0)
{
uint status= WEXITSTATUS(error);
@@ -3045,11 +3348,12 @@ void do_exec(struct st_command *command)
if (command->abort_on_error)
{
- log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d",
- ds_cmd.str, error, status, errno);
+ report_or_die("exec of '%s' failed, error: %d, status: %d, errno: %d\n"
+ "Output from before failure:\n%s\n",
+ ds_cmd.str, error, status, errno,
+ ds_res.str);
dynstr_free(&ds_cmd);
- die("command \"%s\" failed\n\nOutput from before failure:\n%s\n",
- command->first_argument, ds_res.str);
+ return;
}
DBUG_PRINT("info",
@@ -3064,8 +3368,8 @@ void do_exec(struct st_command *command)
{
dynstr_free(&ds_cmd);
if (command->expected_errors.count > 0)
- die("command \"%s\" failed with wrong error: %d",
- command->first_argument, status);
+ report_or_die("command \"%s\" failed with wrong error: %d",
+ command->first_argument, status);
}
}
else if (command->expected_errors.err[0].type == ERR_ERRNO &&
@@ -3075,8 +3379,10 @@ void do_exec(struct st_command *command)
log_msg("exec of '%s failed, error: %d, errno: %d",
ds_cmd.str, error, errno);
dynstr_free(&ds_cmd);
- die("command \"%s\" succeeded - should have failed with errno %d...",
- command->first_argument, command->expected_errors.err[0].code.errnum);
+ report_or_die("command \"%s\" succeeded - should have failed with "
+ "errno %d...",
+ command->first_argument,
+ command->expected_errors.err[0].code.errnum);
}
dynstr_free(&ds_cmd);
@@ -3110,7 +3416,8 @@ int do_modify_var(struct st_command *command,
const char *p= command->first_argument;
VAR* v;
if (!*p)
- die("Missing argument to %.*s", command->first_word_len, command->query);
+ die("Missing argument to %.*s", command->first_word_len,
+ command->query);
if (*p != '$')
die("The argument to %.*s must be a variable (start with $)",
command->first_word_len, command->query);
@@ -3176,7 +3483,10 @@ void do_system(struct st_command *command)
DBUG_ENTER("do_system");
if (strlen(command->first_argument) == 0)
- die("Missing arguments to system, nothing to do!");
+ {
+ report_or_die("Missing arguments to system, nothing to do!");
+ return;
+ }
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
@@ -3197,12 +3507,14 @@ void do_system(struct st_command *command)
if (my_system(&ds_cmd))
{
if (command->abort_on_error)
- die("system command '%s' failed", command->first_argument);
-
- /* If ! abort_on_error, log message and continue */
- dynstr_append(&ds_res, "system command '");
- replace_dynstr_append(&ds_res, command->first_argument);
- dynstr_append(&ds_res, "' failed\n");
+ report_or_die("system command '%s' failed", command->first_argument);
+ else
+ {
+ /* If ! abort_on_error, log message and continue */
+ dynstr_append(&ds_res, "system command '");
+ replace_dynstr_append(&ds_res, command->first_argument);
+ dynstr_append(&ds_res, "' failed\n");
+ }
}
command->last_argument= command->end;
@@ -3270,8 +3582,8 @@ void do_remove_file(struct st_command *command)
' ');
DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
- error= my_delete(ds_filename.str, MYF(0)) != 0;
- handle_command_error(command, error);
+ error= my_delete_allow_opened(ds_filename.str, MYF(disable_warnings ? 0 : MY_WME)) != 0;
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_filename);
DBUG_VOID_RETURN;
}
@@ -3289,8 +3601,9 @@ void do_remove_file(struct st_command *command)
void do_remove_files_wildcard(struct st_command *command)
{
- int error= 0;
+ int error= 0, sys_errno= 0;
uint i;
+ size_t directory_length;
MY_DIR *dir_info;
FILEINFO *file;
char dir_separator[2];
@@ -3313,15 +3626,16 @@ void do_remove_files_wildcard(struct st_command *command)
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))))
+ if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT | MY_WME))))
{
error= 1;
+ sys_errno= my_errno;
goto end;
}
init_dynamic_string(&ds_file_to_remove, dirname, 1024, 1024);
dir_separator[0]= FN_LIBCHAR;
- dir_separator[1]= 0;
- dynstr_append(&ds_file_to_remove, dir_separator);
+ dynstr_append_mem(&ds_file_to_remove, dir_separator, 1);
+ directory_length= ds_file_to_remove.length;
/* Set default wild chars for wild_compare, is changed in embedded mode */
set_wild_chars(1);
@@ -3337,11 +3651,11 @@ void do_remove_files_wildcard(struct st_command *command)
if (ds_wild.length &&
wild_compare(file->name, ds_wild.str, 0))
continue;
- ds_file_to_remove.length= ds_directory.length + 1;
- ds_file_to_remove.str[ds_directory.length + 1]= 0;
+ ds_file_to_remove.length= directory_length;
dynstr_append(&ds_file_to_remove, file->name);
DBUG_PRINT("info", ("removing file: %s", ds_file_to_remove.str));
- error= my_delete(ds_file_to_remove.str, MYF(0)) != 0;
+ if ((error= (my_delete(ds_file_to_remove.str, MYF(MY_WME)) != 0)))
+ sys_errno= my_errno;
if (error)
break;
}
@@ -3349,7 +3663,7 @@ void do_remove_files_wildcard(struct st_command *command)
my_dirend(dir_info);
end:
- handle_command_error(command, error);
+ handle_command_error(command, error, sys_errno);
dynstr_free(&ds_directory);
dynstr_free(&ds_wild);
dynstr_free(&ds_file_to_remove);
@@ -3388,8 +3702,8 @@ void do_copy_file(struct st_command *command)
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,
- MYF(MY_DONT_OVERWRITE_FILE | MY_HOLD_ORIGINAL_MODES)) != 0);
- handle_command_error(command, error);
+ MYF(MY_DONT_OVERWRITE_FILE | MY_WME | MY_HOLD_ORIGINAL_MODES)) != 0);
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_from_file);
dynstr_free(&ds_to_file);
DBUG_VOID_RETURN;
@@ -3424,8 +3738,8 @@ void do_move_file(struct st_command *command)
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(0)) != 0);
- handle_command_error(command, error);
+ MYF(disable_warnings ? 0 : MY_WME)) != 0);
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_from_file);
dynstr_free(&ds_to_file);
DBUG_VOID_RETURN;
@@ -3469,7 +3783,7 @@ void do_chmod_file(struct st_command *command)
err_code= chmod(ds_file.str, mode);
if (err_code < 0)
err_code= 1;
- handle_command_error(command, err_code);
+ handle_command_error(command, err_code, errno);
dynstr_free(&ds_mode);
dynstr_free(&ds_file);
DBUG_VOID_RETURN;
@@ -3502,7 +3816,7 @@ void do_file_exist(struct st_command *command)
DBUG_PRINT("info", ("Checking for existence of file: %s", ds_filename.str));
error= (access(ds_filename.str, F_OK) != 0);
- handle_command_error(command, error);
+ handle_command_error(command, error, errno);
dynstr_free(&ds_filename);
DBUG_VOID_RETURN;
}
@@ -3532,8 +3846,8 @@ void do_mkdir(struct st_command *command)
' ');
DBUG_PRINT("info", ("creating directory: %s", ds_dirname.str));
- error= my_mkdir(ds_dirname.str, 0777, MYF(0)) != 0;
- handle_command_error(command, error);
+ error= my_mkdir(ds_dirname.str, 0777, MYF(MY_WME)) != 0;
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_dirname);
DBUG_VOID_RETURN;
}
@@ -3553,7 +3867,7 @@ 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"}
+ { "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove" }
};
DBUG_ENTER("do_rmdir");
@@ -3563,7 +3877,7 @@ void do_rmdir(struct st_command *command)
DBUG_PRINT("info", ("removing directory: %s", ds_dirname.str));
error= rmdir(ds_dirname.str) != 0;
- handle_command_error(command, error);
+ handle_command_error(command, error, errno);
dynstr_free(&ds_dirname);
DBUG_VOID_RETURN;
}
@@ -3640,7 +3954,7 @@ static void do_list_files(struct st_command *command)
sizeof(list_files_args)/sizeof(struct command_arg), ' ');
error= get_list_files(&ds_res, &ds_dirname, &ds_wild);
- handle_command_error(command, error);
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_dirname);
dynstr_free(&ds_wild);
DBUG_VOID_RETURN;
@@ -3683,7 +3997,7 @@ static void do_list_files_write_file_command(struct st_command *command,
init_dynamic_string(&ds_content, "", 1024, 1024);
error= get_list_files(&ds_content, &ds_dirname, &ds_wild);
- handle_command_error(command, error);
+ handle_command_error(command, error, my_errno);
str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
dynstr_free(&ds_content);
dynstr_free(&ds_filename);
@@ -3747,12 +4061,12 @@ void read_until_delimiter(DYNAMIC_STRING *ds,
No characters except \n are allowed on
the same line as the command
*/
- die("Trailing characters found after command");
+ report_or_die("Trailing characters found after command");
}
if (feof(cur_file->file))
- die("End of file encountered before '%s' delimiter was found",
- ds_delimiter->str);
+ report_or_die("End of file encountered before '%s' delimiter was found",
+ ds_delimiter->str);
if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
{
@@ -3907,7 +4221,7 @@ void do_cat_file(struct st_command *command)
DBUG_PRINT("info", ("Reading from, file: %s", ds_filename.str));
error= cat_file(&ds_res, ds_filename.str);
- handle_command_error(command, error);
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_filename);
DBUG_VOID_RETURN;
}
@@ -3953,9 +4267,10 @@ void do_diff_files(struct st_command *command)
if ((error= compare_files(ds_filename.str, ds_filename2.str)) &&
match_expected_error(command, error, NULL) < 0)
{
- /* Compare of the two files failed, append them to output
- so the failure can be analyzed, but only if it was not
- expected to fail.
+ /*
+ Compare of the two files failed, append them to output
+ so the failure can be analyzed, but only if it was not
+ expected to fail.
*/
show_diff(&ds_res, ds_filename.str, ds_filename2.str);
log_file.write(&ds_res);
@@ -3965,7 +4280,7 @@ void do_diff_files(struct st_command *command)
dynstr_free(&ds_filename);
dynstr_free(&ds_filename2);
- handle_command_error(command, error);
+ handle_command_error(command, error, -1);
DBUG_VOID_RETURN;
}
@@ -4015,7 +4330,7 @@ void do_send_quit(struct st_command *command)
if (!(con= find_connection_by_name(name)))
die("connection '%s' not found in connection pool", name);
- simple_command(&con->mysql,COM_QUIT,0,0,1);
+ simple_command(con->mysql,COM_QUIT,0,0,1);
DBUG_VOID_RETURN;
}
@@ -4039,7 +4354,8 @@ void do_send_quit(struct st_command *command)
void do_change_user(struct st_command *command)
{
- MYSQL *mysql = &cur_con->mysql;
+ MYSQL *mysql = cur_con->mysql;
+ /* static keyword to make the NetWare compiler happy. */
static DYNAMIC_STRING ds_user, ds_passwd, ds_db;
const struct command_arg change_user_args[] = {
{ "user", ARG_STRING, FALSE, &ds_user, "User to connect as" },
@@ -4154,8 +4470,13 @@ void do_perl(struct st_command *command)
/* Format the "perl <filename>" command */
my_snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
- if (!(res_file= popen(buf, "r")) && command->abort_on_error)
- die("popen(\"%s\", \"r\") failed", buf);
+ if (!(res_file= popen(buf, "r")))
+ {
+ if (command->abort_on_error)
+ die("popen(\"%s\", \"r\") failed", buf);
+ dynstr_free(&ds_delimiter);
+ return;
+ }
while (fgets(buf, sizeof(buf), res_file))
{
@@ -4173,7 +4494,7 @@ void do_perl(struct st_command *command)
/* Remove the temporary file, but keep it if perl failed */
if (!error)
- my_delete(temp_file_path, MYF(0));
+ my_delete(temp_file_path, MYF(MY_WME));
/* Check for error code that indicates perl could not be started */
int exstat= WEXITSTATUS(error);
@@ -4186,7 +4507,7 @@ void do_perl(struct st_command *command)
abort_not_supported_test("perl not found in path");
#endif
else
- handle_command_error(command, exstat);
+ handle_command_error(command, exstat, my_errno);
}
dynstr_free(&ds_delimiter);
DBUG_VOID_RETURN;
@@ -4235,7 +4556,7 @@ int do_echo(struct st_command *command)
void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
{
static int SLAVE_POLL_INTERVAL= 300000;
- MYSQL* mysql = &cur_con->mysql;
+ MYSQL* mysql = cur_con->mysql;
for (;;)
{
MYSQL_RES *UNINIT_VAR(res);
@@ -4265,7 +4586,7 @@ void do_sync_with_master2(struct st_command *command, long offset)
{
MYSQL_RES *res;
MYSQL_ROW row;
- MYSQL *mysql= &cur_con->mysql;
+ MYSQL *mysql= cur_con->mysql;
char query_buf[FN_REFLEN+128];
int timeout= 300; /* seconds */
@@ -4310,14 +4631,14 @@ void do_sync_with_master2(struct st_command *command, long offset)
information is not initialized, the arguments are
incorrect, or an error has occured
*/
- die("%.*s failed: '%s' returned NULL "\
+ die("%.*s failed: '%s' returned NULL " \
"indicating slave SQL thread failure",
command->first_word_len, command->query, query_buf);
}
if (result == -1)
- die("%.*s failed: '%s' returned -1 "\
+ die("%.*s failed: '%s' returned -1 " \
"indicating timeout after %d seconds",
command->first_word_len, command->query, query_buf, timeout);
else
@@ -4355,7 +4676,7 @@ int do_save_master_pos()
{
MYSQL_RES *res;
MYSQL_ROW row;
- MYSQL *mysql = &cur_con->mysql;
+ MYSQL *mysql = cur_con->mysql;
const char *query;
DBUG_ENTER("do_save_master_pos");
@@ -4612,7 +4933,8 @@ int do_sleep(struct st_command *command, my_bool real_sleep)
while (my_isspace(charset_info, *p))
p++;
if (!*p)
- die("Missing argument to %.*s", command->first_word_len, command->query);
+ die("Missing argument to %.*s", command->first_word_len,
+ command->query);
sleep_start= p;
/* Check that arg starts with a digit, not handled by my_strtod */
if (!my_isdigit(charset_info, *sleep_start))
@@ -4684,16 +5006,21 @@ int query_get_string(MYSQL* mysql, const char* query,
MYSQL_ROW row;
if (mysql_query(mysql, query))
- die("'%s' failed: %d %s", query,
- mysql_errno(mysql), mysql_error(mysql));
+ {
+ report_or_die("'%s' failed: %d %s", query,
+ mysql_errno(mysql), mysql_error(mysql));
+ return 1;
+ }
if ((res= mysql_store_result(mysql)) == NULL)
- die("Failed to store result: %d %s",
- mysql_errno(mysql), mysql_error(mysql));
+ {
+ report_or_die("Failed to store result: %d %s",
+ mysql_errno(mysql), mysql_error(mysql));
+ return 1;
+ }
if ((row= mysql_fetch_row(res)) == NULL)
{
mysql_free_result(res);
- ds= 0;
return 1;
}
init_dynamic_string(ds, (row[column] ? row[column] : "NULL"), ~0, 32);
@@ -4743,7 +5070,7 @@ void do_shutdown_server(struct st_command *command)
long timeout=60;
int pid;
DYNAMIC_STRING ds_pidfile_name;
- MYSQL* mysql = &cur_con->mysql;
+ MYSQL* mysql = cur_con->mysql;
static DYNAMIC_STRING ds_timeout;
const struct command_arg shutdown_args[] = {
{"timeout", ARG_STRING, FALSE, &ds_timeout, "Timeout before killing server"}
@@ -4880,15 +5207,32 @@ const char *get_errname_from_code (uint error_code)
void do_get_errcodes(struct st_command *command)
{
struct st_match_err *to= saved_expected_errors.err;
- char *p= command->first_argument;
- uint count= 0;
- char *next;
-
DBUG_ENTER("do_get_errcodes");
- if (!*p)
+ if (!*command->first_argument)
die("Missing argument(s) to 'error'");
+ /* TODO: Potentially, there is a possibility of variables
+ being expanded twice, e.g.
+
+ let $errcodes = 1,\$a;
+ let $a = 1051;
+ error $errcodes;
+ DROP TABLE unknown_table;
+ ...
+ Got one of the listed errors
+
+ But since it requires manual escaping, it does not seem
+ particularly dangerous or error-prone.
+ */
+ DYNAMIC_STRING ds;
+ init_dynamic_string(&ds, 0, command->query_len + 64, 256);
+ do_eval(&ds, command->first_argument, command->end, !is_windows);
+ char *p= ds.str;
+
+ uint count= 0;
+ char *next;
+
do
{
char *end;
@@ -4965,7 +5309,7 @@ void do_get_errcodes(struct st_command *command)
while (*p && p != end)
{
if (!my_isdigit(charset_info, *p))
- die("Invalid argument to error: '%s' - "\
+ die("Invalid argument to error: '%s' - " \
"the errno may only consist of digits[0-9]",
command->first_argument);
p++;
@@ -4998,11 +5342,15 @@ void do_get_errcodes(struct st_command *command)
} while (*p);
- command->last_argument= p;
+ command->last_argument= command->first_argument;
+ while (*command->last_argument)
+ command->last_argument++;
+
to->type= ERR_EMPTY; /* End of data */
DBUG_PRINT("info", ("Expected errors: %d", count));
saved_expected_errors.count= count;
+ dynstr_free(&ds);
DBUG_VOID_RETURN;
}
@@ -5087,11 +5435,11 @@ char *get_string(char **to_ptr, char **from_ptr,
}
-void set_reconnect(MYSQL* mysql, int val)
+void set_reconnect(MYSQL* mysql, my_bool val)
{
my_bool reconnect= val;
DBUG_ENTER("set_reconnect");
- DBUG_PRINT("info", ("val: %d", val));
+ DBUG_PRINT("info", ("val: %d", (int) val));
#if MYSQL_VERSION_ID < 50000
mysql->reconnect= reconnect;
#else
@@ -5110,7 +5458,7 @@ void set_current_connection(struct st_connection *con)
cur_con= con;
/* Update $mysql_get_server_version to that of current connection */
var_set_int("$mysql_get_server_version",
- mysql_get_server_version(&con->mysql));
+ mysql_get_server_version(con->mysql));
/* Update $CURRENT_CONNECTION to the name of the current connection */
var_set_string("$CURRENT_CONNECTION", con->name);
}
@@ -5161,7 +5509,7 @@ void select_connection(struct st_command *command)
void do_close_connection(struct st_command *command)
{
- DBUG_ENTER("close_connection");
+ DBUG_ENTER("do_close_connection");
struct st_connection *con;
static DYNAMIC_STRING ds_connection;
@@ -5183,10 +5531,10 @@ void do_close_connection(struct st_command *command)
#ifndef EMBEDDED_LIBRARY
if (command->type == Q_DIRTY_CLOSE)
{
- if (con->mysql.net.vio)
+ if (con->mysql->net.vio)
{
- vio_delete(con->mysql.net.vio);
- con->mysql.net.vio = 0;
+ vio_delete(con->mysql->net.vio);
+ con->mysql->net.vio = 0;
}
}
#else
@@ -5201,7 +5549,8 @@ void do_close_connection(struct st_command *command)
mysql_stmt_close(con->stmt);
con->stmt= 0;
- mysql_close(&con->mysql);
+ mysql_close(con->mysql);
+ con->mysql= 0;
if (con->util_mysql)
mysql_close(con->util_mysql);
@@ -5456,7 +5805,8 @@ void do_connect(struct st_command *command)
int con_port= opt_port;
char *con_options;
my_bool con_ssl= 0, con_compress= 0;
- my_bool con_pipe= 0, con_shm= 0, con_cleartext_enable= 0;
+ my_bool con_pipe= 0;
+ my_bool con_shm __attribute__ ((unused))= 0;
struct st_connection* con_slot;
static DYNAMIC_STRING ds_connection_name;
@@ -5530,7 +5880,8 @@ void do_connect(struct st_command *command)
con_options= ds_options.str;
while (*con_options)
{
- char* end;
+ size_t length;
+ char *end;
/* Step past any spaces in beginning of option*/
while (*con_options && my_isspace(charset_info, *con_options))
con_options++;
@@ -5538,16 +5889,15 @@ void do_connect(struct st_command *command)
end= con_options;
while (*end && !my_isspace(charset_info, *end))
end++;
- if (!strncmp(con_options, "SSL", 3))
+ length= (size_t) (end - con_options);
+ if (length == 3 && !strncmp(con_options, "SSL", 3))
con_ssl= 1;
- else if (!strncmp(con_options, "COMPRESS", 8))
+ else if (length == 8 && !strncmp(con_options, "COMPRESS", 8))
con_compress= 1;
- else if (!strncmp(con_options, "PIPE", 4))
+ else if (length == 4 && !strncmp(con_options, "PIPE", 4))
con_pipe= 1;
- else if (!strncmp(con_options, "SHM", 3))
+ else if (length == 3 && !strncmp(con_options, "SHM", 3))
con_shm= 1;
- else if (!strncmp(con_options, "CLEARTEXT", 9))
- con_cleartext_enable= 1;
else
die("Illegal option to connect: %.*s",
(int) (end - con_options), con_options);
@@ -5565,28 +5915,28 @@ void do_connect(struct st_command *command)
if (!(con_slot= find_connection_by_name("-closed_connection-")))
die("Connection limit exhausted, you can have max %d connections",
opt_max_connections);
+ my_free(con_slot->name);
+ con_slot->name= 0;
}
-#ifdef EMBEDDED_LIBRARY
init_connection_thd(con_slot);
-#endif /*EMBEDDED_LIBRARY*/
- if (!mysql_init(&con_slot->mysql))
+ if (!(con_slot->mysql= mysql_init(0)))
die("Failed on mysql_init()");
if (opt_connect_timeout)
- mysql_options(&con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
+ mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
(void *) &opt_connect_timeout);
+ mysql_options(con_slot->mysql, MYSQL_OPT_NONBLOCK, 0);
if (opt_compress || con_compress)
- mysql_options(&con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
- mysql_options(&con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
- mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_NAME,
+ mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
+ mysql_options(con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
+ mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_NAME,
charset_info->csname);
if (opt_charsets_dir)
- mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_DIR,
+ mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_DIR,
opt_charsets_dir);
-
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
if (opt_use_ssl)
con_ssl= 1;
@@ -5595,12 +5945,12 @@ void do_connect(struct st_command *command)
if (con_ssl)
{
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
- mysql_ssl_set(&con_slot->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
+ mysql_ssl_set(con_slot->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
#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");
- mysql_options(&con_slot->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ mysql_options(con_slot->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
&opt_ssl_verify_server_cert);
#endif
#endif
@@ -5614,22 +5964,20 @@ void do_connect(struct st_command *command)
}
if (opt_protocol)
- mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
+ mysql_options(con_slot->mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
+#ifdef HAVE_SMEM
if (con_shm)
{
-#ifdef HAVE_SMEM
uint protocol= MYSQL_PROTOCOL_MEMORY;
if (!ds_shm.length)
die("Missing shared memory base name");
- mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, ds_shm.str);
- mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, &protocol);
-#endif
+ mysql_options(con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, ds_shm.str);
+ mysql_options(con_slot->mysql, MYSQL_OPT_PROTOCOL, &protocol);
}
-#ifdef HAVE_SMEM
else if (shared_memory_base_name)
{
- mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
+ mysql_options(con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
shared_memory_base_name);
}
#endif
@@ -5639,20 +5987,16 @@ void do_connect(struct st_command *command)
dynstr_set(&ds_database, opt_db);
if (opt_plugin_dir && *opt_plugin_dir)
- mysql_options(&con_slot->mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+ mysql_options(con_slot->mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
if (ds_default_auth.length)
- mysql_options(&con_slot->mysql, MYSQL_DEFAULT_AUTH, ds_default_auth.str);
-
+ mysql_options(con_slot->mysql, MYSQL_DEFAULT_AUTH, ds_default_auth.str);
- if (con_cleartext_enable)
- mysql_options(&con_slot->mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
- (char*) &con_cleartext_enable);
/* Special database to allow one to connect without a database name */
if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
dynstr_set(&ds_database, "");
- if (connect_n_handle_errors(command, &con_slot->mysql,
+ if (connect_n_handle_errors(command, con_slot->mysql,
ds_host.str,ds_user.str,
ds_password.str, ds_database.str,
con_port, ds_sock.str))
@@ -5892,7 +6236,7 @@ void do_block(enum block_cmd cmd, struct st_command* command)
eval_expr(&v2, curr_ptr, &expr_end);
if ((operand!=EQ_OP && operand!=NE_OP) && ! (v.is_int && v2.is_int))
- die ("Only == and != are supported for string values");
+ die("Only == and != are supported for string values");
/* Now we overwrite the first variable with 0 or 1 (for false or true) */
@@ -6250,7 +6594,7 @@ int read_line(char *buf, int size)
*p++= c;
}
}
- die("The input buffer is too small for this query.x\n" \
+ die("The input buffer is too small for this query.x\n" \
"check your query or increase MAX_QUERY and recompile");
DBUG_RETURN(0);
}
@@ -6477,13 +6821,19 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0, 0},
{"basedir", 'b', "Basedir for tests.", &opt_basedir,
&opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"character-sets-dir", OPT_CHARSETS_DIR,
+ {"character-sets-dir", 0,
"Directory for character set files.", &opt_charsets_dir,
&opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"compress", 'C', "Use the compressed server/client protocol.",
&opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
- {"cursor-protocol", OPT_CURSOR_PROTOCOL, "Use cursors for prepared statements.",
+ {"continue-on-error", 0,
+ "Continue test even if we got an error. "
+ "This is mostly useful when testing a storage engine to see what from a test file it can execute, "
+ "or to find all syntax errors in a newly created big test file",
+ &opt_continue_on_error, &opt_continue_on_error, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"cursor-protocol", 0, "Use cursors for prepared statements.",
&cursor_protocol, &cursor_protocol, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"database", 'D', "Database to use.", &opt_db, &opt_db, 0,
@@ -6495,30 +6845,30 @@ static struct my_option my_long_options[] =
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
0, 0, 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", 0, "Check memory and open file usage at exit.",
&debug_check_flag, &debug_check_flag, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
+ {"debug-info", 0, "Print some debug info at exit.",
&debug_info_flag, &debug_info_flag,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host.", &opt_host, &opt_host, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"include", 'i', "Include SQL before each test case.", &opt_include,
- &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"prologue", 0, "Include SQL before each test case.", &opt_prologue,
+ &opt_prologue, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"logdir", OPT_LOG_DIR, "Directory for log files", &opt_logdir,
&opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"mark-progress", OPT_MARK_PROGRESS,
+ {"mark-progress", 0,
"Write line number and elapsed time to <testname>.progress.",
&opt_mark_progress, &opt_mark_progress, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
+ {"max-connect-retries", 0,
"Maximum number of attempts to connect to server.",
&opt_max_connect_retries, &opt_max_connect_retries, 0,
GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
- {"max-connections", OPT_MAX_CONNECTIONS,
+ {"max-connections", 0,
"Max number of open connections to server",
&opt_max_connections, &opt_max_connections, 0,
- GET_INT, REQUIRED_ARG, 128, 8, 5120, 0, 0, 0},
+ GET_INT, REQUIRED_ARG, DEFAULT_MAX_CONN, 8, 5120, 0, 0, 0},
{"password", 'p', "Password to use when connecting to server.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
@@ -6530,10 +6880,14 @@ static struct my_option my_long_options[] =
#endif
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
&opt_port, &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"ps-protocol", OPT_PS_PROTOCOL,
+ {"ps-protocol", 0,
"Use prepared-statement protocol for communication.",
&ps_protocol, &ps_protocol, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"non-blocking-api", 0,
+ "Use the non-blocking client API for communication.",
+ &non_blocking_api_enabled, &non_blocking_api_enabled, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"quiet", 's', "Suppress all normal output.", &silent,
&silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"record", 'r', "Record output of test_file into result file.",
@@ -6550,7 +6904,7 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-file", 'F', "Read embedded server arguments from file.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
+ {"shared-memory-base-name", 0,
"Base name of shared memory.", &shared_memory_base_name,
&shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
0, 0, 0},
@@ -6562,11 +6916,11 @@ static struct my_option my_long_options[] =
{"socket", 'S', "The socket file to use for connection.",
&unix_sock, &unix_sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
0, 0, 0},
- {"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select.",
+ {"sp-protocol", 0, "Use stored procedures for select.",
&sp_protocol, &sp_protocol, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#include "sslopt-longopts.h"
- {"tail-lines", OPT_TAIL_LINES,
+ {"tail-lines", 0,
"Number of lines of the result to include in a failure report.",
&opt_tail_lines, &opt_tail_lines, 0,
GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
@@ -6582,16 +6936,20 @@ static struct my_option my_long_options[] =
GET_BOOL, 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},
- {"view-protocol", OPT_VIEW_PROTOCOL, "Use views for select.",
+ {"view-protocol", 0, "Use views for select.",
&view_protocol, &view_protocol, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"connect_timeout", OPT_CONNECT_TIMEOUT,
+ {"connect_timeout", 0,
"Number of seconds before connection timeout.",
&opt_connect_timeout, &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG,
120, 0, 3600 * 12, 0, 0, 0},
- {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ {"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},
+ {"overlay-dir", 0, "Overlay directory.", &opt_overlay_dir,
+ &opt_overlay_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"suite-dir", 0, "Suite directory.", &opt_suite_dir,
+ &opt_suite_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -6668,6 +7026,7 @@ get_one_option(int optid, const struct my_option *opt, char *argument)
#ifndef DBUG_OFF
DBUG_PUSH(argument ? argument : "d:t:S:i:O,/tmp/mysqltest.trace");
debug_check_flag= 1;
+ debug_info_flag= 1;
#endif
break;
case 'r':
@@ -6783,14 +7142,29 @@ int parse_args(int argc, char **argv)
if (debug_info_flag)
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
if (debug_check_flag)
- my_end_arg= MY_CHECK_ERROR;
+ my_end_arg|= MY_CHECK_ERROR;
+
+ if (global_subst != NULL)
+ {
+ char *comma= strstr(global_subst, ",");
+ if (comma == NULL)
+ die("wrong --global-subst, must be X,Y");
+ memcpy(global_subst_from, global_subst, (comma-global_subst));
+ global_subst_from[comma-global_subst]= 0;
+ memcpy(global_subst_to, comma+1, strlen(comma));
+ }
+ if (!opt_suite_dir)
+ opt_suite_dir= "./";
+ suite_dir_len= strlen(opt_suite_dir);
+ overlay_dir_len= opt_overlay_dir ? strlen(opt_overlay_dir) : 0;
if (!record)
{
/* Check that the result file exists */
if (result_file_name && access(result_file_name, F_OK) != 0)
- die("The specified result file '%s' does not exist", result_file_name);
+ die("The specified result file '%s' does not exist",
+ result_file_name);
}
return 0;
@@ -7079,6 +7453,7 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
my_bool *is_null;
ulong *length;
uint i;
+ int error;
/* Allocate array with bind structs, lengths and NULL flags */
my_bind= (MYSQL_BIND*) my_malloc(num_fields * sizeof(MYSQL_BIND),
@@ -7106,7 +7481,7 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
die("mysql_stmt_bind_result failed: %d: %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
- while (mysql_stmt_fetch(stmt) == 0)
+ while ((error=mysql_stmt_fetch(stmt)) == 0)
{
for (i= 0; i < num_fields; i++)
append_field(ds, i, &fields[i], (char*)my_bind[i].buffer,
@@ -7115,8 +7490,11 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
dynstr_append_mem(ds, "\n", 1);
}
+ if (error != MYSQL_NO_DATA)
+ die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: "
+ "error: %d", error);
if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
- die("fetch didn't end with MYSQL_NO_DATA from statement: %d %s",
+ die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: %d %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
for (i= 0; i < num_fields; i++)
@@ -7211,6 +7589,8 @@ void append_table_headings(DYNAMIC_STRING *ds,
uint num_fields)
{
uint col_idx;
+ if (disable_column_names)
+ return;
for (col_idx= 0; col_idx < num_fields; col_idx++)
{
if (col_idx)
@@ -7260,6 +7640,22 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
/*
+ Handle situation where query is sent but there is no active connection
+ (e.g directly after disconnect).
+
+ We emulate MySQL-compatible behaviour of sending something on a closed
+ connection.
+*/
+static void handle_no_active_connection(struct st_command *command,
+ struct st_connection *cn, DYNAMIC_STRING *ds)
+{
+ handle_error(command, 2006, "MySQL server has gone away", "000000", ds);
+ cn->pending= FALSE;
+ var_set_errno(2006);
+}
+
+
+/*
Run query using MySQL C API
SYNOPSIS
@@ -7277,12 +7673,18 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
{
MYSQL_RES *res= 0;
- MYSQL *mysql= &cn->mysql;
+ MYSQL *mysql= cn->mysql;
int err= 0, counter= 0;
DBUG_ENTER("run_query_normal");
DBUG_PRINT("enter",("flags: %d", flags));
DBUG_PRINT("enter", ("query: '%-.60s'", query));
+ if (!mysql)
+ {
+ handle_no_active_connection(command, cn, ds);
+ DBUG_VOID_RETURN;
+ }
+
if (flags & QUERY_SEND_FLAG)
{
/*
@@ -7436,7 +7838,8 @@ static int match_expected_error(struct st_command *command,
NULL is quite likely, but not in conjunction with a SQL-state expect!
*/
if (unlikely(err_sqlstate == NULL))
- die("expecting a SQL-state (%s) from query '%s' which cannot produce one...",
+ die("expecting a SQL-state (%s) from query '%s' which cannot "
+ "produce one...",
command->expected_errors.err[i].code.sqlstate, command->query);
if (strncmp(command->expected_errors.err[i].code.sqlstate,
@@ -7472,7 +7875,7 @@ void handle_error(struct st_command *command,
DBUG_ENTER("handle_error");
- if (command->require_file[0])
+ if (command->require_file)
{
/*
The query after a "--require" failed. This is fine as long the server
@@ -7490,7 +7893,11 @@ void handle_error(struct st_command *command,
}
if (command->abort_on_error)
- die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
+ {
+ report_or_die("query '%s' failed: %d: %s", command->query, err_errno,
+ err_error);
+ DBUG_VOID_RETURN;
+ }
DBUG_PRINT("info", ("expected_errors.count: %d",
command->expected_errors.count));
@@ -7536,13 +7943,15 @@ void handle_error(struct st_command *command,
if (command->expected_errors.count > 0)
{
if (command->expected_errors.err[0].type == ERR_ERRNO)
- die("query '%s' failed with wrong errno %d: '%s', instead of %d...",
- command->query, err_errno, err_error,
- command->expected_errors.err[0].code.errnum);
+ report_or_die("query '%s' failed with wrong errno %d: '%s', instead of "
+ "%d...",
+ command->query, err_errno, err_error,
+ command->expected_errors.err[0].code.errnum);
else
- die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
- command->query, err_sqlstate, err_error,
- command->expected_errors.err[0].code.sqlstate);
+ report_or_die("query '%s' failed with wrong sqlstate %s: '%s', "
+ "instead of %s...",
+ command->query, err_sqlstate, err_error,
+ command->expected_errors.err[0].code.sqlstate);
}
revert_properties();
@@ -7569,15 +7978,17 @@ void handle_no_error(struct st_command *command)
command->expected_errors.err[0].code.errnum != 0)
{
/* Error code we wanted was != 0, i.e. not an expected success */
- die("query '%s' succeeded - should have failed with errno %d...",
- command->query, command->expected_errors.err[0].code.errnum);
+ report_or_die("query '%s' succeeded - should have failed with errno %d...",
+ command->query, command->expected_errors.err[0].code.errnum);
}
else if (command->expected_errors.err[0].type == ERR_SQLSTATE &&
strcmp(command->expected_errors.err[0].code.sqlstate,"00000") != 0)
{
/* SQLSTATE we wanted was != "00000", i.e. not an expected success */
- die("query '%s' succeeded - should have failed with sqlstate %s...",
- command->query, command->expected_errors.err[0].code.sqlstate);
+ report_or_die("query '%s' succeeded - should have failed with "
+ "sqlstate %s...",
+ command->query,
+ command->expected_errors.err[0].code.sqlstate);
}
DBUG_VOID_RETURN;
}
@@ -7729,10 +8140,15 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
mysql_free_result(res); /* Free normal result set with meta data */
/*
- Clear prepare warnings if there are execute warnings,
- since they are probably duplicated.
+ Normally, if there is a result set, we do not show warnings from the
+ prepare phase. This is because some warnings are generated both during
+ prepare and execute; this would generate different warning output
+ between normal and ps-protocol test runs.
+
+ The --enable_prepare_warnings command can be used to change this so
+ that warnings from both the prepare and execute phase are shown.
*/
- if (ds_execute_warnings.length || mysql->warning_count)
+ if (!disable_warnings && !prepare_warnings_enabled)
dynstr_set(&ds_prepare_warnings, NULL);
}
else
@@ -7746,7 +8162,6 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
Fetch info before fetching warnings, since it will be reset
otherwise.
*/
-
if (!disable_info)
append_info(ds, mysql_stmt_affected_rows(stmt), mysql_info(mysql));
@@ -7780,14 +8195,6 @@ end:
dynstr_free(&ds_prepare_warnings);
dynstr_free(&ds_execute_warnings);
}
- revert_properties();
-
- /* Close the statement if - no reconnect, need new prepare */
- if (mysql->reconnect)
- {
- mysql_stmt_close(stmt);
- cur_con->stmt= NULL;
- }
/*
We save the return code (mysql_stmt_errno(stmt)) from the last call sent
@@ -7797,6 +8204,15 @@ end:
var_set_errno(mysql_stmt_errno(stmt));
+ revert_properties();
+
+ /* Close the statement if reconnect, need new prepare */
+ if (mysql->reconnect)
+ {
+ mysql_stmt_close(stmt);
+ cur_con->stmt= NULL;
+ }
+
DBUG_VOID_RETURN;
}
@@ -7826,6 +8242,7 @@ int util_query(MYSQL* org_mysql, const char* query){
/* enable local infile, in non-binary builds often disabled by default */
mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, 0);
+ mysql_options(mysql, MYSQL_OPT_NONBLOCK, 0);
safe_connect(mysql, "util", org_mysql->host, org_mysql->user,
org_mysql->passwd, org_mysql->db, org_mysql->port,
org_mysql->unix_socket);
@@ -7833,7 +8250,8 @@ int util_query(MYSQL* org_mysql, const char* query){
cur_con->util_mysql= mysql;
}
- DBUG_RETURN(mysql_query(mysql, query));
+ int ret= mysql_query(mysql, query);
+ DBUG_RETURN(ret);
}
@@ -7853,7 +8271,7 @@ int util_query(MYSQL* org_mysql, const char* query){
void run_query(struct st_connection *cn, struct st_command *command, int flags)
{
- MYSQL *mysql= &cn->mysql;
+ MYSQL *mysql= cn->mysql;
DYNAMIC_STRING *ds;
DYNAMIC_STRING *save_ds= NULL;
DYNAMIC_STRING ds_result;
@@ -7868,10 +8286,10 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
DBUG_ENTER("run_query");
if (cn->pending && (flags & QUERY_SEND_FLAG))
- die ("Cannot run query on connection between send and reap");
+ die("Cannot run query on connection between send and reap");
if (!(flags & QUERY_SEND_FLAG) && !cn->pending)
- die ("Cannot reap on a connection without pending send");
+ die("Cannot reap on a connection without pending send");
init_dynamic_string(&ds_warnings, NULL, 0, 256);
ds_warn= &ds_warnings;
@@ -7898,7 +8316,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
Create a temporary dynamic string to contain the output from
this query.
*/
- if (command->require_file[0])
+ if (command->require_file)
{
init_dynamic_string(&ds_result, "", 1024, 1024);
ds= &ds_result;
@@ -7916,6 +8334,15 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
dynstr_append_mem(ds, "\n", 1);
}
+ /*
+ Write the command to the result file before we execute the query
+ This is needed to be able to analyse the log if something goes
+ wrong
+ */
+ log_file.write(&ds_res);
+ log_file.flush();
+ dynstr_set(&ds_res, 0);
+
if (view_protocol_enabled &&
complete_query &&
match_re(&view_re, query))
@@ -7960,7 +8387,6 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
}
dynstr_free(&query_str);
-
}
if (sp_protocol_enabled &&
@@ -8040,7 +8466,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
if (display_result_sorted)
{
/* Sort the result set and append it to result */
- dynstr_append_sorted(save_ds, &ds_sorted);
+ dynstr_append_sorted(save_ds, &ds_sorted, 1);
ds= save_ds;
dynstr_free(&ds_sorted);
}
@@ -8048,17 +8474,18 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
if (sp_created)
{
if (util_query(mysql, "DROP PROCEDURE mysqltest_tmp_sp "))
- die("Failed to drop sp: %d: %s", mysql_errno(mysql), mysql_error(mysql));
+ report_or_die("Failed to drop sp: %d: %s", mysql_errno(mysql),
+ mysql_error(mysql));
}
if (view_created)
{
if (util_query(mysql, "DROP VIEW mysqltest_tmp_v "))
- die("Failed to drop view: %d: %s",
+ report_or_die("Failed to drop view: %d: %s",
mysql_errno(mysql), mysql_error(mysql));
}
- if (command->require_file[0])
+ if (command->require_file)
{
/* A result file was specified for _this_ query
and the output should be checked against an already
@@ -8080,8 +8507,8 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
char *re_eprint(int err)
{
static char epbuf[100];
- size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL,
- epbuf, sizeof(epbuf));
+ size_t len __attribute__((unused))=
+ my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf));
assert(len <= sizeof(epbuf));
return(epbuf);
}
@@ -8218,9 +8645,10 @@ void get_command_type(struct st_command* command)
else
{
/* -- "comment" that didn't contain a mysqltest command */
- die("Found line beginning with -- that didn't contain "\
- "a valid mysqltest command, check your syntax or "\
+ report_or_die("Found line beginning with -- that didn't contain " \
+ "a valid mysqltest command, check your syntax or " \
"use # if you intended to write a comment");
+ command->type= Q_COMMENT;
}
}
@@ -8256,7 +8684,7 @@ void mark_progress(struct st_command* command __attribute__((unused)),
die("Out of memory");
/* Milliseconds since start */
- end= longlong2str(timer, buf, 10);
+ end= longlong10_to_str(timer, buf, 10);
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
dynstr_append_mem(&ds_progress, "\t", 1);
@@ -8290,14 +8718,17 @@ static void dump_backtrace(void)
fprintf(stderr, "read_command_buf (%p): ", read_command_buf);
my_safe_print_str(read_command_buf, sizeof(read_command_buf));
+ fputc('\n', stderr);
if (conn)
{
fprintf(stderr, "conn->name (%p): ", conn->name);
my_safe_print_str(conn->name, conn->name_len);
+ fputc('\n', stderr);
#ifdef EMBEDDED_LIBRARY
fprintf(stderr, "conn->cur_query (%p): ", conn->cur_query);
my_safe_print_str(conn->cur_query, conn->cur_query_len);
+ fputc('\n', stderr);
#endif
}
fputs("Attempting backtrace...\n", stderr);
@@ -8387,7 +8818,6 @@ static void init_signal_handling(void)
#endif
sigaction(SIGILL, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
-
DBUG_VOID_RETURN;
}
@@ -8399,7 +8829,12 @@ int main(int argc, char **argv)
my_bool q_send_flag= 0, abort_flag= 0;
uint command_executed= 0, last_command_executed= 0;
char save_file[FN_REFLEN];
+ bool empty_result= FALSE;
MY_INIT(argv[0]);
+ DBUG_ENTER("main");
+
+ /* mysqltest has no way to free all its memory correctly */
+ sf_leaking_memory= 1;
save_file[0]= 0;
TMPDIR[0]= 0;
@@ -8431,8 +8866,8 @@ int main(int argc, char **argv)
my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
- if (my_hash_init(&var_hash, charset_info,
- 1024, 0, 0, get_var_key, var_free, MYF(0)))
+ if (my_hash_init2(&var_hash, 64, charset_info,
+ 128, 0, 0, get_var_key, var_free, MYF(0)))
die("Variable hash initialization failed");
var_set_string("MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
@@ -8459,6 +8894,7 @@ int main(int argc, char **argv)
#endif
init_dynamic_string(&ds_res, "", 2048, 2048);
+ init_alloc_root(&require_file_root, 1024, 1024);
parse_args(argc, argv);
@@ -8478,6 +8914,7 @@ int main(int argc, char **argv)
next_con= connections + 1;
var_set_int("$PS_PROTOCOL", ps_protocol);
+ var_set_int("$NON_BLOCKING_API", non_blocking_api_enabled);
var_set_int("$SP_PROTOCOL", sp_protocol);
var_set_int("$VIEW_PROTOCOL", view_protocol);
var_set_int("$CURSOR_PROTOCOL", cursor_protocol);
@@ -8518,36 +8955,37 @@ int main(int argc, char **argv)
cursor_protocol_enabled= cursor_protocol;
st_connection *con= connections;
-#ifdef EMBEDDED_LIBRARY
init_connection_thd(con);
-#endif /*EMBEDDED_LIBRARY*/
- if (!( mysql_init(&con->mysql)))
+ if (! (con->mysql= mysql_init(0)))
die("Failed in mysql_init()");
if (opt_connect_timeout)
- mysql_options(&con->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
+ mysql_options(con->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
(void *) &opt_connect_timeout);
if (opt_compress)
- mysql_options(&con->mysql,MYSQL_OPT_COMPRESS,NullS);
- mysql_options(&con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
- mysql_options(&con->mysql, MYSQL_SET_CHARSET_NAME,
+ mysql_options(con->mysql,MYSQL_OPT_COMPRESS,NullS);
+ mysql_options(con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
+ mysql_options(con->mysql, MYSQL_SET_CHARSET_NAME,
charset_info->csname);
if (opt_charsets_dir)
- mysql_options(&con->mysql, MYSQL_SET_CHARSET_DIR,
+ mysql_options(con->mysql, MYSQL_SET_CHARSET_DIR,
opt_charsets_dir);
if (opt_protocol)
- mysql_options(&con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+ mysql_options(con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(con->mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
if (opt_use_ssl)
{
- mysql_ssl_set(&con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
+ mysql_ssl_set(con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
#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");
- mysql_options(&con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ mysql_options(con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
&opt_ssl_verify_server_cert);
#endif
}
@@ -8555,13 +8993,14 @@ int main(int argc, char **argv)
#ifdef HAVE_SMEM
if (shared_memory_base_name)
- mysql_options(&con->mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
+ mysql_options(con->mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
#endif
if (!(con->name = my_strdup("default", MYF(MY_WME))))
die("Out of memory");
+ mysql_options(con->mysql, MYSQL_OPT_NONBLOCK, 0);
- safe_connect(&con->mysql, con->name, opt_host, opt_user, opt_pass,
+ safe_connect(con->mysql, con->name, opt_host, opt_user, opt_pass,
opt_db, opt_port, unix_sock);
/* Use all time until exit if no explicit 'start_timer' */
@@ -8576,14 +9015,15 @@ int main(int argc, char **argv)
set_current_connection(con);
- if (opt_include)
+ if (opt_prologue)
{
- open_file(opt_include);
+ open_file(opt_prologue);
}
verbose_msg("Start processing test commands from '%s' ...", cur_file->file_name);
while (!read_command(&command) && !abort_flag)
{
+ my_bool ok_to_do;
int current_line_inc = 1, processed = 0;
if (command->type == Q_UNKNOWN || command->type == Q_COMMENT_WITH_COMMAND)
get_command_type(command);
@@ -8600,8 +9040,12 @@ int main(int argc, char **argv)
command->abort_on_error= (command->expected_errors.count == 0 &&
abort_on_error);
- /* delimiter needs to be executed so we can continue to parse */
- my_bool ok_to_do= cur_block->ok || command->type == Q_DELIMITER;
+ /*
+ some commmands need to be executed or at least parsed unconditionally,
+ because they change the grammar.
+ */
+ ok_to_do= cur_block->ok || command->type == Q_DELIMITER
+ || command->type == Q_PERL;
/*
Some commands need to be "done" the first time if they may get
re-iterated over in a true context. This can only happen if there's
@@ -8612,8 +9056,7 @@ int main(int argc, char **argv)
if (command->type == Q_SOURCE ||
command->type == Q_ERROR ||
command->type == Q_WRITE_FILE ||
- command->type == Q_APPEND_FILE ||
- command->type == Q_PERL)
+ command->type == Q_APPEND_FILE)
{
for (struct st_block *stb= cur_block-1; stb >= block_stack; stb--)
{
@@ -8640,6 +9083,8 @@ int main(int argc, char **argv)
case Q_DISCONNECT:
case Q_DIRTY_CLOSE:
do_close_connection(command); break;
+ case Q_ENABLE_PREPARE_WARNINGS: prepare_warnings_enabled=1; break;
+ case Q_DISABLE_PREPARE_WARNINGS: prepare_warnings_enabled=0; break;
case Q_ENABLE_QUERY_LOG:
set_property(command, P_QUERY, 0);
break;
@@ -8682,6 +9127,14 @@ int main(int argc, char **argv)
case Q_DISABLE_METADATA:
set_property(command, P_META, 0);
break;
+ case Q_ENABLE_COLUMN_NAMES:
+ disable_column_names= 0;
+ var_set_int("$ENABLED_COLUMN_NAMES", 0);
+ break;
+ case Q_DISABLE_COLUMN_NAMES:
+ disable_column_names= 1;
+ var_set_int("$ENABLED_COLUMN_NAMES", 1);
+ break;
case Q_SOURCE: do_source(command); break;
case Q_SLEEP: do_sleep(command, 0); break;
case Q_REAL_SLEEP: do_sleep(command, 1); break;
@@ -8772,7 +9225,9 @@ int main(int argc, char **argv)
if (save_file[0])
{
- strmake(command->require_file, save_file, sizeof(save_file) - 1);
+ if (!(command->require_file= strdup_root(&require_file_root,
+ save_file)))
+ die("out of memory for require_file");
save_file[0]= 0;
}
run_query(cur_con, command, flags);
@@ -8870,12 +9325,12 @@ int main(int argc, char **argv)
dynstr_append(&ds_res, "\n");
break;
case Q_PING:
- handle_command_error(command, mysql_ping(&cur_con->mysql));
+ handle_command_error(command, mysql_ping(cur_con->mysql), -1);
break;
case Q_SEND_SHUTDOWN:
handle_command_error(command,
- mysql_shutdown(&cur_con->mysql,
- SHUTDOWN_DEFAULT));
+ mysql_shutdown(cur_con->mysql,
+ SHUTDOWN_DEFAULT), -1);
break;
case Q_SHUTDOWN_SERVER:
do_shutdown_server(command);
@@ -8903,11 +9358,17 @@ int main(int argc, char **argv)
case Q_ENABLE_PS_PROTOCOL:
set_property(command, P_PS, ps_protocol);
break;
+ case Q_DISABLE_NON_BLOCKING_API:
+ non_blocking_api_enabled= 0;
+ break;
+ case Q_ENABLE_NON_BLOCKING_API:
+ non_blocking_api_enabled= 1;
+ break;
case Q_DISABLE_RECONNECT:
- set_reconnect(&cur_con->mysql, 0);
+ set_reconnect(cur_con->mysql, 0);
break;
case Q_ENABLE_RECONNECT:
- set_reconnect(&cur_con->mysql, 1);
+ set_reconnect(cur_con->mysql, 1);
/* Close any open statements - no reconnect, need new prepare */
close_statements();
break;
@@ -8915,7 +9376,7 @@ int main(int argc, char **argv)
if (parsing_disabled == 0)
parsing_disabled= 1;
else
- die("Parsing is already disabled");
+ report_or_die("Parsing is already disabled");
break;
case Q_ENABLE_PARSING:
/*
@@ -8925,7 +9386,7 @@ int main(int argc, char **argv)
if (parsing_disabled == 1)
parsing_disabled= 0;
else
- die("Parsing is already enabled");
+ report_or_die("Parsing is already enabled");
break;
case Q_DIE:
/* Abort test with error code and error message */
@@ -8936,7 +9397,10 @@ int main(int argc, char **argv)
abort_flag= 1;
break;
case Q_SKIP:
- abort_not_supported_test("%s", command->first_argument);
+ /* Eval the query, thus replacing all environment variables */
+ dynstr_set(&ds_res, 0);
+ do_eval(&ds_res, command->first_argument, command->end, FALSE);
+ abort_not_supported_test("%s",ds_res.str);
break;
case Q_RESULT:
@@ -9004,8 +9468,6 @@ int main(int argc, char **argv)
if (parsing_disabled)
die("Test ended with parsing disabled");
- my_bool empty_result= FALSE;
-
/*
The whole test has been executed _sucessfully_.
Time to compare result or save it to record file.
@@ -9086,7 +9548,7 @@ void timer_output(void)
{
char buf[32], *end;
ulonglong timer= timer_now() - timer_start;
- end= longlong2str(timer, buf, 10);
+ end= longlong10_to_str(timer, buf, 10);
str_to_file(timer_file,buf, (int) (end-buf));
/* Timer has been written to the file, don't use it anymore */
timer_file= 0;
@@ -9096,7 +9558,7 @@ void timer_output(void)
ulonglong timer_now(void)
{
- return my_micro_time() / 1000;
+ return my_interval_timer() / 1000000;
}
@@ -9128,7 +9590,8 @@ void do_get_replace_column(struct st_command *command)
if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
die("Wrong column number to replace_column in '%s'", command->query);
if (!*from)
- die("Wrong number of arguments to replace_column in '%s'", command->query);
+ die("Wrong number of arguments to replace_column in '%s'",
+ command->query);
to= get_string(&buff, &from, command);
my_free(replace_column[column_number-1]);
replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
@@ -9240,15 +9703,15 @@ void free_replace()
typedef struct st_replace {
- my_bool found;
+ int found;
struct st_replace *next[256];
} REPLACE;
typedef struct st_replace_found {
- my_bool found;
- char *replace_string;
+ int found;
uint to_offset;
int from_offset;
+ char *replace_string;
} REPLACE_STRING;
@@ -9280,7 +9743,7 @@ void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
}
/* Found a string that needs to be replaced */
- DBUG_PRINT("info", ("found: %d, to_offset: %d, from_offset: %d, string: %s",
+ DBUG_PRINT("info", ("found: %d, to_offset: %u, from_offset: %d, string: %s",
rep_str->found, rep_str->to_offset,
rep_str->from_offset, rep_str->replace_string));
@@ -10398,17 +10861,16 @@ void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
}
-
/*
Build a list of pointer to each line in ds_input, sort
the list and use the sorted list to append the strings
sorted to the output ds
SYNOPSIS
- dynstr_append_sorted
- ds - string where the sorted output will be appended
- ds_input - string to be sorted
-
+ dynstr_append_sorted()
+ ds string where the sorted output will be appended
+ ds_input string to be sorted
+ keep_header If header should not be sorted
*/
static int comp_lines(const char **a, const char **b)
@@ -10416,7 +10878,8 @@ static int comp_lines(const char **a, const char **b)
return (strcmp(*a,*b));
}
-void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
+void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input,
+ bool keep_header)
{
unsigned i;
char *start= ds_input->str;
@@ -10428,11 +10891,14 @@ void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
- /* First line is result header, skip past it */
- while (*start && *start != '\n')
- start++;
- start++; /* Skip past \n */
- dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
+ if (keep_header)
+ {
+ /* First line is result header, skip past it */
+ while (*start && *start != '\n')
+ start++;
+ start++; /* Skip past \n */
+ dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
+ }
/* Insert line(s) in array */
while (*start)
@@ -10481,3 +10947,32 @@ static int setenv(const char *name, const char *value, int overwrite)
return 0;
}
#endif
+
+/*
+ for the purpose of testing (see dialog.test)
+ we replace default mysql_authentication_dialog_ask function with the one,
+ that always reads from stdin with explicit echo.
+
+*/
+MYSQL_PLUGIN_EXPORT
+char *mysql_authentication_dialog_ask(MYSQL *mysql, int type,
+ const char *prompt,
+ char *buf, int buf_len)
+{
+ char *s=buf;
+
+ fputs(prompt, stdout);
+ fputs(" ", stdout);
+
+ if (!fgets(buf, buf_len-1, stdin))
+ buf[0]= 0;
+ else if (buf[0] && (s= strend(buf))[-1] == '\n')
+ s[-1]= 0;
+
+ for (s= buf; *s; s++)
+ fputc(type == 2 ? '*' : *s, stdout);
+
+ fputc('\n', stdout);
+
+ return buf;
+}
diff --git a/client/readline.cc b/client/readline.cc
index d850379353f..791a044e0e1 100644
--- a/client/readline.cc
+++ b/client/readline.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates.
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
@@ -33,9 +33,9 @@ static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length);
LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
{
LINE_BUFFER *line_buff;
- MY_STAT input_file_stat;
#ifndef __WIN__
+ MY_STAT input_file_stat;
if (my_fstat(fileno(file), &input_file_stat, MYF(MY_WME)) ||
MY_S_ISDIR(input_file_stat.st_mode) ||
MY_S_ISBLK(input_file_stat.st_mode))
@@ -58,6 +58,7 @@ char *batch_readline(LINE_BUFFER *line_buff)
{
char *pos;
ulong out_length;
+ LINT_INIT(out_length);
if (!(pos=intern_read_line(line_buff, &out_length)))
return 0;
diff --git a/client/sql_string.cc b/client/sql_string.cc.dontuse
index 0ad79ba5633..64219886dd0 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc.dontuse
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates.
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
@@ -483,11 +483,11 @@ uint32 String::numchars()
return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
}
-int String::charpos(int i,uint32 offset)
+int String::charpos(longlong i,uint32 offset)
{
if (i <= 0)
- return i;
- return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
+ return (int)i;
+ return (int)str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,(size_t)i);
}
int String::strstr(const String &s,uint32 offset)
diff --git a/client/sql_string.h b/client/sql_string.h.dontuse
index 0b92c370858..67155ebcee7 100644
--- a/client/sql_string.h
+++ b/client/sql_string.h.dontuse
@@ -1,5 +1,5 @@
-#ifndef CLIENT_SQL_STRING_INCLUDED
-#define CLIENT_SQL_STRING_INCLUDED
+#ifndef SQL_STRING_INCLUDED
+#define SQL_STRING_INCLUDED
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
@@ -32,13 +32,13 @@ uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
class String
{
char *Ptr;
- uint32 str_length,Alloced_length;
+ uint32 str_length,Alloced_length, extra_alloc;
bool alloced;
CHARSET_INFO *str_charset;
public:
String()
{
- Ptr=0; str_length=Alloced_length=0; alloced=0;
+ Ptr=0; str_length=Alloced_length=extra_alloc=0; alloced=0;
str_charset= &my_charset_bin;
}
String(uint32 length_arg)
@@ -48,23 +48,24 @@ public:
}
String(const char *str, CHARSET_INFO *cs)
{
- Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0;
+ Ptr=(char*) str; str_length= (uint32) strlen(str);
+ Alloced_length= extra_alloc= 0; alloced=0;
str_charset=cs;
}
String(const char *str,uint32 len, CHARSET_INFO *cs)
{
- Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0;
+ Ptr=(char*) str; str_length=len; Alloced_length= extra_alloc=0; alloced=0;
str_charset=cs;
}
String(char *str,uint32 len, CHARSET_INFO *cs)
{
- Ptr=(char*) str; Alloced_length=str_length=len; alloced=0;
+ Ptr=(char*) str; Alloced_length=str_length=len; extra_alloc= 0; alloced=0;
str_charset=cs;
}
String(const String &str)
{
Ptr=str.Ptr ; str_length=str.str_length ;
- Alloced_length=str.Alloced_length; alloced=0;
+ Alloced_length=str.Alloced_length; extra_alloc= 0; alloced=0;
str_charset=str.str_charset;
}
static void *operator new(size_t size, MEM_ROOT *mem_root)
@@ -272,7 +273,7 @@ public:
friend int stringcmp(const String *a,const String *b);
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
uint32 numchars();
- int charpos(int i,uint32 offset=0);
+ int charpos(longlong i,uint32 offset=0);
int reserve(uint32 space_needed)
{
@@ -361,4 +362,4 @@ public:
}
};
-#endif /* CLIENT_SQL_STRING_INCLUDED */
+#endif /* SQL_STRING_INCLUDED */