diff options
author | unknown <mskold@mysql.com> | 2004-11-05 08:52:44 +0100 |
---|---|---|
committer | unknown <mskold@mysql.com> | 2004-11-05 08:52:44 +0100 |
commit | d497334164505a4e380bbf4170966379c11d95a8 (patch) | |
tree | 07808bc5c424c039f738849765f57124a6e30512 | |
parent | 80051fa3b622651608506c408e08bc8458158784 (diff) | |
parent | b38510ecd00abbfc99d7767d4b91c8d4d1cfbdc0 (diff) | |
download | mariadb-git-d497334164505a4e380bbf4170966379c11d95a8.tar.gz |
Merge mskold@bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/usr/local/home/marty/MySQL/test/mysql-4.1
41 files changed, 4842 insertions, 89 deletions
diff --git a/acinclude.m4 b/acinclude.m4 index 7f25b447f10..671e279a9f3 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -208,7 +208,7 @@ INCLUDES="$INCLUDES $ZLIB_INCLUDES" LIBS="$LIBS $ZLIB_LIBS" AC_CACHE_VAL([mysql_cv_compress], [AC_TRY_LINK([#include <zlib.h>], - [int link_test() { return compress(0, (unsigned long*) 0, "", 0); }], + [return compress(0, (unsigned long*) 0, "", 0);], [mysql_cv_compress="yes" AC_MSG_RESULT([ok])], [mysql_cv_compress="no"]) diff --git a/client/mysqladmin.c b/client/mysqladmin.c index bccbf29ef83..6258b9685a5 100644 --- a/client/mysqladmin.c +++ b/client/mysqladmin.c @@ -108,7 +108,7 @@ static const char *command_names[]= { }; static TYPELIB command_typelib= -{ array_elements(command_names)-1,"commands", command_names}; +{ array_elements(command_names)-1,"commands", command_names, NULL}; static struct my_option my_long_options[] = { diff --git a/client/mysqldump.c b/client/mysqldump.c index 1686278096b..a8db8ab440b 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -124,7 +124,7 @@ const char *compatible_mode_names[]= (1<<10) /* ANSI */\ ) TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1, - "", compatible_mode_names}; + "", compatible_mode_names, NULL}; static struct my_option my_long_options[] = @@ -317,7 +317,7 @@ static struct my_option my_long_options[] = {"comments", 'i', "Write additional information.", (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"hex-blob", OPT_HEXBLOB, "Dump BLOBs in HEX. this mode does not work with extended-insert", + {"hex-blob", OPT_HEXBLOB, "Dump BLOBs in HEX.", (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -1523,10 +1523,11 @@ static void dumpTable(uint numFields, char *table) /* 63 is my_charset_bin. If charsetnr is not 63, we have not a BLOB but a TEXT column. - we'll dump it in hex only BLOB columns. + we'll dump in hex only BLOB columns. */ is_blob= (opt_hex_blob && field->charsetnr == 63 && - (field->type == FIELD_TYPE_BLOB || + (field->type == FIELD_TYPE_STRING || + field->type == FIELD_TYPE_BLOB || field->type == FIELD_TYPE_LONG_BLOB || field->type == FIELD_TYPE_MEDIUM_BLOB || field->type == FIELD_TYPE_TINY_BLOB)) ? 1 : 0; @@ -1544,6 +1545,13 @@ static void dumpTable(uint numFields, char *table) { if (!IS_NUM_FIELD(field)) { + /* + "length * 2 + 2" is OK for both HEX and non-HEX modes: + - In HEX mode we need exactly 2 bytes per character + plus 2 bytes for '0x' prefix. + - In non-HEX mode we need up to 2 bytes per character, + plus 2 bytes for leading and trailing '\'' characters. + */ if (dynstr_realloc(&extended_row,length * 2+2)) { fputs("Aborting dump (out of memory)",stderr); @@ -1552,15 +1560,11 @@ static void dumpTable(uint numFields, char *table) } if (opt_hex_blob && is_blob) { - ulong counter; - unsigned char *ptr= row[i]; dynstr_append(&extended_row, "0x"); - for (counter = 0; counter < lengths[i]; counter++) - { - char xx[3]; - sprintf(xx, "%02X", ptr[counter]); - dynstr_append(&extended_row, xx); - } + extended_row.length+= mysql_hex_string(extended_row.str + + extended_row.length, + row[i], length); + extended_row.str[extended_row.length]= '\0'; } else { diff --git a/client/mysqltest.c b/client/mysqltest.c index aef36823dfc..df80fc7bb66 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -949,8 +949,11 @@ static void do_exec(struct st_query* q) while (fgets(buf, sizeof(buf), res_file)) replace_dynstr_append_mem(ds, buf, strlen(buf)); } - +#ifndef __WIN__ error= pclose(res_file); +#else + error= _pclose(res_file); +#endif if (error != 0) die("command \"%s\" failed", cmd); @@ -4516,8 +4519,7 @@ static void get_replace_column(struct st_query *q) my_free(start, MYF(0)); } -#ifdef __NETWARE__ - +#if defined(__NETWARE__) || defined(__WIN__) /* Substitute environment variables with text. @@ -4608,9 +4610,13 @@ FILE *my_popen(const char *cmd, const char *mode __attribute__((unused))) FILE *res_file; subst_cmd= subst_env_var(cmd); +#ifndef __WIN__ res_file= popen(subst_cmd, "r0"); +#else + res_file= _popen(subst_cmd, "r0"); +#endif my_free(subst_cmd, MYF(0)); return res_file; } -#endif /* __NETWARE__ */ +#endif /* __NETWARE__ or __WIN__*/ diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h index 9f525042dcc..f8435e14d97 100644 --- a/innobase/include/lock0lock.h +++ b/innobase/include/lock0lock.h @@ -463,6 +463,14 @@ lock_rec_hash( ulint space, /* in: space */ ulint page_no);/* in: page number */ /************************************************************************* +Gets the table covered by an IX table lock. */ + +dict_table_t* +lock_get_ix_table( +/*==============*/ + /* out: the table covered by the lock */ + lock_t* lock); /* in: table lock */ +/************************************************************************* Checks that a transaction id is sensible, i.e., not in the future. */ ibool diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 9437ed4b6ee..73f41dea0da 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -175,8 +175,12 @@ int row_lock_table_for_mysql( /*=====================*/ /* out: error code or DB_SUCCESS */ - row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL + row_prebuilt_t* prebuilt, /* in: prebuilt struct in the MySQL table handle */ + dict_table_t* table); /* in: table to LOCK_IX, or NULL + if prebuilt->table should be + locked as LOCK_TABLE_EXP | + prebuilt->select_lock_type */ /************************************************************************* Does an insert for MySQL. */ diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 68073647248..6f2d58b72c3 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -395,6 +395,19 @@ lock_rec_get_nth_bit( return(ut_bit_get_nth(b, bit_index)); } +/************************************************************************* +Gets the table covered by an IX table lock. */ + +dict_table_t* +lock_get_ix_table( +/*==============*/ + /* out: the table covered by the lock */ + lock_t* lock) /* in: table lock */ +{ + ut_a(lock->type_mode == (LOCK_TABLE | LOCK_IX)); + return(lock->un_member.tab_lock.table); +} + /*************************************************************************/ #define lock_mutex_enter_kernel() mutex_enter(&kernel_mutex) diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index f356ef8081e..17747ae2a8e 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -779,8 +779,12 @@ int row_lock_table_for_mysql( /*=====================*/ /* out: error code or DB_SUCCESS */ - row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL + row_prebuilt_t* prebuilt, /* in: prebuilt struct in the MySQL table handle */ + dict_table_t* table) /* in: table to LOCK_IX, or NULL + if prebuilt->table should be + locked as LOCK_TABLE_EXP | + prebuilt->select_lock_type */ { trx_t* trx = prebuilt->trx; que_thr_t* thr; @@ -813,8 +817,12 @@ run_again: trx_start_if_not_started(trx); - err = lock_table(LOCK_TABLE_EXP, prebuilt->table, - prebuilt->select_lock_type, thr); + if (table) { + err = lock_table(0, table, LOCK_IX, thr); + } else { + err = lock_table(LOCK_TABLE_EXP, prebuilt->table, + prebuilt->select_lock_type, thr); + } trx->error_state = err; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 88f46ce19e7..a57c82e6424 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1563,7 +1563,8 @@ void my_net_local_init(NET *net) trailing '. The caller must supply whichever of those is desired. */ -ulong mysql_hex_string(char *to, const char *from, ulong length) +ulong STDCALL +mysql_hex_string(char *to, const char *from, ulong length) { char *to0= to; const char *end; diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index bc91e90a41c..c9ff70f208d 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -47,6 +47,7 @@ EXPORTS mysql_errno mysql_error mysql_escape_string + mysql_hex_string mysql_stmt_execute mysql_stmt_fetch mysql_stmt_fetch_column diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index c3f9eea875d..4e8601f1b88 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -36,6 +36,11 @@ test_SCRIPTS = mysql-test-run install_test_db test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem CLEANFILES = $(test_SCRIPTS) $(test_DATA) +INCLUDES = -I$(srcdir)/../include -I../include -I.. +bin_PROGRAMS = mysql_test_run_new +mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c + + dist-hook: mkdir -p $(distdir)/t $(distdir)/r $(distdir)/include \ $(distdir)/std_data diff --git a/mysql-test/init_db.sql b/mysql-test/init_db.sql new file mode 100644 index 00000000000..4613e5c0274 --- /dev/null +++ b/mysql-test/init_db.sql @@ -0,0 +1,26 @@ +CREATE DATABASE mysql; +CREATE DATABASE test; + +USE mysql; + +CREATE TABLE db (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User)) comment='Database privileges'; + +INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); +INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); + +CREATE TABLE host (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db)) comment='Host privileges; Merged with database privileges'; + +CREATE TABLE user (Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(45) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') DEFAULT 'N' NOT NULL, File_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User)) comment='Users and global privileges'; + +INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); +INSERT INTO user VALUES ('','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + +INSERT INTO user (host,user) values ('localhost',''); +INSERT INTO user (host,user) values ('',''); + +CREATE TABLE func (name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') NOT NULL, PRIMARY KEY (name)) comment='User defined functions'; + +CREATE TABLE tables_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(60) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp(14), Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor)) comment='Table privileges'; + +CREATE TABLE columns_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp(14), Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name)) comment='Column privileges'; + diff --git a/mysql-test/my_manage.c b/mysql-test/my_manage.c new file mode 100644 index 00000000000..e23d4f2227e --- /dev/null +++ b/mysql-test/my_manage.c @@ -0,0 +1,860 @@ +/* + Copyright (c) 2003 Novell, Inc. All Rights Reserved. + + 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 <stdio.h> +#include <errno.h> +#ifndef __WIN__ +#include <dirent.h> +#endif +#include <string.h> +#ifdef __NETWARE__ +#include <screen.h> +#include <proc.h> +#else +#include <sys/types.h> +#ifndef __WIN__ +#include <sys/wait.h> +#include <unistd.h> +#else +#include <direct.h> +#include <stdlib.h> +#include <stdio.h> +#endif +#endif +#include <ctype.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <assert.h> + +#include "my_manage.h" + +#ifndef __NETWARE__ +#define ASSERT assert +extern char **environ; +#endif + + + +/****************************************************************************** + + macros + +******************************************************************************/ + +/****************************************************************************** + + global variables + +******************************************************************************/ + +/****************************************************************************** + + functions + +******************************************************************************/ + +/****************************************************************************** + + init_args() + + Init an argument list. + +******************************************************************************/ +void init_args(arg_list_t *al) +{ + ASSERT(al != NULL); + + al->argc = 0; + al->size = ARG_BUF; + al->argv = malloc(al->size * sizeof(char *)); + ASSERT(al->argv != NULL); + + return; +} + +/****************************************************************************** + + add_arg() + + Add an argument to a list. + +******************************************************************************/ +void add_arg(arg_list_t *al, const char *format, ...) +{ + va_list ap; + char temp[PATH_MAX]; + + ASSERT(al != NULL); + + // increase size + if (al->argc >= (int)al->size) + { + al->size += ARG_BUF; + al->argv = realloc(al->argv, al->size * sizeof(char *)); + ASSERT(al->argv != NULL); + } + + if (format) + { + va_start(ap, format); + vsprintf(temp, format, ap); + va_end(ap); + + al->argv[al->argc] = malloc(strlen(temp)+1); + ASSERT(al->argv[al->argc] != NULL); + strcpy(al->argv[al->argc], temp); + + ++(al->argc); + } + else + { + al->argv[al->argc] = NULL; + } + + return; +} + +/****************************************************************************** + + free_args() + + Free an argument list. + +******************************************************************************/ +void free_args(arg_list_t *al) +{ + int i; + + ASSERT(al != NULL); + + for(i = 0; i < al->argc; i++) + { + ASSERT(al->argv[i] != NULL); + free(al->argv[i]); + al->argv[i] = NULL; + } + + free(al->argv); + al->argc = 0; + al->argv = NULL; + + return; +} + +/****************************************************************************** + + sleep_until_file_deleted() + + Sleep until the given file is no longer found. + +******************************************************************************/ +#ifndef __WIN__ +int sleep_until_file_deleted(char *pid_file) +#else +int sleep_until_file_deleted(HANDLE pid_file) +#endif +{ + int err; +#ifndef __WIN__ + struct stat buf; + int i; + + for(i = 0; (i < TRY_MAX) && (err = !stat(pid_file, &buf)); i++) sleep(1); + + if (err != 0) err = errno; +#else + err= (WaitForSingleObject(pid_file, TRY_MAX*1000) == WAIT_TIMEOUT); +#endif + return err; +} + +/****************************************************************************** + + sleep_until_file_exists() + + Sleep until the given file exists. + +******************************************************************************/ +#ifndef __WIN__ +int sleep_until_file_exists(char *pid_file) +#else +int sleep_until_file_exists(HANDLE pid_file) +#endif +{ + int err; +#ifndef __WIN__ + struct stat buf; + int i; + + for(i = 0; (i < TRY_MAX) && (err = stat(pid_file, &buf)); i++) sleep(1); + + if (err != 0) err = errno; +#else + err= (WaitForSingleObject(pid_file, TRY_MAX*1000) == WAIT_TIMEOUT); +#endif + return err; +} + +/****************************************************************************** + + wait_for_server_start() + + Wait for the server on the given port to start. + +******************************************************************************/ +int wait_for_server_start(char *bin_dir, char *mysqladmin_file, char *user, char *password, int port,char *tmp_dir) +{ + arg_list_t al; + int err, i; + char trash[PATH_MAX]; + + // mysqladmin file + snprintf(trash, PATH_MAX, "%s/trash.out",tmp_dir); + + // args + init_args(&al); + add_arg(&al, "%s", mysqladmin_file); + add_arg(&al, "--no-defaults"); + add_arg(&al, "--port=%u", port); + add_arg(&al, "--user=%s", user); + add_arg(&al, "--password=%s", password); + add_arg(&al, "--silent"); + +//#ifdef NOT_USED +#ifndef __NETWARE__ + add_arg(&al, "-O"); + add_arg(&al, "connect_timeout=10"); + add_arg(&al, "-w"); +#endif + + add_arg(&al, "--host=localhost"); +#ifndef __NETWARE__ + add_arg(&al, "--protocol=tcp"); +#endif + add_arg(&al, "ping"); + + // NetWare does not support the connect timeout in the TCP/IP stack + // -- we will try the ping multiple times +#ifndef __WIN__ + for(i = 0; (i < TRY_MAX) + && (err = spawn(mysqladmin_file, &al, TRUE, NULL, + trash, NULL, NULL)); i++) sleep(1); +#else + err = spawn(mysqladmin_file, &al, TRUE, NULL,trash, NULL, NULL); +#endif + + // free args + free_args(&al); + + return err; +} + +/****************************************************************************** + + spawn() + + Spawn the given path with the given arguments. + +******************************************************************************/ +#ifdef __NETWARE__ +int spawn(char *path, arg_list_t *al, int join, char *input, + char *output, char *error, char *pid_file) +{ + pid_t pid; + int result = 0; + wiring_t wiring = { FD_UNUSED, FD_UNUSED, FD_UNUSED }; + unsigned long flags = PROC_CURRENT_SPACE | PROC_INHERIT_CWD; + + // open wiring + if (input) + wiring.infd = open(input, O_RDONLY); + + if (output) + wiring.outfd = open(output, O_WRONLY | O_CREAT | O_TRUNC); + + if (error) + wiring.errfd = open(error, O_WRONLY | O_CREAT | O_TRUNC); + + // procve requires a NULL + add_arg(al, NULL); + + // go + pid = procve(path, flags, NULL, &wiring, NULL, NULL, 0, + NULL, (const char **)al->argv); + + // close wiring + if (wiring.infd != -1) + close(wiring.infd); + + if (wiring.outfd != -1) + close(wiring.outfd); + + if (wiring.errfd != -1) + close(wiring.errfd); + + return result; +} +#elif __WIN__ + +int spawn(char *path, arg_list_t *al, int join, char *input, + char *output, char *error, HANDLE *pid) +{ + intptr_t result; + int i; + STARTUPINFO startup_info; + PROCESS_INFORMATION process_information; + DWORD exit_code; + char win_args[1024]= ""; + char command_line[1024]= ""; + + /* + Skip the first parameter + */ + for(i = 1; i < al->argc; i++) + { + ASSERT(al->argv[i] != NULL); + strcat(win_args,al->argv[i]); + strcat(win_args," "); + } + + memset(&startup_info,0,sizeof(STARTUPINFO)); + startup_info.cb = sizeof(STARTUPINFO); + + if (input) + freopen(input, "rb", stdin); + + if (output) + freopen(output, "wb", stdout); + + if (error) + freopen(error, "wb", stderr); + + result= CreateProcess( + path, + (LPSTR)&win_args, + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &startup_info, + &process_information + ); + + if (result && process_information.hProcess) + { + if (join) + { + if (WaitForSingleObject(process_information.hProcess, mysqld_timeout) == WAIT_TIMEOUT) + { + exit_code= -1; + } + else + { + GetExitCodeProcess(process_information.hProcess, &exit_code); + } + CloseHandle(process_information.hProcess); + } + else + { + exit_code= 0; + } + if (pid != NULL) + *pid= process_information.hProcess; + } + else + { + exit_code= -1; + } + if (input) + freopen("CONIN$","rb",stdin); + if (output) + freopen("CONOUT$","wb",stdout); + if (error) + freopen("CONOUT$","wb",stderr); + + return exit_code; +} +#else +int spawn(char *path, arg_list_t *al, int join, char *input, + char *output, char *error, char *pid_file) +{ + pid_t pid; + int res_exec = 0; + int result = 0; + + pid = fork(); + + if (pid == -1) + { + fprintf(stderr, "fork was't created\n"); + /* + We can't create the fork...exit with error + */ + return EXIT_FAILURE; + } + + if (pid > 0) + { + /* + The parent process is waiting for child process if join is not zero + */ + if (join) + { + waitpid(pid, &result, 0); + if (WIFEXITED(result) != 0) + { + result = WEXITSTATUS(result); + } + else + { + result = EXIT_FAILURE; + } + } + } + else + { + + /* + Child process + */ + + add_arg(al, NULL); + + + /* + Reassign streams + */ + if (input) + freopen(input, "r", stdin); + + + if (output) + freopen(output, "w", stdout); + + + if (error) + freopen(error, "w", stderr); + + /* Spawn the process */ + if ((res_exec = execve(path, al->argv, environ)) < 0) + { + exit(EXIT_FAILURE); + } + + /* + Restore streams + */ + if (input) + freopen("/dev/tty", "r", stdin); + + if (output) + freopen("/dev/tty", "w", stdout); + + if (error) + freopen("/dev/tty", "w", stderr); + + exit(0); + } + + return result; +} +#endif +/****************************************************************************** + + stop_server() + + Stop the server with the given port and pid file. + +******************************************************************************/ +#ifndef __WIN__ +int stop_server(char *bin_dir, char *mysqladmin_file, char *user, char *password, int port, + char *pid_file,char *tmp_dir) +#else +int stop_server(char *bin_dir, char *mysqladmin_file, char *user, char *password, int port, + HANDLE pid_file,char *tmp_dir) +#endif +{ + arg_list_t al; + int err = 0; + char trash[PATH_MAX]; + + snprintf(trash, PATH_MAX, "%s/trash.out",tmp_dir); + + // args + init_args(&al); + add_arg(&al, "%s", mysqladmin_file); + add_arg(&al, "--no-defaults"); + add_arg(&al, "--port=%u", port); + add_arg(&al, "--user=%s", user); + add_arg(&al, "--password=%s", password); + add_arg(&al, "-O"); + add_arg(&al, "shutdown_timeout=20"); +#ifndef __NETWARE__ + add_arg(&al, "--protocol=tcp"); +#endif + add_arg(&al, "shutdown"); + + // spawn + if ((err = spawn(mysqladmin_file, &al, TRUE, NULL, + trash, NULL, NULL)) == 0) + { + sleep_until_file_deleted(pid_file); + } + else + { +#ifndef __WIN__ + pid_t pid = get_server_pid(pid_file); + + // shutdown failed - kill server + kill_server(pid); + + sleep(TRY_MAX); + + // remove pid file if possible + err = remove(pid_file); +#else + TerminateProcess(pid_file,err); +#endif + } + + // free args + free_args(&al); + + return err; +} + +/****************************************************************************** + + get_server_pid() + + Get the VM id with the given pid file. + +******************************************************************************/ +#ifndef __WIN__ +pid_t get_server_pid(char *pid_file) +{ + char buf[PATH_MAX]; + int fd, err; + char *p; + pid_t id = 0; + + // discover id + fd = open(pid_file, O_RDONLY); + + err = read(fd, buf, PATH_MAX); + + close(fd); + + if (err > 0) + { + // terminate string + if ((p = strchr(buf, '\n')) != NULL) + { + *p = '\0'; + + // check for a '\r' + if ((p = strchr(buf, '\r')) != NULL) + { + *p = '\0'; + } + } + else + { + buf[err] = '\0'; + } + + id = strtol(buf, NULL, 0); + } + + return id; +} + +/****************************************************************************** + + kill_server() + + Force a kill of the server with the given pid. + +******************************************************************************/ +void kill_server(pid_t pid) +{ + if (pid > 0) + { +#if !defined(__NETWARE__) + /* Send SIGTERM to pid */ + kill(pid, SIGTERM); +#else /* __NETWARE__ */ + /* destroy vm */ + NXVmDestroy(pid); +#endif + } +} +#endif +/****************************************************************************** + + del_tree() + + Delete the directory and subdirectories. + +******************************************************************************/ +void del_tree(char *dir) +{ +#ifndef __WIN__ + DIR *parent = opendir(dir); + struct dirent *entry; + char temp[PATH_MAX]; + + if (parent == NULL) + { + return; + } + + while((entry = readdir(parent)) != NULL) + { + // create long name + snprintf(temp, PATH_MAX, "%s/%s", dir, entry->d_name); + + if (entry->d_name[0] == '.') + { + // Skip + } + else + if (S_ISDIR(entry->d_type)) + { + // delete subdirectory + del_tree(temp); + } + else + { + // remove file + remove(temp); + } + } + // remove directory + rmdir(dir); +#else + struct _finddata_t parent; + intptr_t handle; + char temp[PATH_MAX]; + char mask[PATH_MAX]; + + snprintf(mask,MAX_PATH,"%s/*.*",dir); + + if ((handle=_findfirst(mask,&parent)) == -1L) + { + return; + } + + do + { + // create long name + snprintf(temp, PATH_MAX, "%s/%s", dir, parent.name); + if (parent.name[0] == '.') + { + // Skip + } + else + if (parent.attrib & _A_SUBDIR) + { + // delete subdirectory + del_tree(temp); + } + else + { + // remove file + remove(temp); + } + } while (_findnext(handle,&parent) == 0); + + _findclose(handle); + + // remove directory + _rmdir(dir); +#endif +} + +/****************************************************************************** + + removef() + +******************************************************************************/ +int removef(const char *format, ...) +{ +#ifdef __NETWARE__ + va_list ap; + char path[PATH_MAX]; + + va_start(ap, format); + + vsnprintf(path, PATH_MAX, format, ap); + + va_end(ap); + return remove(path); + +#eldef __WIN__ + { + va_list ap; + char path[PATH_MAX]; + struct _finddata_t parent; + intptr_t handle; + char temp[PATH_MAX]; + char *p; + + va_start(ap, format); + + vsnprintf(path, PATH_MAX, format, ap); + + va_end(ap); + + p = path + strlen(path); + while (*p != '\\' && *p != '/' && p > path) p--; + + if ((handle=_findfirst(path,&parent)) == -1L) + { + /* + if there is not files....it's ok. + */ + return 0; + } + + *p = '\0'; + + do + { + if (! (parent.attrib & _A_SUBDIR)) + { + snprintf(temp, PATH_MAX, "%s/%s", path, parent.name); + remove(temp); + } + }while (_findnext(handle,&parent) == 0); + + _findclose(handle); + } +#else + DIR *parent; + struct dirent *entry; + char temp[PATH_MAX]; + va_list ap; + char path[PATH_MAX]; + char *p; + /* + Get path with mask + */ + va_start(ap, format); + + vsnprintf(path, PATH_MAX, format, ap); + + va_end(ap); + + p = path + strlen(path); + while (*p != '\\' && *p != '/' && p > path) p--; + *p = '\0'; + p++; + + parent = opendir(path); + + if (parent == NULL) + { + return; + } + + while((entry = readdir(parent)) != NULL) + { + /* + entry is not directory and entry matches with mask + */ + if (!S_ISDIR(entry->d_type) && !fnmatch(p, entry->d_name,0)) + { + // create long name + snprintf(temp, PATH_MAX, "%s/%s", path, entry->d_name); + // Delete only files + remove(temp); + } + } +#endif + return 0; +} + +/****************************************************************************** + + get_basedir() + +******************************************************************************/ +void get_basedir(char *argv0, char *basedir) +{ + char temp[PATH_MAX]; + char *p; + int position; + + ASSERT(argv0 != NULL); + ASSERT(basedir != NULL); + + strcpy(temp, strlwr(argv0)); + while((p = strchr(temp, '\\')) != NULL) *p = '/'; + + if ((position = strinstr(temp, "/bin/")) != 0) + { + p = temp + position; + *p = '\0'; + strcpy(basedir, temp); + } +} + +#if !defined(__NETWARE__) && !defined(__WIN__) +char *strlwr(const char *s) +{ + return s; +} +#endif + +uint strinstr(reg1 const char *str,reg4 const char *search) +{ + reg2 my_string i,j; + my_string start = (my_string) str; + + skipp: + while (*str != '\0') + { + if (*str++ == *search) + { + i=(my_string) str; j= (my_string) search+1; + while (*j) + if (*i++ != *j++) goto skipp; + return ((uint) (str - start)); + } + } + return (0); +} + +/****************************************************************************** + + remove_empty_file() + +******************************************************************************/ +void remove_empty_file(const char *file_name) +{ + struct stat file; + + if (!stat(file_name,&file)) + { + if (!file.st_size) + remove(file_name); + } +} diff --git a/mysql-test/my_manage.h b/mysql-test/my_manage.h new file mode 100644 index 00000000000..56ba7ce0496 --- /dev/null +++ b/mysql-test/my_manage.h @@ -0,0 +1,135 @@ +/* + Copyright (c) 2002 Novell, Inc. All Rights Reserved. + + 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 +*/ + +#ifndef _MY_MANAGE +#define _MY_MANAGE + +/****************************************************************************** + + includes + +******************************************************************************/ + +#include <stdlib.h> +#ifndef __WIN__ +#include <unistd.h> +#endif +#ifndef __NETWARE__ +#include <string.h> +#include <my_global.h> +#include <m_string.h> + +#ifndef __WIN__ +#define strnicmp strncasecmp +char *strlwr(const char *s); +#else +int my_vsnprintf_(char *to, size_t n, const char* value, ...); +#endif +#endif + +/****************************************************************************** + + macros + +******************************************************************************/ + +#define ARG_BUF 10 +#define TRY_MAX 5 + +#ifdef __WIN__ +#define PATH_MAX _MAX_PATH +#define NAME_MAX _MAX_FNAME +#define kill(A,B) TerminateProcess((HANDLE)A,0) +#define NOT_NEED_PID 0 +#define MASTER_PID 1 +#define SLAVE_PID 2 +#define mysqld_timeout 60000 + +int pid_mode; +bool run_server; +bool skip_first_param; + +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#endif + + +/****************************************************************************** + + structures + +******************************************************************************/ + +typedef struct +{ + + int argc; + char **argv; + + size_t size; + +} arg_list_t; + +#ifdef __WIN__ +typedef int pid_t; +#endif +/****************************************************************************** + + global variables + +******************************************************************************/ + +/****************************************************************************** + + prototypes + +******************************************************************************/ + +void init_args(arg_list_t *); +void add_arg(arg_list_t *, const char *, ...); +void free_args(arg_list_t *); + +#ifndef __WIN__ +int sleep_until_file_exists(char *); +int sleep_until_file_deleted(char *); +#else +int sleep_until_file_exists(HANDLE); +int sleep_until_file_deleted(HANDLE); +#endif +int wait_for_server_start(char *, char *, char *, char *, int,char *); + +#ifndef __WIN__ +int spawn(char *, arg_list_t *, int, char *, char *, char *, char *); +#else +int spawn(char *, arg_list_t *, int , char *, char *, char *, HANDLE *); +#endif + +#ifndef __WIN__ +int stop_server(char *, char *, char *, char *, int, char *,char *); +pid_t get_server_pid(char *); +void kill_server(pid_t pid); +#else +int stop_server(char *, char *, char *, char *, int, HANDLE,char *); +#endif +void del_tree(char *); +int removef(const char *, ...); + +void get_basedir(char *, char *); +void remove_empty_file(const char *file_name); + +#endif /* _MY_MANAGE */ diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 6b40fb3e974..65be9bf9c8e 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -994,9 +994,11 @@ start_master() if [ -n "$1" ] ; then id=`$EXPR $1 + 101`; this_master_myport=`$EXPR $MASTER_MYPORT + $1` + NOT_FIRST_MASTER_EXTRA_OPTS="--skip-innodb" else id=1; this_master_myport=$MASTER_MYPORT + NOT_FIRST_MASTER_EXTRA_OPTS="" fi if [ -z "$DO_BENCH" ] then @@ -1020,7 +1022,8 @@ start_master() --open-files-limit=1024 \ $MASTER_40_ARGS \ $SMALL_SERVER \ - $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT" + $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \ + $NOT_FIRST_MASTER_EXTRA_OPTS" else master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin$1 \ --server-id=$id --rpl-recovery-rank=1 \ @@ -1039,7 +1042,8 @@ start_master() --innodb_data_file_path=ibdata1:50M \ $MASTER_40_ARGS \ $SMALL_SERVER \ - $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT" + $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \ + $NOT_FIRST_MASTER_EXTRA_OPTS" fi CUR_MYERR=$MASTER_MYERR diff --git a/mysql-test/mysql_test_run.c b/mysql-test/mysql_test_run.c new file mode 100644 index 00000000000..6f388fc4a45 --- /dev/null +++ b/mysql-test/mysql_test_run.c @@ -0,0 +1,1728 @@ +/* + Copyright (c) 2002, 2003 Novell, Inc. All Rights Reserved. + + 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 <stdlib.h> +#include <stdio.h> +#include <errno.h> +#ifndef __WIN__ +#include <dirent.h> +#endif +#include <string.h> +#ifdef __NETWARE__ +#include <screen.h> +#include <nks/vm.h> +#endif +#include <ctype.h> +#include <sys/stat.h> +#ifndef __WIN__ +#include <unistd.h> +#endif +#include <fcntl.h> +#ifdef __NETWARE__ +#include <sys/mode.h> +#endif +#ifdef __WIN__ +#include <Shlwapi.h> +#include <direct.h> +#endif + +#include "my_manage.h" + +/****************************************************************************** + + macros + +******************************************************************************/ + +#define HEADER "TEST RESULT \n" +#define DASH "-------------------------------------------------------\n" + +#define NW_TEST_SUFFIX ".nw-test" +#define NW_RESULT_SUFFIX ".nw-result" +#define TEST_SUFFIX ".test" +#define RESULT_SUFFIX ".result" +#define REJECT_SUFFIX ".reject" +#define OUT_SUFFIX ".out" +#define ERR_SUFFIX ".err" + +const char *TEST_PASS = "[ pass ]"; +const char *TEST_SKIP = "[ skip ]"; +const char *TEST_FAIL = "[ fail ]"; +const char *TEST_BAD = "[ bad ]"; +const char *TEST_IGNORE = "[ignore]"; + +/****************************************************************************** + + global variables + +******************************************************************************/ +#ifdef __NETWARE__ +static char base_dir[PATH_MAX] = "sys:/mysql"; +#else +static char base_dir[PATH_MAX] = ".."; +#endif +static char db[PATH_MAX] = "test"; +static char user[PATH_MAX] = "root"; +static char password[PATH_MAX] = ""; + +int master_port = 9306; +int slave_port = 9307; + +#if !defined(__NETWARE__) && !defined(__WIN__) +static char master_socket[PATH_MAX] = "./var/tmp/master.sock"; +static char slave_socket[PATH_MAX] = "./var/tmp/slave.sock"; +#endif + +// comma delimited list of tests to skip or empty string +#ifndef __WIN__ +static char skip_test[PATH_MAX] = " lowercase_table3 , system_mysql_db_fix "; +#else +/* + The most ignore testes contain the calls of system command +*/ +#define MAX_COUNT_TESTES 1024 +/* + lowercase_table3 is disabled by Gerg + system_mysql_db_fix is disabled by Gerg + sp contains a command system + rpl_EE_error contains a command system + rpl_loaddatalocal contains a command system + ndb_autodiscover contains a command system + rpl_rotate_logs contains a command system + repair contains a command system + rpl_trunc_binlog contains a command system + mysqldump contains a command system + rpl000001 makes non-exit loop...temporary skiped +*/ +static char skip_test[PATH_MAX] = " lowercase_table3 , system_mysql_db_fix , sp , rpl_EE_error , rpl_loaddatalocal , ndb_autodiscover , rpl_rotate_logs , repair , rpl_trunc_binlog , mysqldump , rpl000001 "; +#endif +static char ignore_test[PATH_MAX] = ""; + +static char bin_dir[PATH_MAX]; +static char mysql_test_dir[PATH_MAX]; +static char test_dir[PATH_MAX]; +static char mysql_tmp_dir[PATH_MAX]; +static char result_dir[PATH_MAX]; +static char master_dir[PATH_MAX]; +static char slave_dir[PATH_MAX]; +static char lang_dir[PATH_MAX]; +static char char_dir[PATH_MAX]; + +static char mysqladmin_file[PATH_MAX]; +static char mysqld_file[PATH_MAX]; +static char mysqltest_file[PATH_MAX]; +#ifndef __WIN__ +static char master_pid[PATH_MAX]; +static char slave_pid[PATH_MAX]; +static char sh_file[PATH_MAX] = "/bin/sh"; +#else +static HANDLE master_pid; +static HANDLE slave_pid; +#endif + +static char master_opt[PATH_MAX] = ""; +static char slave_opt[PATH_MAX] = ""; + +static char slave_master_info[PATH_MAX] = ""; + +static char master_init_script[PATH_MAX] = ""; +static char slave_init_script[PATH_MAX] = ""; + +// OpenSSL +static char ca_cert[PATH_MAX]; +static char server_cert[PATH_MAX]; +static char server_key[PATH_MAX]; +static char client_cert[PATH_MAX]; +static char client_key[PATH_MAX]; + +int total_skip = 0; +int total_pass = 0; +int total_fail = 0; +int total_test = 0; + +int total_ignore = 0; + +int use_openssl = FALSE; +int master_running = FALSE; +int slave_running = FALSE; +int skip_slave = TRUE; +int single_test = TRUE; + +int restarts = 0; + +FILE *log_fd = NULL; + +/****************************************************************************** + + functions + +******************************************************************************/ + +/****************************************************************************** + + prototypes + +******************************************************************************/ + +void report_stats(); +void install_db(char *); +void mysql_install_db(); +void start_master(); +void start_slave(); +void mysql_start(); +void stop_slave(); +void stop_master(); +void mysql_stop(); +void mysql_restart(); +int read_option(char *, char *); +void run_test(char *); +void setup(char *); +void vlog(const char *, va_list); +void mlog(const char *, ...); +void log_info(const char *, ...); +void log_error(const char *, ...); +void log_errno(const char *, ...); +void die(const char *); +char *str_tok(char *string, const char *delim); +#ifndef __WIN__ +void run_init_script(const char *script_name); +#endif +/****************************************************************************** + + report_stats() + + Report the gathered statistics. + +******************************************************************************/ +void report_stats() +{ + if (total_fail == 0) + { + mlog("\nAll %d test(s) were successful.\n", total_test); + } + else + { + double percent = ((double)total_pass / total_test) * 100; + + mlog("\nFailed %u/%u test(s), %.02f%% successful.\n", + total_fail, total_test, percent); + mlog("\nThe .out and .err files in %s may give you some\n", result_dir); + mlog("hint of what when wrong.\n"); + mlog("\nIf you want to report this error, please first read the documentation\n"); + mlog("at: http://www.mysql.com/doc/M/y/MySQL_test_suite.html\n"); + } +} + +/****************************************************************************** + + install_db() + + Install the a database. + +******************************************************************************/ +void install_db(char *datadir) +{ + arg_list_t al; + int err; + char input[PATH_MAX]; + char output[PATH_MAX]; + char error[PATH_MAX]; + + // input file +#ifdef __NETWARE__ + snprintf(input, PATH_MAX, "%s/bin/init_db.sql", base_dir); +#else + snprintf(input, PATH_MAX, "%s/mysql-test/init_db.sql", base_dir); +#endif + snprintf(output, PATH_MAX, "%s/install.out", datadir); + snprintf(error, PATH_MAX, "%s/install.err", datadir); + + // args + init_args(&al); + add_arg(&al, mysqld_file); + add_arg(&al, "--no-defaults"); + add_arg(&al, "--bootstrap"); + add_arg(&al, "--skip-grant-tables"); + add_arg(&al, "--basedir=%s", base_dir); + add_arg(&al, "--datadir=%s", datadir); + add_arg(&al, "--skip-innodb"); + add_arg(&al, "--skip-bdb"); +#ifndef __NETWARE__ + add_arg(&al, "--character-sets-dir=%s", char_dir); + add_arg(&al, "--language=%s", lang_dir); +#endif + + // spawn + if ((err = spawn(mysqld_file, &al, TRUE, input, output, error, NULL)) != 0) + { + die("Unable to create database."); + } + + // free args + free_args(&al); +} + +/****************************************************************************** + + mysql_install_db() + + Install the test databases. + +******************************************************************************/ +void mysql_install_db() +{ + char temp[PATH_MAX]; + + // var directory + snprintf(temp, PATH_MAX, "%s/var", mysql_test_dir); + + // clean up old direcotry + del_tree(temp); + + // create var directory +#ifndef __WIN__ + mkdir(temp, S_IRWXU); + // create subdirectories + mlog("Creating test-suite folders...\n"); + snprintf(temp, PATH_MAX, "%s/var/run", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/tmp", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/master-data", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/master-data/mysql", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/master-data/test", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/slave-data/mysql", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/slave-data/test", mysql_test_dir); + mkdir(temp, S_IRWXU); +#else + mkdir(temp); + // create subdirectories + mlog("Creating test-suite folders...\n"); + snprintf(temp, PATH_MAX, "%s/var/run", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/tmp", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/master-data", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/master-data/mysql", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/master-data/test", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/slave-data/mysql", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/slave-data/test", mysql_test_dir); + mkdir(temp); +#endif + + // install databases + mlog("Creating test databases for master... \n"); + install_db(master_dir); + mlog("Creating test databases for slave... \n"); + install_db(slave_dir); +} + +/****************************************************************************** + + start_master() + + Start the master server. + +******************************************************************************/ +void start_master() +{ + arg_list_t al; + int err; + char master_out[PATH_MAX]; + char master_err[PATH_MAX]; +// char temp[PATH_MAX]; + char temp2[PATH_MAX]; + + // remove old berkeley db log files that can confuse the server + removef("%s/log.*", master_dir); + + // remove stale binary logs + removef("%s/var/log/*-bin.*", mysql_test_dir); + + // remove stale binary logs + removef("%s/var/log/*.index", mysql_test_dir); + + // remove master.info file + removef("%s/master.info", master_dir); + + // remove relay files + removef("%s/var/log/*relay*", mysql_test_dir); + + // remove relay-log.info file + removef("%s/relay-log.info", master_dir); + + // init script + if (master_init_script[0] != 0) + { +#ifdef __NETWARE__ + // TODO: use the scripts + if (strinstr(master_init_script, "repair_part2-master.sh") != 0) + { + FILE *fp; + + // create an empty index file + snprintf(temp, PATH_MAX, "%s/test/t1.MYI", master_dir); + fp = fopen(temp, "wb+"); + + fputs("1", fp); + + fclose(fp); + } +#elif !defined(__WIN__) + run_init_script(master_init_script); +#endif + } + + // redirection files + snprintf(master_out, PATH_MAX, "%s/var/run/master%u.out", + mysql_test_dir, restarts); + snprintf(master_err, PATH_MAX, "%s/var/run/master%u.err", + mysql_test_dir, restarts); +#ifndef __WIN__ + snprintf(temp2,PATH_MAX,"%s/var",mysql_test_dir); + mkdir(temp2,S_IRWXU); + snprintf(temp2,PATH_MAX,"%s/var/log",mysql_test_dir); + mkdir(temp2,S_IRWXU); +#else + snprintf(temp2,PATH_MAX,"%s/var",mysql_test_dir); + mkdir(temp2); + snprintf(temp2,PATH_MAX,"%s/var/log",mysql_test_dir); + mkdir(temp2); +#endif + // args + init_args(&al); + add_arg(&al, "%s", mysqld_file); + add_arg(&al, "--no-defaults"); + add_arg(&al, "--log-bin=%s/var/log/master-bin",mysql_test_dir); + add_arg(&al, "--server-id=1"); + add_arg(&al, "--basedir=%s", base_dir); + add_arg(&al, "--port=%u", master_port); +#if !defined(__NETWARE__) && !defined(__WIN__) + add_arg(&al, "--socket=%s",master_socket); +#endif + add_arg(&al, "--local-infile"); + add_arg(&al, "--core"); + add_arg(&al, "--datadir=%s", master_dir); +#ifndef __WIN__ + add_arg(&al, "--pid-file=%s", master_pid); +#endif + add_arg(&al, "--character-sets-dir=%s", char_dir); + add_arg(&al, "--tmpdir=%s", mysql_tmp_dir); + add_arg(&al, "--language=%s", lang_dir); +#ifdef DEBUG //only for debug builds + add_arg(&al, "--debug"); +#endif + + if (use_openssl) + { + add_arg(&al, "--ssl-ca=%s", ca_cert); + add_arg(&al, "--ssl-cert=%s", server_cert); + add_arg(&al, "--ssl-key=%s", server_key); + } + + // $MASTER_40_ARGS + add_arg(&al, "--rpl-recovery-rank=1"); + add_arg(&al, "--init-rpl-role=master"); + + // $SMALL_SERVER + add_arg(&al, "-O"); + add_arg(&al, "key_buffer_size=1M"); + add_arg(&al, "-O"); + add_arg(&al, "sort_buffer=256K"); + add_arg(&al, "-O"); + add_arg(&al, "max_heap_table_size=1M"); + + // $EXTRA_MASTER_OPT + if (master_opt[0] != 0) + { + char *p; + + p = (char *)str_tok(master_opt, " \t"); + if (!strstr(master_opt, "timezone")) + { + while (p) + { + add_arg(&al, "%s", p); + p = (char *)str_tok(NULL, " \t"); + } + } + } + + // remove the pid file if it exists +#ifndef __WIN__ + remove(master_pid); +#endif + + // spawn +#ifdef __WIN__ + if ((err= spawn(mysqld_file, &al, FALSE, NULL, master_out, master_err, &master_pid)) == 0) +#else + if ((err= spawn(mysqld_file, &al, FALSE, NULL, master_out, master_err, master_pid)) == 0) +#endif + { + sleep_until_file_exists(master_pid); + + if ((err = wait_for_server_start(bin_dir, mysqladmin_file, user, password, master_port, + mysql_tmp_dir)) == 0) + { + master_running = TRUE; + } + else + { + log_error("The master server went down early."); + } + } + else + { + log_error("Unable to start master server."); + } + + // free_args + free_args(&al); +} + +/****************************************************************************** + + start_slave() + + Start the slave server. + +******************************************************************************/ +void start_slave() +{ + arg_list_t al; + int err; + char slave_out[PATH_MAX]; + char slave_err[PATH_MAX]; + + // skip? + if (skip_slave) return; + + // remove stale binary logs + removef("%s/*-bin.*", slave_dir); + + // remove stale binary logs + removef("%s/*.index", slave_dir); + + // remove master.info file + removef("%s/master.info", slave_dir); + + // remove relay files + removef("%s/var/log/*relay*", mysql_test_dir); + + // remove relay-log.info file + removef("%s/relay-log.info", slave_dir); + + // init script + if (slave_init_script[0] != 0) + { +#ifdef __NETWARE__ + // TODO: use the scripts + if (strinstr(slave_init_script, "rpl000016-slave.sh") != 0) + { + // create empty master.info file + snprintf(temp, PATH_MAX, "%s/master.info", slave_dir); + close(open(temp, O_WRONLY | O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO)); + } + else if (strinstr(slave_init_script, "rpl000017-slave.sh") != 0) + { + FILE *fp; + + // create a master.info file + snprintf(temp, PATH_MAX, "%s/master.info", slave_dir); + fp = fopen(temp, "wb+"); + + fputs("master-bin.000001\n", fp); + fputs("4\n", fp); + fputs("127.0.0.1\n", fp); + fputs("replicate\n", fp); + fputs("aaaaaaaaaaaaaaab\n", fp); + fputs("9306\n", fp); + fputs("1\n", fp); + fputs("0\n", fp); + + fclose(fp); + } + else if (strinstr(slave_init_script, "rpl_rotate_logs-slave.sh") != 0) + { + // create empty master.info file + snprintf(temp, PATH_MAX, "%s/master.info", slave_dir); + close(open(temp, O_WRONLY | O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO)); + } +#elif !defined(__WIN__) + run_init_script(slave_init_script); +#endif + } + + // redirection files + snprintf(slave_out, PATH_MAX, "%s/var/run/slave%u.out", + mysql_test_dir, restarts); + snprintf(slave_err, PATH_MAX, "%s/var/run/slave%u.err", + mysql_test_dir, restarts); + + // args + init_args(&al); + add_arg(&al, "%s", mysqld_file); + add_arg(&al, "--no-defaults"); + add_arg(&al, "--log-bin=slave-bin"); + add_arg(&al, "--relay_log=slave-relay-bin"); + add_arg(&al, "--basedir=%s", base_dir); + add_arg(&al, "--port=%u", slave_port); +#if !defined(__NETWARE__) && !defined(__WIN__) + add_arg(&al, "--socket=%s",slave_socket); +#endif + add_arg(&al, "--datadir=%s", slave_dir); +#ifndef __WIN__ + add_arg(&al, "--pid-file=%s", slave_pid); +#endif + add_arg(&al, "--character-sets-dir=%s", char_dir); + add_arg(&al, "--core"); + add_arg(&al, "--tmpdir=%s", mysql_tmp_dir); + add_arg(&al, "--language=%s", lang_dir); + + add_arg(&al, "--exit-info=256"); + add_arg(&al, "--log-slave-updates"); + add_arg(&al, "--init-rpl-role=slave"); + add_arg(&al, "--skip-innodb"); + add_arg(&al, "--skip-slave-start"); + add_arg(&al, "--slave-load-tmpdir=../../var/tmp"); + + add_arg(&al, "--report-user=%s", user); + add_arg(&al, "--report-host=127.0.0.1"); + add_arg(&al, "--report-port=%u", slave_port); + + add_arg(&al, "--master-retry-count=10"); + add_arg(&al, "-O"); + add_arg(&al, "slave_net_timeout=10"); +#ifdef DEBUG //only for debug builds + add_arg(&al, "--debug"); +#endif + + if (use_openssl) + { + add_arg(&al, "--ssl-ca=%s", ca_cert); + add_arg(&al, "--ssl-cert=%s", server_cert); + add_arg(&al, "--ssl-key=%s", server_key); + } + + // slave master info + if (slave_master_info[0] != 0) + { + char *p; + + p = (char *)str_tok(slave_master_info, " \t"); + + while(p) + { + add_arg(&al, "%s", p); + + p = (char *)str_tok(NULL, " \t"); + } + } + else + { + add_arg(&al, "--master-user=%s", user); + add_arg(&al, "--master-password=%s", password); + add_arg(&al, "--master-host=127.0.0.1"); + add_arg(&al, "--master-port=%u", master_port); + add_arg(&al, "--master-connect-retry=1"); + add_arg(&al, "--server-id=2"); + add_arg(&al, "--rpl-recovery-rank=2"); + } + + // small server + add_arg(&al, "-O"); + add_arg(&al, "key_buffer_size=1M"); + add_arg(&al, "-O"); + add_arg(&al, "sort_buffer=256K"); + add_arg(&al, "-O"); + add_arg(&al, "max_heap_table_size=1M"); + + + // opt args + if (slave_opt[0] != 0) + { + char *p; + + p = (char *)str_tok(slave_opt, " \t"); + + while(p) + { + add_arg(&al, "%s", p); + + p = (char *)str_tok(NULL, " \t"); + } + } + + // remove the pid file if it exists +#ifndef __WIN__ + remove(slave_pid); +#endif + // spawn +#ifdef __WIN__ + if ((err = spawn(mysqld_file, &al, FALSE, NULL, slave_out, slave_err, &slave_pid)) == 0) +#else + if ((err = spawn(mysqld_file, &al, FALSE, NULL, slave_out, slave_err, slave_pid)) == 0) +#endif + { + sleep_until_file_exists(slave_pid); + + if ((err = wait_for_server_start(bin_dir, mysqladmin_file, user, password, slave_port, + mysql_tmp_dir)) == 0) + { + slave_running = TRUE; + } + else + { + log_error("The slave server went down early."); + } + } + else + { + log_error("Unable to start slave server."); + } + + // free args + free_args(&al); +} + +/****************************************************************************** + + mysql_start() + + Start the mysql servers. + +******************************************************************************/ +void mysql_start() +{ +// log_info("Starting the MySQL server(s): %u", ++restarts); + start_master(); + + start_slave(); + + // activate the test screen +#ifdef __NETWARE__ + ActivateScreen(getscreenhandle()); +#endif +} + +/****************************************************************************** + + stop_slave() + + Stop the slave server. + +******************************************************************************/ +void stop_slave() +{ + int err; + + // running? + if (!slave_running) return; + + // stop + if ((err = stop_server(bin_dir, mysqladmin_file, user, password, slave_port, slave_pid, + mysql_tmp_dir)) == 0) + { + slave_running = FALSE; + } + else + { + log_error("Unable to stop slave server."); + } +} + +/****************************************************************************** + + stop_master() + + Stop the master server. + +******************************************************************************/ +void stop_master() +{ + int err; + + // running? + if (!master_running) return; + + if ((err = stop_server(bin_dir, mysqladmin_file, user, password, master_port, master_pid, + mysql_tmp_dir)) == 0) + { + master_running = FALSE; + } + else + { + log_error("Unable to stop master server."); + } +} + +/****************************************************************************** + + mysql_stop() + + Stop the mysql servers. + +******************************************************************************/ +void mysql_stop() +{ + + stop_master(); + + stop_slave(); + + // activate the test screen +#ifdef __NETWARE__ + ActivateScreen(getscreenhandle()); +#endif +} + +/****************************************************************************** + + mysql_restart() + + Restart the mysql servers. + +******************************************************************************/ +void mysql_restart() +{ +// log_info("Restarting the MySQL server(s): %u", ++restarts); + + mysql_stop(); + + mlog(DASH); + + mysql_start(); +} + +/****************************************************************************** + + read_option() + + Read the option file. + +******************************************************************************/ +int read_option(char *opt_file, char *opt) +{ + int fd, err; + char *p; + char buf[PATH_MAX]; + + // copy current option + strncpy(buf, opt, PATH_MAX); + + // open options file + fd = open(opt_file, O_RDONLY); + + err = read(fd, opt, PATH_MAX); + + close(fd); + + if (err > 0) + { + // terminate string + if ((p = strchr(opt, '\n')) != NULL) + { + *p = 0; + + // check for a '\r' + if ((p = strchr(opt, '\r')) != NULL) + { + *p = 0; + } + } + else + { + opt[err] = 0; + } + + // check for $MYSQL_TEST_DIR + if ((p = strstr(opt, "$MYSQL_TEST_DIR")) != NULL) + { + char temp[PATH_MAX]; + + *p = 0; + + strcpy(temp, p + strlen("$MYSQL_TEST_DIR")); + + strcat(opt, mysql_test_dir); + + strcat(opt, temp); + } + // Check for double backslash and replace it with single bakslash + if ((p = strstr(opt, "\\\\")) != NULL) + { + /* bmove is guranteed to work byte by byte */ + bmove(p, p+1, strlen(p+1)); + } + } + else + { + // clear option + *opt = 0; + } + + // compare current option with previous + return strcmp(opt, buf); +} + +/****************************************************************************** + + run_test() + + Run the given test case. + +******************************************************************************/ +void run_test(char *test) +{ + char temp[PATH_MAX]; + const char *rstr; + int skip = FALSE, ignore=FALSE; + int restart = FALSE; + int flag = FALSE; + struct stat info; + + // skip tests in the skip list + snprintf(temp, PATH_MAX, " %s ", test); + skip = (strinstr(skip_test, temp) != 0); + if (skip == FALSE) + ignore = (strinstr(ignore_test, temp) != 0); + + snprintf(master_init_script, PATH_MAX, "%s/%s-master.sh", test_dir, test); + snprintf(slave_init_script, PATH_MAX, "%s/%s-slave.sh", test_dir, test); +#ifdef __WIN__ + if (! stat(master_init_script, &info)) + skip = TRUE; + if (!stat(slave_init_script, &info)) + skip = TRUE; +#endif + if (ignore) + { + // show test + mlog("%-46s ", test); + + // ignore + rstr = TEST_IGNORE; + ++total_ignore; + } + else if (!skip) // skip test? + { + char test_file[PATH_MAX]; + char master_opt_file[PATH_MAX]; + char slave_opt_file[PATH_MAX]; + char slave_master_info_file[PATH_MAX]; + char result_file[PATH_MAX]; + char reject_file[PATH_MAX]; + char out_file[PATH_MAX]; + char err_file[PATH_MAX]; + int err; + arg_list_t al; +#ifdef __WIN__ + /* + Clean test database + */ + removef("%s/test/*.*", master_dir); + removef("%s/test/*.*", slave_dir); + removef("%s/mysqltest/*.*", master_dir); + removef("%s/mysqltest/*.*", slave_dir); + +#endif + // skip slave? + flag = skip_slave; + skip_slave = (strncmp(test, "rpl", 3) != 0); + if (flag != skip_slave) restart = TRUE; + + // create files + snprintf(master_opt_file, PATH_MAX, "%s/%s-master.opt", test_dir, test); + snprintf(slave_opt_file, PATH_MAX, "%s/%s-slave.opt", test_dir, test); + snprintf(slave_master_info_file, PATH_MAX, "%s/%s.slave-mi", test_dir, test); + snprintf(reject_file, PATH_MAX, "%s/%s%s", result_dir, test, REJECT_SUFFIX); + snprintf(out_file, PATH_MAX, "%s/%s%s", result_dir, test, OUT_SUFFIX); + snprintf(err_file, PATH_MAX, "%s/%s%s", result_dir, test, ERR_SUFFIX); + + // netware specific files + snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, NW_TEST_SUFFIX); + if (stat(test_file, &info)) + { + snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, TEST_SUFFIX); + if (access(test_file,0)) + { + printf("Invalid test name %s, %s file not found\n",test,test_file); + return; + } + } + + snprintf(result_file, PATH_MAX, "%s/%s%s", result_dir, test, NW_RESULT_SUFFIX); + if (stat(result_file, &info)) + { + snprintf(result_file, PATH_MAX, "%s/%s%s", result_dir, test, RESULT_SUFFIX); + } + + // init scripts + if (stat(master_init_script, &info)) + master_init_script[0] = 0; + else + restart = TRUE; + + if (stat(slave_init_script, &info)) + slave_init_script[0] = 0; + else + restart = TRUE; + + // read options + if (read_option(master_opt_file, master_opt)) restart = TRUE; + if (read_option(slave_opt_file, slave_opt)) restart = TRUE; + if (read_option(slave_master_info_file, slave_master_info)) restart = TRUE; + + // cleanup previous run + remove(reject_file); + remove(out_file); + remove(err_file); + + // start or restart? + if (!master_running) mysql_start(); + else if (restart) mysql_restart(); + + // let the system stabalize + sleep(1); + + // show test + mlog("%-46s ", test); + + + // args + init_args(&al); + add_arg(&al, "%s", mysqltest_file); + add_arg(&al, "--no-defaults"); + add_arg(&al, "--port=%u", master_port); +#if !defined(__NETWARE__) && !defined(__WIN__) + add_arg(&al, "--socket=%s", master_socket); + add_arg(&al, "--tmpdir=%s", mysql_tmp_dir); +#endif + add_arg(&al, "--database=%s", db); + add_arg(&al, "--user=%s", user); + add_arg(&al, "--password=%s", password); + add_arg(&al, "--silent"); + add_arg(&al, "--basedir=%s/", mysql_test_dir); + add_arg(&al, "--host=127.0.0.1"); + add_arg(&al, "-v"); + add_arg(&al, "-R"); + add_arg(&al, "%s", result_file); + + if (use_openssl) + { + add_arg(&al, "--ssl-ca=%s", ca_cert); + add_arg(&al, "--ssl-cert=%s", client_cert); + add_arg(&al, "--ssl-key=%s", client_key); + } + + // spawn + err = spawn(mysqltest_file, &al, TRUE, test_file, out_file, err_file, NULL); + + // free args + free_args(&al); + + remove_empty_file(out_file); + remove_empty_file(err_file); + + if (err == 0) + { + // pass + rstr = TEST_PASS; + ++total_pass; + + // increment total + ++total_test; + } + else if (err == 2) + { + // skip + rstr = TEST_SKIP; + ++total_skip; + } + else if (err == 1) + { + // fail + rstr = TEST_FAIL; + ++total_fail; + + // increment total + ++total_test; + } + else + { + rstr = TEST_BAD; + } + } + else // early skips + { + // show test + mlog("%-46s ", test); + + // skip + rstr = TEST_SKIP; + ++total_skip; + } + + // result + mlog("%-14s\n", rstr); +} + +/****************************************************************************** + + vlog() + + Log the message. + +******************************************************************************/ +void vlog(const char *format, va_list ap) +{ + vfprintf(stdout, format, ap); + fflush(stdout); + + if (log_fd) + { + vfprintf(log_fd, format, ap); + fflush(log_fd); + } +} + +/****************************************************************************** + + log() + + Log the message. + +******************************************************************************/ +void mlog(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + vlog(format, ap); + + va_end(ap); +} + +/****************************************************************************** + + log_info() + + Log the given information. + +******************************************************************************/ +void log_info(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + mlog("-- INFO : "); + vlog(format, ap); + mlog("\n"); + + va_end(ap); +} + +/****************************************************************************** + + log_error() + + Log the given error. + +******************************************************************************/ +void log_error(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + mlog("-- ERROR: "); + vlog(format, ap); + mlog("\n"); + + va_end(ap); +} + +/****************************************************************************** + + log_errno() + + Log the given error and errno. + +******************************************************************************/ +void log_errno(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + mlog("-- ERROR: (%003u) ", errno); + vlog(format, ap); + mlog("\n"); + + va_end(ap); +} + +/****************************************************************************** + + die() + + Exit the application. + +******************************************************************************/ +void die(const char *msg) +{ + log_error(msg); +#ifdef __NETWARE__ + pressanykey(); +#endif + exit(-1); +} + +/****************************************************************************** + + setup() + + Setup the mysql test enviornment. + +******************************************************************************/ +void setup(char *file) +{ + char temp[PATH_MAX]; + char file_path[PATH_MAX*2]; + char *p; + int position; + + // set the timezone for the timestamp test +#ifdef __WIN__ + _putenv( "TZ=GMT-3" ); +#else + setenv("TZ", "GMT-3", TRUE); +#endif + // find base dir +#ifdef __NETWARE__ + strcpy(temp, strlwr(file)); + while((p = strchr(temp, '\\')) != NULL) *p = '/'; +#else + getcwd(temp, PATH_MAX); + position = strlen(temp); + temp[position] = '/'; + temp[position+1] = 0; +#ifdef __WIN__ + while((p = strchr(temp, '\\')) != NULL) *p = '/'; +#endif +#endif + + if ((position = strinstr(temp, "/mysql-test/")) != 0) + { + p = temp + position - 1; + *p = 0; + strcpy(base_dir, temp); + } + + log_info("Currect directory: %s",base_dir); + +#ifdef __NETWARE__ + // setup paths + snprintf(bin_dir, PATH_MAX, "%s/bin", base_dir); + snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir); + snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir); + snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir); + snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir); + snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir); + snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + snprintf(lang_dir, PATH_MAX, "%s/share/english", base_dir); + snprintf(char_dir, PATH_MAX, "%s/share/charsets", base_dir); + +#ifdef HAVE_OPENSSL + use_openssl = TRUE; +#endif // HAVE_OPENSSL + + // OpenSSL paths + snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir); + snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir); + snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir); + snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir); + snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir); + + // setup files + snprintf(mysqld_file, PATH_MAX, "%s/mysqld", bin_dir); + snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest", bin_dir); + snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir); + snprintf(master_pid, PATH_MAX, "%s/var/run/master.pid", mysql_test_dir); + snprintf(slave_pid, PATH_MAX, "%s/var/run/slave.pid", mysql_test_dir); +#elif __WIN__ + // setup paths +#ifdef _DEBUG + snprintf(bin_dir, PATH_MAX, "%s/client_debug", base_dir); +#else + snprintf(bin_dir, PATH_MAX, "%s/client_release", base_dir); +#endif + snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir); + snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir); + snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir); + snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir); + snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir); + snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + snprintf(lang_dir, PATH_MAX, "%s/share/english", base_dir); + snprintf(char_dir, PATH_MAX, "%s/share/charsets", base_dir); + +#ifdef HAVE_OPENSSL + use_openssl = TRUE; +#endif // HAVE_OPENSSL + + // OpenSSL paths + snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir); + snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir); + snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir); + snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir); + snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir); + + // setup files + snprintf(mysqld_file, PATH_MAX, "%s/mysqld.exe", bin_dir); + snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest.exe", bin_dir); + snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin.exe", bin_dir); +#else + // setup paths + snprintf(bin_dir, PATH_MAX, "%s/client", base_dir); + snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir); + snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir); + snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir); + snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir); + snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir); + snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + snprintf(lang_dir, PATH_MAX, "%s/sql/share/english", base_dir); + snprintf(char_dir, PATH_MAX, "%s/sql/share/charsets", base_dir); + +#ifdef HAVE_OPENSSL + use_openssl = TRUE; +#endif // HAVE_OPENSSL + + // OpenSSL paths + snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir); + snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir); + snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir); + snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir); + snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir); + + // setup files + snprintf(mysqld_file, PATH_MAX, "%s/sql/mysqld", base_dir); + snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest", bin_dir); + snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir); + snprintf(master_pid, PATH_MAX, "%s/var/run/master.pid", mysql_test_dir); + snprintf(slave_pid, PATH_MAX, "%s/var/run/slave.pid", mysql_test_dir); + + snprintf(master_socket,PATH_MAX, "%s/var/tmp/master.sock", mysql_test_dir); + snprintf(slave_socket,PATH_MAX, "%s/var/tmp/slave.sock", mysql_test_dir); + +#endif + // create log file + snprintf(temp, PATH_MAX, "%s/mysql-test-run.log", mysql_test_dir); + if ((log_fd = fopen(temp, "w+")) == NULL) + { + log_errno("Unable to create log file."); + } + + // prepare skip test list + while((p = strchr(skip_test, ',')) != NULL) *p = ' '; + strcpy(temp, strlwr(skip_test)); + snprintf(skip_test, PATH_MAX, " %s ", temp); + + // environment +#ifdef __NETWARE__ + setenv("MYSQL_TEST_DIR", mysql_test_dir, 1); + snprintf(file_path, PATH_MAX*2, "%s/client/mysqldump --no-defaults -u root --port=%u", bin_dir, master_port); + setenv("MYSQL_DUMP", file_path, 1); + snprintf(file_path, PATH_MAX*2, "%s/client/mysqlbinlog --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir); + setenv("MYSQL_BINLOG", file_path, 1); +#elif __WIN__ + snprintf(file_path,MAX_PATH,"MYSQL_TEST_DIR=%s",mysql_test_dir); + _putenv(file_path); + snprintf(file_path, PATH_MAX*2, "MYSQL_DUMP=%s/mysqldump.exe --no-defaults -u root --port=%u", bin_dir, master_port); + _putenv(file_path); + snprintf(file_path, PATH_MAX*2, "MYSQL_BINLOG=%s/mysqlbinlog.exe --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir); + _putenv(file_path); +#else + setenv("MYSQL_TEST_DIR", mysql_test_dir, 1); + snprintf(file_path, PATH_MAX*2, "%s/mysqldump --no-defaults -u root --port=%u --socket=%s", bin_dir, master_port, master_socket); + setenv("MYSQL_DUMP", file_path, 1); + snprintf(file_path, PATH_MAX*2, "%s/mysqlbinlog --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir); + setenv("MYSQL_BINLOG", file_path, 1); +#endif + +#ifndef __WIN__ + setenv("MASTER_MYPORT", "9306", 1); + setenv("SLAVE_MYPORT", "9307", 1); + setenv("MYSQL_TCP_PORT", "3306", 1); +#else + _putenv("MASTER_MYPORT=9306"); + _putenv("SLAVE_MYPORT=9307"); + _putenv("MYSQL_TCP_PORT=3306"); +#endif + +} + +/****************************************************************************** + + main() + +******************************************************************************/ +int main(int argc, char **argv) +{ + int is_ignore_list = 0; + // setup + setup(argv[0]); + + /* The --ignore option is comma saperated list of test cases to skip and + should be very first command line option to the test suite. + + The usage is now: + mysql_test_run --ignore=test1,test2 test3 test4 + where test1 and test2 are test cases to ignore + and test3 and test4 are test cases to run. + */ + if (argc >= 2 && !strnicmp(argv[1], "--ignore=", sizeof("--ignore=")-1)) + { + char *temp, *token; + temp= strdup(strchr(argv[1],'=') + 1); + for (token=str_tok(temp, ","); token != NULL; token=str_tok(NULL, ",")) + { + if (strlen(ignore_test) + strlen(token) + 2 <= PATH_MAX-1) + sprintf(ignore_test+strlen(ignore_test), " %s ", token); + else + { + free(temp); + die("ignore list too long."); + } + } + free(temp); + is_ignore_list = 1; + } + // header +#ifndef __WIN__ + mlog("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE); +#else + mlog("MySQL Server ---, for %s (%s)\n\n", SYSTEM_TYPE, MACHINE_TYPE); +#endif + + mlog("Initializing Tests...\n"); + + // install test databases + mysql_install_db(); + + mlog("Starting Tests...\n"); + + mlog("\n"); + mlog(HEADER); + mlog(DASH); + + if ( argc > 1 + is_ignore_list ) + { + int i; + + // single test + single_test = TRUE; + + for (i = 1 + is_ignore_list; i < argc; i++) + { + // run given test + run_test(argv[i]); + } + } + else + { + // run all tests +#ifndef __WIN__ + struct dirent **namelist; + int i,n; + char test[NAME_MAX]; + char *p; + int position; + + n = scandir(test_dir, &namelist, 0, alphasort); + if (n < 0) + die("Unable to open tests directory."); + else + { + for (i = 0; i < n; i++) + { + strcpy(test, strlwr(namelist[i]->d_name)); + // find the test suffix + if ((position = strinstr(test, TEST_SUFFIX)) != 0) + { + p = test + position - 1; + // null terminate at the suffix + *p = 0; + // run test + run_test(test); + } + free(namelist[n]); + } + free(namelist); + } +#else + struct _finddata_t dir; + intptr_t handle; + char test[NAME_MAX]; + char mask[PATH_MAX]; + char *p; + int position; + char **names = 0; + char **testes = 0; + int name_index; + int index; + + // single test + single_test = FALSE; + + snprintf(mask,MAX_PATH,"%s/*.test",test_dir); + + if ((handle=_findfirst(mask,&dir)) == -1L) + { + die("Unable to open tests directory."); + } + + names = malloc(MAX_COUNT_TESTES*4); + testes = names; + name_index = 0; + + do + { + if (!(dir.attrib & _A_SUBDIR)) + { + strcpy(test, strlwr(dir.name)); + + // find the test suffix + if ((position = strinstr(test, TEST_SUFFIX)) != 0) + { + p = test + position - 1; + // null terminate at the suffix + *p = 0; + + // insert test + *names = malloc(PATH_MAX); + strcpy(*names,test); + names++; + name_index++; + } + } + }while (_findnext(handle,&dir) == 0); + + _findclose(handle); + + qsort( (void *)testes, name_index, sizeof( char * ), compare ); + + for (index = 0; index <= name_index; index++) + { + run_test(testes[index]); + free(testes[index]); + } + + free(testes); +#endif + } + + // stop server + mysql_stop(); + + mlog(DASH); + mlog("\n"); + + mlog("Ending Tests...\n"); + + // report stats + report_stats(); + + // close log + if (log_fd) fclose(log_fd); + + // keep results up +#ifdef __NETWARE__ + pressanykey(); +#endif + return 0; +} + + +/* + Synopsis: + This function breaks the string into a sequence of tokens. The difference + between this function and strtok is that it respects the quoted string i.e. + it skips any delimiter character within the quoted part of the string. + It return tokens by eliminating quote character. It modifies the input string + passed. It will work with whitespace delimeter but may not work properly with + other delimeter. If the delimeter will contain any quote character, then + function will not tokenize and will return null string. + e.g. if input string is + --init-slave="set global max_connections=500" --skip-external-locking + then the output will two string i.e. + --init-slave=set global max_connections=500 + --skip-external-locking + +Arguments: + string: input string + delim: set of delimiter character +Output: + return the null terminated token of NULL. +*/ + + +char *str_tok(char *string, const char *delim) +{ + char *token; /* current token received from strtok */ + char *qt_token; /* token delimeted by the matching pair of quote */ + /* + if there are any quote chars found in the token then this variable + will hold the concatenated string to return to the caller + */ + char *ptr_token=NULL; + /* pointer to the quote character in the token from strtok */ + char *ptr_quote=NULL; + + /* See if the delimeter contains any quote character */ + if (strchr(delim,'\'') || strchr(delim,'\"')) + return NULL; + + /* repeate till we are getting some token from strtok */ + while ((token = (char*)strtok(string, delim) ) != NULL) + { + /* + make the input string NULL so that next time onward strtok can + be called with NULL input string. + */ + string = NULL; + /* + We don't need to remove any quote character for Windows version + */ +#ifndef __WIN__ + /* check if the current token contain double quote character*/ + if ((ptr_quote = (char*)strchr(token,'\"')) != NULL) + { + /* + get the matching the matching double quote in the remaining + input string + */ + qt_token = (char*)strtok(NULL,"\""); + } + /* check if the current token contain single quote character*/ + else if ((ptr_quote = (char*)strchr(token,'\'')) != NULL) + { + /* + get the matching the matching single quote in the remaining + input string + */ + qt_token = (char*)strtok(NULL,"\'"); + } +#endif + /* + if the current token does not contains any quote character then + return to the caller. + */ + if (ptr_quote == NULL) + { + /* + if there is any earlier token i.e. ptr_token then append the + current token in it and return it else return the current + token directly + */ + return ptr_token ? strcat(ptr_token,token) : token; + } + + /* + remove the quote character i.e. make NULL so that the token will + be devided in two part and later both part can be concatenated + and hence quote will be removed + */ + *ptr_quote= 0; + + /* check if ptr_token has been initialized or not */ + if (ptr_token == NULL) + { + /* initialize the ptr_token with current token */ + ptr_token= token; + /* copy entire string between matching pair of quote*/ + sprintf(ptr_token+strlen(ptr_token),"%s %s", ptr_quote+1, qt_token); + } + else + { + /* + copy the current token and entire string between matching pair + of quote + */ + if (qt_token == NULL) + { + sprintf(ptr_token+strlen(ptr_token),"%s%s", token, ptr_quote+1); + } + else + { + sprintf(ptr_token+strlen(ptr_token),"%s%s %s", token, ptr_quote+1, + qt_token ); + } + } + } + + /* return the concatenated token */ + return ptr_token; +} + +#ifndef __WIN__ + +/* + Synopsis: + This function run scripts files on Linux and Netware + +Arguments: + script_name: name of script file + +Output: + nothing +*/ +void run_init_script(const char *script_name) +{ + arg_list_t al; + int err; + + // args + init_args(&al); + add_arg(&al, sh_file); + add_arg(&al, script_name); + + // spawn + if ((err = spawn(sh_file, &al, TRUE, NULL, NULL, NULL, NULL)) != 0) + { + die("Unable to run script."); + } + + // free args + free_args(&al); +} +#endif diff --git a/mysql-test/mysql_test_run_new.c b/mysql-test/mysql_test_run_new.c new file mode 100644 index 00000000000..6f388fc4a45 --- /dev/null +++ b/mysql-test/mysql_test_run_new.c @@ -0,0 +1,1728 @@ +/* + Copyright (c) 2002, 2003 Novell, Inc. All Rights Reserved. + + 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 <stdlib.h> +#include <stdio.h> +#include <errno.h> +#ifndef __WIN__ +#include <dirent.h> +#endif +#include <string.h> +#ifdef __NETWARE__ +#include <screen.h> +#include <nks/vm.h> +#endif +#include <ctype.h> +#include <sys/stat.h> +#ifndef __WIN__ +#include <unistd.h> +#endif +#include <fcntl.h> +#ifdef __NETWARE__ +#include <sys/mode.h> +#endif +#ifdef __WIN__ +#include <Shlwapi.h> +#include <direct.h> +#endif + +#include "my_manage.h" + +/****************************************************************************** + + macros + +******************************************************************************/ + +#define HEADER "TEST RESULT \n" +#define DASH "-------------------------------------------------------\n" + +#define NW_TEST_SUFFIX ".nw-test" +#define NW_RESULT_SUFFIX ".nw-result" +#define TEST_SUFFIX ".test" +#define RESULT_SUFFIX ".result" +#define REJECT_SUFFIX ".reject" +#define OUT_SUFFIX ".out" +#define ERR_SUFFIX ".err" + +const char *TEST_PASS = "[ pass ]"; +const char *TEST_SKIP = "[ skip ]"; +const char *TEST_FAIL = "[ fail ]"; +const char *TEST_BAD = "[ bad ]"; +const char *TEST_IGNORE = "[ignore]"; + +/****************************************************************************** + + global variables + +******************************************************************************/ +#ifdef __NETWARE__ +static char base_dir[PATH_MAX] = "sys:/mysql"; +#else +static char base_dir[PATH_MAX] = ".."; +#endif +static char db[PATH_MAX] = "test"; +static char user[PATH_MAX] = "root"; +static char password[PATH_MAX] = ""; + +int master_port = 9306; +int slave_port = 9307; + +#if !defined(__NETWARE__) && !defined(__WIN__) +static char master_socket[PATH_MAX] = "./var/tmp/master.sock"; +static char slave_socket[PATH_MAX] = "./var/tmp/slave.sock"; +#endif + +// comma delimited list of tests to skip or empty string +#ifndef __WIN__ +static char skip_test[PATH_MAX] = " lowercase_table3 , system_mysql_db_fix "; +#else +/* + The most ignore testes contain the calls of system command +*/ +#define MAX_COUNT_TESTES 1024 +/* + lowercase_table3 is disabled by Gerg + system_mysql_db_fix is disabled by Gerg + sp contains a command system + rpl_EE_error contains a command system + rpl_loaddatalocal contains a command system + ndb_autodiscover contains a command system + rpl_rotate_logs contains a command system + repair contains a command system + rpl_trunc_binlog contains a command system + mysqldump contains a command system + rpl000001 makes non-exit loop...temporary skiped +*/ +static char skip_test[PATH_MAX] = " lowercase_table3 , system_mysql_db_fix , sp , rpl_EE_error , rpl_loaddatalocal , ndb_autodiscover , rpl_rotate_logs , repair , rpl_trunc_binlog , mysqldump , rpl000001 "; +#endif +static char ignore_test[PATH_MAX] = ""; + +static char bin_dir[PATH_MAX]; +static char mysql_test_dir[PATH_MAX]; +static char test_dir[PATH_MAX]; +static char mysql_tmp_dir[PATH_MAX]; +static char result_dir[PATH_MAX]; +static char master_dir[PATH_MAX]; +static char slave_dir[PATH_MAX]; +static char lang_dir[PATH_MAX]; +static char char_dir[PATH_MAX]; + +static char mysqladmin_file[PATH_MAX]; +static char mysqld_file[PATH_MAX]; +static char mysqltest_file[PATH_MAX]; +#ifndef __WIN__ +static char master_pid[PATH_MAX]; +static char slave_pid[PATH_MAX]; +static char sh_file[PATH_MAX] = "/bin/sh"; +#else +static HANDLE master_pid; +static HANDLE slave_pid; +#endif + +static char master_opt[PATH_MAX] = ""; +static char slave_opt[PATH_MAX] = ""; + +static char slave_master_info[PATH_MAX] = ""; + +static char master_init_script[PATH_MAX] = ""; +static char slave_init_script[PATH_MAX] = ""; + +// OpenSSL +static char ca_cert[PATH_MAX]; +static char server_cert[PATH_MAX]; +static char server_key[PATH_MAX]; +static char client_cert[PATH_MAX]; +static char client_key[PATH_MAX]; + +int total_skip = 0; +int total_pass = 0; +int total_fail = 0; +int total_test = 0; + +int total_ignore = 0; + +int use_openssl = FALSE; +int master_running = FALSE; +int slave_running = FALSE; +int skip_slave = TRUE; +int single_test = TRUE; + +int restarts = 0; + +FILE *log_fd = NULL; + +/****************************************************************************** + + functions + +******************************************************************************/ + +/****************************************************************************** + + prototypes + +******************************************************************************/ + +void report_stats(); +void install_db(char *); +void mysql_install_db(); +void start_master(); +void start_slave(); +void mysql_start(); +void stop_slave(); +void stop_master(); +void mysql_stop(); +void mysql_restart(); +int read_option(char *, char *); +void run_test(char *); +void setup(char *); +void vlog(const char *, va_list); +void mlog(const char *, ...); +void log_info(const char *, ...); +void log_error(const char *, ...); +void log_errno(const char *, ...); +void die(const char *); +char *str_tok(char *string, const char *delim); +#ifndef __WIN__ +void run_init_script(const char *script_name); +#endif +/****************************************************************************** + + report_stats() + + Report the gathered statistics. + +******************************************************************************/ +void report_stats() +{ + if (total_fail == 0) + { + mlog("\nAll %d test(s) were successful.\n", total_test); + } + else + { + double percent = ((double)total_pass / total_test) * 100; + + mlog("\nFailed %u/%u test(s), %.02f%% successful.\n", + total_fail, total_test, percent); + mlog("\nThe .out and .err files in %s may give you some\n", result_dir); + mlog("hint of what when wrong.\n"); + mlog("\nIf you want to report this error, please first read the documentation\n"); + mlog("at: http://www.mysql.com/doc/M/y/MySQL_test_suite.html\n"); + } +} + +/****************************************************************************** + + install_db() + + Install the a database. + +******************************************************************************/ +void install_db(char *datadir) +{ + arg_list_t al; + int err; + char input[PATH_MAX]; + char output[PATH_MAX]; + char error[PATH_MAX]; + + // input file +#ifdef __NETWARE__ + snprintf(input, PATH_MAX, "%s/bin/init_db.sql", base_dir); +#else + snprintf(input, PATH_MAX, "%s/mysql-test/init_db.sql", base_dir); +#endif + snprintf(output, PATH_MAX, "%s/install.out", datadir); + snprintf(error, PATH_MAX, "%s/install.err", datadir); + + // args + init_args(&al); + add_arg(&al, mysqld_file); + add_arg(&al, "--no-defaults"); + add_arg(&al, "--bootstrap"); + add_arg(&al, "--skip-grant-tables"); + add_arg(&al, "--basedir=%s", base_dir); + add_arg(&al, "--datadir=%s", datadir); + add_arg(&al, "--skip-innodb"); + add_arg(&al, "--skip-bdb"); +#ifndef __NETWARE__ + add_arg(&al, "--character-sets-dir=%s", char_dir); + add_arg(&al, "--language=%s", lang_dir); +#endif + + // spawn + if ((err = spawn(mysqld_file, &al, TRUE, input, output, error, NULL)) != 0) + { + die("Unable to create database."); + } + + // free args + free_args(&al); +} + +/****************************************************************************** + + mysql_install_db() + + Install the test databases. + +******************************************************************************/ +void mysql_install_db() +{ + char temp[PATH_MAX]; + + // var directory + snprintf(temp, PATH_MAX, "%s/var", mysql_test_dir); + + // clean up old direcotry + del_tree(temp); + + // create var directory +#ifndef __WIN__ + mkdir(temp, S_IRWXU); + // create subdirectories + mlog("Creating test-suite folders...\n"); + snprintf(temp, PATH_MAX, "%s/var/run", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/tmp", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/master-data", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/master-data/mysql", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/master-data/test", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/slave-data/mysql", mysql_test_dir); + mkdir(temp, S_IRWXU); + snprintf(temp, PATH_MAX, "%s/var/slave-data/test", mysql_test_dir); + mkdir(temp, S_IRWXU); +#else + mkdir(temp); + // create subdirectories + mlog("Creating test-suite folders...\n"); + snprintf(temp, PATH_MAX, "%s/var/run", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/tmp", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/master-data", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/master-data/mysql", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/master-data/test", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/slave-data/mysql", mysql_test_dir); + mkdir(temp); + snprintf(temp, PATH_MAX, "%s/var/slave-data/test", mysql_test_dir); + mkdir(temp); +#endif + + // install databases + mlog("Creating test databases for master... \n"); + install_db(master_dir); + mlog("Creating test databases for slave... \n"); + install_db(slave_dir); +} + +/****************************************************************************** + + start_master() + + Start the master server. + +******************************************************************************/ +void start_master() +{ + arg_list_t al; + int err; + char master_out[PATH_MAX]; + char master_err[PATH_MAX]; +// char temp[PATH_MAX]; + char temp2[PATH_MAX]; + + // remove old berkeley db log files that can confuse the server + removef("%s/log.*", master_dir); + + // remove stale binary logs + removef("%s/var/log/*-bin.*", mysql_test_dir); + + // remove stale binary logs + removef("%s/var/log/*.index", mysql_test_dir); + + // remove master.info file + removef("%s/master.info", master_dir); + + // remove relay files + removef("%s/var/log/*relay*", mysql_test_dir); + + // remove relay-log.info file + removef("%s/relay-log.info", master_dir); + + // init script + if (master_init_script[0] != 0) + { +#ifdef __NETWARE__ + // TODO: use the scripts + if (strinstr(master_init_script, "repair_part2-master.sh") != 0) + { + FILE *fp; + + // create an empty index file + snprintf(temp, PATH_MAX, "%s/test/t1.MYI", master_dir); + fp = fopen(temp, "wb+"); + + fputs("1", fp); + + fclose(fp); + } +#elif !defined(__WIN__) + run_init_script(master_init_script); +#endif + } + + // redirection files + snprintf(master_out, PATH_MAX, "%s/var/run/master%u.out", + mysql_test_dir, restarts); + snprintf(master_err, PATH_MAX, "%s/var/run/master%u.err", + mysql_test_dir, restarts); +#ifndef __WIN__ + snprintf(temp2,PATH_MAX,"%s/var",mysql_test_dir); + mkdir(temp2,S_IRWXU); + snprintf(temp2,PATH_MAX,"%s/var/log",mysql_test_dir); + mkdir(temp2,S_IRWXU); +#else + snprintf(temp2,PATH_MAX,"%s/var",mysql_test_dir); + mkdir(temp2); + snprintf(temp2,PATH_MAX,"%s/var/log",mysql_test_dir); + mkdir(temp2); +#endif + // args + init_args(&al); + add_arg(&al, "%s", mysqld_file); + add_arg(&al, "--no-defaults"); + add_arg(&al, "--log-bin=%s/var/log/master-bin",mysql_test_dir); + add_arg(&al, "--server-id=1"); + add_arg(&al, "--basedir=%s", base_dir); + add_arg(&al, "--port=%u", master_port); +#if !defined(__NETWARE__) && !defined(__WIN__) + add_arg(&al, "--socket=%s",master_socket); +#endif + add_arg(&al, "--local-infile"); + add_arg(&al, "--core"); + add_arg(&al, "--datadir=%s", master_dir); +#ifndef __WIN__ + add_arg(&al, "--pid-file=%s", master_pid); +#endif + add_arg(&al, "--character-sets-dir=%s", char_dir); + add_arg(&al, "--tmpdir=%s", mysql_tmp_dir); + add_arg(&al, "--language=%s", lang_dir); +#ifdef DEBUG //only for debug builds + add_arg(&al, "--debug"); +#endif + + if (use_openssl) + { + add_arg(&al, "--ssl-ca=%s", ca_cert); + add_arg(&al, "--ssl-cert=%s", server_cert); + add_arg(&al, "--ssl-key=%s", server_key); + } + + // $MASTER_40_ARGS + add_arg(&al, "--rpl-recovery-rank=1"); + add_arg(&al, "--init-rpl-role=master"); + + // $SMALL_SERVER + add_arg(&al, "-O"); + add_arg(&al, "key_buffer_size=1M"); + add_arg(&al, "-O"); + add_arg(&al, "sort_buffer=256K"); + add_arg(&al, "-O"); + add_arg(&al, "max_heap_table_size=1M"); + + // $EXTRA_MASTER_OPT + if (master_opt[0] != 0) + { + char *p; + + p = (char *)str_tok(master_opt, " \t"); + if (!strstr(master_opt, "timezone")) + { + while (p) + { + add_arg(&al, "%s", p); + p = (char *)str_tok(NULL, " \t"); + } + } + } + + // remove the pid file if it exists +#ifndef __WIN__ + remove(master_pid); +#endif + + // spawn +#ifdef __WIN__ + if ((err= spawn(mysqld_file, &al, FALSE, NULL, master_out, master_err, &master_pid)) == 0) +#else + if ((err= spawn(mysqld_file, &al, FALSE, NULL, master_out, master_err, master_pid)) == 0) +#endif + { + sleep_until_file_exists(master_pid); + + if ((err = wait_for_server_start(bin_dir, mysqladmin_file, user, password, master_port, + mysql_tmp_dir)) == 0) + { + master_running = TRUE; + } + else + { + log_error("The master server went down early."); + } + } + else + { + log_error("Unable to start master server."); + } + + // free_args + free_args(&al); +} + +/****************************************************************************** + + start_slave() + + Start the slave server. + +******************************************************************************/ +void start_slave() +{ + arg_list_t al; + int err; + char slave_out[PATH_MAX]; + char slave_err[PATH_MAX]; + + // skip? + if (skip_slave) return; + + // remove stale binary logs + removef("%s/*-bin.*", slave_dir); + + // remove stale binary logs + removef("%s/*.index", slave_dir); + + // remove master.info file + removef("%s/master.info", slave_dir); + + // remove relay files + removef("%s/var/log/*relay*", mysql_test_dir); + + // remove relay-log.info file + removef("%s/relay-log.info", slave_dir); + + // init script + if (slave_init_script[0] != 0) + { +#ifdef __NETWARE__ + // TODO: use the scripts + if (strinstr(slave_init_script, "rpl000016-slave.sh") != 0) + { + // create empty master.info file + snprintf(temp, PATH_MAX, "%s/master.info", slave_dir); + close(open(temp, O_WRONLY | O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO)); + } + else if (strinstr(slave_init_script, "rpl000017-slave.sh") != 0) + { + FILE *fp; + + // create a master.info file + snprintf(temp, PATH_MAX, "%s/master.info", slave_dir); + fp = fopen(temp, "wb+"); + + fputs("master-bin.000001\n", fp); + fputs("4\n", fp); + fputs("127.0.0.1\n", fp); + fputs("replicate\n", fp); + fputs("aaaaaaaaaaaaaaab\n", fp); + fputs("9306\n", fp); + fputs("1\n", fp); + fputs("0\n", fp); + + fclose(fp); + } + else if (strinstr(slave_init_script, "rpl_rotate_logs-slave.sh") != 0) + { + // create empty master.info file + snprintf(temp, PATH_MAX, "%s/master.info", slave_dir); + close(open(temp, O_WRONLY | O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO)); + } +#elif !defined(__WIN__) + run_init_script(slave_init_script); +#endif + } + + // redirection files + snprintf(slave_out, PATH_MAX, "%s/var/run/slave%u.out", + mysql_test_dir, restarts); + snprintf(slave_err, PATH_MAX, "%s/var/run/slave%u.err", + mysql_test_dir, restarts); + + // args + init_args(&al); + add_arg(&al, "%s", mysqld_file); + add_arg(&al, "--no-defaults"); + add_arg(&al, "--log-bin=slave-bin"); + add_arg(&al, "--relay_log=slave-relay-bin"); + add_arg(&al, "--basedir=%s", base_dir); + add_arg(&al, "--port=%u", slave_port); +#if !defined(__NETWARE__) && !defined(__WIN__) + add_arg(&al, "--socket=%s",slave_socket); +#endif + add_arg(&al, "--datadir=%s", slave_dir); +#ifndef __WIN__ + add_arg(&al, "--pid-file=%s", slave_pid); +#endif + add_arg(&al, "--character-sets-dir=%s", char_dir); + add_arg(&al, "--core"); + add_arg(&al, "--tmpdir=%s", mysql_tmp_dir); + add_arg(&al, "--language=%s", lang_dir); + + add_arg(&al, "--exit-info=256"); + add_arg(&al, "--log-slave-updates"); + add_arg(&al, "--init-rpl-role=slave"); + add_arg(&al, "--skip-innodb"); + add_arg(&al, "--skip-slave-start"); + add_arg(&al, "--slave-load-tmpdir=../../var/tmp"); + + add_arg(&al, "--report-user=%s", user); + add_arg(&al, "--report-host=127.0.0.1"); + add_arg(&al, "--report-port=%u", slave_port); + + add_arg(&al, "--master-retry-count=10"); + add_arg(&al, "-O"); + add_arg(&al, "slave_net_timeout=10"); +#ifdef DEBUG //only for debug builds + add_arg(&al, "--debug"); +#endif + + if (use_openssl) + { + add_arg(&al, "--ssl-ca=%s", ca_cert); + add_arg(&al, "--ssl-cert=%s", server_cert); + add_arg(&al, "--ssl-key=%s", server_key); + } + + // slave master info + if (slave_master_info[0] != 0) + { + char *p; + + p = (char *)str_tok(slave_master_info, " \t"); + + while(p) + { + add_arg(&al, "%s", p); + + p = (char *)str_tok(NULL, " \t"); + } + } + else + { + add_arg(&al, "--master-user=%s", user); + add_arg(&al, "--master-password=%s", password); + add_arg(&al, "--master-host=127.0.0.1"); + add_arg(&al, "--master-port=%u", master_port); + add_arg(&al, "--master-connect-retry=1"); + add_arg(&al, "--server-id=2"); + add_arg(&al, "--rpl-recovery-rank=2"); + } + + // small server + add_arg(&al, "-O"); + add_arg(&al, "key_buffer_size=1M"); + add_arg(&al, "-O"); + add_arg(&al, "sort_buffer=256K"); + add_arg(&al, "-O"); + add_arg(&al, "max_heap_table_size=1M"); + + + // opt args + if (slave_opt[0] != 0) + { + char *p; + + p = (char *)str_tok(slave_opt, " \t"); + + while(p) + { + add_arg(&al, "%s", p); + + p = (char *)str_tok(NULL, " \t"); + } + } + + // remove the pid file if it exists +#ifndef __WIN__ + remove(slave_pid); +#endif + // spawn +#ifdef __WIN__ + if ((err = spawn(mysqld_file, &al, FALSE, NULL, slave_out, slave_err, &slave_pid)) == 0) +#else + if ((err = spawn(mysqld_file, &al, FALSE, NULL, slave_out, slave_err, slave_pid)) == 0) +#endif + { + sleep_until_file_exists(slave_pid); + + if ((err = wait_for_server_start(bin_dir, mysqladmin_file, user, password, slave_port, + mysql_tmp_dir)) == 0) + { + slave_running = TRUE; + } + else + { + log_error("The slave server went down early."); + } + } + else + { + log_error("Unable to start slave server."); + } + + // free args + free_args(&al); +} + +/****************************************************************************** + + mysql_start() + + Start the mysql servers. + +******************************************************************************/ +void mysql_start() +{ +// log_info("Starting the MySQL server(s): %u", ++restarts); + start_master(); + + start_slave(); + + // activate the test screen +#ifdef __NETWARE__ + ActivateScreen(getscreenhandle()); +#endif +} + +/****************************************************************************** + + stop_slave() + + Stop the slave server. + +******************************************************************************/ +void stop_slave() +{ + int err; + + // running? + if (!slave_running) return; + + // stop + if ((err = stop_server(bin_dir, mysqladmin_file, user, password, slave_port, slave_pid, + mysql_tmp_dir)) == 0) + { + slave_running = FALSE; + } + else + { + log_error("Unable to stop slave server."); + } +} + +/****************************************************************************** + + stop_master() + + Stop the master server. + +******************************************************************************/ +void stop_master() +{ + int err; + + // running? + if (!master_running) return; + + if ((err = stop_server(bin_dir, mysqladmin_file, user, password, master_port, master_pid, + mysql_tmp_dir)) == 0) + { + master_running = FALSE; + } + else + { + log_error("Unable to stop master server."); + } +} + +/****************************************************************************** + + mysql_stop() + + Stop the mysql servers. + +******************************************************************************/ +void mysql_stop() +{ + + stop_master(); + + stop_slave(); + + // activate the test screen +#ifdef __NETWARE__ + ActivateScreen(getscreenhandle()); +#endif +} + +/****************************************************************************** + + mysql_restart() + + Restart the mysql servers. + +******************************************************************************/ +void mysql_restart() +{ +// log_info("Restarting the MySQL server(s): %u", ++restarts); + + mysql_stop(); + + mlog(DASH); + + mysql_start(); +} + +/****************************************************************************** + + read_option() + + Read the option file. + +******************************************************************************/ +int read_option(char *opt_file, char *opt) +{ + int fd, err; + char *p; + char buf[PATH_MAX]; + + // copy current option + strncpy(buf, opt, PATH_MAX); + + // open options file + fd = open(opt_file, O_RDONLY); + + err = read(fd, opt, PATH_MAX); + + close(fd); + + if (err > 0) + { + // terminate string + if ((p = strchr(opt, '\n')) != NULL) + { + *p = 0; + + // check for a '\r' + if ((p = strchr(opt, '\r')) != NULL) + { + *p = 0; + } + } + else + { + opt[err] = 0; + } + + // check for $MYSQL_TEST_DIR + if ((p = strstr(opt, "$MYSQL_TEST_DIR")) != NULL) + { + char temp[PATH_MAX]; + + *p = 0; + + strcpy(temp, p + strlen("$MYSQL_TEST_DIR")); + + strcat(opt, mysql_test_dir); + + strcat(opt, temp); + } + // Check for double backslash and replace it with single bakslash + if ((p = strstr(opt, "\\\\")) != NULL) + { + /* bmove is guranteed to work byte by byte */ + bmove(p, p+1, strlen(p+1)); + } + } + else + { + // clear option + *opt = 0; + } + + // compare current option with previous + return strcmp(opt, buf); +} + +/****************************************************************************** + + run_test() + + Run the given test case. + +******************************************************************************/ +void run_test(char *test) +{ + char temp[PATH_MAX]; + const char *rstr; + int skip = FALSE, ignore=FALSE; + int restart = FALSE; + int flag = FALSE; + struct stat info; + + // skip tests in the skip list + snprintf(temp, PATH_MAX, " %s ", test); + skip = (strinstr(skip_test, temp) != 0); + if (skip == FALSE) + ignore = (strinstr(ignore_test, temp) != 0); + + snprintf(master_init_script, PATH_MAX, "%s/%s-master.sh", test_dir, test); + snprintf(slave_init_script, PATH_MAX, "%s/%s-slave.sh", test_dir, test); +#ifdef __WIN__ + if (! stat(master_init_script, &info)) + skip = TRUE; + if (!stat(slave_init_script, &info)) + skip = TRUE; +#endif + if (ignore) + { + // show test + mlog("%-46s ", test); + + // ignore + rstr = TEST_IGNORE; + ++total_ignore; + } + else if (!skip) // skip test? + { + char test_file[PATH_MAX]; + char master_opt_file[PATH_MAX]; + char slave_opt_file[PATH_MAX]; + char slave_master_info_file[PATH_MAX]; + char result_file[PATH_MAX]; + char reject_file[PATH_MAX]; + char out_file[PATH_MAX]; + char err_file[PATH_MAX]; + int err; + arg_list_t al; +#ifdef __WIN__ + /* + Clean test database + */ + removef("%s/test/*.*", master_dir); + removef("%s/test/*.*", slave_dir); + removef("%s/mysqltest/*.*", master_dir); + removef("%s/mysqltest/*.*", slave_dir); + +#endif + // skip slave? + flag = skip_slave; + skip_slave = (strncmp(test, "rpl", 3) != 0); + if (flag != skip_slave) restart = TRUE; + + // create files + snprintf(master_opt_file, PATH_MAX, "%s/%s-master.opt", test_dir, test); + snprintf(slave_opt_file, PATH_MAX, "%s/%s-slave.opt", test_dir, test); + snprintf(slave_master_info_file, PATH_MAX, "%s/%s.slave-mi", test_dir, test); + snprintf(reject_file, PATH_MAX, "%s/%s%s", result_dir, test, REJECT_SUFFIX); + snprintf(out_file, PATH_MAX, "%s/%s%s", result_dir, test, OUT_SUFFIX); + snprintf(err_file, PATH_MAX, "%s/%s%s", result_dir, test, ERR_SUFFIX); + + // netware specific files + snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, NW_TEST_SUFFIX); + if (stat(test_file, &info)) + { + snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, TEST_SUFFIX); + if (access(test_file,0)) + { + printf("Invalid test name %s, %s file not found\n",test,test_file); + return; + } + } + + snprintf(result_file, PATH_MAX, "%s/%s%s", result_dir, test, NW_RESULT_SUFFIX); + if (stat(result_file, &info)) + { + snprintf(result_file, PATH_MAX, "%s/%s%s", result_dir, test, RESULT_SUFFIX); + } + + // init scripts + if (stat(master_init_script, &info)) + master_init_script[0] = 0; + else + restart = TRUE; + + if (stat(slave_init_script, &info)) + slave_init_script[0] = 0; + else + restart = TRUE; + + // read options + if (read_option(master_opt_file, master_opt)) restart = TRUE; + if (read_option(slave_opt_file, slave_opt)) restart = TRUE; + if (read_option(slave_master_info_file, slave_master_info)) restart = TRUE; + + // cleanup previous run + remove(reject_file); + remove(out_file); + remove(err_file); + + // start or restart? + if (!master_running) mysql_start(); + else if (restart) mysql_restart(); + + // let the system stabalize + sleep(1); + + // show test + mlog("%-46s ", test); + + + // args + init_args(&al); + add_arg(&al, "%s", mysqltest_file); + add_arg(&al, "--no-defaults"); + add_arg(&al, "--port=%u", master_port); +#if !defined(__NETWARE__) && !defined(__WIN__) + add_arg(&al, "--socket=%s", master_socket); + add_arg(&al, "--tmpdir=%s", mysql_tmp_dir); +#endif + add_arg(&al, "--database=%s", db); + add_arg(&al, "--user=%s", user); + add_arg(&al, "--password=%s", password); + add_arg(&al, "--silent"); + add_arg(&al, "--basedir=%s/", mysql_test_dir); + add_arg(&al, "--host=127.0.0.1"); + add_arg(&al, "-v"); + add_arg(&al, "-R"); + add_arg(&al, "%s", result_file); + + if (use_openssl) + { + add_arg(&al, "--ssl-ca=%s", ca_cert); + add_arg(&al, "--ssl-cert=%s", client_cert); + add_arg(&al, "--ssl-key=%s", client_key); + } + + // spawn + err = spawn(mysqltest_file, &al, TRUE, test_file, out_file, err_file, NULL); + + // free args + free_args(&al); + + remove_empty_file(out_file); + remove_empty_file(err_file); + + if (err == 0) + { + // pass + rstr = TEST_PASS; + ++total_pass; + + // increment total + ++total_test; + } + else if (err == 2) + { + // skip + rstr = TEST_SKIP; + ++total_skip; + } + else if (err == 1) + { + // fail + rstr = TEST_FAIL; + ++total_fail; + + // increment total + ++total_test; + } + else + { + rstr = TEST_BAD; + } + } + else // early skips + { + // show test + mlog("%-46s ", test); + + // skip + rstr = TEST_SKIP; + ++total_skip; + } + + // result + mlog("%-14s\n", rstr); +} + +/****************************************************************************** + + vlog() + + Log the message. + +******************************************************************************/ +void vlog(const char *format, va_list ap) +{ + vfprintf(stdout, format, ap); + fflush(stdout); + + if (log_fd) + { + vfprintf(log_fd, format, ap); + fflush(log_fd); + } +} + +/****************************************************************************** + + log() + + Log the message. + +******************************************************************************/ +void mlog(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + vlog(format, ap); + + va_end(ap); +} + +/****************************************************************************** + + log_info() + + Log the given information. + +******************************************************************************/ +void log_info(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + mlog("-- INFO : "); + vlog(format, ap); + mlog("\n"); + + va_end(ap); +} + +/****************************************************************************** + + log_error() + + Log the given error. + +******************************************************************************/ +void log_error(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + mlog("-- ERROR: "); + vlog(format, ap); + mlog("\n"); + + va_end(ap); +} + +/****************************************************************************** + + log_errno() + + Log the given error and errno. + +******************************************************************************/ +void log_errno(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + mlog("-- ERROR: (%003u) ", errno); + vlog(format, ap); + mlog("\n"); + + va_end(ap); +} + +/****************************************************************************** + + die() + + Exit the application. + +******************************************************************************/ +void die(const char *msg) +{ + log_error(msg); +#ifdef __NETWARE__ + pressanykey(); +#endif + exit(-1); +} + +/****************************************************************************** + + setup() + + Setup the mysql test enviornment. + +******************************************************************************/ +void setup(char *file) +{ + char temp[PATH_MAX]; + char file_path[PATH_MAX*2]; + char *p; + int position; + + // set the timezone for the timestamp test +#ifdef __WIN__ + _putenv( "TZ=GMT-3" ); +#else + setenv("TZ", "GMT-3", TRUE); +#endif + // find base dir +#ifdef __NETWARE__ + strcpy(temp, strlwr(file)); + while((p = strchr(temp, '\\')) != NULL) *p = '/'; +#else + getcwd(temp, PATH_MAX); + position = strlen(temp); + temp[position] = '/'; + temp[position+1] = 0; +#ifdef __WIN__ + while((p = strchr(temp, '\\')) != NULL) *p = '/'; +#endif +#endif + + if ((position = strinstr(temp, "/mysql-test/")) != 0) + { + p = temp + position - 1; + *p = 0; + strcpy(base_dir, temp); + } + + log_info("Currect directory: %s",base_dir); + +#ifdef __NETWARE__ + // setup paths + snprintf(bin_dir, PATH_MAX, "%s/bin", base_dir); + snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir); + snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir); + snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir); + snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir); + snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir); + snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + snprintf(lang_dir, PATH_MAX, "%s/share/english", base_dir); + snprintf(char_dir, PATH_MAX, "%s/share/charsets", base_dir); + +#ifdef HAVE_OPENSSL + use_openssl = TRUE; +#endif // HAVE_OPENSSL + + // OpenSSL paths + snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir); + snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir); + snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir); + snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir); + snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir); + + // setup files + snprintf(mysqld_file, PATH_MAX, "%s/mysqld", bin_dir); + snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest", bin_dir); + snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir); + snprintf(master_pid, PATH_MAX, "%s/var/run/master.pid", mysql_test_dir); + snprintf(slave_pid, PATH_MAX, "%s/var/run/slave.pid", mysql_test_dir); +#elif __WIN__ + // setup paths +#ifdef _DEBUG + snprintf(bin_dir, PATH_MAX, "%s/client_debug", base_dir); +#else + snprintf(bin_dir, PATH_MAX, "%s/client_release", base_dir); +#endif + snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir); + snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir); + snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir); + snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir); + snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir); + snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + snprintf(lang_dir, PATH_MAX, "%s/share/english", base_dir); + snprintf(char_dir, PATH_MAX, "%s/share/charsets", base_dir); + +#ifdef HAVE_OPENSSL + use_openssl = TRUE; +#endif // HAVE_OPENSSL + + // OpenSSL paths + snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir); + snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir); + snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir); + snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir); + snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir); + + // setup files + snprintf(mysqld_file, PATH_MAX, "%s/mysqld.exe", bin_dir); + snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest.exe", bin_dir); + snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin.exe", bin_dir); +#else + // setup paths + snprintf(bin_dir, PATH_MAX, "%s/client", base_dir); + snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir); + snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir); + snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir); + snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir); + snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir); + snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + snprintf(lang_dir, PATH_MAX, "%s/sql/share/english", base_dir); + snprintf(char_dir, PATH_MAX, "%s/sql/share/charsets", base_dir); + +#ifdef HAVE_OPENSSL + use_openssl = TRUE; +#endif // HAVE_OPENSSL + + // OpenSSL paths + snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir); + snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir); + snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir); + snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir); + snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir); + + // setup files + snprintf(mysqld_file, PATH_MAX, "%s/sql/mysqld", base_dir); + snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest", bin_dir); + snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir); + snprintf(master_pid, PATH_MAX, "%s/var/run/master.pid", mysql_test_dir); + snprintf(slave_pid, PATH_MAX, "%s/var/run/slave.pid", mysql_test_dir); + + snprintf(master_socket,PATH_MAX, "%s/var/tmp/master.sock", mysql_test_dir); + snprintf(slave_socket,PATH_MAX, "%s/var/tmp/slave.sock", mysql_test_dir); + +#endif + // create log file + snprintf(temp, PATH_MAX, "%s/mysql-test-run.log", mysql_test_dir); + if ((log_fd = fopen(temp, "w+")) == NULL) + { + log_errno("Unable to create log file."); + } + + // prepare skip test list + while((p = strchr(skip_test, ',')) != NULL) *p = ' '; + strcpy(temp, strlwr(skip_test)); + snprintf(skip_test, PATH_MAX, " %s ", temp); + + // environment +#ifdef __NETWARE__ + setenv("MYSQL_TEST_DIR", mysql_test_dir, 1); + snprintf(file_path, PATH_MAX*2, "%s/client/mysqldump --no-defaults -u root --port=%u", bin_dir, master_port); + setenv("MYSQL_DUMP", file_path, 1); + snprintf(file_path, PATH_MAX*2, "%s/client/mysqlbinlog --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir); + setenv("MYSQL_BINLOG", file_path, 1); +#elif __WIN__ + snprintf(file_path,MAX_PATH,"MYSQL_TEST_DIR=%s",mysql_test_dir); + _putenv(file_path); + snprintf(file_path, PATH_MAX*2, "MYSQL_DUMP=%s/mysqldump.exe --no-defaults -u root --port=%u", bin_dir, master_port); + _putenv(file_path); + snprintf(file_path, PATH_MAX*2, "MYSQL_BINLOG=%s/mysqlbinlog.exe --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir); + _putenv(file_path); +#else + setenv("MYSQL_TEST_DIR", mysql_test_dir, 1); + snprintf(file_path, PATH_MAX*2, "%s/mysqldump --no-defaults -u root --port=%u --socket=%s", bin_dir, master_port, master_socket); + setenv("MYSQL_DUMP", file_path, 1); + snprintf(file_path, PATH_MAX*2, "%s/mysqlbinlog --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir); + setenv("MYSQL_BINLOG", file_path, 1); +#endif + +#ifndef __WIN__ + setenv("MASTER_MYPORT", "9306", 1); + setenv("SLAVE_MYPORT", "9307", 1); + setenv("MYSQL_TCP_PORT", "3306", 1); +#else + _putenv("MASTER_MYPORT=9306"); + _putenv("SLAVE_MYPORT=9307"); + _putenv("MYSQL_TCP_PORT=3306"); +#endif + +} + +/****************************************************************************** + + main() + +******************************************************************************/ +int main(int argc, char **argv) +{ + int is_ignore_list = 0; + // setup + setup(argv[0]); + + /* The --ignore option is comma saperated list of test cases to skip and + should be very first command line option to the test suite. + + The usage is now: + mysql_test_run --ignore=test1,test2 test3 test4 + where test1 and test2 are test cases to ignore + and test3 and test4 are test cases to run. + */ + if (argc >= 2 && !strnicmp(argv[1], "--ignore=", sizeof("--ignore=")-1)) + { + char *temp, *token; + temp= strdup(strchr(argv[1],'=') + 1); + for (token=str_tok(temp, ","); token != NULL; token=str_tok(NULL, ",")) + { + if (strlen(ignore_test) + strlen(token) + 2 <= PATH_MAX-1) + sprintf(ignore_test+strlen(ignore_test), " %s ", token); + else + { + free(temp); + die("ignore list too long."); + } + } + free(temp); + is_ignore_list = 1; + } + // header +#ifndef __WIN__ + mlog("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE); +#else + mlog("MySQL Server ---, for %s (%s)\n\n", SYSTEM_TYPE, MACHINE_TYPE); +#endif + + mlog("Initializing Tests...\n"); + + // install test databases + mysql_install_db(); + + mlog("Starting Tests...\n"); + + mlog("\n"); + mlog(HEADER); + mlog(DASH); + + if ( argc > 1 + is_ignore_list ) + { + int i; + + // single test + single_test = TRUE; + + for (i = 1 + is_ignore_list; i < argc; i++) + { + // run given test + run_test(argv[i]); + } + } + else + { + // run all tests +#ifndef __WIN__ + struct dirent **namelist; + int i,n; + char test[NAME_MAX]; + char *p; + int position; + + n = scandir(test_dir, &namelist, 0, alphasort); + if (n < 0) + die("Unable to open tests directory."); + else + { + for (i = 0; i < n; i++) + { + strcpy(test, strlwr(namelist[i]->d_name)); + // find the test suffix + if ((position = strinstr(test, TEST_SUFFIX)) != 0) + { + p = test + position - 1; + // null terminate at the suffix + *p = 0; + // run test + run_test(test); + } + free(namelist[n]); + } + free(namelist); + } +#else + struct _finddata_t dir; + intptr_t handle; + char test[NAME_MAX]; + char mask[PATH_MAX]; + char *p; + int position; + char **names = 0; + char **testes = 0; + int name_index; + int index; + + // single test + single_test = FALSE; + + snprintf(mask,MAX_PATH,"%s/*.test",test_dir); + + if ((handle=_findfirst(mask,&dir)) == -1L) + { + die("Unable to open tests directory."); + } + + names = malloc(MAX_COUNT_TESTES*4); + testes = names; + name_index = 0; + + do + { + if (!(dir.attrib & _A_SUBDIR)) + { + strcpy(test, strlwr(dir.name)); + + // find the test suffix + if ((position = strinstr(test, TEST_SUFFIX)) != 0) + { + p = test + position - 1; + // null terminate at the suffix + *p = 0; + + // insert test + *names = malloc(PATH_MAX); + strcpy(*names,test); + names++; + name_index++; + } + } + }while (_findnext(handle,&dir) == 0); + + _findclose(handle); + + qsort( (void *)testes, name_index, sizeof( char * ), compare ); + + for (index = 0; index <= name_index; index++) + { + run_test(testes[index]); + free(testes[index]); + } + + free(testes); +#endif + } + + // stop server + mysql_stop(); + + mlog(DASH); + mlog("\n"); + + mlog("Ending Tests...\n"); + + // report stats + report_stats(); + + // close log + if (log_fd) fclose(log_fd); + + // keep results up +#ifdef __NETWARE__ + pressanykey(); +#endif + return 0; +} + + +/* + Synopsis: + This function breaks the string into a sequence of tokens. The difference + between this function and strtok is that it respects the quoted string i.e. + it skips any delimiter character within the quoted part of the string. + It return tokens by eliminating quote character. It modifies the input string + passed. It will work with whitespace delimeter but may not work properly with + other delimeter. If the delimeter will contain any quote character, then + function will not tokenize and will return null string. + e.g. if input string is + --init-slave="set global max_connections=500" --skip-external-locking + then the output will two string i.e. + --init-slave=set global max_connections=500 + --skip-external-locking + +Arguments: + string: input string + delim: set of delimiter character +Output: + return the null terminated token of NULL. +*/ + + +char *str_tok(char *string, const char *delim) +{ + char *token; /* current token received from strtok */ + char *qt_token; /* token delimeted by the matching pair of quote */ + /* + if there are any quote chars found in the token then this variable + will hold the concatenated string to return to the caller + */ + char *ptr_token=NULL; + /* pointer to the quote character in the token from strtok */ + char *ptr_quote=NULL; + + /* See if the delimeter contains any quote character */ + if (strchr(delim,'\'') || strchr(delim,'\"')) + return NULL; + + /* repeate till we are getting some token from strtok */ + while ((token = (char*)strtok(string, delim) ) != NULL) + { + /* + make the input string NULL so that next time onward strtok can + be called with NULL input string. + */ + string = NULL; + /* + We don't need to remove any quote character for Windows version + */ +#ifndef __WIN__ + /* check if the current token contain double quote character*/ + if ((ptr_quote = (char*)strchr(token,'\"')) != NULL) + { + /* + get the matching the matching double quote in the remaining + input string + */ + qt_token = (char*)strtok(NULL,"\""); + } + /* check if the current token contain single quote character*/ + else if ((ptr_quote = (char*)strchr(token,'\'')) != NULL) + { + /* + get the matching the matching single quote in the remaining + input string + */ + qt_token = (char*)strtok(NULL,"\'"); + } +#endif + /* + if the current token does not contains any quote character then + return to the caller. + */ + if (ptr_quote == NULL) + { + /* + if there is any earlier token i.e. ptr_token then append the + current token in it and return it else return the current + token directly + */ + return ptr_token ? strcat(ptr_token,token) : token; + } + + /* + remove the quote character i.e. make NULL so that the token will + be devided in two part and later both part can be concatenated + and hence quote will be removed + */ + *ptr_quote= 0; + + /* check if ptr_token has been initialized or not */ + if (ptr_token == NULL) + { + /* initialize the ptr_token with current token */ + ptr_token= token; + /* copy entire string between matching pair of quote*/ + sprintf(ptr_token+strlen(ptr_token),"%s %s", ptr_quote+1, qt_token); + } + else + { + /* + copy the current token and entire string between matching pair + of quote + */ + if (qt_token == NULL) + { + sprintf(ptr_token+strlen(ptr_token),"%s%s", token, ptr_quote+1); + } + else + { + sprintf(ptr_token+strlen(ptr_token),"%s%s %s", token, ptr_quote+1, + qt_token ); + } + } + } + + /* return the concatenated token */ + return ptr_token; +} + +#ifndef __WIN__ + +/* + Synopsis: + This function run scripts files on Linux and Netware + +Arguments: + script_name: name of script file + +Output: + nothing +*/ +void run_init_script(const char *script_name) +{ + arg_list_t al; + int err; + + // args + init_args(&al); + add_arg(&al, sh_file); + add_arg(&al, script_name); + + // spawn + if ((err = spawn(sh_file, &al, TRUE, NULL, NULL, NULL, NULL)) != 0) + { + die("Unable to run script."); + } + + // free args + free_args(&al); +} +#endif diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh index 294d32ac4be..9c6b6093b93 100644 --- a/mysql-test/ndb/ndbcluster.sh +++ b/mysql-test/ndb/ndbcluster.sh @@ -102,12 +102,43 @@ if [ ! -x "$exec_mgmtsrvr" ]; then echo "$exec_mgmtsrvr missing" exit 1 fi +if [ ! -x "$exec_waiter" ]; then + echo "$exec_waiter missing" + exit 1 +fi + +exec_mgmtclient="$exec_mgmtclient --no-defaults" +exec_mgmtsrvr="$exec_mgmtsrvr --no-defaults" +exec_ndb="$exec_ndb --no-defaults" +exec_waiter="$exec_waiter --no-defaults" ndb_host="localhost" ndb_mgmd_port=$port_base NDB_CONNECTSTRING="host=$ndb_host:$ndb_mgmd_port" export NDB_CONNECTSTRING +sleep_until_file_created () { + file=$1 + loop=$2 + org_time=$2 + message=$3 + while (test $loop -gt 0) + do + if [ -r $file ] + then + return 0 + fi + sleep 1 + loop=`expr $loop - 1` + done + if [ $message ] + then + echo $message + fi + echo "ERROR: $file was not created in $org_time seconds; Aborting" + return 1; +} + start_default_ndbcluster() { # do some checks @@ -127,8 +158,8 @@ port_transporter=`expr $ndb_mgmd_port + 2` # Start management server as deamon # Edit file system path and ports in config file - if [ $initial_ndb ] ; then + rm -f $fs_ndb/ndb_* sed \ -e s,"CHOOSE_MaxNoOfOrderedIndexes","$ndb_no_ord",g \ -e s,"CHOOSE_MaxNoOfConcurrentOperations","$ndb_con_op",g \ @@ -146,25 +177,36 @@ fi rm -f "$cfgfile" 2>&1 | cat > /dev/null rm -f "$fs_ndb/$cfgfile" 2>&1 | cat > /dev/null -if ( cd "$fs_ndb" ; $exec_mgmtsrvr -c config.ini ) ; then :; else +if ( cd "$fs_ndb" ; $exec_mgmtsrvr -f config.ini ) ; then :; else echo "Unable to start $exec_mgmtsrvr from `pwd`" exit 1 fi - +if sleep_until_file_created $fs_ndb/ndb_3.pid 30 +then :; else + exit 1 +fi cat `find "$fs_ndb" -name 'ndb_*.pid'` > "$fs_ndb/$pidfile" # Start database node echo "Starting ndbd" ( cd "$fs_ndb" ; $exec_ndb $flags_ndb & ) - +if sleep_until_file_created $fs_ndb/ndb_1.pid 30 +then :; else + stop_default_ndbcluster + exit 1 +fi cat `find "$fs_ndb" -name 'ndb_*.pid'` > "$fs_ndb/$pidfile" # Start database node echo "Starting ndbd" ( cd "$fs_ndb" ; $exec_ndb $flags_ndb & ) - +if sleep_until_file_created $fs_ndb/ndb_2.pid 30 +then :; else + stop_default_ndbcluster + exit 1 +fi cat `find "$fs_ndb" -name 'ndb_*.pid'` > "$fs_ndb/$pidfile" # test if Ndb Cluster starts properly @@ -172,6 +214,7 @@ cat `find "$fs_ndb" -name 'ndb_*.pid'` > "$fs_ndb/$pidfile" echo "Waiting for started..." if ( $exec_waiter ) | grep "NDBT_ProgramExit: 0 - OK"; then :; else echo "Ndbcluster startup failed" + stop_default_ndbcluster exit 1 fi @@ -198,10 +241,12 @@ if [ -f "$fs_ndb/$pidfile" ] ; then attempt=0 while [ $attempt -lt 10 ] ; do new_kill_pid="" + kill_pids2="" for p in $kill_pids ; do kill -0 $p 2> /dev/null if [ $? -eq 0 ] ; then new_kill_pid="$p $new_kill_pid" + kill_pids2="-$p $kill_pids2" fi done kill_pids=$new_kill_pid @@ -211,9 +256,14 @@ if [ -f "$fs_ndb/$pidfile" ] ; then sleep 1 attempt=`expr $attempt + 1` done - if [ "$kill_pids" != "" ] ; then - echo "Failed to shutdown ndbcluster, executing kill -9 "$kill_pids - kill -9 $kill_pids + if [ "$kill_pids2" != "" ] ; then + echo "Failed to shutdown ndbcluster, executing kill "$kill_pids2 + kill -9 -- $kill_pids2 2> /dev/null + /bin/kill -9 -- $kill_pids2 2> /dev/null + /usr/bin/kill -9 -- $kill_pids2 2> /dev/null + kill -9 $kill_pids2 2> /dev/null + /bin/kill -9 $kill_pids2 2> /dev/null + /usr/bin/kill -9 $kill_pids2 2> /dev/null fi rm "$fs_ndb/$pidfile" fi diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 1d3deb0b09a..0e36b00a670 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -480,3 +480,10 @@ a 0061 b 0062 c 0063 drop table t1; +set @ivar= 1234; +set @str1 = 'select ?'; +set @str2 = convert(@str1 using ucs2); +prepare stmt1 from @str2; +execute stmt1 using @ivar; +? +1234 diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 0a26f545ab0..e976cc95383 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -355,9 +355,9 @@ t collation(t) aus Osnabrück utf8_general_ci SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrueck'); t collation(t) -SELECT t, collation(t),MATCH t AGAINST ('Osnabruck') FROM t1 WHERE MATCH t AGAINST ('Osnabruck'); -t collation(t) MATCH t AGAINST ('Osnabruck') -aus Osnabrück utf8_general_ci 1.591139793396 +SELECT t, collation(t),FORMAT(MATCH t AGAINST ('Osnabruck'),6) FROM t1 WHERE MATCH t AGAINST ('Osnabruck'); +t collation(t) FORMAT(MATCH t AGAINST ('Osnabruck'),6) +aus Osnabrück utf8_general_ci 1.591140 alter table t1 modify t varchar(200) collate latin1_german2_ci not null; Warnings: Warning 1265 Data truncated for column 't' at row 3 diff --git a/mysql-test/r/fulltext_order_by.result b/mysql-test/r/fulltext_order_by.result index bfee9eba280..c6c42fa2e8b 100644 --- a/mysql-test/r/fulltext_order_by.result +++ b/mysql-test/r/fulltext_order_by.result @@ -6,53 +6,53 @@ FULLTEXT(message) ) comment = 'original testcase by sroussey@network54.com'; INSERT INTO t1 (message) VALUES ("Testing"),("table"),("testbug"), ("steve"),("is"),("cool"),("steve is cool"); -SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve'); -a MATCH (message) AGAINST ('steve') -4 0.90587323904037 -7 0.89568990468979 +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve'); +a FORMAT(MATCH (message) AGAINST ('steve'),6) +4 0.905873 +7 0.895690 SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve'); a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) 4 1 7 1 -SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE); -a MATCH (message) AGAINST ('steve') -4 0.90587323904037 -7 0.89568990468979 +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE); +a FORMAT(MATCH (message) AGAINST ('steve'),6) +4 0.905873 +7 0.895690 SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE); a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) 4 1 7 1 -SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a; -a MATCH (message) AGAINST ('steve') -4 0.90587323904037 -7 0.89568990468979 +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a; +a FORMAT(MATCH (message) AGAINST ('steve'),6) +4 0.905873 +7 0.895690 SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a; a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) 4 1 7 1 -SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC; -a MATCH (message) AGAINST ('steve') -7 0.89568990468979 -4 0.90587323904037 +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC; +a FORMAT(MATCH (message) AGAINST ('steve'),6) +7 0.895690 +4 0.905873 SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a DESC; a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) 7 1 4 1 -SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1; -a MATCH (message) AGAINST ('steve') -7 0.89568990468979 +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1; +a FORMAT(MATCH (message) AGAINST ('steve'),6) +7 0.895690 SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY 1; a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) 7 1 -SELECT a, MATCH (message) AGAINST ('steve') as rel FROM t1 ORDER BY rel; +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) as rel FROM t1 ORDER BY rel; a rel -1 0 -2 0 -3 0 -5 0 -6 0 -7 0.89568990468979 -4 0.90587323904037 +1 0.000000 +2 0.000000 +3 0.000000 +5 0.000000 +6 0.000000 +7 0.895690 +4 0.905873 SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) as rel FROM t1 ORDER BY rel; a rel 1 0 diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index 374affce8c5..daeda51a12a 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -179,3 +179,9 @@ select 1 in ('1.1',2); select 1 in ('1.1',2.0); 1 in ('1.1',2.0) 0 +create table t1 (a char(20) character set binary); +insert into t1 values ('aa'), ('bb'); +select * from t1 where a in (NULL, 'aa'); +a +aa +drop table t1; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 6cad58282a2..6d9cfabb5a7 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -106,12 +106,6 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp set @fvar= 123.4567; prepare stmt1 from @fvar; 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 '123.4567' at line 1 -set @str1 = 'select ?'; -set @str2 = convert(@str1 using ucs2); -prepare stmt1 from @str2; -execute stmt1 using @ivar; -? -1234 drop table t1,t2; PREPARE stmt1 FROM "select _utf8 'A' collate utf8_bin = ?"; set @var='A'; diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 75f0298797a..2f996382586 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -22,14 +22,14 @@ select * from t1; f1 f2 10 10 100000 100000 -1.23457e+09 1234567890 +1.23457e+9 1234567890 1e+10 10000000000 1e+15 1e+15 1e+20 1e+20 3.40282e+38 1e+50 3.40282e+38 1e+150 -10 -10 -1e-05 1e-05 +1e-5 1e-5 1e-10 1e-10 1e-15 1e-15 1e-20 1e-20 diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index d9ef91496e9..4c6d1bbebef 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -315,3 +315,11 @@ alter table t1 modify a char(5); select a, hex(a) from t1; drop table t1; +# +# Check prepare statement from an UCS2 string +# +set @ivar= 1234; +set @str1 = 'select ?'; +set @str2 = convert(@str1 using ucs2); +prepare stmt1 from @str2; +execute stmt1 using @ivar; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 5af2575ddc4..5a2f2d87194 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -279,7 +279,7 @@ SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück'); SET NAMES latin1; SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück'); SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrueck'); -SELECT t, collation(t),MATCH t AGAINST ('Osnabruck') FROM t1 WHERE MATCH t AGAINST ('Osnabruck'); +SELECT t, collation(t),FORMAT(MATCH t AGAINST ('Osnabruck'),6) FROM t1 WHERE MATCH t AGAINST ('Osnabruck'); #alter table t1 modify t text character set latin1 collate latin1_german2_ci not null; alter table t1 modify t varchar(200) collate latin1_german2_ci not null; SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück'); diff --git a/mysql-test/t/fulltext_order_by.test b/mysql-test/t/fulltext_order_by.test index f8afe49d95d..5856f68ec9e 100644 --- a/mysql-test/t/fulltext_order_by.test +++ b/mysql-test/t/fulltext_order_by.test @@ -10,25 +10,25 @@ CREATE TABLE t1 ( INSERT INTO t1 (message) VALUES ("Testing"),("table"),("testbug"), ("steve"),("is"),("cool"),("steve is cool"); # basic MATCH -SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve'); +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve'); SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve'); -SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE); +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE); SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE); # MATCH + ORDER BY (with ft-ranges) -SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a; +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a; SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a; # MATCH + ORDER BY (with normal ranges) + UNIQUE -SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC; +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC; SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a DESC; # MATCH + ORDER BY + UNIQUE (const_table) -SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1; +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1; SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY 1; # ORDER BY MATCH -SELECT a, MATCH (message) AGAINST ('steve') as rel FROM t1 ORDER BY rel; +SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) as rel FROM t1 ORDER BY rel; SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) as rel FROM t1 ORDER BY rel; drop table t1; diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 22079377ad2..3cd8c064817 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -89,3 +89,10 @@ select 1 in ('1.0',2.0); select 1 in (1.0,'2.0'); select 1 in ('1.1',2); select 1 in ('1.1',2.0); + +# Test case for bug #6365 + +create table t1 (a char(20) character set binary); +insert into t1 values ('aa'), ('bb'); +select * from t1 where a in (NULL, 'aa'); +drop table t1; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 50ab3bdb8bd..a452f79f949 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1110,6 +1110,7 @@ show create table t2; drop table t2; # Test error handling +--replace_result \\ / --error 1005 create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 54379685731..f5acab05108 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -99,46 +99,57 @@ create table t1(number int auto_increment primary key, original_value varchar(50 set @value= "aa"; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= "1aa"; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= "aa1"; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= "1e+1111111111a"; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= "-1e+1111111111a"; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= 1e+1111111111; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= -1e+1111111111; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= 1e+111; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= -1e+111; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= 1; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= -1; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); +--replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() drop table t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 978ce2bc2c3..2b3e961fc28 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -110,10 +110,6 @@ set @fvar= 123.4567; --error 1064 prepare stmt1 from @fvar; -set @str1 = 'select ?'; -set @str2 = convert(@str1 using ucs2); -prepare stmt1 from @str2; -execute stmt1 using @ivar; drop table t1,t2; # diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 216d5bbd286..26ac272c6d4 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -6,7 +6,9 @@ drop table if exists t1; --enable_warnings +--replace_result e-0 e- e+0 e+ SELECT 10,10.0,10.,.1e+2,100.0e-1; +--replace_result e-00 e-0 SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000; SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1; @@ -14,6 +16,7 @@ create table t1 (f1 float(24),f2 float(52)); show full columns from t1; insert into t1 values(10,10),(1e+5,1e+5),(1234567890,1234567890),(1e+10,1e+10),(1e+15,1e+15),(1e+20,1e+20),(1e+50,1e+50),(1e+150,1e+150); insert into t1 values(-10,-10),(1e-5,1e-5),(1e-10,1e-10),(1e-15,1e-15),(1e-20,1e-20),(1e-50,1e-50),(1e-150,1e-150); +--replace_result e-0 e- e+0 e+ select * from t1; drop table t1; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index fd6ab4d6405..d0a78c157c3 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -8,6 +8,7 @@ drop table if exists t1,t2; set @`test`=1,@TEST=3,@select=2,@t5=1.23456; select @test,@`select`,@TEST,@not_used; set @test_int=10,@test_double=1e-10,@test_string="abcdeghi",@test_string2="abcdefghij",@select=NULL; +--replace_result e-0 e- e+0 e+ select @test_int,@test_double,@test_string,@test_string2,@select; set @test_int="hello",@test_double="hello",@test_string="hello",@test_string2="hello"; select @test_int,@test_double,@test_string,@test_string2; diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index 9a1bbd86562..c275e5382f7 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -4501,6 +4501,17 @@ void Dbacc::getdirindex(Signal* signal) /* BUCKET, AND SERCH FOR ELEMENT.THE PRIMARY KEYS WHICH IS SAVED */ /* IN THE OPERATION REC ARE THE CHECK ITEMS IN THE SEARCHING. */ /* --------------------------------------------------------------------------------- */ + +#if __ia64 == 1 +#if __INTEL_COMPILER == 810 +int ndb_acc_ia64_icc810_dummy_var = 0; +void ndb_acc_ia64_icc810_dummy_func() +{ + ndb_acc_ia64_icc810_dummy_var++; +} +#endif +#endif + void Dbacc::getElement(Signal* signal) { DirRangePtr geOverflowrangeptr; @@ -4595,6 +4606,12 @@ void Dbacc::getElement(Signal* signal) /* WE HAVE FOUND THE ELEMENT. GET THE LOCK INDICATOR AND RETURN FOUND. */ /* --------------------------------------------------------------------------------- */ jam(); +#if __ia64 == 1 +#if __INTEL_COMPILER == 810 + // prevents SIGSEGV under icc -O1 + ndb_acc_ia64_icc810_dummy_func(); +#endif +#endif tgeLocked = ElementHeader::getLocked(gePageptr.p->word32[tgeElementptr]); tgeResult = ZTRUE; TdataIndex = tgeElementptr + tgeForward; diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index cd15ad0c3b2..af1131e5e55 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -8725,7 +8725,7 @@ void Dblqh::sendKeyinfo20(Signal* signal, sendSignal(ref, GSN_KEYINFO20, signal, 25, JBB); src += KeyInfo20::DataLength;; keyLen -= KeyInfo20::DataLength; - } while(keyLen >= KeyInfo20::DataLength); + } MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen); sendSignal(ref, GSN_KEYINFO20, signal, diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index c1876f68ea2..15767e4766d 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -101,8 +101,23 @@ static char *opt_connect_str= 0; static struct my_option my_long_options[] = { - NDB_STD_OPTS("ndb_mgmd"), - { "config-file", 'c', "Specify cluster configuration file", +#ifndef DBUG_OFF + { "debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", + 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }, +#endif + { "usage", '?', "Display this help and exit.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "help", '?', "Display this help and exit.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "version", 'V', "Output version information and exit.", 0, 0, 0, + GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "connect-string", 1023, + "Set connect string for connecting to ndb_mgmd. " + "<constr>=\"host=<hostname:port>[;nodeid=<id>]\". " + "Overides specifying entries in NDB_CONNECTSTRING and config file", + (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "config-file", 'f', "Specify cluster configuration file", (gptr*) &glob.config_filename, (gptr*) &glob.config_filename, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "daemon", 'd', "Run ndb_mgmd in daemon mode (default)", @@ -120,6 +135,11 @@ static struct my_option my_long_options[] = { "nodaemon", 258, "Don't run as daemon, but don't read from stdin", (gptr*) &glob.non_interactive, (gptr*) &glob.non_interactive, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "config-file", 'c', + "-c provided for backwards compatability, will be removed in 5.0." + " Use -f instead", + (gptr*) &glob.config_filename, (gptr*) &glob.config_filename, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; static void short_usage_sub(void) @@ -148,6 +168,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case 'V': print_version(); exit(0); + case 'c': + printf("Warning: -c will be removed in 5.0, use -f instead\n"); + break; case '?': usage(); exit(0); diff --git a/ndb/test/run-test/main.cpp b/ndb/test/run-test/main.cpp index 22799a9a1b2..e5f73bc6a5c 100644 --- a/ndb/test/run-test/main.cpp +++ b/ndb/test/run-test/main.cpp @@ -459,7 +459,7 @@ setup_config(atrt_config& config){ proc.m_type = atrt_process::NDB_MGM; proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_mgmd"); proc.m_proc.m_path.assign(dir).append("/libexec/ndb_mgmd"); - proc.m_proc.m_args = "--nodaemon -c initconfig.txt"; + proc.m_proc.m_args = "--nodaemon -f config.ini"; proc.m_proc.m_cwd.appfmt("%d.ndb_mgmd", index); connect_string.appfmt("host=%s:%d;", proc.m_hostname.c_str(), proc.m_ndb_mgm_port); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 0bcb7062437..6e08fc680b2 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2314,6 +2314,34 @@ ha_innobase::write_row( if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); + if (user_thd->lex->sql_command == SQLCOM_ALTER_TABLE + && num_write_row >= 10000) { + /* ALTER TABLE is COMMITted at every 10000 copied rows. + The IX table lock for the original table has to be re-issued. + As this method will be called on a temporary table where the + contents of the original table is being copied to, it is + a bit tricky to determine the source table. The cursor + position in the source table need not be adjusted after the + intermediate COMMIT, since writes by other transactions are + being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */ + ut_a(prebuilt->trx->mysql_n_tables_locked == 2); + ut_a(UT_LIST_GET_LEN(prebuilt->trx->trx_locks) >= 2); + dict_table_t* table = lock_get_ix_table( + UT_LIST_GET_FIRST(prebuilt->trx->trx_locks)); + num_write_row = 0; + /* Commit the transaction. This will release the table + locks, so they have to be acquired again. */ + innobase_commit(user_thd, prebuilt->trx); + /* Note that this transaction is still active. */ + user_thd->transaction.all.innodb_active_trans = 1; + /* Re-acquire the IX table lock on the source table. */ + row_lock_table_for_mysql(prebuilt, table); + /* We will need an IX lock on the destination table. */ + prebuilt->sql_stat_start = TRUE; + } + + num_write_row++; + if (last_query_id != user_thd->query_id) { prebuilt->sql_stat_start = TRUE; last_query_id = user_thd->query_id; @@ -4986,7 +5014,7 @@ ha_innobase::external_lock( if (thd->in_lock_tables && thd->variables.innodb_table_locks) { ulint error; - error = row_lock_table_for_mysql(prebuilt); + error = row_lock_table_for_mysql(prebuilt, 0); if (error != DB_SUCCESS) { error = convert_error_code_to_mysql( diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index c10beacac1b..e76a966c6b9 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -64,6 +64,7 @@ class ha_innobase: public handler uint last_match_mode;/* match mode of the latest search: ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX, or undefined */ + uint num_write_row; /* number of write_row() calls */ longlong auto_inc_counter_for_this_stat; ulong max_supported_row_length(const byte *buf); @@ -85,7 +86,8 @@ class ha_innobase: public handler HA_PRIMARY_KEY_IN_READ_INDEX | HA_TABLE_SCAN_ON_INDEX), last_dup_key((uint) -1), - start_of_scan(0) + start_of_scan(0), + num_write_row(0) { } ~ha_innobase() {} diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 701894cacb5..a28f0f5d4a9 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1749,7 +1749,8 @@ void Item_func_in::fix_length_and_dec() thd->set_n_backup_item_arena(arena, &backup); for (arg= args+1, arg_end= args+arg_count; arg < arg_end; arg++) { - if (!my_charset_same(cmp_collation.collation, + if (!arg[0]->null_value && + !my_charset_same(cmp_collation.collation, arg[0]->collation.collation)) { Item_string *conv; diff --git a/tests/client_test.c b/tests/client_test.c index 227f7e29ef2..004f076c6df 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -11082,12 +11082,77 @@ static void test_bug6096() free(bind[i].buffer); mysql_stmt_close(stmt); mysql_free_result(query_result); + mysql_free_result(stmt_metadata); stmt_text= "drop table t1"; rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); myquery(rc); } +static void test_bug4172() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[3]; + const char *stmt_text; + MYSQL_RES *res; + MYSQL_ROW row; + int rc; + char f[100], d[100], e[100]; + long f_len, d_len, e_len; + + myheader("test_bug4172"); + + mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + mysql_query(mysql, "CREATE TABLE t1 (f float, d double, e decimal(10,4))"); + mysql_query(mysql, "INSERT INTO t1 VALUES (12345.1234, 123456.123456, " + "123456.1234)"); + + stmt= mysql_stmt_init(mysql); + stmt_text= "SELECT f, d, e FROM t1"; + + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + bzero(bind, sizeof(bind)); + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= f; + bind[0].buffer_length= sizeof(f); + bind[0].length= &f_len; + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer= d; + bind[1].buffer_length= sizeof(d); + bind[1].length= &d_len; + bind[2].buffer_type= MYSQL_TYPE_STRING; + bind[2].buffer= e; + bind[2].buffer_length= sizeof(e); + bind[2].length= &e_len; + + mysql_stmt_bind_result(stmt, bind); + + mysql_stmt_store_result(stmt); + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + res= mysql_store_result(mysql); + row= mysql_fetch_row(res); + + printf("Binary protocol: float=%s, double=%s, decimal(10,4)=%s\n", + f, d, e); + printf("Text protocol: float=%s, double=%s, decimal(10,4)=%s\n", + row[0], row[1], row[2]); + + DIE_UNLESS(!strcmp(f, row[0]) && !strcmp(d, row[1]) && !strcmp(e, row[2])); + + mysql_free_result(res); + mysql_stmt_close(stmt); +} + + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -11404,6 +11469,8 @@ int main(int argc, char **argv) test_bug6046(); /* NATURAL JOIN transformation works in PS */ test_bug6081(); /* test of mysql_create_db()/mysql_rm_db() */ test_bug6096(); /* max_length for numeric columns */ + test_bug4172(); /* floating point conversions in libmysql */ + /* XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH. |