diff --git a/CMakeLists.txt b/CMakeLists.txt index 873a73be0ec..d2b6162ba26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,9 @@ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") ADD_DEFINITIONS(-DMYSQL_SERVER -D_WIN32 -DWIN32 -D_LIB) +IF(EMBEDDED_ONLY) + ADD_DEFINITIONS(-DUSE_TLS) +ENDIF(EMBEDDED_ONLY) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib include diff --git a/Makefile.am b/Makefile.am index 5c15b60f10d..30e056d68fb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -154,8 +154,8 @@ libinnobase_a_SOURCES = btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \ ut/ut0ut.c ut/ut0vec.c ut/ut0wqueue.c \ handler/ha_innodb.cc -libinnobase_a_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_SERVER -libinnobase_a_CFLAGS = $(AM_CFLAGS) -DMYSQL_SERVER +libinnobase_a_CXXFLAGS= $(AM_CFLAGS) +libinnobase_a_CFLAGS = $(AM_CFLAGS) EXTRA_LTLIBRARIES = ha_innodb.la pkglib_LTLIBRARIES = @plugin_innobase_shared_target@ diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index 74fa87ed8f7..0cd795d72e1 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -40,22 +40,7 @@ have disabled the InnoDB inlining in this file. */ #include "ha_innodb.h" #include -#ifdef MYSQL_SERVER -/* Define some macros until these functions are declared in . -Once these functions are defined by MySQL, we may consider -removing -DMYSQL_SERVER from ../Makefile.am as well. */ -#define thd_charset(thd) (thd)->charset() -#define thd_get_xid(thd,xid_) ((*xid_) = (thd)->transaction.xid_state.xid) -#define thd_memdup(thd,str,len) (thd)->memdup(str, len) -#define thd_killed(thd) (thd)->killed -#define thd_slave_thread(thd) (thd)->slave_thread -#define thd_query(thd) (&(thd)->query) -#define thd_non_transactional_update(thd) ((thd)->no_trans_update.all) -#define mysql_bin_log_file_name() mysql_bin_log.get_log_fname() -#define mysql_bin_log_file_pos() mysql_bin_log.get_log_file()->pos_in_file -/*#define mysql_tmpfile() fileno(tmpfile())/* BUGGY: leaks memory, Bug #3998 */ -#define mysql_query_cache_invalidate4(a,b,c,d) query_cache.invalidate(a,b,c,d) -#else /* MYSQL_SERVER */ +#ifndef MYSQL_SERVER /* This is needed because of Bug #3596. Let us hope that pthread_mutex_t is defined the same in both builds: the MySQL server and the InnoDB plugin. */ extern pthread_mutex_t LOCK_thread_count; @@ -87,30 +72,30 @@ typedef uchar mysql_byte; /* Include necessary InnoDB headers */ extern "C" { -#include "univ.i" -#include "os0file.h" -#include "os0thread.h" -#include "srv0start.h" -#include "srv0srv.h" -#include "trx0roll.h" -#include "trx0trx.h" -#include "trx0sys.h" -#include "mtr0mtr.h" -#include "row0ins.h" -#include "row0mysql.h" -#include "row0sel.h" -#include "row0upd.h" -#include "log0log.h" -#include "lock0lock.h" -#include "dict0crea.h" -#include "btr0cur.h" -#include "btr0btr.h" -#include "fsp0fsp.h" -#include "sync0sync.h" -#include "fil0fil.h" -#include "trx0xa.h" -#include "thr0loc.h" -#include "ha_prototypes.h" +#include "../storage/innobase/include/univ.i" +#include "../storage/innobase/include/os0file.h" +#include "../storage/innobase/include/os0thread.h" +#include "../storage/innobase/include/srv0start.h" +#include "../storage/innobase/include/srv0srv.h" +#include "../storage/innobase/include/trx0roll.h" +#include "../storage/innobase/include/trx0trx.h" +#include "../storage/innobase/include/trx0sys.h" +#include "../storage/innobase/include/mtr0mtr.h" +#include "../storage/innobase/include/row0ins.h" +#include "../storage/innobase/include/row0mysql.h" +#include "../storage/innobase/include/row0sel.h" +#include "../storage/innobase/include/row0upd.h" +#include "../storage/innobase/include/log0log.h" +#include "../storage/innobase/include/lock0lock.h" +#include "../storage/innobase/include/dict0crea.h" +#include "../storage/innobase/include/btr0cur.h" +#include "../storage/innobase/include/btr0btr.h" +#include "../storage/innobase/include/fsp0fsp.h" +#include "../storage/innobase/include/sync0sync.h" +#include "../storage/innobase/include/fil0fil.h" +#include "../storage/innobase/include/trx0xa.h" +#include "../storage/innobase/include/thr0loc.h" +#include "../storage/innobase/include/ha_prototypes.h" } static long innobase_mirrored_log_groups, innobase_log_files_in_group, @@ -665,7 +650,7 @@ convert_error_code_to_mysql( } else if (error == (int) DB_TABLE_NOT_FOUND) { - return(HA_ERR_KEY_NOT_FOUND); + return(HA_ERR_NO_SUCH_TABLE); } else if (error == (int) DB_TOO_BIG_RECORD) { @@ -893,7 +878,28 @@ innobase_mysql_tmpfile(void) /*========================*/ /* out: temporary file descriptor, or < 0 on error */ { - return(mysql_tmpfile()); + int fd2 = -1; + File fd = mysql_tmpfile("ib"); + if (fd >= 0) { + /* Copy the file descriptor, so that the additional resources + allocated by create_temp_file() can be freed by invoking + my_close(). + + Because the file descriptor returned by this function + will be passed to fdopen(), it will be closed by invoking + fclose(), which in turn will invoke close() instead of + my_close(). */ + fd2 = dup(fd); + if (fd2 < 0) { + DBUG_PRINT("error",("Got error %d on dup",fd2)); + my_errno=errno; + my_error(EE_OUT_OF_FILERESOURCES, + MYF(ME_BELL+ME_WAITTANG), + "ib*", my_errno); + } + my_close(fd, MYF(MY_WME)); + } + return(fd2); } /************************************************************************* @@ -941,6 +947,8 @@ check_trx_exists( /* Update the info whether we should skip XA steps that eat CPU time */ trx->support_xa = THDVAR(thd, support_xa); + + thd_to_trx(thd) = trx; } else { if (trx->magic_n != TRX_MAGIC_N) { mem_analyze_corruption(trx); @@ -976,6 +984,7 @@ ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg) HA_CAN_SQL_HANDLER | HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_PRIMARY_KEY_IN_READ_INDEX | + HA_BINLOG_ROW_CAPABLE | HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ | HA_TABLE_SCAN_ON_INDEX), start_of_scan(0), @@ -1683,7 +1692,6 @@ innobase_init( DBUG_RETURN(FALSE); error: - innobase_hton->state = SHOW_OPTION_DISABLED; DBUG_RETURN(TRUE); } @@ -2300,6 +2308,21 @@ ha_innobase::get_row_type() const return(ROW_TYPE_NOT_USED); } + + +/******************************************************************** +Get the table flags to use for the statement. */ +handler::Table_flags +ha_innobase::table_flags() const +{ + /* Need to use tx_isolation here since table flags is (also) + called before prebuilt is inited. */ + ulong const tx_isolation = thd_tx_isolation(current_thd); + if (tx_isolation <= ISO_READ_COMMITTED) + return int_table_flags; + return int_table_flags | HA_BINLOG_STMT_CAPABLE; +} + /******************************************************************** Gives the file extension of an InnoDB single-table tablespace. */ static const char* ha_innobase_exts[] = { @@ -6105,8 +6128,8 @@ ha_innobase::get_foreign_key_list(THD *thd, List *f_key_list) while (tmp_buff[i] != '/') i++; tmp_buff+= i + 1; - f_key_info.forein_id= make_lex_string(thd, 0, tmp_buff, - (uint) strlen(tmp_buff), 1); + f_key_info.forein_id = thd_make_lex_string(thd, 0, + tmp_buff, (uint) strlen(tmp_buff), 1); tmp_buff= foreign->referenced_table_name; /* Database name */ @@ -6118,22 +6141,23 @@ ha_innobase::get_foreign_key_list(THD *thd, List *f_key_list) } db_name[i]= 0; ulen= filename_to_tablename(db_name, uname, sizeof(uname)); - f_key_info.referenced_db= make_lex_string(thd, 0, uname, ulen, 1); + f_key_info.referenced_db = thd_make_lex_string(thd, 0, + uname, ulen, 1); /* Table name */ tmp_buff+= i + 1; ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname)); - f_key_info.referenced_table= make_lex_string(thd, 0, uname, - ulen, 1); + f_key_info.referenced_table = thd_make_lex_string(thd, 0, + uname, ulen, 1); for (i= 0;;) { tmp_buff= foreign->foreign_col_names[i]; - name= make_lex_string(thd, name, tmp_buff, - (uint) strlen(tmp_buff), 1); + name = thd_make_lex_string(thd, name, + tmp_buff, (uint) strlen(tmp_buff), 1); f_key_info.foreign_fields.push_back(name); tmp_buff= foreign->referenced_col_names[i]; - name= make_lex_string(thd, name, tmp_buff, - (uint) strlen(tmp_buff), 1); + name = thd_make_lex_string(thd, name, + tmp_buff, (uint) strlen(tmp_buff), 1); f_key_info.referenced_fields.push_back(name); if (++i >= foreign->n_fields) break; @@ -6160,8 +6184,8 @@ ha_innobase::get_foreign_key_list(THD *thd, List *f_key_list) length=8; tmp_buff= "RESTRICT"; } - f_key_info.delete_method= make_lex_string(thd, f_key_info.delete_method, - tmp_buff, length, 1); + f_key_info.delete_method = thd_make_lex_string( + thd, f_key_info.delete_method, tmp_buff, length, 1); if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) @@ -6184,19 +6208,19 @@ ha_innobase::get_foreign_key_list(THD *thd, List *f_key_list) length=8; tmp_buff= "RESTRICT"; } - f_key_info.update_method= make_lex_string(thd, f_key_info.update_method, - tmp_buff, length, 1); + f_key_info.update_method = thd_make_lex_string( + thd, f_key_info.update_method, tmp_buff, length, 1); if (foreign->referenced_index && foreign->referenced_index->name) { - f_key_info.referenced_key_name= - make_lex_string(thd, f_key_info.referenced_key_name, - foreign->referenced_index->name, - strlen(foreign->referenced_index->name), 1); + f_key_info.referenced_key_name = thd_make_lex_string( + thd, f_key_info.referenced_key_name, + foreign->referenced_index->name, + strlen(foreign->referenced_index->name), 1); } FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *) - thd_memdup(thd, &f_key_info, sizeof f_key_info); + thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO)); f_key_list->push_back(pf_key_info); foreign = UT_LIST_GET_NEXT(foreign_list, foreign); } @@ -6459,6 +6483,29 @@ ha_innobase::external_lock( update_thd(thd); + /* Statement based binlogging does not work in isolation level + READ UNCOMMITTED and READ COMMITTED since the necessary + locks cannot be taken. In this case, we print an + informative error message and return with an error. */ + if (lock_type == F_WRLCK) + { + ulong const binlog_format= thd_binlog_format(thd); + ulong const tx_isolation = thd_tx_isolation(current_thd); + if (tx_isolation <= ISO_READ_COMMITTED && + binlog_format == BINLOG_FORMAT_STMT) + { + char buf[256]; + my_snprintf(buf, sizeof(buf), + "Transaction level '%s' in" + " InnoDB is not safe for binlog mode '%s'", + tx_isolation_names[tx_isolation], + binlog_format_names[binlog_format]); + my_error(ER_BINLOG_LOGGING_IMPOSSIBLE, MYF(0), buf); + DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE); + } + } + + trx = prebuilt->trx; prebuilt->sql_stat_start = TRUE; @@ -6703,10 +6750,6 @@ innodb_show_status( DBUG_ENTER("innodb_show_status"); - if (hton->state != SHOW_OPTION_YES) { - DBUG_RETURN(FALSE); - } - trx = check_trx_exists(thd); innobase_release_stat_resources(trx); @@ -7685,7 +7728,7 @@ innobase_xa_prepare( return(0); } - thd_get_xid(thd, &trx->xid); + thd_get_xid(thd, (MYSQL_XID*) &trx->xid); /* Release a possible FIFO ticket and search latch. Since we will reserve the kernel mutex, we have to release the search system latch diff --git a/handler/ha_innodb.h b/handler/ha_innodb.h index b74774ed6ad..36216f06f9f 100644 --- a/handler/ha_innodb.h +++ b/handler/ha_innodb.h @@ -57,7 +57,7 @@ class ha_innobase: public handler ulong upd_and_key_val_buff_len; /* the length of each of the previous two buffers */ - ulong int_table_flags; + Table_flags int_table_flags; uint primary_key; ulong start_of_scan; /* this is set to 1 when we are starting a table scan but have not @@ -92,7 +92,7 @@ class ha_innobase: public handler const char* table_type() const { return("InnoDB");} const char *index_type(uint key_number) { return "BTREE"; } const char** bas_ext() const; - ulonglong table_flags() const { return int_table_flags; } + Table_flags table_flags() const; ulong index_flags(uint idx, uint part, bool all_parts) const { return (HA_READ_NEXT | @@ -198,6 +198,52 @@ class ha_innobase: public handler uint table_changes); }; +/* Some accessor functions which the InnoDB plugin needs, but which +can not be added to mysql/plugin.h as part of the public interface; +the definitions are bracketed with #ifdef INNODB_COMPATIBILITY_HOOKS */ + +#ifndef INNODB_COMPATIBILITY_HOOKS +#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS +#endif + +extern "C" { +struct charset_info_st *thd_charset(MYSQL_THD thd); +char **thd_query(MYSQL_THD thd); + +/** Get the file name of the MySQL binlog. + * @return the name of the binlog file + */ +const char* mysql_bin_log_file_name(void); + +/** Get the current position of the MySQL binlog. + * @return byte offset from the beginning of the binlog + */ +ulonglong mysql_bin_log_file_pos(void); + +/** + Check if a user thread is a replication slave thread + @param thd user thread + @retval 0 the user thread is not a replication slave thread + @retval 1 the user thread is a replication slave thread +*/ +int thd_slave_thread(const MYSQL_THD thd); + +/** + Check if a user thread is running a non-transactional update + @param thd user thread + @retval 0 the user thread is not running a non-transactional update + @retval 1 the user thread is running a non-transactional update +*/ +int thd_non_transactional_update(const MYSQL_THD thd); + +/** + Get the user thread's binary logging format + @param thd user thread + @return Value to be used as index into the binlog_format_names array +*/ +int thd_binlog_format(const MYSQL_THD thd); +} + /* don't delete it - it may be re-enabled later as an optimization for the most common case InnoDB+binlog diff --git a/mysql-test/have_innodb.inc b/mysql-test/have_innodb.inc index be8850725e5..cbffe6a2574 100644 --- a/mysql-test/have_innodb.inc +++ b/mysql-test/have_innodb.inc @@ -1,4 +1,4 @@ disable_query_log; --require r/true.require -select support = 'Enabled' as `TRUE` from information_schema.engines where engine = 'innodb'; +select (support = 'YES' or support = 'DEFAULT') as `TRUE` from information_schema.engines where engine = 'innodb'; enable_query_log; diff --git a/mysql-test/innodb.result b/mysql-test/innodb.result index b1160d9ba2d..804c4b81c17 100644 --- a/mysql-test/innodb.result +++ b/mysql-test/innodb.result @@ -1086,6 +1086,39 @@ n d 1 30 2 20 drop table t1,t2; +CREATE TABLE `t1` ( +`a` int(11) NOT NULL auto_increment, +`b` int(11) default NULL, +PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; +CREATE TABLE `t2` ( +`a` int(11) NOT NULL auto_increment, +`b` int(11) default NULL, +PRIMARY KEY (`a`) +) ENGINE=INNODB DEFAULT CHARSET=latin1 ; +insert into t1 values (1,1),(2,2); +insert into t2 values (1,1),(4,4); +reset master; +UPDATE t2,t1 SET t2.a=t1.a+2; +ERROR 23000: Duplicate entry '3' for key 'PRIMARY' +select * from t2 /* must be (3,1), (4,4) */; +a b +1 1 +4 4 +show master status /* there must no UPDATE in binlog */; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 106 +delete from t1; +delete from t2; +insert into t1 values (1,2),(3,4),(4,4); +insert into t2 values (1,2),(3,4),(4,4); +reset master; +UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a; +ERROR 23000: Duplicate entry '4' for key 'PRIMARY' +show master status /* there must be no UPDATE query event */; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 106 +drop table t1, t2; create table t1 (a int, b int) engine=innodb; insert into t1 values(20,null); select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on @@ -1607,7 +1640,7 @@ t2 CREATE TABLE `t2` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t2; create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; -ERROR HY000: Can't create table 'test.t2' (errno: 150) +ERROR 42000: Incorrect foreign key definition for 't1_id_fk': Key reference and table reference don't match create table t2 (a int auto_increment primary key, b int, index(b), foreign key (b) references t1(id), unique(b)) engine=innodb; show create table t2; Table Create Table @@ -1632,30 +1665,6 @@ t2 CREATE TABLE `t2` ( CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t2, t1; -flush status; -show status like "binlog_cache_use"; -Variable_name Value -Binlog_cache_use 0 -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 1 -show status like "binlog_cache_disk_use"; -Variable_name Value -Binlog_cache_disk_use 1 -begin; -delete from t1; -commit; -show status like "binlog_cache_use"; -Variable_name Value -Binlog_cache_use 2 -show status like "binlog_cache_disk_use"; -Variable_name Value -Binlog_cache_disk_use 1 -drop table t1; create table t1 (c char(10), index (c,c)) engine=innodb; ERROR 42S21: Duplicate column name 'c' create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1)) engine=innodb; @@ -1775,13 +1784,13 @@ Variable_name Value Innodb_page_size 16384 show status like "Innodb_rows_deleted"; Variable_name Value -Innodb_rows_deleted 2070 +Innodb_rows_deleted 72 show status like "Innodb_rows_inserted"; Variable_name Value -Innodb_rows_inserted 3083 +Innodb_rows_inserted 1088 show status like "Innodb_rows_updated"; Variable_name Value -Innodb_rows_updated 886 +Innodb_rows_updated 888 show status like "Innodb_row_lock_waits"; Variable_name Value Innodb_row_lock_waits 0 diff --git a/mysql-test/innodb.test b/mysql-test/innodb.test index 4d3b2be41c2..140aac3b9c3 100644 --- a/mysql-test/innodb.test +++ b/mysql-test/innodb.test @@ -13,6 +13,11 @@ -- source include/not_embedded.inc -- source include/have_innodb.inc +-- source include/have_log_bin.inc + +# Disabling it temporarily for statement-based logging since some +# tests are not safe while binlog is on. +-- source include/have_binlog_format_mixed_or_row.inc # # Small basic test with ignore @@ -53,7 +58,7 @@ INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2), update t1 set parent_id=parent_id+100; select * from t1 where parent_id=102; update t1 set id=id+1000; --- error ER_DUP_ENTRY_WITH_KEY_NAME,1022 +-- error ER_DUP_ENTRY,1022 update t1 set id=1024 where id=1009; select * from t1; update ignore t1 set id=id+1; # This will change all rows @@ -134,13 +139,13 @@ commit; select n, "after commit" from t1; commit; insert into t1 values (5); --- error ER_DUP_ENTRY_WITH_KEY_NAME +-- error ER_DUP_ENTRY insert into t1 values (4); commit; select n, "after commit" from t1; set autocommit=1; insert into t1 values (6); --- error ER_DUP_ENTRY_WITH_KEY_NAME +-- error ER_DUP_ENTRY insert into t1 values (4); select n from t1; set autocommit=0; @@ -214,7 +219,7 @@ drop table t1; CREATE TABLE t1 (id char(8) not null primary key, val int not null) engine=innodb; insert into t1 values ('pippo', 12); --- error ER_DUP_ENTRY_WITH_KEY_NAME +-- error ER_DUP_ENTRY insert into t1 values ('pippo', 12); # Gives error delete from t1; delete from t1 where id = 'pippo'; @@ -342,9 +347,9 @@ CREATE TABLE t1 ( insert into t1 (ggid,passwd) values ('test1','xxx'); insert into t1 (ggid,passwd) values ('test2','yyy'); --- error ER_DUP_ENTRY_WITH_KEY_NAME +-- error ER_DUP_ENTRY insert into t1 (ggid,passwd) values ('test2','this will fail'); --- error ER_DUP_ENTRY_WITH_KEY_NAME +-- error ER_DUP_ENTRY insert into t1 (ggid,id) values ('this will fail',1); select * from t1 where ggid='test1'; @@ -353,7 +358,7 @@ select * from t1 where id=2; replace into t1 (ggid,id) values ('this will work',1); replace into t1 (ggid,passwd) values ('test2','this will work'); --- error ER_DUP_ENTRY_WITH_KEY_NAME +-- error ER_DUP_ENTRY update t1 set id=100,ggid='test2' where id=1; select * from t1; select * from t1 where id=1; @@ -524,7 +529,7 @@ drop table t1; create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) engine=innodb; insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL'); LOCK TABLES t1 WRITE; ---error ER_DUP_ENTRY_WITH_KEY_NAME +--error ER_DUP_ENTRY insert into t1 values (99,1,2,'D'),(1,1,2,'D'); select id from t1; select id from t1; @@ -535,7 +540,7 @@ create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(3 insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL'); LOCK TABLES t1 WRITE; begin; ---error ER_DUP_ENTRY_WITH_KEY_NAME +--error ER_DUP_ENTRY insert into t1 values (99,1,2,'D'),(1,1,2,'D'); select id from t1; insert ignore into t1 values (100,1,2,'D'),(1,1,99,'D'); @@ -754,6 +759,45 @@ select * from t1; select * from t2; drop table t1,t2; +# +# Bug#27716 multi-update did partially and has not binlogged +# + +CREATE TABLE `t1` ( + `a` int(11) NOT NULL auto_increment, + `b` int(11) default NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; + +CREATE TABLE `t2` ( + `a` int(11) NOT NULL auto_increment, + `b` int(11) default NULL, + PRIMARY KEY (`a`) +) ENGINE=INNODB DEFAULT CHARSET=latin1 ; + +# A. testing multi_update::send_eof() execution branch +insert into t1 values (1,1),(2,2); +insert into t2 values (1,1),(4,4); +reset master; +--error ER_DUP_ENTRY +UPDATE t2,t1 SET t2.a=t1.a+2; +# check +select * from t2 /* must be (3,1), (4,4) */; +show master status /* there must no UPDATE in binlog */; + +# B. testing multi_update::send_error() execution branch +delete from t1; +delete from t2; +insert into t1 values (1,2),(3,4),(4,4); +insert into t2 values (1,2),(3,4),(4,4); +reset master; +--error ER_DUP_ENTRY +UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a; +show master status /* there must be no UPDATE query event */; + +# cleanup bug#27716 +drop table t1, t2; + # # Testing of IFNULL # @@ -1134,7 +1178,7 @@ drop table t2; # Clean up filename -- embedded server reports whole path without .frm, # regular server reports relative path with .frm (argh!) --replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t2.frm t2 ---error 1005 +--error ER_WRONG_FK_DEF create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; # bug#3749 @@ -1147,41 +1191,6 @@ show create table t2; drop table t2, t1; -# -# Let us test binlog_cache_use and binlog_cache_disk_use status vars. -# Actually this test has nothing to do with innodb per se, it just requires -# transactional table. -# -flush status; -show status like "binlog_cache_use"; -show status like "binlog_cache_disk_use"; - -create table t1 (a int) engine=innodb; - -# Now we are going to create transaction which is long enough so its -# transaction binlog will be flushed to disk... -let $1=2000; -disable_query_log; -begin; -while ($1) -{ - eval insert into t1 values( $1 ); - dec $1; -} -commit; -enable_query_log; -show status like "binlog_cache_use"; -show status like "binlog_cache_disk_use"; - -# Transaction which should not be flushed to disk and so should not -# increase binlog_cache_disk_use. -begin; -delete from t1; -commit; -show status like "binlog_cache_use"; -show status like "binlog_cache_disk_use"; -drop table t1; - # # Bug #6126: Duplicate columns in keys gives misleading error message # @@ -1408,7 +1417,7 @@ create table t1 (rowid int not null auto_increment, val int not null,primary key (rowid), unique(val)) engine=innodb; replace into t1 (val) values ('1'),('2'); replace into t1 (val) values ('1'),('2'); ---error ER_DUP_ENTRY_WITH_KEY_NAME +--error ER_DUP_ENTRY insert into t1 (val) values ('1'),('2'); select * from t1; drop table t1; @@ -1421,7 +1430,7 @@ create table t1 (a int not null auto_increment primary key, val int) engine=Inno insert into t1 (val) values (1); update t1 set a=2 where a=1; # We should get the following error because InnoDB does not update the counter ---error ER_DUP_ENTRY_WITH_KEY_NAME +--error ER_DUP_ENTRY insert into t1 (val) values (1); select * from t1; drop table t1; @@ -1744,13 +1753,13 @@ create table t3 (s1 varchar(2) binary,primary key (s1)) engine=innodb; create table t4 (s1 char(2) binary,primary key (s1)) engine=innodb; insert into t1 values (0x41),(0x4120),(0x4100); --- error ER_DUP_ENTRY_WITH_KEY_NAME +-- error ER_DUP_ENTRY insert into t2 values (0x41),(0x4120),(0x4100); insert into t2 values (0x41),(0x4120); --- error ER_DUP_ENTRY_WITH_KEY_NAME +-- error ER_DUP_ENTRY insert into t3 values (0x41),(0x4120),(0x4100); insert into t3 values (0x41),(0x4100); --- error ER_DUP_ENTRY_WITH_KEY_NAME +-- error ER_DUP_ENTRY insert into t4 values (0x41),(0x4120),(0x4100); insert into t4 values (0x41),(0x4100); select hex(s1) from t1; diff --git a/mysql-test/innodb_trx_weight.test b/mysql-test/innodb_trx_weight.test index 27698323ce0..b72eaad345f 100644 --- a/mysql-test/innodb_trx_weight.test +++ b/mysql-test/innodb_trx_weight.test @@ -10,12 +10,18 @@ SET storage_engine=InnoDB; -# we do not really care about what gets output-ed, we are only +# we do not really care about what gets printed, we are only # interested in getting the deadlock resolved according to our # expectations -- disable_query_log -- disable_result_log +# we want to use "-- eval statement1; statement2" which does not work with +# prepared statements. Because this test should not behave differently with +# or without prepared statements we disable them so the test does not fail +# if someone runs ./mysql-test-run.pl --ps-protocol +-- disable_ps_protocol + -- disable_warnings DROP TABLE IF EXISTS t1, t2, t3, t4, t5_nontrans; -- enable_warnings diff --git a/plug.in b/plug.in index 3ae8a37ab22..6e26a7d3376 100644 --- a/plug.in +++ b/plug.in @@ -3,7 +3,6 @@ MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine], MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase]) MYSQL_PLUGIN_STATIC(innobase, [libinnobase.a]) MYSQL_PLUGIN_DYNAMIC(innobase, [ha_innodb.la]) -MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(innobase, [handler/ha_innodb.cc]) MYSQL_PLUGIN_ACTIONS(innobase, [ AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"]) AC_SUBST(innodb_system_libs) @@ -41,5 +40,4 @@ MYSQL_PLUGIN_ACTIONS(innobase, [ CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";; esac ]) -MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(innobase, [handler/ha_innodb.cc])