diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 6ecbb6802c7..d86e3a44746 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -663,7 +663,8 @@ end: static struct my_option my_long_options[] = { - + {"help", '?', "Display this help and exit.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __NETWARE__ {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -683,13 +684,13 @@ static struct my_option my_long_options[] = {"character-sets-dir", OPT_CHARSETS_DIR, "Directory where character sets are.", (gptr*) &charsets_dir, (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"database", 'd', "List entries for just this database (local log only).", + (gptr*) &database, (gptr*) &database, 0, GET_STR_ALLOC, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, #ifndef DBUG_OFF {"debug", '#', "Output debug log.", (gptr*) &default_dbug_option, (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"database", 'd', "List entries for just this database (local log only).", - (gptr*) &database, (gptr*) &database, 0, GET_STR_ALLOC, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, {"disable-log-bin", 'D', "Disable binary log. This is useful, if you " "enabled --to-last-log and are sending the output to the same MySQL server. " "This way you could avoid an endless loop. You would also like to use it " @@ -700,13 +701,14 @@ static struct my_option my_long_options[] = {"force-read", 'f', "Force reading unknown binlog events.", (gptr*) &force_opt, (gptr*) &force_opt, 0, GET_BOOL, 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}, {"hexdump", 'H', "Augment output with hexadecimal and ASCII event dump.", (gptr*) &opt_hexdump, (gptr*) &opt_hexdump, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"host", 'h', "Get the binlog from server.", (gptr*) &host, (gptr*) &host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.", + (gptr*) &dirname_for_local_load, (gptr*) &dirname_for_local_load, 0, + GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"offset", 'o', "Skip the first N entries.", (gptr*) &offset, (gptr*) &offset, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to connect to remote server.", @@ -722,15 +724,15 @@ static struct my_option my_long_options[] = {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"read-from-remote-server", 'R', "Read binary logs from a MySQL server", (gptr*) &remote_opt, (gptr*) &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"open_files_limit", OPT_OPEN_FILES_LIMIT, - "Used to reserve file descriptors for usage by this program", - (gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG, - REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0}, + {"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR, + REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"server-id", OPT_SERVER_ID, + "Extract only binlog entries created by the server having the given id.", + (gptr*) &server_id, (gptr*) &server_id, 0, GET_ULONG, + REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"short-form", 's', "Just show the queries, no extra info.", (gptr*) &short_form, (gptr*) &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -745,6 +747,13 @@ static struct my_option my_long_options[] = "(you should probably use quotes for your shell to set it properly).", (gptr*) &start_datetime_str, (gptr*) &start_datetime_str, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"start-position", OPT_START_POSITION, + "Start reading the binlog at position N. Applies to the first binlog " + "passed on the command line.", + (gptr*) &start_position, (gptr*) &start_position, 0, GET_ULL, + REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE, + /* COM_BINLOG_DUMP accepts only 4 bytes for the position */ + (ulonglong)(~(uint32)0), 0, 0, 0}, {"stop-datetime", OPT_STOP_DATETIME, "Stop reading the binlog at first event having a datetime equal or " "posterior to the argument; the argument must be a date and time " @@ -753,24 +762,12 @@ static struct my_option my_long_options[] = "(you should probably use quotes for your shell to set it properly).", (gptr*) &stop_datetime_str, (gptr*) &stop_datetime_str, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"start-position", OPT_START_POSITION, - "Start reading the binlog at position N. Applies to the first binlog " - "passed on the command line.", - (gptr*) &start_position, (gptr*) &start_position, 0, GET_ULL, - REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE, - /* COM_BINLOG_DUMP accepts only 4 bytes for the position */ - (ulonglong)(~(uint32)0), 0, 0, 0}, {"stop-position", OPT_STOP_POSITION, "Stop reading the binlog at position N. Applies to the last binlog " "passed on the command line.", (gptr*) &stop_position, (gptr*) &stop_position, 0, GET_ULL, REQUIRED_ARG, (ulonglong)(~(my_off_t)0), BIN_LOG_HEADER_SIZE, (ulonglong)(~(my_off_t)0), 0, 0, 0}, - {"server-id", OPT_SERVER_ID, - "Only extract binlog entries created by a certain server id " - "passed on the command line.", - (gptr*) &server_id, (gptr*) &server_id, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"to-last-log", 't', "Requires -R. Will not stop at the end of the \ requested binlog but rather continue printing until the end of the last \ binlog of the MySQL server. If you send the output to the same MySQL server, \ @@ -780,11 +777,12 @@ that may lead to an endless loop.", {"user", 'u', "Connect to the remote server as username.", (gptr*) &user, (gptr*) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.", - (gptr*) &dirname_for_local_load, (gptr*) &dirname_for_local_load, 0, - GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"open_files_limit", OPT_OPEN_FILES_LIMIT, + "Used to reserve file descriptors for usage by this program", + (gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG, + REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4 index 77208faee0c..b4160ad2a99 100644 --- a/config/ac-macros/yassl.m4 +++ b/config/ac-macros/yassl.m4 @@ -30,7 +30,9 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ ;; esac AC_SUBST([yassl_taocrypt_extra_cxxflags]) - + # Link extra/yassl/include/openssl subdir to include/ + yassl_h_ln_cmd="\$(LN) -s \$(top_srcdir)/extra/yassl/include/openssl openssl" + AC_SUBST(yassl_h_ln_cmd) else yassl_dir="" AC_MSG_RESULT(no) diff --git a/configure.in b/configure.in index 9e2a0748b0d..e8256a5a526 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.1.5-alpha) +AM_INIT_AUTOMAKE(mysql, 5.1.6-alpha) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -15,12 +15,6 @@ DOT_FRM_VERSION=6 # See the libtool docs for information on how to do shared lib versions. SHARED_LIB_VERSION=15:0:0 -# ndb version -NDB_VERSION_MAJOR=5 -NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=19 -NDB_VERSION_STATUS="" - # Set all version vars based on $VERSION. How do we do this more elegant ? # Remember that regexps needs to quote [ and ] since this is run through m4 MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[[a-z]]*-.*$||"` diff --git a/include/Makefile.am b/include/Makefile.am index 44efe0b7211..ba9f8029def 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -34,7 +34,7 @@ noinst_HEADERS = config-win.h config-os2.h config-netware.h \ my_vle.h # mysql_version.h are generated -CLEANFILES = mysql_version.h my_config.h readline +CLEANFILES = mysql_version.h my_config.h readline openssl # Some include files that may be moved and patched by configure DISTCLEANFILES = sched.h $(CLEANFILES) @@ -42,6 +42,7 @@ DISTCLEANFILES = sched.h $(CLEANFILES) link_sources: -$(RM) -fr readline @readline_h_ln_cmd@ + @yassl_h_ln_cmd@ my_config.h: ../config.h $(CP) ../config.h my_config.h diff --git a/include/config-win.h b/include/config-win.h index 6c0937391fb..a08e25ed628 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -22,6 +22,11 @@ functions */ #define _WIN32_WINNT 0x0500 #endif +#if defined(_MSC_VER) && _MSC_VER >= 1400 +/* Avoid endless warnings about sprintf() etc. being unsafe. */ +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + #include #include #include /* Because of rint() */ @@ -341,6 +346,11 @@ inline double ulonglong2double(ulonglong value) #define HAVE_SETFILEPOINTER #define HAVE_VIO_READ_BUFF +#if defined(_WIN64) && defined(_M_X64) +/* Avoid type conflicts with built-in functions. */ +#define HAVE_STRNLEN +#endif + #ifndef __NT__ #undef FILE_SHARE_DELETE #define FILE_SHARE_DELETE 0 /* Not implemented on Win 98/ME */ diff --git a/include/hash.h b/include/hash.h index 9a6d91036e1..8f5ff21ae5e 100644 --- a/include/hash.h +++ b/include/hash.h @@ -33,7 +33,7 @@ typedef void (*hash_free_key)(void *); typedef struct st_hash { uint key_offset,key_length; /* Length of key if const length */ - uint records,blength,current_record; + uint records, blength; uint flags; DYNAMIC_ARRAY array; /* Place for hash_keys */ hash_get_key get_key; @@ -41,6 +41,9 @@ typedef struct st_hash { CHARSET_INFO *charset; } HASH; +/* A search iterator state */ +typedef uint HASH_SEARCH_STATE; + #define hash_init(A,B,C,D,E,F,G,H) _hash_init(A,B,C,D,E,F,G, H CALLER_INFO) my_bool _hash_init(HASH *hash, CHARSET_INFO *charset, uint default_array_elements, uint key_offset, @@ -49,12 +52,15 @@ my_bool _hash_init(HASH *hash, CHARSET_INFO *charset, void hash_free(HASH *tree); void my_hash_reset(HASH *hash); byte *hash_element(HASH *hash,uint idx); -gptr hash_search(HASH *info,const byte *key,uint length); -gptr hash_next(HASH *info,const byte *key,uint length); +gptr hash_search(const HASH *info, const byte *key, uint length); +gptr hash_first(const HASH *info, const byte *key, uint length, + HASH_SEARCH_STATE *state); +gptr hash_next(const HASH *info, const byte *key, uint length, + HASH_SEARCH_STATE *state); my_bool my_hash_insert(HASH *info,const byte *data); my_bool hash_delete(HASH *hash,byte *record); my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length); -void hash_replace(HASH *hash, uint idx, byte *new_row); +void hash_replace(HASH *hash, HASH_SEARCH_STATE *state, byte *new_row); my_bool hash_check(HASH *hash); /* Only in debug library */ #define hash_clear(H) bzero((char*) (H),sizeof(*(H))) diff --git a/include/my_global.h b/include/my_global.h index 8d7ad9e0ad5..82b0585757c 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -961,6 +961,7 @@ typedef off_t os_off_t; #define SOCKET_EAGAIN WSAEINPROGRESS #define SOCKET_ETIMEDOUT WSAETIMEDOUT #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK +#define SOCKET_EADDRINUSE WSAEADDRINUSE #define SOCKET_ENFILE ENFILE #define SOCKET_EMFILE EMFILE #elif defined(OS2) @@ -969,6 +970,7 @@ typedef off_t os_off_t; #define SOCKET_EAGAIN SOCEINPROGRESS #define SOCKET_ETIMEDOUT SOCKET_EINTR #define SOCKET_EWOULDBLOCK SOCEWOULDBLOCK +#define SOCKET_EADDRINUSE SOCEADDRINUSE #define SOCKET_ENFILE SOCENFILE #define SOCKET_EMFILE SOCEMFILE #define closesocket(A) soclose(A) @@ -979,6 +981,7 @@ typedef off_t os_off_t; #define SOCKET_EAGAIN EAGAIN #define SOCKET_ETIMEDOUT SOCKET_EINTR #define SOCKET_EWOULDBLOCK EWOULDBLOCK +#define SOCKET_EADDRINUSE EADDRINUSE #define SOCKET_ENFILE ENFILE #define SOCKET_EMFILE EMFILE #endif diff --git a/include/my_sys.h b/include/my_sys.h index d76098b8c29..39810e61de3 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -755,8 +755,9 @@ extern void delete_dynamic_element(DYNAMIC_ARRAY *array, uint array_index); extern void freeze_size(DYNAMIC_ARRAY *array); #define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element) #define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index)) -#define push_dynamic(A,B) insert_dynamic(A,B) +#define push_dynamic(A,B) insert_dynamic((A),(B)) #define reset_dynamic(array) ((array)->elements= 0) +#define sort_dynamic(A,cmp) qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp)) extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str, uint init_alloc,uint alloc_increment); diff --git a/include/plugin.h b/include/plugin.h index 7677db3ace2..6c571b8504b 100644 --- a/include/plugin.h +++ b/include/plugin.h @@ -39,8 +39,28 @@ #define mysql_declare_plugin \ int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \ +int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \ struct st_mysql_plugin _mysql_plugin_declarations_[]= { -#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0}} +#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0}} + +/* + declarations for SHOW STATUS support in plugins +*/ +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_MY_BOOL, SHOW_INT, SHOW_LONG, + SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC +}; + +struct st_mysql_show_var { + const char *name; + char *value; + enum enum_mysql_show_type type; +}; + +#define SHOW_VAR_FUNC_BUFF_SIZE 1024 +typedef int (*mysql_show_var_func)(void *, struct st_mysql_show_var*, char *); /* Plugin description structure. @@ -56,6 +76,7 @@ struct st_mysql_plugin int (*init)(void); /* the function to invoke when plugin is loaded */ int (*deinit)(void); /* the function to invoke when plugin is unloaded */ uint version; /* plugin version (for SHOW PLUGINS) */ + struct st_mysql_show_var *status_vars; }; /************************************************************************* diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am index ee6dd4cfded..11e65a28a19 100644 --- a/libmysql_r/Makefile.am +++ b/libmysql_r/Makefile.am @@ -22,7 +22,7 @@ target = libmysqlclient_r.la target_defs = -DDONT_USE_RAID -DMYSQL_CLIENT @LIB_EXTRA_CCFLAGS@ -LIBS = @LIBS@ @ZLIB_LIBS@ @openssl_libs@ @yassl_libs@ +LIBS = @LIBS@ @ZLIB_LIBS@ @openssl_libs@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ $(openssl_includes) $(yassl_includes) @ZLIB_INCLUDES@ @@ -32,7 +32,7 @@ include $(top_srcdir)/libmysql/Makefile.shared libmysql_dir = $(top_srcdir)/libmysql libmysqlclient_r_la_SOURCES = $(target_sources) -libmysqlclient_r_la_LIBADD = $(target_libadd) +libmysqlclient_r_la_LIBADD = $(target_libadd) $(yassl_libs_with_path) libmysqlclient_r_la_LDFLAGS = $(target_ldflags) # This is called from the toplevel makefile diff --git a/mysql-test/extra/rpl_tests/rpl_loaddata_m.test b/mysql-test/extra/rpl_tests/rpl_loaddata_m.test deleted file mode 100644 index ef90283f80e..00000000000 --- a/mysql-test/extra/rpl_tests/rpl_loaddata_m.test +++ /dev/null @@ -1,28 +0,0 @@ -# See if the master logs LOAD DATA INFILE correctly when binlog_*_db rules -# exist. -# This is for BUG#1100 (LOAD DATA INFILE was half-logged). - - --- source include/master-slave.inc - ---disable_warnings -drop database if exists mysqltest; ---enable_warnings - -connection slave; -stop slave; # don't need slave for this test - -# Test logging on master - -connection master; -# 'test' is the current database -create database mysqltest; -use mysqltest; -create table t1(a int, b int, unique(b)); -load data infile '../../std_data/rpl_loaddata.dat' into table t1; -# Starting from 5.0.3 LOAD DATA is replicated much in the same way as ordinary -# query so "show binlog ..." should show two events (before 5.0.3 no events -# were returned). ---replace_column 2 # 5 # -show binlog events from 102; -drop database mysqltest; diff --git a/mysql-test/extra/rpl_tests/rpl_row_blob.test b/mysql-test/extra/rpl_tests/rpl_row_blob.test new file mode 100644 index 00000000000..5f1e4bea6f3 --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_row_blob.test @@ -0,0 +1,179 @@ +################################################# +# Author: JBM +# Date: 2006-01-06 +# Purpose: Test test that BLOBs are replicated +# correctly. +################################################ + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +# Pre test clean up section +connection master; +--disable_warnings +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +--enable_warnings + +# Start test section +--echo ***** Table Create Section **** +--echo +--disable_warnings +--replace_result $engine_type engine_type +CREATE TABLE test.t1 (c1 int not null auto_increment, +data LONGBLOB, PRIMARY KEY(c1))ENGINE=$engine_type; +--enable_warnings +--echo + +--echo **** Data Insert Section test.t1 ***** +--echo +INSERT INTO test.t1 VALUES (NULL, NULL); +INSERT INTO test.t1 VALUES (NULL, repeat('a',1*1024)); +INSERT INTO test.t1 VALUES (NULL, repeat('b',16*1024)); +CHECK TABLE test.t1; +--echo + +--echo **** Data Insert Validation Master Section test.t1 **** +--echo +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 3; +save_master_pos; +connection slave; +sync_with_master; +--echo +--echo **** Data Insert Validation Slave Section test.t1 **** +--echo +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 3; +connection master; +--echo + +--echo **** Data Update Section test.t1 **** +--echo +UPDATE test.t1 set data=repeat('a',18*1024) where c1 = 1; +UPDATE t1 set data=repeat('c',17*1024) where c1 = 2; +--echo + +--echo **** Data Update Validation Master Section test.t1 **** +--echo +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +save_master_pos; +connection slave; +sync_with_master; +--echo +--echo **** Data Update Validation Slave Section test.t1 **** +--echo +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +connection master; +--echo +--echo **** End Test Section test.t1 **** +--echo + +--echo **** Create Table test.t2 **** +--echo +--disable_warnings +--replace_result $engine_type engine_type +CREATE TABLE test.t2 ( + c1 INT NOT NULL PRIMARY KEY, + c2 TEXT, + c3 INT, + c4 LONGBLOB, + KEY(c3))ENGINE=$engine_type; +--enable_warnings +--echo + +--echo *** Setup Values For test.t2 *** +# x0 size 256 (current inline size) +set @x0 = '01234567012345670123456701234567'; +set @x0 = concat(@x0,@x0,@x0,@x0,@x0,@x0,@x0,@x0); + +# b1 length 2000+256 (blob part aligned) +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1); +set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1); +set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1); +set @b1 = concat(@b1,@x0); +# d1 length 3000 +set @d1 = 'dd1'; +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); + +# b2 length 20000 +set @b2 = 'b2'; +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); + +# d2 length 30000 +set @d2 = 'dd2'; +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); +--echo + +--echo **** Data Insert Section test.t2 ***** +--echo +INSERT INTO test.t2 VALUES(1,@b1,111,@d1); +INSERT INTO test.t2 VALUES(2,@b2,222,@d2); +--echo + +--echo **** Data Insert Validation Master Section test.t2 **** +--echo +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +save_master_pos; +connection slave; +sync_with_master; +--echo +--echo **** Data Insert Validation Slave Section test.t2 **** +--echo +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +connection master; +--echo + +--echo **** Data Update Section test.t2 **** +--echo +UPDATE test.t2 SET c2=@b2, c4=@d2 WHERE c1=1; +UPDATE test.t2 SET c2=@b1, c4=@d1 WHERE c1=2; +--echo + +--echo **** Data Update Validation Master Section test.t2 **** +--echo +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +save_master_pos; +connection slave; +sync_with_master; +--echo +--echo **** Data Update Validation Slave Section test.t2 **** +--echo +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +connection master; +--echo + +# Post test clean up section +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > ./var/tmp/rpl_row_blob_master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > ./var/tmp/rpl_row_blob_slave.sql + +--exec diff ./var/tmp/rpl_row_blob_master.sql ./var/tmp/rpl_row_blob_slave.sql + +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index b3a243444c1..4d88c9b3322 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -890,7 +890,14 @@ sub mtr_exit ($) { # cluck("Called mtr_exit()"); mtr_timer_stop_all($::glob_timers); local $SIG{HUP} = 'IGNORE'; - kill('HUP', -$$); + # ToDo: Signalling -$$ will only work if we are the process group + # leader (in fact on QNX it will signal our session group leader, + # which might be Do-compile or Pushbuild, causing tests to be + # aborted). So we only do it if we are the group leader. We might + # set ourselves as the group leader at startup (with + # POSIX::setpgrp(0,0)), but then care must be needed to always do + # proper child process cleanup. + kill('HUP', -$$) if $$ == getpgrp(); sleep 2; exit($code); } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 60c9686bf0a..396ae92d34c 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -805,6 +805,12 @@ sub command_line_setup () { } } + # On QNX, /tmp/dir/master.sock and /tmp/dir//master.sock seem to be + # considered different, so avoid the extra slash (/) in the socket + # paths. + my $sockdir = $opt_tmpdir; + $sockdir =~ s|/+$||; + # Put this into a hash, will be a C struct $master->[0]= @@ -813,7 +819,7 @@ sub command_line_setup () { path_myerr => "$opt_vardir/log/master.err", path_mylog => "$opt_vardir/log/master.log", path_mypid => "$opt_vardir/run/master.pid", - path_mysock => "$opt_tmpdir/master.sock", + path_mysock => "$sockdir/master.sock", path_myport => $opt_master_myport, start_timeout => 400, # enough time create innodb tables @@ -826,7 +832,7 @@ sub command_line_setup () { path_myerr => "$opt_vardir/log/master1.err", path_mylog => "$opt_vardir/log/master1.log", path_mypid => "$opt_vardir/run/master1.pid", - path_mysock => "$opt_tmpdir/master1.sock", + path_mysock => "$sockdir/master1.sock", path_myport => $opt_master_myport + 1, start_timeout => 400, # enough time create innodb tables }; @@ -837,7 +843,7 @@ sub command_line_setup () { path_myerr => "$opt_vardir/log/slave.err", path_mylog => "$opt_vardir/log/slave.log", path_mypid => "$opt_vardir/run/slave.pid", - path_mysock => "$opt_tmpdir/slave.sock", + path_mysock => "$sockdir/slave.sock", path_myport => $opt_slave_myport, start_timeout => 400, }; @@ -848,7 +854,7 @@ sub command_line_setup () { path_myerr => "$opt_vardir/log/slave1.err", path_mylog => "$opt_vardir/log/slave1.log", path_mypid => "$opt_vardir/run/slave1.pid", - path_mysock => "$opt_tmpdir/slave1.sock", + path_mysock => "$sockdir/slave1.sock", path_myport => $opt_slave_myport + 1, start_timeout => 300, }; @@ -859,7 +865,7 @@ sub command_line_setup () { path_myerr => "$opt_vardir/log/slave2.err", path_mylog => "$opt_vardir/log/slave2.log", path_mypid => "$opt_vardir/run/slave2.pid", - path_mysock => "$opt_tmpdir/slave2.sock", + path_mysock => "$sockdir/slave2.sock", path_myport => $opt_slave_myport + 2, start_timeout => 300, }; @@ -869,7 +875,7 @@ sub command_line_setup () { path_err => "$opt_vardir/log/im.err", path_log => "$opt_vardir/log/im.log", path_pid => "$opt_vardir/run/im.pid", - path_sock => "$opt_tmpdir/im.sock", + path_sock => "$sockdir/im.sock", port => $im_port, start_timeout => $master->[0]->{'start_timeout'}, admin_login => 'im_admin', @@ -884,7 +890,7 @@ sub command_line_setup () { server_id => 1, port => $im_mysqld1_port, path_datadir => "$opt_vardir/im_mysqld_1.data", - path_sock => "$opt_tmpdir/mysqld_1.sock", + path_sock => "$sockdir/mysqld_1.sock", path_pid => "$opt_vardir/run/mysqld_1.pid", }; @@ -893,7 +899,7 @@ sub command_line_setup () { server_id => 2, port => $im_mysqld2_port, path_datadir => "$opt_vardir/im_mysqld_2.data", - path_sock => "$opt_tmpdir/mysqld_2.sock", + path_sock => "$sockdir/mysqld_2.sock", path_pid => "$opt_vardir/run/mysqld_2.pid", nonguarded => 1, }; diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index 9be2723ef96..c40fd696704 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -1957,4 +1957,9 @@ d varchar(255) character set utf8, e varchar(255) character set utf8, key (a,b,c,d,e)) engine=bdb; ERROR 42000: Specified key was too long; max key length is 3072 bytes +set autocommit=0; +create table t1 (a int) engine=bdb; +commit; +alter table t1 add primary key(a); +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/binlog_row_mix_innodb_myisam.result b/mysql-test/r/binlog_row_mix_innodb_myisam.result index 3a26d84d575..b444d7a3edc 100644 --- a/mysql-test/r/binlog_row_mix_innodb_myisam.result +++ b/mysql-test/r/binlog_row_mix_innodb_myisam.result @@ -262,21 +262,22 @@ master-bin.000001 209 Write_rows 1 # master-bin.000001 243 Table_map 1 # test.t1 master-bin.000001 282 Write_rows 1 # master-bin.000001 316 Xid 1 # COMMIT /* xid= */ -master-bin.000001 343 Table_map 1 # test.t1 -master-bin.000001 382 Delete_rows 1 # -master-bin.000001 421 Xid 1 # COMMIT /* xid= */ -master-bin.000001 448 Query 1 # use `test`; alter table t2 type=MyISAM -master-bin.000001 537 Table_map 1 # test.t1 -master-bin.000001 576 Write_rows 1 # -master-bin.000001 610 Xid 1 # COMMIT /* xid= */ -master-bin.000001 637 Table_map 1 # test.t2 -master-bin.000001 676 Write_rows 1 # -master-bin.000001 710 Query 1 # use `test`; drop table t1,t2 -master-bin.000001 789 Query 1 # use `test`; create table t0 (n int) -master-bin.000001 875 Table_map 1 # test.t0 -master-bin.000001 914 Write_rows 1 # -master-bin.000001 948 Table_map 1 # test.t0 -master-bin.000001 987 Write_rows 1 # -master-bin.000001 1021 Query 1 # use `test`; create table t2 (n int) engine=innodb +master-bin.000001 343 Query 1 # use `test`; delete from t1 +master-bin.000001 420 Xid 1 # COMMIT /* xid= */ +master-bin.000001 447 Query 1 # use `test`; delete from t2 +master-bin.000001 524 Xid 1 # COMMIT /* xid= */ +master-bin.000001 551 Query 1 # use `test`; alter table t2 type=MyISAM +master-bin.000001 640 Table_map 1 # test.t1 +master-bin.000001 679 Write_rows 1 # +master-bin.000001 713 Xid 1 # COMMIT /* xid= */ +master-bin.000001 740 Table_map 1 # test.t2 +master-bin.000001 779 Write_rows 1 # +master-bin.000001 813 Query 1 # use `test`; drop table t1,t2 +master-bin.000001 892 Query 1 # use `test`; create table t0 (n int) +master-bin.000001 978 Table_map 1 # test.t0 +master-bin.000001 1017 Write_rows 1 # +master-bin.000001 1051 Table_map 1 # test.t0 +master-bin.000001 1090 Write_rows 1 # +master-bin.000001 1124 Query 1 # use `test`; create table t2 (n int) engine=innodb do release_lock("lock1"); drop table t0,t2; diff --git a/mysql-test/r/binlog_stm_blackhole.result b/mysql-test/r/binlog_stm_blackhole.result index 7b6e61984ec..994a40832c7 100644 --- a/mysql-test/r/binlog_stm_blackhole.result +++ b/mysql-test/r/binlog_stm_blackhole.result @@ -121,6 +121,7 @@ master-bin.000001 # Query 1 # use `test`; replace into t1 values(100) master-bin.000001 # Query 1 # use `test`; COMMIT master-bin.000001 # Query 1 # use `test`; create table t2 (a varchar(200)) engine=blackhole master-bin.000001 # Begin_load_query 1 # ;file_id=1;block_len=581 +master-bin.000001 # Query 1 # use `test`; COMMIT master-bin.000001 # Execute_load_query 1 # use `test`; load data infile '../../std_data/words.dat' into table t2 ;file_id=1 master-bin.000001 # Query 1 # use `test`; COMMIT master-bin.000001 # Query 1 # use `test`; alter table t1 add b int diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 7b15785a042..123750f2180 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -279,7 +279,6 @@ a b create table if not exists t1 select 3 as 'a',4 as 'b'; Warnings: Note 1050 Table 't1' already exists -Warning 1364 Field 'a' doesn't have a default value create table if not exists t1 select 3 as 'a',3 as 'b'; ERROR 23000: Duplicate entry '3' for key 1 select * from t1; @@ -635,8 +634,6 @@ create table t1 ( a varchar(112) charset utf8 collate utf8_bin not null, primary key (a) ) select 'test' as a ; -Warnings: -Warning 1364 Field 'a' doesn't have a default value show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -652,9 +649,6 @@ create table t1 ( a varchar(12) charset utf8 collate utf8_bin not null, b int not null, primary key (a) ) select a, 1 as b from t2 ; -Warnings: -Warning 1364 Field 'a' doesn't have a default value -Warning 1364 Field 'b' doesn't have a default value show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -664,12 +658,37 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 ( +a varchar(12) charset utf8 collate utf8_bin not null, +b int not null, primary key (a) +) select a, 1 as c from t2 ; +Warnings: +Warning 1364 Field 'b' doesn't have a default value +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` int(11) NOT NULL, + `a` varchar(12) character set utf8 collate utf8_bin NOT NULL, + `c` bigint(1) NOT NULL default '0', + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1 ( +a varchar(12) charset utf8 collate utf8_bin not null, +b int null, primary key (a) +) select a, 1 as c from t2 ; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` int(11) default NULL, + `a` varchar(12) character set utf8 collate utf8_bin NOT NULL, + `c` bigint(1) NOT NULL default '0', + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1 ( a varchar(12) charset utf8 collate utf8_bin not null, b int not null, primary key (a) ) select 'a' as a , 1 as b from t2 ; -Warnings: -Warning 1364 Field 'a' doesn't have a default value -Warning 1364 Field 'b' doesn't have a default value show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -682,8 +701,6 @@ create table t1 ( a varchar(12) charset utf8 collate utf8_bin, b int not null, primary key (a) ) select 'a' as a , 1 as b from t2 ; -Warnings: -Warning 1364 Field 'b' doesn't have a default value show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -702,8 +719,6 @@ a1 varchar(12) charset utf8 collate utf8_bin not null, a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int, primary key (a1) ) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1 ; -Warnings: -Warning 1364 Field 'a1' doesn't have a default value drop table t2; create table t2 ( a1 varchar(12) charset utf8 collate utf8_bin, @@ -719,8 +734,6 @@ a1 varchar(12) charset utf8 collate utf8_bin not null, a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int, primary key (a1) ) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1 ; -Warnings: -Warning 1364 Field 'a1' doesn't have a default value drop table t2; create table t2 ( a int default 3, b int default 3) select a1,a2 from t1; diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result index 133683fb273..104025e83eb 100644 --- a/mysql-test/r/handler.result +++ b/mysql-test/r/handler.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1,t3,t4,t5; create table t1 (a int, b char(10), key a(a), key b(a,b)); insert into t1 values (17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"), diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 8c0a1dfe753..d15705a25f8 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1077,6 +1077,22 @@ character_maximum_length character_octet_length 32 32 64 64 drop table t1; +CREATE TABLE t1 (f1 BIGINT, f2 VARCHAR(20), f3 BIGINT); +INSERT INTO t1 SET f1 = 1, f2 = 'Schoenenbourg', f3 = 1; +CREATE FUNCTION func2() RETURNS BIGINT RETURN 1; +CREATE FUNCTION func1() RETURNS BIGINT +BEGIN +RETURN ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.VIEWS); +END// +CREATE VIEW v1 AS SELECT 1 FROM t1 +WHERE f3 = (SELECT func2 ()); +SELECT func1(); +func1() +1 +DROP TABLE t1; +DROP VIEW v1; +DROP FUNCTION func1; +DROP FUNCTION func2; select * from information_schema.engines WHERE ENGINE="MyISAM"; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS MyISAM ENABLED Default engine as of MySQL 3.23 with great performance NO NO NO diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index 754568093ff..2413834be4f 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -5,8 +5,6 @@ select ((@id := kill_id) - kill_id) from t1; ((@id := kill_id) - kill_id) 0 kill @id; -select 1; -Got one of the listed errors select ((@id := kill_id) - kill_id) from t1; ((@id := kill_id) - kill_id) 0 diff --git a/mysql-test/r/mysqlshow.result b/mysql-test/r/mysqlshow.result index 355c20fdad3..942cde83f21 100644 --- a/mysql-test/r/mysqlshow.result +++ b/mysql-test/r/mysqlshow.result @@ -1,4 +1,4 @@ -DROP TABLE IF EXISTS t1,t2; +DROP TABLE IF EXISTS t1,t2,test1,test2; CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); CREATE TABLE t2 (a int, b int); diff --git a/mysql-test/r/rpl_row_ddl.result b/mysql-test/r/rpl_ddl.result similarity index 100% rename from mysql-test/r/rpl_row_ddl.result rename to mysql-test/r/rpl_ddl.result diff --git a/mysql-test/r/rpl_drop_db.result b/mysql-test/r/rpl_drop_db.result index ce9d39e87f6..3a35dc266b6 100644 --- a/mysql-test/r/rpl_drop_db.result +++ b/mysql-test/r/rpl_drop_db.result @@ -31,5 +31,5 @@ use test; select * from t1; n 1234 -drop table t1; +DROP DATABASE mysqltest1; stop slave; diff --git a/mysql-test/r/rpl_err_ignoredtable.result b/mysql-test/r/rpl_err_ignoredtable.result new file mode 100644 index 00000000000..84072be7d44 --- /dev/null +++ b/mysql-test/r/rpl_err_ignoredtable.result @@ -0,0 +1,42 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +create table t1 (a int primary key); +create table t4 (a int primary key); +insert into t1 values (1),(1); +ERROR 23000: Duplicate entry '1' for key 1 +insert into t4 values (1),(2); +show tables like 't1'; +Tables_in_test (t1) +show tables like 't4'; +Tables_in_test (t4) +t4 +SELECT * FROM test.t4; +a +1 +2 +drop table t1; +select get_lock('crash_lock%20C', 10); +get_lock('crash_lock%20C', 10) +1 +create table t2 (a int primary key); +insert into t2 values(1); +create table t3 (id int); +insert into t3 values(connection_id()); + update t2 set a = a + 1 + get_lock('crash_lock%20C', 10); +select (@id := id) - id from t3; +(@id := id) - id +0 +kill @id; +drop table t2,t3; +insert into t4 values (3),(4); +SELECT * FROM test.t4; +a +1 +2 +3 +4 +DROP TABLE test.t4; diff --git a/mysql-test/r/rpl_loaddata_m.result b/mysql-test/r/rpl_loaddata_m.result new file mode 100644 index 00000000000..1d263a41e1b --- /dev/null +++ b/mysql-test/r/rpl_loaddata_m.result @@ -0,0 +1,38 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +drop database if exists mysqltest; +USE test; +CREATE TABLE t1(a INT, b INT, UNIQUE(b)); +LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE test.t1; +SELECT COUNT(*) FROM test.t1; +COUNT(*) +2 +CREATE DATABASE mysqltest; +USE mysqltest; +CREATE TABLE t1(a INT, b INT, UNIQUE(b)); +LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE mysqltest.t1; +SELECT COUNT(*) FROM mysqltest.t1; +COUNT(*) +2 +SHOW DATABASES; +Database +information_schema +mysql +mysqltest +test +USE test; +SHOW TABLES; +Tables_in_test +USE mysqltest; +SHOW TABLES; +Tables_in_mysqltest +t1 +SELECT COUNT(*) FROM mysqltest.t1; +COUNT(*) +2 +DROP DATABASE mysqltest; +DROP TABLE test.t1; diff --git a/mysql-test/r/rpl_multi_engine.result b/mysql-test/r/rpl_multi_engine.result index 27482eae6d9..0492231be37 100644 --- a/mysql-test/r/rpl_multi_engine.result +++ b/mysql-test/r/rpl_multi_engine.result @@ -363,3 +363,4 @@ id hex(b1) vc bc d f total y t select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id; id hex(b1) vc bc d f total y t DROP TABLE t1; +DROP DATABASE mysqltest1; diff --git a/mysql-test/r/rpl_row_rewrt_db.result b/mysql-test/r/rpl_rewrt_db.result similarity index 100% rename from mysql-test/r/rpl_row_rewrt_db.result rename to mysql-test/r/rpl_rewrt_db.result diff --git a/mysql-test/r/rpl_row_basic_11bugs.result b/mysql-test/r/rpl_row_basic_11bugs.result new file mode 100644 index 00000000000..9249405ac26 --- /dev/null +++ b/mysql-test/r/rpl_row_basic_11bugs.result @@ -0,0 +1,45 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE DATABASE test_ignore; +**** On Master **** +SHOW DATABASES; +Database +information_schema +mysql +test +test_ignore +USE test; +CREATE TABLE t1 (a INT, b INT); +SHOW TABLES; +Tables_in_test +t1 +INSERT INTO t1 VALUES (1,1), (2,2); +USE test_ignore; +CREATE TABLE t2 (a INT, b INT); +SHOW TABLES; +Tables_in_test_ignore +t2 +INSERT INTO t2 VALUES (3,3), (4,4); +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: 5.1.5-alpha-debug-log, Binlog ver: 4 +master-bin.000001 102 Query 1 195 use `test`; CREATE TABLE t1 (a INT, b INT) +master-bin.000001 195 Table_map 1 235 test.t1 +master-bin.000001 235 Write_rows 1 282 +**** On Slave **** +SHOW DATABASES; +Database +information_schema +mysql +test +USE test; +SHOW TABLES; +Tables_in_test +t1 +USE test_ignore; +ERROR 42000: Unknown database 'test_ignore' +DROP DATABASE test_ignore; diff --git a/mysql-test/r/rpl_row_blob_innodb.result b/mysql-test/r/rpl_row_blob_innodb.result new file mode 100644 index 00000000000..92671f10ab9 --- /dev/null +++ b/mysql-test/r/rpl_row_blob_innodb.result @@ -0,0 +1,159 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +***** Table Create Section **** + +CREATE TABLE test.t1 (c1 int not null auto_increment, +data LONGBLOB, PRIMARY KEY(c1))ENGINE=$engine_type; + +**** Data Insert Section test.t1 ***** + +INSERT INTO test.t1 VALUES (NULL, NULL); +INSERT INTO test.t1 VALUES (NULL, repeat('a',1*1024)); +INSERT INTO test.t1 VALUES (NULL, repeat('b',16*1024)); +CHECK TABLE test.t1; +Table Op Msg_type Msg_text +test.t1 check status OK + +**** Data Insert Validation Master Section test.t1 **** + +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +LENGTH(data) +NULL +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +LENGTH(data) +1024 +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 3; +LENGTH(data) +16384 + +**** Data Insert Validation Slave Section test.t1 **** + +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +LENGTH(data) +NULL +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +LENGTH(data) +1024 +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 3; +LENGTH(data) +16384 + +**** Data Update Section test.t1 **** + +UPDATE test.t1 set data=repeat('a',18*1024) where c1 = 1; +UPDATE t1 set data=repeat('c',17*1024) where c1 = 2; + +**** Data Update Validation Master Section test.t1 **** + +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +LENGTH(data) +18432 +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +LENGTH(data) +17408 + +**** Data Update Validation Slave Section test.t1 **** + +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +LENGTH(data) +18432 +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +LENGTH(data) +17408 + +**** End Test Section test.t1 **** + +**** Create Table test.t2 **** + +CREATE TABLE test.t2 ( +c1 INT NOT NULL PRIMARY KEY, +c2 TEXT, +c3 INT, +c4 LONGBLOB, +KEY(c3))ENGINE=$engine_type; + +*** Setup Values For test.t2 *** +set @x0 = '01234567012345670123456701234567'; +set @x0 = concat(@x0,@x0,@x0,@x0,@x0,@x0,@x0,@x0); +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1); +set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1); +set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1); +set @b1 = concat(@b1,@x0); +set @d1 = 'dd1'; +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); +set @b2 = 'b2'; +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @d2 = 'dd2'; +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); + +**** Data Insert Section test.t2 ***** + +INSERT INTO test.t2 VALUES(1,@b1,111,@d1); +INSERT INTO test.t2 VALUES(2,@b2,222,@d2); + +**** Data Insert Validation Master Section test.t2 **** + +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +1 2256 b1 3000 dd1 +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +2 20000 b2 30000 dd2 + +**** Data Insert Validation Slave Section test.t2 **** + +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +1 2256 b1 3000 dd1 +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +2 20000 b2 30000 dd2 + +**** Data Update Section test.t2 **** + +UPDATE test.t2 SET c2=@b2, c4=@d2 WHERE c1=1; +UPDATE test.t2 SET c2=@b1, c4=@d1 WHERE c1=2; + +**** Data Update Validation Master Section test.t2 **** + +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +1 20000 b2 30000 dd2 +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +2 2256 b1 3000 dd1 + +**** Data Update Validation Slave Section test.t2 **** + +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +1 20000 b2 30000 dd2 +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +2 2256 b1 3000 dd1 + +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; diff --git a/mysql-test/r/rpl_row_blob_myisam.result b/mysql-test/r/rpl_row_blob_myisam.result new file mode 100644 index 00000000000..92671f10ab9 --- /dev/null +++ b/mysql-test/r/rpl_row_blob_myisam.result @@ -0,0 +1,159 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +***** Table Create Section **** + +CREATE TABLE test.t1 (c1 int not null auto_increment, +data LONGBLOB, PRIMARY KEY(c1))ENGINE=$engine_type; + +**** Data Insert Section test.t1 ***** + +INSERT INTO test.t1 VALUES (NULL, NULL); +INSERT INTO test.t1 VALUES (NULL, repeat('a',1*1024)); +INSERT INTO test.t1 VALUES (NULL, repeat('b',16*1024)); +CHECK TABLE test.t1; +Table Op Msg_type Msg_text +test.t1 check status OK + +**** Data Insert Validation Master Section test.t1 **** + +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +LENGTH(data) +NULL +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +LENGTH(data) +1024 +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 3; +LENGTH(data) +16384 + +**** Data Insert Validation Slave Section test.t1 **** + +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +LENGTH(data) +NULL +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +LENGTH(data) +1024 +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 3; +LENGTH(data) +16384 + +**** Data Update Section test.t1 **** + +UPDATE test.t1 set data=repeat('a',18*1024) where c1 = 1; +UPDATE t1 set data=repeat('c',17*1024) where c1 = 2; + +**** Data Update Validation Master Section test.t1 **** + +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +LENGTH(data) +18432 +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +LENGTH(data) +17408 + +**** Data Update Validation Slave Section test.t1 **** + +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 1; +LENGTH(data) +18432 +SELECT LENGTH(data) FROM test.t1 WHERE c1 = 2; +LENGTH(data) +17408 + +**** End Test Section test.t1 **** + +**** Create Table test.t2 **** + +CREATE TABLE test.t2 ( +c1 INT NOT NULL PRIMARY KEY, +c2 TEXT, +c3 INT, +c4 LONGBLOB, +KEY(c3))ENGINE=$engine_type; + +*** Setup Values For test.t2 *** +set @x0 = '01234567012345670123456701234567'; +set @x0 = concat(@x0,@x0,@x0,@x0,@x0,@x0,@x0,@x0); +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1); +set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1); +set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1); +set @b1 = concat(@b1,@x0); +set @d1 = 'dd1'; +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); +set @b2 = 'b2'; +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2); +set @d2 = 'dd2'; +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); +set @d2 = concat(@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2,@d2); + +**** Data Insert Section test.t2 ***** + +INSERT INTO test.t2 VALUES(1,@b1,111,@d1); +INSERT INTO test.t2 VALUES(2,@b2,222,@d2); + +**** Data Insert Validation Master Section test.t2 **** + +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +1 2256 b1 3000 dd1 +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +2 20000 b2 30000 dd2 + +**** Data Insert Validation Slave Section test.t2 **** + +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +1 2256 b1 3000 dd1 +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +2 20000 b2 30000 dd2 + +**** Data Update Section test.t2 **** + +UPDATE test.t2 SET c2=@b2, c4=@d2 WHERE c1=1; +UPDATE test.t2 SET c2=@b1, c4=@d1 WHERE c1=2; + +**** Data Update Validation Master Section test.t2 **** + +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +1 20000 b2 30000 dd2 +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +2 2256 b1 3000 dd1 + +**** Data Update Validation Slave Section test.t2 **** + +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=1; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +1 20000 b2 30000 dd2 +SELECT c1, LENGTH(c2), SUBSTR(c2,1+2*900,2), LENGTH(c4), SUBSTR(c4,1+3*900,3) +FROM test.t2 WHERE c1=2; +c1 LENGTH(c2) SUBSTR(c2,1+2*900,2) LENGTH(c4) SUBSTR(c4,1+3*900,3) +2 2256 b1 3000 dd1 + +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; diff --git a/mysql-test/r/rpl_row_sp000.result b/mysql-test/r/rpl_row_sp000.result index a7f72193842..c02fdecf7fd 100644 --- a/mysql-test/r/rpl_row_sp000.result +++ b/mysql-test/r/rpl_row_sp000.result @@ -58,6 +58,9 @@ insert into t1 values (15); grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1; +SELECT 1; +1 +1 create procedure foo4() deterministic begin diff --git a/mysql-test/r/rpl_stm_ddl.result b/mysql-test/r/rpl_stm_ddl.result deleted file mode 100644 index 91163f1fe29..00000000000 --- a/mysql-test/r/rpl_stm_ddl.result +++ /dev/null @@ -1,1693 +0,0 @@ -stop slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -reset master; -reset slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -start slave; -SET AUTOCOMMIT = 1; -DROP DATABASE IF EXISTS mysqltest1; -DROP DATABASE IF EXISTS mysqltest2; -DROP DATABASE IF EXISTS mysqltest3; -CREATE DATABASE mysqltest1; -CREATE DATABASE mysqltest2; -CREATE TABLE mysqltest1.t1 (f1 BIGINT) ENGINE="InnoDB"; -INSERT INTO mysqltest1.t1 SET f1= 0; -CREATE TABLE mysqltest1.t2 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t3 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t4 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t5 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t6 (f1 BIGINT) ENGINE="InnoDB"; -CREATE INDEX my_idx6 ON mysqltest1.t6(f1); -CREATE TABLE mysqltest1.t7 (f1 BIGINT) ENGINE="InnoDB"; -INSERT INTO mysqltest1.t7 SET f1= 0; -CREATE TABLE mysqltest1.t8 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t9 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t10 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t11 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t12 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t13 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t14 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t15 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t16 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t17 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t18 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TABLE mysqltest1.t19 (f1 BIGINT) ENGINE="InnoDB"; -CREATE TEMPORARY TABLE mysqltest1.t23 (f1 BIGINT); -SET AUTOCOMMIT = 0; -use mysqltest1; - --------- switch to slave -------- -SET AUTOCOMMIT = 0; -use mysqltest1; - --------- switch to master ------- - -######## COMMIT ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 0 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -0 - --------- switch to master ------- -COMMIT; -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- - -######## ROLLBACK ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 1 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -2 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - -TEST-INFO: MASTER: The INSERT is not committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - -TEST-INFO: SLAVE: The INSERT is not committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- - -######## SET AUTOCOMMIT=1 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 1 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -2 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -1 - --------- switch to master ------- -SET AUTOCOMMIT=1; -SELECT MAX(f1) FROM t1; -MAX(f1) -2 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -2 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -2 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -2 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SET AUTOCOMMIT=0; - -######## START TRANSACTION ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 2 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -3 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -2 - --------- switch to master ------- -START TRANSACTION; -SELECT MAX(f1) FROM t1; -MAX(f1) -3 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -3 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -3 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -3 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- - -######## BEGIN ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 3 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -4 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -3 - --------- switch to master ------- -BEGIN; -SELECT MAX(f1) FROM t1; -MAX(f1) -4 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -4 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -4 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -4 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- - -######## DROP TABLE mysqltest1.t2 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 4 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -5 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -4 - --------- switch to master ------- -DROP TABLE mysqltest1.t2; -SELECT MAX(f1) FROM t1; -MAX(f1) -5 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -5 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -5 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -5 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW TABLES LIKE 't2'; -Tables_in_mysqltest1 (t2) - --------- switch to slave -------- -SHOW TABLES LIKE 't2'; -Tables_in_mysqltest1 (t2) - --------- switch to master ------- - -######## DROP TEMPORARY TABLE mysqltest1.t23 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 5 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -6 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -5 - --------- switch to master ------- -DROP TEMPORARY TABLE mysqltest1.t23; -SELECT MAX(f1) FROM t1; -MAX(f1) -6 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -5 - --------- switch to master ------- -ROLLBACK; -Warnings: -Warning 1196 Some non-transactional changed tables couldn't be rolled back -SELECT MAX(f1) FROM t1; -MAX(f1) -5 - -TEST-INFO: MASTER: The INSERT is not committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -6 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW TABLES LIKE 't23'; -Tables_in_mysqltest1 (t23) - --------- switch to slave -------- -SHOW TABLES LIKE 't23'; -Tables_in_mysqltest1 (t23) - --------- switch to master ------- - -######## RENAME TABLE mysqltest1.t3 to mysqltest1.t20 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 5 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -6 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -6 - --------- switch to master ------- -RENAME TABLE mysqltest1.t3 to mysqltest1.t20; -SELECT MAX(f1) FROM t1; -MAX(f1) -6 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -6 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -6 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -6 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW TABLES LIKE 't20'; -Tables_in_mysqltest1 (t20) -t20 - --------- switch to slave -------- -SHOW TABLES LIKE 't20'; -Tables_in_mysqltest1 (t20) -t20 - --------- switch to master ------- - -######## ALTER TABLE mysqltest1.t4 ADD column f2 BIGINT ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 6 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -7 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -6 - --------- switch to master ------- -ALTER TABLE mysqltest1.t4 ADD column f2 BIGINT; -SELECT MAX(f1) FROM t1; -MAX(f1) -7 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -7 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -7 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -7 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -describe mysqltest1.t4; -Field Type Null Key Default Extra -f1 bigint(20) YES NULL -f2 bigint(20) YES NULL - --------- switch to slave -------- -describe mysqltest1.t4; -Field Type Null Key Default Extra -f1 bigint(20) YES NULL -f2 bigint(20) YES NULL - --------- switch to master ------- - -######## CREATE TABLE mysqltest1.t21 (f1 BIGINT) ENGINE= "InnoDB" ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 7 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -8 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -7 - --------- switch to master ------- -CREATE TABLE mysqltest1.t21 (f1 BIGINT) ENGINE= "InnoDB"; -SELECT MAX(f1) FROM t1; -MAX(f1) -8 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -8 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -8 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -8 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- - -######## CREATE TEMPORARY TABLE mysqltest1.t22 (f1 BIGINT) ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 8 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -9 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -8 - --------- switch to master ------- -CREATE TEMPORARY TABLE mysqltest1.t22 (f1 BIGINT); -SELECT MAX(f1) FROM t1; -MAX(f1) -9 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -8 - --------- switch to master ------- -ROLLBACK; -Warnings: -Warning 1196 Some non-transactional changed tables couldn't be rolled back -SELECT MAX(f1) FROM t1; -MAX(f1) -8 - -TEST-INFO: MASTER: The INSERT is not committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -9 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- - -######## TRUNCATE TABLE mysqltest1.t7 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 8 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -9 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -9 - --------- switch to master ------- -TRUNCATE TABLE mysqltest1.t7; -SELECT MAX(f1) FROM t1; -MAX(f1) -9 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -9 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -9 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -9 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SELECT * FROM mysqltest1.t7; -f1 - --------- switch to slave -------- -SELECT * FROM mysqltest1.t7; -f1 - --------- switch to master ------- - -######## LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 9 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -9 - --------- switch to master ------- -LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ; -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -UNLOCK TABLES; - -######## UNLOCK TABLES ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 10 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -11 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - --------- switch to master ------- -UNLOCK TABLES; -SELECT MAX(f1) FROM t1; -MAX(f1) -11 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - -TEST-INFO: MASTER: The INSERT is not committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - -TEST-INFO: SLAVE: The INSERT is not committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -LOCK TABLES mysqltest1.t1 READ; - -######## UNLOCK TABLES ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 10 + 1; -ERROR HY000: Table 't1' was locked with a READ lock and can't be updated -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - --------- switch to master ------- -UNLOCK TABLES; -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - -TEST-INFO: MASTER: The INSERT is not committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - -TEST-INFO: SLAVE: The INSERT is not committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ; - -######## UNLOCK TABLES ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 10 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -11 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -10 - --------- switch to master ------- -UNLOCK TABLES; -SELECT MAX(f1) FROM t1; -MAX(f1) -11 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -11 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -11 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -11 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- - -######## DROP INDEX my_idx6 ON mysqltest1.t6 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 11 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -12 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -11 - --------- switch to master ------- -DROP INDEX my_idx6 ON mysqltest1.t6; -SELECT MAX(f1) FROM t1; -MAX(f1) -12 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -12 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -12 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -12 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW INDEX FROM mysqltest1.t6; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment - --------- switch to slave -------- -SHOW INDEX FROM mysqltest1.t6; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment - --------- switch to master ------- - -######## CREATE INDEX my_idx5 ON mysqltest1.t5(f1) ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 12 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -13 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -12 - --------- switch to master ------- -CREATE INDEX my_idx5 ON mysqltest1.t5(f1); -SELECT MAX(f1) FROM t1; -MAX(f1) -13 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -13 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -13 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -13 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW INDEX FROM mysqltest1.t5; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t5 1 my_idx5 1 f1 A 0 NULL NULL YES BTREE - --------- switch to slave -------- -SHOW INDEX FROM mysqltest1.t5; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t5 1 my_idx5 1 f1 A NULL NULL NULL YES BTREE - --------- switch to master ------- - -######## DROP DATABASE mysqltest2 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 13 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -14 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -13 - --------- switch to master ------- -DROP DATABASE mysqltest2; -SELECT MAX(f1) FROM t1; -MAX(f1) -14 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -14 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -14 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -14 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW DATABASES LIKE "mysqltest2"; -Database (mysqltest2) - --------- switch to slave -------- -SHOW DATABASES LIKE "mysqltest2"; -Database (mysqltest2) - --------- switch to master ------- - -######## CREATE DATABASE mysqltest3 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 14 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -15 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -14 - --------- switch to master ------- -CREATE DATABASE mysqltest3; -SELECT MAX(f1) FROM t1; -MAX(f1) -15 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -15 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -15 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -15 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW DATABASES LIKE "mysqltest3"; -Database (mysqltest3) -mysqltest3 - --------- switch to slave -------- -SHOW DATABASES LIKE "mysqltest3"; -Database (mysqltest3) -mysqltest3 - --------- switch to master ------- - -######## CREATE PROCEDURE p1() READS SQL DATA SELECT "this is p1" ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 15 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -16 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -15 - --------- switch to master ------- -CREATE PROCEDURE p1() READS SQL DATA SELECT "this is p1"; -SELECT MAX(f1) FROM t1; -MAX(f1) -16 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -16 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -16 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -16 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW PROCEDURE STATUS LIKE 'p1'; -Db mysqltest1 -Name p1 -Type PROCEDURE -Definer root@localhost -Modified # -Created # -Security_type DEFINER -Comment - -------- switch to slave ------- -SHOW PROCEDURE STATUS LIKE 'p1'; -Db mysqltest1 -Name p1 -Type PROCEDURE -Definer @ -Modified # -Created # -Security_type DEFINER -Comment - -######## ALTER PROCEDURE p1 COMMENT "I have been altered" ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 16 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -17 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -16 - --------- switch to master ------- -ALTER PROCEDURE p1 COMMENT "I have been altered"; -SELECT MAX(f1) FROM t1; -MAX(f1) -17 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -17 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -17 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -17 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW PROCEDURE STATUS LIKE 'p1'; -Db mysqltest1 -Name p1 -Type PROCEDURE -Definer root@localhost -Modified # -Created # -Security_type DEFINER -Comment I have been altered - -------- switch to slave ------- -SHOW PROCEDURE STATUS LIKE 'p1'; -Db mysqltest1 -Name p1 -Type PROCEDURE -Definer @ -Modified # -Created # -Security_type DEFINER -Comment I have been altered - -######## DROP PROCEDURE p1 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 17 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -18 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -17 - --------- switch to master ------- -DROP PROCEDURE p1; -SELECT MAX(f1) FROM t1; -MAX(f1) -18 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -18 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -18 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -18 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW PROCEDURE STATUS LIKE 'p1'; - -------- switch to slave ------- -SHOW PROCEDURE STATUS LIKE 'p1'; - -######## CREATE OR REPLACE VIEW v1 as select * from t1 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 18 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -19 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -18 - --------- switch to master ------- -CREATE OR REPLACE VIEW v1 as select * from t1; -SELECT MAX(f1) FROM t1; -MAX(f1) -19 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -19 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -19 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -19 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW CREATE VIEW v1; -View Create View -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f1` AS `f1` from `t1` - --------- switch to slave ------- -SHOW CREATE VIEW v1; -View Create View -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f1` AS `f1` from `t1` - -######## ALTER VIEW v1 AS select f1 from t1 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 19 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -20 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -19 - --------- switch to master ------- -ALTER VIEW v1 AS select f1 from t1; -SELECT MAX(f1) FROM t1; -MAX(f1) -20 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -20 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -20 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -20 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW CREATE VIEW v1; -View Create View -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f1` AS `f1` from `t1` - --------- switch to slave ------- -SHOW CREATE VIEW v1; -View Create View -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f1` AS `f1` from `t1` - -######## DROP VIEW IF EXISTS v1 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 20 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -21 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -20 - --------- switch to master ------- -DROP VIEW IF EXISTS v1; -SELECT MAX(f1) FROM t1; -MAX(f1) -21 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -21 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -21 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -21 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW CREATE VIEW v1; -ERROR 42S02: Table 'mysqltest1.v1' doesn't exist - --------- switch to slave ------- -SHOW CREATE VIEW v1; -ERROR 42S02: Table 'mysqltest1.v1' doesn't exist - -######## CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW SET @a:=1 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 21 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -22 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -21 - --------- switch to master ------- -CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW SET @a:=1; -SELECT MAX(f1) FROM t1; -MAX(f1) -22 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -22 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -22 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -22 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW TRIGGERS; -Trigger Event Table Statement Timing Created sql_mode Definer -trg1 INSERT t1 SET @a:=1 BEFORE NULL root@localhost - --------- switch to slave ------- -SHOW TRIGGERS; -Trigger Event Table Statement Timing Created sql_mode Definer -trg1 INSERT t1 SET @a:=1 BEFORE NULL root@localhost - -######## DROP TRIGGER trg1 ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 22 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -23 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -22 - --------- switch to master ------- -DROP TRIGGER trg1; -SELECT MAX(f1) FROM t1; -MAX(f1) -23 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -23 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -23 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -23 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SHOW TRIGGERS; -Trigger Event Table Statement Timing Created sql_mode Definer - --------- switch to slave ------- -SHOW TRIGGERS; -Trigger Event Table Statement Timing Created sql_mode Definer - -######## CREATE USER user1@localhost ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 23 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -24 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -23 - --------- switch to master ------- -CREATE USER user1@localhost; -SELECT MAX(f1) FROM t1; -MAX(f1) -24 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -24 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -24 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -24 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SELECT user FROM mysql.user WHERE user = 'user1'; -user -user1 - --------- switch to slave ------- -SELECT user FROM mysql.user WHERE user = 'user1'; -user -user1 - -######## RENAME USER user1@localhost TO rename1@localhost ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 24 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -25 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -24 - --------- switch to master ------- -RENAME USER user1@localhost TO rename1@localhost; -SELECT MAX(f1) FROM t1; -MAX(f1) -25 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -25 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -25 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -25 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SELECT user FROM mysql.user WHERE user = 'rename1'; -user -rename1 - --------- switch to slave ------- -SELECT user FROM mysql.user WHERE user = 'rename1'; -user -rename1 - -######## DROP USER rename1@localhost ######## - --------- switch to master ------- -INSERT INTO t1 SET f1= 25 + 1; -SELECT MAX(f1) FROM t1; -MAX(f1) -26 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -25 - --------- switch to master ------- -DROP USER rename1@localhost; -SELECT MAX(f1) FROM t1; -MAX(f1) -26 - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -26 - --------- switch to master ------- -ROLLBACK; -SELECT MAX(f1) FROM t1; -MAX(f1) -26 - -TEST-INFO: MASTER: The INSERT is committed (Succeeded) - --------- switch to slave -------- -SELECT MAX(f1) FROM t1; -MAX(f1) -26 - -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) - --------- switch to master ------- -flush logs; - --------- switch to slave -------- -flush logs; - --------- switch to master ------- -SELECT user FROM mysql.user WHERE user = 'rename1'; -user - --------- switch to slave ------- -SELECT user FROM mysql.user WHERE user = 'rename1'; -user -DROP DATABASE IF EXISTS mysqltest1; -DROP DATABASE IF EXISTS mysqltest2; -DROP DATABASE IF EXISTS mysqltest3; diff --git a/mysql-test/r/rpl_stm_err_ignoredtable.result b/mysql-test/r/rpl_stm_err_ignoredtable.result deleted file mode 100644 index 42abb2c3c44..00000000000 --- a/mysql-test/r/rpl_stm_err_ignoredtable.result +++ /dev/null @@ -1,39 +0,0 @@ -stop slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -reset master; -reset slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -start slave; -create table t1 (a int primary key); -insert into t1 values (1),(1); -ERROR 23000: Duplicate entry '1' for key 1 -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 292 # # master-bin.000001 Yes Yes test.t3,test.t1,test.t2 0 0 292 # None 0 No # -show tables like 't1'; -Tables_in_test (t1) -drop table t1; -select get_lock('crash_lock%20C', 10); -get_lock('crash_lock%20C', 10) -1 -create table t2 (a int primary key); -insert into t2 values(1); -create table t3 (id int); -insert into t3 values(connection_id()); - update t2 set a = a + 1 + get_lock('crash_lock%20C', 10); -select (@id := id) - id from t3; -(@id := id) - id -0 -kill @id; -drop table t2,t3; -show binlog events from 102; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query 1 # use `test`; create table t1 (a int primary key) -master-bin.000001 # Query 1 # use `test`; insert into t1 values (1),(1) -master-bin.000001 # Query 1 # use `test`; drop table t1 -master-bin.000001 # Query 1 # use `test`; create table t2 (a int primary key) -master-bin.000001 # Query 1 # use `test`; insert into t2 values(1) -master-bin.000001 # Query 1 # use `test`; create table t3 (id int) -master-bin.000001 # Query 1 # use `test`; insert into t3 values(connection_id()) -master-bin.000001 # Query 1 # use `test`; update t2 set a = a + 1 + get_lock('crash_lock%20C', 10) -master-bin.000001 # Query 1 # use `test`; drop table t2,t3 diff --git a/mysql-test/r/rpl_stm_loaddata_m.result b/mysql-test/r/rpl_stm_loaddata_m.result deleted file mode 100644 index 9c7dba0e711..00000000000 --- a/mysql-test/r/rpl_stm_loaddata_m.result +++ /dev/null @@ -1,20 +0,0 @@ -stop slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -reset master; -reset slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -start slave; -drop database if exists mysqltest; -stop slave; -create database mysqltest; -use mysqltest; -create table t1(a int, b int, unique(b)); -load data infile '../../std_data/rpl_loaddata.dat' into table t1; -show binlog events from 102; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query 1 # drop database if exists mysqltest -master-bin.000001 # Query 1 # create database mysqltest -master-bin.000001 # Query 1 # use `mysqltest`; create table t1(a int, b int, unique(b)) -master-bin.000001 # Begin_load_query 1 # ;file_id=1;block_len=12 -master-bin.000001 # Execute_load_query 1 # use `mysqltest`; load data infile '../../std_data/rpl_loaddata.dat' into table t1 ;file_id=1 -drop database mysqltest; diff --git a/mysql-test/r/rpl_stm_rewrt_db.result b/mysql-test/r/rpl_stm_rewrt_db.result deleted file mode 100644 index 6c72e982e3e..00000000000 --- a/mysql-test/r/rpl_stm_rewrt_db.result +++ /dev/null @@ -1,93 +0,0 @@ -stop slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -reset master; -reset slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -start slave; -drop database if exists mysqltest1; -create database mysqltest1; -use mysqltest1; -create table t1 (a int); -insert into t1 values(9); -select * from mysqltest1.t1; -a -9 -show databases like 'mysqltest1'; -Database (mysqltest1) -mysqltest1 -select * from test.t1; -a -9 -drop table t1; -drop database mysqltest1; -drop database if exists rewrite; -create database rewrite; -use test; -create table t1 (a date, b date, c date not null, d date); -load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ','; -Warnings: -Warning 1265 Data truncated for column 'a' at row 1 -Warning 1265 Data truncated for column 'c' at row 1 -Warning 1265 Data truncated for column 'd' at row 1 -Warning 1265 Data truncated for column 'a' at row 2 -Warning 1265 Data truncated for column 'b' at row 2 -Warning 1265 Data truncated for column 'd' at row 2 -load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES; -select * from rewrite.t1; -a b c d -0000-00-00 NULL 0000-00-00 0000-00-00 -0000-00-00 0000-00-00 0000-00-00 0000-00-00 -2003-03-03 2003-03-03 2003-03-03 NULL -2003-03-03 2003-03-03 2003-03-03 NULL -truncate table t1; -load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d); -Warnings: -Warning 1265 Data truncated for column 'c' at row 1 -Warning 1265 Data truncated for column 'd' at row 1 -Warning 1265 Data truncated for column 'b' at row 2 -Warning 1265 Data truncated for column 'd' at row 2 -select * from rewrite.t1; -a b c d -NULL NULL 0000-00-00 0000-00-00 -NULL 0000-00-00 0000-00-00 0000-00-00 -NULL 2003-03-03 2003-03-03 NULL -drop table t1; -create table t1 (a text, b text); -load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; -Warnings: -Warning 1261 Row 3 doesn't contain data for all columns -select concat('|',a,'|'), concat('|',b,'|') from rewrite.t1; -concat('|',a,'|') concat('|',b,'|') -|Field A| |Field B| -|Field 1| |Field 2' -Field 3,'Field 4| -|Field 5' ,'Field 6| NULL -|Field 6| | 'Field 7'| -drop table t1; -create table t1 (a int, b char(10)); -load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; -Warnings: -Warning 1264 Out of range value for column 'a' at row 3 -Warning 1262 Row 3 was truncated; it contained more data than there were input columns -Warning 1264 Out of range value for column 'a' at row 5 -Warning 1262 Row 5 was truncated; it contained more data than there were input columns -select * from rewrite.t1; -a b -1 row 1 -2 row 2 -0 1234567890 -3 row 3 -0 1234567890 -truncate table t1; -load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; -Warnings: -Warning 1264 Out of range value for column 'a' at row 4 -Warning 1261 Row 4 doesn't contain data for all columns -select * from rewrite.t1; -a b -1 row 1 -2 row 2 -3 row 3 -0 -drop database rewrite; -drop table t1; diff --git a/mysql-test/r/rpl_stm_sp.result b/mysql-test/r/rpl_stm_sp.result index 4fe0f61b550..1acb57f67d5 100644 --- a/mysql-test/r/rpl_stm_sp.result +++ b/mysql-test/r/rpl_stm_sp.result @@ -57,6 +57,9 @@ insert into t1 values (15); grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1; +SELECT 1; +1 +1 create procedure foo4() deterministic begin diff --git a/mysql-test/r/rpl_stm_timezone.result b/mysql-test/r/rpl_stm_timezone.result deleted file mode 100644 index 64d05aa787e..00000000000 --- a/mysql-test/r/rpl_stm_timezone.result +++ /dev/null @@ -1,127 +0,0 @@ -stop slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -reset master; -reset slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -start slave; -set timestamp=100000000; -create table t1 (t timestamp); -create table t2 (t char(32)); -select @@time_zone; -@@time_zone -Japan -select @@time_zone; -@@time_zone -Europe/Moscow -insert into t1 values ('20050101000000'), ('20050611093902'); -set time_zone='UTC'; -insert into t1 values ('20040101000000'), ('20040611093902'); -select * from t1; -t -2004-12-31 21:00:00 -2005-06-11 05:39:02 -2004-01-01 00:00:00 -2004-06-11 09:39:02 -set time_zone='UTC'; -select * from t1; -t -2004-12-31 21:00:00 -2005-06-11 05:39:02 -2004-01-01 00:00:00 -2004-06-11 09:39:02 -delete from t1; -set time_zone='Europe/Moscow'; -insert into t1 values ('20040101000000'), ('20040611093902'); -select * from t1; -t -2004-01-01 00:00:00 -2004-06-11 09:39:02 -set time_zone='Europe/Moscow'; -select * from t1; -t -2004-01-01 00:00:00 -2004-06-11 09:39:02 -/*!40019 SET @@session.max_insert_delayed_threads=0*/; -/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; -ROLLBACK; -use test; -SET TIMESTAMP=100000000; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; -SET @@session.sql_mode=0; -SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8; -create table t1 (t timestamp); -SET TIMESTAMP=100000000; -create table t2 (t char(32)); -SET TIMESTAMP=100000000; -SET @@session.time_zone='Europe/Moscow'; -insert into t1 values ('20050101000000'), ('20050611093902'); -SET TIMESTAMP=100000000; -SET @@session.time_zone='UTC'; -insert into t1 values ('20040101000000'), ('20040611093902'); -SET TIMESTAMP=100000000; -delete from t1; -SET TIMESTAMP=100000000; -SET @@session.time_zone='Europe/Moscow'; -insert into t1 values ('20040101000000'), ('20040611093902'); -# End of log file -ROLLBACK /* added by mysqlbinlog */; -/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; -delete from t1; -set time_zone='UTC'; -load data infile '../../std_data/rpl_timezone.dat' into table t1; -select * from t1; -t -2004-01-01 00:00:00 -2004-06-11 09:39:02 -set time_zone='UTC'; -select * from t1; -t -2004-01-01 00:00:00 -2004-06-11 09:39:02 -set time_zone='Europe/Moscow'; -set time_zone='Europe/Moscow'; -delete from t1; -insert into t1 values ('20040101000000'), ('20040611093902'); -set time_zone='MET'; -insert into t2 (select t from t1); -select * from t1; -t -2003-12-31 22:00:00 -2004-06-11 07:39:02 -select * from t2; -t -2003-12-31 22:00:00 -2004-06-11 07:39:02 -delete from t2; -set timestamp=1000072000; -insert into t2 values (current_timestamp), (current_date), (current_time); -select * from t2; -t -2001-09-09 23:46:40 -2001-09-09 -23:46:40 -delete from t2; -insert into t2 values (from_unixtime(1000000000)), -(unix_timestamp('2001-09-09 03:46:40')); -select * from t2; -t -2001-09-09 03:46:40 -1000000000 -select * from t2; -t -2001-09-09 03:46:40 -1000000000 -set global time_zone='MET'; -delete from t2; -set time_zone='UTC'; -insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone)); -insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan')); -select * from t2; -t -2003-12-31 23:00:00 -2005-01-01 08:00:00 -select * from t2; -t -2003-12-31 23:00:00 -2005-01-01 08:00:00 -drop table t1, t2; diff --git a/mysql-test/r/rpl_stm_user_variables.result b/mysql-test/r/rpl_stm_user_variables.result deleted file mode 100644 index 3e2efcbe9da..00000000000 --- a/mysql-test/r/rpl_stm_user_variables.result +++ /dev/null @@ -1,82 +0,0 @@ -stop slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -reset master; -reset slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -start slave; -reset master; -create table t1(n char(30)); -set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1; -set @s1:='This is a test', @r1:=12.5, @r2:=-12.5; -set @n1:=null; -set @s2:='', @s3:='abc\'def', @s4:= 'abc\\def', @s5:= 'abc''def'; -insert into t1 values (@i1), (@i2), (@i3), (@i4); -insert into t1 values (@r1), (@r2); -insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5); -insert into t1 values (@n1); -insert into t1 values (@n2); -insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1); -insert into t1 values (@a+(@b:=@a+1)); -set @q:='abc'; -insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2')); -set @a:=5; -insert into t1 values (@a),(@a); -select * from t1 where n = ''; -n -insert into t1 values (@a),(@a),(@a*5); -select * from t1; -n -12345678901234 --12345678901234 -0 --1 -12.5 --12.5 -This is a test - -abc'def -abc\def -abc'def -NULL -NULL -0 -1 -2 -5 -abc -abcn1 -abcn1n2 -5 -5 -NULL -NULL -NULL -select * from t1; -n -12345678901234 --12345678901234 -0 --1 -12.5 --12.5 -This is a test - -abc'def -abc\def -abc'def -NULL -NULL -0 -1 -2 -5 -abc -abcn1 -abcn1n2 -5 -5 -NULL -NULL -NULL -drop table t1; -stop slave; diff --git a/mysql-test/r/rpl_stm_view.result b/mysql-test/r/rpl_stm_view.result deleted file mode 100644 index cf4c161b296..00000000000 --- a/mysql-test/r/rpl_stm_view.result +++ /dev/null @@ -1,56 +0,0 @@ -stop slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -reset master; -reset slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -start slave; -drop table if exists t1,v1; -drop view if exists t1,v1; -reset master; -create table t1 (a int); -insert into t1 values (1); -create view v1 as select a from t1; -insert into v1 values (2); -select * from v1 order by a; -a -1 -2 -select * from v1 order by a; -a -1 -2 -update v1 set a=3 where a=1; -select * from v1 order by a; -a -2 -3 -select * from v1 order by a; -a -2 -3 -delete from v1 where a=2; -select * from v1 order by a; -a -3 -select * from v1 order by a; -a -3 -alter view v1 as select a as b from t1; -select * from v1 order by 1; -b -3 -drop view v1; -select * from v1 order by a; -ERROR 42S02: Table 'test.v1' doesn't exist -drop table t1; -show binlog events limit 1,100; -Log_name Pos Event_type Server_id End_log_pos Info -slave-bin.000001 # Query 1 # use `test`; create table t1 (a int) -slave-bin.000001 # Query 1 # use `test`; insert into t1 values (1) -slave-bin.000001 # Query 1 # use `test`; CREATE ALGORITHM=UNDEFINED DEFINER=root@localhost SQL SECURITY DEFINER VIEW v1 AS select a from t1 -slave-bin.000001 # Query 1 # use `test`; insert into v1 values (2) -slave-bin.000001 # Query 1 # use `test`; update v1 set a=3 where a=1 -slave-bin.000001 # Query 1 # use `test`; delete from v1 where a=2 -slave-bin.000001 # Query 1 # use `test`; ALTER ALGORITHM=UNDEFINED DEFINER=root@localhost SQL SECURITY DEFINER VIEW v1 AS select a as b from t1 -slave-bin.000001 # Query 1 # use `test`; drop view v1 -slave-bin.000001 # Query 1 # use `test`; drop table t1 diff --git a/mysql-test/r/rpl_row_timezone.result b/mysql-test/r/rpl_timezone.result similarity index 76% rename from mysql-test/r/rpl_row_timezone.result rename to mysql-test/r/rpl_timezone.result index 26c10648ffb..9c45997cbf6 100644 --- a/mysql-test/r/rpl_row_timezone.result +++ b/mysql-test/r/rpl_timezone.result @@ -9,7 +9,7 @@ create table t1 (t timestamp, n int not null auto_increment, PRIMARY KEY(n)); create table t2 (t char(32), n int not null auto_increment, PRIMARY KEY(n)); select @@time_zone; @@time_zone -Europe/Moscow +Japan select @@time_zone; @@time_zone Europe/Moscow @@ -23,10 +23,10 @@ t n 2004-06-11 09:39:02 4 select * from t1; t n -2005-01-01 00:00:00 1 -2005-06-11 09:39:02 2 -2004-01-01 00:00:00 3 -2004-06-11 09:39:02 4 +2005-01-01 06:00:00 1 +2005-06-11 14:39:02 2 +2004-01-01 06:00:00 3 +2004-06-11 14:39:02 4 delete from t1; set time_zone='Europe/Moscow'; insert into t1 values ('20040101000000',NULL), ('20040611093902',NULL); @@ -39,22 +39,6 @@ select * from t1; t n 2004-01-01 00:00:00 5 2004-06-11 09:39:02 6 -/*!40019 SET @@session.max_insert_delayed_threads=0*/; -/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; -ROLLBACK; -use test; -SET TIMESTAMP=100000000; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; -SET @@session.sql_mode=0; -SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8; -create table t1 (t timestamp, n int not null auto_increment, PRIMARY KEY(n)); -SET TIMESTAMP=100000000; -create table t2 (t char(32), n int not null auto_increment, PRIMARY KEY(n)); -SET TIMESTAMP=100000000; -delete from t1; -# End of log file -ROLLBACK /* added by mysqlbinlog */; -/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; delete from t1; set time_zone='UTC'; load data infile '../../std_data/rpl_timezone2.dat' into table t1; diff --git a/mysql-test/r/rpl_row_user_variables.result b/mysql-test/r/rpl_user_variables.result similarity index 100% rename from mysql-test/r/rpl_row_user_variables.result rename to mysql-test/r/rpl_user_variables.result diff --git a/mysql-test/r/rpl_row_view.result b/mysql-test/r/rpl_view.result similarity index 98% rename from mysql-test/r/rpl_row_view.result rename to mysql-test/r/rpl_view.result index ce807a361ba..f038f4d00cb 100644 --- a/mysql-test/r/rpl_row_view.result +++ b/mysql-test/r/rpl_view.result @@ -6,6 +6,7 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; drop table if exists t1,v1; drop view if exists t1,v1; +reset master; create table t1 (a int); insert into t1 values (1); create view v1 as select a from t1; diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index e0048515fed..38dff6f8ca5 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -767,8 +767,7 @@ deallocate prepare stmt1; drop procedure p1; drop table t1, t2, t3; create table t1 (a int); -drop procedure if exists p2; -CREATE PROCEDURE `p2`() +CREATE PROCEDURE `p1`() begin insert into t1 values (1); end// @@ -777,8 +776,8 @@ begin declare done int default 0; set done= not done; end// -CALL p2(); -drop procedure p2; +CALL p1(); +drop procedure p1; drop table t1; create trigger t1_bi before insert on test.t1 for each row set @a:=0; ERROR 3D000: No database selected diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 4f6cfe4a310..029daa14256 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2423,6 +2423,9 @@ drop view v1; drop table t1; create table t1(f1 int, f2 int); insert into t1 values (null, 10), (null,2); +select f1, sum(f2) from t1 group by f1; +f1 sum(f2) +NULL 12 create view v1 as select * from t1; select f1, sum(f2) from v1 group by f1; f1 sum(f2) diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test index 1bb8fa4d55d..60e0129e58a 100644 --- a/mysql-test/t/bdb.test +++ b/mysql-test/t/bdb.test @@ -1036,4 +1036,13 @@ create table t1 (a varchar(255) character set utf8, e varchar(255) character set utf8, key (a,b,c,d,e)) engine=bdb; +# +# Bug #14212: Server crash after COMMIT + ALTER TABLE +# +set autocommit=0; +create table t1 (a int) engine=bdb; +commit; +alter table t1 add primary key(a); +drop table t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index b61dd6add84..2318b739c35 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -565,6 +565,22 @@ create table t1 ( show create table t1; drop table t1; +--warning 1364 +create table t1 ( + a varchar(12) charset utf8 collate utf8_bin not null, + b int not null, primary key (a) +) select a, 1 as c from t2 ; +show create table t1; +drop table t1; + +--warning 1364 +create table t1 ( + a varchar(12) charset utf8 collate utf8_bin not null, + b int null, primary key (a) +) select a, 1 as c from t2 ; +show create table t1; +drop table t1; + --warning 1364 create table t1 ( a varchar(12) charset utf8 collate utf8_bin not null, diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index ef5bdefa1ed..f191c0ab3ef 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,17 +11,16 @@ ############################################################################## sp-goto : GOTO is currently is disabled - will be fixed in the future -kill : Unstable test case, bug#9712 rpl_bit_npk : Bug #13418 ndb_cache2 : Bug #15004 ndb_cache_multi2: Bug #15004 func_group : Bug #15448 func_math : Bug #15448 group_min_max : Bug #15448 -#mysqlslap : Bug #15483 innodb_concurrent : Results are not deterministic, Elliot will fix (BUG#3300) subselect : Bug#15706 type_time : Bug#15805 #rpl000002 : Bug#15920 Temporary tables are not binlogged in SBR -ps_7ndb : Bug#15923 Core dump in RBR mode when executing test suite -sp_trans : Bug#15924 Code dump in RBR mode when executing test suite +#ps_7ndb : Bug#15923 Core dump in RBR mode when executing test suite +rpl_ddl : Bug#15963 SBR does not show "Definer" correctly +mysqlslap : Bug#16167 diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test index f3e14c3cd2b..3fb09df5f2f 100644 --- a/mysql-test/t/handler.test +++ b/mysql-test/t/handler.test @@ -3,7 +3,7 @@ # --disable_warnings -drop table if exists t1; +drop table if exists t1,t3,t4,t5; --enable_warnings create table t1 (a int, b char(10), key a(a), key b(a,b)); diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index d61088a3a28..2f91f27ac79 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -769,6 +769,27 @@ from information_schema.columns where table_name='t1'; drop table t1; # +# Bug#15533 crash, information_schema, function, view +# +CREATE TABLE t1 (f1 BIGINT, f2 VARCHAR(20), f3 BIGINT); +INSERT INTO t1 SET f1 = 1, f2 = 'Schoenenbourg', f3 = 1; + +CREATE FUNCTION func2() RETURNS BIGINT RETURN 1; + +delimiter //; +CREATE FUNCTION func1() RETURNS BIGINT +BEGIN + RETURN ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.VIEWS); +END// +delimiter ;// + +CREATE VIEW v1 AS SELECT 1 FROM t1 + WHERE f3 = (SELECT func2 ()); +SELECT func1(); +DROP TABLE t1; +DROP VIEW v1; +DROP FUNCTION func1; +DROP FUNCTION func2; # Show engines # diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 7f3a9932d31..c50c35825fc 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -25,11 +25,18 @@ select ((@id := kill_id) - kill_id) from t1; kill @id; connection con1; ---sleep 1 +--sleep 2 -# this statement should fail ---error 2006,2013 +--disable_query_log +--disable_result_log +# One of the following statements should fail +--error 0,2006,2013 select 1; +--error 0,2006,2013 +select 1; +--enable_query_log +--enable_result_log + --enable_reconnect # this should work, and we should have a new connection_id() select ((@id := kill_id) - kill_id) from t1; diff --git a/mysql-test/t/mysqlshow.test b/mysql-test/t/mysqlshow.test index 1e2e97a4e07..78c4ae2b531 100644 --- a/mysql-test/t/mysqlshow.test +++ b/mysql-test/t/mysqlshow.test @@ -2,7 +2,7 @@ -- source include/not_embedded.inc --disable_warnings -DROP TABLE IF EXISTS t1,t2; +DROP TABLE IF EXISTS t1,t2,test1,test2; --enable_warnings # diff --git a/mysql-test/t/rpl_row_ddl.test b/mysql-test/t/rpl_ddl.test similarity index 97% rename from mysql-test/t/rpl_row_ddl.test rename to mysql-test/t/rpl_ddl.test index 2433d6a83a7..d08406334d1 100644 --- a/mysql-test/t/rpl_row_ddl.test +++ b/mysql-test/t/rpl_ddl.test @@ -29,7 +29,6 @@ # --source include/have_innodb.inc ---source include/have_binlog_format_row.inc --source include/master-slave.inc let $engine_type= "InnoDB"; -- source extra/rpl_tests/rpl_ddl.test diff --git a/mysql-test/t/rpl_drop_db.test b/mysql-test/t/rpl_drop_db.test index 98afc6e3d02..548009b758e 100644 --- a/mysql-test/t/rpl_drop_db.test +++ b/mysql-test/t/rpl_drop_db.test @@ -46,12 +46,13 @@ show tables; use test; select * from t1; +system rm var/master-data/mysqltest1/f1.txt; connection master; -drop table t1; +DROP DATABASE mysqltest1; sync_slave_with_master; #cleanup connection slave; stop slave; -system rm -rf var/master-data/mysqltest1; +#system rm -rf var/master-data/mysqltest1; diff --git a/mysql-test/t/rpl_stm_err_ignoredtable-slave.opt b/mysql-test/t/rpl_err_ignoredtable-slave.opt similarity index 100% rename from mysql-test/t/rpl_stm_err_ignoredtable-slave.opt rename to mysql-test/t/rpl_err_ignoredtable-slave.opt diff --git a/mysql-test/extra/rpl_tests/rpl_err_ignoredtable.test b/mysql-test/t/rpl_err_ignoredtable.test similarity index 77% rename from mysql-test/extra/rpl_tests/rpl_err_ignoredtable.test rename to mysql-test/t/rpl_err_ignoredtable.test index e439dbdc388..81aa76225be 100644 --- a/mysql-test/extra/rpl_tests/rpl_err_ignoredtable.test +++ b/mysql-test/t/rpl_err_ignoredtable.test @@ -7,20 +7,19 @@ connection master; create table t1 (a int primary key); +create table t4 (a int primary key); # generate an error that goes to the binlog --error 1062 insert into t1 values (1),(1); +insert into t4 values (1),(2); save_master_pos; connection slave; # as the t1 table is ignored on the slave, the slave should be able to sync sync_with_master; -# The port number is different when doing the release build with -# Do-compile, hence we have to replace the port number here accordingly ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # -show slave status; # check that the table has been ignored, because otherwise the test is nonsense show tables like 't1'; +show tables like 't4'; +SELECT * FROM test.t4; connection master; drop table t1; save_master_pos; @@ -46,17 +45,20 @@ real_sleep 2; select (@id := id) - id from t3; kill @id; drop table t2,t3; +insert into t4 values (3),(4); connection master; --error 0,1053,2013 reap; connection master1; ---replace_column 2 # 5 # -show binlog events from 102; save_master_pos; connection slave; -# SQL slave thread should not have stopped (because table of the killed -# query is in the ignore list). sync_with_master; +SELECT * FROM test.t4; +connection master1; +DROP TABLE test.t4; +save_master_pos; +connection slave; +sync_with_master; # End of 4.1 tests # Adding comment for force manual merge 5.0 -> wl1012. delete me if needed diff --git a/mysql-test/t/rpl_stm_loaddata_m-master.opt b/mysql-test/t/rpl_loaddata_m-master.opt similarity index 100% rename from mysql-test/t/rpl_stm_loaddata_m-master.opt rename to mysql-test/t/rpl_loaddata_m-master.opt diff --git a/mysql-test/t/rpl_loaddata_m.test b/mysql-test/t/rpl_loaddata_m.test new file mode 100644 index 00000000000..01ef89d4efc --- /dev/null +++ b/mysql-test/t/rpl_loaddata_m.test @@ -0,0 +1,49 @@ +# See if the master logs LOAD DATA INFILE correctly when binlog_*_db rules +# exist. +# This is for BUG#1100 (LOAD DATA INFILE was half-logged). +###################################################### +# Change Author: JBM +# Change Date: 2005-12-22 +# Change: Test rewritten to remove show binlog events +# and to test the option better + Cleanup +###################################################### +-- source include/master-slave.inc + +--disable_warnings +drop database if exists mysqltest; +--enable_warnings + +connection master; +# 'test' database should be ignored by the slave +USE test; +CREATE TABLE t1(a INT, b INT, UNIQUE(b)); +LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE test.t1; +SELECT COUNT(*) FROM test.t1; + +# 'mysqltest' database should NOT be ignored by the slave +CREATE DATABASE mysqltest; +USE mysqltest; +CREATE TABLE t1(a INT, b INT, UNIQUE(b)); +LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE mysqltest.t1; +SELECT COUNT(*) FROM mysqltest.t1; + +# Now lets check the slave to see what we have :-) +save_master_pos; +connection slave; +sync_with_master; + +SHOW DATABASES; + +USE test; +SHOW TABLES; + +USE mysqltest; +SHOW TABLES; +SELECT COUNT(*) FROM mysqltest.t1; + +#show binlog events; +connection master; +DROP DATABASE mysqltest; +DROP TABLE test.t1; + +# End of test diff --git a/mysql-test/t/rpl_multi_engine.test b/mysql-test/t/rpl_multi_engine.test index b0879757468..3f7b7b11c0d 100644 --- a/mysql-test/t/rpl_multi_engine.test +++ b/mysql-test/t/rpl_multi_engine.test @@ -24,6 +24,7 @@ use mysqltest1; connection master; alter table t1 engine=myisam; show create table t1; +sync_slave_with_master; connection slave; alter table t1 engine=myisam; @@ -48,6 +49,7 @@ show create table t1; connection master; alter table t1 engine=memory; show create table t1; +sync_slave_with_master; connection slave; alter table t1 engine=myisam; @@ -72,6 +74,7 @@ show create table t1; connection master; alter table t1 engine=innodb; show create table t1; +sync_slave_with_master; connection slave; alter table t1 engine=myisam; @@ -94,6 +97,8 @@ show create table t1; # cleanup connection master; DROP TABLE t1; +# Need to drop mysqltest1 as well so other test will pass. +DROP DATABASE mysqltest1; sync_slave_with_master; # End of 5.1 test case diff --git a/mysql-test/t/rpl_row_rewrt_db-slave.opt b/mysql-test/t/rpl_rewrt_db-slave.opt similarity index 100% rename from mysql-test/t/rpl_row_rewrt_db-slave.opt rename to mysql-test/t/rpl_rewrt_db-slave.opt diff --git a/mysql-test/t/rpl_stm_rewrt_db.test b/mysql-test/t/rpl_rewrt_db.test similarity index 100% rename from mysql-test/t/rpl_stm_rewrt_db.test rename to mysql-test/t/rpl_rewrt_db.test diff --git a/mysql-test/t/rpl_row_basic_11bugs-master.opt b/mysql-test/t/rpl_row_basic_11bugs-master.opt new file mode 100644 index 00000000000..d5ae999b180 --- /dev/null +++ b/mysql-test/t/rpl_row_basic_11bugs-master.opt @@ -0,0 +1 @@ +--binlog_ignore_db=test_ignore; diff --git a/mysql-test/t/rpl_row_basic_11bugs.test b/mysql-test/t/rpl_row_basic_11bugs.test new file mode 100644 index 00000000000..76ff5a581c9 --- /dev/null +++ b/mysql-test/t/rpl_row_basic_11bugs.test @@ -0,0 +1,31 @@ +--source include/have_row_based.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +# Bug#15942 (RBR ignores --binlog_ignore_db and tries to map to table +# on slave for writes) + +CREATE DATABASE test_ignore; # --binlog_ignore_db=mysqltest_ignore + +--echo **** On Master **** +SHOW DATABASES; +USE test; +CREATE TABLE t1 (a INT, b INT); +SHOW TABLES; +INSERT INTO t1 VALUES (1,1), (2,2); +USE test_ignore; +CREATE TABLE t2 (a INT, b INT); +SHOW TABLES; +INSERT INTO t2 VALUES (3,3), (4,4); +SHOW BINLOG EVENTS; +sync_slave_with_master; +--echo **** On Slave **** +SHOW DATABASES; +USE test; +SHOW TABLES; +--error 1049 +USE test_ignore; + +connection master; +DROP DATABASE test_ignore; +sync_slave_with_master; diff --git a/mysql-test/t/rpl_row_blob_innodb.test b/mysql-test/t/rpl_row_blob_innodb.test new file mode 100644 index 00000000000..b6832010e22 --- /dev/null +++ b/mysql-test/t/rpl_row_blob_innodb.test @@ -0,0 +1,7 @@ +################################# +# Wrapper for rpl_row_blob.test# +################################# +-- source include/have_innodb.inc +let $engine_type=INNODB; +-- source extra/rpl_tests/rpl_row_blob.test + diff --git a/mysql-test/t/rpl_row_blob_myisam.test b/mysql-test/t/rpl_row_blob_myisam.test new file mode 100644 index 00000000000..2914aa7b348 --- /dev/null +++ b/mysql-test/t/rpl_row_blob_myisam.test @@ -0,0 +1,6 @@ +################################# +# Wrapper for rpl_row_blob.test# +################################# +let $engine_type=myisam; +-- source extra/rpl_tests/rpl_row_blob.test + diff --git a/mysql-test/t/rpl_row_log.test b/mysql-test/t/rpl_row_log.test index 290a08ff75a..29abf5bb93e 100644 --- a/mysql-test/t/rpl_row_log.test +++ b/mysql-test/t/rpl_row_log.test @@ -1,4 +1,4 @@ -# Requires statement logging +# Requires row base logging -- source include/have_binlog_format_row.inc -- source extra/rpl_tests/rpl_log.test diff --git a/mysql-test/t/rpl_row_rewrt_db.test b/mysql-test/t/rpl_row_rewrt_db.test deleted file mode 100644 index 8781b361d87..00000000000 --- a/mysql-test/t/rpl_row_rewrt_db.test +++ /dev/null @@ -1,83 +0,0 @@ -# TBF - difference in row level logging --- source include/have_binlog_format_row.inc --- source include/master-slave.inc - ---disable_warnings -drop database if exists mysqltest1; ---enable_warnings -create database mysqltest1; - -use mysqltest1; -create table t1 (a int); -insert into t1 values(9); -select * from mysqltest1.t1; -sync_slave_with_master; -show databases like 'mysqltest1'; # should be empty -select * from test.t1; -# cleanup -connection master; -drop table t1; -drop database mysqltest1; -sync_slave_with_master; - -# -# BUG#6353: -# Option --replicate-rewrite-db should work together with LOAD DATA INFILE -# - -connection slave; ---disable_warnings -drop database if exists rewrite; ---enable_warnings -create database rewrite; - -connection master; -use test; -create table t1 (a date, b date, c date not null, d date); -load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ','; -load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES; -sync_slave_with_master; - -connection slave; -select * from rewrite.t1; - -connection master; -truncate table t1; -load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d); -sync_slave_with_master; - -connection slave; -select * from rewrite.t1; - -connection master; -drop table t1; -create table t1 (a text, b text); -load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; -sync_slave_with_master; - -connection slave; -select concat('|',a,'|'), concat('|',b,'|') from rewrite.t1; - -connection master; -drop table t1; -create table t1 (a int, b char(10)); -load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; -sync_slave_with_master; - -connection slave; -select * from rewrite.t1; - -connection master; -truncate table t1; -load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; -sync_slave_with_master; - -connection slave; -# The empty line last comes from the end line field in the file -select * from rewrite.t1; - -drop database rewrite; - -connection master; -drop table t1; - diff --git a/mysql-test/t/rpl_row_sp000.test b/mysql-test/t/rpl_row_sp000.test index e591cb054fc..4d638cfcc1c 100644 --- a/mysql-test/t/rpl_row_sp000.test +++ b/mysql-test/t/rpl_row_sp000.test @@ -82,6 +82,14 @@ grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1; +# ToDo: BUG#14931: There is a race between the last grant binlogging, and +# the binlogging in the new connection made below, causing sporadic test +# failures due to switched statement order in binlog. To fix this we do +# SELECT 1 in the first connection before starting the second, ensuring +# that binlogging is done in the expected order. +# Please remove this SELECT 1 when BUG#14931 is fixed. +SELECT 1; + connect (con1,127.0.0.1,zedjzlcsjhd,,mysqltest1,$MASTER_MYPORT,); connection con1; diff --git a/mysql-test/t/rpl_row_timezone-slave.opt b/mysql-test/t/rpl_row_timezone-slave.opt deleted file mode 100644 index c383fd9f17d..00000000000 --- a/mysql-test/t/rpl_row_timezone-slave.opt +++ /dev/null @@ -1,2 +0,0 @@ ---default-time-zone=Europe/Moscow - diff --git a/mysql-test/t/rpl_row_user_variables.test b/mysql-test/t/rpl_row_user_variables.test deleted file mode 100644 index 2ebb668b1a8..00000000000 --- a/mysql-test/t/rpl_row_user_variables.test +++ /dev/null @@ -1,4 +0,0 @@ -# row-based and statement binlog difference in result files --- source include/have_binlog_format_row.inc --- source extra/rpl_tests/rpl_user_variables.test - diff --git a/mysql-test/t/rpl_row_view.test b/mysql-test/t/rpl_row_view.test deleted file mode 100644 index 6d460d58df6..00000000000 --- a/mysql-test/t/rpl_row_view.test +++ /dev/null @@ -1,47 +0,0 @@ -# NYI - row-based cannot use CREATE ... SELECT ---source include/have_binlog_format_row.inc - -source include/master-slave.inc; ---disable_warnings -drop table if exists t1,v1; -drop view if exists t1,v1; -sync_slave_with_master; ---enable_warnings - -# -# Check that createion drop of view is replicated, also check replication of -# updating of view -# -connection master; -create table t1 (a int); -insert into t1 values (1); -create view v1 as select a from t1; -insert into v1 values (2); -select * from v1 order by a; -sync_slave_with_master; -# view already have to be on slave -select * from v1 order by a; -connection master; -update v1 set a=3 where a=1; -select * from v1 order by a; -sync_slave_with_master; -select * from v1 order by a; -connection master; -delete from v1 where a=2; -select * from v1 order by a; -sync_slave_with_master; -select * from v1 order by a; -connection master; -# 'alter view' internally maped to creation, but still check that it works -alter view v1 as select a as b from t1; -sync_slave_with_master; -select * from v1 order by 1; -connection master; -drop view v1; -sync_slave_with_master; -#error, because view have to be removed from slave --- error 1146 -select * from v1 order by a; -connection master; -drop table t1; -sync_slave_with_master; diff --git a/mysql-test/t/rpl_stm_ddl.test b/mysql-test/t/rpl_stm_ddl.test deleted file mode 100644 index 54548114f86..00000000000 --- a/mysql-test/t/rpl_stm_ddl.test +++ /dev/null @@ -1,35 +0,0 @@ -######################## rpl_ddl.test ######################## -# # -# DDL statements (sometimes with implicit COMMIT) executed # -# by the master and it's propagation into the slave # -# # -############################################################## - -# -# NOTE, PLEASE BE CAREFUL, WHEN MODIFYING THE TESTS !! -# -# 1. !All! objects to be dropped, renamed, altered ... must be created -# in AUTOCOMMIT= 1 mode before AUTOCOMMIT is set to 0 and the test -# sequences start. -# -# 2. Never use a test object, which was direct or indirect affected by a -# preceeding test sequence again. -# Except table d1.t1 where ONLY DML is allowed. -# -# If one preceeding test sequence hits a (sometimes not good visible, -# because the sql error code of the statement might be 0) bug -# and these rules are ignored, a following test sequence might earn ugly -# effects like failing 'sync_slave_with_master', crashes of the slave or -# abort of the test case etc.. -# -# 3. The assignment of the DDL command to be tested to $my_stmt can -# be a bit difficult. "'" must be avoided, because the test -# routine "include/rpl_stmt_seq.inc" performs a -# eval SELECT CONCAT('######## ','$my_stmt',' ########') as ""; -# - ---source include/have_innodb.inc ---source include/have_binlog_format_statement.inc ---source include/master-slave.inc -let $engine_type= "InnoDB"; --- source extra/rpl_tests/rpl_ddl.test diff --git a/mysql-test/t/rpl_stm_err_ignoredtable.test b/mysql-test/t/rpl_stm_err_ignoredtable.test deleted file mode 100644 index a426be27b59..00000000000 --- a/mysql-test/t/rpl_stm_err_ignoredtable.test +++ /dev/null @@ -1,8 +0,0 @@ -# Test for -# Bug #797: If a query is ignored on slave (replicate-ignore-table) the slave -# still checks that it has the same error as on the master. - -# Requires statement logging --- source include/have_binlog_format_statement.inc --- source extra/rpl_tests/rpl_err_ignoredtable.test - diff --git a/mysql-test/t/rpl_stm_loaddata_m.test b/mysql-test/t/rpl_stm_loaddata_m.test deleted file mode 100644 index ac52a8dfb9e..00000000000 --- a/mysql-test/t/rpl_stm_loaddata_m.test +++ /dev/null @@ -1,10 +0,0 @@ -# See if the master logs LOAD DATA INFILE correctly when binlog_*_db rules -# exist. -# This is for BUG#1100 (LOAD DATA INFILE was half-logged). - -# Requires statement logging --- source include/have_binlog_format_statement.inc --- source extra/rpl_tests/rpl_loaddata_m.test - -# End of 4.1 tests -# Adding comment for force manual merge 5.0 -> wl1012: Delete me diff --git a/mysql-test/t/rpl_stm_rewrt_db-slave.opt b/mysql-test/t/rpl_stm_rewrt_db-slave.opt deleted file mode 100644 index a462ad19ba0..00000000000 --- a/mysql-test/t/rpl_stm_rewrt_db-slave.opt +++ /dev/null @@ -1 +0,0 @@ -"--replicate-rewrite-db=test->rewrite" "--replicate-rewrite-db=mysqltest1->test" diff --git a/mysql-test/t/rpl_stm_sp.test b/mysql-test/t/rpl_stm_sp.test index 95c4543c952..62ea87e5352 100644 --- a/mysql-test/t/rpl_stm_sp.test +++ b/mysql-test/t/rpl_stm_sp.test @@ -90,6 +90,14 @@ grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1; +# ToDo: BUG#14931: There is a race between the last grant binlogging, and +# the binlogging in the new connection made below, causing sporadic test +# failures due to switched statement order in binlog. To fix this we do +# SELECT 1 in the first connection before starting the second, ensuring +# that binlogging is done in the expected order. +# Please remove this SELECT 1 when BUG#14931 is fixed. +SELECT 1; + connect (con1,127.0.0.1,zedjzlcsjhd,,mysqltest1,$MASTER_MYPORT,); connection con1; diff --git a/mysql-test/t/rpl_stm_timezone-master.opt b/mysql-test/t/rpl_stm_timezone-master.opt deleted file mode 100644 index 8e43bfbbb7e..00000000000 --- a/mysql-test/t/rpl_stm_timezone-master.opt +++ /dev/null @@ -1 +0,0 @@ ---default-time-zone=Europe/Moscow diff --git a/mysql-test/t/rpl_stm_timezone.test b/mysql-test/t/rpl_stm_timezone.test deleted file mode 100644 index 0cd6dbf5d89..00000000000 --- a/mysql-test/t/rpl_stm_timezone.test +++ /dev/null @@ -1,129 +0,0 @@ -# TBF - difference in row level logging --- source include/have_binlog_format_statement.inc - -# Test of replication of time zones. - -# There is currently some bug possibly in prepared statements (this -# test fails with --ps-protocol): sys_var_thd_time_zone::value_ptr() -# is called only at prepare time, not at execution time. So, -# thd->time_zone_used is not equal to 1 (it is back to 0, because of -# reset_thd_for_next_command called at execution time), so the -# timezone used in CONVERT_TZ is not binlogged. To debug (by Guilhem -# and possibly Konstantin). - ---disable_ps_protocol - -source include/master-slave.inc; - -# Some preparations -let $VERSION=`select version()`; -set timestamp=100000000; # for fixed output of mysqlbinlog -create table t1 (t timestamp); -create table t2 (t char(32)); - -connection slave; -select @@time_zone; - -# -# Let us check how well replication works when we are saving datetime -# value in TIMESTAMP field. -# -connection master; -select @@time_zone; -insert into t1 values ('20050101000000'), ('20050611093902'); -set time_zone='UTC'; -insert into t1 values ('20040101000000'), ('20040611093902'); -select * from t1; -sync_slave_with_master; -set time_zone='UTC'; -select * from t1; - -# Let us check also that setting of time_zone back to default also works -# well -connection master; -delete from t1; -set time_zone='Europe/Moscow'; -insert into t1 values ('20040101000000'), ('20040611093902'); -select * from t1; -sync_slave_with_master; -set time_zone='Europe/Moscow'; -select * from t1; -connection master; ---replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001 - -# Let us check with LOAD DATA INFILE -# (we do it after mysqlbinlog because the temp files names are not constant) -connection master; -delete from t1; -set time_zone='UTC'; -load data infile '../../std_data/rpl_timezone.dat' into table t1; -select * from t1; -sync_slave_with_master; -set time_zone='UTC'; -select * from t1; -set time_zone='Europe/Moscow'; - -# Put back values of before the LOAD -connection master; -set time_zone='Europe/Moscow'; -delete from t1; -insert into t1 values ('20040101000000'), ('20040611093902'); - -# -# Now let us check how well we replicate statments reading TIMESTAMP fields -# (We should see the same data on master and on slave but it should differ -# from originally inserted) -# -set time_zone='MET'; -insert into t2 (select t from t1); -select * from t1; -sync_slave_with_master; -select * from t2; - -# -# Now let us check how well we replicate various CURRENT_* functions -# -connection master; -delete from t2; -set timestamp=1000072000; -insert into t2 values (current_timestamp), (current_date), (current_time); -sync_slave_with_master; -select * from t2; - -# -# At last let us check replication of FROM_UNIXTIME/UNIX_TIMESTAMP functions. -# -connection master; -delete from t2; -insert into t2 values (from_unixtime(1000000000)), - (unix_timestamp('2001-09-09 03:46:40')); -select * from t2; -sync_slave_with_master; -# We should get same result on slave as on master -select * from t2; - -# -# Let us check that we are allowing to set global time_zone with -# replication -# -connection master; -set global time_zone='MET'; - -# -# Let us see if CONVERT_TZ(@@time_zone) replicates -# -delete from t2; -set time_zone='UTC'; -insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone)); -insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan')); -select * from t2; -sync_slave_with_master; -select * from t2; - -# Clean up -connection master; -drop table t1, t2; -sync_slave_with_master; - -# End of 4.1 tests diff --git a/mysql-test/t/rpl_stm_user_variables.test b/mysql-test/t/rpl_stm_user_variables.test deleted file mode 100644 index af4e46cdace..00000000000 --- a/mysql-test/t/rpl_stm_user_variables.test +++ /dev/null @@ -1,5 +0,0 @@ -# row-based and statement binlog difference in result files --- source include/have_binlog_format_statement.inc --- source extra/rpl_tests/rpl_user_variables.test - -# End of 4.1 tests diff --git a/mysql-test/t/rpl_row_timezone-master.opt b/mysql-test/t/rpl_timezone-master.opt similarity index 100% rename from mysql-test/t/rpl_row_timezone-master.opt rename to mysql-test/t/rpl_timezone-master.opt diff --git a/mysql-test/t/rpl_stm_timezone-slave.opt b/mysql-test/t/rpl_timezone-slave.opt similarity index 100% rename from mysql-test/t/rpl_stm_timezone-slave.opt rename to mysql-test/t/rpl_timezone-slave.opt diff --git a/mysql-test/t/rpl_row_timezone.test b/mysql-test/t/rpl_timezone.test similarity index 93% rename from mysql-test/t/rpl_row_timezone.test rename to mysql-test/t/rpl_timezone.test index 047a458f09f..e78f1e1899e 100644 --- a/mysql-test/t/rpl_row_timezone.test +++ b/mysql-test/t/rpl_timezone.test @@ -1,6 +1,3 @@ -# TBF - difference in row level logging --- source include/have_binlog_format_row.inc - # Test of replication of time zones. # There is currently some bug possibly in prepared statements (this @@ -51,8 +48,11 @@ sync_slave_with_master; set time_zone='Europe/Moscow'; select * from t1; connection master; ---replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001 +# Change Author: JBM +# Change Date: 2005-12-22 +# Change: Comment out the exec of the binlog so test works for both SBR and RBR +#--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +#--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001 # Let us check with LOAD DATA INFILE # (we do it after mysqlbinlog because the temp files names are not constant) @@ -74,7 +74,7 @@ insert into t1 values ('20040101000000',NULL), ('20040611093902',NULL); # # Now let us check how well we replicate statments reading TIMESTAMP fields -# (We should see the same data on master and on slave but it should differ +# (We should see the same data on master and on slave but it should differ # from originally inserted) # set time_zone='MET'; @@ -127,3 +127,4 @@ select * from t2; connection master; drop table t1, t2; sync_slave_with_master; + diff --git a/mysql-test/extra/rpl_tests/rpl_user_variables.test b/mysql-test/t/rpl_user_variables.test similarity index 96% rename from mysql-test/extra/rpl_tests/rpl_user_variables.test rename to mysql-test/t/rpl_user_variables.test index 256c244d4eb..b46a0fad02e 100644 --- a/mysql-test/extra/rpl_tests/rpl_user_variables.test +++ b/mysql-test/t/rpl_user_variables.test @@ -1,4 +1,3 @@ -# row-based and statement binlog difference in result files # # Test of replicating user variables # diff --git a/mysql-test/t/rpl_stm_view.test b/mysql-test/t/rpl_view.test similarity index 82% rename from mysql-test/t/rpl_stm_view.test rename to mysql-test/t/rpl_view.test index 39f39705f77..0e8c7514488 100644 --- a/mysql-test/t/rpl_stm_view.test +++ b/mysql-test/t/rpl_view.test @@ -1,5 +1,4 @@ # NYI - row-based cannot use CREATE ... SELECT ---source include/have_binlog_format_statement.inc source include/master-slave.inc; --disable_warnings @@ -10,7 +9,7 @@ reset master; --enable_warnings # -# Check that createion drop of view is replicated, also check replication of +# Check that creation drop of view is replicated, also check replication of # updating of view # connection master; @@ -46,5 +45,8 @@ select * from v1 order by a; connection master; drop table t1; sync_slave_with_master; ---replace_column 2 # 5 # -show binlog events limit 1,100; +# Change Author: JBM +# Change Date: 2005-12-22 +# Change: Commented out binlog events to work with SBR and RBR +#--replace_column 2 # 5 # +# show binlog events limit 1,100; diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index b4074897689..f2d9bb6c856 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -930,11 +930,8 @@ drop table t1, t2, t3; # operator. # create table t1 (a int); ---disable_warnings -drop procedure if exists p2; ---enable_warnings DELIMITER //; -CREATE PROCEDURE `p2`() +CREATE PROCEDURE `p1`() begin insert into t1 values (1); end// @@ -944,8 +941,8 @@ begin set done= not done; end// DELIMITER ;// -CALL p2(); -drop procedure p2; +CALL p1(); +drop procedure p1; drop table t1; # diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 4ab2f49280d..bfa12a1ee33 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2279,6 +2279,7 @@ drop table t1; # create table t1(f1 int, f2 int); insert into t1 values (null, 10), (null,2); +select f1, sum(f2) from t1 group by f1; create view v1 as select * from t1; select f1, sum(f2) from v1 group by f1; drop view v1; diff --git a/mysys/hash.c b/mysys/hash.c index d9084ed4fd3..165745986dc 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -36,9 +36,10 @@ typedef struct st_hash_info { static uint hash_mask(uint hashnr,uint buffmax,uint maxlength); static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); -static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length); +static int hashcmp(const HASH *hash, HASH_LINK *pos, const byte *key, + uint length); -static uint calc_hash(HASH *hash,const byte *key,uint length) +static uint calc_hash(const HASH *hash, const byte *key, uint length) { ulong nr1=1, nr2=4; hash->charset->coll->hash_sort(hash->charset,(uchar*) key,length,&nr1,&nr2); @@ -63,7 +64,6 @@ _hash_init(HASH *hash,CHARSET_INFO *charset, hash->key_offset=key_offset; hash->key_length=key_length; hash->blength=1; - hash->current_record= NO_RECORD; /* For the future */ hash->get_key=get_key; hash->free=free_element; hash->flags=flags; @@ -135,7 +135,6 @@ void my_hash_reset(HASH *hash) reset_dynamic(&hash->array); /* Set row pointers so that the hash can be reused at once */ hash->blength= 1; - hash->current_record= NO_RECORD; DBUG_VOID_RETURN; } @@ -147,7 +146,8 @@ void my_hash_reset(HASH *hash) */ static inline char* -hash_key(HASH *hash,const byte *record,uint *length,my_bool first) +hash_key(const HASH *hash, const byte *record, uint *length, + my_bool first) { if (hash->get_key) return (*hash->get_key)(record,length,first); @@ -163,8 +163,8 @@ static uint hash_mask(uint hashnr,uint buffmax,uint maxlength) return (hashnr & ((buffmax >> 1) -1)); } -static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax, - uint maxlength) +static uint hash_rec_mask(const HASH *hash, HASH_LINK *pos, + uint buffmax, uint maxlength) { uint length; byte *key= (byte*) hash_key(hash,pos->data,&length,0); @@ -186,14 +186,25 @@ unsigned int rec_hashnr(HASH *hash,const byte *record) } - /* Search after a record based on a key */ - /* Sets info->current_ptr to found record */ +gptr hash_search(const HASH *hash, const byte *key, uint length) +{ + HASH_SEARCH_STATE state; + return hash_first(hash, key, length, &state); +} -gptr hash_search(HASH *hash,const byte *key,uint length) +/* + Search after a record based on a key + + NOTE + Assigns the number of the found record to HASH_SEARCH_STATE state +*/ + +gptr hash_first(const HASH *hash, const byte *key, uint length, + HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; uint flag,idx; - DBUG_ENTER("hash_search"); + DBUG_ENTER("hash_first"); flag=1; if (hash->records) @@ -206,7 +217,7 @@ gptr hash_search(HASH *hash,const byte *key,uint length) if (!hashcmp(hash,pos,key,length)) { DBUG_PRINT("exit",("found key at %d",idx)); - hash->current_record= idx; + *current_record= idx; DBUG_RETURN (pos->data); } if (flag) @@ -218,31 +229,32 @@ gptr hash_search(HASH *hash,const byte *key,uint length) } while ((idx=pos->next) != NO_RECORD); } - hash->current_record= NO_RECORD; + *current_record= NO_RECORD; DBUG_RETURN(0); } /* Get next record with identical key */ /* Can only be called if previous calls was hash_search */ -gptr hash_next(HASH *hash,const byte *key,uint length) +gptr hash_next(const HASH *hash, const byte *key, uint length, + HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; uint idx; - if (hash->current_record != NO_RECORD) + if (*current_record != NO_RECORD) { HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*); - for (idx=data[hash->current_record].next; idx != NO_RECORD ; idx=pos->next) + for (idx=data[*current_record].next; idx != NO_RECORD ; idx=pos->next) { pos=data+idx; if (!hashcmp(hash,pos,key,length)) { - hash->current_record= idx; + *current_record= idx; return pos->data; } } - hash->current_record=NO_RECORD; + *current_record= NO_RECORD; } return 0; } @@ -281,7 +293,8 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink) != 0 key of record != key */ -static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) +static int hashcmp(const HASH *hash, HASH_LINK *pos, const byte *key, + uint length) { uint rec_keylength; byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1); @@ -307,7 +320,6 @@ my_bool my_hash_insert(HASH *info,const byte *record) if (!(empty=(HASH_LINK*) alloc_dynamic(&info->array))) return(TRUE); /* No more memory */ - info->current_record= NO_RECORD; data=dynamic_element(&info->array,0,HASH_LINK*); halfbuff= info->blength >> 1; @@ -450,7 +462,6 @@ my_bool hash_delete(HASH *hash,byte *record) } if ( --(hash->records) < hash->blength >> 1) hash->blength>>=1; - hash->current_record= NO_RECORD; lastpos=data+hash->records; /* Remove link to record */ @@ -543,7 +554,6 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length) if ((idx=pos->next) == NO_RECORD) DBUG_RETURN(1); /* Not found in links */ } - hash->current_record= NO_RECORD; org_link= *pos; empty=idx; @@ -593,10 +603,10 @@ byte *hash_element(HASH *hash,uint idx) isn't changed */ -void hash_replace(HASH *hash, uint idx, byte *new_row) +void hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record, byte *new_row) { - if (idx != NO_RECORD) /* Safety */ - dynamic_element(&hash->array,idx,HASH_LINK*)->data=new_row; + if (*current_record != NO_RECORD) /* Safety */ + dynamic_element(&hash->array, *current_record, HASH_LINK*)->data= new_row; } diff --git a/mysys/my_once.c b/mysys/my_once.c index ab5fcc51c0e..52f8c4309d5 100644 --- a/mysys/my_once.c +++ b/mysys/my_once.c @@ -75,6 +75,8 @@ gptr my_once_alloc(unsigned int Size, myf MyFlags) point= (gptr) ((char*) next+ (next->size-next->left)); next->left-= Size; + if (MyFlags & MY_ZEROFILL) + bzero(point, Size); return(point); } /* my_once_alloc */ diff --git a/mysys/testhash.c b/mysys/testhash.c index 72badffdbcd..d15016113cd 100644 --- a/mysys/testhash.c +++ b/mysys/testhash.c @@ -74,7 +74,7 @@ static int do_test() bzero((char*) key1,sizeof(key1[0])*1000); printf("- Creating hash\n"); - if (hash_init(&hash,recant/2,0,6,0,free_record,0)) + if (hash_init(&hash, default_charset_info, recant/2, 0, 6, 0, free_record, 0)) goto err; printf("- Writing records:\n"); @@ -172,15 +172,16 @@ static int do_test() break; if (key1[j] > 1) { + HASH_SEARCH_STATE state; printf("- Testing identical read\n"); sprintf(key,"%6d",j); pos=1; - if (!(recpos=hash_search(&hash,key,0))) + if (!(recpos= hash_first(&hash, key, 0, &state))) { printf("can't find key1: \"%s\"\n",key); goto err; } - while (hash_next(&hash,key,0) && pos < (ulong) (key1[j]+10)) + while (hash_next(&hash, key, 0, &state) && pos < (ulong) (key1[j]+10)) pos++; if (pos != (ulong) key1[j]) { @@ -189,7 +190,7 @@ static int do_test() } } printf("- Creating output heap-file 2\n"); - if (hash_init(&hash2,hash.records,0,0,hash2_key,free_record,0)) + if (hash_init(&hash2, default_charset_info, hash.records, 0, 0, hash2_key, free_record,0)) goto err; printf("- Copying and removing records\n"); diff --git a/plugin/fulltext/Makefile.am b/plugin/fulltext/Makefile.am index 70c207a992f..0a3186829da 100644 --- a/plugin/fulltext/Makefile.am +++ b/plugin/fulltext/Makefile.am @@ -1,4 +1,4 @@ INCLUDES= -I$(top_builddir)/include -noinst_LTLIBRARIES= libmypluglib.la -libmypluglib_la_SOURCES= plugin_example.c -libmypluglib_la_LDFLAGS= -module +noinst_LTLIBRARIES= mypluglib.la +mypluglib_la_SOURCES= plugin_example.c +mypluglib_la_LDFLAGS= -module -rpath $(pkglibdir) diff --git a/plugin/fulltext/plugin_example.c b/plugin/fulltext/plugin_example.c index c222d3d85c3..4caa6de3197 100644 --- a/plugin/fulltext/plugin_example.c +++ b/plugin/fulltext/plugin_example.c @@ -18,6 +18,8 @@ #include #include +long number_of_calls= 0; /* for SHOW STATUS, see below */ + /* Simple full-text parser plugin that acts as a replacement for the built-in full-text parser: @@ -167,6 +169,8 @@ int simple_parser_parse(MYSQL_FTPARSER_PARAM *param) { char *end, *start, *docend= param->doc + param->length; + number_of_calls++; + for (end= start= param->doc;; end++) { if (end == docend) @@ -198,6 +202,16 @@ static struct st_mysql_ftparser simple_parser_descriptor= simple_parser_deinit /* parser deinit function */ }; +/* + Plugin status variables for SHOW STATUS +*/ + +struct st_mysql_show_var simple_status[]= +{ + {"static", "just a static text", SHOW_CHAR}, + {"called", (char *)&number_of_calls, SHOW_LONG}, + {0,0,0} +}; /* Plugin library descriptor @@ -211,6 +225,8 @@ mysql_declare_plugin "MySQL AB", /* author */ "Simple Full-Text Parser", /* description */ simple_parser_plugin_init, /* init function (when loaded) */ - simple_parser_plugin_deinit /* deinit function (when unloaded) */ + simple_parser_plugin_deinit,/* deinit function (when unloaded) */ + 0x0001, /* version */ + &simple_status /* status variables */ } mysql_declare_plugin_end; diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index c6deb642edf..2529eaf1937 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -229,7 +229,7 @@ then c_t="$c_t User char(16) binary DEFAULT '' NOT NULL," c_t="$c_t Table_name char(64) binary DEFAULT '' NOT NULL," c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL," - c_t="$c_t Timestamp timestamp(14)," + c_t="$c_t Timestamp timestamp," c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL," c_t="$c_t Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL," c_t="$c_t PRIMARY KEY (Host,Db,User,Table_name)," @@ -251,7 +251,7 @@ then c_c="$c_c User char(16) binary DEFAULT '' NOT NULL," c_c="$c_c Table_name char(64) binary DEFAULT '' NOT NULL," c_c="$c_c Column_name char(64) binary DEFAULT '' NOT NULL," - c_c="$c_c Timestamp timestamp(14)," + c_c="$c_c Timestamp timestamp," c_c="$c_c Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL," c_c="$c_c PRIMARY KEY (Host,Db,User,Table_name,Column_name)" c_c="$c_c ) engine=MyISAM" @@ -273,7 +273,7 @@ then c_pp="$c_pp Routine_type enum('FUNCTION','PROCEDURE') NOT NULL," c_pp="$c_pp Grantor char(77) DEFAULT '' NOT NULL," c_pp="$c_pp Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL," - c_pp="$c_pp Timestamp timestamp(14)," + c_pp="$c_pp Timestamp timestamp," c_pp="$c_pp PRIMARY KEY (Host,Db,User,Routine_name,Routine_type)," c_pp="$c_pp KEY Grantor (Grantor)" c_pp="$c_pp ) engine=MyISAM" @@ -743,7 +743,7 @@ fi cat << END_OF_DATA use mysql; -set table_type=myisam; +set storage_engine=myisam; $c_d $i_d diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh index d61551ffb3b..31282d06abf 100644 --- a/sql-bench/bench-init.pl.sh +++ b/sql-bench/bench-init.pl.sh @@ -447,7 +447,7 @@ All benchmarks takes the following options: --create-options=# Extra argument to all create statements. If you for example want to create all MySQL tables as BDB tables use: - --create-options=TYPE=BDB + --create-options=ENGINE=BDB --database (Default $opt_database) In which database the test tables are created. diff --git a/sql-bench/server-cfg.sh b/sql-bench/server-cfg.sh index b0c40102a6b..75528b24b77 100644 --- a/sql-bench/server-cfg.sh +++ b/sql-bench/server-cfg.sh @@ -174,29 +174,29 @@ sub new # Some fixes that depends on the environment if (defined($main::opt_create_options) && - $main::opt_create_options =~ /type=heap/i) + $main::opt_create_options =~ /engine=heap/i) { $limits{'working_blobs'} = 0; # HEAP tables can't handle BLOB's } if (defined($main::opt_create_options) && - $main::opt_create_options =~ /type=innodb/i) + $main::opt_create_options =~ /engine=innodb/i) { $self->{'transactions'} = 1; # Transactions enabled } if (defined($main::opt_create_options) && - $main::opt_create_options =~ /type=ndb/i) + $main::opt_create_options =~ /engine=ndb/i) { $self->{'transactions'} = 1; # Transactions enabled $limits{'max_columns'} = 90; # Max number of columns in table $limits{'max_tables'} = 32; # No comments } if (defined($main::opt_create_options) && - $main::opt_create_options =~ /type=bdb/i) + $main::opt_create_options =~ /engine=bdb/i) { $self->{'transactions'} = 1; # Transactions enabled } if (defined($main::opt_create_options) && - $main::opt_create_options =~ /type=gemini/i) + $main::opt_create_options =~ /engine=gemini/i) { $limits{'working_blobs'} = 0; # Blobs not implemented yet $limits{'max_tables'} = 500; diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 944333496ae..bc087ac25e7 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -2607,8 +2607,7 @@ int ha_federated::stash_remote_error() { DBUG_ENTER("ha_federated::stash_remote_error()"); remote_error_number= mysql_errno(mysql); - my_snprintf(remote_error_buf, sizeof(remote_error_buf), "%s", - mysql_error(mysql)); + strmake(remote_error_buf, mysql_error(mysql), sizeof(remote_error_buf)-1); DBUG_RETURN(HA_FEDERATED_ERROR_WITH_REMOTE_SYSTEM); } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 27262e6f197..75c1c380a42 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -253,7 +253,7 @@ innobase_commit_low( /*================*/ trx_t* trx); /* in: transaction handle */ -struct show_var_st innodb_status_variables[]= { +SHOW_VAR innodb_status_variables[]= { {"buffer_pool_pages_data", (char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG}, {"buffer_pool_pages_dirty", diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index fd0d3aa7e8c..b9e399509de 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -212,7 +212,7 @@ class ha_innobase: public handler uint table_changes); }; -extern struct show_var_st innodb_status_variables[]; +extern SHOW_VAR innodb_status_variables[]; extern uint innobase_init_flags, innobase_lock_type; extern uint innobase_flush_log_at_trx_commit; extern ulong innobase_cache_size, innobase_fast_shutdown; @@ -277,7 +277,6 @@ void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offse void innobase_drop_database(char *path); bool innobase_show_status(THD* thd, stat_print_fn*, enum ha_stat_type); -int innodb_export_status(void); int innobase_release_temporary_latches(THD *thd); diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index dfbe1993ea8..7bb0eca20b1 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -224,7 +224,7 @@ static int update_status_variables(Ndb_cluster_connection *c) return 0; } -struct show_var_st ndb_status_variables[]= { +SHOW_VAR ndb_status_variables[]= { {"cluster_node_id", (char*) &ndb_cluster_node_id, SHOW_LONG}, {"connected_host", (char*) &ndb_connected_host, SHOW_CHAR_PTR}, {"connected_port", (char*) &ndb_connected_port, SHOW_LONG}, @@ -370,7 +370,8 @@ Thd_ndb::~Thd_ndb() if (ndb) { #ifndef DBUG_OFF - Ndb::Free_list_usage tmp; tmp.m_name= 0; + Ndb::Free_list_usage tmp; + tmp.m_name= 0; while (ndb->get_free_list_usage(&tmp)) { uint leaked= (uint) tmp.m_created - tmp.m_free; @@ -382,8 +383,8 @@ Thd_ndb::~Thd_ndb() } #endif delete ndb; + ndb= NULL; } - ndb= NULL; changed_tables.empty(); } @@ -3359,6 +3360,10 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) if (lock_type != F_UNLCK) { DBUG_PRINT("info", ("lock_type != F_UNLCK")); + if (!thd->transaction.on) + m_transaction_on= FALSE; + else + m_transaction_on= thd->variables.ndb_use_transactions; if (!thd_ndb->lock_count++) { PRINT_OPTION_FLAGS(thd); @@ -3373,7 +3378,8 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) ERR_RETURN(ndb->getNdbError()); no_uncommitted_rows_reset(thd); thd_ndb->stmt= trans; - trans_register_ha(thd, FALSE, &ndbcluster_hton); + if (m_transaction_on) + trans_register_ha(thd, FALSE, &ndbcluster_hton); } else { @@ -3388,7 +3394,8 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) ERR_RETURN(ndb->getNdbError()); no_uncommitted_rows_reset(thd); thd_ndb->all= trans; - trans_register_ha(thd, TRUE, &ndbcluster_hton); + if (m_transaction_on) + trans_register_ha(thd, TRUE, &ndbcluster_hton); /* If this is the start of a LOCK TABLE, a table look @@ -3422,10 +3429,6 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) m_ha_not_exact_count= !thd->variables.ndb_use_exact_count; m_autoincrement_prefetch= (ha_rows) thd->variables.ndb_autoincrement_prefetch_sz; - if (!thd->transaction.on) - m_transaction_on= FALSE; - else - m_transaction_on= thd->variables.ndb_use_transactions; m_active_trans= thd_ndb->all ? thd_ndb->all : thd_ndb->stmt; DBUG_ASSERT(m_active_trans); @@ -5172,7 +5175,8 @@ int ndbcluster_end(ha_panic_function type) if (g_ndb) { #ifndef DBUG_OFF - Ndb::Free_list_usage tmp; tmp.m_name= 0; + Ndb::Free_list_usage tmp; + tmp.m_name= 0; while (g_ndb->get_free_list_usage(&tmp)) { uint leaked= (uint) tmp.m_created - tmp.m_free; @@ -5184,10 +5188,9 @@ int ndbcluster_end(ha_panic_function type) } #endif delete g_ndb; + g_ndb= NULL; } - g_ndb= NULL; - if (g_ndb_cluster_connection) - delete g_ndb_cluster_connection; + delete g_ndb_cluster_connection; g_ndb_cluster_connection= NULL; hash_free(&ndbcluster_open_tables); @@ -8075,7 +8078,8 @@ ndbcluster_show_status(THD* thd, stat_print_fn *stat_print, if (get_thd_ndb(thd) && get_thd_ndb(thd)->ndb) { Ndb* ndb= (get_thd_ndb(thd))->ndb; - Ndb::Free_list_usage tmp; tmp.m_name= 0; + Ndb::Free_list_usage tmp; + tmp.m_name= 0; while (ndb->get_free_list_usage(&tmp)) { uint buflen= diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index fb506375797..2c6af550ffe 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -769,7 +769,7 @@ private: Ndb *get_ndb(); }; -extern struct show_var_st ndb_status_variables[]; +extern SHOW_VAR ndb_status_variables[]; bool ndbcluster_init(void); int ndbcluster_end(ha_panic_function flag); diff --git a/sql/handler.cc b/sql/handler.cc index 8649230511b..ae38e376d54 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1181,15 +1181,6 @@ int ha_release_temporary_latches(THD *thd) return 0; } - -int ha_update_statistics() -{ -#ifdef WITH_INNOBASE_STORAGE_ENGINE - innodb_export_status(); -#endif - return 0; -} - int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) { int error=0; @@ -2084,7 +2075,8 @@ int ha_enable_transaction(THD *thd, bool on) is an optimization hint that storage engine is free to ignore. So, let's commit an open transaction (if any) now. */ - error= end_trans(thd, COMMIT); + if (!(error= ha_commit_stmt(thd))) + error= end_trans(thd, COMMIT); } DBUG_RETURN(error); } @@ -2798,16 +2790,22 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat) - Row-based replication is on - It is not a temporary table - The binlog is enabled - - The table shall be binlogged (binlog_*_db rules) [Seems disabled /Matz] + - The table shall be binlogged (binlog_*_db rules) */ #ifdef HAVE_ROW_BASED_REPLICATION -static bool check_table_binlog_row_based(THD *thd, TABLE *table) -{ - return - binlog_row_based && - thd && (thd->options & OPTION_BIN_LOG) && - (table->s->tmp_table == NO_TMP_TABLE); +/* The Sun compiler cannot instantiate the template below if this is + declared static, but it works by putting it into an anonymous + namespace. */ +namespace { + bool check_table_binlog_row_based(THD *thd, TABLE *table) + { + return + binlog_row_based && + thd && (thd->options & OPTION_BIN_LOG) && + (table->s->tmp_table == NO_TMP_TABLE) && + binlog_filter->db_ok(table->s->db.str); + } } template int binlog_log_row(TABLE* table, diff --git a/sql/handler.h b/sql/handler.h index eff4ecdc4d2..b03b7654c9e 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1538,7 +1538,7 @@ inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag) inline bool ha_storage_engine_is_enabled(const handlerton *db_type) { - return (db_type && db_type->create) ? + return (db_type && db_type->create) ? (db_type->state == SHOW_OPTION_YES) : FALSE; } @@ -1549,7 +1549,6 @@ int ha_initialize_handlerton(handlerton *hton); TYPELIB *ha_known_exts(void); int ha_panic(enum ha_panic_function flag); -int ha_update_statistics(); void ha_close_connection(THD* thd); bool ha_flush_logs(handlerton *db_type); void ha_drop_database(char* path); diff --git a/sql/item.cc b/sql/item.cc index bf5718bb54d..fa5c2b5cc3b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4925,6 +4925,12 @@ int Item_ref::save_in_field(Field *to, bool no_conversions) } +void Item_ref::save_org_in_field(Field *field) +{ + (*ref)->save_org_in_field(field); +} + + void Item_ref::make_field(Send_field *field) { (*ref)->make_field(field); diff --git a/sql/item.h b/sql/item.h index c240733bd04..5de69013605 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1782,11 +1782,7 @@ public: void make_field(Send_field *field); bool fix_fields(THD *, Item **); int save_in_field(Field *field, bool no_conversions); - void save_org_in_field(Field *field) - { - (*ref)->save_org_in_field(field); - null_value= (*ref)->null_value; - } + void save_org_in_field(Field *field); enum Item_result result_type () const { return (*ref)->result_type(); } enum_field_types field_type() const { return (*ref)->field_type(); } Field *get_tmp_table_field() diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 79a5c8e6445..bb5775780fa 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -715,7 +715,7 @@ String *Item_nodeset_func_predicate::val_nodeset(String *str) ((XPathFilter*)str)->append_element(flt->num, pos++); } return str; -}; +} String *Item_nodeset_func_elementbyindex::val_nodeset(String *nodeset) diff --git a/sql/lock.cc b/sql/lock.cc index f544708d075..8e24c56799d 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -731,15 +731,16 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) char key[MAX_DBKEY_LENGTH]; char *db= table_list->db; uint key_length; + HASH_SEARCH_STATE state; DBUG_ENTER("lock_table_name"); DBUG_PRINT("enter",("db: %s name: %s", db, table_list->table_name)); key_length= create_table_def_key(thd, key, table_list, 0); /* Only insert the table if we haven't insert it already */ - for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; + for (table=(TABLE*) hash_first(&open_cache, (byte*)key, key_length, &state); table ; - table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length, &state)) { if (table->in_use == thd) { diff --git a/sql/log.cc b/sql/log.cc index 44d3869e9d5..45ce7776d1a 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -241,13 +241,15 @@ static int binlog_savepoint_set(THD *thd, void *sv) DBUG_ENTER("binlog_savepoint_set"); binlog_trx_data *const trx_data= (binlog_trx_data*) thd->ha_data[binlog_hton.slot]; - IO_CACHE *trans_log= &trx_data->trans_log; - DBUG_ASSERT(mysql_bin_log.is_open() && my_b_tell(trans_log)); + DBUG_ASSERT(mysql_bin_log.is_open() && my_b_tell(&trx_data->trans_log)); - *(my_off_t *)sv= my_b_tell(trans_log); + *(my_off_t *)sv= my_b_tell(&trx_data->trans_log); /* Write it to the binary log */ - Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); - DBUG_RETURN(mysql_bin_log.write(&qinfo)); + + int const error= + thd->binlog_query(THD::STMT_QUERY_TYPE, + thd->query, thd->query_length, TRUE, FALSE); + DBUG_RETURN(error); } static int binlog_savepoint_rollback(THD *thd, void *sv) @@ -265,8 +267,10 @@ static int binlog_savepoint_rollback(THD *thd, void *sv) */ if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE)) { - Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); - DBUG_RETURN(mysql_bin_log.write(&qinfo)); + int const error= + thd->binlog_query(THD::STMT_QUERY_TYPE, + thd->query, thd->query_length, TRUE, FALSE); + DBUG_RETURN(error); } reinit_io_cache(trans_log, WRITE_CACHE, *(my_off_t *)sv, 0, 0); DBUG_RETURN(0); @@ -2556,7 +2560,7 @@ bool MYSQL_LOG::write_table_map(THD *thd, IO_CACHE *file, TABLE* table, #endif Table_map_log_event::flag_set const - flags= Table_map_log_event::NO_FLAGS; + flags= Table_map_log_event::TM_NO_FLAGS; Table_map_log_event the_event(thd, table, table->s->table_map_id, is_transactional, flags); diff --git a/sql/log_event.cc b/sql/log_event.cc index 1ec501e8a36..712fff15774 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -118,13 +118,24 @@ static char *pretty_print_str(char *packet, char *str, int len) /* - slave_load_file_stem() + Creates a temporary name for load data infile: + + SYNOPSIS + slave_load_file_stem() + buf Store new filename here + file_id File_id (part of file name) + event_server_id Event_id (part of file name) + ext Extension for file name + + RETURN + Pointer to start of extension */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -static inline char* slave_load_file_stem(char*buf, uint file_id, - int event_server_id) +static char *slave_load_file_stem(char *buf, uint file_id, + int event_server_id, const char *ext) { + char *res; fn_format(buf,"SQL_LOAD-",slave_load_tmpdir, "", MY_UNPACK_FILENAME); to_unix_path(buf); @@ -133,7 +144,9 @@ static inline char* slave_load_file_stem(char*buf, uint file_id, *buf++ = '-'; buf = int10_to_str(event_server_id, buf, 10); *buf++ = '-'; - return int10_to_str(file_id, buf, 10); + res= int10_to_str(file_id, buf, 10); + strmov(res, ext); // Add extension last + return res; // Pointer to extension } #endif @@ -928,7 +941,6 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) /* Pretty-print event common header if header is exactly 19 bytes */ if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN) { - DBUG_ASSERT(hexdump_from == (unsigned long) hexdump_from); fprintf(file, "# Position Timestamp Type Master ID " "Size Master Pos Flags \n"); fprintf(file, "# %8.8lx %02x %02x %02x %02x %02x " @@ -954,7 +966,6 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) if (i % 16 == 15) { - DBUG_ASSERT(hexdump_from == (unsigned long) hexdump_from); fprintf(file, "# %8.8lx %-48.48s |%16s|\n", (unsigned long) (hexdump_from + (i & 0xfffffff0)), hex_string, char_string); @@ -968,12 +979,10 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) *c= '\0'; /* Non-full last line */ - if (hex_string[0]) { - DBUG_ASSERT(hexdump_from == (unsigned long) hexdump_from); + if (hex_string[0]) fprintf(file, "# %8.8lx %-48.48s |%s|\n# ", (unsigned long) (hexdump_from + (i & 0xfffffff0)), hex_string, char_string); - } } } @@ -4238,16 +4247,15 @@ void Create_file_log_event::pack_info(Protocol *protocol) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) int Create_file_log_event::exec_event(struct st_relay_log_info* rli) { - char proc_info[17+FN_REFLEN+10], *fname_buf= proc_info+17; - char *p; + char proc_info[17+FN_REFLEN+10], *fname_buf; + char *ext; int fd = -1; IO_CACHE file; int error = 1; bzero((char*)&file, sizeof(file)); - p = slave_load_file_stem(fname_buf, file_id, server_id); - strmov(p, ".info"); // strmov takes less code than memcpy - strnmov(proc_info, STRING_WITH_LEN("Making temp file ")); // no end 0 + fname_buf= strmov(proc_info, "Making temp file "); + ext= slave_load_file_stem(fname_buf, file_id, server_id, ".info"); thd->proc_info= proc_info; my_delete(fname_buf, MYF(0)); // old copy may exist already if ((fd= my_create(fname_buf, CREATE_MODE, @@ -4262,12 +4270,11 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli) } // a trick to avoid allocating another buffer - strmov(p, ".data"); - fname = fname_buf; - fname_len = (uint)(p-fname) + 5; + fname= fname_buf; + fname_len= (uint) (strmov(ext, ".data") - fname); if (write_base(&file)) { - strmov(p, ".info"); // to have it right in the error message + strmov(ext, ".info"); // to have it right in the error message slave_print_msg(ERROR_LEVEL, rli, my_errno, "Error in Create_file event: could not write to file '%s'", fname_buf); @@ -4413,13 +4420,12 @@ int Append_block_log_event::get_create_or_append() const int Append_block_log_event::exec_event(struct st_relay_log_info* rli) { char proc_info[17+FN_REFLEN+10], *fname= proc_info+17; - char *p= slave_load_file_stem(fname, file_id, server_id); int fd; int error = 1; DBUG_ENTER("Append_block_log_event::exec_event"); - memcpy(p, ".data", 6); - strnmov(proc_info, STRING_WITH_LEN("Making temp file ")); // no end 0 + fname= strmov(proc_info, "Making temp file "); + slave_load_file_stem(fname, file_id, server_id, ".data"); thd->proc_info= proc_info; if (get_create_or_append()) { @@ -4545,10 +4551,9 @@ void Delete_file_log_event::pack_info(Protocol *protocol) int Delete_file_log_event::exec_event(struct st_relay_log_info* rli) { char fname[FN_REFLEN+10]; - char *p= slave_load_file_stem(fname, file_id, server_id); - memcpy(p, ".data", 6); + char *ext= slave_load_file_stem(fname, file_id, server_id, ".data"); (void) my_delete(fname, MYF(MY_WME)); - memcpy(p, ".info", 6); + strmov(ext, ".info"); (void) my_delete(fname, MYF(MY_WME)); return Log_event::exec_event(rli); } @@ -4641,13 +4646,13 @@ void Execute_load_log_event::pack_info(Protocol *protocol) int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) { char fname[FN_REFLEN+10]; - char *p= slave_load_file_stem(fname, file_id, server_id); + char *ext; int fd; - int error = 1; + int error= 1; IO_CACHE file; - Load_log_event* lev = 0; + Load_log_event *lev= 0; - memcpy(p, ".info", 6); + ext= slave_load_file_stem(fname, file_id, server_id, ".info"); if ((fd = my_open(fname, O_RDONLY | O_BINARY | O_NOFOLLOW, MYF(MY_WME))) < 0 || init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0, @@ -4708,7 +4713,7 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) fd= -1; } (void) my_delete(fname, MYF(MY_WME)); - memcpy(p, ".data", 6); + memcpy(ext, ".data", 6); (void) my_delete(fname, MYF(MY_WME)); error = 0; @@ -4906,11 +4911,10 @@ Execute_load_query_log_event::exec_event(struct st_relay_log_info* rli) memcpy(p, query, fn_pos_start); p+= fn_pos_start; fname= (p= strmake(p, STRING_WITH_LEN(" INFILE \'"))); - p= slave_load_file_stem(p, file_id, server_id); - fname_end= (p= strmake(p, STRING_WITH_LEN(".data"))); + p= slave_load_file_stem(p, file_id, server_id, ".data"); + fname_end= p= strend(p); // Safer than p=p+5 *(p++)='\''; - switch (dup_handling) - { + switch (dup_handling) { case LOAD_DUP_IGNORE: p= strmake(p, STRING_WITH_LEN(" IGNORE")); break; diff --git a/sql/log_event.h b/sql/log_event.h index f4c3867910a..8b665755aab 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1673,8 +1673,11 @@ public: { /* Nothing here right now, but the flags support is there in - preparation for changes that are coming. + preparation for changes that are coming. Need to add a + constant to make it compile under HP-UX: aCC does not like + empty enumerations. */ + ENUM_FLAG_COUNT }; typedef uint16 flag_set; @@ -1682,7 +1685,7 @@ public: /* Special constants representing sets of flags */ enum { - NO_FLAGS = 0U + TM_NO_FLAGS = 0U }; void set_flags(flag_set flag) { m_flags |= flag; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b6be03003c6..e9b79afff7a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -292,7 +292,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define OPTION_SETUP_TABLES_DONE (LL(1) << 30) // intern /* If not set then the thread will ignore all warnings with level notes. */ #define OPTION_SQL_NOTES (LL(1) << 31) // THD, user -/* +/* Force the used temporary table to be a MyISAM table (because we will use fulltext functions when reading from it. */ @@ -322,7 +322,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define MODE_DB2 2048 #define MODE_MAXDB 4096 #define MODE_NO_KEY_OPTIONS 8192 -#define MODE_NO_TABLE_OPTIONS 16384 +#define MODE_NO_TABLE_OPTIONS 16384 #define MODE_NO_FIELD_OPTIONS 32768 #define MODE_MYSQL323 65536 #define MODE_MYSQL40 (MODE_MYSQL323*2) @@ -513,13 +513,11 @@ void free_items(Item *item); void cleanup_items(Item *item); class THD; void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0); -bool check_one_table_access(THD *thd, ulong privilege, - TABLE_LIST *tables); +bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables); bool check_routine_access(THD *thd,ulong want_access,char *db,char *name, bool is_proc, bool no_errors); bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table); -bool check_merge_table_access(THD *thd, char *db, - TABLE_LIST *table_list); +bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list); bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc); bool multi_update_precheck(THD *thd, TABLE_LIST *tables); bool multi_delete_precheck(THD *thd, TABLE_LIST *tables); @@ -884,6 +882,10 @@ void calc_sum_of_all_status(STATUS_VAR *to); void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user, const LEX_STRING *definer_host); +int add_status_vars(SHOW_VAR *list); +void remove_status_vars(SHOW_VAR *list); +void init_status_vars(); +void free_status_vars(); /* information schema */ extern LEX_STRING information_schema_name; @@ -1269,7 +1271,7 @@ extern I_List key_caches; extern MY_BITMAP temp_pool; extern String my_empty_string; extern const String my_null_string; -extern SHOW_VAR init_vars[],status_vars[], internal_vars[]; +extern SHOW_VAR init_vars[], status_vars[], internal_vars[]; extern struct system_variables global_system_variables; extern struct system_variables max_system_variables; extern struct system_status_var global_status_var; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d6d54d180db..0e06351e892 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -348,7 +348,7 @@ my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0; my_bool opt_log_slave_updates= 0; my_bool opt_innodb; #ifdef WITH_INNOBASE_STORAGE_ENGINE -extern struct show_var_st innodb_status_variables[]; +extern SHOW_VAR innodb_status_variables[]; extern uint innobase_init_flags, innobase_lock_type; extern uint innobase_flush_log_at_trx_commit; extern ulong innobase_cache_size, innobase_fast_shutdown; @@ -417,7 +417,7 @@ ulong opt_ndb_cache_check_time; const char *opt_ndb_mgmd; ulong opt_ndb_nodeid; -extern struct show_var_st ndb_status_variables[]; +extern SHOW_VAR ndb_status_variables[]; extern const char *ndb_distribution_names[]; extern TYPELIB ndb_distribution_typelib; extern const char *opt_ndb_distribution; @@ -1154,18 +1154,19 @@ void clean_up(bool print_message) set_var_free(); free_charsets(); (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */ +#ifdef HAVE_DLOPEN if (!opt_noacl) { -#ifdef HAVE_DLOPEN udf_free(); -#endif - plugin_free(); } +#endif + plugin_free(); if (tc_log) tc_log->close(); xid_cache_free(); delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache); multi_keycache_free(); + free_status_vars(); end_thr_alarm(1); /* Free allocated memory */ #ifdef USE_RAID end_raid(); @@ -1489,7 +1490,7 @@ static void network_init(void) { if (((ret= bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr), sizeof(IPaddr))) >= 0) || - (socket_errno != EADDRINUSE) || + (socket_errno != SOCKET_EADDRINUSE) || (waited >= mysqld_port_timeout)) break; sql_print_information("Retrying bind on TCP/IP port %u", mysqld_port); @@ -1701,7 +1702,7 @@ void end_thread(THD *thd, bool put_in_cache) wake_thread--; thd=thread_cache.get(); thd->real_id=pthread_self(); - thd->thread_stack= (char *) &thd; + thd->thread_stack= (char*) &thd; // For store_globals (void) thd->store_globals(); thd->thr_create_time= time(NULL); threads.append(thd); @@ -2670,12 +2671,21 @@ static int init_common_variables(const char *conf_file_name, int argc, mysql_log.init_pthread_objects(); mysql_slow_log.init_pthread_objects(); mysql_bin_log.init_pthread_objects(); - + if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0) strmov(glob_hostname,"mysql"); strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5); strmov(fn_ext(pidfile_name),".pid"); // Add proper extension + /* + Add server status variables to the dynamic list of + status variables that is shown by SHOW STATUS. + Later, in plugin_init, plugin_load, and mysql_install_plugin + new entries could be added to that list. + */ + if (add_status_vars(status_vars)) + return 1; // an error was already reported + if (plugin_init()) { sql_print_error("Failed to init plugins."); @@ -3557,7 +3567,7 @@ we force server id to 2, but this MySQL server will not act as a slave."); #ifndef __NETWARE__ (void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL); #endif /* __NETWARE__ */ - + if (!opt_bootstrap) (void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore @@ -3575,6 +3585,7 @@ we force server id to 2, but this MySQL server will not act as a slave."); udf_init(); #endif } + init_status_vars(); if (opt_bootstrap) /* If running with bootstrap, do not start replication. */ opt_skip_slave_start= 1; /* @@ -6186,8 +6197,337 @@ The minimum value for this variable is 4096.", {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; +static int show_question(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONGLONG; + var->value= (char *)&thd->query_id; + return 0; +} -struct show_var_st status_vars[]= { +static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_MY_BOOL; + var->value= (char *)&thd->net.compress; + return 0; +} + +static int show_starttime(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (long) (thd->query_start() - start_time); + return 0; +} + +#ifdef HAVE_REPLICATION +static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_CHAR; + var->value= const_cast(rpl_status_type[(int)rpl_status]); + return 0; +} + +static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_CHAR; + pthread_mutex_lock(&LOCK_active_mi); + var->value= const_cast((active_mi && active_mi->slave_running && + active_mi->rli.slave_running) ? "ON" : "OFF"); + pthread_mutex_unlock(&LOCK_active_mi); + return 0; +} + +static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff) +{ + /* + TODO: with multimaster, have one such counter per line in + SHOW SLAVE STATUS, and have the sum over all lines here. + */ + pthread_mutex_lock(&LOCK_active_mi); + if (active_mi) + { + var->type= SHOW_LONG; + var->value= buff; + pthread_mutex_lock(&active_mi->rli.data_lock); + *((long *)buff)= (long)active_mi->rli.retried_trans; + pthread_mutex_unlock(&active_mi->rli.data_lock); + } + else + var->type= SHOW_UNDEF; + pthread_mutex_unlock(&LOCK_active_mi); + return 0; +} +#endif /* HAVE_REPLICATION */ + +static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (long)cached_open_tables(); + return 0; +} + +static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (long)cached_table_definitions(); + return 0; +} + +#ifdef HAVE_OPENSSL +/* Functions relying on CTX */ +static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_hits(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_cache_full(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_misses(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_timeouts(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (!ssl_acceptor_fd ? 0 : + SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)); + return 0; +} + +static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_CHAR; + if (!ssl_acceptor_fd) + var->value= "NONE"; + else + switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context)) + { + case SSL_SESS_CACHE_OFF: + var->value= "OFF"; break; + case SSL_SESS_CACHE_CLIENT: + var->value= "CLIENT"; break; + case SSL_SESS_CACHE_SERVER: + var->value= "SERVER"; break; + case SSL_SESS_CACHE_BOTH: + var->value= "BOTH"; break; + case SSL_SESS_CACHE_NO_AUTO_CLEAR: + var->value= "NO_AUTO_CLEAR"; break; + case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP: + var->value= "NO_INTERNAL_LOOKUP"; break; + default: + var->value= "Unknown"; break; + } + return 0; +} + +/* Functions relying on SSL */ +static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_CHAR; + var->value= const_cast(thd->net.vio->ssl_arg ? + SSL_get_version((SSL*) thd->net.vio->ssl_arg) : ""); + return 0; +} + +static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (long)thd->net.vio->ssl_arg ? + SSL_session_reused((SSL*) thd->net.vio->ssl_arg) : + 0; +} + +static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (long)thd->net.vio->ssl_arg ? + SSL_get_default_timeout((SSL*)thd->net.vio->ssl_arg) : + 0; + return 0; +} + +static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (long)thd->net.vio->ssl_arg ? + SSL_get_verify_mode((SSL*)thd->net.vio->ssl_arg) : + 0; + return 0; +} + +static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (long)thd->net.vio->ssl_arg ? + SSL_get_verify_depth((SSL*)thd->net.vio->ssl_arg) : + 0; + return 0; +} + +static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_CHAR; + var->value= const_cast(thd->net.vio->ssl_arg ? + SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : ""); + return 0; +} + +static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_CHAR; + var->value= buff; + if (thd->net.vio->ssl_arg) + { + int i; + const char *p; + for (i=0 ; (p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i)); i++) + { + buff= strmov(buff, p); + *buff++= ':'; + } + if (i) + buff--; + } + *buff=0; + return 0; +} + +#endif /* HAVE_OPENSSL */ + +#ifdef WITH_INNOBASE_STORAGE_ENGINE +int innodb_export_status(void); +static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff) +{ + innodb_export_status(); + var->type= SHOW_ARRAY; + var->value= (char *) &innodb_status_variables; + return 0; +} +#endif + +SHOW_VAR status_vars[]= { {"Aborted_clients", (char*) &aborted_threads, SHOW_LONG}, {"Aborted_connects", (char*) &aborted_connects, SHOW_LONG}, {"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG}, @@ -6218,7 +6558,7 @@ struct show_var_st status_vars[]= { {"Com_drop_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS}, {"Com_drop_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS}, {"Com_drop_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS}, - {"Com_execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS}, + {"Com_execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS}, {"Com_flush", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS}, {"Com_grant", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS}, {"Com_ha_close", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS}, @@ -6296,15 +6636,15 @@ struct show_var_st status_vars[]= { {"Com_xa_recover", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),SHOW_LONG_STATUS}, {"Com_xa_rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS}, {"Com_xa_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS}, - {"Compression", (char*) 0, SHOW_NET_COMPRESSION}, - {"Connections", (char*) &thread_id, SHOW_LONG_CONST}, + {"Compression", (char*) &show_net_compression, SHOW_FUNC}, + {"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH}, {"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS}, {"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG}, {"Created_tmp_tables", (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS}, {"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG}, - {"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_CONST}, + {"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH}, {"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG}, - {"Flush_commands", (char*) &refresh_version, SHOW_LONG_CONST}, + {"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH}, {"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS}, {"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS}, {"Handler_discover", (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS}, @@ -6321,46 +6661,50 @@ struct show_var_st status_vars[]= { {"Handler_update", (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS}, {"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS}, #ifdef WITH_INNOBASE_STORAGE_ENGINE - {"Innodb_", (char*) &innodb_status_variables, SHOW_VARS}, + {"Innodb", (char*) &show_innodb_vars, SHOW_FUNC}, #endif /* WITH_INNOBASE_STORAGE_ENGINE */ - {"Key_blocks_not_flushed", (char*) &dflt_key_cache_var.global_blocks_changed, SHOW_KEY_CACHE_LONG}, - {"Key_blocks_unused", (char*) &dflt_key_cache_var.blocks_unused, SHOW_KEY_CACHE_CONST_LONG}, - {"Key_blocks_used", (char*) &dflt_key_cache_var.blocks_used, SHOW_KEY_CACHE_CONST_LONG}, - {"Key_read_requests", (char*) &dflt_key_cache_var.global_cache_r_requests, SHOW_KEY_CACHE_LONGLONG}, - {"Key_reads", (char*) &dflt_key_cache_var.global_cache_read, SHOW_KEY_CACHE_LONGLONG}, - {"Key_write_requests", (char*) &dflt_key_cache_var.global_cache_w_requests, SHOW_KEY_CACHE_LONGLONG}, - {"Key_writes", (char*) &dflt_key_cache_var.global_cache_write, SHOW_KEY_CACHE_LONGLONG}, + {"Key_blocks_not_flushed", (char*) offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG}, + {"Key_blocks_unused", (char*) offsetof(KEY_CACHE, blocks_unused), SHOW_KEY_CACHE_LONG}, + {"Key_blocks_used", (char*) offsetof(KEY_CACHE, blocks_used), SHOW_KEY_CACHE_LONG}, + {"Key_read_requests", (char*) offsetof(KEY_CACHE, global_cache_r_requests), SHOW_KEY_CACHE_LONGLONG}, + {"Key_reads", (char*) offsetof(KEY_CACHE, global_cache_read), SHOW_KEY_CACHE_LONGLONG}, + {"Key_write_requests", (char*) offsetof(KEY_CACHE, global_cache_w_requests), SHOW_KEY_CACHE_LONGLONG}, + {"Key_writes", (char*) offsetof(KEY_CACHE, global_cache_write), SHOW_KEY_CACHE_LONGLONG}, {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS}, {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG}, #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE - {"Ndb_", (char*) &ndb_status_variables, SHOW_VARS}, + {"Ndb", (char*) &ndb_status_variables, SHOW_ARRAY}, #endif /* WITH_NDBCLUSTER_STORAGE_ENGINE */ - {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST}, - {"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST}, - {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_CONST}, - {"Open_table_definitions", (char*) 0, SHOW_TABLE_DEFINITIONS}, - {"Open_tables", (char*) 0, SHOW_OPEN_TABLES}, + {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH}, + {"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH}, + {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH}, + {"Open_table_definitions", (char*) &show_table_definitions, SHOW_FUNC}, + {"Open_tables", (char*) &show_open_tables, SHOW_FUNC}, {"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS}, #ifdef HAVE_QUERY_CACHE - {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_CONST}, - {"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_CONST}, + {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH}, + {"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH}, {"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG}, {"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG}, {"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG}, {"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG}, - {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST}, - {"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_CONST}, + {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_NOFLUSH}, + {"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_NOFLUSH}, #endif /*HAVE_QUERY_CACHE*/ - {"Questions", (char*) 0, SHOW_QUESTION}, - {"Rpl_status", (char*) 0, SHOW_RPL_STATUS}, + {"Questions", (char*) &show_question, SHOW_FUNC}, +#ifdef HAVE_REPLICATION + {"Rpl_status", (char*) &show_rpl_status, SHOW_FUNC}, +#endif {"Select_full_join", (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONG_STATUS}, {"Select_full_range_join", (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONG_STATUS}, {"Select_range", (char*) offsetof(STATUS_VAR, select_range_count), SHOW_LONG_STATUS}, {"Select_range_check", (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONG_STATUS}, {"Select_scan", (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONG_STATUS}, {"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_LONG}, - {"Slave_retried_transactions",(char*) 0, SHOW_SLAVE_RETRIED_TRANS}, - {"Slave_running", (char*) 0, SHOW_SLAVE_RUNNING}, +#ifdef HAVE_REPLICATION + {"Slave_retried_transactions",(char*) &show_slave_retried_trans, SHOW_FUNC}, + {"Slave_running", (char*) &show_slave_running, SHOW_FUNC}, +#endif {"Slow_launch_threads", (char*) &slow_launch_threads, SHOW_LONG}, {"Slow_queries", (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS}, {"Sort_merge_passes", (char*) offsetof(STATUS_VAR, filesort_merge_passes), SHOW_LONG_STATUS}, @@ -6368,29 +6712,29 @@ struct show_var_st status_vars[]= { {"Sort_rows", (char*) offsetof(STATUS_VAR, filesort_rows), SHOW_LONG_STATUS}, {"Sort_scan", (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONG_STATUS}, #ifdef HAVE_OPENSSL - {"Ssl_accept_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE}, - {"Ssl_accepts", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT}, - {"Ssl_callback_cache_hits", (char*) 0, SHOW_SSL_CTX_SESS_CB_HITS}, - {"Ssl_cipher", (char*) 0, SHOW_SSL_GET_CIPHER}, - {"Ssl_cipher_list", (char*) 0, SHOW_SSL_GET_CIPHER_LIST}, - {"Ssl_client_connects", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT}, - {"Ssl_connect_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE}, - {"Ssl_ctx_verify_depth", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_DEPTH}, - {"Ssl_ctx_verify_mode", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_MODE}, - {"Ssl_default_timeout", (char*) 0, SHOW_SSL_GET_DEFAULT_TIMEOUT}, - {"Ssl_finished_accepts", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_GOOD}, - {"Ssl_finished_connects", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT_GOOD}, - {"Ssl_session_cache_hits", (char*) 0, SHOW_SSL_CTX_SESS_HITS}, - {"Ssl_session_cache_misses", (char*) 0, SHOW_SSL_CTX_SESS_MISSES}, - {"Ssl_session_cache_mode", (char*) 0, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE}, - {"Ssl_session_cache_overflows", (char*) 0, SHOW_SSL_CTX_SESS_CACHE_FULL}, - {"Ssl_session_cache_size", (char*) 0, SHOW_SSL_CTX_SESS_GET_CACHE_SIZE}, - {"Ssl_session_cache_timeouts", (char*) 0, SHOW_SSL_CTX_SESS_TIMEOUTS}, - {"Ssl_sessions_reused", (char*) 0, SHOW_SSL_SESSION_REUSED}, - {"Ssl_used_session_cache_entries",(char*) 0, SHOW_SSL_CTX_SESS_NUMBER}, - {"Ssl_verify_depth", (char*) 0, SHOW_SSL_GET_VERIFY_DEPTH}, - {"Ssl_verify_mode", (char*) 0, SHOW_SSL_GET_VERIFY_MODE}, - {"Ssl_version", (char*) 0, SHOW_SSL_GET_VERSION}, + {"Ssl_accept_renegotiates", (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_FUNC}, + {"Ssl_accepts", (char*) &show_ssl_ctx_sess_accept, SHOW_FUNC}, + {"Ssl_callback_cache_hits", (char*) &show_ssl_ctx_sess_cb_hits, SHOW_FUNC}, + {"Ssl_cipher", (char*) &show_ssl_get_cipher, SHOW_FUNC}, + {"Ssl_cipher_list", (char*) &show_ssl_get_cipher_list, SHOW_FUNC}, + {"Ssl_client_connects", (char*) &show_ssl_ctx_sess_connect, SHOW_FUNC}, + {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_FUNC}, + {"Ssl_ctx_verify_depth", (char*) &show_ssl_ctx_get_verify_depth, SHOW_FUNC}, + {"Ssl_ctx_verify_mode", (char*) &show_ssl_ctx_get_verify_mode, SHOW_FUNC}, + {"Ssl_default_timeout", (char*) &show_ssl_get_default_timeout, SHOW_FUNC}, + {"Ssl_finished_accepts", (char*) &show_ssl_ctx_sess_accept_good, SHOW_FUNC}, + {"Ssl_finished_connects", (char*) &show_ssl_ctx_sess_connect_good, SHOW_FUNC}, + {"Ssl_session_cache_hits", (char*) &show_ssl_ctx_sess_hits, SHOW_FUNC}, + {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_FUNC}, + {"Ssl_session_cache_mode", (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_FUNC}, + {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_FUNC}, + {"Ssl_session_cache_size", (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_FUNC}, + {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_FUNC}, + {"Ssl_sessions_reused", (char*) &show_ssl_session_reused, SHOW_FUNC}, + {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_FUNC}, + {"Ssl_verify_depth", (char*) &show_ssl_get_verify_depth, SHOW_FUNC}, + {"Ssl_verify_mode", (char*) &show_ssl_get_verify_mode, SHOW_FUNC}, + {"Ssl_version", (char*) &show_ssl_get_version, SHOW_FUNC}, #endif /* HAVE_OPENSSL */ {"Table_locks_immediate", (char*) &locks_immediate, SHOW_LONG}, {"Table_locks_waited", (char*) &locks_waited, SHOW_LONG}, @@ -6399,11 +6743,11 @@ struct show_var_st status_vars[]= { {"Tc_log_page_size", (char*) &tc_log_page_size, SHOW_LONG}, {"Tc_log_page_waits", (char*) &tc_log_page_waits, SHOW_LONG}, #endif - {"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_CONST}, - {"Threads_connected", (char*) &thread_count, SHOW_INT_CONST}, - {"Threads_created", (char*) &thread_created, SHOW_LONG_CONST}, - {"Threads_running", (char*) &thread_running, SHOW_INT_CONST}, - {"Uptime", (char*) 0, SHOW_STARTTIME}, + {"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_NOFLUSH}, + {"Threads_connected", (char*) &thread_count, SHOW_INT}, + {"Threads_created", (char*) &thread_created, SHOW_LONG_NOFLUSH}, + {"Threads_running", (char*) &thread_running, SHOW_INT}, + {"Uptime", (char*) &show_starttime, SHOW_FUNC}, {NullS, NullS, SHOW_LONG} }; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index f090fac2ecf..7dd694f3411 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6955,6 +6955,7 @@ bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List *fields) /* Create quick select from ref/ref_or_null scan. + SYNOPSIS get_quick_select_for_ref() thd Thread handle @@ -6974,15 +6975,18 @@ bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List *fields) QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref, ha_rows records) { - MEM_ROOT *old_root= thd->mem_root; - /* The following call may change thd->mem_root */ - QUICK_RANGE_SELECT *quick= new QUICK_RANGE_SELECT(thd, table, ref->key, 0); - /* save mem_root set by QUICK_RANGE_SELECT constructor */ - MEM_ROOT *alloc= thd->mem_root; + MEM_ROOT *old_root, *alloc; + QUICK_RANGE_SELECT *quick; KEY *key_info = &table->key_info[ref->key]; KEY_PART *key_part; QUICK_RANGE *range; uint part; + + old_root= thd->mem_root; + /* The following call may change thd->mem_root */ + quick= new QUICK_RANGE_SELECT(thd, table, ref->key, 0); + /* save mem_root set by QUICK_RANGE_SELECT constructor */ + alloc= thd->mem_root; /* return back default mem_root (thd->mem_root) changed by QUICK_RANGE_SELECT constructor diff --git a/sql/parse_file.cc b/sql/parse_file.cc index 0b2bfe83b6f..3cddc879825 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -956,6 +956,6 @@ File_parser_dummy_hook::process_unknown_string(char *&unknown_key, char *end) { DBUG_ENTER("file_parser_dummy_hook::process_unknown_string"); - DBUG_PRINT("info", ("unknown key:%60s", unknown_key)); + DBUG_PRINT("info", ("Unknown key: '%60s'", unknown_key)); DBUG_RETURN(FALSE); } diff --git a/sql/set_var.cc b/sql/set_var.cc index 01ff30045c4..dd4d36bc421 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -623,12 +623,51 @@ sys_var_have_variable sys_have_row_based_replication("have_row_based_replication /* Global read-only variable describing server license */ sys_var_const_str sys_license("license", STRINGIFY_ARG(LICENSE)); +#ifdef HAVE_REPLICATION +static int show_slave_skip_errors(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type=SHOW_CHAR; + var->value= buff; + if (!use_slave_mask || bitmap_is_clear_all(&slave_error_mask)) + { + var->value= "OFF"; + } + else if (bitmap_is_set_all(&slave_error_mask)) + { + var->value= "ALL"; + } + else + { + /* 10 is enough assuming errors are max 4 digits */ + int i; + var->value= buff; + for (i= 1; + i < MAX_SLAVE_ERROR && + (buff - var->value) < SHOW_VAR_FUNC_BUFF_SIZE; + i++) + { + if (bitmap_is_set(&slave_error_mask, i)) + { + buff= int10_to_str(i, buff, 10); + *buff++= ','; + } + } + if (var->value != buff) + buff--; // Remove last ',' + if (i < MAX_SLAVE_ERROR) + buff= strmov(buff, "..."); // Couldn't show all errors + *buff=0; + } + return 0; +} +#endif /* HAVE_REPLICATION */ + /* Variables shown by SHOW variables in alphabetical order */ -struct show_var_st init_vars[]= { +SHOW_VAR init_vars[]= { {"auto_increment_increment", (char*) &sys_auto_increment_increment, SHOW_SYS}, {"auto_increment_offset", (char*) &sys_auto_increment_offset, SHOW_SYS}, {sys_automatic_sp_privileges.name,(char*) &sys_automatic_sp_privileges, SHOW_SYS}, @@ -695,9 +734,9 @@ struct show_var_st init_vars[]= { {sys_have_partition_db.name,(char*) &have_partition_db, SHOW_HAVE}, {sys_have_query_cache.name, (char*) &have_query_cache, SHOW_HAVE}, {sys_have_raid.name, (char*) &have_raid, SHOW_HAVE}, + {sys_have_row_based_replication.name, (char*) &have_row_based_replication, SHOW_HAVE}, {sys_have_rtree_keys.name, (char*) &have_rtree_keys, SHOW_HAVE}, {sys_have_symlink.name, (char*) &have_symlink, SHOW_HAVE}, - {sys_have_row_based_replication.name, (char*) &have_row_based_replication, SHOW_HAVE}, {"init_connect", (char*) &sys_init_connect, SHOW_SYS}, {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR}, {"init_slave", (char*) &sys_init_slave, SHOW_SYS}, @@ -863,7 +902,7 @@ struct show_var_st init_vars[]= { (char*) &sys_slave_compressed_protocol, SHOW_SYS}, {"slave_load_tmpdir", (char*) &slave_load_tmpdir, SHOW_CHAR_PTR}, {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS}, - {"slave_skip_errors", (char*) &slave_error_mask, SHOW_SLAVE_SKIP_ERRORS}, + {"slave_skip_errors", (char*) &show_slave_skip_errors, SHOW_FUNC}, {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries, SHOW_SYS}, #endif {sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS}, diff --git a/sql/sp.cc b/sql/sp.cc index c85c1f2afef..f70e150419a 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -398,14 +398,14 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, const char *body, st_sp_chistics &chistics, const char *definer, longlong created, longlong modified) { - LEX *oldlex= thd->lex, newlex; - sp_rcontext *save_spcont= thd->spcont; + LEX *old_lex= thd->lex, newlex; String defstr; char olddb[128]; bool dbchanged; ulong old_sql_mode= thd->variables.sql_mode; - ha_rows select_limit= thd->variables.select_limit; - int ret= SP_INTERNAL_ERROR; + ha_rows old_select_limit= thd->variables.select_limit; + sp_rcontext *old_spcont= thd->spcont; + int ret; thd->variables.sql_mode= sql_mode; thd->variables.select_limit= HA_POS_ERROR; @@ -421,7 +421,10 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, returns, strlen(returns), body, strlen(body), &chistics)) + { + ret= SP_INTERNAL_ERROR; goto end; + } dbchanged= FALSE; if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb), @@ -450,10 +453,10 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, (*sphp)->optimize(); } end: - thd->spcont= save_spcont; + thd->spcont= old_spcont; thd->variables.sql_mode= old_sql_mode; - thd->variables.select_limit= select_limit; - thd->lex= oldlex; + thd->variables.select_limit= old_select_limit; + thd->lex= old_lex; return ret; } @@ -927,7 +930,6 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, ulong depth= (type == TYPE_ENUM_PROCEDURE ? thd->variables.max_sp_recursion_depth : 0); - DBUG_ENTER("sp_find_routine"); DBUG_PRINT("enter", ("name: %.*s.%.*s, type: %d, cache only %d", name->m_db.length, name->m_db.str, @@ -937,6 +939,11 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, if ((sp= sp_cache_lookup(cp, name))) { ulong level; + sp_head *new_sp; + const char *returns= ""; + char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2]; + String retstr(64); + DBUG_PRINT("info", ("found: 0x%lx", (ulong)sp)); if (sp->m_first_free_instance) { @@ -947,7 +954,7 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, DBUG_ASSERT(!(sp->m_first_free_instance->m_flags & sp_head::IS_INVOKED)); if (sp->m_first_free_instance->m_recursion_level > depth) { - sp->recursion_level_error(); + sp->recursion_level_error(thd); DBUG_RETURN(0); } DBUG_RETURN(sp->m_first_free_instance); @@ -955,37 +962,32 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, level= sp->m_last_cached_sp->m_recursion_level + 1; if (level > depth) { - sp->recursion_level_error(); + sp->recursion_level_error(thd); DBUG_RETURN(0); } + + strxmov(definer, sp->m_definer_user.str, "@", + sp->m_definer_host.str, NullS); + if (type == TYPE_ENUM_FUNCTION) { - sp_head *new_sp; - const char *returns= ""; - char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2]; - String retstr(64); - strxmov(definer, sp->m_definer_user.str, "@", - sp->m_definer_host.str, NullS); - if (type == TYPE_ENUM_FUNCTION) - { - sp_returns_type(thd, retstr, sp); - returns= retstr.ptr(); - } - if (db_load_routine(thd, type, name, &new_sp, - sp->m_sql_mode, sp->m_params.str, returns, - sp->m_body.str, *sp->m_chistics, definer, - sp->m_created, sp->m_modified) == SP_OK) - { - sp->m_last_cached_sp->m_next_cached_sp= new_sp; - new_sp->m_recursion_level= level; - new_sp->m_first_instance= sp; - sp->m_last_cached_sp= sp->m_first_free_instance= new_sp; - DBUG_PRINT("info", ("added level: 0x%lx, level: %lu, flags %x", + sp_returns_type(thd, retstr, sp); + returns= retstr.ptr(); + } + if (db_load_routine(thd, type, name, &new_sp, + sp->m_sql_mode, sp->m_params.str, returns, + sp->m_body.str, *sp->m_chistics, definer, + sp->m_created, sp->m_modified) == SP_OK) + { + sp->m_last_cached_sp->m_next_cached_sp= new_sp; + new_sp->m_recursion_level= level; + new_sp->m_first_instance= sp; + sp->m_last_cached_sp= sp->m_first_free_instance= new_sp; + DBUG_PRINT("info", ("added level: 0x%lx, level: %lu, flags %x", (ulong)new_sp, new_sp->m_recursion_level, new_sp->m_flags)); - DBUG_RETURN(new_sp); - } - DBUG_RETURN(0); + DBUG_RETURN(new_sp); } + DBUG_RETURN(0); } if (!cache_only) { diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 63d1388473e..1d171d929f3 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -24,6 +24,13 @@ #include "sp_rcontext.h" #include "sp_cache.h" +/* + Sufficient max length of printed destinations and frame offsets (all uints). +*/ +#define SP_INSTR_UINT_MAXLEN 8 +#define SP_STMT_PRINT_MAXLEN 40 + + Item_result sp_map_result_type(enum enum_field_types type) { @@ -876,17 +883,17 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) SYNOPSIS sp_head::recursion_level_error() + thd Thread handle NOTE For functions and triggers we return error about prohibited recursion. For stored procedures we return about reaching recursion limit. */ -void sp_head::recursion_level_error() +void sp_head::recursion_level_error(THD *thd) { if (m_type == TYPE_ENUM_PROCEDURE) { - THD *thd= current_thd; my_error(ER_SP_RECURSION_LIMIT, MYF(0), thd->variables.max_sp_recursion_depth, m_name.str); @@ -937,14 +944,15 @@ sp_head::execute(THD *thd) DBUG_ASSERT(!(m_flags & IS_INVOKED)); m_flags|= IS_INVOKED; m_first_instance->m_first_free_instance= m_next_cached_sp; - DBUG_PRINT("info", ("first free for 0x%lx ++: 0x%lx->0x%lx, level: %lu, flags %x", - (ulong)m_first_instance, this, m_next_cached_sp, - (m_next_cached_sp ? - m_next_cached_sp->m_recursion_level : - 0), - (m_next_cached_sp ? - m_next_cached_sp->m_flags : - 0))); + if (m_next_cached_sp) + { + DBUG_PRINT("info", + ("first free for 0x%lx ++: 0x%lx->0x%lx level: %lu flags %x", + (ulong)m_first_instance, (ulong) this, + (ulong) m_next_cached_sp, + m_next_cached_sp->m_recursion_level, + m_next_cached_sp->m_flags)); + } /* Check that if there are not any instances after this one then pointer to the last instance points on this instance or if there are @@ -1112,13 +1120,15 @@ sp_head::execute(THD *thd) state= EXECUTED; done: - DBUG_PRINT("info", ("err_status=%d killed=%d query_error=%d", + DBUG_PRINT("info", ("err_status: %d killed: %d query_error: %d", err_status, thd->killed, thd->query_error)); if (thd->killed) err_status= TRUE; - /* If the DB has changed, the pointer has changed too, but the - original thd->db will then have been freed */ + /* + If the DB has changed, the pointer has changed too, but the + original thd->db will then have been freed + */ if (dbchanged) { /* @@ -1129,10 +1139,11 @@ sp_head::execute(THD *thd) err_status|= mysql_change_db(thd, olddb, 1); } m_flags&= ~IS_INVOKED; - DBUG_PRINT("info", ("first free for 0x%lx --: 0x%lx->0x%lx, level: %lu, flags %x", - (ulong)m_first_instance, - m_first_instance->m_first_free_instance, this, - m_recursion_level, m_flags)); + DBUG_PRINT("info", + ("first free for 0x%lx --: 0x%lx->0x%lx, level: %lu, flags %x", + (ulong) m_first_instance, + (ulong) m_first_instance->m_first_free_instance, + (ulong) this, m_recursion_level, m_flags)); /* Check that we have one of following: @@ -1142,7 +1153,7 @@ sp_head::execute(THD *thd) 2) There are some free instances which mean that first free instance should go just after this one and recursion level of that free instance - should be on 1 more then recursion leven of this instance. + should be on 1 more then recursion level of this instance. */ DBUG_ASSERT((m_first_instance->m_first_free_instance == 0 && this == m_first_instance->m_last_cached_sp && @@ -1756,16 +1767,16 @@ sp_head::set_info(longlong created, longlong modified, void -sp_head::set_definer(char *definer, uint definerlen) + +sp_head::set_definer(const char *definer, uint definerlen) { - char *p= strrchr(definer, '@'); + const char *p= strrchr(definer, '@'); if (!p) { - m_definer_user.str= strmake_root(mem_root, "", 0); + m_definer_user.str= (char*) ""; m_definer_user.length= 0; - - m_definer_host.str= strmake_root(mem_root, "", 0); + m_definer_host.str= (char*) ""; m_definer_host.length= 0; } else @@ -1860,9 +1871,9 @@ sp_head::show_create_procedure(THD *thd) byte *sql_mode_str; ulong sql_mode_len; bool full_access; - DBUG_ENTER("sp_head::show_create_procedure"); DBUG_PRINT("info", ("procedure %s", m_name.str)); + LINT_INIT(sql_mode_str); LINT_INIT(sql_mode_len); @@ -2215,12 +2226,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) DBUG_RETURN(res); } -/* - Sufficient max length of printed destinations and frame offsets (all uints). -*/ -#define SP_INSTR_UINT_MAXLEN 8 -#define SP_STMT_PRINT_MAXLEN 40 void sp_instr_stmt::print(String *str) { @@ -2242,16 +2248,16 @@ sp_instr_stmt::print(String *str) /* Copy the query string and replace '\n' with ' ' in the process */ for (i= 0 ; i < len ; i++) { - if (m_query.str[i] == '\n') - str->qs_append(' '); - else - str->qs_append(m_query.str[i]); + char c= m_query.str[i]; + if (c == '\n') + c= ' '; + str->qs_append(c); } if (m_query.length > SP_STMT_PRINT_MAXLEN) str->qs_append(STRING_WITH_LEN("...")); /* Indicate truncated string */ str->qs_append('"'); } -#undef SP_STMT_PRINT_MAXLEN + int sp_instr_stmt::exec_core(THD *thd, uint *nextp) @@ -2617,6 +2623,7 @@ sp_instr_hpush_jump::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } + void sp_instr_hpush_jump::print(String *str) { @@ -2627,8 +2634,7 @@ sp_instr_hpush_jump::print(String *str) str->qs_append(m_dest); str->qs_append(' '); str->qs_append(m_frame); - switch (m_type) - { + switch (m_type) { case SP_HANDLER_NONE: str->qs_append(STRING_WITH_LEN(" NONE")); // This would be a bug break; @@ -2642,11 +2648,13 @@ sp_instr_hpush_jump::print(String *str) str->qs_append(STRING_WITH_LEN(" UNDO")); break; default: - str->qs_append(STRING_WITH_LEN(" UNKNOWN:")); // This would be a bug as well + // This would be a bug as well + str->qs_append(STRING_WITH_LEN(" UNKNOWN:")); str->qs_append(m_type); } } + uint sp_instr_hpush_jump::opt_mark(sp_head *sp) { diff --git a/sql/sp_head.h b/sql/sp_head.h index d99b600f6b2..ff3cb8eac3e 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -285,7 +285,7 @@ public: void set_info(longlong created, longlong modified, st_sp_chistics *chistics, ulong sql_mode); - void set_definer(char *definer, uint definerlen); + void set_definer(const char *definer, uint definerlen); void reset_thd_mem_root(THD *thd); @@ -294,7 +294,7 @@ public: void optimize(); void opt_mark(uint ip); - void recursion_level_error(); + void recursion_level_error(THD *thd); inline sp_instr * get_instr(uint i) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f24b30729b1..b15320567c2 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2243,14 +2243,14 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, char helping [NAME_LEN*2+USERNAME_LENGTH+3]; uint len; GRANT_NAME *grant_name,*found=0; + HASH_SEARCH_STATE state; len = (uint) (strmov(strmov(strmov(helping,user)+1,db)+1,tname)-helping)+ 1; - for (grant_name=(GRANT_NAME*) hash_search(name_hash, - (byte*) helping, - len) ; + for (grant_name= (GRANT_NAME*) hash_first(name_hash, (byte*) helping, + len, &state); grant_name ; grant_name= (GRANT_NAME*) hash_next(name_hash,(byte*) helping, - len)) + len, &state)) { if (exact) { @@ -3564,7 +3564,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, of other queries). For simple queries first_not_own_table is 0. */ for (i= 0, table= tables; - table && table != first_not_own_table && i < number; + table != first_not_own_table && i < number; table= table->next_global, i++) { /* Remove SHOW_VIEW_ACL, because it will be checked during making view */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c1fad0a9bbf..74a5848fa0a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1702,6 +1702,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, char key[MAX_DBKEY_LENGTH]; uint key_length; char *alias= table_list->alias; + HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); /* find a unused table in the open table cache */ @@ -1862,9 +1863,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (thd->handler_tables) mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE); - for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; + for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length, + &state); table && table->in_use ; - table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length, + &state)) { if (table->s->version != refresh_version) { @@ -2240,10 +2243,12 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock) uint key_length= table->s->table_cache_key.length; DBUG_PRINT("loop", ("table_name: %s", table->alias)); - for (TABLE *search=(TABLE*) hash_search(&open_cache, - (byte*) key,key_length) ; + HASH_SEARCH_STATE state; + for (TABLE *search= (TABLE*) hash_first(&open_cache, (byte*) key, + key_length, &state); search ; - search = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + search= (TABLE*) hash_next(&open_cache, (byte*) key, + key_length, &state)) { DBUG_PRINT("info", ("share: 0x%lx locked_by_flush: %d " "locked_by_name: %d db_stat: %u version: %u", @@ -5848,11 +5853,14 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1; for (;;) { + HASH_SEARCH_STATE state; result= signalled= 0; - for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; + for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length, + &state); table; - table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length, + &state)) { THD *in_use; table->s->version=0L; /* Free when thread is ready */ diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 674c22b9300..aec370e104a 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -3055,6 +3055,7 @@ my_bool Query_cache::move_by_type(byte **border, } case Query_cache_block::TABLE: { + HASH_SEARCH_STATE record_idx; DBUG_PRINT("qcache", ("block 0x%lx TABLE", (ulong) block)); if (*border == 0) break; @@ -3072,7 +3073,7 @@ my_bool Query_cache::move_by_type(byte **border, byte *key; uint key_length; key=query_cache_table_get_key((byte*) block, &key_length, 0); - hash_search(&tables, (byte*) key, key_length); + hash_first(&tables, (byte*) key, key_length, &record_idx); block->destroy(); new_block->init(len); @@ -3106,7 +3107,7 @@ my_bool Query_cache::move_by_type(byte **border, /* Fix pointer to table name */ new_block->table()->table(new_block->table()->db() + tablename_offset); /* Fix hash to point at moved block */ - hash_replace(&tables, tables.current_record, (byte*) new_block); + hash_replace(&tables, &record_idx, (byte*) new_block); DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx", len, (ulong) new_block, (ulong) *border)); @@ -3114,6 +3115,7 @@ my_bool Query_cache::move_by_type(byte **border, } case Query_cache_block::QUERY: { + HASH_SEARCH_STATE record_idx; DBUG_PRINT("qcache", ("block 0x%lx QUERY", (ulong) block)); if (*border == 0) break; @@ -3131,7 +3133,7 @@ my_bool Query_cache::move_by_type(byte **border, byte *key; uint key_length; key=query_cache_query_get_key((byte*) block, &key_length, 0); - hash_search(&queries, (byte*) key, key_length); + hash_first(&queries, (byte*) key, key_length, &record_idx); // Move table of used tables memmove((char*) new_block->table(0), (char*) block->table(0), ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table))); @@ -3199,7 +3201,7 @@ my_bool Query_cache::move_by_type(byte **border, net->query_cache_query= (gptr) new_block; } /* Fix hash to point at moved block */ - hash_replace(&queries, queries.current_record, (byte*) new_block); + hash_replace(&queries, &record_idx, (byte*) new_block); DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx", len, (ulong) new_block, (ulong) *border)); break; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index da01f59e241..2f392f46627 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1976,6 +1976,25 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, backup->client_capabilities= client_capabilities; backup->savepoints= transaction.savepoints; +#ifdef HAVE_ROW_BASED_REPLICATION + /* + For row-based replication and before executing a function/trigger, + the pending rows event has to be flushed. The function/trigger + might execute statement that require the pending event to be + flushed. A simple example: + + CREATE FUNCTION foo() RETURNS INT + BEGIN + SAVEPOINT x; + RETURN 0; + END + + INSERT INTO t1 VALUES (1), (foo()), (2); + */ + if (binlog_row_based) + binlog_flush_pending_rows_event(false); +#endif /* HAVE_ROW_BASED_REPLICATION */ + if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) && !binlog_row_based) options&= ~OPTION_BIN_LOG; @@ -2154,7 +2173,8 @@ THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id, MY_BITMAP const* cols, my_size_t colcnt, my_size_t needed, - bool is_transactional) + bool is_transactional, + RowsEventT *hint __attribute__((unused))) { /* Pre-conditions */ DBUG_ASSERT(table->s->table_map_id != ULONG_MAX); @@ -2219,17 +2239,19 @@ THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id, compiling option. */ template Rows_log_event* -THD::binlog_prepare_pending_rows_event -(TABLE*, uint32, MY_BITMAP const*, my_size_t colcnt, my_size_t, bool); +THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*, + my_size_t, my_size_t, bool, + Write_rows_log_event*); template Rows_log_event* -THD::binlog_prepare_pending_rows_event -(TABLE*, uint32, MY_BITMAP const*, my_size_t colcnt, my_size_t, bool); +THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*, + my_size_t colcnt, my_size_t, bool, + Delete_rows_log_event *); template Rows_log_event* -THD::binlog_prepare_pending_rows_event -(TABLE*, uint32, MY_BITMAP const*, my_size_t colcnt, my_size_t, bool); - +THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*, + my_size_t colcnt, my_size_t, bool, + Update_rows_log_event *); static char const* field_type_name(enum_field_types type) { @@ -2365,9 +2387,10 @@ int THD::binlog_write_row(TABLE* table, bool is_trans, } my_size_t const len= pack_row(table, cols, row_data, record); - Rows_log_event* const - ev= binlog_prepare_pending_rows_event - (table, server_id, cols, colcnt, len, is_trans); + Rows_log_event* const ev= + binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, + len, is_trans, + static_cast(0)); /* add_row_data copies row_data to internal buffer */ error= likely(ev != 0) ? ev->add_row_data(row_data,len) : HA_ERR_OUT_OF_MEM ; @@ -2410,9 +2433,10 @@ int THD::binlog_update_row(TABLE* table, bool is_trans, my_size_t const after_size= pack_row(table, cols, after_row, after_record); - Rows_log_event* const - ev= binlog_prepare_pending_rows_event - (table, server_id, cols, colcnt, before_size + after_size, is_trans); + Rows_log_event* const ev= + binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, + before_size + after_size, is_trans, + static_cast(0)); error= (unlikely(!ev)) || ev->add_row_data(before_row, before_size) || ev->add_row_data(after_row, after_size); @@ -2443,9 +2467,10 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, return HA_ERR_OUT_OF_MEM; my_size_t const len= pack_row(table, cols, row_data, record); - Rows_log_event* const - ev= binlog_prepare_pending_rows_event - (table, server_id, cols, colcnt, len, is_trans); + Rows_log_event* const ev= + binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, + len, is_trans, + static_cast(0)); error= (unlikely(!ev)) || ev->add_row_data(row_data, len); diff --git a/sql/sql_class.h b/sql/sql_class.h index 1ef3322bc8f..c56924774ba 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -922,7 +922,8 @@ public: MY_BITMAP const* cols, my_size_t colcnt, my_size_t needed, - bool is_transactional); + bool is_transactional, + RowsEventT* hint); Rows_log_event* binlog_get_pending_rows_event() const; void binlog_set_pending_rows_event(Rows_log_event* ev); int binlog_setup_trx_data(); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index ba1cce3abfe..7b30b2d4a3d 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -40,7 +40,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ha_rows deleted; uint usable_index= MAX_KEY; SELECT_LEX *select_lex= &thd->lex->select_lex; - bool ha_delete_row_bypassed= 0; + bool ha_delete_all_rows= 0; + ulonglong const saved_options= thd->options; DBUG_ENTER("mysql_delete"); if (open_and_lock_tables(thd, table_list)) @@ -79,17 +80,20 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, !(table->triggers && table->triggers->has_delete_triggers())) { ha_rows const maybe_deleted= table->file->records; + /* + If all rows shall be deleted, we always log this statement-based + (see [binlog], below), so we set this flag and test it below. + */ + ha_delete_all_rows= 1; if (!(error=table->file->delete_all_rows())) { error= -1; // ok deleted= maybe_deleted; - ha_delete_row_bypassed= 1; goto cleanup; } if (error != HA_ERR_WRONG_COMMAND) { table->file->print_error(error,MYF(0)); - ha_delete_row_bypassed= 1; error=0; goto cleanup; } @@ -200,6 +204,15 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, init_ftfuncs(thd, select_lex, 1); thd->proc_info="updating"; will_batch= !table->file->start_bulk_delete(); + + /* + We saved the thread options above before clearing the + OPTION_BIN_LOG, and will restore below, effectively disabling the + binary log (unless it was already disabled, of course). + */ + if (ha_delete_all_rows) + thd->options&= ~static_cast(OPTION_BIN_LOG); + while (!(error=info.read_record(&info)) && !thd->killed && !thd->net.report_error) { @@ -290,6 +303,13 @@ cleanup: delete select; transactional_table= table->file->has_transactions(); + + /* + Restore the saved value of the OPTION_BIN_LOG bit in the thread + options before executing binlog_query() below. + */ + thd->options|= (saved_options & OPTION_BIN_LOG); + /* See similar binlogging code in sql_update.cc, for comments */ if ((error < 0) || (deleted && !transactional_table)) { @@ -299,14 +319,14 @@ cleanup: thd->clear_error(); /* - If 'handler::delete_all_rows()' was called, we replicate - statement-based; otherwise, 'ha_delete_row()' was used to - delete specific rows which we might log row-based. + [binlog]: If 'handler::delete_all_rows()' was called, we + replicate statement-based; otherwise, 'ha_delete_row()' was + used to delete specific rows which we might log row-based. */ THD::enum_binlog_query_type const - query_type(ha_delete_row_bypassed ? - THD::STMT_QUERY_TYPE : - THD::ROW_QUERY_TYPE); + query_type(ha_delete_all_rows ? + THD::STMT_QUERY_TYPE : + THD::ROW_QUERY_TYPE); int log_result= thd->binlog_query(query_type, thd->query, thd->query_length, transactional_table, FALSE); @@ -890,7 +910,9 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) } // Remove the .frm extension - *(path + path_length - reg_ext_length)= '\0'; + // AIX 5.2 64-bit compiler bug (BUG#16155): this crashes, replacement works. + // *(path + path_length - reg_ext_length)= '\0'; + path[path_length - reg_ext_length] = 0; error= ha_create_table(thd, path, table_list->db, table_list->table_name, &create_info, 1); query_cache_invalidate3(thd, table_list, 0); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 6418f844dbe..f1bbf6f0f5e 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -227,6 +227,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) /* add to hash */ if (my_hash_insert(&thd->handler_tables_hash, (byte*) hash_tables)) { + my_free((char*) hash_tables, MYF(0)); mysql_ha_close(thd, tables); goto err; } @@ -369,28 +370,6 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p", hash_tables->db, hash_tables->table_name, hash_tables->alias, table)); - /* Table might have been flushed. */ - if (table && (table->s->version != refresh_version)) - { - /* - We must follow the thd->handler_tables chain, as we need the - address of the 'next' pointer referencing this table - for close_thread_table(). - */ - for (table_ptr= &(thd->handler_tables); - *table_ptr && (*table_ptr != table); - table_ptr= &(*table_ptr)->next) - {} - (*table_ptr)->file->ha_index_or_rnd_end(); - VOID(pthread_mutex_lock(&LOCK_open)); - if (close_thread_table(thd, table_ptr)) - { - /* Tell threads waiting for refresh that something has happened */ - VOID(pthread_cond_broadcast(&COND_refresh)); - } - VOID(pthread_mutex_unlock(&LOCK_open)); - table= hash_tables->table= NULL; - } if (!table) { /* @@ -436,6 +415,13 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, } tables->table=table; + HANDLER_TABLES_HACK(thd); + lock= mysql_lock_tables(thd, &tables->table, 1, 0, ¬_used); + HANDLER_TABLES_HACK(thd); + + if (!lock) + goto err0; // mysql_lock_tables() printed error message already + if (cond && ((!cond->fixed && cond->fix_fields(thd, &cond)) || cond->check_cols(1))) goto err0; @@ -455,13 +441,6 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); - HANDLER_TABLES_HACK(thd); - lock= mysql_lock_tables(thd, &tables->table, 1, 0, ¬_used); - HANDLER_TABLES_HACK(thd); - - if (!lock) - goto err0; // mysql_lock_tables() printed error message already - /* In ::external_lock InnoDB resets the fields which tell it that the handle is used in the HANDLER interface. Tell it again that diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 598fac102c1..29df467b916 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2529,7 +2529,11 @@ select_create::prepare(List &values, SELECT_LEX_UNIT *u) } /* First field to copy */ - field=table->field+table->s->fields - values.elements; + field= table->field+table->s->fields - values.elements; + + /* Mark all fields that are given values */ + for (Field **f= field ; *f ; f++) + (*f)->query_id= thd->query_id; /* Don't set timestamp if used */ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 483a3540e47..1b36ca8dc97 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4856,7 +4856,6 @@ end_with_restore_list: if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION) reset_one_shot_variables(thd); - /* The return value for ROW_COUNT() is "implementation dependent" if the statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC @@ -4868,13 +4867,10 @@ end_with_restore_list: if (lex->sql_command != SQLCOM_CALL && lex->sql_command != SQLCOM_EXECUTE && uc_update_queries[lex->sql_command]<2) thd->row_count_func= -1; - goto cleanup; + DBUG_RETURN(res || thd->net.report_error); error: - res= 1; - -cleanup: - DBUG_RETURN(res || thd->net.report_error); + DBUG_RETURN(1); } @@ -5097,7 +5093,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, the given table list refers to the list for prelocking (contains tables of other queries). For simple queries first_not_own_table is 0. */ - for (; tables && tables != first_not_own_table; tables= tables->next_global) + for (; tables != first_not_own_table; tables= tables->next_global) { if (tables->schema_table && (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL))) @@ -6641,18 +6637,15 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query) static void refresh_status(void) { pthread_mutex_lock(&LOCK_status); - for (struct show_var_st *ptr=status_vars; ptr->name; ptr++) - { - if (ptr->type == SHOW_LONG) + for (SHOW_VAR *ptr= status_vars; ptr->name; ptr++) + if (ptr->type == SHOW_LONG) // note that SHOW_LONG_NOFLUSH variables are not reset *(ulong*) ptr->value= 0; - else if (ptr->type == SHOW_LONG_STATUS) - { - THD *thd= current_thd; - /* We must update the global status before cleaning up the thread */ - add_to_status(&global_status_var, &thd->status_var); - bzero((char*) &thd->status_var, sizeof(thd->status_var)); - } - } + + /* We must update the global status before cleaning up the thread */ + THD *thd= current_thd; + add_to_status(&global_status_var, &thd->status_var); + bzero((char*) &thd->status_var, sizeof(thd->status_var)); + /* Reset the counters of all key caches (default and named). */ process_key_caches(reset_key_cache_counters); pthread_mutex_unlock(&LOCK_status); @@ -7263,7 +7256,7 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) /* Create and initialize. */ - if (! (definer= (LEX_USER*) thd->alloc(sizeof (LEX_USER)))) + if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) return 0; definer->user= *user_name; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 3063f665564..b8628b18dd4 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -29,6 +29,8 @@ LEX_STRING plugin_type_names[]= }; static const char *plugin_interface_version_sym= "_mysql_plugin_interface_version_"; +static const char *sizeof_st_plugin_sym= + "_mysql_sizeof_struct_st_plugin_"; static const char *plugin_declarations_sym= "_mysql_plugin_declarations_"; static int min_plugin_interface_version= 0x0000; /* Note that 'int version' must be the first field of every plugin @@ -90,6 +92,14 @@ static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl) struct st_plugin_dl *)); } +static inline void free_plugin_mem(struct st_plugin_dl *p) +{ + if (p->handle) + dlclose(p->handle); + my_free(p->dl.str, MYF(MY_ALLOW_ZERO_PTR)); + if (p->version != MYSQL_PLUGIN_INTERFACE_VERSION) + my_free((gptr)p->plugins, MYF(MY_ALLOW_ZERO_PTR)); +} static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) { @@ -121,6 +131,7 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) tmp->ref_count++; DBUG_RETURN(tmp); } + bzero(&plugin_dl, sizeof(plugin_dl)); /* Compile dll path */ strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NullS); plugin_dl.ref_count= 1; @@ -136,7 +147,7 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) /* Determine interface version */ if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym))) { - dlclose(plugin_dl.handle); + free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_interface_version_sym); if (report & REPORT_TO_LOG) @@ -148,7 +159,7 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) if (plugin_dl.version < min_plugin_interface_version || (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8)) { - dlclose(plugin_dl.handle); + free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, 0, "plugin interface version mismatch"); @@ -160,19 +171,76 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) /* Find plugin declarations */ if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym))) { - dlclose(plugin_dl.handle); + free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym); if (report & REPORT_TO_LOG) sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym); DBUG_RETURN(0); } + + if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION) + { + int i, sizeof_st_plugin; + struct st_mysql_plugin *old, *cur; + char *ptr= (char *)sym; + + if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym))) + sizeof_st_plugin= *(int *)sym; + else + { +#ifdef ERROR_ON_NO_SIZEOF_PLUGIN_SYMBOL + free_plugin_mem(&plugin_dl); + if (report & REPORT_TO_USER) + my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), sizeof_st_plugin_sym); + if (report & REPORT_TO_LOG) + sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), sizeof_st_plugin_sym); + DBUG_RETURN(0); +#else + /* + When the following assert starts failing, we'll have to switch + to the upper branch of the #ifdef + */ + DBUG_ASSERT(min_plugin_interface_version == 0); + sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version); +#endif + } + + for (i= 0; + ((struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info; + i++) + /* no op */; + + cur= (struct st_mysql_plugin*) + my_malloc(i*sizeof(struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME)); + if (!cur) + { + free_plugin_mem(&plugin_dl); + if (report & REPORT_TO_USER) + my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length); + if (report & REPORT_TO_LOG) + sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length); + DBUG_RETURN(0); + } + /* + All st_plugin fields not initialized in the plugin explicitly, are + set to 0. It matches C standard behaviour for struct initializers that + have less values than the struct definition. + */ + for (i=0; + (old=(struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info; + i++) + memcpy(cur+i, old, min(sizeof(cur[i]), sizeof_st_plugin)); + + sym= cur; + } plugin_dl.plugins= (struct st_mysql_plugin *)sym; + /* Duplicate and convert dll name */ plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1; if (! (plugin_dl.dl.str= my_malloc(plugin_dl.dl.length, MYF(0)))) { - dlclose(plugin_dl.handle); + free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length); if (report & REPORT_TO_LOG) @@ -186,8 +254,7 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) /* Add this dll to array */ if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl))) { - dlclose(plugin_dl.handle); - my_free(plugin_dl.dl.str, MYF(0)); + free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl)); if (report & REPORT_TO_LOG) @@ -223,8 +290,7 @@ static void plugin_dl_del(LEX_STRING *dl) /* Do not remove this element, unless no other plugin uses this dll. */ if (! --tmp->ref_count) { - dlclose(tmp->handle); - my_free(tmp->dl.str, MYF(0)); + free_plugin_mem(tmp); bzero(tmp, sizeof(struct st_plugin_dl)); } break; @@ -247,7 +313,7 @@ static struct st_plugin_int *plugin_find_internal(LEX_STRING *name, int type) { struct st_plugin_int *plugin= (st_plugin_int *) hash_search(&plugin_hash[i], (const byte *)name->str, name->length); - if (plugin) + if (plugin) DBUG_RETURN(plugin); } } @@ -309,7 +375,6 @@ static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin) struct st_plugin_int *)); } - static my_bool plugin_add(LEX_STRING *name, LEX_STRING *dl, int report) { struct st_plugin_int tmp; @@ -356,21 +421,20 @@ static my_bool plugin_add(LEX_STRING *name, LEX_STRING *dl, int report) tmp.name.length= name_len; tmp.ref_count= 0; tmp.state= PLUGIN_IS_UNINITIALIZED; - if (! (tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) + if (plugin->status_vars) { - if (report & REPORT_TO_USER) - my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_int)); - if (report & REPORT_TO_LOG) - sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_int)); - goto err; + SHOW_VAR array[2]= { + {plugin->name, (char*)plugin->status_vars, SHOW_ARRAY}, + {0, 0, SHOW_UNDEF} + }; + if (add_status_vars(array)) // add_status_vars makes a copy + goto err; } + if (! (tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) + goto err; if (my_hash_insert(&plugin_hash[plugin->type], (byte*)tmp_plugin_ptr)) { tmp_plugin_ptr->state= PLUGIN_IS_FREED; - if (report & REPORT_TO_USER) - my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_int)); - if (report & REPORT_TO_LOG) - sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_int)); goto err; } DBUG_RETURN(FALSE); @@ -381,6 +445,14 @@ static my_bool plugin_add(LEX_STRING *name, LEX_STRING *dl, int report) if (report & REPORT_TO_LOG) sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str); err: + if (plugin->status_vars) + { + SHOW_VAR array[2]= { + {plugin->name, (char*)plugin->status_vars, SHOW_ARRAY}, + {0, 0, SHOW_UNDEF} + }; + remove_status_vars(array); + } plugin_dl_del(dl); DBUG_RETURN(TRUE); } @@ -393,6 +465,14 @@ static void plugin_del(LEX_STRING *name) DBUG_ENTER("plugin_del"); if ((plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN))) { + if (plugin->plugin->status_vars) + { + SHOW_VAR array[2]= { + {plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY}, + {0, 0, SHOW_UNDEF} + }; + remove_status_vars(array); + } hash_delete(&plugin_hash[plugin->plugin->type], (byte*)plugin); plugin_dl_del(&plugin->plugin_dl->dl); plugin->state= PLUGIN_IS_FREED; @@ -421,7 +501,7 @@ void plugin_unlock(struct st_plugin_int *plugin) static int plugin_initialize(struct st_plugin_int *plugin) { DBUG_ENTER("plugin_initialize"); - + if (plugin->plugin->init) { if (plugin->plugin->init()) @@ -433,7 +513,7 @@ static int plugin_initialize(struct st_plugin_int *plugin) goto err; } } - + switch (plugin->plugin->type) { case MYSQL_STORAGE_ENGINE_PLUGIN: @@ -532,11 +612,11 @@ int plugin_init(void) get_hash_key, NULL, 0)) goto err; } - + initialized= 1; DBUG_RETURN(0); - + err: DBUG_RETURN(1); } @@ -578,9 +658,9 @@ void plugin_load(void) MEM_ROOT mem; THD *new_thd; DBUG_ENTER("plugin_load"); - + DBUG_ASSERT(initialized); - + if (!(new_thd= new THD)) { sql_print_error("Can't allocate memory for plugin structures"); @@ -643,13 +723,7 @@ void plugin_free(void) { struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *); -#ifdef HAVE_DLOPEN - if (tmp->handle) - { - dlclose(tmp->handle); - my_free(tmp->dl.str, MYF(0)); - } -#endif + free_plugin_mem(tmp); } delete_dynamic(&plugin_dl_array); if (initialized) @@ -674,7 +748,7 @@ my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl) tables.table_name= tables.alias= (char *)"plugin"; if (check_table_access(thd, INSERT_ACL, &tables, 0)) DBUG_RETURN(TRUE); - + /* need to open before acquiring THR_LOCK_plugin or it will deadlock */ if (! (table = open_ltable(thd, &tables, TL_WRITE))) DBUG_RETURN(TRUE); @@ -683,7 +757,7 @@ my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl) if (plugin_add(name, dl, REPORT_TO_USER)) goto err; tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN); - + if (plugin_initialize(tmp)) { my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str, @@ -702,7 +776,7 @@ my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl) table->file->print_error(error, MYF(0)); goto deinit; } - + rw_unlock(&THR_LOCK_plugin); DBUG_RETURN(FALSE); deinit: @@ -743,7 +817,7 @@ my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name) my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str); goto err; } - + if (plugin->ref_count) { plugin->state= PLUGIN_IS_DELETED; @@ -786,13 +860,13 @@ my_bool plugin_foreach(THD *thd, plugin_foreach_func *func, struct st_plugin_int *plugin; DBUG_ENTER("mysql_uninstall_plugin"); rw_rdlock(&THR_LOCK_plugin); - + if (type == MYSQL_ANY_PLUGIN) { for (idx= 0; idx < plugin_array.elements; idx++) { plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *); - + /* FREED records may have garbage pointers */ if ((plugin->state != PLUGIN_IS_FREED) && func(thd, plugin, arg)) diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index f0b70ca9d26..ce06334ffd7 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -17,7 +17,17 @@ #ifndef _sql_plugin_h #define _sql_plugin_h +/* + the following #define adds server-only members to enum_mysql_show_type, + that is defined in plugin.h +*/ +#define SHOW_FUNC SHOW_FUNC, SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_LONGLONG, \ + SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, SHOW_HAVE, \ + SHOW_HA_ROWS, SHOW_SYS, SHOW_LONG_NOFLUSH #include +#undef SHOW_FUNC +typedef enum enum_mysql_show_type SHOW_TYPE; +typedef struct st_mysql_show_var SHOW_VAR; #define MYSQL_ANY_PLUGIN -1 @@ -65,7 +75,7 @@ extern my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name); extern my_bool plugin_register_builtin(struct st_mysql_plugin *plugin); -typedef my_bool (plugin_foreach_func)(THD *thd, +typedef my_bool (plugin_foreach_func)(THD *thd, st_plugin_int *plugin, void *arg); extern my_bool plugin_foreach(THD *thd, plugin_foreach_func *func, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d5a38b13a0e..8c954297f42 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10772,7 +10772,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), item->save_org_in_field(group->field); /* Store in the used key if the field was 0 */ if (item->maybe_null) - group->buff[-1]=item->null_value ? 1 : 0; + group->buff[-1]= (char) group->field->is_null(); } if (!table->file->index_read(table->record[1], join->tmp_table_param.group_buff,0, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 705ebb4aef3..c1165f2c4b5 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1516,42 +1516,207 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) Status functions *****************************************************************************/ +static DYNAMIC_ARRAY all_status_vars; +static bool status_vars_inited= 0; +static int show_var_cmp(const void *var1, const void *var2) +{ + return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name); +} + +/* + deletes all the SHOW_UNDEF elements from the array and calls + delete_dynamic() if it's completely empty. +*/ +static void shrink_var_array(DYNAMIC_ARRAY *array) +{ + int a,b; + SHOW_VAR *all= dynamic_element(array, 0, SHOW_VAR *); + + for (a= b= 0; b < array->elements; b++) + if (all[b].type != SHOW_UNDEF) + all[a++]= all[b]; + if (a) + { + bzero(all+a, sizeof(SHOW_VAR)); // writing NULL-element to the end + array->elements= a; + } + else // array is completely empty - delete it + delete_dynamic(array); +} + +/* + Adds an array of SHOW_VAR entries to the output of SHOW STATUS + + SYNOPSIS + add_status_vars(SHOW_VAR *list) + list - an array of SHOW_VAR entries to add to all_status_vars + the last entry must be {0,0,SHOW_UNDEF} + + NOTE + The handling of all_status_vars[] is completely internal, it's allocated + automatically when something is added to it, and deleted completely when + the last entry is removed. + + As a special optimization, if add_status_vars() is called before + init_status_vars(), it assumes "startup mode" - neither concurrent access + to the array nor SHOW STATUS are possible (thus it skips locks and qsort) + + The last entry of the all_status_vars[] should always be {0,0,SHOW_UNDEF} +*/ +int add_status_vars(SHOW_VAR *list) +{ + int res= 0; + if (status_vars_inited) + pthread_mutex_lock(&LOCK_status); + if (!all_status_vars.buffer && // array is not allocated yet - do it now + my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20)) + { + res= 1; + goto err; + } + while (list->name) + res|= insert_dynamic(&all_status_vars, (gptr)list++); + res|= insert_dynamic(&all_status_vars, (gptr)list); // appending NULL-element + all_status_vars.elements--; // but next insert_dynamic should overwite it + if (status_vars_inited) + sort_dynamic(&all_status_vars, show_var_cmp); +err: + if (status_vars_inited) + pthread_mutex_unlock(&LOCK_status); + return res; +} + +/* + Make all_status_vars[] usable for SHOW STATUS + + NOTE + See add_status_vars(). Before init_status_vars() call, add_status_vars() + works in a special fast "startup" mode. Thus init_status_vars() + should be called as late as possible but before enabling multi-threading. +*/ +void init_status_vars() +{ + status_vars_inited=1; + sort_dynamic(&all_status_vars, show_var_cmp); +} + +/* + catch-all cleanup function, cleans up everything no matter what + + DESCRIPTION + This function is not strictly required if all add_to_status/ + remove_status_vars are properly paired, but it's a safety measure that + deletes everything from the all_status_vars[] even if some + remove_status_vars were forgotten +*/ +void free_status_vars() +{ + delete_dynamic(&all_status_vars); +} + +/* + Removes an array of SHOW_VAR entries from the output of SHOW STATUS + + SYNOPSIS + remove_status_vars(SHOW_VAR *list) + list - an array of SHOW_VAR entries to remove to all_status_vars + the last entry must be {0,0,SHOW_UNDEF} + + NOTE + there's lots of room for optimizing this, especially in non-sorted mode, + but nobody cares - it may be called only in case of failed plugin + initialization in the mysqld startup. + +*/ +void remove_status_vars(SHOW_VAR *list) +{ + if (status_vars_inited) + { + pthread_mutex_lock(&LOCK_status); + SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *); + int a= 0, b= all_status_vars.elements, c= (a+b)/2, res; + + for (; list->name; list++) + { + for (a= 0, b= all_status_vars.elements; b-a > 1; c= (a+b)/2) + { + res= show_var_cmp(list, all+c); + if (res < 0) + b= c; + else if (res > 0) + a= c; + else break; + } + if (res == 0) + all[c].type= SHOW_UNDEF; + } + shrink_var_array(&all_status_vars); + pthread_mutex_unlock(&LOCK_status); + } + else + { + SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *); + int i; + for (; list->name; list++) + { + for (i= 0; i < all_status_vars.elements; i++) + { + if (show_var_cmp(list, all+i)) + continue; + all[i].type= SHOW_UNDEF; + break; + } + } + shrink_var_array(&all_status_vars); + } +} static bool show_status_array(THD *thd, const char *wild, - show_var_st *variables, + SHOW_VAR *variables, enum enum_var_type value_type, struct system_status_var *status_var, const char *prefix, TABLE *table) { - char buff[1024], *prefix_end; + char buff[SHOW_VAR_FUNC_BUFF_SIZE], *prefix_end; /* the variable name should not be longer then 80 characters */ char name_buffer[80]; int len; LEX_STRING null_lex_str; + SHOW_VAR tmp, *var; DBUG_ENTER("show_status_array"); null_lex_str.str= 0; // For sys_var->value_ptr() null_lex_str.length= 0; prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1); + if (*prefix) + *prefix_end++= '_'; len=name_buffer + sizeof(name_buffer) - prefix_end; for (; variables->name; variables++) { strnmov(prefix_end, variables->name, len); name_buffer[sizeof(name_buffer)-1]=0; /* Safety */ - SHOW_TYPE show_type=variables->type; - if (show_type == SHOW_VARS) + + /* + if var->type is SHOW_FUNC, call the function. + Repeat as necessary, if new var is again SHOW_FUNC + */ + for (var=variables; var->type == SHOW_FUNC; var= &tmp) + ((mysql_show_var_func)(var->value))(thd, &tmp, buff); + + SHOW_TYPE show_type=var->type; + if (show_type == SHOW_ARRAY) { - show_status_array(thd, wild, (show_var_st *) variables->value, - value_type, status_var, variables->name, table); + show_status_array(thd, wild, (SHOW_VAR *) var->value, + value_type, status_var, name_buffer, table); } else { if (!(wild && wild[0] && wild_case_compare(system_charset_info, name_buffer, wild))) { - char *value=variables->value; + char *value=var->value; const char *pos, *end; // We assign a lot of const's long nr; if (show_type == SHOW_SYS) @@ -1562,13 +1727,22 @@ static bool show_status_array(THD *thd, const char *wild, } pos= end= buff; + /* + note that value may be == buff. All SHOW_xxx code below + should still work in this case + */ switch (show_type) { + case SHOW_DOUBLE_STATUS: + { + value= ((char *) status_var + (ulong) value); + end= buff + sprintf(buff, "%f", *(double*) value); + break; + } case SHOW_LONG_STATUS: - case SHOW_LONG_CONST_STATUS: value= ((char *) status_var + (ulong) value); /* fall through */ case SHOW_LONG: - case SHOW_LONG_CONST: + case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status() end= int10_to_str(*(long*) value, buff, 10); break; case SHOW_LONGLONG: @@ -1583,7 +1757,6 @@ static bool show_status_array(THD *thd, const char *wild, case SHOW_MY_BOOL: end= strmov(buff, *(my_bool*) value ? "ON" : "OFF"); break; - case SHOW_INT_CONST: case SHOW_INT: end= int10_to_str((long) *(uint32*) value, buff, 10); break; @@ -1601,80 +1774,6 @@ static bool show_status_array(THD *thd, const char *wild, end= strend(pos); break; } - case SHOW_STARTTIME: - nr= (long) (thd->query_start() - start_time); - end= int10_to_str(nr, buff, 10); - break; - case SHOW_QUESTION: - end= int10_to_str((long) thd->query_id, buff, 10); - break; -#ifdef HAVE_REPLICATION - case SHOW_RPL_STATUS: - end= strmov(buff, rpl_status_type[(int)rpl_status]); - break; - case SHOW_SLAVE_RUNNING: - { - pthread_mutex_lock(&LOCK_active_mi); - end= strmov(buff, (active_mi && active_mi->slave_running && - active_mi->rli.slave_running) ? "ON" : "OFF"); - pthread_mutex_unlock(&LOCK_active_mi); - break; - } - case SHOW_SLAVE_RETRIED_TRANS: - { - /* - TODO: in 5.1 with multimaster, have one such counter per line in - SHOW SLAVE STATUS, and have the sum over all lines here. - */ - pthread_mutex_lock(&LOCK_active_mi); - if (active_mi) - { - pthread_mutex_lock(&active_mi->rli.data_lock); - end= int10_to_str(active_mi->rli.retried_trans, buff, 10); - pthread_mutex_unlock(&active_mi->rli.data_lock); - } - pthread_mutex_unlock(&LOCK_active_mi); - break; - } - case SHOW_SLAVE_SKIP_ERRORS: - { - MY_BITMAP *bitmap= (MY_BITMAP *)value; - if (!use_slave_mask || bitmap_is_clear_all(bitmap)) - { - end= strmov(buff, "OFF"); - } - else if (bitmap_is_set_all(bitmap)) - { - end= strmov(buff, "ALL"); - } - else - { - /* 10 is enough assuming errors are max 4 digits */ - int i; - for (i= 1; - i < MAX_SLAVE_ERROR && (uint) (end-buff) < sizeof(buff)-10; - i++) - { - if (bitmap_is_set(bitmap, i)) - { - end= int10_to_str(i, (char*) end, 10); - *(char*) end++= ','; - } - } - if (end != buff) - end--; // Remove last ',' - if (i < MAX_SLAVE_ERROR) - end= strmov((char*) end, "..."); // Couldn't show all errors - } - break; - } -#endif /* HAVE_REPLICATION */ - case SHOW_OPEN_TABLES: - end= int10_to_str((long) cached_open_tables(), buff, 10); - break; - case SHOW_TABLE_DEFINITIONS: - end= int10_to_str((long) cached_table_definitions(), buff, 10); - break; case SHOW_CHAR_PTR: { if (!(pos= *(char**) value)) @@ -1682,203 +1781,19 @@ static bool show_status_array(THD *thd, const char *wild, end= strend(pos); break; } - case SHOW_DOUBLE_STATUS: - { - value= ((char *) status_var + (ulong) value); - end= buff + sprintf(buff, "%f", *(double*) value); - break; - } -#ifdef HAVE_OPENSSL - /* First group - functions relying on CTX */ - case SHOW_SSL_CTX_SESS_ACCEPT: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_ACCEPT_GOOD: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept_good(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_CONNECT_GOOD: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect_good(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_CB_HITS: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_cb_hits(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_HITS: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_hits(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_CACHE_FULL: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_cache_full(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_MISSES: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_misses(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_TIMEOUTS: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_SESS_NUMBER: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_SESS_CONNECT: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_GET_VERIFY_MODE: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_GET_VERIFY_DEPTH: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE: - if (!ssl_acceptor_fd) - { - pos= "NONE"; - end= pos+4; - break; - } - switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context)) - { - case SSL_SESS_CACHE_OFF: - pos= "OFF"; - break; - case SSL_SESS_CACHE_CLIENT: - pos= "CLIENT"; - break; - case SSL_SESS_CACHE_SERVER: - pos= "SERVER"; - break; - case SSL_SESS_CACHE_BOTH: - pos= "BOTH"; - break; - case SSL_SESS_CACHE_NO_AUTO_CLEAR: - pos= "NO_AUTO_CLEAR"; - break; - case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP: - pos= "NO_INTERNAL_LOOKUP"; - break; - default: - pos= "Unknown"; - break; - } - end= strend(pos); - break; - /* First group - functions relying on SSL */ - case SHOW_SSL_GET_VERSION: - pos= (thd->net.vio->ssl_arg ? - SSL_get_version((SSL*) thd->net.vio->ssl_arg) : ""); - end= strend(pos); - break; - case SHOW_SSL_SESSION_REUSED: - end= int10_to_str((long) (thd->net.vio->ssl_arg ? - SSL_session_reused((SSL*) thd->net.vio-> - ssl_arg) : - 0), - buff, 10); - break; - case SHOW_SSL_GET_DEFAULT_TIMEOUT: - end= int10_to_str((long) (thd->net.vio->ssl_arg ? - SSL_get_default_timeout((SSL*) thd->net.vio-> - ssl_arg) : - 0), - buff, 10); - break; - case SHOW_SSL_GET_VERIFY_MODE: - end= int10_to_str((long) (thd->net.vio->ssl_arg ? - SSL_get_verify_mode((SSL*) thd->net.vio-> - ssl_arg): - 0), - buff, 10); - break; - case SHOW_SSL_GET_VERIFY_DEPTH: - end= int10_to_str((long) (thd->net.vio->ssl_arg ? - SSL_get_verify_depth((SSL*) thd->net.vio-> - ssl_arg): - 0), - buff, 10); - break; - case SHOW_SSL_GET_CIPHER: - pos= (thd->net.vio->ssl_arg ? - SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" ); - end= strend(pos); - break; - case SHOW_SSL_GET_CIPHER_LIST: - if (thd->net.vio->ssl_arg) - { - char *to= buff; - for (int i=0 ; i++ ;) - { - const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i); - if (p == NULL) - break; - to= strmov(to, p); - *to++= ':'; - } - if (to != buff) - to--; // Remove last ':' - end= to; - } - break; - -#endif /* HAVE_OPENSSL */ case SHOW_KEY_CACHE_LONG: - case SHOW_KEY_CACHE_CONST_LONG: - value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache; + value= (char*) dflt_key_cache + (ulong)value; end= int10_to_str(*(long*) value, buff, 10); break; case SHOW_KEY_CACHE_LONGLONG: - value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache; + value= (char*) dflt_key_cache + (ulong)value; end= longlong10_to_str(*(longlong*) value, buff, 10); break; - case SHOW_NET_COMPRESSION: - end= strmov(buff, thd->net.compress ? "ON" : "OFF"); - break; - case SHOW_UNDEF: // Show never happen - case SHOW_SYS: - break; // Return empty string + case SHOW_UNDEF: + break; // Return empty string + case SHOW_SYS: // Cannot happen default: + DBUG_ASSERT(0); break; } restore_record(table, s->default_values); @@ -2238,6 +2153,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) int error= 1; enum legacy_db_type not_used; Open_tables_state open_tables_state_backup; + bool save_view_prepare_mode= lex->view_prepare_mode; + lex->view_prepare_mode= TRUE; DBUG_ENTER("get_all_tables"); LINT_INIT(end); @@ -2423,6 +2340,7 @@ err: lex->derived_tables= derived_tables; lex->all_selects_list= old_all_select_lex; lex->query_tables_last= save_query_tables_last; + lex->view_prepare_mode= save_view_prepare_mode; *save_query_tables_last= 0; lex->sql_command= save_sql_command; DBUG_RETURN(error); @@ -3601,7 +3519,7 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) LEX *lex= thd->lex; const char *wild= lex->wild ? lex->wild->ptr() : NullS; pthread_mutex_lock(&LOCK_global_system_variables); - res= show_status_array(thd, wild, init_vars, + res= show_status_array(thd, wild, init_vars, lex->option_type, 0, "", tables->table); pthread_mutex_unlock(&LOCK_global_system_variables); DBUG_RETURN(res); @@ -3615,12 +3533,13 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) const char *wild= lex->wild ? lex->wild->ptr() : NullS; int res= 0; STATUS_VAR tmp; - ha_update_statistics(); /* Export engines statistics */ pthread_mutex_lock(&LOCK_status); if (lex->option_type == OPT_GLOBAL) calc_sum_of_all_status(&tmp); - res= show_status_array(thd, wild, status_vars, OPT_GLOBAL, - (lex->option_type == OPT_GLOBAL ? + res= show_status_array(thd, wild, + (SHOW_VAR *)all_status_vars.buffer, + OPT_GLOBAL, + (lex->option_type == OPT_GLOBAL ? &tmp: &thd->status_var), "",tables->table); pthread_mutex_unlock(&LOCK_status); DBUG_RETURN(res); @@ -4391,7 +4310,7 @@ ST_FIELD_INFO plugin_fields_info[]= {"PLUGIN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"}, {"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0}, {"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status"}, - {"PLUGIN_TYPE", 10, MYSQL_TYPE_STRING, 0, 0, "Type"}, + {"PLUGIN_TYPE", 80, MYSQL_TYPE_STRING, 0, 0, "Type"}, {"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0}, {"PLUGIN_LIBRARY", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Library"}, {"PLUGIN_LIBRARY_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0}, diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 2b124fb5bb4..e4b22cffca0 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -51,6 +51,13 @@ static File_option triggers_file_parameters[]= { { 0, 0 }, 0, FILE_OPTIONS_STRING } }; +File_option sql_modes_parameters= +{ + {(char*) STRING_WITH_LEN("sql_modes") }, + offsetof(class Table_triggers_list, definition_modes_list), + FILE_OPTIONS_ULLLIST +}; + /* This must be kept up to date whenever a new option is added to the list above, as it specifies the number of required parameters of the trigger in @@ -435,7 +442,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!is_acl_user(lex->definer->host.str, - lex->definer->user.str)) + lex->definer->user.str)) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, @@ -1161,7 +1168,7 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event, if (is_special_var_used(event, time_type)) { - TABLE_LIST table_list; + TABLE_LIST table_list, **save_query_tables_own_last; bzero((char *) &table_list, sizeof (table_list)); table_list.db= (char *) table->s->db.str; table_list.db_length= table->s->db.length; @@ -1169,8 +1176,13 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event, table_list.table_name_length= table->s->table_name.length; table_list.alias= (char *) table->alias; table_list.table= table; + save_query_tables_own_last= thd->lex->query_tables_own_last; + thd->lex->query_tables_own_last= 0; - if (check_table_access(thd, SELECT_ACL | UPDATE_ACL, &table_list, 0)) + err_status= check_table_access(thd, SELECT_ACL | UPDATE_ACL, + &table_list, 0); + thd->lex->query_tables_own_last= save_query_tables_own_last; + if (err_status) { sp_restore_security_context(thd, save_ctx); return TRUE; @@ -1212,32 +1224,29 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event, TRUE Error */ +#define INVALID_SQL_MODES_LENGTH 13 + bool Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key, gptr base, MEM_ROOT *mem_root, char *end) { -#define INVALID_SQL_MODES_LENGTH 13 DBUG_ENTER("handle_old_incorrect_sql_modes"); DBUG_PRINT("info", ("unknown key:%60s", unknown_key)); + if (unknown_key + INVALID_SQL_MODES_LENGTH + 1 < end && unknown_key[INVALID_SQL_MODES_LENGTH] == '=' && !memcmp(unknown_key, STRING_WITH_LEN("sql_modes"))) { + char *ptr= unknown_key + INVALID_SQL_MODES_LENGTH + 1; + DBUG_PRINT("info", ("sql_modes affected by BUG#14090 detected")); push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_OLD_FILE_FORMAT, ER(ER_OLD_FILE_FORMAT), (char *)path, "TRIGGER"); - File_option sql_modes_parameters= - { - {(char *) STRING_WITH_LEN("sql_modes") }, - offsetof(class Table_triggers_list, definition_modes_list), - FILE_OPTIONS_ULLLIST - }; - char *ptr= unknown_key + INVALID_SQL_MODES_LENGTH + 1; if (get_file_options_ulllist(ptr, end, unknown_key, base, &sql_modes_parameters, mem_root)) { diff --git a/sql/structs.h b/sql/structs.h index 85af73794ae..e369d8ed7e8 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -169,54 +169,16 @@ typedef struct st_known_date_time_format { const char *time_format; } KNOWN_DATE_TIME_FORMAT; - -enum SHOW_TYPE -{ - SHOW_UNDEF, - SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, - SHOW_DOUBLE_STATUS, SHOW_BOOL, SHOW_MY_BOOL, - SHOW_OPEN_TABLES, SHOW_TABLE_DEFINITIONS, SHOW_STARTTIME, SHOW_QUESTION, - SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS, - SHOW_VARS, -#ifdef HAVE_OPENSSL - SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD, - SHOW_SSL_GET_VERSION, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE, - SHOW_SSL_CTX_SESS_CB_HITS, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE, - SHOW_SSL_CTX_SESS_NUMBER, SHOW_SSL_SESSION_REUSED, - SHOW_SSL_CTX_SESS_GET_CACHE_SIZE, SHOW_SSL_GET_CIPHER, - SHOW_SSL_GET_DEFAULT_TIMEOUT, SHOW_SSL_GET_VERIFY_MODE, - SHOW_SSL_CTX_GET_VERIFY_MODE, SHOW_SSL_GET_VERIFY_DEPTH, - SHOW_SSL_CTX_GET_VERIFY_DEPTH, SHOW_SSL_CTX_SESS_CONNECT, - SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE, SHOW_SSL_CTX_SESS_CONNECT_GOOD, - SHOW_SSL_CTX_SESS_HITS, SHOW_SSL_CTX_SESS_MISSES, - SHOW_SSL_CTX_SESS_TIMEOUTS, SHOW_SSL_CTX_SESS_CACHE_FULL, - SHOW_SSL_GET_CIPHER_LIST, -#endif /* HAVE_OPENSSL */ - SHOW_NET_COMPRESSION, - SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING, SHOW_SLAVE_RETRIED_TRANS, - SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_CONST_LONG, SHOW_KEY_CACHE_LONGLONG, - SHOW_LONG_STATUS, SHOW_LONG_CONST_STATUS, SHOW_SLAVE_SKIP_ERRORS -}; - enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED}; extern const char *show_comp_option_name[]; -typedef int *(*update_var)(THD *, struct show_var_st *); - - -typedef struct show_var_st { - const char *name; - char *value; - SHOW_TYPE type; -} SHOW_VAR; - +typedef int *(*update_var)(THD *, struct st_mysql_show_var *); typedef struct st_lex_user { LEX_STRING user, host, password; } LEX_USER; - /* This structure specifies the maximum amount of resources which can be consumed by each account. Zero value of a member means diff --git a/storage/csv/Makefile.am b/storage/csv/Makefile.am index 1d3c47bd650..f1802f4e5b0 100644 --- a/storage/csv/Makefile.am +++ b/storage/csv/Makefile.am @@ -29,6 +29,7 @@ WRAPLIBS= pkglib_LTLIBRARIES = ha_csv.la ha_csv_la_LDFLAGS = -module +noinst_HEADERS = ha_tina.h ha_csv_la_SOURCES = ha_tina.cc LDADD = diff --git a/storage/example/Makefile.am b/storage/example/Makefile.am index d5896946c5b..efc0ede91e9 100644 --- a/storage/example/Makefile.am +++ b/storage/example/Makefile.am @@ -29,6 +29,7 @@ WRAPLIBS= pkglib_LTLIBRARIES = ha_example.la ha_example_la_LDFLAGS = -module +noinst_HEADERS = ha_example.h ha_example_la_SOURCES = ha_example.cc LDADD = diff --git a/storage/ndb/test/ndbapi/test_event_merge.cpp b/storage/ndb/test/ndbapi/test_event_merge.cpp index 9c6a16eda2b..f57667caf62 100644 --- a/storage/ndb/test/ndbapi/test_event_merge.cpp +++ b/storage/ndb/test/ndbapi/test_event_merge.cpp @@ -27,6 +27,9 @@ #undef version50 #endif +// until rbr in 5.1 +#undef version51rbr + #if !defined(min) || !defined(max) #define min(x, y) ((x) < (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y)) @@ -42,7 +45,14 @@ * 2) In event API version >= 5.1 separate commits within same GCI are * by default merged. This is required to read blob data via NdbBlob. * - * This test program ignores Blob columns in version 5.0. + * Option --separate-events disables GCI merge and implies --no-blobs. + * This is used to test basic events functionality. + * + * Option --no-blobs omits blob attributes. This is used to test GCI + * merge without getting into blob bugs. + * + * Option --no-multiops allows 1 operation per commit. This avoids TUP + * and blob multi-operation bugs. * * There are 5 ways (ignoring NUL operand) to compose 2 ops: * 5.0 bugs 5.1 bugs @@ -59,42 +69,69 @@ struct Opts { uint loop; uint maxops; uint maxpk; - const char* opstr; + my_bool no_blobs; + my_bool no_multiops; + my_bool one_blob; + const char* opstring; uint seed; my_bool separate_events; my_bool use_table; }; static Opts g_opts; -static const uint g_maxops = 10000; static const uint g_maxpk = 100; +static const uint g_maxopstringpart = 100; +static const char* g_opstringpart[g_maxopstringpart]; +static uint g_opstringparts = 0; +static uint g_loop = 0; static Ndb_cluster_connection* g_ncc = 0; static Ndb* g_ndb = 0; static NdbDictionary::Dictionary* g_dic = 0; static NdbTransaction* g_con = 0; static NdbOperation* g_op = 0; +static NdbScanOperation* g_scan_op = 0; static const char* g_tabname = "tem1"; static const char* g_evtname = "tem1ev1"; static const uint g_charlen = 5; -static const char* g_charval = "abcde"; +static const char* g_charval = "abcdefgh"; static const char* g_csname = "latin1_swedish_ci"; +static uint g_blobinlinesize = 256; +static uint g_blobpartsize = 2000; +static uint g_blobstripesize = 2; +static const uint g_maxblobsize = 100000; + static const NdbDictionary::Table* g_tab = 0; static const NdbDictionary::Event* g_evt = 0; static NdbEventOperation* g_evt_op = 0; +static NdbBlob* g_bh = 0; static uint -urandom(uint n) +urandom() { uint r = (uint)random(); - if (n != 0) - r = r % n; return r; } +static uint +urandom(uint m) +{ + if (m == 0) + return 0; + uint r = urandom(); + r = r % m; + return r; +} + +static bool +urandom(uint per, uint cent) +{ + return urandom(cent) < per; +} + static int& g_loglevel = g_opts.loglevel; // default log level #define chkdb(x) \ @@ -139,11 +176,21 @@ errdb() if (e.code != 0) ll0(++any << " op: error " << e); } + if (g_scan_op != 0) { + const NdbError& e = g_scan_op->getNdbError(); + if (e.code != 0) + ll0(++any << " scan_op: error " << e); + } if (g_evt_op != 0) { const NdbError& e = g_evt_op->getNdbError(); if (e.code != 0) ll0(++any << " evt_op: error " << e); } + if (g_bh != 0) { + const NdbError& e = g_bh->getNdbError(); + if (e.code != 0) + ll0(++any << " evt_op: error " << e); + } if (! any) ll0("unknown db error"); } @@ -156,31 +203,47 @@ struct Col { bool nullable; uint length; uint size; + bool isblob() const { + return type == NdbDictionary::Column::Text; + } }; static Col g_col[] = { { 0, "pk1", NdbDictionary::Column::Unsigned, true, false, 1, 4 }, { 1, "pk2", NdbDictionary::Column::Char, true, false, g_charlen, g_charlen }, { 2, "seq", NdbDictionary::Column::Unsigned, false, false, 1, 4 }, - { 3, "cc1", NdbDictionary::Column::Char, false, true, g_charlen, g_charlen } + { 3, "cc1", NdbDictionary::Column::Char, false, true, g_charlen, g_charlen }, + { 4, "tx1", NdbDictionary::Column::Text, false, true, 0, 0 }, + { 5, "tx2", NdbDictionary::Column::Text, false, true, 0, 0 } }; -static const uint g_ncol = sizeof(g_col)/sizeof(g_col[0]); +static const uint g_maxcol = sizeof(g_col)/sizeof(g_col[0]); + +static uint +ncol() +{ + uint n = g_maxcol; + if (g_opts.no_blobs) + n -= 2; + else if (g_opts.one_blob) + n -= 1; + return n; +} static const Col& getcol(uint i) { - if (i < g_ncol) + if (i < ncol()) return g_col[i]; assert(false); - return g_col[g_ncol]; + return g_col[0]; } static const Col& getcol(const char* name) { uint i; - for (i = 0; i < g_ncol; i++) + for (i = 0; i < ncol(); i++) if (strcmp(g_col[i].name, name) == 0) break; return getcol(i); @@ -195,7 +258,7 @@ createtable() CHARSET_INFO* cs; chkrc((cs = get_charset_by_name(g_csname, MYF(0))) != 0); uint i; - for (i = 0; i < g_ncol; i++) { + for (i = 0; i < ncol(); i++) { const Col& c = g_col[i]; NdbDictionary::Column col(c.name); col.setType(c.type); @@ -210,6 +273,12 @@ createtable() col.setLength(c.length); col.setCharset(cs); break; + case NdbDictionary::Column::Text: + col.setInlineSize(g_blobinlinesize); + col.setPartSize(g_blobpartsize); + col.setStripeSize(g_blobstripesize); + col.setCharset(cs); + break; default: assert(false); break; @@ -256,58 +325,86 @@ droptable() } struct Data { + struct Txt { char* val; uint len; }; + union Ptr { Uint32* u32; char* ch; Txt* txt; void* v; }; Uint32 pk1; char pk2[g_charlen + 1]; Uint32 seq; char cc1[g_charlen + 1]; - void* ptr[g_ncol]; - int ind[g_ncol]; // -1 = no data, 1 = NULL, 0 = not NULL + Txt tx1; + Txt tx2; + Ptr ptr[g_maxcol]; + int ind[g_maxcol]; // -1 = no data, 1 = NULL, 0 = not NULL + uint noop; // bit: omit in NdbOperation (implicit NULL INS or no UPD) + uint ppeq; // bit: post/pre data value equal in GCI data[0]/data[1] void init() { uint i; pk1 = 0; memset(pk2, 0, sizeof(pk2)); seq = 0; memset(cc1, 0, sizeof(cc1)); - ptr[0] = &pk1; - ptr[1] = pk2; - ptr[2] = &seq; - ptr[3] = cc1; - for (i = 0; i < g_ncol; i++) + tx1.val = tx2.val = 0; + tx1.len = tx2.len = 0; + ptr[0].u32 = &pk1; + ptr[1].ch = pk2; + ptr[2].u32 = &seq; + ptr[3].ch = cc1; + ptr[4].txt = &tx1; + ptr[5].txt = &tx2; + for (i = 0; i < g_maxcol; i++) ind[i] = -1; + noop = 0; + ppeq = 0; + } + void free() { + delete [] tx1.val; + delete [] tx2.val; + init(); } }; static int -cmpdata(const Data& d1, const Data& d2) +cmpcol(const Col& c, const Data& d1, const Data& d2) { - uint i; - for (i = 0; i < g_ncol; i++) { - const Col& c = getcol(i); - if (d1.ind[i] != d2.ind[i]) - return 1; - if (d1.ind[i] == 0 && memcmp(d1.ptr[i], d2.ptr[i], c.size) != 0) - return 1; + uint i = c.no; + if (d1.ind[i] != d2.ind[i]) + return 1; + if (d1.ind[i] == 0) { + switch (c.type) { + case NdbDictionary::Column::Unsigned: + if (*d1.ptr[i].u32 != *d2.ptr[i].u32) + return 1; + break; + case NdbDictionary::Column::Char: + if (memcmp(d1.ptr[i].ch, d2.ptr[i].ch, c.size) != 0) + return 1; + break; + case NdbDictionary::Column::Text: + { + const Data::Txt& t1 = *d1.ptr[i].txt; + const Data::Txt& t2 = *d2.ptr[i].txt; + if (t1.len != t2.len) + return 1; + if (memcmp(t1.val, t2.val, t1.len) != 0) + return 1; + } + break; + default: + assert(false); + break; + } } return 0; } -static int -cmpdata(const Data (&d1)[2], const Data (&d2)[2]) -{ - if (cmpdata(d1[0], d2[0]) != 0) - return 1; - if (cmpdata(d1[1], d2[1]) != 0) - return 1; - return 0; -} - static NdbOut& operator<<(NdbOut& out, const Data& d) { uint i; - for (i = 0; i < g_ncol; i++) { + for (i = 0; i < ncol(); i++) { const Col& c = getcol(i); - out << (i == 0 ? "" : " ") << c.name << "="; + out << (i == 0 ? "" : " ") << c.name; + out << (! (d.noop & (1 << i)) ? "=" : ":"); if (d.ind[i] == -1) continue; if (d.ind[i] == 1) { @@ -316,12 +413,12 @@ operator<<(NdbOut& out, const Data& d) } switch (c.type) { case NdbDictionary::Column::Unsigned: - out << *(Uint32*)d.ptr[i]; + out << *d.ptr[i].u32; break; case NdbDictionary::Column::Char: { char buf[g_charlen + 1]; - memcpy(buf, d.ptr[i], g_charlen); + memcpy(buf, d.ptr[i].ch, g_charlen); uint n = g_charlen; while (1) { buf[n] = 0; @@ -332,8 +429,27 @@ operator<<(NdbOut& out, const Data& d) out << "'" << buf << "'"; } break; + case NdbDictionary::Column::Text: + { + Data::Txt& t = *d.ptr[i].txt; + bool first = true; + uint j = 0; + while (j < t.len) { + char c[2]; + c[0] = t.val[j++]; + c[1] = 0; + uint m = 1; + while (j < t.len && t.val[j] == c[0]) + j++, m++; + if (! first) + out << "+"; + first = false; + out << m << c; + } + } + break; default: - out << "?"; + assert(false); break; } } @@ -354,18 +470,26 @@ struct Op { // single or composite Type type; Op* next_op; // within one commit Op* next_com; // next commit chain or next event + Op* next_gci; // groups commit chains (unless --separate-events) + Op* next_ev; + Op* next_free; // free list + bool free; // on free list uint num_op; uint num_com; Data data[2]; // 0-post 1-pre bool match; // matched to event - void init() { + Uint32 gci; // defined for com op and event + void init(Kind a_kind) { + kind = a_kind; assert(kind == OP || kind == EV); type = NUL; - next_op = next_com = 0; + next_op = next_com = next_gci = next_ev = next_free = 0; + free = false; num_op = num_com = 0; data[0].init(); data[1].init(); match = false; + gci = 0; } }; @@ -398,6 +522,8 @@ operator<<(NdbOut& out, const Op& op) out << op.type; out << " " << op.data[0]; out << " [" << op.data[1] << "]"; + if (op.gci != 0) + out << " gci:" << op.gci; return out; } @@ -423,75 +549,104 @@ seteventtype(Op* ev, NdbDictionary::Event::TableEvent te) return 0; } +static Op* g_opfree = 0; +static uint g_freeops = 0; static uint g_usedops = 0; -static uint g_usedevs = 0; -static Op g_oplist[g_maxops]; -static Op g_evlist[g_maxops]; -static uint g_maxcom = 8; // max ops per commit - +static uint g_maxcom = 10; // max ops per commit static Op* g_pk_op[g_maxpk]; static Op* g_pk_ev[g_maxpk]; static uint g_seq = 0; - -static NdbRecAttr* g_ra[2][g_ncol]; // 0-post 1-pre +static NdbRecAttr* g_ev_ra[2][g_maxcol]; // 0-post 1-pre +static NdbBlob* g_ev_bh[2][g_maxcol]; // 0-post 1-pre static Op* g_rec_ev; -static uint g_ev_cnt[g_maxpk]; - -static uint -getfreeops() -{ - assert(g_opts.maxops >= g_usedops); - return g_opts.maxops - g_usedops; -} - -static uint -getfreeevs() -{ - assert(g_opts.maxops >= g_usedevs); - return g_opts.maxops - g_usedevs; -} +static uint g_ev_pos[g_maxpk]; static Op* -getop() +getop(Op::Kind a_kind) { - if (g_usedops < g_opts.maxops) { - Op* op = &g_oplist[g_usedops++]; - op->kind = Op::OP; - op->init(); - return op; + if (g_opfree == 0) { + assert(g_freeops == 0); + Op* op = new Op; + assert(op != 0); + op->next_free = g_opfree; + g_opfree = op; + op->free = true; + g_freeops++; } - assert(false); - return 0; + Op* op = g_opfree; + g_opfree = op->next_free; + assert(g_freeops != 0); + g_freeops--; + g_usedops++; + op->init(a_kind); + return op; } -static Op* -getev() +static void +freeop(Op* op) { - if (g_usedevs < g_opts.maxops) { - Op* ev = &g_evlist[g_usedevs++]; - ev->kind = Op::EV; - ev->init(); - return ev; - } - assert(false); - return 0; + assert(! op->free); + op->data[0].free(); + op->data[1].free(); + op->free = true; + op->next_free = g_opfree; + g_opfree = op; + g_freeops++; + assert(g_usedops != 0); + g_usedops--; } static void resetmem() { int i, j; - for (j = 0; j < 2; j++) - for (i = 0; i < g_ncol; i++) - g_ra[j][i] = 0; - g_rec_ev = 0; - for (i = 0; i < g_opts.maxpk; i++) - g_pk_op[i] = 0; - for (i = 0; i < g_opts.maxpk; i++) - g_ev_cnt[i] = 0; - g_seq = 0; - g_usedops = 0; - g_usedevs = 0; + for (j = 0; j < 2; j++) { + for (i = 0; i < g_maxcol; i++) { + g_ev_ra[j][i] = 0; + g_ev_bh[j][i] = 0; + } + } + if (g_rec_ev != 0) { + freeop(g_rec_ev); + g_rec_ev = 0; + } + Uint32 pk1; + for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) + g_ev_pos[pk1] = 0; + // leave g_seq + for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { + if (g_pk_op[pk1] != 0) { + Op* tot_op = g_pk_op[pk1]; + while (tot_op->next_gci != 0) { + Op* gci_op = tot_op->next_gci; + while (gci_op->next_com != 0) { + Op* com_op = gci_op->next_com; + while (com_op->next_op != 0) { + Op* op = com_op->next_op; + com_op->next_op = op->next_op; + freeop(op); + } + gci_op->next_com = com_op->next_com; + freeop(com_op); + } + tot_op->next_gci = gci_op->next_gci; + freeop(gci_op); + } + freeop(tot_op); + g_pk_op[pk1] = 0; + } + if (g_pk_ev[pk1] != 0) { + Op* tot_op = g_pk_ev[pk1]; + while (tot_op->next_ev != 0) { + Op* ev = tot_op->next_ev; + tot_op->next_ev = ev->next_ev; + freeop(ev); + } + freeop(tot_op); + g_pk_ev[pk1] = 0; + } + } + assert(g_usedops == 0); } struct Comp { @@ -512,39 +667,43 @@ static const uint g_ncomp = sizeof(g_comp)/sizeof(g_comp[0]); static int checkop(const Op* op, Uint32& pk1) { - const Data (&d)[2] = op->data; Op::Type t = op->type; - chkrc(t == Op::NUL || t == Op::INS || t == Op::DEL || t == Op::UPD); - { const Col& c = getcol("pk1"); - chkrc(d[0].ind[c.no] == 0); - pk1 = d[0].pk1; + if (t == Op::NUL) + return 0; + chkrc(t == Op::INS || t == Op::DEL || t == Op::UPD); + const Data& d0 = op->data[0]; + const Data& d1 = op->data[1]; + { + const Col& c = getcol("pk1"); + chkrc(d0.ind[c.no] == 0); + pk1 = d0.pk1; chkrc(pk1 < g_opts.maxpk); } uint i; - for (i = 0; i < g_ncol; i++) { + for (i = 0; i < ncol(); i++) { const Col& c = getcol(i); - if (t != Op::NUL) { - if (c.pk) { - chkrc(d[0].ind[i] == 0); // even DEL has PK in post data - if (t == Op::INS) { - chkrc(d[1].ind[i] == -1); - } else if (t == Op::DEL) { - chkrc(d[1].ind[i] == -1); - } else { - chkrc(d[1].ind[i] == 0); - } - } else { - if (t == Op::INS) { - chkrc(d[0].ind[i] >= 0); - chkrc(d[1].ind[i] == -1); - } else if (t == Op::DEL) { - chkrc(d[0].ind[i] == -1); - chkrc(d[1].ind[i] >= 0); - } else if (op->kind == Op::OP) { - chkrc(d[0].ind[i] >= 0); - chkrc(d[1].ind[i] >= 0); - } - } + const int ind0 = d0.ind[i]; + const int ind1 = d1.ind[i]; + // the rules are the rules.. + if (c.pk) { + chkrc(ind0 == 0); // always PK in post data + if (t == Op::INS) + chkrc(ind1 == -1); + if (t == Op::DEL) + chkrc(ind1 == -1); // no PK in pre data + if (t == Op::UPD) + chkrc(ind1 == 0); + } + if (! c.pk) { + if (t == Op::INS) + chkrc(ind0 >= 0 && ind1 == -1); + if (t == Op::DEL) + chkrc(ind0 == -1 && ind1 >= 0); // always non-PK in pre data + if (t == Op::UPD) + chkrc(ind0 == -1 || ind1 >= 0); // update must have pre data + } + if (! c.nullable) { + chkrc(ind0 <= 0 && ind1 <= 0); } } return 0; @@ -563,27 +722,37 @@ comptype(Op::Type t1, Op::Type t2) // only non-NUL static void copycol(const Col& c, const Data& d1, Data& d3) { - if ((d3.ind[c.no] = d1.ind[c.no]) != -1) - memmove(d3.ptr[c.no], d1.ptr[c.no], c.size); + uint i = c.no; + if ((d3.ind[i] = d1.ind[i]) == 0) { + if (! c.isblob()) { + memmove(d3.ptr[i].v, d1.ptr[i].v, c.size); + } else { + Data::Txt& t1 = *d1.ptr[i].txt; + Data::Txt& t3 = *d3.ptr[i].txt; + delete [] t3.val; + t3.val = new char [t1.len]; + t3.len = t1.len; + memcpy(t3.val, t1.val, t1.len); + } + } } static void copydata(const Data& d1, Data& d3, bool pk, bool nonpk) { uint i; - for (i = 0; i < g_ncol; i++) { + for (i = 0; i < ncol(); i++) { const Col& c = g_col[i]; if (c.pk && pk || ! c.pk && nonpk) copycol(c, d1, d3); } } -// not needed for ops static void compdata(const Data& d1, const Data& d2, Data& d3, bool pk, bool nonpk) { uint i; - for (i = 0; i < g_ncol; i++) { + for (i = 0; i < ncol(); i++) { const Col& c = g_col[i]; if (c.pk && pk || ! c.pk && nonpk) { const Data* d = 0; @@ -607,6 +776,7 @@ copyop(const Op* op1, Op* op3) op3->type = op1->type; copydata(op1->data[0], op3->data[0], true, true); copydata(op1->data[1], op3->data[1], true, true); + op3->gci = op1->gci; Uint32 pk1_tmp; reqrc(checkop(op3, pk1_tmp) == 0); } @@ -623,19 +793,38 @@ compop(const Op* op1, const Op* op2, Op* op3) // op1 o op2 = op3 copyop(op2, op3); return 0; } + Op::Kind kind = + op1->kind == Op::OP && op2->kind == Op::OP ? Op::OP : Op::EV; + Op* res_op = getop(kind); chkrc((comp = comptype(op1->type, op2->type)) != 0); - op3->type = comp->t3; - // sucks - copydata(op2->data[0], op3->data[0], true, false); - if (op3->type != Op::DEL) - copydata(op2->data[0], op3->data[0], false, true); - if (op3->type != Op::INS) - copydata(op1->data[1], op3->data[1], false, true); - if (op3->type == Op::UPD) - copydata(op2->data[0], op3->data[1], true, false); + res_op->type = comp->t3; + if (res_op->type == Op::INS) { + // INS o UPD + compdata(op1->data[0], op2->data[0], res_op->data[0], true, true); + // pre = undef + } + if (res_op->type == Op::DEL) { + // UPD o DEL + copydata(op2->data[0], res_op->data[0], true, false); // PK + copydata(op1->data[1], res_op->data[1], false, true); // non-PK + } + if (res_op->type == Op::UPD && op1->type == Op::DEL) { + // DEL o INS + copydata(op2->data[0], res_op->data[0], true, true); + copydata(op1->data[0], res_op->data[1], true, false); // PK + copydata(op1->data[1], res_op->data[1], false, true); // non-PK + } + if (res_op->type == Op::UPD && op1->type == Op::UPD) { + // UPD o UPD + compdata(op1->data[0], op2->data[0], res_op->data[0], true, true); + compdata(op2->data[1], op1->data[1], res_op->data[1], true, true); + } + assert(op1->gci == op2->gci); + res_op->gci = op2->gci; Uint32 pk1_tmp; - reqrc(checkop(op3, pk1_tmp) == 0); - // not eliminating identical post-pre fields + reqrc(checkop(res_op, pk1_tmp) == 0); + copyop(res_op, op3); + freeop(res_op); return 0; } @@ -648,12 +837,14 @@ createevent() NdbDictionary::Event evt(g_evtname); evt.setTable(*g_tab); evt.addTableEvent(NdbDictionary::Event::TE_ALL); - // pk always - evt.addEventColumn("pk1"); - evt.addEventColumn("pk2"); - // simple cols - evt.addEventColumn("seq"); - evt.addEventColumn("cc1"); + uint i; + for (i = 0; i < ncol(); i++) { + const Col& c = g_col[i]; + evt.addEventColumn(c.name); + } +#ifdef version51rbr + evt.separateEvents(g_opts.separate_events); +#endif if (g_dic->getEvent(evt.getName()) != 0) chkdb(g_dic->dropEvent(evt.getName()) == 0); chkdb(g_dic->createEvent(evt) == 0); @@ -682,20 +873,22 @@ createeventop() chkdb((g_evt_op = g_ndb->createEventOperation(g_evt->getName(), bsz)) != 0); #else chkdb((g_evt_op = g_ndb->createEventOperation(g_evt->getName())) != 0); +#ifdef version51rbr + g_evt_op->separateEvents(g_opts.separate_events); // not yet inherited +#endif #endif uint i; - for (i = 0; i < g_ncol; i++) { + for (i = 0; i < ncol(); i++) { const Col& c = g_col[i]; Data (&d)[2] = g_rec_ev->data; - switch (c.type) { - case NdbDictionary::Column::Unsigned: - case NdbDictionary::Column::Char: - chkdb((g_ra[0][i] = g_evt_op->getValue(c.name, (char*)d[0].ptr[i])) != 0); - chkdb((g_ra[1][i] = g_evt_op->getPreValue(c.name, (char*)d[1].ptr[i])) != 0); - break; - default: - assert(false); - break; + if (! c.isblob()) { + chkdb((g_ev_ra[0][i] = g_evt_op->getValue(c.name, (char*)d[0].ptr[i].v)) != 0); + chkdb((g_ev_ra[1][i] = g_evt_op->getPreValue(c.name, (char*)d[1].ptr[i].v)) != 0); + } else { +#ifdef version51rbr + chkdb((g_ev_bh[0][i] = g_evt_op->getBlobHandle(c.name)) != 0); + chkdb((g_ev_bh[1][i] = g_evt_op->getPreBlobHandle(c.name)) != 0); +#endif } } return 0; @@ -744,56 +937,123 @@ waitgci() // wait for event to be installed and for at least 1 GCI to pass return 0; } +// scan table and set current tot_op for each pk1 static int -makeop(Op* op, Uint32 pk1, Op::Type t, const Op* prev_op) +scantab() { - op->type = t; - if (t != Op::INS) - copydata(prev_op->data[0], op->data[1], true, true); + NdbRecAttr* ra[g_maxcol]; + NdbBlob* bh[g_maxcol]; + Op* rec_op = getop(Op::OP); + Data& d0 = rec_op->data[0]; + chkdb((g_con = g_ndb->startTransaction()) != 0); + chkdb((g_scan_op = g_con->getNdbScanOperation(g_tabname)) != 0); + chkdb(g_scan_op->readTuples() == 0); uint i; - for (i = 0; i < g_ncol; i++) { + for (i = 0; i < ncol(); i++) { const Col& c = getcol(i); - Data (&d)[2] = op->data; - if (c.pk && t == Op::DEL) { - d[1].ind[i] = -1; + if (! c.isblob()) { + chkdb((ra[i] = g_scan_op->getValue(c.name, (char*)d0.ptr[i].v)) != 0); + } else { + chkdb((bh[i] = g_scan_op->getBlobHandle(c.name)) != 0); } - if (i == getcol("pk1").no) { - d[0].pk1 = pk1; - d[0].ind[i] = 0; - continue; - } - if (i == getcol("pk2").no) { - sprintf(d[0].pk2, "%-*u", g_charlen, d[0].pk1); - d[0].ind[i] = 0; - continue; - } - if (t == Op::DEL) { - d[0].ind[i] = -1; - continue; - } - if (i == getcol("seq").no) { - d[0].seq = g_seq++; - d[0].ind[i] = 0; - continue; - } - uint u; - u = urandom(100); - if (c.nullable && u < 10) { - d[0].ind[i] = 1; + } + chkdb(g_con->execute(NoCommit) == 0); + int ret; + while ((ret = g_scan_op->nextResult()) == 0) { + Uint32 pk1 = d0.pk1; + if (pk1 >= g_opts.maxpk) continue; + rec_op->type = Op::INS; + for (i = 0; i < ncol(); i++) { + const Col& c = getcol(i); + int ind; + if (! c.isblob()) { + ind = ra[i]->isNULL(); + } else { +#ifdef version51rbr + int ret; + ret = bh[i]->getDefined(ind); + assert(ret == 0); + if (ind == 0) { + Data::Txt& t = *d0.ptr[i].txt; + Uint64 len64; + ret = bh[i]->getLength(len64); + assert(ret == 0); + t.len = (uint)len64; + delete [] t.val; + t.val = new char [t.len]; + memset(t.val, 'X', t.len); + Uint32 len = t.len; + ret = bh[i]->readData(t.val, len); + assert(ret == 0 && len == t.len); + } +#endif + } + assert(ind >= 0); + d0.ind[i] = ind; } + assert(g_pk_op[pk1] == 0); + Op* tot_op = g_pk_op[pk1] = getop(Op::OP); + copyop(rec_op, tot_op); + tot_op->type = Op::INS; + } + chkdb(ret == 1); + g_ndb->closeTransaction(g_con); + g_scan_op = 0; + g_con = 0; + freeop(rec_op); + return 0; +} + +static void +makedata(const Col& c, Data& d, Uint32 pk1, Op::Type t) +{ + uint i = c.no; + if (c.pk) { switch (c.type) { case NdbDictionary::Column::Unsigned: { - u = urandom(0); - Uint32* p = (Uint32*)d[0].ptr[i]; + Uint32* p = d.ptr[i].u32; + *p = pk1; + } + break; + case NdbDictionary::Column::Char: + { + char* p = d.ptr[i].ch; + sprintf(p, "%-*u", g_charlen, pk1); + } + break; + default: + assert(false); + break; + } + d.ind[i] = 0; + } else if (t == Op::DEL) { + ; + } else if (i == getcol("seq").no) { + d.seq = g_seq++; + d.ind[i] = 0; + } else if (t == Op::INS && c.nullable && urandom(10, 100)) { + d.noop |= (1 << i); + d.ind[i] = 1; // implicit NULL value is known + } else if (t == Op::UPD && urandom(10, 100)) { + d.noop |= (1 << i); + d.ind[i] = -1; // fixed up in caller + } else if (c.nullable && urandom(10, 100)) { + d.ind[i] = 1; + } else { + switch (c.type) { + case NdbDictionary::Column::Unsigned: + { + Uint32* p = d.ptr[i].u32; + uint u = urandom(); *p = u; } break; case NdbDictionary::Column::Char: { - u = urandom(g_charlen); - char* p = (char*)d[0].ptr[i]; + char* p = d.ptr[i].ch; + uint u = urandom(g_charlen); uint j; for (j = 0; j < g_charlen; j++) { uint v = urandom(strlen(g_charval)); @@ -801,78 +1061,103 @@ makeop(Op* op, Uint32 pk1, Op::Type t, const Op* prev_op) } } break; + case NdbDictionary::Column::Text: + { + Data::Txt& t = *d.ptr[i].txt; + uint u = urandom(g_maxblobsize); + u = urandom(u); // 4x bias for smaller blobs + u = urandom(u); + delete [] t.val; + t.val = new char [u]; + t.len = u; + uint j = 0; + while (j < u) { + assert(u > 0); + uint k = 1 + urandom(u - 1); + if (k > u - j) + k = u - j; + uint v = urandom(strlen(g_charval)); + memset(&t.val[j], g_charval[v], k); + j += k; + } + } + break; default: assert(false); break; } - d[0].ind[i] = 0; + d.ind[i] = 0; } - Uint32 pk1_tmp = ~(Uint32)0; - chkrc(checkop(op, pk1_tmp) == 0); - reqrc(pk1 == pk1_tmp); - return 0; } static void -makeop(Op* tot_op, Op* com_op, Uint32 pk1, Op::Type t) +makeop(const Op* prev_op, Op* op, Uint32 pk1, Op::Type t) { - Op tmp_op; - tmp_op.kind = Op::OP; - Op* op = getop(); - reqrc(makeop(op, pk1, t, tot_op) == 0); - // add to end - Op* last_op = com_op; - while (last_op->next_op != 0) - last_op = last_op->next_op; - last_op->next_op = op; - // merge into chain head - tmp_op.init(); - reqrc(compop(com_op, op, &tmp_op) == 0); - copyop(&tmp_op, com_op); - // merge into total op - tmp_op.init(); - reqrc(compop(tot_op, op, &tmp_op) == 0); - copyop(&tmp_op, tot_op); - // counts - com_op->num_op += 1; - tot_op->num_op += 1; + op->type = t; + const Data& dp = prev_op->data[0]; + Data& d0 = op->data[0]; + Data& d1 = op->data[1]; + uint i; + for (i = 0; i < ncol(); i++) { + const Col& c = getcol(i); + makedata(c, d0, pk1, t); + if (t == Op::INS) { + d1.ind[i] = -1; + } else if (t == Op::DEL) { + assert(dp.ind[i] >= 0); + if (c.pk) + d1.ind[i] = -1; + else + copycol(c, dp, d1); + } else if (t == Op::UPD) { + assert(dp.ind[i] >= 0); + if (d0.ind[i] == -1) // not updating this col + copycol(c, dp, d0); // must keep track of data + copycol(c, dp, d1); + } else { + assert(false); + } + } + Uint32 pk1_tmp = ~(Uint32)0; + reqrc(checkop(op, pk1_tmp) == 0); + reqrc(pk1 == pk1_tmp); } static void makeops() { ll1("makeops"); - uint resv = g_opts.opstr == 0 ? 2 * g_opts.maxpk : 0; // for final deletes - uint next = g_opts.opstr == 0 ? g_maxcom : strlen(g_opts.opstr); - Op tmp_op; - tmp_op.kind = Op::OP; Uint32 pk1 = 0; - while (getfreeops() >= resv + 2 + next && pk1 < g_opts.maxpk) { - if (g_opts.opstr == 0) + while (g_usedops < g_opts.maxops && pk1 < g_opts.maxpk) { + if (g_opts.opstring == 0) pk1 = urandom(g_opts.maxpk); - ll2("makeops: pk1=" << pk1 << " free=" << getfreeops()); + ll2("makeops: pk1=" << pk1); // total op on the pk so far // optype either NUL=initial/deleted or INS=created Op* tot_op = g_pk_op[pk1]; if (tot_op == 0) - tot_op = g_pk_op[pk1] = getop(); //1 + tot_op = g_pk_op[pk1] = getop(Op::OP); assert(tot_op->type == Op::NUL || tot_op->type == Op::INS); // add new commit chain to end - Op* last_com = tot_op; - while (last_com->next_com != 0) - last_com = last_com->next_com; - Op* com_op = getop(); //2 - last_com->next_com = com_op; + Op* last_gci = tot_op; + while (last_gci->next_gci != 0) + last_gci = last_gci->next_gci; + Op* gci_op = getop(Op::OP); + last_gci->next_gci = gci_op; + Op* com_op = getop(Op::OP); + gci_op->next_com = com_op; // length of random chain uint len = ~0; - if (g_opts.opstr == 0) + if (g_opts.opstring == 0) { len = 1 + urandom(g_maxcom - 1); + len = 1 + urandom(len - 1); // 2x bias for short chain + } ll2("makeops: com chain"); uint n = 0; while (1) { - // random or from g_opts.opstr + // random or from current g_opts.opstring part Op::Type t; - if (g_opts.opstr == 0) { + if (g_opts.opstring == 0) { if (n == len) break; do { @@ -880,10 +1165,11 @@ makeops() } while (tot_op->type == Op::NUL && (t == Op::DEL || t == Op::UPD) || tot_op->type == Op::INS && t == Op::INS); } else { - uint m = strlen(g_opts.opstr); + const char* str = g_opstringpart[g_loop % g_opstringparts]; + uint m = strlen(str); uint k = tot_op->num_com + tot_op->num_op; assert(k < m); - char c = g_opts.opstr[k]; + char c = str[k]; if (c == 'c') { if (k + 1 == m) pk1 += 1; @@ -894,30 +1180,27 @@ makeops() assert(q != 0); t = (Op::Type)(q - p); } - makeop(tot_op, com_op, pk1, t); + Op* op = getop(Op::OP); + makeop(tot_op, op, pk1, t); + // add to end + Op* last_op = com_op; + while (last_op->next_op != 0) + last_op = last_op->next_op; + last_op->next_op = op; + // merge into chain head and total op + reqrc(compop(com_op, op, com_op) == 0); + reqrc(compop(tot_op, op, tot_op) == 0); assert(tot_op->type == Op::NUL || tot_op->type == Op::INS); + // counts + com_op->num_op += 1; + tot_op->num_op += 1; n++; } + // copy to gci level + copyop(com_op, gci_op); tot_op->num_com += 1; } - assert(getfreeops() >= resv); - // terminate with DEL if necessary - for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { - Op* tot_op = g_pk_op[pk1]; - if (tot_op == 0) - continue; - if (tot_op->type == Op::NUL) - continue; - assert(g_opts.opstr == 0); - Op* last_com = tot_op; - while (last_com->next_com != 0) - last_com = last_com->next_com; - Op* com_op = getop(); //1 - last_com->next_com = com_op; - makeop(tot_op, com_op, pk1, Op::DEL); - assert(tot_op->type == Op::NUL); - tot_op->num_com += 1; - } + ll1("makeops: used ops = " << g_usedops); } static int @@ -939,23 +1222,36 @@ addndbop(Op* op) break; } uint i; - for (i = 0; i < g_ncol; i++) { + for (i = 0; i < ncol(); i++) { const Col& c = getcol(i); const Data& d = op->data[0]; if (! c.pk) continue; - chkdb(g_op->equal(c.name, (char*)d.ptr[i]) == 0); + chkdb(g_op->equal(c.name, (const char*)d.ptr[i].v) == 0); } if (op->type != Op::DEL) { - for (i = 0; i < g_ncol; i++) { + for (i = 0; i < ncol(); i++) { const Col& c = getcol(i); const Data& d = op->data[0]; if (c.pk) continue; - if (d.ind[i] == -1) + if (d.noop & (1 << i)) continue; - const char* ptr = d.ind[i] == 0 ? (char*)d.ptr[i] : 0; - chkdb(g_op->setValue(c.name, ptr) == 0); + assert(d.ind[i] >= 0); + if (! c.isblob()) { + if (d.ind[i] == 0) + chkdb(g_op->setValue(c.name, (const char*)d.ptr[i].v) == 0); + else + chkdb(g_op->setValue(c.name, (const char*)0) == 0); + } else { + const Data::Txt& t = *d.ptr[i].txt; + g_bh = g_op->getBlobHandle(c.name); + if (d.ind[i] == 0) + chkdb(g_bh->setValue(t.val, t.len) == 0); + else + chkdb(g_bh->setValue(0, 0) == 0); + g_bh = 0; + } } } g_op = 0; @@ -967,40 +1263,43 @@ runops() { ll1("runops"); Uint32 pk1; - const Op* com_op[g_maxpk]; - uint left = 0; + Op* gci_op[g_maxpk]; + uint left = 0; // number of pks with ops for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { - com_op[pk1] = 0; + gci_op[pk1] = 0; // total op on the pk Op* tot_op = g_pk_op[pk1]; if (tot_op == 0) continue; // first commit chain - assert(tot_op->next_com != 0); - com_op[pk1] = tot_op->next_com; + assert(tot_op->next_gci != 0); + gci_op[pk1] = tot_op->next_gci; left++; } while (left != 0) { pk1 = urandom(g_opts.maxpk); - if (com_op[pk1] == 0) + if (gci_op[pk1] == 0) continue; // do the ops in one transaction - ll2("runops: pk1=" << pk1); chkdb((g_con = g_ndb->startTransaction()) != 0); + Op* com_op = gci_op[pk1]->next_com; + assert(com_op != 0); // first op in chain - Op* op = com_op[pk1]->next_op; + Op* op = com_op->next_op; assert(op != 0); while (op != 0) { - ll2("add op:" << *op); + ll2("runops:" << *op); chkrc(addndbop(op) == 0); op = op->next_op; } chkdb(g_con->execute(Commit) == 0); + gci_op[pk1]->gci = com_op->gci = g_con->getGCI(); + ll2("commit: gci=" << com_op->gci); g_ndb->closeTransaction(g_con); g_con = 0; // next chain - com_op[pk1] = com_op[pk1]->next_com; - if (com_op[pk1] == 0) { + gci_op[pk1] = gci_op[pk1]->next_gci; + if (gci_op[pk1] == 0) { assert(left != 0); left--; } @@ -1009,6 +1308,99 @@ runops() return 0; } +// move com chains with same gci under same gci entry +static int +mergeops() +{ + ll1("mergeops"); + uint mergecnt = 0; + Uint32 pk1; + for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { + Op* tot_op = g_pk_op[pk1]; + if (tot_op == 0) + continue; + Op* gci_op = tot_op->next_gci; + assert(gci_op != 0); + while (gci_op != 0) { + Op* com_op = gci_op->next_com; + assert(com_op != 0 && com_op->next_com == 0); + assert(gci_op->gci == com_op->gci); + Op* last_com = com_op; + Op* gci_op2 = gci_op->next_gci; + while (gci_op2 != 0 && gci_op->gci == gci_op2->gci) { + // move link to com level + last_com = last_com->next_com = gci_op2->next_com; + // merge to gci + reqrc(compop(gci_op, gci_op2, gci_op) == 0); + // move to next and discard + Op* tmp_op = gci_op2; + gci_op2 = gci_op2->next_gci; + freeop(tmp_op); + mergecnt++; + } + gci_op = gci_op->next_gci = gci_op2; + } + } + ll1("mergeops: used ops = " << g_usedops); + ll1("mergeops: merged " << mergecnt << " gci entries"); + return 0; +} + +// set bit for equal post/pre data in UPD, for use in event match +static void +cmppostpre() +{ + ll1("cmppostpre"); + Uint32 pk1; + for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { + Op* tot_op = g_pk_op[pk1]; + Op* gci_op = tot_op ? tot_op->next_gci : 0; + while (gci_op != 0) { + if (gci_op->type == Op::UPD) { + Data (&d)[2] = gci_op->data; + uint i; + for (i = 0; i < ncol(); i++) { + const Col& c = getcol(i); + bool eq = + d[0].ind[i] == 1 && d[1].ind[i] == 1 || + d[0].ind[i] == 0 && d[1].ind[i] == 0 && cmpcol(c, d[0], d[1]) == 0; + if (eq) { + d[0].ppeq |= (1 << i); + d[1].ppeq |= (1 << i); + } + } + } + gci_op = gci_op->next_gci; + } + } +} +static int +cmpopevdata(const Data& d1, const Data& d2) +{ + uint i; + for (i = 0; i < ncol(); i++) { + const Col& c = getcol(i); + if (cmpcol(c, d1, d2) != 0) { + if ((d1.ppeq & (1 << i)) && d2.ind[i] == -1) + ; // post/pre data equal and no event data returned is OK + else + return 1; + } + } + return 0; +} + +// compare operation to event data +static int +cmpopevdata(const Data (&d1)[2], const Data (&d2)[2]) +{ + if (cmpopevdata(d1[0], d2[0]) != 0) + return 1; + if (cmpopevdata(d1[1], d2[1]) != 0) + return 1; + return 0; +} + static int matchevent(Op* ev) { @@ -1024,41 +1416,53 @@ matchevent(Op* ev) ll1("matchevent: pk1=" << pk1 << " type=" << t); ll2("EVT: " << *ev); Op* tot_op = g_pk_op[pk1]; - Op* com_op = tot_op ? tot_op->next_com : 0; - uint cnt = 0; + Op* gci_op = tot_op ? tot_op->next_gci : 0; + uint pos = 0; bool ok = false; - while (com_op != 0) { - ll2("COM: " << *com_op); - Op* op = com_op->next_op; - assert(op != 0); - while (op != 0) { - ll2("---: " << *op); - op = op->next_op; + while (gci_op != 0) { + ll2("GCI: " << *gci_op); + // print details + Op* com_op = gci_op->next_com; + assert(com_op != 0); + while (com_op != 0) { + ll2("COM: " << *com_op); + Op* op = com_op->next_op; + assert(op != 0); + while (op != 0) { + ll2("OP : " << *op); + op = op->next_op; + } + com_op = com_op->next_com; } - if (com_op->type != Op::NUL) { - const Data (&d1)[2] = com_op->data; - if (cmpdata(d1, d2) == 0) { + // match agains GCI op + if (gci_op->type != Op::NUL) { + const Data (&d1)[2] = gci_op->data; + if (cmpopevdata(d1, d2) == 0) { bool tmpok = true; - if (com_op->type != t) { - ll2("***: wrong type " << com_op->type << " != " << t); + if (gci_op->type != t) { + ll2("***: wrong type " << gci_op->type << " != " << t); tmpok = false; } - if (com_op->match) { + if (gci_op->match) { ll2("***: duplicate match"); tmpok = false; } - if (cnt != g_ev_cnt[pk1]) { - ll2("***: wrong pos " << cnt << " != " << g_ev_cnt[pk1]); + if (pos != g_ev_pos[pk1]) { + ll2("***: wrong pos " << pos << " != " << g_ev_pos[pk1]); + tmpok = false; + } + if (gci_op->gci != ev->gci) { + ll2("***: wrong gci " << gci_op->gci << " != " << ev->gci); tmpok = false; } if (tmpok) { - ok = com_op->match = true; + ok = gci_op->match = true; ll2("===: match"); } } - cnt++; + pos++; } - com_op = com_op->next_com; + gci_op = gci_op->next_gci; } if (ok) { ll1("matchevent: match"); @@ -1081,12 +1485,12 @@ matchevents() Op* tot_ev = g_pk_ev[pk1]; if (tot_ev == 0) continue; - Op* com_ev = tot_ev->next_com; - while (com_ev != 0) { - if (matchevent(com_ev) < 0) + Op* ev = tot_ev->next_ev; + while (ev != 0) { + if (matchevent(ev) < 0) nomatch++; - g_ev_cnt[pk1]++; - com_ev = com_ev->next_com; + g_ev_pos[pk1]++; + ev = ev->next_ev; } } chkrc(nomatch == 0); @@ -1120,13 +1524,49 @@ matchops() return 0; } +static void +geteventdata() +{ + Data (&d)[2] = g_rec_ev->data; + int i, j; + for (j = 0; j < 2; j++) { + for (i = 0; i < ncol(); i++) { + const Col& c = getcol(i); + int ind, ret; + if (! c.isblob()) { + NdbRecAttr* ra = g_ev_ra[j][i]; + ind = ra->isNULL(); + } else { +#ifdef version51rbr + NdbBlob* bh = g_ev_bh[j][i]; + ret = bh->getDefined(ind); + assert(ret == 0); + if (ind == 0) { // value was returned and is not NULL + Data::Txt& t = *d[j].ptr[i].txt; + Uint64 len64; + ret = bh->getLength(len64); + assert(ret == 0); + t.len = (uint)len64; + delete [] t.val; + t.val = new char [t.len]; + memset(t.val, 'X', t.len); + Uint32 len = t.len; + ret = bh->readData(t.val, len); + assert(ret == 0 && len == t.len); + } +#endif + } + d[j].ind[i] = ind; + } + } +} + static int runevents() { ll1("runevents"); - NdbEventOperation* evt_op; uint mspoll = 1000; - uint npoll = 7; // strangely long delay + uint npoll = 6; // strangely long delay while (npoll != 0) { npoll--; int ret; @@ -1135,8 +1575,7 @@ runevents() if (ret <= 0) continue; while (1) { - g_rec_ev->init(); - Data (&d)[2] = g_rec_ev->data; + g_rec_ev->init(Op::EV); #ifdef version50 int overrun = g_opts.maxops; chkdb((ret = g_evt_op->next(&overrun)) >= 0); @@ -1150,32 +1589,35 @@ runevents() reqrc(g_evt_op == tmp_op); #endif chkrc(seteventtype(g_rec_ev, g_evt_op->getEventType()) == 0); - // get indicators - { int i, j; - for (j = 0; j < 2; j++) - for (i = 0; i < g_ncol; i++) - d[j].ind[i] = g_ra[j][i]->isNULL(); + geteventdata(); + g_rec_ev->gci = g_evt_op->getGCI(); +#ifdef version50 + // fix to match 5.1 + if (g_rec_ev->type == Op::UPD) { + Uint32 pk1 = g_rec_ev->data[0].pk1; + makedata(getcol("pk1"), g_rec_ev->data[1], pk1, Op::UPD); + makedata(getcol("pk2"), g_rec_ev->data[1], pk1, Op::UPD); } +#endif + // get indicators and blob value ll2("runevents: EVT: " << *g_rec_ev); // check basic sanity Uint32 pk1 = ~(Uint32)0; chkrc(checkop(g_rec_ev, pk1) == 0); // add to events - chkrc(getfreeevs() >= 2); Op* tot_ev = g_pk_ev[pk1]; if (tot_ev == 0) - tot_ev = g_pk_ev[pk1] = getev(); //1 - Op* last_com = tot_ev; - while (last_com->next_com != 0) - last_com = last_com->next_com; + tot_ev = g_pk_ev[pk1] = getop(Op::EV); + Op* last_ev = tot_ev; + while (last_ev->next_ev != 0) + last_ev = last_ev->next_ev; // copy and add - Op* ev = getev(); //3 + Op* ev = getop(Op::EV); copyop(g_rec_ev, ev); - last_com->next_com = ev; + last_ev->next_ev = ev; } } - chkrc(matchevents() == 0); - chkrc(matchops() == 0); + ll1("runevents: used ops = " << g_usedops); return 0; } @@ -1205,18 +1647,23 @@ runtest() setseed(-1); chkrc(createtable() == 0); chkrc(createevent() == 0); - uint n; - for (n = 0; g_opts.loop == 0 || n < g_opts.loop; n++) { - ll0("loop " << n); - setseed(n); + for (g_loop = 0; g_opts.loop == 0 || g_loop < g_opts.loop; g_loop++) { + ll0("loop " << g_loop); + setseed(g_loop); resetmem(); - g_rec_ev = getev(); + chkrc(scantab() == 0); // alternative: save tot_op for loop > 0 + makeops(); + g_rec_ev = getop(Op::EV); chkrc(createeventop() == 0); chkdb(g_evt_op->execute() == 0); chkrc(waitgci() == 0); - makeops(); chkrc(runops() == 0); + if (! g_opts.separate_events) + chkrc(mergeops() == 0); + cmppostpre(); chkrc(runevents() == 0); + chkrc(matchevents() == 0); + chkrc(matchops() == 0); chkrc(dropeventop() == 0); } chkrc(dropevent() == 0); @@ -1230,31 +1677,41 @@ static struct my_option my_long_options[] = { NDB_STD_OPTS("test_event_merge"), - { "abort-on-error", 1008, "Do abort() on any error", + { "abort-on-error", 1001, "Do abort() on any error", (gptr*)&g_opts.abort_on_error, (gptr*)&g_opts.abort_on_error, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "loglevel", 1001, "Logging level in this program (default 0)", + { "loglevel", 1002, "Logging level in this program (default 0)", (gptr*)&g_opts.loglevel, (gptr*)&g_opts.loglevel, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - { "loop", 1002, "Number of test loops (default 1, 0=forever)", + { "loop", 1003, "Number of test loops (default 2, 0=forever)", (gptr*)&g_opts.loop, (gptr*)&g_opts.loop, 0, - GET_INT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0 }, - { "maxops", 1003, "Number of PK operations (default 2000)", + GET_INT, REQUIRED_ARG, 2, 0, 0, 0, 0, 0 }, + { "maxops", 1004, "Approx number of PK operations (default 1000)", (gptr*)&g_opts.maxops, (gptr*)&g_opts.maxops, 0, - GET_UINT, REQUIRED_ARG, 2000, 0, g_maxops, 0, 0, 0 }, - { "maxpk", 1004, "Number of different PK values (default 10)", + GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0 }, + { "maxpk", 1005, "Number of different PK values (default 10)", (gptr*)&g_opts.maxpk, (gptr*)&g_opts.maxpk, 0, GET_UINT, REQUIRED_ARG, 10, 1, g_maxpk, 0, 0, 0 }, - { "opstr", 1005, "Ops to run e.g. idiucdc (c = commit, default random)", - (gptr*)&g_opts.opstr, (gptr*)&g_opts.opstr, 0, + { "no-blobs", 1006, "Omit blob attributes (5.0: true)", + (gptr*)&g_opts.no_blobs, (gptr*)&g_opts.no_blobs, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "no-multiops", 1007, "Allow only 1 operation per commit", + (gptr*)&g_opts.no_multiops, (gptr*)&g_opts.no_multiops, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "one-blob", 1008, "Only one blob attribute (defautt 2)", + (gptr*)&g_opts.one_blob, (gptr*)&g_opts.one_blob, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "opstring", 1009, "Operations to run e.g. idiucdc (c is commit) or" + " iuuc:uudc (the : separates loops)", + (gptr*)&g_opts.opstring, (gptr*)&g_opts.opstring, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - { "seed", 1006, "Random seed (0=loop number, default -1=random)", + { "seed", 1010, "Random seed (0=loop number, default -1=random)", (gptr*)&g_opts.seed, (gptr*)&g_opts.seed, 0, GET_INT, REQUIRED_ARG, -1, 0, 0, 0, 0, 0 }, - { "separate-events", 1007, "Do not combine events per GCI >5.0", + { "separate-events", 1011, "Do not combine events per GCI (5.0: true)", (gptr*)&g_opts.separate_events, (gptr*)&g_opts.separate_events, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "use-table", 1008, "Use existing table 'tem1'", + { "use-table", 1012, "Use existing table 'tem1'", (gptr*)&g_opts.use_table, (gptr*)&g_opts.use_table, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, @@ -1271,14 +1728,36 @@ usage() static int checkopts() { - if (g_opts.opstr != 0) { - const char* s = g_opts.opstr; - uint n = strlen(s); - if (n < 3 || s[0] != 'i' || s[n-2] != 'd' || s[n-1] != 'c') - return -1; - while (*s != 0) - if (strchr("iduc", *s++) == 0) +#ifdef version50 + g_opts.separate_events = true; +#endif + if (g_opts.separate_events) { + g_opts.no_blobs = true; + } + if (g_opts.no_multiops) { + g_maxcom = 1; + } + if (g_opts.opstring != 0) { + uint len = strlen(g_opts.opstring); + char* str = new char [len + 1]; + memcpy(str, g_opts.opstring, len + 1); + char* s = str; + while (1) { + g_opstringpart[g_opstringparts++] = s; + s = strchr(s, ':'); + if (s == 0) + break; + *s++ = 0; + } + uint i; + for (i = 0; i < g_opstringparts; i++) { + const char* s = g_opstringpart[i]; + while (*s != 0) + if (strchr("iduc", *s++) == 0) + return -1; + if (s == g_opstringpart[i] || s[-1] != 'c') return -1; + } } return 0; }