From af18865e5afedc31a4f58d15d781e420a5588e6a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Oct 2004 18:10:44 +0500 Subject: [PATCH 01/14] A fix (bug #6000 No "@%"-accounts after install). scripts/mysql_install_db.sh: A fix (bug #6000 No "@%"-accounts after install). Why do we need those REPLACE queries? Removed $hostname queries for windows builds. --- scripts/mysql_install_db.sh | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index f9f3160d220..c75f9854a2a 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -275,14 +275,16 @@ then c_u="$c_u )" c_u="$c_u comment='Users and global privileges';" - i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - - REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - - INSERT INTO user (host,user) values ('localhost',''); - INSERT INTO user (host,user) values ('$hostname','');" + if test "$windows" = 1 + then + i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user (host,user) values ('localhost','');" + else + i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user (host,user) values ('localhost',''); + INSERT INTO user (host,user) values ('$hostname','');" + fi fi if test ! -f $mdata/func.frm From a12d52a1d7ff3ae0c6baca766400e7966c6e45a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 27 Jan 2005 14:05:44 +0200 Subject: [PATCH 02/14] InnoDB: Tolerate negative return values from ftell(). sql/ha_innodb.cc: Tolerate negative return values from ftell(). --- sql/ha_innodb.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 2e441b4f085..1a870ce3abf 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4346,12 +4346,12 @@ ha_innobase::update_table_comment( (ulong) innobase_get_free_space()); dict_print_info_on_foreign_keys(FALSE, file, prebuilt->table); flen = ftell(file); - if(length + flen + 3 > 64000) { + if (flen < 0) { + flen = 0; + } else if (length + flen + 3 > 64000) { flen = 64000 - 3 - length; } - ut_ad(flen > 0); - /* allocate buffer for the full string, and read the contents of the temporary file */ @@ -4414,12 +4414,12 @@ ha_innobase::get_foreign_key_create_info(void) prebuilt->trx->op_info = (char*)""; flen = ftell(file); - if(flen > 64000 - 1) { + if (flen < 0) { + flen = 0; + } else if(flen > 64000 - 1) { flen = 64000 - 1; } - ut_ad(flen >= 0); - /* allocate buffer for the string, and read the contents of the temporary file */ @@ -4800,12 +4800,12 @@ innodb_show_status( srv_printf_innodb_monitor(srv_monitor_file); flen = ftell(srv_monitor_file); os_file_set_eof(srv_monitor_file); - if(flen > 64000 - 1) { + if (flen < 0) { + flen = 0; + } else if (flen > 64000 - 1) { flen = 64000 - 1; } - ut_ad(flen > 0); - /* allocate buffer for the string, and read the contents of the temporary file */ From bde9e86041ed3cb80b26f5b3d5bb7168da031c5d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 27 Jan 2005 17:12:21 +0200 Subject: [PATCH 03/14] configure.in: Add -DDBUG_ON to CXXFLAGS whenever it is added to CFLAGS. Thus, sql/ha_innodb.cc will be compiled with the same setting of UNIV_DEBUG as the rest of InnoDB, i.e., --with-debug enables InnoDB ut_ad() assertions everywhere. configure.in: Add -DDBUG_ON to CXXFLAGS whenever it is added to CFLAGS. Thus, sql/ha_innodb.cc will be compiled with the same setting of UNIV_DEBUG as the rest of InnoDB, i.e., --with-debug enables InnoDB ut_ad() assertions everywhere. --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 65af867cbc0..8b8c0690a55 100644 --- a/configure.in +++ b/configure.in @@ -1632,12 +1632,12 @@ if test "$with_debug" = "yes" then # Medium debug. CFLAGS="$DEBUG_CFLAGS $DEBUG_OPTIMIZE_CC -DDBUG_ON -DSAFE_MUTEX $CFLAGS" - CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DSAFE_MUTEX $CXXFLAGS" + CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DDBUG_ON -DSAFE_MUTEX $CXXFLAGS" elif test "$with_debug" = "full" then # Full debug. Very slow in some cases CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS" - CXXFLAGS="$DEBUG_CXXFLAGS -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS" + CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS" else # Optimized version. No debug CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS" From 96e4281f059cd6d534338c539a9e44caff984b93 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Jan 2005 16:43:10 -0800 Subject: [PATCH 04/14] Cleanup for lost file descriptors on close table for ha_archive. sql/examples/ha_archive.cc: More comments, fixed issue with lost file descriptors. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/examples/ha_archive.cc | 26 +++++++++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 52b8b0584bc..a579cac30bd 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -33,6 +33,7 @@ bk@mysql.r18.ru brian@avenger.(none) brian@brian-akers-computer.local brian@private-client-ip-101.oz.net +brian@zim.(none) carsten@tsort.bitbybit.dk davida@isil.mysql.com dellis@goetia.(none) diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index ef609513489..75fba96cad9 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -42,18 +42,20 @@ handle bulk inserts as well (that is if someone was trying to read at the same time since we would want to flush). - A "meta" file is kept. All this file does is contain information on - the number of rows. + A "meta" file is kept alongside the data file. This file serves two purpose. + The first purpose is to track the number of rows in the table. The second + purpose is to determine if the table was closed properly or not. When the + meta file is first opened it is marked as dirty. It is opened when the table + itself is opened for writing. When the table is closed the new count for rows + is written to the meta file and the file is marked as clean. If the meta file + is opened and it is marked as dirty, it is assumed that a crash occured. At + this point an error occurs and the user is told to rebuild the file. + A rebuild scans the rows and rewrites the meta file. If corruption is found + in the data file then the meta file is not repaired. - No attempts at durability are made. You can corrupt your data. A repair - method was added to repair the meta file that stores row information, - but if your data file gets corrupted I haven't solved that. I could - create a repair that would solve this, but do you want to take a - chance of loosing your data? + At some point a recovery method for such a drastic case needs to be divised. - Locks are row level, and you will get a consistant read. Transactions - will be added later (they are not that hard to add at this - stage). + Locks are row level, and you will get a consistant read. For performance as far as table scans go it is quite fast. I don't have good numbers but locally it has out performed both Innodb and MyISAM. For @@ -88,7 +90,6 @@ compression but may speed up ordered searches). Checkpoint the meta file to allow for faster rebuilds. Dirty open (right now the meta file is repaired if a crash occured). - Transactions. Option to allow for dirty reads, this would lower the sync calls, which would make inserts a lot faster, but would mean highly arbitrary reads. @@ -333,6 +334,7 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) opposite. */ (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE); + /* It is expensive to open and close the data files and since you can't have a gzip file that can be both read and written we keep a writer open @@ -379,6 +381,8 @@ int ha_archive::free_share(ARCHIVE_SHARE *share) (void)write_meta_file(share->meta_file, share->rows_recorded, FALSE); if (gzclose(share->archive_write) == Z_ERRNO) rc= 1; + if (my_close(share->meta_file, MYF(0))) + rc= 1; my_free((gptr) share, MYF(0)); } pthread_mutex_unlock(&archive_mutex); From 0e2e3df2b4bbbcc6c7625a9d2c998fa3c2733417 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Jan 2005 12:17:34 -0800 Subject: [PATCH 05/14] Removed duplicate close call and added archive to the debug build and test. BUILD/compile-ia64-debug-max: Added archive for this build. sql/examples/ha_archive.cc: Removed duplicate close call. --- BUILD/compile-ia64-debug-max | 2 +- sql/examples/ha_archive.cc | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/BUILD/compile-ia64-debug-max b/BUILD/compile-ia64-debug-max index 9cd54de428d..56c36059ea9 100755 --- a/BUILD/compile-ia64-debug-max +++ b/BUILD/compile-ia64-debug-max @@ -9,5 +9,5 @@ then (cd gemini && aclocal && autoheader && aclocal && automake && autoconf) fi -CC=ecc CFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" CXX=ecc CXXFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static --with-debug --with-innodb --with-embedded-server +CC=ecc CFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" CXX=ecc CXXFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static --with-debug --with-innodb --with-embedded-server --with-archive-storage-engine gmake diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index 6bf3d485575..491056d0e59 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -405,7 +405,6 @@ int ha_archive::free_share(ARCHIVE_SHARE *share) rc= 1; if (my_close(share->meta_file, MYF(0))) rc= 1; - my_close(share->meta_file,MYF(0)); my_free((gptr) share, MYF(0)); } pthread_mutex_unlock(&archive_mutex); From af39ee001d4c7dbae6aee384802ab0252d2244a1 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Jan 2005 22:28:55 +0200 Subject: [PATCH 06/14] mem0pool.c: Fix an assertion failure in 64-bit computers if UNIV_MEM_DEBUG is defined innobase/mem/mem0pool.c: Fix an assertion failure in 64-bit computers if UNIV_MEM_DEBUG is defined --- innobase/mem/mem0pool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c index cd75728c937..bb1f44d6fb7 100644 --- a/innobase/mem/mem0pool.c +++ b/innobase/mem/mem0pool.c @@ -597,8 +597,8 @@ mem_pool_validate( } } - ut_a(free + pool->reserved == pool->size - - (pool->size % MEM_AREA_MIN_SIZE)); + ut_a(free + pool->reserved == pool->size); + mutex_exit(&(pool->mutex)); return(TRUE); From 4b88e07159d297dfa3a3e89f988e65e86610a9bd Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Jan 2005 17:24:18 -0600 Subject: [PATCH 07/14] Bug #6607 Create table... LIKE... with Windows Symlinks sql_table.cc: use fn_format to resolve symlinks in mysql_create_like_table sql/sql_table.cc: use fn_format to resolve symlinks in mysql_create_like_table --- sql/sql_table.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 423a309767b..f3c107c2696 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2272,8 +2272,7 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, strxmov(src_path, (*tmp_table)->path, reg_ext, NullS); else { - strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table, - reg_ext, NullS); + fn_format( src_path, src_table, src_db, reg_ext, MYF(MY_UNPACK_FILENAME)); if (access(src_path, F_OK)) { my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table); @@ -2300,8 +2299,7 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, } else { - strxmov(dst_path, mysql_data_home, "/", db, "/", table_name, - reg_ext, NullS); + fn_format( dst_path, table_name, db, reg_ext, MYF(MY_UNPACK_FILENAME)); if (!access(dst_path, F_OK)) goto table_exists; } From 199375cbc94eda3d60b9c038037e19a7e9cdf8f4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Jan 2005 23:02:32 -0600 Subject: [PATCH 08/14] Bug #7390 perror.exe doesn't work perror.c: Copy output of strerr to temp buffer to prevent system overwrite on Windows extra/perror.c: Copy output of strerr to temp buffer to prevent system overwrite on Windows --- extra/perror.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/extra/perror.c b/extra/perror.c index 1bd4b203120..fc10d8eaecc 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -184,6 +184,7 @@ int main(int argc,char *argv[]) { int error,code,found; const char *msg; + char *unknown_error = 0; MY_INIT(argv[0]); if (get_options(&argc,&argv)) @@ -212,7 +213,12 @@ int main(int argc,char *argv[]) string 'Unknown Error'. To avoid printing it we try to find the error string by asking for an impossible big error message. */ - const char *unknown_error= strerror(10000); + msg = strerror(10000); + + /* allocate a buffer for unknown_error since strerror always returns the same pointer + on some platforms such as Windows */ + unknown_error = malloc( strlen(msg)+1 ); + strcpy( unknown_error, msg ); for ( ; argc-- > 0 ; argv++) { @@ -262,6 +268,11 @@ int main(int argc,char *argv[]) } } } + + /* if we allocated a buffer for unknown_error, free it now */ + if (unknown_error) + free(unknown_error); + exit(error); return error; } From b95c2d357800867423b2fa98b66fb11ef947ce88 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 11:50:43 +0400 Subject: [PATCH 09/14] character_sets.m4: --with-uca configure.in argument. The rest of the changes are pending from 4.1 tree config/ac-macros/character_sets.m4: --with-uca configure.in argument. The rest of the changes are pending from 4.1 tree --- config/ac-macros/character_sets.m4 | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/config/ac-macros/character_sets.m4 b/config/ac-macros/character_sets.m4 index c83cc63a8aa..6efd31fdb05 100644 --- a/config/ac-macros/character_sets.m4 +++ b/config/ac-macros/character_sets.m4 @@ -405,3 +405,20 @@ AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_CHARSET_NAME], ["$default_charset"], [Define the default charset name]) AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_COLLATION_NAME], ["$default_collation"], [Define the default charset name]) + +# Shall we build the UCA-based Unicode collations +AC_ARG_WITH(uca, + [ --without-uca Skip building of the national Unicode collations.], + [with_uca=$withval], + [with_uca=yes] +) + +AC_MSG_CHECKING([whether to compile national Unicode collations]) + +if test "$with_uca" = "yes" +then + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_UCA_COLLATIONS], [1], [national Unicode collations]) +else + AC_MSG_RESULT(no) +fi From f7606a335e44841e2cac79cc7256b6eb489c7b82 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 14:37:51 +0400 Subject: [PATCH 10/14] Skip cp932 and eucjpms tests when the character sets are not compiled. --- mysql-test/include/have_cp932.inc | 4 ++++ mysql-test/include/have_eucjpms.inc | 4 ++++ mysql-test/r/have_cp932.require | 2 ++ mysql-test/r/have_eucjpms.require | 2 ++ mysql-test/t/ctype_cp932.test | 2 ++ mysql-test/t/ctype_eucjpms.test | 3 +++ 6 files changed, 17 insertions(+) create mode 100644 mysql-test/include/have_cp932.inc create mode 100644 mysql-test/include/have_eucjpms.inc create mode 100644 mysql-test/r/have_cp932.require create mode 100644 mysql-test/r/have_eucjpms.require diff --git a/mysql-test/include/have_cp932.inc b/mysql-test/include/have_cp932.inc new file mode 100644 index 00000000000..b500dac0bbe --- /dev/null +++ b/mysql-test/include/have_cp932.inc @@ -0,0 +1,4 @@ +-- require r/have_cp932.require +disable_query_log; +show collation like "cp932_japanese_ci"; +enable_query_log; diff --git a/mysql-test/include/have_eucjpms.inc b/mysql-test/include/have_eucjpms.inc new file mode 100644 index 00000000000..a5e1a5ac547 --- /dev/null +++ b/mysql-test/include/have_eucjpms.inc @@ -0,0 +1,4 @@ +-- require r/have_eucjpms.require +disable_query_log; +show collation like "eucjpms_japanese_ci"; +enable_query_log; diff --git a/mysql-test/r/have_cp932.require b/mysql-test/r/have_cp932.require new file mode 100644 index 00000000000..988d720ed2c --- /dev/null +++ b/mysql-test/r/have_cp932.require @@ -0,0 +1,2 @@ +Collation Charset Id Default Compiled Sortlen +cp932_japanese_ci cp932 95 Yes Yes 1 diff --git a/mysql-test/r/have_eucjpms.require b/mysql-test/r/have_eucjpms.require new file mode 100644 index 00000000000..f35621b2c1a --- /dev/null +++ b/mysql-test/r/have_eucjpms.require @@ -0,0 +1,2 @@ +Collation Charset Id Default Compiled Sortlen +eucjpms_japanese_ci eucjpms 97 Yes Yes 1 diff --git a/mysql-test/t/ctype_cp932.test b/mysql-test/t/ctype_cp932.test index 24da8a76dcd..fed87af3adc 100644 --- a/mysql-test/t/ctype_cp932.test +++ b/mysql-test/t/ctype_cp932.test @@ -1,3 +1,5 @@ +-- source include/have_cp932.inc + --character_set cp932 --disable_warnings drop table if exists t1; diff --git a/mysql-test/t/ctype_eucjpms.test b/mysql-test/t/ctype_eucjpms.test index 578d116fcb9..cec1e2a9861 100644 --- a/mysql-test/t/ctype_eucjpms.test +++ b/mysql-test/t/ctype_eucjpms.test @@ -1,3 +1,6 @@ +-- source include/have_eucjpms.inc + + --disable_warnings drop table if exists t1; drop table if exists t2; From 0e50e32480920c29f2efacfcbfa35c9c93838840 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 19:48:05 +0000 Subject: [PATCH 11/14] WL#1967 Support for COMMIT/ROLLBACK optional arguments innobase/include/trx0roll.h: WL#1967 trx_release_savepoint_for_mysql() innobase/trx/trx0roll.c: WL#1967 trx_release_savepoint_for_mysql() mysql-test/r/innodb.result: WL#1967 Test for savepoint release mysql-test/t/innodb.test: WL#1967 Test for savepoint release sql/ha_innodb.cc: WL#1967 innobase_release_savepoint_name() sql/ha_innodb.h: WL#1967 innobase_release_savepoint_name() sql/handler.cc: WL#1967 ha_release_savepoint_name() sql/handler.h: WL#1967 ha_release_savepoint_name() sql/lex.h: WL#1967 New tokens: CHAIN, RELEASE sql/mysqld.cc: WL#1967 new option: completion-type sql/set_var.cc: WL#1967 new option: completion-type sql/sql_class.h: WL#1967 new option: completion-type sql/sql_lex.h: WL#1967 Support RELEASE SAVEPOINT additional flags to support COMMIT/ROLLBACK options sql/sql_parse.cc: WL#1967 Transaction operations in mysql_endtrans(), begin_trans() sql/sql_yacc.yy: WL#1967 Support COMMIT/ROLLBACK optional args --- innobase/include/trx0roll.h | 15 +++ innobase/trx/trx0roll.c | 45 ++++++++ mysql-test/r/innodb.result | 34 +++++- mysql-test/t/innodb.test | 13 +++ sql/ha_innodb.cc | 25 +++++ sql/ha_innodb.h | 3 + sql/handler.cc | 29 +++++ sql/handler.h | 1 + sql/lex.h | 2 + sql/mysqld.cc | 6 +- sql/set_var.cc | 23 ++++ sql/sql_class.h | 1 + sql/sql_lex.h | 3 +- sql/sql_parse.cc | 213 ++++++++++++++++++++++++++---------- sql/sql_yacc.yy | 65 +++++++++-- 15 files changed, 402 insertions(+), 76 deletions(-) diff --git a/innobase/include/trx0roll.h b/innobase/include/trx0roll.h index 9d025da4a5f..944142a299d 100644 --- a/innobase/include/trx0roll.h +++ b/innobase/include/trx0roll.h @@ -225,6 +225,21 @@ trx_savepoint_for_mysql( position corresponding to this connection at the time of the savepoint */ + +/*********************************************************************** +Releases a named savepoint. Savepoints which +were set after this savepoint are deleted. */ + +ulint +trx_release_savepoint_for_mysql( +/*================================*/ + /* out: if no savepoint + of the name found then + DB_NO_SAVEPOINT, + otherwise DB_SUCCESS */ + trx_t* trx, /* in: transaction handle */ + const char* savepoint_name); /* in: savepoint name */ + /*********************************************************************** Frees savepoint structs. */ diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c index e5cffd2a4f3..cba3040fd0e 100644 --- a/innobase/trx/trx0roll.c +++ b/innobase/trx/trx0roll.c @@ -316,6 +316,51 @@ trx_savepoint_for_mysql( return(DB_SUCCESS); } +/*********************************************************************** +Releases a named savepoint. Savepoints which +were set after this savepoint are deleted. */ + +ulint +trx_release_savepoint_for_mysql( +/*================================*/ + /* out: if no savepoint + of the name found then + DB_NO_SAVEPOINT, + otherwise DB_SUCCESS */ + trx_t* trx, /* in: transaction handle */ + const char* savepoint_name) /* in: savepoint name */ +{ + trx_named_savept_t* savep; + + savep = UT_LIST_GET_FIRST(trx->trx_savepoints); + + while (savep != NULL) { + if (0 == ut_strcmp(savep->name, savepoint_name)) { + /* Found */ + break; + } + savep = UT_LIST_GET_NEXT(trx_savepoints, savep); + } + + if (savep == NULL) { + + return(DB_NO_SAVEPOINT); + } + + /* We can now free all savepoints strictly later than this one */ + + trx_roll_savepoints_free(trx, savep); + + /* Now we can free this savepoint too */ + + UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); + + mem_free(savep->name); + mem_free(savep); + + return(DB_SUCCESS); +} + /*********************************************************************** Returns a transaction savepoint taken at this point in time. */ diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 8d1c4e3fc90..5928688ca81 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -249,6 +249,30 @@ n 4 5 6 +set autocommit=0; +begin; +savepoint `my_savepoint`; +insert into t1 values (7); +savepoint `savept2`; +insert into t1 values (3); +select n from t1; +n +3 +4 +5 +6 +7 +rollback to savepoint `savept2`; +release savepoint `my_savepoint`; +select n from t1; +n +4 +5 +6 +7 +rollback to savepoint `my_savepoint`; +ERROR HY000: Got error 153 during ROLLBACK +set autocommit=1; rollback; drop table t1; create table t1 (n int not null primary key) engine=innodb; @@ -1609,14 +1633,14 @@ t2 CREATE TABLE `t2` ( drop table t2, t1; show status like "binlog_cache_use"; Variable_name Value -Binlog_cache_use 24 +Binlog_cache_use 25 show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 0 create table t1 (a int) engine=innodb; show status like "binlog_cache_use"; Variable_name Value -Binlog_cache_use 25 +Binlog_cache_use 26 show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 1 @@ -1625,7 +1649,7 @@ delete from t1; commit; show status like "binlog_cache_use"; Variable_name Value -Binlog_cache_use 26 +Binlog_cache_use 27 show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 1 @@ -1693,10 +1717,10 @@ Variable_name Value Innodb_rows_deleted 2070 show status like "Innodb_rows_inserted"; Variable_name Value -Innodb_rows_inserted 31706 +Innodb_rows_inserted 31708 show status like "Innodb_rows_read"; Variable_name Value -Innodb_rows_read 80153 +Innodb_rows_read 80162 show status like "Innodb_rows_updated"; Variable_name Value Innodb_rows_updated 29530 diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 4fff24a61d5..da27fcfc734 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -129,6 +129,19 @@ insert into t1 values (6); -- error 1062 insert into t1 values (4); select n from t1; +set autocommit=0; +begin; +savepoint `my_savepoint`; +insert into t1 values (7); +savepoint `savept2`; +insert into t1 values (3); +select n from t1; +rollback to savepoint `savept2`; +release savepoint `my_savepoint`; +select n from t1; +-- error 1181 +rollback to savepoint `my_savepoint`; +set autocommit=1; # nop rollback; drop table t1; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index d6b6c140fbf..32b203f7ad6 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1612,6 +1612,31 @@ innobase_rollback_to_savepoint( DBUG_RETURN(convert_error_code_to_mysql(error, NULL)); } +/********************************************************************* +Release transaction savepoint name. */ + +int +innobase_release_savepoint_name( +/*===========================*/ + /* out: 0 if success, HA_ERR_NO_SAVEPOINT if + no savepoint with the given name */ + THD* thd, /* in: handle to the MySQL thread of the user + whose transaction should be rolled back */ + char* savepoint_name) /* in: savepoint name */ +{ + ib_longlong mysql_binlog_cache_pos; + int error = 0; + trx_t* trx; + + DBUG_ENTER("innobase_release_savepoint_name"); + + trx = check_trx_exists(thd); + + error = trx_release_savepoint_for_mysql(trx, savepoint_name); + + DBUG_RETURN(convert_error_code_to_mysql(error, NULL)); +} + /********************************************************************* Sets a transaction savepoint. */ diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 2154e238fd1..7a48de52422 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -244,6 +244,9 @@ int innobase_savepoint( THD* thd, char* savepoint_name, my_off_t binlog_cache_pos); +int innobase_release_savepoint_name( + THD* thd, + char* savepoint_name); int innobase_close_connection(THD *thd); int innobase_drop_database(char *path); bool innodb_show_status(THD* thd); diff --git a/sql/handler.cc b/sql/handler.cc index 059d1feaed1..a9bb19158dd 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -869,6 +869,35 @@ int ha_rollback_to_savepoint(THD *thd, char *savepoint_name) DBUG_RETURN(error); } +int ha_release_savepoint_name(THD *thd, char *savepoint_name) +{ + my_off_t binlog_cache_pos=0; + bool operation_done=0; + int error=0; + DBUG_ENTER("ha_release_savepoint_name"); +#ifdef USING_TRANSACTIONS + if (opt_using_transactions) + { +#ifdef HAVE_INNOBASE_DB + if ((error=innobase_release_savepoint_name(thd, savepoint_name))) + { + my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error); + error=1; + } + else if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); + if (mysql_bin_log.write(&qinfo)) + error= 1; + } + operation_done=1; +#endif + } +#endif /* USING_TRANSACTIONS */ + + DBUG_RETURN(error); +} + /* Sets a transaction savepoint. diff --git a/sql/handler.h b/sql/handler.h index e5a794ca1b2..2b5c66fd886 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -653,6 +653,7 @@ int ha_commit_trans(THD *thd, THD_TRANS *trans); int ha_rollback_trans(THD *thd, THD_TRANS *trans); int ha_rollback_to_savepoint(THD *thd, char *savepoint_name); int ha_savepoint(THD *thd, char *savepoint_name); +int ha_release_savepoint_name(THD *thd, char *savepoint_name); int ha_autocommit_or_rollback(THD *thd, int error); void ha_set_spin_retries(uint retries); bool ha_flush_logs(void); diff --git a/sql/lex.h b/sql/lex.h index 871d1d99750..7b03950b35a 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -99,6 +99,7 @@ static SYMBOL symbols[] = { { "CASCADE", SYM(CASCADE)}, { "CASCADED", SYM(CASCADED)}, { "CASE", SYM(CASE_SYM)}, + { "CHAIN", SYM(CHAIN_SYM)}, { "CHANGE", SYM(CHANGE)}, { "CHANGED", SYM(CHANGED)}, { "CHAR", SYM(CHAR_SYM)}, @@ -385,6 +386,7 @@ static SYMBOL symbols[] = { { "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM)}, { "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM)}, { "RELAY_THREAD", SYM(RELAY_THREAD)}, + { "RELEASE", SYM(RELEASE_SYM)}, { "RELOAD", SYM(RELOAD)}, { "RENAME", SYM(RENAME)}, { "REPAIR", SYM(REPAIR)}, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9b39f51fc5b..e4df359d35c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4176,7 +4176,7 @@ enum options_mysqld OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ, OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION, OPT_SKIP_SAFEMALLOC, - OPT_TEMP_POOL, OPT_TX_ISOLATION, + OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE, OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS, OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL, OPT_SAFE_USER_CREATE, OPT_SQL_MODE, @@ -4363,6 +4363,10 @@ Disable with --skip-bdb (will save memory).", {"collation-server", OPT_DEFAULT_COLLATION, "Set the default collation.", (gptr*) &default_collation_name, (gptr*) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + {"completion-type", OPT_COMPLETION_TYPE, "Default completion type.", + (gptr*) &global_system_variables.completion_type, + (gptr*) &max_system_variables.completion_type, 0, GET_ULONG, + REQUIRED_ARG, 0, 0, 2, 0, 1, 0}, {"concurrent-insert", OPT_CONCURRENT_INSERT, "Use concurrent insert with MyISAM. Disable with --skip-concurrent-insert.", (gptr*) &myisam_concurrent_insert, (gptr*) &myisam_concurrent_insert, diff --git a/sql/set_var.cc b/sql/set_var.cc index 7a528467e24..541bcf0ff7d 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -100,6 +100,8 @@ static int check_pseudo_thread_id(THD *thd, set_var *var); static bool set_log_bin(THD *thd, set_var *var); static void fix_low_priority_updates(THD *thd, enum_var_type type); static void fix_tx_isolation(THD *thd, enum_var_type type); +static int check_completion_type(THD *thd, set_var *var); +static void fix_completion_type(THD *thd, enum_var_type type); static void fix_net_read_timeout(THD *thd, enum_var_type type); static void fix_net_write_timeout(THD *thd, enum_var_type type); static void fix_net_retry_count(THD *thd, enum_var_type type); @@ -149,6 +151,10 @@ sys_var_character_set_database sys_character_set_database("character_set_databas sys_var_character_set_client sys_character_set_client("character_set_client"); sys_var_character_set_connection sys_character_set_connection("character_set_connection"); sys_var_character_set_results sys_character_set_results("character_set_results"); +sys_var_thd_ulong sys_completion_type("completion_type", + &SV::completion_type, + check_completion_type, + fix_completion_type); sys_var_collation_connection sys_collation_connection("collation_connection"); sys_var_collation_database sys_collation_database("collation_database"); sys_var_collation_server sys_collation_server("collation_server"); @@ -532,6 +538,7 @@ sys_var *sys_variables[]= &sys_collation_connection, &sys_collation_database, &sys_collation_server, + &sys_completion_type, &sys_concurrent_insert, &sys_connect_timeout, &sys_date_format, @@ -708,6 +715,7 @@ struct show_var_st init_vars[]= { {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS}, {sys_collation_database.name,(char*) &sys_collation_database, SHOW_SYS}, {sys_collation_server.name,(char*) &sys_collation_server, SHOW_SYS}, + {sys_completion_type.name, (char*) &sys_completion_type, SHOW_SYS}, {sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS}, {sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS}, {"datadir", mysql_real_data_home, SHOW_CHAR}, @@ -1122,6 +1130,21 @@ static void fix_tx_isolation(THD *thd, enum_var_type type) thd->variables.tx_isolation); } +static void fix_completion_type(THD *thd __attribute__(unused), + enum_var_type type __attribute__(unused)) {} + +static int check_completion_type(THD *thd, set_var *var) +{ + longlong val= var->value->val_int(); + if (val < 0 || val > 2) + { + char buf[64]; + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf)); + return 1; + } + return 0; +} + /* If we are changing the thread variable, we have to copy it to NET too diff --git a/sql/sql_class.h b/sql/sql_class.h index 8e6204ab3a3..561cf099592 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -408,6 +408,7 @@ struct system_variables ulong table_type; ulong tmp_table_size; ulong tx_isolation; + ulong completion_type; /* Determines which non-standard SQL behaviour should be enabled */ ulong sql_mode; /* check of key presence in updatable view */ diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 6ed5fb247dc..b2c214bf1fa 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -67,7 +67,7 @@ enum enum_sql_command { SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS, SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE, SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT, - SQLCOM_COMMIT, SQLCOM_SAVEPOINT, + SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER, SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE, @@ -718,6 +718,7 @@ typedef struct st_lex uint8 create_view_check; bool drop_if_exists, drop_temporary, local_file, one_shot_set; bool in_comment, ignore_space, verbose, no_write_to_binlog; + bool tx_chain, tx_release; /* special JOIN::prepare mode: changing of query is prohibited */ bool view_prepare_mode; bool safe_to_cache_query; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 820a4f732a3..8b5986a805b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -134,6 +134,27 @@ static bool end_active_trans(THD *thd) DBUG_RETURN(error); } +static bool begin_trans(THD *thd) +{ + int error=0; + if (thd->locked_tables) + { + thd->lock=thd->locked_tables; + thd->locked_tables=0; // Will be automatically closed + close_thread_tables(thd); // Free tables + } + if (end_active_trans(thd)) + error= -1; + else + { + thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) | + OPTION_BEGIN); + thd->server_status|= SERVER_STATUS_IN_TRANS; + if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) + error= ha_start_consistent_snapshot(thd); + } + return error; +} #ifdef HAVE_REPLICATION inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables) @@ -1262,6 +1283,127 @@ err: DBUG_RETURN(error); } +/* + Ends the current transaction and (maybe) begin the next + First uint4 in packet is completion type + Remainder is savepoint name (if required) + + SYNOPSIS + mysql_endtrans() + thd Current thread + completion Completion type + savepoint_name Savepoint when doing ROLLBACK_SAVEPOINT_NAME + or RELEASE_SAVEPOINT_NAME + release (OUT) indicator for release operation + + RETURN + 0 - OK +*/ + +enum enum_mysql_completiontype { + ROLLBACK_RELEASE=-2, + COMMIT_RELEASE=-1, + COMMIT=0, + ROLLBACK=1, + SAVEPOINT_NAME_ROLLBACK=2, + SAVEPOINT_NAME_RELEASE=4, + COMMIT_AND_CHAIN=6, + ROLLBACK_AND_CHAIN=7, +}; + +int mysql_endtrans(THD *thd, enum enum_mysql_completiontype completion, + char *savepoint_name) +{ + bool do_release= 0; + int res= 0; + LEX *lex= thd->lex; + DBUG_ENTER("mysql_endtrans"); + + switch (completion) { + case COMMIT: + /* + We don't use end_active_trans() here to ensure that this works + even if there is a problem with the OPTION_AUTO_COMMIT flag + (Which of course should never happen...) + */ + thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + thd->server_status&= ~SERVER_STATUS_IN_TRANS; + if (!(res= ha_commit(thd))) + send_ok(thd); + break; + case COMMIT_RELEASE: + do_release= 1; + case COMMIT_AND_CHAIN: + res= end_active_trans(thd); + if (!res && completion == COMMIT_AND_CHAIN) + res= begin_trans(thd); + if (!res) + send_ok(thd); + break; + case ROLLBACK_RELEASE: + do_release= 1; + case ROLLBACK: + case ROLLBACK_AND_CHAIN: + { + bool warn= 0; + thd->server_status&= ~SERVER_STATUS_IN_TRANS; + if (!ha_rollback(thd)) + { + /* + If a non-transactional table was updated, warn; don't warn if this is a + slave thread (because when a slave thread executes a ROLLBACK, it has + been read from the binary log, so it's 100% sure and normal to produce + error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the + slave SQL thread, it would not stop the thread but just be printed in + the error log; but we don't want users to wonder why they have this + message in the error log, so we don't send it. + */ + warn= (thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && + !thd->slave_thread; + } + else + res= -1; + thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + if (!res && (completion == ROLLBACK_AND_CHAIN)) + res= begin_trans(thd); + + if (!res) + { + if (warn) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARNING_NOT_COMPLETE_ROLLBACK, + ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); + send_ok(thd); + } + break; + } + case SAVEPOINT_NAME_ROLLBACK: + if (!(res=ha_rollback_to_savepoint(thd, savepoint_name))) + { + if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARNING_NOT_COMPLETE_ROLLBACK, + ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); + send_ok(thd); + } + break; + case SAVEPOINT_NAME_RELEASE: + if (!(res=ha_release_savepoint_name(thd, savepoint_name))) + send_ok(thd); + break; + default: + res= -1; + my_error(ER_UNKNOWN_COM_ERROR, MYF(0)); + DBUG_RETURN(-1); + } + + if (res < 0) + my_error(thd->killed_errno(), MYF(0)); + else if ((res == 0) && do_release) + thd->killed= THD::KILL_CONNECTION; + + DBUG_RETURN(res); +} #ifndef EMBEDDED_LIBRARY @@ -3648,74 +3790,23 @@ unsent_create_error: break; case SQLCOM_BEGIN: - if (thd->locked_tables) - { - thd->lock=thd->locked_tables; - thd->locked_tables=0; // Will be automatically closed - close_thread_tables(thd); // Free tables - } - if (end_active_trans(thd)) + if (begin_trans(thd)) goto error; else - { - thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) | - OPTION_BEGIN); - thd->server_status|= SERVER_STATUS_IN_TRANS; - if (!(lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) || - !(res= ha_start_consistent_snapshot(thd))) - send_ok(thd); - } + send_ok(thd); break; case SQLCOM_COMMIT: - /* - We don't use end_active_trans() here to ensure that this works - even if there is a problem with the OPTION_AUTO_COMMIT flag - (Which of course should never happen...) - */ - { - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); - thd->server_status&= ~SERVER_STATUS_IN_TRANS; - if (!ha_commit(thd)) - { - send_ok(thd); - } - else + if (mysql_endtrans(thd, lex->tx_release ? COMMIT_RELEASE : + lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT, 0)) goto error; break; - } case SQLCOM_ROLLBACK: - thd->server_status&= ~SERVER_STATUS_IN_TRANS; - if (!ha_rollback(thd)) - { - /* - If a non-transactional table was updated, warn; don't warn if this is a - slave thread (because when a slave thread executes a ROLLBACK, it has - been read from the binary log, so it's 100% sure and normal to produce - error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the - slave SQL thread, it would not stop the thread but just be printed in - the error log; but we don't want users to wonder why they have this - message in the error log, so we don't send it. - */ - if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARNING_NOT_COMPLETE_ROLLBACK, - ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); - send_ok(thd); - } - else - res= TRUE; - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + if (mysql_endtrans(thd, lex->tx_release ? ROLLBACK_RELEASE : + lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK, 0)) + goto error; break; case SQLCOM_ROLLBACK_TO_SAVEPOINT: - if (!ha_rollback_to_savepoint(thd, lex->savepoint_name)) - { - if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARNING_NOT_COMPLETE_ROLLBACK, - ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); - send_ok(thd); - } - else + if (mysql_endtrans(thd, SAVEPOINT_NAME_ROLLBACK, lex->savepoint_name)) goto error; break; case SQLCOM_SAVEPOINT: @@ -3724,6 +3815,10 @@ unsent_create_error: else goto error; break; + case SQLCOM_RELEASE_SAVEPOINT: + if (mysql_endtrans(thd, SAVEPOINT_NAME_RELEASE, lex->savepoint_name)) + goto error; + break; case SQLCOM_CREATE_PROCEDURE: case SQLCOM_CREATE_SPFUNCTION: { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cc2443bd41b..e1c7c26060a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -219,6 +219,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token CASCADE %token CASCADED %token CAST_SYM +%token CHAIN_SYM %token CHARSET %token CHECKSUM_SYM %token CHECK_SYM @@ -385,6 +386,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token REDUNDANT_SYM %token REFERENCES %token REGEXP +%token RELEASE_SYM %token RELOAD %token RENAME %token REPEATABLE_SYM @@ -690,7 +692,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct opt_ignore_leaves fulltext_options spatial_type union_option - start_transaction_opts + start_transaction_opts opt_chain opt_work_and_chain opt_release %type ULONG_NUM raid_types merge_insert_types @@ -777,7 +779,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); query verb_clause create change select do drop insert replace insert2 insert_values update delete truncate rename show describe load alter optimize keycache preload flush - reset purge begin commit rollback savepoint + reset purge begin commit rollback savepoint release slave master_def master_defs master_file_def slave_until_opts repair restore backup analyze check start checksum field_list field_list_item field_spec kill column_def key_def @@ -876,6 +878,7 @@ statement: | preload | prepare | purge + | release | rename | repair | replace @@ -6901,6 +6904,7 @@ keyword: | BTREE_SYM {} | CACHE_SYM {} | CASCADED {} + | CHAIN_SYM {} | CHANGED {} | CHARSET {} | CHECKSUM_SYM {} @@ -7854,25 +7858,66 @@ opt_work: | WORK_SYM {;} ; +opt_chain: + /* empty */ { $$= (Lex->thd->variables.completion_type == 1); } + | AND_SYM NO_SYM CHAIN_SYM { $$=0; } + | AND_SYM CHAIN_SYM { $$=1; } + ; + +opt_release: + /* empty */ { $$= (Lex->thd->variables.completion_type == 2); } + | RELEASE_SYM { $$=1; } + | NO_SYM RELEASE_SYM { $$=0; } + ; + +opt_work_and_chain: + opt_work opt_chain { $$=$2; } + ; + +opt_savepoint: + /* empty */ {} + | SAVEPOINT_SYM {} + ; + commit: - COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;}; + COMMIT_SYM opt_work_and_chain opt_release + { + Lex->sql_command= SQLCOM_COMMIT; + Lex->tx_chain= $2; + Lex->tx_release= $3; + } + ; rollback: - ROLLBACK_SYM - { - Lex->sql_command = SQLCOM_ROLLBACK; + ROLLBACK_SYM opt_work_and_chain opt_release + { + Lex->sql_command= SQLCOM_ROLLBACK; + Lex->tx_chain= $2; + Lex->tx_release= $3; } - | ROLLBACK_SYM TO_SYM SAVEPOINT_SYM ident + | ROLLBACK_SYM opt_work + TO_SYM opt_savepoint ident { Lex->sql_command = SQLCOM_ROLLBACK_TO_SAVEPOINT; - Lex->savepoint_name = $4.str; - }; + Lex->savepoint_name = $5.str; + } + ; + savepoint: SAVEPOINT_SYM ident { Lex->sql_command = SQLCOM_SAVEPOINT; Lex->savepoint_name = $2.str; - }; + } + ; + +release: + RELEASE_SYM SAVEPOINT_SYM ident + { + Lex->sql_command = SQLCOM_RELEASE_SAVEPOINT; + Lex->savepoint_name = $3.str; + } + ; /* UNIONS : glue selects together From 7d2dcab3a2b67c0dc32846e5ca4e59a9c3cb553b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 23:55:41 +0200 Subject: [PATCH 12/14] InnoDB: Fix debug compile error on Tru64 (Bug #8244) innobase/include/rem0rec.ic: Eliminate int16_t from an assertion, as it is not defined in the same system headers on all platforms. (Bug #8244) --- innobase/include/rem0rec.ic | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 366f1c3f77d..2593fb8edeb 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -279,7 +279,15 @@ rec_get_next_offs( /* Note that for 64 KiB pages, field_value can 'wrap around' and the debug assertion is not valid */ - ut_ad((int16_t)field_value + /* In the following assertion, field_value is interpreted + as signed 16-bit integer in 2's complement arithmetics. + If all platforms defined int16_t in the standard headers, + the expression could be written simpler as + (int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE + */ + ut_ad((field_value >= 32768 + ? field_value - 65536 + : field_value) + ut_align_offset(rec, UNIV_PAGE_SIZE) < UNIV_PAGE_SIZE); #endif From 099f50b67f2a9e87b2e5d996430410533e578454 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 23:43:09 +0000 Subject: [PATCH 13/14] Fix compile problem - line missing. sql/sql_parse.cc: typo - line awol during commit. --- sql/sql_parse.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8b5986a805b..05d6a00805c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -147,6 +147,7 @@ static bool begin_trans(THD *thd) error= -1; else { + LEX *lex= thd->lex; thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) | OPTION_BEGIN); thd->server_status|= SERVER_STATUS_IN_TRANS; From 2ae812a7d6f5e8789143565364f9700c39c6a424 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 07:51:43 +0300 Subject: [PATCH 14/14] Adjust test results for BUG#7634: The result of EXPLAIN is different if OS doesn't support file sizes > 2G --- mysql-test/r/index_merge.result | 8 ++++---- mysql-test/t/index_merge.test | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index 0f217b7b8ab..693cc63ba9e 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -371,11 +371,11 @@ alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(20 update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500; explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5) from t0 as A, t0 as B -where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1) -and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1); +where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7or16 = 1 or A.key8=1) +and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7or16 = 1 or B.key8=1); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7,i8 i2,i3,i4,i5,i6,i8 4,4,4,4,4,4 NULL 16 Using union(intersect(i2,i3,i4,i5,i6),i8); Using where -1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7,i8 i2,i3,i4,i5,i6,i8 4,4,4,4,4,4 NULL 16 Using union(intersect(i2,i3,i4,i5,i6),i8); Using where +1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL 7or16 Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where +1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL 7or16 Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5) from t0 as A, t0 as B where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1) diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test index f2f71cbe208..5acbcd8eaeb 100644 --- a/mysql-test/t/index_merge.test +++ b/mysql-test/t/index_merge.test @@ -306,6 +306,11 @@ select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(200); update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500; + +# The next query will not use index i7 in intersection if the OS doesn't +# support file sizes > 2GB. (ha_myisam::ref_length depends on this and index +# scan cost estimates depend on ha_myisam::ref_length) +--replace_result "4,4,4,4,4,4,4" X "4,4,4,4,4,4" X "i6,i7" "i6,i7?" "i6" "i6,i7?" 7 7or16 16 7or16 explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5) from t0 as A, t0 as B where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)