summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <cmiller@zippy.cornsilk.net>2006-10-17 11:23:07 -0400
committerunknown <cmiller@zippy.cornsilk.net>2006-10-17 11:23:07 -0400
commitdd8a33c0bcbf092bca3aac03ae8f9414dc0ae9f8 (patch)
treebeb33bece3b1deac1c65d795803da3b3d2e07f51
parente1ff81bbce1bb71b447b754b47521db3e0cd92b0 (diff)
parent309962243d7ade38854c74d729d6dbb33c4a8ff4 (diff)
downloadmariadb-git-dd8a33c0bcbf092bca3aac03ae8f9414dc0ae9f8.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.1
into zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-maint BitKeeper/etc/collapsed: auto-union BitKeeper/etc/ignore: auto-union Makefile.am: Auto merged client/mysql.cc: Auto merged client/mysqldump.c: Auto merged client/mysqltest.c: Auto merged configure.in: Auto merged include/m_ctype.h: Auto merged include/my_global.h: Auto merged mysql-test/lib/mtr_process.pl: Auto merged mysql-test/mysql-test-run.pl: Auto merged mysql-test/r/binlog_row_mix_innodb_myisam.result: Auto merged mysql-test/r/csv.result: Auto merged mysql-test/r/ctype_utf8.result: Auto merged mysql-test/r/func_time.result: Auto merged mysql-test/r/mysql.result: Auto merged mysql-test/r/partition.result: Auto merged mysql-test/r/ps.result: Auto merged mysql-test/r/strict.result: Auto merged mysql-test/r/trigger.result: Auto merged mysql-test/r/warnings.result: Auto merged mysql-test/t/csv.test: Auto merged mysql-test/t/ctype_utf8.test: Auto merged mysql-test/t/func_time.test: Auto merged mysql-test/t/mysql.test: Auto merged mysql-test/t/partition.test: Auto merged mysql-test/t/ps.test: Auto merged mysql-test/t/trigger.test: Auto merged sql/field.cc: Auto merged sql/filesort.cc: Auto merged sql/item.cc: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/item_timefunc.cc: Auto merged sql/item_timefunc.h: Auto merged sql/log.cc: Auto merged sql/mysql_priv.h: Auto merged sql/opt_range.cc: Auto merged sql/opt_range.h: Auto merged sql/set_var.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_insert.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_select.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_update.cc: Auto merged sql/sql_view.cc: Auto merged sql/sql_yacc.yy: Auto merged vio/viosocket.c: Auto merged
-rw-r--r--BitKeeper/etc/collapsed8
-rw-r--r--client/Makefile.am3
-rw-r--r--client/mysql.cc15
-rw-r--r--client/mysqldump.c8
-rw-r--r--client/mysqltest.c5831
-rw-r--r--include/my_time.h34
-rw-r--r--mysql-test/extra/rpl_tests/rpl_flsh_tbls.test2
-rw-r--r--mysql-test/extra/rpl_tests/rpl_truncate_helper.test1
-rw-r--r--mysql-test/include/ctype_like_escape.inc4
-rw-r--r--mysql-test/include/mysqltest_while.inc137
-rw-r--r--mysql-test/include/sourced.inc1
-rw-r--r--mysql-test/include/sourced1.inc1
-rw-r--r--mysql-test/lib/mtr_cases.pl193
-rw-r--r--mysql-test/lib/mtr_gcov.pl18
-rw-r--r--mysql-test/lib/mtr_io.pl14
-rw-r--r--mysql-test/lib/mtr_process.pl74
-rw-r--r--mysql-test/lib/mtr_report.pl41
-rwxr-xr-xmysql-test/mysql-test-run.pl1307
-rw-r--r--mysql-test/r/binlog_row_mix_innodb_myisam.result2
-rw-r--r--mysql-test/r/binlog_stm_mix_innodb_myisam.result2
-rw-r--r--mysql-test/r/check.result2
-rw-r--r--mysql-test/r/csv.result3
-rw-r--r--mysql-test/r/drop.result4
-rw-r--r--mysql-test/r/flush.result8
-rw-r--r--mysql-test/r/flush_block_commit.result8
-rw-r--r--mysql-test/r/flush_read_lock_kill.result2
-rw-r--r--mysql-test/r/flush_table.result6
-rw-r--r--mysql-test/r/func_compress.result10
-rw-r--r--mysql-test/r/func_date_add.result14
-rw-r--r--mysql-test/r/func_misc.result2
-rw-r--r--mysql-test/r/func_sapdb.result15
-rw-r--r--mysql-test/r/func_time.result95
-rw-r--r--mysql-test/r/grant2.result8
-rw-r--r--mysql-test/r/handler_innodb.result4
-rw-r--r--mysql-test/r/handler_myisam.result4
-rw-r--r--mysql-test/r/innodb_notembedded.result2
-rw-r--r--mysql-test/r/kill.result4
-rw-r--r--mysql-test/r/lock_multi.result26
-rw-r--r--mysql-test/r/log_tables.result4
-rw-r--r--mysql-test/r/multi_update.result4
-rw-r--r--mysql-test/r/mysql.result13
-rw-r--r--mysql-test/r/mysqltest.result69
-rw-r--r--mysql-test/r/partition.result36
-rw-r--r--mysql-test/r/ps.result478
-rw-r--r--mysql-test/r/ps_11bugs.result33
-rw-r--r--mysql-test/r/query_cache.result3
-rw-r--r--mysql-test/r/query_cache_notembedded.result2
-rw-r--r--mysql-test/r/rename.result2
-rw-r--r--mysql-test/r/rpl_err_ignoredtable.result2
-rw-r--r--mysql-test/r/rpl_master_pos_wait.result2
-rw-r--r--mysql-test/r/rpl_ndb_sp003.result2
-rw-r--r--mysql-test/r/rpl_row_sp003.result2
-rw-r--r--mysql-test/r/rpl_stm_000001.result2
-rw-r--r--mysql-test/r/show_check.result17
-rw-r--r--mysql-test/r/sp-threads.result4
-rw-r--r--mysql-test/r/sp_notembedded.result3
-rw-r--r--mysql-test/r/subselect.result3
-rw-r--r--mysql-test/r/synchronization.result40
-rw-r--r--mysql-test/r/user_var.result9
-rw-r--r--mysql-test/t/connect.test1
-rw-r--r--mysql-test/t/crash_commit_before.test3
-rw-r--r--mysql-test/t/csv.test2
-rw-r--r--mysql-test/t/disabled.def14
-rw-r--r--mysql-test/t/func_compress.test14
-rw-r--r--mysql-test/t/func_date_add.test15
-rw-r--r--mysql-test/t/func_time.test41
-rw-r--r--mysql-test/t/im_daemon_life_cycle.imtest3
-rw-r--r--mysql-test/t/init_file.test2
-rw-r--r--mysql-test/t/mysql.test17
-rw-r--r--mysql-test/t/mysqltest.test414
-rw-r--r--mysql-test/t/not_embedded_server-master.opt2
-rw-r--r--mysql-test/t/partition.test53
-rw-r--r--mysql-test/t/ps-master.opt1
-rw-r--r--mysql-test/t/ps.test119
-rw-r--r--mysql-test/t/ps_11bugs.test34
-rw-r--r--mysql-test/t/ps_1general.test2
-rw-r--r--mysql-test/t/ps_grant.test2
-rw-r--r--mysql-test/t/query_cache.test2
-rw-r--r--mysql-test/t/rpl_slave_status.test2
-rw-r--r--mysql-test/t/rpl_truncate_7ndb.test1
-rw-r--r--mysql-test/t/show_check-master.opt1
-rw-r--r--mysql-test/t/show_check.test14
-rw-r--r--mysql-test/t/sp-error.test2
-rw-r--r--mysql-test/t/sp.test10
-rw-r--r--mysql-test/t/sp_notembedded.test12
-rw-r--r--mysql-test/t/subselect.test2
-rw-r--r--mysql-test/t/system_mysql_db_fix.test6
-rw-r--r--mysql-test/t/user_var.test10
-rw-r--r--mysql-test/t/wait_timeout.test2
-rw-r--r--mysys/CMakeLists.txt2
-rw-r--r--mysys/Makefile.am2
-rw-r--r--mysys/charset.c15
-rwxr-xr-xmysys/make-ccc2
-rw-r--r--mysys/mf_iocache.c6
-rw-r--r--mysys/my_lread.c53
-rw-r--r--mysys/my_lwrite.c46
-rw-r--r--mysys/my_pread.c12
-rw-r--r--mysys/my_quick.c26
-rw-r--r--mysys/my_read.c9
-rw-r--r--mysys/my_seek.c9
-rw-r--r--mysys/my_write.c20
-rwxr-xr-x[-rw-r--r--]netware/BUILD/compile-netware-max2
-rwxr-xr-x[-rw-r--r--]netware/BUILD/compile-netware-max-debug2
-rwxr-xr-x[-rw-r--r--]netware/BUILD/compile-netware-src0
-rwxr-xr-xnetware/BUILD/mwenv25
-rw-r--r--sql-common/client.c2
-rw-r--r--sql-common/my_time.c90
-rw-r--r--sql/field.cc35
-rw-r--r--sql/item_strfunc.cc1
-rw-r--r--sql/item_timefunc.cc236
-rw-r--r--sql/set_var.cc1
-rw-r--r--sql/sp.cc23
-rw-r--r--sql/sql_acl.cc67
-rw-r--r--sql/sql_db.cc5
-rw-r--r--sql/sql_parse.cc129
-rw-r--r--sql/sql_prepare.cc33
-rw-r--r--sql/sql_table.cc13
-rw-r--r--sql/sql_trigger.cc13
-rw-r--r--sql/sql_view.cc60
-rw-r--r--sql/sql_view.h2
-rw-r--r--sql/time.cc19
-rw-r--r--storage/myisam/sort.c4
122 files changed, 6199 insertions, 4211 deletions
diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed
index 79836bb030e..311c3813abf 100644
--- a/BitKeeper/etc/collapsed
+++ b/BitKeeper/etc/collapsed
@@ -5,5 +5,13 @@
45001f7c3b2hhCXDKfUvzkX9TNe6VA
45002051rHJfMEXAIMiAZV0clxvKSA
4513d8e4Af4dQWuk13sArwofRgFDQw
+45143312u0Tz4r0wPXCbUKwdHa2jWA
+45143b90ewOQuTW8-jrB3ZSAQvMRJw
+45184588w9U72A6KX1hUFeAC4shSHA
+45185df8mZbxfp85FbA0VxUXkmDewA
4519a6c5BVUxEHTf5iJnjZkixMBs8g
451ab499rgdjXyOnUDqHu-wBDoS-OQ
+451b110a3ZV6MITl93ehXk2wxrbW7g
+45214442pBGT9KuZEGixBH71jTzbOA
+45214a07hVsIGwvwa-WrO-jpeaSwVw
+452a92d0-31-8wSzSfZi165fcGcXPA
diff --git a/client/Makefile.am b/client/Makefile.am
index d3e96dd126f..7d48e34b37b 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -46,7 +46,8 @@ mysqladmin_SOURCES = mysqladmin.cc
mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD) $(CXXLDFLAGS)
mysqltest_SOURCES= mysqltest.c $(top_srcdir)/mysys/my_getsystime.c \
$(yassl_dummy_link_fix)
-mysqltest_LDADD = $(top_builddir)/regex/libregex.a $(LDADD)
+mysqltest_LDADD = $(top_builddir)/regex/libregex.a $(LDADD) \
+ $(top_builddir)/mysys/libmysys.a
mysqlbinlog_SOURCES = mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c \
$(top_srcdir)/mysys/my_new.cc \
$(top_srcdir)/mysys/my_bit.c \
diff --git a/client/mysql.cc b/client/mysql.cc
index 1dbdeb8be97..fc26a741632 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -386,6 +386,21 @@ int main(int argc,char *argv[])
else
status.add_to_history=1;
status.exit_status=1;
+
+ {
+ /*
+ The file descriptor-layer may be out-of-sync with the file-number layer,
+ so we make sure that "stdout" is really open. If its file is closed then
+ explicitly close the FD layer.
+ */
+ int stdout_fileno_copy;
+ stdout_fileno_copy= dup(fileno(stdout)); /* Okay if fileno fails. */
+ if (stdout_fileno_copy == -1)
+ fclose(stdout);
+ else
+ close(stdout_fileno_copy); /* Clean up dup(). */
+ }
+
load_defaults("my",load_default_groups,&argc,&argv);
defaults_argv=argv;
if (get_options(argc, (char **) argv))
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 2d2961e465c..8978239a5b0 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -3405,7 +3405,7 @@ static int do_reset_master(MYSQL *mysql_con)
}
-static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now)
+static int start_transaction(MYSQL *mysql_con)
{
/*
We use BEGIN for old servers. --single-transaction --master-data will fail
@@ -3420,10 +3420,8 @@ static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now)
"SET SESSION TRANSACTION ISOLATION "
"LEVEL REPEATABLE READ") ||
mysql_query_with_error_report(mysql_con, 0,
- consistent_read_now ?
"START TRANSACTION "
- "WITH CONSISTENT SNAPSHOT" :
- "BEGIN"));
+ "/*!40100 WITH CONSISTENT SNAPSHOT */"));
}
@@ -3913,7 +3911,7 @@ int main(int argc, char **argv)
if ((opt_lock_all_tables || opt_master_data) &&
do_flush_tables_read_lock(mysql))
goto err;
- if (opt_single_transaction && start_transaction(mysql, test(opt_master_data)))
+ if (opt_single_transaction && start_transaction(mysql))
goto err;
if (opt_delete_master_logs && do_reset_master(mysql))
goto err;
diff --git a/client/mysqltest.c b/client/mysqltest.c
index f9c4ae617fd..e2317560404 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -14,35 +14,24 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* mysqltest test tool
- * See the manual for more information
- * TODO: document better how mysqltest works
- *
- * Written by:
- * Sasha Pachev <sasha@mysql.com>
- * Matt Wagner <matt@mysql.com>
- * Monty
- * Jani
- **/
-
-/**********************************************************************
- TODO:
+/*
+ mysqltest
-- Do comparison line by line, instead of doing a full comparison of
- the text file. This will save space as we don't need to keep many
- results in memory. It will also make it possible to do simple
- 'comparison' fixes like accepting the result even if a float differed
- in the last decimals.
+ Tool used for executing a .test file
-- Don't buffer lines from the test that you don't expect to need
- again.
+ See the "MySQL Test framework manual" for more information
+ http://dev.mysql.com/doc/mysqltest/en/index.html
-- Change 'read_line' to be faster by using the readline.cc code;
- We can do better than calling feof() for each character!
+ Please keep the test framework tools identical in all versions!
-**********************************************************************/
+ Written by:
+ Sasha Pachev <sasha@mysql.com>
+ Matt Wagner <matt@mysql.com>
+ Monty
+ Jani
+*/
-#define MTEST_VERSION "2.6"
+#define MTEST_VERSION "3.0"
#include <my_global.h>
#include <mysql_embed.h>
@@ -51,18 +40,18 @@
#include <mysql.h>
#include <mysql_version.h>
#include <mysqld_error.h>
+#include <errmsg.h>
#include <m_ctype.h>
#include <my_dir.h>
-#include <errmsg.h> /* Error codes */
#include <hash.h>
#include <my_getopt.h>
#include <stdarg.h>
-#include <sys/stat.h>
#include <violite.h>
-#include "my_regex.h" /* Our own version of lib */
+#include "my_regex.h" /* Our own version of regex */
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
+
#ifndef WEXITSTATUS
# ifdef __WIN__
# define WEXITSTATUS(stat_val) (stat_val)
@@ -70,169 +59,116 @@
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
# endif
#endif
-/* MAX_QUERY is 256K -- there is a test in sp-big that is >128K */
-#define MAX_QUERY (256*1024)
-#define MAX_VAR_NAME 256
-#define MAX_COLUMNS 256
-#define MAX_CONS 128
-#define MAX_INCLUDE_DEPTH 16
-#define INIT_Q_LINES 1024
-#define MIN_VAR_ALLOC 32
-#define BLOCK_STACK_DEPTH 32
-#define MAX_EXPECTED_ERRORS 10
-#define QUERY_SEND 1
-#define QUERY_REAP 2
-#define MAX_SERVER_ARGS 64
-
-
-#define SLAVE_POLL_INTERVAL 300000 /* 0.3 of a sec */
-#define DEFAULT_DELIMITER ";"
-#define MAX_DELIMITER 16
-
-#define RESULT_OK 0
-#define RESULT_CONTENT_MISMATCH 1
-#define RESULT_LENGTH_MISMATCH 2
-
-enum {OPT_SKIP_SAFEMALLOC=256, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT,
- OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER, OPT_PS_PROTOCOL,
- OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
- OPT_SSL_VERIFY_SERVER_CERT, OPT_MAX_CONNECT_RETRIES,
- OPT_MARK_PROGRESS};
-
-/* ************************************************************************ */
-/*
- The list of error codes to --error are stored in an internal array of
- structs. This struct can hold numeric SQL error codes or SQLSTATE codes
- as strings. The element next to the last active element in the list is
- set to type ERR_EMPTY. When an SQL statement returns an error, we use
- this list to check if this is an expected error.
-*/
-
-enum match_err_type
-{
- ERR_EMPTY= 0,
- ERR_ERRNO,
- ERR_SQLSTATE
-};
-
-typedef struct
-{
- enum match_err_type type;
- union
- {
- uint errnum;
- char sqlstate[SQLSTATE_LENGTH+1]; /* \0 terminated string */
- } code;
-} match_err;
-
-typedef struct
-{
- const char *name;
- long code;
-} st_error;
-static st_error global_error[] =
-{
-#include <mysqld_ername.h>
- { 0, 0 }
+#define MAX_VAR_NAME_LENGTH 256
+#define MAX_COLUMNS 256
+#define MAX_EMBEDDED_SERVER_ARGS 64
+#define MAX_DELIMITER_LENGTH 16
+
+/* Flags controlling send and reap */
+#define QUERY_SEND_FLAG 1
+#define QUERY_REAP_FLAG 2
+
+ enum {
+ RESULT_OK= 0,
+ RESULT_CONTENT_MISMATCH= 1,
+ RESULT_LENGTH_MISMATCH= 2
+ };
+
+enum {
+ OPT_SKIP_SAFEMALLOC=256, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT,
+ OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER, OPT_PS_PROTOCOL,
+ OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
+ OPT_SSL_VERIFY_SERVER_CERT, OPT_MAX_CONNECT_RETRIES,
+ OPT_MARK_PROGRESS
};
-static match_err global_expected_errno[MAX_EXPECTED_ERRORS];
-static uint global_expected_errors;
-
-/* ************************************************************************ */
-
static int record= 0, opt_sleep= -1;
-static char *db = 0, *pass=0;
-const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./";
+static char *db= 0, *pass= 0;
+const char *user= 0, *host= 0, *unix_sock= 0, *opt_basedir= "./";
const char *opt_include= 0;
-static int port = 0;
+static int port= 0;
static int opt_max_connect_retries;
-static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0;
+static my_bool opt_compress= 0, silent= 0, verbose= 0;
static my_bool tty_password= 0;
static my_bool opt_mark_progress= 0;
static my_bool ps_protocol= 0, ps_protocol_enabled= 0;
static my_bool sp_protocol= 0, sp_protocol_enabled= 0;
static my_bool view_protocol= 0, view_protocol_enabled= 0;
static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0;
-static my_bool opt_valgrind_test= 0;
-static int parsing_disabled= 0;
+static my_bool parsing_disabled= 0;
+static my_bool display_result_vertically= FALSE, display_metadata= FALSE;
+static my_bool disable_query_log= 0, disable_result_log= 0;
+static my_bool disable_warnings= 0, disable_ps_warnings= 0;
+static my_bool disable_info= 1;
+static my_bool abort_on_error= 1;
static char **default_argv;
-static const char *load_default_groups[]= { "mysqltest","client",0 };
-static char line_buffer[MAX_DELIMITER], *line_buffer_pos= line_buffer;
+static const char *load_default_groups[]= { "mysqltest", "client", 0 };
+static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
-typedef struct
-{
- FILE* file;
- const char *file_name;
- uint lineno; /* Current line in file */
-} test_file;
+static uint start_lineno= 0; /* Start line of current command */
+
+static char delimiter[MAX_DELIMITER_LENGTH]= ";";
+static uint delimiter_length= 1;
-static test_file file_stack[MAX_INCLUDE_DEPTH];
-static test_file* cur_file;
-static test_file* file_stack_end;
-uint start_lineno= 0; /* Start line of query */
+static char TMPDIR[FN_REFLEN];
-/* Stores regex substitutions */
+/* Block stack */
+enum block_cmd {
+ cmd_none,
+ cmd_if,
+ cmd_while
+};
-struct st_regex
+struct st_block
{
- char* pattern; /* Pattern to be replaced */
- char* replace; /* String or expression to replace the pattern with */
- int icase; /* true if the match is case insensitive */
+ int line; /* Start line of block */
+ my_bool ok; /* Should block be executed */
+ enum block_cmd cmd; /* Command owning the block */
};
-struct st_replace_regex
+static struct st_block block_stack[32];
+static struct st_block *cur_block, *block_stack_end;
+
+/* Open file stack */
+struct st_test_file
{
- DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
-
- /*
- Temporary storage areas for substitutions. To reduce unnessary copying
- and memory freeing/allocation, we pre-allocate two buffers, and alternate
- their use, one for input/one for output, the roles changing on the next
- st_regex substition. At the end of substitutions buf points to the
- one containing the final result.
- */
- char* buf;
- char* even_buf;
- char* odd_buf;
- int even_buf_len;
- int odd_buf_len;
+ FILE* file;
+ const char *file_name;
+ uint lineno; /* Current line in file */
};
-struct st_replace_regex *glob_replace_regex= 0;
-
-static char TMPDIR[FN_REFLEN];
-static char delimiter[MAX_DELIMITER]= DEFAULT_DELIMITER;
-static uint delimiter_length= 1;
+static struct st_test_file file_stack[16];
+static struct st_test_file* cur_file;
+static struct st_test_file* file_stack_end;
-/* Block stack */
-enum block_cmd { cmd_none, cmd_if, cmd_while };
-typedef struct
-{
- int line; /* Start line of block */
- my_bool ok; /* Should block be executed */
- enum block_cmd cmd; /* Command owning the block */
-} BLOCK;
-static BLOCK block_stack[BLOCK_STACK_DEPTH];
-static BLOCK *cur_block, *block_stack_end;
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
static const char *charset_name= "latin1"; /* Default character set name */
-static int embedded_server_arg_count=0;
-static char *embedded_server_args[MAX_SERVER_ARGS];
+static const char *embedded_server_groups[]=
+{
+ "server",
+ "embedded",
+ "mysqltest_SERVER",
+ NullS
+};
-static my_bool display_result_vertically= FALSE, display_metadata= FALSE;
+static int embedded_server_arg_count=0;
+static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
-/* See the timer_output() definition for details */
+/*
+ Timer related variables
+ See the timer_output() definition for details
+*/
static char *timer_file = NULL;
-static ulonglong timer_start, progress_start= 0;
-static int got_end_timer= FALSE;
+static ulonglong timer_start;
static void timer_output(void);
static ulonglong timer_now(void);
+static ulonglong progress_start= 0;
+
/* Precompiled re's */
static my_regex_t ps_re; /* the query can be run using PS protocol */
static my_regex_t sp_re; /* the query can be run as a SP */
@@ -242,47 +178,25 @@ static void init_re(void);
static int match_re(my_regex_t *, char *);
static void free_re(void);
-static int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
- char *string, int icase);
-
-static const char *embedded_server_groups[]=
-{
- "server",
- "embedded",
- "mysqltest_SERVER",
- NullS
-};
-
DYNAMIC_ARRAY q_lines;
#include "sslopt-vars.h"
-typedef struct
-{
- char file[FN_REFLEN];
- ulong pos;
-} MASTER_POS ;
-
-struct connection
+struct
{
- MYSQL mysql;
- /* Used when creating views and sp, to avoid implicit commit */
- MYSQL* util_mysql;
- char *name;
- MYSQL_STMT* stmt;
-};
+ int read_lines,current_line;
+} parser;
-typedef struct
+struct
{
- int read_lines,current_line;
-} PARSER;
+ char file[FN_REFLEN];
+ ulong pos;
+} master_pos;
-PARSER parser;
-MASTER_POS master_pos;
/* if set, all results are concated and compared against this file */
-const char *result_file = 0;
+const char *result_file_name= 0;
-typedef struct
+typedef struct st_var
{
char *name;
int name_len;
@@ -295,70 +209,68 @@ typedef struct
char *env_s;
} VAR;
-VAR var_reg[10];
/*Perl/shell-like variable registers */
-HASH var_hash;
-my_bool disable_query_log=0, disable_result_log=0, disable_warnings=0;
-my_bool disable_ps_warnings= 0;
-my_bool disable_info= 1; /* By default off */
-my_bool abort_on_error= 1;
+VAR var_reg[10];
-struct connection cons[MAX_CONS];
-struct connection* cur_con, *next_con, *cons_end;
+HASH var_hash;
- /* Add new commands before Q_UNKNOWN !*/
+struct st_connection
+{
+ MYSQL mysql;
+ /* Used when creating views and sp, to avoid implicit commit */
+ MYSQL* util_mysql;
+ char *name;
+ MYSQL_STMT* stmt;
+};
+struct st_connection connections[128];
+struct st_connection* cur_con, *next_con, *connections_end;
+/*
+ List of commands in mysqltest
+ Must match the "command_names" array
+ Add new commands before Q_UNKNOWN!
+*/
enum enum_commands {
-Q_CONNECTION=1, Q_QUERY,
-Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP,
-Q_INC, Q_DEC,
-Q_SOURCE, Q_DISCONNECT,
-Q_LET, Q_ECHO,
-Q_WHILE, Q_END_BLOCK,
-Q_SYSTEM, Q_RESULT,
-Q_REQUIRE, Q_SAVE_MASTER_POS,
-Q_SYNC_WITH_MASTER,
-Q_SYNC_SLAVE_WITH_MASTER,
-Q_ERROR,
-Q_SEND, Q_REAP,
-Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
-Q_PING, Q_EVAL,
-Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
-Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
-Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
-Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
-Q_WAIT_FOR_SLAVE_TO_STOP,
-Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
-Q_ENABLE_PS_WARNINGS, Q_DISABLE_PS_WARNINGS,
-Q_ENABLE_INFO, Q_DISABLE_INFO,
-Q_ENABLE_METADATA, Q_DISABLE_METADATA,
-Q_EXEC, Q_DELIMITER,
-Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
-Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
-Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL,
-Q_START_TIMER, Q_END_TIMER,
-Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
-Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
-Q_IF,
-Q_DISABLE_PARSING, Q_ENABLE_PARSING,
-Q_REPLACE_REGEX, Q_DIE,
-
-Q_UNKNOWN, /* Unknown command. */
-Q_COMMENT, /* Comments, ignored. */
-Q_COMMENT_WITH_COMMAND
+ Q_CONNECTION=1, Q_QUERY,
+ Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP,
+ Q_INC, Q_DEC,
+ Q_SOURCE, Q_DISCONNECT,
+ Q_LET, Q_ECHO,
+ Q_WHILE, Q_END_BLOCK,
+ Q_SYSTEM, Q_RESULT,
+ Q_REQUIRE, Q_SAVE_MASTER_POS,
+ Q_SYNC_WITH_MASTER,
+ Q_SYNC_SLAVE_WITH_MASTER,
+ Q_ERROR,
+ Q_SEND, Q_REAP,
+ Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
+ Q_PING, Q_EVAL,
+ Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
+ Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
+ Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
+ Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
+ Q_WAIT_FOR_SLAVE_TO_STOP,
+ Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
+ Q_ENABLE_PS_WARNINGS, Q_DISABLE_PS_WARNINGS,
+ Q_ENABLE_INFO, Q_DISABLE_INFO,
+ Q_ENABLE_METADATA, Q_DISABLE_METADATA,
+ Q_EXEC, Q_DELIMITER,
+ Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
+ Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
+ Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL,
+ Q_START_TIMER, Q_END_TIMER,
+ Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
+ Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
+ Q_IF,
+ Q_DISABLE_PARSING, Q_ENABLE_PARSING,
+ Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST,
+ Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE,
+
+ Q_UNKNOWN, /* Unknown command. */
+ Q_COMMENT, /* Comments, ignored. */
+ Q_COMMENT_WITH_COMMAND
};
-/* this should really be called command */
-struct st_query
-{
- char *query, *query_buf,*first_argument,*last_argument,*end;
- int first_word_len;
- my_bool abort_on_error, require_file;
- match_err expected_errno[MAX_EXPECTED_ERRORS];
- uint expected_errors;
- char record_file[FN_REFLEN];
- enum enum_commands type;
-};
const char *command_names[]=
{
@@ -427,69 +339,116 @@ const char *command_names[]=
"disable_parsing",
"enable_parsing",
"replace_regex",
+ "remove_file",
+ "file_exists",
+ "write_file",
+ "copy_file",
+ "perl",
"die",
0
};
-TYPELIB command_typelib= {array_elements(command_names),"",
- command_names, 0};
-
-DYNAMIC_STRING ds_res, ds_progress;
-static void die(const char *fmt, ...);
-static void init_var_hash();
-static VAR* var_from_env(const char *, const char *);
-static byte* get_var_key(const byte* rec, uint* len, my_bool t);
-static VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
- int val_len);
-static void var_free(void* v);
+/*
+ The list of error codes to --error are stored in an internal array of
+ structs. This struct can hold numeric SQL error codes, error names or
+ SQLSTATE codes as strings. The element next to the last active element
+ in the list is set to type ERR_EMPTY. When an SQL statement returns an
+ error, we use this list to check if this is an expected error.
+*/
+enum match_err_type
+{
+ ERR_EMPTY= 0,
+ ERR_ERRNO,
+ ERR_SQLSTATE
+};
-void dump_result_to_reject_file(const char *record_file, char *buf, int size);
-void dump_result_to_log_file(const char *record_file, char *buf, int size);
+struct st_match_err
+{
+ enum match_err_type type;
+ union
+ {
+ uint errnum;
+ char sqlstate[SQLSTATE_LENGTH+1]; /* \0 terminated string */
+ } code;
+};
-int close_connection(struct st_query*);
-static void set_charset(struct st_query*);
-VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
- my_bool ignore_not_existing);
-int eval_expr(VAR* v, const char *p, const char** p_end);
-static int read_server_arguments(const char *name);
+struct st_expected_errors
+{
+ struct st_match_err err[10];
+ uint count;
+};
+static struct st_expected_errors saved_expected_errors;
-/* Definitions for replace result */
+struct st_command
+{
+ char *query, *query_buf,*first_argument,*last_argument,*end;
+ int first_word_len, query_len;
+ my_bool abort_on_error;
+ struct st_expected_errors expected_errors;
+ char require_file[FN_REFLEN];
+ enum enum_commands type;
+};
-typedef struct st_pointer_array { /* when using array-strings */
- TYPELIB typelib; /* Pointer to strings */
- byte *str; /* Strings is here */
- int7 *flag; /* Flag about each var. */
- uint array_allocs,max_count,length,max_length;
-} POINTER_ARRAY;
+TYPELIB command_typelib= {array_elements(command_names),"",
+ command_names, 0};
-struct st_replace;
-struct st_replace *init_replace(my_string *from, my_string *to, uint count,
- my_string word_end_chars);
-void free_replace();
-static void free_replace_regex();
-static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name);
-static void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
- const char *from, int len);
-void free_pointer_array(POINTER_ARRAY *pa);
-static void do_eval(DYNAMIC_STRING *query_eval, const char *query,
- my_bool pass_through_escape_chars);
-static void str_to_file(const char *fname, char *str, int size);
+DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
+
+void die(const char *fmt, ...)
+ /* ATTRIBUTE_FORMAT(printf, 1, 2) */;
+void abort_not_supported_test(const char *fmt, ...)
+ /* ATTRIBUTE_FORMAT(printf, 1, 2) */;
+void verbose_msg(const char *fmt, ...)
+ /* ATTRIBUTE_FORMAT(printf, 1, 2) */;
+void warning_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,
+ int val_len);
+void var_free(void* v);
+VAR* var_get(const char *var_name, const char** var_name_end,
+ my_bool raw, my_bool ignore_not_existing);
+void eval_expr(VAR* v, const char *p, const char** p_end);
+my_bool match_delimiter(int c, const char *delim, uint length);
+void dump_result_to_reject_file(char *buf, int size);
+void dump_result_to_log_file(char *buf, int size);
+void dump_warning_messages();
+void dump_progress();
+
+void do_eval(DYNAMIC_STRING *query_eval, const char *query,
+ const char *query_end, my_bool pass_through_escape_chars);
+void str_to_file(const char *fname, char *str, int size);
#ifdef __WIN__
-static void free_tmp_sh_file();
-static void free_win_path_patterns();
+void free_tmp_sh_file();
+void free_win_path_patterns();
#endif
-struct st_replace *glob_replace;
static int eval_result = 0;
-/* For column replace */
-char *replace_column[MAX_COLUMNS];
-uint max_replace_column= 0;
+/* For replace_column */
+static char *replace_column[MAX_COLUMNS];
+static uint max_replace_column= 0;
+void do_get_replace_column(struct st_command*);
+void free_replace_column();
+
+/* For replace */
+void do_get_replace(struct st_command *command);
+void free_replace();
+
+/* For replace_regex */
+void do_get_replace_regex(struct st_command *command);
+void free_replace_regex();
+
+
+void free_all_replace(){
+ free_replace();
+ free_replace_regex();
+ free_replace_column();
+}
-static void get_replace_column(struct st_query *q);
-static void free_replace_column();
/* Disable functions that only exist in MySQL 4.0 */
#if MYSQL_VERSION_ID < 40000
@@ -498,35 +457,40 @@ void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
#endif
-static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
- int len);
-static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
-static void handle_error(const char *query, struct st_query *q,
- unsigned int err_errno, const char *err_error,
- const char *err_sqlstate, DYNAMIC_STRING *ds);
-static void handle_no_error(struct st_query *q);
-static void do_eval(DYNAMIC_STRING* query_eval, const char *query,
- my_bool pass_through_escape_chars)
+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 handle_error(struct st_command*,
+ unsigned int err_errno, const char *err_error,
+ const char *err_sqlstate, DYNAMIC_STRING *ds);
+void handle_no_error(struct st_command*);
+
+
+
+void do_eval(DYNAMIC_STRING *query_eval, const char *query,
+ const char *query_end, my_bool pass_through_escape_chars)
{
const char *p;
register char c, next_c;
register int escaped = 0;
- VAR* v;
+ VAR *v;
DBUG_ENTER("do_eval");
- for (p= query; (c = *p); ++p)
+ for (p= query; (c= *p) && p < query_end; ++p)
{
switch(c) {
case '$':
if (escaped)
{
- escaped = 0;
+ escaped= 0;
dynstr_append_mem(query_eval, p, 1);
}
else
{
- if (!(v = var_get(p, &p, 0, 0)))
+ if (!(v= var_get(p, &p, 0, 0)))
die("Bad variable in eval");
dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
}
@@ -535,13 +499,13 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char *query,
next_c= *(p+1);
if (escaped)
{
- escaped = 0;
+ escaped= 0;
dynstr_append_mem(query_eval, p, 1);
}
- else if (next_c == '\\' || next_c == '$')
+ else if (next_c == '\\' || next_c == '$' || next_c == '"')
{
- /* Set escaped only if next char is \ or $ */
- escaped = 1;
+ /* Set escaped only if next char is \, " or $ */
+ escaped= 1;
if (pass_through_escape_chars)
{
@@ -561,10 +525,131 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char *query,
}
-static void close_cons()
+enum arg_type
+{
+ ARG_STRING,
+ ARG_REST
+};
+
+struct command_arg {
+ const char *argname; /* Name of argument */
+ enum arg_type type; /* Type of argument */
+ my_bool required; /* Argument required */
+ DYNAMIC_STRING *ds; /* Storage for argument */
+ const char *description; /* Description of the argument */
+};
+
+
+void check_command_args(struct st_command *command,
+ const char *arguments,
+ const struct command_arg *args,
+ int num_args, const char delimiter_arg)
+{
+ int i;
+ const char *ptr= arguments;
+ const char *start;
+
+ DBUG_ENTER("check_command_args");
+ DBUG_PRINT("enter", ("num_args: %d", num_args));
+ for (i= 0; i < num_args; i++)
+ {
+ const struct command_arg *arg= &args[i];
+
+ switch (arg->type)
+ {
+ /* A string */
+ case ARG_STRING:
+ /* Skip leading spaces */
+ while (*ptr && *ptr == ' ')
+ ptr++;
+ start= ptr;
+ /* Find end of arg, terminated by "delimiter_arg" */
+ while (*ptr && *ptr != delimiter_arg)
+ ptr++;
+ if (ptr > start)
+ {
+ init_dynamic_string(arg->ds, 0, ptr-start, 32);
+ do_eval(arg->ds, start, ptr, FALSE);
+ }
+ else
+ {
+ /* Empty string */
+ init_dynamic_string(arg->ds, "", 0, 0);
+ }
+ command->last_argument= (char*)ptr;
+
+ /* Step past the delimiter */
+ if (*ptr && *ptr == delimiter_arg)
+ ptr++;
+ DBUG_PRINT("info", ("val: %s", arg->ds->str));
+ break;
+
+ /* Rest of line */
+ case ARG_REST:
+ start= ptr;
+ init_dynamic_string(arg->ds, 0, command->query_len, 256);
+ do_eval(arg->ds, start, command->end, FALSE);
+ command->last_argument= command->end;
+ DBUG_PRINT("info", ("val: %s", arg->ds->str));
+ break;
+
+ default:
+ DBUG_ASSERT("Unknown argument type");
+ break;
+ }
+
+ /* Check required arg */
+ if (arg->ds->length == 0 && arg->required)
+ die("Missing required argument '%s' to command '%.*s'", arg->argname,
+ command->first_word_len, command->query);
+
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void handle_command_error(struct st_command *command, uint error)
+{
+ DBUG_ENTER("handle_command_error");
+ DBUG_PRINT("enter", ("error: %d", error));
+ if (error != 0)
+ {
+ uint i;
+
+ if (command->abort_on_error)
+ die("command \"%.*s\" failed with error %d",
+ command->first_word_len, command->query, error);
+ for (i= 0; i < command->expected_errors.count; i++)
+ {
+ DBUG_PRINT("info", ("expected error: %d",
+ command->expected_errors.err[i].code.errnum));
+ if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
+ (command->expected_errors.err[i].code.errnum == error))
+ {
+ DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %d",
+ command->first_word_len, command->query, error));
+ DBUG_VOID_RETURN;
+ }
+ }
+ die("command \"%.*s\" failed with wrong error: %d",
+ command->first_word_len, command->query, error);
+ }
+ 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...",
+ command->first_word_len, command->query,
+ command->expected_errors.err[0].code.errnum);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void close_connections()
{
- DBUG_ENTER("close_cons");
- for (--next_con; next_con >= cons; --next_con)
+ DBUG_ENTER("close_connections");
+ for (--next_con; next_con >= connections; --next_con)
{
if (next_con->stmt)
mysql_stmt_close(next_con->stmt);
@@ -578,14 +663,16 @@ static void close_cons()
}
-static void close_files()
+void close_files()
{
DBUG_ENTER("close_files");
for (; cur_file >= file_stack; cur_file--)
{
- DBUG_PRINT("info", ("file_name: %s", cur_file->file_name));
if (cur_file->file && cur_file->file != stdin)
+ {
+ DBUG_PRINT("info", ("closing file: %s", cur_file->file_name));
my_fclose(cur_file->file, MYF(0));
+ }
my_free((gptr)cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
cur_file->file_name= 0;
}
@@ -593,22 +680,22 @@ static void close_files()
}
-static void free_used_memory()
+void free_used_memory()
{
uint i;
DBUG_ENTER("free_used_memory");
- close_cons();
+ close_connections();
close_files();
hash_free(&var_hash);
- for (i=0 ; i < q_lines.elements ; i++)
+ for (i= 0 ; i < q_lines.elements ; i++)
{
- struct st_query **q= dynamic_element(&q_lines, i, struct st_query**);
+ struct st_command **q= dynamic_element(&q_lines, i, struct st_command**);
my_free((gptr) (*q)->query_buf,MYF(MY_ALLOW_ZERO_PTR));
my_free((gptr) (*q),MYF(0));
}
- for (i=0; i < 10; i++)
+ for (i= 0; i < 10; i++)
{
if (var_reg[i].alloced_len)
my_free(var_reg[i].str_val, MYF(MY_WME));
@@ -618,8 +705,8 @@ static void free_used_memory()
delete_dynamic(&q_lines);
dynstr_free(&ds_res);
dynstr_free(&ds_progress);
- free_replace();
- free_replace_column();
+ dynstr_free(&ds_warning_messages);
+ free_all_replace();
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
free_defaults(default_argv);
mysql_server_end();
@@ -631,10 +718,12 @@ static void free_used_memory()
DBUG_VOID_RETURN;
}
-static void die(const char *fmt, ...)
+
+void die(const char *fmt, ...)
{
va_list args;
DBUG_ENTER("die");
+ DBUG_PRINT("enter", ("start_lineno: %d", start_lineno));
/* Print the error message */
va_start(args, fmt);
@@ -653,8 +742,12 @@ static void die(const char *fmt, ...)
va_end(args);
/* Dump the result that has been accumulated so far to .log file */
- if (result_file && ds_res.length)
- dump_result_to_log_file(result_file, ds_res.str, ds_res.length);
+ if (result_file_name && ds_res.length)
+ dump_result_to_log_file(ds_res.str, ds_res.length);
+
+ /* Dump warning messages */
+ if (result_file_name && ds_warning_messages.length)
+ dump_warning_messages();
/* Clean up and exit */
free_used_memory();
@@ -667,10 +760,10 @@ static void die(const char *fmt, ...)
}
-static void abort_not_supported_test(const char *fmt, ...)
+void abort_not_supported_test(const char *fmt, ...)
{
va_list args;
- test_file* err_file= cur_file;
+ struct st_test_file* err_file= cur_file;
DBUG_ENTER("abort_not_supported_test");
/* Print include filestack */
@@ -706,7 +799,14 @@ static void abort_not_supported_test(const char *fmt, ...)
exit(62);
}
-static void verbose_msg(const char *fmt, ...)
+
+void abort_not_in_this_version()
+{
+ die("Not available in this version of mysqltest");
+}
+
+
+void verbose_msg(const char *fmt, ...)
{
va_list args;
DBUG_ENTER("verbose_msg");
@@ -715,6 +815,9 @@ static void verbose_msg(const char *fmt, ...)
va_start(args, fmt);
fprintf(stderr, "mysqltest: ");
+ if (cur_file && cur_file != file_stack)
+ fprintf(stderr, "In included file \"%s\": ",
+ cur_file->file_name);
if (start_lineno != 0)
fprintf(stderr, "At line %u: ", start_lineno);
vfprintf(stderr, fmt, args);
@@ -725,14 +828,46 @@ static void verbose_msg(const char *fmt, ...)
}
-void init_parser()
+void warning_msg(const char *fmt, ...)
{
- parser.current_line= parser.read_lines= 0;
- memset(&var_reg, 0, sizeof(var_reg));
+ va_list args;
+ char buff[512];
+ size_t len;
+ DBUG_ENTER("warning_msg");
+
+ va_start(args, fmt);
+ dynstr_append(&ds_warning_messages, "mysqltest: ");
+ if (start_lineno != 0)
+ {
+ dynstr_append(&ds_warning_messages, "Warning detected ");
+ if (cur_file && cur_file != file_stack)
+ {
+ len= my_snprintf(buff, sizeof(buff), "in included file %s ",
+ cur_file->file_name);
+ dynstr_append_mem(&ds_warning_messages,
+ buff, len);
+ }
+ len= my_snprintf(buff, sizeof(buff), "at line %d: ",
+ start_lineno);
+ dynstr_append_mem(&ds_warning_messages,
+ buff, len);
+ }
+#ifndef __WIN__
+ len= vsnprintf(buff, sizeof(buff), fmt, args);
+ dynstr_append_mem(&ds_warning_messages, buff, len);
+#endif
+ dynstr_append(&ds_warning_messages, "\n");
+ va_end(args);
+
+ DBUG_VOID_RETURN;
}
-static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
+/*
+ Compare content of the string ds to content of file fname
+*/
+
+int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
{
MY_STAT stat_info;
char *tmp, *res_ptr;
@@ -761,19 +896,20 @@ static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
DBUG_RETURN(RESULT_LENGTH_MISMATCH);
}
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
- die(NullS);
+ die("Out of memory");
if ((fd = my_open(eval_file, O_RDONLY, MYF(MY_WME))) < 0)
- die(NullS);
+ die("Failed to open file %s", eval_file);
if (my_read(fd, (byte*)tmp, stat_info.st_size, MYF(MY_WME|MY_NABP)))
- die(NullS);
+ die("Failed to read from file %s, errno: %d", eval_file, errno);
tmp[stat_info.st_size] = 0;
- init_dynamic_string(&res_ds, "", 0, 65536);
+ init_dynamic_string(&res_ds, "", stat_info.st_size+256, 256);
if (eval_result)
{
- do_eval(&res_ds, tmp, FALSE);
- res_ptr = res_ds.str;
- if ((res_len = res_ds.length) != ds->length)
+ do_eval(&res_ds, tmp, tmp + stat_info.st_size, FALSE);
+ res_ptr= res_ds.str;
+ res_len= res_ds.length;
+ if (res_len != ds->length)
{
res= RESULT_LENGTH_MISMATCH;
goto err;
@@ -794,48 +930,41 @@ err:
MY_REPLACE_EXT),
res_ptr, res_len);
+ dynstr_free(&res_ds);
my_free((gptr) tmp, MYF(0));
my_close(fd, MYF(MY_WME));
- dynstr_free(&res_ds);
DBUG_RETURN(res);
}
+
/*
- Check the content of ds against content of file fname
+ Check the content of ds against result file
SYNOPSIS
check_result
ds - content to be checked
- fname - name of file to check against
- require_option - if set and check fails, the test will be aborted
- with the special exit code "not supported test"
RETURN VALUES
- error - the function will not return
+ error - the function will not return
*/
-static void check_result(DYNAMIC_STRING* ds, const char *fname,
- my_bool require_option)
+
+void check_result(DYNAMIC_STRING* ds)
{
- int res= dyn_string_cmp(ds, fname);
DBUG_ENTER("check_result");
+ DBUG_ASSERT(result_file_name);
- if (res && require_option)
+ switch (dyn_string_cmp(ds, result_file_name))
{
- char reason[FN_REFLEN];
- fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
- abort_not_supported_test("Test requires: '%s'", reason);
- }
- switch (res) {
case RESULT_OK:
break; /* ok */
case RESULT_LENGTH_MISMATCH:
- dump_result_to_reject_file(fname, ds->str, ds->length);
+ dump_result_to_reject_file(ds->str, ds->length);
die("Result length mismatch");
break;
case RESULT_CONTENT_MISMATCH:
- dump_result_to_reject_file(fname, ds->str, ds->length);
+ dump_result_to_reject_file(ds->str, ds->length);
die("Result content mismatch");
break;
default: /* impossible */
@@ -846,13 +975,109 @@ static void check_result(DYNAMIC_STRING* ds, const char *fname,
}
-VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
+/*
+ Check the content of ds against a require file
+ If match fails, abort the test with special error code
+ indicating that test is not supported
+
+ SYNOPSIS
+ check_result
+ ds - content to be checked
+ fname - name of file to check against
+
+ RETURN VALUES
+ error - the function will not return
+
+*/
+
+void check_require(DYNAMIC_STRING* ds, const char *fname)
+{
+ DBUG_ENTER("check_require");
+
+ if (dyn_string_cmp(ds, fname))
+ {
+ char reason[FN_REFLEN];
+ fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
+ abort_not_supported_test("Test requires: '%s'", reason);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+static byte *get_var_key(const byte* var, uint* len,
+ my_bool __attribute__((unused)) t)
+{
+ register char* key;
+ key = ((VAR*)var)->name;
+ *len = ((VAR*)var)->name_len;
+ return (byte*)key;
+}
+
+
+VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
+ int val_len)
+{
+ int val_alloc_len;
+ VAR *tmp_var;
+ if (!name_len && name)
+ name_len = strlen(name);
+ if (!val_len && val)
+ val_len = strlen(val) ;
+ val_alloc_len = val_len + 16; /* room to grow */
+ if (!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
+ + name_len+1, MYF(MY_WME))))
+ die("Out of memory");
+
+ tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
+ tmp_var->alloced = (v == 0);
+
+ if (!(tmp_var->str_val = my_malloc(val_alloc_len+1, MYF(MY_WME))))
+ die("Out of memory");
+
+ memcpy(tmp_var->name, name, name_len);
+ if (val)
+ {
+ memcpy(tmp_var->str_val, val, val_len);
+ tmp_var->str_val[val_len]= 0;
+ }
+ tmp_var->name_len = name_len;
+ tmp_var->str_val_len = val_len;
+ tmp_var->alloced_len = val_alloc_len;
+ tmp_var->int_val = (val) ? atoi(val) : 0;
+ tmp_var->int_dirty = 0;
+ tmp_var->env_s = 0;
+ return tmp_var;
+}
+
+
+void var_free(void *v)
+{
+ my_free(((VAR*) v)->str_val, MYF(MY_WME));
+ if (((VAR*)v)->alloced)
+ my_free((char*) v, MYF(MY_WME));
+}
+
+
+VAR* var_from_env(const char *name, const char *def_val)
+{
+ const char *tmp;
+ VAR *v;
+ if (!(tmp = getenv(name)))
+ tmp = def_val;
+
+ v = var_init(0, name, strlen(name), tmp, strlen(tmp));
+ my_hash_insert(&var_hash, (byte*)v);
+ return v;
+}
+
+
+VAR* var_get(const char *var_name, const char **var_name_end, my_bool raw,
my_bool ignore_not_existing)
{
int digit;
- VAR* v;
+ VAR *v;
DBUG_ENTER("var_get");
- DBUG_PRINT("enter",("var_name: %s",var_name));
+ DBUG_PRINT("enter", ("var_name: %s",var_name));
if (*var_name != '$')
goto err;
@@ -871,16 +1096,16 @@ VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
die("Empty variable");
}
length= (uint) (var_name - save_var_name);
- if (length >= MAX_VAR_NAME)
+ if (length >= MAX_VAR_NAME_LENGTH)
die("Too long variable name: %s", save_var_name);
if (!(v = (VAR*) hash_search(&var_hash, save_var_name, length)))
{
- char buff[MAX_VAR_NAME+1];
+ char buff[MAX_VAR_NAME_LENGTH+1];
strmake(buff, save_var_name, length);
v= var_from_env(buff, "");
}
- var_name--; /* Point at last character */
+ var_name--; /* Point at last character */
}
else
v = var_reg + digit;
@@ -901,7 +1126,8 @@ err:
DBUG_RETURN(0);
}
-static VAR *var_obtain(const char *name, int len)
+
+VAR *var_obtain(const char *name, int len)
{
VAR* v;
if ((v = (VAR*)hash_search(&var_hash, name, len)))
@@ -911,16 +1137,18 @@ static VAR *var_obtain(const char *name, int len)
return v;
}
+
/*
- if variable starts with a $ it is regarded as a local test varable
- if not it is treated as a environment variable, and the corresponding
environment variable will be updated
*/
-int var_set(const char *var_name, const char *var_name_end,
- const char *var_val, const char *var_val_end)
+
+void var_set(const char *var_name, const char *var_name_end,
+ const char *var_val, const char *var_val_end)
{
- int digit, result, env_var= 0;
- VAR* v;
+ int digit, env_var= 0;
+ VAR *v;
DBUG_ENTER("var_set");
DBUG_PRINT("enter", ("var_name: '%.*s' = '%.*s' (length: %d)",
(int) (var_name_end - var_name), var_name,
@@ -932,15 +1160,15 @@ int var_set(const char *var_name, const char *var_name_end,
else
var_name++;
- digit = *var_name - '0';
+ digit= *var_name - '0';
if (!(digit < 10 && digit >= 0))
{
- v = var_obtain(var_name, (uint) (var_name_end - var_name));
+ v= var_obtain(var_name, (uint) (var_name_end - var_name));
}
else
- v = var_reg + digit;
+ v= var_reg + digit;
- result= eval_expr(v, var_val, (const char**) &var_val_end);
+ eval_expr(v, var_val, (const char**) &var_val_end);
if (env_var)
{
@@ -957,7 +1185,183 @@ int var_set(const char *var_name, const char *var_name_end,
putenv(v->env_s);
my_free((gptr)old_env_s, MYF(MY_ALLOW_ZERO_PTR));
}
- DBUG_RETURN(result);
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Store an integer (typically the returncode of the last SQL)
+ statement in the mysqltest builtin variable $mysql_errno, by
+ simulating of a user statement "let $mysql_errno= <integer>"
+*/
+
+void var_set_errno(int sql_errno)
+{
+ /* TODO MASV make easier */
+ const char *var_name= "$mysql_errno";
+ char var_val[21];
+ uint length= my_sprintf(var_val, (var_val, "%d", sql_errno));
+ var_set(var_name, var_name + 12, var_val, var_val + length);
+ return;
+}
+
+
+/*
+ Set variable from the result of a query
+
+ SYNOPSIS
+ var_query_set()
+ var variable to set from query
+ query start of query string to execute
+ query_end end of the query string to execute
+
+
+ DESCRIPTION
+ let @<var_name> = `<query>`
+
+ Execute the query and assign the first row of result to var as
+ a tab separated strings
+
+ Also assign each column of the result set to
+ variable "$<var_name>_<column_name>"
+ Thus the tab separated output can be read from $<var_name> and
+ and each individual column can be read as $<var_name>_<col_name>
+
+*/
+
+void var_query_set(VAR *var, const char *query, const char** query_end)
+{
+ char* end = (char*)((query_end && *query_end) ?
+ *query_end : query + strlen(query));
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ MYSQL* mysql = &cur_con->mysql;
+ DBUG_ENTER("var_query_set");
+ LINT_INIT(res);
+
+ while (end > query && *end != '`')
+ --end;
+ if (query == end)
+ die("Syntax error in query, missing '`'");
+ ++query;
+
+ if (mysql_real_query(mysql, query, (int)(end - query)) ||
+ !(res = mysql_store_result(mysql)))
+ {
+ *end = 0;
+ die("Error running query '%s': %d %s", query,
+ mysql_errno(mysql), mysql_error(mysql));
+ }
+
+ if ((row = mysql_fetch_row(res)) && row[0])
+ {
+ /*
+ Concatenate all row results with tab in between to allow us to work
+ with results from many columns (for example from SHOW VARIABLES)
+ */
+ DYNAMIC_STRING result;
+ uint i;
+ ulong *lengths;
+ char *end;
+#ifdef NOT_YET
+ MYSQL_FIELD *fields= mysql_fetch_fields(res);
+#endif
+
+ init_dynamic_string(&result, "", 2048, 2048);
+ lengths= mysql_fetch_lengths(res);
+ for (i=0; i < mysql_num_fields(res); i++)
+ {
+ if (row[0])
+ {
+#ifdef NOT_YET
+ /* Add to <var_name>_<col_name> */
+ uint j;
+ char var_col_name[MAX_VAR_NAME_LENGTH];
+ uint length= snprintf(var_col_name, MAX_VAR_NAME_LENGTH,
+ "$%s_%s", var->name, fields[i].name);
+ /* Convert characters not allowed in variable names to '_' */
+ for (j= 1; j < length; j++)
+ {
+ if (!my_isvar(charset_info,var_col_name[j]))
+ var_col_name[j]= '_';
+ }
+ var_set(var_col_name, var_col_name + length,
+ row[i], row[i] + lengths[i]);
+#endif
+ /* Add column to tab separated string */
+ dynstr_append_mem(&result, row[i], lengths[i]);
+ }
+ dynstr_append_mem(&result, "\t", 1);
+ }
+ end= result.str + result.length-1;
+ eval_expr(var, result.str, (const char**) &end);
+ dynstr_free(&result);
+ }
+ else
+ eval_expr(var, "", 0);
+
+ mysql_free_result(res);
+ DBUG_VOID_RETURN;
+}
+
+
+void var_copy(VAR *dest, VAR *src)
+{
+ dest->int_val= src->int_val;
+ dest->int_dirty= src->int_dirty;
+
+ /* Alloc/realloc data for str_val in dest */
+ if (dest->alloced_len < src->alloced_len &&
+ !(dest->str_val= dest->str_val
+ ? my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
+ : my_malloc(src->alloced_len, MYF(MY_WME))))
+ die("Out of memory");
+ else
+ dest->alloced_len= src->alloced_len;
+
+ /* Copy str_val data to dest */
+ dest->str_val_len= src->str_val_len;
+ if (src->str_val_len)
+ memcpy(dest->str_val, src->str_val, src->str_val_len);
+}
+
+
+void eval_expr(VAR *v, const char *p, const char **p_end)
+{
+ static int MIN_VAR_ALLOC= 32; /* MASV why 32? */
+ VAR *vp;
+ if (*p == '$')
+ {
+ if ((vp= var_get(p, p_end, 0, 0)))
+ {
+ var_copy(v, vp);
+ return;
+ }
+ }
+ else if (*p == '`')
+ {
+ var_query_set(v, p, p_end);
+ }
+ else
+ {
+ int new_val_len = (p_end && *p_end) ?
+ (int) (*p_end - p) : (int) strlen(p);
+ if (new_val_len + 1 >= v->alloced_len)
+ {
+ v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
+ MIN_VAR_ALLOC : new_val_len + 1;
+ if (!(v->str_val =
+ v->str_val ? my_realloc(v->str_val, v->alloced_len+1,
+ MYF(MY_WME)) :
+ my_malloc(v->alloced_len+1, MYF(MY_WME))))
+ die("Out of memory");
+ }
+ v->str_val_len = new_val_len;
+ memcpy(v->str_val, p, new_val_len);
+ v->str_val[new_val_len] = 0;
+ v->int_val=atoi(p);
+ v->int_dirty=0;
+ }
+ return;
}
@@ -988,103 +1392,53 @@ int open_file(const char *name)
/*
- Check for unexpected "junk" after the end of query
- This is normally caused by missing delimiters
-*/
-
-int check_eol_junk(const char *eol)
-{
- const char *p= eol;
- DBUG_ENTER("check_eol_junk");
- DBUG_PRINT("enter", ("eol: %s", eol));
- /* Remove all spacing chars except new line */
- while (*p && my_isspace(charset_info, *p) && (*p != '\n'))
- p++;
-
- /* Check for extra delimiter */
- if (*p && !strncmp(p, delimiter, delimiter_length))
- die("Extra delimiter \"%s\" found", delimiter);
-
- /* Allow trailing # comment */
- if (*p && *p != '#')
- {
- if (*p == '\n')
- die("Missing delimiter");
- die("End of line junk detected: \"%s\"", p);
- }
- DBUG_RETURN(0);
-}
-
-
-/* ugly long name, but we are following the convention */
-int do_wait_for_slave_to_stop(struct st_query *q __attribute__((unused)))
-{
- MYSQL* mysql = &cur_con->mysql;
- for (;;)
- {
- MYSQL_RES *res;
- MYSQL_ROW row;
- int done;
- LINT_INIT(res);
-
- if (mysql_query(mysql,"show status like 'Slave_running'") ||
- !(res=mysql_store_result(mysql)))
- die("Query failed while probing slave for stop: %s",
- mysql_error(mysql));
- if (!(row=mysql_fetch_row(res)) || !row[1])
- {
- mysql_free_result(res);
- die("Strange result from query while probing slave for stop");
- }
- done = !strcmp(row[1],"OFF");
- mysql_free_result(res);
- if (done)
- break;
- my_sleep(SLAVE_POLL_INTERVAL);
- }
- return 0;
-}
-
-
-/*
Source and execute the given file
SYNOPSIS
- do_source()
- query called command
+ do_source()
+ query called command
DESCRIPTION
- source <file_name>
+ source <file_name>
- Open the file <file_name> and execute it
+ Open the file <file_name> and execute it
*/
-int do_source(struct st_query *query)
+void do_source(struct st_command *command)
{
- char *p= query->first_argument, *name;
- if (!*p)
- die("Missing file name in source");
- name= p;
- while (*p && !my_isspace(charset_info,*p))
- p++;
- if (*p)
- *p++= 0;
- query->last_argument= p;
+ DYNAMIC_STRING ds_filename;
+ const struct command_arg source_args[] = {
+ "filename", ARG_STRING, TRUE, &ds_filename, "File to source"
+ };
+ DBUG_ENTER("do_source");
+
+ check_command_args(command, command->first_argument, source_args,
+ sizeof(source_args)/sizeof(struct command_arg),
+ ' ');
+
/*
- If this file has already been sourced, don't source it again.
- It's already available in the q_lines cache.
+ If this file has already been sourced, don't source it again.
+ It's already available in the q_lines cache.
*/
if (parser.current_line < (parser.read_lines - 1))
- return 0;
- return open_file(name);
+ ; /* Do nothing */
+ else
+ {
+ DBUG_PRINT("info", ("sourcing file: %s", ds_filename.str));
+ open_file(ds_filename.str);
+ }
+
+ dynstr_free(&ds_filename);
+ return;
}
+
#ifdef __WIN__
-/* Variables used for temuprary sh files used for emulating Unix on Windows */
+/* Variables used for temporary sh files used for emulating Unix on Windows */
char tmp_sh_name[64], tmp_sh_cmd[70];
-static void init_tmp_sh_file()
+void init_tmp_sh_file()
{
/* Format a name for the tmp sh file that is unique for this process */
my_snprintf(tmp_sh_name, sizeof(tmp_sh_name), "tmp_%d.sh", getpid());
@@ -1092,13 +1446,15 @@ static void init_tmp_sh_file()
my_snprintf(tmp_sh_cmd, sizeof(tmp_sh_cmd), "sh %s", tmp_sh_name);
}
-static void free_tmp_sh_file()
+
+void free_tmp_sh_file()
{
my_delete(tmp_sh_name, MYF(0));
}
#endif
-FILE* my_popen(DYNAMIC_STRING* ds_cmd, const char* mode)
+
+FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode)
{
#ifdef __WIN__
/* Dump the command into a sh script file and execute with popen */
@@ -1114,49 +1470,49 @@ FILE* my_popen(DYNAMIC_STRING* ds_cmd, const char* mode)
Execute given command.
SYNOPSIS
- do_exec()
- query called command
+ do_exec()
+ query called command
DESCRIPTION
- exec <command>
+ exec <command>
- Execute the text between exec and end of line in a subprocess.
- The error code returned from the subprocess is checked against the
- expected error array, previously set with the --error command.
- It can thus be used to execute a command that shall fail.
+ Execute the text between exec and end of line in a subprocess.
+ The error code returned from the subprocess is checked against the
+ expected error array, previously set with the --error command.
+ It can thus be used to execute a command that shall fail.
NOTE
- Although mysqltest is executed from cygwin shell, the command will be
- executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use
- system for those commands.
+ Although mysqltest is executed from cygwin shell, the command will be
+ executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use
+ system for those commands.
*/
-static void do_exec(struct st_query *query)
+void do_exec(struct st_command *command)
{
int error;
char buf[1024];
FILE *res_file;
- char *cmd= query->first_argument;
+ char *cmd= command->first_argument;
DYNAMIC_STRING ds_cmd;
DBUG_ENTER("do_exec");
DBUG_PRINT("enter", ("cmd: '%s'", cmd));
+ /* Skip leading space */
while (*cmd && my_isspace(charset_info, *cmd))
cmd++;
if (!*cmd)
die("Missing argument in exec");
- query->last_argument= query->end;
+ command->last_argument= command->end;
- init_dynamic_string(&ds_cmd, 0, strlen(cmd)+256, 256);
+ init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
/* Eval the command, thus replacing all environment variables */
- do_eval(&ds_cmd, cmd, TRUE);
- cmd= ds_cmd.str;
+ do_eval(&ds_cmd, cmd, command->end, TRUE);
DBUG_PRINT("info", ("Executing '%s' as '%s'",
- query->first_argument, cmd));
+ command->first_argument, cmd));
- if (!(res_file= my_popen(&ds_cmd, "r")) && query->abort_on_error)
- die("popen(\"%s\", \"r\") failed", query->first_argument);
+ if (!(res_file= my_popen(&ds_cmd, "r")) && command->abort_on_error)
+ die("popen(\"%s\", \"r\") failed", command->first_argument);
while (fgets(buf, sizeof(buf), res_file))
{
@@ -1176,229 +1532,70 @@ static void do_exec(struct st_query *query)
uint status= WEXITSTATUS(error), i;
my_bool ok= 0;
- if (query->abort_on_error)
- die("command \"%s\" failed", query->first_argument);
+ if (command->abort_on_error)
+ die("command \"%s\" failed", command->first_argument);
DBUG_PRINT("info",
("error: %d, status: %d", error, status));
- for (i= 0; i < query->expected_errors; i++)
+ for (i= 0; i < command->expected_errors.count; i++)
{
DBUG_PRINT("info", ("expected error: %d",
- query->expected_errno[i].code.errnum));
- if ((query->expected_errno[i].type == ERR_ERRNO) &&
- (query->expected_errno[i].code.errnum == status))
+ command->expected_errors.err[i].code.errnum));
+ if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
+ (command->expected_errors.err[i].code.errnum == status))
{
ok= 1;
DBUG_PRINT("info", ("command \"%s\" failed with expected error: %d",
- query->first_argument, status));
+ command->first_argument, status));
}
}
if (!ok)
die("command \"%s\" failed with wrong error: %d",
- query->first_argument, status);
+ command->first_argument, status);
}
- else if (query->expected_errno[0].type == ERR_ERRNO &&
- query->expected_errno[0].code.errnum != 0)
+ 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...",
- query->first_argument, query->expected_errno[0].code.errnum);
+ command->first_argument, command->expected_errors.err[0].code.errnum);
}
- free_replace();
+ dynstr_free(&ds_cmd);
DBUG_VOID_RETURN;
}
-/*
- Set variable from the result of a query
-
- SYNOPSIS
- var_query_set()
- var variable to set from query
- query start of query string to execute
- query_end end of the query string to execute
-
-
- DESCRIPTION
- let @<var_name> = `<query>`
-
- Execute the query and assign the first row of result to var as
- a tab separated strings
-
- Also assign each column of the result set to
- variable "$<var_name>_<column_name>"
- Thus the tab separated output can be read from $<var_name> and
- and each individual column can be read as $<var_name>_<col_name>
-
-*/
-
-int var_query_set(VAR* var, const char *query, const char** query_end)
-{
- char* end = (char*)((query_end && *query_end) ?
- *query_end : query + strlen(query));
- MYSQL_RES *res;
- MYSQL_ROW row;
- MYSQL* mysql = &cur_con->mysql;
- DBUG_ENTER("var_query_set");
- LINT_INIT(res);
-
- while (end > query && *end != '`')
- --end;
- if (query == end)
- die("Syntax error in query, missing '`'");
- ++query;
-
- if (mysql_real_query(mysql, query, (int)(end - query)) ||
- !(res = mysql_store_result(mysql)))
- {
- *end = 0;
- die("Error running query '%s': %d: %s", query,
- mysql_errno(mysql) ,mysql_error(mysql));
- }
-
- if ((row = mysql_fetch_row(res)) && row[0])
- {
- /*
- Concatenate all row results with tab in between to allow us to work
- with results from many columns (for example from SHOW VARIABLES)
- */
- DYNAMIC_STRING result;
- uint i;
- ulong *lengths;
- char *end;
-#ifdef NOT_YET
- MYSQL_FIELD *fields= mysql_fetch_fields(res);
-#endif
-
- init_dynamic_string(&result, "", 16384, 65536);
- lengths= mysql_fetch_lengths(res);
- for (i=0; i < mysql_num_fields(res); i++)
- {
- if (row[0])
- {
-#ifdef NOT_YET
- /* Add to <var_name>_<col_name> */
- uint j;
- char var_col_name[MAX_VAR_NAME];
- uint length= snprintf(var_col_name, MAX_VAR_NAME,
- "$%s_%s", var->name, fields[i].name);
- /* Convert characters not allowed in variable names to '_' */
- for (j= 1; j < length; j++)
- {
- if (!my_isvar(charset_info,var_col_name[j]))
- var_col_name[j]= '_';
- }
- var_set(var_col_name, var_col_name + length,
- row[i], row[i] + lengths[i]);
-#endif
- /* Add column to tab separated string */
- dynstr_append_mem(&result, row[i], lengths[i]);
- }
- dynstr_append_mem(&result, "\t", 1);
- }
- end= result.str + result.length-1;
- eval_expr(var, result.str, (const char**) &end);
- dynstr_free(&result);
- }
- else
- eval_expr(var, "", 0);
-
- mysql_free_result(res);
- DBUG_RETURN(0);
-}
-
-void var_copy(VAR *dest, VAR *src)
-{
- dest->int_val= src->int_val;
- dest->int_dirty= src->int_dirty;
-
- /* Alloc/realloc data for str_val in dest */
- if (dest->alloced_len < src->alloced_len &&
- !(dest->str_val= dest->str_val
- ? my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
- : my_malloc(src->alloced_len, MYF(MY_WME))))
- die("Out of memory");
- else
- dest->alloced_len= src->alloced_len;
-
- /* Copy str_val data to dest */
- dest->str_val_len= src->str_val_len;
- if (src->str_val_len)
- memcpy(dest->str_val, src->str_val, src->str_val_len);
-}
-
-int eval_expr(VAR* v, const char *p, const char** p_end)
-{
- VAR* vp;
- if (*p == '$')
- {
- if ((vp = var_get(p,p_end,0,0)))
- {
- var_copy(v, vp);
- return 0;
- }
- }
- else if (*p == '`')
- {
- return var_query_set(v, p, p_end);
- }
- else
- {
- int new_val_len = (p_end && *p_end) ?
- (int) (*p_end - p) : (int) strlen(p);
- if (new_val_len + 1 >= v->alloced_len)
- {
- v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
- MIN_VAR_ALLOC : new_val_len + 1;
- if (!(v->str_val =
- v->str_val ? my_realloc(v->str_val, v->alloced_len+1,
- MYF(MY_WME)) :
- my_malloc(v->alloced_len+1, MYF(MY_WME))))
- die("Out of memory");
- }
- v->str_val_len = new_val_len;
- memcpy(v->str_val, p, new_val_len);
- v->str_val[new_val_len] = 0;
- v->int_val=atoi(p);
- v->int_dirty=0;
- return 0;
- }
-
- die("Invalid expr: %s", p);
- return 1;
-}
-
-
enum enum_operator
{
DO_DEC,
DO_INC
};
+
/*
Decrease or increase the value of a variable
SYNOPSIS
- do_modify_var()
- query called command
- operator operation to perform on the var
+ do_modify_var()
+ query called command
+ operator operation to perform on the var
DESCRIPTION
- dec $var_name
- inc $var_name
+ dec $var_name
+ inc $var_name
*/
-int do_modify_var(struct st_query *query,
+int do_modify_var(struct st_command *command,
enum enum_operator operator)
{
- const char *p= query->first_argument;
+ const char *p= command->first_argument;
VAR* v;
if (!*p)
- die("Missing argument to %.*s", query->first_word_len, query->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 $)",
- query->first_word_len, query->query);
+ command->first_word_len, command->query);
v= var_get(p, &p, 1, 0);
switch (operator) {
case DO_DEC:
@@ -1412,7 +1609,7 @@ int do_modify_var(struct st_query *query,
break;
}
v->int_dirty= 1;
- query->last_argument= (char*)++p;
+ command->last_argument= (char*)++p;
return 0;
}
@@ -1421,10 +1618,10 @@ int do_modify_var(struct st_query *query,
Wrapper for 'system' function
NOTE
- If mysqltest is executed from cygwin shell, the command will be
- executed in the "windows command interpreter" cmd.exe and we prepend "sh"
- to make it be executed by cygwins "bash". Thus commands like "rm",
- "mkdir" as well as shellscripts can executed by "system" in Windows.
+ If mysqltest is executed from cygwin shell, the command will be
+ executed in the "windows command interpreter" cmd.exe and we prepend "sh"
+ to make it be executed by cygwins "bash". Thus commands like "rm",
+ "mkdir" as well as shellscripts can executed by "system" in Windows.
*/
@@ -1441,20 +1638,19 @@ int my_system(DYNAMIC_STRING* ds_cmd)
/*
-
SYNOPSIS
do_system
- command called command
+ command called command
DESCRIPTION
- system <command>
+ system <command>
- Eval the query to expand any $variables in the command.
- Execute the command with the "system" command.
+ Eval the query to expand any $variables in the command.
+ Execute the command with the "system" command.
*/
-void do_system(struct st_query *command)
+void do_system(struct st_command *command)
{
DYNAMIC_STRING ds_cmd;
DBUG_ENTER("do_system");
@@ -1462,10 +1658,10 @@ void do_system(struct st_query *command)
if (strlen(command->first_argument) == 0)
die("Missing arguments to system, nothing to do!");
- init_dynamic_string(&ds_cmd, 0, strlen(command->first_argument) + 64, 256);
+ init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
/* Eval the system command, thus replacing all environment variables */
- do_eval(&ds_cmd, command->first_argument, TRUE);
+ do_eval(&ds_cmd, command->first_argument, command->end, TRUE);
DBUG_PRINT("info", ("running system command '%s' as '%s'",
command->first_argument, ds_cmd.str));
@@ -1487,50 +1683,375 @@ void do_system(struct st_query *command)
/*
+ SYNOPSIS
+ do_remove_file
+ command called command
+
+ DESCRIPTION
+ remove_file <file_name>
+ Remove the file <file_name>
+*/
+
+void do_remove_file(struct st_command *command)
+{
+ int error;
+ DYNAMIC_STRING ds_filename;
+ const struct command_arg rm_args[] = {
+ "filename", ARG_STRING, TRUE, &ds_filename, "File to delete"
+ };
+ DBUG_ENTER("do_remove_file");
+
+ check_command_args(command, command->first_argument,
+ rm_args, sizeof(rm_args)/sizeof(struct command_arg),
+ ' ');
+
+ DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
+ error= my_delete(ds_filename.str, MYF(0)) != 0;
+ handle_command_error(command, error);
+ dynstr_free(&ds_filename);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ SYNOPSIS
+ do_copy_file
+ command command handle
+
+ DESCRIPTION
+ copy_file <from_file> <to_file>
+ Copy <from_file> to <to_file>
+
+ NOTE! Will fail if <to_file> exists
+*/
+
+void do_copy_file(struct st_command *command)
+{
+ int error;
+ DYNAMIC_STRING ds_from_file;
+ DYNAMIC_STRING ds_to_file;
+ const struct command_arg copy_file_args[] = {
+ "from_file", ARG_STRING, TRUE, &ds_from_file, "Filename to copy from",
+ "to_file", ARG_STRING, TRUE, &ds_to_file, "Filename to copy to"
+ };
+ DBUG_ENTER("do_copy_file");
+
+ check_command_args(command, command->first_argument,
+ copy_file_args,
+ sizeof(copy_file_args)/sizeof(struct command_arg),
+ ' ');
+
+ DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
+ error= (my_copy(ds_from_file.str, ds_to_file.str,
+ MYF(MY_DONT_OVERWRITE_FILE)) != 0);
+ handle_command_error(command, error);
+ dynstr_free(&ds_from_file);
+ dynstr_free(&ds_to_file);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ SYNOPSIS
+ do_file_exists
+ command called command
+
+ DESCRIPTION
+ fiile_exist <file_name>
+ Check if file <file_name> exists
+*/
+
+void do_file_exist(struct st_command *command)
+{
+ int error;
+ DYNAMIC_STRING ds_filename;
+ const struct command_arg file_exist_args[] = {
+ "filename", ARG_STRING, TRUE, &ds_filename, "File to check if it exist"
+ };
+ DBUG_ENTER("do_file_exist");
+
+ check_command_args(command, command->first_argument,
+ file_exist_args,
+ sizeof(file_exist_args)/sizeof(struct command_arg),
+ ' ');
+
+ 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);
+ dynstr_free(&ds_filename);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Read characters from line buffer or file. This is needed to allow
+ my_ungetc() to buffer MAX_DELIMITER_LENGTH characters for a file
+
+ NOTE:
+ This works as long as one doesn't change files (with 'source file_name')
+ when there is things pushed into the buffer. This should however not
+ happen for any tests in the test suite.
+*/
+
+int my_getc(FILE *file)
+{
+ if (line_buffer_pos == line_buffer)
+ return fgetc(file);
+ return *--line_buffer_pos;
+}
+
+
+void my_ungetc(int c)
+{
+ *line_buffer_pos++= (char) c;
+}
+
+
+void read_until_delimiter(DYNAMIC_STRING *ds,
+ DYNAMIC_STRING *ds_delimiter)
+{
+ int c;
+ DBUG_ENTER("read_until_delimiter");
+ DBUG_PRINT("enter", ("delimiter: %s, length: %d",
+ ds_delimiter->str, ds_delimiter->length));
+
+ if (ds_delimiter->length > MAX_DELIMITER_LENGTH)
+ die("Max delimiter length(%d) exceeded", MAX_DELIMITER_LENGTH);
+
+ /* Read from file until delimiter is found */
+ while (1)
+ {
+ c= my_getc(cur_file->file);
+
+ if (c == '\n')
+ cur_file->lineno++;
+
+ if (feof(cur_file->file))
+ die("End of file encountered before '%s' delimiter was found",
+ ds_delimiter->str);
+
+ if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
+ {
+ DBUG_PRINT("exit", ("Found delimiter '%s'", ds_delimiter->str));
+ break;
+ }
+ dynstr_append_mem(ds, (const char*)&c, 1);
+ }
+ DBUG_PRINT("exit", ("ds: %s", ds->str));
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ SYNOPSIS
+ do_write_file
+ command called command
+
+ DESCRIPTION
+ write_file <file_name> [<delimiter>];
+ <what to write line 1>
+ <...>
+ < what to write line n>
+ EOF
+
+ --write_file <file_name>;
+ <what to write line 1>
+ <...>
+ < what to write line n>
+ EOF
+
+ Write everything between the "write_file" command and 'delimiter'
+ to "file_name"
+
+ NOTE! Overwrites existing file
+
+ Default <delimiter> is EOF
+
+*/
+
+void do_write_file(struct st_command *command)
+{
+ DYNAMIC_STRING ds_content;
+ DYNAMIC_STRING ds_filename;
+ DYNAMIC_STRING ds_delimiter;
+ const struct command_arg write_file_args[] = {
+ "filename", ARG_STRING, TRUE, &ds_filename, "File to write to",
+ "delimiter", ARG_STRING, FALSE, &ds_delimiter, "Delimiter to read until"
+ };
+ DBUG_ENTER("do_write_file");
+
+ check_command_args(command,
+ command->first_argument,
+ write_file_args,
+ sizeof(write_file_args)/sizeof(struct command_arg),
+ ' ');
+
+ /* If no delimiter was provided, use EOF */
+ if (ds_delimiter.length == 0)
+ dynstr_set(&ds_delimiter, "EOF");
+
+ init_dynamic_string(&ds_content, "", 1024, 1024);
+ read_until_delimiter(&ds_content, &ds_delimiter);
+ DBUG_PRINT("info", ("Writing to file: %s", ds_filename.str));
+ str_to_file(ds_filename.str, ds_content.str, ds_content.length);
+ dynstr_free(&ds_content);
+ dynstr_free(&ds_filename);
+ dynstr_free(&ds_delimiter);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ SYNOPSIS
+ do_perl
+ command command handle
+
+ DESCRIPTION
+ perl [<delimiter>];
+ <perlscript line 1>
+ <...>
+ <perlscript line n>
+ EOF
+
+ Execute everything after "perl" until <delimiter> as perl.
+ Useful for doing more advanced things
+ but still being able to execute it on all platforms.
+
+ Default <delimiter> is EOF
+*/
+
+void do_perl(struct st_command *command)
+{
+ int error;
+ char buf[FN_REFLEN];
+ FILE *res_file;
+ DYNAMIC_STRING ds_script;
+ DYNAMIC_STRING ds_delimiter;
+ const struct command_arg perl_args[] = {
+ "delimiter", ARG_STRING, FALSE, &ds_delimiter, "Delimiter to read until"
+ };
+ DBUG_ENTER("do_perl");
+
+ check_command_args(command,
+ command->first_argument,
+ perl_args,
+ sizeof(perl_args)/sizeof(struct command_arg),
+ ' ');
+
+ /* If no delimiter was provided, use EOF */
+ if (ds_delimiter.length == 0)
+ dynstr_set(&ds_delimiter, "EOF");
+
+ init_dynamic_string(&ds_script, "", 1024, 1024);
+ read_until_delimiter(&ds_script, &ds_delimiter);
+
+ DBUG_PRINT("info", ("Executing perl: %s", ds_script.str));
+
+ /* Format a name for a tmp .pl file that is unique for this process */
+ my_snprintf(buf, sizeof(buf), "%s/tmp/tmp_%d.pl",
+ getenv("MYSQLTEST_VARDIR"), getpid());
+ str_to_file(buf, ds_script.str, ds_script.length);
+
+ /* Format the perl <filename> command */
+ my_snprintf(buf, sizeof(buf), "perl %s/tmp/tmp_%d.pl",
+ getenv("MYSQLTEST_VARDIR"), getpid());
+
+ if (!(res_file= popen(buf, "r")) && command->abort_on_error)
+ die("popen(\"%s\", \"r\") failed", buf);
+
+ while (fgets(buf, sizeof(buf), res_file))
+ {
+ if (disable_result_log)
+ {
+ buf[strlen(buf)-1]=0;
+ DBUG_PRINT("exec_result",("%s", buf));
+ }
+ else
+ {
+ replace_dynstr_append(&ds_res, buf);
+ }
+ }
+ error= pclose(res_file);
+ handle_command_error(command, WEXITSTATUS(error));
+ dynstr_free(&ds_script);
+ dynstr_free(&ds_delimiter);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
Print the content between echo and <delimiter> to result file.
Evaluate all variables in the string before printing, allow
for variable names to be escaped using \
SYNOPSIS
- do_echo()
- q called command
+ do_echo()
+ command called command
DESCRIPTION
- echo text
- Print the text after echo until end of command to result file
+ echo text
+ Print the text after echo until end of command to result file
- echo $<var_name>
- Print the content of the variable <var_name> to result file
+ echo $<var_name>
+ Print the content of the variable <var_name> to result file
- echo Some text $<var_name>
- Print "Some text" plus the content of the variable <var_name> to
- result file
+ echo Some text $<var_name>
+ Print "Some text" plus the content of the variable <var_name> to
+ result file
- echo Some text \$<var_name>
- Print "Some text" plus $<var_name> to result file
+ echo Some text \$<var_name>
+ Print "Some text" plus $<var_name> to result file
*/
-int do_echo(struct st_query *command)
+int do_echo(struct st_command *command)
{
- DYNAMIC_STRING *ds, ds_echo;
+ DYNAMIC_STRING ds_echo;
- ds= &ds_res;
-
- init_dynamic_string(&ds_echo, "", 256, 256);
- do_eval(&ds_echo, command->first_argument, FALSE);
- dynstr_append_mem(ds, ds_echo.str, ds_echo.length);
- dynstr_append_mem(ds, "\n", 1);
+ init_dynamic_string(&ds_echo, "", command->query_len, 256);
+ do_eval(&ds_echo, command->first_argument, command->end, FALSE);
+ dynstr_append_mem(&ds_res, ds_echo.str, ds_echo.length);
+ dynstr_append_mem(&ds_res, "\n", 1);
dynstr_free(&ds_echo);
command->last_argument= command->end;
return(0);
}
-int do_sync_with_master2(long offset)
+void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
{
- MYSQL_RES* res;
+ static int SLAVE_POLL_INTERVAL= 300000;
+ MYSQL* mysql = &cur_con->mysql;
+ for (;;)
+ {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int done;
+ LINT_INIT(res);
+
+ if (mysql_query(mysql,"show status like 'Slave_running'") ||
+ !(res=mysql_store_result(mysql)))
+ die("Query failed while probing slave for stop: %s",
+ mysql_error(mysql));
+ if (!(row=mysql_fetch_row(res)) || !row[1])
+ {
+ mysql_free_result(res);
+ die("Strange result from query while probing slave for stop");
+ }
+ done = !strcmp(row[1],"OFF");
+ mysql_free_result(res);
+ if (done)
+ break;
+ my_sleep(SLAVE_POLL_INTERVAL);
+ }
+ return;
+}
+
+
+void do_sync_with_master2(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 tries= 0;
int rpl_parse;
@@ -1546,7 +2067,7 @@ int do_sync_with_master2(long offset)
wait_for_position:
if (mysql_query(mysql, query_buf))
- die("failed in %s: %d: %s", query_buf, mysql_errno(mysql),
+ die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
mysql_error(mysql));
if (!(res= mysql_store_result(mysql)))
@@ -1569,13 +2090,14 @@ wait_for_position:
if (rpl_parse)
mysql_enable_rpl_parse(mysql);
- return 0;
+ return;
}
-int do_sync_with_master(struct st_query *query)
+
+void do_sync_with_master(struct st_command *command)
{
long offset= 0;
- char *p= query->first_argument;
+ char *p= command->first_argument;
const char *offset_start= p;
if (*offset_start)
{
@@ -1584,20 +2106,22 @@ int do_sync_with_master(struct st_query *query)
if(*p && !my_isspace(charset_info, *p))
die("Invalid integer argument \"%s\"", offset_start);
- query->last_argument= p;
+ command->last_argument= p;
}
- return do_sync_with_master2(offset);
+ do_sync_with_master2(offset);
+ return;
}
+
/*
when ndb binlog is on, this call will wait until last updated epoch
(locally in the mysqld) has been received into the binlog
*/
int do_save_master_pos()
{
- MYSQL_RES* res;
+ MYSQL_RES *res;
MYSQL_ROW row;
- MYSQL* mysql = &cur_con->mysql;
+ MYSQL *mysql = &cur_con->mysql;
const char *query;
int rpl_parse;
@@ -1606,19 +2130,18 @@ int do_save_master_pos()
#ifdef HAVE_NDB_BINLOG
/*
- Wait for ndb binlog to be up-to-date with all changes
- done on the local mysql server
+ Wait for ndb binlog to be up-to-date with all changes
+ done on the local mysql server
*/
{
ulong have_ndbcluster;
if (mysql_query(mysql, query= "show variables like 'have_ndbcluster'"))
- die("At line %u: failed in %s: %d: %s", start_lineno, query,
+ die("'%s' failed: %d %s", query,
mysql_errno(mysql), mysql_error(mysql));
if (!(res= mysql_store_result(mysql)))
- die("line %u: mysql_store_result() retuned NULL for '%s'", start_lineno,
- query);
+ die("mysql_store_result() returned NULL for '%s'", query);
if (!(row= mysql_fetch_row(res)))
- die("line %u: empty result in %s", start_lineno, query);
+ die("Query '%s' returned empty result", query);
have_ndbcluster= strcmp("YES", row[1]) == 0;
mysql_free_result(res);
@@ -1626,7 +2149,7 @@ int do_save_master_pos()
if (have_ndbcluster)
{
ulonglong start_epoch= 0, applied_epoch= 0,
- latest_epoch=0, latest_trans_epoch=0,
+ latest_epoch=0, latest_trans_epoch=0,
latest_handled_binlog_epoch= 0, latest_received_binlog_epoch= 0,
latest_applied_binlog_epoch= 0;
int count= 0;
@@ -1647,11 +2170,10 @@ int do_save_master_pos()
if (count)
sleep(1);
if (mysql_query(mysql, query= "show engine ndb status"))
- die("At line %u: failed in '%s': %d: %s", start_lineno, query,
+ die("failed in '%s': %d %s", query,
mysql_errno(mysql), mysql_error(mysql));
if (!(res= mysql_store_result(mysql)))
- die("line %u: mysql_store_result() retuned NULL for '%s'",
- start_lineno, query);
+ die("mysql_store_result() returned NULL for '%s'", query);
while ((row= mysql_fetch_row(res)))
{
if (strcmp(row[1], binlog) == 0)
@@ -1668,8 +2190,8 @@ int do_save_master_pos()
latest_epoch= strtoull(status, (char**) 0, 10);
}
else
- die("line %u: result does not contain '%s' in '%s'",
- start_lineno, latest_epoch_str, query);
+ die("result does not contain '%s' in '%s'",
+ latest_epoch_str, query);
/* latest_trans_epoch */
while (*status && strncmp(status, latest_trans_epoch_str,
sizeof(latest_trans_epoch_str)-1))
@@ -1680,10 +2202,10 @@ int do_save_master_pos()
latest_trans_epoch= strtoull(status, (char**) 0, 10);
}
else
- die("line %u: result does not contain '%s' in '%s'",
- start_lineno, latest_trans_epoch_str, query);
+ die("result does not contain '%s' in '%s'",
+ latest_trans_epoch_str, query);
/* latest_received_binlog_epoch */
- while (*status &&
+ while (*status &&
strncmp(status, latest_received_binlog_epoch_str,
sizeof(latest_received_binlog_epoch_str)-1))
status++;
@@ -1693,10 +2215,10 @@ int do_save_master_pos()
latest_received_binlog_epoch= strtoull(status, (char**) 0, 10);
}
else
- die("line %u: result does not contain '%s' in '%s'",
- start_lineno, latest_received_binlog_epoch_str, query);
+ die("result does not contain '%s' in '%s'",
+ latest_received_binlog_epoch_str, query);
/* latest_handled_binlog */
- while (*status &&
+ while (*status &&
strncmp(status, latest_handled_binlog_epoch_str,
sizeof(latest_handled_binlog_epoch_str)-1))
status++;
@@ -1706,10 +2228,10 @@ int do_save_master_pos()
latest_handled_binlog_epoch= strtoull(status, (char**) 0, 10);
}
else
- die("line %u: result does not contain '%s' in '%s'",
- start_lineno, latest_handled_binlog_epoch_str, query);
+ die("result does not contain '%s' in '%s'",
+ latest_handled_binlog_epoch_str, query);
/* latest_applied_binlog_epoch */
- while (*status &&
+ while (*status &&
strncmp(status, latest_applied_binlog_epoch_str,
sizeof(latest_applied_binlog_epoch_str)-1))
status++;
@@ -1719,16 +2241,16 @@ int do_save_master_pos()
latest_applied_binlog_epoch= strtoull(status, (char**) 0, 10);
}
else
- die("line %u: result does not contain '%s' in '%s'",
- start_lineno, latest_applied_binlog_epoch_str, query);
+ die("result does not contain '%s' in '%s'",
+ latest_applied_binlog_epoch_str, query);
if (count == 0)
start_epoch= latest_trans_epoch;
break;
}
}
if (!row)
- die("line %u: result does not contain '%s' in '%s'",
- start_lineno, binlog, query);
+ die("result does not contain '%s' in '%s'",
+ binlog, query);
if (latest_applied_binlog_epoch > applied_epoch)
count= 0;
applied_epoch= latest_applied_binlog_epoch;
@@ -1745,7 +2267,7 @@ int do_save_master_pos()
}
#endif
if (mysql_query(mysql, query= "show master status"))
- die("failed in show master status: %d: %s",
+ die("failed in 'show master status': %d %s",
mysql_errno(mysql), mysql_error(mysql));
if (!(res = mysql_store_result(mysql)))
@@ -1767,28 +2289,29 @@ int do_save_master_pos()
Assign the variable <var_name> with <var_val>
SYNOPSIS
- do_let()
- query called command
+ do_let()
+ query called command
DESCRIPTION
- let $<var_name>=<var_val><delimiter>
+ let $<var_name>=<var_val><delimiter>
- <var_name> - is the string string found between the $ and =
- <var_val> - is the content between the = and <delimiter>, it may span
- multiple line and contain any characters except <delimiter>
- <delimiter> - is a string containing of one or more chars, default is ;
+ <var_name> - is the string string found between the $ and =
+ <var_val> - is the content between the = and <delimiter>, it may span
+ multiple line and contain any characters except <delimiter>
+ <delimiter> - is a string containing of one or more chars, default is ;
RETURN VALUES
- Program will die if error detected
+ Program will die if error detected
*/
-int do_let(struct st_query *query)
+void do_let(struct st_command *command)
{
- int ret;
- char *p= query->first_argument;
+ char *p= command->first_argument;
char *var_name, *var_name_end;
DYNAMIC_STRING let_rhs_expr;
+ DBUG_ENTER("do_let");
+
init_dynamic_string(&let_rhs_expr, "", 512, 2048);
/* Find <var_name> */
@@ -1810,34 +2333,18 @@ int do_let(struct st_query *query)
while (*p && my_isspace(charset_info,*p))
p++;
- do_eval(&let_rhs_expr, p, FALSE);
+ do_eval(&let_rhs_expr, p, command->end, FALSE);
- query->last_argument= query->end;
+ command->last_argument= command->end;
/* Assign var_val to var_name */
- ret= var_set(var_name, var_name_end, let_rhs_expr.str,
- (let_rhs_expr.str + let_rhs_expr.length));
+ var_set(var_name, var_name_end, let_rhs_expr.str,
+ (let_rhs_expr.str + let_rhs_expr.length));
dynstr_free(&let_rhs_expr);
-
- return(ret);
-}
-
-
-/*
- Store an integer (typically the returncode of the last SQL)
- statement in the mysqltest builtin variable $mysql_errno, by
- simulating of a user statement "let $mysql_errno= <integer>"
-*/
-
-int var_set_errno(int sql_errno)
-{
- const char *var_name= "$mysql_errno";
- char var_val[21];
- uint length= my_sprintf(var_val, (var_val, "%d", sql_errno));
- return var_set(var_name, var_name + 12, var_val, var_val + length);
+ DBUG_VOID_RETURN;
}
-int do_rpl_probe(struct st_query *query __attribute__((unused)))
+int do_rpl_probe(struct st_command *command __attribute__((unused)))
{
DBUG_ENTER("do_rpl_probe");
if (mysql_rpl_probe(&cur_con->mysql))
@@ -1846,14 +2353,14 @@ int do_rpl_probe(struct st_query *query __attribute__((unused)))
}
-int do_enable_rpl_parse(struct st_query *query __attribute__((unused)))
+int do_enable_rpl_parse(struct st_command *command __attribute__((unused)))
{
mysql_enable_rpl_parse(&cur_con->mysql);
return 0;
}
-int do_disable_rpl_parse(struct st_query *query __attribute__((unused)))
+int do_disable_rpl_parse(struct st_command *command __attribute__((unused)))
{
mysql_disable_rpl_parse(&cur_con->mysql);
return 0;
@@ -1861,17 +2368,17 @@ int do_disable_rpl_parse(struct st_query *query __attribute__((unused)))
/*
- Sleep the number of specifed seconds
+ Sleep the number of specified seconds
SYNOPSIS
- do_sleep()
- q called command
- real_sleep use the value from opt_sleep as number of seconds to sleep
- if real_sleep is false
+ do_sleep()
+ q called command
+ real_sleep use the value from opt_sleep as number of seconds to sleep
+ if real_sleep is false
DESCRIPTION
- sleep <seconds>
- real_sleep <seconds>
+ sleep <seconds>
+ real_sleep <seconds>
The difference between the sleep and real_sleep commands is that sleep
uses the delay from the --sleep command-line option if there is one.
@@ -1882,26 +2389,26 @@ int do_disable_rpl_parse(struct st_query *query __attribute__((unused)))
used for cpu-independent delays.
*/
-int do_sleep(struct st_query *query, my_bool real_sleep)
+int do_sleep(struct st_command *command, my_bool real_sleep)
{
int error= 0;
- char *p= query->first_argument;
- char *sleep_start, *sleep_end= query->end;
+ char *p= command->first_argument;
+ char *sleep_start, *sleep_end= command->end;
double sleep_val;
while (my_isspace(charset_info, *p))
p++;
if (!*p)
- die("Missing argument to %.*s", query->first_word_len, query->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))
- die("Invalid argument to %.*s \"%s\"", query->first_word_len, query->query,
- query->first_argument);
+ die("Invalid argument to %.*s \"%s\"", command->first_word_len,
+ command->query,command->first_argument);
sleep_val= my_strtod(sleep_start, &sleep_end, &error);
if (error)
- die("Invalid argument to %.*s \"%s\"", query->first_word_len, query->query,
- query->first_argument);
+ die("Invalid argument to %.*s \"%s\"", command->first_word_len,
+ command->query, command->first_argument);
/* Fixed sleep time selected by --sleep option */
if (opt_sleep >= 0 && !real_sleep)
@@ -1910,13 +2417,15 @@ int do_sleep(struct st_query *query, my_bool real_sleep)
DBUG_PRINT("info", ("sleep_val: %f", sleep_val));
if (sleep_val)
my_sleep((ulong) (sleep_val * 1000000L));
- query->last_argument= sleep_end;
+ command->last_argument= sleep_end;
return 0;
}
-static void get_file_name(char *filename, struct st_query *q)
+
+void do_get_file_name(struct st_command *command,
+ char* dest, uint dest_max_len)
{
- char *p= q->first_argument, *name;
+ char *p= command->first_argument, *name;
if (!*p)
die("Missing file name argument");
name= p;
@@ -1924,13 +2433,14 @@ static void get_file_name(char *filename, struct st_query *q)
p++;
if (*p)
*p++= 0;
- q->last_argument= p;
- strmake(filename, name, FN_REFLEN);
+ command->last_argument= p;
+ strmake(dest, name, dest_max_len);
}
-static void set_charset(struct st_query *q)
+
+void do_set_charset(struct st_command *command)
{
- char *charset_name= q->first_argument;
+ char *charset_name= command->first_argument;
char *p;
if (!charset_name || !*charset_name)
@@ -1941,78 +2451,182 @@ static void set_charset(struct st_query *q)
p++;
if(*p)
*p++= 0;
- q->last_argument= p;
+ command->last_argument= p;
charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
if (!charset_info)
abort_not_supported_test("Test requires charset '%s'", charset_name);
}
-static uint get_errcodes(match_err *to,struct st_query *q)
+
+#if MYSQL_VERSION_ID >= 50000
+/* List of error names to error codes, available from 5.0 */
+typedef struct
+{
+ const char *name;
+ uint code;
+} st_error;
+
+static st_error global_error_names[] =
+{
+#include <mysqld_ername.h>
+ { 0, 0 }
+};
+
+uint get_errcode_from_name(char *error_name, char *error_end)
{
- char *p= q->first_argument;
+ /* SQL error as string */
+ st_error *e= global_error_names;
+
+ DBUG_ENTER("get_errcode_from_name");
+ DBUG_PRINT("enter", ("error_name: %s", error_name));
+
+ /* Loop through the array of known error names */
+ for (; e->name; e++)
+ {
+ /*
+ If we get a match, we need to check the length of the name we
+ matched against in case it was longer than what we are checking
+ (as in ER_WRONG_VALUE vs. ER_WRONG_VALUE_COUNT).
+ */
+ if (!strncmp(error_name, e->name, (int) (error_end - error_name)) &&
+ (uint) strlen(e->name) == (uint) (error_end - error_name))
+ {
+ DBUG_RETURN(e->code);
+ }
+ }
+ if (!e->name)
+ die("Unknown SQL error name '%s'", error_name);
+ DBUG_RETURN(0);
+}
+#else
+uint get_errcode_from_name(char *error_name __attribute__((unused)),
+ char *error_end __attribute__((unused)))
+{
+ abort_not_in_this_version();
+ return 0; /* Never reached */
+}
+#endif
+
+
+
+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;
- DBUG_ENTER("get_errcodes");
+ DBUG_ENTER("do_get_errcodes");
if (!*p)
- die("Missing argument in %s", q->query);
+ die("Missing argument(s) to 'error'");
do
{
+ char *end;
+
+ /* Skip leading spaces */
+ while (*p && *p == ' ')
+ p++;
+
+ /* Find end */
+ end= p;
+ while (*end && *end != ',' && *end != ' ')
+ end++;
+
if (*p == 'S')
{
- /* SQLSTATE string */
- char *end= ++p + SQLSTATE_LENGTH;
- char *to_ptr= to[count].code.sqlstate;
+ char *to_ptr= to->code.sqlstate;
- for (; my_isalnum(charset_info, *p) && p != end; p++)
- *to_ptr++= *p;
- *to_ptr= 0;
+ /*
+ SQLSTATE string
+ - Must be SQLSTATE_LENGTH long
+ - May contain only digits[0-9] and _uppercase_ letters
+ */
+ p++; /* Step past the S */
+ if ((end - p) != SQLSTATE_LENGTH)
+ die("The sqlstate must be exactly %d chars long", SQLSTATE_LENGTH);
+
+ /* Check sqlstate string validity */
+ while (*p && p < end)
+ {
+ if (my_isdigit(charset_info, *p) || my_isupper(charset_info, *p))
+ *to_ptr++= *p++;
+ else
+ die("The sqlstate may only consist of digits[0-9] " \
+ "and _uppercase_ letters");
+ }
- to[count].type= ERR_SQLSTATE;
+ *to_ptr= 0;
+ to->type= ERR_SQLSTATE;
+ DBUG_PRINT("info", ("ERR_SQLSTATE: %d", to->code.sqlstate));
+ }
+ else if (*p == 's')
+ {
+ die("The sqlstate definition must start with an uppercase S");
}
else if (*p == 'E')
{
- /* SQL error as string */
- st_error *e= global_error;
- char *start= p++;
+ /* Error name string */
- for (; *p == '_' || my_isalnum(charset_info, *p); p++)
- ;
- for (; e->name; e++)
- {
- /*
- If we get a match, we need to check the length of the name we
- matched against in case it was longer than what we are checking
- (as in ER_WRONG_VALUE vs. ER_WRONG_VALUE_COUNT).
- */
- if (!strncmp(start, e->name, (int) (p - start)) &&
- (uint) strlen(e->name) == (uint) (p - start))
- {
- to[count].code.errnum= (uint) e->code;
- to[count].type= ERR_ERRNO;
- break;
- }
- }
- if (!e->name)
- die("Unknown SQL error '%s'", start);
+ DBUG_PRINT("info", ("Error name: %s", p));
+ to->code.errnum= get_errcode_from_name(p, end);
+ to->type= ERR_ERRNO;
+ DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum));
+ }
+ else if (*p == 'e')
+ {
+ die("The error name definition must start with an uppercase E");
}
else
{
long val;
+ char *start= p;
+ /* Check that the string passed to str2int only contain digits */
+ while (*p && p != end)
+ {
+ if (!my_isdigit(charset_info, *p))
+ die("Invalid argument to error: '%s' - "\
+ "the errno may only consist of digits[0-9]",
+ command->first_argument);
+ p++;
+ }
- if (!(p= str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val)))
- die("Invalid argument in %s", q->query);
- to[count].code.errnum= (uint) val;
- to[count].type= ERR_ERRNO;
+ /* Convert the sting to int */
+ if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
+ die("Invalid argument to error: '%s'", command->first_argument);
+
+ to->code.errnum= (uint) val;
+ to->type= ERR_ERRNO;
+ DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum));
}
+ to++;
count++;
- } while (*(p++) == ',');
- q->last_argument= (p - 1);
- to[count].type= ERR_EMPTY; /* End of data */
- DBUG_RETURN(count);
+
+ if (count >= (sizeof(saved_expected_errors.err) /
+ sizeof(struct st_match_err)))
+ die("Too many errorcodes specified");
+
+ /* Set pointer to the end of the last error code */
+ p= end;
+
+ /* Find next ',' */
+ while (*p && *p != ',')
+ p++;
+
+ if (*p)
+ p++; /* Step past ',' */
+
+ } while (*p);
+
+ command->last_argument= p;
+ to->type= ERR_EMPTY; /* End of data */
+
+ DBUG_PRINT("info", ("Expected errors: %d", count));
+ saved_expected_errors.count= count;
+ DBUG_VOID_RETURN;
}
+
/*
Get a string; Return ptr to end of string
Strings may be surrounded by " or '
@@ -2020,11 +2634,10 @@ static uint get_errcodes(match_err *to,struct st_query *q)
If string is a '$variable', return the value of the variable.
*/
-
-static char *get_string(char **to_ptr, char **from_ptr,
- struct st_query *q)
+char *get_string(char **to_ptr, char **from_ptr,
+ struct st_command *command)
{
- reg1 char c,sep;
+ char c, sep;
char *to= *to_ptr, *from= *from_ptr, *start=to;
DBUG_ENTER("get_string");
@@ -2070,7 +2683,7 @@ static char *get_string(char **to_ptr, char **from_ptr,
*to++=c;
}
if (*from != ' ' && *from)
- die("Wrong string argument in %s", q->query);
+ die("Wrong string argument in %s", command->query);
while (my_isspace(charset_info,*from)) /* Point to next string */
from++;
@@ -2093,282 +2706,25 @@ static char *get_string(char **to_ptr, char **from_ptr,
DBUG_RETURN(start);
}
-/*
- Finds the next (non-escaped) '/' in the expression.
- (If the character '/' is needed, it can be escaped using '\'.)
-*/
-
-#define PARSE_REGEX_ARG \
- while (p < expr_end) \
- {\
- char c= *p;\
- if (c == '/')\
- {\
- if (last_c == '\\')\
- {\
- buf_p[-1]= '/';\
- }\
- else\
- {\
- *buf_p++ = 0;\
- break;\
- } \
- } \
- else\
- *buf_p++ = c;\
- \
- last_c= c;\
- p++;\
- } \
-
-/*
- Initializes the regular substitution expression to be used in the
- result output of test.
-
- Returns: st_replace_regex struct with pairs of substitutions
-*/
-
-static struct st_replace_regex* init_replace_regex(char* expr)
-{
- struct st_replace_regex* res;
- char* buf,*expr_end;
- char* p;
- char* buf_p;
- uint expr_len= strlen(expr);
- char last_c = 0;
- struct st_regex reg;
-
- /* my_malloc() will die on fail with MY_FAE */
- res=(struct st_replace_regex*)my_malloc(
- sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME));
- my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
-
- buf= (char*)res + sizeof(*res);
- expr_end= expr + expr_len;
- p= expr;
- buf_p= buf;
-
- /* for each regexp substitution statement */
- while (p < expr_end)
- {
- bzero(&reg,sizeof(reg));
- /* find the start of the statement */
- while (p < expr_end)
- {
- if (*p == '/')
- break;
- p++;
- }
-
- if (p == expr_end || ++p == expr_end)
- {
- if (res->regex_arr.elements)
- break;
- else
- goto err;
- }
- /* we found the start */
- reg.pattern= buf_p;
-
- /* Find first argument -- pattern string to be removed */
- PARSE_REGEX_ARG
-
- if (p == expr_end || ++p == expr_end)
- goto err;
-
- /* buf_p now points to the replacement pattern terminated with \0 */
- reg.replace= buf_p;
-
- /* Find second argument -- replace string to replace pattern */
- PARSE_REGEX_ARG
-
- if (p == expr_end)
- goto err;
-
- /* skip the ending '/' in the statement */
- p++;
-
- /* Check if we should do matching case insensitive */
- if (p < expr_end && *p == 'i')
- reg.icase= 1;
-
- /* done parsing the statement, now place it in regex_arr */
- if (insert_dynamic(&res->regex_arr,(gptr) &reg))
- die("Out of memory");
- }
- res->odd_buf_len= res->even_buf_len= 8192;
- res->even_buf= (char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
- res->odd_buf= (char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
- res->buf= res->even_buf;
-
- return res;
-
-err:
- my_free((gptr)res,0);
- die("Error parsing replace_regex \"%s\"", expr);
- return 0;
-}
-
-/*
- Execute all substitutions on val.
-
- Returns: true if substituition was made, false otherwise
- Side-effect: Sets r->buf to be the buffer with all substitutions done.
-
- IN:
- struct st_replace_regex* r
- char* val
- Out:
- struct st_replace_regex* r
- r->buf points at the resulting buffer
- r->even_buf and r->odd_buf might have been reallocated
- r->even_buf_len and r->odd_buf_len might have been changed
-
- TODO: at some point figure out if there is a way to do everything
- in one pass
-*/
-
-static int multi_reg_replace(struct st_replace_regex* r,char* val)
-{
- uint i;
- char* in_buf, *out_buf;
- int* buf_len_p;
-
- in_buf= val;
- out_buf= r->even_buf;
- buf_len_p= &r->even_buf_len;
- r->buf= 0;
-
- /* For each substitution, do the replace */
- for (i= 0; i < r->regex_arr.elements; i++)
- {
- struct st_regex re;
- char* save_out_buf= out_buf;
-
- get_dynamic(&r->regex_arr,(gptr)&re,i);
-
- if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
- in_buf, re.icase))
- {
- /* if the buffer has been reallocated, make adjustements */
- if (save_out_buf != out_buf)
- {
- if (save_out_buf == r->even_buf)
- r->even_buf= out_buf;
- else
- r->odd_buf= out_buf;
- }
-
- r->buf= out_buf;
- if (in_buf == val)
- in_buf= r->odd_buf;
-
- swap_variables(char*,in_buf,out_buf);
-
- buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
- &r->odd_buf_len;
- }
- }
-
- return (r->buf == 0);
-}
-
-/*
- Parse the regular expression to be used in all result files
- from now on.
-
- The syntax is --replace_regex /from/to/i /from/to/i ...
- i means case-insensitive match. If omitted, the match is
- case-sensitive
-
-*/
-static void get_replace_regex(struct st_query *q)
-{
- char *expr= q->first_argument;
- free_replace_regex();
- if (!(glob_replace_regex=init_replace_regex(expr)))
- die("Could not init replace_regex");
- q->last_argument= q->end;
-}
-
-/*
- Get arguments for replace. The syntax is:
- replace from to [from to ...]
- Where each argument may be quoted with ' or "
- A argument may also be a variable, in which case the value of the
- variable is replaced.
-*/
-
-static void get_replace(struct st_query *q)
+void set_reconnect(MYSQL* mysql, int val)
{
- uint i;
- char *from= q->first_argument;
- char *buff,*start;
- char word_end_chars[256],*pos;
- POINTER_ARRAY to_array,from_array;
- DBUG_ENTER("get_replace");
-
- free_replace();
-
- bzero((char*) &to_array,sizeof(to_array));
- bzero((char*) &from_array,sizeof(from_array));
- if (!*from)
- die("Missing argument in %s", q->query);
- start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
- while (*from)
- {
- char *to=buff;
- to=get_string(&buff, &from, q);
- if (!*from)
- die("Wrong number of arguments to replace_result in '%s'", q->query);
- insert_pointer_name(&from_array,to);
- to=get_string(&buff, &from, q);
- insert_pointer_name(&to_array,to);
- }
- for (i=1,pos=word_end_chars ; i < 256 ; i++)
- if (my_isspace(charset_info,i))
- *pos++= i;
- *pos=0; /* End pointer */
- if (!(glob_replace=init_replace((char**) from_array.typelib.type_names,
- (char**) to_array.typelib.type_names,
- (uint) from_array.typelib.count,
- word_end_chars)))
- die("Can't initialize replace from '%s'", q->query);
- free_pointer_array(&from_array);
- free_pointer_array(&to_array);
- my_free(start, MYF(0));
- q->last_argument= q->end;
+ my_bool reconnect= val;
+ DBUG_ENTER("set_reconnect");
+ DBUG_PRINT("info", ("val: %d", val));
+#if MYSQL_VERSION_ID < 50000
+ mysql->reconnect= reconnect;
+#else
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
+#endif
DBUG_VOID_RETURN;
}
-static void free_replace_regex()
-{
- if (glob_replace_regex)
- {
- my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
- my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*) glob_replace_regex,MYF(0));
- glob_replace_regex=0;
- }
-}
-
-void free_replace()
-{
- DBUG_ENTER("free_replace");
- if (glob_replace)
- {
- my_free((char*) glob_replace,MYF(0));
- glob_replace=0;
- }
- DBUG_VOID_RETURN;
-}
-
-struct connection * find_connection_by_name(const char *name)
+struct st_connection * find_connection_by_name(const char *name)
{
- struct connection *con;
- for (con= cons; con < next_con; con++)
+ struct st_connection *con;
+ for (con= connections; con < next_con; con++)
{
if (!strcmp(con->name, name))
{
@@ -2390,10 +2746,10 @@ int select_connection_name(const char *name)
}
-int select_connection(struct st_query *query)
+int select_connection(struct st_command *command)
{
char *name;
- char *p= query->first_argument;
+ char *p= command->first_argument;
DBUG_ENTER("select_connection");
if (!*p)
@@ -2403,15 +2759,16 @@ int select_connection(struct st_query *query)
p++;
if (*p)
*p++= 0;
- query->last_argument= p;
+ command->last_argument= p;
return select_connection_name(name);
}
-int close_connection(struct st_query *q)
+void do_close_connection(struct st_command *command)
{
- char *p= q->first_argument, *name;
- struct connection *con;
+ char *p= command->first_argument, *name;
+ struct st_connection *con;
+
DBUG_ENTER("close_connection");
DBUG_PRINT("enter",("name: '%s'",p));
@@ -2423,13 +2780,17 @@ int close_connection(struct st_query *q)
if (*p)
*p++= 0;
- q->last_argument= p;
- for (con= cons; con < next_con; con++)
+ command->last_argument= p;
+
+ /* Loop through connection pool for connection to close */
+ for (con= connections; con < next_con; con++)
{
+ DBUG_PRINT("info", ("con->name: %s", con->name));
if (!strcmp(con->name, name))
{
+ DBUG_PRINT("info", ("Closing connection %s", con->name));
#ifndef EMBEDDED_LIBRARY
- if (q->type == Q_DIRTY_CLOSE)
+ if (command->type == Q_DIRTY_CLOSE)
{
if (con->mysql.net.vio)
{
@@ -2443,59 +2804,19 @@ int close_connection(struct st_query *q)
mysql_close(con->util_mysql);
con->util_mysql= 0;
my_free(con->name, MYF(0));
+
/*
- When the connection is closed set name to "closed_connection"
- to make it possible to reuse the connection name.
- The connection slot will not be reused
- */
+ When the connection is closed set name to "closed_connection"
+ to make it possible to reuse the connection name.
+ The connection slot will not be reused
+ */
if (!(con->name = my_strdup("closed_connection", MYF(MY_WME))))
die("Out of memory");
- DBUG_RETURN(0);
+
+ DBUG_VOID_RETURN;
}
}
die("connection '%s' not found in connection pool", name);
- DBUG_RETURN(1); /* Never reached */
-}
-
-
-/*
- This one now is a hack - we may want to improve in in the
- future to handle quotes. For now we assume that anything that is not
- a comma, a space or ) belongs to the argument. space is a chopper, comma or
- ) are delimiters/terminators
-
- SYNOPSIS
- safe_get_param
- str - string to get param from
- arg - pointer to string where result will be stored
- msg - Message to display if param is not found
- if msg is 0 this param is not required and param may be empty
-
- RETURNS
- pointer to str after param
-
-*/
-
-char* safe_get_param(char *str, char** arg, const char *msg)
-{
- DBUG_ENTER("safe_get_param");
- if(!*str)
- {
- if (msg)
- die(msg);
- *arg= str;
- DBUG_RETURN(str);
- }
- while (*str && my_isspace(charset_info,*str))
- str++;
- *arg= str;
- while (*str && *str != ',' && *str != ')')
- str++;
- if (msg && !*arg)
- die(msg);
-
- *str++= 0;
- DBUG_RETURN(str);
}
@@ -2503,54 +2824,60 @@ char* safe_get_param(char *str, char** arg, const char *msg)
Connect to a server doing several retries if needed.
SYNOPSIS
- safe_connect()
- con - connection structure to be used
- host, user, pass, - connection parameters
- db, port, sock
+ safe_connect()
+ con - connection structure to be used
+ host, user, pass, - connection parameters
+ db, port, sock
NOTE
- Sometimes in a test the client starts before
- the server - to solve the problem, we try again
- after some sleep if connection fails the first
- time
+ Sometimes in a test the client starts before
+ the server - to solve the problem, we try again
+ after some sleep if connection fails the first
+ time
- This function will try to connect to the given server
- "opt_max_connect_retries" times and sleep "connection_retry_sleep"
- seconds between attempts before finally giving up.
- This helps in situation when the client starts
- before the server (which happens sometimes).
- It will ignore any errors during these retries. One should use
- connect_n_handle_errors() if he expects a connection error and wants
- handle as if it was an error from a usual statement.
+ This function will try to connect to the given server
+ "opt_max_connect_retries" times and sleep "connection_retry_sleep"
+ seconds between attempts before finally giving up.
+ This helps in situation when the client starts
+ before the server (which happens sometimes).
+ It will only ignore connection errors during these retries.
- RETURN VALUE
- 0 - success, non-0 - failure
*/
-int safe_connect(MYSQL* mysql, const char *host, const char *user,
- const char *pass, const char *db, int port, const char *sock)
+void safe_connect(MYSQL* mysql, const char *name, const char *host,
+ const char *user, const char *pass, const char *db,
+ int port, const char *sock)
{
- int con_error= 1;
- my_bool reconnect= 1;
+ int failed_attempts= 0;
static ulong connection_retry_sleep= 100000; /* Microseconds */
- int i;
- for (i= 0; i < opt_max_connect_retries; i++)
+
+ DBUG_ENTER("safe_connect");
+ while(!mysql_real_connect(mysql, host,user, pass, db, port, sock,
+ CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
{
- if (mysql_real_connect(mysql, host,user, pass, db, port, sock,
- CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
+ /*
+ Connect failed
+
+ Only allow retry if this was an error indicating the server
+ could not be contacted
+ */
+
+ if (mysql_errno(mysql) == CR_CONNECTION_ERROR &&
+ failed_attempts < opt_max_connect_retries)
+ my_sleep(connection_retry_sleep);
+ else
{
- con_error= 0;
- break;
+ if (failed_attempts > 0)
+ die("Could not open connection '%s' after %d attempts: %d %s", name,
+ failed_attempts, mysql_errno(mysql), mysql_error(mysql));
+ else
+ die("Could not open connection '%s': %d %s", name,
+ mysql_errno(mysql), mysql_error(mysql));
}
- my_sleep(connection_retry_sleep);
+ failed_attempts++;
}
- /*
- TODO: change this to 0 in future versions, but the 'kill' test relies on
- existing behavior
- */
- mysql_options(mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
- return con_error;
+ DBUG_VOID_RETURN;
}
@@ -2558,45 +2885,41 @@ int safe_connect(MYSQL* mysql, const char *host, const char *user,
Connect to a server and handle connection errors in case they occur.
SYNOPSIS
- connect_n_handle_errors()
- q - context of connect "query" (command)
- con - connection structure to be used
- host, user, pass, - connection parameters
- db, port, sock
- create_conn - out parameter, set to zero if connection was
- not established and is not touched otherwise
+ connect_n_handle_errors()
+ q - context of connect "query" (command)
+ con - connection structure to be used
+ host, user, pass, - connection parameters
+ db, port, sock
DESCRIPTION
- This function will try to establish a connection to server and handle
- possible errors in the same manner as if "connect" was usual SQL-statement
- (If error is expected it will ignore it once it occurs and log the
- "statement" to the query log).
- Unlike safe_connect() it won't do several attempts.
+ This function will try to establish a connection to server and handle
+ possible errors in the same manner as if "connect" was usual SQL-statement
+ (If error is expected it will ignore it once it occurs and log the
+ "statement" to the query log).
+ Unlike safe_connect() it won't do several attempts.
+
+ RETURN VALUES
+ 1 - Connected
+ 0 - Not connected
- RETURN VALUE
- 0 - success, non-0 - failure
*/
-int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
+int connect_n_handle_errors(struct st_command *command,
+ MYSQL* con, const char* host,
const char* user, const char* pass,
- const char* db, int port, const char* sock,
- int* create_conn)
+ const char* db, int port, const char* sock)
{
DYNAMIC_STRING *ds;
- my_bool reconnect= 1;
- int error= 0;
ds= &ds_res;
- if (!disable_query_log)
+ /* Only log if an error is expected */
+ if (!command->abort_on_error &&
+ !disable_query_log)
{
/*
- It is nice to have connect() statement logged in result file
- in this case.
- QQ: Should we do this only if we are expecting an error ?
+ Log the connect to result log
*/
- char port_buff[22]; /* This should be enough for any int */
- char *port_end;
dynstr_append_mem(ds, "connect(", 8);
replace_dynstr_append(ds, host);
dynstr_append_mem(ds, ",", 1);
@@ -2607,8 +2930,7 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
if (db)
replace_dynstr_append(ds, db);
dynstr_append_mem(ds, ",", 1);
- port_end= int10_to_str(port, port_buff, 10);
- replace_dynstr_append_mem(ds, port_buff, port_end - port_buff);
+ replace_dynstr_append_uint(ds, port);
dynstr_append_mem(ds, ",", 1);
if (sock)
replace_dynstr_append(ds, sock);
@@ -2619,148 +2941,150 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
if (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
CLIENT_MULTI_STATEMENTS))
{
- handle_error("connect", q, mysql_errno(con), mysql_error(con),
+ handle_error(command, mysql_errno(con), mysql_error(con),
mysql_sqlstate(con), ds);
- *create_conn= 0;
- goto err;
+ return 0; /* Not connected */
}
- handle_no_error(q);
-
- /*
- TODO: change this to 0 in future versions, but the 'kill' test relies on
- existing behavior
- */
- mysql_options(con, MYSQL_OPT_RECONNECT, (char *)&reconnect);
-
-err:
- free_replace();
- free_replace_regex();
- return error;
+ handle_no_error(command);
+ return 1; /* Connected */
}
/*
Open a new connection to MySQL Server with the parameters
- specified
+ specified. Make the new connection the current connection.
SYNOPSIS
- do_connect()
- q called command
+ do_connect()
+ q called command
DESCRIPTION
- connect(<name>,<host>,<user>,<pass>,<db>,[<port>,<sock>[<opts>]]);
-
- <name> - name of the new connection
- <host> - hostname of server
- <user> - user to connect as
- <pass> - password used when connecting
- <db> - initial db when connected
- <port> - server port
- <sock> - server socket
- <opts> - options to use for the connection
- SSL - use SSL if available
- COMPRESS - use compression if available
-
- */
-
-int do_connect(struct st_query *q)
-{
- char *con_name, *con_user,*con_pass, *con_host, *con_port_str,
- *con_db, *con_sock, *con_options;
- char *con_buf, *p;
- char buff[FN_REFLEN];
- int con_port;
- bool con_ssl= 0;
- bool con_compress= 0;
- int free_con_sock= 0;
- int error= 0;
- int create_conn= 1;
- VAR *var_port, *var_sock;
+ connect(<name>,<host>,<user>,[<pass>,[<db>,[<port>,<sock>[<opts>]]]]);
+ connect <name>,<host>,<user>,[<pass>,[<db>,[<port>,<sock>[<opts>]]]];
+
+ <name> - name of the new connection
+ <host> - hostname of server
+ <user> - user to connect as
+ <pass> - password used when connecting
+ <db> - initial db when connected
+ <port> - server port
+ <sock> - server socket
+ <opts> - options to use for the connection
+ * SSL - use SSL if available
+ * COMPRESS - use compression if available
+
+*/
+
+void do_connect(struct st_command *command)
+{
+ int con_port= port;
+ char *con_options;
+ bool con_ssl= 0, con_compress= 0;
+ char *ptr;
+
+ DYNAMIC_STRING ds_connection_name;
+ DYNAMIC_STRING ds_host;
+ DYNAMIC_STRING ds_user;
+ DYNAMIC_STRING ds_password;
+ DYNAMIC_STRING ds_database;
+ DYNAMIC_STRING ds_port;
+ DYNAMIC_STRING ds_sock;
+ DYNAMIC_STRING ds_options;
+ const struct command_arg connect_args[] = {
+ "connection name", ARG_STRING, TRUE, &ds_connection_name,
+ "Name of the connection",
+ "host", ARG_STRING, TRUE, &ds_host, "Host to connect to",
+ "user", ARG_STRING, FALSE, &ds_user, "User to connect as",
+ "passsword", ARG_STRING, FALSE, &ds_password,
+ "Password used when connecting",
+ "database", ARG_STRING, FALSE, &ds_database,
+ "Dtabase to select after connect",
+ "port", ARG_STRING, FALSE, &ds_port, "Port to connect to",
+ "socket", ARG_STRING, FALSE, &ds_sock, "Socket to connect with",
+ "options", ARG_STRING, FALSE, &ds_options,
+ "Options to use while connecting"
+ };
DBUG_ENTER("do_connect");
- DBUG_PRINT("enter",("connect: %s", q->first_argument));
-
- /* Make a copy of query before parsing, safe_get_param will modify */
- if (!(con_buf= my_strdup(q->first_argument, MYF(MY_WME))))
- die("Could not allocate con_buf");
- p= con_buf;
-
- if (*p != '(')
- die("Syntax error in connect - expected '(' found '%c'", *p);
- p++;
- p= safe_get_param(p, &con_name, "Missing connection name");
- p= safe_get_param(p, &con_host, "Missing connection host");
- p= safe_get_param(p, &con_user, "Missing connection user");
- p= safe_get_param(p, &con_pass, "Missing connection password");
- p= safe_get_param(p, &con_db, "Missing connection db");
+ DBUG_PRINT("enter",("connect: %s", command->first_argument));
- /* Port */
- p= safe_get_param(p, &con_port_str, 0);
- if (*con_port_str)
+ /* Remove parenteses around connect arguments */
+ if ((ptr= strstr(command->first_argument, "(")))
{
- if (*con_port_str == '$')
+ /* Replace it with a space */
+ *ptr= ' ';
+ if ((ptr= strstr(command->first_argument, ")")))
{
- if (!(var_port= var_get(con_port_str, 0, 0, 0)))
- die("Unknown variable '%s'", con_port_str+1);
- con_port= var_port->int_val;
+ /* Replace it with \0 */
+ *ptr= 0;
}
else
- {
- con_port= atoi(con_port_str);
- if (con_port == 0)
- die("Illegal argument for port: '%s'", con_port_str);
- }
+ die("connect - argument list started with '(' must be ended with ')'");
}
- else
+
+ check_command_args(command, command->first_argument, connect_args,
+ sizeof(connect_args)/sizeof(struct command_arg),
+ ',');
+
+ /* Port */
+ if (ds_port.length)
{
- con_port= port;
+ con_port= atoi(ds_port.str);
+ if (con_port == 0)
+ die("Illegal argument for port: '%s'", ds_port.str);
}
/* Sock */
- p= safe_get_param(p, &con_sock, 0);
- if (*con_sock)
+ if (ds_sock.length)
{
- if (*con_sock == '$')
+ /*
+ If the socket is specified just as a name without path
+ append tmpdir in front
+ */
+ if (*ds_sock.str != FN_LIBCHAR)
{
- if (!(var_sock= var_get(con_sock, 0, 0, 0)))
- die("Unknown variable '%s'", con_sock+1);
- if (!(con_sock= (char*)my_malloc(var_sock->str_val_len+1, MYF(0))))
- die("Out of memory");
- free_con_sock= 1;
- memcpy(con_sock, var_sock->str_val, var_sock->str_val_len);
- con_sock[var_sock->str_val_len]= 0;
+ char buff[FN_REFLEN];
+ fn_format(buff, ds_sock.str, TMPDIR, "", 0);
+ dynstr_set(&ds_sock, buff);
}
}
else
{
- con_sock= (char*) unix_sock;
+ /* No socket specified, use default */
+ dynstr_set(&ds_sock, unix_sock);
}
+ DBUG_PRINT("info", ("socket: %s", ds_sock.str));
+
/* Options */
- p= safe_get_param(p, &con_options, 0);
+ con_options= ds_options.str;
while (*con_options)
{
- char* str= con_options;
- while (*str && !my_isspace(charset_info, *str))
- str++;
- *str++= 0;
- if (!strcmp(con_options, "SSL"))
+ char* end;
+ /* Step past any spaces in beginning of option*/
+ while (*con_options && my_isspace(charset_info, *con_options))
+ con_options++;
+ /* Find end of this option */
+ end= con_options;
+ while (*end && !my_isspace(charset_info, *end))
+ end++;
+ if (!strncmp(con_options, "SSL", 3))
con_ssl= 1;
- else if (!strcmp(con_options, "COMPRESS"))
+ else if (!strncmp(con_options, "COMPRESS", 8))
con_compress= 1;
else
- die("Illegal option to connect: %s", con_options);
- con_options= str;
+ die("Illegal option to connect: %.*s", end - con_options, con_options);
+ /* Process next option */
+ con_options= end;
}
- /* Note: 'p' is pointing into the copy 'con_buf' */
- q->last_argument= q->first_argument + (p - con_buf);
- if (next_con == cons_end)
- die("Connection limit exhausted - increase MAX_CONS in mysqltest.c");
+ if (next_con == connections_end)
+ die("Connection limit exhausted, you can have max %d connections",
+ (sizeof(connections)/sizeof(struct st_connection)));
- if (find_connection_by_name(con_name))
- die("Connection %s already exists", con_name);
+ if (find_connection_by_name(ds_connection_name.str))
+ die("Connection %s already exists", ds_connection_name.str);
if (!mysql_init(&next_con->mysql))
die("Failed on mysql_init()");
@@ -2772,53 +3096,56 @@ int do_connect(struct st_query *q)
#ifdef HAVE_OPENSSL
if (opt_use_ssl || con_ssl)
{
- /* Turn on ssl_verify_server_cert only if host is "localhost" */
- opt_ssl_verify_server_cert= !strcmp(con_host, "localhost");
-
mysql_ssl_set(&next_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= !strcmp(ds_connection_name.str, "localhost");
mysql_options(&next_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
&opt_ssl_verify_server_cert);
+#endif
}
#endif
- if (con_sock && !free_con_sock && *con_sock && *con_sock != FN_LIBCHAR)
- con_sock=fn_format(buff, con_sock, TMPDIR, "", 0);
- if (!con_db[0])
- con_db= db;
+
+ /* Use default db name */
+ if (ds_database.length == 0)
+ dynstr_set(&ds_database, db);
+
/* Special database to allow one to connect without a database name */
- if (con_db && !strcmp(con_db,"*NO-ONE*"))
- con_db= 0;
- if (q->abort_on_error)
- {
- if (safe_connect(&next_con->mysql, con_host, con_user, con_pass,
- con_db, con_port, con_sock ? con_sock: 0))
- die("Could not open connection '%s': %d %s", con_name,
- mysql_errno(&next_con->mysql), mysql_error(&next_con->mysql));
- }
- else
- error= connect_n_handle_errors(q, &next_con->mysql, con_host, con_user,
- con_pass, con_db, con_port, con_sock,
- &create_conn);
+ if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
+ dynstr_set(&ds_database, "");
+
- if (create_conn)
+ if (connect_n_handle_errors(command, &next_con->mysql,
+ ds_host.str,ds_user.str,
+ ds_password.str, ds_database.str,
+ con_port, ds_sock.str))
{
- if (!(next_con->name= my_strdup(con_name, MYF(MY_WME))))
- die(NullS);
+ DBUG_PRINT("info", ("Inserting connection %s in connection pool",
+ ds_connection_name.str));
+ if (!(next_con->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
+ die("Out of memory");
cur_con= next_con++;
}
- if (free_con_sock)
- my_free(con_sock, MYF(MY_WME));
- my_free(con_buf, MYF(MY_WME));
- DBUG_RETURN(error);
+
+ dynstr_free(&ds_connection_name);
+ dynstr_free(&ds_host);
+ dynstr_free(&ds_user);
+ dynstr_free(&ds_password);
+ dynstr_free(&ds_database);
+ dynstr_free(&ds_port);
+ dynstr_free(&ds_sock);
+ dynstr_free(&ds_options);
+ DBUG_VOID_RETURN;
}
-int do_done(struct st_query *q)
+int do_done(struct st_command *command)
{
/* Check if empty block stack */
if (cur_block == block_stack)
{
- if (*q->query != '}')
+ if (*command->query != '}')
die("Stray 'end' command - end of block before beginning");
die("Stray '}' - end of block before beginning");
}
@@ -2844,31 +3171,31 @@ int do_done(struct st_query *q)
Process start of a "if" or "while" statement
SYNOPSIS
- do_block()
- cmd Type of block
- q called command
+ do_block()
+ cmd Type of block
+ q called command
DESCRIPTION
- if ([!]<expr>)
- {
- <block statements>
- }
+ if ([!]<expr>)
+ {
+ <block statements>
+ }
- while ([!]<expr>)
- {
- <block statements>
- }
+ while ([!]<expr>)
+ {
+ <block statements>
+ }
- Evaluates the <expr> and if it evaluates to
- greater than zero executes the following code block.
- A '!' can be used before the <expr> to indicate it should
- be executed if it evaluates to zero.
+ Evaluates the <expr> and if it evaluates to
+ greater than zero executes the following code block.
+ A '!' can be used before the <expr> to indicate it should
+ be executed if it evaluates to zero.
- */
+*/
-void do_block(enum block_cmd cmd, struct st_query* q)
+void do_block(enum block_cmd cmd, struct st_command* command)
{
- char *p= q->first_argument;
+ char *p= command->first_argument;
const char *expr_start, *expr_end;
VAR v;
const char *cmd_name= (cmd == cmd_while ? "while" : "if");
@@ -2912,9 +3239,7 @@ void do_block(enum block_cmd cmd, struct st_query* q)
while (*p && my_isspace(charset_info, *p))
p++;
- if (*p == '{')
- die("Missing newline between %s and '{'", cmd_name);
- if (*p)
+ if (*p && *p != '{')
die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
var_init(&v,0,0,0,0);
@@ -2935,43 +3260,41 @@ void do_block(enum block_cmd cmd, struct st_query* q)
}
-/*
- Read characters from line buffer or file. This is needed to allow
- my_ungetc() to buffer MAX_DELIMITER characters for a file
+void do_delimiter(struct st_command* command)
+{
+ char* p= command->first_argument;
+ DBUG_ENTER("do_delimiter");
+ DBUG_PRINT("enter", ("first_argument: %s", command->first_argument));
- NOTE:
- This works as long as one doesn't change files (with 'source file_name')
- when there is things pushed into the buffer. This should however not
- happen for any tests in the test suite.
-*/
+ while (*p && my_isspace(charset_info, *p))
+ p++;
-int my_getc(FILE *file)
-{
- if (line_buffer_pos == line_buffer)
- return fgetc(file);
- return *--line_buffer_pos;
-}
+ if (!(*p))
+ die("Can't set empty delimiter");
-void my_ungetc(int c)
-{
- *line_buffer_pos++= (char) c;
+ strmake(delimiter, p, sizeof(delimiter) - 1);
+ delimiter_length= strlen(delimiter);
+
+ DBUG_PRINT("exit", ("delimiter: %s", delimiter));
+ command->last_argument= p + delimiter_length;
+ DBUG_VOID_RETURN;
}
-my_bool end_of_query(int c)
+my_bool match_delimiter(int c, const char *delim, uint length)
{
uint i;
- char tmp[MAX_DELIMITER];
+ char tmp[MAX_DELIMITER_LENGTH];
- if (c != *delimiter)
+ if (c != *delim)
return 0;
- for (i= 1; i < delimiter_length &&
- (c= my_getc(cur_file->file)) == *(delimiter + i);
+ for (i= 1; i < length &&
+ (c= my_getc(cur_file->file)) == *(delim + i);
i++)
tmp[i]= c;
- if (i == delimiter_length)
+ if (i == length)
return 1; /* Found delimiter */
/* didn't find delimiter, push back things that we read */
@@ -2982,45 +3305,51 @@ my_bool end_of_query(int c)
}
+my_bool end_of_query(int c)
+{
+ return match_delimiter(c, delimiter, delimiter_length);
+}
+
+
/*
Read one "line" from the file
SYNOPSIS
- read_line
- buf buffer for the read line
- size size of the buffer i.e max size to read
+ read_line
+ buf buffer for the read line
+ size size of the buffer i.e max size to read
DESCRIPTION
- This function actually reads several lines and adds them to the
- buffer buf. It continues to read until it finds what it believes
- is a complete query.
+ This function actually reads several lines and adds them to the
+ buffer buf. It continues to read until it finds what it believes
+ is a complete query.
- Normally that means it will read lines until it reaches the
- "delimiter" that marks end of query. Default delimiter is ';'
- The function should be smart enough not to detect delimiter's
- found inside strings surrounded with '"' and '\'' escaped strings.
+ Normally that means it will read lines until it reaches the
+ "delimiter" that marks end of query. Default delimiter is ';'
+ The function should be smart enough not to detect delimiter's
+ found inside strings surrounded with '"' and '\'' escaped strings.
- If the first line in a query starts with '#' or '-' this line is treated
- as a comment. A comment is always terminated when end of line '\n' is
- reached.
+ If the first line in a query starts with '#' or '-' this line is treated
+ as a comment. A comment is always terminated when end of line '\n' is
+ reached.
*/
int read_line(char *buf, int size)
{
- int c;
- char quote;
+ char c, last_quote;
char *p= buf, *buf_end= buf + size - 1;
- int no_save= 0;
- enum {R_NORMAL, R_Q, R_Q_IN_Q, R_SLASH_IN_Q,
- R_COMMENT, R_LINE_START} state= R_LINE_START;
+ int skip_char= 0;
+ enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
+ R_COMMENT, R_LINE_START} state= R_LINE_START;
DBUG_ENTER("read_line");
- LINT_INIT(quote);
+ LINT_INIT(last_quote);
start_lineno= cur_file->lineno;
+ DBUG_PRINT("info", ("start_lineno: %d", start_lineno));
for (; p < buf_end ;)
{
- no_save= 0;
+ skip_char= 0;
c= my_getc(cur_file->file);
if (feof(cur_file->file))
{
@@ -3036,12 +3365,13 @@ int read_line(char *buf, int size)
{
/* We're back at the first file, check if
all { have matching }
- */
+ */
if (cur_block != block_stack)
die("Missing end of block");
+ *p= 0;
DBUG_PRINT("info", ("end of file"));
- DBUG_RETURN(1);
+ DBUG_RETURN(1);
}
cur_file--;
start_lineno= cur_file->lineno;
@@ -3055,61 +3385,74 @@ int read_line(char *buf, int size)
/* Convert cr/lf to lf */
if (p != buf && *(p-1) == '\r')
- *(p-1)= 0;
+ p--;
}
switch(state) {
case R_NORMAL:
- /* Only accept '{' in the beginning of a line */
if (end_of_query(c))
{
*p= 0;
+ DBUG_PRINT("exit", ("Found delimiter '%s'", delimiter));
DBUG_RETURN(0);
}
- else if (c == '\'' || c == '"' || c == '`')
+ else if ((c == '{' &&
+ (!strncasecmp(buf, "while", min(5, p - buf)) ||
+ !strncasecmp(buf, "if", min(2, p - buf)))))
{
- quote= c;
- state= R_Q;
+ /* Only if and while commands can be terminated by { */
+ *p++= c;
+ *p= 0;
+ DBUG_PRINT("exit", ("Found '{' indicating begining of block"));
+ DBUG_RETURN(0);
}
- else if (c == '\n')
+ else if (c == '\'' || c == '"' || c == '`')
{
- state = R_LINE_START;
+ last_quote= c;
+ state= R_Q;
}
break;
+
case R_COMMENT:
if (c == '\n')
{
+ /* Comments are terminated by newline */
*p= 0;
+ DBUG_PRINT("exit", ("Found newline in comment"));
DBUG_RETURN(0);
}
break;
+
case R_LINE_START:
- /* Only accept start of comment if this is the first line in query */
- if ((cur_file->lineno == start_lineno) &&
- (c == '#' || c == '-' || parsing_disabled))
+ if (c == '#' || c == '-')
{
+ /* A # or - in the first position of the line - this is a comment */
state = R_COMMENT;
}
else if (my_isspace(charset_info, c))
{
+ /* Skip all space at begining of line */
if (c == '\n')
start_lineno= cur_file->lineno; /* Query hasn't started yet */
- no_save= 1;
+ skip_char= 1;
}
- else if (c == '}')
+ else if (end_of_query(c))
{
- *buf++= '}';
- *buf= 0;
+ *p= 0;
+ DBUG_PRINT("exit", ("Found delimiter '%s'", delimiter));
DBUG_RETURN(0);
}
- else if (end_of_query(c) || c == '{')
+ else if (c == '}')
{
+ /* A "}" need to be by itself in the begining of a line to terminate */
+ *p++= c;
*p= 0;
+ DBUG_PRINT("exit", ("Found '}' in begining of a line"));
DBUG_RETURN(0);
}
else if (c == '\'' || c == '"' || c == '`')
{
- quote= c;
+ last_quote= c;
state= R_Q;
}
else
@@ -3117,29 +3460,19 @@ int read_line(char *buf, int size)
break;
case R_Q:
- if (c == quote)
- state= R_Q_IN_Q;
+ if (c == last_quote)
+ state= R_NORMAL;
else if (c == '\\')
state= R_SLASH_IN_Q;
break;
- case R_Q_IN_Q:
- if (end_of_query(c))
- {
- *p= 0;
- DBUG_RETURN(0);
- }
- if (c != quote)
- state= R_NORMAL;
- else
- state= R_Q;
- break;
+
case R_SLASH_IN_Q:
state= R_Q;
break;
}
- if (!no_save)
+ if (!skip_char)
{
/* Could be a multibyte character */
/* This code is based on the code in "sql_load.cc" */
@@ -3157,7 +3490,7 @@ int read_line(char *buf, int size)
for (i= 1; i < charlen; i++)
{
if (feof(cur_file->file))
- goto found_eof; /* FIXME: could we just break here?! */
+ goto found_eof;
c= my_getc(cur_file->file);
*p++ = c;
}
@@ -3174,99 +3507,253 @@ int read_line(char *buf, int size)
*p++= c;
}
}
- *p= 0; /* Always end with \0 */
- DBUG_RETURN(feof(cur_file->file));
+ die("The input buffer is too small for this query.x\n" \
+ "check your query or increase MAX_QUERY and recompile");
+ DBUG_RETURN(0);
}
+
/*
- Create a query from a set of lines
+ Convert the read query to result format version 1
+
+ That is: After newline, all spaces need to be skipped
+ unless the previous char was a quote
+
+ This is due to an old bug that has now been fixed, but the
+ version 1 output format is preserved by using this function
+
+*/
+
+void convert_to_format_v1(char* query)
+{
+ int last_c_was_quote= 0;
+ char *p= query, *write= query;
+ char *end= strend(query);
+ char last_c;
+
+ while (p <= end)
+ {
+ if (*p == '\n' && !last_c_was_quote)
+ {
+ *write++ = *p++; /* Save the newline */
+
+ /* Skip any spaces on next line */
+ while (*p && my_isspace(charset_info, *p))
+ p++;
+
+ last_c_was_quote= 0;
+ }
+ else if (*p == '\'' || *p == '"' || *p == '`')
+ {
+ last_c= *p;
+ *write++ = *p++;
+
+ /* Copy anything until the next quote of same type */
+ while (*p && *p != last_c)
+ *write++ = *p++;
+
+ *write++ = *p++;
+
+ last_c_was_quote= 1;
+ }
+ else
+ {
+ *write++ = *p++;
+ last_c_was_quote= 0;
+ }
+ }
+}
+
+
+/*
+ Check a command that is about to be sent (or should have been
+ sent if parsing was enabled) to mysql server for
+ suspicious things and generate warnings.
+*/
+
+void scan_command_for_warnings(struct st_command *command)
+{
+ const char *ptr= command->query;
+ DBUG_ENTER("scan_command_for_warnings");
+ DBUG_PRINT("enter", ("query: %s", command->query));
+
+ while(*ptr)
+ {
+ /*
+ Look for query's that lines that start with a -- comment
+ and has a mysqltest command
+ */
+ if (ptr[0] == '\n' &&
+ ptr[1] && ptr[1] == '-' &&
+ ptr[2] && ptr[2] == '-' &&
+ ptr[3])
+ {
+ uint type;
+ char save;
+ char *end, *start= (char*)ptr+3;
+ /* Skip leading spaces */
+ while (*start && my_isspace(charset_info, *start))
+ start++;
+ end= start;
+ /* Find end of command(next space) */
+ while (*end && !my_isspace(charset_info, *end))
+ end++;
+ save= *end;
+ *end= 0;
+ DBUG_PRINT("info", ("Checking '%s'", start));
+ type= find_type(start, &command_typelib, 1+2);
+ if (type)
+ warning_msg("Embedded mysqltest command '--%s' detected in "
+ "query '%s' was this intentional? ",
+ start, command->query);
+ *end= save;
+ }
+
+ ptr++;
+ }
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Check for unexpected "junk" after the end of query
+ This is normally caused by missing delimiters or when
+ switching between different delimiters
+*/
+
+void check_eol_junk_line(const char *line)
+{
+ const char *p= line;
+ DBUG_ENTER("check_eol_junk_line");
+ DBUG_PRINT("enter", ("line: %s", line));
+
+ /* Check for extra delimiter */
+ if (*p && !strncmp(p, delimiter, delimiter_length))
+ die("Extra delimiter \"%s\" found", delimiter);
+
+ /* Allow trailing # comment */
+ if (*p && *p != '#')
+ {
+ if (*p == '\n')
+ die("Missing delimiter");
+ die("End of line junk detected: \"%s\"", p);
+ }
+ DBUG_VOID_RETURN;
+}
+
+void check_eol_junk(const char *eol)
+{
+ const char *p= eol;
+ DBUG_ENTER("check_eol_junk");
+ DBUG_PRINT("enter", ("eol: %s", eol));
+
+ /* Skip past all spacing chars and comments */
+ while (*p && (my_isspace(charset_info, *p) || *p == '#' || *p == '\n'))
+ {
+ /* Skip past comments started with # and ended with newline */
+ if (*p && *p == '#')
+ {
+ p++;
+ while (*p && *p != '\n')
+ p++;
+ }
+
+ /* Check this line */
+ if (*p && *p == '\n')
+ check_eol_junk_line(p);
+
+ if (*p)
+ p++;
+ }
+
+ check_eol_junk_line(p);
+
+ DBUG_VOID_RETURN;
+}
+
+
+
+/*
+ Create a command from a set of lines
SYNOPSIS
- read_query()
- q_ptr pointer where to return the new query
+ read_command()
+ command_ptr pointer where to return the new query
DESCRIPTION
- Converts lines returned by read_line into a query, this involves
- parsing the first word in the read line to find the query type.
+ Converts lines returned by read_line into a command, this involves
+ parsing the first word in the read line to find the command type.
- A -- comment may contain a valid query as the first word after the
- comment start. Thus it's always checked to see if that is the case.
- The advantage with this approach is to be able to execute commands
- terminated by new line '\n' regardless how many "delimiter" it contain.
+ A -- comment may contain a valid query as the first word after the
+ comment start. Thus it's always checked to see if that is the case.
+ The advantage with this approach is to be able to execute commands
+ terminated by new line '\n' regardless how many "delimiter" it contain.
*/
-static char read_query_buf[MAX_QUERY];
+#define MAX_QUERY (256*1024) /* 256K -- a test in sp-big is >128K */
+static char read_command_buf[MAX_QUERY];
-int read_query(struct st_query** q_ptr)
+int read_command(struct st_command** command_ptr)
{
- char *p= read_query_buf;
- struct st_query* q;
- DBUG_ENTER("read_query");
+ char *p= read_command_buf;
+ struct st_command* command;
+ DBUG_ENTER("read_command");
if (parser.current_line < parser.read_lines)
{
- get_dynamic(&q_lines, (gptr) q_ptr, parser.current_line) ;
+ get_dynamic(&q_lines, (gptr) command_ptr, parser.current_line) ;
DBUG_RETURN(0);
}
- if (!(*q_ptr= q= (struct st_query*) my_malloc(sizeof(*q), MYF(MY_WME))) ||
- insert_dynamic(&q_lines, (gptr) &q))
+ if (!(*command_ptr= command=
+ (struct st_command*) my_malloc(sizeof(*command), MYF(MY_WME))) ||
+ insert_dynamic(&q_lines, (gptr) &command))
die(NullS);
- q->record_file[0]= 0;
- q->require_file= 0;
- q->first_word_len= 0;
+ command->require_file[0]= 0;
+ command->first_word_len= 0;
+ command->query_len= 0;
- q->type= Q_UNKNOWN;
- q->query_buf= q->query= 0;
- read_query_buf[0]= 0;
- if (read_line(read_query_buf, sizeof(read_query_buf)))
+ command->type= Q_UNKNOWN;
+ command->query_buf= command->query= 0;
+ read_command_buf[0]= 0;
+ if (read_line(read_command_buf, sizeof(read_command_buf)))
{
- check_eol_junk(read_query_buf);
+ check_eol_junk(read_command_buf);
DBUG_RETURN(1);
}
-
- DBUG_PRINT("info", ("query: %s", read_query_buf));
- if (*p == '#')
- {
- q->type= Q_COMMENT;
- /* This goto is to avoid losing the "expected error" info. */
- goto end;
- }
- if (!parsing_disabled)
- {
- memcpy((gptr) q->expected_errno, (gptr) global_expected_errno,
- sizeof(global_expected_errno));
- q->expected_errors= global_expected_errors;
- q->abort_on_error= (global_expected_errors == 0 && abort_on_error);
- }
- if (p[0] == '-' && p[1] == '-')
+ convert_to_format_v1(read_command_buf);
+
+ DBUG_PRINT("info", ("query: %s", read_command_buf));
+ if (*p == '#')
{
- q->type= Q_COMMENT_WITH_COMMAND;
- p+= 2; /* To calculate first word */
+ command->type= Q_COMMENT;
}
- else if (!parsing_disabled)
+ else if (p[0] == '-' && p[1] == '-')
{
- while (*p && my_isspace(charset_info, *p))
- p++ ;
+ command->type= Q_COMMENT_WITH_COMMAND;
+ p+= 2; /* Skip past -- */
}
-end:
+ /* Skip leading spaces */
while (*p && my_isspace(charset_info, *p))
p++;
- if (!(q->query_buf= q->query= my_strdup(p, MYF(MY_WME))))
- die(NullS);
+ if (!(command->query_buf= command->query= my_strdup(p, MYF(MY_WME))))
+ die("Out of memory");
/* Calculate first word and first argument */
- for (p= q->query; *p && !my_isspace(charset_info, *p) ; p++) ;
- q->first_word_len= (uint) (p - q->query);
+ for (p= command->query; *p && !my_isspace(charset_info, *p) ; p++) ;
+ command->first_word_len= (uint) (p - command->query);
+
+ /* Skip spaces between command and first argument */
while (*p && my_isspace(charset_info, *p))
p++;
- q->first_argument= p;
- q->end= strend(q->query);
+ command->first_argument= p;
+
+ command->end= strend(command->query);
+ command->query_len= (command->end - command->query);
parser.read_lines++;
DBUG_RETURN(0);
}
@@ -3278,8 +3765,6 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0, 0},
{"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir,
(gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"big-test", 'B', "Define BIG_TEST to 1.", (gptr*) &opt_big_test,
- (gptr*) &opt_big_test, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"compress", 'C', "Use the compressed server/client protocol.",
(gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
@@ -3319,8 +3804,8 @@ static struct my_option my_long_options[] =
{"record", 'r', "Record output of test_file into result file.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"result-file", 'R', "Read/Store result from/in this file.",
- (gptr*) &result_file, (gptr*) &result_file, 0, GET_STR, REQUIRED_ARG,
- 0, 0, 0, 0, 0, 0},
+ (gptr*) &result_file_name, (gptr*) &result_file_name, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-arg", 'A', "Send option value to embedded server as a parameter.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-file", 'F', "Read embedded server arguments from file.",
@@ -3348,8 +3833,6 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"user", 'u', "User for login.", (gptr*) &user, (gptr*) &user, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"valgrind", 'N', "Define VALGRIND_TEST to 1.", (gptr*) &opt_valgrind_test,
- (gptr*) &opt_valgrind_test, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"verbose", 'v', "Write more.", (gptr*) &verbose, (gptr*) &verbose, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit.",
@@ -3363,7 +3846,7 @@ static struct my_option my_long_options[] =
#include <help_start.h>
-static void print_version(void)
+void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
@@ -3384,6 +3867,52 @@ void usage()
#include <help_end.h>
+/*
+ Read arguments for embedded server and put them into
+ embedded_server_args[]
+*/
+
+void read_embedded_server_arguments(const char *name)
+{
+ char argument[1024],buff[FN_REFLEN], *str=0;
+ FILE *file;
+
+ if (!test_if_hard_path(name))
+ {
+ strxmov(buff, opt_basedir, name, NullS);
+ name=buff;
+ }
+ fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
+
+ if (!embedded_server_arg_count)
+ {
+ embedded_server_arg_count=1;
+ embedded_server_args[0]= (char*) ""; /* Progname */
+ }
+ if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
+ die("Failed to open file %s", buff);
+
+ while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
+ (str=fgets(argument,sizeof(argument), file)))
+ {
+ *(strend(str)-1)=0; /* Remove end newline */
+ if (!(embedded_server_args[embedded_server_arg_count]=
+ (char*) my_strdup(str,MYF(MY_WME))))
+ {
+ my_fclose(file,MYF(0));
+ die("Out of memory");
+
+ }
+ embedded_server_arg_count++;
+ }
+ my_fclose(file,MYF(0));
+ if (str)
+ die("Too many arguments in option file: %s",name);
+
+ return;
+}
+
+
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
@@ -3398,35 +3927,35 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
record = 1;
break;
case 'x':
+ {
+ char buff[FN_REFLEN];
+ if (!test_if_hard_path(argument))
{
- char buff[FN_REFLEN];
- if (!test_if_hard_path(argument))
- {
- strxmov(buff, opt_basedir, argument, NullS);
- argument= buff;
- }
- fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
- DBUG_ASSERT(cur_file == file_stack && cur_file->file == 0);
- if (!(cur_file->file=
- my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
- die("Could not open %s: errno = %d", buff, errno);
- cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
- cur_file->lineno= 1;
- break;
+ strxmov(buff, opt_basedir, argument, NullS);
+ argument= buff;
}
+ fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
+ DBUG_ASSERT(cur_file == file_stack && cur_file->file == 0);
+ if (!(cur_file->file=
+ my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
+ die("Could not open %s: errno = %d", buff, errno);
+ cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
+ cur_file->lineno= 1;
+ break;
+ }
case 'm':
+ {
+ static char buff[FN_REFLEN];
+ if (!test_if_hard_path(argument))
{
- static char buff[FN_REFLEN];
- if (!test_if_hard_path(argument))
- {
- strxmov(buff, opt_basedir, argument, NullS);
- argument= buff;
- }
- fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
- timer_file= buff;
- unlink(timer_file); /* Ignore error, may not exist */
- break;
+ strxmov(buff, opt_basedir, argument, NullS);
+ argument= buff;
}
+ fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
+ timer_file= buff;
+ unlink(timer_file); /* Ignore error, may not exist */
+ break;
+ }
case 'p':
if (argument)
{
@@ -3448,7 +3977,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
embedded_server_arg_count=1;
embedded_server_args[0]= (char*) "";
}
- if (embedded_server_arg_count == MAX_SERVER_ARGS-1 ||
+ if (embedded_server_arg_count == MAX_EMBEDDED_SERVER_ARGS-1 ||
!(embedded_server_args[embedded_server_arg_count++]=
my_strdup(argument, MYF(MY_FAE))))
{
@@ -3456,8 +3985,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
break;
case 'F':
- if (read_server_arguments(argument))
- die(NullS);
+ read_embedded_server_arguments(argument);
break;
case OPT_SKIP_SAFEMALLOC:
#ifdef SAFEMALLOC
@@ -3498,16 +4026,16 @@ int parse_args(int argc, char **argv)
/*
- Write the content of str into file
+ Write the content of str into file
- SYNOPSIS
- str_to_file
- fname - name of file to truncate/create and write to
- str - content to write to file
- size - size of content witten to file
+ SYNOPSIS
+ str_to_file
+ fname - name of file to truncate/create and write to
+ str - content to write to file
+ size - size of content witten to file
*/
-static void str_to_file(const char *fname, char *str, int size)
+void str_to_file(const char *fname, char *str, int size)
{
int fd;
char buff[FN_REFLEN];
@@ -3519,7 +4047,7 @@ static void str_to_file(const char *fname, char *str, int size)
fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
if ((fd= my_open(buff, O_WRONLY | O_CREAT | O_TRUNC,
- MYF(MY_WME | MY_FFNF))) < 0)
+ MYF(MY_WME | MY_FFNF))) < 0)
die("Could not open %s: errno = %d", buff, errno);
if (my_write(fd, (byte*)str, size, MYF(MY_WME|MY_FNABP)))
die("write failed");
@@ -3527,236 +4055,48 @@ static void str_to_file(const char *fname, char *str, int size)
}
-void dump_result_to_reject_file(const char *record_file, char *buf, int size)
+void dump_result_to_reject_file(char *buf, int size)
{
char reject_file[FN_REFLEN];
- str_to_file(fn_format(reject_file, record_file, "", ".reject",
+ str_to_file(fn_format(reject_file, result_file_name, "", ".reject",
MY_REPLACE_EXT),
buf, size);
}
-void dump_result_to_log_file(const char *record_file, char *buf, int size)
+void dump_result_to_log_file(char *buf, int size)
{
char log_file[FN_REFLEN];
- str_to_file(fn_format(log_file, record_file, "", ".log",
+ str_to_file(fn_format(log_file, result_file_name, "", ".log",
MY_REPLACE_EXT),
buf, size);
}
-void dump_progress(const char *record_file)
+void dump_progress(void)
{
char log_file[FN_REFLEN];
- str_to_file(fn_format(log_file, record_file, "", ".progress",
+ str_to_file(fn_format(log_file, result_file_name, "", ".progress",
MY_REPLACE_EXT),
ds_progress.str, ds_progress.length);
}
-static void check_regerr(my_regex_t* r, int err)
+void dump_warning_messages(void)
{
- char err_buf[1024];
+ char warn_file[FN_REFLEN];
- if (err)
- {
- my_regerror(err,r,err_buf,sizeof(err_buf));
- die("Regex error: %s\n", err_buf);
- }
+ str_to_file(fn_format(warn_file, result_file_name, "", ".warnings",
+ MY_REPLACE_EXT),
+ ds_warning_messages.str, ds_warning_messages.length);
}
-/*
- auxiluary macro used by reg_replace
- makes sure the result buffer has sufficient length
-*/
-#define SECURE_REG_BUF if (buf_len < need_buf_len)\
- {\
- int off= res_p - buf;\
- buf= (char*)my_realloc(buf,need_buf_len,MYF(MY_WME+MY_FAE));\
- res_p= buf + off;\
- buf_len= need_buf_len;\
- }\
-
-/*
- Performs a regex substitution
-
- IN:
-
- buf_p - result buffer pointer. Will change if reallocated
- buf_len_p - result buffer length. Will change if the buffer is reallocated
- pattern - regexp pattern to match
- replace - replacement expression
- string - the string to perform substituions in
- icase - flag, if set to 1 the match is case insensitive
- */
-static int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
- char *replace, char *string, int icase)
+void check_regerr(my_regex_t* r, int err)
{
- my_regex_t r;
- my_regmatch_t* subs;
- char* buf_end, *replace_end;
- char* buf= *buf_p;
- int len;
- int buf_len,need_buf_len;
- int cflags= REG_EXTENDED;
- int err_code;
- char* res_p,*str_p,*str_end;
-
- buf_len= *buf_len_p;
- len= strlen(string);
- str_end= string + len;
-
- /* start with a buffer of a reasonable size that hopefully will not
- need to be reallocated
- */
- need_buf_len= len * 2 + 1;
- res_p= buf;
+ char err_buf[1024];
- SECURE_REG_BUF
-
- buf_end = buf + buf_len;
-
- if (icase)
- cflags |= REG_ICASE;
-
- if ((err_code=my_regcomp(&r,pattern,cflags,&my_charset_latin1)))
- {
- check_regerr(&r,err_code);
- return 1;
- }
-
- subs= (my_regmatch_t*)my_malloc(sizeof(my_regmatch_t) * (r.re_nsub+1),
- MYF(MY_WME+MY_FAE));
-
- *res_p= 0;
- str_p= string;
- replace_end= replace + strlen(replace);
-
- /* for each pattern match instance perform a replacement */
- while (!err_code)
+ if (err)
{
- /* find the match */
- err_code= my_regexec(&r,str_p, r.re_nsub+1, subs,
- (str_p == string) ? REG_NOTBOL : 0);
-
- /* if regular expression error (eg. bad syntax, or out of memory) */
- if (err_code && err_code != REG_NOMATCH)
- {
- check_regerr(&r,err_code);
- my_regfree(&r);
- return 1;
- }
-
- /* if match found */
- if (!err_code)
- {
- char* expr_p= replace;
- int c;
-
- /*
- we need at least what we have so far in the buffer + the part
- before this match
- */
- need_buf_len= (res_p - buf) + subs[0].rm_so;
-
- /* on this pass, calculate the memory for the result buffer */
- while (expr_p < replace_end)
- {
- int back_ref_num= -1;
- c= *expr_p;
-
- if (c == '\\' && expr_p + 1 < replace_end)
- {
- back_ref_num= expr_p[1] - '0';
- }
-
- /* found a valid back_ref (eg. \1)*/
- if (back_ref_num >= 0 && back_ref_num <= (int)r.re_nsub)
- {
- int start_off,end_off;
- if ((start_off=subs[back_ref_num].rm_so) > -1 &&
- (end_off=subs[back_ref_num].rm_eo) > -1)
- {
- need_buf_len += (end_off - start_off);
- }
- expr_p += 2;
- }
- else
- {
- expr_p++;
- need_buf_len++;
- }
- }
- need_buf_len++;
- /*
- now that we know the size of the buffer,
- make sure it is big enough
- */
- SECURE_REG_BUF
-
- /* copy the pre-match part */
- if (subs[0].rm_so)
- {
- memcpy(res_p,str_p,subs[0].rm_so);
- res_p += subs[0].rm_so;
- }
-
- expr_p= replace;
-
- /* copy the match and expand back_refs */
- while (expr_p < replace_end)
- {
- int back_ref_num= -1;
- c= *expr_p;
-
- if (c == '\\' && expr_p + 1 < replace_end)
- {
- back_ref_num= expr_p[1] - '0';
- }
-
- if (back_ref_num >= 0 && back_ref_num <= (int)r.re_nsub)
- {
- int start_off,end_off;
- if ((start_off=subs[back_ref_num].rm_so) > -1 &&
- (end_off=subs[back_ref_num].rm_eo) > -1)
- {
- int block_len= end_off - start_off;
- memcpy(res_p,str_p + start_off, block_len);
- res_p += block_len;
- }
- expr_p += 2;
- }
- else
- {
- *res_p++ = *expr_p++;
- }
- }
-
- /* handle the post-match part */
- if (subs[0].rm_so == subs[0].rm_eo)
- {
- if (str_p + subs[0].rm_so >= str_end)
- break;
- str_p += subs[0].rm_eo ;
- *res_p++ = *str_p++;
- }
- else
- {
- str_p += subs[0].rm_eo;
- }
- }
- else /* no match this time, just copy the string as is */
- {
- int left_in_str= str_end-str_p;
- need_buf_len= (res_p-buf) + left_in_str;
- SECURE_REG_BUF
- memcpy(res_p,str_p,left_in_str);
- res_p += left_in_str;
- str_p= str_end;
- }
- }
- my_regfree(&r);
- *res_p= 0;
- *buf_p= buf;
- *buf_len_p= buf_len;
- return 0;
+ my_regerror(err,r,err_buf,sizeof(err_buf));
+ die("Regex error: %s\n", err_buf);
+ }
}
@@ -3768,12 +4108,12 @@ DYNAMIC_ARRAY patterns;
init_win_path_patterns
DESCRIPTION
- Setup string patterns that will be used to detect filenames that
- needs to be converted from Win to Unix format
+ Setup string patterns that will be used to detect filenames that
+ needs to be converted from Win to Unix format
*/
-static void init_win_path_patterns()
+void init_win_path_patterns()
{
/* List of string patterns to match in order to find paths */
const char* paths[] = { "$MYSQL_TEST_DIR",
@@ -3800,7 +4140,7 @@ static void init_win_path_patterns()
p= my_strdup(paths[i], MYF(MY_FAE));
if (insert_dynamic(&patterns, (gptr) &p))
- die(NullS);
+ die(NullS);
DBUG_PRINT("info", ("p: %s", p));
while (*p)
@@ -3813,7 +4153,7 @@ static void init_win_path_patterns()
DBUG_VOID_RETURN;
}
-static void free_win_path_patterns()
+void free_win_path_patterns()
{
uint i= 0;
for (i=0 ; i < patterns.elements ; i++)
@@ -3828,17 +4168,17 @@ static void free_win_path_patterns()
fix_win_paths
DESCRIPTION
- Search the string 'val' for the patterns that are known to be
- strings that contain filenames. Convert all \ to / in the
- filenames that are found.
-
- Ex:
- val = 'Error "c:\mysql\mysql-test\var\test\t1.frm" didn't exist'
- => $MYSQL_TEST_DIR is found by strstr
- => all \ from c:\mysql\m... until next space is converted into /
+ Search the string 'val' for the patterns that are known to be
+ strings that contain filenames. Convert all \ to / in the
+ filenames that are found.
+
+ Ex:
+ val = 'Error "c:\mysql\mysql-test\var\test\t1.frm" didn't exist'
+ => $MYSQL_TEST_DIR is found by strstr
+ => all \ from c:\mysql\m... until next space is converted into /
*/
-static void fix_win_paths(const char* val, int len)
+void fix_win_paths(const char *val, int len)
{
uint i;
char *p;
@@ -3868,43 +4208,14 @@ static void fix_win_paths(const char* val, int len)
}
#endif
-/* Append the string to ds, with optional replace */
-static void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
- const char *val, int len)
-{
-#ifdef __WIN__
- fix_win_paths(val, len);
-#endif
-
- if (glob_replace_regex)
- {
- if (!multi_reg_replace(glob_replace_regex, (char*)val))
- {
- val= glob_replace_regex->buf;
- len= strlen(val);
- }
- }
-
- if (glob_replace)
- replace_strings_append(glob_replace, ds, val, len);
- else
- dynstr_append_mem(ds, val, len);
-}
-
-
-/* Append zero-terminated string to ds, with optional replace */
-static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
-{
- replace_dynstr_append_mem(ds, val, strlen(val));
-}
/*
Append the result for one field to the dynamic string ds
*/
-static void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field,
- const char* val, ulonglong len, bool is_null)
+void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field,
+ const char* val, ulonglong len, bool is_null)
{
if (col_idx < max_replace_column && replace_column[col_idx])
{
@@ -3955,7 +4266,7 @@ static void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field,
Values may be converted with 'replace_column'
*/
-static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
+void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
{
MYSQL_ROW row;
uint num_fields= mysql_num_fields(res);
@@ -3972,7 +4283,6 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
if (!display_result_vertically)
dynstr_append_mem(ds, "\n", 1);
}
- free_replace_column();
}
@@ -3981,8 +4291,8 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
with '\t'. Values may be converted with 'replace_column'
*/
-static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
- MYSQL_FIELD *fields, uint num_fields)
+void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
+ MYSQL_FIELD *fields, uint num_fields)
{
MYSQL_BIND *bind;
my_bool *is_null;
@@ -4028,8 +4338,6 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
die("fetch didn't end with MYSQL_NO_DATA from statement: %d %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
- free_replace_column();
-
for (i= 0; i < num_fields; i++)
{
/* Free data for output */
@@ -4046,9 +4354,9 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
Append metadata for fields to output
*/
-static void append_metadata(DYNAMIC_STRING *ds,
- MYSQL_FIELD *field,
- uint num_fields)
+void append_metadata(DYNAMIC_STRING *ds,
+ MYSQL_FIELD *field,
+ uint num_fields)
{
MYSQL_FIELD *field_end;
dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
@@ -4059,44 +4367,36 @@ static void append_metadata(DYNAMIC_STRING *ds,
field < field_end ;
field++)
{
- char buff[22];
dynstr_append_mem(ds, field->catalog,
- field->catalog_length);
+ field->catalog_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, field->db, field->db_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, field->org_table,
- field->org_table_length);
+ field->org_table_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, field->table,
- field->table_length);
+ field->table_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, field->org_name,
- field->org_name_length);
+ field->org_name_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, field->name, field->name_length);
dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->type, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->type);
dynstr_append_mem(ds, "\t", 1);
- longlong10_to_str((unsigned int) field->length, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->length);
dynstr_append_mem(ds, "\t", 1);
- longlong10_to_str((unsigned int) field->max_length, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->max_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
"N" : "Y"), 1);
dynstr_append_mem(ds, "\t", 1);
-
- int10_to_str((int) field->flags, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->flags);
dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->decimals, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->decimals);
dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->charsetnr, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->charsetnr);
dynstr_append_mem(ds, "\n", 1);
}
}
@@ -4106,8 +4406,8 @@ static void append_metadata(DYNAMIC_STRING *ds,
Append affected row count and other info to output
*/
-static void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows,
- const char *info)
+void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows,
+ const char *info)
{
char buf[40], buff2[21];
sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2));
@@ -4122,12 +4422,12 @@ static void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows,
/*
- Display the table headings with the names tab separated
+ Display the table headings with the names tab separated
*/
-static void append_table_headings(DYNAMIC_STRING *ds,
- MYSQL_FIELD *field,
- uint num_fields)
+void append_table_headings(DYNAMIC_STRING *ds,
+ MYSQL_FIELD *field,
+ uint num_fields)
{
uint col_idx;
for (col_idx= 0; col_idx < num_fields; col_idx++)
@@ -4143,10 +4443,10 @@ static void append_table_headings(DYNAMIC_STRING *ds,
Fetch warnings from server and append to ds
RETURN VALUE
- Number of warnings appended to ds
+ Number of warnings appended to ds
*/
-static int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
+int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
{
uint count;
MYSQL_RES *warn_res;
@@ -4195,9 +4495,9 @@ static int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
error - function will not return
*/
-static void run_query_normal(MYSQL *mysql, struct st_query *command,
- int flags, char *query, int query_len,
- DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
+void run_query_normal(MYSQL *mysql, struct st_command *command,
+ int flags, char *query, int query_len,
+ DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
{
MYSQL_RES *res= 0;
int err= 0, counter= 0;
@@ -4205,20 +4505,20 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command,
DBUG_PRINT("enter",("flags: %d", flags));
DBUG_PRINT("enter", ("query: '%-.60s'", query));
- if (flags & QUERY_SEND)
+ if (flags & QUERY_SEND_FLAG)
{
/*
- Send the query
- */
+ Send the query
+ */
if (mysql_send_query(mysql, query, query_len))
{
- handle_error(query, command, mysql_errno(mysql), mysql_error(mysql),
+ handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
}
}
- if (!(flags & QUERY_REAP))
+ if (!(flags & QUERY_REAP_FLAG))
DBUG_VOID_RETURN;
do
@@ -4226,22 +4526,22 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command,
/*
When on first result set, call mysql_read_query_result to retrieve
answer to the query sent earlier
- */
+ */
if ((counter==0) && mysql_read_query_result(mysql))
{
- handle_error(query, command, mysql_errno(mysql), mysql_error(mysql),
+ handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
}
/*
- Store the result. If res is NULL, use mysql_field_count to
- determine if that was expected
- */
+ Store the result. If res is NULL, use mysql_field_count to
+ determine if that was expected
+ */
if (!(res= mysql_store_result(mysql)) && mysql_field_count(mysql))
{
- handle_error(query, command, mysql_errno(mysql), mysql_error(mysql),
+ handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
}
@@ -4297,7 +4597,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command,
if (err > 0)
{
/* We got an error from mysql_next_result, maybe expected */
- handle_error(query, command, mysql_errno(mysql), mysql_error(mysql),
+ handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
}
@@ -4307,8 +4607,6 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command,
handle_no_error(command);
end:
- free_replace();
- free_replace_regex();
/*
We save the return code (mysql_errno(mysql)) from the last call sent
@@ -4324,58 +4622,62 @@ end:
Handle errors which occurred during execution
SYNOPSIS
- handle_error()
- query - query string
- q - query context
- err_errno - error number
- err_error - error message
- err_sqlstate - sql state
- ds - dynamic string which is used for output buffer
+ handle_error()
+ q - query context
+ err_errno - error number
+ err_error - error message
+ err_sqlstate - sql state
+ ds - dynamic string which is used for output buffer
NOTE
- If there is an unexpected error this function will abort mysqltest
- immediately.
+ If there is an unexpected error this function will abort mysqltest
+ immediately.
RETURN VALUE
- error - function will not return
+ error - function will not return
*/
-static void handle_error(const char *query, struct st_query *q,
- unsigned int err_errno, const char *err_error,
- const char *err_sqlstate, DYNAMIC_STRING *ds)
+void handle_error(struct st_command *command,
+ unsigned int err_errno, const char *err_error,
+ const char *err_sqlstate, DYNAMIC_STRING *ds)
{
uint i;
DBUG_ENTER("handle_error");
- if (q->require_file)
+ if (command->require_file[0])
{
/*
The query after a "--require" failed. This is fine as long the server
returned a valid reponse. Don't allow 2013 or 2006 to trigger an
abort_not_supported_test
- */
+ */
if (err_errno == CR_SERVER_LOST ||
err_errno == CR_SERVER_GONE_ERROR)
- die("require query '%s' failed: %d: %s", query, err_errno, err_error);
+ die("require query '%s' failed: %d: %s", command->query,
+ err_errno, err_error);
/* Abort the run of this test, pass the failed query as reason */
- abort_not_supported_test("Query '%s' failed, required functionality not supported", query);
+ abort_not_supported_test("Query '%s' failed, required functionality" \
+ "not supported", command->query);
}
- if (q->abort_on_error)
- die("query '%s' failed: %d: %s", query, err_errno, err_error);
+ if (command->abort_on_error)
+ die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
- for (i= 0 ; (uint) i < q->expected_errors ; i++)
+ DBUG_PRINT("info", ("expected_errors.count: %d",
+ command->expected_errors.count));
+ for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
{
- if (((q->expected_errno[i].type == ERR_ERRNO) &&
- (q->expected_errno[i].code.errnum == err_errno)) ||
- ((q->expected_errno[i].type == ERR_SQLSTATE) &&
- (strcmp(q->expected_errno[i].code.sqlstate, err_sqlstate) == 0)))
+ if (((command->expected_errors.err[i].type == ERR_ERRNO) &&
+ (command->expected_errors.err[i].code.errnum == err_errno)) ||
+ ((command->expected_errors.err[i].type == ERR_SQLSTATE) &&
+ (strncmp(command->expected_errors.err[i].code.sqlstate,
+ err_sqlstate, SQLSTATE_LENGTH) == 0)))
{
if (!disable_result_log)
{
- if (q->expected_errors == 1)
+ if (command->expected_errors.count == 1)
{
/* Only log error if there is one possible error */
dynstr_append_mem(ds, "ERROR ", 6);
@@ -4385,9 +4687,9 @@ static void handle_error(const char *query, struct st_query *q,
dynstr_append_mem(ds,"\n",1);
}
/* Don't log error if we may not get an error */
- else if (q->expected_errno[0].type == ERR_SQLSTATE ||
- (q->expected_errno[0].type == ERR_ERRNO &&
- q->expected_errno[0].code.errnum != 0))
+ else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
+ (command->expected_errors.err[0].type == ERR_ERRNO &&
+ command->expected_errors.err[0].code.errnum != 0))
dynstr_append(ds,"Got one of the listed errors\n");
}
/* OK */
@@ -4395,7 +4697,8 @@ static void handle_error(const char *query, struct st_query *q,
}
}
- DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors));
+ DBUG_PRINT("info",("i: %d expected_errors: %d", i,
+ command->expected_errors.count));
if (!disable_result_log)
{
@@ -4408,13 +4711,14 @@ static void handle_error(const char *query, struct st_query *q,
if (i)
{
- if (q->expected_errno[0].type == ERR_ERRNO)
+ if (command->expected_errors.err[0].type == ERR_ERRNO)
die("query '%s' failed with wrong errno %d: '%s', instead of %d...",
- q->query, err_errno, err_error, q->expected_errno[0].code.errnum);
+ 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...",
- q->query, err_sqlstate, err_error,
- q->expected_errno[0].code.sqlstate);
+ command->query, err_sqlstate, err_error,
+ command->expected_errors.err[0].code.sqlstate);
}
DBUG_VOID_RETURN;
@@ -4425,30 +4729,30 @@ static void handle_error(const char *query, struct st_query *q,
Handle absence of errors after execution
SYNOPSIS
- handle_no_error()
- q - context of query
+ handle_no_error()
+ q - context of query
RETURN VALUE
- error - function will not return
+ error - function will not return
*/
-static void handle_no_error(struct st_query *q)
+void handle_no_error(struct st_command *command)
{
DBUG_ENTER("handle_no_error");
- if (q->expected_errno[0].type == ERR_ERRNO &&
- q->expected_errno[0].code.errnum != 0)
+ 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("query '%s' succeeded - should have failed with errno %d...",
- q->query, q->expected_errno[0].code.errnum);
+ command->query, command->expected_errors.err[0].code.errnum);
}
- else if (q->expected_errno[0].type == ERR_SQLSTATE &&
- strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0)
+ 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...",
- q->query, q->expected_errno[0].code.sqlstate);
+ command->query, command->expected_errors.err[0].code.sqlstate);
}
DBUG_VOID_RETURN;
@@ -4470,9 +4774,9 @@ static void handle_no_error(struct st_query *q)
error - function will not return
*/
-static void run_query_stmt(MYSQL *mysql, struct st_query *command,
- char *query, int query_len, DYNAMIC_STRING *ds,
- DYNAMIC_STRING *ds_warnings)
+void run_query_stmt(MYSQL *mysql, struct st_command *command,
+ char *query, int query_len, DYNAMIC_STRING *ds,
+ DYNAMIC_STRING *ds_warnings)
{
MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */
MYSQL_STMT *stmt;
@@ -4503,7 +4807,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
*/
if (mysql_stmt_prepare(stmt, query, query_len))
{
- handle_error(query, command, mysql_stmt_errno(stmt),
+ handle_error(command, mysql_stmt_errno(stmt),
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
goto end;
}
@@ -4520,6 +4824,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
parameter markers.
*/
+#if MYSQL_VERSION_ID >= 50000
if (cursor_protocol_enabled)
{
/*
@@ -4530,13 +4835,14 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
}
+#endif
/*
Execute the query
*/
if (mysql_stmt_execute(stmt))
{
- handle_error(query, command, mysql_stmt_errno(stmt),
+ handle_error(command, mysql_stmt_errno(stmt),
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
goto end;
}
@@ -4550,8 +4856,8 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
/*
We instruct that we want to update the "max_length" field in
- mysql_stmt_store_result(), this is our only way to know how much
- buffer to allocate for result data
+ mysql_stmt_store_result(), this is our only way to know how much
+ buffer to allocate for result data
*/
{
my_bool one= 1;
@@ -4566,7 +4872,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
*/
if (mysql_stmt_store_result(stmt))
{
- handle_error(query, command, mysql_stmt_errno(stmt),
+ handle_error(command, mysql_stmt_errno(stmt),
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
goto end;
}
@@ -4636,9 +4942,6 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
}
end:
- free_replace();
- free_replace_regex();
-
if (!disable_warnings)
{
dynstr_free(&ds_prepare_warnings);
@@ -4650,7 +4953,7 @@ end:
to the server into the mysqltest builtin variable $mysql_errno. This
variable then can be used from the test case itself.
*/
-
+
var_set_errno(mysql_stmt_errno(stmt));
#ifndef BUG15518_FIXED
mysql_stmt_close(stmt);
@@ -4668,7 +4971,7 @@ end:
as view, sp etc.
*/
-static int util_query(MYSQL* org_mysql, const char* query){
+int util_query(MYSQL* org_mysql, const char* query){
MYSQL* mysql;
DBUG_ENTER("util_query");
@@ -4679,11 +4982,9 @@ static int util_query(MYSQL* org_mysql, const char* query){
if (!(mysql= mysql_init(mysql)))
die("Failed in mysql_init()");
- if (safe_connect(mysql, org_mysql->host, org_mysql->user,
- org_mysql->passwd, org_mysql->db, org_mysql->port,
- org_mysql->unix_socket))
- die("Could not open util connection: %d %s",
- mysql_errno(mysql), mysql_error(mysql));
+ safe_connect(mysql, "util", org_mysql->host, org_mysql->user,
+ org_mysql->passwd, org_mysql->db, org_mysql->port,
+ org_mysql->unix_socket);
cur_con->util_mysql= mysql;
}
@@ -4697,8 +4998,8 @@ static int util_query(MYSQL* org_mysql, const char* query){
Run query
flags control the phased/stages of query execution to be performed
- if QUERY_SEND bit is on, the query will be sent. If QUERY_REAP is on
- the result will be read - for regular query, both bits must be on
+ if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
+ is on the result will be read - for regular query, both bits must be on
SYNPOSIS
run_query
@@ -4707,7 +5008,7 @@ static int util_query(MYSQL* org_mysql, const char* query){
*/
-static void run_query(MYSQL *mysql, struct st_query *command, int flags)
+void run_query(MYSQL *mysql, struct st_command *command, int flags)
{
DYNAMIC_STRING *ds;
DYNAMIC_STRING ds_result;
@@ -4716,17 +5017,21 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags)
char *query;
int query_len;
my_bool view_created= 0, sp_created= 0;
- my_bool complete_query= ((flags & QUERY_SEND) && (flags & QUERY_REAP));
+ my_bool complete_query= ((flags & QUERY_SEND_FLAG) &&
+ (flags & QUERY_REAP_FLAG));
init_dynamic_string(&ds_warnings, NULL, 0, 256);
+ /* Scan for warning before sendign to server */
+ scan_command_for_warnings(command);
+
/*
Evaluate query if this is an eval command
- */
+ */
if (command->type == Q_EVAL)
{
- init_dynamic_string(&eval_query, "", 16384, 65536);
- do_eval(&eval_query, command->query, FALSE);
+ init_dynamic_string(&eval_query, "", command->query_len+256, 1024);
+ do_eval(&eval_query, command->query, command->end, FALSE);
query = eval_query.str;
query_len = eval_query.length;
}
@@ -4737,23 +5042,23 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags)
}
/*
- When command->record_file is set the output of _this_ query
+ When command->require_file is set the output of _this_ query
should be compared with an already existing file
Create a temporary dynamic string to contain the output from
this query.
- */
- if (command->record_file[0])
+ */
+ if (command->require_file[0])
{
- init_dynamic_string(&ds_result, "", 16384, 65536);
+ init_dynamic_string(&ds_result, "", 1024, 1024);
ds= &ds_result;
}
else
ds= &ds_res;
/*
- Log the query into the output buffer
+ Log the query into the output buffer
*/
- if (!disable_query_log && (flags & QUERY_SEND))
+ if (!disable_query_log && (flags & QUERY_SEND_FLAG))
{
replace_dynstr_append_mem(ds, query, query_len);
dynstr_append_mem(ds, delimiter, delimiter_length);
@@ -4765,8 +5070,8 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags)
match_re(&view_re, query))
{
/*
- Create the query as a view.
- Use replace since view can exist from a failed mysqltest run
+ Create the query as a view.
+ Use replace since view can exist from a failed mysqltest run
*/
DYNAMIC_STRING query_str;
init_dynamic_string(&query_str,
@@ -4778,7 +5083,7 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags)
/*
Failed to create the view, this is not fatal
just run the query the normal way
- */
+ */
DBUG_PRINT("view_create_error",
("Failed to create view '%s': %d: %s", query_str.str,
mysql_errno(mysql), mysql_error(mysql)));
@@ -4791,14 +5096,14 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags)
{
/*
Yes, it was possible to create this query as a view
- */
+ */
view_created= 1;
query= (char*)"SELECT * FROM mysqltest_tmp_v";
query_len = strlen(query);
/*
- Collect warnings from create of the view that should otherwise
- have been produced when the SELECT was executed
+ Collect warnings from create of the view that should otherwise
+ have been produced when the SELECT was executed
*/
append_warnings(&ds_warnings, cur_con->util_mysql);
}
@@ -4877,26 +5182,14 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags)
mysql_errno(mysql), mysql_error(mysql));
}
- if (command->record_file[0])
+ if (command->require_file[0])
{
- /* A result file was specified for _this_ query */
- if (record)
- {
- /*
- Recording in progress
- Dump the output from _this_ query to the specified record_file
- */
- str_to_file(command->record_file, ds->str, ds->length);
-
- } else {
-
- /*
- The output from _this_ query should be checked against an already
- existing file which has been specified using --require or --result
- */
- check_result(ds, command->record_file, command->require_file);
- }
+ /* A result file was specified for _this_ query
+ and the output should be checked against an already
+ existing file which has been specified using --require or --result
+ */
+ check_require(ds, command->require_file);
}
dynstr_free(&ds_warnings);
@@ -4906,12 +5199,12 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags)
dynstr_free(&eval_query);
}
+/****************************************************************************/
+/*
+ Functions to detect different SQL statements
+*/
-/****************************************************************************\
- * Functions to detect different SQL statements
-\****************************************************************************/
-
-static char *re_eprint(int err)
+char *re_eprint(int err)
{
static char epbuf[100];
size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL,
@@ -4920,7 +5213,7 @@ static char *re_eprint(int err)
return(epbuf);
}
-static void init_re_comp(my_regex_t *re, const char* str)
+void init_re_comp(my_regex_t *re, const char* str)
{
int err= my_regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB),
&my_charset_latin1);
@@ -4933,11 +5226,11 @@ static void init_re_comp(my_regex_t *re, const char* str)
}
}
-static void init_re(void)
+void init_re(void)
{
/*
- Filter for queries that can be run using the
- MySQL Prepared Statements C API
+ Filter for queries that can be run using the
+ MySQL Prepared Statements C API
*/
const char *ps_re_str =
"^("
@@ -4954,13 +5247,13 @@ static void init_re(void)
"[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])";
/*
- Filter for queries that can be run using the
- Stored procedures
+ Filter for queries that can be run using the
+ Stored procedures
*/
const char *sp_re_str =ps_re_str;
/*
- Filter for queries that can be run as views
+ Filter for queries that can be run as views
*/
const char *view_re_str =
"^("
@@ -4972,7 +5265,7 @@ static void init_re(void)
}
-static int match_re(my_regex_t *re, char *str)
+int match_re(my_regex_t *re, char *str)
{
int err= my_regexec(re, str, (size_t)0, NULL, 0);
@@ -4990,7 +5283,7 @@ static int match_re(my_regex_t *re, char *str)
return 0;
}
-static void free_re(void)
+void free_re(void)
{
my_regfree(&ps_re);
my_regfree(&sp_re);
@@ -5000,142 +5293,85 @@ static void free_re(void)
/****************************************************************************/
-void get_query_type(struct st_query* q)
+void get_command_type(struct st_command* command)
{
char save;
uint type;
- DBUG_ENTER("get_query_type");
+ DBUG_ENTER("get_command_type");
- if (!parsing_disabled && *q->query == '}')
+ if (*command->query == '}')
{
- q->type = Q_END_BLOCK;
+ command->type = Q_END_BLOCK;
DBUG_VOID_RETURN;
}
- if (q->type != Q_COMMENT_WITH_COMMAND)
- q->type= parsing_disabled ? Q_COMMENT : Q_QUERY;
- save=q->query[q->first_word_len];
- q->query[q->first_word_len]=0;
- type=find_type(q->query, &command_typelib, 1+2);
- q->query[q->first_word_len]=save;
+ save= command->query[command->first_word_len];
+ command->query[command->first_word_len]= 0;
+ type= find_type(command->query, &command_typelib, 1+2);
+ command->query[command->first_word_len]= save;
if (type > 0)
{
- q->type=(enum enum_commands) type; /* Found command */
+ command->type=(enum enum_commands) type; /* Found command */
+
/*
- If queries are disabled, only recognize
- --enable_parsing and --disable_parsing
+ Look for case where "query" was explicitly specified to
+ force command being sent to server
*/
- if (parsing_disabled && q->type != Q_ENABLE_PARSING &&
- q->type != Q_DISABLE_PARSING)
- q->type= Q_COMMENT;
+ if (type == Q_QUERY)
+ {
+ /* Skip the "query" part */
+ command->query= command->first_argument;
+ }
}
- else if (q->type == Q_COMMENT_WITH_COMMAND &&
- q->first_word_len &&
- q->query[q->first_word_len-1] == ';')
+ else
{
- /*
- Detect comment with command using extra delimiter
- Ex --disable_query_log;
- ^ Extra delimiter causing the command
- to be skipped
- */
- save= q->query[q->first_word_len-1];
- q->query[q->first_word_len-1]= 0;
- type= find_type(q->query, &command_typelib, 1+2);
- q->query[q->first_word_len-1]= save;
- if (type > 0)
- die("Extra delimiter \";\" found");
- }
- DBUG_VOID_RETURN;
-}
-
-
-static byte *get_var_key(const byte* var, uint* len,
- my_bool __attribute__((unused)) t)
-{
- register char* key;
- key = ((VAR*)var)->name;
- *len = ((VAR*)var)->name_len;
- return (byte*)key;
-}
+ /* No mysqltest command matched */
-static VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
- int val_len)
-{
- int val_alloc_len;
- VAR *tmp_var;
- if (!name_len && name)
- name_len = strlen(name);
- if (!val_len && val)
- val_len = strlen(val) ;
- val_alloc_len = val_len + 16; /* room to grow */
- if (!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
- + name_len+1, MYF(MY_WME))))
- die("Out of memory");
-
- tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
- tmp_var->alloced = (v == 0);
-
- if (!(tmp_var->str_val = my_malloc(val_alloc_len+1, MYF(MY_WME))))
- die("Out of memory");
+ if (command->type != Q_COMMENT_WITH_COMMAND)
+ {
+ /* A query that will sent to mysqld */
+ command->type= Q_QUERY;
+ }
+ else
+ {
+ /* -- comment that didn't contain a mysqltest command */
+ command->type= Q_COMMENT;
+ warning_msg("Suspicious command '--%s' detected, was this intentional? "\
+ "Use # instead of -- to avoid this warning",
+ command->query);
+
+ if (command->first_word_len &&
+ strcmp(command->query + command->first_word_len - 1, delimiter) == 0)
+ {
+ /*
+ Detect comment with command using extra delimiter
+ Ex --disable_query_log;
+ ^ Extra delimiter causing the command
+ to be skipped
+ */
+ save= command->query[command->first_word_len-1];
+ command->query[command->first_word_len-1]= 0;
+ if (find_type(command->query, &command_typelib, 1+2) > 0)
+ die("Extra delimiter \";\" found");
+ command->query[command->first_word_len-1]= save;
- memcpy(tmp_var->name, name, name_len);
- if (val)
- {
- memcpy(tmp_var->str_val, val, val_len);
- tmp_var->str_val[val_len]= 0;
+ }
+ }
}
- tmp_var->name_len = name_len;
- tmp_var->str_val_len = val_len;
- tmp_var->alloced_len = val_alloc_len;
- tmp_var->int_val = (val) ? atoi(val) : 0;
- tmp_var->int_dirty = 0;
- tmp_var->env_s = 0;
- return tmp_var;
-}
-
-static void var_free(void *v)
-{
- my_free(((VAR*) v)->str_val, MYF(MY_WME));
- if (((VAR*)v)->alloced)
- my_free((char*) v, MYF(MY_WME));
-}
-
-
-static VAR* var_from_env(const char *name, const char *def_val)
-{
- const char *tmp;
- VAR *v;
- if (!(tmp = getenv(name)))
- tmp = def_val;
-
- v = var_init(0, name, strlen(name), tmp, strlen(tmp));
- my_hash_insert(&var_hash, (byte*)v);
- return v;
-}
+ /* Set expected error on command */
+ memcpy(&command->expected_errors, &saved_expected_errors,
+ sizeof(saved_expected_errors));
+ DBUG_PRINT("info", ("There are %d expected errors",
+ command->expected_errors.count));
+ command->abort_on_error= (command->expected_errors.count == 0 &&
+ abort_on_error);
-static void init_var_hash(MYSQL *mysql)
-{
- VAR *v;
- DBUG_ENTER("init_var_hash");
- if (hash_init(&var_hash, charset_info,
- 1024, 0, 0, get_var_key, var_free, MYF(0)))
- die("Variable hash initialization failed");
- my_hash_insert(&var_hash, (byte*) var_init(0,"BIG_TEST", 0,
- (opt_big_test) ? "1" : "0", 0));
- my_hash_insert(&var_hash, (byte*) var_init(0,"VALGRIND_TEST", 0,
- (opt_valgrind_test) ? "1" : "0",
- 0));
- v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0);
- my_hash_insert(&var_hash, (byte*) v);
- v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0);
- my_hash_insert(&var_hash, (byte*) v); v= var_init(0,"DB", 2, db, 0);
- my_hash_insert(&var_hash, (byte*) v);
DBUG_VOID_RETURN;
}
+
/*
Record how many milliseconds it took to execute the test file
up until the current line and save it in the dynamic string ds_progress.
@@ -5144,7 +5380,9 @@ static void init_var_hash(MYSQL *mysql)
test run completes
*/
-static void mark_progress(struct st_query* q __attribute__((unused)), int line)
+
+void mark_progress(struct st_command* command __attribute__((unused)),
+ int line)
{
char buf[32], *end;
ulonglong timer= timer_now();
@@ -5178,47 +5416,63 @@ static void mark_progress(struct st_query* q __attribute__((unused)), int line)
int main(int argc, char **argv)
{
- struct st_query *q;
- my_bool require_file=0, q_send_flag=0,
- query_executed= 0;
+ struct st_command *command;
+ my_bool q_send_flag= 0;
+ uint command_executed= 0, last_command_executed= 0;
char save_file[FN_REFLEN];
MY_STAT res_info;
MY_INIT(argv[0]);
- /* Use all time until exit if no explicit 'start_timer' */
- timer_start= timer_now();
+ save_file[0]= 0;
+ TMPDIR[0]= 0;
- save_file[0]=0;
- TMPDIR[0]=0;
+ /* Init expected errors */
+ memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
- /* Init cons */
- memset(cons, 0, sizeof(cons));
- cons_end = cons + MAX_CONS;
- next_con = cons + 1;
- cur_con = cons;
+ /* Init connections */
+ memset(connections, 0, sizeof(connections));
+ connections_end= connections +
+ (sizeof(connections)/sizeof(struct st_connection)) - 1;
+ next_con= connections + 1;
+ cur_con= connections;
/* Init file stack */
memset(file_stack, 0, sizeof(file_stack));
- file_stack_end= file_stack + MAX_INCLUDE_DEPTH - 1;
+ file_stack_end=
+ file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
cur_file= file_stack;
/* Init block stack */
memset(block_stack, 0, sizeof(block_stack));
- block_stack_end= block_stack + BLOCK_STACK_DEPTH - 1;
+ block_stack_end=
+ block_stack + (sizeof(block_stack)/sizeof(struct st_block)) - 1;
cur_block= block_stack;
cur_block->ok= TRUE; /* Outer block should always be executed */
cur_block->cmd= cmd_none;
- my_init_dynamic_array(&q_lines, sizeof(struct st_query*), INIT_Q_LINES,
- INIT_Q_LINES);
+ my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
+
+ if (hash_init(&var_hash, charset_info,
+ 1024, 0, 0, get_var_key, var_free, MYF(0)))
+ die("Variable hash initialization failed");
memset(&master_pos, 0, sizeof(master_pos));
- init_dynamic_string(&ds_res, "", 0, 65536);
+ parser.current_line= parser.read_lines= 0;
+ memset(&var_reg, 0, sizeof(var_reg));
+
+#ifdef __WIN__
+ init_tmp_sh_file();
+ init_win_path_patterns();
+#endif
+
+ init_dynamic_string(&ds_res, "", 65536, 65536);
init_dynamic_string(&ds_progress, "", 0, 2048);
+ init_dynamic_string(&ds_warning_messages, "", 0, 2048);
parse_args(argc, argv);
- DBUG_PRINT("info",("result_file: '%s'", result_file ? result_file : ""));
+ DBUG_PRINT("info",("result_file: '%s'",
+ result_file_name ? result_file_name : ""));
if (mysql_server_init(embedded_server_arg_count,
embedded_server_args,
(char**) embedded_server_groups))
@@ -5246,29 +5500,30 @@ int main(int argc, char **argv)
mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name);
#ifdef HAVE_OPENSSL
+
+#if MYSQL_VERSION_ID >= 50000
opt_ssl_verify_server_cert= TRUE; /* Always on in mysqltest */
+#endif
+
if (opt_use_ssl)
{
mysql_ssl_set(&cur_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+#if MYSQL_VERSION_ID >= 50000
mysql_options(&cur_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
&opt_ssl_verify_server_cert);
+#endif
}
#endif
if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
die("Out of memory");
- if (safe_connect(&cur_con->mysql, host, user, pass, db, port, unix_sock))
- die("Could not open connection '%s': %d %s", cur_con->name,
- mysql_errno(&cur_con->mysql), mysql_error(&cur_con->mysql));
-
- init_var_hash(&cur_con->mysql);
+ safe_connect(&cur_con->mysql, cur_con->name, host, user, pass,
+ db, port, unix_sock);
-#ifdef __WIN__
- init_tmp_sh_file();
- init_win_path_patterns();
-#endif
+ /* Use all time until exit if no explicit 'start_timer' */
+ timer_start= timer_now();
/*
Initialize $mysql_errno with -1, so we can
@@ -5282,26 +5537,35 @@ int main(int argc, char **argv)
open_file(opt_include);
}
- while (!read_query(&q))
+ while (!read_command(&command))
{
int current_line_inc = 1, processed = 0;
- if (q->type == Q_UNKNOWN || q->type == Q_COMMENT_WITH_COMMAND)
- get_query_type(q);
+ if (command->type == Q_UNKNOWN || command->type == Q_COMMENT_WITH_COMMAND)
+ get_command_type(command);
+
+ if (parsing_disabled &&
+ command->type != Q_ENABLE_PARSING &&
+ command->type != Q_DISABLE_PARSING)
+ {
+ command->type= Q_COMMENT;
+ scan_command_for_warnings(command);
+ }
+
if (cur_block->ok)
{
- q->last_argument= q->first_argument;
+ command->last_argument= command->first_argument;
processed = 1;
- switch (q->type) {
+ switch (command->type) {
case Q_CONNECT:
- do_connect(q);
+ do_connect(command);
break;
- case Q_CONNECTION: select_connection(q); break;
+ case Q_CONNECTION: select_connection(command); break;
case Q_DISCONNECT:
case Q_DIRTY_CLOSE:
- close_connection(q); break;
- case Q_RPL_PROBE: do_rpl_probe(q); break;
- case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break;
- case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break;
+ do_close_connection(command); break;
+ case Q_RPL_PROBE: do_rpl_probe(command); break;
+ case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(command); break;
+ case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(command); break;
case Q_ENABLE_QUERY_LOG: disable_query_log=0; break;
case Q_DISABLE_QUERY_LOG: disable_query_log=1; break;
case Q_ENABLE_ABORT_ON_ERROR: abort_on_error=1; break;
@@ -5316,18 +5580,21 @@ int main(int argc, char **argv)
case Q_DISABLE_INFO: disable_info=1; break;
case Q_ENABLE_METADATA: display_metadata=1; break;
case Q_DISABLE_METADATA: display_metadata=0; break;
- case Q_SOURCE: do_source(q); break;
- case Q_SLEEP: do_sleep(q, 0); break;
- case Q_REAL_SLEEP: do_sleep(q, 1); break;
- case Q_WAIT_FOR_SLAVE_TO_STOP: do_wait_for_slave_to_stop(q); break;
- case Q_INC: do_modify_var(q, DO_INC); break;
- case Q_DEC: do_modify_var(q, DO_DEC); break;
- case Q_ECHO: do_echo(q); query_executed= 1; break;
- case Q_SYSTEM: do_system(q); 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;
+ case Q_WAIT_FOR_SLAVE_TO_STOP: do_wait_for_slave_to_stop(command); break;
+ case Q_INC: do_modify_var(command, DO_INC); break;
+ case Q_DEC: do_modify_var(command, DO_DEC); break;
+ case Q_ECHO: do_echo(command); command_executed++; break;
+ case Q_SYSTEM: do_system(command); break;
+ case Q_REMOVE_FILE: do_remove_file(command); break;
+ case Q_FILE_EXIST: do_file_exist(command); break;
+ case Q_WRITE_FILE: do_write_file(command); break;
+ case Q_COPY_FILE: do_copy_file(command); break;
+ case Q_PERL: do_perl(command); break;
case Q_DELIMITER:
- strmake(delimiter, q->first_argument, sizeof(delimiter) - 1);
- delimiter_length= strlen(delimiter);
- q->last_argument= q->first_argument+delimiter_length;
+ do_delimiter(command);
break;
case Q_DISPLAY_VERTICAL_RESULTS:
display_result_vertically= TRUE;
@@ -5335,133 +5602,128 @@ int main(int argc, char **argv)
case Q_DISPLAY_HORIZONTAL_RESULTS:
display_result_vertically= FALSE;
break;
- case Q_LET: do_let(q); break;
+ case Q_LET: do_let(command); break;
case Q_EVAL_RESULT:
eval_result = 1; break;
case Q_EVAL:
- if (q->query == q->query_buf)
+ if (command->query == command->query_buf)
{
- q->query= q->first_argument;
- q->first_word_len= 0;
+ command->query= command->first_argument;
+ command->first_word_len= 0;
}
/* fall through */
case Q_QUERY_VERTICAL:
case Q_QUERY_HORIZONTAL:
{
my_bool old_display_result_vertically= display_result_vertically;
- /* fix up query pointer if this is first iteration for this line */
- if (q->query == q->query_buf)
- q->query += q->first_word_len + 1;
- display_result_vertically= (q->type==Q_QUERY_VERTICAL);
+
+ /* Remove "query_*" if this is first iteration */
+ if (command->query == command->query_buf)
+ command->query= command->first_argument;
+
+ display_result_vertically= (command->type == Q_QUERY_VERTICAL);
if (save_file[0])
{
- strmov(q->record_file,save_file);
- q->require_file=require_file;
- save_file[0]=0;
+ strmake(command->require_file, save_file, sizeof(save_file));
+ save_file[0]= 0;
}
- run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND);
+ run_query(&cur_con->mysql, command, QUERY_REAP_FLAG|QUERY_SEND_FLAG);
display_result_vertically= old_display_result_vertically;
- q->last_argument= q->end;
- query_executed= 1;
+ command->last_argument= command->end;
+ command_executed++;
break;
}
case Q_QUERY:
case Q_REAP:
{
- /*
- We read the result always regardless of the mode for both full
- query and read-result only (reap)
- */
- int flags = QUERY_REAP;
- if (q->type != Q_REAP) /* for a full query, enable the send stage */
- flags |= QUERY_SEND;
- if (q_send_flag)
- {
- flags= QUERY_SEND;
- q_send_flag=0;
- }
+ int flags;
+ if (q_send_flag)
+ {
+ /* Last command was an empty 'send' */
+ flags= QUERY_SEND_FLAG;
+ q_send_flag= 0;
+ }
+ else if (command->type == Q_REAP)
+ {
+ flags= QUERY_REAP_FLAG;
+ }
+ else
+ {
+ /* full query, both reap and send */
+ flags= QUERY_REAP_FLAG | QUERY_SEND_FLAG;
+ }
+
if (save_file[0])
{
- strmov(q->record_file,save_file);
- q->require_file=require_file;
- save_file[0]=0;
+ strmake(command->require_file, save_file, sizeof(save_file));
+ save_file[0]= 0;
}
- /*
- To force something being sent as a query to the mysqld one can
- use the prefix "query". Remove "query" from string before executing
- */
- if (strncmp(q->query, "query ", 6) == 0)
- {
- q->query= q->first_argument;
- }
- run_query(&cur_con->mysql, q, flags);
- query_executed= 1;
- q->last_argument= q->end;
+ run_query(&cur_con->mysql, command, flags);
+ command_executed++;
+ command->last_argument= command->end;
break;
}
case Q_SEND:
- if (!q->query[q->first_word_len])
- {
- /* This happens when we use 'send' on its own line */
- q_send_flag=1;
- break;
- }
- /* fix up query pointer if this is first iteration for this line */
- if (q->query == q->query_buf)
- q->query += q->first_word_len;
+ if (!*command->first_argument)
+ {
+ /*
+ This is a send without arguments, it indicates that _next_ query
+ should be send only
+ */
+ q_send_flag= 1;
+ break;
+ }
+
+ /* Remove "send" if this is first iteration */
+ if (command->query == command->query_buf)
+ command->query= command->first_argument;
+
/*
run_query() can execute a query partially, depending on the flags.
- QUERY_SEND flag without QUERY_REAP tells it to just send the
- query and read the result some time later when reap instruction
+ QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
+ the query and read the result some time later when reap instruction
is given on this connection.
- */
- run_query(&cur_con->mysql, q, QUERY_SEND);
- query_executed= 1;
- q->last_argument= q->end;
+ */
+ run_query(&cur_con->mysql, command, QUERY_SEND_FLAG);
+ command_executed++;
+ command->last_argument= command->end;
break;
- case Q_RESULT:
- get_file_name(save_file,q);
- require_file=0;
+ case Q_REQUIRE:
+ do_get_file_name(command, save_file, sizeof(save_file));
break;
case Q_ERROR:
- global_expected_errors=get_errcodes(global_expected_errno,q);
- break;
- case Q_REQUIRE:
- get_file_name(save_file,q);
- require_file=1;
+ do_get_errcodes(command);
break;
case Q_REPLACE:
- get_replace(q);
+ do_get_replace(command);
break;
case Q_REPLACE_REGEX:
- get_replace_regex(q);
+ do_get_replace_regex(command);
break;
-
case Q_REPLACE_COLUMN:
- get_replace_column(q);
+ do_get_replace_column(command);
break;
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
- case Q_SYNC_WITH_MASTER: do_sync_with_master(q); break;
+ case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
case Q_SYNC_SLAVE_WITH_MASTER:
{
do_save_master_pos();
- if (*q->first_argument)
- select_connection(q);
+ if (*command->first_argument)
+ select_connection(command);
else
select_connection_name("slave");
do_sync_with_master2(0);
break;
}
case Q_COMMENT: /* Ignore row */
- case Q_COMMENT_WITH_COMMAND:
- q->last_argument= q->end;
+ command->last_argument= command->end;
break;
case Q_PING:
(void) mysql_ping(&cur_con->mysql);
break;
case Q_EXEC:
- do_exec(q);
- query_executed= 1;
+ do_exec(command);
+ command_executed++;
break;
case Q_START_TIMER:
/* Overwrite possible earlier start of timer */
@@ -5470,10 +5732,9 @@ int main(int argc, char **argv)
case Q_END_TIMER:
/* End timer before ending mysqltest */
timer_output();
- got_end_timer= TRUE;
break;
case Q_CHARACTER_SET:
- set_charset(q);
+ do_set_charset(command);
break;
case Q_DISABLE_PS_PROTOCOL:
ps_protocol_enabled= 0;
@@ -5482,31 +5743,33 @@ int main(int argc, char **argv)
ps_protocol_enabled= ps_protocol;
break;
case Q_DISABLE_RECONNECT:
- {
- my_bool reconnect= 0;
- mysql_options(&cur_con->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
+ set_reconnect(&cur_con->mysql, 0);
break;
- }
case Q_ENABLE_RECONNECT:
- {
- my_bool reconnect= 1;
- mysql_options(&cur_con->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
+ set_reconnect(&cur_con->mysql, 1);
break;
- }
case Q_DISABLE_PARSING:
- parsing_disabled++;
+ if (parsing_disabled == 0)
+ parsing_disabled= 1;
+ else
+ die("Parsing is already disabled");
break;
case Q_ENABLE_PARSING:
/*
Ensure we don't get parsing_disabled < 0 as this would accidentally
disable code we don't want to have disabled
*/
- if (parsing_disabled > 0)
- parsing_disabled--;
+ if (parsing_disabled == 1)
+ parsing_disabled= 0;
+ else
+ die("Parsing is already enabled");
break;
-
case Q_DIE:
- die("%s", q->first_argument);
+ die("%s", command->first_argument);
+ break;
+
+ case Q_RESULT:
+ die("result, deprecated command");
break;
default:
@@ -5518,33 +5781,46 @@ int main(int argc, char **argv)
if (!processed)
{
current_line_inc= 0;
- switch (q->type) {
- case Q_WHILE: do_block(cmd_while, q); break;
- case Q_IF: do_block(cmd_if, q); break;
- case Q_END_BLOCK: do_done(q); break;
+ switch (command->type) {
+ case Q_WHILE: do_block(cmd_while, command); break;
+ case Q_IF: do_block(cmd_if, command); break;
+ case Q_END_BLOCK: do_done(command); break;
default: current_line_inc = 1; break;
}
}
else
- check_eol_junk(q->last_argument);
+ check_eol_junk(command->last_argument);
- if (q->type != Q_ERROR)
+ if (command->type != Q_ERROR &&
+ command->type != Q_COMMENT)
{
/*
- As soon as any non "error" command has been executed,
+ As soon as any non "error" command or comment has been executed,
the array with expected errors should be cleared
*/
- global_expected_errors= 0;
- bzero((gptr) global_expected_errno, sizeof(global_expected_errno));
+ memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
+ }
+
+ if (command_executed != last_command_executed)
+ {
+ /*
+ As soon as any command has been executed,
+ the replace structures should be cleared
+ */
+ free_all_replace();
}
+ last_command_executed= command_executed;
parser.current_line += current_line_inc;
if ( opt_mark_progress )
- mark_progress(q, parser.current_line);
+ mark_progress(command, parser.current_line);
}
start_lineno= 0;
+ if (parsing_disabled)
+ die("Test ended with parsing disabled");
+
/*
The whole test has been executed _sucessfully_.
Time to compare result or save it to record file.
@@ -5552,25 +5828,27 @@ int main(int argc, char **argv)
*/
if (ds_res.length)
{
- if (result_file)
+ if (result_file_name)
{
+ /* A result file has been specified */
+
if (record)
{
- /* Dump the output from test to result file */
- str_to_file(result_file, ds_res.str, ds_res.length);
+ /* Recording - dump the output from test to result file */
+ str_to_file(result_file_name, ds_res.str, ds_res.length);
}
else
{
/* Check that the output from test is equal to result file
- detect missing result file
- detect zero size result file
- */
- check_result(&ds_res, result_file, 0);
+ */
+ check_result(&ds_res);
}
}
else
{
- /* No result_file specified to compare with, print to stdout */
+ /* No result_file_name specified to compare with, print to stdout */
printf("%s", ds_res.str);
}
}
@@ -5579,7 +5857,8 @@ int main(int argc, char **argv)
die("The test didn't produce any output");
}
- if (!query_executed && result_file && my_stat(result_file, &res_info, 0))
+ if (!command_executed &&
+ result_file_name && my_stat(result_file_name, &res_info, 0))
{
/*
my_stat() successful on result file. Check if we have not run a
@@ -5591,14 +5870,16 @@ int main(int argc, char **argv)
die("No queries executed but result file found!");
}
- if ( opt_mark_progress )
- dump_progress(result_file);
- dynstr_free(&ds_progress);
+ if ( opt_mark_progress && result_file_name )
+ dump_progress();
+
+ /* Dump warning messages */
+ if (result_file_name && ds_warning_messages.length)
+ dump_warning_messages();
dynstr_free(&ds_res);
- if (!got_end_timer)
- timer_output(); /* No end_timer cmd, end it */
+ timer_output();
free_used_memory();
my_end(MY_CHECK_ERROR);
@@ -5611,101 +5892,188 @@ int main(int argc, char **argv)
/*
- Read arguments for embedded server and put them into
- embedded_server_args_count and embedded_server_args[]
-*/
+ A primitive timer that give results in milliseconds if the
+ --timer-file=<filename> is given. The timer result is written
+ to that file when the result is available. To not confuse
+ mysql-test-run with an old obsolete result, we remove the file
+ before executing any commands. The time we measure is
+ - If no explicit 'start_timer' or 'end_timer' is given in the
+ test case, the timer measure how long we execute in mysqltest.
-static int read_server_arguments(const char *name)
-{
- char argument[1024],buff[FN_REFLEN], *str=0;
- FILE *file;
+ - If only 'start_timer' is given we measure how long we execute
+ from that point until we terminate mysqltest.
- if (!test_if_hard_path(name))
+ - If only 'end_timer' is given we measure how long we execute
+ from that we enter mysqltest to the 'end_timer' is command is
+ executed.
+
+ - If both 'start_timer' and 'end_timer' are given we measure
+ the time between executing the two commands.
+*/
+
+void timer_output(void)
+{
+ if (timer_file)
{
- strxmov(buff, opt_basedir, name, NullS);
- name=buff;
+ char buf[32], *end;
+ ulonglong timer= timer_now() - timer_start;
+ end= longlong2str(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;
}
- fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
+}
- if (!embedded_server_arg_count)
+
+ulonglong timer_now(void)
+{
+ return my_getsystime() / 10000;
+}
+
+
+/*
+ Get arguments for replace_columns. The syntax is:
+ replace-column column_number to_string [column_number to_string ...]
+ Where each argument may be quoted with ' or "
+ A argument may also be a variable, in which case the value of the
+ variable is replaced.
+*/
+
+void do_get_replace_column(struct st_command *command)
+{
+ char *from= command->first_argument;
+ char *buff, *start;
+ DBUG_ENTER("get_replace_columns");
+
+ free_replace_column();
+ if (!*from)
+ die("Missing argument in %s", command->query);
+
+ /* Allocate a buffer for results */
+ start= buff= my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
+ while (*from)
{
- embedded_server_arg_count=1;
- embedded_server_args[0]= (char*) ""; /* Progname */
+ char *to;
+ uint column_number;
+
+ to= get_string(&buff, &from, 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);
+ to= get_string(&buff, &from, command);
+ my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
+ replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
+ set_if_bigger(max_replace_column, column_number);
}
- if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
- return 1;
- while (embedded_server_arg_count < MAX_SERVER_ARGS &&
- (str=fgets(argument,sizeof(argument), file)))
+ my_free(start, MYF(0));
+ command->last_argument= command->end;
+}
+
+
+void free_replace_column()
+{
+ uint i;
+ for (i=0 ; i < max_replace_column ; i++)
{
- *(strend(str)-1)=0; /* Remove end newline */
- if (!(embedded_server_args[embedded_server_arg_count]=
- (char*) my_strdup(str,MYF(MY_WME))))
+ if (replace_column[i])
{
- my_fclose(file,MYF(0));
- return 1;
+ my_free(replace_column[i], 0);
+ replace_column[i]= 0;
}
- embedded_server_arg_count++;
}
- my_fclose(file,MYF(0));
- if (str)
- {
- fprintf(stderr,"Too many arguments in option file: %s\n",name);
- return 1;
- }
- return 0;
+ max_replace_column= 0;
}
-/****************************************************************************\
- *
- * A primitive timer that give results in milliseconds if the
- * --timer-file=<filename> is given. The timer result is written
- * to that file when the result is available. To not confuse
- * mysql-test-run with an old obsolete result, we remove the file
- * before executing any commands. The time we measure is
- *
- * - If no explicit 'start_timer' or 'end_timer' is given in the
- * test case, the timer measure how long we execute in mysqltest.
- *
- * - If only 'start_timer' is given we measure how long we execute
- * from that point until we terminate mysqltest.
- *
- * - If only 'end_timer' is given we measure how long we execute
- * from that we enter mysqltest to the 'end_timer' is command is
- * executed.
- *
- * - If both 'start_timer' and 'end_timer' are given we measure
- * the time between executing the two commands.
- *
-\****************************************************************************/
-
-static void timer_output(void)
+
+/****************************************************************************/
+/*
+ Replace functions
+*/
+
+/* Definitions for replace result */
+
+typedef struct st_pointer_array { /* when using array-strings */
+ TYPELIB typelib; /* Pointer to strings */
+ byte *str; /* Strings is here */
+ int7 *flag; /* Flag about each var. */
+ uint array_allocs,max_count,length,max_length;
+} POINTER_ARRAY;
+
+struct st_replace;
+struct st_replace *init_replace(my_string *from, my_string *to, uint count,
+ my_string word_end_chars);
+int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name);
+void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
+ const char *from, int len);
+void free_pointer_array(POINTER_ARRAY *pa);
+
+struct st_replace *glob_replace;
+
+/*
+ Get arguments for replace. The syntax is:
+ replace from to [from to ...]
+ Where each argument may be quoted with ' or "
+ A argument may also be a variable, in which case the value of the
+ variable is replaced.
+*/
+
+void do_get_replace(struct st_command *command)
{
- if (timer_file)
+ uint i;
+ char *from= command->first_argument;
+ char *buff, *start;
+ char word_end_chars[256], *pos;
+ POINTER_ARRAY to_array, from_array;
+ DBUG_ENTER("get_replace");
+
+ free_replace();
+
+ bzero((char*) &to_array,sizeof(to_array));
+ bzero((char*) &from_array,sizeof(from_array));
+ if (!*from)
+ die("Missing argument in %s", command->query);
+ start= buff= my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
+ while (*from)
{
- char buf[32], *end;
- ulonglong timer= timer_now() - timer_start;
- end= longlong2str(timer, buf, 10);
- str_to_file(timer_file,buf, (int) (end-buf));
+ char *to= buff;
+ to= get_string(&buff, &from, command);
+ if (!*from)
+ die("Wrong number of arguments to replace_result in '%s'",
+ command->query);
+ insert_pointer_name(&from_array,to);
+ to= get_string(&buff, &from, command);
+ insert_pointer_name(&to_array,to);
}
+ for (i= 1,pos= word_end_chars ; i < 256 ; i++)
+ if (my_isspace(charset_info,i))
+ *pos++= i;
+ *pos=0; /* End pointer */
+ if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
+ (char**) to_array.typelib.type_names,
+ (uint) from_array.typelib.count,
+ word_end_chars)))
+ die("Can't initialize replace from '%s'", command->query);
+ free_pointer_array(&from_array);
+ free_pointer_array(&to_array);
+ my_free(start, MYF(0));
+ command->last_argument= command->end;
+ DBUG_VOID_RETURN;
}
-static ulonglong timer_now(void)
+
+void free_replace()
{
- return my_getsystime() / 10000;
+ DBUG_ENTER("free_replace");
+ if (glob_replace)
+ {
+ my_free((char*) glob_replace,MYF(0));
+ glob_replace=0;
+ }
+ DBUG_VOID_RETURN;
}
-/****************************************************************************
-* Handle replacement of strings
-****************************************************************************/
-
-#define PC_MALLOC 256 /* Bytes for pointers */
-#define PS_MALLOC 512 /* Bytes for data */
-
-#define SPACE_CHAR 256
-#define START_OF_LINE 257
-#define END_OF_LINE 258
-#define LAST_CHAR_CODE 259
typedef struct st_replace {
bool found;
@@ -5719,99 +6087,514 @@ typedef struct st_replace_found {
int from_offset;
} REPLACE_STRING;
-#ifndef WORD_BIT
-#define WORD_BIT (8*sizeof(uint))
-#endif
+void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
+ const char *str, int len)
+{
+ reg1 REPLACE *rep_pos;
+ reg2 REPLACE_STRING *rep_str;
+ const char *start, *from;
+ DBUG_ENTER("replace_strings_append");
+
+ start= from= str;
+ rep_pos=rep+1;
+ for (;;)
+ {
+ /* Loop through states */
+ DBUG_PRINT("info", ("Looping through states"));
+ while (!rep_pos->found)
+ rep_pos= rep_pos->next[(uchar) *from++];
+
+ /* Does this state contain a string to be replaced */
+ if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
+ {
+ /* No match found */
+ dynstr_append_mem(ds, start, from - start - 1);
+ DBUG_PRINT("exit", ("Found no more string to replace, appended: %s", start));
+ DBUG_VOID_RETURN;
+ }
-static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name)
+ /* Found a string that needs to be replaced */
+ DBUG_PRINT("info", ("found: %d, to_offset: %d, from_offset: %d, string: %s",
+ rep_str->found, rep_str->to_offset,
+ rep_str->from_offset, rep_str->replace_string));
+
+ /* Append part of original string before replace string */
+ dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
+
+ /* Append replace string */
+ dynstr_append_mem(ds, rep_str->replace_string,
+ strlen(rep_str->replace_string));
+
+ if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
+ {
+ /* End of from string */
+ DBUG_PRINT("exit", ("Found end of from string"));
+ DBUG_VOID_RETURN;
+ }
+ DBUG_ASSERT(from <= str+len);
+ start= from;
+ rep_pos=rep;
+ }
+}
+
+
+/*
+ Regex replace functions
+*/
+
+
+/* Stores regex substitutions */
+
+struct st_regex
{
- uint i,length,old_count;
- byte *new_pos;
- const char **new_array;
- DBUG_ENTER("insert_pointer_name");
+ char* pattern; /* Pattern to be replaced */
+ char* replace; /* String or expression to replace the pattern with */
+ int icase; /* true if the match is case insensitive */
+};
- if (! pa->typelib.count)
+struct st_replace_regex
+{
+ DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
+
+ /*
+ Temporary storage areas for substitutions. To reduce unnessary copying
+ and memory freeing/allocation, we pre-allocate two buffers, and alternate
+ their use, one for input/one for output, the roles changing on the next
+ st_regex substition. At the end of substitutions buf points to the
+ one containing the final result.
+ */
+ char* buf;
+ char* even_buf;
+ char* odd_buf;
+ int even_buf_len;
+ int odd_buf_len;
+};
+
+struct st_replace_regex *glob_replace_regex= 0;
+
+int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
+ char *string, int icase);
+
+
+
+/*
+ Finds the next (non-escaped) '/' in the expression.
+ (If the character '/' is needed, it can be escaped using '\'.)
+*/
+
+#define PARSE_REGEX_ARG \
+ while (p < expr_end) \
+ { \
+ char c= *p; \
+ if (c == '/') \
+ { \
+ if (last_c == '\\') \
+ { \
+ buf_p[-1]= '/'; \
+ } \
+ else \
+ { \
+ *buf_p++ = 0; \
+ break; \
+ } \
+ } \
+ else \
+ *buf_p++ = c; \
+ \
+ last_c= c; \
+ p++; \
+ } \
+ \
+/*
+ Initializes the regular substitution expression to be used in the
+ result output of test.
+
+ Returns: st_replace_regex struct with pairs of substitutions
+*/
+
+struct st_replace_regex* init_replace_regex(char* expr)
+{
+ struct st_replace_regex* res;
+ char* buf,*expr_end;
+ char* p;
+ char* buf_p;
+ uint expr_len= strlen(expr);
+ char last_c = 0;
+ struct st_regex reg;
+
+ /* my_malloc() will die on fail with MY_FAE */
+ res=(struct st_replace_regex*)my_malloc(
+ sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME));
+ my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
+
+ buf= (char*)res + sizeof(*res);
+ expr_end= expr + expr_len;
+ p= expr;
+ buf_p= buf;
+
+ /* for each regexp substitution statement */
+ while (p < expr_end)
{
- if (!(pa->typelib.type_names=(const char **)
- my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
- (sizeof(my_string)+sizeof(*pa->flag))*
- (sizeof(my_string)+sizeof(*pa->flag))),MYF(MY_WME))))
- DBUG_RETURN(-1);
- if (!(pa->str= (byte*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
- MYF(MY_WME))))
+ bzero(&reg,sizeof(reg));
+ /* find the start of the statement */
+ while (p < expr_end)
{
- my_free((gptr) pa->typelib.type_names,MYF(0));
- DBUG_RETURN (-1);
+ if (*p == '/')
+ break;
+ p++;
}
- pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(byte*)+
- sizeof(*pa->flag));
- pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
- pa->length=0;
- pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
- pa->array_allocs=1;
+
+ if (p == expr_end || ++p == expr_end)
+ {
+ if (res->regex_arr.elements)
+ break;
+ else
+ goto err;
+ }
+ /* we found the start */
+ reg.pattern= buf_p;
+
+ /* Find first argument -- pattern string to be removed */
+ PARSE_REGEX_ARG
+
+ if (p == expr_end || ++p == expr_end)
+ goto err;
+
+ /* buf_p now points to the replacement pattern terminated with \0 */
+ reg.replace= buf_p;
+
+ /* Find second argument -- replace string to replace pattern */
+ PARSE_REGEX_ARG
+
+ if (p == expr_end)
+ goto err;
+
+ /* skip the ending '/' in the statement */
+ p++;
+
+ /* Check if we should do matching case insensitive */
+ if (p < expr_end && *p == 'i')
+ reg.icase= 1;
+
+ /* done parsing the statement, now place it in regex_arr */
+ if (insert_dynamic(&res->regex_arr,(gptr) &reg))
+ die("Out of memory");
}
- length=(uint) strlen(name)+1;
- if (pa->length+length >= pa->max_length)
+ res->odd_buf_len= res->even_buf_len= 8192;
+ res->even_buf= (char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
+ res->odd_buf= (char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
+ res->buf= res->even_buf;
+
+ return res;
+
+err:
+ my_free((gptr)res,0);
+ die("Error parsing replace_regex \"%s\"", expr);
+ return 0;
+}
+
+/*
+ Execute all substitutions on val.
+
+ Returns: true if substituition was made, false otherwise
+ Side-effect: Sets r->buf to be the buffer with all substitutions done.
+
+ IN:
+ struct st_replace_regex* r
+ char* val
+ Out:
+ struct st_replace_regex* r
+ r->buf points at the resulting buffer
+ r->even_buf and r->odd_buf might have been reallocated
+ r->even_buf_len and r->odd_buf_len might have been changed
+
+ TODO: at some point figure out if there is a way to do everything
+ in one pass
+*/
+
+int multi_reg_replace(struct st_replace_regex* r,char* val)
+{
+ uint i;
+ char* in_buf, *out_buf;
+ int* buf_len_p;
+
+ in_buf= val;
+ out_buf= r->even_buf;
+ buf_len_p= &r->even_buf_len;
+ r->buf= 0;
+
+ /* For each substitution, do the replace */
+ for (i= 0; i < r->regex_arr.elements; i++)
{
- if (!(new_pos= (byte*) my_realloc((gptr) pa->str,
- (uint) (pa->max_length+PS_MALLOC),
- MYF(MY_WME))))
- DBUG_RETURN(1);
- if (new_pos != pa->str)
+ struct st_regex re;
+ char* save_out_buf= out_buf;
+
+ get_dynamic(&r->regex_arr,(gptr)&re,i);
+
+ if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
+ in_buf, re.icase))
{
- my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
- for (i=0 ; i < pa->typelib.count ; i++)
- pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
- char*);
- pa->str=new_pos;
+ /* if the buffer has been reallocated, make adjustements */
+ if (save_out_buf != out_buf)
+ {
+ if (save_out_buf == r->even_buf)
+ r->even_buf= out_buf;
+ else
+ r->odd_buf= out_buf;
+ }
+
+ r->buf= out_buf;
+ if (in_buf == val)
+ in_buf= r->odd_buf;
+
+ swap_variables(char*,in_buf,out_buf);
+
+ buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
+ &r->odd_buf_len;
}
- pa->max_length+=PS_MALLOC;
}
- if (pa->typelib.count >= pa->max_count-1)
+
+ return (r->buf == 0);
+}
+
+/*
+ Parse the regular expression to be used in all result files
+ from now on.
+
+ The syntax is --replace_regex /from/to/i /from/to/i ...
+ i means case-insensitive match. If omitted, the match is
+ case-sensitive
+
+*/
+void do_get_replace_regex(struct st_command *command)
+{
+ char *expr= command->first_argument;
+ free_replace_regex();
+ if (!(glob_replace_regex=init_replace_regex(expr)))
+ die("Could not init replace_regex");
+ command->last_argument= command->end;
+}
+
+void free_replace_regex()
+{
+ if (glob_replace_regex)
{
- int len;
- pa->array_allocs++;
- len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
- if (!(new_array=(const char **) my_realloc((gptr) pa->typelib.type_names,
- (uint) len/
- (sizeof(byte*)+sizeof(*pa->flag))*
- (sizeof(byte*)+sizeof(*pa->flag)),
- MYF(MY_WME))))
- DBUG_RETURN(1);
- pa->typelib.type_names=new_array;
- old_count=pa->max_count;
- pa->max_count=len/(sizeof(byte*) + sizeof(*pa->flag));
- pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
- memcpy((byte*) pa->flag,(my_string) (pa->typelib.type_names+old_count),
- old_count*sizeof(*pa->flag));
+ delete_dynamic(&glob_replace_regex->regex_arr);
+ my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*) glob_replace_regex,MYF(0));
+ glob_replace_regex=0;
}
- pa->flag[pa->typelib.count]=0; /* Reset flag */
- pa->typelib.type_names[pa->typelib.count++]= pa->str+pa->length;
- pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */
- VOID(strmov(pa->str+pa->length,name));
- pa->length+=length;
- DBUG_RETURN(0);
-} /* insert_pointer_name */
+}
- /* free pointer array */
-void free_pointer_array(POINTER_ARRAY *pa)
+/*
+ auxiluary macro used by reg_replace
+ makes sure the result buffer has sufficient length
+*/
+#define SECURE_REG_BUF if (buf_len < need_buf_len) \
+ { \
+ int off= res_p - buf; \
+ buf= (char*)my_realloc(buf,need_buf_len,MYF(MY_WME+MY_FAE)); \
+ res_p= buf + off; \
+ buf_len= need_buf_len; \
+ } \
+ \
+/*
+ Performs a regex substitution
+
+ IN:
+
+ buf_p - result buffer pointer. Will change if reallocated
+ buf_len_p - result buffer length. Will change if the buffer is reallocated
+ pattern - regexp pattern to match
+ replace - replacement expression
+ string - the string to perform substituions in
+ icase - flag, if set to 1 the match is case insensitive
+*/
+int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
+ char *replace, char *string, int icase)
{
- if (pa->typelib.count)
+ my_regex_t r;
+ my_regmatch_t *subs;
+ char *buf_end, *replace_end;
+ char *buf= *buf_p;
+ int len;
+ int buf_len, need_buf_len;
+ int cflags= REG_EXTENDED;
+ int err_code;
+ char *res_p,*str_p,*str_end;
+
+ buf_len= *buf_len_p;
+ len= strlen(string);
+ str_end= string + len;
+
+ /* start with a buffer of a reasonable size that hopefully will not
+ need to be reallocated
+ */
+ need_buf_len= len * 2 + 1;
+ res_p= buf;
+
+ SECURE_REG_BUF
+
+ buf_end= buf + buf_len;
+
+ if (icase)
+ cflags|= REG_ICASE;
+
+ if ((err_code= my_regcomp(&r,pattern,cflags,&my_charset_latin1)))
{
- pa->typelib.count=0;
- my_free((gptr) pa->typelib.type_names,MYF(0));
- pa->typelib.type_names=0;
- my_free((gptr) pa->str,MYF(0));
+ check_regerr(&r,err_code);
+ return 1;
}
-} /* free_pointer_array */
+ subs= (my_regmatch_t*)my_malloc(sizeof(my_regmatch_t) * (r.re_nsub+1),
+ MYF(MY_WME+MY_FAE));
+
+ *res_p= 0;
+ str_p= string;
+ replace_end= replace + strlen(replace);
+
+ /* for each pattern match instance perform a replacement */
+ while (!err_code)
+ {
+ /* find the match */
+ err_code= my_regexec(&r,str_p, r.re_nsub+1, subs,
+ (str_p == string) ? REG_NOTBOL : 0);
+
+ /* if regular expression error (eg. bad syntax, or out of memory) */
+ if (err_code && err_code != REG_NOMATCH)
+ {
+ check_regerr(&r,err_code);
+ my_regfree(&r);
+ return 1;
+ }
+
+ /* if match found */
+ if (!err_code)
+ {
+ char* expr_p= replace;
+ int c;
+
+ /*
+ we need at least what we have so far in the buffer + the part
+ before this match
+ */
+ need_buf_len= (res_p - buf) + subs[0].rm_so;
+
+ /* on this pass, calculate the memory for the result buffer */
+ while (expr_p < replace_end)
+ {
+ int back_ref_num= -1;
+ c= *expr_p;
+
+ if (c == '\\' && expr_p + 1 < replace_end)
+ {
+ back_ref_num= expr_p[1] - '0';
+ }
+
+ /* found a valid back_ref (eg. \1)*/
+ if (back_ref_num >= 0 && back_ref_num <= (int)r.re_nsub)
+ {
+ int start_off,end_off;
+ if ((start_off=subs[back_ref_num].rm_so) > -1 &&
+ (end_off=subs[back_ref_num].rm_eo) > -1)
+ {
+ need_buf_len += (end_off - start_off);
+ }
+ expr_p += 2;
+ }
+ else
+ {
+ expr_p++;
+ need_buf_len++;
+ }
+ }
+ need_buf_len++;
+ /*
+ now that we know the size of the buffer,
+ make sure it is big enough
+ */
+ SECURE_REG_BUF
+
+ /* copy the pre-match part */
+ if (subs[0].rm_so)
+ {
+ memcpy(res_p, str_p, subs[0].rm_so);
+ res_p+= subs[0].rm_so;
+ }
+
+ expr_p= replace;
+
+ /* copy the match and expand back_refs */
+ while (expr_p < replace_end)
+ {
+ int back_ref_num= -1;
+ c= *expr_p;
+
+ if (c == '\\' && expr_p + 1 < replace_end)
+ {
+ back_ref_num= expr_p[1] - '0';
+ }
- /* Code for replace rutines */
+ if (back_ref_num >= 0 && back_ref_num <= (int)r.re_nsub)
+ {
+ int start_off,end_off;
+ if ((start_off=subs[back_ref_num].rm_so) > -1 &&
+ (end_off=subs[back_ref_num].rm_eo) > -1)
+ {
+ int block_len= end_off - start_off;
+ memcpy(res_p,str_p + start_off, block_len);
+ res_p += block_len;
+ }
+ expr_p += 2;
+ }
+ else
+ {
+ *res_p++ = *expr_p++;
+ }
+ }
+
+ /* handle the post-match part */
+ if (subs[0].rm_so == subs[0].rm_eo)
+ {
+ if (str_p + subs[0].rm_so >= str_end)
+ break;
+ str_p += subs[0].rm_eo ;
+ *res_p++ = *str_p++;
+ }
+ else
+ {
+ str_p += subs[0].rm_eo;
+ }
+ }
+ else /* no match this time, just copy the string as is */
+ {
+ int left_in_str= str_end-str_p;
+ need_buf_len= (res_p-buf) + left_in_str;
+ SECURE_REG_BUF
+ memcpy(res_p,str_p,left_in_str);
+ res_p += left_in_str;
+ str_p= str_end;
+ }
+ }
+ my_free((gptr)subs, MYF(0));
+ my_regfree(&r);
+ *res_p= 0;
+ *buf_p= buf;
+ *buf_len_p= buf_len;
+ return 0;
+}
+
+
+#ifndef WORD_BIT
+#define WORD_BIT (8*sizeof(uint))
+#endif
#define SET_MALLOC_HUNC 64
+#define LAST_CHAR_CODE 259
typedef struct st_rep_set {
uint *bits; /* Pointer to used sets */
@@ -5843,32 +6626,48 @@ typedef struct st_follow {
} FOLLOWS;
-static int init_sets(REP_SETS *sets,uint states);
-static REP_SET *make_new_set(REP_SETS *sets);
-static void make_sets_invisible(REP_SETS *sets);
-static void free_last_set(REP_SETS *sets);
-static void free_sets(REP_SETS *sets);
-static void internal_set_bit(REP_SET *set, uint bit);
-static void internal_clear_bit(REP_SET *set, uint bit);
-static void or_bits(REP_SET *to,REP_SET *from);
-static void copy_bits(REP_SET *to,REP_SET *from);
-static int cmp_bits(REP_SET *set1,REP_SET *set2);
-static int get_next_bit(REP_SET *set,uint lastpos);
-static int find_set(REP_SETS *sets,REP_SET *find);
-static int find_found(FOUND_SET *found_set,uint table_offset,
- int found_offset);
-static uint start_at_word(my_string pos);
-static uint end_of_word(my_string pos);
-static uint replace_len(my_string pos);
+int init_sets(REP_SETS *sets,uint states);
+REP_SET *make_new_set(REP_SETS *sets);
+void make_sets_invisible(REP_SETS *sets);
+void free_last_set(REP_SETS *sets);
+void free_sets(REP_SETS *sets);
+void internal_set_bit(REP_SET *set, uint bit);
+void internal_clear_bit(REP_SET *set, uint bit);
+void or_bits(REP_SET *to,REP_SET *from);
+void copy_bits(REP_SET *to,REP_SET *from);
+int cmp_bits(REP_SET *set1,REP_SET *set2);
+int get_next_bit(REP_SET *set,uint lastpos);
+int find_set(REP_SETS *sets,REP_SET *find);
+int find_found(FOUND_SET *found_set,uint table_offset,
+ int found_offset);
+uint start_at_word(my_string pos);
+uint end_of_word(my_string pos);
static uint found_sets=0;
- /* Init a replace structure for further calls */
+uint replace_len(my_string str)
+{
+ uint len=0;
+ while (*str)
+ {
+ if (str[0] == '\\' && str[1])
+ str++;
+ str++;
+ len++;
+ }
+ return len;
+}
+
+/* Init a replace structure for further calls */
REPLACE *init_replace(my_string *from, my_string *to,uint count,
my_string word_end_chars)
{
+ static const int SPACE_CHAR= 256;
+ static const int START_OF_LINE= 257;
+ static const int END_OF_LINE= 258;
+
uint i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
int used_sets,chr,default_state;
char used_chars[LAST_CHAR_CODE],is_word_end[256];
@@ -5921,7 +6720,7 @@ REPLACE *init_replace(my_string *from, my_string *to,uint count,
DBUG_RETURN(0);
}
- /* Init follow_ptr[] */
+ /* Init follow_ptr[] */
for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
{
if (from[i][0] == '\\' && from[i][1] == '^')
@@ -6104,7 +6903,7 @@ REPLACE *init_replace(my_string *from, my_string *to,uint count,
}
}
- /* Alloc replace structure for the replace-state-machine */
+ /* Alloc replace structure for the replace-state-machine */
if ((replace=(REPLACE*) my_malloc(sizeof(REPLACE)*(sets.count)+
sizeof(REPLACE_STRING)*(found_sets+1)+
@@ -6147,7 +6946,7 @@ REPLACE *init_replace(my_string *from, my_string *to,uint count,
}
-static int init_sets(REP_SETS *sets,uint states)
+int init_sets(REP_SETS *sets,uint states)
{
bzero((char*) sets,sizeof(*sets));
sets->size_of_bits=((states+7)/8);
@@ -6163,16 +6962,16 @@ static int init_sets(REP_SETS *sets,uint states)
return 0;
}
- /* Make help sets invisible for nicer codeing */
+/* Make help sets invisible for nicer codeing */
-static void make_sets_invisible(REP_SETS *sets)
+void make_sets_invisible(REP_SETS *sets)
{
sets->invisible=sets->count;
sets->set+=sets->count;
sets->count=0;
}
-static REP_SET *make_new_set(REP_SETS *sets)
+REP_SET *make_new_set(REP_SETS *sets)
{
uint i,count,*bit_buffer;
REP_SET *set;
@@ -6190,7 +6989,7 @@ static REP_SET *make_new_set(REP_SETS *sets)
}
count=sets->count+sets->invisible+SET_MALLOC_HUNC;
if (!(set=(REP_SET*) my_realloc((gptr) sets->set_buffer,
- sizeof(REP_SET)*count,
+ sizeof(REP_SET)*count,
MYF(MY_WME))))
return 0;
sets->set_buffer=set;
@@ -6209,34 +7008,34 @@ static REP_SET *make_new_set(REP_SETS *sets)
return make_new_set(sets);
}
-static void free_last_set(REP_SETS *sets)
+void free_last_set(REP_SETS *sets)
{
sets->count--;
sets->extra++;
return;
}
-static void free_sets(REP_SETS *sets)
+void free_sets(REP_SETS *sets)
{
my_free((gptr)sets->set_buffer,MYF(0));
my_free((gptr)sets->bit_buffer,MYF(0));
return;
}
-static void internal_set_bit(REP_SET *set, uint bit)
+void internal_set_bit(REP_SET *set, uint bit)
{
set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
return;
}
-static void internal_clear_bit(REP_SET *set, uint bit)
+void internal_clear_bit(REP_SET *set, uint bit)
{
set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
return;
}
-static void or_bits(REP_SET *to,REP_SET *from)
+void or_bits(REP_SET *to,REP_SET *from)
{
reg1 uint i;
for (i=0 ; i < to->size_of_bits ; i++)
@@ -6244,22 +7043,22 @@ static void or_bits(REP_SET *to,REP_SET *from)
return;
}
-static void copy_bits(REP_SET *to,REP_SET *from)
+void copy_bits(REP_SET *to,REP_SET *from)
{
memcpy((byte*) to->bits,(byte*) from->bits,
(size_t) (sizeof(uint) * to->size_of_bits));
}
-static int cmp_bits(REP_SET *set1,REP_SET *set2)
+int cmp_bits(REP_SET *set1,REP_SET *set2)
{
return bcmp((byte*) set1->bits,(byte*) set2->bits,
sizeof(uint) * set1->size_of_bits);
}
- /* Get next set bit from set. */
+/* Get next set bit from set. */
-static int get_next_bit(REP_SET *set,uint lastpos)
+int get_next_bit(REP_SET *set,uint lastpos)
{
uint pos,*start,*end,bits;
@@ -6280,11 +7079,11 @@ static int get_next_bit(REP_SET *set,uint lastpos)
return pos;
}
- /* find if there is a same set in sets. If there is, use it and
- free given set, else put in given set in sets and return its
- position */
+/* find if there is a same set in sets. If there is, use it and
+ free given set, else put in given set in sets and return its
+ position */
-static int find_set(REP_SETS *sets,REP_SET *find)
+int find_set(REP_SETS *sets,REP_SET *find)
{
uint i;
for (i=0 ; i < sets->count-1 ; i++)
@@ -6298,14 +7097,14 @@ static int find_set(REP_SETS *sets,REP_SET *find)
return i; /* return new postion */
}
- /* find if there is a found_set with same table_offset & found_offset
- If there is return offset to it, else add new offset and return pos.
- Pos returned is -offset-2 in found_set_structure because it is
- saved in set->next and set->next[] >= 0 points to next set and
- set->next[] == -1 is reserved for end without replaces.
- */
+/* find if there is a found_set with same table_offset & found_offset
+ If there is return offset to it, else add new offset and return pos.
+ Pos returned is -offset-2 in found_set_structure because it is
+ saved in set->next and set->next[] >= 0 points to next set and
+ set->next[] == -1 is reserved for end without replaces.
+*/
-static int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
+int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
{
int i;
for (i=0 ; (uint) i < found_sets ; i++)
@@ -6318,145 +7117,155 @@ static int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
return -i-2; /* return new postion */
}
- /* Return 1 if regexp starts with \b or ends with \b*/
+/* Return 1 if regexp starts with \b or ends with \b*/
-static uint start_at_word(my_string pos)
+uint start_at_word(my_string pos)
{
return (((!bcmp(pos,"\\b",2) && pos[2]) || !bcmp(pos,"\\^",2)) ? 1 : 0);
}
-static uint end_of_word(my_string pos)
+uint end_of_word(my_string pos)
{
my_string end=strend(pos);
return ((end > pos+2 && !bcmp(end-2,"\\b",2)) ||
(end >= pos+2 && !bcmp(end-2,"\\$",2))) ?
- 1 : 0;
+ 1 : 0;
}
+/****************************************************************************
+ * Handle replacement of strings
+ ****************************************************************************/
-static uint replace_len(my_string str)
-{
- uint len=0;
- while (*str)
- {
- if (str[0] == '\\' && str[1])
- str++;
- str++;
- len++;
- }
- return len;
-}
-
+#define PC_MALLOC 256 /* Bytes for pointers */
+#define PS_MALLOC 512 /* Bytes for data */
-/* Replace strings while appending to ds */
-void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
- const char *str, int len)
+int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name)
{
- reg1 REPLACE *rep_pos;
- reg2 REPLACE_STRING *rep_str;
- const char *start, *from;
- DBUG_ENTER("replace_strings_append");
+ uint i,length,old_count;
+ byte *new_pos;
+ const char **new_array;
+ DBUG_ENTER("insert_pointer_name");
- start= from= str;
- rep_pos=rep+1;
- for (;;)
+ if (! pa->typelib.count)
{
- /* Loop through states */
- DBUG_PRINT("info", ("Looping through states"));
- while (!rep_pos->found)
- rep_pos= rep_pos->next[(uchar) *from++];
-
- /* Does this state contain a string to be replaced */
- if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
+ if (!(pa->typelib.type_names=(const char **)
+ my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
+ (sizeof(my_string)+sizeof(*pa->flag))*
+ (sizeof(my_string)+sizeof(*pa->flag))),MYF(MY_WME))))
+ DBUG_RETURN(-1);
+ if (!(pa->str= (byte*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
+ MYF(MY_WME))))
{
- /* No match found */
- dynstr_append_mem(ds, start, from - start - 1);
- DBUG_PRINT("exit", ("Found no more string to replace, appended: %s", start));
- DBUG_VOID_RETURN;
+ my_free((gptr) pa->typelib.type_names,MYF(0));
+ DBUG_RETURN (-1);
}
-
- /* Found a string that needs to be replaced */
- DBUG_PRINT("info", ("found: %d, to_offset: %d, from_offset: %d, string: %s",
- rep_str->found, rep_str->to_offset,
- rep_str->from_offset, rep_str->replace_string));
-
- /* Append part of original string before replace string */
- dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
-
- /* Append replace string */
- dynstr_append_mem(ds, rep_str->replace_string,
- strlen(rep_str->replace_string));
-
- if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
+ pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(byte*)+
+ sizeof(*pa->flag));
+ pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
+ pa->length=0;
+ pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
+ pa->array_allocs=1;
+ }
+ length=(uint) strlen(name)+1;
+ if (pa->length+length >= pa->max_length)
+ {
+ if (!(new_pos= (byte*) my_realloc((gptr) pa->str,
+ (uint) (pa->max_length+PS_MALLOC),
+ MYF(MY_WME))))
+ DBUG_RETURN(1);
+ if (new_pos != pa->str)
{
- /* End of from string */
- DBUG_PRINT("exit", ("Found end of from string"));
- DBUG_VOID_RETURN;
+ my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
+ for (i=0 ; i < pa->typelib.count ; i++)
+ pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
+ char*);
+ pa->str=new_pos;
}
- DBUG_ASSERT(from <= str+len);
- start= from;
- rep_pos=rep;
+ pa->max_length+=PS_MALLOC;
}
-}
+ if (pa->typelib.count >= pa->max_count-1)
+ {
+ int len;
+ pa->array_allocs++;
+ len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
+ if (!(new_array=(const char **) my_realloc((gptr) pa->typelib.type_names,
+ (uint) len/
+ (sizeof(byte*)+sizeof(*pa->flag))*
+ (sizeof(byte*)+sizeof(*pa->flag)),
+ MYF(MY_WME))))
+ DBUG_RETURN(1);
+ pa->typelib.type_names=new_array;
+ old_count=pa->max_count;
+ pa->max_count=len/(sizeof(byte*) + sizeof(*pa->flag));
+ pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
+ memcpy((byte*) pa->flag,(my_string) (pa->typelib.type_names+old_count),
+ old_count*sizeof(*pa->flag));
+ }
+ pa->flag[pa->typelib.count]=0; /* Reset flag */
+ pa->typelib.type_names[pa->typelib.count++]= pa->str+pa->length;
+ pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */
+ VOID(strmov(pa->str+pa->length,name));
+ pa->length+=length;
+ DBUG_RETURN(0);
+} /* insert_pointer_name */
-/****************************************************************************
- Replace results for a column
-*****************************************************************************/
+/* free pointer array */
-static void free_replace_column()
+void free_pointer_array(POINTER_ARRAY *pa)
{
- uint i;
- for (i=0 ; i < max_replace_column ; i++)
+ if (pa->typelib.count)
{
- if (replace_column[i])
- {
- my_free(replace_column[i], 0);
- replace_column[i]= 0;
- }
+ pa->typelib.count=0;
+ my_free((gptr) pa->typelib.type_names,MYF(0));
+ pa->typelib.type_names=0;
+ my_free((gptr) pa->str,MYF(0));
}
- max_replace_column= 0;
-}
+} /* free_pointer_array */
-/*
- Get arguments for replace_columns. The syntax is:
- replace-column column_number to_string [column_number to_string ...]
- Where each argument may be quoted with ' or "
- A argument may also be a variable, in which case the value of the
- variable is replaced.
-*/
-static void get_replace_column(struct st_query *q)
-{
- char *from=q->first_argument;
- char *buff,*start;
- DBUG_ENTER("get_replace_columns");
+/* Functions that uses replace and replace_regex */
- free_replace_column();
- if (!*from)
- die("Missing argument in %s", q->query);
+/* Append the string to ds, with optional replace */
+void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
+ const char *val, int len)
+{
+#ifdef __WIN__
+ fix_win_paths(val, len);
+#endif
- /* Allocate a buffer for results */
- start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
- while (*from)
+ if (glob_replace_regex)
{
- char *to;
- uint column_number;
+ /* Regex replace */
+ if (!multi_reg_replace(glob_replace_regex, (char*)val))
+ {
+ val= glob_replace_regex->buf;
+ len= strlen(val);
+ }
+ }
- to= get_string(&buff, &from, q);
- if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
- die("Wrong column number to replace_column in '%s'", q->query);
- if (!*from)
- die("Wrong number of arguments to replace_column in '%s'", q->query);
- to= get_string(&buff, &from, q);
- my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
- replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
- set_if_bigger(max_replace_column, column_number);
+ if (glob_replace)
+ {
+ /* Normal replace */
+ replace_strings_append(glob_replace, ds, val, len);
}
- my_free(start, MYF(0));
- q->last_argument= q->end;
+ else
+ dynstr_append_mem(ds, val, len);
}
+/* Append zero-terminated string to ds, with optional replace */
+void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
+{
+ replace_dynstr_append_mem(ds, val, strlen(val));
+}
+
+/* Append uint to ds, with optional replace */
+void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
+{
+ char buff[22]; /* This should be enough for any int */
+ char *end= longlong10_to_str(val, buff, 10);
+ replace_dynstr_append_mem(ds, buff, end - buff);
+}
diff --git a/include/my_time.h b/include/my_time.h
index d0f2fc323d8..069cecc7b14 100644
--- a/include/my_time.h
+++ b/include/my_time.h
@@ -57,6 +57,16 @@ typedef long my_time_t;
#define TIME_NO_ZERO_DATE (TIME_NO_ZERO_IN_DATE*2)
#define TIME_INVALID_DATES (TIME_NO_ZERO_DATE*2)
+#define MYSQL_TIME_WARN_TRUNCATED 1
+#define MYSQL_TIME_WARN_OUT_OF_RANGE 2
+
+/* Limits for the TIME data type */
+#define TIME_MAX_HOUR 838
+#define TIME_MAX_MINUTE 59
+#define TIME_MAX_SECOND 59
+#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + \
+ TIME_MAX_SECOND)
+
enum enum_mysql_timestamp_type
str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
uint flags, int *was_cut);
@@ -69,7 +79,9 @@ ulonglong TIME_to_ulonglong(const MYSQL_TIME *time);
my_bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time,
- int *was_cut);
+ int *warning);
+
+int check_time_range(struct st_mysql_time *time, int *warning);
long calc_daynr(uint year,uint month,uint day);
uint calc_days_in_year(uint year);
@@ -97,15 +109,25 @@ int my_date_to_str(const MYSQL_TIME *l_time, char *to);
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to);
int my_TIME_to_str(const MYSQL_TIME *l_time, char *to);
-/*
- The following must be sorted so that simple intervals comes first.
- (get_interval_value() depends on this)
+/*
+ Available interval types used in any statement.
+
+ 'interval_type' must be sorted so that simple intervals comes first,
+ ie year, quarter, month, week, day, hour, etc. The order based on
+ interval size is also important and the intervals should be kept in a
+ large to smaller order. (get_interval_value() depends on this)
+
+ Note: If you change the order of elements in this enum you should fix
+ order of elements in 'interval_type_to_name' and 'interval_names'
+ arrays
+
+ See also interval_type_to_name, get_interval_value, interval_names
*/
enum interval_type
{
- INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR,
- INTERVAL_MINUTE, INTERVAL_WEEK, INTERVAL_SECOND, INTERVAL_MICROSECOND ,
+ INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_WEEK, INTERVAL_DAY,
+ INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND, INTERVAL_MICROSECOND,
INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND,
diff --git a/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test b/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test
index 7a097fd1eae..ee6b0ed1426 100644
--- a/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test
+++ b/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test
@@ -7,6 +7,8 @@
-- source include/master-slave.inc
+let $SERVER_VERSION=`select version()`;
+
create table t1 (a int);
insert into t1 values (10);
create table t2 (a int);
diff --git a/mysql-test/extra/rpl_tests/rpl_truncate_helper.test b/mysql-test/extra/rpl_tests/rpl_truncate_helper.test
index 1e485baca36..7f1506c4010 100644
--- a/mysql-test/extra/rpl_tests/rpl_truncate_helper.test
+++ b/mysql-test/extra/rpl_tests/rpl_truncate_helper.test
@@ -36,6 +36,7 @@ SELECT * FROM t1;
--echo **** On Master ****
connection master;
DROP TABLE t1;
+let $SERVER_VERSION=`select version()`;
--replace_result $SERVER_VERSION SERVER_VERSION
--replace_regex /\/\* xid=[0-9]+ \*\//\/* xid= *\// /table_id: [0-9]+/table_id: #/
SHOW BINLOG EVENTS;
diff --git a/mysql-test/include/ctype_like_escape.inc b/mysql-test/include/ctype_like_escape.inc
index ac97fbaa1a0..d4abc33c178 100644
--- a/mysql-test/include/ctype_like_escape.inc
+++ b/mysql-test/include/ctype_like_escape.inc
@@ -11,8 +11,8 @@ insert into t1 values('ab_def');
insert into t1 values('abc_ef');
insert into t1 values('abcd_f');
insert into t1 values('abcde_');
--- should return ab_def
+# should return ab_def
select c1 as c1u from t1 where c1 like 'ab\_def';
--- should return ab_def
+# should return ab_def
select c1 as c2h from t1 where c1 like 'ab#_def' escape '#';
drop table t1;
diff --git a/mysql-test/include/mysqltest_while.inc b/mysql-test/include/mysqltest_while.inc
deleted file mode 100644
index 90b05ee2695..00000000000
--- a/mysql-test/include/mysqltest_while.inc
+++ /dev/null
@@ -1,137 +0,0 @@
-let $1 = 10;
-while ($1)
-{
-while ($1)
-{
-while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- echo $1;
- dec $1;
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
diff --git a/mysql-test/include/sourced.inc b/mysql-test/include/sourced.inc
deleted file mode 100644
index be1a270641a..00000000000
--- a/mysql-test/include/sourced.inc
+++ /dev/null
@@ -1 +0,0 @@
-echo here is the sourced script;
diff --git a/mysql-test/include/sourced1.inc b/mysql-test/include/sourced1.inc
deleted file mode 100644
index 920561e5de2..00000000000
--- a/mysql-test/include/sourced1.inc
+++ /dev/null
@@ -1 +0,0 @@
---source include/sourced.inc
diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl
index bb92730444c..e6980a0abb9 100644
--- a/mysql-test/lib/mtr_cases.pl
+++ b/mysql-test/lib/mtr_cases.pl
@@ -143,7 +143,7 @@ sub collect_test_cases ($) {
{
next;
}
-
+
next if $::opt_do_test and ! defined mtr_match_prefix($elem,$::opt_do_test);
collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled,
@@ -152,43 +152,79 @@ sub collect_test_cases ($) {
closedir TESTDIR;
}
- # To speed things up, we sort first in if the test require a restart
- # or not, second in alphanumeric order.
-
+ # Reorder the test cases in an order that wil make them faster to run
if ( $::opt_reorder )
{
my %sort_criteria;
- my $tinfo;
# Make a mapping of test name to a string that represents how that test
# should be sorted among the other tests. Put the most important criterion
# first, then a sub-criterion, then sub-sub-criterion, et c.
- foreach $tinfo (@$cases)
+ foreach my $tinfo (@$cases)
{
- my @this_criteria = ();
-
- # Append the criteria for sorting, in order of importance.
- push(@this_criteria, join("!", sort @{$tinfo->{'master_opt'}}) . "~"); # Ending with "~" makes empty sort later than filled
- push(@this_criteria, "ndb=" . ($tinfo->{'ndb_test'} ? "1" : "0"));
- push(@this_criteria, "restart=" . ($tinfo->{'master_restart'} ? "1" : "0"));
- push(@this_criteria, "big_test=" . ($tinfo->{'big_test'} ? "1" : "0"));
- push(@this_criteria, join("|", sort keys %{$tinfo})); # Group similar things together. The values may differ substantially. FIXME?
- push(@this_criteria, $tinfo->{'name'}); # Finally, order by the name
-
- $sort_criteria{$tinfo->{"name"}} = join(" ", @this_criteria);
+ my @criteria = ();
+
+ # Look for tests that muct be in run in a defined order
+ # that is defined by test having the same name except for
+ # the ending digit
+
+ # Put variables into hash
+ my $test_name= $tinfo->{'name'};
+ my $depend_on_test_name;
+ if ( $test_name =~ /^([\D]+)([0-9]{1})$/ )
+ {
+ my $base_name= $1;
+ my $idx= $2;
+ mtr_verbose("$test_name => $base_name idx=$idx");
+ if ( $idx > 1 )
+ {
+ $idx-= 1;
+ $base_name= "$base_name$idx";
+ mtr_verbose("New basename $base_name");
+ }
+
+ foreach my $tinfo2 (@$cases)
+ {
+ if ( $tinfo2->{'name'} eq $base_name )
+ {
+ mtr_verbose("found dependent test $tinfo2->{'name'}");
+ $depend_on_test_name=$base_name;
+ }
+ }
+ }
+
+ if ( defined $depend_on_test_name )
+ {
+ mtr_verbose("Giving $test_name same critera as $depend_on_test_name");
+ $sort_criteria{$test_name} = $sort_criteria{$depend_on_test_name};
+ }
+ else
+ {
+ #
+ # Append the criteria for sorting, in order of importance.
+ #
+ push(@criteria, "ndb=" . ($tinfo->{'ndb_test'} ? "1" : "0"));
+ # Group test with equal options together.
+ # Ending with "~" makes empty sort later than filled
+ push(@criteria, join("!", sort @{$tinfo->{'master_opt'}}) . "~");
+
+ $sort_criteria{$test_name} = join(" ", @criteria);
+ }
}
- @$cases = sort { $sort_criteria{$a->{"name"}} cmp $sort_criteria{$b->{"name"}}; } @$cases;
+ @$cases = sort {
+ $sort_criteria{$a->{'name'}} . $a->{'name'} cmp
+ $sort_criteria{$b->{'name'}} . $b->{'name'}; } @$cases;
-### For debugging the sort-order
-# foreach $tinfo (@$cases)
-# {
-# print $sort_criteria{$tinfo->{"name"}};
-# print " -> \t";
-# print $tinfo->{"name"};
-# print "\n";
-# }
+ if ( $::opt_script_debug )
+ {
+ # For debugging the sort-order
+ foreach my $tinfo (@$cases)
+ {
+ print("$sort_criteria{$tinfo->{'name'}} -> \t$tinfo->{'name'}\n");
+ }
+ }
}
return $cases;
@@ -245,6 +281,7 @@ sub collect_one_test_case($$$$$$$) {
$tinfo->{'path'}= $path;
$tinfo->{'timezone'}= "GMT-3"; # for UNIX_TIMESTAMP tests to work
+ $tinfo->{'slave_num'}= 0; # Default, no slave
if ( defined mtr_match_prefix($tname,"rpl") )
{
if ( $::opt_skip_rpl )
@@ -254,7 +291,8 @@ sub collect_one_test_case($$$$$$$) {
return;
}
- $tinfo->{'slave_num'}= 1; # Default, use one slave
+
+ $tinfo->{'slave_num'}= 1; # Default for rpl* tests, use one slave
if ( $tname eq 'rpl_failsafe' or $tname eq 'rpl_chain_temp_table' )
{
@@ -272,18 +310,18 @@ sub collect_one_test_case($$$$$$$) {
{
# This is an ndb test or all tests should be run with ndb cluster started
$tinfo->{'ndb_test'}= 1;
- if ( $::opt_skip_ndbcluster )
+ if ( ! $::opt_ndbcluster_supported )
{
- # All ndb test's should be skipped
+ # Ndb is not supported, skip them
$tinfo->{'skip'}= 1;
- $tinfo->{'comment'}= "No ndbcluster test(--skip-ndbcluster)";
+ $tinfo->{'comment'}= "No ndbcluster support";
return;
}
- if ( ! $::opt_ndbcluster_supported )
+ elsif ( $::opt_skip_ndbcluster )
{
- # Ndb is not supported, skip them
+ # All ndb test's should be skipped
$tinfo->{'skip'}= 1;
- $tinfo->{'comment'}= "No ndbcluster support";
+ $tinfo->{'comment'}= "No ndbcluster tests(--skip-ndbcluster)";
return;
}
}
@@ -316,57 +354,58 @@ sub collect_one_test_case($$$$$$$) {
if ( -f $master_opt_file )
{
- $tinfo->{'master_restart'}= 1; # We think so for now
- MASTER_OPT:
- {
- my $master_opt= mtr_get_opts_from_file($master_opt_file);
+ my $master_opt= mtr_get_opts_from_file($master_opt_file);
- foreach my $opt ( @$master_opt )
- {
- my $value;
+ foreach my $opt ( @$master_opt )
+ {
+ my $value;
- # This is a dirty hack from old mysql-test-run, we use the opt
- # file to flag other things as well, it is not a opt list at
- # all
+ # The opt file is used both to send special options to the mysqld
+ # as well as pass special test case specific options to this
+ # script
- $value= mtr_match_prefix($opt, "--timezone=");
- if ( defined $value )
- {
- $tinfo->{'timezone'}= $value;
- last MASTER_OPT;
- }
+ $value= mtr_match_prefix($opt, "--timezone=");
+ if ( defined $value )
+ {
+ $tinfo->{'timezone'}= $value;
+ next;
+ }
- $value= mtr_match_prefix($opt, "--result-file=");
- if ( defined $value )
- {
- $tinfo->{'result_file'}= "r/$value.result";
- if ( $::opt_result_ext and $::opt_record or
- -f "$tinfo->{'result_file'}$::opt_result_ext")
- {
- $tinfo->{'result_file'}.= $::opt_result_ext;
- }
- $tinfo->{'master_restart'}= 0;
- last MASTER_OPT;
- }
+ $value= mtr_match_prefix($opt, "--result-file=");
+ if ( defined $value )
+ {
+ # Specifies the file mysqltest should compare
+ # output against
+ $tinfo->{'result_file'}= "r/$value.result";
+ next;
+ }
- # If we set default time zone, remove the one we have
- $value= mtr_match_prefix($opt, "--default-time-zone=");
- if ( defined $value )
- {
- $tinfo->{'master_opt'}= [];
- }
+ # If we set default time zone, remove the one we have
+ $value= mtr_match_prefix($opt, "--default-time-zone=");
+ if ( defined $value )
+ {
+ $tinfo->{'timezone'}= "";
+ # Fallthrough, add this option
+ }
+ # The --restart option forces a restart even if no special
+ # option is set. If the options are the same as next testcase
+ # there is no need to restart after the testcase
+ # has completed
+ if ( $opt eq "--force-restart" )
+ {
+ $tinfo->{'force_restart'}= 1;
+ next;
}
- # Ok, this was a real option list, add it
- push(@{$tinfo->{'master_opt'}}, @$master_opt);
+ # Ok, this was a real option, add it
+ push(@{$tinfo->{'master_opt'}}, $opt);
}
}
if ( -f $slave_opt_file )
{
- $tinfo->{'slave_restart'}= 1;
my $slave_opt= mtr_get_opts_from_file($slave_opt_file);
foreach my $opt ( @$slave_opt )
@@ -381,7 +420,6 @@ sub collect_one_test_case($$$$$$$) {
if ( -f $slave_mi_file )
{
$tinfo->{'slave_mi'}= mtr_get_opts_from_file($slave_mi_file);
- $tinfo->{'slave_restart'}= 1;
}
if ( -f $master_sh )
@@ -395,7 +433,6 @@ sub collect_one_test_case($$$$$$$) {
else
{
$tinfo->{'master_sh'}= $master_sh;
- $tinfo->{'master_restart'}= 1;
}
}
@@ -410,7 +447,6 @@ sub collect_one_test_case($$$$$$$) {
else
{
$tinfo->{'slave_sh'}= $slave_sh;
- $tinfo->{'slave_restart'}= 1;
}
}
@@ -515,17 +551,6 @@ sub collect_one_test_case($$$$$$$) {
return;
}
}
-
- # We can't restart a running server that may be in use
-
- if ( $::glob_use_running_server and
- ( $tinfo->{'master_restart'} or $tinfo->{'slave_restart'} ) )
- {
- $tinfo->{'skip'}= 1;
- $tinfo->{'comment'}= "Can't restart a running server";
- return;
- }
-
}
diff --git a/mysql-test/lib/mtr_gcov.pl b/mysql-test/lib/mtr_gcov.pl
index 07aac1d2017..71d3d6a2a43 100644
--- a/mysql-test/lib/mtr_gcov.pl
+++ b/mysql-test/lib/mtr_gcov.pl
@@ -23,12 +23,28 @@ sub gcov_prepare () {
-or -name \*.da | xargs rm`;
}
+# Used by gcov
+our @mysqld_src_dirs=
+ (
+ "strings",
+ "mysys",
+ "include",
+ "extra",
+ "regex",
+ "isam",
+ "merge",
+ "myisam",
+ "myisammrg",
+ "heap",
+ "sql",
+ );
+
sub gcov_collect () {
print "Collecting source coverage info...\n";
-f $::opt_gcov_msg and unlink($::opt_gcov_msg);
-f $::opt_gcov_err and unlink($::opt_gcov_err);
- foreach my $d ( @::mysqld_src_dirs )
+ foreach my $d ( @mysqld_src_dirs )
{
chdir("$::glob_basedir/$d");
foreach my $f ( (glob("*.h"), glob("*.cc"), glob("*.c")) )
diff --git a/mysql-test/lib/mtr_io.pl b/mysql-test/lib/mtr_io.pl
index e8dcb0262c9..a1d7ffe87d8 100644
--- a/mysql-test/lib/mtr_io.pl
+++ b/mysql-test/lib/mtr_io.pl
@@ -12,6 +12,7 @@ sub mtr_fromfile ($);
sub mtr_tofile ($@);
sub mtr_tonewfile($@);
sub mtr_lastlinefromfile($);
+sub mtr_appendfile_to_file ($$);
##############################################################################
#
@@ -170,4 +171,17 @@ sub mtr_tonewfile ($@) {
close FILE;
}
+sub mtr_appendfile_to_file ($$) {
+ my $from_file= shift;
+ my $to_file= shift;
+
+ open(TOFILE,">>",$to_file) or mtr_error("can't open file \"$to_file\": $!");
+ open(FROMFILE,"<",$from_file)
+ or mtr_error("can't open file \"$from_file\": $!");
+ print TOFILE while (<FROMFILE>);
+ close FROMFILE;
+ close TOFILE;
+}
+
+
1;
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index 868b6d4f1ec..2831c179ea5 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -4,7 +4,6 @@
# and is part of the translation of the Bourne shell script with the
# same name.
-#use Carp qw(cluck);
use Socket;
use Errno;
use strict;
@@ -93,8 +92,6 @@ sub spawn_impl ($$$$$$$$) {
my $pid_file= shift; # FIXME
my $spawn_opts= shift;
- mtr_error("Can't spawn with empty \"path\"") unless defined $path;
-
if ( $::opt_script_debug )
{
print STDERR "\n";
@@ -118,6 +115,9 @@ sub spawn_impl ($$$$$$$$) {
print STDERR "#### ", "-" x 78, "\n";
}
+ mtr_error("Can't spawn with empty \"path\"") unless defined $path;
+
+
FORK:
{
my $pid= fork();
@@ -339,19 +339,6 @@ sub mtr_kill_leftovers () {
mtr_report("Killing Possible Leftover Processes");
mtr_debug("mtr_kill_leftovers(): started.");
- mkpath("$::opt_vardir/log"); # Needed for mysqladmin log
-
- # Stop or kill Instance Manager and all its children. If we failed to do
- # that, we can only abort -- there is nothing left to do.
-
- mtr_error("Failed to stop Instance Manager.")
- unless mtr_im_stop($::instance_manager);
-
- # Start shutdown of masters and slaves. Don't touch IM-managed mysqld
- # instances -- they should be stopped by mtr_im_stop().
-
- mtr_debug("Shutting down mysqld-instances...");
-
my @kill_pids;
my %admin_pids;
@@ -377,40 +364,41 @@ sub mtr_kill_leftovers () {
$srv->{'pid'}= 0; # Assume we are done with it
}
- # Start shutdown of clusters.
-
- mtr_debug("Shutting down cluster...");
-
- foreach my $cluster (@{$::clusters})
+ if ( ! $::opt_skip_ndbcluster )
{
- mtr_debug(" - cluster " .
- "(pid: $cluster->{pid}; " .
- "pid file: '$cluster->{path_pid})");
+ # Start shutdown of clusters.
+ mtr_debug("Shutting down cluster...");
- my $pid= mtr_ndbmgm_start($cluster, "shutdown");
-
- # Save the pid of the ndb_mgm process
- $admin_pids{$pid}= 1;
-
- push(@kill_pids,{
- pid => $cluster->{'pid'},
- pidfile => $cluster->{'path_pid'}
- });
+ foreach my $cluster (@{$::clusters})
+ {
+ mtr_debug(" - cluster " .
+ "(pid: $cluster->{pid}; " .
+ "pid file: '$cluster->{path_pid})");
- $cluster->{'pid'}= 0; # Assume we are done with it
+ my $pid= mtr_ndbmgm_start($cluster, "shutdown");
-
- foreach my $ndbd (@{$cluster->{'ndbds'}})
- {
- mtr_debug(" - ndbd " .
- "(pid: $ndbd->{pid}; " .
- "pid file: '$ndbd->{path_pid})");
+ # Save the pid of the ndb_mgm process
+ $admin_pids{$pid}= 1;
push(@kill_pids,{
- pid => $ndbd->{'pid'},
- pidfile => $ndbd->{'path_pid'},
+ pid => $cluster->{'pid'},
+ pidfile => $cluster->{'path_pid'}
});
- $ndbd->{'pid'}= 0; # Assume we are done with it
+
+ $cluster->{'pid'}= 0; # Assume we are done with it
+
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ mtr_debug(" - ndbd " .
+ "(pid: $ndbd->{pid}; " .
+ "pid file: '$ndbd->{path_pid})");
+
+ push(@kill_pids,{
+ pid => $ndbd->{'pid'},
+ pidfile => $ndbd->{'path_pid'},
+ });
+ $ndbd->{'pid'}= 0; # Assume we are done with it
+ }
}
}
diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl
index 6e3796133f2..ec1bed9671b 100644
--- a/mysql-test/lib/mtr_report.pl
+++ b/mysql-test/lib/mtr_report.pl
@@ -53,13 +53,6 @@ sub mtr_show_failed_diff ($) {
{
$result_file= $eval_file;
}
- elsif ( $::opt_result_ext and
- ( $::opt_record or -f "$result_file$::opt_result_ext" ))
- {
- # If we have an special externsion for result files we use it if we are
- # recording or a result file with that extension exists.
- $result_file= "$result_file$::opt_result_ext";
- }
my $diffopts= $::opt_udiff ? "-u" : "-c";
@@ -151,9 +144,11 @@ sub mtr_report_test_failed ($) {
print "[ fail ]\n";
}
- # FIXME Instead of this test, and meaningless error message in 'else'
- # we should write out into $::path_timefile when the error occurs.
- if ( -f $::path_timefile )
+ if ( $tinfo->{'comment'} )
+ {
+ print "\nERROR: $tinfo->{'comment'}\n";
+ }
+ elsif ( -f $::path_timefile )
{
print "\nErrors are (from $::path_timefile) :\n";
print mtr_fromfile($::path_timefile); # FIXME print_file() instead
@@ -177,7 +172,7 @@ sub mtr_report_stats ($) {
my $tot_failed= 0;
my $tot_tests= 0;
my $tot_restarts= 0;
- my $found_problems= 0; # Some warnings are errors...
+ my $found_problems= 0; # Some warnings in the logfiles are errors...
foreach my $tinfo (@$tests)
{
@@ -288,6 +283,7 @@ sub mtr_report_stats ($) {
print "\n";
+ # Print a list of testcases that failed
if ( $tot_failed != 0 )
{
my $test_mode= join(" ", @::glob_test_mode) || "default";
@@ -301,7 +297,30 @@ sub mtr_report_stats ($) {
}
}
print "\n";
+
+ }
+
+ # Print a list of check_testcases that failed(if any)
+ if ( $::opt_check_testcases )
+ {
+ my @check_testcases= ();
+
+ foreach my $tinfo (@$tests)
+ {
+ if ( defined $tinfo->{'check_testcase_failed'} )
+ {
+ push(@check_testcases, $tinfo->{'name'});
+ }
+ }
+
+ if ( @check_testcases )
+ {
+ print "Check of testcase failed for: ";
+ print join(" ", @check_testcases);
+ print "\n\n";
+ }
}
+
if ( $tot_failed != 0 || $found_problems)
{
mtr_error("there where failing test cases");
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index e5ed8a99304..0c46bbeac79 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -1,30 +1,24 @@
#!/usr/bin/perl
# -*- cperl -*-
-# This is a transformation of the "mysql-test-run" Bourne shell script
-# to Perl. There are reasons this rewrite is not the prettiest Perl
-# you have seen
#
-# - The original script is huge and for most part uncommented,
-# not even a usage description of the flags.
+##############################################################################
+#
+# mysql-test-run.pl
+#
+# Tool used for executing a suite of .test file
#
-# - There has been an attempt to write a replacement in C for the
-# original Bourne shell script. It was kind of working but lacked
-# lot of functionality to really be a replacement. Not to redo
-# that mistake and catch all the obscure features of the original
-# script, the rewrite in Perl is more close to the original script
-# meaning it also share some of the ugly parts as well.
+# See the "MySQL Test framework manual" for more information
+# http://dev.mysql.com/doc/mysqltest/en/index.html
#
-# - The original intention was that this script was to be a prototype
-# to be the base for a new C version with full functionality. Since
-# then it was decided that the Perl version should replace the
-# Bourne shell version, but the Perl style still reflects the wish
-# to make the Perl to C step easy.
+# Please keep the test framework tools identical in all versions!
#
-# Some coding style from the original intent has been kept
+##############################################################################
+#
+# Coding style directions for this perl script
#
# - To make this Perl script easy to alter even for those that not
-# code Perl that often, the coding style is as close as possible to
+# code Perl that often, keeep the coding style as close as possible to
# the C/C++ MySQL coding standard.
#
# - All lists of arguments to send to commands are Perl lists/arrays,
@@ -42,15 +36,6 @@
# the information. This separates the "find information" from the
# "do the work" and makes the program more easy to maintain.
#
-# - At the moment, there are tons of "global" variables that control
-# this script, even accessed from the files in "lib/*.pl". This
-# will change over time, for now global variables are used instead
-# of using %opt, %path and %exe hashes, because I want more
-# compile time checking, that hashes would not give me. Once this
-# script is debugged, hashes will be used and passed as parameters
-# to functions, to more closely mimic how it would be coded in C
-# using structs.
-#
# - The rule when it comes to the logic of this program is
#
# command_line_setup() - is to handle the logic between flags
@@ -66,10 +51,6 @@
# "http://www.plover.com/~mjd/perl/Trace/" and run this script like
# "perl -d:Trace mysql-test-run.pl"
#
-# FIXME Save a PID file from this code as well, to record the process
-# id we think it has. In Cygwin, a fork creates one Cygwin process,
-# and then the real Win32 process. Cygwin Perl can only kill Cygwin
-# processes. And "mysqld --bootstrap ..." doesn't save a PID file.
$Devel::Trace::TRACE= 0; # Don't trace boring init stuff
@@ -80,12 +61,16 @@ use File::Copy;
use Cwd;
use Getopt::Long;
use Sys::Hostname;
-#use Carp;
use IO::Socket;
use IO::Socket::INET;
use Data::Dumper;
use strict;
-#use diagnostics;
+use diagnostics;
+
+our $glob_win32_perl= ($^O eq "MSWin32"); # ActiveState Win32 Perl
+our $glob_cygwin_perl= ($^O eq "cygwin"); # Cygwin Perl
+our $glob_win32= ($glob_win32_perl or $glob_cygwin_perl);
+our $glob_netware= ($^O eq "NetWare"); # NetWare
require "lib/mtr_cases.pl";
require "lib/mtr_im.pl";
@@ -102,22 +87,6 @@ require "lib/mtr_stress.pl";
$Devel::Trace::TRACE= 1;
-# Used by gcov
-our @mysqld_src_dirs=
- (
- "strings",
- "mysys",
- "include",
- "extra",
- "regex",
- "isam",
- "merge",
- "myisam",
- "myisammrg",
- "heap",
- "sql",
- );
-
##############################################################################
#
# Default settings
@@ -130,10 +99,7 @@ our @mysqld_src_dirs=
# structs. We let each struct be a separate hash.
# Misc global variables
-
-our $glob_win32= 0; # OS and native Win32 executables
-our $glob_win32_perl= 0; # ActiveState Win32 Perl
-our $glob_cygwin_perl= 0; # Cygwin Perl
+our $mysql_version_id;
our $glob_mysql_test_dir= undef;
our $glob_mysql_bench_dir= undef;
our $glob_hostname= undef;
@@ -147,42 +113,38 @@ our @glob_test_mode;
our $glob_basedir;
-# The total result
-
our $path_charsetsdir;
our $path_client_bindir;
our $path_language;
our $path_timefile;
our $path_snapshot;
-our $path_slave_load_tmpdir; # What is this?!
our $path_mysqltest_log;
our $path_current_test_log;
our $path_my_basedir;
+
our $opt_vardir; # A path but set directly on cmd line
-our $opt_vardir_trace; # unix formatted opt_vardir for trace files
+our $path_vardir_trace; # unix formatted opt_vardir for trace files
our $opt_tmpdir; # A path but set directly on cmd line
+our $default_vardir;
+
our $opt_usage;
our $opt_suite;
-our $opt_netware;
-
our $opt_script_debug= 0; # Script debugging, enable with --script-debug
our $opt_verbose= 0; # Verbose output, enable with --verbose
-# Options FIXME not all....
-
our $exe_master_mysqld;
our $exe_mysql;
our $exe_mysqladmin;
our $exe_mysqlbinlog;
our $exe_mysql_client_test;
our $exe_mysqld;
-our $exe_mysqlcheck; # Called from test case
-our $exe_mysqldump; # Called from test case
-our $exe_mysqlslap; # Called from test case
-our $exe_mysqlimport; # Called from test case
-our $exe_mysqlshow; # Called from test case
+our $exe_mysqlcheck;
+our $exe_mysqldump;
+our $exe_mysqlslap;
+our $exe_mysqlimport;
+our $exe_mysqlshow;
our $exe_mysql_fix_system_tables;
our $exe_mysqltest;
our $exe_ndbd;
@@ -218,6 +180,7 @@ our $opt_fast;
our $opt_force;
our $opt_reorder= 0;
our $opt_enable_disabled;
+our $opt_mem;
our $opt_gcov;
our $opt_gcov_err;
@@ -239,7 +202,7 @@ our $opt_gprof_dir;
our $opt_gprof_master;
our $opt_gprof_slave;
-our $master; # Will be struct in C
+our $master;
our $slave;
our $clusters;
@@ -253,8 +216,6 @@ our $opt_ndbconnectstring_slave;
our $opt_record;
our $opt_check_testcases;
-our $opt_result_ext;
-
our $opt_skip;
our $opt_skip_rpl;
our $max_slave_num= 0;
@@ -326,7 +287,7 @@ our $exe_ndb_waiter;
our $path_ndb_tools_dir;
our $path_ndb_examples_dir;
our $exe_ndb_example;
-our $file_ndb_testrun_log;
+our $path_ndb_testrun_log;
our @data_dir_lst;
@@ -334,6 +295,9 @@ our $used_binlog_format;
our $debug_compiled_binaries;
our $glob_tot_real_time= 0;
+our %mysqld_variables;
+
+
######################################################################
#
# Function declarations
@@ -343,14 +307,14 @@ our $glob_tot_real_time= 0;
sub main ();
sub initial_setup ();
sub command_line_setup ();
-sub snapshot_setup ();
+sub datadir_setup ();
sub executable_setup ();
sub environment_setup ();
-sub kill_running_server ();
+sub kill_running_servers ();
sub cleanup_stale_files ();
-sub check_ssl_support ();
+sub check_ssl_support ($);
sub check_running_as_root();
-sub check_ndbcluster_support ();
+sub check_ndbcluster_support ($);
sub rm_ndbcluster_tables ($);
sub ndbcluster_start_install ($);
sub ndbcluster_start ($$);
@@ -366,8 +330,8 @@ sub run_testcase_stop_servers ($$$);
sub run_testcase_start_servers ($);
sub run_testcase_check_skip_test($);
sub report_failure_and_restart ($);
-sub do_before_start_master ($$);
-sub do_before_start_slave ($$);
+sub do_before_start_master ($);
+sub do_before_start_slave ($);
sub ndbd_start ($$$);
sub ndb_mgmd_start ($);
sub mysqld_start ($$$);
@@ -388,11 +352,12 @@ sub main () {
initial_setup();
command_line_setup();
- executable_setup();
- check_ndbcluster_support();
- check_ssl_support();
- check_debug_support();
+ check_ndbcluster_support(\%mysqld_variables);
+ check_ssl_support(\%mysqld_variables);
+ check_debug_support(\%mysqld_variables);
+
+ executable_setup();
environment_setup();
signal_setup();
@@ -441,7 +406,6 @@ sub main () {
unless $need_ndbcluster;
$opt_skip_im= 1 unless $need_im;
- snapshot_setup();
initialize_servers();
run_suite($opt_suite, $tests);
@@ -463,13 +427,8 @@ sub initial_setup () {
$glob_scriptname= basename($0);
- $glob_win32_perl= ($^O eq "MSWin32");
- $glob_cygwin_perl= ($^O eq "cygwin");
- $glob_win32= ($glob_win32_perl or $glob_cygwin_perl);
-
# We require that we are in the "mysql-test" directory
# to run mysql-test-run
-
if (! -f $glob_scriptname)
{
mtr_error("Can't find the location for the mysql-test-run script\n" .
@@ -493,17 +452,44 @@ sub initial_setup () {
chomp($glob_mysql_test_dir);
}
$glob_basedir= dirname($glob_mysql_test_dir);
+
# Expect mysql-bench to be located adjacent to the source tree, by default
$glob_mysql_bench_dir= "$glob_basedir/../mysql-bench"
unless defined $glob_mysql_bench_dir;
- # needs to be same length to test logging (FIXME what???)
- $path_slave_load_tmpdir= "../../var/tmp";
-
$path_my_basedir=
$opt_source_dist ? $glob_mysql_test_dir : $glob_basedir;
$glob_timers= mtr_init_timers();
+
+ #
+ # Find the mysqld executable to be able to find the mysqld version
+ # number as early as possible
+ #
+
+ # Look for the path where to find the client binaries
+ $path_client_bindir= mtr_path_exists("$glob_basedir/client/release",
+ "$glob_basedir/client/debug",
+ "$glob_basedir/client",
+ "$glob_basedir/client_release",
+ "$glob_basedir/client_debug",
+ "$glob_basedir/bin");
+
+ # Look for the mysqld executable
+ $exe_mysqld= mtr_exe_exists ("$glob_basedir/sql/mysqld",
+ "$path_client_bindir/mysqld-max-nt",
+ "$path_client_bindir/mysqld-max",
+ "$path_client_bindir/mysqld-nt",
+ "$path_client_bindir/mysqld",
+ "$path_client_bindir/mysqld-debug",
+ "$path_client_bindir/mysqld-max",
+ "$glob_basedir/libexec/mysqld",
+ "$glob_basedir/sql/release/mysqld",
+ "$glob_basedir/sql/debug/mysqld");
+
+ # Use the mysqld found above to find out what features are available
+ collect_mysqld_features();
+
}
@@ -661,12 +647,12 @@ sub command_line_setup () {
'tmpdir=s' => \$opt_tmpdir,
'vardir=s' => \$opt_vardir,
'benchdir=s' => \$glob_mysql_bench_dir,
+ 'mem' => \$opt_mem,
# Misc
'comment=s' => \$opt_comment,
'debug' => \$opt_debug,
'fast' => \$opt_fast,
- 'netware' => \$opt_netware,
'reorder' => \$opt_reorder,
'enable-disabled' => \$opt_enable_disabled,
'script-debug' => \$opt_script_debug,
@@ -722,7 +708,6 @@ sub command_line_setup () {
# --------------------------------------------------------------------------
# Find out type of logging that are being used
# --------------------------------------------------------------------------
-
# NOTE if the default binlog format is changed, this has to be changed
$used_binlog_format= "stmt";
foreach my $arg ( @opt_extra_mysqld_opt )
@@ -735,16 +720,53 @@ sub command_line_setup () {
mtr_report("Using binlog format '$used_binlog_format'");
# --------------------------------------------------------------------------
- # Set the "var/" directory, as it is the base for everything else
+ # Check if we should speed up tests by trying to run on tmpfs
# --------------------------------------------------------------------------
+ if ( $opt_mem )
+ {
+ mtr_error("Can't use --mem and --vardir at the same time ")
+ if $opt_vardir;
+ mtr_error("Can't use --mem and --tmpdir at the same time ")
+ if $opt_tmpdir;
+
+ # Use /dev/shm as the preferred location for vardir and
+ # thus implicitly also tmpdir. Add other locations to list
+ my @tmpfs_locations= ("/dev/shm");
+ # One could maybe use "mount" to find tmpfs location(s)
+ foreach my $fs (@tmpfs_locations)
+ {
+ if ( -d $fs )
+ {
+ mtr_report("Using tmpfs in $fs");
+ $opt_mem= "$fs/var";
+ $opt_mem .= $ENV{'MTR_BUILD_THREAD'} if $ENV{'MTR_BUILD_THREAD'};
+ last;
+ }
+ }
+ }
+ # --------------------------------------------------------------------------
+ # Set the "var/" directory, as it is the base for everything else
+ # --------------------------------------------------------------------------
+ $default_vardir= "$glob_mysql_test_dir/var";
if ( ! $opt_vardir )
{
- $opt_vardir= "$glob_mysql_test_dir/var";
+ $opt_vardir= $default_vardir;
+ }
+ elsif ( $mysql_version_id < 50000 and
+ $opt_vardir ne $default_vardir )
+ {
+ # Version 4.1 and --vardir was specified
+ # Only supported as a symlink from var/
+ # by setting up $opt_mem that symlink will be created
+ $opt_mem= $opt_vardir;
+ $opt_vardir= $default_vardir;
+ mtr_report("Using 4.1 vardir trick");
}
- $opt_vardir_trace= $opt_vardir;
+
+ $path_vardir_trace= $opt_vardir;
# Chop off any "c:", DBUG likes a unix path ex: c:/src/... => /src/...
- $opt_vardir_trace=~ s/^\w://;
+ $path_vardir_trace=~ s/^\w://;
# We make the path absolute, as the server will do a chdir() before usage
unless ( $opt_vardir =~ m,^/, or
@@ -755,31 +777,46 @@ sub command_line_setup () {
}
# --------------------------------------------------------------------------
- # If not set, set these to defaults
+ # Set tmpdir
# --------------------------------------------------------------------------
-
$opt_tmpdir= "$opt_vardir/tmp" unless $opt_tmpdir;
$opt_tmpdir =~ s,/+$,,; # Remove ending slash if any
# --------------------------------------------------------------------------
- # Do sanity checks of command line arguments
+ # Set socket
# --------------------------------------------------------------------------
-
- if ( ! $opt_socket )
- { # FIXME set default before reading options?
-# $opt_socket= '@MYSQL_UNIX_ADDR@';
- $opt_socket= "/tmp/mysql.sock"; # FIXME
+ if (!$opt_socket)
+ {
+ $opt_socket= $mysqld_variables{'socket'};
}
# --------------------------------------------------------------------------
- # Look at the command line options and set script flags
+ # Check im suport
# --------------------------------------------------------------------------
+ if ( $mysql_version_id < 50000 )
+ {
+ # Instance manager is not supported until 5.0
+ $opt_skip_im= 1;
+
+ }
+
+ if ( $glob_win32 )
+ {
+ mtr_report("Disable Instance manager - not supported on Windows");
+ $opt_skip_im= 1;
+ }
+ # --------------------------------------------------------------------------
+ # Record flag
+ # --------------------------------------------------------------------------
if ( $opt_record and ! @opt_cases )
{
mtr_error("Will not run in record mode without a specific test case");
}
+ # --------------------------------------------------------------------------
+ # Embedded server flag
+ # --------------------------------------------------------------------------
if ( $opt_embedded_server )
{
$glob_use_embedded_server= 1;
@@ -794,11 +831,18 @@ sub command_line_setup () {
}
}
+
+ # --------------------------------------------------------------------------
+ # ps protcol flag
+ # --------------------------------------------------------------------------
if ( $opt_ps_protocol )
{
push(@glob_test_mode, "ps-protocol");
}
+ # --------------------------------------------------------------------------
+ # Ndb cluster flags
+ # --------------------------------------------------------------------------
if ( $opt_with_ndbcluster and $opt_skip_ndbcluster)
{
mtr_error("Can't specify both --with-ndbcluster and --skip-ndbcluster");
@@ -834,22 +878,33 @@ sub command_line_setup () {
$opt_ndbconnectstring_slave= "host=localhost:$opt_ndbcluster_port_slave";
}
+ # --------------------------------------------------------------------------
+ # Bench flags
+ # --------------------------------------------------------------------------
if ( $opt_small_bench )
{
$opt_bench= 1;
}
+ # --------------------------------------------------------------------------
+ # Sleep flag
+ # --------------------------------------------------------------------------
if ( $opt_sleep )
{
$opt_sleep_time_after_restart= $opt_sleep;
}
+ # --------------------------------------------------------------------------
+ # Gcov flag
+ # --------------------------------------------------------------------------
if ( $opt_gcov and ! $opt_source_dist )
{
mtr_error("Coverage test needs the source - please use source dist");
}
+ # --------------------------------------------------------------------------
# Check debug related options
+ # --------------------------------------------------------------------------
if ( $opt_gdb || $opt_client_gdb || $opt_ddd || $opt_client_ddd ||
$opt_manual_gdb || $opt_manual_ddd || $opt_manual_debug ||
$opt_debugger || $opt_client_debugger )
@@ -864,13 +919,15 @@ sub command_line_setup () {
}
}
- # Check IM arguments
- if ( $glob_win32 )
- {
- mtr_report("Disable Instance manager - not supported on Windows");
- $opt_skip_im= 1;
- }
+ # --------------------------------------------------------------------------
+ # Check if special exe was selected for master or slave
+ # --------------------------------------------------------------------------
+ $exe_master_mysqld= $exe_master_mysqld || $exe_mysqld;
+ $exe_slave_mysqld= $exe_slave_mysqld || $exe_mysqld;
+
+ # --------------------------------------------------------------------------
# Check valgrind arguments
+ # --------------------------------------------------------------------------
if ( $opt_valgrind or $opt_valgrind_path or defined $opt_valgrind_options)
{
mtr_report("Turning on valgrind for all executables");
@@ -1120,11 +1177,12 @@ sub command_line_setup () {
$path_timefile= "$opt_vardir/log/mysqltest-time";
$path_mysqltest_log= "$opt_vardir/log/mysqltest.log";
$path_current_test_log= "$opt_vardir/log/current_test";
+ $path_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log";
$path_snapshot= "$opt_tmpdir/snapshot_$opt_master_myport/";
}
-sub snapshot_setup () {
+sub datadir_setup () {
# Make a list of all data_dirs
@data_dir_lst = (
@@ -1152,6 +1210,87 @@ sub snapshot_setup () {
#
##############################################################################
+
+sub collect_mysqld_features () {
+ #
+ # Execute "mysqld --no-defaults --help --verbose", that will
+ # print out version and a list of all features and settings
+ #
+ my $found_variable_list_start= 0;
+ my $spec_file= "$glob_mysql_test_dir/mysqld.spec.$$";
+ if ( mtr_run($exe_mysqld,
+ ["--no-defaults",
+ "--verbose",
+ "--help"],
+ "", "$spec_file", "$spec_file", "") != 0 )
+ {
+ mtr_error("Failed to get version and list of features from %s",
+ $exe_mysqld);
+ }
+
+ my $F= IO::File->new($spec_file) or
+ mtr_error("can't open file \"$spec_file\": $!");
+
+ while ( my $line= <$F> )
+ {
+ # First look for version
+ if ( !$mysql_version_id )
+ {
+ # Look for version
+ my $exe_name= basename($exe_mysqld);
+ mtr_verbose("exe_name: $exe_name");
+ if ( $line =~ /^\S*$exe_name\s\sVer\s([0-9]*)\.([0-9]*)\.([0-9]*)/ )
+ {
+ #print "Major: $1 Minor: $2 Build: $3\n";
+ $mysql_version_id= $1*10000 + $2*100 + $3;
+ #print "mysql_version_id: $mysql_version_id\n";
+ mtr_report("MySQL Version $1.$2.$3");
+ }
+ }
+ else
+ {
+ if (!$found_variable_list_start)
+ {
+ # Look for start of variables list
+ if ( $line =~ /[\-]+\s[\-]+/ )
+ {
+ $found_variable_list_start= 1;
+ }
+ }
+ else
+ {
+ # Put variables into hash
+ if ( $line =~ /^([\S]+)[ \t]+(.*)$/ )
+ {
+ # print "$1=$2\n";
+ $mysqld_variables{$1}= $2;
+ }
+ else
+ {
+ # The variable list is ended with a blank line
+ if ( $line =~ /^[\s]*$/ )
+ {
+ last;
+ }
+ else
+ {
+ # Send out a warning, we should fix the variables that has no
+ # space between variable name and it's value
+ # or should it be fixed width column parsing? It does not
+ # look like that in function my_print_variables in my_getopt.c
+ mtr_warning("Could not parse variable list line : $line");
+ }
+ }
+ }
+ }
+ }
+ unlink($spec_file);
+ mtr_error("Could not find version of MySQL") unless $mysql_version_id;
+ mtr_error("Could not find variabes list") unless $found_variable_list_start;
+
+}
+
+
sub executable_setup () {
#
@@ -1169,161 +1308,124 @@ sub executable_setup () {
}
}
- if ( $opt_source_dist )
+ # Look for language files and charsetsdir, use same share
+ my $path_share= mtr_path_exists("$glob_basedir/share",
+ "$glob_basedir/sql/share",
+ "$glob_basedir/share/mysql",
+ "$glob_basedir/share");
+
+ $path_language= mtr_path_exists("$path_share/english");
+ $path_charsetsdir= mtr_path_exists("$path_share/charsets");
+
+ # Look for my_print_defaults
+ $exe_my_print_defaults=
+ mtr_exe_exists("$path_client_bindir/my_print_defaults",
+ "$glob_basedir/extra/my_print_defaults",
+ "$glob_basedir/extra/release/my_print_defaults",
+ "$glob_basedir/extra/debug/my_print_defaults");
+
+ # Look for perror
+ $exe_perror= mtr_exe_exists("$glob_basedir/extra/perror",
+ "$path_client_bindir/perror",
+ "$glob_basedir/extra/release/perror",
+ "$glob_basedir/extra/debug/perror");
+
+
+ if ( ! $opt_skip_im )
{
- if ( $glob_win32 )
- {
- $path_client_bindir= mtr_path_exists("$glob_basedir/client_release",
- "$glob_basedir/client_debug",
- "$glob_basedir/bin",
- # New CMake locations.
- "$glob_basedir/client/release",
- "$glob_basedir/client/debug");
- $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-max-nt",
- "$path_client_bindir/mysqld-max",
- "$path_client_bindir/mysqld-nt",
- "$path_client_bindir/mysqld",
- "$path_client_bindir/mysqld-max",
- "$path_client_bindir/mysqld-debug",
- "$glob_basedir/sql/release/mysqld",
- "$glob_basedir/sql/debug/mysqld");
- $path_language= mtr_path_exists("$glob_basedir/share/english/",
- "$glob_basedir/sql/share/english/");
- $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets",
- "$glob_basedir/sql/share/charsets");
- $exe_my_print_defaults=
- mtr_exe_exists("$path_client_bindir/my_print_defaults",
- "$glob_basedir/extra/release/my_print_defaults",
- "$glob_basedir/extra/debug/my_print_defaults");
- $exe_perror=
- mtr_exe_exists("$path_client_bindir/perror",
- "$glob_basedir/extra/release/perror",
- "$glob_basedir/extra/debug/perror");
- }
- else
- {
- $path_client_bindir= mtr_path_exists("$glob_basedir/client");
- $exe_mysqld= mtr_exe_exists ("$glob_basedir/sql/mysqld");
- $exe_mysqlslap= mtr_exe_exists ("$path_client_bindir/mysqlslap");
- $path_language= mtr_path_exists("$glob_basedir/sql/share/english/");
- $path_charsetsdir= mtr_path_exists("$glob_basedir/sql/share/charsets");
-
- $exe_im= mtr_exe_exists(
- "$glob_basedir/server-tools/instance-manager/mysqlmanager");
- $exe_my_print_defaults=
- mtr_exe_exists("$glob_basedir/extra/my_print_defaults");
- $exe_perror=
- mtr_exe_exists("$glob_basedir/extra/perror");
- }
+ # Look for instance manager binary - mysqlmanager
+ $exe_im=
+ mtr_exe_exists(
+ "$glob_basedir/server-tools/instance-manager/mysqlmanager",
+ "$glob_basedir/libexec/mysqlmanager");
+ }
+ else
+ {
+ $exe_im= "not_available";
+ }
- if ( $glob_use_embedded_server )
- {
- my $path_examples= "$glob_basedir/libmysqld/examples";
- $exe_mysqltest= mtr_exe_exists("$path_examples/mysqltest_embedded");
- $exe_mysql_client_test=
- mtr_exe_exists("$path_examples/mysql_client_test_embedded",
- "/usr/bin/false");
- }
- else
- {
- $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
- $exe_mysql_client_test=
- mtr_exe_exists("$glob_basedir/tests/mysql_client_test",
- "$glob_basedir/tests/release/mysql_client_test",
- "$glob_basedir/tests/debug/mysql_client_test",
- "$path_client_bindir/mysql_client_test",
- "/usr/bin/false");
- }
- $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck");
- $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
- $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
- $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
- $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
- $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
- $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
+ # Look for the client binaries
+ $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck");
+ $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
+ $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
+ $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
+ $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
+ $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
+ $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
+ if ( $mysql_version_id >= 50100 )
+ {
+ $exe_mysqlslap= mtr_exe_exists("$path_client_bindir/mysqlslap");
+ }
+
+ if ( ! $glob_win32 )
+ {
+ # Look for mysql_fix_system_table script
$exe_mysql_fix_system_tables=
mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables",
- "/usr/bin/false");
- $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/storage/ndb/tools");
- $path_ndb_examples_dir= mtr_path_exists("$glob_basedir/storage/ndb/ndbapi-examples");
- $exe_ndb_example= mtr_file_exists("$path_ndb_examples_dir/ndbapi_simple/ndbapi_simple");
- $exe_ndb_mgm= "$glob_basedir/storage/ndb/src/mgmclient/ndb_mgm";
- $exe_ndb_waiter= "$glob_basedir/storage/ndb/tools/ndb_waiter";
- $exe_ndbd= "$glob_basedir/storage/ndb/src/kernel/ndbd";
- $exe_ndb_mgmd= "$glob_basedir/storage/ndb/src/mgmsrv/ndb_mgmd";
- $lib_udf_example=
- mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so",
- "$glob_basedir/sql/release/udf_example.dll",
- "$glob_basedir/sql/debug/udf_example.dll");
+ "$path_client_bindir/mysql_fix_privilege_tables");
+ }
+
+ if ( ! $opt_skip_ndbcluster)
+ {
+ # Look for ndb tols and binaries
+ my $ndb_path= mtr_path_exists("$glob_basedir/ndb",
+ "$glob_basedir/storage/ndb");
+
+ $path_ndb_tools_dir= mtr_path_exists("$ndb_path/tools",
+ "$glob_basedir/bin");
+ $exe_ndb_mgm=
+ mtr_exe_exists("$ndb_path/src/mgmclient/ndb_mgm",
+ "$glob_basedir/bin/ndb_mgm");
+ $exe_ndb_mgmd=
+ mtr_exe_exists("$ndb_path/src/mgmsrv/ndb_mgmd",
+ "$glob_basedir/bin/ndb_mgmd");
+ $exe_ndb_waiter=
+ mtr_exe_exists("$ndb_path/tools/ndb_waiter",
+ "$glob_basedir/bin/ndb_waiter");
+ $exe_ndbd=
+ mtr_exe_exists("$ndb_path/src/kernel/ndbd",
+ "$glob_basedir/bin/ndbd");
+
+ $path_ndb_examples_dir=
+ mtr_path_exists("$ndb_path/ndbapi-examples",
+ "$ndb_path/examples");
+ $exe_ndb_example=
+ mtr_file_exists("$path_ndb_examples_dir/ndbapi_simple/ndbapi_simple");
+ }
+
+ # Look for the udf_example library
+ $lib_udf_example=
+ mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so",
+ "$glob_basedir/sql/release/udf_example.dll",
+ "$glob_basedir/sql/debug/udf_example.dll");
+
+ # Look for mysqltest executable
+ if ( $glob_use_embedded_server )
+ {
+ $exe_mysqltest=
+ mtr_exe_exists("$glob_basedir/libmysqld/examples/mysqltest_embedded",
+ "$path_client_bindir/mysqltest_embedded");
}
else
{
- $path_client_bindir= mtr_path_exists("$glob_basedir/bin");
- $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck");
- $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
- $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
- $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
- $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
- $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
- $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
- $exe_mysql_fix_system_tables=
- mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables",
- "$glob_basedir/scripts/mysql_fix_privilege_tables",
- "/usr/bin/false");
- $exe_my_print_defaults=
- mtr_exe_exists("$path_client_bindir/my_print_defaults");
- $exe_perror=
- mtr_exe_exists("$path_client_bindir/perror");
-
- $path_language= mtr_path_exists("$glob_basedir/share/mysql/english/",
- "$glob_basedir/share/english/");
- $path_charsetsdir= mtr_path_exists("$glob_basedir/share/mysql/charsets",
- "$glob_basedir/share/charsets");
-
- if ( $glob_win32 )
- {
- $exe_mysqld= mtr_exe_exists ("$glob_basedir/bin/mysqld-nt",
- "$glob_basedir/bin/mysqld",
- "$glob_basedir/bin/mysqld-debug",);
- }
- else
- {
- $exe_mysqld= mtr_exe_exists ("$glob_basedir/libexec/mysqld",
- "$glob_basedir/bin/mysqld");
- $exe_mysqlslap= mtr_exe_exists("$path_client_bindir/mysqlslap");
- }
- $exe_im= mtr_exe_exists("$glob_basedir/libexec/mysqlmanager",
- "$glob_basedir/bin/mysqlmanager");
- if ( $glob_use_embedded_server )
- {
- $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest_embedded");
- $exe_mysql_client_test=
- mtr_exe_exists("$glob_basedir/tests/mysql_client_test_embedded",
- "$path_client_bindir/mysql_client_test_embedded",
- "/usr/bin/false");
- }
- else
- {
$exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
- $exe_mysql_client_test=
- mtr_exe_exists("$path_client_bindir/mysql_client_test",
- "$glob_basedir/tests/release/mysql_client_test",
- "$glob_basedir/tests/debug/mysql_client_test",
- "/usr/bin/false"); # FIXME temporary
- }
- $path_ndb_tools_dir= "$glob_basedir/bin";
- $path_ndb_examples_dir= "$glob_basedir/ndbapi-examples";
- $exe_ndb_mgm= "$glob_basedir/bin/ndb_mgm";
- $exe_ndb_waiter= "$glob_basedir/bin/ndb_waiter";
- $exe_ndbd= "$glob_basedir/bin/ndbd";
- $exe_ndb_mgmd= "$glob_basedir/bin/ndb_mgmd";
- }
- $exe_master_mysqld= $exe_master_mysqld || $exe_mysqld;
- $exe_slave_mysqld= $exe_slave_mysqld || $exe_mysqld;
+ }
- $file_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log";
+ # Look for mysql_client_test executable
+ if ( $glob_use_embedded_server )
+ {
+ $exe_mysql_client_test=
+ mtr_exe_exists("$glob_basedir/libmysqld/examples/mysql_client_test_embedded");
+ }
+ else
+ {
+ $exe_mysql_client_test=
+ mtr_exe_exists("$glob_basedir/tests/mysql_client_test",
+ "$glob_basedir/tests/release/mysql_client_test",
+ "$glob_basedir/tests/debug/mysql_client_test");
+ }
}
@@ -1394,11 +1496,13 @@ sub environment_setup () {
}
$ENV{'LD_LIBRARY_PATH'}= join(":", @ld_library_paths,
- split(':', $ENV{'LD_LIBRARY_PATH'}));
+ $ENV{'LD_LIBRARY_PATHS'} ?
+ split(':', $ENV{'LD_LIBRARY_PATH'}) : ());
mtr_debug("LD_LIBRARY_PATH: $ENV{'LD_LIBRARY_PATH'}");
$ENV{'DYLD_LIBRARY_PATH'}= join(":", @ld_library_paths,
- split(':', $ENV{'DYLD_LIBRARY_PATH'}));
+ $ENV{'DYLD_LIBRARY_PATH'} ?
+ split(':', $ENV{'DYLD_LIBRARY_PATH'}) : ());
mtr_debug("DYLD_LIBRARY_PATH: $ENV{'DYLD_LIBRARY_PATH'}");
@@ -1422,30 +1526,32 @@ sub environment_setup () {
$ENV{'SLAVE_MYPORT'}= $slave->[0]->{'port'};
$ENV{'SLAVE_MYPORT1'}= $slave->[1]->{'port'};
$ENV{'SLAVE_MYPORT2'}= $slave->[2]->{'port'};
-# $ENV{'MYSQL_TCP_PORT'}= '@MYSQL_TCP_PORT@'; # FIXME
- $ENV{'MYSQL_TCP_PORT'}= 3306;
+ $ENV{'MYSQL_TCP_PORT'}= $mysqld_variables{'port'};
$ENV{MTR_BUILD_THREAD}= 0 unless $ENV{MTR_BUILD_THREAD}; # Set if not set
# ----------------------------------------------------
# Setup env for NDB
# ----------------------------------------------------
- $ENV{'NDB_MGM'}= $exe_ndb_mgm;
+ if ( ! $opt_skip_ndbcluster )
+ {
+ $ENV{'NDB_MGM'}= $exe_ndb_mgm;
- $ENV{'NDBCLUSTER_PORT'}= $opt_ndbcluster_port;
- $ENV{'NDBCLUSTER_PORT_SLAVE'}= $opt_ndbcluster_port_slave;
+ $ENV{'NDBCLUSTER_PORT'}= $opt_ndbcluster_port;
+ $ENV{'NDBCLUSTER_PORT_SLAVE'}= $opt_ndbcluster_port_slave;
- $ENV{'NDB_EXTRA_TEST'}= $opt_ndb_extra_test;
+ $ENV{'NDB_EXTRA_TEST'}= $opt_ndb_extra_test;
- $ENV{'NDB_BACKUP_DIR'}= $clusters->[0]->{'data_dir'};
- $ENV{'NDB_DATA_DIR'}= $clusters->[0]->{'data_dir'};
- $ENV{'NDB_TOOLS_DIR'}= $path_ndb_tools_dir;
- $ENV{'NDB_TOOLS_OUTPUT'}= $file_ndb_testrun_log;
- $ENV{'NDB_CONNECTSTRING'}= $opt_ndbconnectstring;
+ $ENV{'NDB_BACKUP_DIR'}= $clusters->[0]->{'data_dir'};
+ $ENV{'NDB_DATA_DIR'}= $clusters->[0]->{'data_dir'};
+ $ENV{'NDB_TOOLS_DIR'}= $path_ndb_tools_dir;
+ $ENV{'NDB_TOOLS_OUTPUT'}= $path_ndb_testrun_log;
+ $ENV{'NDB_CONNECTSTRING'}= $opt_ndbconnectstring;
- $ENV{'NDB_EXAMPLES_DIR'}= $path_ndb_examples_dir;
- $ENV{'MY_NDB_EXAMPLES_BINARY'}= $exe_ndb_example;
- $ENV{'NDB_EXAMPLES_OUTPUT'}= $file_ndb_testrun_log;
+ $ENV{'NDB_EXAMPLES_DIR'}= $path_ndb_examples_dir;
+ $ENV{'MY_NDB_EXAMPLES_BINARY'}= $exe_ndb_example;
+ $ENV{'NDB_EXAMPLES_OUTPUT'}= $path_ndb_testrun_log;
+ }
# ----------------------------------------------------
# Setup env for IM
@@ -1475,7 +1581,7 @@ sub environment_setup () {
if ( $opt_debug )
{
$cmdline_mysqlcheck .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqlcheck.trace";
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlcheck.trace";
}
$ENV{'MYSQL_CHECK'}= $cmdline_mysqlcheck;
@@ -1488,9 +1594,9 @@ sub environment_setup () {
if ( $opt_debug )
{
$cmdline_mysqldump .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqldump-master.trace";
+ " --debug=d:t:A,$path_vardir_trace/log/mysqldump-master.trace";
$cmdline_mysqldumpslave .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqldump-slave.trace";
+ " --debug=d:t:A,$path_vardir_trace/log/mysqldump-slave.trace";
}
$ENV{'MYSQL_DUMP'}= $cmdline_mysqldump;
$ENV{'MYSQL_DUMP_SLAVE'}= $cmdline_mysqldumpslave;
@@ -1499,7 +1605,7 @@ sub environment_setup () {
# ----------------------------------------------------
# Setup env so childs can execute mysqlslap
# ----------------------------------------------------
- unless ( $glob_win32 )
+ if ( $exe_mysqlslap )
{
my $cmdline_mysqlslap=
"$exe_mysqlslap -uroot " .
@@ -1510,7 +1616,7 @@ sub environment_setup () {
if ( $opt_debug )
{
$cmdline_mysqlslap .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqlslap.trace";
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlslap.trace";
}
$ENV{'MYSQL_SLAP'}= $cmdline_mysqlslap;
}
@@ -1526,7 +1632,7 @@ sub environment_setup () {
if ( $opt_debug )
{
$cmdline_mysqlimport .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqlimport.trace";
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlimport.trace";
}
$ENV{'MYSQL_IMPORT'}= $cmdline_mysqlimport;
@@ -1542,7 +1648,7 @@ sub environment_setup () {
if ( $opt_debug )
{
$cmdline_mysqlshow .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqlshow.trace";
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlshow.trace";
}
$ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow;
@@ -1551,13 +1657,16 @@ sub environment_setup () {
# ----------------------------------------------------
my $cmdline_mysqlbinlog=
"$exe_mysqlbinlog" .
- " --no-defaults --local-load=$opt_tmpdir" .
- " --character-sets-dir=$path_charsetsdir";
+ " --no-defaults --local-load=$opt_tmpdir";
+ if ( $mysql_version_id >= 50000 )
+ {
+ $cmdline_mysqlbinlog .=" --character-sets-dir=$path_charsetsdir";
+ }
if ( $opt_debug )
{
$cmdline_mysqlbinlog .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqlbinlog.trace";
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlbinlog.trace";
}
$ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog;
@@ -1578,13 +1687,16 @@ sub environment_setup () {
my $cmdline_mysql_client_test=
"$exe_mysql_client_test --no-defaults --testcase --user=root --silent " .
"--port=$master->[0]->{'port'} " .
- "--vardir=$opt_vardir " .
"--socket=$master->[0]->{'path_sock'}";
+ if ( $mysql_version_id >= 50000 )
+ {
+ $cmdline_mysql_client_test .=" --vardir=$opt_vardir";
+ }
if ( $opt_debug )
{
$cmdline_mysql_client_test .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysql_client_test.trace";
+ " --debug=d:t:A,$path_vardir_trace/log/mysql_client_test.trace";
}
if ( $glob_use_embedded_server )
@@ -1601,7 +1713,8 @@ sub environment_setup () {
# Setup env so childs can execute mysql_fix_system_tables
# ----------------------------------------------------
my $cmdline_mysql_fix_system_tables=
- "$exe_mysql_fix_system_tables --no-defaults --host=localhost --user=root --password= " .
+ "$exe_mysql_fix_system_tables --no-defaults --host=localhost " .
+ "--user=root --password= " .
"--basedir=$glob_basedir --bindir=$path_client_bindir --verbose " .
"--port=$master->[0]->{'port'} " .
"--socket=$master->[0]->{'path_sock'}";
@@ -1641,12 +1754,26 @@ sub environment_setup () {
print "Using SLAVE_MYPORT = $ENV{SLAVE_MYPORT}\n";
print "Using SLAVE_MYPORT1 = $ENV{SLAVE_MYPORT1}\n";
print "Using SLAVE_MYPORT2 = $ENV{SLAVE_MYPORT2}\n";
- print "Using NDBCLUSTER_PORT = $ENV{NDBCLUSTER_PORT}\n";
- print "Using NDBCLUSTER_PORT_SLAVE = $ENV{NDBCLUSTER_PORT_SLAVE}\n";
- print "Using IM_PORT = $ENV{IM_PORT}\n";
- print "Using IM_MYSQLD1_PORT = $ENV{IM_MYSQLD1_PORT}\n";
- print "Using IM_MYSQLD2_PORT = $ENV{IM_MYSQLD2_PORT}\n";
+ if ( ! $opt_skip_ndbcluster )
+ {
+ print "Using NDBCLUSTER_PORT = $ENV{NDBCLUSTER_PORT}\n";
+ if ( ! $opt_skip_ndbcluster_slave )
+ {
+ print "Using NDBCLUSTER_PORT_SLAVE = $ENV{NDBCLUSTER_PORT_SLAVE}\n";
+ }
+ }
+ if ( ! $opt_skip_im )
+ {
+ print "Using IM_PORT = $ENV{IM_PORT}\n";
+ print "Using IM_MYSQLD1_PORT = $ENV{IM_MYSQLD1_PORT}\n";
+ print "Using IM_MYSQLD2_PORT = $ENV{IM_MYSQLD2_PORT}\n";
+ }
}
+
+ # Create an environment variable to make it possible
+ # to detect that valgrind is being used from test cases
+ $ENV{'VALGRIND_TEST'}= $opt_valgrind;
+
}
@@ -1676,7 +1803,7 @@ sub handle_int_signal () {
#
##############################################################################
-sub kill_running_server () {
+sub kill_running_servers () {
if ( $opt_fast or $glob_use_embedded_server )
{
@@ -1694,28 +1821,48 @@ sub kill_running_server () {
# started from this run of the script, this is terminating
# leftovers from previous runs.
+ if ( ! -d $opt_vardir )
+ {
+ # The "var" dir does not exist already
+ # the processes that mtr_kill_leftovers start will write
+ # their log files to var/log so it should be created
+ mkpath("$opt_vardir/log");
+ }
mtr_kill_leftovers();
}
}
sub cleanup_stale_files () {
+ my $created_by_mem_file= "$glob_mysql_test_dir/var/created_by_mem";
+
mtr_report("Removing Stale Files");
- if ( $opt_vardir eq "$glob_mysql_test_dir/var" )
+ if ( $opt_vardir eq $default_vardir )
{
#
# Running with "var" in mysql-test dir
#
- if ( -l "$glob_mysql_test_dir/var" )
+ if ( -l $opt_vardir)
{
- # Some users creates a soft link in mysql-test/var to another area
- # - allow it
- mtr_report("WARNING: Using the 'mysql-test/var' symlink");
- rmtree("$opt_vardir/log");
- rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port");
- rmtree("$opt_vardir/run");
- rmtree("$opt_vardir/tmp");
+ # var is a symlink
+ if (-f $created_by_mem_file)
+ {
+ # Remove the directory which the link points at
+ rmtree(readlink($opt_vardir));
+ # Remove the entire "var" dir
+ rmtree("$opt_vardir/");
+ }
+ else
+ {
+ # Some users creates a soft link in mysql-test/var to another area
+ # - allow it
+ mtr_report("WARNING: Using the 'mysql-test/var' symlink");
+ rmtree("$opt_vardir/log");
+ rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port");
+ rmtree("$opt_vardir/run");
+ rmtree("$opt_vardir/tmp");
+ }
}
else
{
@@ -1731,12 +1878,23 @@ sub cleanup_stale_files () {
# Remove the var/ dir in mysql-test dir if any
# this could be an old symlink that shouldn't be there
- rmtree("$glob_mysql_test_dir/var");
+ rmtree($default_vardir);
# Remove the "var" dir
rmtree("$opt_vardir/");
}
+ if ( $opt_mem )
+ {
+ # Runinng with var as a link to some "memory" location, normally tmpfs
+ rmtree($opt_mem);
+ mkpath($opt_mem);
+ mtr_report("Creating symlink from $opt_vardir to $opt_mem");
+ symlink($opt_mem, $opt_vardir);
+ # Put a small file to recognize this dir was created by --mem
+ mtr_tofile($created_by_mem_file, $opt_mem);
+ }
+
mkpath("$opt_vardir/log");
mkpath("$opt_vardir/run");
mkpath("$opt_vardir/tmp");
@@ -1797,8 +1955,8 @@ sub check_running_as_root () {
}
-
-sub check_ssl_support () {
+sub check_ssl_support ($) {
+ my $mysqld_variables= shift;
if ($opt_skip_ssl || $opt_extern)
{
@@ -1808,13 +1966,7 @@ sub check_ssl_support () {
return;
}
- # check ssl support by testing using a switch
- # that is only available in that case
- if ( mtr_run($exe_mysqld,
- ["--no-defaults",
- "--ssl",
- "--help"],
- "", "/dev/null", "/dev/null", "") != 0 )
+ if ( ! $mysqld_variables->{'ssl'} )
{
if ( $opt_ssl)
{
@@ -1831,17 +1983,12 @@ sub check_ssl_support () {
}
-sub check_debug_support () {
+sub check_debug_support ($) {
+ my $mysqld_variables= shift;
- # check debug support by testing using a switch
- # that is only available in that case
- if ( mtr_run($exe_mysqld,
- ["--no-defaults",
- "--debug",
- "--help"],
- "", "/dev/null", "/dev/null", "") != 0 )
+ if ( ! $mysqld_variables->{'debug'} )
{
- # mtr_report("Binaries are not debug compiled");
+ #mtr_report("Binaries are not debug compiled");
$debug_compiled_binaries= 0;
if ( $opt_debug )
@@ -1860,7 +2007,8 @@ sub check_debug_support () {
#
##############################################################################
-sub check_ndbcluster_support () {
+sub check_ndbcluster_support ($) {
+ my $mysqld_variables= shift;
if ($opt_skip_ndbcluster)
{
@@ -1869,13 +2017,7 @@ sub check_ndbcluster_support () {
return;
}
- # check ndbcluster support by runnning mysqld using a switch
- # that is only available in that case
- if ( mtr_run($exe_mysqld,
- ["--no-defaults",
- "--ndb-use-exact-count",
- "--help"],
- "", "/dev/null", "/dev/null", "") != 0 )
+ if ( ! $mysqld_variables->{'ndb-connectstring'} )
{
mtr_report("Skipping ndbcluster, mysqld not compiled with ndbcluster");
$opt_skip_ndbcluster= 1;
@@ -1884,6 +2026,14 @@ sub check_ndbcluster_support () {
}
$opt_ndbcluster_supported= 1;
mtr_report("Using ndbcluster when necessary, mysqld supports it");
+
+ if ( $mysql_version_id < 50100 )
+ {
+ # Slave cluster is not supported until 5.1
+ $opt_skip_ndbcluster_slave= 1;
+
+ }
+
return;
}
@@ -1914,11 +2064,22 @@ sub ndbcluster_start_install ($) {
if (!$opt_bench)
{
# Use a smaller configuration
- $ndb_no_ord=32;
- $ndb_con_op=5000;
- $ndb_dmem="20M";
- $ndb_imem="1M";
- $ndb_pbmem="4M";
+ if ( $mysql_version_id < 50100 )
+ {
+ # 4.1 and 5.0 is using a "larger" --small configuration
+ $ndb_no_ord=128;
+ $ndb_con_op=10000;
+ $ndb_dmem="40M";
+ $ndb_imem="12M";
+ }
+ else
+ {
+ $ndb_no_ord=32;
+ $ndb_con_op=5000;
+ $ndb_dmem="20M";
+ $ndb_imem="1M";
+ $ndb_pbmem="4M";
+ }
}
my $config_file_template= "ndb/ndb_config_${nodes}_node.ini";
@@ -1941,6 +2102,11 @@ sub ndbcluster_start_install ($) {
s/CHOOSE_HOSTNAME_.*/$ndb_host/;
s/CHOOSE_FILESYSTEM/$cluster->{'data_dir'}/;
s/CHOOSE_PORT_MGM/$cluster->{'port'}/;
+ if ( $mysql_version_id < 50000 )
+ {
+ my $base_port= $cluster->{'port'} + 1;
+ s/CHOOSE_PORT_TRANSPORTER/$base_port/;
+ }
s/CHOOSE_DiskPageBufferMemory/$ndb_pbmem/;
print OUT "$_ \n";
@@ -2062,7 +2228,10 @@ sub ndbd_start ($$$) {
mtr_add_arg($args, "--no-defaults");
mtr_add_arg($args, "--core");
mtr_add_arg($args, "--ndb-connectstring=%s", "$cluster->{'connect_string'}");
- mtr_add_arg($args, "--character-sets-dir=%s", "$path_charsetsdir");
+ if ( $mysql_version_id >= 50000)
+ {
+ mtr_add_arg($args, "--character-sets-dir=%s", "$path_charsetsdir");
+ }
mtr_add_arg($args, "--nodaemon");
mtr_add_arg($args, "$extra_args");
@@ -2163,8 +2332,6 @@ sub run_benchmarks ($) {
chdir($glob_mysql_bench_dir)
or mtr_error("Couldn't chdir to '$glob_mysql_bench_dir': $!");
- # FIXME write shorter....
-
if ( ! $benchmark )
{
mtr_add_arg($args, "--log");
@@ -2196,9 +2363,6 @@ sub run_benchmarks ($) {
#
##############################################################################
-# FIXME how to specify several suites to run? Comma separated list?
-
-
sub run_suite () {
my ($suite, $tests)= @_;
@@ -2255,11 +2419,14 @@ sub run_suite () {
##############################################################################
sub initialize_servers () {
+
+ datadir_setup();
+
if ( ! $glob_use_running_server )
{
- kill_running_server();
+ kill_running_servers();
- unless ( $opt_start_dirty )
+ if ( ! $opt_start_dirty )
{
cleanup_stale_files();
mysql_install_db();
@@ -2293,7 +2460,8 @@ sub mysql_install_db () {
my $cluster_started_ok= 1; # Assume it can be started
if (ndbcluster_start_install($clusters->[0]) ||
- $max_slave_num && ndbcluster_start_install($clusters->[1]))
+ ($max_slave_num && !$opt_skip_ndbcluster_slave &&
+ ndbcluster_start_install($clusters->[1])))
{
mtr_warning("Failed to start install of cluster");
$cluster_started_ok= 0;
@@ -2396,10 +2564,10 @@ sub install_db ($$) {
if ( $opt_debug )
{
mtr_add_arg($args, "--debug=d:t:i:A,%s/log/bootstrap_%s.trace",
- $opt_vardir_trace, $type);
+ $path_vardir_trace, $type);
}
- if ( ! $opt_netware )
+ if ( ! $glob_netware )
{
mtr_add_arg($args, "--language=%s", $path_language);
mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
@@ -2492,9 +2660,15 @@ skip-innodb
skip-ndbcluster
EOF
;
-
+ if ( $mysql_version_id < 50100 )
+ {
+ print OUT "skip-bdb\n";
+ }
print OUT "nonguarded\n" if $instance->{'nonguarded'};
- print OUT "log-output=FILE\n" if $instance->{'old_log_format'};
+ if ( $mysql_version_id >= 50100 )
+ {
+ print OUT "log-output=FILE\n" if $instance->{'old_log_format'};
+ }
print OUT "\n";
}
@@ -2553,21 +2727,24 @@ sub run_testcase_check_skip_test($)
return 1;
}
- # If test needs cluster, check that master installed ok
- if ( $tinfo->{'ndb_test'} and !$clusters->[0]->{'installed_ok'} )
+ if ($tinfo->{'ndb_test'})
{
- mtr_report_test_name($tinfo);
- mtr_report_test_failed($tinfo);
- return 1;
- }
+ foreach my $cluster (@{$clusters})
+ {
+ last if ($opt_skip_ndbcluster_slave and
+ $cluster->{'name'} eq 'Slave');
- # If test needs slave cluster, check that it installed ok
- if ( $tinfo->{'ndb_test'} and $tinfo->{'slave_num'} and
- !$clusters->[1]->{'installed_ok'} )
- {
- mtr_report_test_name($tinfo);
- mtr_report_test_failed($tinfo);
- return 1;
+ # If test needs this cluster, check it was installed ok
+ if ( !$cluster->{'installed_ok'} )
+ {
+ mtr_tofile($path_timefile,
+ "Test marked as failed because $cluster->{'name'} " .
+ "was not installed ok!");
+ mtr_report_test_name($tinfo);
+ mtr_report_test_failed($tinfo);
+ return 1;
+ }
+ }
}
return 0;
@@ -2579,28 +2756,40 @@ sub do_before_run_mysqltest($)
my $tinfo= shift;
my $tname= $tinfo->{'name'};
- # Remove old reject file
- if ( $opt_suite eq "main" )
- {
- unlink("r/$tname.reject");
- }
- else
+ # Remove old files produced by mysqltest
+ my $result_dir= "r";
+ if ( $opt_suite ne "main" )
{
- unlink("suite/$opt_suite/r/$tname.reject");
+ $result_dir= "suite/$opt_suite/r";
}
+ unlink("$result_dir/$tname.reject");
+ unlink("$result_dir/$tname.progress");
+ unlink("$result_dir/$tname.log");
+ unlink("$result_dir/$tname.warnings");
-
-# MASV cleanup...
mtr_tonewfile($path_current_test_log,"$tname\n"); # Always tell where we are
# output current test to ndbcluster log file to enable diagnostics
- mtr_tofile($file_ndb_testrun_log,"CURRENT TEST $tname\n");
+ mtr_tofile($path_ndb_testrun_log,"CURRENT TEST $tname\n");
mtr_tofile($master->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n");
if ( $master->[1]->{'pid'} )
{
mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n");
}
+
+ if ( $mysql_version_id < 50000 )
+ {
+ # Set envirnoment variable NDB_STATUS_OK to 1
+ # if script decided to run mysqltest cluster _is_ installed ok
+ $ENV{'NDB_STATUS_OK'} = "1";
+ }
+ elsif ( $mysql_version_id < 50100 )
+ {
+ # Set envirnoment variable NDB_STATUS_OK to YES
+ # if script decided to run mysqltest cluster _is_ installed ok
+ $ENV{'NDB_STATUS_OK'} = "YES";
+ }
}
sub do_after_run_mysqltest($)
@@ -2608,12 +2797,16 @@ sub do_after_run_mysqltest($)
my $tinfo= shift;
my $tname= $tinfo->{'name'};
- #MASV cleanup
- # Save info from this testcase run to mysqltest.log
- my $testcase_log= mtr_fromfile($path_timefile) if -f $path_timefile;
- mtr_tofile($path_mysqltest_log,"CURRENT TEST $tname\n");
- mtr_tofile($path_mysqltest_log, $testcase_log);
- }
+ mtr_tofile($path_mysqltest_log,"CURRENT TEST $tname\n");
+
+ # Save info from this testcase run to mysqltest.log
+ mtr_appendfile_to_file($path_timefile, $path_mysqltest_log)
+ if -f $path_timefile;
+
+ # Remove the file that mysqltest writes info to
+ unlink($path_timefile);
+
+}
##############################################################################
@@ -2640,12 +2833,28 @@ sub run_testcase ($) {
if ($master_restart or $slave_restart)
{
+ # Can't restart a running server that may be in use
+ if ( $glob_use_running_server )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Can't restart a running server";
+
+ mtr_report_test_name($tinfo);
+ mtr_report_test_skipped($tinfo);
+ return;
+ }
+
run_testcase_stop_servers($tinfo, $master_restart, $slave_restart);
}
my $died= mtr_record_dead_children();
if ($died or $master_restart or $slave_restart)
{
- run_testcase_start_servers($tinfo);
+ if (run_testcase_start_servers($tinfo))
+ {
+ mtr_report_test_name($tinfo);
+ report_failure_and_restart($tinfo);
+ return 1;
+ }
}
# ----------------------------------------------------------------------
@@ -2702,13 +2911,10 @@ sub run_testcase ($) {
# ----------------------------------------------------------------------
# Stop Instance Manager if we are processing an IM-test case.
# ----------------------------------------------------------------------
-
- if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' )
+ if ( $tinfo->{'component_id'} eq 'im' and
+ !mtr_im_stop($instance_manager, $tinfo->{'name'}) )
{
- unless ( mtr_im_stop($instance_manager, $tinfo->{'name'}) )
- {
- mtr_error("Failed to stop Instance Manager.")
- }
+ mtr_error("Failed to stop Instance Manager.")
}
}
@@ -2824,24 +3030,17 @@ sub report_failure_and_restart ($) {
##############################################################################
-# The embedded server needs the cleanup so we do some of the start work
-# but stop before actually running mysqld or anything.
-sub do_before_start_master ($$) {
- my $tname= shift;
- my $init_script= shift;
+sub do_before_start_master ($) {
+ my ($tinfo)= @_;
+
+ my $tname= $tinfo->{'name'};
+ my $init_script= $tinfo->{'master_sh'};
# FIXME what about second master.....
- # Remove stale binary logs except for 2 tests which need them FIXME here????
- if ( $tname ne "rpl_crash_binlog_ib_1b" and
- $tname ne "rpl_crash_binlog_ib_2b" and
- $tname ne "rpl_crash_binlog_ib_3b")
+ foreach my $bin ( glob("$opt_vardir/log/master*-bin*") )
{
- # FIXME we really want separate dir for binlogs
- foreach my $bin ( glob("$opt_vardir/log/master*-bin*") )
- {
- unlink($bin);
- }
+ unlink($bin);
}
# FIXME only remove the ones that are tied to this master
@@ -2861,31 +3060,23 @@ sub do_before_start_master ($$) {
# mtr_warning("$init_script exited with code $ret");
}
}
- # for gcov FIXME needed? If so we need more absolute paths
- # chdir($glob_basedir);
}
-sub do_before_start_slave ($$) {
- my $tname= shift;
- my $init_script= shift;
+sub do_before_start_slave ($) {
+ my ($tinfo)= @_;
- # Remove stale binary logs and old master.info files
- # except for too tests which need them
- if ( $tname ne "rpl_crash_binlog_ib_1b" and
- $tname ne "rpl_crash_binlog_ib_2b" and
- $tname ne "rpl_crash_binlog_ib_3b" )
+ my $tname= $tinfo->{'name'};
+ my $init_script= $tinfo->{'master_sh'};
+
+ foreach my $bin ( glob("$opt_vardir/log/slave*-bin*") )
{
- # FIXME we really want separate dir for binlogs
- foreach my $bin ( glob("$opt_vardir/log/slave*-bin*") )
- {
- unlink($bin);
- }
- # FIXME really master?!
- unlink("$slave->[0]->{'path_myddir'}/master.info");
- unlink("$slave->[0]->{'path_myddir'}/relay-log.info");
+ unlink($bin);
}
+ unlink("$slave->[0]->{'path_myddir'}/master.info");
+ unlink("$slave->[0]->{'path_myddir'}/relay-log.info");
+
# Run slave initialization shell script if one exists
if ( $init_script )
{
@@ -2924,14 +3115,18 @@ sub mysqld_arguments ($$$$$) {
$prefix= "--server-arg=";
} else {
# We can't pass embedded server --no-defaults
- mtr_add_arg($args, "%s--no-defaults", $prefix);
+ mtr_add_arg($args, "--no-defaults");
}
mtr_add_arg($args, "%s--console", $prefix);
mtr_add_arg($args, "%s--basedir=%s", $prefix, $path_my_basedir);
mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir);
- mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);
+ if ( $mysql_version_id >= 50000 )
+ {
+ mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);
+ }
+
mtr_add_arg($args, "%s--default-character-set=latin1", $prefix);
mtr_add_arg($args, "%s--language=%s", $prefix, $path_language);
mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix);
@@ -2980,7 +3175,10 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--ndbcluster", $prefix);
mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
$cluster->{'connect_string'});
- mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
+ if ( $mysql_version_id >= 50100 )
+ {
+ mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
+ }
}
}
@@ -2998,7 +3196,7 @@ sub mysqld_arguments ($$$$$) {
$opt_vardir, $sidx); # FIXME use own dir for binlogs
mtr_add_arg($args, "%s--log-slave-updates", $prefix);
}
- # FIXME option duplicated for slave
+
mtr_add_arg($args, "%s--log=%s", $prefix,
$slave->[$idx]->{'path_mylog'});
mtr_add_arg($args, "%s--master-retry-count=10", $prefix);
@@ -3019,8 +3217,9 @@ sub mysqld_arguments ($$$$$) {
# Directory where slaves find the dumps generated by "load data"
# on the server. The path need to have constant length otherwise
# test results will vary, thus a relative path is used.
+ my $slave_load_path= "../tmp";
mtr_add_arg($args, "%s--slave-load-tmpdir=%s", $prefix,
- "../tmp");
+ $slave_load_path);
mtr_add_arg($args, "%s--socket=%s", $prefix,
$slave->[$idx]->{'path_sock'});
mtr_add_arg($args, "%s--set-variable=slave_net_timeout=10", $prefix);
@@ -3055,7 +3254,10 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--ndbcluster", $prefix);
mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
$clusters->[$slave->[$idx]->{'cluster'}]->{'connect_string'});
- mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
+ if ( $mysql_version_id >= 50100 )
+ {
+ mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
+ }
}
} # end slave
@@ -3064,12 +3266,12 @@ sub mysqld_arguments ($$$$$) {
if ( $type eq 'master' )
{
mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/master%s.trace",
- $prefix, $opt_vardir_trace, $sidx);
+ $prefix, $path_vardir_trace, $sidx);
}
if ( $type eq 'slave' )
{
mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/slave%s.trace",
- $prefix, $opt_vardir_trace, $sidx);
+ $prefix, $path_vardir_trace, $sidx);
}
}
@@ -3077,7 +3279,6 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix);
mtr_add_arg($args, "%s--sort_buffer=256K", $prefix);
mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix);
- mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);
if ( $opt_ssl_supported )
{
@@ -3255,10 +3456,13 @@ sub stop_all_servers () {
print "Stopping All Servers\n";
- print "Shutting-down Instance Manager\n";
- unless (mtr_im_stop($instance_manager, "stop_all_servers"))
+ if ( ! $opt_skip_im )
{
- mtr_error("Failed to stop Instance Manager.")
+ print "Shutting-down Instance Manager\n";
+ unless (mtr_im_stop($instance_manager, "stop_all_servers"))
+ {
+ mtr_error("Failed to stop Instance Manager.")
+ }
}
my %admin_pids; # hash of admin processes that requests shutdown
@@ -3333,46 +3537,46 @@ sub run_testcase_need_master_restart($)
# We try to find out if we are to restart the master(s)
my $do_restart= 0; # Assumes we don't have to
- if ( $tinfo->{'master_sh'} )
+ if ( $glob_use_embedded_server )
+ {
+ mtr_verbose("Never start or restart for embedded server");
+ return $do_restart;
+ }
+ elsif ( $tinfo->{'master_sh'} )
{
$do_restart= 1; # Always restart if script to run
- mtr_verbose("Restart because: Always restart if script to run");
+ mtr_verbose("Restart master: Always restart if script to run");
+ }
+ if ( $tinfo->{'force_restart'} )
+ {
+ $do_restart= 1; # Always restart if --force-restart in -opt file
+ mtr_verbose("Restart master: Restart forced with --force-restart");
}
elsif ( ! $opt_skip_ndbcluster and
$tinfo->{'ndb_test'} == 0 and
$clusters->[0]->{'pid'} != 0 )
{
$do_restart= 1; # Restart without cluster
- mtr_verbose("Restart because: Test does not need cluster");
+ mtr_verbose("Restart master: Test does not need cluster");
}
elsif ( ! $opt_skip_ndbcluster and
$tinfo->{'ndb_test'} == 1 and
$clusters->[0]->{'pid'} == 0 )
{
$do_restart= 1; # Restart with cluster
- mtr_verbose("Restart because: Test need cluster");
- }
- elsif ( $master->[0]->{'running_master_is_special'} and
- $master->[0]->{'running_master_is_special'}->{'timezone'} eq
- $tinfo->{'timezone'} and
- mtr_same_opts($master->[0]->{'running_master_is_special'}->{'master_opt'},
- $tinfo->{'master_opt'}) )
- {
- # If running master was started with special settings, but
- # the current test requires the same ones, we *don't* restart.
- $do_restart= 0;
- mtr_verbose("Skip restart: options are equal " .
- join(" ", @{$tinfo->{'master_opt'}}));
+ mtr_verbose("Restart master: Test need cluster");
}
- elsif ( $tinfo->{'master_restart'} )
+ elsif( $tinfo->{'component_id'} eq 'im' )
{
$do_restart= 1;
- mtr_verbose("Restart because: master_restart");
+ mtr_verbose("Restart master: Always restart for im tests");
}
- elsif ( $master->[0]->{'running_master_is_special'} )
+ elsif ( $master->[0]->{'running_master_options'} and
+ $master->[0]->{'running_master_options'}->{'timezone'} ne
+ $tinfo->{'timezone'})
{
$do_restart= 1;
- mtr_verbose("Restart because: running_master_is_special");
+ mtr_verbose("Restart master: Different timezone");
}
# Check that running master was started with same options
# as the current test requires
@@ -3380,10 +3584,15 @@ sub run_testcase_need_master_restart($)
$tinfo->{'master_opt'}) )
{
$do_restart= 1;
- mtr_verbose("Restart because: running with different options '" .
+ mtr_verbose("Restart master: running with different options '" .
join(" ", @{$tinfo->{'master_opt'}}) . "' != '" .
join(" ", @{$master->[0]->{'start_opts'}}) . "'" );
}
+ elsif( ! $master->[0]->{'pid'} )
+ {
+ $do_restart= 1;
+ mtr_verbose("Restart master: master is not started");
+ }
return $do_restart;
}
@@ -3395,57 +3604,40 @@ sub run_testcase_need_slave_restart($)
# We try to find out if we are to restart the slaves
my $do_slave_restart= 0; # Assumes we don't have to
- # FIXME only restart slave when necessary
- $do_slave_restart= 1;
-
-# if ( ! $slave->[0]->{'pid'} )
-# {
-# # mtr_verbose("Slave not started, no need to check slave restart");
-# }
-# elsif ( $do_restart )
-# {
-# $do_slave_restart= 1; # Always restart if master restart
-# mtr_verbose("Restart slave because: Master restart");
-# }
-# elsif ( $tinfo->{'slave_sh'} )
-# {
-# $do_slave_restart= 1; # Always restart if script to run
-# mtr_verbose("Restart slave because: Always restart if script to run");
-# }
-# elsif ( ! $opt_skip_ndbcluster_slave and
-# $tinfo->{'ndb_test'} == 0 and
-# $clusters->[1]->{'pid'} != 0 )
-# {
-# $do_slave_restart= 1; # Restart without slave cluster
-# mtr_verbose("Restart slave because: Test does not need slave cluster");
-# }
-# elsif ( ! $opt_with_ndbcluster_slave and
-# $tinfo->{'ndb_test'} == 1 and
-# $clusters->[1]->{'pid'} == 0 )
-# {
-# $do_slave_restart= 1; # Restart with slave cluster
-# mtr_verbose("Restart slave because: Test need slave cluster");
-# }
-# elsif ( $tinfo->{'slave_restart'} )
-# {
-# $do_slave_restart= 1;
-# mtr_verbose("Restart slave because: slave_restart");
-# }
-# elsif ( $slave->[0]->{'running_slave_is_special'} )
-# {
-# $do_slave_restart= 1;
-# mtr_verbose("Restart slave because: running_slave_is_special");
-# }
-# # Check that running slave was started with same options
-# # as the current test requires
-# elsif (! mtr_same_opts($slave->[0]->{'start_opts'},
-# $tinfo->{'slave_opt'}) )
-# {
-# $do_slave_restart= 1;
-# mtr_verbose("Restart slave because: running with different options '" .
-# join(" ", @{$tinfo->{'slave_opt'}}) . "' != '" .
-# join(" ", @{$slave->[0]->{'start_opts'}}) . "'" );
-# }
+ if ( $glob_use_embedded_server )
+ {
+ mtr_verbose("Never start or restart for embedded server");
+ return $do_slave_restart;
+ }
+ elsif ( $max_slave_num == 0)
+ {
+ mtr_verbose("Skip slave restart: No testcase use slaves");
+ }
+ else
+ {
+
+ # Check if any slave is currently started
+ my $any_slave_started= 0;
+ foreach my $mysqld (@{$slave})
+ {
+ if ( $mysqld->{'pid'} )
+ {
+ $any_slave_started= 1;
+ last;
+ }
+ }
+
+ if ($any_slave_started)
+ {
+ mtr_verbose("Restart slave: Slave is started, always restart");
+ $do_slave_restart= 1;
+ }
+ elsif ( $tinfo->{'slave_num'} )
+ {
+ mtr_verbose("Restart slave: Test need slave");
+ $do_slave_restart= 1;
+ }
+ }
return $do_slave_restart;
@@ -3464,22 +3656,16 @@ sub run_testcase_need_slave_restart($)
sub run_testcase_stop_servers($$$) {
my ($tinfo, $do_restart, $do_slave_restart)= @_;
-
- if ( $glob_use_running_server || $glob_use_embedded_server )
- {
- return;
- }
-
my $pid;
my %admin_pids; # hash of admin processes that requests shutdown
my @kill_pids; # list of processes to shutdown/kill
- # Remember if we restarted for this test case
+ # Remember if we restarted for this test case (count restarts)
$tinfo->{'restarted'}= $do_restart;
if ( $do_restart )
{
- delete $master->[0]->{'running_master_is_special'}; # Forget history
+ delete $master->[0]->{'running_master_options'}; # Forget history
# Start shutdown of all started masters
foreach my $mysqld (@{$master})
@@ -3529,7 +3715,7 @@ sub run_testcase_stop_servers($$$) {
if ( $do_restart || $do_slave_restart )
{
- delete $slave->[0]->{'running_slave_is_special'}; # Forget history
+ delete $slave->[0]->{'running_slave_options'}; # Forget history
# Start shutdown of all started slaves
foreach my $mysqld (@{$slave})
@@ -3600,15 +3786,26 @@ sub run_testcase_stop_servers($$$) {
}
}
+
+#
+# run_testcase_start_servers
+#
+# Start the servers needed by this test case
+#
+# RETURN
+# 0 OK
+# 1 Start failed
+#
+
sub run_testcase_start_servers($) {
my $tinfo= shift;
-
my $tname= $tinfo->{'name'};
- if ( $glob_use_running_server or $glob_use_embedded_server )
- {
- return;
- }
+ # -------------------------------------------------------
+ # Init variables that can change between server starts
+ # -------------------------------------------------------
+ $ENV{'TZ'}= $tinfo->{'timezone'};
+ mtr_verbose("Starting server with timezone: $tinfo->{'timezone'}");
if ( $tinfo->{'component_id'} eq 'mysqld' )
{
@@ -3623,7 +3820,7 @@ sub run_testcase_start_servers($) {
if ( !$master->[0]->{'pid'} )
{
# Master mysqld is not started
- do_before_start_master($tname,$tinfo->{'master_sh'});
+ do_before_start_master($tinfo);
mysqld_start($master->[0],$tinfo->{'master_opt'},[]);
@@ -3633,27 +3830,28 @@ sub run_testcase_start_servers($) {
{
# Test needs cluster, start an extra mysqld connected to cluster
- # First wait for first mysql server to have created ndb system tables ok
- # FIXME This is a workaround so that only one mysqld creates the tables
- if ( ! sleep_until_file_created(
- "$master->[0]->{'path_myddir'}/cluster/apply_status.ndb",
- $master->[0]->{'start_timeout'},
- $master->[0]->{'pid'}))
+ if ( $mysql_version_id >= 50100 )
{
- mtr_report("Failed to create 'cluster/apply_status' table");
- report_failure_and_restart($tinfo);
- return;
+ # First wait for first mysql server to have created ndb system
+ # tables ok FIXME This is a workaround so that only one mysqld
+ # create the tables
+ if ( ! sleep_until_file_created(
+ "$master->[0]->{'path_myddir'}/cluster/apply_status.ndb",
+ $master->[0]->{'start_timeout'},
+ $master->[0]->{'pid'}))
+ {
+
+ $tinfo->{'comment'}= "Failed to create 'cluster/apply_status' table";
+ return 1;
+ }
}
mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n");
mysqld_start($master->[1],$tinfo->{'master_opt'},[]);
}
- if ( $tinfo->{'master_restart'} )
- {
- # Save this test case information, so next can examine it
- $master->[0]->{'running_master_is_special'}= $tinfo;
- }
+ # Save this test case information, so next can examine it
+ $master->[0]->{'running_master_options'}= $tinfo;
}
elsif ( ! $opt_skip_im and $tinfo->{'component_id'} eq 'im' )
{
@@ -3664,12 +3862,10 @@ sub run_testcase_start_servers($) {
im_create_defaults_file($instance_manager);
- unless ( mtr_im_start($instance_manager, $tinfo->{im_opts}) )
+ if ( ! mtr_im_start($instance_manager, $tinfo->{im_opts}) )
{
- report_failure_and_restart($tinfo);
- mtr_report("Failed to start Instance Manager. " .
- "The test '$tname' is marked as failed.");
- return;
+ $tinfo->{'comment'}= "Failed to start Instance Manager. ";
+ return 1;
}
}
@@ -3682,7 +3878,7 @@ sub run_testcase_start_servers($) {
restore_slave_databases($tinfo->{'slave_num'});
- do_before_start_slave($tname,$tinfo->{'slave_sh'});
+ do_before_start_slave($tinfo);
if ( ! $opt_skip_ndbcluster_slave and
!$clusters->[1]->{'pid'} and
@@ -3702,12 +3898,8 @@ sub run_testcase_start_servers($) {
}
}
- if ( $tinfo->{'slave_restart'} )
- {
- # Save this test case information, so next can examine it
- $slave->[0]->{'running_slave_is_special'}= $tinfo;
- }
-
+ # Save this test case information, so next can examine it
+ $slave->[0]->{'running_slave_options'}= $tinfo;
}
# Wait for clusters to start
@@ -3719,7 +3911,8 @@ sub run_testcase_start_servers($) {
if (ndbcluster_wait_started($cluster, ""))
{
# failed to start
- mtr_report("Start of $cluster->{'name'} cluster failed, ");
+ $tinfo->{'comment'}= "Start of $cluster->{'name'} cluster failed";
+ return 1;
}
}
@@ -3731,9 +3924,13 @@ sub run_testcase_start_servers($) {
if (mysqld_wait_started($mysqld))
{
- mtr_warning("Failed to start $mysqld->{'type'} mysqld $mysqld->{'idx'}");
+ # failed to start
+ $tinfo->{'comment'}=
+ "Failed to start $mysqld->{'type'} mysqld $mysqld->{'idx'}";
+ return 1;
}
}
+ return 0;
}
#
@@ -3741,6 +3938,10 @@ sub run_testcase_start_servers($) {
# Before a testcase, run in record mode, save result file to var
# After testcase, run and compare with the recorded file, they should be equal!
#
+# RETURN VALUE
+# 0 OK
+# 1 Check failed
+#
sub run_check_testcase ($$) {
my $mode= shift;
@@ -3774,7 +3975,7 @@ sub run_check_testcase ($$) {
my $res = mtr_run_test($exe_mysqltest,$args,
"include/check-testcase.test", "", "", "");
- if ( $res == 1 and $mode = "after")
+ if ( $res == 1 and $mode eq "after")
{
mtr_run("diff",["-u",
"$opt_vardir/tmp/$name.result",
@@ -3785,6 +3986,7 @@ sub run_check_testcase ($$) {
{
mtr_error("Could not execute 'check-testcase' $mode testcase");
}
+ return $res;
}
@@ -3856,11 +4058,6 @@ sub run_mysqltest ($) {
mtr_add_arg($args, "--big-test");
}
- if ( $opt_valgrind )
- {
- mtr_add_arg($args, "--valgrind");
- }
-
if ( $opt_compress )
{
mtr_add_arg($args, "--compress");
@@ -3874,7 +4071,7 @@ sub run_mysqltest ($) {
if ( $opt_debug )
{
mtr_add_arg($args, "--debug=d:t:A,%s/log/mysqltest.trace",
- $opt_vardir_trace);
+ $path_vardir_trace);
}
if ( $opt_ssl_supported )
@@ -3971,11 +4168,6 @@ sub run_mysqltest ($) {
}
}
- # -------------------------------------------------------
- # Init variables that change for each testcase
- # -------------------------------------------------------
- $ENV{'TZ'}= $tinfo->{'timezone'};
-
my $res = mtr_run_test($exe,$args,"","",$path_timefile,"");
if ( $opt_check_testcases )
@@ -3984,7 +4176,11 @@ sub run_mysqltest ($) {
{
if ($mysqld->{'pid'})
{
- run_check_testcase("after", $mysqld);
+ if (run_check_testcase("after", $mysqld))
+ {
+ # Check failed, mark the test case with that info
+ $tinfo->{'check_testcase_failed'}= 1;
+ }
}
}
}
@@ -4205,9 +4401,7 @@ sub usage ($) {
print STDERR <<HERE;
-mysql-test-run [ OPTIONS ] [ TESTCASE ]
-
-FIXME when is TESTCASE arg used or not?!
+$0 [ OPTIONS ] [ TESTCASE ]
Options to control what engine/variation to run
@@ -4231,6 +4425,9 @@ Options to control directories to use
vardir=DIR The directory where files generated from the test run
is stored (default: ./var). Specifying a ramdisk or
tmpfs will speed up tests.
+ mem=DIR Run testsuite in "memory" using tmpfs if
+ available(default: /dev/shm)
+
Options to control what test suites or cases to run
diff --git a/mysql-test/r/binlog_row_mix_innodb_myisam.result b/mysql-test/r/binlog_row_mix_innodb_myisam.result
index a192d243bb0..e063d7371a9 100644
--- a/mysql-test/r/binlog_row_mix_innodb_myisam.result
+++ b/mysql-test/r/binlog_row_mix_innodb_myisam.result
@@ -220,7 +220,7 @@ select (@before:=unix_timestamp())*0;
(@before:=unix_timestamp())*0
0
begin;
- select * from t1 for update;
+select * from t1 for update;
insert into t2 values (20);
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
select (@after:=unix_timestamp())*0;
diff --git a/mysql-test/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/r/binlog_stm_mix_innodb_myisam.result
index 95b6eb953a2..8ab6840d441 100644
--- a/mysql-test/r/binlog_stm_mix_innodb_myisam.result
+++ b/mysql-test/r/binlog_stm_mix_innodb_myisam.result
@@ -195,7 +195,7 @@ select (@before:=unix_timestamp())*0;
(@before:=unix_timestamp())*0
0
begin;
- select * from t1 for update;
+select * from t1 for update;
insert into t2 values (20);
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
select (@after:=unix_timestamp())*0;
diff --git a/mysql-test/r/check.result b/mysql-test/r/check.result
index 4c565f4f1b1..60806e7393e 100644
--- a/mysql-test/r/check.result
+++ b/mysql-test/r/check.result
@@ -1,6 +1,6 @@
drop table if exists t1;
create table t1(n int not null, key(n), key(n), key(n), key(n));
- check table t1 extended;
+check table t1 extended;
insert into t1 values (200000);
Table Op Msg_type Msg_text
test.t1 check status OK
diff --git a/mysql-test/r/csv.result b/mysql-test/r/csv.result
index 222d4de8059..32ca47e20d2 100644
--- a/mysql-test/r/csv.result
+++ b/mysql-test/r/csv.result
@@ -4913,8 +4913,7 @@ bonfire
Colombo
nondecreasing
DROP TABLE t1;
-ALTER TABLE t2 RENAME t1
-#;
+ALTER TABLE t2 RENAME t1;
DROP TABLE t1;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index 53b2ea8c84a..24f1b654733 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -79,9 +79,9 @@ drop table if exists t1;
create table t1 (i int);
lock tables t1 read;
create database mysqltest;
- drop table t1;
+drop table t1;
show open tables;
- drop database mysqltest;
+drop database mysqltest;
select 1;
1
1
diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result
index a7f5e5e8fec..7eb7fd16edb 100644
--- a/mysql-test/r/flush.result
+++ b/mysql-test/r/flush.result
@@ -9,13 +9,13 @@ n
flush tables with read lock;
drop table t2;
ERROR HY000: Can't execute the query because you have a conflicting read lock
- drop table t2;
+drop table t2;
unlock tables;
create database mysqltest;
create table mysqltest.t1(n int);
insert into mysqltest.t1 values (23);
flush tables with read lock;
- drop database mysqltest;
+drop database mysqltest;
select * from mysqltest.t1;
n
23
@@ -51,7 +51,7 @@ drop table t1, t2, t3;
create table t1 (c1 int);
create table t2 (c1 int);
lock table t1 write;
- flush tables with read lock;
- insert into t2 values(1);
+flush tables with read lock;
+insert into t2 values(1);
unlock tables;
drop table t1, t2;
diff --git a/mysql-test/r/flush_block_commit.result b/mysql-test/r/flush_block_commit.result
index e4a9dfcfff1..56f8acab896 100644
--- a/mysql-test/r/flush_block_commit.result
+++ b/mysql-test/r/flush_block_commit.result
@@ -5,7 +5,7 @@ insert into t1 values(1);
flush tables with read lock;
select * from t1;
a
- commit;
+commit;
select * from t1;
a
unlock tables;
@@ -14,8 +14,8 @@ select * from t1 for update;
a
1
begin;
- select * from t1 for update;
- flush tables with read lock;
+select * from t1 for update;
+flush tables with read lock;
commit;
a
1
@@ -45,7 +45,7 @@ flush tables with read lock;
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 102
- commit;
+commit;
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 102
diff --git a/mysql-test/r/flush_read_lock_kill.result b/mysql-test/r/flush_read_lock_kill.result
index dfdcf51457a..6703b6bd533 100644
--- a/mysql-test/r/flush_read_lock_kill.result
+++ b/mysql-test/r/flush_read_lock_kill.result
@@ -1,7 +1,7 @@
drop table if exists t1;
create table t1 (kill_id int);
insert into t1 values(connection_id());
- flush tables with read lock;
+flush tables with read lock;
select ((@id := kill_id) - kill_id) from t1;
((@id := kill_id) - kill_id)
0
diff --git a/mysql-test/r/flush_table.result b/mysql-test/r/flush_table.result
index b29c83eb574..8821bade6b4 100644
--- a/mysql-test/r/flush_table.result
+++ b/mysql-test/r/flush_table.result
@@ -9,7 +9,7 @@ test.t1 check status OK
unlock tables;
lock table t1 read;
lock table t1 read;
- flush table t1;
+flush table t1;
select * from t1;
a
1
@@ -19,7 +19,7 @@ a
1
unlock tables;
lock table t1 write;
- lock table t1 read;
+lock table t1 read;
flush table t1;
select * from t1;
a
@@ -27,7 +27,7 @@ a
unlock tables;
unlock tables;
lock table t1 read;
- lock table t1 write;
+lock table t1 write;
flush table t1;
select * from t1;
a
diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result
index 1a5e64978e6..715f319198c 100644
--- a/mysql-test/r/func_compress.result
+++ b/mysql-test/r/func_compress.result
@@ -79,6 +79,16 @@ uncompress(a) uncompressed_length(a)
NULL NULL
a 1
drop table t1;
+create table t1(a blob);
+insert into t1 values ('0'), (NULL), ('0');
+select compress(a), compress(a) from t1;
+select compress(a) is null from t1;
+compress(a) is null
+0
+1
+0
+drop table t1;
+End of 4.1 tests
create table t1 (a varchar(32) not null);
insert into t1 values ('foo');
explain select * from t1 where uncompress(a) is null;
diff --git a/mysql-test/r/func_date_add.result b/mysql-test/r/func_date_add.result
index 841d13a6ea6..ac5709260fd 100644
--- a/mysql-test/r/func_date_add.result
+++ b/mysql-test/r/func_date_add.result
@@ -71,3 +71,17 @@ NULL
NULL
NULL
drop table t1;
+End of 4.1 tests
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 DAY;
+CAST('2006-09-26' AS DATE) + INTERVAL 1 DAY
+2006-09-27
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 MONTH;
+CAST('2006-09-26' AS DATE) + INTERVAL 1 MONTH
+2006-10-26
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR;
+CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR
+2007-09-26
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK;
+CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK
+2006-10-03
+End of 5.0 tests
diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index f383a717a85..3ebf071a5bb 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -63,7 +63,7 @@ FROM t1
WHERE conn = 'default';
IS_USED_LOCK('bug16501') = connection_id
1
- SELECT GET_LOCK('bug16501',600);
+SELECT GET_LOCK('bug16501',600);
SELECT IS_USED_LOCK('bug16501') = CONNECTION_ID();
IS_USED_LOCK('bug16501') = CONNECTION_ID()
1
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
index 7e9bba9710c..29ceb6ecaa4 100644
--- a/mysql-test/r/func_sapdb.result
+++ b/mysql-test/r/func_sapdb.result
@@ -107,7 +107,9 @@ subtime("02:01:01.999999", "01:01:01.999999")
01:00:00.000000
select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002");
timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002")
-8807:59:59.999999
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '8807:59:59.999999'
select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002");
timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002")
46:58:57.999999
@@ -219,13 +221,16 @@ SELECT TIMEDIFF(t1, t4) As ttt, TIMEDIFF(t2, t3) As qqq,
TIMEDIFF(t3, t2) As eee, TIMEDIFF(t2, t4) As rrr from test;
ttt qqq eee rrr
-744:00:00 NULL NULL NULL
-26305:01:02 22:58:58 -22:58:58 NULL
--26305:01:02 -22:58:58 22:58:58 NULL
+838:59:59 22:58:58 -22:58:58 NULL
+-838:59:59 -22:58:58 22:58:58 NULL
NULL 26:02:02 -26:02:02 NULL
00:00:00 -26:02:02 26:02:02 NULL
NULL NULL NULL NULL
NULL NULL NULL NULL
00:00:00 -24:00:00 24:00:00 NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '26305:01:02'
+Warning 1292 Truncated incorrect time value: '-26305:01:02'
drop table t1, test;
select addtime("-01:01:01.01", "-23:59:59.1") as a;
a
@@ -235,7 +240,9 @@ a
10000
select microsecond(19971231235959.01) as a;
a
-10000
+0
+Warnings:
+Warning 1292 Truncated incorrect time value: '19971231235959.01'
select date_add("1997-12-31",INTERVAL "10.09" SECOND_MICROSECOND) as a;
a
1997-12-31 00:00:10.090000
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 82c361edd39..7cafd641dd6 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -339,7 +339,9 @@ extract(DAY_MINUTE FROM "02 10:11:12")
21011
select extract(DAY_SECOND FROM "225 10:11:12");
extract(DAY_SECOND FROM "225 10:11:12")
-225101112
+8385959
+Warnings:
+Warning 1292 Truncated incorrect time value: '225 10:11:12'
select extract(HOUR FROM "1999-01-02 10:11:12");
extract(HOUR FROM "1999-01-02 10:11:12")
10
@@ -612,7 +614,7 @@ date_add(date,INTERVAL "1 1:1:1" DAY_SECOND)
2003-01-03 01:01:01
select date_add(date,INTERVAL "1" WEEK) from t1;
date_add(date,INTERVAL "1" WEEK)
-2003-01-09 00:00:00
+2003-01-09
select date_add(date,INTERVAL "1" QUARTER) from t1;
date_add(date,INTERVAL "1" QUARTER)
2003-04-02
@@ -621,7 +623,7 @@ timestampadd(MINUTE, 1, date)
2003-01-02 00:01:00
select timestampadd(WEEK, 1, date) from t1;
timestampadd(WEEK, 1, date)
-2003-01-09 00:00:00
+2003-01-09
select timestampadd(SQL_TSI_SECOND, 1, date) from t1;
timestampadd(SQL_TSI_SECOND, 1, date)
2003-01-02 00:00:01
@@ -902,6 +904,93 @@ fmtddate field2
Sep-4 12:00AM abcd
DROP TABLE testBug8868;
SET NAMES DEFAULT;
+SELECT SEC_TO_TIME(3300000);
+SEC_TO_TIME(3300000)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '3300000'
+SELECT SEC_TO_TIME(3300000)+0;
+SEC_TO_TIME(3300000)+0
+8385959.000000
+Warnings:
+Warning 1292 Truncated incorrect time value: '3300000'
+SELECT SEC_TO_TIME(3600 * 4294967296);
+SEC_TO_TIME(3600 * 4294967296)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '15461882265600'
+SELECT TIME_TO_SEC('916:40:00');
+TIME_TO_SEC('916:40:00')
+3020399
+Warnings:
+Warning 1292 Truncated incorrect time value: '916:40:00'
+SELECT ADDTIME('500:00:00', '416:40:00');
+ADDTIME('500:00:00', '416:40:00')
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '916:40:00'
+SELECT ADDTIME('916:40:00', '416:40:00');
+ADDTIME('916:40:00', '416:40:00')
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '916:40:00'
+Warning 1292 Truncated incorrect time value: '1255:39:59'
+SELECT SUBTIME('916:40:00', '416:40:00');
+SUBTIME('916:40:00', '416:40:00')
+422:19:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '916:40:00'
+SELECT SUBTIME('-916:40:00', '416:40:00');
+SUBTIME('-916:40:00', '416:40:00')
+-838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '-916:40:00'
+Warning 1292 Truncated incorrect time value: '-1255:39:59'
+SELECT MAKETIME(916,0,0);
+MAKETIME(916,0,0)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '916:00:00'
+SELECT MAKETIME(4294967296, 0, 0);
+MAKETIME(4294967296, 0, 0)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '4294967296:00:00'
+SELECT MAKETIME(-4294967296, 0, 0);
+MAKETIME(-4294967296, 0, 0)
+-838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '-4294967296:00:00'
+SELECT MAKETIME(0, 4294967296, 0);
+MAKETIME(0, 4294967296, 0)
+NULL
+SELECT MAKETIME(0, 0, 4294967296);
+MAKETIME(0, 0, 4294967296)
+NULL
+SELECT MAKETIME(CAST(-1 AS UNSIGNED), 0, 0);
+MAKETIME(CAST(-1 AS UNSIGNED), 0, 0)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00'
+SELECT EXTRACT(HOUR FROM '100000:02:03');
+EXTRACT(HOUR FROM '100000:02:03')
+838
+Warnings:
+Warning 1292 Truncated incorrect time value: '100000:02:03'
+CREATE TABLE t1(f1 TIME);
+INSERT INTO t1 VALUES('916:00:00 a');
+Warnings:
+Warning 1265 Data truncated for column 'f1' at row 1
+Warning 1264 Out of range value adjusted for column 'f1' at row 1
+SELECT * FROM t1;
+f1
+838:59:59
+DROP TABLE t1;
+SELECT SEC_TO_TIME(CAST(-1 AS UNSIGNED));
+SEC_TO_TIME(CAST(-1 AS UNSIGNED))
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '18446744073709551615'
(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H)
union
(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H);
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index 79ba073a856..4b089c1d5e9 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -336,12 +336,12 @@ drop database mysqltest_1;
set password = password("changed");
ERROR 42000: Access denied for user ''@'localhost' to database 'mysql'
lock table mysql.user write;
- flush privileges;
- grant all on *.* to 'mysqltest_1'@'localhost';
+flush privileges;
+grant all on *.* to 'mysqltest_1'@'localhost';
unlock tables;
lock table mysql.user write;
- set password for 'mysqltest_1'@'localhost' = password('');
- revoke all on *.* from 'mysqltest_1'@'localhost';
+set password for 'mysqltest_1'@'localhost' = password('');
+revoke all on *.* from 'mysqltest_1'@'localhost';
unlock tables;
drop user 'mysqltest_1'@'localhost';
create database TESTDB;
diff --git a/mysql-test/r/handler_innodb.result b/mysql-test/r/handler_innodb.result
index 89569d918ca..1bd50612a3f 100644
--- a/mysql-test/r/handler_innodb.result
+++ b/mysql-test/r/handler_innodb.result
@@ -476,7 +476,7 @@ handler t1 read first;
c1
1
send the below to another connection, do not wait for the result
- optimize table t1;
+optimize table t1;
proceed with the normal connection
handler t1 read next;
c1
@@ -502,7 +502,7 @@ flush tables with read lock;
drop table t1;
ERROR HY000: Can't execute the query because you have a conflicting read lock
send the below to another connection, do not wait for the result
- drop table t1;
+drop table t1;
proceed with the normal connection
select * from t1;
c1
diff --git a/mysql-test/r/handler_myisam.result b/mysql-test/r/handler_myisam.result
index 8edf191b1b0..beb1a40c318 100644
--- a/mysql-test/r/handler_myisam.result
+++ b/mysql-test/r/handler_myisam.result
@@ -476,7 +476,7 @@ handler t1 read first;
c1
1
send the below to another connection, do not wait for the result
- optimize table t1;
+optimize table t1;
proceed with the normal connection
handler t1 read next;
c1
@@ -502,7 +502,7 @@ flush tables with read lock;
drop table t1;
ERROR HY000: Can't execute the query because you have a conflicting read lock
send the below to another connection, do not wait for the result
- drop table t1;
+drop table t1;
proceed with the normal connection
select * from t1;
c1
diff --git a/mysql-test/r/innodb_notembedded.result b/mysql-test/r/innodb_notembedded.result
index 9aac20e515d..cc13a429dfc 100644
--- a/mysql-test/r/innodb_notembedded.result
+++ b/mysql-test/r/innodb_notembedded.result
@@ -10,7 +10,7 @@ start transaction;
select f1();
f1()
100
- update t1 set col2=0 where col1=1;
+update t1 set col2=0 where col1=1;
select * from t1;
col1 col2
1 100
diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result
index b78c677fb02..cf5486d1091 100644
--- a/mysql-test/r/kill.result
+++ b/mysql-test/r/kill.result
@@ -22,7 +22,7 @@ create table t2 (id int unsigned not null);
insert into t2 select id from t1;
create table t3 (kill_id int);
insert into t3 values(connection_id());
- select id from t1 where id in (select distinct id from t2);
+select id from t1 where id in (select distinct id from t2);
select ((@id := kill_id) - kill_id) from t3;
((@id := kill_id) - kill_id)
0
@@ -32,7 +32,7 @@ drop table t1, t2, t3;
select get_lock("a", 10);
get_lock("a", 10)
1
- select get_lock("a", 10);
+select get_lock("a", 10);
get_lock("a", 10)
NULL
select 1;
diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result
index 8ff02d898a3..2445b3e0c69 100644
--- a/mysql-test/r/lock_multi.result
+++ b/mysql-test/r/lock_multi.result
@@ -2,8 +2,8 @@ drop table if exists t1,t2;
create table t1(n int);
insert into t1 values (1);
lock tables t1 write;
- update low_priority t1 set n = 4;
- select n from t1;
+update low_priority t1 set n = 4;
+select n from t1;
unlock tables;
n
4
@@ -11,8 +11,8 @@ drop table t1;
create table t1(n int);
insert into t1 values (1);
lock tables t1 read;
- update low_priority t1 set n = 4;
- select n from t1;
+update low_priority t1 set n = 4;
+select n from t1;
unlock tables;
n
1
@@ -23,7 +23,7 @@ insert into t1 values(1,1);
insert into t1 values(2,2);
insert into t2 values(1,2);
lock table t1 read;
- update t1,t2 set c=a where b=d;
+update t1,t2 set c=a where b=d;
select c from t2;
c
2
@@ -32,14 +32,14 @@ drop table t2;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write;
- insert t1 select * from t2;
+insert t1 select * from t2;
drop table t2;
ERROR 42S02: Table 'test.t2' doesn't exist
drop table t1;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write, t1 as t1_2 write, t2 as t2_2 write;
- insert t1 select * from t2;
+insert t1 select * from t2;
drop table t2;
ERROR 42S02: Table 'test.t2' doesn't exist
drop table t1;
@@ -54,7 +54,7 @@ use mysql;
LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE;
FLUSH TABLES;
use mysql;
- SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
+SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
OPTIMIZE TABLES columns_priv, db, host, user;
Table Op Msg_type Msg_text
mysql.columns_priv optimize status OK
@@ -68,14 +68,14 @@ use test;
use test;
CREATE TABLE t1 (c1 int);
LOCK TABLE t1 WRITE;
- FLUSH TABLES WITH READ LOCK;
+FLUSH TABLES WITH READ LOCK;
CREATE TABLE t2 (c1 int);
UNLOCK TABLES;
UNLOCK TABLES;
DROP TABLE t1, t2;
CREATE TABLE t1 (c1 int);
LOCK TABLE t1 WRITE;
- FLUSH TABLES WITH READ LOCK;
+FLUSH TABLES WITH READ LOCK;
CREATE TABLE t2 AS SELECT * FROM t1;
ERROR HY000: Table 't2' was not locked with LOCK TABLES
UNLOCK TABLES;
@@ -83,7 +83,7 @@ UNLOCK TABLES;
DROP TABLE t1;
CREATE DATABASE mysqltest_1;
FLUSH TABLES WITH READ LOCK;
- DROP DATABASE mysqltest_1;
+DROP DATABASE mysqltest_1;
DROP DATABASE mysqltest_1;
ERROR HY000: Can't execute the query because you have a conflicting read lock
UNLOCK TABLES;
@@ -91,7 +91,7 @@ DROP DATABASE mysqltest_1;
ERROR HY000: Can't drop database 'mysqltest_1'; database doesn't exist
create table t1 (f1 int(12) unsigned not null auto_increment, primary key(f1)) engine=innodb;
lock tables t1 write;
- alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
- alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
+alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
+alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
unlock tables;
drop table t1;
diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result
index a9683cc7c56..8df848fb2d0 100644
--- a/mysql-test/r/log_tables.result
+++ b/mysql-test/r/log_tables.result
@@ -39,14 +39,14 @@ ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL inste
lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL;
unlock tables;
lock tables mysql.general_log READ LOCAL;
- flush logs;
+flush logs;
unlock tables;
select "Mark that we woke up from flush logs in the test"
as "test passed";
test passed
Mark that we woke up from flush logs in the test
lock tables mysql.general_log READ LOCAL;
- truncate mysql.general_log;
+truncate mysql.general_log;
unlock tables;
select "Mark that we woke up from TRUNCATE in the test"
as "test passed";
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index 3ed0222fcdb..6d8e5dfdf2c 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -509,8 +509,8 @@ create table t2 (a int);
insert into t2 values (10), (20), (30);
create view v1 as select a as b, a/10 as a from t2;
lock table t1 write;
- alter table t1 add column c int default 100 after a;
- update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
+alter table t1 add column c int default 100 after a;
+update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
unlock tables;
select * from t1;
a c b
diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result
index 1053b1918fb..86ac7a8d72d 100644
--- a/mysql-test/r/mysql.result
+++ b/mysql-test/r/mysql.result
@@ -149,4 +149,17 @@ ERROR at line 1: USE must be followed by a database name
\\
';
';
+create table t17583 (a int);
+insert into t17583 (a) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+select count(*) from t17583;
+count(*)
+1280
+drop table t17583;
End of 5.0 tests
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index ce9fb6941f3..a0fce5f483f 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -152,8 +152,38 @@ mysqltest: At line 1: Missing delimiter
mysqltest: At line 1: End of line junk detected: "sleep 7
# Another comment
"
+mysqltest: At line 1: Missing delimiter
+mysqltest: At line 1: Missing delimiter
+mysqltest: At line 1: End of line junk detected: "disconnect default
+
+#
+# comment
+# comment2
+
+# comment 3
+--disable_query_log
+"
+mysqltest: At line 1: End of line junk detected: "disconnect default # comment
+# comment part2
+
+# comment 3
+--disable_query_log
+"
mysqltest: At line 1: Extra delimiter ";" found
mysqltest: At line 1: Extra delimiter ";" found
+mysqltest: At line 1: Missing argument(s) to 'error'
+mysqltest: At line 1: Missing argument(s) to 'error'
+mysqltest: At line 1: The sqlstate definition must start with an uppercase S
+mysqltest: At line 1: The error name definition must start with an uppercase E
+mysqltest: At line 1: Invalid argument to error: '9eeeee' - the errno may only consist of digits[0-9]
+mysqltest: At line 1: Invalid argument to error: '1sssss' - the errno may only consist of digits[0-9]
+mysqltest: At line 1: The sqlstate must be exactly 5 chars long
+mysqltest: At line 1: The sqlstate may only consist of digits[0-9] and _uppercase_ letters
+mysqltest: At line 1: The sqlstate must be exactly 5 chars long
+mysqltest: At line 1: Unknown SQL error name 'E9999'
+mysqltest: At line 1: Invalid argument to error: '999e9' - the errno may only consist of digits[0-9]
+mysqltest: At line 1: Invalid argument to error: '9b' - the errno may only consist of digits[0-9]
+mysqltest: At line 1: Too many errorcodes specified
MySQL
"MySQL"
MySQL: The world''s most popular open source database
@@ -239,7 +269,7 @@ mysqltest: At line 1: Missing assignment operator in let
1
# Execute: echo $success ;
1
-mysqltest: At line 1: Missing file name in source
+mysqltest: At line 1: Missing required argument 'filename' to command 'source'
mysqltest: At line 1: Could not open file ./non_existingFile
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/recursive.sql": At line 1: Source directives are nesting too deep
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/error.sql": At line 1: query 'garbage ' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
@@ -332,16 +362,16 @@ Counter is greater than 0, (counter=10)
Counter is not 0, (counter=0)
1
Testing while with not
-mysqltest: In included file "./include/mysqltest_while.inc": At line 64: Nesting too deeply
+mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest_while.inc": At line 64: Nesting too deeply
mysqltest: At line 1: missing '(' in while
mysqltest: At line 1: missing ')' in while
mysqltest: At line 1: Missing '{' after while. Found "dec $i"
mysqltest: At line 1: Stray '}' - end of block before beginning
mysqltest: At line 1: Stray 'end' command - end of block before beginning
-mysqltest: At line 1: query '' failed: 1065: Query was empty
+mysqltest: At line 1: query '{' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '{' at line 1
mysqltest: At line 1: Missing '{' after while. Found "echo hej"
mysqltest: At line 3: Missing end of block
-mysqltest: At line 1: Missing newline between while and '{'
+mysqltest: At line 3: Missing end of block
mysqltest: At line 1: missing '(' in if
mysqltest: At line 1: Stray 'end' command - end of block before beginning
select "b" bs col1, "c" bs col2;
@@ -371,17 +401,15 @@ mysqltest: At line 1: Wrong column number to replace_column in 'replace_column 1
mysqltest: At line 1: Invalid integer argument "10!"
mysqltest: At line 1: End of line junk detected: "!"
mysqltest: At line 1: Invalid integer argument "a"
-mysqltest: At line 1: Syntax error in connect - expected '(' found 'mysqltest: At line 1: Missing connection host
-mysqltest: At line 1: Missing connection host
-mysqltest: At line 1: Missing connection user
-mysqltest: At line 1: Missing connection user
-mysqltest: At line 1: Missing connection password
-mysqltest: At line 1: Missing connection db
-mysqltest: At line 1: Could not open connection 'con2': 1049 Unknown database 'illegal_db'
+mysqltest: At line 1: Missing required argument 'connection name' to command 'connect'
+mysqltest: At line 1: Missing required argument 'connection name' to command 'connect'
+mysqltest: At line 1: Missing required argument 'host' to command 'connect'
+mysqltest: At line 1: Missing required argument 'host' to command 'connect'
+mysqltest: At line 1: query 'connect con2,localhost,root,,illegal_db' failed: 1049: Unknown database 'illegal_db'
mysqltest: At line 1: Illegal argument for port: 'illegal_port'
mysqltest: At line 1: Illegal option to connect: SMTP
OK
-mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": At line 7: Connection limit exhausted - increase MAX_CONS in mysqltest.c
+mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": At line 7: Connection limit exhausted, you can have max 128 connections
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": At line 3: connection 'test_con1' not found in connection pool
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": At line 2: Connection test_con1 already exists
connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET);
@@ -449,7 +477,6 @@ sleep;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'sleep' at line 1
;
ERROR 42000: Query was empty
-End of 5.0 tests
select "b" as col1, "c" as col2;
col1 col2
b c
@@ -477,4 +504,18 @@ a D
1 1
1 4
drop table t1;
-End of 5.1 tests
+mysqltest: At line 1: Missing required argument 'filename' to command 'remove_file'
+mysqltest: At line 1: Missing required argument 'filename' to command 'write_file'
+mysqltest: At line 1: End of file encountered before 'EOF' delimiter was found
+mysqltest: At line 1: End of line junk detected: "write_file filename ";
+"
+mysqltest: At line 1: Missing required argument 'filename' to command 'file_exists'
+mysqltest: At line 1: Missing required argument 'from_file' to command 'copy_file'
+mysqltest: At line 1: Missing required argument 'to_file' to command 'copy_file'
+hello
+hello
+hello
+mysqltest: At line 1: Max delimiter length(16) exceeded
+hello
+hello
+End of tests
diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result
index f3e44a1df60..5a8f5a3137d 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -1090,41 +1090,15 @@ drop table t1;
create table t1 (a int) engine myisam
partition by range (a)
subpartition by hash (a)
-(partition p0 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx'
+(partition p0 VALUES LESS THAN (1) DATA DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpdata' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpinx'
(SUBPARTITION subpart00, SUBPARTITION subpart01));
-hello/master-data/test/t1.frm
-hello/master-data/test/t1.par
-hello/master-data/test/t1#P#p0#SP#subpart00.MYD
-hello/master-data/test/t1#P#p0#SP#subpart00.MYI
-hello/master-data/test/t1#P#p0#SP#subpart01.MYD
-hello/master-data/test/t1#P#p0#SP#subpart01.MYI
-hello/master-data/tmpdata/t1#P#p0#SP#subpart00.MYD
-hello/master-data/tmpdata/t1#P#p0#SP#subpart01.MYD
-hello/master-data/tmpinx/t1#P#p0#SP#subpart00.MYI
-hello/master-data/tmpinx/t1#P#p0#SP#subpart01.MYI
+Checking if file exists before alter
ALTER TABLE t1 REORGANIZE PARTITION p0 INTO
-(partition p1 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx'
+(partition p1 VALUES LESS THAN (1) DATA DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpdata' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpinx'
(SUBPARTITION subpart10, SUBPARTITION subpart11),
-partition p2 VALUES LESS THAN (2) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx'
+partition p2 VALUES LESS THAN (2) DATA DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpdata' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpinx'
(SUBPARTITION subpart20, SUBPARTITION subpart21));
-hello/master-data/test/t1.frm
-hello/master-data/test/t1.par
-hello/master-data/test/t1#P#p1#SP#subpart10.MYD
-hello/master-data/test/t1#P#p1#SP#subpart10.MYI
-hello/master-data/test/t1#P#p1#SP#subpart11.MYD
-hello/master-data/test/t1#P#p1#SP#subpart11.MYI
-hello/master-data/test/t1#P#p2#SP#subpart20.MYD
-hello/master-data/test/t1#P#p2#SP#subpart20.MYI
-hello/master-data/test/t1#P#p2#SP#subpart21.MYD
-hello/master-data/test/t1#P#p2#SP#subpart21.MYI
-hello/master-data/tmpdata/t1#P#p1#SP#subpart10.MYD
-hello/master-data/tmpdata/t1#P#p1#SP#subpart11.MYD
-hello/master-data/tmpdata/t1#P#p2#SP#subpart20.MYD
-hello/master-data/tmpdata/t1#P#p2#SP#subpart21.MYD
-hello/master-data/tmpinx/t1#P#p1#SP#subpart10.MYI
-hello/master-data/tmpinx/t1#P#p1#SP#subpart11.MYI
-hello/master-data/tmpinx/t1#P#p2#SP#subpart20.MYI
-hello/master-data/tmpinx/t1#P#p2#SP#subpart21.MYI
+Checking if file exists after alter
drop table t1;
create table t1 (a bigint unsigned not null, primary key(a))
engine = myisam
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index b7dae03bf47..7dadb3207a8 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -499,54 +499,6 @@ create temporary table if not exists t1 (a1 int);
execute stmt;
drop temporary table t1;
deallocate prepare stmt;
-CREATE TABLE t1(
-ID int(10) unsigned NOT NULL auto_increment,
-Member_ID varchar(15) NOT NULL default '',
-Action varchar(12) NOT NULL,
-Action_Date datetime NOT NULL,
-Track varchar(15) default NULL,
-User varchar(12) default NULL,
-Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
-CURRENT_TIMESTAMP,
-PRIMARY KEY (ID),
-KEY Action (Action),
-KEY Action_Date (Action_Date)
-);
-INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES
-('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
-('111111', 'Enrolled', '2006-03-01', 'CAD' ),
-('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
-('222222', 'Enrolled', '2006-03-07', 'CAD' ),
-('222222', 'Enrolled', '2006-03-07', 'CHF' ),
-('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
-('333333', 'Enrolled', '2006-03-01', 'CAD' ),
-('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
-('444444', 'Enrolled', '2006-03-01', 'CAD' ),
-('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
-('555555', 'Enrolled', '2006-07-21', 'CAD' ),
-('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
-('666666', 'Enrolled', '2006-02-09', 'CAD' ),
-('666666', 'Enrolled', '2006-05-12', 'CHF' ),
-('666666', 'Disenrolled', '2006-06-01', 'CAD' );
-PREPARE STMT FROM
-"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1
- WHERE Member_ID=? AND Action='Enrolled' AND
- (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1
- WHERE Member_ID=?
- GROUP BY Track
- HAVING Track>='CAD' AND
- MAX(Action_Date)>'2006-03-01')";
-SET @id='111111';
-EXECUTE STMT USING @id,@id;
-GROUP_CONCAT(Track SEPARATOR ', ')
-NULL
-SET @id='222222';
-EXECUTE STMT USING @id,@id;
-GROUP_CONCAT(Track SEPARATOR ', ')
-CAD
-DEALLOCATE PREPARE STMT;
-DROP TABLE t1;
-End of 4.1 tests
create table t1 (a varchar(20));
insert into t1 values ('foo');
prepare stmt FROM 'SELECT char_length (a) FROM t1';
@@ -564,77 +516,6 @@ SELECT FOUND_ROWS();
FOUND_ROWS()
2
deallocate prepare stmt;
-create table t1 (a char(3) not null, b char(3) not null,
-c char(3) not null, primary key (a, b, c));
-create table t2 like t1;
-prepare stmt from
-"select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b)
- where t1.a=1";
-execute stmt;
-a
-execute stmt;
-a
-execute stmt;
-a
-prepare stmt from
-"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from
-(t1 left outer join t2 on t2.a=? and t1.b=t2.b)
-left outer join t2 t3 on t3.a=? where t1.a=?";
-set @a:=1, @b:=1, @c:=1;
-execute stmt using @a, @b, @c;
-a b c a b c
-execute stmt using @a, @b, @c;
-a b c a b c
-execute stmt using @a, @b, @c;
-a b c a b c
-deallocate prepare stmt;
-drop table t1,t2;
-SET @aux= "SELECT COUNT(*)
- FROM INFORMATION_SCHEMA.COLUMNS A,
- INFORMATION_SCHEMA.COLUMNS B
- WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA
- AND A.TABLE_NAME = B.TABLE_NAME
- AND A.COLUMN_NAME = B.COLUMN_NAME AND
- A.TABLE_NAME = 'user'";
-prepare my_stmt from @aux;
-execute my_stmt;
-COUNT(*)
-39
-execute my_stmt;
-COUNT(*)
-39
-execute my_stmt;
-COUNT(*)
-39
-deallocate prepare my_stmt;
-drop procedure if exists p1|
-drop table if exists t1|
-create table t1 (id int)|
-insert into t1 values(1)|
-create procedure p1(a int, b int)
-begin
-declare c int;
-select max(id)+1 into c from t1;
-insert into t1 select a+b;
-insert into t1 select a-b;
-insert into t1 select a-c;
-end|
-set @a= 3, @b= 4|
-prepare stmt from "call p1(?, ?)"|
-execute stmt using @a, @b|
-execute stmt using @a, @b|
-select * from t1|
-id
-1
-7
--1
-1
-7
--1
--5
-deallocate prepare stmt|
-drop procedure p1|
-drop table t1|
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
@@ -698,47 +579,6 @@ id
3
deallocate prepare stmt;
drop table t1, t2;
-create table t1 (a int);
-insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
-prepare stmt from "select * from t1 limit ?, ?";
-set @offset=0, @limit=1;
-execute stmt using @offset, @limit;
-a
-1
-select * from t1 limit 0, 1;
-a
-1
-set @offset=3, @limit=2;
-execute stmt using @offset, @limit;
-a
-4
-5
-select * from t1 limit 3, 2;
-a
-4
-5
-prepare stmt from "select * from t1 limit ?";
-execute stmt using @limit;
-a
-1
-2
-prepare stmt from "select * from t1 where a in (select a from t1 limit ?)";
-ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
-prepare stmt from "select * from t1 union all select * from t1 limit ?, ?";
-set @offset=9;
-set @limit=2;
-execute stmt using @offset, @limit;
-a
-10
-1
-prepare stmt from "(select * from t1 limit ?, ?) union all
- (select * from t1 limit ?, ?) order by a limit ?";
-execute stmt using @offset, @limit, @offset, @limit, @limit;
-a
-10
-10
-drop table t1;
-deallocate prepare stmt;
create table t1 (id int);
prepare stmt from "insert into t1 (id) select id from t1 union select id from t1";
execute stmt;
@@ -839,15 +679,6 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
select ? from t1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t1' at line 1
drop table t1;
-CREATE TABLE b12651_T1(a int) ENGINE=MYISAM;
-CREATE TABLE b12651_T2(b int) ENGINE=MYISAM;
-CREATE VIEW b12651_V1 as SELECT b FROM b12651_T2;
-PREPARE b12651 FROM 'SELECT 1 FROM b12651_T1 WHERE a IN (SELECT b FROM b12651_V1)';
-EXECUTE b12651;
-1
-DROP VIEW b12651_V1;
-DROP TABLE b12651_T1, b12651_T2;
-DEALLOCATE PREPARE b12651;
prepare stmt from "select @@time_zone";
execute stmt;
@@time_zone
@@ -1064,6 +895,194 @@ select @@max_prepared_stmt_count, @@prepared_stmt_count;
@@max_prepared_stmt_count @@prepared_stmt_count
3 0
set global max_prepared_stmt_count= @old_max_prepared_stmt_count;
+drop table if exists t1;
+create temporary table if not exists t1 (a1 int);
+prepare stmt from "delete t1 from t1 where (cast(a1/3 as unsigned) * 3) = a1";
+drop temporary table t1;
+create temporary table if not exists t1 (a1 int);
+execute stmt;
+drop temporary table t1;
+create temporary table if not exists t1 (a1 int);
+execute stmt;
+drop temporary table t1;
+create temporary table if not exists t1 (a1 int);
+execute stmt;
+drop temporary table t1;
+deallocate prepare stmt;
+CREATE TABLE t1(
+ID int(10) unsigned NOT NULL auto_increment,
+Member_ID varchar(15) NOT NULL default '',
+Action varchar(12) NOT NULL,
+Action_Date datetime NOT NULL,
+Track varchar(15) default NULL,
+User varchar(12) default NULL,
+Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
+CURRENT_TIMESTAMP,
+PRIMARY KEY (ID),
+KEY Action (Action),
+KEY Action_Date (Action_Date)
+);
+INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES
+('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
+('111111', 'Enrolled', '2006-03-01', 'CAD' ),
+('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
+('222222', 'Enrolled', '2006-03-07', 'CAD' ),
+('222222', 'Enrolled', '2006-03-07', 'CHF' ),
+('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
+('333333', 'Enrolled', '2006-03-01', 'CAD' ),
+('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
+('444444', 'Enrolled', '2006-03-01', 'CAD' ),
+('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
+('555555', 'Enrolled', '2006-07-21', 'CAD' ),
+('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
+('666666', 'Enrolled', '2006-02-09', 'CAD' ),
+('666666', 'Enrolled', '2006-05-12', 'CHF' ),
+('666666', 'Disenrolled', '2006-06-01', 'CAD' );
+PREPARE STMT FROM
+"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1
+ WHERE Member_ID=? AND Action='Enrolled' AND
+ (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1
+ WHERE Member_ID=?
+ GROUP BY Track
+ HAVING Track>='CAD' AND
+ MAX(Action_Date)>'2006-03-01')";
+SET @id='111111';
+EXECUTE STMT USING @id,@id;
+GROUP_CONCAT(Track SEPARATOR ', ')
+NULL
+SET @id='222222';
+EXECUTE STMT USING @id,@id;
+GROUP_CONCAT(Track SEPARATOR ', ')
+CAD
+DEALLOCATE PREPARE STMT;
+DROP TABLE t1;
+End of 4.1 tests
+create table t1 (a varchar(20));
+insert into t1 values ('foo');
+prepare stmt FROM 'SELECT char_length (a) FROM t1';
+ERROR 42000: FUNCTION test.char_length does not exist
+drop table t1;
+create table t1 (a char(3) not null, b char(3) not null,
+c char(3) not null, primary key (a, b, c));
+create table t2 like t1;
+prepare stmt from
+"select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b)
+ where t1.a=1";
+execute stmt;
+a
+execute stmt;
+a
+execute stmt;
+a
+prepare stmt from
+"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from
+(t1 left outer join t2 on t2.a=? and t1.b=t2.b)
+left outer join t2 t3 on t3.a=? where t1.a=?";
+set @a:=1, @b:=1, @c:=1;
+execute stmt using @a, @b, @c;
+a b c a b c
+execute stmt using @a, @b, @c;
+a b c a b c
+execute stmt using @a, @b, @c;
+a b c a b c
+deallocate prepare stmt;
+drop table t1,t2;
+SET @aux= "SELECT COUNT(*)
+ FROM INFORMATION_SCHEMA.COLUMNS A,
+ INFORMATION_SCHEMA.COLUMNS B
+ WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA
+ AND A.TABLE_NAME = B.TABLE_NAME
+ AND A.COLUMN_NAME = B.COLUMN_NAME AND
+ A.TABLE_NAME = 'user'";
+prepare my_stmt from @aux;
+execute my_stmt;
+COUNT(*)
+39
+execute my_stmt;
+COUNT(*)
+39
+execute my_stmt;
+COUNT(*)
+39
+deallocate prepare my_stmt;
+drop procedure if exists p1|
+drop table if exists t1|
+create table t1 (id int)|
+insert into t1 values(1)|
+create procedure p1(a int, b int)
+begin
+declare c int;
+select max(id)+1 into c from t1;
+insert into t1 select a+b;
+insert into t1 select a-b;
+insert into t1 select a-c;
+end|
+set @a= 3, @b= 4|
+prepare stmt from "call p1(?, ?)"|
+execute stmt using @a, @b|
+execute stmt using @a, @b|
+select * from t1|
+id
+1
+7
+-1
+1
+7
+-1
+-5
+deallocate prepare stmt|
+drop procedure p1|
+drop table t1|
+create table t1 (a int);
+insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+prepare stmt from "select * from t1 limit ?, ?";
+set @offset=0, @limit=1;
+execute stmt using @offset, @limit;
+a
+1
+select * from t1 limit 0, 1;
+a
+1
+set @offset=3, @limit=2;
+execute stmt using @offset, @limit;
+a
+4
+5
+select * from t1 limit 3, 2;
+a
+4
+5
+prepare stmt from "select * from t1 limit ?";
+execute stmt using @limit;
+a
+1
+2
+prepare stmt from "select * from t1 where a in (select a from t1 limit ?)";
+ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
+prepare stmt from "select * from t1 union all select * from t1 limit ?, ?";
+set @offset=9;
+set @limit=2;
+execute stmt using @offset, @limit;
+a
+10
+1
+prepare stmt from "(select * from t1 limit ?, ?) union all
+ (select * from t1 limit ?, ?) order by a limit ?";
+execute stmt using @offset, @limit, @offset, @limit, @limit;
+a
+10
+10
+drop table t1;
+deallocate prepare stmt;
+CREATE TABLE b12651_T1(a int) ENGINE=MYISAM;
+CREATE TABLE b12651_T2(b int) ENGINE=MYISAM;
+CREATE VIEW b12651_V1 as SELECT b FROM b12651_T2;
+PREPARE b12651 FROM 'SELECT 1 FROM b12651_T1 WHERE a IN (SELECT b FROM b12651_V1)';
+EXECUTE b12651;
+1
+DROP VIEW b12651_V1;
+DROP TABLE b12651_T1, b12651_T2;
+DEALLOCATE PREPARE b12651;
create table t1 (id int);
prepare ins_call from "insert into t1 (id) values (1)";
execute ins_call;
@@ -1360,27 +1379,48 @@ i
1
DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;
+flush status;
+prepare sq from 'show status like "slow_queries"';
+execute sq;
+Variable_name Value
+Slow_queries 0
+prepare no_index from 'select 1 from information_schema.tables limit 1';
+execute sq;
+Variable_name Value
+Slow_queries 0
+execute no_index;
+1
+1
+execute sq;
+Variable_name Value
+Slow_queries 1
+deallocate prepare no_index;
+deallocate prepare sq;
End of 5.0 tests.
create procedure proc_1() reset query cache;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
create function func_1() returns int begin reset query cache; return 1; end|
+ERROR 0A000: RESET is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 0A000: FLUSH is not allowed in stored function or trigger
+ERROR 0A000: RESET is not allowed in stored function or trigger
drop function func_1;
+drop procedure proc_1;
prepare abc from "reset query cache";
execute abc;
execute abc;
execute abc;
deallocate prepare abc;
create procedure proc_1() reset master;
-drop procedure proc_1;
create function func_1() returns int begin reset master; return 1; end|
+ERROR 0A000: RESET is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 0A000: FLUSH is not allowed in stored function or trigger
+ERROR 0A000: RESET is not allowed in stored function or trigger
drop function func_1;
+drop procedure proc_1;
prepare abc from "reset master";
execute abc;
execute abc;
@@ -1390,11 +1430,13 @@ create procedure proc_1() reset slave;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
create function func_1() returns int begin reset slave; return 1; end|
+ERROR 0A000: RESET is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 0A000: FLUSH is not allowed in stored function or trigger
+ERROR 0A000: RESET is not allowed in stored function or trigger
drop function func_1;
+drop procedure proc_1;
prepare abc from "reset slave";
execute abc;
execute abc;
@@ -1429,13 +1471,13 @@ call proc_1();
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
create function func_1() returns int begin flush hosts; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
+drop procedure proc_1;
prepare abc from "flush hosts";
execute abc;
execute abc;
@@ -1445,13 +1487,13 @@ create procedure proc_1() flush privileges;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
create function func_1() returns int begin flush privileges; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
+drop procedure proc_1;
prepare abc from "flush privileges";
deallocate prepare abc;
create procedure proc_1() flush tables with read lock;
@@ -1461,9 +1503,13 @@ call proc_1();
unlock tables;
call proc_1();
unlock tables;
-drop procedure proc_1;
create function func_1() returns int begin flush tables with read lock; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
+select func_1(), func_1(), func_1() from dual;
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+drop function func_1;
+drop procedure proc_1;
prepare abc from "flush tables with read lock";
execute abc;
execute abc;
@@ -1474,13 +1520,13 @@ create procedure proc_1() flush tables;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
create function func_1() returns int begin flush tables; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
+drop procedure proc_1;
prepare abc from "flush tables";
execute abc;
execute abc;
@@ -1540,13 +1586,13 @@ mysql user 0 0
mysql general_log 1 0
mysql host 0 0
flush tables;
-drop procedure proc_1;
create function func_1() returns int begin flush tables; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
+drop procedure proc_1;
flush tables;
select Host, User from mysql.user limit 0;
Host User
@@ -1603,13 +1649,13 @@ create procedure proc_1() flush logs;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
create function func_1() returns int begin flush logs; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
+drop procedure proc_1;
prepare abc from "flush logs";
execute abc;
execute abc;
@@ -1619,13 +1665,13 @@ create procedure proc_1() flush status;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
create function func_1() returns int begin flush status; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
+drop procedure proc_1;
prepare abc from "flush status";
execute abc;
execute abc;
@@ -1635,39 +1681,39 @@ create procedure proc_1() flush slave;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
create function func_1() returns int begin flush slave; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
+drop procedure proc_1;
prepare abc from "flush slave";
execute abc;
execute abc;
execute abc;
deallocate prepare abc;
create procedure proc_1() flush master;
-drop procedure proc_1;
create function func_1() returns int begin flush master; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
+drop procedure proc_1;
prepare abc from "flush master";
deallocate prepare abc;
create procedure proc_1() flush des_key_file;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
create function func_1() returns int begin flush des_key_file; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
+drop procedure proc_1;
prepare abc from "flush des_key_file";
execute abc;
execute abc;
@@ -1677,13 +1723,13 @@ create procedure proc_1() flush user_resources;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
create function func_1() returns int begin flush user_resources; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
+drop procedure proc_1;
prepare abc from "flush user_resources";
execute abc;
execute abc;
@@ -1763,18 +1809,6 @@ Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
execute abc;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
deallocate prepare abc;
-create procedure proc_1() show scheduler status;
-drop procedure proc_1;
-create function func_1() returns int begin show scheduler status; return 1; end|
-ERROR 0A000: Not allowed to return a result set from a function
-select func_1(), func_1(), func_1() from dual;
-ERROR 42000: FUNCTION test.func_1 does not exist
-drop function func_1;
-ERROR 42000: FUNCTION test.func_1 does not exist
-prepare abc from "show scheduler status";
-ERROR HY000: This command is not supported in the prepared statement protocol yet
-deallocate prepare abc;
-ERROR HY000: Unknown prepared statement handler (abc) given to DEALLOCATE PREPARE
drop procedure if exists a;
create procedure a() select 42;
create procedure proc_1(a char(2)) show create procedure a;
@@ -1952,11 +1986,11 @@ ERROR HY000: No paths allowed for shared library
drop procedure proc_1;
create procedure proc_1() install plugin my_plug soname 'some_plugin.so';
call proc_1();
-ERROR HY000: Can't open shared library '/work/mysql-5.1-runtime/mysql-test/lib/mysql/some_plugin.so' (errno: 0 cannot open shared object file: No such file or directory)
+ERROR HY000: Can't open shared library
call proc_1();
-ERROR HY000: Can't open shared library '/work/mysql-5.1-runtime/mysql-test/lib/mysql/some_plugin.so' (errno: 22 cannot open shared object file: No such file or directory)
+ERROR HY000: Can't open shared library
call proc_1();
-ERROR HY000: Can't open shared library '/work/mysql-5.1-runtime/mysql-test/lib/mysql/some_plugin.so' (errno: 22 cannot open shared object file: No such file or directory)
+ERROR HY000: Can't open shared library
drop procedure proc_1;
create function func_1() returns int begin install plugin my_plug soname '/tmp/plugin'; return 1; end|
ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
@@ -2086,7 +2120,7 @@ drop user pstest_xyz@localhost;
deallocate prepare abc;
drop event if exists xyz;
create function func_1() returns int begin create event xyz on schedule at now() do select 123; return 1; end|
-ERROR 0A000: Not allowed to return a result set from a function
+ERROR HY000: Recursivity of EVENT DDL statements is forbidden when body is present
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
drop function func_1;
diff --git a/mysql-test/r/ps_11bugs.result b/mysql-test/r/ps_11bugs.result
index c849c25d646..ebe161f46b3 100644
--- a/mysql-test/r/ps_11bugs.result
+++ b/mysql-test/r/ps_11bugs.result
@@ -130,3 +130,36 @@ prepare st_18492 from 'select * from t1 where 3 in (select (1+1) union select 1)
execute st_18492;
a
drop table t1;
+create table t1 (a int, b varchar(4));
+create table t2 (a int, b varchar(4), primary key(a));
+prepare stmt1 from 'insert into t1 (a, b) values (?, ?)';
+prepare stmt2 from 'insert into t2 (a, b) values (?, ?)';
+set @intarg= 11;
+set @varchararg= '2222';
+execute stmt1 using @intarg, @varchararg;
+execute stmt2 using @intarg, @varchararg;
+set @intarg= 12;
+execute stmt1 using @intarg, @UNDEFINED;
+execute stmt2 using @intarg, @UNDEFINED;
+set @intarg= 13;
+execute stmt1 using @UNDEFINED, @varchararg;
+execute stmt2 using @UNDEFINED, @varchararg;
+ERROR 23000: Column 'a' cannot be null
+set @intarg= 14;
+set @nullarg= Null;
+execute stmt1 using @UNDEFINED, @nullarg;
+execute stmt2 using @nullarg, @varchararg;
+ERROR 23000: Column 'a' cannot be null
+select * from t1;
+a b
+11 2222
+12 NULL
+NULL 2222
+NULL NULL
+select * from t2;
+a b
+11 2222
+12 NULL
+drop table t1;
+drop table t2;
+End of 5.0 tests.
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 96289305da1..d5996ee8163 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -934,8 +934,7 @@ abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
zyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba
flush query cache;
drop table t1, t2;
-set GLOBAL query_cache_size=1355776
-#;
+set GLOBAL query_cache_size=1355776;
flush status;
CREATE TABLE t1 (
`date` datetime NOT NULL default '0000-00-00 00:00:00',
diff --git a/mysql-test/r/query_cache_notembedded.result b/mysql-test/r/query_cache_notembedded.result
index 4226738725a..8e5df012cfb 100644
--- a/mysql-test/r/query_cache_notembedded.result
+++ b/mysql-test/r/query_cache_notembedded.result
@@ -326,7 +326,7 @@ insert into t1 values(3);
set i_var = sleep(3);
return 0;
end;|
- select f1();
+select f1();
select sleep(4);
sleep(4)
0
diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result
index 76c0f4422fe..964babb1228 100644
--- a/mysql-test/r/rename.result
+++ b/mysql-test/r/rename.result
@@ -43,7 +43,7 @@ Note 1051 Unknown table 't4'
CREATE TABLE t1 (a int);
CREATE TABLE t3 (a int);
FLUSH TABLES WITH READ LOCK;
- RENAME TABLE t1 TO t2, t3 to t4;
+RENAME TABLE t1 TO t2, t3 to t4;
show tables;
Tables_in_test
t1
diff --git a/mysql-test/r/rpl_err_ignoredtable.result b/mysql-test/r/rpl_err_ignoredtable.result
index 27db9c0372c..f211d5d9a2f 100644
--- a/mysql-test/r/rpl_err_ignoredtable.result
+++ b/mysql-test/r/rpl_err_ignoredtable.result
@@ -26,7 +26,7 @@ create table t2 (a int primary key);
insert into t2 values(1);
create table t3 (id int);
insert into t3 values(connection_id());
- update t2 set a = a + 1 + get_lock('crash_lock%20C', 10);
+update t2 set a = a + 1 + get_lock('crash_lock%20C', 10);
select (@id := id) - id from t3;
(@id := id) - id
0
diff --git a/mysql-test/r/rpl_master_pos_wait.result b/mysql-test/r/rpl_master_pos_wait.result
index 81d9043c8ce..951e944fddc 100644
--- a/mysql-test/r/rpl_master_pos_wait.result
+++ b/mysql-test/r/rpl_master_pos_wait.result
@@ -12,7 +12,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select master_pos_wait(_latin1'master-bin.999999',0,2) AS `master_pos_wait('master-bin.999999',0,2)`
- select master_pos_wait('master-bin.999999',0);
+select master_pos_wait('master-bin.999999',0);
stop slave sql_thread;
master_pos_wait('master-bin.999999',0)
NULL
diff --git a/mysql-test/r/rpl_ndb_sp003.result b/mysql-test/r/rpl_ndb_sp003.result
index 94f320f387b..d7922c61b52 100644
--- a/mysql-test/r/rpl_ndb_sp003.result
+++ b/mysql-test/r/rpl_ndb_sp003.result
@@ -21,7 +21,7 @@ END|
SELECT get_lock("test", 200);
get_lock("test", 200)
1
- CALL test.p1();
+CALL test.p1();
CALL test.p2();
SELECT release_lock("test");
release_lock("test")
diff --git a/mysql-test/r/rpl_row_sp003.result b/mysql-test/r/rpl_row_sp003.result
index 01e352c3d46..df3e2a7ceed 100644
--- a/mysql-test/r/rpl_row_sp003.result
+++ b/mysql-test/r/rpl_row_sp003.result
@@ -21,7 +21,7 @@ END|
SELECT get_lock("test", 200);
get_lock("test", 200)
1
- CALL test.p1();
+CALL test.p1();
CALL test.p2();
SELECT release_lock("test");
release_lock("test")
diff --git a/mysql-test/r/rpl_stm_000001.result b/mysql-test/r/rpl_stm_000001.result
index ef4226e07b5..3b4cd05f640 100644
--- a/mysql-test/r/rpl_stm_000001.result
+++ b/mysql-test/r/rpl_stm_000001.result
@@ -44,7 +44,7 @@ create table t2(id int);
insert into t2 values(connection_id());
create temporary table t3(n int);
insert into t3 select get_lock('crash_lock%20C', 1) from t2;
- update t1 set n = n + get_lock('crash_lock%20C', 2);
+update t1 set n = n + get_lock('crash_lock%20C', 2);
select (@id := id) - id from t2;
(@id := id) - id
0
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index b473bbac923..3836148faa9 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -672,7 +672,22 @@ SHOW TABLES FROM no_such_database;
ERROR 42000: Unknown database 'no_such_database'
SHOW COLUMNS FROM no_such_table;
ERROR 42S02: Table 'test.no_such_table' doesn't exist
-End of 5.0 tests.
+flush status;
+show status like 'slow_queries';
+Variable_name Value
+Slow_queries 0
+show tables;
+Tables_in_test
+show status like 'slow_queries';
+Variable_name Value
+Slow_queries 0
+select 1 from information_schema.tables limit 1;
+1
+1
+show status like 'slow_queries';
+Variable_name Value
+Slow_queries 1
+End of 5.0 tests
SHOW AUTHORS;
create database mysqltest;
show create database mysqltest;
diff --git a/mysql-test/r/sp-threads.result b/mysql-test/r/sp-threads.result
index c516d7a643f..953830ecc87 100644
--- a/mysql-test/r/sp-threads.result
+++ b/mysql-test/r/sp-threads.result
@@ -31,7 +31,7 @@ create procedure bug9486()
update t1, t2 set val= 1 where id1=id2;
call bug9486();
lock tables t2 write;
- call bug9486();
+call bug9486();
show processlist;
Id User Host db Command Time State Info
# root localhost test Sleep # NULL
@@ -77,7 +77,7 @@ select * from t1;
end|
use test;
lock table t1 write;
- call p2();
+call p2();
use test;
drop procedure p1;
create procedure p1() select * from t1;
diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result
index 564b8031c35..0b1fa565d28 100644
--- a/mysql-test/r/sp_notembedded.result
+++ b/mysql-test/r/sp_notembedded.result
@@ -74,8 +74,7 @@ flush status|
flush query cache|
delete from t1|
drop procedure bug3583|
-drop table t1;
-#|
+drop table t1|
drop procedure if exists bug6807|
create procedure bug6807()
begin
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index a1463bc2b3c..8b41ba87423 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -2717,8 +2717,7 @@ select (1,2,3) = (select * from t1);
ERROR 21000: Operand should contain 3 column(s)
select (select * from t1) = (1,2,3);
ERROR 21000: Operand should contain 2 column(s)
-drop table t1
-#;
+drop table t1;
CREATE TABLE `t1` (
`itemid` bigint(20) unsigned NOT NULL auto_increment,
`sessionid` bigint(20) unsigned default NULL,
diff --git a/mysql-test/r/synchronization.result b/mysql-test/r/synchronization.result
index 697eb064998..4543a829494 100644
--- a/mysql-test/r/synchronization.result
+++ b/mysql-test/r/synchronization.result
@@ -1,6 +1,6 @@
drop table if exists t1;
CREATE TABLE t1 (x1 int);
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -8,7 +8,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -16,7 +16,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -24,7 +24,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -32,7 +32,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -40,7 +40,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -48,7 +48,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -56,7 +56,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -64,7 +64,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -72,7 +72,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -80,7 +80,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -88,7 +88,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -96,7 +96,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -104,7 +104,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -112,7 +112,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -120,7 +120,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -128,7 +128,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -136,7 +136,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -144,7 +144,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -152,7 +152,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index 53497fd528b..8382f521b84 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -215,6 +215,7 @@ select @@version;
select @@global.version;
@@global.version
#
+End of 4.1 tests
set @first_var= NULL;
create table t1 select @first_var;
show create table t1;
@@ -301,3 +302,11 @@ select @var;
@var
3
drop table t1;
+insert into city 'blah';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''blah'' at line 1
+SHOW COUNT(*) WARNINGS;
+@@session.warning_count
+1
+SHOW COUNT(*) ERRORS;
+@@session.error_count
+1
diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test
index 5ee3d64e56f..2e66c24d877 100644
--- a/mysql-test/t/connect.test
+++ b/mysql-test/t/connect.test
@@ -59,6 +59,7 @@ flush privileges;
connect (con10,localhost,test,gambling2,);
connect (con5,localhost,test,gambling2,mysql);
+connection con5;
set password="";
--error 1372
set password='gambling3';
diff --git a/mysql-test/t/crash_commit_before.test b/mysql-test/t/crash_commit_before.test
index a10cf254a83..757817915dd 100644
--- a/mysql-test/t/crash_commit_before.test
+++ b/mysql-test/t/crash_commit_before.test
@@ -20,6 +20,9 @@ SET SESSION debug="d,crash_commit_before";
--error 2013
COMMIT;
+# Turn on reconnect
+--enable_reconnect
+
# Call script that will poll the server waiting for it to be back online again
--source include/wait_until_connected_again.inc
diff --git a/mysql-test/t/csv.test b/mysql-test/t/csv.test
index f70b5b40766..82102a6078e 100644
--- a/mysql-test/t/csv.test
+++ b/mysql-test/t/csv.test
@@ -1295,7 +1295,7 @@ SELECT fld3 FROM t2;
#
DROP TABLE t1;
-ALTER TABLE t2 RENAME t1
+ALTER TABLE t2 RENAME t1;
#
# Drop and recreate
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index 8c4a76c78a9..6af71e32cc4 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -9,29 +9,18 @@
# Do not use any TAB characters for whitespace.
#
##############################################################################
-#events_bugs : BUG#17619 2006-02-21 andrey Race conditions
-#events_stress : BUG#17619 2006-02-21 andrey Race conditions
-#events : BUG#17619 2006-02-21 andrey Race conditions
-#events_scheduling : BUG#19170 2006-04-26 andrey Test case of 19170 fails on some platforms. Has to be checked.
im_options : Bug#20294 2006-07-24 stewart Instance manager test im_options fails randomly
-#im_life_cycle : Bug#20368 2006-06-10 alik im_life_cycle test fails
-im_daemon_life_cycle : BUG#22379 2006-09-15 ingo im_daemon_life_cycle.test fails on merge of 5.1 -> 5.1-engines
-im_instance_conf : BUG#20294 2006-09-16 ingo Instance manager test im_instance_conf fails randomly
concurrent_innodb : BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences
ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog
ndb_autodiscover2 : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog
-#ndb_binlog_ignore_db : BUG#21279 2006-07-25 ingo Randomly throws a warning
ndb_load : BUG#17233 2006-05-04 tomas failed load data from infile causes mysqld dbug_assert, binlog not flushed
partition_03ndb : BUG#16385 2006-03-24 mikael Partitions: crash when updating a range partitioned NDB table
-ps : BUG#21524 2006-08-08 pgalbraith 'ps' test fails in --ps-protocol test AMD64 bit
ps_7ndb : BUG#18950 2006-02-16 jmiller create table like does not obtain LOCK_open
rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated
rpl_ndb_2myisam : BUG#19227 Seems to pass currently
-#rpl_ndb_commit_afterflush : BUG#19328 2006-05-04 tomas Slave timeout with COM_REGISTER_SLAVE error causing stop
rpl_ndb_dd_partitions : BUG#19259 2006-04-21 rpl_ndb_dd_partitions fails on s/AMD
rpl_ndb_ddl : BUG#18946 result file needs update + test needs to checked
rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
-#rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ
rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly
rpl_sp : BUG#16456 2006-02-16 jmiller
@@ -39,8 +28,5 @@ rpl_multi_engine : BUG#22583 2006-09-23 lars
# the below testcase have been reworked to avoid the bug, test contains comment, keep bug open
#ndb_binlog_ddl_multi : BUG#18976 2006-04-10 kent CRBR: multiple binlog, second binlog may miss schema log events
-#rpl_ndb_idempotent : BUG#21298 2006-07-27 msvensson
-#rpl_row_basic_7ndb : BUG#21298 2006-07-27 msvensson
-#rpl_truncate_7ndb : BUG#21298 2006-07-27 msvensson
ndb_binlog_discover : bug#21806 2006-08-24
ndb_autodiscover3 : bug#21806
diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test
index eeb5d509b94..68f07f258bf 100644
--- a/mysql-test/t/func_compress.test
+++ b/mysql-test/t/func_compress.test
@@ -56,7 +56,19 @@ insert into t1 values(NULL), (compress('a'));
select uncompress(a), uncompressed_length(a) from t1;
drop table t1;
-# End of 4.1 tests
+#
+# Bug #23254: problem with compress(NULL)
+#
+
+create table t1(a blob);
+insert into t1 values ('0'), (NULL), ('0');
+--disable_result_log
+select compress(a), compress(a) from t1;
+--enable_result_log
+select compress(a) is null from t1;
+drop table t1;
+
+--echo End of 4.1 tests
#
# Bug #18539: uncompress(d) is null: impossible?
diff --git a/mysql-test/t/func_date_add.test b/mysql-test/t/func_date_add.test
index e01fce30577..b575eeececa 100644
--- a/mysql-test/t/func_date_add.test
+++ b/mysql-test/t/func_date_add.test
@@ -64,4 +64,17 @@ insert into t1 values (date_add('2000-01-04', INTERVAL NULL DAY));
select * from t1;
drop table t1;
-# End of 4.1 tests
+--echo End of 4.1 tests
+
+#
+# Bug#21811
+#
+# Make sure we end up with an appropriate
+# date format (DATE) after addition operation
+#
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 DAY;
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 MONTH;
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR;
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK;
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index d49a4fed9d2..a0b0a929b6a 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -466,6 +466,47 @@ SET NAMES DEFAULT;
#
+# Bug #11655: Wrong time is returning from nested selects - maximum time exists
+#
+# check if SEC_TO_TIME() handles out-of-range values correctly
+SELECT SEC_TO_TIME(3300000);
+SELECT SEC_TO_TIME(3300000)+0;
+SELECT SEC_TO_TIME(3600 * 4294967296);
+
+# check if TIME_TO_SEC() handles out-of-range values correctly
+SELECT TIME_TO_SEC('916:40:00');
+
+# check if ADDTIME() handles out-of-range values correctly
+SELECT ADDTIME('500:00:00', '416:40:00');
+SELECT ADDTIME('916:40:00', '416:40:00');
+
+# check if SUBTIME() handles out-of-range values correctly
+SELECT SUBTIME('916:40:00', '416:40:00');
+SELECT SUBTIME('-916:40:00', '416:40:00');
+
+# check if MAKETIME() handles out-of-range values correctly
+SELECT MAKETIME(916,0,0);
+SELECT MAKETIME(4294967296, 0, 0);
+SELECT MAKETIME(-4294967296, 0, 0);
+SELECT MAKETIME(0, 4294967296, 0);
+SELECT MAKETIME(0, 0, 4294967296);
+SELECT MAKETIME(CAST(-1 AS UNSIGNED), 0, 0);
+
+# check if EXTRACT() handles out-of-range values correctly
+SELECT EXTRACT(HOUR FROM '100000:02:03');
+
+# check if we get proper warnings if both input string truncation
+# and out-of-range value occur
+CREATE TABLE t1(f1 TIME);
+INSERT INTO t1 VALUES('916:00:00 a');
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Bug #20927: sec_to_time treats big unsigned as signed
+#
+# check if SEC_TO_TIME() handles BIGINT UNSIGNED values correctly
+SELECT SEC_TO_TIME(CAST(-1 AS UNSIGNED));
# Bug #19844 time_format in Union truncates values
#
diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest
index 55e52f4e464..5f8eb16a5d2 100644
--- a/mysql-test/t/im_daemon_life_cycle.imtest
+++ b/mysql-test/t/im_daemon_life_cycle.imtest
@@ -8,6 +8,9 @@
--source include/im_check_env.inc
+# Turn on reconnect, not on by default anymore
+--enable_reconnect
+
###########################################################################
# Kill the IM main process and check that the IM Angel will restart the main
diff --git a/mysql-test/t/init_file.test b/mysql-test/t/init_file.test
index 6b5e032fd99..31a6ef5a541 100644
--- a/mysql-test/t/init_file.test
+++ b/mysql-test/t/init_file.test
@@ -4,7 +4,7 @@
#
# See mysql-test/std_data/init_file.dat and
# mysql-test/t/init_file-master.opt for the actual test
-#
+#
--echo ok
--echo end of 4.1 tests
diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test
index f3296e6f706..6b2c84f880a 100644
--- a/mysql-test/t/mysql.test
+++ b/mysql-test/t/mysql.test
@@ -153,4 +153,21 @@ drop table t1;
--exec echo "SELECT '\';';" >> $MYSQLTEST_VARDIR/tmp/bug20103.sql
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20103.sql 2>&1
+#
+# Bug#17583: mysql drops connection when stdout is not writable
+#
+create table t17583 (a int);
+insert into t17583 (a) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+# Close to the minimal data needed to exercise bug.
+select count(*) from t17583;
+--exec echo "select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; " |$MYSQL test >&-
+drop table t17583;
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
index 25f8d63d0b2..d98375ca746 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -317,7 +317,6 @@ select 3 from t1 ;
#
#select 3 from t1 ;
-# End of 4.1 tests
--error 1
--exec echo "disable_abort_on_error; enable_abort_on_error; error 1064; select 3 from t1; select 3 from t1;" | $MYSQL_TEST 2>&1
@@ -360,18 +359,80 @@ select 3 from t1 ;
# Missing delimiter
# The comment will be "sucked into" the sleep command since
# delimiter is missing until after "show status"
---system echo "sleep 4" > $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "# A comment" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "show status;" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+sleep 4
+# A comment
+show status;
+EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
#
# Missing delimiter until eof
# The comment will be "sucked into" the sleep command since
-# delimiter is missing
---system echo "sleep 7" > $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "# Another comment" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+# delimiter is missing
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+sleep 7
+# Another comment
+EOF
+--error 1
+--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
+
+#
+# Missing delimiter until "disable_query_log"
+#
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+disconnect default
+
+#
+# comment
+# comment 3
+disable_query_log;
+EOF
+--error 1
+--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
+
+#
+# Missing delimiter until "disable_query_log"
+#
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+disconnect default
+
+#
+# comment
+
+# comment 3
+disable_query_log;
+EOF
+--error 1
+--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
+
+#
+# Missing delimiter until eof
+#
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+disconnect default
+
+#
+# comment
+# comment2
+
+# comment 3
+--disable_query_log
+EOF
+--error 1
+--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
+
+#
+# Missing delimiter until eof
+#
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+disconnect default # comment
+# comment part2
+
+# comment 3
+--disable_query_log
+EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
@@ -388,6 +449,67 @@ select 3 from t1 ;
--sleep 1 # Wait for insert delayed to be executed.
--sleep 1 # Wait for insert delayed to be executed.
+# ----------------------------------------------------------------------------
+# Test error
+# ----------------------------------------------------------------------------
+
+# Missing argument
+--error 1
+--exec echo "error;" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--error" | $MYSQL_TEST 2>&1
+
+# First char must be uppercase 'S' or 'E' or [0-9]
+--error 1
+--exec echo "--error s99999" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--error e99999" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--error 9eeeee" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--error 1sssss" | $MYSQL_TEST 2>&1
+
+# First char 'S' but too long
+--error 1
+--exec echo "--error S999999" | $MYSQL_TEST 2>&1
+
+# First char 'S' but lowercase char found
+--error 1
+--exec echo "--error S99a99" | $MYSQL_TEST 2>&1
+
+# First char 'S' but too short
+--error 1
+--exec echo "--error S9999" | $MYSQL_TEST 2>&1
+
+# First char 'E' but not found in error array
+--error 1
+--exec echo "--error E9999" | $MYSQL_TEST 2>&1
+
+# First char [0-9] but contains chars
+--error 1
+--exec echo "--error 999e9" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--error 9b" | $MYSQL_TEST 2>&1
+
+# Multiple errorcodes separated by ','
+--error 1,1,1,1
+#--error 9,ER_PARSE_ERROR
+#--error ER_PARSE_ERROR
+#--error 9,ER_PARSE_ERROR,9,ER_PARSE_ERROR
+#--error 9, ER_PARSE_ERROR, 9, ER_PARSE_ERROR
+#--error 9,S00000,9,ER_PARSE_ERROR
+#--error 9,S00000,9,ER_PARSE_ERROR,ER_PARSE_ERROR,ER_PARSE_ERROR,9,10,11,12
+--error 9,S00000,9
+--error 9,S00000,9,9,10,11,12
+--error 9 ,10
+--error 9 , 10
+--error 9 , 10
+--error 9 , 10
+
+# Too many errorcodes specified
+--error 1
+--exec echo "--error 1,2,3,4,5,6,7,8,9,10,11" | $MYSQL_TEST 2>&1
+
# ----------------------------------------------------------------------------
# Test echo command
@@ -610,6 +732,7 @@ echo $var3_var3;
# Fix win paths
--replace_result \\ /
+# Source a nonexisting file
--error 1
--exec echo "source non_existingFile;" | $MYSQL_TEST 2>&1
@@ -627,13 +750,16 @@ echo $var3_var3;
# Test execution of source in a while loop
+--write_file $MYSQLTEST_VARDIR/tmp/sourced.inc
+echo here is the sourced script;
+EOF
--disable_query_log
let $outer= 2; # Number of outer loops
while ($outer)
{
eval SELECT '$outer = outer loop variable after while' AS "";
- --source include/sourced.inc
+ --source $MYSQLTEST_VARDIR/tmp/sourced.inc
eval SELECT '$outer = outer loop variable before dec' AS "";
dec $outer;
@@ -661,11 +787,12 @@ let $num= 9;
while ($num)
{
SELECT 'In loop' AS "";
- --source include/sourced1.inc
+ --source $MYSQLTEST_VARDIR/tmp/sourced.inc
dec $num;
}
--enable_abort_on_error
--enable_query_log
+--remove_file $MYSQLTEST_VARDIR/tmp/sourced.inc
# ----------------------------------------------------------------------------
# Test sleep command
@@ -817,10 +944,150 @@ while (!$i)
}
# Exceed max nesting level
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest_while.inc
+let $1 = 10;
+while ($1)
+{
+while ($1)
+{
+while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ echo $1;
+ dec $1;
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+EOF
# Fix win path
---replace_result \\ /
+--replace_result \\ / $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 1
---exec echo "source include/mysqltest_while.inc;" | $MYSQL_TEST 2>&1
+--exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest_while.inc;" | $MYSQL_TEST 2>&1
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqltest_while.inc
--error 1
--exec echo "while \$i;" | $MYSQL_TEST 2>&1
--error 1
@@ -925,12 +1192,6 @@ select "a" as col1, "c" as col2;
--error 1
--exec echo "connect (con2,);" | $MYSQL_TEST 2>&1
--error 1
---exec echo "connect (con2,localhost);" | $MYSQL_TEST 2>&1
---error 1
---exec echo "connect (con2, localhost, root);" | $MYSQL_TEST 2>&1
---error 1
---exec echo "connect (con2, localhost, root,);" | $MYSQL_TEST 2>&1
---error 1
--exec echo "connect (con2,localhost,root,,illegal_db);" | $MYSQL_TEST 2>&1
--error 1
--exec echo "connect (con1,localhost,root,,,illegal_port,);" | $MYSQL_TEST 2>&1
@@ -938,13 +1199,15 @@ select "a" as col1, "c" as col2;
--exec echo "connect (con1,localhost,root,,,,,SMTP POP);" | $MYSQL_TEST 2>&1
# Repeat connect/disconnect
---system echo "let \$i=100;" > $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "while (\$i)" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "{" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo " connect (test_con1,localhost,root,,); " >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo " disconnect test_con1; " >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo " dec \$i; " >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "}" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+let $i=100;
+while ($i)
+{
+ connect (test_con1,localhost,root,,);
+ disconnect test_con1;
+ dec $i;
+}
+EOF
--exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql; echo OK;" | $MYSQL_TEST 2>&1
# Repeat connect/disconnect, exceed max number of connections
@@ -1149,8 +1412,6 @@ query sleep;
--error 1065
query ;
---echo End of 5.0 tests
-
# test for replace_regex
--replace_regex /at/b/
select "at" as col1, "c" as col2;
@@ -1189,4 +1450,103 @@ insert into t1 values (2,4);
select * from t1;
drop table t1;
---echo End of 5.1 tests
+# ----------------------------------------------------------------------------
+# test for remove_file
+# ----------------------------------------------------------------------------
+
+--error 1
+--exec echo "remove_file ;" | $MYSQL_TEST 2>&1
+
+--error 1
+remove_file non_existing_file;
+
+# ----------------------------------------------------------------------------
+# test for write_file
+# ----------------------------------------------------------------------------
+--error 1
+--exec echo "write_file ;" | $MYSQL_TEST 2>&1
+
+--error 1
+--exec echo "write_file filename ;" | $MYSQL_TEST 2>&1
+
+--error 1
+--exec echo "write_file filename \";" | $MYSQL_TEST 2>&1
+
+write_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+Content for test_file1
+EOF
+file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+
+write_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp END_DELIMITER;
+Content for test_file1 contains EOF
+END_DELIMITER
+file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+
+# ----------------------------------------------------------------------------
+# test for file_exist
+# ----------------------------------------------------------------------------
+--error 1
+--exec echo "file_exists ;" | $MYSQL_TEST 2>&1
+
+--error 0,1
+remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+--error 1
+file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+write_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+Content for test_file1
+EOF
+file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+--error 1
+file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+
+
+# ----------------------------------------------------------------------------
+# test for copy_file
+# ----------------------------------------------------------------------------
+--write_file $MYSQLTEST_VARDIR/tmp/file1.tmp
+file1
+EOF
+
+copy_file $MYSQLTEST_VARDIR/tmp/file1.tmp $MYSQLTEST_VARDIR/tmp/file2.tmp;
+file_exists $MYSQLTEST_VARDIR/tmp/file2.tmp;
+remove_file $MYSQLTEST_VARDIR/tmp/file1.tmp;
+remove_file $MYSQLTEST_VARDIR/tmp/file2.tmp;
+
+--error 1
+--exec echo "copy_file ;" | $MYSQL_TEST 2>&1
+
+--error 1
+--exec echo "copy_file from_file;" | $MYSQL_TEST 2>&1
+
+# ----------------------------------------------------------------------------
+# test for perl
+# ----------------------------------------------------------------------------
+--perl
+print "hello\n";
+EOF
+
+--perl EOF
+print "hello\n";
+EOF
+
+--perl DELIMITER
+print "hello\n";
+DELIMITER
+
+--error 1
+--exec echo "perl TOO_LONG_DELIMITER ;" | $MYSQL_TEST 2>&1
+
+perl;
+print "hello\n";
+EOF
+
+perl;
+ # Print "hello"
+ print "hello\n";
+EOF
+
+
+--echo End of tests
diff --git a/mysql-test/t/not_embedded_server-master.opt b/mysql-test/t/not_embedded_server-master.opt
index 35fcc5f30c6..cef79bc8585 100644
--- a/mysql-test/t/not_embedded_server-master.opt
+++ b/mysql-test/t/not_embedded_server-master.opt
@@ -1 +1 @@
---loose-to-force-a-restart
+--force-restart
diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test
index 42fd0426d01..e66dcde71d2 100644
--- a/mysql-test/t/partition.test
+++ b/mysql-test/t/partition.test
@@ -4,6 +4,7 @@
# Taken fromm the select test
#
-- source include/have_partition.inc
+-- source include/have_innodb.inc
#
# This test is disabled on Windows due to BUG#19107
#
@@ -1286,37 +1287,51 @@ eval SET @inx_dir = 'INDEX DIRECTORY = ''$MYSQLTEST_VARDIR/master-data/tmpinx'''
let $inx_directory = `select @inx_dir`;
--enable_query_log
---replace_result $MYSQLTEST_VARDIR "hello"
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval create table t1 (a int) engine myisam
partition by range (a)
subpartition by hash (a)
(partition p0 VALUES LESS THAN (1) $data_directory $inx_directory
(SUBPARTITION subpart00, SUBPARTITION subpart01));
---replace_result $MYSQLTEST_VARDIR "hello"
---exec ls $MYSQLTEST_VARDIR/master-data/test/t1.* || true
---replace_result $MYSQLTEST_VARDIR "hello"
---exec ls $MYSQLTEST_VARDIR/master-data/test/t1#* || true
---replace_result $MYSQLTEST_VARDIR "hello"
---exec ls $MYSQLTEST_VARDIR/master-data/tmpdata/t1#* || true
---replace_result $MYSQLTEST_VARDIR "hello"
---exec ls $MYSQLTEST_VARDIR/master-data/tmpinx/t1#* || true
---replace_result $MYSQLTEST_VARDIR "hello"
-
+--echo Checking if file exists before alter
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1.frm
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1.par
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p0#SP#subpart00.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p0#SP#subpart00.MYI
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p0#SP#subpart01.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p0#SP#subpart01.MYI
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpdata/t1#P#p0#SP#subpart00.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpdata/t1#P#p0#SP#subpart01.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpinx/t1#P#p0#SP#subpart00.MYI
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpinx/t1#P#p0#SP#subpart01.MYI
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval ALTER TABLE t1 REORGANIZE PARTITION p0 INTO
(partition p1 VALUES LESS THAN (1) $data_directory $inx_directory
(SUBPARTITION subpart10, SUBPARTITION subpart11),
partition p2 VALUES LESS THAN (2) $data_directory $inx_directory
(SUBPARTITION subpart20, SUBPARTITION subpart21));
---replace_result $MYSQLTEST_VARDIR "hello"
---exec ls $MYSQLTEST_VARDIR/master-data/test/t1.* || true
---replace_result $MYSQLTEST_VARDIR "hello"
---exec ls $MYSQLTEST_VARDIR/master-data/test/t1#* || true
---replace_result $MYSQLTEST_VARDIR "hello"
---exec ls $MYSQLTEST_VARDIR/master-data/tmpdata/t1#* || true
---replace_result $MYSQLTEST_VARDIR "hello"
---exec ls $MYSQLTEST_VARDIR/master-data/tmpinx/t1#* || true
+--echo Checking if file exists after alter
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1.frm
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1.par
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p1#SP#subpart10.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p1#SP#subpart10.MYI
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p1#SP#subpart11.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p1#SP#subpart11.MYI
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p2#SP#subpart20.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p2#SP#subpart20.MYI
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p2#SP#subpart21.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p2#SP#subpart21.MYI
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpdata/t1#P#p1#SP#subpart10.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpdata/t1#P#p1#SP#subpart11.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpdata/t1#P#p2#SP#subpart20.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpdata/t1#P#p2#SP#subpart21.MYD
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpinx/t1#P#p1#SP#subpart10.MYI
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpinx/t1#P#p1#SP#subpart11.MYI
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpinx/t1#P#p2#SP#subpart20.MYI
+--file_exists $MYSQLTEST_VARDIR/master-data/tmpinx/t1#P#p2#SP#subpart21.MYI
drop table t1;
--exec rmdir $MYSQLTEST_VARDIR/master-data/tmpdata || true
diff --git a/mysql-test/t/ps-master.opt b/mysql-test/t/ps-master.opt
new file mode 100644
index 00000000000..3eb98fc3d6b
--- /dev/null
+++ b/mysql-test/t/ps-master.opt
@@ -0,0 +1 @@
+--log-slow-queries --log-long-format --log-queries-not-using-indexes
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index ac79dbc3434..62e2e9e8dd9 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -354,14 +354,14 @@ create table t1 (a int, b int);
insert into t1 (a, b) values (1,1), (1,2), (2,1), (2,2);
prepare stmt from
"explain select * from t1 where t1.a=2 and t1.a=t1.b and t1.b > 1 + ?";
---replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
set @v=5;
-execute stmt using @v;
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
-set @v=0;
execute stmt using @v;
+set @v=0;
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
+execute stmt using @v;
set @v=5;
+--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
execute stmt using @v;
drop table t1;
deallocate prepare stmt;
@@ -1437,6 +1437,20 @@ DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;
+#
+# Bug 19764: SHOW commands end up in the slow log as table scans
+#
+
+flush status;
+prepare sq from 'show status like "slow_queries"';
+execute sq;
+prepare no_index from 'select 1 from information_schema.tables limit 1';
+execute sq;
+execute no_index;
+execute sq;
+deallocate prepare no_index;
+deallocate prepare sq;
+
--echo End of 5.0 tests.
#
@@ -1447,13 +1461,15 @@ create procedure proc_1() reset query cache;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
delimiter |;
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin reset query cache; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
drop function func_1;
+drop procedure proc_1;
prepare abc from "reset query cache";
execute abc;
execute abc;
@@ -1462,13 +1478,15 @@ deallocate prepare abc;
create procedure proc_1() reset master;
-drop procedure proc_1;
delimiter |;
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin reset master; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
drop function func_1;
+drop procedure proc_1;
prepare abc from "reset master";
execute abc;
execute abc;
@@ -1480,13 +1498,15 @@ create procedure proc_1() reset slave;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
delimiter |;
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin reset slave; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
drop function func_1;
+drop procedure proc_1;
prepare abc from "reset slave";
execute abc;
execute abc;
@@ -1527,15 +1547,15 @@ call proc_1();
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush hosts; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
---error ER_SP_DOES_NOT_EXIST
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
drop function func_1;
+drop procedure proc_1;
prepare abc from "flush hosts";
execute abc;
execute abc;
@@ -1547,15 +1567,15 @@ create procedure proc_1() flush privileges;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush privileges; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
---error ER_SP_DOES_NOT_EXIST
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
drop function func_1;
+drop procedure proc_1;
prepare abc from "flush privileges";
deallocate prepare abc;
@@ -1567,11 +1587,15 @@ call proc_1();
unlock tables;
call proc_1();
unlock tables;
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush tables with read lock; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
+select func_1(), func_1(), func_1() from dual;
+drop function func_1;
+drop procedure proc_1;
prepare abc from "flush tables with read lock";
execute abc;
execute abc;
@@ -1584,15 +1608,15 @@ create procedure proc_1() flush tables;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush tables; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
---error ER_SP_DOES_NOT_EXIST
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
drop function func_1;
+drop procedure proc_1;
prepare abc from "flush tables";
execute abc;
execute abc;
@@ -1622,15 +1646,15 @@ select Host, User from mysql.user limit 0;
select Host, Db from mysql.host limit 0;
show open tables from mysql;
flush tables;
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush tables; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
---error ER_SP_DOES_NOT_EXIST
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
drop function func_1;
+drop procedure proc_1;
flush tables;
select Host, User from mysql.user limit 0;
select Host, Db from mysql.host limit 0;
@@ -1659,15 +1683,15 @@ create procedure proc_1() flush logs;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush logs; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
---error ER_SP_DOES_NOT_EXIST
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
drop function func_1;
+drop procedure proc_1;
prepare abc from "flush logs";
execute abc;
execute abc;
@@ -1679,15 +1703,15 @@ create procedure proc_1() flush status;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush status; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
---error ER_SP_DOES_NOT_EXIST
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
drop function func_1;
+drop procedure proc_1;
prepare abc from "flush status";
execute abc;
execute abc;
@@ -1699,15 +1723,15 @@ create procedure proc_1() flush slave;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush slave; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
---error ER_SP_DOES_NOT_EXIST
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
drop function func_1;
+drop procedure proc_1;
prepare abc from "flush slave";
execute abc;
execute abc;
@@ -1716,15 +1740,15 @@ deallocate prepare abc;
create procedure proc_1() flush master;
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush master; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
---error ER_SP_DOES_NOT_EXIST
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
drop function func_1;
+drop procedure proc_1;
prepare abc from "flush master";
deallocate prepare abc;
@@ -1733,15 +1757,15 @@ create procedure proc_1() flush des_key_file;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush des_key_file; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
---error ER_SP_DOES_NOT_EXIST
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
drop function func_1;
+drop procedure proc_1;
prepare abc from "flush des_key_file";
execute abc;
execute abc;
@@ -1753,15 +1777,15 @@ create procedure proc_1() flush user_resources;
call proc_1();
call proc_1();
call proc_1();
-drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush user_resources; return 1; end|
+create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
---error ER_SP_DOES_NOT_EXIST
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
drop function func_1;
+drop procedure proc_1;
prepare abc from "flush user_resources";
execute abc;
execute abc;
@@ -1865,22 +1889,6 @@ execute abc;
deallocate prepare abc;
-create procedure proc_1() show scheduler status;
-drop procedure proc_1;
-delimiter |;
---error ER_SP_NO_RETSET
-create function func_1() returns int begin show scheduler status; return 1; end|
-delimiter ;|
---error ER_SP_DOES_NOT_EXIST
-select func_1(), func_1(), func_1() from dual;
---error ER_SP_DOES_NOT_EXIST
-drop function func_1;
---error ER_UNSUPPORTED_PS
-prepare abc from "show scheduler status";
---error ER_UNKNOWN_STMT_HANDLER
-deallocate prepare abc;
-
-
--disable_warnings
drop procedure if exists a;
--enable_warnings
@@ -1997,10 +2005,13 @@ call proc_1();
call proc_1();
drop procedure proc_1;
create procedure proc_1() install plugin my_plug soname 'some_plugin.so';
+--replace_regex /(Can\'t open shared library).*$/\1/
--error ER_CANT_OPEN_LIBRARY
call proc_1();
+--replace_regex /(Can\'t open shared library).*$/\1/
--error ER_CANT_OPEN_LIBRARY
call proc_1();
+--replace_regex /(Can\'t open shared library).*$/\1/
--error ER_CANT_OPEN_LIBRARY
call proc_1();
drop procedure proc_1;
@@ -2150,7 +2161,7 @@ drop event if exists xyz;
#drop event xyz;
#drop procedure proc_1;
delimiter |;
---error ER_SP_NO_RETSET
+--error ER_EVENT_RECURSIVITY_FORBIDDEN
create function func_1() returns int begin create event xyz on schedule at now() do select 123; return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
diff --git a/mysql-test/t/ps_11bugs.test b/mysql-test/t/ps_11bugs.test
index ff1c87f3bd8..515bcc03c1a 100644
--- a/mysql-test/t/ps_11bugs.test
+++ b/mysql-test/t/ps_11bugs.test
@@ -144,3 +144,37 @@ prepare st_18492 from 'select * from t1 where 3 in (select (1+1) union select 1)
execute st_18492;
drop table t1;
+
+#
+# Bug#19356: Assertion failure with undefined @uservar in prepared statement execution
+#
+create table t1 (a int, b varchar(4));
+create table t2 (a int, b varchar(4), primary key(a));
+
+prepare stmt1 from 'insert into t1 (a, b) values (?, ?)';
+prepare stmt2 from 'insert into t2 (a, b) values (?, ?)';
+
+set @intarg= 11;
+set @varchararg= '2222';
+execute stmt1 using @intarg, @varchararg;
+execute stmt2 using @intarg, @varchararg;
+set @intarg= 12;
+execute stmt1 using @intarg, @UNDEFINED;
+execute stmt2 using @intarg, @UNDEFINED;
+set @intarg= 13;
+execute stmt1 using @UNDEFINED, @varchararg;
+--error 1048
+execute stmt2 using @UNDEFINED, @varchararg;
+set @intarg= 14;
+set @nullarg= Null;
+execute stmt1 using @UNDEFINED, @nullarg;
+--error 1048
+execute stmt2 using @nullarg, @varchararg;
+
+select * from t1;
+select * from t2;
+
+drop table t1;
+drop table t2;
+
+--echo End of 5.0 tests.
diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test
index c0b81796731..4c0f411c758 100644
--- a/mysql-test/t/ps_1general.test
+++ b/mysql-test/t/ps_1general.test
@@ -316,8 +316,8 @@ prepare stmt4 from ' show table status from test like ''t9%'' ';
--replace_column 8 # 12 # 13 # 14 #
# Bug#4288
execute stmt4;
---replace_column 2 #
prepare stmt4 from ' show status like ''Threads_running'' ';
+--replace_column 2 #
execute stmt4;
prepare stmt4 from ' show variables like ''sql_mode'' ';
execute stmt4;
diff --git a/mysql-test/t/ps_grant.test b/mysql-test/t/ps_grant.test
index 4c48b4d151f..b25facdb418 100644
--- a/mysql-test/t/ps_grant.test
+++ b/mysql-test/t/ps_grant.test
@@ -35,7 +35,7 @@ use mysqltest;
--source include/ps_create.inc
--source include/ps_renew.inc
--enable_query_log
-eval use $DB;
+use test;
grant usage on mysqltest.* to second_user@localhost
identified by 'looser' ;
grant select on mysqltest.t9 to second_user@localhost
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 2c94fe63c04..67c4c4cb20b 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -699,7 +699,7 @@ select a from t1;
flush query cache;
drop table t1, t2;
-set GLOBAL query_cache_size=1355776
+set GLOBAL query_cache_size=1355776;
#
diff --git a/mysql-test/t/rpl_slave_status.test b/mysql-test/t/rpl_slave_status.test
index a4a276b63d6..f98cc7a7d14 100644
--- a/mysql-test/t/rpl_slave_status.test
+++ b/mysql-test/t/rpl_slave_status.test
@@ -19,7 +19,7 @@ start slave;
connection master;
--disable_warnings
drop table if exists t1;
---enable_warning
+--enable_warnings
create table t1 (n int);
insert into t1 values (1);
save_master_pos;
diff --git a/mysql-test/t/rpl_truncate_7ndb.test b/mysql-test/t/rpl_truncate_7ndb.test
index b0d4bdfc763..1d69eee5dd0 100644
--- a/mysql-test/t/rpl_truncate_7ndb.test
+++ b/mysql-test/t/rpl_truncate_7ndb.test
@@ -39,6 +39,7 @@ SELECT * FROM t1 ORDER BY a,b;
--echo **** On Master ****
connection master;
DROP TABLE t1;
+let SERVER_VERSION=`select version()`;
--replace_regex /\/\* xid=[0-9]+ \*\//\/* xid= *\// /table_id: [0-9]+/table_id: #/
--replace_result $SERVER_VERSION SERVER_VERSION
SHOW BINLOG EVENTS;
diff --git a/mysql-test/t/show_check-master.opt b/mysql-test/t/show_check-master.opt
new file mode 100644
index 00000000000..3eb98fc3d6b
--- /dev/null
+++ b/mysql-test/t/show_check-master.opt
@@ -0,0 +1 @@
+--log-slow-queries --log-long-format --log-queries-not-using-indexes
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index 553b3d9059b..7d4ad099e6f 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -501,7 +501,19 @@ SHOW TABLES FROM no_such_database;
--error ER_NO_SUCH_TABLE
SHOW COLUMNS FROM no_such_table;
-# End of 5.0 tests.
+
+#
+# Bug #19764: SHOW commands end up in the slow log as table scans
+#
+flush status;
+show status like 'slow_queries';
+show tables;
+show status like 'slow_queries';
+# Table scan query, to ensure that slow_queries does still get incremented
+# (mysqld is started with --log-queries-not-using-indexes)
+select 1 from information_schema.tables limit 1;
+show status like 'slow_queries';
+
--echo End of 5.0 tests.
--disable_result_log
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index e829a71c45a..2c85c6ae643 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -319,7 +319,7 @@ begin
declare x int;
end|
---error 1332
+--error 1332
create procedure p()
begin
declare c condition for 1064;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index b3563e21bdd..14c5bb00cee 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -2940,11 +2940,11 @@ begin
end|
--disable_parsing
--replace_regex /table_id: [0-9]+/table_id: #/
-show binlog events;
-show storage engines;
-show master status;
-show slave hosts;
-show slave status;
+show binlog events|
+show storage engines|
+show master status|
+show slave hosts|
+show slave status|
--enable_parsing
call bug4902()|
diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test
index 28abf448089..6335ad55606 100644
--- a/mysql-test/t/sp_notembedded.test
+++ b/mysql-test/t/sp_notembedded.test
@@ -19,11 +19,11 @@ begin
show grants for 'root'@'localhost';
end|
--disable_parsing
-show binlog events;
-show storage engines;
-show master status;
-show slave hosts;
-show slave status;
+show binlog events|
+show storage engines|
+show master status|
+show slave hosts|
+show slave status|
--enable_parsing
call bug4902()|
@@ -110,7 +110,7 @@ flush status|
flush query cache|
delete from t1|
drop procedure bug3583|
-drop table t1;
+drop table t1|
#
# BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 7811301a9bc..d357b983703 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1728,7 +1728,7 @@ select (select a from t1) = (1,2);
select (1,2,3) = (select * from t1);
-- error 1241
select (select * from t1) = (1,2,3);
-drop table t1
+drop table t1;
#
# Item_int_with_ref check (BUG#10020)
diff --git a/mysql-test/t/system_mysql_db_fix.test b/mysql-test/t/system_mysql_db_fix.test
index daba3b6ff86..3956e26e9cc 100644
--- a/mysql-test/t/system_mysql_db_fix.test
+++ b/mysql-test/t/system_mysql_db_fix.test
@@ -42,7 +42,7 @@ CREATE TABLE db (
KEY User (User)
)
engine=MyISAM;
---enable-warnings
+--enable_warnings
INSERT INTO db VALUES ('%','test', '','Y','Y','Y','Y','Y','Y');
INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y');
@@ -60,7 +60,7 @@ CREATE TABLE host (
PRIMARY KEY Host (Host,Db)
)
engine=MyISAM;
---enable-warnings
+--enable_warnings
--disable_warnings
CREATE TABLE user (
@@ -79,7 +79,7 @@ CREATE TABLE user (
PRIMARY KEY Host (Host,User)
)
engine=MyISAM;
---enable-warnings
+--enable_warnings
INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y');
INSERT INTO user VALUES ('localhost','', '','N','N','N','N','N','N','N','N','N');
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index 644ca506eba..65ca1b2c1b7 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -144,6 +144,8 @@ select @@version;
--replace_column 1 #
select @@global.version;
+--echo End of 4.1 tests
+
# Bug #6598: problem with cast(NULL as signed integer);
#
@@ -210,4 +212,10 @@ select @var:=f2 from t1 group by f1 order by f2 desc limit 1;
select @var;
drop table t1;
-# End of 4.1 tests
+#
+# Bug#19024 - SHOW COUNT(*) WARNINGS not return Errors
+#
+--error 1064
+insert into city 'blah';
+SHOW COUNT(*) WARNINGS;
+SHOW COUNT(*) ERRORS;
diff --git a/mysql-test/t/wait_timeout.test b/mysql-test/t/wait_timeout.test
index dbd792e48d8..bdff72cdc76 100644
--- a/mysql-test/t/wait_timeout.test
+++ b/mysql-test/t/wait_timeout.test
@@ -55,7 +55,7 @@ select 2;
select 3;
# Disconnect so that we will not be confused by a future abort from this
# connection.
-disconnect default
+disconnect default;
#
# Do the same test as above on a TCP connection
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index 4aa99a70121..7b362b4c1f9 100644
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -20,7 +20,7 @@ ADD_LIBRARY(mysys array.c charset-def.c charset.c checksum.c default.c default_m
my_clock.c my_compress.c my_conio.c my_copy.c my_crc32.c my_create.c my_delete.c
my_div.c my_error.c my_file.c my_fopen.c my_fstream.c my_gethostbyname.c
my_gethwaddr.c my_getopt.c my_getsystime.c my_getwd.c my_handler.c my_init.c
- my_lib.c my_lock.c my_lockmem.c my_lread.c my_lwrite.c my_malloc.c my_messnc.c
+ my_lib.c my_lock.c my_lockmem.c my_malloc.c my_messnc.c
my_mkdir.c my_mmap.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c
my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_sleep.c
my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index b209d64e78f..79d79d41c34 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -43,7 +43,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
tree.c trie.c list.c hash.c array.c string.c typelib.c \
my_copy.c my_append.c my_lib.c \
my_delete.c my_rename.c my_redel.c \
- my_chsize.c my_lread.c my_lwrite.c my_clock.c \
+ my_chsize.c my_clock.c \
my_quick.c my_lockmem.c my_static.c \
my_sync.c my_getopt.c my_mkdir.c \
default_modify.c default.c \
diff --git a/mysys/charset.c b/mysys/charset.c
index 64b15fab0c2..d10a580ae4e 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -312,7 +312,7 @@ static my_bool my_read_charset_file(const char *filename, myf myflags)
{
char *buf;
int fd;
- uint len;
+ uint len, tmp_len;
MY_STAT stat_info;
if (!my_stat(filename, &stat_info, MYF(myflags)) ||
@@ -321,12 +321,11 @@ static my_bool my_read_charset_file(const char *filename, myf myflags)
return TRUE;
if ((fd=my_open(filename,O_RDONLY,myflags)) < 0)
- {
- my_free(buf,myflags);
- return TRUE;
- }
- len=read(fd,buf,len);
+ goto error;
+ tmp_len=my_read(fd, buf, len, myflags);
my_close(fd,myflags);
+ if (tmp_len != len)
+ goto error;
if (my_parse_charset_xml(buf,len,add_collation))
{
@@ -340,6 +339,10 @@ static my_bool my_read_charset_file(const char *filename, myf myflags)
my_free(buf, myflags);
return FALSE;
+
+error:
+ my_free(buf, myflags);
+ return TRUE;
}
diff --git a/mysys/make-ccc b/mysys/make-ccc
index 9c54185682a..b34bd80e1d1 100755
--- a/mysys/make-ccc
+++ b/mysys/make-ccc
@@ -1,4 +1,4 @@
rm -f .deps/* raid.o mf_iocache.o libmysys.a
-ccc -DDEFAULT_BASEDIR="\"/usr/local/mysql\"" -DDATADIR="\"/usr/local/mysql/var\"" -DHAVE_CONFIG_H -I./../include -I../include -I.. -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c array.c checksum.c default.c errors.c getopt.c getopt1.c getvar.c hash.c list.c mf_brkhant.c mf_cache.c mf_casecnv.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_keycache.c mf_loadpath.c mf_pack.c mf_pack2.c mf_path.c mf_qsort.c mf_qsort2.c mf_radix.c mf_reccache.c mf_same.c mf_sort.c mf_soundex.c mf_stripp.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_alarm.c my_alloc.c my_append.c my_chsize.c my_clock.c my_compress.c my_copy.c my_create.c my_delete.c my_div.c my_error.c my_fopen.c my_fstream.c my_getwd.c my_init.c my_lib.c my_lockmem.c my_lread.c my_lwrite.c my_malloc.c my_messnc.c my_mkdir.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_static.c my_tempnam.c my_thr_init.c my_write.c ptr_cmp.c queues.c safemalloc.c string.c thr_alarm.c thr_lock.c thr_mutex.c thr_rwlock.c tree.c typelib.c
+ccc -DDEFAULT_BASEDIR="\"/usr/local/mysql\"" -DDATADIR="\"/usr/local/mysql/var\"" -DHAVE_CONFIG_H -I./../include -I../include -I.. -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c array.c checksum.c default.c errors.c getopt.c getopt1.c getvar.c hash.c list.c mf_brkhant.c mf_cache.c mf_casecnv.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_keycache.c mf_loadpath.c mf_pack.c mf_pack2.c mf_path.c mf_qsort.c mf_qsort2.c mf_radix.c mf_reccache.c mf_same.c mf_sort.c mf_soundex.c mf_stripp.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_alarm.c my_alloc.c my_append.c my_chsize.c my_clock.c my_compress.c my_copy.c my_create.c my_delete.c my_div.c my_error.c my_fopen.c my_fstream.c my_getwd.c my_init.c my_lib.c my_lockmem.c my_malloc.c my_messnc.c my_mkdir.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_static.c my_tempnam.c my_thr_init.c my_write.c ptr_cmp.c queues.c safemalloc.c string.c thr_alarm.c thr_lock.c thr_mutex.c thr_rwlock.c tree.c typelib.c
make raid.o mf_iocache.o my_lock.o
ar -cr libmysys.a array.o raid.o mf_iocache.o my_lock.o
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index cd2a140182e..eb8b992c601 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -333,7 +333,11 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
{
info->read_end=info->write_pos;
info->end_of_file=my_b_tell(info);
- info->seek_not_done=1;
+ /*
+ Trigger a new seek only if we have a valid
+ file handle.
+ */
+ info->seek_not_done= (info->file != -1);
}
else if (type == WRITE_CACHE)
{
diff --git a/mysys/my_lread.c b/mysys/my_lread.c
deleted file mode 100644
index 601d772b844..00000000000
--- a/mysys/my_lread.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright (C) 2000 MySQL 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program 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 General Public License for more details.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "mysys_priv.h"
-#include "mysys_err.h"
-
- /* Read a chunk of bytes from a file */
-
-uint32 my_lread(int Filedes, byte *Buffer, uint32 Count, myf MyFlags)
- /* File descriptor */
- /* Buffer must be at least count bytes */
- /* Max number of bytes returnd */
- /* Flags on what to do on error */
-{
- uint32 readbytes;
- DBUG_ENTER("my_lread");
- DBUG_PRINT("my",("Fd: %d Buffer: %ld Count: %ld MyFlags: %d",
- Filedes, Buffer, Count, MyFlags));
-
- /* Temp hack to get count to int32 while read wants int */
- if ((readbytes = (uint32) read(Filedes, Buffer, (uint) Count)) != Count)
- {
- my_errno=errno;
- if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
- {
- if (readbytes == MY_FILE_ERROR)
- my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
- my_filename(Filedes),errno);
- else
- if (MyFlags & (MY_NABP | MY_FNABP))
- my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
- my_filename(Filedes),errno);
- }
- if (readbytes == MY_FILE_ERROR || MyFlags & (MY_NABP | MY_FNABP))
- DBUG_RETURN((uint32) -1); /* Return med felkod */
- }
- if (MyFlags & (MY_NABP | MY_FNABP))
- DBUG_RETURN(0); /* Ok vid l{sning */
- DBUG_RETURN(readbytes);
-} /* my_lread */
diff --git a/mysys/my_lwrite.c b/mysys/my_lwrite.c
deleted file mode 100644
index 3b9afdbd71f..00000000000
--- a/mysys/my_lwrite.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (C) 2000 MySQL 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program 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 General Public License for more details.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "mysys_priv.h"
-#include "mysys_err.h"
-
- /* Write a chunk of bytes to a file */
-
-uint32 my_lwrite(int Filedes, const byte *Buffer, uint32 Count, myf MyFlags)
-{
- uint32 writenbytes;
- DBUG_ENTER("my_lwrite");
- DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %ld MyFlags: %d",
- Filedes, Buffer, Count, MyFlags));
-
- /* Temp hack to get count to int32 while write wants int */
- if ((writenbytes = (uint32) write(Filedes, Buffer, (uint) Count)) != Count)
- {
- my_errno=errno;
- if (writenbytes == (uint32) -1 || MyFlags & (MY_NABP | MY_FNABP))
- {
- if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
- {
- my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG),
- my_filename(Filedes),errno);
- }
- DBUG_RETURN((uint32) -1); /* Return med felkod */
- }
- }
- if (MyFlags & (MY_NABP | MY_FNABP))
- DBUG_RETURN(0); /* Ok vid l{sning */
- DBUG_RETURN(writenbytes);
-} /* my_lwrite */
diff --git a/mysys/my_pread.c b/mysys/my_pread.c
index 978366e57e5..45a4a363c0a 100644
--- a/mysys/my_pread.c
+++ b/mysys/my_pread.c
@@ -75,8 +75,12 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d",
readbytes,Count,Filedes,my_errno));
#ifdef THREAD
- if (readbytes == 0 && errno == EINTR)
- continue; /* Interrupted */
+ if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR)
+ {
+ DBUG_PRINT("debug", ("my_pread() was interrupted and returned %d",
+ (int) readbytes));
+ continue; /* Interrupted */
+ }
#endif
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
@@ -170,8 +174,8 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC));
continue;
}
- if ((writenbytes == 0 && my_errno == EINTR) ||
- (writenbytes > 0 && (uint) writenbytes != (uint) -1))
+ if ((writenbytes > 0 && (uint) writenbytes != (uint) -1) ||
+ my_errno == EINTR)
continue; /* Retry */
#endif
if (MyFlags & (MY_NABP | MY_FNABP))
diff --git a/mysys/my_quick.c b/mysys/my_quick.c
index 44ed3fc0b2c..ffc8160c371 100644
--- a/mysys/my_quick.c
+++ b/mysys/my_quick.c
@@ -26,6 +26,14 @@ uint my_quick_read(File Filedes,byte *Buffer,uint Count,myf MyFlags)
if ((readbytes = (uint) read(Filedes, Buffer, Count)) != Count)
{
+#ifndef DBUG_OFF
+ if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR)
+ {
+ DBUG_PRINT("error", ("my_quick_read() was interrupted and returned %d"
+ ". This function does not retry the read!",
+ (int) readbytes));
+ }
+#endif
my_errno=errno;
return readbytes;
}
@@ -35,8 +43,24 @@ uint my_quick_read(File Filedes,byte *Buffer,uint Count,myf MyFlags)
uint my_quick_write(File Filedes,const byte *Buffer,uint Count)
{
- if ((uint) write(Filedes,Buffer,Count) != Count)
+#ifndef DBUG_OFF
+ uint writtenbytes;
+#endif
+
+ if ((
+#ifndef DBUG_OFF
+ writtenbytes =
+#endif
+ (uint) write(Filedes,Buffer,Count)) != Count)
{
+#ifndef DBUG_OFF
+ if ((writtenbytes == 0 || (int) writtenbytes == -1) && errno == EINTR)
+ {
+ DBUG_PRINT("error", ("my_quick_write() was interrupted and returned %d"
+ ". This function does not retry the write!",
+ (int) writtenbytes));
+ }
+#endif
my_errno=errno;
return (uint) -1;
}
diff --git a/mysys/my_read.c b/mysys/my_read.c
index 2e23f2175f8..8b88e483fef 100644
--- a/mysys/my_read.c
+++ b/mysys/my_read.c
@@ -51,10 +51,11 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags)
DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d",
readbytes, Count, Filedes, my_errno));
#ifdef THREAD
- if ((int) readbytes <= 0 && errno == EINTR)
- {
- DBUG_PRINT("debug", ("my_read() was interrupted and returned %d", (int) readbytes));
- continue; /* Interrupted */
+ if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR)
+ {
+ DBUG_PRINT("debug", ("my_read() was interrupted and returned %d",
+ (int) readbytes));
+ continue; /* Interrupted */
}
#endif
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
diff --git a/mysys/my_seek.c b/mysys/my_seek.c
index e5b1905e551..239136c4e7c 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -29,8 +29,13 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
whence, MyFlags));
DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */
- if (-1 != fd)
- newpos=lseek(fd, pos, whence);
+ /*
+ Make sure we are using a valid file descriptor!
+ */
+ DBUG_ASSERT(fd != -1);
+
+ newpos= lseek(fd, pos, whence);
+
if (newpos == (os_off_t) -1)
{
my_errno=errno;
diff --git a/mysys/my_write.c b/mysys/my_write.c
index 4e8369480b3..ae8cb4ab02b 100644
--- a/mysys/my_write.c
+++ b/mysys/my_write.c
@@ -57,18 +57,24 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags)
VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC));
continue;
}
- if (!writenbytes)
+
+ if ((writenbytes == 0 || (int) writenbytes == -1))
{
- /* We may come here on an interrupt or if the file quote is exeeded */
if (my_errno == EINTR)
- continue;
- if (!errors++) /* Retry once */
{
- errno=EFBIG; /* Assume this is the error */
- continue;
+ DBUG_PRINT("debug", ("my_write() was interrupted and returned %d",
+ (int) writenbytes));
+ continue; /* Interrupted */
+ }
+
+ if (!writenbytes && !errors++) /* Retry once */
+ {
+ /* We may come here if the file quota is exeeded */
+ errno=EFBIG; /* Assume this is the error */
+ continue;
}
}
- else if ((uint) writenbytes != (uint) -1)
+ else
continue; /* Retry */
#endif
if (MyFlags & (MY_NABP | MY_FNABP))
diff --git a/netware/BUILD/compile-netware-max b/netware/BUILD/compile-netware-max
index ec737d4615c..d8278a4e915 100644..100755
--- a/netware/BUILD/compile-netware-max
+++ b/netware/BUILD/compile-netware-max
@@ -15,7 +15,7 @@ suffix="max"
extra_configs=" \
--with-innodb \
--with-embedded-server \
- --with-openssl \
+ --with-ssl \
"
. $path/compile-netware-END
diff --git a/netware/BUILD/compile-netware-max-debug b/netware/BUILD/compile-netware-max-debug
index ea3553ae6e1..de1b5dd17cc 100644..100755
--- a/netware/BUILD/compile-netware-max-debug
+++ b/netware/BUILD/compile-netware-max-debug
@@ -15,7 +15,7 @@ extra_configs=" \
--with-innodb \
--with-debug=full \
--with-embedded-server \
- --with-openssl \
+ --with-ssl \
"
. $path/compile-netware-END
diff --git a/netware/BUILD/compile-netware-src b/netware/BUILD/compile-netware-src
index f4e8a53ffea..f4e8a53ffea 100644..100755
--- a/netware/BUILD/compile-netware-src
+++ b/netware/BUILD/compile-netware-src
diff --git a/netware/BUILD/mwenv b/netware/BUILD/mwenv
index d8d53293b2c..c3869d2ec90 100755
--- a/netware/BUILD/mwenv
+++ b/netware/BUILD/mwenv
@@ -26,8 +26,17 @@ WINE_BUILD_DIR=`echo "$BUILD_DIR" | sed 's_'$base_unix_part'/__'`
WINE_BUILD_DIR="$base/$WINE_BUILD_DIR"
echo "WINE_BUILD_DIR: $WINE_BUILD_DIR"
-export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.2.3;$WINE_BUILD_DIR/include;$MYDEV"
-export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.2.3;$MYDEV/openssl;$WINE_BUILD_DIR/netware/BUILD"
+# Look for libc, MySQL 5.1.x uses libc-2006 by default
+libcdir="$MYDEV/libc-2006"
+if test ! -d $libcdir
+then
+ # The libcdir didn't exist, set default
+ libc_dir="$MYDEV/libc"
+fi
+echo "Using libc in $libc_dir";
+
+export MWCNWx86Includes="$libc_dir/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.2.3;$WINE_BUILD_DIR/include;$MYDEV"
+export MWNWx86Libraries="$libc_dir/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.2.3;$MYDEV/openssl;$WINE_BUILD_DIR/netware/BUILD"
export MWNWx86LibraryFiles="libcpre.o;libc.imp;netware.imp;mwcrtl.lib;mwcpp.lib;libz.a;neb.imp;zPublics.imp;knetware.imp"
export WINEPATH="$MYDEV/mw/bin"
@@ -46,3 +55,15 @@ export LD='mwldnlm'
export LDFLAGS='-entry _LibCPrelude -exit _LibCPostlude -map -flags pseudopreemption'
export RANLIB=:
export STRIP=:
+
+#
+# Check that TERM has been set to avoid problem "Error opening
+# terminal: unknown" when the script is executed using non interactive ssh
+#
+if test -z "$TERM" -o "$TERM"=dumb
+then
+ export TERM=linux
+fi
+
+# Print all env. variables
+export
diff --git a/sql-common/client.c b/sql-common/client.c
index 79a5be938b2..b6947028e74 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -2364,6 +2364,8 @@ my_bool mysql_reconnect(MYSQL *mysql)
{
MYSQL tmp_mysql;
DBUG_ENTER("mysql_reconnect");
+ DBUG_ASSERT(mysql);
+ DBUG_PRINT("enter", ("mysql->reconnect: %d", mysql->reconnect));
if (!mysql->reconnect ||
(mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index b4cfe041529..29de0504468 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -465,8 +465,10 @@ err:
There may be an optional [.second_part] after seconds
length Length of str
l_time Store result here
- was_cut Set to 1 if value was cut during conversion or to 0
- otherwise.
+ warning Set MYSQL_TIME_WARN_TRUNCATED flag if the input string
+ was cut during conversion, and/or
+ MYSQL_TIME_WARN_OUT_OF_RANGE flag, if the value is
+ out of range.
NOTES
Because of the extra days argument, this function can only
@@ -478,15 +480,16 @@ err:
*/
my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
- int *was_cut)
+ int *warning)
{
- long date[5],value;
+ ulong date[5];
+ ulonglong value;
const char *end=str+length, *end_of_days;
my_bool found_days,found_hours;
uint state;
l_time->neg=0;
- *was_cut= 0;
+ *warning= 0;
for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
length--;
if (str != end && *str == '-')
@@ -501,13 +504,16 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
/* Check first if this is a full TIMESTAMP */
if (length >= 12)
{ /* Probably full timestamp */
+ int was_cut;
enum enum_mysql_timestamp_type
res= str_to_datetime(str, length, l_time,
- (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), was_cut);
+ (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut);
if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR)
+ {
+ if (was_cut)
+ *warning|= MYSQL_TIME_WARN_TRUNCATED;
return res == MYSQL_TIMESTAMP_ERROR;
- /* We need to restore was_cut flag since str_to_datetime can modify it */
- *was_cut= 0;
+ }
}
/* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */
@@ -587,7 +593,7 @@ fractional:
if (field_length > 0)
value*= (long) log_10_int[field_length];
else if (field_length < 0)
- *was_cut= 1;
+ *warning|= MYSQL_TIME_WARN_TRUNCATED;
date[4]=value;
}
else
@@ -601,10 +607,7 @@ fractional:
((str[1] == '-' || str[1] == '+') &&
(end - str) > 2 &&
my_isdigit(&my_charset_latin1, str[2]))))
- {
- *was_cut= 1;
return 1;
- }
if (internal_format_positions[7] != 255)
{
@@ -623,12 +626,12 @@ fractional:
}
}
- /* Some simple checks */
- if (date[2] >= 60 || date[3] >= 60)
- {
- *was_cut= 1;
+ /* Integer overflow checks */
+ if (date[0] > UINT_MAX || date[1] > UINT_MAX ||
+ date[2] > UINT_MAX || date[3] > UINT_MAX ||
+ date[4] > UINT_MAX)
return 1;
- }
+
l_time->year= 0; /* For protocol::store_time */
l_time->month= 0;
l_time->day= date[0];
@@ -638,6 +641,10 @@ fractional:
l_time->second_part= date[4];
l_time->time_type= MYSQL_TIMESTAMP_TIME;
+ /* Check if the value is valid and fits into TIME range */
+ if (check_time_range(l_time, warning))
+ return 1;
+
/* Check if there is garbage at end of the TIME specification */
if (str != end)
{
@@ -645,7 +652,7 @@ fractional:
{
if (!my_isspace(&my_charset_latin1,*str))
{
- *was_cut= 1;
+ *warning|= MYSQL_TIME_WARN_TRUNCATED;
break;
}
} while (++str != end);
@@ -655,6 +662,47 @@ fractional:
/*
+ Check 'time' value to lie in the TIME range
+
+ SYNOPSIS:
+ check_time_range()
+ time pointer to TIME value
+ warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range
+
+ DESCRIPTION
+ If the time value lies outside of the range [-838:59:59, 838:59:59],
+ set it to the closest endpoint of the range and set
+ MYSQL_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable.
+
+ RETURN
+ 0 time value is valid, but was possibly truncated
+ 1 time value is invalid
+*/
+
+int check_time_range(struct st_mysql_time *time, int *warning)
+{
+ longlong hour;
+
+ if (time->minute >= 60 || time->second >= 60)
+ return 1;
+
+ hour= time->hour + (24*time->day);
+ if (hour <= TIME_MAX_HOUR &&
+ (hour != TIME_MAX_HOUR || time->minute != TIME_MAX_MINUTE ||
+ time->second != TIME_MAX_SECOND || !time->second_part))
+ return 0;
+
+ time->day= 0;
+ time->hour= TIME_MAX_HOUR;
+ time->minute= TIME_MAX_MINUTE;
+ time->second= TIME_MAX_SECOND;
+ time->second_part= 0;
+ *warning|= MYSQL_TIME_WARN_OUT_OF_RANGE;
+ return 0;
+}
+
+
+/*
Prepare offset of system time zone from UTC for my_system_gmt_sec() func.
SYNOPSIS
@@ -840,7 +888,7 @@ void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type)
int my_time_to_str(const MYSQL_TIME *l_time, char *to)
{
uint extra_hours= 0;
- return my_sprintf(to, (to, "%s%02d:%02d:%02d",
+ return my_sprintf(to, (to, "%s%02u:%02u:%02u",
(l_time->neg ? "-" : ""),
extra_hours+ l_time->hour,
l_time->minute,
@@ -849,7 +897,7 @@ int my_time_to_str(const MYSQL_TIME *l_time, char *to)
int my_date_to_str(const MYSQL_TIME *l_time, char *to)
{
- return my_sprintf(to, (to, "%04d-%02d-%02d",
+ return my_sprintf(to, (to, "%04u-%02u-%02u",
l_time->year,
l_time->month,
l_time->day));
@@ -857,7 +905,7 @@ int my_date_to_str(const MYSQL_TIME *l_time, char *to)
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to)
{
- return my_sprintf(to, (to, "%04d-%02d-%02d %02d:%02d:%02d",
+ return my_sprintf(to, (to, "%04u-%02u-%02u %02u:%02u:%02u",
l_time->year,
l_time->month,
l_time->day,
diff --git a/sql/field.cc b/sql/field.cc
index 09e919d872a..122a44305f2 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4875,9 +4875,10 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
{
TIME ltime;
long tmp;
- int error;
+ int error= 0;
+ int warning;
- if (str_to_time(from, len, &ltime, &error))
+ if (str_to_time(from, len, &ltime, &warning))
{
tmp=0L;
error= 2;
@@ -4886,29 +4887,27 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
}
else
{
- if (error)
+ if (warning & MYSQL_TIME_WARN_TRUNCATED)
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED,
from, len, MYSQL_TIMESTAMP_TIME, 1);
-
- if (ltime.month)
- ltime.day=0;
- tmp=(ltime.day*24L+ltime.hour)*10000L+(ltime.minute*100+ltime.second);
- if (tmp > 8385959)
+ if (warning & MYSQL_TIME_WARN_OUT_OF_RANGE)
{
- tmp=8385959;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
from, len, MYSQL_TIMESTAMP_TIME, !error);
error= 1;
}
+ if (ltime.month)
+ ltime.day=0;
+ tmp=(ltime.day*24L+ltime.hour)*10000L+(ltime.minute*100+ltime.second);
if (error > 1)
error= 2;
}
if (ltime.neg)
tmp= -tmp;
- error |= Field_time::store((longlong) tmp, FALSE);
+ int3store(ptr,tmp);
return error;
}
@@ -4928,16 +4927,16 @@ int Field_time::store(double nr)
ASSERT_COLUMN_MARKED_FOR_WRITE;
long tmp;
int error= 0;
- if (nr > 8385959.0)
+ if (nr > (double)TIME_MAX_VALUE)
{
- tmp=8385959L;
+ tmp= TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr, MYSQL_TIMESTAMP_TIME);
error= 1;
}
- else if (nr < -8385959.0)
+ else if (nr < (double)-TIME_MAX_VALUE)
{
- tmp= -8385959L;
+ tmp= -TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr, MYSQL_TIMESTAMP_TIME);
error= 1;
@@ -4966,17 +4965,17 @@ int Field_time::store(longlong nr, bool unsigned_val)
ASSERT_COLUMN_MARKED_FOR_WRITE;
long tmp;
int error= 0;
- if (nr < (longlong) -8385959L && !unsigned_val)
+ if (nr < (longlong) -TIME_MAX_VALUE && !unsigned_val)
{
- tmp= -8385959L;
+ tmp= -TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr,
MYSQL_TIMESTAMP_TIME, 1);
error= 1;
}
- else if (nr > (longlong) 8385959 || nr < 0 && unsigned_val)
+ else if (nr > (longlong) TIME_MAX_VALUE || nr < 0 && unsigned_val)
{
- tmp=8385959L;
+ tmp= TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr,
MYSQL_TIMESTAMP_TIME, 1);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 7a82dd753b3..bf837f6720b 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2965,6 +2965,7 @@ String *Item_func_compress::val_str(String *str)
null_value= 1;
return 0;
}
+ null_value= 0;
if (res->is_empty()) return res;
/*
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index d32adde5e64..f378e5037dc 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -96,6 +96,125 @@ static bool make_datetime(date_time_format_types format, TIME *ltime,
/*
+ Wrapper over make_datetime() with validation of the input TIME value
+
+ NOTE
+ see make_datetime() for more information
+
+ RETURN
+ 1 if there was an error during converion
+ 0 otherwise
+*/
+
+static bool make_datetime_with_warn(date_time_format_types format, TIME *ltime,
+ String *str)
+{
+ int warning= 0;
+ bool rc;
+
+ if (make_datetime(format, ltime, str))
+ return 1;
+ if (check_time_range(ltime, &warning))
+ return 1;
+ if (!warning)
+ return 0;
+
+ make_truncated_value_warning(current_thd, str->ptr(), str->length(),
+ MYSQL_TIMESTAMP_TIME, NullS);
+ return make_datetime(format, ltime, str);
+}
+
+
+/*
+ Wrapper over make_time() with validation of the input TIME value
+
+ NOTE
+ see make_time() for more info
+
+ RETURN
+ 1 if there was an error during conversion
+ 0 otherwise
+*/
+
+static bool make_time_with_warn(const DATE_TIME_FORMAT *format,
+ TIME *l_time, String *str)
+{
+ int warning= 0;
+ make_time(format, l_time, str);
+ if (check_time_range(l_time, &warning))
+ return 1;
+ if (warning)
+ {
+ make_truncated_value_warning(current_thd, str->ptr(), str->length(),
+ MYSQL_TIMESTAMP_TIME, NullS);
+ make_time(format, l_time, str);
+ }
+
+ return 0;
+}
+
+
+/*
+ Convert seconds to TIME value with overflow checking
+
+ SYNOPSIS:
+ sec_to_time()
+ seconds number of seconds
+ unsigned_flag 1, if 'seconds' is unsigned, 0, otherwise
+ ltime output TIME value
+
+ DESCRIPTION
+ If the 'seconds' argument is inside TIME data range, convert it to a
+ corresponding value.
+ Otherwise, truncate the resulting value to the nearest endpoint, and
+ produce a warning message.
+
+ RETURN
+ 1 if the value was truncated during conversion
+ 0 otherwise
+*/
+
+static bool sec_to_time(longlong seconds, bool unsigned_flag, TIME *ltime)
+{
+ uint sec;
+
+ bzero((char *)ltime, sizeof(*ltime));
+
+ if (seconds < 0)
+ {
+ if (unsigned_flag)
+ goto overflow;
+ ltime->neg= 1;
+ if (seconds < -3020399)
+ goto overflow;
+ seconds= -seconds;
+ }
+ else if (seconds > 3020399)
+ goto overflow;
+
+ sec= (uint) ((ulonglong) seconds % 3600);
+ ltime->hour= (uint) (seconds/3600);
+ ltime->minute= sec/60;
+ ltime->second= sec % 60;
+
+ return 0;
+
+overflow:
+ ltime->hour= TIME_MAX_HOUR;
+ ltime->minute= TIME_MAX_MINUTE;
+ ltime->second= TIME_MAX_SECOND;
+
+ char buf[22];
+ int len= (int)(longlong10_to_str(seconds, buf, unsigned_flag ? 10 : -10)
+ - buf);
+ make_truncated_value_warning(current_thd, buf, len, MYSQL_TIMESTAMP_TIME,
+ NullS);
+
+ return 1;
+}
+
+
+/*
Date formats corresponding to compound %r and %T conversion specifiers
Note: We should init at least first element of "positions" array
@@ -1546,8 +1665,6 @@ int Item_func_sysdate_local::save_in_field(Field *to, bool no_conversions)
String *Item_func_sec_to_time::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- longlong seconds=(longlong) args[0]->val_int();
- uint sec;
TIME ltime;
if ((null_value=args[0]->null_value) || str->alloc(19))
@@ -1556,19 +1673,8 @@ String *Item_func_sec_to_time::val_str(String *str)
return (String*) 0;
}
- ltime.neg= 0;
- if (seconds < 0)
- {
- seconds= -seconds;
- ltime.neg= 1;
- }
-
- sec= (uint) ((ulonglong) seconds % 3600);
- ltime.day= 0;
- ltime.hour= (uint) (seconds/3600);
- ltime.minute= sec/60;
- ltime.second= sec % 60;
-
+ sec_to_time(args[0]->val_int(), args[0]->unsigned_flag, &ltime);
+
make_time((DATE_TIME_FORMAT *) 0, &ltime, str);
return str;
}
@@ -1577,16 +1683,15 @@ String *Item_func_sec_to_time::val_str(String *str)
longlong Item_func_sec_to_time::val_int()
{
DBUG_ASSERT(fixed == 1);
- longlong seconds=args[0]->val_int();
- longlong sign=1;
+ TIME ltime;
+
if ((null_value=args[0]->null_value))
return 0;
- if (seconds < 0)
- {
- seconds= -seconds;
- sign= -1;
- }
- return sign*((seconds / 3600)*10000+((seconds/60) % 60)*100+ (seconds % 60));
+
+ sec_to_time(args[0]->val_int(), args[0]->unsigned_flag, &ltime);
+
+ return (ltime.neg ? -1 : 1) *
+ ((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
}
@@ -2030,11 +2135,15 @@ bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
(date_sub_interval == other->date_sub_interval));
}
+/*
+ 'interval_names' reflects the order of the enumeration interval_type.
+ See item_timefunc.h
+ */
static const char *interval_names[]=
{
- "year", "quarter", "month", "day", "hour",
- "minute", "week", "second", "microsecond",
+ "year", "quarter", "month", "week", "day",
+ "hour", "minute", "second", "microsecond",
"year_month", "day_hour", "day_minute",
"day_second", "hour_minute", "hour_second",
"minute_second", "day_microsecond",
@@ -2571,7 +2680,9 @@ String *Item_func_add_time::val_str(String *str)
}
if (l_time1.neg != l_time2.neg)
l_sign= -l_sign;
-
+
+ bzero((char *)&l_time3, sizeof(l_time3));
+
l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
&seconds, &microseconds);
@@ -2600,9 +2711,9 @@ String *Item_func_add_time::val_str(String *str)
}
l_time3.hour+= days*24;
- if (!make_datetime(l_time1.second_part || l_time2.second_part ?
- TIME_MICROSECOND : TIME_ONLY,
- &l_time3, str))
+ if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY,
+ &l_time3, str))
return str;
null_date:
@@ -2657,6 +2768,8 @@ String *Item_func_timediff::val_str(String *str)
if (l_time1.neg != l_time2.neg)
l_sign= -l_sign;
+ bzero((char *)&l_time3, sizeof(l_time3));
+
l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
&seconds, &microseconds);
@@ -2670,9 +2783,9 @@ String *Item_func_timediff::val_str(String *str)
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
- if (!make_datetime(l_time1.second_part || l_time2.second_part ?
- TIME_MICROSECOND : TIME_ONLY,
- &l_time3, str))
+ if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY,
+ &l_time3, str))
return str;
null_date:
@@ -2690,29 +2803,58 @@ String *Item_func_maketime::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
+ bool overflow= 0;
- long hour= (long) args[0]->val_int();
- long minute= (long) args[1]->val_int();
- long second= (long) args[2]->val_int();
+ longlong hour= args[0]->val_int();
+ longlong minute= args[1]->val_int();
+ longlong second= args[2]->val_int();
if ((null_value=(args[0]->null_value ||
- args[1]->null_value ||
- args[2]->null_value ||
- minute > 59 || minute < 0 ||
- second > 59 || second < 0 ||
- str->alloc(19))))
+ args[1]->null_value ||
+ args[2]->null_value ||
+ minute < 0 || minute > 59 ||
+ second < 0 || second > 59 ||
+ str->alloc(19))))
return 0;
+ bzero((char *)&ltime, sizeof(ltime));
ltime.neg= 0;
+
+ /* Check for integer overflows */
if (hour < 0)
{
- ltime.neg= 1;
- hour= -hour;
+ if (args[0]->unsigned_flag)
+ overflow= 1;
+ else
+ ltime.neg= 1;
+ }
+ if (-hour > UINT_MAX || hour > UINT_MAX)
+ overflow= 1;
+
+ if (!overflow)
+ {
+ ltime.hour= (uint) ((hour < 0 ? -hour : hour));
+ ltime.minute= (uint) minute;
+ ltime.second= (uint) second;
+ }
+ else
+ {
+ ltime.hour= TIME_MAX_HOUR;
+ ltime.minute= TIME_MAX_MINUTE;
+ ltime.second= TIME_MAX_SECOND;
+ char buf[28];
+ char *ptr= longlong10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
+ int len = (int)(ptr - buf) +
+ my_sprintf(ptr, (ptr, ":%02u:%02u", (uint)minute, (uint)second));
+ make_truncated_value_warning(current_thd, buf, len, MYSQL_TIMESTAMP_TIME,
+ NullS);
+ }
+
+ if (make_time_with_warn((DATE_TIME_FORMAT *) 0, &ltime, str))
+ {
+ null_value= 1;
+ return 0;
}
- ltime.hour= (ulong) hour;
- ltime.minute= (ulong) minute;
- ltime.second= (ulong) second;
- make_time((DATE_TIME_FORMAT *) 0, &ltime, str);
return str;
}
@@ -3056,7 +3198,7 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
goto null_date;
null_value= 0;
- bzero((char*) ltime, sizeof(ltime));
+ bzero((char*) ltime, sizeof(*ltime));
date_time_format.format.str= (char*) format->ptr();
date_time_format.format.length= format->length();
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 4369c288cd5..8769ca6c1cb 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -3141,6 +3141,7 @@ static byte *get_warning_count(THD *thd)
{
thd->sys_var_tmp.long_value=
(thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
+ thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
return (byte*) &thd->sys_var_tmp.long_value;
}
diff --git a/sql/sp.cc b/sql/sp.cc
index 3411a18c17a..fd42ec8e9f2 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -653,6 +653,17 @@ db_drop_routine(THD *thd, int type, sp_name *name)
if (table->file->ha_delete_row(table->record[0]))
ret= SP_DELETE_ROW_FAILED;
}
+
+ if (ret == SP_OK)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
+
close_thread_tables(thd);
DBUG_RETURN(ret);
}
@@ -687,6 +698,17 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
if ((table->file->ha_update_row(table->record[1],table->record[0])))
ret= SP_WRITE_ROW_FAILED;
}
+
+ if (ret == SP_OK)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
+
close_thread_tables(thd);
DBUG_RETURN(ret);
}
@@ -765,6 +787,7 @@ print_field_values(THD *thd, TABLE *table,
return SP_INTERNAL_ERROR;
}
}
+
return SP_OK;
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index c55fc744cd0..aa13c2f08f4 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3140,9 +3140,22 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
grant_option=TRUE;
thd->mem_root= old_root;
pthread_mutex_unlock(&acl_cache->lock);
+
+ if (!result) /* success */
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
+
rw_unlock(&LOCK_grant);
- if (!result)
+
+ if (!result) /* success */
send_ok(thd);
+
/* Tables are automatically closed */
DBUG_RETURN(result);
}
@@ -3294,9 +3307,21 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
grant_option=TRUE;
thd->mem_root= old_root;
pthread_mutex_unlock(&acl_cache->lock);
+ if (!result && !no_error)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
+
rw_unlock(&LOCK_grant);
+
if (!result && !no_error)
send_ok(thd);
+
/* Tables are automatically closed */
DBUG_RETURN(result);
}
@@ -3394,11 +3419,23 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
}
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (!result)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (!result)
send_ok(thd);
+
DBUG_RETURN(result);
}
@@ -5398,6 +5435,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
@@ -5454,6 +5498,13 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
rebuild_check_host();
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
@@ -5523,6 +5574,13 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
rebuild_check_host();
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
@@ -5697,6 +5755,13 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 3960236e828..37096fd897e 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -705,6 +705,7 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
qinfo.db = db;
qinfo.db_len = strlen(db);
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -783,6 +784,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
qinfo.db_len = strlen(db);
thd->clear_error();
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -905,6 +907,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
qinfo.db_len = strlen(db);
thd->clear_error();
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
mysql_bin_log.write(&qinfo);
}
thd->server_status|= SERVER_STATUS_DB_DROPPED;
@@ -931,6 +934,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
tbl_name_len= strlen(tbl->table_name) + 3;
if (query_pos + tbl_name_len + 1 >= query_end)
{
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
query_pos= query_data_start;
}
@@ -943,6 +947,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
if (query_pos != query_data_start)
{
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
}
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index fc7ed7ff673..a3772e3709a 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3237,6 +3237,7 @@ end_with_restore_list:
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
+ /* Presumably, REPAIR and binlog writing doesn't require synchronization */
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -3269,6 +3270,7 @@ end_with_restore_list:
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
+ /* Presumably, ANALYZE and binlog writing doesn't require synchronization */
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -3293,6 +3295,7 @@ end_with_restore_list:
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
+ /* Presumably, OPTIMIZE and binlog writing doesn't require synchronization */
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -3580,6 +3583,7 @@ end_with_restore_list:
/* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
thd->options|= OPTION_KEEP_LOG;
}
+ /* DDL and binlog write order protected by LOCK_open */
res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
lex->drop_temporary);
}
@@ -3979,13 +3983,9 @@ end_with_restore_list:
break;
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog */
if (!(res= mysql_create_user(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
send_ok(thd);
- }
break;
}
case SQLCOM_DROP_USER:
@@ -3995,15 +3995,9 @@ end_with_restore_list:
break;
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog */
if (!(res= mysql_drop_user(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- {
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
send_ok(thd);
- }
break;
}
case SQLCOM_RENAME_USER:
@@ -4013,15 +4007,9 @@ end_with_restore_list:
break;
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog */
if (!(res= mysql_rename_user(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- {
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
send_ok(thd);
- }
break;
}
case SQLCOM_REVOKE_ALL:
@@ -4029,15 +4017,9 @@ end_with_restore_list:
if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
check_global_access(thd,CREATE_USER_ACL))
break;
+ /* Conditionally writes to binlog */
if (!(res = mysql_revoke_all(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- {
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
send_ok(thd);
- }
break;
}
case SQLCOM_REVOKE:
@@ -4096,6 +4078,7 @@ end_with_restore_list:
check_grant_routine(thd, grants | GRANT_ACL, all_tables,
lex->type == TYPE_ENUM_PROCEDURE, 0))
goto error;
+ /* Conditionally writes to binlog */
res= mysql_routine_grant(thd, all_tables,
lex->type == TYPE_ENUM_PROCEDURE,
lex->users_list, grants,
@@ -4108,16 +4091,11 @@ end_with_restore_list:
GRANT_ACL),
all_tables, 0, UINT_MAX, 0))
goto error;
+ /* Conditionally writes to binlog */
res= mysql_table_grant(thd, all_tables, lex->users_list,
lex->columns, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
}
- if (!res && mysql_bin_log.is_open())
- {
- thd->clear_error();
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
}
else
{
@@ -4128,16 +4106,11 @@ end_with_restore_list:
goto error;
}
else
+ /* Conditionally writes to binlog */
res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
if (!res)
{
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
if (lex->sql_command == SQLCOM_GRANT)
{
List_iterator <LEX_USER> str_list(lex->users_list);
@@ -4175,6 +4148,7 @@ end_with_restore_list:
We WANT to write and we CAN write.
! we write after unlocking the table.
*/
+ /* Presumably, RESET and binlog writing doesn't require synchronization */
if (!lex->no_write_to_binlog && write_to_binlog)
{
if (mysql_bin_log.is_open())
@@ -4691,20 +4665,16 @@ end_with_restore_list:
already puts on CREATE FUNCTION.
*/
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
+ /* Conditionally writes to binlog */
result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
else
+ /* Conditionally writes to binlog */
result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
}
}
switch (result)
{
case SP_OK:
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
send_ok(thd);
break;
case SP_KEY_NOT_FOUND:
@@ -4749,9 +4719,11 @@ end_with_restore_list:
}
#endif
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
- result= sp_drop_procedure(thd, lex->spname);
+ /* Conditionally writes to binlog */
+ result= sp_drop_procedure(thd, lex->spname); /* Conditionally writes to binlog */
else
- result= sp_drop_function(thd, lex->spname);
+ /* Conditionally writes to binlog */
+ result= sp_drop_function(thd, lex->spname); /* Conditionally writes to binlog */
}
else
{
@@ -4764,6 +4736,8 @@ end_with_restore_list:
{
if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0))
goto error;
+
+ /* Does NOT write to binlog */
if (!(res = mysql_drop_function(thd, &lex->spname->m_name)))
{
send_ok(thd);
@@ -4784,12 +4758,6 @@ end_with_restore_list:
switch (result)
{
case SP_OK:
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
send_ok(thd);
break;
case SP_KEY_NOT_FOUND:
@@ -4887,50 +4855,8 @@ end_with_restore_list:
{
if (end_active_trans(thd))
goto error;
-
- if (!(res= mysql_create_view(thd, thd->lex->create_view_mode)) &&
- mysql_bin_log.is_open())
- {
- String buff;
- const LEX_STRING command[3]=
- {{ C_STRING_WITH_LEN("CREATE ") },
- { C_STRING_WITH_LEN("ALTER ") },
- { C_STRING_WITH_LEN("CREATE OR REPLACE ") }};
- thd->clear_error();
-
- buff.append(command[thd->lex->create_view_mode].str,
- command[thd->lex->create_view_mode].length);
- view_store_options(thd, first_table, &buff);
- buff.append(STRING_WITH_LEN("VIEW "));
- /* Test if user supplied a db (ie: we did not use thd->db) */
- if (first_table->db && first_table->db[0] &&
- (thd->db == NULL || strcmp(first_table->db, thd->db)))
- {
- append_identifier(thd, &buff, first_table->db,
- first_table->db_length);
- buff.append('.');
- }
- append_identifier(thd, &buff, first_table->table_name,
- first_table->table_name_length);
- if (lex->view_list.elements)
- {
- List_iterator_fast<LEX_STRING> names(lex->view_list);
- LEX_STRING *name;
- int i;
-
- for (i= 0; name= names++; i++)
- {
- buff.append(i ? ", " : "(");
- append_identifier(thd, &buff, name->str, name->length);
- }
- buff.append(')');
- }
- buff.append(STRING_WITH_LEN(" AS "));
- buff.append(first_table->source.str, first_table->source.length);
-
- thd->binlog_query(THD::STMT_QUERY_TYPE,
- buff.ptr(), buff.length(), FALSE, FALSE);
- }
+ /* Conditionally writes to binlog. */
+ res= mysql_create_view(thd, first_table, thd->lex->create_view_mode);
break;
}
case SQLCOM_DROP_VIEW:
@@ -4938,13 +4864,8 @@ end_with_restore_list:
if (check_table_access(thd, DROP_ACL, all_tables, 0) ||
end_active_trans(thd))
goto error;
- if (!(res= mysql_drop_view(thd, first_table, thd->lex->drop_mode)) &&
- mysql_bin_log.is_open())
- {
- thd->clear_error();
- thd->binlog_query(THD::STMT_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
+ /* Conditionally writes to binlog. */
+ res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
break;
}
case SQLCOM_CREATE_TRIGGER:
@@ -4952,6 +4873,7 @@ end_with_restore_list:
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog. */
res= mysql_create_or_drop_trigger(thd, all_tables, 1);
/* We don't care about trigger body after this point */
@@ -4964,6 +4886,7 @@ end_with_restore_list:
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog. */
res= mysql_create_or_drop_trigger(thd, all_tables, 0);
break;
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 63a129918d0..fa33cafdab1 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2287,6 +2287,14 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
#endif
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+
+ /*
+ If the free_list is not empty, we'll wrongly free some externally
+ allocated items when cleaning up after validation of the prepared
+ statement.
+ */
+ DBUG_ASSERT(thd->free_list == NULL);
+
error= stmt->execute(&expanded_query,
test(flags & (ulong) CURSOR_TYPE_READ_ONLY));
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -2349,6 +2357,13 @@ void mysql_sql_stmt_execute(THD *thd)
DBUG_PRINT("info",("stmt: %p", stmt));
+ /*
+ If the free_list is not empty, we'll wrongly free some externally
+ allocated items when cleaning up after validation of the prepared
+ statement.
+ */
+ DBUG_ASSERT(thd->free_list == NULL);
+
if (stmt->set_params_from_vars(stmt, lex->prepared_stmt_params,
&expanded_query))
goto set_params_data_err;
@@ -2827,12 +2842,12 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
external changes when cleaning up after validation.
*/
DBUG_ASSERT(thd->change_list.is_empty());
- /*
- If the free_list is not empty, we'll wrongly free some externally
- allocated items when cleaning up after validation of the prepared
- statement.
+
+ /*
+ The only case where we should have items in the thd->free_list is
+ after stmt->set_params_from_vars(), which may in some cases create
+ Item_null objects.
*/
- DBUG_ASSERT(thd->free_list == NULL);
if (error == 0)
error= check_prepared_statement(this, name.str != 0);
@@ -2930,7 +2945,13 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
allocated items when cleaning up after execution of this statement.
*/
DBUG_ASSERT(thd->change_list.is_empty());
- DBUG_ASSERT(thd->free_list == NULL);
+
+ /*
+ The only case where we should have items in the thd->free_list is
+ after stmt->set_params_from_vars(), which may in some cases create
+ Item_null objects.
+ */
+
thd->set_n_backup_statement(this, &stmt_backup);
if (expanded_query->length() &&
alloc_query(thd, (char*) expanded_query->ptr(),
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 7796bc35a79..1b91c269e9f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5232,6 +5232,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
+ /* Conditionally writes to binlog. */
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
alter_info->tablespace_op));
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
@@ -5341,10 +5342,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
!table->s->tmp_table) // no need to touch frm
{
error=0;
+ VOID(pthread_mutex_lock(&LOCK_open));
if (new_name != table_name || new_db != db)
{
thd->proc_info="rename";
- VOID(pthread_mutex_lock(&LOCK_open));
/* Then do a 'simple' rename of the table */
error=0;
if (!access(new_name_buff,F_OK))
@@ -5367,7 +5368,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
error= -1;
}
}
- VOID(pthread_mutex_unlock(&LOCK_open));
}
if (!error)
@@ -5376,16 +5376,12 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
case LEAVE_AS_IS:
break;
case ENABLE:
- VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- VOID(pthread_mutex_unlock(&LOCK_open));
error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
/* COND_refresh will be signaled in close_thread_tables() */
break;
case DISABLE:
- VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- VOID(pthread_mutex_unlock(&LOCK_open));
error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
/* COND_refresh will be signaled in close_thread_tables() */
break;
@@ -5410,6 +5406,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
table->file->print_error(error, MYF(0));
error= -1;
}
+ VOID(pthread_mutex_unlock(&LOCK_open));
table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0);
DBUG_RETURN(error);
@@ -6410,7 +6407,7 @@ end_temporary:
thd->some_tables_deleted=0;
DBUG_RETURN(FALSE);
- err1:
+err1:
if (new_table)
{
/* close_temporary_table() frees the new_table pointer. */
@@ -6419,7 +6416,7 @@ end_temporary:
else
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
- err:
+err:
DBUG_RETURN(TRUE);
}
/* mysql_alter_table */
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index acb7d5b61df..61d2992ed1b 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -276,8 +276,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
table->triggers->drop_trigger(thd, tables, &stmt_query));
end:
- VOID(pthread_mutex_unlock(&LOCK_open));
- start_waiting_global_read_lock(thd);
if (!result)
{
@@ -286,13 +284,16 @@ end:
thd->clear_error();
/* Such a statement can always go directly to binlog, no trans cache. */
- Query_log_event qinfo(thd, stmt_query.ptr(), stmt_query.length(), 0,
- FALSE);
- mysql_bin_log.write(&qinfo);
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ stmt_query.ptr(), stmt_query.length(), FALSE, FALSE);
}
+ }
+
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ start_waiting_global_read_lock(thd);
+ if (!result)
send_ok(thd);
- }
DBUG_RETURN(result);
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 7f6d935ff5e..79ecf12cf27 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -212,6 +212,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
SYNOPSIS
mysql_create_view()
thd - thread handler
+ views - views to create
mode - VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
RETURN VALUE
@@ -219,7 +220,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
TRUE Error
*/
-bool mysql_create_view(THD *thd,
+bool mysql_create_view(THD *thd, TABLE_LIST *views,
enum_view_create_mode mode)
{
LEX *lex= thd->lex;
@@ -548,6 +549,49 @@ bool mysql_create_view(THD *thd,
}
VOID(pthread_mutex_lock(&LOCK_open));
res= mysql_register_view(thd, view, mode);
+
+ if (mysql_bin_log.is_open())
+ {
+ String buff;
+ const LEX_STRING command[3]=
+ {{ C_STRING_WITH_LEN("CREATE ") },
+ { C_STRING_WITH_LEN("ALTER ") },
+ { C_STRING_WITH_LEN("CREATE OR REPLACE ") }};
+
+ buff.append(command[thd->lex->create_view_mode].str,
+ command[thd->lex->create_view_mode].length);
+ view_store_options(thd, views, &buff);
+ buff.append(STRING_WITH_LEN("VIEW "));
+ /* Test if user supplied a db (ie: we did not use thd->db) */
+ if (views->db && views->db[0] &&
+ (thd->db == NULL || strcmp(views->db, thd->db)))
+ {
+ append_identifier(thd, &buff, views->db,
+ views->db_length);
+ buff.append('.');
+ }
+ append_identifier(thd, &buff, views->table_name,
+ views->table_name_length);
+ if (lex->view_list.elements)
+ {
+ List_iterator_fast<LEX_STRING> names(lex->view_list);
+ LEX_STRING *name;
+ int i;
+
+ for (i= 0; name= names++; i++)
+ {
+ buff.append(i ? ", " : "(");
+ append_identifier(thd, &buff, name->str, name->length);
+ }
+ buff.append(')');
+ }
+ buff.append(STRING_WITH_LEN(" AS "));
+ buff.append(views->source.str, views->source.length);
+
+ thd->binlog_query(THD::STMT_QUERY_TYPE,
+ buff.ptr(), buff.length(), FALSE, FALSE);
+ }
+
VOID(pthread_mutex_unlock(&LOCK_open));
if (view->revision != 1)
query_cache_invalidate3(thd, view, 0);
@@ -1318,13 +1362,13 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
enum legacy_db_type not_used;
DBUG_ENTER("mysql_drop_view");
+ VOID(pthread_mutex_lock(&LOCK_open));
for (view= views; view; view= view->next_local)
{
TABLE_SHARE *share;
frm_type_enum type= FRMTYPE_ERROR;
build_table_filename(path, sizeof(path),
view->db, view->table_name, reg_ext, 0);
- VOID(pthread_mutex_lock(&LOCK_open));
if (access(path, F_OK) ||
FRMTYPE_VIEW != (type= mysql_frm_type(thd, path, &not_used)))
@@ -1336,7 +1380,6 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
name);
- VOID(pthread_mutex_unlock(&LOCK_open));
continue;
}
if (type == FRMTYPE_TABLE)
@@ -1353,7 +1396,6 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
non_existant_views.append(',');
non_existant_views.append(String(view->table_name,system_charset_info));
}
- VOID(pthread_mutex_unlock(&LOCK_open));
continue;
}
if (my_delete(path, MYF(MY_WME)))
@@ -1374,8 +1416,16 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
}
query_cache_invalidate3(thd, view, 0);
sp_cache_invalidate();
- VOID(pthread_mutex_unlock(&LOCK_open));
}
+
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
+ VOID(pthread_mutex_unlock(&LOCK_open));
if (error)
{
DBUG_RETURN(TRUE);
diff --git a/sql/sql_view.h b/sql/sql_view.h
index 7e54d57cfdf..fc480167216 100644
--- a/sql/sql_view.h
+++ b/sql/sql_view.h
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-bool mysql_create_view(THD *thd,
+bool mysql_create_view(THD *thd, TABLE_LIST *view,
enum_view_create_mode mode);
bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
diff --git a/sql/time.cc b/sql/time.cc
index 0461f7723c6..25a1995dd01 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -25,14 +25,25 @@
#ifndef TESTTIME
+/*
+ Name description of interval names used in statements.
+
+ 'interval_type_to_name' is ordered and sorted on interval size and
+ interval complexity.
+ Order of elements in 'interval_type_to_name' should correspond to
+ the order of elements in 'interval_type' enum
+
+ See also interval_type, interval_names
+*/
+
LEX_STRING interval_type_to_name[INTERVAL_LAST] = {
{ C_STRING_WITH_LEN("YEAR")},
{ C_STRING_WITH_LEN("QUARTER")},
{ C_STRING_WITH_LEN("MONTH")},
+ { C_STRING_WITH_LEN("WEEK")},
{ C_STRING_WITH_LEN("DAY")},
{ C_STRING_WITH_LEN("HOUR")},
{ C_STRING_WITH_LEN("MINUTE")},
- { C_STRING_WITH_LEN("WEEK")},
{ C_STRING_WITH_LEN("SECOND")},
{ C_STRING_WITH_LEN("MICROSECOND")},
{ C_STRING_WITH_LEN("YEAR_MONTH")},
@@ -278,9 +289,9 @@ my_time_t TIME_to_timestamp(THD *thd, const TIME *t, my_bool *in_dst_time_gap)
bool
str_to_time_with_warn(const char *str, uint length, TIME *l_time)
{
- int was_cut;
- bool ret_val= str_to_time(str, length, l_time, &was_cut);
- if (was_cut)
+ int warning;
+ bool ret_val= str_to_time(str, length, l_time, &warning);
+ if (ret_val || warning)
make_truncated_value_warning(current_thd, str, length,
MYSQL_TIMESTAMP_TIME, NullS);
return ret_val;
diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c
index 099c3173396..9d7eda9f5ba 100644
--- a/storage/myisam/sort.c
+++ b/storage/myisam/sort.c
@@ -324,7 +324,7 @@ pthread_handler_t thr_find_all_keys(void *arg)
if (info->sort_info->got_error)
goto err;
- if (info->keyinfo->flag && HA_VAR_LENGTH_KEY)
+ if (info->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
info->write_keys=write_keys_varlen;
info->read_to_buffer=read_to_buffer_varlen;
@@ -517,7 +517,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
{
if (got_error)
continue;
- if (sinfo->keyinfo->flag && HA_VAR_LENGTH_KEY)
+ if (sinfo->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
sinfo->write_keys=write_keys_varlen;
sinfo->read_to_buffer=read_to_buffer_varlen;