From 8f4d1026de4fdac693da5639e5c6f3f6753075fa Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Mon, 21 Sep 2009 15:20:14 -0700 Subject: [PATCH 001/344] The mysql command line client ignored the --skip-column-names option when used in conjunction with --vertical. (Bug #47147, patch by Harrison Fisk) --- client/mysql.cc | 3 ++- mysql-test/r/mysql.result | 11 ++++++++--- mysql-test/t/mysql.test | 5 +++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index bafd173343e..c579d0ccaaa 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -3510,7 +3510,8 @@ print_table_data_vertically(MYSQL_RES *result) for (uint off=0; off < mysql_num_fields(result); off++) { field= mysql_fetch_field(result); - tee_fprintf(PAGER, "%*s: ",(int) max_length,field->name); + if (column_names) + tee_fprintf(PAGER, "%*s: ",(int) max_length,field->name); if (cur[off]) { unsigned int i; diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index c02073df677..32917888b81 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -162,8 +162,8 @@ ERROR 1049 (42000) at line 1: Unknown database 'invalid' ERROR 1049 (42000) at line 1: Unknown database 'invalid' Test connect with dbname + hostname Test connect with dbname + _invalid_ hostname -ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'invalid_hostname' (errno) -ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'invalid_hostname' (errno) +ERROR 2003 (HY000) at line 1: Can't connect to MySQL server on 'invalid_hostname' (errno) +ERROR 2003 (HY000) at line 1: Can't connect to MySQL server on 'invalid_hostname' (errno) The commands reported in the bug report ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'cyril has found a bug :)XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' (errno) Too long dbname @@ -198,7 +198,7 @@ COUNT (*) 1 COUNT (*) 1 -ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'invalid_hostname' (errno) +ERROR 2003 (HY000) at line 1: Can't connect to MySQL server on 'invalid_hostname' (errno) End of 5.0 tests WARNING: --server-arg option not supported in this configuration. Warning (Code 1286): Unknown table engine 'nonexistent' @@ -230,4 +230,9 @@ a: b drop table t1; +Bug #47147: mysql client option --skip-column-names does not apply to vertical output + +*************************** 1. row *************************** +1 + End of tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index cffa6392fa3..7b87ae10e59 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -401,5 +401,10 @@ insert into t1 values ('\0b\0'); --exec $MYSQL --xml test -e "select a from t1" drop table t1; +--echo +--echo Bug #47147: mysql client option --skip-column-names does not apply to vertical output +--echo +--exec $MYSQL --skip-column-names --vertical test -e "select 1 as a" + --echo --echo End of tests From deea727fced84c96e5f3f2f55d3a1a9fb5e475d0 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 22 Oct 2009 01:10:42 +0100 Subject: [PATCH 002/344] BUG#48091 valgrind errors when slave has double not null and master has double null Backporting BUG#38173 to mysql-5.1-bugteam The reason of the bug was incompatibile with the master side behaviour. INSERT query on the master is allowed to insert into a table without specifying values of DEFAULT-less fields if sql_mode is not strict. Fixed with checking sql_mode by the sql thread to decide how to react. Non-strict sql_mode should allow Write_rows event to complete. todo: warnings can be shown via show slave status, still this is a separate rather general issue how to show warnings for the slave threads. --- .../extra/rpl_tests/rpl_extraSlave_Col.test | 35 +++++++++---- .../extra/rpl_tests/rpl_row_tabledefs.test | 15 +++--- .../suite/rpl/r/rpl_extraCol_innodb.result | 52 ++++--------------- .../suite/rpl/r/rpl_extraCol_myisam.result | 52 ++++--------------- .../rpl/r/rpl_row_tabledefs_2myisam.result | 44 ++-------------- .../rpl/r/rpl_row_tabledefs_3innodb.result | 44 ++-------------- sql/log_event.cc | 5 +- sql/rpl_record.cc | 34 ++++++++---- sql/rpl_record.h | 3 +- 9 files changed, 88 insertions(+), 196 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test index a7b02065144..1eaefa661f9 100644 --- a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test +++ b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test @@ -407,13 +407,18 @@ sync_slave_with_master; ########################################### # Bug#22234, Bug#23907 Extra Slave Col is not # erroring on extra col with no default values. -######################################################## +############################################################### +# Error reaction is up to sql_mode of the slave sql (bug#38173) #--echo *** Create t9 on slave *** STOP SLAVE; RESET SLAVE; eval CREATE TABLE t9 (a INT KEY, b BLOB, c CHAR(5), d TIMESTAMP, - e INT NOT NULL) ENGINE=$engine_type; + e INT NOT NULL, + f text not null, + g text, + h blob not null, + i blob) ENGINE=$engine_type; --echo *** Create t9 on Master *** connection master; @@ -431,13 +436,25 @@ set @b1 = 'b1b1b1b1'; set @b1 = concat(@b1,@b1); INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); -connection slave; ---source include/wait_for_slave_sql_to_stop.inc ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 # ---query_vertical SHOW SLAVE STATUS -SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; -START SLAVE; +# the test would stop slave if @@sql_mode for the sql thread +# was set to strict. Otherwise, as with this tests setup, +# the implicit defaults will be inserted into fields even though +# they are declared without DEFAULT clause. + +sync_slave_with_master; +select * from t9; + +# todo: fix Bug #43992 slave sql thread can't tune own sql_mode ... +# and add/restore waiting for stop test + +#--source include/wait_for_slave_sql_to_stop.inc +#--replace_result $MASTER_MYPORT MASTER_PORT +#--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 # +#--query_vertical SHOW SLAVE STATUS +#SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +#START SLAVE; + + #--echo *** Drop t9 *** #connection master; diff --git a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test index 3b03caee35c..083088f12ff 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test +++ b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test @@ -111,21 +111,18 @@ SELECT a,b,x FROM t1_int ORDER BY a; SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit ORDER BY a; SELECT a,b,x FROM t1_char ORDER BY a; -# Each of these inserts should generate an error and stop the slave - connection master; INSERT INTO t9 VALUES (2); sync_slave_with_master; # Now slave is guaranteed to be running connection master; INSERT INTO t1_nodef VALUES (1,2); -connection slave; ---source include/wait_for_slave_sql_to_stop.inc ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 4 # 7 # 8 # 9 # 20 22 # 23 # 33 # 35 36 38 ---query_vertical SHOW SLAVE STATUS -SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; -START SLAVE; + +# Last insert on wider slave table succeeds while slave sql sql_mode permits. +# The previous version of the above test expected slave sql to stop. +# bug#38173 relaxed conditions to stop only with the strict mode. +sync_slave_with_master; +select count(*) from t1_nodef; # # Replicating to tables with fewer columns at the end works as of WL#3228 diff --git a/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result b/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result index e2ec78e7adc..63154383e8c 100644 --- a/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result +++ b/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result @@ -404,7 +404,11 @@ STOP SLAVE; RESET SLAVE; CREATE TABLE t9 (a INT KEY, b BLOB, c CHAR(5), d TIMESTAMP, -e INT NOT NULL) ENGINE='InnoDB'; +e INT NOT NULL, +f text not null, +g text, +h blob not null, +i blob) ENGINE='InnoDB'; *** Create t9 on Master *** CREATE TABLE t9 (a INT PRIMARY KEY, b BLOB, c CHAR(5) ) ENGINE='InnoDB'; @@ -415,47 +419,11 @@ START SLAVE; set @b1 = 'b1b1b1b1'; set @b1 = concat(@b1,@b1); INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); -SHOW SLAVE STATUS; -Slave_IO_State # -Master_Host 127.0.0.1 -Master_User root -Master_Port # -Connect_Retry 1 -Master_Log_File master-bin.000001 -Read_Master_Log_Pos # -Relay_Log_File # -Relay_Log_Pos # -Relay_Master_Log_File master-bin.000001 -Slave_IO_Running Yes -Slave_SQL_Running No -Replicate_Do_DB -Replicate_Ignore_DB -Replicate_Do_Table -Replicate_Ignore_Table # -Replicate_Wild_Do_Table -Replicate_Wild_Ignore_Table -Last_Errno 1364 -Last_Error Could not execute Write_rows event on table test.t9; Field 'e' doesn't have a default value, Error_code: 1364; handler error HA_ERR_ROWS_EVENT_APPLY; the event's master log master-bin.000001, end_log_pos 330 -Skip_Counter 0 -Exec_Master_Log_Pos # -Relay_Log_Space # -Until_Condition None -Until_Log_File -Until_Log_Pos 0 -Master_SSL_Allowed No -Master_SSL_CA_File -Master_SSL_CA_Path -Master_SSL_Cert -Master_SSL_Cipher -Master_SSL_Key -Seconds_Behind_Master # -Master_SSL_Verify_Server_Cert No -Last_IO_Errno # -Last_IO_Error # -Last_SQL_Errno 1364 -Last_SQL_Error Could not execute Write_rows event on table test.t9; Field 'e' doesn't have a default value, Error_code: 1364; handler error HA_ERR_ROWS_EVENT_APPLY; the event's master log master-bin.000001, end_log_pos 330 -SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; -START SLAVE; +select * from t9; +a b c d e f g h i +1 b1b1b1b1b1b1b1b1 Kyle 0000-00-00 00:00:00 0 NULL NULL +2 b1b1b1b1b1b1b1b1 JOE 0000-00-00 00:00:00 0 NULL NULL +3 b1b1b1b1b1b1b1b1 QA 0000-00-00 00:00:00 0 NULL NULL *** Create t10 on slave *** STOP SLAVE; RESET SLAVE; diff --git a/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result b/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result index ed5b4eac27d..d80ac5eea2c 100644 --- a/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result +++ b/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result @@ -404,7 +404,11 @@ STOP SLAVE; RESET SLAVE; CREATE TABLE t9 (a INT KEY, b BLOB, c CHAR(5), d TIMESTAMP, -e INT NOT NULL) ENGINE='MyISAM'; +e INT NOT NULL, +f text not null, +g text, +h blob not null, +i blob) ENGINE='MyISAM'; *** Create t9 on Master *** CREATE TABLE t9 (a INT PRIMARY KEY, b BLOB, c CHAR(5) ) ENGINE='MyISAM'; @@ -415,47 +419,11 @@ START SLAVE; set @b1 = 'b1b1b1b1'; set @b1 = concat(@b1,@b1); INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); -SHOW SLAVE STATUS; -Slave_IO_State # -Master_Host 127.0.0.1 -Master_User root -Master_Port # -Connect_Retry 1 -Master_Log_File master-bin.000001 -Read_Master_Log_Pos # -Relay_Log_File # -Relay_Log_Pos # -Relay_Master_Log_File master-bin.000001 -Slave_IO_Running Yes -Slave_SQL_Running No -Replicate_Do_DB -Replicate_Ignore_DB -Replicate_Do_Table -Replicate_Ignore_Table # -Replicate_Wild_Do_Table -Replicate_Wild_Ignore_Table -Last_Errno 1364 -Last_Error Could not execute Write_rows event on table test.t9; Field 'e' doesn't have a default value, Error_code: 1364; handler error HA_ERR_ROWS_EVENT_APPLY; the event's master log master-bin.000001, end_log_pos 330 -Skip_Counter 0 -Exec_Master_Log_Pos # -Relay_Log_Space # -Until_Condition None -Until_Log_File -Until_Log_Pos 0 -Master_SSL_Allowed No -Master_SSL_CA_File -Master_SSL_CA_Path -Master_SSL_Cert -Master_SSL_Cipher -Master_SSL_Key -Seconds_Behind_Master # -Master_SSL_Verify_Server_Cert No -Last_IO_Errno # -Last_IO_Error # -Last_SQL_Errno 1364 -Last_SQL_Error Could not execute Write_rows event on table test.t9; Field 'e' doesn't have a default value, Error_code: 1364; handler error HA_ERR_ROWS_EVENT_APPLY; the event's master log master-bin.000001, end_log_pos 330 -SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; -START SLAVE; +select * from t9; +a b c d e f g h i +1 b1b1b1b1b1b1b1b1 Kyle 0000-00-00 00:00:00 0 NULL NULL +2 b1b1b1b1b1b1b1b1 JOE 0000-00-00 00:00:00 0 NULL NULL +3 b1b1b1b1b1b1b1b1 QA 0000-00-00 00:00:00 0 NULL NULL *** Create t10 on slave *** STOP SLAVE; RESET SLAVE; diff --git a/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result b/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result index a6a2181cd2a..bb9865ab2d1 100644 --- a/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result +++ b/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result @@ -105,47 +105,9 @@ a b x 2 10 Foo is a bar INSERT INTO t9 VALUES (2); INSERT INTO t1_nodef VALUES (1,2); -SHOW SLAVE STATUS; -Slave_IO_State # -Master_Host 127.0.0.1 -Master_User root -Master_Port # -Connect_Retry 1 -Master_Log_File master-bin.000001 -Read_Master_Log_Pos # -Relay_Log_File # -Relay_Log_Pos # -Relay_Master_Log_File master-bin.000001 -Slave_IO_Running Yes -Slave_SQL_Running No -Replicate_Do_DB -Replicate_Ignore_DB -Replicate_Do_Table -Replicate_Ignore_Table -Replicate_Wild_Do_Table -Replicate_Wild_Ignore_Table -Last_Errno 1364 -Last_Error -Skip_Counter 0 -Exec_Master_Log_Pos # -Relay_Log_Space # -Until_Condition None -Until_Log_File -Until_Log_Pos 0 -Master_SSL_Allowed No -Master_SSL_CA_File -Master_SSL_CA_Path -Master_SSL_Cert -Master_SSL_Cipher -Master_SSL_Key -Seconds_Behind_Master # -Master_SSL_Verify_Server_Cert No -Last_IO_Errno -Last_IO_Error -Last_SQL_Errno 1364 -Last_SQL_Error -SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; -START SLAVE; +select count(*) from t1_nodef; +count(*) +1 INSERT INTO t9 VALUES (2); **** On Master **** INSERT INTO t2 VALUES (2,4); diff --git a/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result b/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result index 02e8c074354..f606a28c2d9 100644 --- a/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result +++ b/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result @@ -105,47 +105,9 @@ a b x 2 10 Foo is a bar INSERT INTO t9 VALUES (2); INSERT INTO t1_nodef VALUES (1,2); -SHOW SLAVE STATUS; -Slave_IO_State # -Master_Host 127.0.0.1 -Master_User root -Master_Port # -Connect_Retry 1 -Master_Log_File master-bin.000001 -Read_Master_Log_Pos # -Relay_Log_File # -Relay_Log_Pos # -Relay_Master_Log_File master-bin.000001 -Slave_IO_Running Yes -Slave_SQL_Running No -Replicate_Do_DB -Replicate_Ignore_DB -Replicate_Do_Table -Replicate_Ignore_Table -Replicate_Wild_Do_Table -Replicate_Wild_Ignore_Table -Last_Errno 1364 -Last_Error -Skip_Counter 0 -Exec_Master_Log_Pos # -Relay_Log_Space # -Until_Condition None -Until_Log_File -Until_Log_Pos 0 -Master_SSL_Allowed No -Master_SSL_CA_File -Master_SSL_CA_Path -Master_SSL_Cert -Master_SSL_Cipher -Master_SSL_Key -Seconds_Behind_Master # -Master_SSL_Verify_Server_Cert No -Last_IO_Errno -Last_IO_Error -Last_SQL_Errno 1364 -Last_SQL_Error -SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; -START SLAVE; +select count(*) from t1_nodef; +count(*) +1 INSERT INTO t9 VALUES (2); **** On Master **** INSERT INTO t2 VALUES (2,4); diff --git a/sql/log_event.cc b/sql/log_event.cc index 76532836b73..935dfa1a536 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8452,7 +8452,10 @@ Rows_log_event::write_row(const Relay_log_info *const rli, /* fill table->record[0] with default values */ if ((error= prepare_record(table, m_width, - TRUE /* check if columns have def. values */))) + table->file->ht->db_type != DB_TYPE_NDBCLUSTER, + (rli->sql_thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | + MODE_STRICT_ALL_TABLES))))) DBUG_RETURN(error); /* unpack row into table->record[0] */ diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 14a80cbb4b6..f4768e2456a 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -305,13 +305,17 @@ unpack_row(Relay_log_info const *rli, @param table Table whose record[0] buffer is prepared. @param skip Number of columns for which default/nullable check should be skipped. - @param check Indicates if errors should be raised when checking - default/nullable field properties. + @param check Specifies if lack of default error needs checking. + @param abort_on_warning + Controls how to react on lack of a field's default. + The parameter mimics the master side one for + @c check_that_all_fields_are_given_values. @returns 0 on success or a handler level error code */ int prepare_record(TABLE *const table, - const uint skip, const bool check) + const uint skip, const bool check, + const bool abort_on_warning) { DBUG_ENTER("prepare_record"); @@ -326,17 +330,27 @@ int prepare_record(TABLE *const table, if (skip >= table->s->fields || !check) DBUG_RETURN(0); - /* Checking if exists default/nullable fields in the default values. */ - - for (Field **field_ptr= table->field+skip ; *field_ptr ; ++field_ptr) + /* + For fields the extra fields on the slave, we check if they have a default. + The check follows the same rules as the INSERT query without specifying an + explicit value for a field not having the explicit default + (@c check_that_all_fields_are_given_values()). + */ + for (Field **field_ptr= table->field+skip; *field_ptr; ++field_ptr) { uint32 const mask= NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG; Field *const f= *field_ptr; - - if (((f->flags & mask) == mask)) + if ((f->flags & NO_DEFAULT_VALUE_FLAG) && + (f->real_type() != MYSQL_TYPE_ENUM)) { - my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), f->field_name); - error = HA_ERR_ROWS_EVENT_APPLY; + push_warning_printf(current_thd, abort_on_warning? + MYSQL_ERROR::WARN_LEVEL_ERROR : + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NO_DEFAULT_FOR_FIELD, + ER(ER_NO_DEFAULT_FOR_FIELD), + f->field_name); + if (abort_on_warning) + error = HA_ERR_ROWS_EVENT_APPLY; } } diff --git a/sql/rpl_record.h b/sql/rpl_record.h index f9e64f0ab1d..ab2bcd382ca 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -30,7 +30,8 @@ int unpack_row(Relay_log_info const *rli, uchar const **const row_end, ulong *const master_reclength); // Fill table's record[0] with default values. -int prepare_record(TABLE *const, const uint =0, const bool =FALSE); +int prepare_record(TABLE *const table, const uint skip, const bool check, + const bool abort_on_warning= FALSE); #endif #endif From 7e5cf52c3e0a52960a1f564bbb78c1ab42d1a0a1 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 22 Oct 2009 01:15:45 +0100 Subject: [PATCH 003/344] BUG#48091 valgrind errors when slave has double not null and master has double null Backporting BUG#43789 to mysql-5.1-bugteam The replication was generating corrupted data, warning messages on Valgrind and aborting on debug mode while replicating a "null" to "not null" field. Specifically the unpack_row routine, was considering the slave's table definition and trying to retrieve a field value, where there was nothing to be retrieved, ignoring the fact that the value was defined as "null" by the master. To fix the problem, we proceed as follows: 1 - If it is not STRICT sql_mode, implicit default values are used, regardless if it is multi-row or single-row statement. 2 - However, if it is STRICT mode, then a we do what follows: 2.1 If it is a transactional engine, we do a rollback on the first NULL that is to be set into a NOT NULL column and return an error. 2.2 If it is a non-transactional engine and it is the first row to be inserted with multi-row, we also return the error. Otherwise, we proceed with the execution, use implicit default values and print out warning messages. Unfortunately, the current patch cannot mimic the behavior showed by the master for updates on multi-tables and multi-row inserts. This happens because such statements are unfolded in different row events. For instance, considering the following updates and strict mode: (master) create table t1 (a int); create table t2 (a int not null); insert into t1 values (1); insert into t2 values (2); update t1, t2 SET t1.a=10, t2.a=NULL; t1 would have (10) and t2 would have (0) as this would be handled as a multi-row update. On the other hand, if we had the following updates: (master) create table t1 (a int); create table t2 (a int); (slave) create table t1 (a int); create table t2 (a int not null); (master) insert into t1 values (1); insert into t2 values (2); update t1, t2 SET t1.a=10, t2.a=NULL; On the master t1 would have (10) and t2 would have (NULL). On the slave, t1 would have (10) but the update on t1 would fail. --- mysql-test/extra/rpl_tests/rpl_not_null.test | 364 ++++++++++++++++++ .../suite/rpl/r/rpl_not_null_innodb.result | 202 ++++++++++ .../suite/rpl/r/rpl_not_null_myisam.result | 202 ++++++++++ .../suite/rpl/t/rpl_not_null_innodb.test | 19 + .../suite/rpl/t/rpl_not_null_myisam.test | 18 + sql/log_event.cc | 17 +- sql/log_event.h | 8 +- sql/rpl_record.cc | 56 ++- sql/rpl_record.h | 6 +- 9 files changed, 873 insertions(+), 19 deletions(-) create mode 100644 mysql-test/extra/rpl_tests/rpl_not_null.test create mode 100644 mysql-test/suite/rpl/r/rpl_not_null_innodb.result create mode 100644 mysql-test/suite/rpl/r/rpl_not_null_myisam.result create mode 100644 mysql-test/suite/rpl/t/rpl_not_null_innodb.test create mode 100644 mysql-test/suite/rpl/t/rpl_not_null_myisam.test diff --git a/mysql-test/extra/rpl_tests/rpl_not_null.test b/mysql-test/extra/rpl_tests/rpl_not_null.test new file mode 100644 index 00000000000..88f37f9a95e --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_not_null.test @@ -0,0 +1,364 @@ +################################################################################# +# This test checks if the replication between "null" fields to either "null" +# fields or "not null" fields works properly. In the first case, the execution +# should work fine. In the second case, it may fail according to the sql_mode +# being used. +# +# The test is devided in three main parts: +# +# 1 - NULL --> NULL (no failures) +# 2 - NULL --> NOT NULL ( sql-mode = STRICT and failures) +# 3 - NULL --> NOT NULL ( sql-mode != STRICT and no failures) +# +################################################################################# +connection master; + +SET SQL_LOG_BIN= 0; +eval CREATE TABLE t1(`a` INT, `b` DATE DEFAULT NULL, +`c` INT DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; + +eval CREATE TABLE t2(`a` INT, `b` DATE DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; + +eval CREATE TABLE t3(`a` INT, `b` DATE DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; + +eval CREATE TABLE t4(`a` INT, `b` DATE DEFAULT NULL, +`c` INT DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +SET SQL_LOG_BIN= 1; + +connection slave; + +eval CREATE TABLE t1(`a` INT, `b` DATE DEFAULT NULL, +`c` INT DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; + +eval CREATE TABLE t2(`a` INT, `b` DATE DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; + +eval CREATE TABLE t3(`a` INT, `b` DATE DEFAULT '0000-00-00', +`c` INT DEFAULT 500, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; + +eval CREATE TABLE t4(`a` INT, `b` DATE DEFAULT '0000-00-00', +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; + +--echo ************* EXECUTION WITH INSERTS ************* +connection master; +INSERT INTO t1(a,b,c) VALUES (1, null, 1); +INSERT INTO t1(a,b,c) VALUES (2,'1111-11-11', 2); +INSERT INTO t1(a,b) VALUES (3, null); +INSERT INTO t1(a,c) VALUES (4, 4); +INSERT INTO t1(a) VALUES (5); + +INSERT INTO t2(a,b) VALUES (1, null); +INSERT INTO t2(a,b) VALUES (2,'1111-11-11'); +INSERT INTO t2(a) VALUES (3); + +INSERT INTO t3(a,b) VALUES (1, null); +INSERT INTO t3(a,b) VALUES (2,'1111-11-11'); +INSERT INTO t3(a) VALUES (3); + +INSERT INTO t4(a,b,c) VALUES (1, null, 1); +INSERT INTO t4(a,b,c) VALUES (2,'1111-11-11', 2); +INSERT INTO t4(a,b) VALUES (3, null); +INSERT INTO t4(a,c) VALUES (4, 4); +INSERT INTO t4(a) VALUES (5); + +--echo ************* SHOWING THE RESULT SETS WITH INSERTS ************* +sync_slave_with_master; + +--echo TABLES t1 and t2 must be equal otherwise an error will be thrown. +let $diff_table_1=master:test.t1; +let $diff_table_2=slave:test.t1; +source include/diff_tables.inc; + +let $diff_table_1=master:test.t2; +let $diff_table_2=slave:test.t2; +source include/diff_tables.inc; + +--echo TABLES t2 and t3 must be different. +connection master; +SELECT * FROM t3; +connection slave; +SELECT * FROM t3; +connection master; +SELECT * FROM t4; +connection slave; +SELECT * FROM t4; + +--echo ************* EXECUTION WITH UPDATES and REPLACES ************* +connection master; +DELETE FROM t1; +INSERT INTO t1(a,b,c) VALUES (1,'1111-11-11', 1); +REPLACE INTO t1(a,b,c) VALUES (2,'1111-11-11', 2); +UPDATE t1 set b= NULL, c= 300 where a= 1; +REPLACE INTO t1(a,b,c) VALUES (2, NULL, 300); + +--echo ************* SHOWING THE RESULT SETS WITH UPDATES and REPLACES ************* +sync_slave_with_master; + +--echo TABLES t1 and t2 must be equal otherwise an error will be thrown. +let $diff_table_1=master:test.t1; +let $diff_table_2=slave:test.t1; +source include/diff_tables.inc; + +--echo ************* CLEANING ************* +connection master; + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; + +sync_slave_with_master; + +connection master; + +SET SQL_LOG_BIN= 0; +eval CREATE TABLE t1 (`a` INT, `b` BIT DEFAULT NULL, `c` BIT DEFAULT NULL, +PRIMARY KEY (`a`)) ENGINE= $engine; +SET SQL_LOG_BIN= 1; + +connection slave; + +eval CREATE TABLE t1 (`a` INT, `b` BIT DEFAULT b'01', `c` BIT DEFAULT NULL, +PRIMARY KEY (`a`)) ENGINE= $engine; + +--echo ************* EXECUTION WITH INSERTS ************* +connection master; +INSERT INTO t1(a,b,c) VALUES (1, null, b'01'); +INSERT INTO t1(a,b,c) VALUES (2,b'00', b'01'); +INSERT INTO t1(a,b) VALUES (3, null); +INSERT INTO t1(a,c) VALUES (4, b'01'); +INSERT INTO t1(a) VALUES (5); + +--echo ************* SHOWING THE RESULT SETS WITH INSERTS ************* +--echo TABLES t1 and t2 must be different. +sync_slave_with_master; +connection master; +SELECT a,b+0,c+0 FROM t1; +connection slave; +SELECT a,b+0,c+0 FROM t1; + +--echo ************* EXECUTION WITH UPDATES and REPLACES ************* +connection master; +DELETE FROM t1; +INSERT INTO t1(a,b,c) VALUES (1,b'00', b'01'); +REPLACE INTO t1(a,b,c) VALUES (2,b'00',b'01'); +UPDATE t1 set b= NULL, c= b'00' where a= 1; +REPLACE INTO t1(a,b,c) VALUES (2, NULL, b'00'); + +--echo ************* SHOWING THE RESULT SETS WITH UPDATES and REPLACES ************* +--echo TABLES t1 and t2 must be equal otherwise an error will be thrown. +sync_slave_with_master; +let $diff_table_1=master:test.t1; +let $diff_table_2=slave:test.t1; +source include/diff_tables.inc; + +connection master; + +DROP TABLE t1; + +sync_slave_with_master; + +--echo ################################################################################ +--echo # NULL ---> NOT NULL (STRICT MODE) +--echo # UNCOMMENT THIS AFTER FIXING BUG#43992 +--echo ################################################################################ +#connection slave; +#SET GLOBAL sql_mode="TRADITIONAL"; +# +#STOP SLAVE; +#--source include/wait_for_slave_to_stop.inc +#START SLAVE; +#--source include/wait_for_slave_to_start.inc +# +#let $y=0; +#while (`select $y < 6`) +#{ +# connection master; +# +# SET SQL_LOG_BIN= 0; +# eval CREATE TABLE t1(`a` INT NOT NULL, `b` INT, +# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +# eval CREATE TABLE t2(`a` INT NOT NULL, `b` INT, +# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +# eval CREATE TABLE t3(`a` INT NOT NULL, `b` INT, +# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +# SET SQL_LOG_BIN= 1; +# +# connection slave; +# +# eval CREATE TABLE t1(`a` INT NOT NULL, `b` INT NOT NULL, +# `c` INT NOT NULL, +# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +# eval CREATE TABLE t2(`a` INT NOT NULL, `b` INT NOT NULL, +# `c` INT, +# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +# eval CREATE TABLE t3(`a` INT NOT NULL, `b` INT NOT NULL, +# `c` INT DEFAULT 500, +# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +# +# if (`select $y=0`) +# { +# --echo ************* EXECUTION WITH INSERTS ************* +# connection master; +# INSERT INTO t1(a) VALUES (1); +# } +# +# if (`select $y=1`) +# { +# --echo ************* EXECUTION WITH INSERTS ************* +# connection master; +# INSERT INTO t1(a, b) VALUES (1, NULL); +# } +# +# if (`select $y=2`) +# { +# --echo ************* EXECUTION WITH UPDATES ************* +# connection master; +# INSERT INTO t3(a, b) VALUES (1, 1); +# INSERT INTO t3(a, b) VALUES (2, 1); +# UPDATE t3 SET b = NULL where a= 1; +# } +# +# if (`select $y=3`) +# { +# --echo ************* EXECUTION WITH INSERTS/REPLACES ************* +# connection master; +# REPLACE INTO t3(a, b) VALUES (1, null); +# } +# +# if (`select $y=4`) +# { +# --echo ************* EXECUTION WITH UPDATES/REPLACES ************* +# connection master; +# INSERT INTO t3(a, b) VALUES (1, 1); +# REPLACE INTO t3(a, b) VALUES (1, null); +# } +# +# if (`select $y=5`) +# { +# --echo ************* EXECUTION WITH MULTI-ROW INSERTS ************* +# connection master; +# +# SET SQL_LOG_BIN= 0; +# INSERT INTO t2(a, b) VALUES (1, 1); +# INSERT INTO t2(a, b) VALUES (2, 1); +# INSERT INTO t2(a, b) VALUES (3, null); +# INSERT INTO t2(a, b) VALUES (4, 1); +# INSERT INTO t2(a, b) VALUES (5, 1); +# SET SQL_LOG_BIN= 1; +# +# INSERT INTO t2 SELECT a + 10, b from t2; +# --echo The statement below is just executed to stop processing +# INSERT INTO t1(a) VALUES (1); +# } +# +# --echo ************* SHOWING THE RESULT SETS ************* +# connection slave; +# --source include/wait_for_slave_sql_to_stop.inc +# connection master; +# SELECT * FROM t1; +# connection slave; +# SELECT * FROM t1; +# connection master; +# SELECT * FROM t2; +# connection slave; +# SELECT * FROM t2; +# connection master; +# SELECT * FROM t3; +# connection slave; +# SELECT * FROM t3; +# --source include/reset_master_and_slave.inc +# +# connection master; +# +# DROP TABLE t1; +# DROP TABLE t2; +# DROP TABLE t3; +# +# sync_slave_with_master; +# +# inc $y; +#} +#connection slave; +#SET GLOBAL sql_mode=""; +# +#STOP SLAVE; +#source include/wait_for_slave_to_stop.inc; +#START SLAVE; +#--source include/wait_for_slave_to_start.inc + +--echo ################################################################################ +--echo # NULL ---> NOT NULL (NON-STRICT MODE) +--echo ################################################################################ +connection master; + +SET SQL_LOG_BIN= 0; +eval CREATE TABLE t1(`a` INT NOT NULL, `b` INT, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +eval CREATE TABLE t2(`a` INT NOT NULL, `b` INT, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +eval CREATE TABLE t3(`a` INT NOT NULL, `b` INT, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +SET SQL_LOG_BIN= 1; + +connection slave; + +eval CREATE TABLE t1(`a` INT NOT NULL, `b` INT NOT NULL, +`c` INT NOT NULL, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +eval CREATE TABLE t2(`a` INT NOT NULL, `b` INT NOT NULL, +`c` INT, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; +eval CREATE TABLE t3(`a` INT NOT NULL, `b` INT NOT NULL, +`c` INT DEFAULT 500, +PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1; + +--echo ************* EXECUTION WITH INSERTS ************* +connection master; +INSERT INTO t1(a) VALUES (1); +INSERT INTO t1(a, b) VALUES (2, NULL); +INSERT INTO t1(a, b) VALUES (3, 1); + +INSERT INTO t2(a) VALUES (1); +INSERT INTO t2(a, b) VALUES (2, NULL); +INSERT INTO t2(a, b) VALUES (3, 1); + +INSERT INTO t3(a) VALUES (1); +INSERT INTO t3(a, b) VALUES (2, NULL); +INSERT INTO t3(a, b) VALUES (3, 1); +INSERT INTO t3(a, b) VALUES (4, 1); +REPLACE INTO t3(a, b) VALUES (5, null); + +REPLACE INTO t3(a, b) VALUES (3, null); +UPDATE t3 SET b = NULL where a = 4; + +--echo ************* SHOWING THE RESULT SETS ************* +connection master; +sync_slave_with_master; + +connection master; +SELECT * FROM t1; +connection slave; +SELECT * FROM t1; +connection master; +SELECT * FROM t2; +connection slave; +SELECT * FROM t2; +connection master; +SELECT * FROM t3; +connection slave; +SELECT * FROM t3; + +connection master; + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +sync_slave_with_master; diff --git a/mysql-test/suite/rpl/r/rpl_not_null_innodb.result b/mysql-test/suite/rpl/r/rpl_not_null_innodb.result new file mode 100644 index 00000000000..7717beb0a47 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_not_null_innodb.result @@ -0,0 +1,202 @@ +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 SQL_LOG_BIN= 0; +CREATE TABLE t1(`a` INT, `b` DATE DEFAULT NULL, +`c` INT DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +CREATE TABLE t2(`a` INT, `b` DATE DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +CREATE TABLE t3(`a` INT, `b` DATE DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +CREATE TABLE t4(`a` INT, `b` DATE DEFAULT NULL, +`c` INT DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +SET SQL_LOG_BIN= 1; +CREATE TABLE t1(`a` INT, `b` DATE DEFAULT NULL, +`c` INT DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +CREATE TABLE t2(`a` INT, `b` DATE DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +CREATE TABLE t3(`a` INT, `b` DATE DEFAULT '0000-00-00', +`c` INT DEFAULT 500, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +CREATE TABLE t4(`a` INT, `b` DATE DEFAULT '0000-00-00', +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +************* EXECUTION WITH INSERTS ************* +INSERT INTO t1(a,b,c) VALUES (1, null, 1); +INSERT INTO t1(a,b,c) VALUES (2,'1111-11-11', 2); +INSERT INTO t1(a,b) VALUES (3, null); +INSERT INTO t1(a,c) VALUES (4, 4); +INSERT INTO t1(a) VALUES (5); +INSERT INTO t2(a,b) VALUES (1, null); +INSERT INTO t2(a,b) VALUES (2,'1111-11-11'); +INSERT INTO t2(a) VALUES (3); +INSERT INTO t3(a,b) VALUES (1, null); +INSERT INTO t3(a,b) VALUES (2,'1111-11-11'); +INSERT INTO t3(a) VALUES (3); +INSERT INTO t4(a,b,c) VALUES (1, null, 1); +INSERT INTO t4(a,b,c) VALUES (2,'1111-11-11', 2); +INSERT INTO t4(a,b) VALUES (3, null); +INSERT INTO t4(a,c) VALUES (4, 4); +INSERT INTO t4(a) VALUES (5); +************* SHOWING THE RESULT SETS WITH INSERTS ************* +TABLES t1 and t2 must be equal otherwise an error will be thrown. +Comparing tables master:test.t1 and slave:test.t1 +Comparing tables master:test.t2 and slave:test.t2 +TABLES t2 and t3 must be different. +SELECT * FROM t3; +a b +1 NULL +2 1111-11-11 +3 NULL +SELECT * FROM t3; +a b c +1 NULL 500 +2 1111-11-11 500 +3 NULL 500 +SELECT * FROM t4; +a b c +1 NULL 1 +2 1111-11-11 2 +3 NULL NULL +4 NULL 4 +5 NULL NULL +SELECT * FROM t4; +a b +1 NULL +2 1111-11-11 +3 NULL +4 NULL +5 NULL +************* EXECUTION WITH UPDATES and REPLACES ************* +DELETE FROM t1; +INSERT INTO t1(a,b,c) VALUES (1,'1111-11-11', 1); +REPLACE INTO t1(a,b,c) VALUES (2,'1111-11-11', 2); +UPDATE t1 set b= NULL, c= 300 where a= 1; +REPLACE INTO t1(a,b,c) VALUES (2, NULL, 300); +************* SHOWING THE RESULT SETS WITH UPDATES and REPLACES ************* +TABLES t1 and t2 must be equal otherwise an error will be thrown. +Comparing tables master:test.t1 and slave:test.t1 +************* CLEANING ************* +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; +SET SQL_LOG_BIN= 0; +CREATE TABLE t1 (`a` INT, `b` BIT DEFAULT NULL, `c` BIT DEFAULT NULL, +PRIMARY KEY (`a`)) ENGINE= Innodb; +SET SQL_LOG_BIN= 1; +CREATE TABLE t1 (`a` INT, `b` BIT DEFAULT b'01', `c` BIT DEFAULT NULL, +PRIMARY KEY (`a`)) ENGINE= Innodb; +************* EXECUTION WITH INSERTS ************* +INSERT INTO t1(a,b,c) VALUES (1, null, b'01'); +INSERT INTO t1(a,b,c) VALUES (2,b'00', b'01'); +INSERT INTO t1(a,b) VALUES (3, null); +INSERT INTO t1(a,c) VALUES (4, b'01'); +INSERT INTO t1(a) VALUES (5); +************* SHOWING THE RESULT SETS WITH INSERTS ************* +TABLES t1 and t2 must be different. +SELECT a,b+0,c+0 FROM t1; +a b+0 c+0 +1 NULL 1 +2 0 1 +3 NULL NULL +4 NULL 1 +5 NULL NULL +SELECT a,b+0,c+0 FROM t1; +a b+0 c+0 +1 NULL 1 +2 0 1 +3 NULL NULL +4 NULL 1 +5 NULL NULL +************* EXECUTION WITH UPDATES and REPLACES ************* +DELETE FROM t1; +INSERT INTO t1(a,b,c) VALUES (1,b'00', b'01'); +REPLACE INTO t1(a,b,c) VALUES (2,b'00',b'01'); +UPDATE t1 set b= NULL, c= b'00' where a= 1; +REPLACE INTO t1(a,b,c) VALUES (2, NULL, b'00'); +************* SHOWING THE RESULT SETS WITH UPDATES and REPLACES ************* +TABLES t1 and t2 must be equal otherwise an error will be thrown. +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; +################################################################################ +# NULL ---> NOT NULL (STRICT MODE) +# UNCOMMENT THIS AFTER FIXING BUG#43992 +################################################################################ +################################################################################ +# NULL ---> NOT NULL (NON-STRICT MODE) +################################################################################ +SET SQL_LOG_BIN= 0; +CREATE TABLE t1(`a` INT NOT NULL, `b` INT, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +CREATE TABLE t2(`a` INT NOT NULL, `b` INT, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +CREATE TABLE t3(`a` INT NOT NULL, `b` INT, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +SET SQL_LOG_BIN= 1; +CREATE TABLE t1(`a` INT NOT NULL, `b` INT NOT NULL, +`c` INT NOT NULL, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +CREATE TABLE t2(`a` INT NOT NULL, `b` INT NOT NULL, +`c` INT, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +CREATE TABLE t3(`a` INT NOT NULL, `b` INT NOT NULL, +`c` INT DEFAULT 500, +PRIMARY KEY(`a`)) ENGINE=Innodb DEFAULT CHARSET=LATIN1; +************* EXECUTION WITH INSERTS ************* +INSERT INTO t1(a) VALUES (1); +INSERT INTO t1(a, b) VALUES (2, NULL); +INSERT INTO t1(a, b) VALUES (3, 1); +INSERT INTO t2(a) VALUES (1); +INSERT INTO t2(a, b) VALUES (2, NULL); +INSERT INTO t2(a, b) VALUES (3, 1); +INSERT INTO t3(a) VALUES (1); +INSERT INTO t3(a, b) VALUES (2, NULL); +INSERT INTO t3(a, b) VALUES (3, 1); +INSERT INTO t3(a, b) VALUES (4, 1); +REPLACE INTO t3(a, b) VALUES (5, null); +REPLACE INTO t3(a, b) VALUES (3, null); +UPDATE t3 SET b = NULL where a = 4; +************* SHOWING THE RESULT SETS ************* +SELECT * FROM t1; +a b +1 NULL +2 NULL +3 1 +SELECT * FROM t1; +a b c +1 0 0 +2 0 0 +3 1 0 +SELECT * FROM t2; +a b +1 NULL +2 NULL +3 1 +SELECT * FROM t2; +a b c +1 0 NULL +2 0 NULL +3 1 NULL +SELECT * FROM t3; +a b +1 NULL +2 NULL +3 NULL +4 NULL +5 NULL +SELECT * FROM t3; +a b c +1 0 500 +2 0 500 +3 0 500 +4 0 500 +5 0 500 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; diff --git a/mysql-test/suite/rpl/r/rpl_not_null_myisam.result b/mysql-test/suite/rpl/r/rpl_not_null_myisam.result new file mode 100644 index 00000000000..57a015367bb --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_not_null_myisam.result @@ -0,0 +1,202 @@ +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 SQL_LOG_BIN= 0; +CREATE TABLE t1(`a` INT, `b` DATE DEFAULT NULL, +`c` INT DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +CREATE TABLE t2(`a` INT, `b` DATE DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +CREATE TABLE t3(`a` INT, `b` DATE DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +CREATE TABLE t4(`a` INT, `b` DATE DEFAULT NULL, +`c` INT DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +SET SQL_LOG_BIN= 1; +CREATE TABLE t1(`a` INT, `b` DATE DEFAULT NULL, +`c` INT DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +CREATE TABLE t2(`a` INT, `b` DATE DEFAULT NULL, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +CREATE TABLE t3(`a` INT, `b` DATE DEFAULT '0000-00-00', +`c` INT DEFAULT 500, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +CREATE TABLE t4(`a` INT, `b` DATE DEFAULT '0000-00-00', +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +************* EXECUTION WITH INSERTS ************* +INSERT INTO t1(a,b,c) VALUES (1, null, 1); +INSERT INTO t1(a,b,c) VALUES (2,'1111-11-11', 2); +INSERT INTO t1(a,b) VALUES (3, null); +INSERT INTO t1(a,c) VALUES (4, 4); +INSERT INTO t1(a) VALUES (5); +INSERT INTO t2(a,b) VALUES (1, null); +INSERT INTO t2(a,b) VALUES (2,'1111-11-11'); +INSERT INTO t2(a) VALUES (3); +INSERT INTO t3(a,b) VALUES (1, null); +INSERT INTO t3(a,b) VALUES (2,'1111-11-11'); +INSERT INTO t3(a) VALUES (3); +INSERT INTO t4(a,b,c) VALUES (1, null, 1); +INSERT INTO t4(a,b,c) VALUES (2,'1111-11-11', 2); +INSERT INTO t4(a,b) VALUES (3, null); +INSERT INTO t4(a,c) VALUES (4, 4); +INSERT INTO t4(a) VALUES (5); +************* SHOWING THE RESULT SETS WITH INSERTS ************* +TABLES t1 and t2 must be equal otherwise an error will be thrown. +Comparing tables master:test.t1 and slave:test.t1 +Comparing tables master:test.t2 and slave:test.t2 +TABLES t2 and t3 must be different. +SELECT * FROM t3; +a b +1 NULL +2 1111-11-11 +3 NULL +SELECT * FROM t3; +a b c +1 NULL 500 +2 1111-11-11 500 +3 NULL 500 +SELECT * FROM t4; +a b c +1 NULL 1 +2 1111-11-11 2 +3 NULL NULL +4 NULL 4 +5 NULL NULL +SELECT * FROM t4; +a b +1 NULL +2 1111-11-11 +3 NULL +4 NULL +5 NULL +************* EXECUTION WITH UPDATES and REPLACES ************* +DELETE FROM t1; +INSERT INTO t1(a,b,c) VALUES (1,'1111-11-11', 1); +REPLACE INTO t1(a,b,c) VALUES (2,'1111-11-11', 2); +UPDATE t1 set b= NULL, c= 300 where a= 1; +REPLACE INTO t1(a,b,c) VALUES (2, NULL, 300); +************* SHOWING THE RESULT SETS WITH UPDATES and REPLACES ************* +TABLES t1 and t2 must be equal otherwise an error will be thrown. +Comparing tables master:test.t1 and slave:test.t1 +************* CLEANING ************* +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; +SET SQL_LOG_BIN= 0; +CREATE TABLE t1 (`a` INT, `b` BIT DEFAULT NULL, `c` BIT DEFAULT NULL, +PRIMARY KEY (`a`)) ENGINE= MyISAM; +SET SQL_LOG_BIN= 1; +CREATE TABLE t1 (`a` INT, `b` BIT DEFAULT b'01', `c` BIT DEFAULT NULL, +PRIMARY KEY (`a`)) ENGINE= MyISAM; +************* EXECUTION WITH INSERTS ************* +INSERT INTO t1(a,b,c) VALUES (1, null, b'01'); +INSERT INTO t1(a,b,c) VALUES (2,b'00', b'01'); +INSERT INTO t1(a,b) VALUES (3, null); +INSERT INTO t1(a,c) VALUES (4, b'01'); +INSERT INTO t1(a) VALUES (5); +************* SHOWING THE RESULT SETS WITH INSERTS ************* +TABLES t1 and t2 must be different. +SELECT a,b+0,c+0 FROM t1; +a b+0 c+0 +1 NULL 1 +2 0 1 +3 NULL NULL +4 NULL 1 +5 NULL NULL +SELECT a,b+0,c+0 FROM t1; +a b+0 c+0 +1 NULL 1 +2 0 1 +3 NULL NULL +4 NULL 1 +5 NULL NULL +************* EXECUTION WITH UPDATES and REPLACES ************* +DELETE FROM t1; +INSERT INTO t1(a,b,c) VALUES (1,b'00', b'01'); +REPLACE INTO t1(a,b,c) VALUES (2,b'00',b'01'); +UPDATE t1 set b= NULL, c= b'00' where a= 1; +REPLACE INTO t1(a,b,c) VALUES (2, NULL, b'00'); +************* SHOWING THE RESULT SETS WITH UPDATES and REPLACES ************* +TABLES t1 and t2 must be equal otherwise an error will be thrown. +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; +################################################################################ +# NULL ---> NOT NULL (STRICT MODE) +# UNCOMMENT THIS AFTER FIXING BUG#43992 +################################################################################ +################################################################################ +# NULL ---> NOT NULL (NON-STRICT MODE) +################################################################################ +SET SQL_LOG_BIN= 0; +CREATE TABLE t1(`a` INT NOT NULL, `b` INT, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +CREATE TABLE t2(`a` INT NOT NULL, `b` INT, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +CREATE TABLE t3(`a` INT NOT NULL, `b` INT, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +SET SQL_LOG_BIN= 1; +CREATE TABLE t1(`a` INT NOT NULL, `b` INT NOT NULL, +`c` INT NOT NULL, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +CREATE TABLE t2(`a` INT NOT NULL, `b` INT NOT NULL, +`c` INT, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +CREATE TABLE t3(`a` INT NOT NULL, `b` INT NOT NULL, +`c` INT DEFAULT 500, +PRIMARY KEY(`a`)) ENGINE=MyISAM DEFAULT CHARSET=LATIN1; +************* EXECUTION WITH INSERTS ************* +INSERT INTO t1(a) VALUES (1); +INSERT INTO t1(a, b) VALUES (2, NULL); +INSERT INTO t1(a, b) VALUES (3, 1); +INSERT INTO t2(a) VALUES (1); +INSERT INTO t2(a, b) VALUES (2, NULL); +INSERT INTO t2(a, b) VALUES (3, 1); +INSERT INTO t3(a) VALUES (1); +INSERT INTO t3(a, b) VALUES (2, NULL); +INSERT INTO t3(a, b) VALUES (3, 1); +INSERT INTO t3(a, b) VALUES (4, 1); +REPLACE INTO t3(a, b) VALUES (5, null); +REPLACE INTO t3(a, b) VALUES (3, null); +UPDATE t3 SET b = NULL where a = 4; +************* SHOWING THE RESULT SETS ************* +SELECT * FROM t1; +a b +1 NULL +2 NULL +3 1 +SELECT * FROM t1; +a b c +1 0 0 +2 0 0 +3 1 0 +SELECT * FROM t2; +a b +1 NULL +2 NULL +3 1 +SELECT * FROM t2; +a b c +1 0 NULL +2 0 NULL +3 1 NULL +SELECT * FROM t3; +a b +1 NULL +2 NULL +3 NULL +4 NULL +5 NULL +SELECT * FROM t3; +a b c +1 0 500 +2 0 500 +3 0 500 +4 0 500 +5 0 500 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; diff --git a/mysql-test/suite/rpl/t/rpl_not_null_innodb.test b/mysql-test/suite/rpl/t/rpl_not_null_innodb.test new file mode 100644 index 00000000000..dca0ea6589c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_not_null_innodb.test @@ -0,0 +1,19 @@ +################################################################################# +# This test checks if the replication between "null" fields to either "null" +# fields or "not null" fields works properly. In the first case, the execution +# should work fine. In the second case, it may fail according to the sql_mode +# being used. +# +# The test is devided in three main parts: +# +# 1 - NULL --> NULL (no failures) +# 2 - NULL --> NOT NULL ( sql-mode = STRICT and failures) +# 3 - NULL --> NOT NULL ( sql-mode != STRICT and no failures) +# +################################################################################# +--source include/master-slave.inc +--source include/have_innodb.inc +--source include/have_binlog_format_row.inc + +let $engine=Innodb; +--source extra/rpl_tests/rpl_not_null.test diff --git a/mysql-test/suite/rpl/t/rpl_not_null_myisam.test b/mysql-test/suite/rpl/t/rpl_not_null_myisam.test new file mode 100644 index 00000000000..0c036f5bfd7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_not_null_myisam.test @@ -0,0 +1,18 @@ +################################################################################# +# This test checks if the replication between "null" fields to either "null" +# fields or "not null" fields works properly. In the first case, the execution +# should work fine. In the second case, it may fail according to the sql_mode +# being used. +# +# The test is devided in three main parts: +# +# 1 - NULL --> NULL (no failures) +# 2 - NULL --> NOT NULL ( sql-mode = STRICT and failures) +# 3 - NULL --> NOT NULL ( sql-mode != STRICT and no failures) +# +################################################################################# +--source include/master-slave.inc +--source include/have_binlog_format_row.inc + +let $engine=MyISAM; +--source extra/rpl_tests/rpl_not_null.test diff --git a/sql/log_event.cc b/sql/log_event.cc index 935dfa1a536..ddedf07a70e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8450,16 +8450,17 @@ Rows_log_event::write_row(const Relay_log_info *const rli, auto_afree_ptr key(NULL); /* fill table->record[0] with default values */ - + bool abort_on_warnings= (rli->sql_thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)); if ((error= prepare_record(table, m_width, table->file->ht->db_type != DB_TYPE_NDBCLUSTER, - (rli->sql_thd->variables.sql_mode & - (MODE_STRICT_TRANS_TABLES | - MODE_STRICT_ALL_TABLES))))) + abort_on_warnings, m_curr_row == m_rows_buf))) DBUG_RETURN(error); /* unpack row into table->record[0] */ - error= unpack_current_row(rli); // TODO: how to handle errors? + if ((error= unpack_current_row(rli, abort_on_warnings))) + DBUG_RETURN(error); + if (m_curr_row == m_rows_buf) { /* this is the first row to be inserted, we estimate the rows with @@ -9256,8 +9257,12 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) store_record(m_table,record[1]); + bool abort_on_warnings= (rli->sql_thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)); m_curr_row= m_curr_row_end; - error= unpack_current_row(rli); // this also updates m_curr_row_end + /* this also updates m_curr_row_end */ + if ((error= unpack_current_row(rli, abort_on_warnings))) + return error; /* Now we have the right row to update. The old row (the one we're diff --git a/sql/log_event.h b/sql/log_event.h index 31d4a7480c2..0b4c63a73af 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -3541,12 +3541,16 @@ protected: int write_row(const Relay_log_info *const, const bool); // Unpack the current row into m_table->record[0] - int unpack_current_row(const Relay_log_info *const rli) + int unpack_current_row(const Relay_log_info *const rli, + const bool abort_on_warning= TRUE) { DBUG_ASSERT(m_table); + + bool first_row= (m_curr_row == m_rows_buf); ASSERT_OR_RETURN_ERROR(m_curr_row < m_rows_end, HA_ERR_CORRUPT_EVENT); int const result= ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols, - &m_curr_row_end, &m_master_reclength); + &m_curr_row_end, &m_master_reclength, + abort_on_warning, first_row); if (m_curr_row_end > m_rows_end) my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0)); ASSERT_OR_RETURN_ERROR(m_curr_row_end <= m_rows_end, HA_ERR_CORRUPT_EVENT); diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index f4768e2456a..8e80620dd2c 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -180,7 +180,8 @@ int unpack_row(Relay_log_info const *rli, TABLE *table, uint const colcnt, uchar const *const row_data, MY_BITMAP const *cols, - uchar const **const row_end, ulong *const master_reclength) + uchar const **const row_end, ulong *const master_reclength, + const bool abort_on_warning, const bool first_row) { DBUG_ENTER("unpack_row"); DBUG_ASSERT(row_data); @@ -224,8 +225,35 @@ unpack_row(Relay_log_info const *rli, /* Field...::unpack() cannot return 0 */ DBUG_ASSERT(pack_ptr != NULL); - if ((null_bits & null_mask) && f->maybe_null()) - f->set_null(); + if (null_bits & null_mask) + { + if (f->maybe_null()) + { + DBUG_PRINT("debug", ("Was NULL; null mask: 0x%x; null bits: 0x%x", + null_mask, null_bits)); + f->set_null(); + } + else + { + MYSQL_ERROR::enum_warning_level error_type= + MYSQL_ERROR::WARN_LEVEL_NOTE; + if (abort_on_warning && (table->file->has_transactions() || + first_row)) + { + error = HA_ERR_ROWS_EVENT_APPLY; + error_type= MYSQL_ERROR::WARN_LEVEL_ERROR; + } + else + { + f->set_default(); + error_type= MYSQL_ERROR::WARN_LEVEL_WARN; + } + push_warning_printf(current_thd, error_type, + ER_BAD_NULL_ERROR, + ER(ER_BAD_NULL_ERROR), + f->field_name); + } + } else { f->set_notnull(); @@ -315,7 +343,7 @@ unpack_row(Relay_log_info const *rli, */ int prepare_record(TABLE *const table, const uint skip, const bool check, - const bool abort_on_warning) + const bool abort_on_warning, const bool first_row) { DBUG_ENTER("prepare_record"); @@ -343,14 +371,24 @@ int prepare_record(TABLE *const table, if ((f->flags & NO_DEFAULT_VALUE_FLAG) && (f->real_type() != MYSQL_TYPE_ENUM)) { - push_warning_printf(current_thd, abort_on_warning? - MYSQL_ERROR::WARN_LEVEL_ERROR : - MYSQL_ERROR::WARN_LEVEL_WARN, + + MYSQL_ERROR::enum_warning_level error_type= + MYSQL_ERROR::WARN_LEVEL_NOTE; + if (abort_on_warning && (table->file->has_transactions() || + first_row)) + { + error= HA_ERR_ROWS_EVENT_APPLY; + error_type= MYSQL_ERROR::WARN_LEVEL_ERROR; + } + else + { + f->set_default(); + error_type= MYSQL_ERROR::WARN_LEVEL_WARN; + } + push_warning_printf(current_thd, error_type, ER_NO_DEFAULT_FOR_FIELD, ER(ER_NO_DEFAULT_FOR_FIELD), f->field_name); - if (abort_on_warning) - error = HA_ERR_ROWS_EVENT_APPLY; } } diff --git a/sql/rpl_record.h b/sql/rpl_record.h index ab2bcd382ca..6e8838f82b3 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -27,11 +27,13 @@ size_t pack_row(TABLE* table, MY_BITMAP const* cols, int unpack_row(Relay_log_info const *rli, TABLE *table, uint const colcnt, uchar const *const row_data, MY_BITMAP const *cols, - uchar const **const row_end, ulong *const master_reclength); + uchar const **const row_end, ulong *const master_reclength, + const bool abort_on_warning= TRUE, const bool first_row= TRUE); // Fill table's record[0] with default values. int prepare_record(TABLE *const table, const uint skip, const bool check, - const bool abort_on_warning= FALSE); + const bool abort_on_warning= TRUE, + const bool first_row= TRUE); #endif #endif From 925ac7f4eb3672b09b3414b257750345e80022b6 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 22 Oct 2009 01:19:52 +0100 Subject: [PATCH 004/344] BUG#48091 valgrind errors when slave has double not null and master has double null Backporting BUG#43789 to mysql-5.1-bugteam Post-fix for BUG#43789. --- mysql-test/extra/rpl_tests/rpl_not_null.test | 36 +++++++++---------- .../suite/rpl/r/rpl_not_null_innodb.result | 24 ++++++------- .../suite/rpl/r/rpl_not_null_myisam.result | 24 ++++++------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_not_null.test b/mysql-test/extra/rpl_tests/rpl_not_null.test index 88f37f9a95e..58dbd9ce29f 100644 --- a/mysql-test/extra/rpl_tests/rpl_not_null.test +++ b/mysql-test/extra/rpl_tests/rpl_not_null.test @@ -81,13 +81,13 @@ source include/diff_tables.inc; --echo TABLES t2 and t3 must be different. connection master; -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; connection slave; -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; connection master; -SELECT * FROM t4; +SELECT * FROM t4 ORDER BY a; connection slave; -SELECT * FROM t4; +SELECT * FROM t4 ORDER BY a; --echo ************* EXECUTION WITH UPDATES and REPLACES ************* connection master; @@ -139,9 +139,9 @@ INSERT INTO t1(a) VALUES (5); --echo TABLES t1 and t2 must be different. sync_slave_with_master; connection master; -SELECT a,b+0,c+0 FROM t1; +SELECT a,b+0,c+0 FROM t1 ORDER BY a; connection slave; -SELECT a,b+0,c+0 FROM t1; +SELECT a,b+0,c+0 FROM t1 ORDER BY a; --echo ************* EXECUTION WITH UPDATES and REPLACES ************* connection master; @@ -262,17 +262,17 @@ sync_slave_with_master; # connection slave; # --source include/wait_for_slave_sql_to_stop.inc # connection master; -# SELECT * FROM t1; +# SELECT * FROM t1 ORDER BY a; # connection slave; -# SELECT * FROM t1; +# SELECT * FROM t1 ORDER BY a; # connection master; -# SELECT * FROM t2; +# SELECT * FROM t2 ORDER BY a; # connection slave; -# SELECT * FROM t2; +# SELECT * FROM t2 ORDER BY a; # connection master; -# SELECT * FROM t3; +# SELECT * FROM t3 ORDER BY a; # connection slave; -# SELECT * FROM t3; +# SELECT * FROM t3 ORDER BY a; # --source include/reset_master_and_slave.inc # # connection master; @@ -343,17 +343,17 @@ connection master; sync_slave_with_master; connection master; -SELECT * FROM t1; +SELECT * FROM t1 ORDER BY a; connection slave; -SELECT * FROM t1; +SELECT * FROM t1 ORDER BY a; connection master; -SELECT * FROM t2; +SELECT * FROM t2 ORDER BY a; connection slave; -SELECT * FROM t2; +SELECT * FROM t2 ORDER BY a; connection master; -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; connection slave; -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; connection master; diff --git a/mysql-test/suite/rpl/r/rpl_not_null_innodb.result b/mysql-test/suite/rpl/r/rpl_not_null_innodb.result index 7717beb0a47..b09fbab905a 100644 --- a/mysql-test/suite/rpl/r/rpl_not_null_innodb.result +++ b/mysql-test/suite/rpl/r/rpl_not_null_innodb.result @@ -48,24 +48,24 @@ TABLES t1 and t2 must be equal otherwise an error will be thrown. Comparing tables master:test.t1 and slave:test.t1 Comparing tables master:test.t2 and slave:test.t2 TABLES t2 and t3 must be different. -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; a b 1 NULL 2 1111-11-11 3 NULL -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; a b c 1 NULL 500 2 1111-11-11 500 3 NULL 500 -SELECT * FROM t4; +SELECT * FROM t4 ORDER BY a; a b c 1 NULL 1 2 1111-11-11 2 3 NULL NULL 4 NULL 4 5 NULL NULL -SELECT * FROM t4; +SELECT * FROM t4 ORDER BY a; a b 1 NULL 2 1111-11-11 @@ -100,14 +100,14 @@ INSERT INTO t1(a,c) VALUES (4, b'01'); INSERT INTO t1(a) VALUES (5); ************* SHOWING THE RESULT SETS WITH INSERTS ************* TABLES t1 and t2 must be different. -SELECT a,b+0,c+0 FROM t1; +SELECT a,b+0,c+0 FROM t1 ORDER BY a; a b+0 c+0 1 NULL 1 2 0 1 3 NULL NULL 4 NULL 1 5 NULL NULL -SELECT a,b+0,c+0 FROM t1; +SELECT a,b+0,c+0 FROM t1 ORDER BY a; a b+0 c+0 1 NULL 1 2 0 1 @@ -163,34 +163,34 @@ REPLACE INTO t3(a, b) VALUES (5, null); REPLACE INTO t3(a, b) VALUES (3, null); UPDATE t3 SET b = NULL where a = 4; ************* SHOWING THE RESULT SETS ************* -SELECT * FROM t1; +SELECT * FROM t1 ORDER BY a; a b 1 NULL 2 NULL 3 1 -SELECT * FROM t1; +SELECT * FROM t1 ORDER BY a; a b c 1 0 0 2 0 0 3 1 0 -SELECT * FROM t2; +SELECT * FROM t2 ORDER BY a; a b 1 NULL 2 NULL 3 1 -SELECT * FROM t2; +SELECT * FROM t2 ORDER BY a; a b c 1 0 NULL 2 0 NULL 3 1 NULL -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; a b 1 NULL 2 NULL 3 NULL 4 NULL 5 NULL -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; a b c 1 0 500 2 0 500 diff --git a/mysql-test/suite/rpl/r/rpl_not_null_myisam.result b/mysql-test/suite/rpl/r/rpl_not_null_myisam.result index 57a015367bb..09611dc6480 100644 --- a/mysql-test/suite/rpl/r/rpl_not_null_myisam.result +++ b/mysql-test/suite/rpl/r/rpl_not_null_myisam.result @@ -48,24 +48,24 @@ TABLES t1 and t2 must be equal otherwise an error will be thrown. Comparing tables master:test.t1 and slave:test.t1 Comparing tables master:test.t2 and slave:test.t2 TABLES t2 and t3 must be different. -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; a b 1 NULL 2 1111-11-11 3 NULL -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; a b c 1 NULL 500 2 1111-11-11 500 3 NULL 500 -SELECT * FROM t4; +SELECT * FROM t4 ORDER BY a; a b c 1 NULL 1 2 1111-11-11 2 3 NULL NULL 4 NULL 4 5 NULL NULL -SELECT * FROM t4; +SELECT * FROM t4 ORDER BY a; a b 1 NULL 2 1111-11-11 @@ -100,14 +100,14 @@ INSERT INTO t1(a,c) VALUES (4, b'01'); INSERT INTO t1(a) VALUES (5); ************* SHOWING THE RESULT SETS WITH INSERTS ************* TABLES t1 and t2 must be different. -SELECT a,b+0,c+0 FROM t1; +SELECT a,b+0,c+0 FROM t1 ORDER BY a; a b+0 c+0 1 NULL 1 2 0 1 3 NULL NULL 4 NULL 1 5 NULL NULL -SELECT a,b+0,c+0 FROM t1; +SELECT a,b+0,c+0 FROM t1 ORDER BY a; a b+0 c+0 1 NULL 1 2 0 1 @@ -163,34 +163,34 @@ REPLACE INTO t3(a, b) VALUES (5, null); REPLACE INTO t3(a, b) VALUES (3, null); UPDATE t3 SET b = NULL where a = 4; ************* SHOWING THE RESULT SETS ************* -SELECT * FROM t1; +SELECT * FROM t1 ORDER BY a; a b 1 NULL 2 NULL 3 1 -SELECT * FROM t1; +SELECT * FROM t1 ORDER BY a; a b c 1 0 0 2 0 0 3 1 0 -SELECT * FROM t2; +SELECT * FROM t2 ORDER BY a; a b 1 NULL 2 NULL 3 1 -SELECT * FROM t2; +SELECT * FROM t2 ORDER BY a; a b c 1 0 NULL 2 0 NULL 3 1 NULL -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; a b 1 NULL 2 NULL 3 NULL 4 NULL 5 NULL -SELECT * FROM t3; +SELECT * FROM t3 ORDER BY a; a b c 1 0 500 2 0 500 From 0c2d74c60be4604d08b7893178da69fbf1105146 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 22 Oct 2009 01:21:50 +0100 Subject: [PATCH 005/344] BUG#48091 valgrind errors when slave has double not null and master has double null Backporting BUG#47741 to mysql-5.1-bugteam --- .../extra/rpl_tests/rpl_extraSlave_Col.test | 75 ++++++++++--------- .../suite/rpl_ndb/r/rpl_ndb_extraCol.result | 56 -------------- 2 files changed, 39 insertions(+), 92 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test index 1eaefa661f9..46168d6b97a 100644 --- a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test +++ b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test @@ -410,51 +410,54 @@ sync_slave_with_master; ############################################################### # Error reaction is up to sql_mode of the slave sql (bug#38173) #--echo *** Create t9 on slave *** -STOP SLAVE; -RESET SLAVE; -eval CREATE TABLE t9 (a INT KEY, b BLOB, c CHAR(5), - d TIMESTAMP, - e INT NOT NULL, - f text not null, - g text, - h blob not null, - i blob) ENGINE=$engine_type; +# Please, check BUG#47741 to see why you are not testing NDB. +if (`SELECT $engine_type != 'NDB'`) +{ + STOP SLAVE; + RESET SLAVE; + eval CREATE TABLE t9 (a INT KEY, b BLOB, c CHAR(5), + d TIMESTAMP, + e INT NOT NULL, + f text not null, + g text, + h blob not null, + i blob) ENGINE=$engine_type; ---echo *** Create t9 on Master *** -connection master; -eval CREATE TABLE t9 (a INT PRIMARY KEY, b BLOB, c CHAR(5) + --echo *** Create t9 on Master *** + connection master; + eval CREATE TABLE t9 (a INT PRIMARY KEY, b BLOB, c CHAR(5) ) ENGINE=$engine_type; -RESET MASTER; + RESET MASTER; ---echo *** Start Slave *** -connection slave; -START SLAVE; + --echo *** Start Slave *** + connection slave; + START SLAVE; ---echo *** Master Data Insert *** -connection master; -set @b1 = 'b1b1b1b1'; -set @b1 = concat(@b1,@b1); -INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); + --echo *** Master Data Insert *** + connection master; + set @b1 = 'b1b1b1b1'; -# the test would stop slave if @@sql_mode for the sql thread -# was set to strict. Otherwise, as with this tests setup, -# the implicit defaults will be inserted into fields even though -# they are declared without DEFAULT clause. + set @b1 = concat(@b1,@b1); + INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); -sync_slave_with_master; -select * from t9; + # the test would stop slave if @@sql_mode for the sql thread + # was set to strict. Otherwise, as with this tests setup, + # the implicit defaults will be inserted into fields even though + # they are declared without DEFAULT clause. -# todo: fix Bug #43992 slave sql thread can't tune own sql_mode ... -# and add/restore waiting for stop test - -#--source include/wait_for_slave_sql_to_stop.inc -#--replace_result $MASTER_MYPORT MASTER_PORT -#--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 # -#--query_vertical SHOW SLAVE STATUS -#SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; -#START SLAVE; + sync_slave_with_master; + select * from t9; + # todo: fix Bug #43992 slave sql thread can't tune own sql_mode ... + # and add/restore waiting for stop test + #--source include/wait_for_slave_sql_to_stop.inc + #--replace_result $MASTER_MYPORT MASTER_PORT + #--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 # + #--query_vertical SHOW SLAVE STATUS + #SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; + #START SLAVE; +} #--echo *** Drop t9 *** #connection master; diff --git a/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result index f812509de6f..f514bf7a75b 100644 --- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result +++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result @@ -400,62 +400,6 @@ set @b1 = concat(@b1,@b1); INSERT INTO t8 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); *** Drop t8 *** DROP TABLE t8; -STOP SLAVE; -RESET SLAVE; -CREATE TABLE t9 (a INT KEY, b BLOB, c CHAR(5), -d TIMESTAMP, -e INT NOT NULL) ENGINE='NDB'; -*** Create t9 on Master *** -CREATE TABLE t9 (a INT PRIMARY KEY, b BLOB, c CHAR(5) -) ENGINE='NDB'; -RESET MASTER; -*** Start Slave *** -START SLAVE; -*** Master Data Insert *** -set @b1 = 'b1b1b1b1'; -set @b1 = concat(@b1,@b1); -INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); -SHOW SLAVE STATUS; -Slave_IO_State # -Master_Host 127.0.0.1 -Master_User root -Master_Port # -Connect_Retry 1 -Master_Log_File master-bin.000001 -Read_Master_Log_Pos # -Relay_Log_File # -Relay_Log_Pos # -Relay_Master_Log_File master-bin.000001 -Slave_IO_Running Yes -Slave_SQL_Running No -Replicate_Do_DB -Replicate_Ignore_DB -Replicate_Do_Table -Replicate_Ignore_Table # -Replicate_Wild_Do_Table -Replicate_Wild_Ignore_Table -Last_Errno 1364 -Last_Error Could not execute Write_rows event on table test.t9; Field 'e' doesn't have a default value, Error_code: 1364; handler error HA_ERR_ROWS_EVENT_APPLY; the event's master log master-bin.000001, end_log_pos 447 -Skip_Counter 0 -Exec_Master_Log_Pos # -Relay_Log_Space # -Until_Condition None -Until_Log_File -Until_Log_Pos 0 -Master_SSL_Allowed No -Master_SSL_CA_File -Master_SSL_CA_Path -Master_SSL_Cert -Master_SSL_Cipher -Master_SSL_Key -Seconds_Behind_Master # -Master_SSL_Verify_Server_Cert No -Last_IO_Errno # -Last_IO_Error # -Last_SQL_Errno 1364 -Last_SQL_Error Could not execute Write_rows event on table test.t9; Field 'e' doesn't have a default value, Error_code: 1364; handler error HA_ERR_ROWS_EVENT_APPLY; the event's master log master-bin.000001, end_log_pos 447 -SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; -START SLAVE; *** Create t10 on slave *** STOP SLAVE; RESET SLAVE; From 45889a58c765a20e98b49bdf6e03dbf8b016f91a Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 3 Nov 2009 15:49:13 +0200 Subject: [PATCH 006/344] Bug #32167: another privilege bypass with DATA/INDEX DIRECTORY Fixed a initialization order remark by Serg : correct directory expansion order implemented on server startup. --- sql/mysqld.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ce1d562d0ca..424ca727409 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7854,14 +7854,8 @@ static void fix_paths(void) pos[0]= FN_LIBCHAR; pos[1]= 0; } - convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS); - my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0)); - mysql_unpacked_real_data_home_len= (int) strlen(mysql_unpacked_real_data_home); - if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR) - --mysql_unpacked_real_data_home_len; - - convert_dirname(language,language,NullS); + convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS); (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home); (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home); @@ -7869,6 +7863,12 @@ static void fix_paths(void) "", ""); opt_plugin_dir_ptr= opt_plugin_dir; + my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0)); + mysql_unpacked_real_data_home_len= + (int) strlen(mysql_unpacked_real_data_home); + if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR) + --mysql_unpacked_real_data_home_len; + char *sharedir=get_relative_path(SHAREDIR); if (test_if_hard_path(sharedir)) strmake(buff,sharedir,sizeof(buff)-1); /* purecov: tested */ From cf2a674060cb27000dfd5aecaa361fee0ba4eb28 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 10 Nov 2009 11:34:58 +0200 Subject: [PATCH 007/344] removed a duplicate make target --- Makefile.am | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 49ab3103c25..821f7e4fd0f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -196,10 +196,6 @@ test-bt-fast: -cd mysql-test ; MTR_BUILD_THREAD=auto \ @PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress -test-bt-fast: - -cd mysql-test ; MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --force --comment=ps --ps-protocol --report-features - test-bt-debug: -cd mysql-test ; MTR_BUILD_THREAD=auto \ @PERL@ ./mysql-test-run.pl --comment=debug --force --timer \ From 313c5a01eea6fe4ab528066a7b14fe6b63e2c633 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 27 Oct 2009 14:43:12 +0200 Subject: [PATCH 008/344] Bug #47930: MATCH IN BOOLEAN MODE returns too many results inside subquery Re-setting a fulltext index was a no-operation if not all the matches of a search were consumed by reading them. This was preventing a joined table using a fulltext index in a subquery that requires only 1 row of output (e.g. EXISTS) from working correctly because the second execution of the sub-query has the fulltext index cursor in a wrong state and was not finding results. Fixed by making the re-init code _ftb_init_index_search() to re-set open cursors in addition to depleted ones. --- mysql-test/r/fulltext.result | 39 ++++++++++++++++++++++++++++ mysql-test/t/fulltext.test | 41 ++++++++++++++++++++++++++++++ storage/myisam/ft_boolean_search.c | 3 +-- 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index a5216189d9a..6022231907b 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -551,3 +551,42 @@ EXECUTE s; MATCH (col) AGAINST('findme') DEALLOCATE PREPARE s; DROP TABLE t1; +# +# Bug #47930: MATCH IN BOOLEAN MODE returns too many results +# inside subquery +# +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1), (2); +CREATE TABLE t2 (a int, b2 char(10), FULLTEXT KEY b2 (b2)); +INSERT INTO t2 VALUES (1,'Scargill'); +CREATE TABLE t3 (a int, b int); +INSERT INTO t3 VALUES (1,1), (2,1); +# t2 should use full text index +EXPLAIN +SELECT count(*) FROM t1 WHERE +not exists( +SELECT 1 FROM t2, t3 +WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t2 fulltext b2 b2 0 1 Using where +2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using where +# should return 0 +SELECT count(*) FROM t1 WHERE +not exists( +SELECT 1 FROM t2, t3 +WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE) +); +count(*) +0 +# should return 0 +SELECT count(*) FROM t1 WHERE +not exists( +SELECT 1 FROM t2 IGNORE INDEX (b2), t3 +WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE) +); +count(*) +0 +DROP TABLE t1,t2,t3; +End of 5.1 tests diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 80c8658d35c..4537559509d 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -484,3 +484,44 @@ PREPARE s FROM EXECUTE s; DEALLOCATE PREPARE s; DROP TABLE t1; + +--echo # +--echo # Bug #47930: MATCH IN BOOLEAN MODE returns too many results +--echo # inside subquery +--echo # + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1), (2); + +CREATE TABLE t2 (a int, b2 char(10), FULLTEXT KEY b2 (b2)); +INSERT INTO t2 VALUES (1,'Scargill'); + +CREATE TABLE t3 (a int, b int); +INSERT INTO t3 VALUES (1,1), (2,1); + +--echo # t2 should use full text index +EXPLAIN +SELECT count(*) FROM t1 WHERE + not exists( + SELECT 1 FROM t2, t3 + WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE) + ); + +--echo # should return 0 +SELECT count(*) FROM t1 WHERE + not exists( + SELECT 1 FROM t2, t3 + WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE) + ); + +--echo # should return 0 +SELECT count(*) FROM t1 WHERE + not exists( + SELECT 1 FROM t2 IGNORE INDEX (b2), t3 + WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE) + ); + +DROP TABLE t1,t2,t3; + + +--echo End of 5.1 tests diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 0a2847be514..492261c5efc 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -475,8 +475,7 @@ static void _ftb_init_index_search(FT_INFO *ftb) int i; FTB_WORD *ftbw; - if ((ftb->state != READY && ftb->state !=INDEX_DONE) || - ftb->keynr == NO_SUCH_KEY) + if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY) return; ftb->state=INDEX_SEARCH; From be04d1a47953188ced936a81824fdf871b8e9656 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Thu, 29 Oct 2009 22:06:10 -0700 Subject: [PATCH 009/344] Bug#48319: Server crashes on "GRANT/REVOKE ... TO CURRENT_USER" CURRENT_USER() in GRANT ... TO CURRENT_USER() only gave us a definer, not a full user (i.e., password-element was not initiliazed). Hence dereferencing the password led to a crash. Properly initializes definers now, just so there are no misunderstandings. Also does some magic so IDENTIFIED BY ... works with CURRENT_USER(). mysql-test/r/grant2.result: Show GRANT ... TO CURRENT_USER() no longer crashes. Show it to work with IDENTIFIED BY to boot. mysql-test/t/grant2.test: Show GRANT ... TO CURRENT_USER() no longer crashes. Show it to work with IDENTIFIED BY to boot. sql/sql_acl.cc: Make IDENTIFIED BY ... work with CURRENT_USER() sql/sql_parse.cc: Zero password-part of definer just in case somebody mistakes this for a complete LEX_USER! --- mysql-test/r/grant2.result | 27 +++++++++++++++++++++++++++ mysql-test/t/grant2.test | 35 +++++++++++++++++++++++++++++++++++ sql/sql_acl.cc | 7 +++++++ sql/sql_parse.cc | 5 +++++ 4 files changed, 74 insertions(+) diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index 7c2023127f0..12269f0cb1c 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -443,3 +443,30 @@ DROP TABLE db1.t1, db1.t2; DROP USER mysqltest1@localhost; DROP DATABASE db1; End of 5.0 tests +USE mysql; +SELECT LEFT(CURRENT_USER(),INSTR(CURRENT_USER(),'@')-1) INTO @u; +SELECT MID(CURRENT_USER(),INSTR(CURRENT_USER(),'@')+1) INTO @h; +SELECT password FROM user WHERE user=@u AND host=@h INTO @pwd; +SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; +user host password insert_priv +root localhost Y +UPDATE user SET insert_priv='N' WHERE user=@u AND host=@h; +SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; +user host password insert_priv +root localhost N +GRANT INSERT ON *.* TO CURRENT_USER(); +SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; +user host password insert_priv +root localhost Y +UPDATE user SET insert_priv='N' WHERE user=@u AND host=@h; +GRANT INSERT ON *.* TO CURRENT_USER() IDENTIFIED BY 'keksdose'; +SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; +user host password insert_priv +root localhost *0BB7188CF0DE9B403BA66E9DD810D82652D002EB Y +UPDATE user SET password=@pwd WHERE user=@u AND host=@h; +SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; +user host password insert_priv +root localhost Y +FLUSH PRIVILEGES; +USE test; +End of 5.1 tests diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index 54cdf8d6cc1..447848013f9 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -632,5 +632,40 @@ DROP DATABASE db1; --echo End of 5.0 tests +# +# Bug #48319: Server crashes on "GRANT/REVOKE ... TO CURRENT_USER" +# + +# work out who we are. +USE mysql; +SELECT LEFT(CURRENT_USER(),INSTR(CURRENT_USER(),'@')-1) INTO @u; +SELECT MID(CURRENT_USER(),INSTR(CURRENT_USER(),'@')+1) INTO @h; +SELECT password FROM user WHERE user=@u AND host=@h INTO @pwd; + +# show current privs. +SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; + +# toggle INSERT +UPDATE user SET insert_priv='N' WHERE user=@u AND host=@h; +SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; + +# show that GRANT ... TO CURRENT_USER() no longer crashes +GRANT INSERT ON *.* TO CURRENT_USER(); +SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; +UPDATE user SET insert_priv='N' WHERE user=@u AND host=@h; + +# show that GRANT ... TO CURRENT_USER() IDENTIFIED BY ... works now +GRANT INSERT ON *.* TO CURRENT_USER() IDENTIFIED BY 'keksdose'; +SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; + +UPDATE user SET password=@pwd WHERE user=@u AND host=@h; +SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; + +FLUSH PRIVILEGES; + +USE test; + +--echo End of 5.1 tests + # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0592bb3be1d..5259b560532 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3451,6 +3451,13 @@ bool mysql_grant(THD *thd, const char *db, List &list, result= TRUE; continue; } + /* + No User, but a password? + They did GRANT ... TO CURRENT_USER() IDENTIFIED BY ... ! + Get the current user, and shallow-copy the new password to them! + */ + if (!tmp_Str->user.str && tmp_Str->password.str) + Str->password= tmp_Str->password; if (replace_user_table(thd, tables[0].table, *Str, (!db ? rights : 0), revoke_grant, create_new_users, test(thd->variables.sql_mode & diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2e150ca1542..65d86814045 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7573,6 +7573,9 @@ void get_default_definer(THD *thd, LEX_USER *definer) definer->host.str= (char *) sctx->priv_host; definer->host.length= strlen(definer->host.str); + + definer->password.str= NULL; + definer->password.length= 0; } @@ -7624,6 +7627,8 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) definer->user= *user_name; definer->host= *host_name; + definer->password.str= NULL; + definer->password.length= 0; return definer; } From 141e79616303320289b33323cedbcdbe2d78c445 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Fri, 30 Oct 2009 14:28:33 -0600 Subject: [PATCH 010/344] Bug#35106: mysql_secure_installation fails on Windows, missing "use Term::ReadKey" Add the missing module import. Also, while here, fix a few glaring problems with the script, and ensure that it behaves properly. It seems this script may have never been working correctly (e.g., reading password didn't chomp() the result, so password was set with \n at the end; comparing the re-typed password to original was done with inverted test). Add END { cleanup(); } block to ensure the script removes temporary working files. Add SIG{INT} / SIG{QUIT} handler. Do a bit of reorganization to make the code easier to understand. Limit failed connection attempts to 3. Use ./bin/mysql if it exists, and then fall back on mysql in PATH (before it assumed 'mysql' in the path). Print a nicer error if 'mysql' can't be called. This has been tested on Windows (ActivePerl from cmd.exe, no cygwin needed) and Linux. --- scripts/mysql_secure_installation.pl.in | 175 +++++++++++++----------- 1 file changed, 95 insertions(+), 80 deletions(-) diff --git a/scripts/mysql_secure_installation.pl.in b/scripts/mysql_secure_installation.pl.in index 4eeb50e6d2f..281f3558808 100755 --- a/scripts/mysql_secure_installation.pl.in +++ b/scripts/mysql_secure_installation.pl.in @@ -17,17 +17,42 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA use Fcntl; +use File::Spec; +use if $^O eq 'MSWin32', 'Term::ReadKey' => qw/ReadMode/; use strict; my $config = ".my.cnf.$$"; my $command = ".mysql.$$"; my $hadpass = 0; - -# FIXME -# trap "interrupt" 2 - +my $mysql; # How to call the mysql client my $rootpass = ""; + +$SIG{QUIT} = $SIG{INT} = sub { + print "\nAborting!\n\n"; + echo_on(); + cleanup(); + exit 1; +}; + + +END { + # Remove temporary files, even if exiting via die(), etc. + cleanup(); +} + + +sub read_without_echo { + my ($prompt) = @_; + print $prompt; + echo_off(); + my $answer = ; + echo_on(); + print "\n"; + chomp($answer); + return $answer; +} + sub echo_on { if ($^O eq 'MSWin32') { ReadMode('normal'); @@ -55,6 +80,25 @@ sub write_file { } sub prepare { + # Locate the mysql client; look in current directory first, then + # in path + our $SAVEERR; # Suppress Perl warning message + open SAVEERR, ">& STDERR"; + close STDERR; + for my $m (File::Spec->catfile('bin', 'mysql'), 'mysql') { + # mysql --version should always work + qx($m --no-defaults --version); + next unless $? == 0; + + $mysql = $m; + last; + } + open STDERR, ">& SAVEERR"; + + die "Can't find a 'mysql' client in PATH or ./bin\n" + unless $mysql; + + # Create safe files to avoid leaking info to other users foreach my $file ( $config, $command ) { next if -f $file; # Already exists local *FILE; @@ -67,8 +111,9 @@ sub prepare { sub do_query { my $query = shift; write_file($command, $query); - system("mysql --defaults-file=$config < $command"); - return $?; + my $rv = system("$mysql --defaults-file=$config < $command"); + die "Failed to execute mysql client '$mysql'\n" if $rv == -1; + return ($rv == 0 ? 1 : undef); } sub make_config { @@ -82,12 +127,9 @@ sub make_config { } sub get_root_password { - my $status = 1; - while ( $status == 1 ) { - echo_off(); - print "Enter current password for root (enter for none): "; - my $password = ; - echo_on(); + my $attempts = 3; + for (;;) { + my $password = read_without_echo("Enter current password for root (enter for none): "); if ( $password ) { $hadpass = 1; } else { @@ -95,64 +137,56 @@ sub get_root_password { } $rootpass = $password; make_config($rootpass); - do_query(""); - $status = $?; + last if do_query(""); + + die "Unable to connect to the server as root user, giving up.\n" + if --$attempts == 0; } print "OK, successfully used password, moving on...\n\n"; } sub set_root_password { - echo_off(); - print "New password: "; - my $password1 = ; - print "\nRe-enter new password: "; - my $password2 = ; - print "\n"; - echo_on(); + my $password1; + for (;;) { + $password1 = read_without_echo("New password: "); - if ( $password1 eq $password2 ) { - print "Sorry, passwords do not match.\n\n"; - return 1; - } - - if ( !$password1 ) { - print "Sorry, you can't use an empty password here.\n\n"; - return 1; - } - - do_query("UPDATE mysql.user SET Password=PASSWORD('$password1') WHERE User='root';"); - if ( $? == 0 ) { - print "Password updated successfully!\n"; - print "Reloading privilege tables..\n"; - if ( !reload_privilege_tables() ) { - exit 1; + if ( !$password1 ) { + print "Sorry, you can't use an empty password here.\n\n"; + next; } - print "\n"; - $rootpass = $password1; - make_config($rootpass); - } else { - print "Password update failed!\n"; - exit 1; + + my $password2 = read_without_echo("Re-enter new password: "); + + if ( $password1 ne $password2 ) { + print "Sorry, passwords do not match.\n\n"; + next; + } + + last; } - return 0; + # FIXME: Quote password1 properly for SQL + do_query("UPDATE mysql.user SET Password=PASSWORD('$password1') WHERE User='root';") + or die "Password update failed!\n"; + + print "Password updated successfully!\n"; + print "Reloading privilege tables..\n"; + reload_privilege_tables() + or die "Can not continue.\n"; + + print "\n"; + $rootpass = $password1; + make_config($rootpass); } sub remove_anonymous_users { - do_query("DELETE FROM mysql.user WHERE User='';"); - if ( $? == 0 ) { - print " ... Success!\n"; - } else { - print " ... Failed!\n"; - exit 1; - } - - return 0; + do_query("DELETE FROM mysql.user WHERE User='';") + or die print " ... Failed!\n"; + print " ... Success!\n"; } sub remove_remote_root { - do_query("DELETE FROM mysql.user WHERE User='root' AND Host!='localhost';"); - if ( $? == 0 ) { + if (do_query("DELETE FROM mysql.user WHERE User='root' AND Host!='localhost';")) { print " ... Success!\n"; } else { print " ... Failed!\n"; @@ -161,44 +195,31 @@ sub remove_remote_root { sub remove_test_database { print " - Dropping test database...\n"; - do_query("DROP DATABASE test;"); - if ( $? == 0 ) { + if (do_query("DROP DATABASE test;")) { print " ... Success!\n"; } else { print " ... Failed! Not critical, keep moving...\n"; } print " - Removing privileges on test database...\n"; - do_query("DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'"); - if ( $? == 0 ) { + if (do_query("DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'")) { print " ... Success!\n"; } else { print " ... Failed! Not critical, keep moving...\n"; } - - return 0; } sub reload_privilege_tables { - do_query("FLUSH PRIVILEGES;"); - if ( $? == 0 ) { + if (do_query("FLUSH PRIVILEGES;")) { print " ... Success!\n"; - return 0; + return 1; } else { print " ... Failed!\n"; - return 1; + return undef; } } -sub interrupt { - print "\nAborting!\n\n"; - cleanup(); - echo_on(); - exit 1; -} - sub cleanup { - print "Cleaning up...\n"; unlink($config,$command); } @@ -242,11 +263,7 @@ my $reply = ; if ( $reply =~ /n/i ) { print " ... skipping.\n"; } else { - my $status = 1; - while ( $status == 1 ) { - set_root_password(); - $status = $?; - } + set_root_password(); } print "\n"; @@ -334,8 +351,6 @@ if ( $reply =~ /n/i ) { } print "\n"; -cleanup(); - print < Date: Mon, 2 Nov 2009 00:46:00 -0800 Subject: [PATCH 011/344] Bug#47655: Memory free error when connecting to 4.1 server from 5.1+ client When starting the (5.1+) mysql command-line client, we try to get "select @@version_comment" from the server to present it to the user. Recent clients are aware that older servers do not have that variable and fall back on other info to be able to present *something* at least. This fallback string was allocated through the POSIX interface, but released through the my*() suite, which rightfully complained about the imbalance in calls when compiled with --debug. While this wasn't as bad as it looked (no double-free, use of uninitialized or freed buffer, etc.), it did look funky. Using my_strdup() now for what will be my_free()d later. client/mysql.cc: Use my_strdup() for server_version, as we'll my_free() it later and don't want to upset the mysql client's memory accounting. --- client/mysql.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index b76a3d624ab..4f9aef411ca 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -4474,9 +4474,7 @@ server_version_string(MYSQL *con) */ if (server_version == NULL) - { - server_version= strdup(mysql_get_server_info(con)); - } + server_version= my_strdup(mysql_get_server_info(con), MYF(MY_WME)); } return server_version ? server_version : ""; From b35feb1ed0aa934ea244163ecea54b5e45157138 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Tue, 3 Nov 2009 09:22:01 +0100 Subject: [PATCH 012/344] Bug#46923: select count(*) from partitioned table fails with ONLY_FULL_GROUP_BY Problem was that during checking and preparation of the partitioining function as a side effect in fix_fields the full_group_by_flag was changed. Solution was to set it back to its original value after calling fix_fields. Updated patch, to also exclude allow_sum_func from being affected of fix_fields, as requested by reviewer. mysql-test/r/partition.result: Bug#46923: select count(*) from partitioned table fails with ONLY_FULL_GROUP_BY Updated result file mysql-test/t/partition.test: Bug#46923: select count(*) from partitioned table fails with ONLY_FULL_GROUP_BY Extended test case to cover this bug sql/sql_partition.cc: Bug#46923: select count(*) from partitioned table fails with ONLY_FULL_GROUP_BY Resetting full_group_by_flag and allow_sum_func back to their original values, not conflicting with the sql_mode 'ONLY_FULL_GROUP_BY' --- mysql-test/r/partition.result | 5 +++++ mysql-test/t/partition.test | 3 +++ sql/sql_partition.cc | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 2d54a66fe11..abdeb3a77e1 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -2030,10 +2030,15 @@ DROP TABLE t1; # # Bug #45807: crash accessing partitioned table and sql_mode # contains ONLY_FULL_GROUP_BY +# Bug#46923: select count(*) from partitioned table fails with +# ONLY_FULL_GROUP_BY # SET SESSION SQL_MODE='ONLY_FULL_GROUP_BY'; CREATE TABLE t1(id INT,KEY(id)) ENGINE=MYISAM PARTITION BY HASH(id) PARTITIONS 2; +SELECT COUNT(*) FROM t1; +COUNT(*) +0 DROP TABLE t1; SET SESSION SQL_MODE=DEFAULT; # diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index c5ed098b678..6486b56a551 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -2018,11 +2018,14 @@ DROP TABLE t1; --echo # --echo # Bug #45807: crash accessing partitioned table and sql_mode --echo # contains ONLY_FULL_GROUP_BY +--echo # Bug#46923: select count(*) from partitioned table fails with +--echo # ONLY_FULL_GROUP_BY --echo # SET SESSION SQL_MODE='ONLY_FULL_GROUP_BY'; CREATE TABLE t1(id INT,KEY(id)) ENGINE=MYISAM PARTITION BY HASH(id) PARTITIONS 2; +SELECT COUNT(*) FROM t1; DROP TABLE t1; SET SESSION SQL_MODE=DEFAULT; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 08ff2daacb9..bd66c48b852 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -905,6 +905,8 @@ bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, char* db_name; char db_name_string[FN_REFLEN]; bool save_use_only_table_context; + uint8 saved_full_group_by_flag; + nesting_map saved_allow_sum_func; DBUG_ENTER("fix_fields_part_func"); if (part_info->fixed) @@ -974,9 +976,19 @@ bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, save_use_only_table_context= thd->lex->use_only_table_context; thd->lex->use_only_table_context= TRUE; thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS; + saved_full_group_by_flag= thd->lex->current_select->full_group_by_flag; + saved_allow_sum_func= thd->lex->allow_sum_func; + thd->lex->allow_sum_func= 0; error= func_expr->fix_fields(thd, (Item**)&func_expr); + /* + Restore full_group_by_flag and allow_sum_func, + fix_fields should not affect mysql_select later, see Bug#46923. + */ + thd->lex->current_select->full_group_by_flag= saved_full_group_by_flag; + thd->lex->allow_sum_func= saved_allow_sum_func; + thd->lex->use_only_table_context= save_use_only_table_context; context->table_list= save_table_list; From d31e4636b6e84a0b7ffb0d3d2c86ff0af912a38d Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Tue, 3 Nov 2009 13:32:12 -0700 Subject: [PATCH 013/344] Bug#48086: mysql_secure_installation does NOT work on Solaris Remove a bash-ism (if ! ...). --- scripts/mysql_secure_installation.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh index 6c2d88d6d29..597f6cac83f 100644 --- a/scripts/mysql_secure_installation.sh +++ b/scripts/mysql_secure_installation.sh @@ -98,9 +98,7 @@ set_root_password() { if [ $? -eq 0 ]; then echo "Password updated successfully!" echo "Reloading privilege tables.." - if ! reload_privilege_tables; then - exit 1 - fi + reload_privilege_tables || exit 1 echo rootpass=$password1 make_config From e29b7ef5b8f663c04d7a40a575a6ff8c231c9433 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Tue, 3 Nov 2009 13:50:28 -0700 Subject: [PATCH 014/344] Bug#48031: mysql_secure_installation -- bash bug regarding passwords with special chars This script failed when the user tried passwords with multiple spaces, \, # or ' characters. Now proper escaping and quoting is used in all contexts. This problem occurs in the Perl version of this script, too, so fix it in both places. --- scripts/mysql_secure_installation.pl.in | 24 +++++++++++++++++--- scripts/mysql_secure_installation.sh | 30 ++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/scripts/mysql_secure_installation.pl.in b/scripts/mysql_secure_installation.pl.in index 281f3558808..255416763ef 100755 --- a/scripts/mysql_secure_installation.pl.in +++ b/scripts/mysql_secure_installation.pl.in @@ -108,6 +108,23 @@ sub prepare { } } +# Simple escape mechanism (\-escape any ' and \), suitable for two contexts: +# - single-quoted SQL strings +# - single-quoted option values on the right hand side of = in my.cnf +# +# These two contexts don't handle escapes identically. SQL strings allow +# quoting any character (\C => C, for any C), but my.cnf parsing allows +# quoting only \, ' or ". For example, password='a\b' quotes a 3-character +# string in my.cnf, but a 2-character string in SQL. +# +# This simple escape works correctly in both places. +sub basic_single_escape { + my ($str) = @_; + # Inside a character class, \ is not special; this escapes both \ and ' + $str =~ s/([\'])/\\$1/g; + return $str; +} + sub do_query { my $query = shift; write_file($command, $query); @@ -119,11 +136,12 @@ sub do_query { sub make_config { my $password = shift; + my $esc_pass = basic_single_escape($rootpass); write_file($config, "# mysql_secure_installation config file", "[mysql]", "user=root", - "password=$rootpass"); + "password='$esc_pass'"); } sub get_root_password { @@ -165,8 +183,8 @@ sub set_root_password { last; } - # FIXME: Quote password1 properly for SQL - do_query("UPDATE mysql.user SET Password=PASSWORD('$password1') WHERE User='root';") + my $esc_pass = basic_single_escape($password1); + do_query("UPDATE mysql.user SET Password=PASSWORD('$esc_pass') WHERE User='root';") or die "Password update failed!\n"; print "Password updated successfully!\n"; diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh index 597f6cac83f..25d6343ee2c 100644 --- a/scripts/mysql_secure_installation.sh +++ b/scripts/mysql_secure_installation.sh @@ -38,16 +38,39 @@ prepare() { } do_query() { - echo $1 >$command + echo "$1" >$command + #sed 's,^,> ,' < $command # Debugging mysql --defaults-file=$config <$command return $? } +# Simple escape mechanism (\-escape any ' and \), suitable for two contexts: +# - single-quoted SQL strings +# - single-quoted option values on the right hand side of = in my.cnf +# +# These two contexts don't handle escapes identically. SQL strings allow +# quoting any character (\C => C, for any C), but my.cnf parsing allows +# quoting only \, ' or ". For example, password='a\b' quotes a 3-character +# string in my.cnf, but a 2-character string in SQL. +# +# This simple escape works correctly in both places. +basic_single_escape () { + # The quoting on this sed command is a bit complex. Single-quoted strings + # don't allow *any* escape mechanism, so they cannot contain a single + # quote. The string sed gets (as argv[1]) is: s/\(['\]\)/\\\1/g + # + # Inside a character class, \ and ' are not special, so the ['\] character + # class is balanced and contains two characters. + echo "$1" | sed 's/\(['"'"'\]\)/\\\1/g' +} + make_config() { echo "# mysql_secure_installation config file" >$config echo "[mysql]" >>$config echo "user=root" >>$config - echo "password=$rootpass" >>$config + esc_pass=`basic_single_escape "$rootpass"` + echo "password='$esc_pass'" >>$config + #sed 's,^,> ,' < $config # Debugging } get_root_password() { @@ -94,7 +117,8 @@ set_root_password() { return 1 fi - do_query "UPDATE mysql.user SET Password=PASSWORD('$password1') WHERE User='root';" + esc_pass=`basic_single_escape "$password1"` + do_query "UPDATE mysql.user SET Password=PASSWORD('$esc_pass') WHERE User='root';" if [ $? -eq 0 ]; then echo "Password updated successfully!" echo "Reloading privilege tables.." From 345054c916672dcfb51492d68fc0d00eb999d430 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Tue, 3 Nov 2009 14:34:01 -0700 Subject: [PATCH 015/344] Add a few comments to clarify do_query() return values in mysql_secure_installation.pl --- scripts/mysql_secure_installation.pl.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/mysql_secure_installation.pl.in b/scripts/mysql_secure_installation.pl.in index 255416763ef..25339f9b916 100755 --- a/scripts/mysql_secure_installation.pl.in +++ b/scripts/mysql_secure_installation.pl.in @@ -129,7 +129,11 @@ sub do_query { my $query = shift; write_file($command, $query); my $rv = system("$mysql --defaults-file=$config < $command"); + # system() returns -1 if exec fails (e.g., command not found, etc.); die + # in this case because nothing is going to work die "Failed to execute mysql client '$mysql'\n" if $rv == -1; + # Return true if query executed OK, or false if there was some problem + # (for example, SQL error or wrong password) return ($rv == 0 ? 1 : undef); } From 27028272f31a8b79ef708a68ccf90b03f9907688 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Wed, 4 Nov 2009 01:56:36 +0000 Subject: [PATCH 016/344] BUG#47743: rpl.rpl_log_pos fails sporadically BUG#47983: rpl_extraColmaster_myisam failed in PB2 with "Found warnings!!" BUG 45214 fixed the case when get_master_version_and_clock function, used by the slave, would not report errors. The slave now detects them and if related to transient network failures, it prints some warnings and retries to connect. On the other hand, if not network related, it just gives up and fails. As such, sometimes, in PB2, the slave comes across some transient communication issues between master and slave, while calling get_master_version_and_clock, causing warnings print outs to the error log. Nevertheless, in such cases slave retries to connect, in which it succeeds, and the test case continues as it normally would. But then, at the end of a successful test run, MTR checks the error log, finds the unexpected warnings and considers them harmful. This causes MTR to report error and, consequently, PB2 to report a failing test. We fix this by adding to the global warnings suppress list the warnings related to transient network failures only, which are reported while in function get_master_version_and_clock. --- mysql-test/include/mtr_warnings.sql | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index 134e448953a..5ff6fa5cf11 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -175,6 +175,15 @@ INSERT INTO global_suppressions VALUES ("Can't find file: '.\\\\test\\\\\\?{8}.frm'"), ("Slave: Unknown table 't1' Error_code: 1051"), + /* + Transient network failures that cause warnings on reconnect. + BUG#47743 and BUG#47983. + */ + ("Slave I/O: Get master SERVER_ID failed with error:.*"), + ("Slave I/O: Get master clock failed with error:.*"), + ("Slave I/O: Get master COLLATION_SERVER failed with error:.*"), + ("Slave I/O: Get master TIME_ZONE failed with error:.*"), + ("THE_LAST_SUPPRESSION")|| From b958fc655f85025d7dd6c2b8923ba8fd74652f67 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Nov 2009 14:07:31 +0800 Subject: [PATCH 017/344] Bug #34739 unexpected binlog file name when --log-bin is set to a directory name If --log-bin is set to a directory name with the trailing 'FN_LIBCHAR', which will be '/' on Unix like systems, and '\\' on Windows like systems. the basename of the binlog is empty so that the created files named '.000001' and '.index'. It is not expected. The same thing happened to --log-bin-index, --relay-log and --relay-log-index options. To resolve the problem, in these cases the program should report an error and abort. sql/mysqld.cc: Added a check for the value of the --log-bin and --log-bin-index arguments, if it's a directory, reports an error and aborts. sql/rpl_rli.cc: Added a check for the value of the --relay-log and --relay-log-index arguments, if it's a directory, reports an error and aborts. --- sql/mysqld.cc | 21 +++++++++++++++++++++ sql/rpl_rli.cc | 23 +++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1da51338517..2be95bca54d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3888,6 +3888,27 @@ server."); if (opt_bin_log) { + /* Reports an error and aborts, if the --log-bin's path + is a directory.*/ + if (opt_bin_logname && + opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR) + { + sql_print_error("Path '%s' is a directory name, please specify \ +a file name for --log-bin option", opt_bin_logname); + unireg_abort(1); + } + + /* Reports an error and aborts, if the --log-bin-index's path + is a directory.*/ + if (opt_binlog_index_name && + opt_binlog_index_name[strlen(opt_binlog_index_name) - 1] + == FN_LIBCHAR) + { + sql_print_error("Path '%s' is a directory name, please specify \ +a file name for --log-bin-index option", opt_binlog_index_name); + unireg_abort(1); + } + char buf[FN_REFLEN]; const char *ln; ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf); diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 0c6cc15297f..a9ed736b453 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -132,6 +132,29 @@ int init_relay_log_info(Relay_log_info* rli, rli->relay_log.max_size (and mysql_bin_log.max_size). */ { + /* Reports an error and returns, if the --relay-log's path + is a directory.*/ + if (opt_relay_logname && + opt_relay_logname[strlen(opt_relay_logname) - 1] == FN_LIBCHAR) + { + pthread_mutex_unlock(&rli->data_lock); + sql_print_error("Path '%s' is a directory name, please specify \ +a file name for --relay-log option", opt_relay_logname); + DBUG_RETURN(1); + } + + /* Reports an error and returns, if the --relay-log-index's path + is a directory.*/ + if (opt_relaylog_index_name && + opt_relaylog_index_name[strlen(opt_relaylog_index_name) - 1] + == FN_LIBCHAR) + { + pthread_mutex_unlock(&rli->data_lock); + sql_print_error("Path '%s' is a directory name, please specify \ +a file name for --relay-log-index option", opt_relaylog_index_name); + DBUG_RETURN(1); + } + char buf[FN_REFLEN]; const char *ln; static bool name_warning_sent= 0; From b7ceeccdbe4f021e3d370a2448a0bd1916591474 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 5 Nov 2009 07:48:50 -0200 Subject: [PATCH 018/344] Introduce support for automake-1.11 silent-rules. configure.in: Activate silent-rules if automake supports it. --- configure.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configure.in b/configure.in index d479088356b..dda7b268d19 100644 --- a/configure.in +++ b/configure.in @@ -13,6 +13,12 @@ AC_CANONICAL_SYSTEM AM_INIT_AUTOMAKE(mysql, 5.1.41) AM_CONFIG_HEADER([include/config.h:config.h.in]) +# Request support for automake silent-rules if available. +# Default to verbose output. One can use the configure-time +# option --enable-silent-rules or make V=1 to activate +# silent rules. +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([no])]) + PROTOCOL_VERSION=10 DOT_FRM_VERSION=6 # See the libtool docs for information on how to do shared lib versions. From 43d7fb43cd965ae8e53d8253388b6ac58a7ebddc Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 4 Nov 2009 13:54:28 +0200 Subject: [PATCH 019/344] Bug #46175: NULL read_view and consistent read assertion The SE API requires mysql to notify the storage engine that it's going to read certain tables at the beginning of the statement (by calling start_stmt(), store_lock() or external_lock()). These are typically called by the lock_tables(). However SHOW CREATE TABLE is not pre-locking the tables because it's not expected to access the data at all. But for some view definitions (that include comparing a date/datetime/timestamp column to a string returning scalar subquery) the JOIN::prepare may still access data when materializing the scalar non-correlated subquery in Arg_comparator::can_compare_as_dates(). Fixed by not materializing the subquery when the function is called in a SHOW/EXPLAIN/CREATE VIEW --- mysql-test/r/innodb_mysql.result | 22 +++++++++++++++ mysql-test/t/innodb_mysql.test | 46 ++++++++++++++++++++++++++++++++ sql/item_cmpfunc.cc | 10 +++++-- 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index c882d2af1ed..402ab3c1b16 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -2251,4 +2251,26 @@ c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables DROP TABLE t1; +# +# Bug #46175: NULL read_view and consistent read assertion +# +CREATE TABLE t1(a CHAR(13),KEY(a)) ENGINE=innodb; +CREATE TABLE t2(b DATETIME,KEY(b)) ENGINE=innodb; +INSERT INTO t1 VALUES (),(); +INSERT INTO t2 VALUES (),(); +CREATE OR REPLACE VIEW v1 AS SELECT 1 FROM t2 +WHERE b =(SELECT a FROM t1 LIMIT 1); +CREATE PROCEDURE p1(num INT) +BEGIN +DECLARE i INT DEFAULT 0; +REPEAT +SHOW CREATE VIEW v1; +SET i:=i+1; +UNTIL i>num END REPEAT; +END| +# Should not crash +# Should not crash +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1,t2; End of 5.1 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 7055879ce1a..a2a1113598d 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -489,5 +489,51 @@ EXPLAIN SELECT * FROM t1 WHERE a = 'TEST' AND c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; DROP TABLE t1; +--echo # +--echo # Bug #46175: NULL read_view and consistent read assertion +--echo # + +CREATE TABLE t1(a CHAR(13),KEY(a)) ENGINE=innodb; +CREATE TABLE t2(b DATETIME,KEY(b)) ENGINE=innodb; +INSERT INTO t1 VALUES (),(); +INSERT INTO t2 VALUES (),(); +CREATE OR REPLACE VIEW v1 AS SELECT 1 FROM t2 + WHERE b =(SELECT a FROM t1 LIMIT 1); + +--disable_query_log +--disable_result_log +CONNECT (con1, localhost, root,,); +--enable_query_log +--enable_result_log +CONNECTION default; + +DELIMITER |; +CREATE PROCEDURE p1(num INT) +BEGIN + DECLARE i INT DEFAULT 0; + REPEAT + SHOW CREATE VIEW v1; + SET i:=i+1; + UNTIL i>num END REPEAT; +END| +DELIMITER ;| + +--echo # Should not crash +--disable_query_log +--disable_result_log +--send CALL p1(1000) +CONNECTION con1; +--echo # Should not crash +CALL p1(1000); + +CONNECTION default; +--reap +--enable_query_log +--enable_result_log + +DISCONNECT con1; +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1,t2; --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c6b88cd8188..0f02b83ade4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -785,15 +785,21 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value) if (cmp_type != CMP_DATE_DFLT) { + THD *thd= current_thd; /* Do not cache GET_USER_VAR() function as its const_item() may return TRUE for the current thread but it still may change during the execution. + Don't use cache while in the context analysis mode only (i.e. for + EXPLAIN/CREATE VIEW and similar queries). Cache is useless in such + cases and can cause problems. For example evaluating subqueries can + confuse storage engines since in context analysis mode tables + aren't locked. */ - if (cmp_type != CMP_DATE_WITH_DATE && str_arg->const_item() && + if (!thd->is_context_analysis_only() && + cmp_type != CMP_DATE_WITH_DATE && str_arg->const_item() && (str_arg->type() != Item::FUNC_ITEM || ((Item_func*)str_arg)->functype() != Item_func::GUSERVAR_FUNC)) { - THD *thd= current_thd; ulonglong value; bool error; String tmp, *str_val= 0; From 4819f65a8b1751f126c8ef79d8cfced5ada8f50f Mon Sep 17 00:00:00 2001 From: Aleksandr Kuzminsky Date: Wed, 4 Nov 2009 12:11:12 -0800 Subject: [PATCH 020/344] Sync with rev. 114 --- buf/buf0buddy.c | 7 +- buf/buf0buf.c | 106 ++++++++++- buf/buf0flu.c | 25 +-- buf/buf0lru.c | 15 +- buf/buf0rea.c | 34 ++-- dict/dict0dict.c | 2 +- fil/fil0fil.c | 9 +- handler/ha_innodb.cc | 215 ++++++++++++++++++---- handler/handler0alter.cc | 17 ++ handler/i_s.cc | 137 ++++++++++++++ handler/i_s.h | 1 + handler/innodb_patch_info.h | 3 + include/buf0buf.ic | 8 +- include/buf0rea.h | 7 +- include/fil0fil.h | 8 +- include/os0file.h | 12 +- include/srv0srv.h | 13 +- include/sync0rw.h | 9 +- include/sync0sync.h | 8 +- include/trx0purge.h | 24 +++ include/trx0trx.h | 11 ++ lock/lock0lock.c | 12 ++ log/log0log.c | 10 + mysql-test/innodb-index.result | 1 + mysql-test/innodb-index.test | 2 + mysql-test/innodb_file_format.result | 4 +- mysql-test/innodb_file_format.test | 16 +- mysql-test/innodb_xtradb_bug317074.result | 1 - mysql-test/innodb_xtradb_bug317074.test | 4 +- mysql-test/patches/disabled.def.diff | 11 +- mysql-test/patches/innodb_bug46000.diff | 26 +++ os/os0file.c | 60 +++++- row/row0mysql.c | 10 - srv/srv0srv.c | 107 ++++++++++- srv/srv0start.c | 13 +- sync/sync0arr.c | 9 +- sync/sync0rw.c | 35 ++-- sync/sync0sync.c | 19 +- trx/trx0purge.c | 86 ++++++++- trx/trx0trx.c | 42 +++++ 40 files changed, 965 insertions(+), 174 deletions(-) create mode 100644 mysql-test/patches/innodb_bug46000.diff diff --git a/buf/buf0buddy.c b/buf/buf0buddy.c index 6ee7a71a2e5..586a8dee1a2 100644 --- a/buf/buf0buddy.c +++ b/buf/buf0buddy.c @@ -531,11 +531,10 @@ buf_buddy_relocate( UNIV_MEM_ASSERT_W(src, size); mutex = buf_page_get_mutex_enter(bpage); - ut_a(mutex); mutex_enter(&zip_free_mutex); - if (buf_page_can_relocate(bpage)) { + if (mutex && buf_page_can_relocate(bpage)) { /* Relocate the compressed page. */ ut_a(bpage->zip.data == src); memcpy(dst, src, size); @@ -563,7 +562,9 @@ success: rw_lock_x_unlock(&page_hash_latch); } - mutex_exit(mutex); + if (mutex) { + mutex_exit(mutex); + } } else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) { /* This must be a buf_page_t object. */ UNIV_MEM_ASSERT_RW(src, size); diff --git a/buf/buf0buf.c b/buf/buf0buf.c index 8da0a87751d..dd17f6faf21 100644 --- a/buf/buf0buf.c +++ b/buf/buf0buf.c @@ -52,6 +52,39 @@ Created 11/5/1995 Heikki Tuuri #include "log0recv.h" #include "page0zip.h" +/* prototypes for new functions added to ha_innodb.cc */ +trx_t* innobase_get_trx(); + +inline void _increment_page_get_statistics(buf_block_t* block, trx_t* trx) +{ + ulint block_hash; + ulint block_hash_byte; + byte block_hash_offset; + + ut_ad(block); + + if (!innobase_get_slow_log() || !trx || !trx->take_stats) + return; + + if (!trx->distinct_page_access_hash) { + trx->distinct_page_access_hash = mem_alloc(DPAH_SIZE); + memset(trx->distinct_page_access_hash, 0, DPAH_SIZE); + } + + block_hash = ut_hash_ulint((block->page.space << 20) + block->page.space + + block->page.offset, DPAH_SIZE << 3); + block_hash_byte = block_hash >> 3; + block_hash_offset = (byte) block_hash & 0x07; + if (block_hash_byte < 0 || block_hash_byte >= DPAH_SIZE) + fprintf(stderr, "!!! block_hash_byte = %lu block_hash_offset = %lu !!!\n", block_hash_byte, block_hash_offset); + if (block_hash_offset < 0 || block_hash_offset > 7) + fprintf(stderr, "!!! block_hash_byte = %lu block_hash_offset = %lu !!!\n", block_hash_byte, block_hash_offset); + if ((trx->distinct_page_access_hash[block_hash_byte] & ((byte) 0x01 << block_hash_offset)) == 0) + trx->distinct_page_access++; + trx->distinct_page_access_hash[block_hash_byte] |= (byte) 0x01 << block_hash_offset; + return; +} + /* IMPLEMENTATION OF THE BUFFER POOL ================================= @@ -1696,10 +1729,18 @@ buf_page_get_zip( buf_page_t* bpage; mutex_t* block_mutex; ibool must_read; + trx_t* trx = NULL; + ulint sec; + ulint ms; + ib_uint64_t start_time; + ib_uint64_t finish_time; #ifndef UNIV_LOG_DEBUG ut_ad(!ibuf_inside()); #endif + if (innobase_get_slow_log()) { + trx = innobase_get_trx(); + } buf_pool->n_page_gets++; for (;;) { @@ -1716,7 +1757,7 @@ lookup: //buf_pool_mutex_exit(); rw_lock_s_unlock(&page_hash_latch); - buf_read_page(space, zip_size, offset); + buf_read_page(space, zip_size, offset, trx); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG ut_a(++buf_dbg_counter % 37 || buf_validate()); @@ -1793,6 +1834,13 @@ got_block: /* Let us wait until the read operation completes */ + if (innobase_get_slow_log() && trx && trx->take_stats) + { + ut_usectime(&sec, &ms); + start_time = (ib_uint64_t)sec * 1000000 + ms; + } else { + start_time = 0; + } for (;;) { enum buf_io_fix io_fix; @@ -1807,6 +1855,12 @@ got_block: break; } } + if (innobase_get_slow_log() && trx && trx->take_stats && start_time) + { + ut_usectime(&sec, &ms); + finish_time = (ib_uint64_t)sec * 1000000 + ms; + trx->io_reads_wait_timer += (ulint)(finish_time - start_time); + } } #ifdef UNIV_IBUF_COUNT_DEBUG @@ -2062,6 +2116,11 @@ buf_page_get_gen( ulint fix_type; ibool must_read; mutex_t* block_mutex; + trx_t* trx = NULL; + ulint sec; + ulint ms; + ib_uint64_t start_time; + ib_uint64_t finish_time; ut_ad(mtr); ut_ad((rw_latch == RW_S_LATCH) @@ -2075,6 +2134,9 @@ buf_page_get_gen( #ifndef UNIV_LOG_DEBUG ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL)); #endif + if (innobase_get_slow_log()) { + trx = innobase_get_trx(); + } buf_pool->n_page_gets++; loop: block = guess; @@ -2082,7 +2144,6 @@ loop: if (block) { block_mutex = buf_page_get_mutex_enter((buf_page_t*)block); - ut_a(block_mutex); /* If the guess is a compressed page descriptor that has been allocated by buf_buddy_alloc(), it may have @@ -2092,7 +2153,9 @@ loop: the guess may be pointing to a buffer pool chunk that has been released when resizing the buffer pool. */ - if (!buf_block_is_uncompressed(block) + if (!block_mutex) { + block = guess = NULL; + } else if (!buf_block_is_uncompressed(block) || offset != block->page.offset || space != block->page.space || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { @@ -2127,7 +2190,7 @@ loop2: return(NULL); } - buf_read_page(space, zip_size, offset); + buf_read_page(space, zip_size, offset, trx); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG ut_a(++buf_dbg_counter % 37 || buf_validate()); @@ -2379,6 +2442,13 @@ wait_until_unfixed: /* Let us wait until the read operation completes */ + if (innobase_get_slow_log() && trx && trx->take_stats) + { + ut_usectime(&sec, &ms); + start_time = (ib_uint64_t)sec * 1000000 + ms; + } else { + start_time = 0; + } for (;;) { enum buf_io_fix io_fix; @@ -2393,6 +2463,12 @@ wait_until_unfixed: break; } } + if (innobase_get_slow_log() && trx && trx->take_stats && start_time) + { + ut_usectime(&sec, &ms); + finish_time = (ib_uint64_t)sec * 1000000 + ms; + trx->io_reads_wait_timer += (ulint)(finish_time - start_time); + } } fix_type = MTR_MEMO_BUF_FIX; @@ -2418,13 +2494,17 @@ wait_until_unfixed: /* In the case of a first access, try to apply linear read-ahead */ - buf_read_ahead_linear(space, zip_size, offset); + buf_read_ahead_linear(space, zip_size, offset, trx); } #ifdef UNIV_IBUF_COUNT_DEBUG ut_a(ibuf_count_get(buf_block_get_space(block), buf_block_get_page_no(block)) == 0); #endif + if (innobase_get_slow_log()) { + _increment_page_get_statistics(block, trx); + } + return(block); } @@ -2447,6 +2527,7 @@ buf_page_optimistic_get_func( ibool accessed; ibool success; ulint fix_type; + trx_t* trx = NULL; ut_ad(mtr && block); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); @@ -2520,13 +2601,17 @@ buf_page_optimistic_get_func( #ifdef UNIV_DEBUG_FILE_ACCESSES ut_a(block->page.file_page_was_freed == FALSE); #endif + if (innobase_get_slow_log()) { + trx = innobase_get_trx(); + } + if (UNIV_UNLIKELY(!accessed)) { /* In the case of a first access, try to apply linear read-ahead */ buf_read_ahead_linear(buf_block_get_space(block), buf_block_get_zip_size(block), - buf_block_get_page_no(block)); + buf_block_get_page_no(block), trx); } #ifdef UNIV_IBUF_COUNT_DEBUG @@ -2535,6 +2620,9 @@ buf_page_optimistic_get_func( #endif buf_pool->n_page_gets++; + if (innobase_get_slow_log()) { + _increment_page_get_statistics(block, trx); + } return(TRUE); } @@ -2556,6 +2644,7 @@ buf_page_get_known_nowait( { ibool success; ulint fix_type; + trx_t* trx = NULL; ut_ad(mtr); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); @@ -2623,6 +2712,11 @@ buf_page_get_known_nowait( #endif buf_pool->n_page_gets++; + if (innobase_get_slow_log()) { + trx = innobase_get_trx(); + _increment_page_get_statistics(block, trx); + } + return(TRUE); } diff --git a/buf/buf0flu.c b/buf/buf0flu.c index d465483691a..6c25f0f55ae 100644 --- a/buf/buf0flu.c +++ b/buf/buf0flu.c @@ -994,9 +994,7 @@ buf_flush_try_neighbors( || buf_page_is_old(bpage)) { mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); - ut_a(block_mutex); - - if (buf_flush_ready_for_flush(bpage, flush_type) + if (block_mutex && buf_flush_ready_for_flush(bpage, flush_type) && (i == offset || !bpage->buf_fix_count)) { /* We only try to flush those neighbors != offset where the buf fix count is @@ -1012,7 +1010,7 @@ buf_flush_try_neighbors( //buf_pool_mutex_enter(); rw_lock_s_lock(&page_hash_latch); - } else { + } else if (block_mutex) { mutex_exit(block_mutex); } } @@ -1123,11 +1121,14 @@ flush_next: mutex_t*block_mutex = buf_page_get_mutex_enter(bpage); ibool ready; - ut_a(buf_page_in_file(bpage)); + //ut_a(buf_page_in_file(bpage)); - ut_a(block_mutex); - ready = buf_flush_ready_for_flush(bpage, flush_type); - mutex_exit(block_mutex); + if (block_mutex) { + ready = buf_flush_ready_for_flush(bpage, flush_type); + mutex_exit(block_mutex); + } else { + ready = FALSE; + } if (ready) { space = buf_page_get_space(bpage); @@ -1271,13 +1272,13 @@ buf_flush_LRU_recommendation(void) } block_mutex = buf_page_get_mutex_enter(bpage); - ut_a(block_mutex); - - if (buf_flush_ready_for_replace(bpage)) { + if (block_mutex && buf_flush_ready_for_replace(bpage)) { n_replaceable++; } - mutex_exit(block_mutex); + if (block_mutex) { + mutex_exit(block_mutex); + } distance++; diff --git a/buf/buf0lru.c b/buf/buf0lru.c index 2270ea5dce2..caddb51c983 100644 --- a/buf/buf0lru.c +++ b/buf/buf0lru.c @@ -255,9 +255,12 @@ scan_again: mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); buf_page_t* prev_bpage; - ut_a(block_mutex); prev_bpage = UT_LIST_GET_PREV(LRU, bpage); + if (!block_mutex) { + goto next_page; + } + ut_a(buf_page_in_file(bpage)); if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE @@ -360,9 +363,13 @@ scan_again: ut_a(buf_page_in_file(bpage)); - ut_a(block_mutex); prev_bpage = UT_LIST_GET_PREV(LRU, bpage); + if (!block_mutex) { + bpage = prev_bpage; + continue; + } + if (buf_page_get_space(bpage) == id) { if (bpage->buf_fix_count > 0 || buf_page_get_io_fix(bpage) != BUF_IO_NONE) { @@ -634,7 +641,9 @@ restart: mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); - ut_a(block_mutex); + if (!block_mutex) { + goto restart; + } if (!bpage->in_LRU_list || !buf_page_in_file(bpage)) { diff --git a/buf/buf0rea.c b/buf/buf0rea.c index f2dbe939c92..88ee5eb7431 100644 --- a/buf/buf0rea.c +++ b/buf/buf0rea.c @@ -82,7 +82,8 @@ buf_read_page_low( treat the tablespace as dropped; this is a timestamp we use to stop dangling page reads from a tablespace which we have DISCARDed + IMPORTed back */ - ulint offset) /*!< in: page number */ + ulint offset, /*!< in: page number */ + trx_t* trx) { buf_page_t* bpage; ulint wake_later; @@ -183,15 +184,15 @@ not_to_recover: ut_ad(buf_page_in_file(bpage)); if (zip_size) { - *err = fil_io(OS_FILE_READ | wake_later, + *err = _fil_io(OS_FILE_READ | wake_later, sync, space, zip_size, offset, 0, zip_size, - bpage->zip.data, bpage); + bpage->zip.data, bpage, trx); } else { ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); - *err = fil_io(OS_FILE_READ | wake_later, + *err = _fil_io(OS_FILE_READ | wake_later, sync, space, 0, offset, 0, UNIV_PAGE_SIZE, - ((buf_block_t*) bpage)->frame, bpage); + ((buf_block_t*) bpage)->frame, bpage, trx); } ut_a(*err == DB_SUCCESS); @@ -223,8 +224,9 @@ buf_read_ahead_random( /*==================*/ ulint space, /*!< in: space id */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ - ulint offset) /*!< in: page number of a page which the current thread + ulint offset, /*!< in: page number of a page which the current thread wants to access */ + trx_t* trx) { ib_int64_t tablespace_version; ulint recent_blocks = 0; @@ -340,7 +342,7 @@ read_ahead: &err, FALSE, ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, space, zip_size, FALSE, - tablespace_version, i); + tablespace_version, i, trx); if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); fprintf(stderr, @@ -387,7 +389,8 @@ buf_read_page( /*==========*/ ulint space, /*!< in: space id */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ - ulint offset) /*!< in: page number */ + ulint offset, /*!< in: page number */ + trx_t* trx) { ib_int64_t tablespace_version; ulint count; @@ -396,14 +399,14 @@ buf_read_page( tablespace_version = fil_space_get_version(space); - count = buf_read_ahead_random(space, zip_size, offset); + count = buf_read_ahead_random(space, zip_size, offset, trx); /* We do the i/o in the synchronous aio mode to save thread switches: hence TRUE */ count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, zip_size, FALSE, - tablespace_version, offset); + tablespace_version, offset, trx); srv_buf_pool_reads+= count2; if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); @@ -454,8 +457,9 @@ buf_read_ahead_linear( /*==================*/ ulint space, /*!< in: space id */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ - ulint offset) /*!< in: page number of a page; NOTE: the current thread + ulint offset, /*!< in: page number of a page; NOTE: the current thread must want access to this page (see NOTE 3 above) */ + trx_t* trx) { ib_int64_t tablespace_version; buf_page_t* bpage; @@ -670,7 +674,7 @@ buf_read_ahead_linear( count += buf_read_page_low( &err, FALSE, ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, - space, zip_size, FALSE, tablespace_version, i); + space, zip_size, FALSE, tablespace_version, i, trx); if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); fprintf(stderr, @@ -760,7 +764,7 @@ buf_read_ibuf_merge_pages( buf_read_page_low(&err, sync && (i + 1 == n_stored), BUF_READ_ANY_PAGE, space_ids[i], zip_size, TRUE, space_versions[i], - page_nos[i]); + page_nos[i], NULL); if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) { tablespace_deleted: @@ -857,12 +861,12 @@ buf_read_recv_pages( if ((i + 1 == n_stored) && sync) { buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, zip_size, TRUE, tablespace_version, - page_nos[i]); + page_nos[i], NULL); } else { buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE | OS_AIO_SIMULATED_WAKE_LATER, space, zip_size, TRUE, - tablespace_version, page_nos[i]); + tablespace_version, page_nos[i], NULL); } } diff --git a/dict/dict0dict.c b/dict/dict0dict.c index 1a28f354a67..050182bc831 100644 --- a/dict/dict0dict.c +++ b/dict/dict0dict.c @@ -1231,7 +1231,7 @@ dict_col_name_is_reserved( ulint i; for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) { - if (strcmp(name, reserved_names[i]) == 0) { + if (innobase_strcasecmp(name, reserved_names[i]) == 0) { return(TRUE); } diff --git a/fil/fil0fil.c b/fil/fil0fil.c index 31fa257e51c..e06dc1906c6 100644 --- a/fil/fil0fil.c +++ b/fil/fil0fil.c @@ -4161,7 +4161,7 @@ fil_extend_space_to_desired_size( node->name, node->handle, buf, offset_low, offset_high, page_size * n_pages, - NULL, NULL); + NULL, NULL, NULL); #endif if (success) { node->size += n_pages; @@ -4488,7 +4488,7 @@ Reads or writes data. This operation is asynchronous (aio). i/o on a tablespace which does not exist */ UNIV_INTERN ulint -fil_io( +_fil_io( /*===*/ ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE, ORed to OS_FILE_LOG, if a log i/o @@ -4513,8 +4513,9 @@ fil_io( void* buf, /*!< in/out: buffer where to store read data or from where to write; in aio this must be appropriately aligned */ - void* message) /*!< in: message for aio handler if non-sync + void* message, /*!< in: message for aio handler if non-sync aio used, else ignored */ + trx_t* trx) { ulint mode; fil_space_t* space; @@ -4684,7 +4685,7 @@ fil_io( #else /* Queue the aio request */ ret = os_aio(type, mode | wake_later, node->name, node->handle, buf, - offset_low, offset_high, len, node, message); + offset_low, offset_high, len, node, message, trx); #endif ut_a(ret); diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index 2d05f4936a6..c2f2113d571 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -206,7 +206,6 @@ static my_bool innobase_use_doublewrite = TRUE; static my_bool innobase_use_checksums = TRUE; static my_bool innobase_extra_undoslots = FALSE; static my_bool innobase_fast_recovery = FALSE; -static my_bool innobase_use_purge_thread = FALSE; static my_bool innobase_locks_unsafe_for_binlog = FALSE; static my_bool innobase_overwrite_relay_log_info = FALSE; static my_bool innobase_rollback_on_timeout = FALSE; @@ -300,8 +299,27 @@ innobase_alter_table_flags( /*=======================*/ uint flags); +/*********************************************************************** +This function checks each index name for a table against reserved +system default primary index name 'GEN_CLUST_INDEX'. If a name matches, +this function pushes an error message to the client, and returns true. */ +static +bool +innobase_index_name_is_reserved( +/*============================*/ + /* out: true if index name matches a + reserved name */ + const trx_t* trx, /* in: InnoDB transaction handle */ + const TABLE* form, /* in: information on table + columns and indexes */ + const char* norm_name); /* in: table name */ + static const char innobase_hton_name[]= "InnoDB"; +/* "GEN_CLUST_INDEX" is the name reserved for Innodb default +system primary index. */ +static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX"; + /*************************************************************//** Check for a valid value of innobase_commit_concurrency. @return 0 for valid innodb_commit_concurrency */ @@ -895,17 +913,8 @@ convert_error_code_to_mysql( return(ER_PRIMARY_CANT_HAVE_NULL); case DB_TOO_MANY_CONCURRENT_TRXS: - /* Once MySQL add the appropriate code to errmsg.txt then - we can get rid of this #ifdef. NOTE: The code checked by - the #ifdef is the suggested name for the error condition - and the actual error code name could very well be different. - This will require some monitoring, ie. the status - of this request on our part.*/ -#ifdef ER_TOO_MANY_CONCURRENT_TRXS - return(ER_TOO_MANY_CONCURRENT_TRXS); -#else - return(HA_ERR_RECORD_FILE_FULL); -#endif + return(HA_ERR_TOO_MANY_CONCURRENT_TRXS); + case DB_UNSUPPORTED: return(HA_ERR_UNSUPPORTED); } @@ -979,7 +988,22 @@ innobase_get_cset_width( *mbminlen = cs->mbminlen; *mbmaxlen = cs->mbmaxlen; } else { + if (current_thd + && (thd_sql_command(current_thd) == SQLCOM_DROP_TABLE)) { + + /* Fix bug#46256: allow tables to be dropped if the + collation is not found, but issue a warning. */ + if ((global_system_variables.log_warnings) + && (cset != 0)){ + + sql_print_warning( + "Unknown collation #%lu.", cset); + } + } else { + ut_a(cset == 0); + } + *mbminlen = *mbmaxlen = 0; } } @@ -1053,6 +1077,7 @@ innobase_get_charset( } #if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) +extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list; /*******************************************************************//** Map an OS error to an errno value. The OS error number is stored in _doserrno and the mapped value is stored in errno) */ @@ -1340,6 +1365,16 @@ innobase_trx_init( trx->check_unique_secondary = !thd_test_options( thd, OPTION_RELAXED_UNIQUE_CHECKS); +#ifdef EXTENDED_SLOWLOG + if (thd_log_slow_verbosity(thd) & SLOG_V_INNODB) { + trx->take_stats = TRUE; + } else { + trx->take_stats = FALSE; + } +#else + trx->take_stats = FALSE; +#endif + DBUG_VOID_RETURN; } @@ -1396,6 +1431,32 @@ check_trx_exists( } +/************************************************************************* +Gets current trx. */ +extern "C" +trx_t* +innobase_get_trx() +{ + THD *thd=current_thd; + if (likely(thd != 0)) { + trx_t*& trx = thd_to_trx(thd); + return(trx); + } else { + return(NULL); + } +} + +extern "C" +ibool +innobase_get_slow_log() +{ +#ifdef EXTENDED_SLOWLOG + return((ibool) thd_opt_slow_log()); +#else + return(FALSE); +#endif +} + /*********************************************************************//** Construct ha_innobase handler. */ UNIV_INTERN @@ -2294,8 +2355,6 @@ innobase_change_buffering_inited_ok: srv_fast_recovery = (ibool) innobase_fast_recovery; - srv_use_purge_thread = (ibool) innobase_use_purge_thread; - srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite; srv_use_checksums = (ibool) innobase_use_checksums; @@ -5871,6 +5930,28 @@ create_table_def( } } + /* First check whether the column to be added has a + system reserved name. */ + if (dict_col_name_is_reserved(field->field_name)){ + push_warning_printf( + (THD*) trx->mysql_thd, + MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_CANT_CREATE_TABLE, + "Error creating table '%s' with " + "column name '%s'. '%s' is a " + "reserved name. Please try to " + "re-create the table with a " + "different column name.", + table->name, (char*) field->field_name, + (char*) field->field_name); + + dict_mem_table_free(table); + trx_commit_for_mysql(trx); + + error = DB_ERROR; + goto error_ret; + } + dict_mem_table_add_col(table, table->heap, (char*) field->field_name, col_type, @@ -5884,6 +5965,7 @@ create_table_def( error = row_create_table_for_mysql(table, trx); +error_ret: error = convert_error_code_to_mysql(error, flags, NULL); DBUG_RETURN(error); @@ -5922,6 +6004,9 @@ create_index( n_fields = key->key_parts; + /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */ + ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0); + ind_type = 0; if (key_num == form->s->primary_key) { @@ -6030,8 +6115,8 @@ create_clustered_index_when_no_primary( /* We pass 0 as the space id, and determine at a lower level the space id where to store the table */ - - index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX", + index = dict_mem_index_create(table_name, + innobase_index_reserve_name, 0, DICT_CLUSTERED, 0); error = row_create_index_for_mysql(index, trx, NULL); @@ -6457,14 +6542,6 @@ ha_innobase::create( flags = DICT_TF_COMPACT; } - error = create_table_def(trx, form, norm_name, - create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL, - flags); - - if (error) { - goto cleanup; - } - /* Look for a primary key */ primary_key_no= (form->s->primary_key != MAX_KEY ? @@ -6476,6 +6553,22 @@ ha_innobase::create( ut_a(primary_key_no == -1 || primary_key_no == 0); + /* Check for name conflicts (with reserved name) for + any user indices to be created. */ + if (innobase_index_name_is_reserved(trx, form, norm_name)) { + error = -1; + goto cleanup; + } + + error = create_table_def(trx, form, norm_name, + create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL, + flags); + + if (error) { + goto cleanup; + } + + /* Create the keys */ if (form->s->keys == 0 || primary_key_no == -1) { @@ -8127,6 +8220,23 @@ ha_innobase::external_lock( statement has ended */ if (trx->n_mysql_tables_in_use == 0) { +#ifdef EXTENDED_SLOWLOG + increment_thd_innodb_stats(thd, trx->io_reads, + trx->io_read, + trx->io_reads_wait_timer, + trx->lock_que_wait_timer, + trx->innodb_que_wait_timer, + trx->distinct_page_access); + + trx->io_reads = 0; + trx->io_read = 0; + trx->io_reads_wait_timer = 0; + trx->lock_que_wait_timer = 0; + trx->innodb_que_wait_timer = 0; + trx->distinct_page_access = 0; + if (trx->distinct_page_access_hash) + memset(trx->distinct_page_access_hash, 0, DPAH_SIZE); +#endif trx->mysql_n_tables_locked = 0; prebuilt->used_in_HANDLER = FALSE; @@ -8414,8 +8524,8 @@ innodb_mutex_show_status( rw_lock_wait_time += mutex->lspent_time; } #else /* UNIV_DEBUG */ - buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s:%lu", - mutex->cfile_name, (ulong) mutex->cline); + buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s", + mutex->cmutex_name); buf2len= (uint) my_snprintf(buf2, sizeof(buf2), "os_waits=%lu", mutex->count_os_wait); @@ -8440,8 +8550,8 @@ next_mutex: while (lock != NULL) { if (lock->count_os_wait && !buf_pool_is_block_lock(lock)) { - buf1len= my_snprintf(buf1, sizeof(buf1), "%s:%lu", - lock->cfile_name, (ulong) lock->cline); + buf1len= my_snprintf(buf1, sizeof(buf1), "%s", + lock->lock_name); buf2len= my_snprintf(buf2, sizeof(buf2), "os_waits=%lu", lock->count_os_wait); @@ -9905,6 +10015,46 @@ static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff) return 0; } +/*********************************************************************** +This function checks each index name for a table against reserved +system default primary index name 'GEN_CLUST_INDEX'. If a name matches, +this function pushes an error message to the client, and returns true. */ +static +bool +innobase_index_name_is_reserved( +/*============================*/ + /* out: true if an index name + matches the reserved name */ + const trx_t* trx, /* in: InnoDB transaction handle */ + const TABLE* form, /* in: information on table + columns and indexes */ + const char* norm_name) /* in: table name */ +{ + KEY* key; + uint key_num; /* index number */ + + for (key_num = 0; key_num < form->s->keys; key_num++) { + key = form->key_info + key_num; + + if (innobase_strcasecmp(key->name, + innobase_index_reserve_name) == 0) { + /* Push warning to mysql */ + push_warning_printf((THD*) trx->mysql_thd, + MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_CANT_CREATE_TABLE, + "Cannot Create Index with name " + "'%s'. The name is reserved " + "for the system default primary " + "index.", + innobase_index_reserve_name); + + return(true); + } + } + + return(false); +} + static SHOW_VAR innodb_status_variables_export[]= { {"Innodb", (char*) &show_innodb_vars, SHOW_FUNC}, {NullS, NullS, SHOW_LONG} @@ -9937,10 +10087,10 @@ static MYSQL_SYSVAR_BOOL(fast_recovery, innobase_fast_recovery, "Enable to use speed hack of recovery avoiding flush list sorting.", NULL, NULL, FALSE); -static MYSQL_SYSVAR_BOOL(use_purge_thread, innobase_use_purge_thread, - PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, - "Enable to use purge devoted thread.", - NULL, NULL, FALSE); +static MYSQL_SYSVAR_ULONG(use_purge_thread, srv_use_purge_thread, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Number of purge devoted threads. #### over 1 is EXPERIMENTAL ####", + NULL, NULL, 0, 0, 64, 0); static MYSQL_SYSVAR_BOOL(overwrite_relay_log_info, innobase_overwrite_relay_log_info, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, @@ -10451,6 +10601,7 @@ i_s_innodb_cmpmem, i_s_innodb_cmpmem_reset, i_s_innodb_table_stats, i_s_innodb_index_stats, +i_s_innodb_admin_command, i_s_innodb_patches mysql_declare_plugin_end; diff --git a/handler/handler0alter.cc b/handler/handler0alter.cc index 12f6099eeb3..c85e61d307b 100644 --- a/handler/handler0alter.cc +++ b/handler/handler0alter.cc @@ -670,6 +670,23 @@ err_exit: DBUG_RETURN(error); } + /* Check for name conflicts (with reserved name) for + any user indices to be created. */ + if (innobase_strcasecmp(key_info->name, + "GEN_CLUST_INDEX") == 0) { + /* Push warning to mysql */ + push_warning_printf((THD*) trx->mysql_thd, + MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_CANT_CREATE_TABLE, + "Cannot Create Index with name " + "'%s'. The name is reserved " + "for the system default primary " + "index.", + "GEN_CLUST_INDEX"); + error = ER_CANT_CREATE_TABLE; + goto err_exit; + } + /* Create table containing all indexes to be built in this alter table add index so that they are in the correct order in the table. */ diff --git a/handler/i_s.cc b/handler/i_s.cc index 1a9e304c33d..4b61971f8b0 100644 --- a/handler/i_s.cc +++ b/handler/i_s.cc @@ -2953,3 +2953,140 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(__reserved1, NULL) }; + +/*********************************************************************** +*/ +static ST_FIELD_INFO i_s_innodb_admin_command_info[] = +{ + {STRUCT_FLD(field_name, "result_message"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +#ifndef INNODB_COMPATIBILITY_HOOKS +#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS +#endif + +extern "C" { +char **thd_query(MYSQL_THD thd); +} + +static +int +i_s_innodb_admin_command_fill( +/*==========================*/ + THD* thd, + TABLE_LIST* tables, + COND* cond) +{ + TABLE* i_s_table = (TABLE *) tables->table; + CHARSET_INFO *cs= system_charset_info; + char** query_str; + char* ptr; + char quote = '\0'; + char* command_head = "XTRA_"; + + DBUG_ENTER("i_s_innodb_admin_command_fill"); + + /* deny access to non-superusers */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + if(thd_sql_command(thd) != SQLCOM_SELECT) { + field_store_string(i_s_table->field[0], + "SELECT command is only accepted."); + goto end_func; + } + + query_str = thd_query(thd); + ptr = *query_str; + + for (; *ptr; ptr++) { + if (*ptr == quote) { + quote = '\0'; + } else if (quote) { + } else if (*ptr == '`' || *ptr == '"') { + quote = *ptr; + } else { + long i; + for (i = 0; command_head[i]; i++) { + if (toupper((int)(unsigned char)(ptr[i])) + != toupper((int)(unsigned char) + (command_head[i]))) { + goto nomatch; + } + } + break; +nomatch: + ; + } + } + + if (!*ptr) { + field_store_string(i_s_table->field[0], + "No XTRA_* command in the SQL statement." + " Please add /*!XTRA_xxxx*/ to the SQL."); + goto end_func; + } + + if (!strncasecmp("XTRA_HELLO", ptr, 10)) { + /* This is example command XTRA_HELLO */ + + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: administration command test for XtraDB" + " 'XTRA_HELLO' was detected.\n"); + + field_store_string(i_s_table->field[0], + "Hello!"); + goto end_func; + } + + field_store_string(i_s_table->field[0], + "Undefined XTRA_* command."); + goto end_func; + +end_func: + if (schema_table_store_record(thd, i_s_table)) { + DBUG_RETURN(1); + } else { + DBUG_RETURN(0); + } +} + +static +int +i_s_innodb_admin_command_init( +/*==========================*/ + void* p) +{ + DBUG_ENTER("i_s_innodb_admin_command_init"); + ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p; + + schema->fields_info = i_s_innodb_admin_command_info; + schema->fill_table = i_s_innodb_admin_command_fill; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_admin_command = +{ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + STRUCT_FLD(info, &i_s_info), + STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"), + STRUCT_FLD(author, plugin_author), + STRUCT_FLD(descr, "XtraDB specific command acceptor"), + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + STRUCT_FLD(init, i_s_innodb_admin_command_init), + STRUCT_FLD(deinit, i_s_common_deinit), + STRUCT_FLD(version, 0x0100 /* 1.0 */), + STRUCT_FLD(status_vars, NULL), + STRUCT_FLD(system_vars, NULL), + STRUCT_FLD(__reserved1, NULL) +}; diff --git a/handler/i_s.h b/handler/i_s.h index 7bb03460285..6d0f426acc3 100644 --- a/handler/i_s.h +++ b/handler/i_s.h @@ -40,5 +40,6 @@ extern struct st_mysql_plugin i_s_innodb_patches; extern struct st_mysql_plugin i_s_innodb_rseg; extern struct st_mysql_plugin i_s_innodb_table_stats; extern struct st_mysql_plugin i_s_innodb_index_stats; +extern struct st_mysql_plugin i_s_innodb_admin_command; #endif /* i_s_h */ diff --git a/handler/innodb_patch_info.h b/handler/innodb_patch_info.h index f8a728d0d27..184fd65af63 100644 --- a/handler/innodb_patch_info.h +++ b/handler/innodb_patch_info.h @@ -38,5 +38,8 @@ struct innodb_enhancement { {"innodb_stats","Additional features about InnoDB statistics/optimizer","","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_recovery_patches","Bugfixes and adjustments about recovery process","","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_purge_thread","Enable to use purge devoted thread","","http://www.percona.com/docs/wiki/percona-xtradb"}, +{"innodb_admin_command_base","XtraDB specific command interface through i_s","","http://www.percona.com/docs/wiki/percona-xtradb"}, +{"innodb_show_lock_name","Show mutex/lock name instead of crated file/line","","http://www.percona.com/docs/wiki/percona-xtradb"}, +{"innodb_extend_slow","Extended statistics in slow.log","It is InnoDB-part only. It needs to patch also to mysqld.","http://www.percona.com/docs/wiki/percona-xtradb"}, {NULL, NULL, NULL, NULL} }; diff --git a/include/buf0buf.ic b/include/buf0buf.ic index 9dc104b25b5..014b69a5dc2 100644 --- a/include/buf0buf.ic +++ b/include/buf0buf.ic @@ -825,15 +825,15 @@ buf_page_get_newest_modification( ib_uint64_t lsn; mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); - ut_a(block_mutex); - - if (buf_page_in_file(bpage)) { + if (block_mutex && buf_page_in_file(bpage)) { lsn = bpage->newest_modification; } else { lsn = 0; } - mutex_exit(block_mutex); + if (block_mutex) { + mutex_exit(block_mutex); + } return(lsn); } diff --git a/include/buf0rea.h b/include/buf0rea.h index b4d25e6fde0..e19f50124e5 100644 --- a/include/buf0rea.h +++ b/include/buf0rea.h @@ -27,6 +27,7 @@ Created 11/5/1995 Heikki Tuuri #define buf0rea_h #include "univ.i" +#include "trx0types.h" #include "buf0types.h" /********************************************************************//** @@ -43,7 +44,8 @@ buf_read_page( /*==========*/ ulint space, /*!< in: space id */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ - ulint offset);/*!< in: page number */ + ulint offset, /*!< in: page number */ + trx_t* trx); /********************************************************************//** Applies linear read-ahead if in the buf_pool the page is a border page of a linear read-ahead area and all the pages in the area have been accessed. @@ -74,8 +76,9 @@ buf_read_ahead_linear( /*==================*/ ulint space, /*!< in: space id */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ - ulint offset);/*!< in: page number of a page; NOTE: the current thread + ulint offset, /*!< in: page number of a page; NOTE: the current thread must want access to this page (see NOTE 3 above) */ + trx_t* trx); /********************************************************************//** Issues read requests for pages which the ibuf module wants to read in, in order to contract the insert buffer tree. Technically, this function is like diff --git a/include/fil0fil.h b/include/fil0fil.h index 0470d533dec..edf10b1dd5c 100644 --- a/include/fil0fil.h +++ b/include/fil0fil.h @@ -614,9 +614,12 @@ fil_space_get_n_reserved_extents( Reads or writes data. This operation is asynchronous (aio). @return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do i/o on a tablespace which does not exist */ +#define fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message) \ + _fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, NULL) + UNIV_INTERN ulint -fil_io( +_fil_io( /*===*/ ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE, ORed to OS_FILE_LOG, if a log i/o @@ -641,8 +644,9 @@ fil_io( void* buf, /*!< in/out: buffer where to store read data or from where to write; in aio this must be appropriately aligned */ - void* message); /*!< in: message for aio handler if non-sync + void* message, /*!< in: message for aio handler if non-sync aio used, else ignored */ + trx_t* trx); /**********************************************************************//** Waits for an aio operation to complete. This function is used to write the handler for completed requests. The aio array of pending requests is divided diff --git a/include/os0file.h b/include/os0file.h index d8d2f0e5d9e..4dda4476d9e 100644 --- a/include/os0file.h +++ b/include/os0file.h @@ -53,6 +53,7 @@ Created 10/21/1995 Heikki Tuuri #define os0file_h #include "univ.i" +#include "trx0types.h" #ifndef __WIN__ #include @@ -497,9 +498,12 @@ os_file_get_last_error( /*******************************************************************//** Requests a synchronous read operation. @return TRUE if request was successful, FALSE if fail */ +#define os_file_read(file, buf, offset, offset_high, n) \ + _os_file_read(file, buf, offset, offset_high, n, NULL) + UNIV_INTERN ibool -os_file_read( +_os_file_read( /*=========*/ os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ @@ -507,7 +511,8 @@ os_file_read( offset where to read */ ulint offset_high,/*!< in: most significant 32 bits of offset */ - ulint n); /*!< in: number of bytes to read */ + ulint n, /*!< in: number of bytes to read */ + trx_t* trx); /*******************************************************************//** Rewind file to its start, read at most size - 1 bytes from it to str, and NUL-terminate str. All errors are silently ignored. This function is @@ -654,10 +659,11 @@ os_aio( (can be used to identify a completed aio operation); ignored if mode is OS_AIO_SYNC */ - void* message2);/*!< in: message for the aio handler + void* message2,/*!< in: message for the aio handler (can be used to identify a completed aio operation); ignored if mode is OS_AIO_SYNC */ + trx_t* trx); /************************************************************************//** Wakes up all async i/o threads so that they know to exit themselves in shutdown. */ diff --git a/include/srv0srv.h b/include/srv0srv.h index ac409e1093d..4700ca11f7a 100644 --- a/include/srv0srv.h +++ b/include/srv0srv.h @@ -80,6 +80,9 @@ at a time */ #define SRV_AUTO_EXTEND_INCREMENT \ (srv_auto_extend_increment * ((1024 * 1024) / UNIV_PAGE_SIZE)) +/* prototypes for new functions added to ha_innodb.cc */ +ibool innobase_get_slow_log(); + /* This is set to TRUE if the MySQL user has set it in MySQL */ extern ibool srv_lower_case_table_names; @@ -134,7 +137,7 @@ extern ibool srv_extra_undoslots; extern ibool srv_fast_recovery; -extern ibool srv_use_purge_thread; +extern ulint srv_use_purge_thread; extern ibool srv_auto_extend_last_data_file; extern ulint srv_last_file_size_max; @@ -428,6 +431,7 @@ enum srv_thread_type { SRV_INSERT, /**< thread flushing the insert buffer to disk */ #endif SRV_PURGE, /* thread purging undo records */ + SRV_PURGE_WORKER, /* thread purging undo records */ SRV_MASTER /**< the master thread, (whose type number must be biggest) */ }; @@ -509,6 +513,13 @@ srv_purge_thread( /*=============*/ void* arg); /* in: a dummy parameter required by os_thread_create */ +/************************************************************************* +The undo purge thread. */ +UNIV_INTERN +os_thread_ret_t +srv_purge_worker_thread( +/*====================*/ + void* arg); /*******************************************************************//** Tells the Innobase server that there has been activity in the database and wakes up the master thread if it is suspended (not sleeping). Used diff --git a/include/sync0rw.h b/include/sync0rw.h index aedfd5f3f86..85fa014d77a 100644 --- a/include/sync0rw.h +++ b/include/sync0rw.h @@ -120,7 +120,7 @@ is necessary only if the memory block containing it is freed. */ # endif /* UNIV_SYNC_DEBUG */ #else /* UNIV_DEBUG */ # define rw_lock_create(L, level) \ - rw_lock_create_func((L), __FILE__, __LINE__) + rw_lock_create_func((L), #L, NULL, 0) #endif /* UNIV_DEBUG */ /******************************************************************//** @@ -137,8 +137,8 @@ rw_lock_create_func( # ifdef UNIV_SYNC_DEBUG ulint level, /*!< in: level */ # endif /* UNIV_SYNC_DEBUG */ - const char* cmutex_name, /*!< in: mutex name */ #endif /* UNIV_DEBUG */ + const char* cmutex_name, /*!< in: mutex name */ const char* cfile_name, /*!< in: file name where created */ ulint cline); /*!< in: file line where created */ /******************************************************************//** @@ -540,7 +540,8 @@ struct rw_lock_struct { ulint level; /*!< Level in the global latching order. */ #endif /* UNIV_SYNC_DEBUG */ ulint count_os_wait; /*!< Count of os_waits. May not be accurate */ - const char* cfile_name;/*!< File name where lock created */ + //const char* cfile_name;/*!< File name where lock created */ + const char* lock_name;/*!< lock name */ /* last s-lock file/line is not guaranteed to be correct */ const char* last_s_file_name;/*!< File name where last s-locked */ const char* last_x_file_name;/*!< File name where last x-locked */ @@ -551,7 +552,7 @@ struct rw_lock_struct { are at the start of this struct, thus we can peek this field without causing much memory bus traffic */ - unsigned cline:14; /*!< Line where created */ + //unsigned cline:14; /*!< Line where created */ unsigned last_s_line:14; /*!< Line number where last time s-locked */ unsigned last_x_line:14; /*!< Line number where last time x-locked */ ulint magic_n; /*!< RW_LOCK_MAGIC_N */ diff --git a/include/sync0sync.h b/include/sync0sync.h index 966bcced722..a6697638081 100644 --- a/include/sync0sync.h +++ b/include/sync0sync.h @@ -80,7 +80,7 @@ necessary only if the memory block containing it is freed. */ # endif #else # define mutex_create(M, level) \ - mutex_create_func((M), __FILE__, __LINE__) + mutex_create_func((M), #M, NULL, 0) #endif /******************************************************************//** @@ -93,8 +93,8 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /*!< in: pointer to memory */ -#ifdef UNIV_DEBUG const char* cmutex_name, /*!< in: mutex name */ +#ifdef UNIV_DEBUG # ifdef UNIV_SYNC_DEBUG ulint level, /*!< in: level */ # endif /* UNIV_SYNC_DEBUG */ @@ -524,9 +524,9 @@ struct mutex_struct { ulint line; /*!< Line where the mutex was locked */ ulint level; /*!< Level in the global latching order */ #endif /* UNIV_SYNC_DEBUG */ +#ifdef UNIV_DEBUG const char* cfile_name;/*!< File name where mutex created */ ulint cline; /*!< Line where created */ -#ifdef UNIV_DEBUG os_thread_id_t thread_id; /*!< The thread id of the thread which locked the mutex. */ ulint magic_n; /*!< MUTEX_MAGIC_N */ @@ -541,9 +541,9 @@ struct mutex_struct { ulong count_os_yield; /*!< count of os_wait */ ulonglong lspent_time; /*!< mutex os_wait timer msec */ ulonglong lmax_spent_time;/*!< mutex os_wait timer msec */ - const char* cmutex_name; /*!< mutex name */ ulint mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */ #endif /* UNIV_DEBUG */ + const char* cmutex_name; /*!< mutex name */ }; /** The global array of wait cells for implementation of the databases own diff --git a/include/trx0purge.h b/include/trx0purge.h index 7812ad7eb92..d9a470f4036 100644 --- a/include/trx0purge.h +++ b/include/trx0purge.h @@ -108,6 +108,25 @@ UNIV_INTERN ulint trx_purge(void); /*===========*/ +/********************************************************************** +This function runs a purge worker batch */ +UNIV_INTERN +void +trx_purge_worker( +/*=============*/ + ulint worker_id); +/********************************************************************** +This function waits the event for worker batch */ +UNIV_INTERN +void +trx_purge_worker_wait(void); +/*========================*/ +/********************************************************************** +This function wakes the waiting worker batch */ +UNIV_INTERN +void +trx_purge_worker_wake(void); +/*========================*/ /******************************************************************//** Prints information of the purge system to stderr. */ UNIV_INTERN @@ -125,6 +144,11 @@ struct trx_purge_struct{ of the trx system and it never ends */ que_t* query; /*!< The query graph which will do the parallelized purge operation */ + ulint n_worker; + os_event_t worker_event; + sess_t** sess_arr; + trx_t** trx_arr; + que_t** query_arr; rw_lock_t latch; /*!< The latch protecting the purge view. A purge operation must acquire an x-latch here for the instant at which diff --git a/include/trx0trx.h b/include/trx0trx.h index da031d9d5d3..2d8987284e5 100644 --- a/include/trx0trx.h +++ b/include/trx0trx.h @@ -729,6 +729,17 @@ struct trx_struct{ /*------------------------------*/ char detailed_error[256]; /*!< detailed error message for last error, or empty. */ + /*------------------------------*/ + ulint io_reads; + ib_uint64_t io_read; + ulint io_reads_wait_timer; + ib_uint64_t lock_que_wait_ustarted; + ulint lock_que_wait_timer; + ulint innodb_que_wait_timer; + ulint distinct_page_access; +#define DPAH_SIZE 8192 + byte* distinct_page_access_hash; + ibool take_stats; }; #define TRX_MAX_N_THREADS 32 /* maximum number of diff --git a/lock/lock0lock.c b/lock/lock0lock.c index f76c27e093c..ea414676b73 100644 --- a/lock/lock0lock.c +++ b/lock/lock0lock.c @@ -1739,6 +1739,8 @@ lock_rec_enqueue_waiting( { lock_t* lock; trx_t* trx; + ulint sec; + ulint ms; ut_ad(mutex_own(&kernel_mutex)); @@ -1797,6 +1799,10 @@ lock_rec_enqueue_waiting( trx->que_state = TRX_QUE_LOCK_WAIT; trx->was_chosen_as_deadlock_victim = FALSE; trx->wait_started = time(NULL); + if (innobase_get_slow_log() && trx->take_stats) { + ut_usectime(&sec, &ms); + trx->lock_que_wait_ustarted = (ib_uint64_t)sec * 1000000 + ms; + } ut_a(que_thr_stop(thr)); @@ -3607,6 +3613,8 @@ lock_table_enqueue_waiting( { lock_t* lock; trx_t* trx; + ulint sec; + ulint ms; ut_ad(mutex_own(&kernel_mutex)); @@ -3660,6 +3668,10 @@ lock_table_enqueue_waiting( return(DB_SUCCESS); } + if (innobase_get_slow_log() && trx->take_stats) { + ut_usectime(&sec, &ms); + trx->lock_que_wait_ustarted = (ib_uint64_t)sec * 1000000 + ms; + } trx->que_state = TRX_QUE_LOCK_WAIT; trx->was_chosen_as_deadlock_victim = FALSE; trx->wait_started = time(NULL); diff --git a/log/log0log.c b/log/log0log.c index 3a89f540b77..09956bff215 100644 --- a/log/log0log.c +++ b/log/log0log.c @@ -3120,6 +3120,16 @@ loop: goto loop; } + /* Check that the purge threads ended */ + if (srv_use_purge_thread + && (srv_n_threads_active[SRV_PURGE] != 0 + || srv_n_threads_active[SRV_PURGE_WORKER] != 0)) { + + mutex_exit(&kernel_mutex); + + goto loop; + } + mutex_exit(&kernel_mutex); mutex_enter(&(log_sys->mutex)); diff --git a/mysql-test/innodb-index.result b/mysql-test/innodb-index.result index 8772d8354e6..f2c90c54df8 100644 --- a/mysql-test/innodb-index.result +++ b/mysql-test/innodb-index.result @@ -1125,6 +1125,7 @@ t2 CREATE TABLE `t2` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t2; DROP TABLE t1; +call mtr.add_suppression("InnoDB: insufficient history for index"); CREATE TABLE t1 (a INT, b CHAR(1)) ENGINE=InnoDB; INSERT INTO t1 VALUES (3,'a'),(3,'b'),(1,'c'),(0,'d'),(1,'e'); BEGIN; diff --git a/mysql-test/innodb-index.test b/mysql-test/innodb-index.test index 59f1e5d3d2b..1ec1a503c63 100644 --- a/mysql-test/innodb-index.test +++ b/mysql-test/innodb-index.test @@ -499,6 +499,8 @@ SHOW CREATE TABLE t2; DROP TABLE t2; DROP TABLE t1; +call mtr.add_suppression("InnoDB: insufficient history for index"); + connect (a,localhost,root,,); connect (b,localhost,root,,); connection a; diff --git a/mysql-test/innodb_file_format.result b/mysql-test/innodb_file_format.result index 45285542936..fbc67ada1bb 100644 --- a/mysql-test/innodb_file_format.result +++ b/mysql-test/innodb_file_format.result @@ -1,4 +1,4 @@ -set @old_innodb_file_format=@@innodb_file_format; +call mtr.add_suppression("InnoDB: invalid innodb_file_format_check value"); select @@innodb_file_format; @@innodb_file_format Antelope @@ -43,5 +43,3 @@ ERROR HY000: Incorrect arguments to SET select @@innodb_file_format_check; @@innodb_file_format_check Barracuda -set global innodb_file_format=@old_innodb_file_format; -set global innodb_file_format_check=Antelope; diff --git a/mysql-test/innodb_file_format.test b/mysql-test/innodb_file_format.test index 62f8468a818..3bd1dd2fa6f 100644 --- a/mysql-test/innodb_file_format.test +++ b/mysql-test/innodb_file_format.test @@ -1,5 +1,9 @@ -- source include/have_innodb.inc -set @old_innodb_file_format=@@innodb_file_format; + +call mtr.add_suppression("InnoDB: invalid innodb_file_format_check value"); + +let $format=`select @@innodb_file_format`; +let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; select @@innodb_file_format; select @@innodb_file_format_check; @@ -28,5 +32,11 @@ set global innodb_file_format=on; set global innodb_file_format=off; select @@innodb_file_format_check; -set global innodb_file_format=@old_innodb_file_format; -set global innodb_file_format_check=Antelope; +# +# restore environment to the state it was before this test execution +# + +-- disable_query_log +eval set global innodb_file_format=$format; +eval set global innodb_file_format_check=$innodb_file_format_check_orig; +-- enable_query_log diff --git a/mysql-test/innodb_xtradb_bug317074.result b/mysql-test/innodb_xtradb_bug317074.result index 52c758a5eed..82a98844652 100644 --- a/mysql-test/innodb_xtradb_bug317074.result +++ b/mysql-test/innodb_xtradb_bug317074.result @@ -1,5 +1,4 @@ SET @old_innodb_file_format=@@innodb_file_format; SET @old_innodb_file_per_table=@@innodb_file_per_table; -SET @old_innodb_file_format_check=@@innodb_file_format_check; SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_per_table=ON; diff --git a/mysql-test/innodb_xtradb_bug317074.test b/mysql-test/innodb_xtradb_bug317074.test index a15d64d6bb5..757ac87bf18 100644 --- a/mysql-test/innodb_xtradb_bug317074.test +++ b/mysql-test/innodb_xtradb_bug317074.test @@ -2,7 +2,7 @@ SET @old_innodb_file_format=@@innodb_file_format; SET @old_innodb_file_per_table=@@innodb_file_per_table; -SET @old_innodb_file_format_check=@@innodb_file_format_check; +let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_per_table=ON; @@ -41,4 +41,4 @@ ALTER TABLE test1 ENGINE=MyISAM; DROP TABLE test1; SET GLOBAL innodb_file_format=@old_innodb_file_format; SET GLOBAL innodb_file_per_table=@old_innodb_file_per_table; -SET GLOBAL innodb_file_format_check=@old_innodb_file_format_check; +eval set global innodb_file_format_check=$innodb_file_format_check_orig; diff --git a/mysql-test/patches/disabled.def.diff b/mysql-test/patches/disabled.def.diff index e2e20cd000a..b8b3ed2d02d 100644 --- a/mysql-test/patches/disabled.def.diff +++ b/mysql-test/patches/disabled.def.diff @@ -1,9 +1,8 @@ ---- mysql-test/t/disabled.def.orig 2009-09-21 20:12:29.000000000 +0000 -+++ mysql-test/t/disabled.def 2009-09-21 20:20:16.000000000 +0000 -@@ -13,4 +13,6 @@ - innodb_bug39438 : Bug#42383 2009-01-28 lsoares "This fails in embedded and on windows. Note that this test is not run on windows and on embedded in PB for main trees currently" +--- mysql-test/t/disabled.def.orig 2009-10-25 05:54:05.000000000 +0000 ++++ mysql-test/t/disabled.def 2009-10-25 05:54:25.000000000 +0000 +@@ -14,3 +14,5 @@ query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically - init_connect : Bug#44920 2009-07-06 pcrews MTR not processing master.opt input properly on Windows. *Must be done this way due to the nature of the bug* + partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes + partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes +read_many_rows_innodb : Bug#433409 2009-09-20 the test fails on 5.1.37 https://bugs.launchpad.net/bugs/433409 +innodb-zip : Bug#47495 2009-09-21 the test fails on ubuntu - diff --git a/mysql-test/patches/innodb_bug46000.diff b/mysql-test/patches/innodb_bug46000.diff new file mode 100644 index 00000000000..d57cbde387e --- /dev/null +++ b/mysql-test/patches/innodb_bug46000.diff @@ -0,0 +1,26 @@ +--- mysql-test/r/innodb_bug46000.result.orig 2009-10-07 03:21:43.000000000 +0900 ++++ mysql-test/r/innodb_bug46000.result 2009-10-28 14:08:55.000000000 +0900 +@@ -8,10 +8,10 @@ + Error 1005 Can't create table 'test.bug46000' (errno: -1) + create table bug46000(id int) engine=innodb; + create index GEN_CLUST_INDEX on bug46000(id); +-ERROR HY000: Can't create table '#sql-temporary' (errno: -1) ++ERROR HY000: Got error 1005 from storage engine + show errors; + Level Code Message + Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index. +-Error 1005 Can't create table '#sql-temporary' (errno: -1) ++Error 1030 Got error 1005 from storage engine + create index idx on bug46000(id); + drop table bug46000; +--- mysql-test/t/innodb_bug46000.test.orig 2009-10-07 03:21:12.000000000 +0900 ++++ mysql-test/t/innodb_bug46000.test 2009-10-28 14:08:37.000000000 +0900 +@@ -20,7 +20,7 @@ + + # This 'create index' operation should fail. + --replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/ +---error ER_CANT_CREATE_TABLE ++--error ER_GET_ERRNO + create index GEN_CLUST_INDEX on bug46000(id); + + --replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/ diff --git a/os/os0file.c b/os/os0file.c index f961ea2adb2..980c44df82a 100644 --- a/os/os0file.c +++ b/os/os0file.c @@ -55,6 +55,7 @@ Created 10/21/1995 Heikki Tuuri #include "srv0start.h" #include "fil0fil.h" #include "buf0buf.h" +#include "trx0sys.h" #ifndef UNIV_HOTBACKUP # include "os0sync.h" # include "os0thread.h" @@ -2046,20 +2047,28 @@ os_file_flush( /*******************************************************************//** Does a synchronous read operation in Posix. @return number of bytes read, -1 if error */ +#define os_file_pread(file, buf, n, offset, offset_high) \ + _os_file_pread(file, buf, n, offset, offset_high, NULL); + static ssize_t -os_file_pread( +_os_file_pread( /*==========*/ os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ ulint n, /*!< in: number of bytes to read */ ulint offset, /*!< in: least significant 32 bits of file offset from where to read */ - ulint offset_high) /*!< in: most significant 32 bits of + ulint offset_high, /*!< in: most significant 32 bits of offset */ + trx_t* trx) { off_t offs; ssize_t n_bytes; + ulint sec; + ulint ms; + ib_uint64_t start_time; + ib_uint64_t finish_time; ut_a((offset & 0xFFFFFFFFUL) == offset); @@ -2080,6 +2089,15 @@ os_file_pread( os_n_file_reads++; + if (innobase_get_slow_log() && trx && trx->take_stats) + { + trx->io_reads++; + trx->io_read += n; + ut_usectime(&sec, &ms); + start_time = (ib_uint64_t)sec * 1000000 + ms; + } else { + start_time = 0; + } #if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD) os_mutex_enter(os_file_count_mutex); os_file_n_pending_preads++; @@ -2093,6 +2111,13 @@ os_file_pread( os_n_pending_reads--; os_mutex_exit(os_file_count_mutex); + if (innobase_get_slow_log() && trx && trx->take_stats && start_time) + { + ut_usectime(&sec, &ms); + finish_time = (ib_uint64_t)sec * 1000000 + ms; + trx->io_reads_wait_timer += (ulint)(finish_time - start_time); + } + return(n_bytes); #else { @@ -2123,6 +2148,13 @@ os_file_pread( os_n_pending_reads--; os_mutex_exit(os_file_count_mutex); + if (innobase_get_slow_log() && trx && trx->take_stats && start_time) + { + ut_usectime(&sec, &ms); + finish_time = (ib_uint64_t)sec * 1000000 + ms; + trx->io_reads_wait_timer += (ulint)(finish_time - start_time); + } + return(ret); } #endif @@ -2247,7 +2279,7 @@ Requests a synchronous positioned read operation. @return TRUE if request was successful, FALSE if fail */ UNIV_INTERN ibool -os_file_read( +_os_file_read( /*=========*/ os_file_t file, /*!< in: handle to a file */ void* buf, /*!< in: buffer where to read */ @@ -2255,7 +2287,8 @@ os_file_read( offset where to read */ ulint offset_high, /*!< in: most significant 32 bits of offset */ - ulint n) /*!< in: number of bytes to read */ + ulint n, /*!< in: number of bytes to read */ + trx_t* trx) { #ifdef __WIN__ BOOL ret; @@ -2319,7 +2352,7 @@ try_again: os_bytes_read_since_printout += n; try_again: - ret = os_file_pread(file, buf, n, offset, offset_high); + ret = _os_file_pread(file, buf, n, offset, offset_high, trx); if ((ulint)ret == n) { @@ -3211,7 +3244,8 @@ os_aio_array_reserve_slot( offset */ ulint offset_high, /*!< in: most significant 32 bits of offset */ - ulint len) /*!< in: length of the block to read or write */ + ulint len, /*!< in: length of the block to read or write */ + trx_t* trx) { os_aio_slot_t* slot; #ifdef WIN_ASYNC_IO @@ -3482,10 +3516,11 @@ os_aio( (can be used to identify a completed aio operation); ignored if mode is OS_AIO_SYNC */ - void* message2)/*!< in: message for the aio handler + void* message2,/*!< in: message for the aio handler (can be used to identify a completed aio operation); ignored if mode is OS_AIO_SYNC */ + trx_t* trx) { os_aio_array_t* array; os_aio_slot_t* slot; @@ -3524,8 +3559,8 @@ os_aio( wait in the Windows case. */ if (type == OS_FILE_READ) { - return(os_file_read(file, buf, offset, - offset_high, n)); + return(_os_file_read(file, buf, offset, + offset_high, n, trx)); } ut_a(type == OS_FILE_WRITE); @@ -3558,8 +3593,13 @@ try_again: ut_error; } + if (trx && type == OS_FILE_READ) + { + trx->io_reads++; + trx->io_read += n; + } slot = os_aio_array_reserve_slot(type, array, message1, message2, file, - name, buf, offset, offset_high, n); + name, buf, offset, offset_high, n, trx); if (type == OS_FILE_READ) { if (os_aio_use_native_aio) { #ifdef WIN_ASYNC_IO diff --git a/row/row0mysql.c b/row/row0mysql.c index 25946399fb6..8d480191d03 100644 --- a/row/row0mysql.c +++ b/row/row0mysql.c @@ -1770,7 +1770,6 @@ row_create_table_for_mysql( const char* table_name; ulint table_name_len; ulint err; - ulint i; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); #ifdef UNIV_SYNC_DEBUG @@ -1805,15 +1804,6 @@ err_exit: goto err_exit; } - /* Check that no reserved column names are used. */ - for (i = 0; i < dict_table_get_n_user_cols(table); i++) { - if (dict_col_name_is_reserved( - dict_table_get_col_name(table, i))) { - - goto err_exit; - } - } - trx_start_if_not_started(trx); /* The table name is prefixed with the database name and a '/'. diff --git a/srv/srv0srv.c b/srv/srv0srv.c index 2cfc852dc5c..9a1a6998199 100644 --- a/srv/srv0srv.c +++ b/srv/srv0srv.c @@ -103,6 +103,9 @@ Created 10/8/1995 Heikki Tuuri #include "ha_prototypes.h" #include "trx0i_s.h" +/* prototypes for new functions added to ha_innodb.cc */ +ibool innobase_get_slow_log(); + /* This is set to TRUE if the MySQL user has set it in MySQL; currently affects only FOREIGN KEY definition parsing */ UNIV_INTERN ibool srv_lower_case_table_names = FALSE; @@ -162,7 +165,7 @@ UNIV_INTERN ibool srv_extra_undoslots = FALSE; UNIV_INTERN ibool srv_fast_recovery = FALSE; -UNIV_INTERN ibool srv_use_purge_thread = FALSE; +UNIV_INTERN ulint srv_use_purge_thread = 0; /* if TRUE, then we auto-extend the last data file */ UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE; @@ -1154,6 +1157,10 @@ srv_conc_enter_innodb( ibool has_slept = FALSE; srv_conc_slot_t* slot = NULL; ulint i; + ib_uint64_t start_time = 0L; + ib_uint64_t finish_time = 0L; + ulint sec; + ulint ms; if (trx->mysql_thd != NULL && thd_is_replication_slave_thread(trx->mysql_thd)) { @@ -1230,6 +1237,7 @@ retry: switches. */ if (SRV_THREAD_SLEEP_DELAY > 0) { os_thread_sleep(SRV_THREAD_SLEEP_DELAY); + trx->innodb_que_wait_timer += SRV_THREAD_SLEEP_DELAY; } trx->op_info = ""; @@ -1285,12 +1293,25 @@ retry: /* Go to wait for the event; when a thread leaves InnoDB it will release this thread */ + if (innobase_get_slow_log() && trx->take_stats) { + ut_usectime(&sec, &ms); + start_time = (ib_uint64_t)sec * 1000000 + ms; + } else { + start_time = 0; + } + trx->op_info = "waiting in InnoDB queue"; os_event_wait(slot->event); trx->op_info = ""; + if (innobase_get_slow_log() && trx->take_stats && start_time) { + ut_usectime(&sec, &ms); + finish_time = (ib_uint64_t)sec * 1000000 + ms; + trx->innodb_que_wait_timer += (ulint)(finish_time - start_time); + } + os_fast_mutex_lock(&srv_conc_mutex); srv_conc_n_waiting_threads--; @@ -3130,6 +3151,7 @@ srv_purge_thread( ulint n_pages_purged_sum = 1; /* dummy */ ulint history_len; ulint sleep_ms= 10000; /* initial: 10 sec. */ + ibool can_be_last = FALSE; #ifdef UNIV_DEBUG_THREAD_CREATION fprintf(stderr, "Purge thread starts, id %lu\n", @@ -3142,8 +3164,21 @@ srv_purge_thread( mutex_exit(&kernel_mutex); loop: - if (srv_fast_shutdown && srv_shutdown_state > 0) { - goto exit_func; + if (srv_shutdown_state > 0) { + if (srv_fast_shutdown) { + /* someone other should wait the end of the workers */ + goto exit_func; + } + + mutex_enter(&kernel_mutex); + if (srv_n_threads_active[SRV_PURGE_WORKER]) { + can_be_last = FALSE; + } else { + can_be_last = TRUE; + } + mutex_exit(&kernel_mutex); + + sleep_ms = 10; } os_thread_sleep( sleep_ms * 1000 ); @@ -3164,6 +3199,15 @@ loop: n_pages_purged_sum += n_pages_purged; } while (n_pages_purged); + if (srv_shutdown_state > 0 && can_be_last) { + /* the last trx_purge() is executed without workers */ + goto exit_func; + } + + if (n_pages_purged_sum) { + srv_active_wake_master_thread(); + } + if (n_pages_purged_sum == 0) sleep_ms *= 10; if (sleep_ms > 10000) @@ -3172,9 +3216,62 @@ loop: goto loop; exit_func: - /* We count the number of threads in os_thread_exit(). A created - thread should always use that to exit and not use return() to exit. */ + trx_purge_worker_wake(); /* It may not make sense. for safety only */ + /* wake master thread to flush the pages */ + srv_wake_master_thread(); + + mutex_enter(&kernel_mutex); + srv_n_threads_active[SRV_PURGE]--; + mutex_exit(&kernel_mutex); + os_thread_exit(NULL); + + OS_THREAD_DUMMY_RETURN; +} + +/************************************************************************* +A thread which is devoted to purge, for take over the master thread's +purging */ +UNIV_INTERN +os_thread_ret_t +srv_purge_worker_thread( +/*====================*/ + void* arg) +{ + ulint worker_id; /* index for array */ + + worker_id = *((ulint*)arg); + +#ifdef UNIV_DEBUG_THREAD_CREATION + fprintf(stderr, "Purge worker thread starts, id %lu\n", + os_thread_pf(os_thread_get_curr_id())); +#endif + srv_table_reserve_slot(SRV_PURGE_WORKER); + mutex_enter(&kernel_mutex); + srv_n_threads_active[SRV_PURGE_WORKER]++; + mutex_exit(&kernel_mutex); + +loop: + /* purge worker threads only works when srv_shutdown_state==0 */ + /* for safety and exactness. */ + if (srv_shutdown_state > 0) { + goto exit_func; + } + + trx_purge_worker_wait(); + + if (srv_shutdown_state > 0) { + goto exit_func; + } + + trx_purge_worker(worker_id); + + goto loop; + +exit_func: + mutex_enter(&kernel_mutex); + srv_n_threads_active[SRV_PURGE_WORKER]--; + mutex_exit(&kernel_mutex); os_thread_exit(NULL); OS_THREAD_DUMMY_RETURN; diff --git a/srv/srv0start.c b/srv/srv0start.c index e8a9dabdc41..6f29b22e811 100644 --- a/srv/srv0start.c +++ b/srv/srv0start.c @@ -141,9 +141,9 @@ static mutex_t ios_mutex; static ulint ios; /** io_handler_thread parameters for thread identification */ -static ulint n[SRV_MAX_N_IO_THREADS + 5]; +static ulint n[SRV_MAX_N_IO_THREADS + 5 + 64]; /** io_handler_thread identifiers */ -static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5]; +static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5 + 64]; /** We use this mutex to test the return value of pthread_mutex_trylock on successful locking. HP-UX does NOT return 0, though Linux et al do. */ @@ -1739,8 +1739,17 @@ innobase_start_or_create_for_mysql(void) + (1 + SRV_MAX_N_IO_THREADS)); if (srv_use_purge_thread) { + ulint i; + os_thread_create(&srv_purge_thread, NULL, thread_ids + (4 + SRV_MAX_N_IO_THREADS)); + + for (i = 0; i < srv_use_purge_thread - 1; i++) { + n[5 + i + SRV_MAX_N_IO_THREADS] = i; /* using as index for arrays in purge_sys */ + os_thread_create(&srv_purge_worker_thread, + n + (5 + i + SRV_MAX_N_IO_THREADS), + thread_ids + (5 + i + SRV_MAX_N_IO_THREADS)); + } } #ifdef UNIV_DEBUG /* buf_debug_prints = TRUE; */ diff --git a/sync/sync0arr.c b/sync/sync0arr.c index 0519e13dee0..0e30fd054a8 100644 --- a/sync/sync0arr.c +++ b/sync/sync0arr.c @@ -492,12 +492,12 @@ sync_array_cell_print( mutex = cell->old_wait_mutex; fprintf(file, - "Mutex at %p created file %s line %lu, lock var %lu\n" + "Mutex at %p '%s', lock var %lu\n" #ifdef UNIV_SYNC_DEBUG "Last time reserved in file %s line %lu, " #endif /* UNIV_SYNC_DEBUG */ "waiters flag %lu\n", - (void*) mutex, mutex->cfile_name, (ulong) mutex->cline, + (void*) mutex, mutex->cmutex_name, (ulong) mutex->lock_word, #ifdef UNIV_SYNC_DEBUG mutex->file_name, (ulong) mutex->line, @@ -513,9 +513,8 @@ sync_array_cell_print( rwlock = cell->old_wait_rw_lock; fprintf(file, - " RW-latch at %p created in file %s line %lu\n", - (void*) rwlock, rwlock->cfile_name, - (ulong) rwlock->cline); + " RW-latch at %p '%s'\n", + (void*) rwlock, rwlock->lock_name); writer = rw_lock_get_writer(rwlock); if (writer != RW_LOCK_NOT_LOCKED) { fprintf(file, diff --git a/sync/sync0rw.c b/sync/sync0rw.c index 0ed114e330c..b07bd21dcac 100644 --- a/sync/sync0rw.c +++ b/sync/sync0rw.c @@ -230,8 +230,8 @@ rw_lock_create_func( # ifdef UNIV_SYNC_DEBUG ulint level, /*!< in: level */ # endif /* UNIV_SYNC_DEBUG */ - const char* cmutex_name, /*!< in: mutex name */ #endif /* UNIV_DEBUG */ + const char* cmutex_name, /*!< in: mutex name */ const char* cfile_name, /*!< in: file name where created */ ulint cline) /*!< in: file line where created */ { @@ -241,14 +241,15 @@ rw_lock_create_func( #ifndef INNODB_RW_LOCKS_USE_ATOMICS mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK); - lock->mutex.cfile_name = cfile_name; - lock->mutex.cline = cline; + ut_d(lock->mutex.cfile_name = cfile_name); + ut_d(lock->mutex.cline = cline); - ut_d(lock->mutex.cmutex_name = cmutex_name); + lock->mutex.cmutex_name = cmutex_name; ut_d(lock->mutex.mutex_type = 1); #else /* INNODB_RW_LOCKS_USE_ATOMICS */ # ifdef UNIV_DEBUG - UT_NOT_USED(cmutex_name); + UT_NOT_USED(cfile_name); + UT_NOT_USED(cline); # endif #endif /* INNODB_RW_LOCKS_USE_ATOMICS */ @@ -268,8 +269,7 @@ rw_lock_create_func( lock->magic_n = RW_LOCK_MAGIC_N; - lock->cfile_name = cfile_name; - lock->cline = (unsigned int) cline; + lock->lock_name = cmutex_name; lock->count_os_wait = 0; lock->last_s_file_name = "not yet reserved"; @@ -304,8 +304,6 @@ rw_lock_free( ut_ad(rw_lock_validate(lock)); ut_a(lock->lock_word == X_LOCK_DECR); - lock->magic_n = 0; - #ifndef INNODB_RW_LOCKS_USE_ATOMICS mutex_free(rw_lock_get_mutex(lock)); #endif /* INNODB_RW_LOCKS_USE_ATOMICS */ @@ -325,6 +323,8 @@ rw_lock_free( UT_LIST_REMOVE(list, rw_lock_list, lock); mutex_exit(&rw_lock_list_mutex); + + lock->magic_n = 0; } #ifdef UNIV_DEBUG @@ -390,10 +390,10 @@ lock_loop: if (srv_print_latch_waits) { fprintf(stderr, "Thread %lu spin wait rw-s-lock at %p" - " cfile %s cline %lu rnds %lu\n", + " '%s' rnds %lu\n", (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) lock, - lock->cfile_name, (ulong) lock->cline, (ulong) i); + lock->lock_name, (ulong) i); } /* We try once again to obtain the lock */ @@ -426,10 +426,9 @@ lock_loop: if (srv_print_latch_waits) { fprintf(stderr, "Thread %lu OS wait rw-s-lock at %p" - " cfile %s cline %lu\n", + " '%s'\n", os_thread_pf(os_thread_get_curr_id()), - (void*) lock, lock->cfile_name, - (ulong) lock->cline); + (void*) lock, lock->lock_name); } /* these stats may not be accurate */ @@ -648,9 +647,9 @@ lock_loop: if (srv_print_latch_waits) { fprintf(stderr, "Thread %lu spin wait rw-x-lock at %p" - " cfile %s cline %lu rnds %lu\n", + " '%s' rnds %lu\n", os_thread_pf(os_thread_get_curr_id()), (void*) lock, - lock->cfile_name, (ulong) lock->cline, (ulong) i); + lock->lock_name, (ulong) i); } sync_array_reserve_cell(sync_primary_wait_array, @@ -671,9 +670,9 @@ lock_loop: if (srv_print_latch_waits) { fprintf(stderr, "Thread %lu OS wait for rw-x-lock at %p" - " cfile %s cline %lu\n", + " '%s'\n", os_thread_pf(os_thread_get_curr_id()), (void*) lock, - lock->cfile_name, (ulong) lock->cline); + lock->lock_name); } /* these stats may not be accurate */ diff --git a/sync/sync0sync.c b/sync/sync0sync.c index 01aa49688b7..9302f6bebf2 100644 --- a/sync/sync0sync.c +++ b/sync/sync0sync.c @@ -237,8 +237,8 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /*!< in: pointer to memory */ -#ifdef UNIV_DEBUG const char* cmutex_name, /*!< in: mutex name */ +#ifdef UNIV_DEBUG # ifdef UNIV_SYNC_DEBUG ulint level, /*!< in: level */ # endif /* UNIV_SYNC_DEBUG */ @@ -262,11 +262,13 @@ mutex_create_func( mutex->file_name = "not yet reserved"; mutex->level = level; #endif /* UNIV_SYNC_DEBUG */ +#ifdef UNIV_DEBUG mutex->cfile_name = cfile_name; mutex->cline = cline; +#endif /* UNIV_DEBUG */ mutex->count_os_wait = 0; -#ifdef UNIV_DEBUG mutex->cmutex_name= cmutex_name; +#ifdef UNIV_DEBUG mutex->count_using= 0; mutex->mutex_type= 0; mutex->lspent_time= 0; @@ -498,9 +500,9 @@ spin_loop: #ifdef UNIV_SRV_PRINT_LATCH_WAITS fprintf(stderr, "Thread %lu spin wait mutex at %p" - " cfile %s cline %lu rnds %lu\n", + " '%s' rnds %lu\n", (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex, - mutex->cfile_name, (ulong) mutex->cline, (ulong) i); + mutex->cmutex_name, (ulong) i); #endif mutex_spin_round_count += i; @@ -575,9 +577,9 @@ spin_loop: #ifdef UNIV_SRV_PRINT_LATCH_WAITS fprintf(stderr, - "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n", + "Thread %lu OS wait mutex at %p '%s' rnds %lu\n", (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex, - mutex->cfile_name, (ulong) mutex->cline, (ulong) i); + mutex->cmutex_name, (ulong) i); #endif mutex_os_wait_count++; @@ -873,9 +875,8 @@ sync_thread_levels_g( if (mutex->magic_n == MUTEX_MAGIC_N) { fprintf(stderr, - "Mutex created at %s %lu\n", - mutex->cfile_name, - (ulong) mutex->cline); + "Mutex '%s'\n", + mutex->cmutex_name); if (mutex_get_lock_word(mutex) != 0) { const char* file_name; diff --git a/trx/trx0purge.c b/trx/trx0purge.c index cd79fd1c315..62fbd1c1446 100644 --- a/trx/trx0purge.c +++ b/trx/trx0purge.c @@ -184,8 +184,9 @@ this query graph. @return own: the query graph */ static que_t* -trx_purge_graph_build(void) +trx_purge_graph_build( /*=======================*/ + trx_t* trx) { mem_heap_t* heap; que_fork_t* fork; @@ -194,7 +195,7 @@ trx_purge_graph_build(void) heap = mem_heap_create(512); fork = que_fork_create(NULL, NULL, QUE_FORK_PURGE, heap); - fork->trx = purge_sys->trx; + fork->trx = trx; thr = que_thr_create(fork, heap); @@ -243,10 +244,35 @@ trx_purge_sys_create(void) ut_a(trx_start_low(purge_sys->trx, ULINT_UNDEFINED)); - purge_sys->query = trx_purge_graph_build(); + purge_sys->query = trx_purge_graph_build(purge_sys->trx); purge_sys->view = read_view_oldest_copy_or_open_new(ut_dulint_zero, purge_sys->heap); + + purge_sys->n_worker = 0; + if (srv_use_purge_thread > 1) { + /* Use worker threads */ + ulint i; + + purge_sys->n_worker = srv_use_purge_thread - 1; + + purge_sys->sess_arr = mem_alloc(sizeof(sess_t*) * purge_sys->n_worker); + purge_sys->trx_arr = mem_alloc(sizeof(trx_t*) * purge_sys->n_worker); + purge_sys->query_arr = mem_alloc(sizeof(que_t*) * purge_sys->n_worker); + + purge_sys->worker_event = os_event_create(NULL); + os_event_reset(purge_sys->worker_event); + + for (i = 0; i < purge_sys->n_worker; i++) { + purge_sys->sess_arr[i] = sess_open(); + + purge_sys->trx_arr[i] = purge_sys->sess_arr[i]->trx; + purge_sys->trx_arr[i]->is_purge = 1; + ut_a(trx_start_low(purge_sys->trx_arr[i], ULINT_UNDEFINED)); + + purge_sys->query_arr[i] = trx_purge_graph_build(purge_sys->trx_arr[i]); + } + } } /*================ UNDO LOG HISTORY LIST =============================*/ @@ -1110,7 +1136,7 @@ trx_purge(void) /* Handle at most 20 undo log pages in one purge batch */ - purge_sys->handle_limit = purge_sys->n_pages_handled + 20; + purge_sys->handle_limit = purge_sys->n_pages_handled + 20 * (srv_use_purge_thread + 1); old_pages_handled = purge_sys->n_pages_handled; @@ -1129,6 +1155,9 @@ trx_purge(void) mutex_exit(&kernel_mutex); + if (purge_sys->n_worker) + os_event_set(purge_sys->worker_event); + /* srv_que_task_enqueue(thr2); */ if (srv_print_thread_releases) { @@ -1138,6 +1167,9 @@ trx_purge(void) que_run_threads(thr); + if (purge_sys->n_worker) + os_event_reset(purge_sys->worker_event); + if (srv_print_thread_releases) { fprintf(stderr, @@ -1148,6 +1180,52 @@ trx_purge(void) return(purge_sys->n_pages_handled - old_pages_handled); } +/********************************************************************** +This function runs a purge worker batch */ +UNIV_INTERN +void +trx_purge_worker( +/*=============*/ + ulint worker_id) +{ + que_thr_t* thr; + + mutex_enter(&kernel_mutex); + + thr = que_fork_start_command(purge_sys->query_arr[worker_id]); + + ut_ad(thr); + + mutex_exit(&kernel_mutex); + + que_run_threads(thr); + + if (purge_sys->state == TRX_STOP_PURGE) { /* optimistic */ + os_event_reset(purge_sys->worker_event); + } +} + +/********************************************************************** +This function waits the event for worker batch */ +UNIV_INTERN +void +trx_purge_worker_wait(void) +/*=======================*/ +{ + os_event_wait(purge_sys->worker_event); +} + +/********************************************************************** +This function wakes the waiting worker batch */ +UNIV_INTERN +void +trx_purge_worker_wake(void) +/*=======================*/ +{ + if (purge_sys->n_worker) + os_event_set(purge_sys->worker_event); +} + /******************************************************************//** Prints information of the purge system to stderr. */ UNIV_INTERN diff --git a/trx/trx0trx.c b/trx/trx0trx.c index 12253c131a8..b7fedf58c2a 100644 --- a/trx/trx0trx.c +++ b/trx/trx0trx.c @@ -178,6 +178,15 @@ trx_create( trx->global_read_view = NULL; trx->read_view = NULL; + trx->io_reads = 0; + trx->io_read = 0; + trx->io_reads_wait_timer = 0; + trx->lock_que_wait_timer = 0; + trx->innodb_que_wait_timer = 0; + trx->distinct_page_access = 0; + trx->distinct_page_access_hash = NULL; + trx->take_stats = FALSE; + /* Set X/Open XA transaction identification to NULL */ memset(&trx->xid, 0, sizeof(trx->xid)); trx->xid.formatID = -1; @@ -215,6 +224,11 @@ trx_allocate_for_mysql(void) trx->mysql_process_no = os_proc_get_number(); + if (innobase_get_slow_log() && trx->take_stats) { + trx->distinct_page_access_hash = mem_alloc(DPAH_SIZE); + memset(trx->distinct_page_access_hash, 0, DPAH_SIZE); + } + return(trx); } @@ -346,6 +360,12 @@ trx_free_for_mysql( /*===============*/ trx_t* trx) /*!< in, own: trx object */ { + if (trx->distinct_page_access_hash) + { + mem_free(trx->distinct_page_access_hash); + trx->distinct_page_access_hash= NULL; + } + mutex_enter(&kernel_mutex); UT_LIST_REMOVE(mysql_trx_list, trx_sys->mysql_trx_list, trx); @@ -367,6 +387,12 @@ trx_free_for_background( /*====================*/ trx_t* trx) /*!< in, own: trx object */ { + if (trx->distinct_page_access_hash) + { + mem_free(trx->distinct_page_access_hash); + trx->distinct_page_access_hash= NULL; + } + mutex_enter(&kernel_mutex); trx_free(trx); @@ -1072,6 +1098,9 @@ trx_end_lock_wait( trx_t* trx) /*!< in: transaction */ { que_thr_t* thr; + ulint sec; + ulint ms; + ib_uint64_t now; ut_ad(mutex_own(&kernel_mutex)); ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT); @@ -1086,6 +1115,11 @@ trx_end_lock_wait( thr = UT_LIST_GET_FIRST(trx->wait_thrs); } + if (innobase_get_slow_log() && trx->take_stats) { + ut_usectime(&sec, &ms); + now = (ib_uint64_t)sec * 1000000 + ms; + trx->lock_que_wait_timer += (ulint)(now - trx->lock_que_wait_ustarted); + } trx->que_state = TRX_QUE_RUNNING; } @@ -1099,6 +1133,9 @@ trx_lock_wait_to_suspended( trx_t* trx) /*!< in: transaction in the TRX_QUE_LOCK_WAIT state */ { que_thr_t* thr; + ulint sec; + ulint ms; + ib_uint64_t now; ut_ad(mutex_own(&kernel_mutex)); ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT); @@ -1113,6 +1150,11 @@ trx_lock_wait_to_suspended( thr = UT_LIST_GET_FIRST(trx->wait_thrs); } + if (innobase_get_slow_log() && trx->take_stats) { + ut_usectime(&sec, &ms); + now = (ib_uint64_t)sec * 1000000 + ms; + trx->lock_que_wait_timer += (ulint)(now - trx->lock_que_wait_ustarted); + } trx->que_state = TRX_QUE_RUNNING; } From b93268ba8038e429b6d6c1bcac889d1931f9d51f Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Wed, 4 Nov 2009 15:34:42 -0700 Subject: [PATCH 021/344] Fix for Bug#40700: aclocal warnings for missing cache-id's Just change mysql_foo to mysql_cv_foo for one cache-id variable name. There was only one bad variable name, present in 5.0 and 5.1, but not in the -pe branch. --- config/ac-macros/misc.m4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4 index 9e575862848..7c829ed303a 100644 --- a/config/ac-macros/misc.m4 +++ b/config/ac-macros/misc.m4 @@ -726,15 +726,15 @@ dnl --------------------------------------------------------------------------- dnl MYSQL_NEEDS_MYSYS_NEW AC_DEFUN([MYSQL_NEEDS_MYSYS_NEW], -[AC_CACHE_CHECK([needs mysys_new helpers], mysql_use_mysys_new, +[AC_CACHE_CHECK([needs mysys_new helpers], mysql_cv_use_mysys_new, [ AC_LANG_PUSH(C++) AC_TRY_LINK([], [ class A { public: int b; }; A *a=new A; a->b=10; delete a; -], mysql_use_mysys_new=no, mysql_use_mysys_new=yes) +], mysql_cv_use_mysys_new=no, mysql_cv_use_mysys_new=yes) AC_LANG_POP(C++) ]) -if test "$mysql_use_mysys_new" = "yes" +if test "$mysql_cv_use_mysys_new" = "yes" then AC_DEFINE([USE_MYSYS_NEW], [1], [Needs to use mysys_new helpers]) fi From 39f9a3ffd0de8828be2a43b9674a19fa58c52f98 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Fri, 6 Nov 2009 09:44:01 +0300 Subject: [PATCH 022/344] Bug #48475: DISTINCT is ignored with GROUP BY WITH ROLLUP and only const tables The problem was caused by two shortcuts in the optimizer that are inapplicable in the ROLLUP case. Normally in a case when only const tables are involved in a query, DISTINCT clause can be safely optimized away since there may be only one row produced by the join. Similarly, we don't need to create a temporary table to resolve DISTINCT/GROUP BY/ORDER BY. Both of these are inapplicable when the WITH ROLLUP modifier is present. Fixed by disabling the said optimizations for the WITH ROLLUP case. mysql-test/r/olap.result: Added a test case for bug #48475. mysql-test/t/olap.test: Added a test case for bug #48475. sql/sql_select.cc: Disabled const-only table optimizations for the WITH ROLLUP case. --- mysql-test/r/olap.result | 12 ++++++++++++ mysql-test/t/olap.test | 13 +++++++++++++ sql/sql_select.cc | 23 ++++++++++++++++------- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 56e06f03378..eabe3a50309 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -753,4 +753,16 @@ b 100 NULL DROP TABLE t1, t2; +# +# Bug #48475: DISTINCT is ignored with GROUP BY WITH ROLLUP +# and only const tables +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP; +b +1 +NULL +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index 8f672af40a3..fec5df1a1c7 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -390,4 +390,17 @@ SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP; DROP TABLE t1, t2; +--echo # +--echo # Bug #48475: DISTINCT is ignored with GROUP BY WITH ROLLUP +--echo # and only const tables + +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP; + +DROP TABLE t1, t2; + --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 51794c1f158..1ee31c788ff 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -929,14 +929,20 @@ JOIN::optimize() DBUG_RETURN(1); } - if (select_lex->olap == ROLLUP_TYPE && rollup_process_const_fields()) + if (rollup.state != ROLLUP::STATE_NONE) { - DBUG_PRINT("error", ("Error: rollup_process_fields() failed")); - DBUG_RETURN(1); + if (rollup_process_const_fields()) + { + DBUG_PRINT("error", ("Error: rollup_process_fields() failed")); + DBUG_RETURN(1); + } + } + else + { + /* Remove distinct if only const tables */ + select_distinct= select_distinct && (const_tables != tables); } - /* Remove distinct if only const tables */ - select_distinct= select_distinct && (const_tables != tables); thd_proc_info(thd, "preparing"); if (result->initialize_tables(this)) { @@ -1216,11 +1222,14 @@ JOIN::optimize() - We are using an ORDER BY or GROUP BY on fields not in the first table - We are using different ORDER BY and GROUP BY orders - The user wants us to buffer the result. + When the WITH ROLLUP modifier is present, we cannot skip temporary table + creation for the DISTINCT clause just because there are only const tables. */ - need_tmp= (const_tables != tables && + need_tmp= ((const_tables != tables && ((select_distinct || !simple_order || !simple_group) || (group_list && order) || - test(select_options & OPTION_BUFFER_RESULT))); + test(select_options & OPTION_BUFFER_RESULT))) || + rollup.state != ROLLUP::STATE_NONE && select_distinct); // No cache for MATCH make_join_readinfo(this, From c81e23457aca99ea760fbd9143e22b95bb1a7cf2 Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Fri, 6 Nov 2009 22:34:25 +0300 Subject: [PATCH 023/344] Bug#34384: Slow down on constant conversion. When values of different types are compared they're converted to a type that allows correct comparison. This conversion is done for each comparison and takes some time. When a constant is being compared it's possible to cache the value after conversion to speedup comparison. In some cases (large dataset, complex WHERE condition with many type conversions) query might be executed 7% faster. A test case isn't provided because all changes are internal and isn't visible outside. The behavior of the Item_cache is changed to cache values on the first request of cached value rather than at the moment of storing item to be cached. A flag named value_cached is added to the Item_cache class. It's set to TRUE when cache holds the value of the last stored item. Function named cache_value() is added to the Item_cache class and derived classes. This function actually caches the value of the saved item. Item_cache_xxx::store functions now only store item to be cached and set value_cached flag to FALSE. Item_cache_xxx::val_xxx functions are changed to call cache_value function prior to returning cached value if value_cached is FALSE. The Arg_comparator::set_cmp_func function now calls cache_converted_constant to cache constants if they need a type conversion. The Item_cache::get_cache function is overloaded to allow setting of the cache type. The cache_converted_constant function is added to the Arg_comparator class. It checks whether a value can and should be cached and if so caches it. sql/item.cc: Bug#34384: Slow down on constant conversion. Function named cache_value() is added to the Item_cache class and derived classes. This function actually caches the value of the saved item. Item_cache_xxx::store functions now only store item to be cached and set value_cached flag to FALSE. Item_cache_xxx::val_xxx functions are changed to call cache_value function prior to returning cached value if value_cached is FALSE. The Item_cache::get_cache function is overloaded to allow setting of the cache type. sql/item.h: Bug#34384: Slow down on constant conversion. A flag named value_cached is added to the Item_cache class. It's set to TRUE when we need to start caching values when the store method is called. Function named cache_value() is added to the Item_cache class and derived classes. sql/item_cmpfunc.cc: Bug#34384: Slow down on constant conversion. A helper function cache_converted_constant is added to the Arg_comparator class. It checks whether a given item can and should be cached and caches it if so. The Arg_comparator::set_cmp_func function now calls cache_converted_constant to cache constants if they need a type conversion. sql/item_cmpfunc.h: Bug#34384: Slow down on constant conversion. The cache_converted_constant function is added to the Arg_comparator class. It checks whether a value can and should be cached and if so caches it. sql/item_subselect.cc: Bug#34384: Slow down on constant conversion. Force immediate caching of subselect result. sql/item_xmlfunc.cc: Bug#34384: Slow down on constant conversion. sql/sp_rcontext.cc: Bug#34384: Slow down on constant conversion. Force immediate caching of values of an SP CASE function. --- sql/item.cc | 131 ++++++++++++++++++++++++++++++++++++------ sql/item.h | 50 +++++++++++----- sql/item_cmpfunc.cc | 47 +++++++++++++-- sql/item_cmpfunc.h | 2 + sql/item_subselect.cc | 2 + sql/item_xmlfunc.cc | 6 +- sql/sp_rcontext.cc | 2 +- 7 files changed, 199 insertions(+), 41 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index f637f9ffaea..d394435baed 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6958,7 +6958,22 @@ int stored_field_cmp_to_item(Field *field, Item *item) Item_cache* Item_cache::get_cache(const Item *item) { - switch (item->result_type()) { + return get_cache(item, item->result_type()); +} + + +/** + Get a cache item of given type. + + @param item value to be cached + @param type required type of cache + + @return cache item +*/ + +Item_cache* Item_cache::get_cache(const Item *item, const Item_result type) +{ + switch (type) { case INT_RESULT: return new Item_cache_int(); case REAL_RESULT: @@ -6976,6 +6991,12 @@ Item_cache* Item_cache::get_cache(const Item *item) } } +void Item_cache::store(Item *item) +{ + if (item) + example= item; + value_cached= FALSE; +} void Item_cache::print(String *str, enum_query_type query_type) { @@ -6987,17 +7008,19 @@ void Item_cache::print(String *str, enum_query_type query_type) str->append(')'); } - -void Item_cache_int::store(Item *item) +void Item_cache_int::cache_value() { - value= item->val_int_result(); - null_value= item->null_value; - unsigned_flag= item->unsigned_flag; + value_cached= TRUE; + value= example->val_int_result(); + null_value= example->null_value; + unsigned_flag= example->unsigned_flag; } void Item_cache_int::store(Item *item, longlong val_arg) { + /* An explicit values is given, save it. */ + value_cached= TRUE; value= val_arg; null_value= item->null_value; unsigned_flag= item->unsigned_flag; @@ -7007,6 +7030,8 @@ void Item_cache_int::store(Item *item, longlong val_arg) String *Item_cache_int::val_str(String *str) { DBUG_ASSERT(fixed == 1); + if (!value_cached) + cache_value(); str->set(value, default_charset()); return str; } @@ -7015,21 +7040,49 @@ String *Item_cache_int::val_str(String *str) my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val) { DBUG_ASSERT(fixed == 1); + if (!value_cached) + cache_value(); int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_val); return decimal_val; } - -void Item_cache_real::store(Item *item) +double Item_cache_int::val_real() { - value= item->val_result(); - null_value= item->null_value; + DBUG_ASSERT(fixed == 1); + if (!value_cached) + cache_value(); + return (double) value; } +longlong Item_cache_int::val_int() +{ + DBUG_ASSERT(fixed == 1); + if (!value_cached) + cache_value(); + return value; +} + +void Item_cache_real::cache_value() +{ + value_cached= TRUE; + value= example->val_result(); + null_value= example->null_value; +} + + +double Item_cache_real::val_real() +{ + DBUG_ASSERT(fixed == 1); + if (!value_cached) + cache_value(); + return value; +} longlong Item_cache_real::val_int() { DBUG_ASSERT(fixed == 1); + if (!value_cached) + cache_value(); return (longlong) rint(value); } @@ -7037,6 +7090,8 @@ longlong Item_cache_real::val_int() String* Item_cache_real::val_str(String *str) { DBUG_ASSERT(fixed == 1); + if (!value_cached) + cache_value(); str->set_real(value, decimals, default_charset()); return str; } @@ -7045,15 +7100,18 @@ String* Item_cache_real::val_str(String *str) my_decimal *Item_cache_real::val_decimal(my_decimal *decimal_val) { DBUG_ASSERT(fixed == 1); + if (!value_cached) + cache_value(); double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val); return decimal_val; } -void Item_cache_decimal::store(Item *item) +void Item_cache_decimal::cache_value() { - my_decimal *val= item->val_decimal_result(&decimal_value); - if (!(null_value= item->null_value) && val != &decimal_value) + value_cached= TRUE; + my_decimal *val= example->val_decimal_result(&decimal_value); + if (!(null_value= example->null_value) && val != &decimal_value) my_decimal2decimal(val, &decimal_value); } @@ -7061,6 +7119,8 @@ double Item_cache_decimal::val_real() { DBUG_ASSERT(fixed); double res; + if (!value_cached) + cache_value(); my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res); return res; } @@ -7069,6 +7129,8 @@ longlong Item_cache_decimal::val_int() { DBUG_ASSERT(fixed); longlong res; + if (!value_cached) + cache_value(); my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &res); return res; } @@ -7076,6 +7138,8 @@ longlong Item_cache_decimal::val_int() String* Item_cache_decimal::val_str(String *str) { DBUG_ASSERT(fixed); + if (!value_cached) + cache_value(); my_decimal_round(E_DEC_FATAL_ERROR, &decimal_value, decimals, FALSE, &decimal_value); my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, str); @@ -7085,15 +7149,18 @@ String* Item_cache_decimal::val_str(String *str) my_decimal *Item_cache_decimal::val_decimal(my_decimal *val) { DBUG_ASSERT(fixed); + if (!value_cached) + cache_value(); return &decimal_value; } -void Item_cache_str::store(Item *item) +void Item_cache_str::cache_value() { - value_buff.set(buffer, sizeof(buffer), item->collation.collation); - value= item->str_result(&value_buff); - if ((null_value= item->null_value)) + value_cached= TRUE; + value_buff.set(buffer, sizeof(buffer), example->collation.collation); + value= example->str_result(&value_buff); + if ((null_value= example->null_value)) value= 0; else if (value != &value_buff) { @@ -7115,6 +7182,8 @@ double Item_cache_str::val_real() DBUG_ASSERT(fixed == 1); int err_not_used; char *end_not_used; + if (!value_cached) + cache_value(); if (value) return my_strntod(value->charset(), (char*) value->ptr(), value->length(), &end_not_used, &err_not_used); @@ -7126,6 +7195,8 @@ longlong Item_cache_str::val_int() { DBUG_ASSERT(fixed == 1); int err; + if (!value_cached) + cache_value(); if (value) return my_strntoll(value->charset(), value->ptr(), value->length(), 10, (char**) 0, &err); @@ -7133,9 +7204,21 @@ longlong Item_cache_str::val_int() return (longlong)0; } + +String* Item_cache_str::val_str(String *str) +{ + DBUG_ASSERT(fixed == 1); + if (!value_cached) + cache_value(); + return value; +} + + my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val) { DBUG_ASSERT(fixed == 1); + if (!value_cached) + cache_value(); if (value) string2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val); else @@ -7146,6 +7229,8 @@ my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val) int Item_cache_str::save_in_field(Field *field, bool no_conversions) { + if (!value_cached) + cache_value(); int res= Item_cache::save_in_field(field, no_conversions); return (is_varbinary && field->type() == MYSQL_TYPE_STRING && value->length() < field->field_length) ? 1 : res; @@ -7180,11 +7265,19 @@ bool Item_cache_row::setup(Item * item) void Item_cache_row::store(Item * item) { + for (uint i= 0; i < item_count; i++) + values[i]->store(item->element_index(i)); +} + + +void Item_cache_row::cache_value() +{ + value_cached= TRUE; null_value= 0; - item->bring_value(); + example->bring_value(); for (uint i= 0; i < item_count; i++) { - values[i]->store(item->element_index(i)); + values[i]->cache_value(); null_value|= values[i]->null_value; } } diff --git a/sql/item.h b/sql/item.h index a2cff3ab3a9..ff951754b98 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1025,7 +1025,11 @@ class sp_head; class Item_basic_constant :public Item { + table_map used_table_map; public: + Item_basic_constant(): Item(), used_table_map(0) {}; + void set_used_tables(table_map map) { used_table_map= map; } + table_map used_tables() const { return used_table_map; } /* to prevent drop fixed flag (no need parent cleanup call) */ void cleanup() { @@ -2890,15 +2894,25 @@ protected: */ Field *cached_field; enum enum_field_types cached_field_type; + /* + TRUE <=> cache holds value of the last stored item (i.e actual value). + store() stores item to be cached and sets this flag to FALSE. + On the first call of val_xxx function if this flag is set to FALSE the + cache_value() will be called to actually cache value of saved item. + cache_value() will set this flag to TRUE. + */ + bool value_cached; public: - Item_cache(): - example(0), used_table_map(0), cached_field(0), cached_field_type(MYSQL_TYPE_STRING) + Item_cache(): + example(0), used_table_map(0), cached_field(0), cached_field_type(MYSQL_TYPE_STRING), + value_cached(0) { fixed= 1; null_value= 1; } Item_cache(enum_field_types field_type_arg): - example(0), used_table_map(0), cached_field(0), cached_field_type(field_type_arg) + example(0), used_table_map(0), cached_field(0), cached_field_type(field_type_arg), + value_cached(0) { fixed= 1; null_value= 1; @@ -2918,10 +2932,10 @@ public: cached_field= ((Item_field *)item)->field; return 0; }; - virtual void store(Item *)= 0; enum Type type() const { return CACHE_ITEM; } enum_field_types field_type() const { return cached_field_type; } static Item_cache* get_cache(const Item *item); + static Item_cache* get_cache(const Item* item, const Item_result type); table_map used_tables() const { return used_table_map; } virtual void keep_array() {} virtual void print(String *str, enum_query_type query_type); @@ -2933,6 +2947,8 @@ public: { return this == item; } + virtual void store(Item *item); + virtual void cache_value()= 0; }; @@ -2941,18 +2957,19 @@ class Item_cache_int: public Item_cache protected: longlong value; public: - Item_cache_int(): Item_cache(), value(0) {} + Item_cache_int(): Item_cache(), + value(0) {} Item_cache_int(enum_field_types field_type_arg): Item_cache(field_type_arg), value(0) {} - void store(Item *item); void store(Item *item, longlong val_arg); - double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; } - longlong val_int() { DBUG_ASSERT(fixed == 1); return value; } + double val_real(); + longlong val_int(); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); enum Item_result result_type() const { return INT_RESULT; } bool result_as_longlong() { return TRUE; } + void cache_value(); }; @@ -2960,14 +2977,15 @@ class Item_cache_real: public Item_cache { double value; public: - Item_cache_real(): Item_cache(), value(0) {} + Item_cache_real(): Item_cache(), + value(0) {} - void store(Item *item); - double val_real() { DBUG_ASSERT(fixed == 1); return value; } + double val_real(); longlong val_int(); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); enum Item_result result_type() const { return REAL_RESULT; } + void cache_value(); }; @@ -2978,12 +2996,12 @@ protected: public: Item_cache_decimal(): Item_cache() {} - void store(Item *item); double val_real(); longlong val_int(); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); enum Item_result result_type() const { return DECIMAL_RESULT; } + void cache_value(); }; @@ -3001,14 +3019,14 @@ public: MYSQL_TYPE_VARCHAR && !((const Item_field *) item)->field->has_charset()) {} - void store(Item *item); double val_real(); longlong val_int(); - String* val_str(String *) { DBUG_ASSERT(fixed == 1); return value; } + String* val_str(String *); my_decimal *val_decimal(my_decimal *); enum Item_result result_type() const { return STRING_RESULT; } CHARSET_INFO *charset() const { return value->charset(); }; int save_in_field(Field *field, bool no_conversions); + void cache_value(); }; class Item_cache_row: public Item_cache @@ -3018,7 +3036,8 @@ class Item_cache_row: public Item_cache bool save_array; public: Item_cache_row() - :Item_cache(), values(0), item_count(2), save_array(0) {} + :Item_cache(), values(0), item_count(2), + save_array(0) {} /* 'allocate' used only in row transformer, to preallocate space for row @@ -3076,6 +3095,7 @@ public: values= 0; DBUG_VOID_RETURN; } + void cache_value(); }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c29031d25b5..97ad45d9774 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -855,13 +855,13 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, { enum enum_date_cmp_type cmp_type; ulonglong const_value= (ulonglong)-1; + thd= current_thd; + owner= owner_arg; a= a1; b= a2; if ((cmp_type= can_compare_as_dates(*a, *b, &const_value))) { - thd= current_thd; - owner= owner_arg; a_type= (*a)->field_type(); b_type= (*b)->field_type(); a_cache= 0; @@ -869,6 +869,10 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, if (const_value != (ulonglong)-1) { + /* + cache_converted_constant can't be used here because it can't + correctly convert a DATETIME value from string to int representation. + */ Item_cache_int *cache= new Item_cache_int(); /* Mark the cache as non-const to prevent re-caching. */ cache->set_used_tables(1); @@ -894,8 +898,6 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, (*b)->field_type() == MYSQL_TYPE_TIME) { /* Compare TIME values as integers. */ - thd= current_thd; - owner= owner_arg; a_cache= 0; b_cache= 0; is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC); @@ -914,10 +916,46 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, return 1; } + a= cache_converted_constant(thd, a, &a_cache, type); + b= cache_converted_constant(thd, b, &b_cache, type); return set_compare_func(owner_arg, type); } +/** + Convert and cache a constant. + + @param value [in] An item to cache + @param cache_item [out] Placeholder for the cache item + @param type [in] Comparison type + + @details + When given item is a constant and its type differs from comparison type + then cache its value to avoid type conversion of this constant on each + evaluation. In this case the value is cached and the reference to the cache + is returned. + Original value is returned otherwise. + + @return cache item or original value. +*/ + +Item** Arg_comparator::cache_converted_constant(THD *thd, Item **value, + Item **cache_item, + Item_result type) +{ + /* Don't need cache if doing context analysis only. */ + if (!thd->is_context_analysis_only() && + (*value)->const_item() && type != (*value)->result_type()) + { + Item_cache *cache= Item_cache::get_cache(*value, type); + cache->store(*value); + *cache_item= cache; + return cache_item; + } + return value; +} + + void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1) { thd= current_thd; @@ -1556,6 +1594,7 @@ longlong Item_in_optimizer::val_int() bool tmp; DBUG_ASSERT(fixed == 1); cache->store(args[0]); + cache->cache_value(); if (cache->null_value) { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index c2227fa04e0..c6badd9d920 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -94,6 +94,8 @@ public: ulonglong *const_val_arg); void set_datetime_cmp_func(Item **a1, Item **b1); + Item** cache_converted_constant(THD *thd, Item **value, Item **cache, + Item_result type); static arg_cmp_func comparator_matrix [5][2]; friend class Item_func; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index da651cec70c..27beadaed17 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -475,6 +475,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) void Item_singlerow_subselect::store(uint i, Item *item) { row[i]->store(item); + row[i]->cache_value(); } enum Item_result Item_singlerow_subselect::result_type() const @@ -1826,6 +1827,7 @@ void subselect_engine::set_row(List &item_list, Item_cache **row) if (!(row[i]= Item_cache::get_cache(sel_item))) return; row[i]->setup(sel_item); + row[i]->store(sel_item); } if (item_list.elements > 1) res_type= ROW_RESULT; diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 1eff00027f2..3e20b90e68e 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -941,14 +941,16 @@ static Item *create_comparator(MY_XPATH *xpath, in a loop through all of the nodes in the node set. */ - Item *fake= new Item_string("", 0, xpath->cs); + Item_string *fake= new Item_string("", 0, xpath->cs); + /* Don't cache fake because its value will be changed during comparison.*/ + fake->set_used_tables(RAND_TABLE_BIT); Item_nodeset_func *nodeset; Item *scalar, *comp; if (a->type() == Item::XPATH_NODESET) { nodeset= (Item_nodeset_func*) a; scalar= b; - comp= eq_func(oper, fake, scalar); + comp= eq_func(oper, (Item*)fake, scalar); } else { diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 9b237b3e7cc..be8f705a53e 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -617,7 +617,7 @@ sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr } m_case_expr_holders[case_expr_id]->store(case_expr_item); - + m_case_expr_holders[case_expr_id]->cache_value(); return FALSE; } From 2f16acf9dd9eccbdae872bf2421c7b5cde3d354b Mon Sep 17 00:00:00 2001 From: Aleksandr Kuzminsky Date: Sun, 8 Nov 2009 13:13:39 -0800 Subject: [PATCH 024/344] Sync with rev. 115 --- include/univ.i | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/univ.i b/include/univ.i index ac1de67a411..19ef867eeb8 100644 --- a/include/univ.i +++ b/include/univ.i @@ -47,7 +47,11 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 1 #define INNODB_VERSION_MINOR 0 #define INNODB_VERSION_BUGFIX 4 -#define PERCONA_INNODB_VERSION 7 + +#ifndef PERCONA_INNODB_VERSION +#define PERCONA_INNODB_VERSION unknown +#endif + /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; @@ -59,14 +63,15 @@ component, i.e. we show M.N.P as M.N */ (INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR) /* auxiliary macros to help creating the version as string */ -#define __INNODB_VERSION(a, b, c, d) (#a "." #b "." #c "-" #d) -#define _INNODB_VERSION(a, b, c, d) __INNODB_VERSION(a, b, c, d) +#define __INNODB_VERSION(a, b, c, d) (#a "." #b "." #c "-" #d) +#define _INNODB_VERSION(a, b, c, d) __INNODB_VERSION(a, b, c, d) + #define INNODB_VERSION_STR \ _INNODB_VERSION(INNODB_VERSION_MAJOR, \ INNODB_VERSION_MINOR, \ - INNODB_VERSION_BUGFIX, \ - PERCONA_INNODB_VERSION) + INNODB_VERSION_BUGFIX, \ + PERCONA_INNODB_VERSION) #define REFMAN "http://dev.mysql.com/doc/refman/5.1/en/" From 785b5c4e7a06445d2b23b57c3dce120828844c69 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 9 Nov 2009 11:26:01 +0100 Subject: [PATCH 025/344] Bug#48276: can't add column if subpartition exists Bug when setting up default partitioning, used an uninitialized variabe. mysql-test/r/partition.result: Bug#48276: can't add column if subpartition exists Added result mysql-test/t/partition.test: Bug#48276: can't add column if subpartition exists Added test sql/sql_partition.cc: Bug#48276: can't add column if subpartition exists even if is_create_table_ind was set, one tried to set no_subparts with the unitialized no_parts local variable. Fixed by rearrange the code to be to only execute the statements when is_create_table_ind was not set. --- mysql-test/r/partition.result | 6 ++++++ mysql-test/t/partition.test | 9 +++++++++ sql/sql_partition.cc | 31 ++++++++++++++++--------------- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 6611d39628f..9ee62c978d0 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1,4 +1,10 @@ drop table if exists t1, t2; +CREATE TABLE t1 (a INT, b INT) +PARTITION BY LIST (a) +SUBPARTITION BY HASH (b) +(PARTITION p1 VALUES IN (1)); +ALTER TABLE t1 ADD COLUMN c INT; +DROP TABLE t1; CREATE TABLE t1 ( a int NOT NULL, b int NOT NULL); diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 1dfc53c6232..3fc67a1f147 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -14,6 +14,15 @@ drop table if exists t1, t2; --enable_warnings +# +# Bug#48276: can't add column if subpartition exists +CREATE TABLE t1 (a INT, b INT) +PARTITION BY LIST (a) +SUBPARTITION BY HASH (b) +(PARTITION p1 VALUES IN (1)); +ALTER TABLE t1 ADD COLUMN c INT; +DROP TABLE t1; + # # Bug#46639: 1030 (HY000): Got error 124 from storage engine on # INSERT ... SELECT ... diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 04d22174c8e..9f1844d746c 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -196,26 +196,27 @@ bool partition_default_handling(TABLE *table, partition_info *part_info, { DBUG_ENTER("partition_default_handling"); - if (part_info->use_default_no_partitions) + if (!is_create_table_ind) { - if (!is_create_table_ind && - table->file->get_no_parts(normalized_path, &part_info->no_parts)) + if (part_info->use_default_no_partitions) { - DBUG_RETURN(TRUE); + if (table->file->get_no_parts(normalized_path, &part_info->no_parts)) + { + DBUG_RETURN(TRUE); + } } - } - else if (part_info->is_sub_partitioned() && - part_info->use_default_no_subpartitions) - { - uint no_parts; - if (!is_create_table_ind && - (table->file->get_no_parts(normalized_path, &no_parts))) + else if (part_info->is_sub_partitioned() && + part_info->use_default_no_subpartitions) { - DBUG_RETURN(TRUE); + uint no_parts; + if (table->file->get_no_parts(normalized_path, &no_parts)) + { + DBUG_RETURN(TRUE); + } + DBUG_ASSERT(part_info->no_parts > 0); + DBUG_ASSERT((no_parts % part_info->no_parts) == 0); + part_info->no_subparts= no_parts / part_info->no_parts; } - DBUG_ASSERT(part_info->no_parts > 0); - part_info->no_subparts= no_parts / part_info->no_parts; - DBUG_ASSERT((no_parts % part_info->no_parts) == 0); } part_info->set_up_defaults_for_partitioning(table->file, (ulonglong)0, (uint)0); From ddd90017e75cf1241da12cdc3fd55b44da0c4a9d Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 10 Nov 2009 10:21:41 +0200 Subject: [PATCH 026/344] Bug #42760: Select doesn't return desired results when we have null values We should re-set the access method functions when changing the access method when switching to another index to avoid sorting. Fixed by doing a little re-engineering : encapsulating all the function assignment into a special function and calling it when flipping the indexes. --- mysql-test/r/order_by.result | 21 +++++++ mysql-test/t/order_by.test | 26 ++++++++ sql/sql_select.cc | 111 +++++++++++++++++++---------------- 3 files changed, 108 insertions(+), 50 deletions(-) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index f64bbc79cbd..f0e5b5fde3d 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -1092,3 +1092,24 @@ FROM t3; 2 NULL DROP TABLE t1, t2, t3; +# +# Bug #42760: Select doesn't return desired results when we have null +# values +# +CREATE TABLE t1 ( +a INT, +c INT, +UNIQUE KEY a_c (a,c), +KEY (a)); +INSERT INTO t1 VALUES (1, 10), (2, NULL); +# Must use ref-or-null on the a_c index +EXPLAIN +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref_or_null a_c,a a_c 10 const,const 1 Using where +# Must return 1 row +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c; +col +1 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 6d7ee1c1ca7..d9a6c0f844d 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -756,3 +756,29 @@ SELECT FROM t3; DROP TABLE t1, t2, t3; + + + +--echo # +--echo # Bug #42760: Select doesn't return desired results when we have null +--echo # values +--echo # + +CREATE TABLE t1 ( + a INT, + c INT, + UNIQUE KEY a_c (a,c), + KEY (a)); + +INSERT INTO t1 VALUES (1, 10), (2, NULL); + +--echo # Must use ref-or-null on the a_c index +EXPLAIN +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c; +--echo # Must return 1 row +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c; + +DROP TABLE t1; + + +--echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1ee31c788ff..f7c1fcec2a4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6202,6 +6202,56 @@ void rr_unlock_row(st_join_table *tab) +/** + Pick the appropriate access method functions + + Sets the functions for the selected table access method + + @param tab Table reference to put access method +*/ + +static void +pick_table_access_method(JOIN_TAB *tab) +{ + switch (tab->type) + { + case JT_REF: + tab->read_first_record= join_read_always_key; + tab->read_record.read_record= join_read_next_same; + break; + + case JT_REF_OR_NULL: + tab->read_first_record= join_read_always_key_or_null; + tab->read_record.read_record= join_read_next_same_or_null; + break; + + case JT_CONST: + tab->read_first_record= join_read_const; + tab->read_record.read_record= join_no_more_records; + break; + + case JT_EQ_REF: + tab->read_first_record= join_read_key; + tab->read_record.read_record= join_no_more_records; + break; + + case JT_FT: + tab->read_first_record= join_ft_read_first; + tab->read_record.read_record= join_ft_read_next; + break; + + case JT_SYSTEM: + tab->read_first_record= join_read_system; + tab->read_record.read_record= join_no_more_records; + break; + + /* keep gcc happy */ + default: + break; + } +} + + static void make_join_readinfo(JOIN *join, ulonglong options) { @@ -6234,45 +6284,15 @@ make_join_readinfo(JOIN *join, ulonglong options) (join->sort_by_table == (TABLE *) 1 && i != join->const_tables))) ordered_set= 1; + table->status=STATUS_NO_RECORD; + pick_table_access_method (tab); + switch (tab->type) { - case JT_SYSTEM: // Only happens with left join - table->status=STATUS_NO_RECORD; - tab->read_first_record= join_read_system; - tab->read_record.read_record= join_no_more_records; - break; - case JT_CONST: // Only happens with left join - table->status=STATUS_NO_RECORD; - tab->read_first_record= join_read_const; - tab->read_record.read_record= join_no_more_records; - if (table->used_keys.is_set(tab->ref.key) && - !table->no_keyread) - { - table->key_read=1; - table->file->extra(HA_EXTRA_KEYREAD); - } - break; case JT_EQ_REF: - table->status=STATUS_NO_RECORD; - if (tab->select) - { - delete tab->select->quick; - tab->select->quick=0; - } - delete tab->quick; - tab->quick=0; - tab->read_first_record= join_read_key; tab->read_record.unlock_row= join_read_key_unlock_row; - tab->read_record.read_record= join_no_more_records; - if (table->used_keys.is_set(tab->ref.key) && - !table->no_keyread) - { - table->key_read=1; - table->file->extra(HA_EXTRA_KEYREAD); - } - break; + /* fall through */ case JT_REF_OR_NULL: case JT_REF: - table->status=STATUS_NO_RECORD; if (tab->select) { delete tab->select->quick; @@ -6280,34 +6300,20 @@ make_join_readinfo(JOIN *join, ulonglong options) } delete tab->quick; tab->quick=0; + /* fall through */ + case JT_CONST: // Only happens with left join if (table->used_keys.is_set(tab->ref.key) && !table->no_keyread) { table->key_read=1; table->file->extra(HA_EXTRA_KEYREAD); } - if (tab->type == JT_REF) - { - tab->read_first_record= join_read_always_key; - tab->read_record.read_record= join_read_next_same; - } - else - { - tab->read_first_record= join_read_always_key_or_null; - tab->read_record.read_record= join_read_next_same_or_null; - } - break; - case JT_FT: - table->status=STATUS_NO_RECORD; - tab->read_first_record= join_ft_read_first; - tab->read_record.read_record= join_ft_read_next; break; case JT_ALL: /* If previous table use cache If the incoming data set is already sorted don't use cache. */ - table->status=STATUS_NO_RECORD; if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) && tab->use_quick != 2 && !tab->first_inner && !ordered_set) { @@ -6381,6 +6387,9 @@ make_join_readinfo(JOIN *join, ulonglong options) } } break; + case JT_FT: + case JT_SYSTEM: + break; default: DBUG_PRINT("error",("Table type %d found",tab->type)); /* purecov: deadcode */ break; /* purecov: deadcode */ @@ -12753,6 +12762,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, if (create_ref_for_key(tab->join, tab, keyuse, tab->join->const_table_map)) DBUG_RETURN(0); + + pick_table_access_method(tab); } else { From 4519d5e4f1ce1c9081f711d88d7508f58453d219 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 9 Nov 2009 16:09:46 +0200 Subject: [PATCH 027/344] Bug #48458: simple query tries to allocate enormous amount of memory The server was doing a bad class typecast causing setting of wrong value for the maximum number of items in an internal structure used in equality propagation. Fixed by not doing the wrong typecast and asserting the type of the Item where it should be done. --- mysql-test/r/select.result | 14 ++++++++++++++ mysql-test/t/select.test | 13 +++++++++++++ sql/sql_select.cc | 10 +++++----- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 5d07c97149f..ff59eadab0c 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4442,4 +4442,18 @@ ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1)) INTO @var0; ERROR 21000: Subquery returns more than 1 row DROP TABLE t1; +# +# Bug #48458: simple query tries to allocate enormous amount of +# memory +# +CREATE TABLE t1(a INT NOT NULL, b YEAR); +INSERT INTO t1 VALUES (); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +CREATE TABLE t2(c INT); +# Should not err out because of out-of-memory +SELECT 1 FROM t2 JOIN t1 ON 1=1 +WHERE a != '1' AND NOT a >= b OR NOT ROW(b,a )<> ROW(a,a); +1 +DROP TABLE t1,t2; End of 5.0 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index ceb67215614..a4d3056b66e 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3783,5 +3783,18 @@ INTO @var0; DROP TABLE t1; +--echo # +--echo # Bug #48458: simple query tries to allocate enormous amount of +--echo # memory +--echo # + +CREATE TABLE t1(a INT NOT NULL, b YEAR); +INSERT INTO t1 VALUES (); +CREATE TABLE t2(c INT); +--echo # Should not err out because of out-of-memory +SELECT 1 FROM t2 JOIN t1 ON 1=1 + WHERE a != '1' AND NOT a >= b OR NOT ROW(b,a )<> ROW(a,a); +DROP TABLE t1,t2; + --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f7c1fcec2a4..768bbc3478d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7535,12 +7535,12 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond, { item_equal->fix_length_and_dec(); item_equal->update_used_tables(); + set_if_bigger(thd->lex->current_select->max_equal_elems, + item_equal->members()); + return item_equal; } - else - item_equal= (Item_equal *) eq_list.pop(); - set_if_bigger(thd->lex->current_select->max_equal_elems, - item_equal->members()); - return item_equal; + + return eq_list.pop(); } else { From 46ca22b093406d566d8f108f55111fc70b49af80 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 9 Nov 2009 17:36:13 +0000 Subject: [PATCH 028/344] BUG#48357: SHOW BINLOG EVENTS: Wrong offset or I/O error In function log_event.cc:Query_log_event::write, there was a cast that was triggering undefined behavior. The offending cast is the following: write_str_with_code_and_len((char **)(&start), catalog, catalog_len, Q_CATALOG_NZ_CODE); This results in calling write_str_with_code_and_len with first argument pointing to a (char **) while "start" is itself a pointer to uchar (uchar *). Inside write_str_with_..., the content of start is then be updated: (*dst)+= len; The instruction above would cause the (*dst) pointer (ie, the "start" argument, from the caller point of view, and which actually points to uchar instead of pointing to char) to be updated so that it would increment catalog_len. However, this seems to break strict-aliasing rules ultimately causing the increment and assignment to behave unexpectedly. We fix this by removing the cast and by making the types match. --- sql/log_event.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 2cb253c9c56..9a3c6537b9e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2138,8 +2138,8 @@ void Query_log_event::pack_info(Protocol *protocol) /** Utility function for the next method (Query_log_event::write()) . */ -static void write_str_with_code_and_len(char **dst, const char *src, - int len, uint code) +static void write_str_with_code_and_len(uchar **dst, const char *src, + uint len, uint code) { /* only 1 byte to store the length of catalog, so it should not @@ -2234,7 +2234,7 @@ bool Query_log_event::write(IO_CACHE* file) } if (catalog_len) // i.e. this var is inited (false for 4.0 events) { - write_str_with_code_and_len((char **)(&start), + write_str_with_code_and_len(&start, catalog, catalog_len, Q_CATALOG_NZ_CODE); /* In 5.0.x where x<4 masters we used to store the end zero here. This was @@ -2272,7 +2272,7 @@ bool Query_log_event::write(IO_CACHE* file) { /* In the TZ sys table, column Name is of length 64 so this should be ok */ DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH); - write_str_with_code_and_len((char **)(&start), + write_str_with_code_and_len(&start, time_zone_str, time_zone_len, Q_TIME_ZONE_CODE); } if (lc_time_names_number) From c7b07ff0cb0a84b147752efc7cf8e19f474578a7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Nov 2009 19:22:35 +0100 Subject: [PATCH 029/344] Raise version number after cloning 5.0.88 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 11c97e517ba..e14b4014bea 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.0.88) +AM_INIT_AUTOMAKE(mysql, 5.0.89) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=88 +NDB_VERSION_BUILD=89 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From ac3a08c3d2517c6af9827554cb98a245ce52bd8c Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Mon, 9 Nov 2009 23:28:31 +0100 Subject: [PATCH 030/344] Bug#46043 mysqld --skip-innodb does not skip InnoDB The prefix --skip- didn't work on 64 bit big endian machines because of how the value pointer was casted. mysys/my_getopt.c: * Use the interface! The value pointer must correspond to the type mask or it will break on big endian platforms. --- mysys/my_getopt.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 5e81dbf2ee2..e561d74f4d1 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -413,17 +413,17 @@ invalid value '%s'", else if (optp->arg_type == OPT_ARG && (((optp->var_type & GET_TYPE_MASK) == GET_BOOL) || (optp->var_type & GET_TYPE_MASK) == GET_ENUM)) - { - if (optend == disabled_my_option) - *((my_bool*) value)= (my_bool) 0; - else - { - if (!optend) /* No argument -> enable option */ - *((my_bool*) value)= (my_bool) 1; - else - argument= optend; - } - } + { + if (optend == disabled_my_option) + init_one_value(optp, value, 0); + else + { + if (!optend) /* No argument -> enable option */ + init_one_value(optp, value, 1); + else + argument= optend; + } + } else if (optp->arg_type == REQUIRED_ARG && !optend) { /* Check if there are more arguments after this one */ From b97dacce925fd8c3565846768555f76b4a44f85d Mon Sep 17 00:00:00 2001 From: Aleksandr Kuzminsky Date: Mon, 9 Nov 2009 15:54:33 -0800 Subject: [PATCH 031/344] Sync with rev. 118 --- mysql-test/patches/information_schema.diff | 110 ++++-------------- mysql-test/patches/information_schema_db.diff | 24 ++++ mysql-test/patches/mysqlshow.diff | 46 ++++++++ 3 files changed, 93 insertions(+), 87 deletions(-) create mode 100644 mysql-test/patches/information_schema_db.diff create mode 100644 mysql-test/patches/mysqlshow.diff diff --git a/mysql-test/patches/information_schema.diff b/mysql-test/patches/information_schema.diff index 4c6359700a6..38111fbbe98 100644 --- a/mysql-test/patches/information_schema.diff +++ b/mysql-test/patches/information_schema.diff @@ -1,6 +1,6 @@ ---- mysql-test/r/information_schema.result.orig 2009-07-14 08:44:24.000000000 +0900 -+++ mysql-test/r/information_schema.result 2009-09-07 16:42:01.000000000 +0900 -@@ -71,6 +71,20 @@ +--- mysql-test/r/information_schema.result.orig 2009-11-09 11:19:50.000000000 -0800 ++++ mysql-test/r/information_schema.result 2009-11-09 11:21:21.000000000 -0800 +@@ -71,6 +71,21 @@ TRIGGERS USER_PRIVILEGES VIEWS @@ -10,18 +10,19 @@ +INNODB_BUFFER_POOL_PAGES +XTRADB_ENHANCEMENTS +INNODB_TRX -+INNODB_INDEX_STATS ++XTRADB_ADMIN_COMMAND +INNODB_LOCK_WAITS +INNODB_CMP_RESET +INNODB_CMP +INNODB_CMPMEM_RESET -+INNODB_BUFFER_POOL_PAGES_BLOB -+INNODB_CMPMEM +INNODB_TABLE_STATS ++INNODB_CMPMEM ++INNODB_INDEX_STATS ++INNODB_BUFFER_POOL_PAGES_BLOB columns_priv db event -@@ -799,6 +813,8 @@ +@@ -799,6 +814,8 @@ TABLES UPDATE_TIME datetime TABLES CHECK_TIME datetime TRIGGERS CREATED datetime @@ -30,24 +31,24 @@ event execute_at datetime event last_executed datetime event starts datetime -@@ -847,12 +863,15 @@ +@@ -847,12 +864,15 @@ TABLE_CONSTRAINTS TABLE_NAME select TABLE_PRIVILEGES TABLE_NAME select VIEWS TABLE_NAME select +INNODB_BUFFER_POOL_PAGES_INDEX table_name select -+INNODB_INDEX_STATS table_name select +INNODB_TABLE_STATS table_name select ++INNODB_INDEX_STATS table_name select delete from mysql.user where user='mysqltest_4'; delete from mysql.db where user='mysqltest_4'; flush privileges; SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA; table_schema count(*) -information_schema 28 -+information_schema 42 ++information_schema 43 mysql 22 create table t1 (i int, j int); create trigger trg1 before insert on t1 for each row -@@ -1267,6 +1286,20 @@ +@@ -1267,6 +1287,21 @@ TRIGGERS TRIGGER_SCHEMA USER_PRIVILEGES GRANTEE VIEWS TABLE_SCHEMA @@ -57,18 +58,19 @@ +INNODB_BUFFER_POOL_PAGES page_type +XTRADB_ENHANCEMENTS name +INNODB_TRX trx_id -+INNODB_INDEX_STATS table_name ++XTRADB_ADMIN_COMMAND result_message +INNODB_LOCK_WAITS requesting_trx_id +INNODB_CMP_RESET page_size +INNODB_CMP page_size +INNODB_CMPMEM_RESET page_size -+INNODB_BUFFER_POOL_PAGES_BLOB space_id -+INNODB_CMPMEM page_size +INNODB_TABLE_STATS table_name ++INNODB_CMPMEM page_size ++INNODB_INDEX_STATS table_name ++INNODB_BUFFER_POOL_PAGES_BLOB space_id SELECT t.table_name, c1.column_name FROM information_schema.tables t INNER JOIN -@@ -1310,14 +1343,28 @@ +@@ -1310,14 +1345,29 @@ TRIGGERS TRIGGER_SCHEMA USER_PRIVILEGES GRANTEE VIEWS TABLE_SCHEMA @@ -78,14 +80,15 @@ +INNODB_BUFFER_POOL_PAGES page_type +XTRADB_ENHANCEMENTS name +INNODB_TRX trx_id -+INNODB_INDEX_STATS table_name ++XTRADB_ADMIN_COMMAND result_message +INNODB_LOCK_WAITS requesting_trx_id +INNODB_CMP_RESET page_size +INNODB_CMP page_size +INNODB_CMPMEM_RESET page_size -+INNODB_BUFFER_POOL_PAGES_BLOB space_id -+INNODB_CMPMEM page_size +INNODB_TABLE_STATS table_name ++INNODB_CMPMEM page_size ++INNODB_INDEX_STATS table_name ++INNODB_BUFFER_POOL_PAGES_BLOB space_id SELECT MAX(table_name) FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test'); MAX(table_name) -VIEWS @@ -99,7 +102,7 @@ DROP TABLE IF EXISTS bug23037; DROP FUNCTION IF EXISTS get_value; SELECT COLUMN_NAME, MD5(COLUMN_DEFAULT), LENGTH(COLUMN_DEFAULT) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='bug23037'; -@@ -1386,6 +1433,19 @@ +@@ -1386,6 +1436,19 @@ FILES information_schema.FILES 1 GLOBAL_STATUS information_schema.GLOBAL_STATUS 1 GLOBAL_VARIABLES information_schema.GLOBAL_VARIABLES 1 @@ -119,7 +122,7 @@ KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1 PARTITIONS information_schema.PARTITIONS 1 PLUGINS information_schema.PLUGINS 1 -@@ -1404,6 +1464,7 @@ +@@ -1404,6 +1467,7 @@ TRIGGERS information_schema.TRIGGERS 1 USER_PRIVILEGES information_schema.USER_PRIVILEGES 1 VIEWS information_schema.VIEWS 1 @@ -127,70 +130,3 @@ create table t1(f1 int); create view v1 as select f1+1 as a from t1; create table t2 (f1 int, f2 int); ---- mysql-test/r/information_schema_db.result.orig 2009-07-14 08:44:24.000000000 +0900 -+++ mysql-test/r/information_schema_db.result 2009-09-07 16:42:26.000000000 +0900 -@@ -33,6 +33,20 @@ - TRIGGERS - USER_PRIVILEGES - VIEWS -+INNODB_BUFFER_POOL_PAGES_INDEX -+INNODB_RSEG -+INNODB_LOCKS -+INNODB_BUFFER_POOL_PAGES -+XTRADB_ENHANCEMENTS -+INNODB_TRX -+INNODB_INDEX_STATS -+INNODB_LOCK_WAITS -+INNODB_CMP_RESET -+INNODB_CMP -+INNODB_CMPMEM_RESET -+INNODB_BUFFER_POOL_PAGES_BLOB -+INNODB_CMPMEM -+INNODB_TABLE_STATS - show tables from INFORMATION_SCHEMA like 'T%'; - Tables_in_information_schema (T%) - TABLES ---- mysql-test/r/mysqlshow.result.orig 2009-07-14 08:44:28.000000000 +0900 -+++ mysql-test/r/mysqlshow.result 2009-09-07 16:42:52.000000000 +0900 -@@ -107,6 +107,20 @@ - | TRIGGERS | - | USER_PRIVILEGES | - | VIEWS | -+| INNODB_BUFFER_POOL_PAGES_INDEX | -+| INNODB_RSEG | -+| INNODB_LOCKS | -+| INNODB_BUFFER_POOL_PAGES | -+| XTRADB_ENHANCEMENTS | -+| INNODB_TRX | -+| INNODB_INDEX_STATS | -+| INNODB_LOCK_WAITS | -+| INNODB_CMP_RESET | -+| INNODB_CMP | -+| INNODB_CMPMEM_RESET | -+| INNODB_BUFFER_POOL_PAGES_BLOB | -+| INNODB_CMPMEM | -+| INNODB_TABLE_STATS | - +---------------------------------------+ - Database: INFORMATION_SCHEMA - +---------------------------------------+ -@@ -140,6 +154,20 @@ - | TRIGGERS | - | USER_PRIVILEGES | - | VIEWS | -+| INNODB_BUFFER_POOL_PAGES_INDEX | -+| INNODB_RSEG | -+| INNODB_LOCKS | -+| INNODB_BUFFER_POOL_PAGES | -+| XTRADB_ENHANCEMENTS | -+| INNODB_TRX | -+| INNODB_INDEX_STATS | -+| INNODB_LOCK_WAITS | -+| INNODB_CMP_RESET | -+| INNODB_CMP | -+| INNODB_CMPMEM_RESET | -+| INNODB_BUFFER_POOL_PAGES_BLOB | -+| INNODB_CMPMEM | -+| INNODB_TABLE_STATS | - +---------------------------------------+ - Wildcard: inf_rmation_schema - +--------------------+ diff --git a/mysql-test/patches/information_schema_db.diff b/mysql-test/patches/information_schema_db.diff new file mode 100644 index 00000000000..1f93612b318 --- /dev/null +++ b/mysql-test/patches/information_schema_db.diff @@ -0,0 +1,24 @@ +--- mysql-test/r/information_schema_db.result.orig 2009-11-09 14:40:34.000000000 -0800 ++++ mysql-test/r/information_schema_db.result 2009-11-09 14:41:37.000000000 -0800 +@@ -33,6 +33,21 @@ + TRIGGERS + USER_PRIVILEGES + VIEWS ++INNODB_BUFFER_POOL_PAGES_INDEX ++INNODB_RSEG ++INNODB_LOCKS ++INNODB_BUFFER_POOL_PAGES ++XTRADB_ENHANCEMENTS ++INNODB_TRX ++XTRADB_ADMIN_COMMAND ++INNODB_LOCK_WAITS ++INNODB_CMP_RESET ++INNODB_CMP ++INNODB_CMPMEM_RESET ++INNODB_TABLE_STATS ++INNODB_CMPMEM ++INNODB_INDEX_STATS ++INNODB_BUFFER_POOL_PAGES_BLOB + show tables from INFORMATION_SCHEMA like 'T%'; + Tables_in_information_schema (T%) + TABLES diff --git a/mysql-test/patches/mysqlshow.diff b/mysql-test/patches/mysqlshow.diff new file mode 100644 index 00000000000..78965e75da4 --- /dev/null +++ b/mysql-test/patches/mysqlshow.diff @@ -0,0 +1,46 @@ +--- mysql-test/r/mysqlshow.result.orig 2009-11-09 15:17:43.000000000 -0800 ++++ mysql-test/r/mysqlshow.result 2009-11-09 15:17:53.000000000 -0800 +@@ -107,6 +107,21 @@ + | TRIGGERS | + | USER_PRIVILEGES | + | VIEWS | ++| INNODB_BUFFER_POOL_PAGES_INDEX | ++| INNODB_RSEG | ++| INNODB_LOCKS | ++| INNODB_BUFFER_POOL_PAGES | ++| XTRADB_ENHANCEMENTS | ++| INNODB_TRX | ++| XTRADB_ADMIN_COMMAND | ++| INNODB_LOCK_WAITS | ++| INNODB_CMP_RESET | ++| INNODB_CMP | ++| INNODB_CMPMEM_RESET | ++| INNODB_TABLE_STATS | ++| INNODB_CMPMEM | ++| INNODB_INDEX_STATS | ++| INNODB_BUFFER_POOL_PAGES_BLOB | + +---------------------------------------+ + Database: INFORMATION_SCHEMA + +---------------------------------------+ +@@ -140,6 +155,21 @@ + | TRIGGERS | + | USER_PRIVILEGES | + | VIEWS | ++| INNODB_BUFFER_POOL_PAGES_INDEX | ++| INNODB_RSEG | ++| INNODB_LOCKS | ++| INNODB_BUFFER_POOL_PAGES | ++| XTRADB_ENHANCEMENTS | ++| INNODB_TRX | ++| XTRADB_ADMIN_COMMAND | ++| INNODB_LOCK_WAITS | ++| INNODB_CMP_RESET | ++| INNODB_CMP | ++| INNODB_CMPMEM_RESET | ++| INNODB_TABLE_STATS | ++| INNODB_CMPMEM | ++| INNODB_INDEX_STATS | ++| INNODB_BUFFER_POOL_PAGES_BLOB | + +---------------------------------------+ + Wildcard: inf_rmation_schema + +--------------------+ From e0cb24c3c7fb10ba68c3dcbd4f3274edcc01ecf3 Mon Sep 17 00:00:00 2001 From: Christopher Powers Date: Tue, 10 Nov 2009 13:41:43 -0600 Subject: [PATCH 032/344] Bug#47382 'mysqladmin debug' crash on 64-bit Windows The crash occurs because SAFEMALLOC is defined for the MySQL server but not for the Archive or Federated engines, resulting in a parameter mismatch between the function prototype and definition for functions using the CALLER_INFO macro. storage/archive/CMakeLists.txt: Set SAFEMALLOC by default to be consistent with the server. storage/federated/CMakeLists.txt: Set SAFEMALLOC by default to be consistent with the server. --- storage/archive/CMakeLists.txt | 3 +++ storage/federated/CMakeLists.txt | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) mode change 100644 => 100755 storage/archive/CMakeLists.txt mode change 100644 => 100755 storage/federated/CMakeLists.txt diff --git a/storage/archive/CMakeLists.txt b/storage/archive/CMakeLists.txt old mode 100644 new mode 100755 index ce4d92d3f99..f4492c3ce77 --- a/storage/archive/CMakeLists.txt +++ b/storage/archive/CMakeLists.txt @@ -13,6 +13,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") SET(ARCHIVE_SOURCES azio.c ha_archive.cc ha_archive.h) MYSQL_STORAGE_ENGINE(ARCHIVE) diff --git a/storage/federated/CMakeLists.txt b/storage/federated/CMakeLists.txt old mode 100644 new mode 100755 index fa54d36481a..d371c0fc02b --- a/storage/federated/CMakeLists.txt +++ b/storage/federated/CMakeLists.txt @@ -1,18 +1,21 @@ # Copyright (C) 2006 MySQL AB -# +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") SET(FEDERATED_SOURCES ha_federated.cc) MYSQL_STORAGE_ENGINE(FEDERATED) From c87375150b922526f9699aee86614481ac711ad0 Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Wed, 11 Nov 2009 13:33:29 +0530 Subject: [PATCH 033/344] Bug #47012 archive tables are not upgradeable, and server crashes on any access Archive engine for 5.1 (and latter) version uses a modified version of zlib (azlib). These two version are incompatible so a proper upgrade is needed before tables created in 5.0 can be used reliable. This upgrade can be performed using repair. But due to lack of test its risky to allow upgrade for now. This patch addresses only the crashing issue. Any attempt to repair will be blocked. Eventually repair can be allowed to run through (which will also cause an upgrade from older version to newer) but only after a thorough testing. mysql-test/r/archive.result: Updated result file for test case for bug#47012 mysql-test/std_data/bug47012.ARM: part of archive table (t1) created in mysql 5.0 mysql-test/std_data/bug47012.ARZ: part of archive table (t1) created in mysql 5.0 mysql-test/std_data/bug47012.frm: part of archive table (t1) created in mysql 5.0 mysql-test/t/archive.test: Added test case for bug#47012. storage/archive/azio.c: Fixed a minor issues (minor version overwriting version in stream structure) Removed assertion when an older version is found. Instead setting the correct version (2) in s->version If an unknown version is found marked it as corrupt. storage/archive/ha_archive.cc: Detecting the archive version in getShare and marking it as need to upgrade. Blocking open if the archive needs an upgrade. This can be allowed in case of open for repair to upgrade the archive but needs to tested. --- mysql-test/r/archive.result | 11 +++++++++++ mysql-test/std_data/bug47012.ARM | Bin 0 -> 19 bytes mysql-test/std_data/bug47012.ARZ | Bin 0 -> 22 bytes mysql-test/std_data/bug47012.frm | Bin 0 -> 8590 bytes mysql-test/t/archive.test | 21 +++++++++++++++++++++ storage/archive/azio.c | 17 +++++++++++++---- storage/archive/ha_archive.cc | 16 +++++++++++++++- 7 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 mysql-test/std_data/bug47012.ARM create mode 100644 mysql-test/std_data/bug47012.ARZ create mode 100644 mysql-test/std_data/bug47012.frm diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index e865d775c6a..c620eb97cab 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -12717,3 +12717,14 @@ COUNT(t1.a) 729 DROP TABLE t1; SET @@join_buffer_size= @save_join_buffer_size; +SHOW CREATE TABLE t1; +ERROR HY000: Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! +SELECT * FROM t1; +ERROR HY000: Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! +INSERT INTO t1 (col1, col2) VALUES (1, "value"); +ERROR HY000: Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair Error Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! +test.t1 repair error Corrupt +DROP TABLE t1; diff --git a/mysql-test/std_data/bug47012.ARM b/mysql-test/std_data/bug47012.ARM new file mode 100644 index 0000000000000000000000000000000000000000..86bbaf829d22ee058861f931dae20197622b040c GIT binary patch literal 19 Lcmeyz$bb$268`}J literal 0 HcmV?d00001 diff --git a/mysql-test/std_data/bug47012.ARZ b/mysql-test/std_data/bug47012.ARZ new file mode 100644 index 0000000000000000000000000000000000000000..f2aa19ffea67065ff063620cb31f822785e61579 GIT binary patch literal 22 Zcmb2|=3oE==HJIT7^2=i+`|Oq0suAJ1!n*N literal 0 HcmV?d00001 diff --git a/mysql-test/std_data/bug47012.frm b/mysql-test/std_data/bug47012.frm new file mode 100644 index 0000000000000000000000000000000000000000..6c0a535cce7cd14adb9e554ed62e94177d2c109d GIT binary patch literal 8590 zcmeI&Jqp4=5QgC|8`r-GrU(|X(ALVI6DT5RCl+47R`3d*z;k#H?`51VvbL6r?-ZGt zkFbQN%|4TEo=SNl&8(?ZEZ0^?@?me+VQ$0yA!T(iol4_+p(B6*0tg_000IagfB*sr zAb`Nv3OH5q+ul=*;?UCSu-@*Do0u>lfB*srAbP3gW29}3fDs`@yj6Wtransparent = 0; s->mode = 'r'; s->version = (unsigned char)az_magic[1]; /* this needs to be a define to version */ - s->version = (unsigned char)az_magic[2]; /* minor version */ + s->minor_version= (unsigned char) az_magic[2]; /* minor version */ /* We do our own version of append by nature. @@ -352,10 +352,19 @@ void read_header(azio_stream *s, unsigned char *buffer) s->comment_length= (unsigned int)uint4korr(buffer + AZ_COMMENT_LENGTH_POS); s->dirty= (unsigned int)buffer[AZ_DIRTY_POS]; } - else + else if (buffer[0] == gz_magic[0] && buffer[1] == gz_magic[1]) { - DBUG_ASSERT(buffer[0] == az_magic[0] && buffer[1] == az_magic[1]); - return; + /* + Set version number to previous version (2). + */ + s->version= (unsigned char) 2; + } else { + /* + Unknown version. + Most probably due to a corrupt archive. + */ + s->dirty= AZ_STATE_DIRTY; + s->z_err= Z_VERSION_ERROR; } } diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 6fa8333c1b7..4648ca798da 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -360,6 +360,12 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc) stats.auto_increment_value= archive_tmp.auto_increment + 1; share->rows_recorded= (ha_rows)archive_tmp.rows; share->crashed= archive_tmp.dirty; + /* + If archive version is less than 3, It should be upgraded before + use. + */ + if (archive_tmp.version < ARCHIVE_VERSION) + *rc= HA_ERR_TABLE_NEEDS_UPGRADE; azclose(&archive_tmp); VOID(my_hash_insert(&archive_open_tables, (uchar*) share)); @@ -491,7 +497,15 @@ int ha_archive::open(const char *name, int mode, uint open_options) (open_options & HA_OPEN_FOR_REPAIR) ? "yes" : "no")); share= get_share(name, &rc); - if (rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR)) + /* + Allow open on crashed table in repair mode only. + Block open on 5.0 ARCHIVE table. Though we have almost all + routines to access these tables, they were not well tested. + For now we have to refuse to open such table to avoid + potential data loss. + */ + if ((rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR)) + || rc == HA_ERR_TABLE_NEEDS_UPGRADE) { /* purecov: begin inspected */ free_share(); From 552965eff927dff2f0248169e5c0510ef3783ccf Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Thu, 12 Nov 2009 12:43:33 +0100 Subject: [PATCH 034/344] Bug #37183 insert ignore into .. select ... hangs after deadlock was encountered The bug is caused by an inconsistent handling of the IGNORE clause. A read from a const table caused a lock timeout (ER_LOCK_TIMEOUT) in innodb. Since the IGNORE clause was given, the timeout was converted into a warning instead of an error, thus not populating the diagnostics area. When innodb subsequently marked the transaction for rollback, mysql asserted since the diag.area was empty. This patch consists of only a test case, as the bug itself was fixed by the patch for Bug #46539 --- .../r/innodb_lock_wait_timeout_1.result | 18 ++++++++++ mysql-test/t/innodb_lock_wait_timeout_1.test | 34 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/mysql-test/r/innodb_lock_wait_timeout_1.result b/mysql-test/r/innodb_lock_wait_timeout_1.result index a635b0d527a..bd8760b8f79 100644 --- a/mysql-test/r/innodb_lock_wait_timeout_1.result +++ b/mysql-test/r/innodb_lock_wait_timeout_1.result @@ -48,6 +48,24 @@ commit; set autocommit=default; drop table t1; # +# Bug #37183 insert ignore into .. select ... hangs +# after deadlock was encountered +# +create table t1(id int primary key,v int)engine=innodb; +insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7); +create table t2 like t1; +begin; +update t1 set v=id*2 where id=1; +begin; +update t1 set v=id*2 where id=2; +update t1 set v=id*2 where id=2; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +insert ignore into t2 select * from t1 where id=1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +rollback; +rollback; +drop table t1, t2; +# # Bug#41756 Strange error messages about locks from InnoDB # drop table if exists t1; diff --git a/mysql-test/t/innodb_lock_wait_timeout_1.test b/mysql-test/t/innodb_lock_wait_timeout_1.test index e42e9f3e37c..fcbf2b1cfc7 100644 --- a/mysql-test/t/innodb_lock_wait_timeout_1.test +++ b/mysql-test/t/innodb_lock_wait_timeout_1.test @@ -70,6 +70,40 @@ commit; set autocommit=default; drop table t1; +--echo # +--echo # Bug #37183 insert ignore into .. select ... hangs +--echo # after deadlock was encountered +--echo # +connect (con1,localhost,root,,); +create table t1(id int primary key,v int)engine=innodb; +insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7); +create table t2 like t1; + +--connection con1 +begin; +update t1 set v=id*2 where id=1; + +--connection default +begin; +update t1 set v=id*2 where id=2; + +--connection con1 +--error 1205 +update t1 set v=id*2 where id=2; + +--connection default +--error 1205 +insert ignore into t2 select * from t1 where id=1; +rollback; + +--connection con1 +rollback; + +--connection default +disconnect con1; +drop table t1, t2; + + --echo # --echo # Bug#41756 Strange error messages about locks from InnoDB --echo # From f1abd015dcec3c1347e96e6197db8fd05c021537 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Thu, 12 Nov 2009 17:10:19 +0200 Subject: [PATCH 035/344] Bug #47210 first execution of "start slave until" stops too early Until-pos guarding did not distiguish the master originated events from ones that the slave can introduce to the relay log e.g Rotate to the next relay log at slave restarting. The local Rotate's coordinate are incomparable with the Until-master-pos. That led to the unexpectable stop this bug describes. Fixed with to avoid Until-master-pos comparison for a local slave's event. Notice that if --replicate-same-server is true such event is treated as coming from the master side. mysql-test/r/rpl_until.result: results changed. mysql-test/t/rpl_until.test: regression test for bug#47210 is added. sql/slave.cc: st_relay_log_info::is_until_satisfied() is augmented with avoidance of Until-master-pos comparison for a local slave's event. if --replicate-same-server is true such event is treated as coming from the master side. sql/slave.h: signature of is_until_satisfied() changed to supply THD and Event to the routine. --- mysql-test/r/rpl_until.result | 28 +++++++++++++++ mysql-test/t/rpl_until.test | 65 ++++++++++++++++++++++++++++++++++- sql/slave.cc | 14 ++++---- sql/slave.h | 2 +- 4 files changed, 101 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index 60b956785ba..3dac55ec5c1 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -194,3 +194,31 @@ start slave sql_thread; start slave until master_log_file='master-bin.000001', master_log_pos=776; Warnings: Note 1254 Slave is already running +include/stop_slave.inc +drop table if exists t1; +reset slave; +change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; +drop table if exists t1; +reset master; +create table t1 (a int primary key auto_increment); +start slave; +include/stop_slave.inc +master and slave are in sync now +select 0 as zero; +zero +0 +insert into t1 set a=null; +insert into t1 set a=null; +select count(*) as two from t1; +two +2 +start slave until master_log_file='master-bin.000001', master_log_pos= UNTIL_POS;; +slave stopped at the prescribed position +select 0 as zero; +zero +0 +select count(*) as one from t1; +one +1 +drop table t1; +start slave; diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index c404ea7e58b..abd78b6a005 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -84,4 +84,67 @@ start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561; start slave sql_thread; start slave until master_log_file='master-bin.000001', master_log_pos=776; -# End of 4.1 tests +# +# bug#47210 first execution of "start slave until" stops too early +# +# testing that a slave rotate event that is caused by stopping the slave +# does not intervene anymore in UNTIL condition. +# + +connection slave; +source include/stop_slave.inc; +--disable_warnings +drop table if exists t1; +--enable_warnings +reset slave; +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; + +connection master; +--disable_warnings +drop table if exists t1; +--enable_warnings +reset master; +create table t1 (a int primary key auto_increment); +save_master_pos; +let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1); + +connection slave; +start slave; +sync_with_master; + +# at this point slave will close the relay log stamping it with its own +# Rotate log event. This event won't be examined on matter of the master +# UNTIL pos anymore. +source include/stop_slave.inc; +let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); + +--echo master and slave are in sync now +let $diff_pos= `select $master_pos - $slave_exec_pos`; +eval select $diff_pos as zero; + +connection master; +insert into t1 set a=null; +let $until_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +insert into t1 set a=null; +select count(*) as two from t1; + +connection slave; +--replace_result $until_pos UNTIL_POS; +eval start slave until master_log_file='master-bin.000001', master_log_pos= $until_pos; +source include/wait_for_slave_sql_to_stop.inc; +let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); +--echo slave stopped at the prescribed position +let $diff_pos= `select $until_pos - $slave_exec_pos`; +eval select $diff_pos as zero; +select count(*) as one from t1; + + +connection master; +drop table t1; + +connection slave; +start slave; +sync_with_master; + +# End of tests diff --git a/sql/slave.cc b/sql/slave.cc index dd29a3f45c9..87bd7e2be8c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3223,7 +3223,7 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error) false - condition not met */ -bool st_relay_log_info::is_until_satisfied(my_off_t master_beg_pos) +bool st_relay_log_info::is_until_satisfied(THD *thd, Log_event *ev) { const char *log_name; ulonglong log_pos; @@ -3232,8 +3232,12 @@ bool st_relay_log_info::is_until_satisfied(my_off_t master_beg_pos) if (until_condition == UNTIL_MASTER_POS) { + if (ev && ev->server_id == (uint32) ::server_id && !replicate_same_server_id) + return FALSE; log_name= group_master_log_name; - log_pos= master_beg_pos; + log_pos= (!ev)? group_master_log_pos : + ((thd->options & OPTION_BEGIN || !ev->log_pos) ? + group_master_log_pos : ev->log_pos - ev->data_written); } else { /* until_condition == UNTIL_RELAY_POS */ @@ -3333,9 +3337,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) hits the UNTIL barrier. */ if (rli->until_condition != RELAY_LOG_INFO::UNTIL_NONE && - rli->is_until_satisfied((thd->options & OPTION_BEGIN || !ev->log_pos) ? - rli->group_master_log_pos : - ev->log_pos - ev->data_written)) + rli->is_until_satisfied(thd, ev)) { char buf[22]; sql_print_information("Slave SQL thread stopped because it reached its" @@ -4065,7 +4067,7 @@ Slave SQL thread aborted. Can't execute init_slave query"); */ pthread_mutex_lock(&rli->data_lock); if (rli->until_condition != RELAY_LOG_INFO::UNTIL_NONE && - rli->is_until_satisfied(rli->group_master_log_pos)) + rli->is_until_satisfied(thd, NULL)) { char buf[22]; sql_print_information("Slave SQL thread stopped because it reached its" diff --git a/sql/slave.h b/sql/slave.h index 5ae596f1eb5..78627214eef 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -348,7 +348,7 @@ typedef struct st_relay_log_info void close_temporary_tables(); /* Check if UNTIL condition is satisfied. See slave.cc for more. */ - bool is_until_satisfied(my_off_t master_beg_pos); + bool is_until_satisfied(THD *thd, Log_event *ev); inline ulonglong until_pos() { return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : From fb2e17903fe51094a083e4eceabd9857c6090ce8 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Thu, 12 Nov 2009 20:11:33 +0300 Subject: [PATCH 036/344] Fixed a gcc warning introduced by the patch for bug #48475. --- sql/sql_select.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1ee31c788ff..483f9f6e2e3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1229,7 +1229,7 @@ JOIN::optimize() ((select_distinct || !simple_order || !simple_group) || (group_list && order) || test(select_options & OPTION_BUFFER_RESULT))) || - rollup.state != ROLLUP::STATE_NONE && select_distinct); + (rollup.state != ROLLUP::STATE_NONE && select_distinct)); // No cache for MATCH make_join_readinfo(this, From 356b3df7430a46b3472682a827e357b3f7482257 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 12 Nov 2009 23:03:26 -0200 Subject: [PATCH 037/344] Bug#47627 SET @@{global.session}.local_variable in stored routine causes crash This patch borrows ideas, text and code from Kristofer Pettersson's patch. An assignment of a system variable sharing the same base name as a declared stored procedure variable in the same context could lead to a crash. The reason was that during the parsing of the syntactic rule 'option_value' an uninitialized set_var object was pushed to the parameter stack of the SET statement. The parent rule 'option_type_value' interpreted the existence of variables on the parameter stack as an assignment and wrapped it in a sp_instr_set object. As the procedure later was executed an attempt was made to run the method 'check()' on an uninitialized member object (NULL value) belonging to the previously created but uninitialized object. This patch refactors the 'internal_variable_name' rule and copies the semantic analysis part to the depending parent rule: 'option_value'. This makes it possible to account for any prefixes affecting the interpretation of the internal_variable_name. mysql-test/r/sp.result: Add test case result. mysql-test/t/sp.test: Add test case for bug. sql/sql_yacc.yy: - Reduce churn in rule sys_option_value by moving to specialized functions. - Comment the the lookup in the rule internel_variable_name is a best effort operation. - Lookup for a system variable in the option_value if one was not found (the variable could have been shadowed) --- mysql-test/r/sp.result | 58 ++++++++++ mysql-test/t/sp.test | 67 +++++++++++ sql/sql_yacc.yy | 252 +++++++++++++++++++++++++++-------------- 3 files changed, 289 insertions(+), 88 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 67514c314f4..83ad7545685 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6979,6 +6979,64 @@ CALL p1; ERROR 42S22: Unknown column 'A.b' in 'IN/ALL/ANY subquery' DROP PROCEDURE p1; DROP TABLE t1, t2; +# +# Bug#47627: SET @@{global.session}.local_variable in stored routine causes crash +# Bug#48626: Crash or lost connection using SET for declared variables with @@ +# +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +CREATE PROCEDURE p1() +BEGIN +DECLARE v INT DEFAULT 0; +SET @@SESSION.v= 10; +END// +ERROR HY000: Unknown system variable 'v' +CREATE PROCEDURE p2() +BEGIN +DECLARE v INT DEFAULT 0; +SET v= 10; +END// +call p2()// +CREATE PROCEDURE p3() +BEGIN +DECLARE v INT DEFAULT 0; +SELECT @@SESSION.v; +END// +ERROR HY000: Unknown system variable 'v' +CREATE PROCEDURE p4() +BEGIN +DECLARE v INT DEFAULT 0; +SET @@GLOBAL.v= 10; +END// +ERROR HY000: Unknown system variable 'v' +CREATE PROCEDURE p5() +BEGIN +DECLARE init_connect INT DEFAULT 0; +SET init_connect= 10; +SET @@GLOBAL.init_connect= 'SELECT 1'; +SET @@SESSION.IDENTITY= 1; +SELECT @@SESSION.IDENTITY; +SELECT @@GLOBAL.init_connect; +SELECT init_connect; +END// +CREATE PROCEDURE p6() +BEGIN +DECLARE v INT DEFAULT 0; +SET @@v= 0; +END// +ERROR HY000: Unknown system variable 'v' +SET @old_init_connect= @@GLOBAL.init_connect; +CALL p5(); +@@SESSION.IDENTITY +1 +@@GLOBAL.init_connect +SELECT 1 +init_connect +10 +SET @@GLOBAL.init_connect= @old_init_connect; +DROP PROCEDURE p2; +DROP PROCEDURE p5; # ------------------------------------------------------------------ # -- End of 5.1 tests # ------------------------------------------------------------------ diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 44c4556340e..73ba62612b8 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -8263,6 +8263,73 @@ CALL p1; DROP PROCEDURE p1; DROP TABLE t1, t2; +--echo # +--echo # Bug#47627: SET @@{global.session}.local_variable in stored routine causes crash +--echo # Bug#48626: Crash or lost connection using SET for declared variables with @@ +--echo # + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +--enable_warnings + +delimiter //; + +--error ER_UNKNOWN_SYSTEM_VARIABLE +CREATE PROCEDURE p1() +BEGIN + DECLARE v INT DEFAULT 0; + SET @@SESSION.v= 10; +END// + +CREATE PROCEDURE p2() +BEGIN + DECLARE v INT DEFAULT 0; + SET v= 10; +END// +call p2()// + +--error ER_UNKNOWN_SYSTEM_VARIABLE +CREATE PROCEDURE p3() +BEGIN + DECLARE v INT DEFAULT 0; + SELECT @@SESSION.v; +END// + +--error ER_UNKNOWN_SYSTEM_VARIABLE +CREATE PROCEDURE p4() +BEGIN + DECLARE v INT DEFAULT 0; + SET @@GLOBAL.v= 10; +END// + +CREATE PROCEDURE p5() +BEGIN + DECLARE init_connect INT DEFAULT 0; + SET init_connect= 10; + SET @@GLOBAL.init_connect= 'SELECT 1'; + SET @@SESSION.IDENTITY= 1; + SELECT @@SESSION.IDENTITY; + SELECT @@GLOBAL.init_connect; + SELECT init_connect; +END// + +--error ER_UNKNOWN_SYSTEM_VARIABLE +CREATE PROCEDURE p6() +BEGIN + DECLARE v INT DEFAULT 0; + SET @@v= 0; +END// + +delimiter ;// + +SET @old_init_connect= @@GLOBAL.init_connect; +CALL p5(); +SET @@GLOBAL.init_connect= @old_init_connect; + +DROP PROCEDURE p2; +DROP PROCEDURE p5; --echo # ------------------------------------------------------------------ --echo # -- End of 5.1 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 86bef83cf1a..b0f45fe845a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -389,6 +389,138 @@ void case_stmt_action_end_case(LEX *lex, bool simple) lex->sphead->do_cont_backpatch(); } + +static bool +find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp) +{ + tmp->var= find_sys_var(thd, tmp->base_name.str, tmp->base_name.length); + + if (tmp->var == NULL) + my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), tmp->base_name.str); + else + tmp->base_name= null_lex_str; + + return thd->is_error(); +} + + +/** + Helper action for a SET statement. + Used to push a system variable into the assignment list. + + @param thd the current thread + @param tmp the system variable with base name + @param var_type the scope of the variable + @param val the value being assigned to the variable + + @return TRUE if error, FALSE otherwise. +*/ + +static bool +set_system_variable(THD *thd, struct sys_var_with_base *tmp, + enum enum_var_type var_type, Item *val) +{ + set_var *var; + LEX *lex= thd->lex; + + /* No AUTOCOMMIT from a stored function or trigger. */ + if (lex->spcont && tmp->var == &sys_autocommit) + lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; + + if (! (var= new set_var(var_type, tmp->var, &tmp->base_name, val))) + return TRUE; + + return lex->var_list.push_back(var); +} + + +/** + Helper action for a SET statement. + Used to push a SP local variable into the assignment list. + + @param thd the current thread + @param var_type the SP local variable + @param val the value being assigned to the variable + + @return TRUE if error, FALSE otherwise. +*/ + +static bool +set_local_variable(THD *thd, sp_variable_t *spv, Item *val) +{ + Item *it; + LEX *lex= thd->lex; + sp_instr_set *sp_set; + + if (val) + it= val; + else if (spv->dflt) + it= spv->dflt; + else + { + it= new (thd->mem_root) Item_null(); + if (it == NULL) + return TRUE; + } + + sp_set= new sp_instr_set(lex->sphead->instructions(), lex->spcont, + spv->offset, it, spv->type, lex, TRUE); + + return (sp_set == NULL || lex->sphead->add_instr(sp_set)); +} + + +/** + Helper action for a SET statement. + Used to SET a field of NEW row. + + @param thd the current thread + @param name the field name + @param val the value being assigned to the row + + @return TRUE if error, FALSE otherwise. +*/ + +static bool +set_trigger_new_row(THD *thd, LEX_STRING *name, Item *val) +{ + LEX *lex= thd->lex; + Item_trigger_field *trg_fld; + sp_instr_set_trigger_field *sp_fld; + + /* QQ: Shouldn't this be field's default value ? */ + if (! val) + val= new Item_null(); + + DBUG_ASSERT(lex->trg_chistics.action_time == TRG_ACTION_BEFORE && + (lex->trg_chistics.event == TRG_EVENT_INSERT || + lex->trg_chistics.event == TRG_EVENT_UPDATE)); + + trg_fld= new (thd->mem_root) + Item_trigger_field(lex->current_context(), + Item_trigger_field::NEW_ROW, + name->str, UPDATE_ACL, FALSE); + + if (trg_fld == NULL) + return TRUE; + + sp_fld= new sp_instr_set_trigger_field(lex->sphead->instructions(), + lex->spcont, trg_fld, val, lex); + + if (sp_fld == NULL) + return TRUE; + + /* + Let us add this item to list of all Item_trigger_field + objects in trigger. + */ + lex->trg_table_fields.link_in_list((uchar *) trg_fld, + (uchar **) &trg_fld->next_trg_field); + + return lex->sphead->add_instr(sp_fld); +} + + /** Helper to resolve the SQL:2003 Syntax exception 1) in . See SQL:2003, Part 2, section 8.4 , Note 184, page 383. @@ -11809,98 +11941,42 @@ sys_option_value: option_type internal_variable_name equal set_expr_or_default { THD *thd= YYTHD; - LEX *lex=Lex; + LEX *lex= Lex; + LEX_STRING *name= &$2.base_name; if ($2.var == trg_new_row_fake_var) { /* We are in trigger and assigning value to field of new row */ - Item *it; - Item_trigger_field *trg_fld; - sp_instr_set_trigger_field *sp_fld; - LINT_INIT(sp_fld); if ($1) { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; } - if ($4) - it= $4; - else - { - /* QQ: Shouldn't this be field's default value ? */ - it= new Item_null(); - } - - DBUG_ASSERT(lex->trg_chistics.action_time == TRG_ACTION_BEFORE && - (lex->trg_chistics.event == TRG_EVENT_INSERT || - lex->trg_chistics.event == TRG_EVENT_UPDATE)); - - trg_fld= new (thd->mem_root) - Item_trigger_field(Lex->current_context(), - Item_trigger_field::NEW_ROW, - $2.base_name.str, - UPDATE_ACL, FALSE); - if (trg_fld == NULL) - MYSQL_YYABORT; - - sp_fld= new sp_instr_set_trigger_field(lex->sphead-> - instructions(), - lex->spcont, - trg_fld, - it, lex); - if (sp_fld == NULL) - MYSQL_YYABORT; - - /* - Let us add this item to list of all Item_trigger_field - objects in trigger. - */ - lex->trg_table_fields.link_in_list((uchar *)trg_fld, - (uchar **) &trg_fld-> - next_trg_field); - - if (lex->sphead->add_instr(sp_fld)) + if (set_trigger_new_row(YYTHD, name, $4)) MYSQL_YYABORT; } else if ($2.var) - { /* System variable */ + { if ($1) lex->option_type= $1; - set_var *var= new set_var(lex->option_type, $2.var, - &$2.base_name, $4); - if (var == NULL) + + /* It is a system variable. */ + if (set_system_variable(thd, &$2, lex->option_type, $4)) MYSQL_YYABORT; - lex->var_list.push_back(var); } else { - /* An SP local variable */ - sp_pcontext *ctx= lex->spcont; - sp_variable_t *spv; - sp_instr_set *sp_set; - Item *it; + sp_pcontext *spc= lex->spcont; + sp_variable_t *spv= spc->find_variable(name); + if ($1) { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; } - spv= ctx->find_variable(&$2.base_name); - - if ($4) - it= $4; - else if (spv->dflt) - it= spv->dflt; - else - { - it= new (thd->mem_root) Item_null(); - if (it == NULL) - MYSQL_YYABORT; - } - sp_set= new sp_instr_set(lex->sphead->instructions(), ctx, - spv->offset, it, spv->type, lex, TRUE); - if (sp_set == NULL || - lex->sphead->add_instr(sp_set)) + /* It is a local variable. */ + if (set_local_variable(thd, spv, $4)) MYSQL_YYABORT; } } @@ -11936,11 +12012,16 @@ option_value: } | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default { - LEX *lex=Lex; - set_var *var= new set_var($3, $4.var, &$4.base_name, $6); - if (var == NULL) + THD *thd= YYTHD; + struct sys_var_with_base tmp= $4; + /* Lookup if necessary: must be a system variable. */ + if (tmp.var == NULL) + { + if (find_sys_var_null_base(thd, &tmp)) + MYSQL_YYABORT; + } + if (set_system_variable(thd, &tmp, $3, $6)) MYSQL_YYABORT; - lex->var_list.push_back(var); } | charset old_or_new_charset_name_or_default { @@ -12033,31 +12114,26 @@ internal_variable_name: ident { THD *thd= YYTHD; - LEX *lex= thd->lex; - sp_pcontext *spc= lex->spcont; + sp_pcontext *spc= thd->lex->spcont; sp_variable_t *spv; - /* We have to lookup here since local vars can shadow sysvars */ + /* Best effort lookup for system variable. */ if (!spc || !(spv = spc->find_variable(&$1))) { + struct sys_var_with_base tmp= {NULL, $1}; + /* Not an SP local variable */ - sys_var *tmp=find_sys_var(thd, $1.str, $1.length); - if (!tmp) + if (find_sys_var_null_base(thd, &tmp)) MYSQL_YYABORT; - $$.var= tmp; - $$.base_name= null_lex_str; - if (spc && tmp == &sys_autocommit) - { - /* - We don't allow setting AUTOCOMMIT from a stored function - or trigger. - */ - lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; - } + + $$= tmp; } else { - /* An SP local variable */ + /* + Possibly an SP local variable (or a shadowed sysvar). + Will depend on the context of the SET statement. + */ $$.var= NULL; $$.base_name= $1; } From 9c23a442b257c0ddb9066930c7bf9b0aac6cacdd Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Fri, 13 Nov 2009 10:30:56 +0000 Subject: [PATCH 038/344] BUG#48738: Backport patch for Bug 34582 to 5.0 codebase. From BUG 34582 commit message: Issuing 'FLUSH LOGS' does not close and reopen indexfile. Instead a SEEK_SET is performed. This patch makes index file to be closed and reopened whenever a rotation happens (FLUSH LOGS is issued or binary log exceeds maximum configured size). --- .../r/binlog_delete_and_flush_index.result | 44 +++++ .../t/binlog_delete_and_flush_index.test | 176 ++++++++++++++++++ sql/log.cc | 10 +- 3 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 mysql-test/r/binlog_delete_and_flush_index.result create mode 100644 mysql-test/t/binlog_delete_and_flush_index.test diff --git a/mysql-test/r/binlog_delete_and_flush_index.result b/mysql-test/r/binlog_delete_and_flush_index.result new file mode 100644 index 00000000000..153900f3081 --- /dev/null +++ b/mysql-test/r/binlog_delete_and_flush_index.result @@ -0,0 +1,44 @@ +RESET MASTER; +CREATE TABLE t1 (a int); +### assertion: index file contains regular entries +SET @index=LOAD_FILE('MYSQLD_DATADIR/master-bin.index'); +master-bin.000001 + +### assertion: show original binlogs +show binary logs; +Log_name File_size +master-bin.000001 # +### assertion: binlog contents from regular entries +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a int) +FLUSH LOGS; +### assertion: index file contains renamed binlog and the new one +SET @index=LOAD_FILE('MYSQLD_DATADIR/master-bin.index'); +master-bin-b34582.000001 +master-bin.000002 + +### assertion: original binlog content still exists, despite we +### renamed and changed the index file +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin-b34582.000001 # Query # # use `test`; CREATE TABLE t1 (a int) +### assertion: user changed binlog index shows correct entries +show binary logs; +Log_name File_size +master-bin-b34582.000001 # +master-bin.000002 # +DROP TABLE t1; +### assertion: purging binlogs up to binlog created after instrumenting index file should work +PURGE BINARY LOGS TO 'master-bin.000002'; +### assertion: show binary logs should only contain latest binlog +show binary logs; +Log_name File_size +master-bin.000002 # +### assertion: assert that binlog files were indeed purged (using file_exists calls) +### assertion: assert that not purged binlog file exists +### assertion: show index file contents and these should match show binary logs issued above +SET @index=LOAD_FILE('MYSQLD_DATADIR/master-bin.index'); +master-bin.000002 + +RESET MASTER; diff --git a/mysql-test/t/binlog_delete_and_flush_index.test b/mysql-test/t/binlog_delete_and_flush_index.test new file mode 100644 index 00000000000..6784043386d --- /dev/null +++ b/mysql-test/t/binlog_delete_and_flush_index.test @@ -0,0 +1,176 @@ +# BUG#34582: FLUSH LOGS does not close and reopen the binlog index +# file +# +# WHAT +# ==== +# +# We want to test that FLUSH LOGS closes and reopens binlog index +# file. +# +# HOW +# === +# +# PREPARE: +# 1. create some binlog events +# 2. show index content, binlog events and binlog contents +# for mysql-bin.000001 +# 3. copy the mysql-bin.000001 to mysql-bin-b34582.000001 +# 4. change the index file so that mysql-bin.000001 is replaced +# with mysql-bin-b34582.000001 +# 5. FLUSH the logs so that new index is closed and reopened +# +# ASSERTIONS: +# 1. index file contents shows mysql-bin-b34582.000001 and +# mysql-bin.000002 +# 1. show binary logs shows current index entries +# 2. binlog contents for mysql-bin-b34582.000001 are displayed +# 3. Purge binlogs up to the latest one succeeds +# 4. SHOW BINARY LOGS presents the latest one only after purging +# 5. Purged binlogs files don't exist in the filesystem +# 6. Not purged binlog file exists in the filesystem +# +# CLEAN UP: +# 1. RESET MASTER +# + +-- source include/have_log_bin.inc + +RESET MASTER; + +-- let $datadir= $MYSQLTEST_VARDIR/log +-- let $index=$datadir/master-bin.index +-- chmod 0666 $index + +# action: issue one command so that binlog gets some event +CREATE TABLE t1 (a int); + +-- echo ### assertion: index file contains regular entries +-- replace_regex /[\\\/].*master/MYSQLD_DATADIR\/master/ +-- eval SET @index=LOAD_FILE('$index') +if (`SELECT convert(@@version_compile_os using latin1) + IN ('Win32','Win64','Windows')`) +{ + -- disable_query_log + -- disable_result_log + -- let $a= `SELECT REPLACE (@index, '$datadir\', '')` + -- enable_result_log + -- enable_query_log + + -- echo $a + +} +if (!`SELECT convert(@@version_compile_os using latin1) + IN ('Win32','Win64','Windows')`) +{ + -- disable_query_log + -- disable_result_log + -- let $a= `SELECT REPLACE (@index, '$datadir/', '')` + -- enable_result_log + -- enable_query_log + + -- echo $a +} + +--echo ### assertion: show original binlogs +-- source include/show_binary_logs.inc + +--echo ### assertion: binlog contents from regular entries +-- source include/show_binlog_events.inc + +# action: copy binlogs to other names and change entries in index file +-- copy_file $datadir/master-bin.000001 $datadir/master-bin-b34582.000001 +-- let newbinfile=$datadir/master-bin-b34582.000001 +let INDEX_FILE=$index; +perl; +$newbinfile= $ENV{'newbinfile'}; +$file= $ENV{'INDEX_FILE'}; +open(FILE, ">$file") || die "Unable to open $file."; +truncate(FILE,0); +print FILE $newbinfile . "\n"; +close ($file); +EOF + +# action: should cause rotation, and creation of new binlogs +FLUSH LOGS; + +# file is not used anymore - remove it (mysql closed on flush logs). +-- remove_file $datadir/master-bin.000001 + +-- echo ### assertion: index file contains renamed binlog and the new one +-- replace_regex /[\\\/].*master/MYSQLD_DATADIR\/master/ +-- eval SET @index=LOAD_FILE('$index') +if (`SELECT convert(@@version_compile_os using latin1) + IN ('Win32','Win64','Windows')`) +{ + -- disable_query_log + -- disable_result_log + -- let $a= `SELECT REPLACE (@index, '$datadir\', '')` + -- enable_result_log + -- enable_query_log + + -- echo $a + +} +if (!`SELECT convert(@@version_compile_os using latin1) + IN ('Win32','Win64','Windows')`) +{ + -- disable_query_log + -- disable_result_log + -- let $a= `SELECT REPLACE (@index, '$datadir/', '')` + -- enable_result_log + -- enable_query_log + + -- echo $a +} + +-- echo ### assertion: original binlog content still exists, despite we +-- echo ### renamed and changed the index file +-- source include/show_binlog_events.inc + +-- echo ### assertion: user changed binlog index shows correct entries +-- source include/show_binary_logs.inc + +DROP TABLE t1; + +-- echo ### assertion: purging binlogs up to binlog created after instrumenting index file should work +-- let $current_binlog= query_get_value(SHOW MASTER STATUS, File, 1) +-- eval PURGE BINARY LOGS TO '$current_binlog' + +-- echo ### assertion: show binary logs should only contain latest binlog +-- source include/show_binary_logs.inc + +-- echo ### assertion: assert that binlog files were indeed purged (using file_exists calls) +-- error 1 +-- file_exists $datadir/master-bin-b34852.000001 + +-- echo ### assertion: assert that not purged binlog file exists +-- file_exists $datadir/$current_binlog + +-- echo ### assertion: show index file contents and these should match show binary logs issued above +-- replace_regex /[\\\/].*master/MYSQLD_DATADIR\/master/ +-- eval SET @index=LOAD_FILE('$index') +if (`SELECT convert(@@version_compile_os using latin1) + IN ('Win32','Win64','Windows')`) +{ + -- disable_query_log + -- disable_result_log + -- let $a= `SELECT REPLACE (@index, '$datadir\', '')` + -- enable_result_log + -- enable_query_log + + -- echo $a + +} +if (!`SELECT convert(@@version_compile_os using latin1) + IN ('Win32','Win64','Windows')`) +{ + -- disable_query_log + -- disable_result_log + -- let $a= `SELECT REPLACE (@index, '$datadir/', '')` + -- enable_result_log + -- enable_query_log + + -- echo $a +} + +RESET MASTER; diff --git a/sql/log.cc b/sql/log.cc index c042651216c..8c0abaeff44 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1635,7 +1635,7 @@ void MYSQL_LOG::new_file(bool need_lock) old_name=name; save_log_type=log_type; name=0; // Don't free name - close(LOG_CLOSE_TO_BE_OPENED); + close(LOG_CLOSE_TO_BE_OPENED | LOG_CLOSE_INDEX); /* Note that at this point, log_type != LOG_CLOSED (important for is_open()). @@ -1649,9 +1649,11 @@ void MYSQL_LOG::new_file(bool need_lock) Format_description_log_event written at server startup, which should trigger temp tables deletion on slaves. */ - - open(old_name, save_log_type, new_name_ptr, - io_cache_type, no_auto_events, max_size, 1); + + /* reopen index binlog file, BUG#34582 */ + if (!open_index_file(index_file_name, 0)) + open(old_name, save_log_type, new_name_ptr, + io_cache_type, no_auto_events, max_size, 1); my_free(old_name,MYF(0)); end: From a120e969a83128f075b54a06155ccee0bb46b312 Mon Sep 17 00:00:00 2001 From: Jorgen Loland Date: Fri, 13 Nov 2009 12:22:39 +0100 Subject: [PATCH 039/344] Bug#48052: Valgrind warning - uninitialized value in init_read_record() - (records.cc:274) Item_cond::used_tables_cache was accessed in records.cc#init_read_record() without being initialized. It had not been initialized because it was wrongly assumed that the Item's variables would not be accessed, and hence quick_fix_field() was used instead of fix_fields() to save a few CPU cycles at creation time. The fix is to properly initilize the Item by replacing quick_fix_field() with fix_fields(). mysql-test/r/select.result: Add test for BUG#48052 mysql-test/t/select.test: Add test for BUG#48052 sql/sql_select.cc: Properly initialize Item_cond_and by calling fix_fields (instead of quick_fix_field) when the Item that "ANDs" WHERE clause conditions with HAVING clause conditions is created. --- mysql-test/r/select.result | 18 ++++++++++++++++++ mysql-test/t/select.test | 33 +++++++++++++++++++++++++++++++++ sql/sql_select.cc | 8 ++------ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index e528b63ddb7..d0b2a575a32 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4591,4 +4591,22 @@ field2 15:13:38 drop table A,AA,B,BB; #end of test for bug#45266 +# +# BUG#48052: Valgrind warning - uninitialized value in init_read_record() +# +CREATE TABLE t1 ( +pk int(11) NOT NULL, +i int(11) DEFAULT NULL, +v varchar(1) DEFAULT NULL, +PRIMARY KEY (pk) +); +INSERT INTO t1 VALUES (2,7,'m'); +INSERT INTO t1 VALUES (3,9,'m'); +SELECT v +FROM t1 +WHERE NOT pk > 0 +HAVING v <= 't' +ORDER BY pk; +v +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 7502f451b69..ac65e5cbaf5 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3931,4 +3931,37 @@ SELECT table1 .`time_key` field2 FROM B table1 LEFT JOIN BB JOIN A table5 ON drop table A,AA,B,BB; --echo #end of test for bug#45266 + +--echo # +--echo # BUG#48052: Valgrind warning - uninitialized value in init_read_record() +--echo # + +# Needed in 6.0 codebase +#--echo # Disable Index condition pushdown +#--replace_column 1 # +#SELECT @old_icp:=@@engine_condition_pushdown; +#SET SESSION engine_condition_pushdown = 'OFF'; + +CREATE TABLE t1 ( + pk int(11) NOT NULL, + i int(11) DEFAULT NULL, + v varchar(1) DEFAULT NULL, + PRIMARY KEY (pk) +); + +INSERT INTO t1 VALUES (2,7,'m'); +INSERT INTO t1 VALUES (3,9,'m'); + +SELECT v +FROM t1 +WHERE NOT pk > 0 +HAVING v <= 't' +ORDER BY pk; + +# Needed in 6.0 codebase +#--echo # Restore old value for Index condition pushdown +#SET SESSION engine_condition_pushdown=@old_icp; + +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7a4ab1c8365..00080b9b9d9 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2131,17 +2131,13 @@ JOIN::exec() DBUG_VOID_RETURN; if (!curr_table->select->cond) curr_table->select->cond= sort_table_cond; - else // This should never happen + else { if (!(curr_table->select->cond= new Item_cond_and(curr_table->select->cond, sort_table_cond))) DBUG_VOID_RETURN; - /* - Item_cond_and do not need fix_fields for execution, its parameters - are fixed or do not need fix_fields, too - */ - curr_table->select->cond->quick_fix_field(); + curr_table->select->cond->fix_fields(thd, 0); } curr_table->select_cond= curr_table->select->cond; curr_table->select_cond->top_level_item(); From c4584fc6d40a6a673e7a46750b575effddef6207 Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Tue, 17 Nov 2009 17:44:27 +0530 Subject: [PATCH 040/344] fix for pb2 failure after bug#47012 push. --- storage/archive/azio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/archive/azio.c b/storage/archive/azio.c index 603e328c715..c1dd6e6f38c 100644 --- a/storage/archive/azio.c +++ b/storage/archive/azio.c @@ -70,6 +70,7 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd) s->mode = 'r'; s->version = (unsigned char)az_magic[1]; /* this needs to be a define to version */ s->minor_version= (unsigned char) az_magic[2]; /* minor version */ + s->dirty= AZ_STATE_CLEAN; /* We do our own version of append by nature. From bc43bff7edf79095c243cf6858acb29213fb152b Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Tue, 17 Nov 2009 17:06:46 +0300 Subject: [PATCH 041/344] Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) MySQL manual describes values of the YEAR(2) field type as follows: values 00 - 69 mean 2000 - 2069 years and values 70 - 99 mean 1970 - 1999 years. MIN/MAX and comparison functions was comparing them as int values thus producing wrong result. Now the Arg_comparator class is extended with compare_year function which performs correct comparison of the YEAR type. The Item_sum_hybrid class now uses Item_cache and Arg_comparator objects to correctly calculate its value. To allow Arg_comparator to use func_name() function for Item_func and Item_sum objects the func_name declaration is moved to the Item_result_field class. A helper function is_owner_equal_func is added to the Arg_comparator class. It checks whether the Arg_comparator object owner is the <=> function or not. A helper function setup is added to the Item_sum_hybrid class. It sets up cache item and comparator. mysql-test/r/func_group.result: Added a test case for the bug#43668. mysql-test/t/func_group.test: Added a test case for the bug#43668. sql/item.cc: Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) Now Item_cache_int returns the type of cached item. sql/item.h: Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) To allow Arg_comparator to use func_name() function for Item_func and Item_sum objects the func_name declaration is moved to the Item_result_field class. sql/item_cmpfunc.cc: Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) The Arg_comparator class is extended with compare_year function which performs correct comparison of the YEAR type. sql/item_cmpfunc.h: Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) The year_as_datetime variable is added to the Arg_comparator class. It's set to TRUE when YEAR value should be converted to the YYYY-00-00 00:00:00 format for correct YEAR-DATETIME comparison. sql/item_geofunc.cc: Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) Item_func_spatial_rel::val_int chenged to use Arg_comparator's string buffers. sql/item_subselect.h: Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) Added an implementation of the virtual func_name function. sql/item_sum.cc: Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) The Item_sum_hybrid class now uses Item_cache and Arg_comparator objects to correctly calculate its value. A helper function setup is added to the Item_sum_hybrid class. It sets up cache item and comparator. sql/item_sum.h: Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) The Item_sum_hybrid class now uses Item_cache and Arg_comparator objects to correctly calculate its value. Added an implementation of the virtual func_name function. --- mysql-test/r/func_group.result | 195 ++++++++++++++++++++++- mysql-test/t/func_group.test | 32 ++++ sql/item.cc | 2 +- sql/item.h | 17 ++ sql/item_cmpfunc.cc | 275 ++++++++++++++++++++++++-------- sql/item_cmpfunc.h | 43 +++-- sql/item_func.h | 11 -- sql/item_geofunc.cc | 4 +- sql/item_subselect.h | 1 + sql/item_sum.cc | 283 +++++++-------------------------- sql/item_sum.h | 37 ++--- 11 files changed, 560 insertions(+), 340 deletions(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 3d989ad1730..b0877991367 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -885,7 +885,7 @@ cast(sum(distinct df) as signed) 3 select cast(min(df) as signed) from t1; cast(min(df) as signed) -0 +1 select 1e8 * sum(distinct df) from t1; 1e8 * sum(distinct df) 330000000 @@ -1477,3 +1477,196 @@ COUNT(*) SET SQL_MODE=default; DROP TABLE t1; End of 5.0 tests +# +# Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) +# +create table t1 (f1 year(2), f2 year(4), f3 date, f4 datetime); +insert into t1 values +(98,1998,19980101,"1998-01-01 00:00:00"), +(00,2000,20000101,"2000-01-01 00:00:01"), +(02,2002,20020101,"2002-01-01 23:59:59"), +(60,2060,20600101,"2060-01-01 11:11:11"), +(70,1970,19700101,"1970-11-11 22:22:22"), +(NULL,NULL,NULL,NULL); +select min(f1),max(f1) from t1; +min(f1) max(f1) +70 60 +select min(f2),max(f2) from t1; +min(f2) max(f2) +1970 2060 +select min(f3),max(f3) from t1; +min(f3) max(f3) +1970-01-01 2060-01-01 +select min(f4),max(f4) from t1; +min(f4) max(f4) +1970-11-11 22:22:22 2060-01-01 11:11:11 +select a.f1 as a, b.f1 as b, a.f1 > b.f1 as gt, +a.f1 < b.f1 as lt, a.f1<=>b.f1 as eq +from t1 a, t1 b; +a b gt lt eq +98 98 0 0 1 +00 98 1 0 0 +02 98 1 0 0 +60 98 1 0 0 +70 98 0 1 0 +NULL 98 NULL NULL 0 +98 00 0 1 0 +00 00 0 0 1 +02 00 1 0 0 +60 00 1 0 0 +70 00 0 1 0 +NULL 00 NULL NULL 0 +98 02 0 1 0 +00 02 0 1 0 +02 02 0 0 1 +60 02 1 0 0 +70 02 0 1 0 +NULL 02 NULL NULL 0 +98 60 0 1 0 +00 60 0 1 0 +02 60 0 1 0 +60 60 0 0 1 +70 60 0 1 0 +NULL 60 NULL NULL 0 +98 70 1 0 0 +00 70 1 0 0 +02 70 1 0 0 +60 70 1 0 0 +70 70 0 0 1 +NULL 70 NULL NULL 0 +98 NULL NULL NULL 0 +00 NULL NULL NULL 0 +02 NULL NULL NULL 0 +60 NULL NULL NULL 0 +70 NULL NULL NULL 0 +NULL NULL NULL NULL 1 +select a.f1 as a, b.f2 as b, a.f1 > b.f2 as gt, +a.f1 < b.f2 as lt, a.f1<=>b.f2 as eq +from t1 a, t1 b; +a b gt lt eq +98 1998 0 0 1 +00 1998 1 0 0 +02 1998 1 0 0 +60 1998 1 0 0 +70 1998 0 1 0 +NULL 1998 NULL NULL 0 +98 2000 0 1 0 +00 2000 0 0 1 +02 2000 1 0 0 +60 2000 1 0 0 +70 2000 0 1 0 +NULL 2000 NULL NULL 0 +98 2002 0 1 0 +00 2002 0 1 0 +02 2002 0 0 1 +60 2002 1 0 0 +70 2002 0 1 0 +NULL 2002 NULL NULL 0 +98 2060 0 1 0 +00 2060 0 1 0 +02 2060 0 1 0 +60 2060 0 0 1 +70 2060 0 1 0 +NULL 2060 NULL NULL 0 +98 1970 1 0 0 +00 1970 1 0 0 +02 1970 1 0 0 +60 1970 1 0 0 +70 1970 0 0 1 +NULL 1970 NULL NULL 0 +98 NULL NULL NULL 0 +00 NULL NULL NULL 0 +02 NULL NULL NULL 0 +60 NULL NULL NULL 0 +70 NULL NULL NULL 0 +NULL NULL NULL NULL 1 +select a.f1 as a, b.f3 as b, a.f1 > b.f3 as gt, +a.f1 < b.f3 as lt, a.f1<=>b.f3 as eq +from t1 a, t1 b; +a b gt lt eq +98 1998-01-01 0 1 0 +00 1998-01-01 1 0 0 +02 1998-01-01 1 0 0 +60 1998-01-01 1 0 0 +70 1998-01-01 0 1 0 +NULL 1998-01-01 NULL NULL 0 +98 2000-01-01 0 1 0 +00 2000-01-01 0 1 0 +02 2000-01-01 1 0 0 +60 2000-01-01 1 0 0 +70 2000-01-01 0 1 0 +NULL 2000-01-01 NULL NULL 0 +98 2002-01-01 0 1 0 +00 2002-01-01 0 1 0 +02 2002-01-01 0 1 0 +60 2002-01-01 1 0 0 +70 2002-01-01 0 1 0 +NULL 2002-01-01 NULL NULL 0 +98 2060-01-01 0 1 0 +00 2060-01-01 0 1 0 +02 2060-01-01 0 1 0 +60 2060-01-01 0 1 0 +70 2060-01-01 0 1 0 +NULL 2060-01-01 NULL NULL 0 +98 1970-01-01 1 0 0 +00 1970-01-01 1 0 0 +02 1970-01-01 1 0 0 +60 1970-01-01 1 0 0 +70 1970-01-01 0 1 0 +NULL 1970-01-01 NULL NULL 0 +98 NULL NULL NULL 0 +00 NULL NULL NULL 0 +02 NULL NULL NULL 0 +60 NULL NULL NULL 0 +70 NULL NULL NULL 0 +NULL NULL NULL NULL 1 +select a.f1 as a, b.f4 as b, a.f1 > b.f4 as gt, +a.f1 < b.f4 as lt, a.f1<=>b.f4 as eq +from t1 a, t1 b; +a b gt lt eq +98 1998-01-01 00:00:00 0 1 0 +00 1998-01-01 00:00:00 1 0 0 +02 1998-01-01 00:00:00 1 0 0 +60 1998-01-01 00:00:00 1 0 0 +70 1998-01-01 00:00:00 0 1 0 +NULL 1998-01-01 00:00:00 NULL NULL 0 +98 2000-01-01 00:00:01 0 1 0 +00 2000-01-01 00:00:01 0 1 0 +02 2000-01-01 00:00:01 1 0 0 +60 2000-01-01 00:00:01 1 0 0 +70 2000-01-01 00:00:01 0 1 0 +NULL 2000-01-01 00:00:01 NULL NULL 0 +98 2002-01-01 23:59:59 0 1 0 +00 2002-01-01 23:59:59 0 1 0 +02 2002-01-01 23:59:59 0 1 0 +60 2002-01-01 23:59:59 1 0 0 +70 2002-01-01 23:59:59 0 1 0 +NULL 2002-01-01 23:59:59 NULL NULL 0 +98 2060-01-01 11:11:11 0 1 0 +00 2060-01-01 11:11:11 0 1 0 +02 2060-01-01 11:11:11 0 1 0 +60 2060-01-01 11:11:11 0 1 0 +70 2060-01-01 11:11:11 0 1 0 +NULL 2060-01-01 11:11:11 NULL NULL 0 +98 1970-11-11 22:22:22 1 0 0 +00 1970-11-11 22:22:22 1 0 0 +02 1970-11-11 22:22:22 1 0 0 +60 1970-11-11 22:22:22 1 0 0 +70 1970-11-11 22:22:22 0 1 0 +NULL 1970-11-11 22:22:22 NULL NULL 0 +98 NULL NULL NULL 0 +00 NULL NULL NULL 0 +02 NULL NULL NULL 0 +60 NULL NULL NULL 0 +70 NULL NULL NULL 0 +NULL NULL NULL NULL 1 +select *, f1 = f2 from t1; +f1 f2 f3 f4 f1 = f2 +98 1998 1998-01-01 1998-01-01 00:00:00 1 +00 2000 2000-01-01 2000-01-01 00:00:01 1 +02 2002 2002-01-01 2002-01-01 23:59:59 1 +60 2060 2060-01-01 2060-01-01 11:11:11 1 +70 1970 1970-01-01 1970-11-11 22:22:22 1 +NULL NULL NULL NULL NULL +drop table t1; +# diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index b0a3d0feb79..02d2676a3c2 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -1006,3 +1006,35 @@ DROP TABLE t1; ### --echo End of 5.0 tests + +--echo # +--echo # Bug#43668: Wrong comparison and MIN/MAX for YEAR(2) +--echo # +create table t1 (f1 year(2), f2 year(4), f3 date, f4 datetime); +insert into t1 values + (98,1998,19980101,"1998-01-01 00:00:00"), + (00,2000,20000101,"2000-01-01 00:00:01"), + (02,2002,20020101,"2002-01-01 23:59:59"), + (60,2060,20600101,"2060-01-01 11:11:11"), + (70,1970,19700101,"1970-11-11 22:22:22"), + (NULL,NULL,NULL,NULL); +select min(f1),max(f1) from t1; +select min(f2),max(f2) from t1; +select min(f3),max(f3) from t1; +select min(f4),max(f4) from t1; +select a.f1 as a, b.f1 as b, a.f1 > b.f1 as gt, + a.f1 < b.f1 as lt, a.f1<=>b.f1 as eq +from t1 a, t1 b; +select a.f1 as a, b.f2 as b, a.f1 > b.f2 as gt, + a.f1 < b.f2 as lt, a.f1<=>b.f2 as eq +from t1 a, t1 b; +select a.f1 as a, b.f3 as b, a.f1 > b.f3 as gt, + a.f1 < b.f3 as lt, a.f1<=>b.f3 as eq +from t1 a, t1 b; +select a.f1 as a, b.f4 as b, a.f1 > b.f4 as gt, + a.f1 < b.f4 as lt, a.f1<=>b.f4 as eq +from t1 a, t1 b; +select *, f1 = f2 from t1; +drop table t1; +--echo # + diff --git a/sql/item.cc b/sql/item.cc index 86e4551e55b..baa35b977e3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6940,7 +6940,7 @@ Item_cache* Item_cache::get_cache(const Item *item) { switch (item->result_type()) { case INT_RESULT: - return new Item_cache_int(); + return new Item_cache_int(item->field_type()); case REAL_RESULT: return new Item_cache_real(); case DECIMAL_RESULT: diff --git a/sql/item.h b/sql/item.h index a2cff3ab3a9..00ecda105d3 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2135,6 +2135,23 @@ public: save_in_field(result_field, no_conversions); } void cleanup(); + /* + This method is used for debug purposes to print the name of an + item to the debug log. The second use of this method is as + a helper function of print() and error messages, where it is + applicable. To suit both goals it should return a meaningful, + distinguishable and sintactically correct string. This method + should not be used for runtime type identification, use enum + {Sum}Functype and Item_func::functype()/Item_sum::sum_func() + instead. + Added here, to the parent class of both Item_func and Item_sum_func. + + NOTE: for Items inherited from Item_sum, func_name() return part of + function name till first argument (including '(') to make difference in + names for functions with 'distinct' clause and without 'distinct' and + also to make printing of items inherited from Item_sum uniform. + */ + virtual const char *func_name() const= 0; }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c29031d25b5..aa279bced44 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -30,6 +30,9 @@ #include "sql_select.h" static bool convert_constant_item(THD *, Item_field *, Item **); +static longlong +get_year_value(THD *thd, Item ***item_arg, Item **cache_arg, + Item *warn_item, bool *is_null); static Item_result item_store_type(Item_result a, Item *item, my_bool unsigned_flag) @@ -533,11 +536,12 @@ void Item_bool_func2::fix_length_and_dec() } -int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) +int Arg_comparator::set_compare_func(Item_result_field *item, Item_result type) { owner= item; func= comparator_matrix[type] - [test(owner->functype() == Item_func::EQUAL_FUNC)]; + [is_owner_equal_func()]; + switch (type) { case ROW_RESULT: { @@ -557,7 +561,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols()); return 1; } - if (comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i))) + if (comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i), + set_null)) return 1; } break; @@ -571,7 +576,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) if (cmp_collation.set((*a)->collation, (*b)->collation) || cmp_collation.derivation == DERIVATION_NONE) { - my_coll_agg_error((*a)->collation, (*b)->collation, owner->func_name()); + my_coll_agg_error((*a)->collation, (*b)->collation, + owner->func_name()); return 1; } if (cmp_collation.collation == &my_charset_bin) @@ -849,7 +855,7 @@ get_time_value(THD *thd, Item ***item_arg, Item **cache_arg, } -int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, +int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, Item **a1, Item **a2, Item_result type) { @@ -857,11 +863,11 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, ulonglong const_value= (ulonglong)-1; a= a1; b= a2; + owner= owner_arg; + thd= current_thd; if ((cmp_type= can_compare_as_dates(*a, *b, &const_value))) { - thd= current_thd; - owner= owner_arg; a_type= (*a)->field_type(); b_type= (*b)->field_type(); a_cache= 0; @@ -885,22 +891,22 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, b= (Item **)&b_cache; } } - is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC); + is_nulls_eq= is_owner_equal_func(); func= &Arg_comparator::compare_datetime; - get_value_func= &get_datetime_value; + get_value_a_func= &get_datetime_value; + get_value_b_func= &get_datetime_value; return 0; } else if (type == STRING_RESULT && (*a)->field_type() == MYSQL_TYPE_TIME && (*b)->field_type() == MYSQL_TYPE_TIME) { /* Compare TIME values as integers. */ - thd= current_thd; - owner= owner_arg; a_cache= 0; b_cache= 0; - is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC); + is_nulls_eq= is_owner_equal_func(); func= &Arg_comparator::compare_datetime; - get_value_func= &get_time_value; + get_value_a_func= &get_time_value; + get_value_b_func= &get_time_value; return 0; } else if (type == STRING_RESULT && @@ -909,20 +915,39 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, { DTCollation coll; coll.set((*a)->collation.collation); - if (agg_item_set_converter(coll, owner_arg->func_name(), + if (agg_item_set_converter(coll, owner->func_name(), b, 1, MY_COLL_CMP_CONV, 1)) return 1; - } + } else if (type != ROW_RESULT && ((*a)->field_type() == MYSQL_TYPE_YEAR || + (*b)->field_type() == MYSQL_TYPE_YEAR)) + { + is_nulls_eq= is_owner_equal_func(); + if ((*a)->is_datetime()) + { + year_as_datetime= TRUE; + get_value_a_func= &get_datetime_value; + } else if ((*a)->field_type() == MYSQL_TYPE_YEAR) + get_value_a_func= &get_year_value; + if ((*b)->is_datetime()) + { + year_as_datetime= TRUE; + get_value_b_func= &get_datetime_value; + } else if ((*b)->field_type() == MYSQL_TYPE_YEAR) + get_value_b_func= &get_year_value; + + func= &Arg_comparator::compare_year; + return 0; + } return set_compare_func(owner_arg, type); } -void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1) +void Arg_comparator::set_datetime_cmp_func(Item_result_field *owner_arg, + Item **a1, Item **b1) { thd= current_thd; - /* A caller will handle null values by itself. */ - owner= NULL; + owner= owner_arg; a= a1; b= b1; a_type= (*a)->field_type(); @@ -931,7 +956,8 @@ void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1) b_cache= 0; is_nulls_eq= FALSE; func= &Arg_comparator::compare_datetime; - get_value_func= &get_datetime_value; + get_value_a_func= &get_datetime_value; + get_value_b_func= &get_datetime_value; } @@ -1031,6 +1057,51 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, return value; } + +/* + Retrieves YEAR value of 19XX form from given item. + + SYNOPSIS + get_year_value() + thd thread handle + item_arg [in/out] item to retrieve YEAR value from + cache_arg [in/out] pointer to place to store the caching item to + warn_item [in] item for issuing the conversion warning + is_null [out] TRUE <=> the item_arg is null + + DESCRIPTION + Retrieves the YEAR value of 19XX form from given item for comparison by the + compare_year() function. + + RETURN + obtained value +*/ + +static longlong +get_year_value(THD *thd, Item ***item_arg, Item **cache_arg, + Item *warn_item, bool *is_null) +{ + longlong value= 0; + Item *item= **item_arg; + + value= item->val_int(); + *is_null= item->null_value; + if (*is_null) + return ~(ulonglong) 0; + + /* + Coerce value to the 19XX form in order to correctly compare + YEAR(2) & YEAR(4) types. + */ + if (value < 70) + value+= 100; + if (value <= 1900) + value+= 1900; + + return value; +} + + /* Compare items values as dates. @@ -1063,25 +1134,25 @@ int Arg_comparator::compare_datetime() longlong a_value, b_value; /* Get DATE/DATETIME/TIME value of the 'a' item. */ - a_value= (*get_value_func)(thd, &a, &a_cache, *b, &a_is_null); + a_value= (*get_value_a_func)(thd, &a, &a_cache, *b, &a_is_null); if (!is_nulls_eq && a_is_null) { - if (owner) + if (set_null) owner->null_value= 1; return -1; } /* Get DATE/DATETIME/TIME value of the 'b' item. */ - b_value= (*get_value_func)(thd, &b, &b_cache, *a, &b_is_null); + b_value= (*get_value_b_func)(thd, &b, &b_cache, *a, &b_is_null); if (a_is_null || b_is_null) { - if (owner) + if (set_null) owner->null_value= is_nulls_eq ? 0 : 1; return is_nulls_eq ? (a_is_null == b_is_null) : -1; } /* Here we have two not-NULL values. */ - if (owner) + if (set_null) owner->null_value= 0; /* Compare values. */ @@ -1094,15 +1165,17 @@ int Arg_comparator::compare_datetime() int Arg_comparator::compare_string() { String *res1,*res2; - if ((res1= (*a)->val_str(&owner->tmp_value1))) + if ((res1= (*a)->val_str(&value1))) { - if ((res2= (*b)->val_str(&owner->tmp_value2))) + if ((res2= (*b)->val_str(&value2))) { - owner->null_value= 0; + if (set_null) + owner->null_value= 0; return sortcmp(res1,res2,cmp_collation.collation); } } - owner->null_value= 1; + if (set_null) + owner->null_value= 1; return -1; } @@ -1121,18 +1194,20 @@ int Arg_comparator::compare_string() int Arg_comparator::compare_binary_string() { String *res1,*res2; - if ((res1= (*a)->val_str(&owner->tmp_value1))) + if ((res1= (*a)->val_str(&value1))) { - if ((res2= (*b)->val_str(&owner->tmp_value2))) + if ((res2= (*b)->val_str(&value2))) { - owner->null_value= 0; + if (set_null) + owner->null_value= 0; uint res1_length= res1->length(); uint res2_length= res2->length(); int cmp= memcmp(res1->ptr(), res2->ptr(), min(res1_length,res2_length)); return cmp ? cmp : (int) (res1_length - res2_length); } } - owner->null_value= 1; + if (set_null) + owner->null_value= 1; return -1; } @@ -1145,8 +1220,8 @@ int Arg_comparator::compare_binary_string() int Arg_comparator::compare_e_string() { String *res1,*res2; - res1= (*a)->val_str(&owner->tmp_value1); - res2= (*b)->val_str(&owner->tmp_value2); + res1= (*a)->val_str(&value1); + res2= (*b)->val_str(&value2); if (!res1 || !res2) return test(res1 == res2); return test(sortcmp(res1, res2, cmp_collation.collation) == 0); @@ -1156,8 +1231,8 @@ int Arg_comparator::compare_e_string() int Arg_comparator::compare_e_binary_string() { String *res1,*res2; - res1= (*a)->val_str(&owner->tmp_value1); - res2= (*b)->val_str(&owner->tmp_value2); + res1= (*a)->val_str(&value1); + res2= (*b)->val_str(&value2); if (!res1 || !res2) return test(res1 == res2); return test(stringcmp(res1, res2) == 0); @@ -1178,13 +1253,15 @@ int Arg_comparator::compare_real() val2= (*b)->val_real(); if (!(*b)->null_value) { - owner->null_value= 0; + if (set_null) + owner->null_value= 0; if (val1 < val2) return -1; if (val1 == val2) return 0; return 1; } } - owner->null_value= 1; + if (set_null) + owner->null_value= 1; return -1; } @@ -1198,11 +1275,13 @@ int Arg_comparator::compare_decimal() my_decimal *val2= (*b)->val_decimal(&value2); if (!(*b)->null_value) { - owner->null_value= 0; + if (set_null) + owner->null_value= 0; return my_decimal_cmp(val1, val2); } } - owner->null_value= 1; + if (set_null) + owner->null_value= 1; return -1; } @@ -1240,7 +1319,8 @@ int Arg_comparator::compare_real_fixed() val2= (*b)->val_real(); if (!(*b)->null_value) { - owner->null_value= 0; + if (set_null) + owner->null_value= 0; if (val1 == val2 || fabs(val1 - val2) < precision) return 0; if (val1 < val2) @@ -1248,7 +1328,8 @@ int Arg_comparator::compare_real_fixed() return 1; } } - owner->null_value= 1; + if (set_null) + owner->null_value= 1; return -1; } @@ -1271,13 +1352,15 @@ int Arg_comparator::compare_int_signed() longlong val2= (*b)->val_int(); if (!(*b)->null_value) { - owner->null_value= 0; + if (set_null) + owner->null_value= 0; if (val1 < val2) return -1; if (val1 == val2) return 0; return 1; } } - owner->null_value= 1; + if (set_null) + owner->null_value= 1; return -1; } @@ -1294,13 +1377,15 @@ int Arg_comparator::compare_int_unsigned() ulonglong val2= (*b)->val_int(); if (!(*b)->null_value) { - owner->null_value= 0; + if (set_null) + owner->null_value= 0; if (val1 < val2) return -1; if (val1 == val2) return 0; return 1; } } - owner->null_value= 1; + if (set_null) + owner->null_value= 1; return -1; } @@ -1317,7 +1402,8 @@ int Arg_comparator::compare_int_signed_unsigned() ulonglong uval2= (ulonglong)(*b)->val_int(); if (!(*b)->null_value) { - owner->null_value= 0; + if (set_null) + owner->null_value= 0; if (sval1 < 0 || (ulonglong)sval1 < uval2) return -1; if ((ulonglong)sval1 == uval2) @@ -1325,7 +1411,8 @@ int Arg_comparator::compare_int_signed_unsigned() return 1; } } - owner->null_value= 1; + if (set_null) + owner->null_value= 1; return -1; } @@ -1342,7 +1429,8 @@ int Arg_comparator::compare_int_unsigned_signed() longlong sval2= (*b)->val_int(); if (!(*b)->null_value) { - owner->null_value= 0; + if (set_null) + owner->null_value= 0; if (sval2 < 0) return 1; if (uval1 < (ulonglong)sval2) @@ -1352,7 +1440,8 @@ int Arg_comparator::compare_int_unsigned_signed() return 1; } } - owner->null_value= 1; + if (set_null) + owner->null_value= 1; return -1; } @@ -1388,10 +1477,11 @@ int Arg_comparator::compare_row() for (uint i= 0; inull_value) + /* Aggregate functions don't need special null handling. */ + if (owner->null_value && owner->type() == Item::FUNC_ITEM) { // NULL was compared - switch (owner->functype()) { + switch (((Item_func*)owner)->functype()) { case Item_func::NE_FUNC: break; // NE never aborts on NULL even if abort_on_null is set case Item_func::LT_FUNC: @@ -1400,7 +1490,7 @@ int Arg_comparator::compare_row() case Item_func::GE_FUNC: return -1; // <, <=, > and >= always fail on NULL default: // EQ_FUNC - if (owner->abort_on_null) + if (((Item_bool_func2*)owner)->abort_on_null) return -1; // We do not need correct NULL returning } was_null= 1; @@ -1437,6 +1527,67 @@ int Arg_comparator::compare_e_row() } +/** + Compare values as YEAR. + + @details + Compare items as YEAR for EQUAL_FUNC and for other comparison functions. + The YEAR values of form 19XX are obtained with help of the get_year_value() + function. + If one of arguments is of DATE/DATETIME type its value is obtained + with help of the get_datetime_value function. In this case YEAR values + prior to comparison are converted to the ulonglong YYYY-00-00 00:00:00 + DATETIME form. + If an argument type neither YEAR nor DATE/DATEIME then val_int function + is used to obtain value for comparison. + + RETURN + If is_nulls_eq is TRUE: + 1 if items are equal or both are null + 0 otherwise + If is_nulls_eq is FALSE: + -1 a < b + 0 a == b or at least one of items is null + 1 a > b + See the table: + is_nulls_eq | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | + a_is_null | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | + b_is_null | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | + result | 1 | 0 | 0 |0/1| 0 | 0 | 0 |-1/0/1| +*/ + +int Arg_comparator::compare_year() +{ + bool a_is_null, b_is_null; + ulonglong val1= get_value_a_func ? + (*get_value_a_func)(thd, &a, &a_cache, *b, &a_is_null) : + (*a)->val_int(); + ulonglong val2= get_value_b_func ? + (*get_value_b_func)(thd, &b, &b_cache, *a, &b_is_null) : + (*b)->val_int(); + if (!(*a)->null_value) + { + if (!(*b)->null_value) + { + if (set_null) + owner->null_value= 0; + /* Convert year to DATETIME of form YYYY-00-00 00:00:00 when necessary. */ + if((*a)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime) + val1*= 10000000000LL; + if((*b)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime) + val2*= 10000000000LL; + + if (val1 < val2) return is_nulls_eq ? 0 : -1; + if (val1 == val2) return is_nulls_eq ? 1 : 0; + return is_nulls_eq ? 0 : 1; + } + } + if (set_null) + owner->null_value= is_nulls_eq ? 0 : 1; + return (is_nulls_eq && (*a)->null_value == (*b)->null_value) ? 1 : 0; +} + + void Item_func_truth::fix_length_and_dec() { maybe_null= 0; @@ -1711,8 +1862,8 @@ longlong Item_func_lt::val_int() longlong Item_func_strcmp::val_int() { DBUG_ASSERT(fixed == 1); - String *a=args[0]->val_str(&tmp_value1); - String *b=args[1]->val_str(&tmp_value2); + String *a=args[0]->val_str(&cmp.value1); + String *b=args[1]->val_str(&cmp.value2); if (!a || !b) { null_value=1; @@ -1995,8 +2146,8 @@ void Item_func_between::fix_length_and_dec() if (compare_as_dates) { - ge_cmp.set_datetime_cmp_func(args, args + 1); - le_cmp.set_datetime_cmp_func(args, args + 2); + ge_cmp.set_datetime_cmp_func(this, args, args + 1); + le_cmp.set_datetime_cmp_func(this, args, args + 2); } else if (time_items_found == 3) { @@ -4324,13 +4475,13 @@ void Item_func_isnotnull::print(String *str, enum_query_type query_type) longlong Item_func_like::val_int() { DBUG_ASSERT(fixed == 1); - String* res = args[0]->val_str(&tmp_value1); + String* res = args[0]->val_str(&cmp.value1); if (args[0]->null_value) { null_value=1; return 0; } - String* res2 = args[1]->val_str(&tmp_value2); + String* res2 = args[1]->val_str(&cmp.value2); if (args[1]->null_value) { null_value=1; @@ -4354,7 +4505,7 @@ Item_func::optimize_type Item_func_like::select_optimize() const { if (args[1]->const_item()) { - String* res2= args[1]->val_str((String *)&tmp_value2); + String* res2= args[1]->val_str((String *)&cmp.value2); if (!res2) return OPTIMIZE_NONE; @@ -4385,7 +4536,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref) if (escape_item->const_item()) { /* If we are on execution stage */ - String *escape_str= escape_item->val_str(&tmp_value1); + String *escape_str= escape_item->val_str(&cmp.value1); if (escape_str) { if (escape_used_in_parsing && ( @@ -4440,7 +4591,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref) if (args[1]->const_item() && !use_strnxfrm(collation.collation) && !(specialflag & SPECIAL_NO_NEW_FUNC)) { - String* res2 = args[1]->val_str(&tmp_value2); + String* res2 = args[1]->val_str(&cmp.value2); if (!res2) return FALSE; // Null argument diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index c2227fa04e0..3cf4a1473cc 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -32,7 +32,7 @@ class Arg_comparator: public Sql_alloc { Item **a, **b; arg_cmp_func func; - Item_bool_func2 *owner; + Item_result_field *owner; Arg_comparator *comparators; // used only for compare_row() double precision; /* Fields used in DATE/DATETIME comparison. */ @@ -40,30 +40,42 @@ class Arg_comparator: public Sql_alloc enum_field_types a_type, b_type; // Types of a and b items Item *a_cache, *b_cache; // Cached values of a and b items bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC + bool set_null; // TRUE <=> set owner->null_value + // when one of arguments is NULL. + bool year_as_datetime; // TRUE <=> convert YEAR value to + // the YYYY-00-00 00:00:00 DATETIME + // format. See compare_year. enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE, CMP_DATE_WITH_STR, CMP_STR_WITH_DATE }; - longlong (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg, - Item *warn_item, bool *is_null); + longlong (*get_value_a_func)(THD *thd, Item ***item_arg, Item **cache_arg, + Item *warn_item, bool *is_null); + longlong (*get_value_b_func)(THD *thd, Item ***item_arg, Item **cache_arg, + Item *warn_item, bool *is_null); public: DTCollation cmp_collation; + /* Allow owner function to use string buffers. */ + String value1, value2; - Arg_comparator(): thd(0), a_cache(0), b_cache(0) {}; + Arg_comparator(): thd(0), a_cache(0), b_cache(0), set_null(0), + year_as_datetime(0), get_value_a_func(0), get_value_b_func(0) {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), thd(0), - a_cache(0), b_cache(0) {}; + a_cache(0), b_cache(0), set_null(0), year_as_datetime(0), + get_value_a_func(0), get_value_b_func(0) {}; - int set_compare_func(Item_bool_func2 *owner, Item_result type); - inline int set_compare_func(Item_bool_func2 *owner_arg) + int set_compare_func(Item_result_field *owner, Item_result type); + inline int set_compare_func(Item_result_field *owner_arg) { return set_compare_func(owner_arg, item_cmp_type((*a)->result_type(), (*b)->result_type())); } - int set_cmp_func(Item_bool_func2 *owner_arg, + int set_cmp_func(Item_result_field *owner_arg, Item **a1, Item **a2, Item_result type); - inline int set_cmp_func(Item_bool_func2 *owner_arg, - Item **a1, Item **a2) + inline int set_cmp_func(Item_result_field *owner_arg, + Item **a1, Item **a2, bool set_null_arg) { + set_null= set_null_arg; return set_cmp_func(owner_arg, a1, a2, item_cmp_type((*a1)->result_type(), (*a2)->result_type())); @@ -89,12 +101,18 @@ public: int compare_real_fixed(); int compare_e_real_fixed(); int compare_datetime(); // compare args[0] & args[1] as DATETIMEs + int compare_year(); static enum enum_date_cmp_type can_compare_as_dates(Item *a, Item *b, ulonglong *const_val_arg); - void set_datetime_cmp_func(Item **a1, Item **b1); + void set_datetime_cmp_func(Item_result_field *owner_arg, Item **a1, Item **b1); static arg_cmp_func comparator_matrix [5][2]; + inline bool is_owner_equal_func() + { + return (owner->type() == Item::FUNC_ITEM && + ((Item_func*)owner)->functype() == Item_func::EQUAL_FUNC); + } friend class Item_func; }; @@ -324,7 +342,6 @@ class Item_bool_func2 :public Item_int_func { /* Bool with 2 string args */ protected: Arg_comparator cmp; - String tmp_value1,tmp_value2; bool abort_on_null; public: @@ -333,7 +350,7 @@ public: void fix_length_and_dec(); void set_cmp_func() { - cmp.set_cmp_func(this, tmp_arg, tmp_arg+1); + cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, TRUE); } optimize_type select_optimize() const { return OPTIMIZE_OP; } virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; } diff --git a/sql/item_func.h b/sql/item_func.h index fdbbff89e60..4a3632fd87e 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -124,17 +124,6 @@ public: virtual optimize_type select_optimize() const { return OPTIMIZE_NONE; } virtual bool have_rev_func() const { return 0; } virtual Item *key_item() const { return args[0]; } - /* - This method is used for debug purposes to print the name of an - item to the debug log. The second use of this method is as - a helper function of print(), where it is applicable. - To suit both goals it should return a meaningful, - distinguishable and sintactically correct string. This method - should not be used for runtime type identification, use enum - {Sum}Functype and Item_func::functype()/Item_sum::sum_func() - instead. - */ - virtual const char *func_name() const= 0; virtual bool const_item() const { return const_item_cache; } inline Item **arguments() const { return args; } void set_arguments(List &list); diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index a34204b7181..9b01f77c9a1 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -506,8 +506,8 @@ err: longlong Item_func_spatial_rel::val_int() { DBUG_ASSERT(fixed == 1); - String *res1= args[0]->val_str(&tmp_value1); - String *res2= args[1]->val_str(&tmp_value2); + String *res1= args[0]->val_str(&cmp.value1); + String *res2= args[1]->val_str(&cmp.value2); Geometry_buffer buffer1, buffer2; Geometry *g1, *g2; MBR mbr1, mbr2; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index d4aa621c083..467e9b22637 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -132,6 +132,7 @@ public: @return the SELECT_LEX structure associated with this Item */ st_select_lex* get_select_lex(); + const char *func_name() const { DBUG_ASSERT(0); return "subselect"; } friend class select_subselect; friend class Item_in_optimizer; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 08a48c6ce2f..52292486662 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -614,35 +614,6 @@ Item_sum_num::fix_fields(THD *thd, Item **ref) } -Item_sum_hybrid::Item_sum_hybrid(THD *thd, Item_sum_hybrid *item) - :Item_sum(thd, item), value(item->value), hybrid_type(item->hybrid_type), - hybrid_field_type(item->hybrid_field_type), cmp_sign(item->cmp_sign), - was_values(item->was_values) -{ - /* copy results from old value */ - switch (hybrid_type) { - case INT_RESULT: - sum_int= item->sum_int; - break; - case DECIMAL_RESULT: - my_decimal2decimal(&item->sum_dec, &sum_dec); - break; - case REAL_RESULT: - sum= item->sum; - break; - case STRING_RESULT: - /* - This can happen with ROLLUP. Note that the value is already - copied at function call. - */ - break; - case ROW_RESULT: - default: - DBUG_ASSERT(0); - } - collation.set(item->collation); -} - bool Item_sum_hybrid::fix_fields(THD *thd, Item **ref) { @@ -662,15 +633,12 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) switch (hybrid_type= item->result_type()) { case INT_RESULT: max_length= 20; - sum_int= 0; break; case DECIMAL_RESULT: max_length= item->max_length; - my_decimal_set_zero(&sum_dec); break; case REAL_RESULT: max_length= float_length(decimals); - sum= 0.0; break; case STRING_RESULT: max_length= item->max_length; @@ -679,10 +647,10 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) default: DBUG_ASSERT(0); }; + setup(args[0], NULL); /* MIN/MAX can return NULL for empty set indepedent of the used column */ maybe_null= 1; unsigned_flag=item->unsigned_flag; - collation.set(item->collation); result_field=0; null_value=1; fix_length_and_dec(); @@ -700,6 +668,31 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) return FALSE; } + +/** + MIN/MAX function setup. + + @param item argument of MIN/MAX function + @param value_arg calculated value of MIN/MAX function + + @details + Setup cache/comparator of MIN/MAX functions. When called by the + copy_or_same function value_arg parameter contains calculated value + of the original MIN/MAX object and it is saved in this object's cache. +*/ + +void Item_sum_hybrid::setup(Item *item, Item *value_arg) +{ + value= Item_cache::get_cache(item); + value->setup(item); + if (value_arg) + value->store(value_arg); + cmp= new Arg_comparator(); + cmp->set_cmp_func(this, args, (Item**)&value, FALSE); + collation.set(item->collation); +} + + Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, uint convert_blob_length) { @@ -1591,19 +1584,7 @@ void Item_sum_variance::update_field() void Item_sum_hybrid::clear() { - switch (hybrid_type) { - case INT_RESULT: - sum_int= 0; - break; - case DECIMAL_RESULT: - my_decimal_set_zero(&sum_dec); - break; - case REAL_RESULT: - sum= 0.0; - break; - default: - value.length(0); - } + value->null_value= 1; null_value= 1; } @@ -1612,30 +1593,7 @@ double Item_sum_hybrid::val_real() DBUG_ASSERT(fixed == 1); if (null_value) return 0.0; - switch (hybrid_type) { - case STRING_RESULT: - { - char *end_not_used; - int err_not_used; - String *res; res=val_str(&str_value); - return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(), - &end_not_used, &err_not_used) : 0.0); - } - case INT_RESULT: - if (unsigned_flag) - return ulonglong2double(sum_int); - return (double) sum_int; - case DECIMAL_RESULT: - my_decimal2double(E_DEC_FATAL_ERROR, &sum_dec, &sum); - return sum; - case REAL_RESULT: - return sum; - case ROW_RESULT: - default: - // This case should never be choosen - DBUG_ASSERT(0); - return 0; - } + return value->val_real(); } longlong Item_sum_hybrid::val_int() @@ -1643,18 +1601,7 @@ longlong Item_sum_hybrid::val_int() DBUG_ASSERT(fixed == 1); if (null_value) return 0; - switch (hybrid_type) { - case INT_RESULT: - return sum_int; - case DECIMAL_RESULT: - { - longlong result; - my_decimal2int(E_DEC_FATAL_ERROR, &sum_dec, unsigned_flag, &result); - return sum_int; - } - default: - return (longlong) rint(Item_sum_hybrid::val_real()); - } + return value->val_int(); } @@ -1663,26 +1610,7 @@ my_decimal *Item_sum_hybrid::val_decimal(my_decimal *val) DBUG_ASSERT(fixed == 1); if (null_value) return 0; - switch (hybrid_type) { - case STRING_RESULT: - string2my_decimal(E_DEC_FATAL_ERROR, &value, val); - break; - case REAL_RESULT: - double2my_decimal(E_DEC_FATAL_ERROR, sum, val); - break; - case DECIMAL_RESULT: - val= &sum_dec; - break; - case INT_RESULT: - int2my_decimal(E_DEC_FATAL_ERROR, sum_int, unsigned_flag, val); - break; - case ROW_RESULT: - default: - // This case should never be choosen - DBUG_ASSERT(0); - break; - } - return val; // Keep compiler happy + return value->val_decimal(val); } @@ -1692,25 +1620,7 @@ Item_sum_hybrid::val_str(String *str) DBUG_ASSERT(fixed == 1); if (null_value) return 0; - switch (hybrid_type) { - case STRING_RESULT: - return &value; - case REAL_RESULT: - str->set_real(sum,decimals, &my_charset_bin); - break; - case DECIMAL_RESULT: - my_decimal2string(E_DEC_FATAL_ERROR, &sum_dec, 0, 0, 0, str); - return str; - case INT_RESULT: - str->set_int(sum_int, unsigned_flag, &my_charset_bin); - break; - case ROW_RESULT: - default: - // This case should never be choosen - DBUG_ASSERT(0); - break; - } - return str; // Keep compiler happy + return value->val_str(str); } @@ -1719,7 +1629,9 @@ void Item_sum_hybrid::cleanup() DBUG_ENTER("Item_sum_hybrid::cleanup"); Item_sum::cleanup(); forced_const= FALSE; - + if (cmp) + delete cmp; + cmp= 0; /* by default it is TRUE to avoid TRUE reporting by Item_func_not_all/Item_func_nop_all if this item was never called. @@ -1740,63 +1652,21 @@ void Item_sum_hybrid::no_rows_in_result() Item *Item_sum_min::copy_or_same(THD* thd) { - return new (thd->mem_root) Item_sum_min(thd, this); + Item_sum_min *item= new (thd->mem_root) Item_sum_min(thd, this); + item->setup(args[0], value); + return item; } bool Item_sum_min::add() { - switch (hybrid_type) { - case STRING_RESULT: + /* args[0] < value */ + int res= cmp->compare(); + if (!args[0]->null_value && + (null_value || res < 0)) { - String *result=args[0]->val_str(&tmp_value); - if (!args[0]->null_value && - (null_value || sortcmp(&value,result,collation.collation) > 0)) - { - value.copy(*result); - null_value=0; - } - } - break; - case INT_RESULT: - { - longlong nr=args[0]->val_int(); - if (!args[0]->null_value && (null_value || - (unsigned_flag && - (ulonglong) nr < (ulonglong) sum_int) || - (!unsigned_flag && nr < sum_int))) - { - sum_int=nr; - null_value=0; - } - } - break; - case DECIMAL_RESULT: - { - my_decimal value_buff, *val= args[0]->val_decimal(&value_buff); - if (!args[0]->null_value && - (null_value || (my_decimal_cmp(&sum_dec, val) > 0))) - { - my_decimal2decimal(val, &sum_dec); - null_value= 0; - } - } - break; - case REAL_RESULT: - { - double nr= args[0]->val_real(); - if (!args[0]->null_value && (null_value || nr < sum)) - { - sum=nr; - null_value=0; - } - } - break; - case ROW_RESULT: - default: - // This case should never be choosen - DBUG_ASSERT(0); - break; + value->store(args[0]); + null_value= 0; } return 0; } @@ -1804,63 +1674,21 @@ bool Item_sum_min::add() Item *Item_sum_max::copy_or_same(THD* thd) { - return new (thd->mem_root) Item_sum_max(thd, this); + Item_sum_max *item= new (thd->mem_root) Item_sum_max(thd, this); + item->setup(args[0], value); + return item; } bool Item_sum_max::add() { - switch (hybrid_type) { - case STRING_RESULT: + /* args[0] > value */ + int res= cmp->compare(); + if (!args[0]->null_value && + (null_value || res > 0)) { - String *result=args[0]->val_str(&tmp_value); - if (!args[0]->null_value && - (null_value || sortcmp(&value,result,collation.collation) < 0)) - { - value.copy(*result); - null_value=0; - } - } - break; - case INT_RESULT: - { - longlong nr=args[0]->val_int(); - if (!args[0]->null_value && (null_value || - (unsigned_flag && - (ulonglong) nr > (ulonglong) sum_int) || - (!unsigned_flag && nr > sum_int))) - { - sum_int=nr; - null_value=0; - } - } - break; - case DECIMAL_RESULT: - { - my_decimal value_buff, *val= args[0]->val_decimal(&value_buff); - if (!args[0]->null_value && - (null_value || (my_decimal_cmp(val, &sum_dec) > 0))) - { - my_decimal2decimal(val, &sum_dec); - null_value= 0; - } - } - break; - case REAL_RESULT: - { - double nr= args[0]->val_real(); - if (!args[0]->null_value && (null_value || nr > sum)) - { - sum=nr; - null_value=0; - } - } - break; - case ROW_RESULT: - default: - // This case should never be choosen - DBUG_ASSERT(0); - break; + value->store(args[0]); + null_value= 0; } return 0; } @@ -2225,14 +2053,15 @@ void Item_sum_hybrid::update_field() void Item_sum_hybrid::min_max_update_str_field() { - String *res_str=args[0]->val_str(&value); + DBUG_ASSERT(cmp); + String *res_str=args[0]->val_str(&cmp->value1); if (!args[0]->null_value) { - result_field->val_str(&tmp_value); + result_field->val_str(&cmp->value2); if (result_field->is_null() || - (cmp_sign * sortcmp(res_str,&tmp_value,collation.collation)) < 0) + (cmp_sign * sortcmp(res_str,&cmp->value2,collation.collation)) < 0) result_field->store(res_str->ptr(),res_str->length(),res_str->charset()); result_field->set_notnull(); } diff --git a/sql/item_sum.h b/sql/item_sum.h index d991327d847..f70da52bcd1 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -323,22 +323,6 @@ public: virtual void update_field()=0; virtual bool keep_field_type(void) const { return 0; } virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } - /* - This method is used for debug purposes to print the name of an - item to the debug log. The second use of this method is as - a helper function of print(), where it is applicable. - To suit both goals it should return a meaningful, - distinguishable and sintactically correct string. This method - should not be used for runtime type identification, use enum - {Sum}Functype and Item_func::functype()/Item_sum::sum_func() - instead. - - NOTE: for Items inherited from Item_sum, func_name() return part of - function name till first argument (including '(') to make difference in - names for functions with 'distinct' clause and without 'distinct' and - also to make printing of items inherited from Item_sum uniform. - */ - virtual const char *func_name() const= 0; virtual Item *result_item(Field *field) { return new Item_field(field); } table_map used_tables() const { return used_tables_cache; } @@ -664,6 +648,7 @@ public: } void fix_length_and_dec() {} enum Item_result result_type () const { return hybrid_type; } + const char *func_name() const { DBUG_ASSERT(0); return "avg_field"; } }; @@ -732,6 +717,7 @@ public: } void fix_length_and_dec() {} enum Item_result result_type () const { return hybrid_type; } + const char *func_name() const { DBUG_ASSERT(0); return "variance_field"; } }; @@ -807,6 +793,7 @@ public: my_decimal *val_decimal(my_decimal *); enum Item_result result_type () const { return REAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;} + const char *func_name() const { DBUG_ASSERT(0); return "std_field"; } }; /* @@ -832,14 +819,13 @@ class Item_sum_std :public Item_sum_variance }; // This class is a string or number function depending on num_func - +class Arg_comparator; +class Item_cache; class Item_sum_hybrid :public Item_sum { protected: - String value,tmp_value; - double sum; - longlong sum_int; - my_decimal sum_dec; + Item_cache *value; + Arg_comparator *cmp; Item_result hybrid_type; enum_field_types hybrid_field_type; int cmp_sign; @@ -847,12 +833,17 @@ protected: public: Item_sum_hybrid(Item *item_par,int sign) - :Item_sum(item_par), sum(0.0), sum_int(0), + :Item_sum(item_par), value(0), cmp(0), hybrid_type(INT_RESULT), hybrid_field_type(MYSQL_TYPE_LONGLONG), cmp_sign(sign), was_values(TRUE) { collation.set(&my_charset_bin); } - Item_sum_hybrid(THD *thd, Item_sum_hybrid *item); + Item_sum_hybrid(THD *thd, Item_sum_hybrid *item) + :Item_sum(thd, item), value(item->value), hybrid_type(item->hybrid_type), + hybrid_field_type(item->hybrid_field_type), cmp_sign(item->cmp_sign), + was_values(item->was_values) + { } bool fix_fields(THD *, Item **); + void setup(Item *item, Item *value_arg); void clear(); double val_real(); longlong val_int(); From 8cfa50e6771f1dbd6f265be44d9340a7d53084c2 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Tue, 17 Nov 2009 17:07:14 +0300 Subject: [PATCH 042/344] Bug #48472: Loose index scan inappropriately chosen for some WHERE conditions check_group_min_max() checks if the loose index scan optimization is applicable for a given WHERE condition, that is if the MIN/MAX attribute participates only in range predicates comparing the corresponding field with constants. The problem was that it considered the whole predicate suitable for the loose index scan optimization as soon as it encountered a constant as a predicate argument. This is obviously wrong for cases when a constant is the first argument of a predicate which does not satisfy the above condition. Fixed check_group_min_max() so that all arguments of the input predicate are considered to decide if it passes the test, even though a constant has already been encountered. mysql-test/r/group_min_max.result: Added a test case for bug #48472. mysql-test/t/group_min_max.test: Added a test case for bug #48472. sql/opt_range.cc: Fixed check_group_min_max() so that all arguments of the input predicate are considered to decide if it passes the test, even though a constant has already been encountered. --- mysql-test/r/group_min_max.result | 11 +++++++++++ mysql-test/t/group_min_max.test | 12 ++++++++++++ sql/opt_range.cc | 6 +++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 9acbbaac499..46076fb288d 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2480,4 +2480,15 @@ SELECT a, MAX(b) FROM t WHERE b > 0 AND b < 2 GROUP BY a; a MAX(b) 2 1 DROP TABLE t; +# +# Bug #48472: Loose index scan inappropriately chosen for some WHERE +# conditions +# +CREATE TABLE t (a INT, b INT, INDEX (a,b)); +INSERT INTO t VALUES (2,0), (2,0), (2,1), (2,1); +INSERT INTO t SELECT * FROM t; +SELECT a, MAX(b) FROM t WHERE 0=b+0 GROUP BY a; +a MAX(b) +2 0 +DROP TABLE t; End of 5.0 tests diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index c81babb42e6..0d1cd076fb7 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -991,5 +991,17 @@ SELECT a, MAX(b) FROM t WHERE b > 0 AND b < 2 GROUP BY a; DROP TABLE t; +--echo # +--echo # Bug #48472: Loose index scan inappropriately chosen for some WHERE +--echo # conditions +--echo # + +CREATE TABLE t (a INT, b INT, INDEX (a,b)); +INSERT INTO t VALUES (2,0), (2,0), (2,1), (2,1); +INSERT INTO t SELECT * FROM t; + +SELECT a, MAX(b) FROM t WHERE 0=b+0 GROUP BY a; + +DROP TABLE t; --echo End of 5.0 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3236ccd2cf4..84519c091b9 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8244,7 +8244,11 @@ check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item, } else if (cur_arg->const_item()) { - DBUG_RETURN(TRUE); + /* + For predicates of the form "const OP expr" we also have to check 'expr' + to make a decision. + */ + continue; } else DBUG_RETURN(FALSE); From f881a7baa1c9ff29f4c84c9c96dbb326d14691d7 Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Tue, 17 Nov 2009 17:49:24 +0100 Subject: [PATCH 043/344] Include the "mysql-test/collections" directory when creating windows ZIP archive --- scripts/make_win_bin_dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist index 24e869fe6a4..9e3fc010885 100755 --- a/scripts/make_win_bin_dist +++ b/scripts/make_win_bin_dist @@ -332,7 +332,7 @@ fi mkdir $DESTDIR/mysql-test cp mysql-test/mysql-test-run.pl $DESTDIR/mysql-test/ cp mysql-test/README $DESTDIR/mysql-test/ -cp -R mysql-test/{t,r,include,suite,std_data,lib} $DESTDIR/mysql-test/ +cp -R mysql-test/{t,r,include,suite,std_data,lib,collections} $DESTDIR/mysql-test/ # Note that this will not copy "extra" if a soft link if [ -d mysql-test/extra ] ; then From 87349334004e7f3ae3beeb347661ffba18df3e38 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Tue, 17 Nov 2009 20:02:16 +0100 Subject: [PATCH 044/344] Bug#48846: Too much time spent in ha_partition::records_in_range if not able to prune Problem was that ha_partition::records_in_range called records_in_range for all non pruned partitions, even if an estimate should be given. Solution is to only use 1/3 of the partitions (up to 10) for records_in_range and estimate the total from this subset. (And continue until a non zero return value from the called partitions records_in_range is given, since 0 means no rows will match.) sql/ha_partition.cc: Bug#48846: Too much time spent in ha_partition::records_in_range if not able to prune estimate_rows_upper_bound and records_in_range are very similar (the only difference is the function and its parameters to use) so I created a common function for this. Since these calls from the optimizer are only estimates, it is not neccesary to call them for every partition, it can use a much smaller subset of the used partitions instead, which improves performance for selects. sql/ha_partition.h: Bug#48846: Too much time spent in ha_partition::records_in_range if not able to prune Added two private functions to help some optimizer calls. --- sql/ha_partition.cc | 144 ++++++++++++++++++++++++++++---------------- sql/ha_partition.h | 12 ++++ 2 files changed, 105 insertions(+), 51 deletions(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 451631ff373..b854e270029 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5747,6 +5747,23 @@ const key_map *ha_partition::keys_to_use_for_scanning() DBUG_RETURN(m_file[0]->keys_to_use_for_scanning()); } +#define MAX_PARTS_FOR_OPTIMIZER_CALLS 10 +/* + Prepare start variables for estimating optimizer costs. + + @param[out] num_used_parts Number of partitions after pruning. + @param[out] check_min_num Number of partitions to call. + @param[out] first first used partition. +*/ +void ha_partition::partitions_optimizer_call_preparations(uint *first, + uint *num_used_parts, + uint *check_min_num) +{ + *first= bitmap_get_first_set(&(m_part_info->used_partitions)); + *num_used_parts= bitmap_bits_set(&(m_part_info->used_partitions)); + *check_min_num= min(MAX_PARTS_FOR_OPTIMIZER_CALLS, *num_used_parts); +} + /* Return time for a scan of the table @@ -5760,43 +5777,67 @@ const key_map *ha_partition::keys_to_use_for_scanning() double ha_partition::scan_time() { - double scan_time= 0; - handler **file; + double scan_time= 0.0; + uint first, part_id, num_used_parts, check_min_num, partitions_called= 0; DBUG_ENTER("ha_partition::scan_time"); - for (file= m_file; *file; file++) - if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file))) - scan_time+= (*file)->scan_time(); + partitions_optimizer_call_preparations(&first, &num_used_parts, &check_min_num); + for (part_id= first; partitions_called < num_used_parts ; part_id++) + { + if (!bitmap_is_set(&(m_part_info->used_partitions), part_id)) + continue; + scan_time+= m_file[part_id]->scan_time(); + partitions_called++; + if (partitions_called >= check_min_num && scan_time != 0.0) + { + DBUG_RETURN(scan_time * + (double) num_used_parts / (double) partitions_called); + } + } DBUG_RETURN(scan_time); } /* - Get time to read + Estimate rows for records_in_range or estimate_rows_upper_bound. - SYNOPSIS - read_time() - index Index number used - ranges Number of ranges - rows Number of rows + @param is_records_in_range call records_in_range instead of + estimate_rows_upper_bound. + @param inx (only for records_in_range) index to use. + @param min_key (only for records_in_range) start of range. + @param max_key (only for records_in_range) end of range. - RETURN VALUE - time for read - - DESCRIPTION - This will be optimised later to include whether or not the index can - be used with partitioning. To achieve we need to add another parameter - that specifies how many of the index fields that are bound in the ranges. - Possibly added as a new call to handlers. + @return Number of rows or HA_POS_ERROR. */ - -double ha_partition::read_time(uint index, uint ranges, ha_rows rows) +ha_rows ha_partition::estimate_rows(bool is_records_in_range, uint inx, + key_range *min_key, key_range *max_key) { - DBUG_ENTER("ha_partition::read_time"); + ha_rows rows, estimated_rows= 0; + uint first, part_id, num_used_parts, check_min_num, partitions_called= 0; + DBUG_ENTER("ha_partition::records_in_range"); - DBUG_RETURN(m_file[0]->read_time(index, ranges, rows)); + partitions_optimizer_call_preparations(&first, &num_used_parts, &check_min_num); + for (part_id= first; partitions_called < num_used_parts ; part_id++) + { + if (!bitmap_is_set(&(m_part_info->used_partitions), part_id)) + continue; + if (is_records_in_range) + rows= m_file[part_id]->records_in_range(inx, min_key, max_key); + else + rows= m_file[part_id]->estimate_rows_upper_bound(); + if (rows == HA_POS_ERROR) + DBUG_RETURN(HA_POS_ERROR); + estimated_rows+= rows; + partitions_called++; + if (partitions_called >= check_min_num && estimated_rows) + { + DBUG_RETURN(estimated_rows * num_used_parts / partitions_called); + } + } + DBUG_RETURN(estimated_rows); } + /* Find number of records in a range @@ -5824,22 +5865,9 @@ double ha_partition::read_time(uint index, uint ranges, ha_rows rows) ha_rows ha_partition::records_in_range(uint inx, key_range *min_key, key_range *max_key) { - handler **file; - ha_rows in_range= 0; DBUG_ENTER("ha_partition::records_in_range"); - file= m_file; - do - { - if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file))) - { - ha_rows tmp_in_range= (*file)->records_in_range(inx, min_key, max_key); - if (tmp_in_range == HA_POS_ERROR) - DBUG_RETURN(tmp_in_range); - in_range+= tmp_in_range; - } - } while (*(++file)); - DBUG_RETURN(in_range); + DBUG_RETURN(estimate_rows(TRUE, inx, min_key, max_key)); } @@ -5855,22 +5883,36 @@ ha_rows ha_partition::records_in_range(uint inx, key_range *min_key, ha_rows ha_partition::estimate_rows_upper_bound() { - ha_rows rows, tot_rows= 0; - handler **file; DBUG_ENTER("ha_partition::estimate_rows_upper_bound"); - file= m_file; - do - { - if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file))) - { - rows= (*file)->estimate_rows_upper_bound(); - if (rows == HA_POS_ERROR) - DBUG_RETURN(HA_POS_ERROR); - tot_rows+= rows; - } - } while (*(++file)); - DBUG_RETURN(tot_rows); + DBUG_RETURN(estimate_rows(FALSE, 0, NULL, NULL)); +} + + +/* + Get time to read + + SYNOPSIS + read_time() + index Index number used + ranges Number of ranges + rows Number of rows + + RETURN VALUE + time for read + + DESCRIPTION + This will be optimised later to include whether or not the index can + be used with partitioning. To achieve we need to add another parameter + that specifies how many of the index fields that are bound in the ranges. + Possibly added as a new call to handlers. +*/ + +double ha_partition::read_time(uint index, uint ranges, ha_rows rows) +{ + DBUG_ENTER("ha_partition::read_time"); + + DBUG_RETURN(m_file[0]->read_time(index, ranges, rows)); } diff --git a/sql/ha_partition.h b/sql/ha_partition.h index c08b1f77eca..9f6d9e0a5ba 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -547,6 +547,18 @@ public: ------------------------------------------------------------------------- */ +private: + /* + Helper function to get the minimum number of partitions to use for + the optimizer hints/cost calls. + */ + void partitions_optimizer_call_preparations(uint *num_used_parts, + uint *check_min_num, + uint *first); + ha_rows estimate_rows(bool is_records_in_range, uint inx, + key_range *min_key, key_range *max_key); +public: + /* keys_to_use_for_scanning can probably be implemented as the intersection of all underlying handlers if mixed handlers are used. From 98fd304278ca029b56671412e8bec72ed4f17537 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Tue, 17 Nov 2009 22:47:34 +0100 Subject: [PATCH 045/344] backport of bug#45904 from mysql-pe to 5.1 sql/sql_partition.cc: Bug#45904 Used list_of_part_fields instead of list_of_subpart_fields to discover if KEY subpartitioning => caused failure when charset=utf8 even for subpartitioning by key, would also allow for subpartitioning by hash with utf8 erroneously --- mysql-test/r/partition.result | 7 +++++++ mysql-test/t/partition.test | 11 +++++++++++ sql/sql_partition.cc | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 6611d39628f..425f1e85d00 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -50,6 +50,13 @@ t1 CREATE TABLE `t1` ( PARTITION p3 VALUES LESS THAN (733969) ENGINE = MyISAM, PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */ DROP TABLE t1; +create table t1 (a int NOT NULL, b varchar(5) NOT NULL) +default charset=utf8 +partition by list (a) +subpartition by key (b) +(partition p0 values in (1), +partition p1 values in (2)); +drop table t1; create table t1 (a int, b int, key(a)) partition by list (a) ( partition p0 values in (1), diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 1dfc53c6232..1d77128d33b 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -61,6 +61,17 @@ SELECT * FROM t1; SHOW CREATE TABLE t1; DROP TABLE t1; +# +# Bug#45904: Error when CHARSET=utf8 and subpartitioning +# +create table t1 (a int NOT NULL, b varchar(5) NOT NULL) +default charset=utf8 +partition by list (a) +subpartition by key (b) +(partition p0 values in (1), + partition p1 values in (2)); +drop table t1; + # # Bug#44059: rec_per_key on empty partition gives weird optimiser results # diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 04d22174c8e..d07c07f11c7 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1679,7 +1679,7 @@ bool fix_partition_func(THD *thd, TABLE *table, if (((part_info->part_type != HASH_PARTITION || part_info->list_of_part_fields == FALSE) && check_part_func_fields(part_info->part_field_array, TRUE)) || - (part_info->list_of_part_fields == FALSE && + (part_info->list_of_subpart_fields == FALSE && part_info->is_sub_partitioned() && check_part_func_fields(part_info->subpart_field_array, TRUE))) { From 41ba42928628fc555cb2f222fbacefa178f63f0a Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Wed, 18 Nov 2009 10:02:21 +0100 Subject: [PATCH 046/344] Bug #47682 strange behaviour of INSERT DELAYED The problem was a "self-deadlock" if the connection issuing INSERT DELAYED had both the global read lock (FLUSH TABLES WITH READ LOCK) and LOCK TABLES mode active. The table being inserted into had to be different from the table(s) locked by LOCK TABLES. For INSERT DELAYED, the connection thread waits until the handler thread has opened and locked its table before returning. But since the global read lock was active, the handler thread would be unable to lock and would wait for the global read lock to go away. So the handler thread would be waiting for the connection thread to release the global read lock while the connection thread was waiting for the handler thread to lock the table. This gave a "self-deadlock" (same connection, different threads). The deadlock would only happen if we also had LOCK TABLES mode since the INSERT otherwise will try to get protection against global read lock before starting the handler thread. It will then notice that the global read lock is owned by the same connection and report ER_CANT_UPDATE_WITH_READLOCK. This patch removes the deadlock by reporting ER_CANT_UPDATE_WITH_READLOCK also if we are inside LOCK TABLES mode. Test case added to delayed.test. --- mysql-test/r/delayed.result | 12 ++++++++++++ mysql-test/t/delayed.test | 22 ++++++++++++++++++++++ sql/sql_insert.cc | 16 ++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index 4d5d656f3ce..11156b0f883 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -310,4 +310,16 @@ a b 2 2 drop table t1; set global low_priority_updates = @old_delayed_updates; +# +# Bug #47682 strange behaviour of INSERT DELAYED +# +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 (f1 integer); +CREATE TABLE t2 (f1 integer); +FLUSH TABLES WITH READ LOCK; +LOCK TABLES t1 READ; +INSERT DELAYED INTO t2 VALUES (1); +ERROR HY000: Can't execute the query because you have a conflicting read lock +UNLOCK TABLES; +DROP TABLE t1, t2; End of 5.1 tests diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test index 94ad22b80d0..99ec99803a7 100644 --- a/mysql-test/t/delayed.test +++ b/mysql-test/t/delayed.test @@ -328,4 +328,26 @@ drop table t1; set global low_priority_updates = @old_delayed_updates; + +--echo # +--echo # Bug #47682 strange behaviour of INSERT DELAYED +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1 (f1 integer); +CREATE TABLE t2 (f1 integer); + +FLUSH TABLES WITH READ LOCK; +LOCK TABLES t1 READ; + +--error ER_CANT_UPDATE_WITH_READLOCK +INSERT DELAYED INTO t2 VALUES (1); + +UNLOCK TABLES; +DROP TABLE t1, t2; + + --echo End of 5.1 tests diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 6e2b3903b52..e9a36629c66 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -500,6 +500,22 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list) DBUG_ENTER("open_and_lock_for_insert_delayed"); #ifndef EMBEDDED_LIBRARY + if (thd->locked_tables && thd->global_read_lock) + { + /* + If this connection has the global read lock, the handler thread + will not be able to lock the table. It will wait for the global + read lock to go away, but this will never happen since the + connection thread will be stuck waiting for the handler thread + to open and lock the table. + If we are not in locked tables mode, INSERT will seek protection + against the global read lock (and fail), thus we will only get + to this point in locked tables mode. + */ + my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0)); + DBUG_RETURN(TRUE); + } + if (delayed_get_table(thd, table_list)) DBUG_RETURN(TRUE); From 3987c7ac4b7ecfde471c10386bb413205809dfe1 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Wed, 18 Nov 2009 10:32:03 +0100 Subject: [PATCH 047/344] Bug #46425 crash in Diagnostics_area::set_ok_status , empty statement, DELETE IGNORE The ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG error was set in the diagnostics area when it happened, but the DELETE cleanup code never checked for a non-fatal error condition, thus trying to set diag.area to "ok". This triggered an assert checking that the diag.area was empty. The fix was to test if there existed a non-fatal error condition (thd->is_error() before ok'ing the operation. --- mysql-test/r/delete.result | 13 +++++++++++++ mysql-test/t/delete.test | 22 ++++++++++++++++++++++ sql/sql_delete.cc | 3 ++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index 0124a7da35a..1df19a75854 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -324,3 +324,16 @@ a 1 2 DROP TABLE t1, t2, t3; +# +# Bug #46425 crash in Diagnostics_area::set_ok_status, +# empty statement, DELETE IGNORE +# +CREATE table t1 (i INTEGER); +INSERT INTO t1 VALUES (1); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +BEGIN +INSERT INTO t1 SELECT * FROM t1 AS A; +END | +DELETE IGNORE FROM t1; +ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. +DROP TABLE t1; diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index d77f5eb128b..a5dff38c078 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -336,3 +336,25 @@ SELECT * FROM t2; SELECT * FROM t3; DROP TABLE t1, t2, t3; + +--echo # +--echo # Bug #46425 crash in Diagnostics_area::set_ok_status, +--echo # empty statement, DELETE IGNORE +--echo # + +CREATE table t1 (i INTEGER); + +INSERT INTO t1 VALUES (1); + +--delimiter | + +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +BEGIN + INSERT INTO t1 SELECT * FROM t1 AS A; +END | + +--delimiter ; +--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG +DELETE IGNORE FROM t1; + +DROP TABLE t1; \ No newline at end of file diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index b80138af7f2..93b19c5b233 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -426,7 +426,8 @@ cleanup: } DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table); free_underlaid_joins(thd, select_lex); - if (error < 0 || (thd->lex->ignore && !thd->is_fatal_error)) + if (error < 0 || + (thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error)) { /* If a TRUNCATE TABLE was issued, the number of rows should be reported as From 7524b96102bcfeb7366b88d307bb53e9fe8c309f Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Wed, 18 Nov 2009 13:49:45 +0100 Subject: [PATCH 048/344] Postfix for Bug #47682 strange behaviour of INSERT DELAYED Fixed a problem with the test case when executed with ps-protocol. There the conflicing lock would be noticed during prepare, not during execution of the insert - leading to a different (but equally appropriate) error message. --- mysql-test/r/delayed.result | 2 +- mysql-test/t/delayed.test | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index 11156b0f883..d8048a703a2 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -319,7 +319,7 @@ CREATE TABLE t2 (f1 integer); FLUSH TABLES WITH READ LOCK; LOCK TABLES t1 READ; INSERT DELAYED INTO t2 VALUES (1); -ERROR HY000: Can't execute the query because you have a conflicting read lock +Got one of the listed errors UNLOCK TABLES; DROP TABLE t1, t2; End of 5.1 tests diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test index 99ec99803a7..689341391c9 100644 --- a/mysql-test/t/delayed.test +++ b/mysql-test/t/delayed.test @@ -343,7 +343,9 @@ CREATE TABLE t2 (f1 integer); FLUSH TABLES WITH READ LOCK; LOCK TABLES t1 READ; ---error ER_CANT_UPDATE_WITH_READLOCK +# ER_CANT_UPDATE_WITH_READLOCK with normal execution +# ER_TABLE_NOT_LOCKED when executed as prepared statement +--error ER_CANT_UPDATE_WITH_READLOCK, ER_TABLE_NOT_LOCKED INSERT DELAYED INTO t2 VALUES (1); UNLOCK TABLES; From 2f78abd21b11aa53fc8426c018b78621f77157f7 Mon Sep 17 00:00:00 2001 From: Sven Sandberg Date: Wed, 18 Nov 2009 15:50:31 +0100 Subject: [PATCH 049/344] BUG#47995: Mark system functions as unsafe Problem: Some system functions that could return different values on master and slave were not marked unsafe. In particular: GET_LOCK IS_FREE_LOCK IS_USED_LOCK MASTER_POS_WAIT RELEASE_LOCK SLEEP SYSDATE VERSION Fix: Mark these functions unsafe. mysql-test/extra/rpl_tests/rpl_stm_000001.test: - The test does not work in mixed mode any more, since it tries to simulate an error in the sql thread in a query that uses get_lock. Since get_lock now causes the query to be logged in row format, the error didn't happen. Hence, we now force statement mode. - Warnings must be disabled when the unsafe query is issued. - Replaced some save_master_pos+connection slave+sync_with_master by sync_slave_with_master. mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result: updated result file mysql-test/suite/binlog/r/binlog_stm_row.result: updated result file mysql-test/suite/binlog/r/binlog_unsafe.result: updated result file mysql-test/suite/binlog/t/binlog_killed.test: binlog_killed only works in statement format now, since it switches to row mode in mixed mode. mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test: suppress warnings for unsafe statements mysql-test/suite/binlog/t/binlog_stm_row.test: - Suppress warnings in test that causes warnings. - The test sets binlog format explicitly, so no need to execute it twice. mysql-test/suite/binlog/t/binlog_unsafe.test: Added test for all unsafe system functions. This test also includes system functions that were unsafe prior to BUG#47995. mysql-test/suite/rpl/r/rpl_err_ignoredtable.result: updated result file mysql-test/suite/rpl/r/rpl_get_lock.result: updated result file mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result: new result file mysql-test/suite/rpl/r/rpl_stm_000001.result: updated result file mysql-test/suite/rpl/r/rpl_trigger.result: updated result file mysql-test/suite/rpl/t/rpl_err_ignoredtable.test: - suppress warnings for unsafe statement - replaced save_master_pos+connection slave+sync_with_master with sync_slave_with_master mysql-test/suite/rpl/t/rpl_get_lock.test: update test case that causes new warnings mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test: Added new test case for nondeterministic functions. mysql-test/suite/rpl/t/rpl_trigger.test: update test case that causes new warnings sql/item_create.cc: Marked some system functions unsafe. sql/item_strfunc.cc: Clarified comment related to this bug. sql/sql_yacc.yy: Marked sysdate unsafe. --- .../extra/rpl_tests/rpl_stm_000001.test | 33 ++++---- .../r/binlog_stm_mix_innodb_myisam.result | 3 + .../suite/binlog/r/binlog_stm_row.result | 3 + .../suite/binlog/r/binlog_unsafe.result | 82 +++++++++++++++++++ mysql-test/suite/binlog/t/binlog_killed.test | 2 +- .../t/binlog_stm_mix_innodb_myisam.test | 3 + mysql-test/suite/binlog/t/binlog_stm_row.test | 5 +- mysql-test/suite/binlog/t/binlog_unsafe.test | 52 ++++++++++++ .../suite/rpl/r/rpl_err_ignoredtable.result | 1 + mysql-test/suite/rpl/r/rpl_get_lock.result | 1 + .../r/rpl_nondeterministic_functions.result | 26 ++++++ mysql-test/suite/rpl/r/rpl_stm_000001.result | 1 + mysql-test/suite/rpl/r/rpl_trigger.result | 1 + .../suite/rpl/t/rpl_err_ignoredtable.test | 21 ++--- mysql-test/suite/rpl/t/rpl_get_lock.test | 5 ++ .../rpl/t/rpl_nondeterministic_functions.test | 53 ++++++++++++ mysql-test/suite/rpl/t/rpl_trigger.test | 10 +++ sql/item_create.cc | 8 ++ sql/item_strfunc.cc | 5 +- sql/sql_yacc.yy | 8 ++ 20 files changed, 290 insertions(+), 33 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result create mode 100644 mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test diff --git a/mysql-test/extra/rpl_tests/rpl_stm_000001.test b/mysql-test/extra/rpl_tests/rpl_stm_000001.test index 869a9e3b07c..4397e81aadf 100644 --- a/mysql-test/extra/rpl_tests/rpl_stm_000001.test +++ b/mysql-test/extra/rpl_tests/rpl_stm_000001.test @@ -1,6 +1,11 @@ --- source include/have_binlog_format_mixed_or_statement.inc +# Requires binlog_format=statement format since query involving +# get_lock() is logged in row format if binlog_format=mixed or row. +-- source include/have_binlog_format_statement.inc -- source include/master-slave.inc +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); + +# Load some data into t1 create table t1 (word char(20) not null); load data infile '../../std_data/words.dat' into table t1; --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR @@ -10,9 +15,7 @@ select * from t1 limit 10; # # Test slave with wrong password # -save_master_pos; -connection slave; -sync_with_master; +sync_slave_with_master; stop slave; connection master; set password for root@"localhost" = password('foo'); @@ -29,16 +32,12 @@ sleep 2; create table t3(n int); insert into t3 values(1),(2); -save_master_pos; -connection slave; -sync_with_master; +sync_slave_with_master; select * from t3; select sum(length(word)) from t1; connection master; drop table t1,t3; -save_master_pos; -connection slave; -sync_with_master; +sync_slave_with_master; # Test if the slave SQL thread can be more than 16K behind the slave # I/O thread (> IO_SIZE) @@ -77,12 +76,13 @@ unlock tables; connection master; create table t2(id int); insert into t2 values(connection_id()); -save_master_pos; connection master1; # Avoid generating result create temporary table t3(n int); +--disable_warnings insert into t3 select get_lock('crash_lock%20C', 1) from t2; +--enable_warnings connection master; send update t1 set n = n + get_lock('crash_lock%20C', 2); @@ -93,8 +93,11 @@ kill @id; # We don't drop t3 as this is a temporary table drop table t2; connection master; +# The get_lock function causes warning for unsafe statement. +--disable_warnings --error 1317,2013 reap; +--enable_warnings connection slave; # The SQL slave thread should now have stopped because the query was killed on # the master (so it has a non-zero error code in the binlog). @@ -117,16 +120,12 @@ insert into mysql.user (Host, User, Password) select select_priv,user from mysql.user where user = _binary'blafasel2'; update mysql.user set Select_priv = "Y" where User= _binary"blafasel2"; select select_priv,user from mysql.user where user = _binary'blafasel2'; -save_master_pos; -connection slave; -sync_with_master; +sync_slave_with_master; select n from t1; select select_priv,user from mysql.user where user = _binary'blafasel2'; connection master1; drop table t1; delete from mysql.user where user="blafasel2"; -save_master_pos; -connection slave; -sync_with_master; +sync_slave_with_master; # End of 4.1 tests diff --git a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result index 06c57fba2e7..de83c7a873d 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result @@ -1,3 +1,4 @@ +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); drop table if exists t1, t2; create table t1 (a int) engine=innodb; create table t2 (a int) engine=myisam; @@ -224,6 +225,8 @@ create table t0 (n int); insert t0 select * from t1; set autocommit=1; insert into t0 select GET_LOCK("lock1",null); +Warnings: +Note 1592 Statement may not be safe to log in statement format. set autocommit=0; create table t2 (n int) engine=innodb; insert into t2 values (3); diff --git a/mysql-test/suite/binlog/r/binlog_stm_row.result b/mysql-test/suite/binlog/r/binlog_stm_row.result index f96073a2b92..e74a05e8827 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_row.result +++ b/mysql-test/suite/binlog/r/binlog_stm_row.result @@ -1,3 +1,4 @@ +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; set @saved_global_binlog_format = @@global.binlog_format; @@ -29,6 +30,8 @@ SELECT RELEASE_LOCK('Bug#34306'); RELEASE_LOCK('Bug#34306') 1 # con2 +Warnings: +Note 1592 Statement may not be safe to log in statement format. SELECT RELEASE_LOCK('Bug#34306'); RELEASE_LOCK('Bug#34306') 1 diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result index 4c2c32ad8f1..8bbf993a727 100644 --- a/mysql-test/suite/binlog/r/binlog_unsafe.result +++ b/mysql-test/suite/binlog/r/binlog_unsafe.result @@ -327,4 +327,86 @@ Warnings: Note 1592 Statement may not be safe to log in statement format. DROP TABLE t1, t2; SET @@SESSION.SQL_MODE = @save_sql_mode; +CREATE TABLE t1 (a VARCHAR(1000)); +INSERT INTO t1 VALUES (CURRENT_USER()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (FOUND_ROWS()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (GET_LOCK('tmp', 1)); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (IS_FREE_LOCK('tmp')); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (IS_USED_LOCK('tmp')); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (LOAD_FILE('../../std_data/words2.dat')); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (MASTER_POS_WAIT('dummy arg', 4711, 1)); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (RELEASE_LOCK('tmp')); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (ROW_COUNT()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (SESSION_USER()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (SLEEP(1)); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (SYSDATE()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (SYSTEM_USER()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (USER()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (UUID()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (UUID_SHORT()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (VERSION()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +DELETE FROM t1; +SET TIMESTAMP=1000000; +INSERT INTO t1 VALUES +(CURDATE()), +(CURRENT_DATE()), +(CURRENT_TIME()), +(CURRENT_TIMESTAMP()), +(CURTIME()), +(LOCALTIME()), +(LOCALTIMESTAMP()), +(NOW()), +(UNIX_TIMESTAMP()), +(UTC_DATE()), +(UTC_TIME()), +(UTC_TIMESTAMP()); +SELECT * FROM t1; +a +1970-01-12 +1970-01-12 +16:46:40 +1970-01-12 16:46:40 +16:46:40 +1970-01-12 16:46:40 +1970-01-12 16:46:40 +1970-01-12 16:46:40 +1000000 +1970-01-12 +13:46:40 +1970-01-12 13:46:40 +DROP TABLE t1; "End of tests" diff --git a/mysql-test/suite/binlog/t/binlog_killed.test b/mysql-test/suite/binlog/t/binlog_killed.test index 9b30ec4a0db..e2db326129d 100644 --- a/mysql-test/suite/binlog/t/binlog_killed.test +++ b/mysql-test/suite/binlog/t/binlog_killed.test @@ -1,5 +1,5 @@ -- source include/have_innodb.inc --- source include/have_binlog_format_mixed_or_statement.inc +-- source include/have_binlog_format_statement.inc # You cannot use `KILL' with the Embedded MySQL Server library, # because the embedded server merely runs inside the threads of the host diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test index e4661526982..ba3da73dead 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test +++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test @@ -2,6 +2,9 @@ # For both statement and row based bin logs 9/19/2005 [jbm] -- source include/have_binlog_format_statement.inc + +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); + -- source extra/binlog_tests/mix_innodb_myisam_binlog.test set @@session.binlog_format=statement; diff --git a/mysql-test/suite/binlog/t/binlog_stm_row.test b/mysql-test/suite/binlog/t/binlog_stm_row.test index e923faae940..29b0a69330d 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_row.test +++ b/mysql-test/suite/binlog/t/binlog_stm_row.test @@ -1,5 +1,8 @@ --source include/have_log_bin.inc ---source include/have_binlog_format_row_or_statement.inc +# Test sets its own binlog_format, so we restrict it to run only once +--source include/have_binlog_format_row.inc + +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); # Get rid of previous tests binlog --disable_query_log diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test index c4e1f31cbce..1acb4d090ca 100644 --- a/mysql-test/suite/binlog/t/binlog_unsafe.test +++ b/mysql-test/suite/binlog/t/binlog_unsafe.test @@ -388,4 +388,56 @@ DELETE FROM t1 LIMIT 1; DROP TABLE t1, t2; SET @@SESSION.SQL_MODE = @save_sql_mode; + +# +# BUG#47995: Mark user functions as unsafe +# +# Test that the system functions that are supposed to be marked unsafe +# generate a warning. Each INSERT statement below should generate a +# warning. +# + +CREATE TABLE t1 (a VARCHAR(1000)); +INSERT INTO t1 VALUES (CURRENT_USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (FOUND_ROWS()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (GET_LOCK('tmp', 1)); +INSERT INTO t1 VALUES (IS_FREE_LOCK('tmp')); +INSERT INTO t1 VALUES (IS_USED_LOCK('tmp')); +INSERT INTO t1 VALUES (LOAD_FILE('../../std_data/words2.dat')); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (MASTER_POS_WAIT('dummy arg', 4711, 1)); +INSERT INTO t1 VALUES (RELEASE_LOCK('tmp')); +INSERT INTO t1 VALUES (ROW_COUNT()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (SESSION_USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (SLEEP(1)); +INSERT INTO t1 VALUES (SYSDATE()); +INSERT INTO t1 VALUES (SYSTEM_USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (UUID()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (UUID_SHORT()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (VERSION()); +DELETE FROM t1; + +# Since we replicate the TIMESTAMP variable, functions affected by the +# TIMESTAMP variable are safe to replicate. So we check that the +# following following functions depend on the TIMESTAMP variable and +# don't generate a warning. + +SET TIMESTAMP=1000000; +INSERT INTO t1 VALUES + (CURDATE()), + (CURRENT_DATE()), + (CURRENT_TIME()), + (CURRENT_TIMESTAMP()), + (CURTIME()), + (LOCALTIME()), + (LOCALTIMESTAMP()), + (NOW()), + (UNIX_TIMESTAMP()), + (UTC_DATE()), + (UTC_TIME()), + (UTC_TIMESTAMP()); +SELECT * FROM t1; + +DROP TABLE t1; + --echo "End of tests" diff --git a/mysql-test/suite/rpl/r/rpl_err_ignoredtable.result b/mysql-test/suite/rpl/r/rpl_err_ignoredtable.result index f211d5d9a2f..75fefdad2a2 100644 --- a/mysql-test/suite/rpl/r/rpl_err_ignoredtable.result +++ b/mysql-test/suite/rpl/r/rpl_err_ignoredtable.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); create table t1 (a int primary key); create table t4 (a int primary key); insert into t1 values (1),(1); diff --git a/mysql-test/suite/rpl/r/rpl_get_lock.result b/mysql-test/suite/rpl/r/rpl_get_lock.result index f7c9541bd9f..cbad759b17f 100644 --- a/mysql-test/suite/rpl/r/rpl_get_lock.result +++ b/mysql-test/suite/rpl/r/rpl_get_lock.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); create table t1(n int); insert into t1 values(get_lock("lock",2)); select get_lock("lock",2); diff --git a/mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result b/mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result new file mode 100644 index 00000000000..c4842a284cd --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result @@ -0,0 +1,26 @@ +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 VARCHAR(1000)); +INSERT INTO t1 VALUES (CONNECTION_ID()); +INSERT INTO t1 VALUES (CONNECTION_ID()); +INSERT INTO t1 VALUES +(CURDATE()), +(CURRENT_DATE()), +(CURRENT_TIME()), +(CURRENT_TIMESTAMP()), +(CURTIME()), +(LOCALTIME()), +(LOCALTIMESTAMP()), +(NOW()), +(UNIX_TIMESTAMP()), +(UTC_DATE()), +(UTC_TIME()), +(UTC_TIMESTAMP()); +INSERT INTO t1 VALUES (RAND()); +INSERT INTO t1 VALUES (LAST_INSERT_ID()); +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; diff --git a/mysql-test/suite/rpl/r/rpl_stm_000001.result b/mysql-test/suite/rpl/r/rpl_stm_000001.result index 24e454eb876..c2a24cbaa82 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_000001.result +++ b/mysql-test/suite/rpl/r/rpl_stm_000001.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); create table t1 (word char(20) not null); load data infile '../../std_data/words.dat' into table t1; load data local infile 'MYSQL_TEST_DIR/std_data/words.dat' into table t1; diff --git a/mysql-test/suite/rpl/r/rpl_trigger.result b/mysql-test/suite/rpl/r/rpl_trigger.result index 3d7757613a7..86534fa8f7d 100644 --- a/mysql-test/suite/rpl/r/rpl_trigger.result +++ b/mysql-test/suite/rpl/r/rpl_trigger.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; DROP TABLE IF EXISTS t3; diff --git a/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test index e77cd308f39..f358c0ee356 100644 --- a/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test +++ b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test @@ -7,6 +7,8 @@ -- source include/master-slave.inc +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); + connection master; create table t1 (a int primary key); create table t4 (a int primary key); @@ -14,19 +16,15 @@ create table t4 (a int primary key); --error 1022, ER_DUP_ENTRY 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; +sync_slave_with_master; # 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 ORDER BY a; connection master; drop table t1; -save_master_pos; -connection slave; -sync_with_master; +sync_slave_with_master; # Now test that even critical errors (connection killed) # are ignored if rules allow it. @@ -50,18 +48,17 @@ kill @id; drop table t2,t3; insert into t4 values (3),(4); connection master; +# The get_lock function causes warning for unsafe statement. +--disable_warnings --error 0,1317,2013 reap; +--enable_warnings connection master1; -save_master_pos; -connection slave; -sync_with_master; +sync_slave_with_master; SELECT * FROM test.t4 ORDER BY a; connection master1; DROP TABLE test.t4; -save_master_pos; -connection slave; -sync_with_master; +sync_slave_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/suite/rpl/t/rpl_get_lock.test b/mysql-test/suite/rpl/t/rpl_get_lock.test index 945bd98c993..87366f41ba2 100644 --- a/mysql-test/suite/rpl/t/rpl_get_lock.test +++ b/mysql-test/suite/rpl/t/rpl_get_lock.test @@ -1,7 +1,12 @@ source include/master-slave.inc; +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); + create table t1(n int); +# Use of get_lock gives a warning for unsafeness if binlog_format=statement +--disable_warnings insert into t1 values(get_lock("lock",2)); +--enable_warnings dirty_close master; connection master1; select get_lock("lock",2); diff --git a/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test b/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test new file mode 100644 index 00000000000..a30eb3be374 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test @@ -0,0 +1,53 @@ +# ==== Purpose ==== +# +# Test that nondeterministic system functions are correctly replicated. +# +# (Some functions are only correctly replicated if binlog_format=MIXED +# or ROW. See binlog_unsafe.test for a test that those variables are +# indeed unsafe.) +# +# ==== Implementation ==== +# +# We insert the values of each unsafe function into a table. Then we +# replicate and check that the table is identical on slave. +# +# ==== Related bugs ==== +# +# BUG#47995 + +--source include/master-slave.inc + +CREATE TABLE t1 (a VARCHAR(1000)); + +# We replicate the connection_id in the query_log_event +INSERT INTO t1 VALUES (CONNECTION_ID()); +--connection master1 +INSERT INTO t1 VALUES (CONNECTION_ID()); + +# We replicate the TIMESTAMP variable, so the following functions that +# are affected by the TIMESTAMP variable should be safe to replicate. +INSERT INTO t1 VALUES + (CURDATE()), + (CURRENT_DATE()), + (CURRENT_TIME()), + (CURRENT_TIMESTAMP()), + (CURTIME()), + (LOCALTIME()), + (LOCALTIMESTAMP()), + (NOW()), + (UNIX_TIMESTAMP()), + (UTC_DATE()), + (UTC_TIME()), + (UTC_TIMESTAMP()); + +# We replicate the random seed in a rand_log_event +INSERT INTO t1 VALUES (RAND()); +# We replicate the last_insert_id in an intvar_log_event +INSERT INTO t1 VALUES (LAST_INSERT_ID()); + +--sync_slave_with_master +--let $diff_table_1= master:test.t1 +--let $diff_table_2= slave:test.t1 +--source include/diff_tables.inc + +DROP TABLE t1; diff --git a/mysql-test/suite/rpl/t/rpl_trigger.test b/mysql-test/suite/rpl/t/rpl_trigger.test index a3929458026..4b40fbea719 100644 --- a/mysql-test/suite/rpl/t/rpl_trigger.test +++ b/mysql-test/suite/rpl/t/rpl_trigger.test @@ -5,6 +5,8 @@ --source include/have_binlog_format_mixed_or_statement.inc --source include/master-slave.inc +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); + --disable_warnings DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; @@ -89,7 +91,11 @@ end | delimiter ;| +# The trigger causes a warning for unsafe statement when +# binlog_format=statement since it uses get_lock. +--disable_warnings insert into t1 set a = now(); +--enable_warnings select a=b && a=c from t1; let $time=`select a from t1`; @@ -135,7 +141,11 @@ disconnect con2; truncate table t1; drop trigger t1_first; +# The trigger causes a warning for unsafe statement when +# binlog_format=statement since it uses get_lock. +--disable_warnings insert into t1 values ("2003-03-03","2003-03-03","2003-03-03"),(bug12480(),bug12480(),bug12480()),(now(),now(),now()); +--enable_warnings select a=b && a=c from t1; drop function bug12480; diff --git a/sql/item_create.cc b/sql/item_create.cc index 7991d9adf82..53aa8081da1 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -3524,6 +3524,7 @@ Create_func_get_lock Create_func_get_lock::s_singleton; Item* Create_func_get_lock::create(THD *thd, Item *arg1, Item *arg2) { + thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_get_lock(arg1, arg2); } @@ -3635,6 +3636,7 @@ Create_func_is_free_lock Create_func_is_free_lock::s_singleton; Item* Create_func_is_free_lock::create(THD *thd, Item *arg1) { + thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_is_free_lock(arg1); } @@ -3645,6 +3647,7 @@ Create_func_is_used_lock Create_func_is_used_lock::s_singleton; Item* Create_func_is_used_lock::create(THD *thd, Item *arg1) { + thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_is_used_lock(arg1); } @@ -3961,6 +3964,8 @@ Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name, Item *func= NULL; int arg_count= 0; + thd->lex->set_stmt_unsafe(); + if (item_list != NULL) arg_count= item_list->elements; @@ -4203,6 +4208,7 @@ Create_func_release_lock Create_func_release_lock::s_singleton; Item* Create_func_release_lock::create(THD *thd, Item *arg1) { + thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_release_lock(arg1); } @@ -4325,6 +4331,7 @@ Create_func_sleep Create_func_sleep::s_singleton; Item* Create_func_sleep::create(THD *thd, Item *arg1) { + thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_sleep(arg1); } @@ -4591,6 +4598,7 @@ Create_func_version Create_func_version::s_singleton; Item* Create_func_version::create(THD *thd) { + thd->lex->set_stmt_unsafe(); return new (thd->mem_root) Item_static_string_func("version()", server_version, (uint) strlen(server_version), diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 39c4b8e7033..183a628f8e4 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1827,8 +1827,9 @@ String *Item_func_database::val_str(String *str) /** - @todo - make USER() replicate properly (currently it is replicated to "") + @note USER() is replicated correctly if binlog_format=ROW or (as of + BUG#28086) binlog_format=MIXED, but is incorrectly replicated to '' + if binlog_format=STATEMENT. */ bool Item_func_user::init(const char *user, const char *host) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 86bef83cf1a..28e1272e244 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7523,6 +7523,14 @@ function_call_nonkeyword: } | SYSDATE optional_braces { + /* + Unlike other time-related functions, SYSDATE() is + replication-unsafe because it is not affected by the + TIMESTAMP variable. It is unsafe even if + sysdate_is_now=1, because the slave may have + sysdate_is_now=0. + */ + Lex->set_stmt_unsafe(); if (global_system_variables.sysdate_is_now == 0) $$= new (YYTHD->mem_root) Item_func_sysdate_local(); else From ed9e3409e4e034f353e87874d960c1d320c63f7d Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 18 Nov 2009 17:24:10 +0200 Subject: [PATCH 050/344] Bug#48864: MySQL fails to compile on 64 bit Fedora 12 Fixed 2 errors in comp_err executable : 1. Wrong (off by 1) length passed to my_checksum() 2. strmov() was used on overlapping strings. This is not legal according to the docs in stpcpy(). Used the overlap safe memmove() instead. --- extra/comp_err.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/extra/comp_err.c b/extra/comp_err.c index 8814a045f36..342085b64d6 100644 --- a/extra/comp_err.c +++ b/extra/comp_err.c @@ -660,7 +660,7 @@ static ha_checksum checksum_format_specifier(const char* msg) case 'u': case 'x': case 's': - chksum= my_checksum(chksum, start, (uint) (p - start)); + chksum= my_checksum(chksum, start, (uint) (p + 1 - start)); start= 0; /* Not in format specifier anymore */ break; @@ -1030,8 +1030,10 @@ static char *parse_text_line(char *pos) { int i, nr; char *row= pos; + size_t len; DBUG_ENTER("parse_text_line"); + len= strlen (pos); while (*pos) { if (*pos == '\\') @@ -1039,11 +1041,11 @@ static char *parse_text_line(char *pos) switch (*++pos) { case '\\': case '"': - VOID(strmov(pos - 1, pos)); + VOID(memmove (pos - 1, pos, len - (row - pos))); break; case 'n': pos[-1]= '\n'; - VOID(strmov(pos, pos + 1)); + VOID(memmove (pos, pos + 1, len - (row - pos))); break; default: if (*pos >= '0' && *pos < '8') @@ -1053,10 +1055,10 @@ static char *parse_text_line(char *pos) nr= nr * 8 + (*(pos++) - '0'); pos -= i; pos[-1]= nr; - VOID(strmov(pos, pos + i)); + VOID(memmove (pos, pos + i, len - (row - pos))); } else if (*pos) - VOID(strmov(pos - 1, pos)); /* Remove '\' */ + VOID(memmove (pos - 1, pos, len - (row - pos))); /* Remove '\' */ } } else From 405c9310cfe2cf4673f5fb66dc221016b4e92ed6 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 19 Nov 2009 18:26:19 +0200 Subject: [PATCH 051/344] Bug #48665: sql-bench's insert test fails due to wrong result When merging ranges during calculation of the result of OR to two range sets the current range may be obsoleted by the resulting merged range. The first overlapping range can be obsoleted as well. Fixed by moving the pointer to the first overlapping range to the pointer of the resulting union range. Added few comments at key places in key_or(). --- mysql-test/r/range.result | 17 +++++++++++++++++ mysql-test/t/range.test | 21 +++++++++++++++++++++ sql/opt_range.cc | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 2306f8b501e..ab40eefdc82 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -1603,4 +1603,21 @@ SELECT str_to_date('', '%Y-%m-%d'); str_to_date('', '%Y-%m-%d') 0000-00-00 DROP TABLE t1, t2; +# +# Bug #48665: sql-bench's insert test fails due to wrong result +# +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a)); +INSERT INTO t1 VALUES (0,0), (1,1); +EXPLAIN +SELECT * FROM t1 FORCE INDEX (PRIMARY) +WHERE (a>=1 AND a<=2) OR (a>=4 AND a<=5) OR (a>=0 AND a <=10); +id select_type table type possible_keys key key_len ref rows Extra +@ @ @ range @ @ @ @ @ @ +# Should return 2 rows +SELECT * FROM t1 FORCE INDEX (PRIMARY) +WHERE (a>=1 AND a<=2) OR (a>=4 AND a<=5) OR (a>=0 AND a <=10); +a b +0 0 +1 1 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index 3a845471cd0..736d65792c5 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -1260,4 +1260,25 @@ SELECT str_to_date('', '%Y-%m-%d'); DROP TABLE t1, t2; + +--echo # +--echo # Bug #48665: sql-bench's insert test fails due to wrong result +--echo # + +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a)); + +INSERT INTO t1 VALUES (0,0), (1,1); + +--replace_column 1 @ 2 @ 3 @ 5 @ 6 @ 7 @ 8 @ 9 @ 10 @ +EXPLAIN +SELECT * FROM t1 FORCE INDEX (PRIMARY) + WHERE (a>=1 AND a<=2) OR (a>=4 AND a<=5) OR (a>=0 AND a <=10); + +--echo # Should return 2 rows +SELECT * FROM t1 FORCE INDEX (PRIMARY) + WHERE (a>=1 AND a<=2) OR (a>=4 AND a<=5) OR (a>=0 AND a <=10); + +DROP TABLE t1; + + --echo End of 5.1 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 5f9bae22c70..909e3d36be5 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6671,6 +6671,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) else if ((cmp=tmp->cmp_max_to_min(key2)) < 0) { // Found tmp.max < key2.min SEL_ARG *next=tmp->next; + /* key1 on the left of key2 non-overlapping */ if (cmp == -2 && eq_tree(tmp->next_key_part,key2->next_key_part)) { // Join near ranges like tmp.max < 0 and key2.min >= 0 @@ -6699,6 +6700,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) int tmp_cmp; if ((tmp_cmp=tmp->cmp_min_to_max(key2)) > 0) // if tmp.min > key2.max { + /* tmp is on the right of key2 non-overlapping */ if (tmp_cmp == 2 && eq_tree(tmp->next_key_part,key2->next_key_part)) { // ranges are connected tmp->copy_min_to_min(key2); @@ -6733,25 +6735,52 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) } } - // tmp.max >= key2.min && tmp.min <= key.max (overlapping ranges) + /* + tmp.min >= key2.min && tmp.min <= key.max (overlapping ranges) + key2.min <= tmp.min <= key2.max + */ if (eq_tree(tmp->next_key_part,key2->next_key_part)) { if (tmp->is_same(key2)) { + /* + Found exact match of key2 inside key1. + Use the relevant range in key1. + */ tmp->merge_flags(key2); // Copy maybe flags key2->increment_use_count(-1); // Free not used tree } else { SEL_ARG *last=tmp; + SEL_ARG *first=tmp; + /* + Find the last range in tmp that overlaps key2 and has the same + condition on the rest of the keyparts. + */ while (last->next && last->next->cmp_min_to_max(key2) <= 0 && eq_tree(last->next->next_key_part,key2->next_key_part)) { + /* + We've found the last overlapping key1 range in last. + This means that the ranges between (and including) the + first overlapping range (tmp) and the last overlapping range + (last) are fully nested into the current range of key2 + and can safely be discarded. We just need the minimum endpoint + of the first overlapping range (tmp) so we can compare it with + the minimum endpoint of the enclosing key2 range. + */ SEL_ARG *save=last; last=last->next; key1=key1->tree_delete(save); } - last->copy_min(tmp); + /* + The tmp range (the first overlapping range) could have been discarded + by the previous loop. We should re-direct tmp to the new united range + that's taking its place. + */ + tmp= last; + last->copy_min(first); bool full_range= last->copy_min(key2); if (!full_range) { From c74609b12627b7405a21c22f166702da6cc93120 Mon Sep 17 00:00:00 2001 From: Christopher Powers Date: Thu, 19 Nov 2009 16:49:13 -0600 Subject: [PATCH 052/344] Bug #48739 MySQL crashes on specific INTERVAL in select query Fixed crash caused by x64 int/long incompatibility introduced in Bug #29125. sql/item_timefunc.cc: Fixed crash caused by int/long incompatibility on x64 systems. Changed two "uint" casts and a "long" declartion to "int" in order to ensure that the integer sign is preserved. See Bug #48739 for details. --- sql/item_timefunc.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index b5037c08b3c..b293145cc27 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -386,7 +386,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, if (tmp - val > 6) tmp= (char*) val + 6; l_time->second_part= (int) my_strtoll10(val, &tmp, &error); - frac_part= 6 - (uint) (tmp - val); + frac_part= 6 - (int) (tmp - val); if (frac_part > 0) l_time->second_part*= (ulong) log_10_int[frac_part]; val= tmp; @@ -876,9 +876,9 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, value= value*LL(10) + (longlong) (*str - '0'); if (transform_msec && i == count - 1) // microseconds always last { - long msec_length= 6 - (uint) (str - start); + int msec_length= 6 - (int)(str - start); if (msec_length > 0) - value*= (long) log_10_int[msec_length]; + value*= (long)log_10_int[msec_length]; } values[i]= value; while (str != end && !my_isdigit(cs,*str)) From a21cd97c3506a70297afc3dd3f64cdfd2dc0a4e6 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 20 Nov 2009 12:10:47 +0200 Subject: [PATCH 053/344] Bug #45261 : Crash, stored procedure + decimal Bug #48370 Absolutely wrong calculations with GROUP BY and decimal fields when using IF Added the test cases in the above two bugs for regression testing. Added additional tests that demonstrate a incomplete fix. Added a new factory method for Field_new_decimal to create a field from an (decimal returning) Item. In the new method made sure that all the precision and length variables are capped in a proper way. This is required because Item's can have larger precision than the decimal fields and thus need to be capped when creating a field based on an Item type. Fixed the wrong typecast to Item_decimal. --- mysql-test/r/type_newdecimal.result | 284 ++++++++++++++++++++++++++++ mysql-test/t/type_newdecimal.test | 226 ++++++++++++++++++++++ sql/field.cc | 44 +++++ sql/field.h | 1 + sql/item.cc | 4 +- sql/item_func.cc | 39 +--- sql/item_sum.cc | 6 +- sql/sql_select.cc | 41 +--- 8 files changed, 560 insertions(+), 85 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 748aadee4fb..70ee3a56cf3 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1630,3 +1630,287 @@ SELECT my_col FROM t1; my_col 0.012345687012345687012345687012 DROP TABLE t1; +# +# Bug#45261: Crash, stored procedure + decimal +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 SELECT +/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001 +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,0) NO 0 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001. +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,0) NO 0 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */ +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,0) NO 0 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001 +AS c1; +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,0) NO 0 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */ +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999.999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */ +AS c1; +DESC t1; +Field Type Null Key Default Extra +c1 decimal(31,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +1.100000000000000000000000000000 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ +AS c1; +DESC t1; +Field Type Null Key Default Extra +c1 decimal(31,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +1.100000000000000000000000000000 +DROP TABLE t1; +CREATE TABLE t1 SELECT +.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ +AS c1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(30,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +0.100000000000000000000000000000 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */ +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999.999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */ +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,1) NO 0.0 +SELECT * FROM t1; +c1 +9999999999999999999999999999999999999999999999999999999999999999.9 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */ +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,1) NO 0.0 +SELECT * FROM t1; +c1 +9999999999999999999999999999999999999999999999999999999999999999.9 +DROP TABLE t1; +CREATE TABLE t1 SELECT +.123456789012345678901234567890123456789012345678901234567890123456 /* 66 */ +AS c1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(30,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +0.123456789012345678901234567890 +DROP TABLE t1; +CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(33,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +123.123456789012345678901234567890 +DROP TABLE t1; +CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1; +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +2.100000000000000000000000000000 +DROP TABLE t1; +# +# Test that the integer and decimal parts are properly calculated. +# +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 3 +DESC t2; +Field Type Null Key Default Extra +c1 decimal(32,30) YES NULL +DROP TABLE t1,t2; +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +Note 1265 Data truncated for column 'c1' at row 2 +Note 1265 Data truncated for column 'c1' at row 3 +DESC t2; +Field Type Null Key Default Extra +c1 decimal(34,0) YES NULL +DROP TABLE t1,t2; +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +DESC t2; +Field Type Null Key Default Extra +c1 decimal(65,30) YES NULL +DROP TABLE t1,t2; +# +# Test that variables get maximum precision. +# +SET @decimal= 1.1; +CREATE TABLE t1 SELECT @decimal AS c1; +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,30) YES NULL +SELECT * FROM t1; +c1 +1.100000000000000000000000000000 +DROP TABLE t1; +# +# Bug #45261 : Crash, stored procedure + decimal +# Original test by the reporter. +# +# should not crash +CREATE TABLE t1 +SELECT .123456789012345678901234567890123456789012345678901234567890123456 AS a; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +DROP TABLE t1; +CREATE PROCEDURE test_proc() +BEGIN +# The las non critical CUSER definition is: +# DECLARE mycursor CURSOR FOR SELECT 1 % +# .12345678912345678912345678912345678912345678912345678912345678912 AS my_col; +DECLARE mycursor CURSOR FOR +SELECT 1 % +.123456789123456789123456789123456789123456789123456789123456789123456789123456789 +AS my_col; +OPEN mycursor; +CLOSE mycursor; +END| +# should not crash +CALL test_proc(); +DROP PROCEDURE test_proc; +# +# Bug #48370 Absolutely wrong calculations with GROUP BY and +# decimal fields when using IF +# +CREATE TABLE currencies (id int, rate decimal(16,4), +PRIMARY KEY (id), KEY (rate)); +INSERT INTO currencies VALUES (11,0.7028); +INSERT INTO currencies VALUES (1,1); +CREATE TABLE payments ( +id int, +supplier_id int, +status int, +currency_id int, +vat decimal(7,4), +PRIMARY KEY (id), +KEY currency_id (currency_id), +KEY supplier_id (supplier_id) +); +INSERT INTO payments (id,status,vat,supplier_id,currency_id) VALUES +(3001,2,0.0000,344,11), (1,2,0.0000,1,1); +CREATE TABLE sub_tasks ( +id int, +currency_id int, +price decimal(16,4), +discount decimal(10,4), +payment_id int, +PRIMARY KEY (id), +KEY currency_id (currency_id), +KEY payment_id (payment_id) +) ; +INSERT INTO sub_tasks (id, price, discount, payment_id, currency_id) VALUES +(52, 12.60, 0, 3001, 11), (56, 14.58, 0, 3001, 11); +# should return 1 and the same values in col 2 and 3 +select STRAIGHT_JOIN +(1 + PAY.vat) AS mult, +SUM(ROUND((SUB.price - ROUND(ROUND(SUB.price, 2) * SUB.discount, 2)) * +CUR.rate / CUR.rate, 2) +) v_net_with_discount, +SUM(ROUND((SUB.price - ROUND(ROUND(SUB.price, 2) * SUB.discount, 1)) * +CUR.rate / CUR.rate , 2) +* (1 + PAY.vat) +) v_total +from +currencies CUR, payments PAY, sub_tasks SUB +where +SUB.payment_id = PAY.id and +PAY.currency_id = CUR.id and +PAY.id > 2 +group by PAY.id + 1; +mult v_net_with_discount v_total +1.0000 27.18 27.180000 +DROP TABLE currencies, payments, sub_tasks; +End of 5.1 tests diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index cd3c3f81510..2cf7ab8fbdf 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1286,3 +1286,229 @@ CREATE TABLE t1 SELECT 1 % .1234567891234567891234567891234567891234567891234567 DESCRIBE t1; SELECT my_col FROM t1; DROP TABLE t1; + +--echo # +--echo # Bug#45261: Crash, stored procedure + decimal +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 SELECT + /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001 + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001. + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001 + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + .100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + .123456789012345678901234567890123456789012345678901234567890123456 /* 66 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # Test that the integer and decimal parts are properly calculated. +--echo # + +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1; +DESC t2; +DROP TABLE t1,t2; + +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1; +DESC t2; +DROP TABLE t1,t2; + +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1; +DESC t2; +DROP TABLE t1,t2; + +--echo # +--echo # Test that variables get maximum precision. +--echo # + +SET @decimal= 1.1; +CREATE TABLE t1 SELECT @decimal AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # Bug #45261 : Crash, stored procedure + decimal +--echo # Original test by the reporter. +--echo # + +--echo # should not crash +CREATE TABLE t1 +SELECT .123456789012345678901234567890123456789012345678901234567890123456 AS a; +DROP TABLE t1; + +delimiter |; +CREATE PROCEDURE test_proc() +BEGIN + # The las non critical CUSER definition is: + # DECLARE mycursor CURSOR FOR SELECT 1 % + # .12345678912345678912345678912345678912345678912345678912345678912 AS my_col; + DECLARE mycursor CURSOR FOR +SELECT 1 % +.123456789123456789123456789123456789123456789123456789123456789123456789123456789 + AS my_col; + + OPEN mycursor; + CLOSE mycursor; +END| +delimiter ;| +--echo # should not crash +CALL test_proc(); +DROP PROCEDURE test_proc; + +--echo # +--echo # Bug #48370 Absolutely wrong calculations with GROUP BY and +--echo # decimal fields when using IF +--echo # + +CREATE TABLE currencies (id int, rate decimal(16,4), + PRIMARY KEY (id), KEY (rate)); + +INSERT INTO currencies VALUES (11,0.7028); +INSERT INTO currencies VALUES (1,1); + +CREATE TABLE payments ( + id int, + supplier_id int, + status int, + currency_id int, + vat decimal(7,4), + PRIMARY KEY (id), + KEY currency_id (currency_id), + KEY supplier_id (supplier_id) +); + +INSERT INTO payments (id,status,vat,supplier_id,currency_id) VALUES +(3001,2,0.0000,344,11), (1,2,0.0000,1,1); + +CREATE TABLE sub_tasks ( + id int, + currency_id int, + price decimal(16,4), + discount decimal(10,4), + payment_id int, + PRIMARY KEY (id), + KEY currency_id (currency_id), + KEY payment_id (payment_id) +) ; + +INSERT INTO sub_tasks (id, price, discount, payment_id, currency_id) VALUES +(52, 12.60, 0, 3001, 11), (56, 14.58, 0, 3001, 11); + +--echo # should return 1 and the same values in col 2 and 3 +select STRAIGHT_JOIN + (1 + PAY.vat) AS mult, + SUM(ROUND((SUB.price - ROUND(ROUND(SUB.price, 2) * SUB.discount, 2)) * + CUR.rate / CUR.rate, 2) + ) v_net_with_discount, + + SUM(ROUND((SUB.price - ROUND(ROUND(SUB.price, 2) * SUB.discount, 1)) * + CUR.rate / CUR.rate , 2) + * (1 + PAY.vat) + ) v_total +from + currencies CUR, payments PAY, sub_tasks SUB +where + SUB.payment_id = PAY.id and + PAY.currency_id = CUR.id and + PAY.id > 2 +group by PAY.id + 1; + +DROP TABLE currencies, payments, sub_tasks; + + +--echo End of 5.1 tests diff --git a/sql/field.cc b/sql/field.cc index 354c911e1c0..01ccc338782 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2486,6 +2486,50 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg, } +Field *Field_new_decimal::create_from_item (Item *item) +{ + uint8 dec= item->decimals; + uint8 intg= item->decimal_precision() - dec; + uint32 len= item->max_length; + + DBUG_ASSERT (item->result_type() == DECIMAL_RESULT); + + /* + Trying to put too many digits overall in a DECIMAL(prec,dec) + will always throw a warning. We must limit dec to + DECIMAL_MAX_SCALE however to prevent an assert() later. + */ + + if (dec > 0) + { + signed int overflow; + + dec= min(dec, DECIMAL_MAX_SCALE); + + /* + If the value still overflows the field with the corrected dec, + we'll throw out decimals rather than integers. This is still + bad and of course throws a truncation warning. + +1: for decimal point + */ + + const int required_length= + my_decimal_precision_to_length(intg + dec, dec, + item->unsigned_flag); + + overflow= required_length - len; + + if (overflow > 0) + dec= max(0, dec - overflow); // too long, discard fract + else + /* Corrected value fits. */ + len= required_length; + } + return new Field_new_decimal(len, item->maybe_null, item->name, + dec, item->unsigned_flag); +} + + int Field_new_decimal::reset(void) { store_value(&decimal_zero); diff --git a/sql/field.h b/sql/field.h index 784b9133790..ae074cc1a30 100644 --- a/sql/field.h +++ b/sql/field.h @@ -807,6 +807,7 @@ public: uint is_equal(Create_field *new_field); virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); + static Field *create_from_item (Item *); }; diff --git a/sql/item.cc b/sql/item.cc index e1dbc1ba21a..ab70996e541 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4899,9 +4899,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) switch (field_type()) { case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: - field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0, - Field::NONE, name, decimals, 0, - unsigned_flag); + field= Field_new_decimal::create_from_item(this); break; case MYSQL_TYPE_TINY: field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE, diff --git a/sql/item_func.cc b/sql/item_func.cc index ac52f36474a..977a0de39af 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -451,45 +451,8 @@ Field *Item_func::tmp_table_field(TABLE *table) return make_string_field(table); break; case DECIMAL_RESULT: - { - uint8 dec= decimals; - uint8 intg= decimal_precision() - dec; - uint32 len= max_length; - - /* - Trying to put too many digits overall in a DECIMAL(prec,dec) - will always throw a warning. We must limit dec to - DECIMAL_MAX_SCALE however to prevent an assert() later. - */ - - if (dec > 0) - { - int overflow; - - dec= min(dec, DECIMAL_MAX_SCALE); - - /* - If the value still overflows the field with the corrected dec, - we'll throw out decimals rather than integers. This is still - bad and of course throws a truncation warning. - */ - - const int required_length= - my_decimal_precision_to_length(intg + dec, dec, - unsigned_flag); - - overflow= required_length - len; - - if (overflow > 0) - dec= max(0, dec - overflow); // too long, discard fract - else - /* Corrected value fits. */ - len= required_length; - } - - field= new Field_new_decimal(len, maybe_null, name, dec, unsigned_flag); + field= Field_new_decimal::create_from_item(this); break; - } case ROW_RESULT: default: // This case should never be chosen diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 38251294053..7bbe167e7ac 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -517,8 +517,7 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, name, table->s, collation.collation); break; case DECIMAL_RESULT: - field= new Field_new_decimal(max_length, maybe_null, name, - decimals, unsigned_flag); + field= Field_new_decimal::create_from_item(this); break; case ROW_RESULT: default: @@ -1270,8 +1269,7 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table, 0, name, &my_charset_bin); } else if (hybrid_type == DECIMAL_RESULT) - field= new Field_new_decimal(max_length, maybe_null, name, - decimals, unsigned_flag); + field= Field_new_decimal::create_from_item(this); else field= new Field_double(max_length, maybe_null, name, decimals, TRUE); if (field) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 18fc3b20748..569d8183ab6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9466,47 +9466,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, new_field->set_derivation(item->collation.derivation); break; case DECIMAL_RESULT: - { - uint8 dec= item->decimals; - uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec; - uint32 len= item->max_length; - - /* - Trying to put too many digits overall in a DECIMAL(prec,dec) - will always throw a warning. We must limit dec to - DECIMAL_MAX_SCALE however to prevent an assert() later. - */ - - if (dec > 0) - { - signed int overflow; - - dec= min(dec, DECIMAL_MAX_SCALE); - - /* - If the value still overflows the field with the corrected dec, - we'll throw out decimals rather than integers. This is still - bad and of course throws a truncation warning. - +1: for decimal point - */ - - const int required_length= - my_decimal_precision_to_length(intg + dec, dec, - item->unsigned_flag); - - overflow= required_length - len; - - if (overflow > 0) - dec= max(0, dec - overflow); // too long, discard fract - else - /* Corrected value fits. */ - len= required_length; - } - - new_field= new Field_new_decimal(len, maybe_null, item->name, - dec, item->unsigned_flag); + new_field= Field_new_decimal::create_from_item(item); break; - } case ROW_RESULT: default: // This case should never be choosen From 26a37b36efe214e8976a9412fea405b599bd4ac9 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 20 Nov 2009 13:09:50 +0100 Subject: [PATCH 054/344] Bug#47571 : idle named pipe connection is unkillable implement Davi's review suggestions (post-push fixes) include/violite.h: Use official abbreviation for milliseconds (ms) sql/mysqld.cc: Fix formatting Add error handling for the case of CreateEvent error vio/vio.c: Use official abbreviation for milliseconds(ms) Remove superfluous memset Fix formatting vio/viosocket.c: Use official abbreviation for milliseconds (ms) Use size_t datatype instead of int in pipe_complete_io --- include/violite.h | 4 ++-- sql/mysqld.cc | 16 +++++++++++----- vio/vio.c | 40 +++++++++++++++++--------------------- vio/viosocket.c | 49 ++++++++++++++++++++++++++++------------------- 4 files changed, 60 insertions(+), 49 deletions(-) diff --git a/include/violite.h b/include/violite.h index 3f68ccde10f..1eef3ef5730 100644 --- a/include/violite.h +++ b/include/violite.h @@ -224,8 +224,8 @@ struct st_vio #endif /* HAVE_SMEM */ #ifdef _WIN32 OVERLAPPED pipe_overlapped; - DWORD read_timeout_millis; - DWORD write_timeout_millis; + DWORD read_timeout_ms; + DWORD write_timeout_ms; #endif }; #endif /* vio_violite_h_ */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a8e99e08092..5c643b03798 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5224,12 +5224,16 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) pthread_handler_t handle_connections_namedpipes(void *arg) { HANDLE hConnectedPipe; - OVERLAPPED connectOverlapped = {0}; + OVERLAPPED connectOverlapped= {0}; THD *thd; my_thread_init(); DBUG_ENTER("handle_connections_namedpipes"); - connectOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - + connectOverlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL); + if (!connectOverlapped.hEvent) + { + sql_print_error("Can't create event, last error=%u", GetLastError()); + unireg_abort(1); + } DBUG_PRINT("general",("Waiting for named pipe connections.")); while (!abort_loop) { @@ -5252,7 +5256,8 @@ pthread_handler_t handle_connections_namedpipes(void *arg) { CloseHandle(hPipe); if ((hPipe= CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, + PIPE_ACCESS_DUPLEX | + FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, @@ -5272,7 +5277,8 @@ pthread_handler_t handle_connections_namedpipes(void *arg) hConnectedPipe = hPipe; /* create new pipe for new connection */ if ((hPipe = CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, + PIPE_ACCESS_DUPLEX | + FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, diff --git a/vio/vio.c b/vio/vio.c index fd8e2e5a402..4253651bf84 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -62,10 +62,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->timeout=vio_win32_timeout; /* Set default timeout */ - vio->read_timeout_millis = INFINITE; - vio->write_timeout_millis = INFINITE; - - memset(&(vio->pipe_overlapped), 0, sizeof(OVERLAPPED)); + vio->read_timeout_ms= INFINITE; + vio->write_timeout_ms= INFINITE; vio->pipe_overlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL); DBUG_VOID_RETURN; } @@ -90,8 +88,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type, /* Currently, shared memory is on Windows only, hence the below is ok*/ vio->timeout= vio_win32_timeout; /* Set default timeout */ - vio->read_timeout_millis= INFINITE; - vio->write_timeout_millis= INFINITE; + vio->read_timeout_ms= INFINITE; + vio->write_timeout_ms= INFINITE; DBUG_VOID_RETURN; } #endif @@ -115,22 +113,20 @@ static void vio_init(Vio* vio, enum enum_vio_type type, DBUG_VOID_RETURN; } #endif /* HAVE_OPENSSL */ - { - vio->viodelete =vio_delete; - vio->vioerrno =vio_errno; - vio->read= (flags & VIO_BUFFERED_READ) ? vio_read_buff : vio_read; - vio->write =vio_write; - vio->fastsend =vio_fastsend; - vio->viokeepalive =vio_keepalive; - vio->should_retry =vio_should_retry; - vio->was_interrupted=vio_was_interrupted; - vio->vioclose =vio_close; - vio->peer_addr =vio_peer_addr; - vio->in_addr =vio_in_addr; - vio->vioblocking =vio_blocking; - vio->is_blocking =vio_is_blocking; - vio->timeout =vio_timeout; - } + vio->viodelete =vio_delete; + vio->vioerrno =vio_errno; + vio->read= (flags & VIO_BUFFERED_READ) ? vio_read_buff : vio_read; + vio->write =vio_write; + vio->fastsend =vio_fastsend; + vio->viokeepalive =vio_keepalive; + vio->should_retry =vio_should_retry; + vio->was_interrupted=vio_was_interrupted; + vio->vioclose =vio_close; + vio->peer_addr =vio_peer_addr; + vio->in_addr =vio_in_addr; + vio->vioblocking =vio_blocking; + vio->is_blocking =vio_is_blocking; + vio->timeout =vio_timeout; DBUG_VOID_RETURN; } diff --git a/vio/viosocket.c b/vio/viosocket.c index c929cac2a05..f73b890c697 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -415,14 +415,14 @@ void vio_timeout(Vio *vio, uint which, uint timeout) /* Finish pending IO on pipe. Honor wait timeout */ -static int pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_millis) +static size_t pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_ms) { DWORD length; DWORD ret; DBUG_ENTER("pipe_complete_io"); - ret= WaitForSingleObject(vio->pipe_overlapped.hEvent, timeout_millis); + ret= WaitForSingleObject(vio->pipe_overlapped.hEvent, timeout_ms); /* WaitForSingleObjects will normally return WAIT_OBJECT_O (success, IO completed) or WAIT_TIMEOUT. @@ -431,14 +431,14 @@ static int pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_mill { CancelIo(vio->hPipe); DBUG_PRINT("error",("WaitForSingleObject() returned %d", ret)); - DBUG_RETURN(-1); + DBUG_RETURN((size_t)-1); } if (!GetOverlappedResult(vio->hPipe,&(vio->pipe_overlapped),&length, FALSE)) { DBUG_PRINT("error",("GetOverlappedResult() returned last error %d", GetLastError())); - DBUG_RETURN(-1); + DBUG_RETURN((size_t)-1); } DBUG_RETURN(length); @@ -448,12 +448,17 @@ static int pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_mill size_t vio_read_pipe(Vio * vio, uchar *buf, size_t size) { DWORD bytes_read; + size_t retval; DBUG_ENTER("vio_read_pipe"); DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio->sd, (long) buf, (uint) size)); - if (!ReadFile(vio->hPipe, buf, (DWORD)size, &bytes_read, + if (ReadFile(vio->hPipe, buf, (DWORD)size, &bytes_read, &(vio->pipe_overlapped))) + { + retval= bytes_read; + } + else { if (GetLastError() != ERROR_IO_PENDING) { @@ -461,23 +466,28 @@ size_t vio_read_pipe(Vio * vio, uchar *buf, size_t size) GetLastError())); DBUG_RETURN((size_t)-1); } - bytes_read= pipe_complete_io(vio, buf, size,vio->read_timeout_millis); + retval= pipe_complete_io(vio, buf, size,vio->read_timeout_ms); } - DBUG_PRINT("exit", ("%d", bytes_read)); - DBUG_RETURN(bytes_read); + DBUG_PRINT("exit", ("%lld", (longlong)retval)); + DBUG_RETURN(retval); } size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size) { DWORD bytes_written; + size_t retval; DBUG_ENTER("vio_write_pipe"); DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio->sd, (long) buf, (uint) size)); - if (!WriteFile(vio->hPipe, buf, (DWORD)size, &bytes_written, + if (WriteFile(vio->hPipe, buf, (DWORD)size, &bytes_written, &(vio->pipe_overlapped))) + { + retval= bytes_written; + } + else { if (GetLastError() != ERROR_IO_PENDING) { @@ -485,12 +495,11 @@ size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size) GetLastError())); DBUG_RETURN((size_t)-1); } - bytes_written = pipe_complete_io(vio, (char *)buf, size, - vio->write_timeout_millis); + retval= pipe_complete_io(vio, (char *)buf, size, vio->write_timeout_ms); } - DBUG_PRINT("exit", ("%d", bytes_written)); - DBUG_RETURN(bytes_written); + DBUG_PRINT("exit", ("%lld", (longlong)retval)); + DBUG_RETURN(retval); } @@ -515,21 +524,21 @@ int vio_close_pipe(Vio * vio) void vio_win32_timeout(Vio *vio, uint which , uint timeout_sec) { - DWORD timeout_millis; + DWORD timeout_ms; /* Windows is measuring timeouts in milliseconds. Check for possible int overflow. */ if (timeout_sec > UINT_MAX/1000) - timeout_millis= INFINITE; + timeout_ms= INFINITE; else - timeout_millis= timeout_sec * 1000; + timeout_ms= timeout_sec * 1000; /* which == 1 means "write", which == 0 means "read".*/ if(which) - vio->write_timeout_millis= timeout_millis; + vio->write_timeout_ms= timeout_ms; else - vio->read_timeout_millis= timeout_millis; + vio->read_timeout_ms= timeout_ms; } @@ -564,7 +573,7 @@ size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size) WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything */ if (WaitForMultipleObjects(array_elements(events), events, FALSE, - vio->read_timeout_millis) != WAIT_OBJECT_0) + vio->read_timeout_ms) != WAIT_OBJECT_0) { DBUG_RETURN(-1); }; @@ -621,7 +630,7 @@ size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size) while (remain != 0) { if (WaitForMultipleObjects(array_elements(events), events, FALSE, - vio->write_timeout_millis) != WAIT_OBJECT_0) + vio->write_timeout_ms) != WAIT_OBJECT_0) { DBUG_RETURN((size_t) -1); } From 41085809c39f1dc44d530a83b59ba8d0d14c1d8d Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Fri, 20 Nov 2009 13:49:06 +0100 Subject: [PATCH 055/344] Bug#39253 Large query cache still freezes server after fix for bug #21074 This patch introduce a limit on the time the query cache can block with a lock on SELECTs. Other operations which causes a change in the table data will still be blocked. sql/sql_cache.cc: * Introduced a timeout value for the qc lock when entering send_result_to_client() and store_query() methods. sql/sql_cache.h: * New signature for Query_cache::try_lock() --- sql/sql_cache.cc | 39 +++++++++++++++++++++++++++++++++++---- sql/sql_cache.h | 2 +- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 861bd97928d..f862cbed4f1 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -421,12 +421,16 @@ TYPELIB query_cache_type_typelib= effect by another thread. This enables a quick path in execution to skip waits when the outcome is known. + @param use_timeout TRUE if the lock can abort because of a timeout. + + @note use_timeout is optional and default value is FALSE. + @return @retval FALSE An exclusive lock was taken @retval TRUE The locking attempt failed */ -bool Query_cache::try_lock(void) +bool Query_cache::try_lock(bool use_timeout) { bool interrupt= FALSE; DBUG_ENTER("Query_cache::try_lock"); @@ -456,7 +460,26 @@ bool Query_cache::try_lock(void) else { DBUG_ASSERT(m_cache_lock_status == Query_cache::LOCKED); - pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex); + /* + To prevent send_result_to_client() and query_cache_insert() from + blocking execution for too long a timeout is put on the lock. + */ + if (use_timeout) + { + struct timespec waittime; + set_timespec_nsec(waittime,(ulong)(50000000L)); /* Wait for 50 msec */ + int res= pthread_cond_timedwait(&COND_cache_status_changed, + &structure_guard_mutex,&waittime); + if (res == ETIMEDOUT) + { + interrupt= TRUE; + break; + } + } + else + { + pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex); + } } } pthread_mutex_unlock(&structure_guard_mutex); @@ -1190,8 +1213,14 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", A table- or a full flush operation can potentially take a long time to finish. We choose not to wait for them and skip caching statements instead. + + In case the wait time can't be determined there is an upper limit which + causes try_lock() to abort with a time out. + + The 'TRUE' parameter indicate that the lock is allowed to timeout + */ - if (try_lock()) + if (try_lock(TRUE)) DBUG_VOID_RETURN; if (query_cache_size == 0) { @@ -1385,8 +1414,10 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) Try to obtain an exclusive lock on the query cache. If the cache is disabled or if a full cache flush is in progress, the attempt to get the lock is aborted. + + The 'TRUE' parameter indicate that the lock is allowed to timeout */ - if (try_lock()) + if (try_lock(TRUE)) goto err; if (query_cache_size == 0) diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 777ddd39280..44fc3123b98 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -485,7 +485,7 @@ protected: const char *name); my_bool in_blocks(Query_cache_block * point); - bool try_lock(void); + bool try_lock(bool use_timeout= FALSE); void lock(void); void lock_and_suspend(void); void unlock(void); From 0a686030589dae2fe6bf99f4c3d4a73d4268a491 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Fri, 20 Nov 2009 16:18:01 +0100 Subject: [PATCH 056/344] Bug#45613 handle failures from my_hash_insert Not all my_hash_insert() calls are checked for return value. This patch adds appropriate checks and failure responses where needed. mysys/hash.c: * Debug hook for testing failures in my_hash_insert() --- mysys/hash.c | 1 + sql/log.cc | 3 +-- sql/repl_failsafe.cc | 7 ++++++- sql/rpl_tblmap.cc | 8 +++++++- sql/sp.cc | 15 ++++++++++++--- sql/sp.h | 2 +- sql/sp_cache.cc | 12 +++++++++--- sql/sp_head.cc | 24 ++++++++++++++++++------ sql/sp_head.h | 2 +- sql/sql_acl.cc | 22 ++++++++++++++++------ sql/sql_base.cc | 7 ++++++- sql/sql_select.cc | 5 ++++- sql/sql_yacc.yy | 37 +++++++++++++++++++++++++------------ sql/table.cc | 12 ++++++++++-- 14 files changed, 117 insertions(+), 40 deletions(-) diff --git a/mysys/hash.c b/mysys/hash.c index 9c1957bf0aa..48ac122fa34 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -334,6 +334,7 @@ my_bool my_hash_insert(HASH *info, const uchar *record) size_t idx,halfbuff,hash_nr,first_index; uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; + DBUG_EXECUTE("fail_hash_insert",return(TRUE);); if (HASH_UNIQUE & info->flags) { diff --git a/sql/log.cc b/sql/log.cc index e1c3944392f..cc17286d5f9 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5649,9 +5649,8 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle) Xid_log_event *xev=(Xid_log_event *)ev; uchar *x= (uchar *) memdup_root(&mem_root, (uchar*) &xev->xid, sizeof(xev->xid)); - if (! x) + if (!x || my_hash_insert(&xids, x)) goto err2; - my_hash_insert(&xids, x); } delete ev; } diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 312499bb4ee..c6a05e93bf4 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -559,7 +559,12 @@ HOSTS"; goto err; } si->server_id = log_server_id; - my_hash_insert(&slave_list, (uchar*)si); + if (my_hash_insert(&slave_list, (uchar*)si)) + { + error= "the slave is out of memory"; + pthread_mutex_unlock(&LOCK_slave_list); + goto err; + } } strmake(si->host, row[1], sizeof(si->host)-1); si->port = atoi(row[port_ind]); diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc index a004c354263..6ef9a8623fe 100644 --- a/sql/rpl_tblmap.cc +++ b/sql/rpl_tblmap.cc @@ -119,7 +119,13 @@ int table_mapping::set_table(ulong table_id, TABLE* table) } e->table_id= table_id; e->table= table; - my_hash_insert(&m_table_ids,(uchar *)e); + if (my_hash_insert(&m_table_ids,(uchar *)e)) + { + /* we add this entry to the chain of free (free for use) entries */ + e->next= m_free; + m_free= e; + DBUG_RETURN(ERR_MEMORY_ALLOCATION); + } DBUG_PRINT("info", ("tid %lu -> table 0x%lx (%s)", table_id, (long) e->table, diff --git a/sql/sp.cc b/sql/sp.cc index fd420732628..b254ba8e694 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1506,7 +1506,8 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, rn->key.length= key->length; rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry); memcpy(rn->key.str, key->str, key->length + 1); - my_hash_insert(&lex->sroutines, (uchar *)rn); + if (my_hash_insert(&lex->sroutines, (uchar *)rn)) + return FALSE; lex->sroutines_list.link_in_list((uchar *)rn, (uchar **)&rn->next); rn->belong_to_view= belong_to_view; return TRUE; @@ -1584,16 +1585,24 @@ void sp_remove_not_own_routines(LEX *lex) dependant on time of life of elements from source hash. It also won't touch lists linking elements in source and destination hashes. + + @returns + @return TRUE Failure + @return FALSE Success */ -void sp_update_sp_used_routines(HASH *dst, HASH *src) +bool sp_update_sp_used_routines(HASH *dst, HASH *src) { for (uint i=0 ; i < src->records ; i++) { Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i); if (!hash_search(dst, (uchar *)rt->key.str, rt->key.length)) - my_hash_insert(dst, (uchar *)rt); + { + if (my_hash_insert(dst, (uchar *)rt)) + return TRUE; + } } + return FALSE; } diff --git a/sql/sp.h b/sql/sp.h index 5a190c5480e..876287d9704 100644 --- a/sql/sp.h +++ b/sql/sp.h @@ -69,7 +69,7 @@ void sp_get_prelocking_info(THD *thd, bool *need_prelocking, void sp_add_used_routine(LEX *lex, Query_arena *arena, sp_name *rt, char rt_type); void sp_remove_not_own_routines(LEX *lex); -void sp_update_sp_used_routines(HASH *dst, HASH *src); +bool sp_update_sp_used_routines(HASH *dst, HASH *src); int sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock); int sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index 64898915b7e..b8209a373a2 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -36,10 +36,16 @@ public: sp_cache(); ~sp_cache(); - inline void insert(sp_head *sp) + /** + Inserts a sp_head object into a hash table. + + @returns Success status + @return TRUE Failure + @return FALSE Success + */ + inline bool insert(sp_head *sp) { - /* TODO: why don't we check return value? */ - my_hash_insert(&m_hashtable, (const uchar *)sp); + return my_hash_insert(&m_hashtable, (const uchar *)sp); } inline sp_head *lookup(char *name, uint namelen) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 78b3df525f5..e823bf25d7e 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2087,8 +2087,18 @@ sp_head::reset_lex(THD *thd) DBUG_RETURN(FALSE); } -/// Restore lex during parsing, after we have parsed a sub statement. -void + +/** + Restore lex during parsing, after we have parsed a sub statement. + + @param thd Thread handle + + @return + @retval TRUE failure + @retval FALSE success +*/ + +bool sp_head::restore_lex(THD *thd) { DBUG_ENTER("sp_head::restore_lex"); @@ -2099,7 +2109,7 @@ sp_head::restore_lex(THD *thd) oldlex= (LEX *)m_lex.pop(); if (! oldlex) - return; // Nothing to restore + DBUG_RETURN(FALSE); // Nothing to restore oldlex->trg_table_fields.push_back(&sublex->trg_table_fields); @@ -2115,7 +2125,8 @@ sp_head::restore_lex(THD *thd) Add routines which are used by statement to respective set for this routine. */ - sp_update_sp_used_routines(&m_sroutines, &sublex->sroutines); + if (sp_update_sp_used_routines(&m_sroutines, &sublex->sroutines)) + DBUG_RETURN(TRUE); /* Merge tables used by this statement (but not by its functions or procedures) to multiset of tables used by this routine. @@ -2127,7 +2138,7 @@ sp_head::restore_lex(THD *thd) delete sublex; } thd->lex= oldlex; - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } /** @@ -3865,7 +3876,8 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) tab->lock_type= table->lock_type; tab->lock_count= tab->query_lock_count= 1; tab->trg_event_map= table->trg_event_map; - my_hash_insert(&m_sptabs, (uchar *)tab); + if (my_hash_insert(&m_sptabs, (uchar *)tab)) + return FALSE; } } return TRUE; diff --git a/sql/sp_head.h b/sql/sp_head.h index dd11f8693ac..00c96d44f70 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -340,7 +340,7 @@ public: @todo Conflicting comment in sp_head.cc */ - void + bool restore_lex(THD *thd); /// Put the instruction on the backpatch list, associated with the label. diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 35047ca7407..6580bc50b22 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2400,7 +2400,12 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) privs = cols = 0; /* purecov: deadcode */ return; /* purecov: deadcode */ } - my_hash_insert(&hash_columns, (uchar *) mem_check); + if (my_hash_insert(&hash_columns, (uchar *) mem_check)) + { + /* Invalidate this entry */ + privs= cols= 0; + return; + } } while (!col_privs->file->index_next(col_privs->record[0]) && !key_cmp_if_same(col_privs,key,0,key_prefix_len)); col_privs->file->ha_index_end(); @@ -2605,7 +2610,11 @@ static int replace_column_table(GRANT_TABLE *g_t, goto end; /* purecov: inspected */ } grant_column= new GRANT_COLUMN(column->column,privileges); - my_hash_insert(&g_t->hash_columns,(uchar*) grant_column); + if (my_hash_insert(&g_t->hash_columns,(uchar*) grant_column)) + { + result= -1; + goto end; + } } } @@ -3130,12 +3139,12 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, Str->user.str, table_name, rights, column_priv); - if (!grant_table) // end of memory + if (!grant_table || + my_hash_insert(&column_priv_hash,(uchar*) grant_table)) { result= TRUE; /* purecov: deadcode */ continue; /* purecov: deadcode */ } - my_hash_insert(&column_priv_hash,(uchar*) grant_table); } /* If revoke_grant, calculate the new column privilege for tables_priv */ @@ -3339,12 +3348,13 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, grant_name= new GRANT_NAME(Str->host.str, db_name, Str->user.str, table_name, rights); - if (!grant_name) + if (!grant_name || + my_hash_insert(is_proc ? + &proc_priv_hash : &func_priv_hash,(uchar*) grant_name)) { result= TRUE; continue; } - my_hash_insert(is_proc ? &proc_priv_hash : &func_priv_hash,(uchar*) grant_name); } if (replace_routine_table(thd, grant_name, tables[1].table, *Str, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e706bd04ea6..a421ca584ff 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2933,7 +2933,12 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, DBUG_PRINT("info", ("inserting table '%s'.'%s' 0x%lx into the cache", table->s->db.str, table->s->table_name.str, (long) table)); - VOID(my_hash_insert(&open_cache,(uchar*) table)); + if (my_hash_insert(&open_cache,(uchar*) table)) + { + my_free(table, MYF(0)); + VOID(pthread_mutex_unlock(&LOCK_open)); + DBUG_RETURN(NULL); + } } check_unused(); // Debugging call diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c5e0bce498d..a5f50c7903c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13862,7 +13862,10 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table, goto err; } else - (void) my_hash_insert(&hash, org_key_pos); + { + if (my_hash_insert(&hash, org_key_pos)) + goto err; + } key_pos+=extra_length; } my_free((char*) key_buffer,MYF(0)); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a837a10325b..17543196602 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2330,8 +2330,8 @@ sp_decl: } pctx->declare_var_boundary(0); - lex->sphead->restore_lex(YYTHD); - + if (lex->sphead->restore_lex(YYTHD)) + MYSQL_YYABORT; $$.vars= $2; $$.conds= $$.hndlrs= $$.curs= 0; } @@ -2441,7 +2441,8 @@ sp_cursor_stmt: } lex->sp_lex_in_use= TRUE; $$= lex; - lex->sphead->restore_lex(YYTHD); + if (lex->sphead->restore_lex(YYTHD)) + MYSQL_YYABORT; } ; @@ -2660,7 +2661,8 @@ sp_proc_stmt_statement: sp->add_instr(i)) MYSQL_YYABORT; } - sp->restore_lex(thd); + if (sp->restore_lex(thd)) + MYSQL_YYABORT; } ; @@ -2688,7 +2690,8 @@ sp_proc_stmt_return: MYSQL_YYABORT; sp->m_flags|= sp_head::HAS_RETURN; } - sp->restore_lex(YYTHD); + if (sp->restore_lex(YYTHD)) + MYSQL_YYABORT; } ; @@ -2928,7 +2931,8 @@ sp_if: sp->add_cont_backpatch(i) || sp->add_instr(i)) MYSQL_YYABORT; - sp->restore_lex(YYTHD); + if (sp->restore_lex(YYTHD)) + MYSQL_YYABORT; } sp_proc_stmts1 { @@ -2974,7 +2978,9 @@ simple_case_stmt: if (case_stmt_action_expr(lex, $3)) MYSQL_YYABORT; - lex->sphead->restore_lex(YYTHD); /* For expr $3 */ + /* For expr $3 */ + if (lex->sphead->restore_lex(YYTHD)) + MYSQL_YYABORT; } simple_when_clause_list else_clause_opt @@ -3024,7 +3030,9 @@ simple_when_clause: LEX *lex= Lex; if (case_stmt_action_when(lex, $3, true)) MYSQL_YYABORT; - lex->sphead->restore_lex(YYTHD); /* For expr $3 */ + /* For expr $3 */ + if (lex->sphead->restore_lex(YYTHD)) + MYSQL_YYABORT; } THEN_SYM sp_proc_stmts1 @@ -3045,7 +3053,9 @@ searched_when_clause: LEX *lex= Lex; if (case_stmt_action_when(lex, $3, false)) MYSQL_YYABORT; - lex->sphead->restore_lex(YYTHD); /* For expr $3 */ + /* For expr $3 */ + if (lex->sphead->restore_lex(YYTHD)) + MYSQL_YYABORT; } THEN_SYM sp_proc_stmts1 @@ -3222,7 +3232,8 @@ sp_unlabeled_control: sp->new_cont_backpatch(i) || sp->add_instr(i)) MYSQL_YYABORT; - sp->restore_lex(YYTHD); + if (sp->restore_lex(YYTHD)) + MYSQL_YYABORT; } sp_proc_stmts1 END WHILE_SYM { @@ -3248,7 +3259,8 @@ sp_unlabeled_control: if (i == NULL || lex->sphead->add_instr(i)) MYSQL_YYABORT; - lex->sphead->restore_lex(YYTHD); + if (lex->sphead->restore_lex(YYTHD)) + MYSQL_YYABORT; /* We can shortcut the cont_backpatch here */ i->m_cont_dest= ip+1; } @@ -11770,7 +11782,8 @@ option_type_value: if (sp->add_instr(i)) MYSQL_YYABORT; } - lex->sphead->restore_lex(thd); + if (lex->sphead->restore_lex(thd)) + MYSQL_YYABORT; } } ; diff --git a/sql/table.cc b/sql/table.cc index d2538eb4d59..35e8d83369f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1315,8 +1315,16 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, share->timestamp_field_offset= i; if (use_hash) - (void) my_hash_insert(&share->name_hash, - (uchar*) field_ptr); // never fail + if (my_hash_insert(&share->name_hash, (uchar*) field_ptr) ) + { + /* + Set return code 8 here to indicate that an error has + occurred but that the error message already has been + sent (OOM). + */ + error= 8; + goto err; + } } *field_ptr=0; // End marker From c70a9fa1e3c459e030546b0ca1ac916970bb489b Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Sat, 21 Nov 2009 09:18:21 -0200 Subject: [PATCH 057/344] Bug#41726: upgrade from 5.0 to 5.1.30 crashes if you didn't run mysql_upgrade The problem is that the server could crash when attempting to access a non-conformant proc system table. One such case was a crash when invoking stored procedure related statements on a 5.1 server with a proc system table in the 5.0 format. The solution is to validate the proc system table format before attempts to access it are made. If the table is not in the format that the server expects, a message is written to the error log and the statement that caused the table to be accessed fails. mysql-test/r/sp-destruct.result: Add test case result for Bug#41726 mysql-test/t/sp-destruct.test: Add test case for Bug#41726 sql/event_db_repository.cc: Update code to use new structures. sql/sp.cc: Describe the proc table format and use it to validate when opening a instance of the table. Add a check to insure that a error message is written to the error log only once. sql/sql_acl.cc: Remove unused variable and use new structure. sql/sql_acl.h: Export field definition. sql/table.cc: Accept the field count and definition in a single structure. sql/table.h: Combine the field count and definition in a single structure. Transform function into a class in order to support different ways of reporting a error. Add a pointer cache to TABLE_SHARE. --- mysql-test/r/sp-destruct.result | 34 +++++- mysql-test/t/sp-destruct.test | 54 ++++++++- sql/event_db_repository.cc | 27 ++++- sql/sp.cc | 194 +++++++++++++++++++++++++++++--- sql/sql_acl.cc | 7 +- sql/sql_acl.h | 3 +- sql/table.cc | 98 ++++++++-------- sql/table.h | 53 +++++++-- 8 files changed, 381 insertions(+), 89 deletions(-) diff --git a/mysql-test/r/sp-destruct.result b/mysql-test/r/sp-destruct.result index d7d44061b76..b6891df2420 100644 --- a/mysql-test/r/sp-destruct.result +++ b/mysql-test/r/sp-destruct.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("Column count of mysql.proc is wrong. Expected 20, found 19. The table is probably corrupted"); use test; drop procedure if exists bug14233; drop function if exists bug14233; @@ -11,11 +12,13 @@ create table t1 (id int); create trigger t1_ai after insert on t1 for each row call bug14233(); alter table mysql.proc drop type; call bug14233(); -ERROR HY000: Failed to load routine test.bug14233. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5) +ERROR HY000: Column count of mysql.proc is wrong. Expected 20, found 19. The table is probably corrupted create view v1 as select bug14233_f(); -ERROR HY000: Failed to load routine test.bug14233_f. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5) +ERROR HY000: Column count of mysql.proc is wrong. Expected 20, found 19. The table is probably corrupted insert into t1 values (0); -ERROR HY000: Failed to load routine test.bug14233. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5) +ERROR HY000: Column count of mysql.proc is wrong. Expected 20, found 19. The table is probably corrupted +show procedure status; +ERROR HY000: Column count of mysql.proc is wrong. Expected 20, found 19. The table is probably corrupted flush table mysql.proc; call bug14233(); ERROR HY000: Incorrect information in file: './mysql/proc.frm' @@ -88,3 +91,28 @@ show procedure status where db=DATABASE(); Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation show function status where db=DATABASE(); Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +DROP TABLE IF EXISTS proc_backup; +DROP PROCEDURE IF EXISTS p1; +# Backup the proc table +RENAME TABLE mysql.proc TO proc_backup; +CREATE TABLE mysql.proc LIKE proc_backup; +FLUSH TABLE mysql.proc; +# Test with a valid table. +CREATE PROCEDURE p1() +SET @foo = 10; +CALL p1(); +SHOW PROCEDURE STATUS; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test p1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +# Modify a field of the table. +ALTER TABLE mysql.proc MODIFY comment CHAR (32); +CREATE PROCEDURE p2() +SET @foo = 10; +ERROR HY000: Cannot load from mysql.proc. The table is probably corrupted +# Procedure loaded from the cache +CALL p1(); +SHOW PROCEDURE STATUS; +ERROR HY000: Cannot load from mysql.proc. The table is probably corrupted +DROP TABLE mysql.proc; +RENAME TABLE proc_backup TO mysql.proc; +FLUSH TABLE mysql.proc; diff --git a/mysql-test/t/sp-destruct.test b/mysql-test/t/sp-destruct.test index 14c38a2fdb4..720c24b2c24 100644 --- a/mysql-test/t/sp-destruct.test +++ b/mysql-test/t/sp-destruct.test @@ -12,6 +12,9 @@ # mysqltest should be fixed to allow REPLACE_RESULT in error message -- source include/not_embedded.inc +# Supress warnings written to the log file +call mtr.add_suppression("Column count of mysql.proc is wrong. Expected 20, found 19. The table is probably corrupted"); + # Backup proc table let $MYSQLD_DATADIR= `select @@datadir`; --copy_file $MYSQLD_DATADIR/mysql/proc.frm $MYSQLTEST_VARDIR/tmp/proc.frm @@ -38,15 +41,14 @@ create trigger t1_ai after insert on t1 for each row call bug14233(); # Unsupported tampering with the mysql.proc definition alter table mysql.proc drop type; ---replace_result $MYSQL_TEST_DIR . ---error ER_SP_PROC_TABLE_CORRUPT +--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED call bug14233(); ---replace_result $MYSQL_TEST_DIR . ---error ER_SP_PROC_TABLE_CORRUPT +--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED create view v1 as select bug14233_f(); ---replace_result $MYSQL_TEST_DIR . ---error ER_SP_PROC_TABLE_CORRUPT +--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED insert into t1 values (0); +--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED +show procedure status; flush table mysql.proc; @@ -155,3 +157,43 @@ drop procedure bug14233_3; # Assert: These should show nothing. show procedure status where db=DATABASE(); show function status where db=DATABASE(); + +# +# Bug#41726 upgrade from 5.0 to 5.1.30 crashes if you didn't run mysql_upgrade +# + + +--disable_warnings +DROP TABLE IF EXISTS proc_backup; +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +--echo # Backup the proc table + +RENAME TABLE mysql.proc TO proc_backup; +CREATE TABLE mysql.proc LIKE proc_backup; +FLUSH TABLE mysql.proc; + +--echo # Test with a valid table. + +CREATE PROCEDURE p1() + SET @foo = 10; +CALL p1(); +--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' +SHOW PROCEDURE STATUS; + +--echo # Modify a field of the table. + +ALTER TABLE mysql.proc MODIFY comment CHAR (32); + +--error ER_CANNOT_LOAD_FROM_TABLE +CREATE PROCEDURE p2() + SET @foo = 10; +--echo # Procedure loaded from the cache +CALL p1(); +--error ER_CANNOT_LOAD_FROM_TABLE +SHOW PROCEDURE STATUS; + +DROP TABLE mysql.proc; +RENAME TABLE proc_backup TO mysql.proc; +FLUSH TABLE mysql.proc; diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 8faab5023da..9f3863eb2b0 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -26,7 +26,7 @@ */ static -const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = +const TABLE_FIELD_TYPE event_table_fields[ET_FIELD_COUNT] = { { { C_STRING_WITH_LEN("db") }, @@ -151,6 +151,24 @@ const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = } }; +static const TABLE_FIELD_DEF + event_table_def= {ET_FIELD_COUNT, event_table_fields}; + +class Event_db_intact : public Table_check_intact +{ +protected: + void report_error(uint, const char *fmt, ...) + { + va_list args; + va_start(args, fmt); + error_log_print(ERROR_LEVEL, fmt, args); + va_end(args); + } +}; + +/** In case of an error, a message is printed to the error log. */ +static Event_db_intact table_intact; + /** Puts some data common to CREATE and ALTER EVENT into a row. @@ -1117,10 +1135,8 @@ Event_db_repository::check_system_tables(THD *thd) } else { - if (table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT, - mysql_db_table_fields)) + if (table_intact.check(tables.table, &mysql_db_table_def)) ret= 1; - /* in case of an error, the message is printed inside table_check_intact */ close_thread_tables(thd); } @@ -1154,9 +1170,8 @@ Event_db_repository::check_system_tables(THD *thd) } else { - if (table_check_intact(tables.table, ET_FIELD_COUNT, event_table_fields)) + if (table_intact.check(tables.table, &event_table_def)) ret= 1; - /* in case of an error, the message is printed inside table_check_intact */ close_thread_tables(thd); } diff --git a/sql/sp.cc b/sql/sp.cc index b254ba8e694..d3c5dfb96d0 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -70,6 +70,122 @@ enum MYSQL_PROC_FIELD_COUNT }; +static const +TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] = +{ + { + { C_STRING_WITH_LEN("db") }, + { C_STRING_WITH_LEN("char(64)") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("name") }, + { C_STRING_WITH_LEN("char(64)") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("type") }, + { C_STRING_WITH_LEN("enum('FUNCTION','PROCEDURE')") }, + { NULL, 0 } + }, + { + { C_STRING_WITH_LEN("specific_name") }, + { C_STRING_WITH_LEN("char(64)") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("language") }, + { C_STRING_WITH_LEN("enum('SQL')") }, + { NULL, 0 } + }, + { + { C_STRING_WITH_LEN("sql_data_access") }, + { C_STRING_WITH_LEN("enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')") }, + { NULL, 0 } + }, + { + { C_STRING_WITH_LEN("is_deterministic") }, + { C_STRING_WITH_LEN("enum('YES','NO')") }, + { NULL, 0 } + }, + { + { C_STRING_WITH_LEN("security_type") }, + { C_STRING_WITH_LEN("enum('INVOKER','DEFINER')") }, + { NULL, 0 } + }, + { + { C_STRING_WITH_LEN("param_list") }, + { C_STRING_WITH_LEN("blob") }, + { NULL, 0 } + }, + + { + { C_STRING_WITH_LEN("returns") }, + { C_STRING_WITH_LEN("longblob") }, + { NULL, 0 } + }, + { + { C_STRING_WITH_LEN("body") }, + { C_STRING_WITH_LEN("longblob") }, + { NULL, 0 } + }, + { + { C_STRING_WITH_LEN("definer") }, + { C_STRING_WITH_LEN("char(77)") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("created") }, + { C_STRING_WITH_LEN("timestamp") }, + { NULL, 0 } + }, + { + { C_STRING_WITH_LEN("modified") }, + { C_STRING_WITH_LEN("timestamp") }, + { NULL, 0 } + }, + { + { C_STRING_WITH_LEN("sql_mode") }, + { C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES'," + "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION'," + "'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB'," + "'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40'," + "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES'," + "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES'," + "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER'," + "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')") }, + { NULL, 0 } + }, + { + { C_STRING_WITH_LEN("comment") }, + { C_STRING_WITH_LEN("char(64)") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("character_set_client") }, + { C_STRING_WITH_LEN("char(32)") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("collation_connection") }, + { C_STRING_WITH_LEN("char(32)") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("db_collation") }, + { C_STRING_WITH_LEN("char(32)") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("body_utf8") }, + { C_STRING_WITH_LEN("longblob") }, + { NULL, 0 } + } +}; + +static const TABLE_FIELD_DEF + proc_table_def= {MYSQL_PROC_FIELD_COUNT, proc_table_fields}; + /*************************************************************************/ /** @@ -247,6 +363,50 @@ Stored_routine_creation_ctx::load_from_db(THD *thd, /*************************************************************************/ +class Proc_table_intact : public Table_check_intact +{ +private: + bool m_print_once; + +public: + Proc_table_intact() : m_print_once(TRUE) {} + +protected: + void report_error(uint code, const char *fmt, ...); +}; + + +/** + Report failure to validate the mysql.proc table definition. + Print a message to the error log only once. +*/ + +void Proc_table_intact::report_error(uint code, const char *fmt, ...) +{ + va_list args; + char buf[512]; + + va_start(args, fmt); + my_vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + if (code) + my_message(code, buf, MYF(0)); + else + my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "proc"); + + if (m_print_once) + { + m_print_once= FALSE; + sql_print_error("%s", buf); + } +}; + + +/** Single instance used to control printing to the error log. */ +static Proc_table_intact proc_table_intact; + + /** Open the mysql.proc table for read. @@ -266,15 +426,17 @@ TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup) DBUG_ENTER("open_proc_table_for_read"); TABLE_LIST table; - bzero((char*) &table, sizeof(table)); - table.db= (char*) "mysql"; - table.table_name= table.alias= (char*)"proc"; - table.lock_type= TL_READ; + table.init_one_table("mysql", "proc", TL_READ); - if (!open_system_tables_for_read(thd, &table, backup)) + if (open_system_tables_for_read(thd, &table, backup)) + DBUG_RETURN(NULL); + + if (!proc_table_intact.check(table.table, &proc_table_def)) DBUG_RETURN(table.table); - else - DBUG_RETURN(0); + + close_system_tables(thd, backup); + + DBUG_RETURN(NULL); } @@ -296,13 +458,19 @@ static TABLE *open_proc_table_for_update(THD *thd) { DBUG_ENTER("open_proc_table_for_update"); - TABLE_LIST table; - bzero((char*) &table, sizeof(table)); - table.db= (char*) "mysql"; - table.table_name= table.alias= (char*)"proc"; - table.lock_type= TL_WRITE; + TABLE *table; + TABLE_LIST table_list; + table_list.init_one_table("mysql", "proc", TL_WRITE); - DBUG_RETURN(open_system_table_for_update(thd, &table)); + if (!(table= open_system_table_for_update(thd, &table_list))) + DBUG_RETURN(NULL); + + if (!proc_table_intact.check(table, &proc_table_def)) + DBUG_RETURN(table); + + close_thread_tables(thd); + + DBUG_RETURN(NULL); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index fd87a5c0961..eb91f66d114 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -31,9 +31,8 @@ #include "sp_head.h" #include "sp.h" -time_t mysql_db_table_last_check= 0L; - -TABLE_FIELD_W_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = { +static const +TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = { { { C_STRING_WITH_LEN("Host") }, { C_STRING_WITH_LEN("char(60)") }, @@ -146,6 +145,8 @@ TABLE_FIELD_W_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = { } }; +const TABLE_FIELD_DEF + mysql_db_table_def= {MYSQL_DB_FIELD_COUNT, mysql_db_table_fields}; #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/sql_acl.h b/sql/sql_acl.h index a8090fba2e7..4c835e2718c 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -159,8 +159,7 @@ enum mysql_db_table_field MYSQL_DB_FIELD_COUNT }; -extern TABLE_FIELD_W_TYPE mysql_db_table_fields[]; -extern time_t mysql_db_table_last_check; +extern const TABLE_FIELD_DEF mysql_db_table_def; /* Classes */ diff --git a/sql/table.cc b/sql/table.cc index 35e8d83369f..752b6ba0bd4 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2811,34 +2811,38 @@ bool check_column_name(const char *name) and such errors never reach the user. */ -my_bool -table_check_intact(TABLE *table, const uint table_f_count, - const TABLE_FIELD_W_TYPE *table_def) +bool +Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) { uint i; my_bool error= FALSE; - my_bool fields_diff_count; + const TABLE_FIELD_TYPE *field_def= table_def->field; DBUG_ENTER("table_check_intact"); DBUG_PRINT("info",("table: %s expected_count: %d", - table->alias, table_f_count)); + table->alias, table_def->count)); - fields_diff_count= (table->s->fields != table_f_count); - if (fields_diff_count) + /* Whether the table definition has already been validated. */ + if (table->s->table_field_def_cache == table_def) + DBUG_RETURN(FALSE); + + if (table->s->fields != table_def->count) { DBUG_PRINT("info", ("Column count has changed, checking the definition")); /* previous MySQL version */ if (MYSQL_VERSION_ID > table->s->mysql_version) { - sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE), - table->alias, table_f_count, table->s->fields, - table->s->mysql_version, MYSQL_VERSION_ID); + report_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, + ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE), + table->alias, table_def->count, table->s->fields, + table->s->mysql_version, MYSQL_VERSION_ID); DBUG_RETURN(TRUE); } else if (MYSQL_VERSION_ID == table->s->mysql_version) { - sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias, - table_f_count, table->s->fields); + report_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED, + ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias, + table_def->count, table->s->fields); DBUG_RETURN(TRUE); } /* @@ -2850,7 +2854,7 @@ table_check_intact(TABLE *table, const uint table_f_count, */ } char buffer[STRING_BUFFER_USUAL_SIZE]; - for (i=0 ; i < table_f_count; i++, table_def++) + for (i=0 ; i < table_def->count; i++, field_def++) { String sql_type(buffer, sizeof(buffer), system_charset_info); sql_type.length(0); @@ -2858,18 +2862,18 @@ table_check_intact(TABLE *table, const uint table_f_count, { Field *field= table->field[i]; - if (strncmp(field->field_name, table_def->name.str, - table_def->name.length)) + if (strncmp(field->field_name, field_def->name.str, + field_def->name.length)) { /* Name changes are not fatal, we use ordinal numbers to access columns. Still this can be a sign of a tampered table, output an error to the error log. */ - sql_print_error("Incorrect definition of table %s.%s: " - "expected column '%s' at position %d, found '%s'.", - table->s->db.str, table->alias, table_def->name.str, i, - field->field_name); + report_error(0, "Incorrect definition of table %s.%s: " + "expected column '%s' at position %d, found '%s'.", + table->s->db.str, table->alias, field_def->name.str, i, + field->field_name); } field->sql_type(sql_type); /* @@ -2889,47 +2893,51 @@ table_check_intact(TABLE *table, const uint table_f_count, the new table definition is backward compatible with the original one. */ - if (strncmp(sql_type.c_ptr_safe(), table_def->type.str, - table_def->type.length - 1)) + if (strncmp(sql_type.c_ptr_safe(), field_def->type.str, + field_def->type.length - 1)) { - sql_print_error("Incorrect definition of table %s.%s: " - "expected column '%s' at position %d to have type " - "%s, found type %s.", table->s->db.str, table->alias, - table_def->name.str, i, table_def->type.str, - sql_type.c_ptr_safe()); + report_error(0, "Incorrect definition of table %s.%s: " + "expected column '%s' at position %d to have type " + "%s, found type %s.", table->s->db.str, table->alias, + field_def->name.str, i, field_def->type.str, + sql_type.c_ptr_safe()); error= TRUE; } - else if (table_def->cset.str && !field->has_charset()) + else if (field_def->cset.str && !field->has_charset()) { - sql_print_error("Incorrect definition of table %s.%s: " - "expected the type of column '%s' at position %d " - "to have character set '%s' but the type has no " - "character set.", table->s->db.str, table->alias, - table_def->name.str, i, table_def->cset.str); + report_error(0, "Incorrect definition of table %s.%s: " + "expected the type of column '%s' at position %d " + "to have character set '%s' but the type has no " + "character set.", table->s->db.str, table->alias, + field_def->name.str, i, field_def->cset.str); error= TRUE; } - else if (table_def->cset.str && - strcmp(field->charset()->csname, table_def->cset.str)) + else if (field_def->cset.str && + strcmp(field->charset()->csname, field_def->cset.str)) { - sql_print_error("Incorrect definition of table %s.%s: " - "expected the type of column '%s' at position %d " - "to have character set '%s' but found " - "character set '%s'.", table->s->db.str, table->alias, - table_def->name.str, i, table_def->cset.str, - field->charset()->csname); + report_error(0, "Incorrect definition of table %s.%s: " + "expected the type of column '%s' at position %d " + "to have character set '%s' but found " + "character set '%s'.", table->s->db.str, table->alias, + field_def->name.str, i, field_def->cset.str, + field->charset()->csname); error= TRUE; } } else { - sql_print_error("Incorrect definition of table %s.%s: " - "expected column '%s' at position %d to have type %s " - " but the column is not found.", - table->s->db.str, table->alias, - table_def->name.str, i, table_def->type.str); + report_error(0, "Incorrect definition of table %s.%s: " + "expected column '%s' at position %d to have type %s " + " but the column is not found.", + table->s->db.str, table->alias, + field_def->name.str, i, field_def->type.str); error= TRUE; } } + + if (! error) + table->s->table_field_def_cache= table_def; + DBUG_RETURN(error); } diff --git a/sql/table.h b/sql/table.h index e4a382c799f..eae261cc97d 100644 --- a/sql/table.h +++ b/sql/table.h @@ -285,6 +285,36 @@ typedef enum enum_table_category TABLE_CATEGORY; TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name); + +typedef struct st_table_field_type +{ + LEX_STRING name; + LEX_STRING type; + LEX_STRING cset; +} TABLE_FIELD_TYPE; + + +typedef struct st_table_field_def +{ + uint count; + const TABLE_FIELD_TYPE *field; +} TABLE_FIELD_DEF; + + +class Table_check_intact +{ +protected: + virtual void report_error(uint code, const char *fmt, ...)= 0; + +public: + Table_check_intact() {} + virtual ~Table_check_intact() {} + + /** Checks whether a table is intact. */ + bool check(TABLE *table, const TABLE_FIELD_DEF *table_def); +}; + + /* This structure is shared between different table objects. There is one instance of table share per one table in the database. @@ -421,6 +451,18 @@ typedef struct st_table_share handlerton *default_part_db_type; #endif + /** + Cache the checked structure of this table. + + The pointer data is used to describe the structure that + a instance of the table must have. Each element of the + array specifies a field that must exist on the table. + + The pointer is cached in order to perform the check only + once -- when the table is loaded from the disk. + */ + const TABLE_FIELD_DEF *table_field_def_cache; + /** place to store storage engine specific data */ void *ha_data; @@ -1662,17 +1704,6 @@ typedef struct st_open_table_list{ uint32 in_use,locked; } OPEN_TABLE_LIST; -typedef struct st_table_field_w_type -{ - LEX_STRING name; - LEX_STRING type; - LEX_STRING cset; -} TABLE_FIELD_W_TYPE; - - -my_bool -table_check_intact(TABLE *table, const uint table_f_count, - const TABLE_FIELD_W_TYPE *table_def); static inline my_bitmap_map *tmp_use_all_columns(TABLE *table, MY_BITMAP *bitmap) From 64f097dc8021ac810ac1fcaba3d341bb610e8204 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Sat, 21 Nov 2009 10:11:45 -0200 Subject: [PATCH 058/344] Post-merge fixes: fix typo and remove unused variables. --- client/mysqltest.cc | 5 +---- configure.in | 2 +- vio/viosslfactories.c | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index cb1d21ebe8a..e0cdec42a60 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6827,10 +6827,8 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command, MYSQL_STMT *stmt; DYNAMIC_STRING ds_prepare_warnings; DYNAMIC_STRING ds_execute_warnings; - ulonglong affected_rows; DBUG_ENTER("run_query_stmt"); DBUG_PRINT("query", ("'%-.60s'", query)); - LINT_INIT(affected_rows); /* Init a new stmt if it's not already one created for this connection @@ -6966,8 +6964,7 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command, warnings here */ { - ulonglong affected_rows; - LINT_INIT(affected_rows); + ulonglong UNINIT_VAR(affected_rows); if (!disable_info) affected_rows= mysql_affected_rows(mysql); diff --git a/configure.in b/configure.in index a32956858f4..79138561dcb 100644 --- a/configure.in +++ b/configure.in @@ -15,7 +15,7 @@ AM_CONFIG_HEADER([include/config.h:config.h.in]) # Request support for automake silent-rules if available. # Default to verbose output. One can use the configure-time -# option --enable-silent-rules or make V=1 to activate +# option --enable-silent-rules or make V=0 to activate # silent rules. m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([no])]) diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 51d049b18b9..d0a0a69f70b 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -19,7 +19,6 @@ static my_bool ssl_algorithms_added = FALSE; static my_bool ssl_error_strings_loaded= FALSE; -static int verify_depth = 0; static unsigned char dh512_p[]= { From a2ed682967bdc29d249d0f607f4eea4d84a81761 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Nov 2009 13:10:33 +0800 Subject: [PATCH 059/344] Bug #48350 truncate temporary table crashes replication In RBR, All statements operating on temporary tables should not be binlogged. Despite this fact, after executing 'TRUNCATE... ' on a temporary table, the command is still logged, even if in row-based mode. Consequently, this raises problems in the slave as the table may not exist, resulting in an execution failure. Ultimately, this causes the slave to report an error and abort. After this patch, 'TRUNCATE ...' statement on a temporary table will not be binlogged in RBR. --- .../suite/rpl/r/rpl_row_trunc_temp.result | 29 +++++++++++++++ .../suite/rpl/t/rpl_row_trunc_temp.test | 35 +++++++++++++++++++ sql/sql_delete.cc | 10 +++--- 3 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_row_trunc_temp.result create mode 100644 mysql-test/suite/rpl/t/rpl_row_trunc_temp.test diff --git a/mysql-test/suite/rpl/r/rpl_row_trunc_temp.result b/mysql-test/suite/rpl/r/rpl_row_trunc_temp.result new file mode 100644 index 00000000000..f9181be9bc0 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_row_trunc_temp.result @@ -0,0 +1,29 @@ +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 TEMPORARY TABLE t1(c1 INTEGER); +CREATE TABLE t2(c1 INTEGER); +CREATE TABLE t1(c1 INTEGER); +INSERT INTO t1 VALUES(1), (2); +INSERT INTO t2 VALUES(1), (2); +SELECT * FROM t1; +c1 +1 +2 +SELECT * FROM t2; +c1 +1 +2 +TRUNCATE t1; +TRUNCATE t2; +SELECT * FROM t1; +c1 +1 +2 +SELECT * FROM t2; +c1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/rpl/t/rpl_row_trunc_temp.test b/mysql-test/suite/rpl/t/rpl_row_trunc_temp.test new file mode 100644 index 00000000000..60e1cd73200 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_trunc_temp.test @@ -0,0 +1,35 @@ +# +# Bug#48350 truncate temporary table crashes replication +# +# All statements operating on temporary tables should not be binlogged in RBR. +# However, before fix of bug#48350, 'TRUNCATE ...' statement on a temporary +# table was binlogged in RBR. +# + +--source include/master-slave.inc +--source include/have_binlog_format_row.inc + +#This statement is not binlogged in RBR. +CREATE TEMPORARY TABLE t1(c1 INTEGER); +CREATE TABLE t2(c1 INTEGER); +sync_slave_with_master; + +CREATE TABLE t1(c1 INTEGER); +INSERT INTO t1 VALUES(1), (2); +INSERT INTO t2 VALUES(1), (2); +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; +TRUNCATE t1; +TRUNCATE t2; +sync_slave_with_master; +# t1 will have nothing, if 'TRUNCATE t1' has been replicate from master to +# slave. +SELECT * FROM t1; +SELECT * FROM t2; + +DROP TABLE t1; +connection master; +DROP TABLE t2; +--source include/master-slave-end.inc diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 93b19c5b233..6b9a83e695b 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1090,6 +1090,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) TABLE *table; bool error; uint path_length; + bool is_temporary_table= false; DBUG_ENTER("mysql_truncate"); bzero((char*) &create_info,sizeof(create_info)); @@ -1100,6 +1101,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) /* If it is a temporary table, close and regenerate it */ if (!dont_send_ok && (table= find_temporary_table(thd, table_list))) { + is_temporary_table= true; handlerton *table_type= table->s->db_type(); TABLE_SHARE *share= table->s; if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE)) @@ -1163,11 +1165,9 @@ end: { if (!error) { - /* - TRUNCATE must always be statement-based binlogged (not row-based) so - we don't test current_stmt_binlog_row_based. - */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + /* In RBR, the statement is not binlogged if the table is temporary. */ + if (!is_temporary_table || !thd->current_stmt_binlog_row_based) + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); my_ok(thd); // This should return record count } VOID(pthread_mutex_lock(&LOCK_open)); From d4db598110fbf2a4ae92a7d4549e9f7f11fa42a6 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 23 Nov 2009 17:32:10 +0200 Subject: [PATCH 060/344] Additional fix for bug #45613: handle failures from my_hash_insert Testing for presence of stuff in a hash inside the function that's filling in the hash creates chicken-and-egg type of problems. This results in test suite failures in mysql-pe in debug mode and adds bad initialization dependency in 5.1. Fixed by removing the debug code. --- mysys/hash.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mysys/hash.c b/mysys/hash.c index 48ac122fa34..9c1957bf0aa 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -334,7 +334,6 @@ my_bool my_hash_insert(HASH *info, const uchar *record) size_t idx,halfbuff,hash_nr,first_index; uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; - DBUG_EXECUTE("fail_hash_insert",return(TRUE);); if (HASH_UNIQUE & info->flags) { From f20d15d07faa14a865148e6d965a908138e36bbf Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Mon, 23 Nov 2009 13:54:27 -0800 Subject: [PATCH 061/344] Fix C99 aliasing violation due to mismatched types that were papered over with a cast. (Bug #48284) --- libmysql/libmysql.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 77ff2a01d7c..98955c8fc89 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2285,7 +2285,7 @@ mysql_stmt_param_metadata(MYSQL_STMT *stmt) /* Store type of parameter in network buffer. */ -static void store_param_type(char **pos, MYSQL_BIND *param) +static void store_param_type(unsigned char **pos, MYSQL_BIND *param) { uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0); int2store(*pos, typecode); @@ -2565,7 +2565,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt) that is sent to the server. */ for (param= stmt->params; param < param_end ; param++) - store_param_type((char**) &net->write_pos, param); + store_param_type(&net->write_pos, param); } for (param= stmt->params; param < param_end; param++) From 84c5abbd33856ba730b1e9091146d986f1923bfa Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Mon, 23 Nov 2009 14:38:08 -0800 Subject: [PATCH 062/344] Backport fix for Bug #27884. --- client/mysql.cc | 11 +++++++---- mysql-test/r/mysql.result | 1 + mysql-test/t/mysql.test | 6 ++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 9474e4beccc..e4eabe8de33 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -3387,9 +3387,12 @@ print_table_data_html(MYSQL_RES *result) { while((field = mysql_fetch_field(result))) { - tee_fprintf(PAGER, "%s", (field->name ? - (field->name[0] ? field->name : - "   ") : "NULL")); + tee_fputs("", PAGER); + if (field->name && field->name[0]) + xmlencode_print(field->name, field->name_length); + else + tee_fputs(field->name ? "   " : "NULL", PAGER); + tee_fputs("", PAGER); } (void) tee_fputs("", PAGER); } @@ -3400,7 +3403,7 @@ print_table_data_html(MYSQL_RES *result) for (uint i=0; i < mysql_num_fields(result); i++) { (void) tee_fputs("", PAGER); - safe_put_field(cur[i],lengths[i]); + xmlencode_print(cur[i], lengths[i]); (void) tee_fputs("", PAGER); } (void) tee_fputs("", PAGER); diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 4affd884753..1945f893f04 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -199,4 +199,5 @@ COUNT (*) COUNT (*) 1 ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'invalid_hostname' (errno) +
<
< & >
End of 5.0 tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index b2d7400d156..0cdb0ddb653 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -356,4 +356,10 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug31060.sql; --exec $MYSQL --default-character-set=binary test -e "CONNECT test invalid_hostname" 2>&1 --exec $MYSQL --default-character-set=binary test -e "DELIMITER //" 2>&1 +# +# Bug #27884: mysql --html does not quote HTML special characters in output +# +--exec $MYSQL --html test -e "select '< & >' as \`<\`" +--echo + --echo End of 5.0 tests From dfe177aa227c0bbdb4beb844ab7f62ca4e6106b6 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Tue, 24 Nov 2009 20:04:02 +0000 Subject: [PATCH 063/344] BUG#48340: rpl_cross_version: Found warnings/errors in server log file! Valgrind reports a conditional jump that depends on uninitialized data while doing a LOAD DATA and for this test case only. This test case, tests that loading data from a 4.0 or 4.1 instance into a 5.1 instance is working. As such it handles old binary log with a different set of events than currently 5.1 codebase uses. See the following reference for details: http://forge.mysql.com/wiki/MySQL_Internals_Binary_Log#LOAD_DATA_INFILE_Events Problem: The server is handling an Execute_load_log_event, which results in reading a Load_log_event from the binary log and applying it. When applying the Load_log_event, some variable setup is done and then mysql_load is called. Late in mysql_load execution, if not in row mode logging, the event is binlogged write_execute_load_query_log_event. In write_execute_load_query_log_event, thd->lex->local_file is inspected. The problem is that it has not been set before in the execution stack. This causes valgrind to report the warning. Fix: We fix this by initializing thd->lex->local_file to be the same as the value of Load_log_event::local_fname, when lex_start is called inside Load_log_event::do_apply_event. --- sql/log_event.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/log_event.cc b/sql/log_event.cc index 2cb253c9c56..73580636b7b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -4510,6 +4510,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, as the present method does not call mysql_parse(). */ lex_start(thd); + thd->lex->local_file= local_fname; mysql_reset_thd_for_next_command(thd); if (!use_rli_only_for_errors) From 6cfe31e382ac5fb22eada408dc37eb368536a592 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 24 Nov 2009 19:25:23 -0200 Subject: [PATCH 064/344] Post-merge fix for bug 41728: revert fix that was pushed in mistake to 5.1 and up. --- include/mysql.h | 10 ---------- include/mysql.h.pp | 10 ---------- libmysql/libmysql.c | 14 -------------- libmysql/libmysql.def | 1 - libmysqld/libmysqld.def | 1 - 5 files changed, 36 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index 68cce3196a0..d114afb6c93 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -557,16 +557,6 @@ unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length); void STDCALL mysql_debug(const char *debug); -char * STDCALL mysql_odbc_escape_string(MYSQL *mysql, - char *to, - unsigned long to_length, - const char *from, - unsigned long from_length, - void *param, - char * - (*extend_buffer) - (void *, char *to, - unsigned long *length)); void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name); unsigned int STDCALL mysql_thread_safe(void); my_bool STDCALL mysql_embedded(void); diff --git a/include/mysql.h.pp b/include/mysql.h.pp index bd4c79916dd..633cde41130 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -518,16 +518,6 @@ unsigned long mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length); void mysql_debug(const char *debug); -char * mysql_odbc_escape_string(MYSQL *mysql, - char *to, - unsigned long to_length, - const char *from, - unsigned long from_length, - void *param, - char * - (*extend_buffer) - (void *, char *to, - unsigned long *length)); void myodbc_remove_escape(MYSQL *mysql,char *name); unsigned int mysql_thread_safe(void); my_bool mysql_embedded(void); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 77ff2a01d7c..1264f2765ba 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1629,20 +1629,6 @@ mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, return (uint) escape_string_for_mysql(mysql->charset, to, 0, from, length); } - -char * STDCALL -mysql_odbc_escape_string(MYSQL *mysql __attribute__((unused)), - char *to __attribute__((unused)), - ulong to_length __attribute__((unused)), - const char *from __attribute__((unused)), - ulong from_length __attribute__((unused)), - void *param __attribute__((unused)), - char * (*extend_buffer)(void *, char *, ulong *) - __attribute__((unused))) -{ - return NULL; -} - void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name) { diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 8c6b71d9553..81f86dc8726 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -78,7 +78,6 @@ EXPORTS mysql_next_result mysql_num_fields mysql_num_rows - mysql_odbc_escape_string mysql_options mysql_stmt_param_count mysql_stmt_param_metadata diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def index e0f02003963..047cfe0fe57 100644 --- a/libmysqld/libmysqld.def +++ b/libmysqld/libmysqld.def @@ -50,7 +50,6 @@ EXPORTS mysql_next_result mysql_num_fields mysql_num_rows - mysql_odbc_escape_string mysql_options mysql_ping mysql_query From 82b115ec1619b7cf6dc1f308d875e154530b16a3 Mon Sep 17 00:00:00 2001 From: Satya B Date: Wed, 25 Nov 2009 12:25:49 +0530 Subject: [PATCH 065/344] Fix for BUG#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39 mysql client displays wrong character-set of server. When a user changes the charset of a server, mysql client 'status' command displays wrong charset but the command "SHOW VARIABLES LIKE "%charset%" displayed correct charset results. The problem is only with the mysql client's 'status' command output. In mysql client, the method mysql_store_lazy_result() returns 0 for success and non-zero for failure. The method com_status() was using this method wrongly. Fixed all such instances according to return value of the method mysql_store_lazy_result(). client/mysql.cc: Fix for BUG#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39 Fix com_status() method to use mysql_store_lazy_result() properly. mysql-test/r/bug47671.result: Fix for BUG#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39 Testcase for BUG#47671 mysql-test/t/bug47671-master.opt: Fix for BUG#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39 Testcase for BUG#47671 mysql-test/t/bug47671.test: Fix for BUG#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39 Testcase for BUG#47671 --- client/mysql.cc | 4 ++-- mysql-test/r/bug47671.result | 13 +++++++++++++ mysql-test/t/bug47671-master.opt | 1 + mysql-test/t/bug47671.test | 6 ++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/bug47671.result create mode 100644 mysql-test/t/bug47671-master.opt create mode 100644 mysql-test/t/bug47671.test diff --git a/client/mysql.cc b/client/mysql.cc index b76a3d624ab..44bd362fc56 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -4335,7 +4335,7 @@ com_status(String *buffer __attribute__((unused)), Don't remove "limit 1", it is protection againts SQL_SELECT_LIMIT=0 */ - if (mysql_store_result_for_lazy(&result)) + if (!mysql_store_result_for_lazy(&result)) { MYSQL_ROW cur=mysql_fetch_row(result); if (cur) @@ -4379,7 +4379,7 @@ com_status(String *buffer __attribute__((unused)), if (mysql_errno(&mysql) == CR_SERVER_GONE_ERROR) return 0; } - if (mysql_store_result_for_lazy(&result)) + if (!mysql_store_result_for_lazy(&result)) { MYSQL_ROW cur=mysql_fetch_row(result); if (cur) diff --git a/mysql-test/r/bug47671.result b/mysql-test/r/bug47671.result new file mode 100644 index 00000000000..2cff6f1b59c --- /dev/null +++ b/mysql-test/r/bug47671.result @@ -0,0 +1,13 @@ +# +# Bug#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39 +# +# Extract only charset information from 'status' command output using regex +-------------- + +Server characterset: utf8 +Db characterset: utf8 +Client characterset: utf8 +Conn. characterset: utf8 + +-------------- + diff --git a/mysql-test/t/bug47671-master.opt b/mysql-test/t/bug47671-master.opt new file mode 100644 index 00000000000..0afdf49e022 --- /dev/null +++ b/mysql-test/t/bug47671-master.opt @@ -0,0 +1 @@ +--default-character-set=utf8 --skip-character-set-client-handshake diff --git a/mysql-test/t/bug47671.test b/mysql-test/t/bug47671.test new file mode 100644 index 00000000000..3efff39ff58 --- /dev/null +++ b/mysql-test/t/bug47671.test @@ -0,0 +1,6 @@ +--echo # +--echo # Bug#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39 +--echo # +--echo # Extract only charset information from 'status' command output using regex +--replace_regex /.*mysql.*// /Connection.*// /Current.*// /SSL.*// /Using.*// /Server version.*// /Protocol.*// /UNIX.*// /Uptime.*// /Threads.*// +--exec $MYSQL -u root test -e "status"; From 2bf2e8f9dd619ba7ecb635a0eb51a7a4f9db977b Mon Sep 17 00:00:00 2001 From: Satya B Date: Wed, 25 Nov 2009 15:08:52 +0530 Subject: [PATCH 066/344] Applying InnoDB snapshot 5.0-ss6230, Part 1. Fixes BUG#47777 BUG#47777 - innodb dies with spatial pk: Failing assertion: buf <= original_buf + buf_len Detailed revision comments: r6178 | jyang | 2009-11-17 08:52:11 +0200 (Tue, 17 Nov 2009) | 6 lines branches/5.0: Merge fix for bug #47777 from branches/5.1 -r6045 to bracnches/5.0. Treat the Geometry data same as Binary BLOB in ha_innobase::store_key_val_for_row(), since the Geometry data is stored as Binary BLOB in Innodb. --- mysql-test/r/innodb_bug47777.result | 13 +++++++++++++ mysql-test/t/innodb_bug47777.test | 24 ++++++++++++++++++++++++ sql/ha_innodb.cc | 5 ++++- 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/innodb_bug47777.result create mode 100644 mysql-test/t/innodb_bug47777.test diff --git a/mysql-test/r/innodb_bug47777.result b/mysql-test/r/innodb_bug47777.result new file mode 100644 index 00000000000..fbba47edcfc --- /dev/null +++ b/mysql-test/r/innodb_bug47777.result @@ -0,0 +1,13 @@ +create table bug47777(c2 linestring not null, primary key (c2(1))) engine=innodb; +insert into bug47777 values (geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)')); +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +count(*) +1 +update bug47777 set c2=GeomFromText('POINT(1 1)'); +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +count(*) +0 +select count(*) from bug47777 where c2 = GeomFromText('POINT(1 1)'); +count(*) +1 +drop table bug47777; diff --git a/mysql-test/t/innodb_bug47777.test b/mysql-test/t/innodb_bug47777.test new file mode 100644 index 00000000000..8f2985b2cf0 --- /dev/null +++ b/mysql-test/t/innodb_bug47777.test @@ -0,0 +1,24 @@ +# This is the test for bug 47777. GEOMETRY +# data is treated as BLOB data in innodb. +# Consequently, its key value generation/storing +# should follow the process for the BLOB +# datatype as well. + +--source include/have_innodb.inc + +create table bug47777(c2 linestring not null, primary key (c2(1))) engine=innodb; + +insert into bug47777 values (geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)')); + +# Verify correct row get inserted. +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); + +# Update table bug47777 should be successful. +update bug47777 set c2=GeomFromText('POINT(1 1)'); + +# Verify the row get updated successfully. The original +# c2 value should be changed to GeomFromText('POINT(1 1)'). +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +select count(*) from bug47777 where c2 = GeomFromText('POINT(1 1)'); + +drop table bug47777; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 4bd54805a95..29d416c666c 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2767,7 +2767,10 @@ ha_innobase::store_key_val_for_row( } else if (mysql_type == FIELD_TYPE_TINY_BLOB || mysql_type == FIELD_TYPE_MEDIUM_BLOB || mysql_type == FIELD_TYPE_BLOB - || mysql_type == FIELD_TYPE_LONG_BLOB) { + || mysql_type == FIELD_TYPE_LONG_BLOB + /* MYSQL_TYPE_GEOMETRY data is treated + as BLOB data in innodb. */ + || mysql_type == FIELD_TYPE_GEOMETRY) { CHARSET_INFO* cs; ulint key_len; From 0039944e0c739940a7228e916058f57b0e39b5db Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Wed, 25 Nov 2009 12:52:03 +0300 Subject: [PATCH 067/344] Additional fix for the bug#43668. Arg_comparator now takes into account that some of optimizations aren't done in the PREPARE stmt. --- sql/item_cmpfunc.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 9662c0209c8..fd5eca8911a 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -960,12 +960,23 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, (*b)->field_type() == MYSQL_TYPE_YEAR)) { is_nulls_eq= is_owner_equal_func(); + year_as_datetime= FALSE; + if ((*a)->is_datetime()) { year_as_datetime= TRUE; get_value_a_func= &get_datetime_value; } else if ((*a)->field_type() == MYSQL_TYPE_YEAR) get_value_a_func= &get_year_value; + else + { + /* + Because convert_constant_item is called only for EXECUTE in PS mode + the value of get_value_x_func set in PREPARE might be not + valid for EXECUTE. + */ + get_value_a_func= NULL; + } if ((*b)->is_datetime()) { @@ -973,6 +984,8 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, get_value_b_func= &get_datetime_value; } else if ((*b)->field_type() == MYSQL_TYPE_YEAR) get_value_b_func= &get_year_value; + else + get_value_b_func= NULL; func= &Arg_comparator::compare_year; return 0; From 97d74332c2edd81754f3771f4212fa653f8c7864 Mon Sep 17 00:00:00 2001 From: Satya B Date: Wed, 25 Nov 2009 15:29:25 +0530 Subject: [PATCH 068/344] Applying InnoDB snapshot 5.0-ss6230, part 2. Fixes BUG#46000 BUG#46000 - using index called GEN_CLUST_INDEX crashes server Detailed revision comments: r6180 | jyang | 2009-11-17 10:54:57 +0200 (Tue, 17 Nov 2009) | 7 lines branches/5.0: Merge/Port fix for bug #46000 from branches/5.1 -r5895 to branches/5.0. Disallow creating index with the name of "GEN_CLUST_INDEX" which is reserved for the default system primary index. Minor adjusts on table name screening format for added tests. --- mysql-test/r/innodb_bug46000.result | 13 ++++ mysql-test/t/innodb_bug46000.test | 34 +++++++++++ sql/ha_innodb.cc | 94 ++++++++++++++++++++++++----- 3 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 mysql-test/r/innodb_bug46000.result create mode 100644 mysql-test/t/innodb_bug46000.test diff --git a/mysql-test/r/innodb_bug46000.result b/mysql-test/r/innodb_bug46000.result new file mode 100644 index 00000000000..8a92fa973c0 --- /dev/null +++ b/mysql-test/r/innodb_bug46000.result @@ -0,0 +1,13 @@ +create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb; +ERROR HY000: Can't create table bug46000.frm' (errno: -1) +show warnings; +Level Code Message +Warning 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index. +Error 1005 Can't create table bug46000.frm' (errno: -1) +create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb; +ERROR HY000: Can't create table bug46000.frm' (errno: -1) +create table bug46000(id int) engine=innodb; +create index GEN_CLUST_INDEX on bug46000(id); +ERROR HY000: Can't create table #sql-temporary' (errno: -1) +create index idx on bug46000(id); +drop table bug46000; diff --git a/mysql-test/t/innodb_bug46000.test b/mysql-test/t/innodb_bug46000.test new file mode 100644 index 00000000000..d8b4ed6a638 --- /dev/null +++ b/mysql-test/t/innodb_bug46000.test @@ -0,0 +1,34 @@ +# This is the test for bug 46000. We shall +# block any index creation with the name of +# "GEN_CLUST_INDEX", which is the reserved +# name for innodb default primary index. + +--source include/have_innodb.inc + +# This 'create table' operation should fail because of +# using the reserve name as its index name. +--replace_regex /'[^']*test\/// +--error ER_CANT_CREATE_TABLE +create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb; + +--replace_regex /'[^']*test\/// +show warnings; + +# Mixed upper/lower case of the reserved key words +--replace_regex /'[^']*test\/// +--error ER_CANT_CREATE_TABLE +create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb; + +create table bug46000(id int) engine=innodb; + +# This 'create index' operation should fail. +--replace_regex /'[^']*test\/#sql-[0-9a-f_]*.frm/#sql-temporary/ +--error ER_CANT_CREATE_TABLE +create index GEN_CLUST_INDEX on bug46000(id); + +# This 'create index' operation should succeed, no +# temp table left from last failed create index +# operation. +create index idx on bug46000(id); + +drop table bug46000; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 29d416c666c..6586bf818c1 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -226,6 +226,24 @@ handlerton innobase_hton = { innobase_close_cursor_view, HTON_NO_FLAGS }; +/*********************************************************************** +This function checks each index name for a table against reserved +system default primary index name 'GEN_CLUST_INDEX'. If a name matches, +this function pushes an error message to the client, and returns true. */ +static +bool +innobase_index_name_is_reserved( +/*============================*/ + /* out: true if index name matches a + reserved name */ + const trx_t* trx, /* in: InnoDB transaction handle */ + const TABLE* form, /* in: information on table + columns and indexes */ + const char* norm_name); /* in: table name */ + +/* "GEN_CLUST_INDEX" is the name reserved for Innodb default +system primary index. */ +static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX"; /********************************************************************* Commits a transaction in an InnoDB database. */ @@ -4496,7 +4514,10 @@ create_index( n_fields = key->key_parts; - ind_type = 0; + /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */ + ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0); + + ind_type = 0; if (key_num == form->s->primary_key) { ind_type = ind_type | DICT_CLUSTERED; @@ -4606,9 +4627,8 @@ create_clustered_index_when_no_primary( /* We pass 0 as the space id, and determine at a lower level the space id where to store the table */ - - index = dict_mem_index_create((char*) table_name, - (char*) "GEN_CLUST_INDEX", + index = dict_mem_index_create(table_name, + innobase_index_reserve_name, 0, DICT_CLUSTERED, 0); error = row_create_index_for_mysql(index, trx, NULL); @@ -4706,16 +4726,6 @@ ha_innobase::create( row_mysql_lock_data_dictionary(trx); - /* Create the table definition in InnoDB */ - - error = create_table_def(trx, form, norm_name, - create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL, - form->s->row_type != ROW_TYPE_REDUNDANT); - - if (error) { - goto cleanup; - } - /* Look for a primary key */ primary_key_no= (table->s->primary_key != MAX_KEY ? @@ -4727,6 +4737,23 @@ ha_innobase::create( DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0); + /* Check for name conflicts (with reserved name) for + any user indices to be created. */ + if (innobase_index_name_is_reserved(trx, form, norm_name)) { + error = -1; + goto cleanup; + } + + /* Create the table definition in InnoDB */ + error = create_table_def(trx, form, norm_name, + create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL, + form->s->row_type != ROW_TYPE_REDUNDANT); + + if (error) { + goto cleanup; + } + + /* Create the keys */ if (form->s->keys == 0 || primary_key_no == -1) { @@ -7431,4 +7458,43 @@ innobase_set_cursor_view( (cursor_view_t*) curview); } +/*********************************************************************** +This function checks each index name for a table against reserved +system default primary index name 'GEN_CLUST_INDEX'. If a name matches, +this function pushes an error message to the client, and returns true. */ +static +bool +innobase_index_name_is_reserved( +/*============================*/ + /* out: true if an index name + matches the reserved name */ + const trx_t* trx, /* in: InnoDB transaction handle */ + const TABLE* form, /* in: information on table + columns and indexes */ + const char* norm_name) /* in: table name */ +{ + KEY* key; + uint key_num; /* index number */ + + for (key_num = 0; key_num < form->s->keys; key_num++) { + key = form->key_info + key_num; + + if (innobase_strcasecmp(key->name, + innobase_index_reserve_name) == 0) { + /* Push warning to mysql */ + push_warning_printf((THD*) trx->mysql_thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_CANT_CREATE_TABLE, + "Cannot Create Index with name " + "'%s'. The name is reserved " + "for the system default primary " + "index.", + innobase_index_reserve_name); + + return(true); + } + } + + return(false); +} #endif /* HAVE_INNOBASE_DB */ From 14f2eb124448d69922c10fb818cbdf9b57f8ff63 Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Wed, 25 Nov 2009 11:02:25 +0100 Subject: [PATCH 069/344] Bug#48459: valgrind errors with query using 'Range checked for each record' There was an error in an internal structure in the range optimizer (SEL_ARG). Bad design causes parts of a data structure not to be initialized when it is in a certain state. All client code must check that this state is not present before trying to access the structure's data. Fixed by - Checking the state before trying to access data (in several places, most of which not covered by test case.) - Copying the keypart id when cloning SEL_ARGs mysql-test/r/range.result: Bug#48459: Test result. mysql-test/t/range.test: Bug#48459: Test case. sql/opt_range.cc: Bug#48459: Fix + doxygenated count_key_part_usage comment. --- mysql-test/r/range.result | 33 ++++++++++++++++++++++++ mysql-test/t/range.test | 34 ++++++++++++++++++++++++- sql/opt_range.cc | 53 +++++++++++++++++++-------------------- 3 files changed, 92 insertions(+), 28 deletions(-) diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index ab40eefdc82..64e00521cd2 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -1604,6 +1604,39 @@ str_to_date('', '%Y-%m-%d') 0000-00-00 DROP TABLE t1, t2; # +# Bug#48459: valgrind errors with query using 'Range checked for each +# record' +# +CREATE TABLE t1 ( +a INT, +b CHAR(2), +c INT, +d INT, +KEY ( c ), +KEY ( d, a, b ( 2 ) ), +KEY ( b ( 1 ) ) +); +INSERT INTO t1 VALUES ( NULL, 'a', 1, 2 ), ( NULL, 'a', 1, 2 ), +( 1, 'a', 1, 2 ), ( 1, 'a', 1, 2 ); +CREATE TABLE t2 ( +a INT, +c INT, +e INT, +KEY ( e ) +); +INSERT INTO t2 VALUES ( 1, 1, NULL ), ( 1, 1, NULL ); +# Should not give Valgrind warnings +SELECT 1 +FROM t1, t2 +WHERE t1.d <> '1' AND t1.b > '1' +AND t1.a = t2.a AND t1.c = t2.c; +1 +1 +1 +1 +1 +DROP TABLE t1, t2; +# # Bug #48665: sql-bench's insert test fails due to wrong result # CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a)); diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index 736d65792c5..5d5ad180f1a 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -1260,6 +1260,39 @@ SELECT str_to_date('', '%Y-%m-%d'); DROP TABLE t1, t2; +--echo # +--echo # Bug#48459: valgrind errors with query using 'Range checked for each +--echo # record' +--echo # +CREATE TABLE t1 ( + a INT, + b CHAR(2), + c INT, + d INT, + KEY ( c ), + KEY ( d, a, b ( 2 ) ), + KEY ( b ( 1 ) ) +); + +INSERT INTO t1 VALUES ( NULL, 'a', 1, 2 ), ( NULL, 'a', 1, 2 ), + ( 1, 'a', 1, 2 ), ( 1, 'a', 1, 2 ); + +CREATE TABLE t2 ( + a INT, + c INT, + e INT, + KEY ( e ) +); + +INSERT INTO t2 VALUES ( 1, 1, NULL ), ( 1, 1, NULL ); + +--echo # Should not give Valgrind warnings +SELECT 1 +FROM t1, t2 +WHERE t1.d <> '1' AND t1.b > '1' +AND t1.a = t2.a AND t1.c = t2.c; + +DROP TABLE t1, t2; --echo # --echo # Bug #48665: sql-bench's insert test fails due to wrong result @@ -1280,5 +1313,4 @@ SELECT * FROM t1 FORCE INDEX (PRIMARY) DROP TABLE t1; - --echo End of 5.1 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 9d8d3bd43d9..94204962345 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -446,9 +446,9 @@ public: range_key, *range_key_flag); *range_key_flag|= key_tree->min_flag; if (key_tree->next_key_part && + key_tree->next_key_part->type == SEL_ARG::KEY_RANGE && key_tree->next_key_part->part == key_tree->part+1 && - !(*range_key_flag & (NO_MIN_RANGE | NEAR_MIN)) && - key_tree->next_key_part->type == SEL_ARG::KEY_RANGE) + !(*range_key_flag & (NO_MIN_RANGE | NEAR_MIN))) res+= key_tree->next_key_part->store_min_key(key, range_key, range_key_flag); return res; @@ -462,9 +462,9 @@ public: range_key, *range_key_flag); (*range_key_flag)|= key_tree->max_flag; if (key_tree->next_key_part && + key_tree->next_key_part->type == SEL_ARG::KEY_RANGE && key_tree->next_key_part->part == key_tree->part+1 && - !(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX)) && - key_tree->next_key_part->type == SEL_ARG::KEY_RANGE) + !(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX))) res+= key_tree->next_key_part->store_max_key(key, range_key, range_key_flag); return res; @@ -1700,6 +1700,7 @@ SEL_ARG *SEL_ARG::clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent, tmp->prev= *next_arg; // Link into next/prev chain (*next_arg)->next=tmp; (*next_arg)= tmp; + tmp->part= this->part; } else { @@ -7290,27 +7291,25 @@ int test_rb_tree(SEL_ARG *element,SEL_ARG *parent) } -/* - Count how many times SEL_ARG graph "root" refers to its part "key" +/** + Count how many times SEL_ARG graph "root" refers to its part "key" via + transitive closure. - SYNOPSIS - count_key_part_usage() - root An RB-Root node in a SEL_ARG graph. - key Another RB-Root node in that SEL_ARG graph. + @param root An RB-Root node in a SEL_ARG graph. + @param key Another RB-Root node in that SEL_ARG graph. - DESCRIPTION - The passed "root" node may refer to "key" node via root->next_key_part, - root->next->n + The passed "root" node may refer to "key" node via root->next_key_part, + root->next->n - This function counts how many times the node "key" is referred (via - SEL_ARG::next_key_part) by - - intervals of RB-tree pointed by "root", - - intervals of RB-trees that are pointed by SEL_ARG::next_key_part from - intervals of RB-tree pointed by "root", - - and so on. + This function counts how many times the node "key" is referred (via + SEL_ARG::next_key_part) by + - intervals of RB-tree pointed by "root", + - intervals of RB-trees that are pointed by SEL_ARG::next_key_part from + intervals of RB-tree pointed by "root", + - and so on. - Here is an example (horizontal links represent next_key_part pointers, - vertical links - next/prev prev pointers): + Here is an example (horizontal links represent next_key_part pointers, + vertical links - next/prev prev pointers): +----+ $ |root|-----------------+ @@ -7330,8 +7329,8 @@ int test_rb_tree(SEL_ARG *element,SEL_ARG *parent) ... +---+ $ | | |------------+ +---+ $ - RETURN - Number of links to "key" from nodes reachable from "root". + @return + Number of links to "key" from nodes reachable from "root". */ static ulong count_key_part_usage(SEL_ARG *root, SEL_ARG *key) @@ -7586,8 +7585,8 @@ check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree, param->first_null_comp= key_tree->part+1; if (key_tree->next_key_part && - key_tree->next_key_part->part == key_tree->part+1 && - key_tree->next_key_part->type == SEL_ARG::KEY_RANGE) + key_tree->next_key_part->type == SEL_ARG::KEY_RANGE && + key_tree->next_key_part->part == key_tree->part+1) { // const key as prefix if (min_key_length == max_key_length && !memcmp(min_key, max_key, (uint) (tmp_max_key - max_key)) && @@ -7868,8 +7867,8 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, &tmp_max_key,max_key_flag); if (key_tree->next_key_part && - key_tree->next_key_part->part == key_tree->part+1 && - key_tree->next_key_part->type == SEL_ARG::KEY_RANGE) + key_tree->next_key_part->type == SEL_ARG::KEY_RANGE && + key_tree->next_key_part->part == key_tree->part+1) { // const key as prefix if ((tmp_min_key - min_key) == (tmp_max_key - max_key) && memcmp(min_key, max_key, (uint)(tmp_max_key - max_key))==0 && From 04a344540947ff174c1a14f36fbbe1bb5e55341b Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Wed, 25 Nov 2009 13:23:25 +0100 Subject: [PATCH 070/344] Set version number for mysql-5.1.40sp1 release --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 3e43a5f5779..1d123c96bc9 100644 --- a/configure.in +++ b/configure.in @@ -10,7 +10,7 @@ AC_CANONICAL_SYSTEM # # When changing major version number please also check switch statement # in mysqlbinlog::check_master_version(). -AM_INIT_AUTOMAKE(mysql, 5.1.40) +AM_INIT_AUTOMAKE(mysql, 5.1.40sp1) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 From e55e76d2ddb1c5282522defa396919f8c6d1dbc7 Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Wed, 25 Nov 2009 16:48:29 +0100 Subject: [PATCH 071/344] Move DBG_* macros to after the variable declaration section in a block, might expand to function calls (Bug#48331) --- mysys/my_sync.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysys/my_sync.c b/mysys/my_sync.c index ba6964b00d6..97540f5eb48 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -103,11 +103,11 @@ static const char cur_dir_name[]= {FN_CURLIB, 0}; int my_sync_dir(const char *dir_name, myf my_flags) { #ifdef NEED_EXPLICIT_SYNC_DIR - DBUG_ENTER("my_sync_dir"); - DBUG_PRINT("my",("Dir: '%s' my_flags: %d", dir_name, my_flags)); File dir_fd; int res= 0; const char *correct_dir_name; + DBUG_ENTER("my_sync_dir"); + DBUG_PRINT("my",("Dir: '%s' my_flags: %d", dir_name, my_flags)); /* Sometimes the path does not contain an explicit directory */ correct_dir_name= (dir_name[0] == 0) ? cur_dir_name : dir_name; /* From df570b7ce79801705343750980cb86291d15e6d5 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 17:32:04 +0100 Subject: [PATCH 072/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 1810.3959.4 > revision-id: ramil@mysql.com-20091021090408-208mvwwrcroi2j8c > parent: azundris@mysql.com-20091021033856-ydodp4q42o58e7ka > committer: Ramil Kalimullin > branch nick: b47019-5.0-bugteam > timestamp: Wed 2009-10-21 14:04:08 +0500 > message: > Fix for bug#47019: Assertion failed: 0, file .\rt_mbr.c, > line 138 when forcing a spatial index > > Problem: "Spatial indexes can be involved in the search > for queries that use a function such as MBRContains() > or MBRWithin() in the WHERE clause". > Using spatial indexes for JOINs with =, <=> etc. > predicates is incorrect. > > Fix: disable spatial indexes for such queries. --- mysql-test/r/select.result | 29 +++++++++++++++++++++++++++++ mysql-test/t/select.test | 16 ++++++++++++++++ sql/sql_select.cc | 2 +- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 50b5c3c13fb..a41f95de077 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4386,6 +4386,35 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = `test`.`t1`.`b`) and (`test`.`t1`.`a` > 1)) limit 2 DROP TABLE t1; +# +# Bug#47019: Assertion failed: 0, file .\rt_mbr.c, line 138 when +# forcing a spatial index +# +CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a)); +INSERT INTO t1 VALUES +(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')), +(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')); +EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 +1 SIMPLE t2 ALL a NULL NULL NULL 2 +SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2; +1 +1 +1 +1 +1 +EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 +1 SIMPLE t2 ALL a NULL NULL NULL 2 +SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); +1 +1 +1 +1 +1 +DROP TABLE t1; End of 5.0 tests create table t1(a INT, KEY (a)); INSERT INTO t1 VALUES (1),(2),(3),(4),(5); diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 7d3785ecccc..1e7e853da32 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3739,6 +3739,22 @@ EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND a = b LIMIT 2; EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND b = a LIMIT 2; DROP TABLE t1; + + +--echo # +--echo # Bug#47019: Assertion failed: 0, file .\rt_mbr.c, line 138 when +--echo # forcing a spatial index +--echo # +CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a)); +INSERT INTO t1 VALUES + (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')), + (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')); +EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2; +SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2; +EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); +SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3f1432914a0..79e7012346c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3539,7 +3539,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field) { if (!(form->keys_in_use_for_query.is_set(key))) continue; - if (form->key_info[key].flags & HA_FULLTEXT) + if (form->key_info[key].flags & (HA_FULLTEXT | HA_SPATIAL)) continue; // ToDo: ft-keys in non-ft queries. SerG uint key_parts= (uint) form->key_info[key].key_parts; From e24d997fdbf4610fa2e1f1adefb6162ea54a1996 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 17:35:05 +0100 Subject: [PATCH 073/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 1810.3959.5 > revision-id: ramil@mysql.com-20091023112648-gie6o3odj57cxh1e > parent: ramil@mysql.com-20091021090408-208mvwwrcroi2j8c > committer: Ramil Kalimullin > branch nick: b48258-5.0-bugteam > timestamp: Fri 2009-10-23 16:26:48 +0500 > message: > Fix for bug#48258: Assertion failed when using a spatial index > > Problem: involving a spatial index for "non-spatial" queries > (that don't containt MBRXXX() functions) may lead to failed assert. > > Fix: don't use spatial indexes in such cases. --- mysql-test/r/gis-rtree.result | 39 +++++++++++++++++++++++++++++++++++ mysql-test/t/gis-rtree.test | 21 +++++++++++++++++++ sql/opt_range.cc | 21 +++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result index b030139e40e..68c4a6a13e5 100644 --- a/mysql-test/r/gis-rtree.result +++ b/mysql-test/r/gis-rtree.result @@ -1487,4 +1487,43 @@ MBRINTERSECTS(b, GEOMFROMTEXT('LINESTRING(1 1,1102219 2)') ); COUNT(*) 2 DROP TABLE t1; +# +# Bug #48258: Assertion failed when using a spatial index +# +CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a)); +INSERT INTO t1 VALUES +(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')), +(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')); +EXPLAIN SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where +SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +1 +1 +1 +EXPLAIN SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where +SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +1 +EXPLAIN SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where +SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +1 +1 +1 +EXPLAIN SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where +SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +1 +EXPLAIN SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where +SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +1 +1 +1 +DROP TABLE t1; End of 5.0 tests. diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test index 19bbcf19cca..c325b3bd223 100644 --- a/mysql-test/t/gis-rtree.test +++ b/mysql-test/t/gis-rtree.test @@ -881,4 +881,25 @@ SELECT COUNT(*) FROM t1 IGNORE INDEX (b) WHERE DROP TABLE t1; + +--echo # +--echo # Bug #48258: Assertion failed when using a spatial index +--echo # +CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a)); +INSERT INTO t1 VALUES + (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')), + (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')); +EXPLAIN SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +EXPLAIN SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +EXPLAIN SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +EXPLAIN SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +EXPLAIN SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +DROP TABLE t1; + + --echo End of 5.0 tests. diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 05575e2744b..68c70c915c3 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5709,6 +5709,27 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, !(conf_func->compare_collation()->state & MY_CS_BINSORT)) goto end; + if (key_part->image_type == Field::itMBR) + { + switch (type) { + case Item_func::SP_EQUALS_FUNC: + case Item_func::SP_DISJOINT_FUNC: + case Item_func::SP_INTERSECTS_FUNC: + case Item_func::SP_TOUCHES_FUNC: + case Item_func::SP_CROSSES_FUNC: + case Item_func::SP_WITHIN_FUNC: + case Item_func::SP_CONTAINS_FUNC: + case Item_func::SP_OVERLAPS_FUNC: + break; + default: + /* + We cannot involve spatial indexes for queries that + don't use MBREQUALS(), MBRDISJOINT(), etc. functions. + */ + goto end; + } + } + if (param->using_real_indexes) optimize_range= field->optimize_range(param->real_keynr[key_part->key], key_part->part); From ecd2a1b25950f39e2ca1517ab526f8abb14e9b21 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 17:36:58 +0100 Subject: [PATCH 074/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 1810.3959.6 > revision-id: joro@sun.com-20091021084345-iki6z0uceieoupey > parent: ramil@mysql.com-20091023112648-gie6o3odj57cxh1e > committer: Georgi Kodinov > branch nick: B47780-5.0-bugteam > timestamp: Wed 2009-10-21 11:43:45 +0300 > message: > Bug #47780: crash when comparing GIS items from subquery > > If the first argument to GeomFromWKB function is a geometry > field then the function just returns its value. > However in doing so it's not preserving first argument's > null_value flag and this causes unexpected null value to > be returned to the calling function. > > Fixed by updating the null_value of the GeomFromWKB function > in such cases (and all other cases that return a NULL e.g. > because of not enough memory for the return buffer). --- mysql-test/r/gis.result | 12 ++++++++++++ mysql-test/t/gis.test | 16 ++++++++++++++++ sql/item_geofunc.cc | 9 +++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index a3708d06a1c..b40ff6be160 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -972,6 +972,18 @@ select min(`col002`) from t1 union select `col002` from t1; min(`col002`) NULL drop table t1; +# +# Bug #47780: crash when comparing GIS items from subquery +# +CREATE TABLE t1(a INT, b MULTIPOLYGON); +INSERT INTO t1 VALUES +(0, +GEOMFROMTEXT( +'multipolygon(((1 2,3 4,5 6,7 8,9 8),(7 6,5 4,3 2,1 2,3 4)))')); +# must not crash +SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); +1 +DROP TABLE t1; End of 5.0 tests create table t1 (f1 tinyint(1), f2 char(1), f3 varchar(1), f4 geometry, f5 datetime); create view v1 as select * from t1; diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 4a60e777cc7..2d10c3bf1e1 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -655,6 +655,22 @@ insert into t1 values (),(),(); select min(`col002`) from t1 union select `col002` from t1; drop table t1; +--echo # +--echo # Bug #47780: crash when comparing GIS items from subquery +--echo # + +CREATE TABLE t1(a INT, b MULTIPOLYGON); +INSERT INTO t1 VALUES + (0, + GEOMFROMTEXT( + 'multipolygon(((1 2,3 4,5 6,7 8,9 8),(7 6,5 4,3 2,1 2,3 4)))')); + +--echo # must not crash +SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); + +DROP TABLE t1; + + --echo End of 5.0 tests diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index a34204b7181..3c5990eb359 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -84,7 +84,9 @@ String *Item_func_geometry_from_wkb::val_str(String *str) if (args[0]->field_type() == MYSQL_TYPE_GEOMETRY) { - return args[0]->val_str(str); + String *str_ret= args[0]->val_str(str); + null_value= args[0]->null_value; + return str_ret; } wkb= args[0]->val_str(&arg_val); @@ -94,7 +96,10 @@ String *Item_func_geometry_from_wkb::val_str(String *str) str->set_charset(&my_charset_bin); if (str->reserve(SRID_SIZE, 512)) - return 0; + { + null_value= TRUE; /* purecov: inspected */ + return 0; /* purecov: inspected */ + } str->length(0); str->q_append(srid); if ((null_value= From 4d7944f866cd6b761bc266361b8fffb5c76cb785 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 17:42:10 +0100 Subject: [PATCH 075/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 1810.3961.12 > revision-id: li-bing.song@sun.com-20091103090041-zj7nedx6ok5jgges > parent: davi.arnaut@sun.com-20091102201021-1brn7cjb1kvqg9gr > committer: > branch nick: mysql-5.0-bugteam > timestamp: Tue 2009-11-03 17:00:41 +0800 > message: > BUG#48216 Replication fails on all slaves after upgrade to 5.0.86 on master > > When a sessione is closed, all temporary tables of the session are automatically > dropped and are binlogged. But it will be binlogged with wrong database names when > the length of the temporary tables' database names are greater than the > length of the current database name or the current database is not set. > > Query_log_event's db_len is forgot to set when Query_log_event's db is set. > This patch wrote code to set db_len immediately after db has set. --- sql/sql_base.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d1e96fcdbb3..5225c15f319 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1547,6 +1547,7 @@ void close_temporary_tables(THD *thd) s_query.length() - 1 /* to remove trailing ',' */, 0, FALSE, 0); qinfo.db= db.ptr(); + qinfo.db_len= db.length(); thd->variables.character_set_client= cs_save; mysql_bin_log.write(&qinfo); thd->variables.pseudo_thread_id= save_pseudo_thread_id; From edabd315d608fd8c8979660edb1121f27f770b10 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 17:43:47 +0100 Subject: [PATCH 076/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 1810.3961.6 > revision-id: joro@sun.com-20091030094044-quadg0bwjy7cwqzw > parent: joro@sun.com-20091029152429-ks55fhrp4lhknyij > committer: Georgi Kodinov > branch nick: B48293-5.0-bugteam > timestamp: Fri 2009-10-30 11:40:44 +0200 > message: > Bug #48293: crash with procedure analyse, view with > 10 columns, > having clause... > > The fix for bug 46184 was not very complete. It was not covering > views using temporary tables and multiple tables in a FROM clause. > Fixed by reverting the fix for 46184 and making a more general > check that is checking at the right execution stage and for all > of the non-supported cases. > Now PROCEDURE ANALYZE on non-top level SELECT is also forbidden. > Updated the analyse.test and subselect.test accordingly. --- mysql-test/r/analyse.result | 112 ++++++++++++---------------------- mysql-test/r/subselect.result | 2 +- mysql-test/t/analyse.test | 70 +++++++++++++-------- mysql-test/t/subselect.test | 2 +- sql/sql_select.cc | 12 ++++ sql/sql_yacc.yy | 3 +- 6 files changed, 99 insertions(+), 102 deletions(-) diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index 6eaa8731dc6..1820782d2f8 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -19,81 +19,10 @@ test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL create table t2 select * from t1 procedure analyse(); -select * from t2; -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -test.t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL -test.t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL -test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL -test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL -test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL -drop table t1,t2; +ERROR HY000: Incorrect usage of PROCEDURE and non-SELECT +drop table t1; EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(); ERROR HY000: Incorrect usage of PROCEDURE and subquery -create table t1 (a int not null); -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `Field_name` varbinary(255) NOT NULL DEFAULT '', - `Min_value` varbinary(255) DEFAULT NULL, - `Max_value` varbinary(255) DEFAULT NULL, - `Min_length` bigint(11) NOT NULL DEFAULT '0', - `Max_length` bigint(11) NOT NULL DEFAULT '0', - `Empties_or_zeros` bigint(11) NOT NULL DEFAULT '0', - `Nulls` bigint(11) NOT NULL DEFAULT '0', - `Avg_value_or_avg_length` varbinary(255) NOT NULL DEFAULT '', - `Std` varbinary(255) DEFAULT NULL, - `Optimal_fieldtype` varbinary(64) NOT NULL DEFAULT '' -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -select * from t1 where 0=1 procedure analyse(); -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -insert into t1 values(1); -drop table t2; -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `Field_name` varbinary(255) NOT NULL DEFAULT '', - `Min_value` varbinary(255) DEFAULT NULL, - `Max_value` varbinary(255) DEFAULT NULL, - `Min_length` bigint(11) NOT NULL DEFAULT '0', - `Max_length` bigint(11) NOT NULL DEFAULT '0', - `Empties_or_zeros` bigint(11) NOT NULL DEFAULT '0', - `Nulls` bigint(11) NOT NULL DEFAULT '0', - `Avg_value_or_avg_length` varbinary(255) NOT NULL DEFAULT '', - `Std` varbinary(255) DEFAULT NULL, - `Optimal_fieldtype` varbinary(64) NOT NULL DEFAULT '' -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -select * from t2; -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -insert into t2 select * from t1 procedure analyse(); -select * from t2; -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -test.t1.a 1 1 1 1 0 0 1.0000 0.0000 ENUM('1') NOT NULL -insert into t1 values(2); -drop table t2; -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `Field_name` varbinary(255) NOT NULL DEFAULT '', - `Min_value` varbinary(255) DEFAULT NULL, - `Max_value` varbinary(255) DEFAULT NULL, - `Min_length` bigint(11) NOT NULL DEFAULT '0', - `Max_length` bigint(11) NOT NULL DEFAULT '0', - `Empties_or_zeros` bigint(11) NOT NULL DEFAULT '0', - `Nulls` bigint(11) NOT NULL DEFAULT '0', - `Avg_value_or_avg_length` varbinary(255) NOT NULL DEFAULT '', - `Std` varbinary(255) DEFAULT NULL, - `Optimal_fieldtype` varbinary(64) NOT NULL DEFAULT '' -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -select * from t2; -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -insert into t2 select * from t1 procedure analyse(); -select * from t2; -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -test.t1.a 1 2 1 1 0 0 1.5000 0.5000 ENUM('1','2') NOT NULL -drop table t1,t2; create table t1 (v varchar(128)); insert into t1 values ('abc'),('abc\'def\\hij\"klm\0opq'),('\''),('\"'),('\\'),('a\0'),('b\''),('c\"'),('d\\'),('\'b'),('\"c'),('\\d'),('a\0\0\0b'),('a\'\'\'\'b'),('a\"\"\"\"b'),('a\\\\\\\\b'),('\'\0\\\"'),('\'\''),('\"\"'),('\\\\'),('The\ZEnd'); select * from t1 procedure analyse(); @@ -157,3 +86,40 @@ SELECT * FROM (SELECT * FROM t1) d PROCEDURE ANALYSE(); ERROR HY000: Incorrect usage of PROCEDURE and subquery DROP TABLE t1; End of 4.1 tests +# +# Bug #48293: crash with procedure analyse, view with > 10 columns, +# having clause... +# +CREATE TABLE t1(a INT, b INT, c INT, d INT, e INT, +f INT, g INT, h INT, i INT, j INT,k INT); +INSERT INTO t1 VALUES (),(); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +#should have a derived table +EXPLAIN SELECT * FROM v1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 2 +2 DERIVED t1 ALL NULL NULL NULL NULL 2 +#should not crash +SELECT * FROM v1 PROCEDURE analyse(); +ERROR HY000: Incorrect usage of PROCEDURE and view +#should not crash +SELECT * FROM t1 a, v1, t1 b PROCEDURE analyse(); +ERROR HY000: Incorrect usage of PROCEDURE and view +#should not crash +SELECT * FROM (SELECT * FROM t1 having a > 1) x PROCEDURE analyse(); +ERROR HY000: Incorrect usage of PROCEDURE and subquery +#should not crash +SELECT * FROM t1 a, (SELECT * FROM t1 having a > 1) x, t1 b PROCEDURE analyse(); +ERROR HY000: Incorrect usage of PROCEDURE and subquery +#should not crash +SELECT 1 FROM t1 group by a having a > 1 order by 1 PROCEDURE analyse(); +ERROR HY000: Can't use ORDER clause with this procedure +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1),(2); +# should not crash +CREATE TABLE t2 SELECT 1 FROM t1, t1 t3 GROUP BY t3.a PROCEDURE ANALYSE(); +ERROR HY000: Incorrect usage of PROCEDURE and non-SELECT +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c60ac9790c5..8fd976081d0 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -75,7 +75,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); ERROR HY000: Incorrect usage of PROCEDURE and subquery SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -ERROR HY000: Incorrect usage of PROCEDURE and subquery +ERROR HY000: Incorrect parameters to procedure 'ANALYSE' SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; ERROR 42S22: Unknown column 'a' in 'field list' SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL; diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test index d8466df14bf..05f739bfd69 100644 --- a/mysql-test/t/analyse.test +++ b/mysql-test/t/analyse.test @@ -10,36 +10,13 @@ insert into t1 values (1,2,"","Y","2002-03-03"), (3,4,"","N","2002-03-04"), (5,6 select count(*) from t1 procedure analyse(); select * from t1 procedure analyse(); select * from t1 procedure analyse(2); +--error ER_WRONG_USAGE create table t2 select * from t1 procedure analyse(); -select * from t2; -drop table t1,t2; +drop table t1; --error ER_WRONG_USAGE EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(); -# -# Test with impossible where -# -create table t1 (a int not null); -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -select * from t1 where 0=1 procedure analyse(); -insert into t1 values(1); -drop table t2; -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -select * from t2; -insert into t2 select * from t1 procedure analyse(); -select * from t2; -insert into t1 values(2); -drop table t2; -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -select * from t2; -insert into t2 select * from t1 procedure analyse(); -select * from t2; -drop table t1,t2; - # # Bug#2813 - analyse does not quote string values in enums from string # @@ -113,3 +90,46 @@ SELECT * FROM (SELECT * FROM t1) d PROCEDURE ANALYSE(); DROP TABLE t1; --echo End of 4.1 tests + +--echo # +--echo # Bug #48293: crash with procedure analyse, view with > 10 columns, +--echo # having clause... +--echo # + +CREATE TABLE t1(a INT, b INT, c INT, d INT, e INT, + f INT, g INT, h INT, i INT, j INT,k INT); +INSERT INTO t1 VALUES (),(); + +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +--echo #should have a derived table +EXPLAIN SELECT * FROM v1; +--echo #should not crash +--error ER_WRONG_USAGE +SELECT * FROM v1 PROCEDURE analyse(); +--echo #should not crash +--error ER_WRONG_USAGE +SELECT * FROM t1 a, v1, t1 b PROCEDURE analyse(); +--echo #should not crash +--error ER_WRONG_USAGE +SELECT * FROM (SELECT * FROM t1 having a > 1) x PROCEDURE analyse(); +--echo #should not crash +--error ER_WRONG_USAGE +SELECT * FROM t1 a, (SELECT * FROM t1 having a > 1) x, t1 b PROCEDURE analyse(); +--echo #should not crash +--error ER_ORDER_WITH_PROC +SELECT 1 FROM t1 group by a having a > 1 order by 1 PROCEDURE analyse(); + +DROP VIEW v1; +DROP TABLE t1; + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1),(2); + +--echo # should not crash +--error ER_WRONG_USAGE +CREATE TABLE t2 SELECT 1 FROM t1, t1 t3 GROUP BY t3.a PROCEDURE ANALYSE(); + +DROP TABLE t1; + + +--echo End of 5.0 tests diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 544017ebb97..d8c08b7aa55 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -30,7 +30,7 @@ SELECT 1 IN (SELECT 1); SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); -- error ER_WRONG_USAGE select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); --- error ER_WRONG_USAGE +-- error ER_WRONG_PARAMETERS_TO_PROCEDURE SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -- error ER_BAD_FIELD_ERROR SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 79e7012346c..4b466203800 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -633,6 +633,18 @@ JOIN::prepare(Item ***rref_pointer_array, MYF(0)); /* purecov: inspected */ goto err; /* purecov: inspected */ } + if (thd->lex->derived_tables) + { + my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", + thd->lex->derived_tables & DERIVED_VIEW ? + "view" : "subquery"); + goto err; + } + if (thd->lex->sql_command != SQLCOM_SELECT) + { + my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "non-SELECT"); + goto err; + } } if (!procedure && result && result->prepare(fields_list, unit_arg)) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 12e124230e5..148ca76606f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9082,8 +9082,7 @@ procedure_clause: MYSQL_YYABORT; } - if (&lex->select_lex != lex->current_select || - lex->select_lex.get_table_list()->derived) + if (&lex->select_lex != lex->current_select) { my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery"); MYSQL_YYABORT; From c5ec57b5934f9b5b036216a67e2b78c565c148c6 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 17:45:33 +0100 Subject: [PATCH 077/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 1810.3964.1 > revision-id: alexey.kopytov@sun.com-20091030155453-0vlfwki805h9os62 > parent: joerg@mysql.com-20091016122941-rf6z0keqvmlgjfto > committer: Alexey Kopytov > branch nick: my50-bug48131 > timestamp: Fri 2009-10-30 18:54:53 +0300 > message: > Bug #48131: crash group by with rollup, distinct, filesort, > with temporary tables > > There were two problems the test case from this bug was > triggering: > > 1. JOIN::rollup_init() was supposed to wrap all constant Items > into another object for queries with the WITH ROLLUP modifier > to ensure they are never considered as constants and therefore > are written into temporary tables if the optimizer chooses to > employ them for DISTINCT/GROUP BY handling. > > However, JOIN::rollup_init() was called before > make_join_statistics(), so Items corresponding to fields in > const tables could not be handled as intended, which was > causing all kinds of problems later in the query execution. In > particular, create_tmp_table() assumed all constant items > except "hidden" ones to be removed earlier by remove_const() > which led to improperly initialized Field objects for the > temporary table being created. This is what was causing crashes > and valgrind errors in storage engines. > > 2. Even when the above problem had been fixed, the query from > the test case produced incorrect results due to some > DISTINCT/GROUP BY optimizations being performed by the > optimizer that are inapplicable in the WITH ROLLUP case. > > Fixed by disabling inapplicable DISTINCT/GROUP BY optimizations > when the WITH ROLLUP modifier is present, and splitting the > const-wrapping part of JOIN::rollup_init() into a separate > method which is now invoked after make_join_statistics() when > the const tables are already known. --- mysql-test/r/olap.result | 20 +++++++++ mysql-test/t/olap.test | 15 +++++++ sql/sql_select.cc | 92 ++++++++++++++++++++++++++++------------ sql/sql_select.h | 1 + 4 files changed, 100 insertions(+), 28 deletions(-) diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 4540c9d5218..a7516d97888 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -733,4 +733,24 @@ SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP; 1 1 DROP TABLE t1; +# +# Bug #48131: crash group by with rollup, distinct, +# filesort, with temporary tables +# +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); +INSERT INTO t1 VALUES (1), (2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (100); +SELECT a, b FROM t1, t2 GROUP BY a, b WITH ROLLUP; +a b +1 100 +1 NULL +2 100 +2 NULL +NULL NULL +SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP; +b +100 +NULL +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index d1e40024733..8f672af40a3 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -375,4 +375,19 @@ INSERT INTO t1 VALUES(0); SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP; DROP TABLE t1; +--echo # +--echo # Bug #48131: crash group by with rollup, distinct, +--echo # filesort, with temporary tables +--echo # + +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); +INSERT INTO t1 VALUES (1), (2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (100); + +SELECT a, b FROM t1, t2 GROUP BY a, b WITH ROLLUP; +SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP; + +DROP TABLE t1, t2; + --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4b466203800..94f1206f26c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -970,6 +970,12 @@ JOIN::optimize() DBUG_RETURN(1); } + if (select_lex->olap == ROLLUP_TYPE && rollup_process_const_fields()) + { + DBUG_PRINT("error", ("Error: rollup_process_fields() failed")); + DBUG_RETURN(1); + } + /* Remove distinct if only const tables */ select_distinct= select_distinct && (const_tables != tables); thd_proc_info(thd, "preparing"); @@ -1100,7 +1106,7 @@ JOIN::optimize() join_tab[const_tables].select->quick->get_type() != QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)) { - if (group_list && + if (group_list && rollup.state == ROLLUP::STATE_NONE && list_contains_unique_index(join_tab[const_tables].table, find_field_in_order_list, (void *) group_list)) @@ -1144,7 +1150,8 @@ JOIN::optimize() if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE) select_distinct=0; } - else if (select_distinct && tables - const_tables == 1) + else if (select_distinct && tables - const_tables == 1 && + rollup.state == ROLLUP::STATE_NONE) { /* We are only using one table. In this case we change DISTINCT to a @@ -10203,6 +10210,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, for (; cur_group ; cur_group= cur_group->next, key_part_info++) { Field *field=(*cur_group->item)->get_tmp_table_field(); + DBUG_ASSERT(field->table == table); bool maybe_null=(*cur_group->item)->maybe_null; key_part_info->null_bit=0; key_part_info->field= field; @@ -15622,32 +15630,7 @@ bool JOIN::rollup_init() { item->maybe_null= 1; found_in_group= 1; - if (item->const_item()) - { - /* - For ROLLUP queries each constant item referenced in GROUP BY list - is wrapped up into an Item_func object yielding the same value - as the constant item. The objects of the wrapper class are never - considered as constant items and besides they inherit all - properties of the Item_result_field class. - This wrapping allows us to ensure writing constant items - into temporary tables whenever the result of the ROLLUP - operation has to be written into a temporary table, e.g. when - ROLLUP is used together with DISTINCT in the SELECT list. - Usually when creating temporary tables for a intermidiate - result we do not include fields for constant expressions. - */ - Item* new_item= new Item_func_rollup_const(item); - if (!new_item) - return 1; - new_item->fix_fields(thd, (Item **) 0); - thd->change_item_tree(it.ref(), new_item); - for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next) - { - if (*tmp->item == item) - thd->change_item_tree(tmp->item, new_item); - } - } + break; } } if (item->type() == Item::FUNC_ITEM && !found_in_group) @@ -15666,6 +15649,59 @@ bool JOIN::rollup_init() } return 0; } + +/** + Wrap all constant Items in GROUP BY list. + + For ROLLUP queries each constant item referenced in GROUP BY list + is wrapped up into an Item_func object yielding the same value + as the constant item. The objects of the wrapper class are never + considered as constant items and besides they inherit all + properties of the Item_result_field class. + This wrapping allows us to ensure writing constant items + into temporary tables whenever the result of the ROLLUP + operation has to be written into a temporary table, e.g. when + ROLLUP is used together with DISTINCT in the SELECT list. + Usually when creating temporary tables for a intermidiate + result we do not include fields for constant expressions. + + @retval + 0 if ok + @retval + 1 on error +*/ + +bool JOIN::rollup_process_const_fields() +{ + ORDER *group_tmp; + Item *item; + List_iterator it(all_fields); + + for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next) + { + if (!(*group_tmp->item)->const_item()) + continue; + while ((item= it++)) + { + if (*group_tmp->item == item) + { + Item* new_item= new Item_func_rollup_const(item); + if (!new_item) + return 1; + new_item->fix_fields(thd, (Item **) 0); + thd->change_item_tree(it.ref(), new_item); + for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next) + { + if (*tmp->item == item) + thd->change_item_tree(tmp->item, new_item); + } + break; + } + } + it.rewind(); + } + return 0; +} /** diff --git a/sql/sql_select.h b/sql/sql_select.h index a0366d47149..4c729fa915c 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -502,6 +502,7 @@ public: } bool rollup_init(); + bool rollup_process_const_fields(); bool rollup_make_fields(List &all_fields, List &fields, Item_sum ***func); int rollup_send_data(uint idx); From 6aeeacb8c30224d5e04202873628d4bbc8c3f7d1 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 17:52:26 +0100 Subject: [PATCH 078/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 1810.3961.7 > committer: Georgi Kodinov > branch nick: B48291-5.0-bugteam > timestamp: Fri 2009-10-30 15:15:43 +0200 > message: > Bug #48291 : crash with row() operator,select into @var, and > subquery returning multiple rows > > Error handling was missing when handling subqueires in WHERE > and when assigning a SELECT result to a @variable. > This caused crash(es). > > Fixed by adding error handling code to both the WHERE > condition evaluation and to assignment to an @variable. > ------------------------------------------------------------ --- mysql-test/r/select.result | 12 ++++++++++++ mysql-test/t/select.test | 17 +++++++++++++++++ sql/sql_class.cc | 6 ++++-- sql/sql_select.cc | 13 ++++++++++++- 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index a41f95de077..1b615233a14 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4415,6 +4415,18 @@ SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); 1 1 DROP TABLE t1; +# +# Bug #48291 : crash with row() operator,select into @var, and +# subquery returning multiple rows +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (2),(3); +# Should not crash +SELECT 1 FROM t1 WHERE a <> 1 AND NOT +ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1)) +INTO @var0; +ERROR 21000: Subquery returns more than 1 row +DROP TABLE t1; End of 5.0 tests create table t1(a INT, KEY (a)); INSERT INTO t1 VALUES (1),(2),(3),(4),(5); diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 1e7e853da32..51f0cd73374 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3755,7 +3755,24 @@ EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); DROP TABLE t1; + +--echo # +--echo # Bug #48291 : crash with row() operator,select into @var, and +--echo # subquery returning multiple rows +--echo # + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (2),(3); + +--echo # Should not crash +--error ER_SUBQUERY_NO_1_ROW +SELECT 1 FROM t1 WHERE a <> 1 AND NOT +ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1)) +INTO @var0; + +DROP TABLE t1; + --echo End of 5.0 tests # diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f75dc2cb88a..6f8b5bd6be9 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2715,9 +2715,11 @@ bool select_dumpvar::send_data(List &items) else { Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item); - suv->fix_fields(thd, 0); + if (suv->fix_fields(thd, 0)) + DBUG_RETURN (1); suv->save_item_result(item); - suv->update(); + if (suv->update()) + DBUG_RETURN (1); } } DBUG_RETURN(thd->is_error()); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 94f1206f26c..55ea1c81782 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11182,6 +11182,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, bool not_used_in_distinct=join_tab->not_used_in_distinct; ha_rows found_records=join->found_records; COND *select_cond= join_tab->select_cond; + bool select_cond_result= TRUE; if (error > 0 || (join->thd->is_error())) // Fatal error return NESTED_LOOP_ERROR; @@ -11193,7 +11194,17 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, return NESTED_LOOP_KILLED; /* purecov: inspected */ } DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond)); - if (!select_cond || select_cond->val_int()) + + if (select_cond) + { + select_cond_result= test(select_cond->val_int()); + + /* check for errors evaluating the condition */ + if (join->thd->is_error()) + return NESTED_LOOP_ERROR; + } + + if (!select_cond || select_cond_result) { /* There is no select condition or the attached pushed down From 53347284832bf68765dae64197d7a9363c78cdb1 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 17:56:33 +0100 Subject: [PATCH 079/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 3148.13.3 > revision-id: svoj@sun.com-20091102144140-8de1z6mdy5dopw3j > parent: svoj@sun.com-20091102143655-lo69f57p82nky58q > committer: Sergey Vojtovich > branch nick: mysql-5.1-bugteam > timestamp: Mon 2009-11-02 18:41:40 +0400 > message: > Applying InnoDB snashot 5.1-ss6129 > > Detailed revision comments: > > r6045 | jyang | 2009-10-08 02:27:08 +0300 (Thu, 08 Oct 2009) | 7 lines > branches/5.1: Fix bug #47777. Treat the Geometry data same as > Binary BLOB in ha_innobase::store_key_val_for_row(), since the > Geometry data is stored as Binary BLOB in Innodb. > > Review: rb://180 approved by Marko Makela. --- storage/innobase/handler/ha_innodb.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a8b9b678282..698e9ac8e28 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3240,7 +3240,10 @@ ha_innobase::store_key_val_for_row( } else if (mysql_type == MYSQL_TYPE_TINY_BLOB || mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB - || mysql_type == MYSQL_TYPE_LONG_BLOB) { + || mysql_type == MYSQL_TYPE_LONG_BLOB + /* MYSQL_TYPE_GEOMETRY data is treated + as BLOB data in innodb. */ + || mysql_type == MYSQL_TYPE_GEOMETRY) { CHARSET_INFO* cs; ulint key_len; From 9a69c37b5d8a2a3a6289ba586b9a6aa8507a24f0 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 17:58:51 +0100 Subject: [PATCH 080/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 3148.13.4 > revision-id: svoj@sun.com-20091102144320-0hz2ti21em510ee5 > parent: svoj@sun.com-20091102144140-8de1z6mdy5dopw3j > committer: Sergey Vojtovich > branch nick: mysql-5.1-bugteam > timestamp: Mon 2009-11-02 18:43:20 +0400 > message: > Applying InnoDB snashot 5.1-ss6129 > > Detailed revision comments: > > r6051 | sunny | 2009-10-12 07:05:00 +0300 (Mon, 12 Oct 2009) | 6 lines > branches/5.1: Ignore negative values supplied by the user when calculating the > next value to store in dict_table_t. Setting autoincrement columns top negative > values is undefined behavior and this change should bring the behavior of > InnoDB closer to what users expect. Added several tests to check. > rb://162 --- mysql-test/r/innodb-autoinc.result | 215 ++++++++++++++++++++++++++ mysql-test/t/innodb-autoinc.test | 105 +++++++++++++ storage/innobase/handler/ha_innodb.cc | 4 +- 3 files changed, 323 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index d2e8eb19e0c..ce96baf11c1 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -889,3 +889,218 @@ d1 3 4 DROP TABLE t1; +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +SHOW VARIABLES LIKE "%auto_inc%"; +Variable_name Value +auto_increment_increment 1 +auto_increment_offset 1 +CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-127, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` tinyint(4) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-127 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-127, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` tinyint(3) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 SMALLINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-32767, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` smallint(6) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-32767 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-32757, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` smallint(5) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 MEDIUMINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-8388607, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` mediumint(9) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-8388607 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 MEDIUMINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-8388607, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-2147483647 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(10) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bigint(20) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-9223372036854775807 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index 61c42f45733..a4ffc64c99f 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -498,3 +498,108 @@ ALTER TABLE t1 AUTO_INCREMENT = 3; INSERT INTO t1 VALUES(null); SELECT * FROM t1; DROP TABLE t1; + +# If the user has specified negative values for an AUTOINC column then +# InnoDB should ignore those values when setting the table's max value. +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +SHOW VARIABLES LIKE "%auto_inc%"; +# TINYINT +CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-127, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-127, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# SMALLINT +# +CREATE TABLE t1 (c1 SMALLINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-32767, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-32757, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# MEDIUMINT +# +CREATE TABLE t1 (c1 MEDIUMINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-8388607, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 MEDIUMINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-8388607, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# INT +# +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# BIGINT +# +CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +# End negative number check diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 698e9ac8e28..41b5c9f8311 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7868,6 +7868,7 @@ ha_innobase::get_auto_increment( AUTOINC counter after attempting to insert the row. */ if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { ulonglong need; + ulonglong current; ulonglong next_value; ulonglong col_max_value; @@ -7876,11 +7877,12 @@ ha_innobase::get_auto_increment( col_max_value = innobase_get_int_col_max_value( table->next_number_field); + current = *first_value > col_max_value ? autoinc : *first_value; need = *nb_reserved_values * increment; /* Compute the last value in the interval */ next_value = innobase_next_autoinc( - *first_value, need, offset, col_max_value); + current, need, offset, col_max_value); prebuilt->autoinc_last_value = next_value; From ffea980606d85947e4b2bc450a0ab9769e76befe Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 18:00:46 +0100 Subject: [PATCH 081/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 3148.8.5 > revision-id: davi.arnaut@sun.com-20091102112139-pztthzy6qj8jzomn > parent: svoj@sun.com-20091103091902-vwszwwpfi1f4zrpn > committer: Davi Arnaut > branch nick: 48370-5.1 > timestamp: Mon 2009-11-02 09:21:39 -0200 > message: > Bug#48370: Absolutely wrong calculations with GROUP BY and decimal fields when using IF > Bug#45261: Crash, stored procedure + decimal > > Revert fix for Bug#45261 due to unforeseen bugs. --- mysql-test/r/type_newdecimal.result | 220 +--------------------------- mysql-test/t/type_newdecimal.test | 134 ----------------- sql/field.cc | 85 ----------- sql/field.h | 9 -- sql/item.cc | 25 ++-- sql/item.h | 3 +- sql/item_cmpfunc.cc | 6 +- sql/item_func.cc | 52 +++++-- sql/item_func.h | 1 - sql/item_sum.cc | 3 +- sql/my_decimal.h | 14 +- sql/sql_select.cc | 41 +++++- 12 files changed, 110 insertions(+), 483 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index c3d1e400b23..748aadee4fb 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1495,9 +1495,9 @@ CREATE TABLE t1 (a int DEFAULT NULL, b int DEFAULT NULL); INSERT INTO t1 VALUES (3,30), (1,10), (2,10); SELECT a+CAST(1 AS decimal(65,30)) AS aa, SUM(b) FROM t1 GROUP BY aa; aa SUM(b) -2.00000000000000000000000000000 10 -3.00000000000000000000000000000 10 -4.00000000000000000000000000000 30 +2.000000000000000000000000000000 10 +3.000000000000000000000000000000 10 +4.000000000000000000000000000000 30 SELECT a+CAST(1 AS decimal(65,31)) AS aa, SUM(b) FROM t1 GROUP BY aa; ERROR 42000: Too big scale 31 specified for column '1'. Maximum is 30. DROP TABLE t1; @@ -1521,13 +1521,13 @@ f1 DROP TABLE t1; CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1; Warnings: -Note 1265 Data truncated for column 'f1' at row 1 +Warning 1264 Out of range value for column 'f1' at row 1 DESC t1; Field Type Null Key Default Extra -f1 decimal(65,20) NO 0.00000000000000000000 +f1 decimal(65,30) NO 0.000000000000000000000000000000 SELECT f1 FROM t1; f1 -123451234512345123451234512345123451234512345.67890678906789067891 +99999999999999999999999999999999999.999999999999999999999999999999 DROP TABLE t1; select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 * 1.01500000 * 1.01500000 * 0.99500000); @@ -1595,7 +1595,7 @@ Warnings: Note 1265 Data truncated for column 'my_col' at row 1 DESCRIBE t1; Field Type Null Key Default Extra -my_col decimal(32,30) NO 0.000000000000000000000000000000 +my_col decimal(65,30) NO 0.000000000000000000000000000000 SELECT my_col FROM t1; my_col 1.123456789123456789123456789123 @@ -1625,212 +1625,8 @@ Warnings: Note 1265 Data truncated for column 'my_col' at row 1 DESCRIBE t1; Field Type Null Key Default Extra -my_col decimal(30,30) YES NULL +my_col decimal(65,30) YES NULL SELECT my_col FROM t1; my_col 0.012345687012345687012345687012 DROP TABLE t1; -# -# Bug#45261: Crash, stored procedure + decimal -# -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 SELECT -/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001 -AS c1; -Warnings: -Warning 1264 Out of range value for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -99999999999999999999999999999999999999999999999999999999999999999 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001. -AS c1; -Warnings: -Warning 1264 Out of range value for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -99999999999999999999999999999999999999999999999999999999999999999 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */ -AS c1; -Warnings: -Warning 1264 Out of range value for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -99999999999999999999999999999999999999999999999999999999999999999 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001 -AS c1; -Warnings: -Error 1292 Truncated incorrect DECIMAL value: '' -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -99999999999999999999999999999999999999999999999999999999999999999 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */ -AS c1; -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,25) NO 0.0000000000000000000000000 -SELECT * FROM t1; -c1 -1000000000000000000000000000000000000001.1000000000000000000000000 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */ -AS c1; -DESC t1; -Field Type Null Key Default Extra -c1 decimal(31,30) NO 0.000000000000000000000000000000 -SELECT * FROM t1; -c1 -1.100000000000000000000000000000 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ -AS c1; -DESC t1; -Field Type Null Key Default Extra -c1 decimal(31,30) NO 0.000000000000000000000000000000 -SELECT * FROM t1; -c1 -1.100000000000000000000000000000 -DROP TABLE t1; -CREATE TABLE t1 SELECT -.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ -AS c1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(30,30) NO 0.000000000000000000000000000000 -SELECT * FROM t1; -c1 -0.100000000000000000000000000000 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */ -AS c1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,20) NO 0.00000000000000000000 -SELECT * FROM t1; -c1 -123456789012345678901234567890123456789012345.12345678901234567890 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */ -AS c1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -12345678901234567890123456789012345678901234567890123456789012345 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */ -AS c1; -Warnings: -Warning 1264 Out of range value for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -99999999999999999999999999999999999999999999999999999999999999999 -DROP TABLE t1; -CREATE TABLE t1 SELECT -.123456789012345678901234567890123456789012345678901234567890123456 /* 66 */ -AS c1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(30,30) NO 0.000000000000000000000000000000 -SELECT * FROM t1; -c1 -0.123456789012345678901234567890 -DROP TABLE t1; -CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(33,30) NO 0.000000000000000000000000000000 -SELECT * FROM t1; -c1 -123.123456789012345678901234567890 -DROP TABLE t1; -CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1; -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,29) NO 0.00000000000000000000000000000 -SELECT * FROM t1; -c1 -2.10000000000000000000000000000 -DROP TABLE t1; -# -# Test that the integer and decimal parts are properly calculated. -# -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 3 -DESC t2; -Field Type Null Key Default Extra -c1 decimal(32,30) YES NULL -DROP TABLE t1,t2; -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -Note 1265 Data truncated for column 'c1' at row 2 -Note 1265 Data truncated for column 'c1' at row 3 -DESC t2; -Field Type Null Key Default Extra -c1 decimal(32,30) YES NULL -DROP TABLE t1,t2; -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t2; -Field Type Null Key Default Extra -c1 decimal(31,30) YES NULL -DROP TABLE t1,t2; -# -# Test that variables get maximum precision. -# -SET @decimal= 1.1; -CREATE TABLE t1 SELECT @decimal AS c1; -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,30) YES NULL -SELECT * FROM t1; -c1 -1.100000000000000000000000000000 -DROP TABLE t1; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 65bafaae77e..cd3c3f81510 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1286,137 +1286,3 @@ CREATE TABLE t1 SELECT 1 % .1234567891234567891234567891234567891234567891234567 DESCRIBE t1; SELECT my_col FROM t1; DROP TABLE t1; - ---echo # ---echo # Bug#45261: Crash, stored procedure + decimal ---echo # - ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - -CREATE TABLE t1 SELECT - /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001 - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001. - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001 - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - .100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - .123456789012345678901234567890123456789012345678901234567890123456 /* 66 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - ---echo # ---echo # Test that the integer and decimal parts are properly calculated. ---echo # - -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1; -DESC t2; -DROP TABLE t1,t2; - -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1; -DESC t2; -DROP TABLE t1,t2; - -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1; -DESC t2; -DROP TABLE t1,t2; - ---echo # ---echo # Test that variables get maximum precision. ---echo # - -SET @decimal= 1.1; -CREATE TABLE t1 SELECT @decimal AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 0df9b0fc2e4..0ec5b3a9aed 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2480,97 +2480,12 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg, { precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg); set_if_smaller(precision, DECIMAL_MAX_PRECISION); - DBUG_ASSERT(precision >= dec); DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) && (dec <= DECIMAL_MAX_SCALE)); bin_size= my_decimal_get_binary_size(precision, dec); } -/** - Create a field to hold a decimal value from an item. - - @remark The MySQL DECIMAL data type has a characteristic that needs to be - taken into account when deducing the type from a Item_decimal. - - But first, let's briefly recap what is the new MySQL DECIMAL type: - - The declaration syntax for a decimal is DECIMAL(M,D), where: - - * M is the maximum number of digits (the precision). - It has a range of 1 to 65. - * D is the number of digits to the right of the decimal separator (the scale). - It has a range of 0 to 30 and must be no larger than M. - - D and M are used to determine the storage requirements for the integer - and fractional parts of each value. The integer part is to the left of - the decimal separator and to the right is the fractional part. Hence: - - M is the number of digits for the integer and fractional part. - D is the number of digits for the fractional part. - - Consequently, M - D is the number of digits for the integer part. For - example, a DECIMAL(20,10) column has ten digits on either side of - the decimal separator. - - The characteristic that needs to be taken into account is that the - backing type for Item_decimal is a my_decimal that has a higher - precision (DECIMAL_MAX_POSSIBLE_PRECISION, see my_decimal.h) than - DECIMAL. - - Drawing a comparison between my_decimal and DECIMAL: - - * M has a range of 1 to 81. - * D has a range of 0 to 81. - - There can be a difference in range if the decimal contains a integer - part. This is because the fractional part must always be on a group - boundary, leaving at least one group for the integer part. Since each - group is 9 (DIG_PER_DEC1) digits and there are 9 (DECIMAL_BUFF_LENGTH) - groups, the fractional part is limited to 72 digits if there is at - least one digit in the integral part. - - Although the backing type for a DECIMAL is also my_decimal, every - time a my_decimal is stored in a DECIMAL field, the precision and - scale are explicitly capped at 65 (DECIMAL_MAX_PRECISION) and 30 - (DECIMAL_MAX_SCALE) digits, following my_decimal truncation procedure - (FIX_INTG_FRAC_ERROR). -*/ - -Field_new_decimal * -Field_new_decimal::new_decimal_field(const Item *item) -{ - uint32 len; - uint intg= item->decimal_int_part(), scale= item->decimals; - - DBUG_ASSERT(item->decimal_precision() >= item->decimals); - - /* - Employ a procedure along the lines of the my_decimal truncation process: - - If the integer part is equal to or bigger than the maximum precision: - Truncate integer part to fit and the fractional becomes zero. - - Otherwise: - Truncate fractional part to fit. - */ - if (intg >= DECIMAL_MAX_PRECISION) - { - intg= DECIMAL_MAX_PRECISION; - scale= 0; - } - else - { - uint room= min(DECIMAL_MAX_PRECISION - intg, DECIMAL_MAX_SCALE); - if (scale > room) - scale= room; - } - - len= my_decimal_precision_to_length(intg + scale, scale, item->unsigned_flag); - - return new Field_new_decimal(len, item->maybe_null, item->name, scale, - item->unsigned_flag); -} - - int Field_new_decimal::reset(void) { store_value(&decimal_zero); diff --git a/sql/field.h b/sql/field.h index 7a9b69eff40..a58a95a1f77 100644 --- a/sql/field.h +++ b/sql/field.h @@ -615,10 +615,6 @@ protected: class Field_num :public Field { public: - /** - The scale of the Field's value, i.e. the number of digits to the right - of the decimal point. - */ const uint8 dec; bool zerofill,unsigned_flag; // Purify cannot handle bit fields Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, @@ -777,11 +773,6 @@ public: Field_new_decimal(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, uint8 dec_arg, bool unsigned_arg); - /* - Create a field to hold a decimal value from an item. - Truncates the precision and/or scale if necessary. - */ - static Field_new_decimal *new_decimal_field(const Item *item); enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } Item_result result_type () const { return DECIMAL_RESULT; } diff --git a/sql/item.cc b/sql/item.cc index 86e4551e55b..613310e483e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -435,26 +435,17 @@ Item::Item(THD *thd, Item *item): } -/** - Decimal precision of the item. - - @remark The precision must not be capped as it can be used in conjunction - with Item::decimals to determine the size of the integer part when - constructing a decimal data type. - - @see Item::decimal_int_part() - @see Item::decimals -*/ - uint Item::decimal_precision() const { - uint precision= max_length; Item_result restype= result_type(); if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT)) - precision= my_decimal_length_to_precision(max_length, decimals, unsigned_flag); - - return precision; + { + uint prec= + my_decimal_length_to_precision(max_length, decimals, unsigned_flag); + return min(prec, DECIMAL_MAX_PRECISION); + } + return min(max_length, DECIMAL_MAX_PRECISION); } @@ -4908,7 +4899,9 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) switch (field_type()) { case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: - field= Field_new_decimal::new_decimal_field(this); + field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0, + Field::NONE, name, decimals, 0, + unsigned_flag); break; case MYSQL_TYPE_TINY: field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE, diff --git a/sql/item.h b/sql/item.h index a2cff3ab3a9..73f1fc6feed 100644 --- a/sql/item.h +++ b/sql/item.h @@ -762,10 +762,9 @@ public: virtual cond_result eq_cmp_result() const { return COND_OK; } inline uint float_length(uint decimals_par) const { return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;} - /** Returns the uncapped decimal precision of this item. */ virtual uint decimal_precision() const; inline int decimal_int_part() const - { return decimal_precision() - decimals; } + { return my_decimal_int_part(decimal_precision(), decimals); } /* Returns true if this is constant (during query execution, i.e. its value will not change until next fix_fields) and its value is known. diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c29031d25b5..ab59da42ae0 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2191,7 +2191,7 @@ uint Item_func_ifnull::decimal_precision() const int arg1_int_part= args[1]->decimal_int_part(); int max_int_part= max(arg0_int_part, arg1_int_part); int precision= max_int_part + decimals; - return precision; + return min(precision, DECIMAL_MAX_PRECISION); } @@ -2375,7 +2375,7 @@ uint Item_func_if::decimal_precision() const int arg1_prec= args[1]->decimal_int_part(); int arg2_prec= args[2]->decimal_int_part(); int precision=max(arg1_prec,arg2_prec) + decimals; - return precision; + return min(precision, DECIMAL_MAX_PRECISION); } @@ -2783,7 +2783,7 @@ uint Item_func_case::decimal_precision() const if (else_expr_num != -1) set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part()); - return max_int_part + decimals; + return min(max_int_part + decimals, DECIMAL_MAX_PRECISION); } diff --git a/sql/item_func.cc b/sql/item_func.cc index d9e6f76dd6b..ac52f36474a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -451,8 +451,45 @@ Field *Item_func::tmp_table_field(TABLE *table) return make_string_field(table); break; case DECIMAL_RESULT: - field= Field_new_decimal::new_decimal_field(this); + { + uint8 dec= decimals; + uint8 intg= decimal_precision() - dec; + uint32 len= max_length; + + /* + Trying to put too many digits overall in a DECIMAL(prec,dec) + will always throw a warning. We must limit dec to + DECIMAL_MAX_SCALE however to prevent an assert() later. + */ + + if (dec > 0) + { + int overflow; + + dec= min(dec, DECIMAL_MAX_SCALE); + + /* + If the value still overflows the field with the corrected dec, + we'll throw out decimals rather than integers. This is still + bad and of course throws a truncation warning. + */ + + const int required_length= + my_decimal_precision_to_length(intg + dec, dec, + unsigned_flag); + + overflow= required_length - len; + + if (overflow > 0) + dec= max(0, dec - overflow); // too long, discard fract + else + /* Corrected value fits. */ + len= required_length; + } + + field= new Field_new_decimal(len, maybe_null, name, dec, unsigned_flag); break; + } case ROW_RESULT: default: // This case should never be chosen @@ -4739,19 +4776,6 @@ void Item_func_get_user_var::fix_length_and_dec() } -uint Item_func_get_user_var::decimal_precision() const -{ - uint precision= max_length; - Item_result restype= result_type(); - - /* Default to maximum as the precision is unknown a priori. */ - if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT)) - precision= DECIMAL_MAX_PRECISION; - - return precision; -} - - bool Item_func_get_user_var::const_item() const { return (!var_entry || current_thd->query_id != var_entry->update_query_id); diff --git a/sql/item_func.h b/sql/item_func.h index fdbbff89e60..025ac12fe07 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1393,7 +1393,6 @@ public: table_map used_tables() const { return const_item() ? 0 : RAND_TABLE_BIT; } bool eq(const Item *item, bool binary_cmp) const; - uint decimal_precision() const; private: bool set_value(THD *thd, sp_rcontext *ctx, Item **it); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 08a48c6ce2f..38251294053 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -517,7 +517,8 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, name, table->s, collation.collation); break; case DECIMAL_RESULT: - field= Field_new_decimal::new_decimal_field(this); + field= new Field_new_decimal(max_length, maybe_null, name, + decimals, unsigned_flag); break; case ROW_RESULT: default: diff --git a/sql/my_decimal.h b/sql/my_decimal.h index b1df1395dcd..21669e82c44 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -48,12 +48,10 @@ C_MODE_END digits * number of decimal digits in one our big digit - number of decimal digits in one our big digit decreased by 1 (because we always put decimal point on the border of our big digits)) - - This value is 65 due to historical reasons partly due to it being used - as the maximum allowed precision and not the actual maximum precision. */ #define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2) #define DECIMAL_MAX_SCALE 30 +#define DECIMAL_NOT_SPECIFIED 31 /** maximum length of string representation (number of maximum decimal @@ -77,6 +75,12 @@ inline uint my_decimal_size(uint precision, uint scale) } +inline int my_decimal_int_part(uint precision, uint decimals) +{ + return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals); +} + + /** my_decimal class limits 'decimal_t' type to what we need in MySQL. @@ -180,7 +184,7 @@ inline uint my_decimal_length_to_precision(uint length, uint scale, } inline uint32 my_decimal_precision_to_length_no_truncation(uint precision, - uint scale, + uint8 scale, bool unsigned_flag) { /* @@ -192,7 +196,7 @@ inline uint32 my_decimal_precision_to_length_no_truncation(uint precision, (unsigned_flag || !precision ? 0 : 1)); } -inline uint32 my_decimal_precision_to_length(uint precision, uint scale, +inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale, bool unsigned_flag) { /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 55ea1c81782..34d23ace89b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9409,8 +9409,47 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, new_field->set_derivation(item->collation.derivation); break; case DECIMAL_RESULT: - new_field= Field_new_decimal::new_decimal_field(item); + { + uint8 dec= item->decimals; + uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec; + uint32 len= item->max_length; + + /* + Trying to put too many digits overall in a DECIMAL(prec,dec) + will always throw a warning. We must limit dec to + DECIMAL_MAX_SCALE however to prevent an assert() later. + */ + + if (dec > 0) + { + signed int overflow; + + dec= min(dec, DECIMAL_MAX_SCALE); + + /* + If the value still overflows the field with the corrected dec, + we'll throw out decimals rather than integers. This is still + bad and of course throws a truncation warning. + +1: for decimal point + */ + + const int required_length= + my_decimal_precision_to_length(intg + dec, dec, + item->unsigned_flag); + + overflow= required_length - len; + + if (overflow > 0) + dec= max(0, dec - overflow); // too long, discard fract + else + /* Corrected value fits. */ + len= required_length; + } + + new_field= new Field_new_decimal(len, maybe_null, item->name, + dec, item->unsigned_flag); break; + } case ROW_RESULT: default: // This case should never be choosen From 54d239f78ff6b6a3dfd6a13ebe152c442905b632 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 18:04:39 +0100 Subject: [PATCH 082/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 3148.9.3 > revision-id: azundris@mysql.com-20091029230154-jp2xqvzw2nhj9q41 > parent: azundris@mysql.com-20091027095316-54lwjr9vqkscq1ik > committer: Tatiana A. Nurnberg > branch nick: 51-48295 > timestamp: Thu 2009-10-29 16:01:54 -0700 > message: > Bug#48295: explain extended crash with subquery and ONLY_FULL_GROUP_BY sql_mode > > If an outer query is broken, a subquery might not even get set up. > EXPLAIN EXTENDED did not expect this and merrily tried to de-ref all > of the half-setup info. > > We now catch this case and print as much as we have, as it doesn't cost us > anything (doesn't make regular execution slower). --- mysql-test/r/explain.result | 16 ++++++++++++++++ mysql-test/t/explain.test | 20 ++++++++++++++++++++ sql/item_subselect.cc | 11 ++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result index 96fcbc33d3f..5a1bf1a1290 100644 --- a/mysql-test/r/explain.result +++ b/mysql-test/r/explain.result @@ -194,4 +194,20 @@ dt 2001-01-01 01:01:01 2001-01-01 01:01:01 drop tables t1, t2; +# +# Bug#48295: +# explain extended crash with subquery and ONLY_FULL_GROUP_BY sql_mode +# +CREATE TABLE t1 (f1 INT); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +EXPLAIN EXTENDED SELECT 1 FROM t1 +WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t ); +ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause +SHOW WARNINGS; +Level Code Message +Error 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause +Note 1003 select 1 AS `1` from `test`.`t1` where ((...)) +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1; End of 5.1 tests. diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test index 18f1145a25d..77b49a8b1a5 100644 --- a/mysql-test/t/explain.test +++ b/mysql-test/t/explain.test @@ -167,4 +167,24 @@ flush tables; SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' ); drop tables t1, t2; +--echo # +--echo # Bug#48295: +--echo # explain extended crash with subquery and ONLY_FULL_GROUP_BY sql_mode +--echo # + +CREATE TABLE t1 (f1 INT); + +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; + +# EXPLAIN EXTENDED (with subselect). used to crash. should give NOTICE. +--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS +EXPLAIN EXTENDED SELECT 1 FROM t1 + WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t ); +SHOW WARNINGS; + +SET SESSION sql_mode=@old_sql_mode; + +DROP TABLE t1; + --echo End of 5.1 tests. diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index da651cec70c..29db9eb0903 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -311,9 +311,14 @@ void Item_subselect::update_used_tables() void Item_subselect::print(String *str, enum_query_type query_type) { - str->append('('); - engine->print(str, query_type); - str->append(')'); + if (engine) + { + str->append('('); + engine->print(str, query_type); + str->append(')'); + } + else + str->append("(...)"); } From 37066594f659b5b102d4ab836026975a5ea5536f Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 18:09:30 +0100 Subject: [PATCH 083/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 3148.9.6 > revision-id: martin.hansson@sun.com-20091102122407-krzh4h0i052lbwr5 > parent: davi.arnaut@sun.com-20091102112236-k3myix2xy8miyv4s > committer: Martin Hansson > branch nick: 5.1bt > timestamp: Mon 2009-11-02 13:24:07 +0100 > message: > Bug#47925: regression of range optimizer and date comparison in 5.1.39! > > When a query was using a DATE or DATETIME value formatted > using any other separator characters beside hyphen '-', a > query with a greater-or-equal '>=' condition matching only > the greatest value in an indexed column, the result was > empty if index range scan was employed. > > The range optimizer got a new feature between 5.1.38 and > 5.1.39 that changes a greater-or-equal condition to a > greater-than if the value matching that in the query was not > present in the table. But the value comparison function > compared the dates as strings instead of dates. > > The bug was fixed by splitting the function > get_date_from_str in two: One part that parses and does > error checking. This function is now visible outside the > module. The old get_date_from_str now calls the new > function. --- mysql-test/r/range.result | 198 ++++++++++++++++++++++++++++++++++++++ mysql-test/t/range.test | 80 +++++++++++++++ sql/item.cc | 61 +++++++----- sql/item.h | 2 +- sql/item_cmpfunc.cc | 102 ++++++++++++-------- sql/item_cmpfunc.h | 3 + sql/opt_range.cc | 6 +- sql/time.cc | 16 +-- 8 files changed, 393 insertions(+), 75 deletions(-) diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index cc5e8d2be96..c5842bc45aa 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -1219,3 +1219,201 @@ explain select * from t2 where a=1000 and b<11; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 5 const 502 Using where drop table t1, t2; +# +# Bug#47925: regression of range optimizer and date comparison in 5.1.39! +# +CREATE TABLE t1 ( a DATE, KEY ( a ) ); +CREATE TABLE t2 ( a DATETIME, KEY ( a ) ); +# Make optimizer choose range scan +INSERT INTO t1 VALUES ('2009-09-22'), ('2009-09-22'), ('2009-09-22'); +INSERT INTO t1 VALUES ('2009-09-23'), ('2009-09-23'), ('2009-09-23'); +INSERT INTO t2 VALUES ('2009-09-22 12:00:00'), ('2009-09-22 12:00:00'), +('2009-09-22 12:00:00'); +INSERT INTO t2 VALUES ('2009-09-23 12:00:00'), ('2009-09-23 12:00:00'), +('2009-09-23 12:00:00'); +# DATE vs DATE +EXPLAIN +SELECT * FROM t1 WHERE a >= '2009/09/23'; +id select_type table type possible_keys key key_len ref rows Extra +X X X range a a X X X X +SELECT * FROM t1 WHERE a >= '2009/09/23'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '20090923'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= 20090923; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009-9-23'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009.09.23'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009:09:23'; +a +2009-09-23 +2009-09-23 +2009-09-23 +# DATE vs DATETIME +EXPLAIN +SELECT * FROM t2 WHERE a >= '2009/09/23'; +id select_type table type possible_keys key key_len ref rows Extra +X X X range a a X X X X +SELECT * FROM t2 WHERE a >= '2009/09/23'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009/09/23'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '20090923'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= 20090923; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009-9-23'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009.09.23'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009:09:23'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +# DATETIME vs DATETIME +EXPLAIN +SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +X X X range a a X X X X +SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '20090923120000'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= 20090923120000; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009-9-23 12:00:00'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009.09.23 12:00:00'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009:09:23 12:00:00'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +# DATETIME vs DATE +EXPLAIN +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +X X X range a a X X X X +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '20090923000000'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= 20090923000000; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009-9-23 00:00:00'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009.09.23 00:00:00'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009:09:23 00:00:00'; +a +2009-09-23 +2009-09-23 +2009-09-23 +# Test of the new get_date_from_str implementation +# Behavior differs slightly between the trunk and mysql-pe. +# The former may give errors for the truncated values, while the latter +# gives warnings. The purpose of this test is not to interfere, and only +# preserve existing behavior. +SELECT str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND +str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20'; +str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND +str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20' +1 +Warnings: +Warning 1292 Truncated incorrect date value: '' +SELECT str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND +str_to_date('2007-20-00', '%Y-%m-%d') <= ''; +str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND +str_to_date('2007-20-00', '%Y-%m-%d') <= '' +NULL +Warnings: +Warning 1292 Truncated incorrect date value: '' +Error 1411 Incorrect datetime value: '2007-20-00' for function str_to_date +Error 1411 Incorrect datetime value: '2007-20-00' for function str_to_date +SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'; +str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20' +1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '' +SELECT str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND ''; +str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND '' +NULL +Warnings: +Error 1411 Incorrect datetime value: '2007-20-00' for function str_to_date +SELECT str_to_date('', '%Y-%m-%d'); +str_to_date('', '%Y-%m-%d') +0000-00-00 +DROP TABLE t1, t2; +End of 5.1 tests diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index e1411e7fd46..ddddb66f38d 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -1046,3 +1046,83 @@ explain select * from t2 where a=1000 and b<11; drop table t1, t2; +--echo # +--echo # Bug#47925: regression of range optimizer and date comparison in 5.1.39! +--echo # +CREATE TABLE t1 ( a DATE, KEY ( a ) ); +CREATE TABLE t2 ( a DATETIME, KEY ( a ) ); + +--echo # Make optimizer choose range scan +INSERT INTO t1 VALUES ('2009-09-22'), ('2009-09-22'), ('2009-09-22'); +INSERT INTO t1 VALUES ('2009-09-23'), ('2009-09-23'), ('2009-09-23'); + +INSERT INTO t2 VALUES ('2009-09-22 12:00:00'), ('2009-09-22 12:00:00'), + ('2009-09-22 12:00:00'); +INSERT INTO t2 VALUES ('2009-09-23 12:00:00'), ('2009-09-23 12:00:00'), + ('2009-09-23 12:00:00'); + +--echo # DATE vs DATE +--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X +EXPLAIN +SELECT * FROM t1 WHERE a >= '2009/09/23'; +SELECT * FROM t1 WHERE a >= '2009/09/23'; +SELECT * FROM t1 WHERE a >= '20090923'; +SELECT * FROM t1 WHERE a >= 20090923; +SELECT * FROM t1 WHERE a >= '2009-9-23'; +SELECT * FROM t1 WHERE a >= '2009.09.23'; +SELECT * FROM t1 WHERE a >= '2009:09:23'; + +--echo # DATE vs DATETIME +--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X +EXPLAIN +SELECT * FROM t2 WHERE a >= '2009/09/23'; +SELECT * FROM t2 WHERE a >= '2009/09/23'; +SELECT * FROM t2 WHERE a >= '2009/09/23'; +SELECT * FROM t2 WHERE a >= '20090923'; +SELECT * FROM t2 WHERE a >= 20090923; +SELECT * FROM t2 WHERE a >= '2009-9-23'; +SELECT * FROM t2 WHERE a >= '2009.09.23'; +SELECT * FROM t2 WHERE a >= '2009:09:23'; + +--echo # DATETIME vs DATETIME +--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X +EXPLAIN +SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00'; +SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00'; +SELECT * FROM t2 WHERE a >= '20090923120000'; +SELECT * FROM t2 WHERE a >= 20090923120000; +SELECT * FROM t2 WHERE a >= '2009-9-23 12:00:00'; +SELECT * FROM t2 WHERE a >= '2009.09.23 12:00:00'; +SELECT * FROM t2 WHERE a >= '2009:09:23 12:00:00'; + +--echo # DATETIME vs DATE +--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X +EXPLAIN +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +SELECT * FROM t1 WHERE a >= '20090923000000'; +SELECT * FROM t1 WHERE a >= 20090923000000; +SELECT * FROM t1 WHERE a >= '2009-9-23 00:00:00'; +SELECT * FROM t1 WHERE a >= '2009.09.23 00:00:00'; +SELECT * FROM t1 WHERE a >= '2009:09:23 00:00:00'; + +--echo # Test of the new get_date_from_str implementation +--echo # Behavior differs slightly between the trunk and mysql-pe. +--echo # The former may give errors for the truncated values, while the latter +--echo # gives warnings. The purpose of this test is not to interfere, and only +--echo # preserve existing behavior. +SELECT str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND + str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20'; + +SELECT str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND + str_to_date('2007-20-00', '%Y-%m-%d') <= ''; + +SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'; +SELECT str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND ''; + +SELECT str_to_date('', '%Y-%m-%d'); + +DROP TABLE t1, t2; + +--echo End of 5.1 tests diff --git a/sql/item.cc b/sql/item.cc index 613310e483e..8f487872f1b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6859,52 +6859,61 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) } /** - Compare the value stored in field, with the original item. + Compare the value stored in field with the expression from the query. - @param field field which the item is converted and stored in - @param item original item + @param field Field which the Item is stored in after conversion + @param item Original expression from query - @return Return an integer greater than, equal to, or less than 0 if - the value stored in the field is greater than, equal to, - or less than the original item + @return Returns an integer greater than, equal to, or less than 0 if + the value stored in the field is greater than, equal to, + or less than the original Item. A 0 may also be returned if + out of memory. @note We only use this on the range optimizer/partition pruning, because in some cases we can't store the value in the field without some precision/character loss. */ -int stored_field_cmp_to_item(Field *field, Item *item) +int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) { - Item_result res_type=item_cmp_type(field->result_type(), item->result_type()); if (res_type == STRING_RESULT) { char item_buff[MAX_FIELD_WIDTH]; char field_buff[MAX_FIELD_WIDTH]; - String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin),*item_result; + + String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin); String field_tmp(field_buff,sizeof(field_buff),&my_charset_bin); - enum_field_types field_type; - item_result=item->val_str(&item_tmp); + String *item_result= item->val_str(&item_tmp); + /* + Some implementations of Item::val_str(String*) actually modify + the field Item::null_value, hence we can't check it earlier. + */ if (item->null_value) return 0; - field->val_str(&field_tmp); + String *field_result= field->val_str(&field_tmp); - /* - If comparing DATE with DATETIME, append the time-part to the DATE. - So that the strings are equally formatted. - A DATE converted to string is 10 characters, and a DATETIME converted - to string is 19 characters. - */ - field_type= field->type(); - if (field_type == MYSQL_TYPE_DATE && - item_result->length() == 19) - field_tmp.append(" 00:00:00"); - else if (field_type == MYSQL_TYPE_DATETIME && - item_result->length() == 10) - item_result->append(" 00:00:00"); + enum_field_types field_type= field->type(); - return stringcmp(&field_tmp,item_result); + if (field_type == MYSQL_TYPE_DATE || field_type == MYSQL_TYPE_DATETIME) + { + enum_mysql_timestamp_type type= MYSQL_TIMESTAMP_ERROR; + + if (field_type == MYSQL_TYPE_DATE) + type= MYSQL_TIMESTAMP_DATE; + + if (field_type == MYSQL_TYPE_DATETIME) + type= MYSQL_TIMESTAMP_DATETIME; + + const char *field_name= field->field_name; + MYSQL_TIME field_time, item_time; + get_mysql_time_from_str(thd, field_result, type, field_name, &field_time); + get_mysql_time_from_str(thd, item_result, type, field_name, &item_time); + + return my_time_compare(&field_time, &item_time); + } + return stringcmp(field_result, item_result); } if (res_type == INT_RESULT) return 0; // Both are of type int diff --git a/sql/item.h b/sql/item.h index 73f1fc6feed..3a4b6e53b3a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3124,4 +3124,4 @@ void mark_select_range_as_dependent(THD *thd, extern Cached_item *new_Cached_item(THD *thd, Item *item); extern Item_result item_cmp_type(Item_result a,Item_result b); extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item); -extern int stored_field_cmp_to_item(Field *field, Item *item); +extern int stored_field_cmp_to_item(THD *thd, Field *field, Item *item); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index ab59da42ae0..df92c165f2d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -636,6 +636,62 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) return 0; } +/** + Parse date provided in a string to a MYSQL_TIME. + + @param[in] thd Thread handle + @param[in] str A string to convert + @param[in] warn_type Type of the timestamp for issuing the warning + @param[in] warn_name Field name for issuing the warning + @param[out] l_time The MYSQL_TIME objects is initialized. + + Parses a date provided in the string str into a MYSQL_TIME object. If the + string contains an incorrect date or doesn't correspond to a date at all + then a warning is issued. The warn_type and the warn_name arguments are used + as the name and the type of the field when issuing the warning. If any input + was discarded (trailing or non-timestamp-y characters), return value will be + TRUE. + + @return Status flag + @retval FALSE Success. + @retval True Indicates failure. +*/ + +bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type, + const char *warn_name, MYSQL_TIME *l_time) +{ + bool value; + int error; + enum_mysql_timestamp_type timestamp_type; + + timestamp_type= + str_to_datetime(str->ptr(), str->length(), l_time, + (TIME_FUZZY_DATE | MODE_INVALID_DATES | + (thd->variables.sql_mode & + (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE))), + &error); + + if (timestamp_type == MYSQL_TIMESTAMP_DATETIME || + timestamp_type == MYSQL_TIMESTAMP_DATE) + /* + Do not return yet, we may still want to throw a "trailing garbage" + warning. + */ + value= FALSE; + else + { + value= TRUE; + error= 1; /* force warning */ + } + + if (error > 0) + make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + str->ptr(), str->length(), + warn_type, warn_name); + + return value; +} + /** @brief Convert date provided in a string to the int representation. @@ -650,51 +706,21 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) representation. If the string contains wrong date or doesn't contain it at all then a warning is issued. The warn_type and the warn_name arguments are used as the name and the type of the - field when issuing the warning. If any input was discarded - (trailing or non-timestampy characters), was_cut will be non-zero. - was_type will return the type str_to_datetime() could correctly - extract. + field when issuing the warning. @return converted value. 0 on error and on zero-dates -- check 'failure' */ - -static ulonglong -get_date_from_str(THD *thd, String *str, timestamp_type warn_type, - char *warn_name, bool *error_arg) +static ulonglong get_date_from_str(THD *thd, String *str, + timestamp_type warn_type, + const char *warn_name, bool *error_arg) { - ulonglong value= 0; - int error; MYSQL_TIME l_time; - enum_mysql_timestamp_type ret; + *error_arg= get_mysql_time_from_str(thd, str, warn_type, warn_name, &l_time); - ret= str_to_datetime(str->ptr(), str->length(), &l_time, - (TIME_FUZZY_DATE | MODE_INVALID_DATES | - (thd->variables.sql_mode & - (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE))), - &error); - - if (ret == MYSQL_TIMESTAMP_DATETIME || ret == MYSQL_TIMESTAMP_DATE) - { - /* - Do not return yet, we may still want to throw a "trailing garbage" - warning. - */ - *error_arg= FALSE; - value= TIME_to_ulonglong_datetime(&l_time); - } - else - { - *error_arg= TRUE; - error= 1; /* force warning */ - } - - if (error > 0) - make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - str->ptr(), str->length(), - warn_type, warn_name); - - return value; + if (*error_arg) + return 0; + return TIME_to_ulonglong_datetime(&l_time); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index c2227fa04e0..437d9541e50 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1721,3 +1721,6 @@ inline Item *and_conds(Item *a, Item *b) } Item *and_expressions(Item *a, Item *b, Item **org_item); + +bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type, + const char *warn_name, MYSQL_TIME *l_time); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 68c70c915c3..4112f40b683 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5954,7 +5954,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, switch (type) { case Item_func::LT_FUNC: - if (stored_field_cmp_to_item(field,value) == 0) + if (stored_field_cmp_to_item(param->thd, field, value) == 0) tree->max_flag=NEAR_MAX; /* fall through */ case Item_func::LE_FUNC: @@ -5969,14 +5969,14 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, case Item_func::GT_FUNC: /* Don't use open ranges for partial key_segments */ if ((!(key_part->flag & HA_PART_KEY_SEG)) && - (stored_field_cmp_to_item(field, value) <= 0)) + (stored_field_cmp_to_item(param->thd, field, value) <= 0)) tree->min_flag=NEAR_MIN; tree->max_flag= NO_MAX_RANGE; break; case Item_func::GE_FUNC: /* Don't use open ranges for partial key_segments */ if ((!(key_part->flag & HA_PART_KEY_SEG)) && - (stored_field_cmp_to_item(field,value) < 0)) + (stored_field_cmp_to_item(param->thd, field, value) < 0)) tree->min_flag= NEAR_MIN; tree->max_flag=NO_MAX_RANGE; break; diff --git a/sql/time.cc b/sql/time.cc index 962b65e454c..8b554beb94b 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -965,20 +965,22 @@ calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign, longlong *s 0 - a == b 1 - a > b - NOTES - TIME.second_part is not considered during comparison */ -int -my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b) +int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b) { - my_ulonglong a_t= TIME_to_ulonglong_datetime(a); - my_ulonglong b_t= TIME_to_ulonglong_datetime(b); + ulonglong a_t= TIME_to_ulonglong_datetime(a); + ulonglong b_t= TIME_to_ulonglong_datetime(b); + if (a_t < b_t) + return -1; if (a_t > b_t) return 1; - else if (a_t < b_t) + + if (a->second_part < b->second_part) return -1; + if (a->second_part > b->second_part) + return 1; return 0; } From 49383941f5b73ccc7aafe23114e56705f0c4c0f2 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 18:11:54 +0100 Subject: [PATCH 084/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 3181 > revision-id: alexey.kopytov@sun.com-20091016201951-fsht0wm8xn8vkzsx > parent: joerg@mysql.com-20091016164025-kb4sbrggq5o7zufc > committer: Alexey Kopytov > branch nick: mysql-5.1-bugteam > timestamp: Sat 2009-10-17 00:19:51 +0400 > message: > Bug #47123: Endless 100% CPU loop with STRAIGHT_JOIN > > The problem was in incorrect handling of predicates involving > NULL as a constant value by the range optimizer. > > For example, when creating a SEL_ARG node from a condition of > the form "field < const" (which would normally result in the > "NULL < field < const" SEL_ARG), the special case when "const" > is NULL was not taken into account, so "NULL < field < NULL" > was produced for the "field < NULL" condition. > > As a result, SEL_ARG structures of this form could not be > further optimized which in turn could lead to incorrectly > constructed SEL_ARG trees. In particular, code assuming SEL_ARG > structures to always form a sequence of ordered disjoint > intervals could enter an infinite loop under some > circumstances. > > Fixed by changing get_mm_leaf() so that for any sargable > predicate except "<=>" involving NULL as a constant, "empty" > SEL_ARG is returned, since such a predicate is always false. --- mysql-test/r/partition_pruning.result | 3 +-- mysql-test/r/range.result | 8 ++++++++ mysql-test/r/subselect.result | 3 +-- mysql-test/t/range.test | 9 +++++++++ sql/opt_range.cc | 11 +++++++++++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index 769d499fc0a..3128c57b2cf 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -1272,10 +1272,9 @@ INSERT INTO t1 VALUES (1, '2009-01-01'), (2, NULL); # test with an invalid date, which lead to item->null_value is set. EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-99' AS DATETIME); id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p20090401 ALL NULL NULL NULL NULL 2 Using where +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables Warnings: Warning 1292 Incorrect datetime value: '2009-04-99' -Warning 1292 Incorrect datetime value: '2009-04-99' DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index c5842bc45aa..3ed2c3f53d0 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -1216,6 +1216,14 @@ select 'In following EXPLAIN the access method should be ref, #rows~=500 (and no Z In following EXPLAIN the access method should be ref, #rows~=500 (and not 2) explain select * from t2 where a=1000 and b<11; +# +# Bug #47123: Endless 100% CPU loop with STRAIGHT_JOIN +# +CREATE TABLE t1(a INT, KEY(a)); +INSERT INTO t1 VALUES (1), (NULL); +SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL); +a +DROP TABLE t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 5 const 502 Using where drop table t1, t2; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 8fd976081d0..3a736849f94 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4403,8 +4403,7 @@ FROM t1 WHERE a = 230; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables -2 DEPENDENT SUBQUERY st1 index NULL a 5 NULL 2 Using index -2 DEPENDENT SUBQUERY st2 index b b 5 NULL 2 Using where; Using index; Using join buffer +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) FROM t1 WHERE a = 230; diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index ddddb66f38d..272df5f272e 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -1043,6 +1043,15 @@ alter table t2 add index (a,b); select 'In following EXPLAIN the access method should be ref, #rows~=500 (and not 2)' Z; explain select * from t2 where a=1000 and b<11; +--echo # +--echo # Bug #47123: Endless 100% CPU loop with STRAIGHT_JOIN +--echo # + +CREATE TABLE t1(a INT, KEY(a)); +INSERT INTO t1 VALUES (1), (NULL); +SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL); +DROP TABLE t1; + drop table t1, t2; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 4112f40b683..b4d778089a9 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5911,6 +5911,17 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, goto end; } field->table->in_use->variables.sql_mode= orig_sql_mode; + + /* + Any sargable predicate except "<=>" involving NULL as a constant is always + FALSE + */ + if (type != Item_func::EQUAL_FUNC && field->is_real_null()) + { + tree= &null_element; + goto end; + } + str= (uchar*) alloc_root(alloc, key_part->store_length+1); if (!str) goto end; From 5fb71256d2faa7ad0f09f56abe96673b088b96fd Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 18:14:34 +0100 Subject: [PATCH 085/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 3182 [merge] > revision-id: ramil@mysql.com-20091018162655-z4dlolfx5s0zem8l > parent: alexey.kopytov@sun.com-20091016201951-fsht0wm8xn8vkzsx > parent: ramil@mysql.com-20091013044327-24km05wc060ied87 > committer: Ramil Kalimullin > branch nick: mysql-5.1-bugteam > timestamp: Sun 2009-10-18 21:26:55 +0500 > message: > Fix for bug#47963: Wrong results when index is used > > Problem: using null microsecond part in a WHERE condition > (e.g. WHERE date_time_field <= "YYYY-MM-DD HH:MM:SS.0000") > may lead to wrong results due to improper DATETIMEs > comparison in some cases. > > Fix: comparing DATETIMEs as strings we must trim trailing 0's > in such cases. > ------------------------------------------------------------ > Use --include-merges or -n0 to see merged revisions. --- mysql-test/r/innodb_mysql.result | 42 ++++++++++++++++++++++++++++++++ mysql-test/t/innodb_mysql.test | 29 ++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index b112bde4f27..c882d2af1ed 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -2209,4 +2209,46 @@ EXPLAIN SELECT * FROM t1 FORCE INDEX(PRIMARY) WHERE b=1 AND c=1 ORDER BY a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 128 Using where DROP TABLE t1; +# +# Bug #47963: Wrong results when index is used +# +CREATE TABLE t1( +a VARCHAR(5) NOT NULL, +b VARCHAR(5) NOT NULL, +c DATETIME NOT NULL, +KEY (c) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES('TEST', 'TEST', '2009-10-09 00:00:00'); +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00.0'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00.0'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.000' AND c <= '2009-10-09 00:00:00.000'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.00' AND c <= '2009-10-09 00:00:00.001'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +a b c +EXPLAIN SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index c643465b2f3..7055879ce1a 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -461,4 +461,33 @@ EXPLAIN SELECT * FROM t1 FORCE INDEX(PRIMARY) WHERE b=1 AND c=1 ORDER BY a; DROP TABLE t1; +--echo # +--echo # Bug #47963: Wrong results when index is used +--echo # +CREATE TABLE t1( + a VARCHAR(5) NOT NULL, + b VARCHAR(5) NOT NULL, + c DATETIME NOT NULL, + KEY (c) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES('TEST', 'TEST', '2009-10-09 00:00:00'); +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00.0'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00.0'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.000' AND c <= '2009-10-09 00:00:00.000'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.00' AND c <= '2009-10-09 00:00:00.001'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +EXPLAIN SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +DROP TABLE t1; + + --echo End of 5.1 tests From 8b1103e0ae13fc8380b96827cf31ca624c5a5ac9 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 18:16:26 +0100 Subject: [PATCH 086/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 3184.3.13 > revision-id: joro@sun.com-20091019135504-e6fmhf4xyy0wdymb > parent: joro@sun.com-20091026095557-euhe1z9oxtgkw35h > committer: Georgi Kodinov > branch nick: B47788-5.1-bugteam > timestamp: Mon 2009-10-19 16:55:04 +0300 > message: > Bug #47788: Crash in TABLE_LIST::hide_view_error on > UPDATE + VIEW + SP + MERGE + ALTER > > When cleaning up the stored procedure's internal > structures the flag to ignore the errors for > INSERT/UPDATE IGNORE was not cleaned up. > As a result error ignoring was on during name > resolution. And this is an abnormal situation : the > SELECT_LEX flag can be on only during query execution. > > Fixed by correctly cleaning up the SELECT_LEX flag > when reusing the SELECT_LEX in a second execution. --- mysql-test/r/sp-error.result | 16 ++++++++++++++++ mysql-test/t/sp-error.test | 24 ++++++++++++++++++++++++ sql/sql_prepare.cc | 3 +++ 3 files changed, 43 insertions(+) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 17ab2b79043..b3968ea7eb6 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1670,3 +1670,19 @@ NULL SELECT non_existent (a) FROM t1 WHERE b = 999999; ERROR 42000: FUNCTION test.non_existent does not exist DROP TABLE t1; +# +# Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW + +# SP + MERGE + ALTER +# +CREATE TABLE t1 (pk INT, b INT, KEY (b)); +CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT * FROM t1; +CREATE PROCEDURE p1 (a int) UPDATE IGNORE v1 SET b = a; +CALL p1(5); +ERROR HY000: The target table v1 of the UPDATE is not updatable +ALTER TABLE t1 CHANGE COLUMN b b2 INT; +CALL p1(7); +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 66b960c938f..18a4a117939 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2448,3 +2448,27 @@ SELECT AVG (a) FROM t1 WHERE b = 999999; --error ER_SP_DOES_NOT_EXIST SELECT non_existent (a) FROM t1 WHERE b = 999999; DROP TABLE t1; + +--echo # +--echo # Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW + +--echo # SP + MERGE + ALTER +--echo # + +CREATE TABLE t1 (pk INT, b INT, KEY (b)); +CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT * FROM t1; + +CREATE PROCEDURE p1 (a int) UPDATE IGNORE v1 SET b = a; + +--error ER_NON_UPDATABLE_TABLE +CALL p1(5); + +ALTER TABLE t1 CHANGE COLUMN b b2 INT; + +--error ER_VIEW_INVALID +CALL p1(7); + +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c1839b7220f..7c618ac4b37 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2342,6 +2342,9 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) /* Fix ORDER list */ for (order= (ORDER *)sl->order_list.first; order; order= order->next) order->item= &order->item_ptr; + + /* clear the no_error flag for INSERT/UPDATE IGNORE */ + sl->no_error= FALSE; } { SELECT_LEX_UNIT *unit= sl->master_unit(); From 610f0f1b2a4af69f86367efb497202edc98afb40 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 18:17:57 +0100 Subject: [PATCH 087/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 3184.7.1 > revision-id: luis.soares@sun.com-20091027151553-ri74b2zdchw8wyg7 > parent: joro@sun.com-20091019135504-e6fmhf4xyy0wdymb > committer: Luis Soares > branch nick: mysql-5.1-bugteam > timestamp: Tue 2009-10-27 15:15:53 +0000 > message: > BUG#48297: Schema name is ignored when LOAD DATA is written into > binlog, replication aborts > > In SBR or MBR, the schema name is not being written to the binlog > when executing a LOAD DATA statement. This becomes a problem when > the current database (lets call it db1) is different from the > table's schema (lets call it db2). For instance, take the > following statements: > > use db1; > load data local infile 'infile.txt' into table db2.t > > Should this statement be logged without t's schema (db2), when > replaying it, one can get db1.t populated instead of db2.t (if > db1.t exists). On the other hand, if there is no db1.t at all, > replication will stop. > > We fix this by always logging the table (in load file) with fully > qualified name when its schema is different from the current > database or when no default database was selected. --- mysql-test/extra/rpl_tests/rpl_loaddata.test | 61 ++++++++++++++++++++ mysql-test/suite/rpl/r/rpl_loaddata.result | 29 ++++++++++ sql/sql_load.cc | 30 ++++++++-- 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_loaddata.test b/mysql-test/extra/rpl_tests/rpl_loaddata.test index 26916642cae..7db12600456 100644 --- a/mysql-test/extra/rpl_tests/rpl_loaddata.test +++ b/mysql-test/extra/rpl_tests/rpl_loaddata.test @@ -158,4 +158,65 @@ LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1; DROP TABLE IF EXISTS t1; +# BUG#48297: Schema name is ignored when LOAD DATA is written into binlog, +# replication aborts +-- source include/master-slave-reset.inc + +-- let $db1= b48297_db1 +-- let $db2= b42897_db2 + +-- connection master + +-- disable_warnings +-- eval drop database if exists $db1 +-- eval drop database if exists $db2 +-- enable_warnings + +-- eval create database $db1 +-- eval create database $db2 + +-- eval use $db1 +-- eval CREATE TABLE t1 (c1 VARCHAR(256)) engine=$engine_type; + +-- eval use $db2 + +-- echo ### assertion: works with cross-referenced database +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 + +-- eval use $db1 +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- echo ### assertion: works with fully qualified name on current database +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 + +-- echo ### assertion: works without fully qualified name on current database +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1 + +-- echo ### create connection without default database +-- echo ### connect (conn2,localhost,root,,*NO-ONE*); +connect (conn2,localhost,root,,*NO-ONE*); +-- connection conn2 +-- echo ### assertion: works without stating the default database +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- echo ### disconnect and switch back to master connection +-- disconnect conn2 +-- connection master + +-- sync_slave_with_master +-- eval use $db1 + +let $diff_table_1=master:$db1.t1; +let $diff_table_2=slave:$db1.t1; +source include/diff_tables.inc; + +-- connection master + +-- eval DROP DATABASE $db1 +-- eval DROP DATABASE $db2 + +-- sync_slave_with_master + # End of 4.1 tests diff --git a/mysql-test/suite/rpl/r/rpl_loaddata.result b/mysql-test/suite/rpl/r/rpl_loaddata.result index 0653936f0ec..ca9c14691b0 100644 --- a/mysql-test/suite/rpl/r/rpl_loaddata.result +++ b/mysql-test/suite/rpl/r/rpl_loaddata.result @@ -86,3 +86,32 @@ CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB; LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1; ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY' DROP TABLE IF EXISTS t1; +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 b48297_db1; +drop database if exists b42897_db2; +create database b48297_db1; +create database b42897_db2; +use b48297_db1; +CREATE TABLE t1 (c1 VARCHAR(256)) engine=MyISAM;; +use b42897_db2; +### assertion: works with cross-referenced database +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +use b48297_db1; +### assertion: works with fully qualified name on current database +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +### assertion: works without fully qualified name on current database +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1; +### create connection without default database +### connect (conn2,localhost,root,,*NO-ONE*); +### assertion: works without stating the default database +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +### disconnect and switch back to master connection +use b48297_db1; +Comparing tables master:b48297_db1.t1 and slave:b48297_db1.t1 +DROP DATABASE b48297_db1; +DROP DATABASE b42897_db2; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index e830e29176b..238678ef9bc 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -84,7 +84,7 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, bool ignore_check_option_errors); #ifndef EMBEDDED_LIBRARY static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, - const char* db_arg, + const char* db_arg, /* table's database */ const char* table_name_arg, enum enum_duplicates duplicates, bool ignore, @@ -501,7 +501,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (thd->transaction.stmt.modified_non_trans_table) write_execute_load_query_log_event(thd, ex, - tdb, table_list->table_name, + table_list->db, + table_list->table_name, handle_duplicates, ignore, transactional_table, errcode); @@ -548,7 +549,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); write_execute_load_query_log_event(thd, ex, - tdb, table_list->table_name, + table_list->db, table_list->table_name, handle_duplicates, ignore, transactional_table, errcode); @@ -573,7 +574,7 @@ err: /* Not a very useful function; just to avoid duplication of code */ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, - const char* db_arg, + const char* db_arg, /* table's database */ const char* table_name_arg, enum enum_duplicates duplicates, bool ignore, @@ -590,8 +591,27 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, Item *item, *val; String pfield, pfields; int n; + const char *tbl= table_name_arg; + const char *tdb= (thd->db != NULL ? thd->db : db_arg); + String string_buf; - Load_log_event lle(thd, ex, db_arg, table_name_arg, fv, duplicates, + if (!thd->db || strcmp(db_arg, thd->db)) + { + /* + If used database differs from table's database, + prefix table name with database name so that it + becomes a FQ name. + */ + string_buf.set_charset(system_charset_info); + string_buf.append(db_arg); + string_buf.append("`"); + string_buf.append("."); + string_buf.append("`"); + string_buf.append(table_name_arg); + tbl= string_buf.c_ptr_safe(); + } + + Load_log_event lle(thd, ex, tdb, tbl, fv, duplicates, ignore, transactional_table); /* From d301f60f0107d51f9d98fc7407bda55d3fd1b96f Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 18:18:52 +0100 Subject: [PATCH 088/344] Backport into build-200911241145-5.1.40sp1 > ------------------------------------------------------------ > revno: 3190 [merge] > revision-id: kostja@sun.com-20091103174552-bfpak6r7ngf5cbjb > parent: magnus.blaudd@sun.com-20091103170719-6b64sjnivsiyz6xy > parent: kostja@sun.com-20091103165854-7di545xruez8w207 > committer: Konstantin Osipov > branch nick: 5.1-41756 > timestamp: Tue 2009-11-03 20:45:52 +0300 > message: > A fix and a test case for > Bug#41756 "Strange error messages about locks from InnoDB". > > In JT_EQ_REF (join_read_key()) access method, > don't try to unlock rows in the handler, unless certain that > a) they were locked > b) they are not used. > > Unlocking of rows is done by the logic of the nested join loop, > and is unaware of the possible caching that the access method may > have. This could lead to double unlocking, when a row > was unlocked first after reading into the cache, and then > when taken from cache, as well as to unlocking of rows which > were actually used (but taken from cache). > > Delegate part of the unlocking logic to the access method, > and in JT_EQ_REF count how many times a record was actually > used in the join. Unlock it only if it's usage count is 0. > > Implemented review comments. > ------------------------------------------------------------ > Use --include-merges or -n0 to see merged revisions. --- sql/item_subselect.cc | 1 + sql/records.cc | 2 ++ sql/sql_select.cc | 60 +++++++++++++++++++++++++++++++++++++++++-- sql/sql_select.h | 7 +++++ sql/structs.h | 14 +++++++--- 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 29db9eb0903..fa776ea3dca 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1954,6 +1954,7 @@ int subselect_single_select_engine::exec() tab->read_record.record= tab->table->record[0]; tab->read_record.thd= join->thd; tab->read_record.ref_length= tab->table->file->ref_length; + tab->read_record.unlock_row= rr_unlock_row; *(last_changed_tab++)= tab; break; } diff --git a/sql/records.cc b/sql/records.cc index 9e040de3fda..ed927ac3bc8 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -61,6 +61,7 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, info->file= table->file; info->record= table->record[0]; info->print_error= print_error; + info->unlock_row= rr_unlock_row; table->status=0; /* And it's always found */ if (!table->file->inited) @@ -186,6 +187,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, } info->select=select; info->print_error=print_error; + info->unlock_row= rr_unlock_row; info->ignore_not_found_rows= 0; table->status=0; /* And it's always found */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 34d23ace89b..c230363a045 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -149,6 +149,7 @@ static int join_read_const_table(JOIN_TAB *tab, POSITION *pos); static int join_read_system(JOIN_TAB *tab); static int join_read_const(JOIN_TAB *tab); static int join_read_key(JOIN_TAB *tab); +static void join_read_key_unlock_row(st_join_table *tab); static int join_read_always_key(JOIN_TAB *tab); static int join_read_last_key(JOIN_TAB *tab); static int join_no_more_records(READ_RECORD *info); @@ -5607,7 +5608,9 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, } j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length); j->ref.key_err=1; + j->ref.has_record= FALSE; j->ref.null_rejecting= 0; + j->ref.use_count= 0; keyuse=org_keyuse; store_key **ref_key= j->ref.key_copy; @@ -6440,6 +6443,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) DBUG_RETURN(0); } + +/** + The default implementation of unlock-row method of READ_RECORD, + used in all access methods. +*/ + +void rr_unlock_row(st_join_table *tab) +{ + READ_RECORD *info= &tab->read_record; + info->file->unlock_row(); +} + + + static void make_join_readinfo(JOIN *join, ulonglong options) { @@ -6455,6 +6472,7 @@ make_join_readinfo(JOIN *join, ulonglong options) TABLE *table=tab->table; tab->read_record.table= table; tab->read_record.file=table->file; + tab->read_record.unlock_row= rr_unlock_row; tab->next_select=sub_select; /* normal select */ /* @@ -6500,6 +6518,7 @@ make_join_readinfo(JOIN *join, ulonglong options) delete tab->quick; tab->quick=0; tab->read_first_record= join_read_key; + tab->read_record.unlock_row= join_read_key_unlock_row; tab->read_record.read_record= join_no_more_records; if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) @@ -11327,7 +11346,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, return NESTED_LOOP_NO_MORE_ROWS; } else - join_tab->read_record.file->unlock_row(); + join_tab->read_record.unlock_row(join_tab); } else { @@ -11337,7 +11356,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, */ join->examined_rows++; join->thd->row_count++; - join_tab->read_record.file->unlock_row(); + join_tab->read_record.unlock_row(join_tab); } return NESTED_LOOP_OK; } @@ -11697,18 +11716,55 @@ join_read_key(JOIN_TAB *tab) table->status=STATUS_NOT_FOUND; return -1; } + /* + Moving away from the current record. Unlock the row + in the handler if it did not match the partial WHERE. + */ + if (tab->ref.has_record && tab->ref.use_count == 0) + { + tab->read_record.file->unlock_row(); + tab->ref.has_record= FALSE; + } error=table->file->index_read_map(table->record[0], tab->ref.key_buff, make_prev_keypart_map(tab->ref.key_parts), HA_READ_KEY_EXACT); if (error && error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) return report_error(table, error); + + if (! error) + { + tab->ref.has_record= TRUE; + tab->ref.use_count= 1; + } + } + else if (table->status == 0) + { + DBUG_ASSERT(tab->ref.has_record); + tab->ref.use_count++; } table->null_row=0; return table->status ? -1 : 0; } +/** + Since join_read_key may buffer a record, do not unlock + it if it was not used in this invocation of join_read_key(). + Only count locks, thus remembering if the record was left unused, + and unlock already when pruning the current value of + TABLE_REF buffer. + @sa join_read_key() +*/ + +static void +join_read_key_unlock_row(st_join_table *tab) +{ + DBUG_ASSERT(tab->ref.use_count); + if (tab->ref.use_count) + tab->ref.use_count--; +} + /* ref access method implementation: "read_first" function diff --git a/sql/sql_select.h b/sql/sql_select.h index 4c729fa915c..991bc900df0 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -58,6 +58,8 @@ class store_key; typedef struct st_table_ref { bool key_err; + /** True if something was read into buffer in join_read_key. */ + bool has_record; uint key_parts; ///< num of ... uint key_length; ///< length of key_buff int key; ///< key no @@ -85,6 +87,11 @@ typedef struct st_table_ref table_map depend_map; ///< Table depends on these tables. /* null byte position in the key_buf. Used for REF_OR_NULL optimization */ uchar *null_ref_key; + /* + The number of times the record associated with this key was used + in the join. + */ + ha_rows use_count; } TABLE_REF; diff --git a/sql/structs.h b/sql/structs.h index a58c18f97c5..2546d241059 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -115,16 +115,22 @@ typedef struct st_reginfo { /* Extra info about reg */ } REGINFO; -struct st_read_record; /* For referense later */ class SQL_SELECT; class THD; class handler; +struct st_join_table; -typedef struct st_read_record { /* Parameter to read_record */ +void rr_unlock_row(st_join_table *tab); + +struct READ_RECORD { /* Parameter to read_record */ + typedef int (*Read_func)(READ_RECORD*); + typedef void (*Unlock_row_func)(st_join_table *); struct st_table *table; /* Head-form */ handler *file; struct st_table **forms; /* head and ref forms */ - int (*read_record)(struct st_read_record *); + + Read_func read_record; + Unlock_row_func unlock_row; THD *thd; SQL_SELECT *select; uint cache_records; @@ -136,7 +142,7 @@ typedef struct st_read_record { /* Parameter to read_record */ uchar *cache,*cache_pos,*cache_end,*read_positions; IO_CACHE *io_cache; bool print_error, ignore_not_found_rows; -} READ_RECORD; +}; /* From 8620b3518cb17bc51d55b9668642a0e6e9ef8a34 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 18:21:48 +0100 Subject: [PATCH 089/344] Test cases added --- mysql-test/r/innodb_bug47777.result | 13 + .../r/innodb_lock_wait_timeout_1.result | 308 ++++++++++++++++++ mysql-test/t/innodb_bug47777.test | 24 ++ .../t/innodb_lock_wait_timeout_1-master.opt | 1 + mysql-test/t/innodb_lock_wait_timeout_1.test | 160 +++++++++ 5 files changed, 506 insertions(+) create mode 100644 mysql-test/r/innodb_bug47777.result create mode 100644 mysql-test/r/innodb_lock_wait_timeout_1.result create mode 100644 mysql-test/t/innodb_bug47777.test create mode 100644 mysql-test/t/innodb_lock_wait_timeout_1-master.opt create mode 100644 mysql-test/t/innodb_lock_wait_timeout_1.test diff --git a/mysql-test/r/innodb_bug47777.result b/mysql-test/r/innodb_bug47777.result new file mode 100644 index 00000000000..fbba47edcfc --- /dev/null +++ b/mysql-test/r/innodb_bug47777.result @@ -0,0 +1,13 @@ +create table bug47777(c2 linestring not null, primary key (c2(1))) engine=innodb; +insert into bug47777 values (geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)')); +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +count(*) +1 +update bug47777 set c2=GeomFromText('POINT(1 1)'); +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +count(*) +0 +select count(*) from bug47777 where c2 = GeomFromText('POINT(1 1)'); +count(*) +1 +drop table bug47777; diff --git a/mysql-test/r/innodb_lock_wait_timeout_1.result b/mysql-test/r/innodb_lock_wait_timeout_1.result new file mode 100644 index 00000000000..f331d3acd27 --- /dev/null +++ b/mysql-test/r/innodb_lock_wait_timeout_1.result @@ -0,0 +1,308 @@ +# +# Bug#41756 Strange error messages about locks from InnoDB +# +drop table if exists t1; +# In the default transaction isolation mode, and/or with +# innodb_locks_unsafe_for_binlog=OFF, handler::unlock_row() +# in InnoDB does nothing. +# Thus in order to reproduce the condition that led to the +# warning, one needs to relax isolation by either +# setting a weaker tx_isolation value, or by turning on +# the unsafe replication switch. +# For testing purposes, choose to tweak the isolation level, +# since it's settable at runtime, unlike +# innodb_locks_unsafe_for_binlog, which is +# only a command-line switch. +# +set @@session.tx_isolation="read-committed"; +# Prepare data. We need a table with a unique index, +# for join_read_key to be used. The other column +# allows to control what passes WHERE clause filter. +create table t1 (a int primary key, b int) engine=innodb; +# Let's make sure t1 has sufficient amount of rows +# to exclude JT_ALL access method when reading it, +# i.e. make sure that JT_EQ_REF(a) is always preferred. +insert into t1 values (1,1), (2,null), (3,1), (4,1), +(5,1), (6,1), (7,1), (8,1), (9,1), (10,1), +(11,1), (12,1), (13,1), (14,1), (15,1), +(16,1), (17,1), (18,1), (19,1), (20,1); +# +# Demonstrate that for the SELECT statement +# used later in the test JT_EQ_REF access method is used. +# +explain +select 1 from t1 natural join (select 2 as a, 1 as b union all +select 2 as a, 2 as b) as t2 for update; +id 1 +select_type PRIMARY +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows 2 +Extra +id 1 +select_type PRIMARY +table t1 +type eq_ref +possible_keys PRIMARY +key PRIMARY +key_len 4 +ref t2.a +rows 1 +Extra Using where +id 2 +select_type DERIVED +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id 3 +select_type UNION +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id NULL +select_type UNION RESULT +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra +# +# Demonstrate that the reported SELECT statement +# no longer produces warnings. +# +select 1 from t1 natural join (select 2 as a, 1 as b union all +select 2 as a, 2 as b) as t2 for update; +1 +commit; +# +# Demonstrate that due to lack of inter-sweep "reset" function, +# we keep some non-matching records locked, even though we know +# we could unlock them. +# To do that, show that if there is only one distinct value +# for a in t2 (a=2), we will keep record (2,null) in t1 locked. +# But if we add another value for "a" to t2, say 6, +# join_read_key cache will be pruned at least once, +# and thus record (2, null) in t1 will get unlocked. +# +begin; +select 1 from t1 natural join (select 2 as a, 1 as b union all +select 2 as a, 2 as b) as t2 for update; +1 +# +# Switching to connection con1 +# We should be able to delete all records from t1 except (2, null), +# since they were not locked. +begin; +# Delete in series of 3 records so that full scan +# is not used and we're not blocked on record (2,null) +delete from t1 where a in (1,3,4); +delete from t1 where a in (5,6,7); +delete from t1 where a in (8,9,10); +delete from t1 where a in (11,12,13); +delete from t1 where a in (14,15,16); +delete from t1 where a in (17,18); +delete from t1 where a in (19,20); +# +# Record (2, null) is locked. This is actually unnecessary, +# because the previous select returned no rows. +# Just demonstrate the effect. +# +delete from t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +rollback; +# +# Switching to connection default +# +# Show that the original contents of t1 is intact: +select * from t1; +a b +1 1 +2 NULL +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +commit; +# +# Have a one more record in t2 to show that +# if join_read_key cache is purned, the current +# row under the cursor is unlocked (provided, this row didn't +# match the partial WHERE clause, of course). +# Sic: the result of this test dependent on the order of retrieval +# of records --echo # from the derived table, if ! +# We use DELETE to disable the JOIN CACHE. This DELETE modifies no +# records. It also should leave no InnoDB row locks. +# +begin; +delete t1.* from t1 natural join (select 2 as a, 2 as b union all +select 0 as a, 0 as b) as t2; +# Demonstrate that nothing was deleted form t1 +select * from t1; +a b +1 1 +2 NULL +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +# +# Switching to connection con1 +begin; +# Since there is another distinct record in the derived table +# the previous matching record in t1 -- (2,null) -- was unlocked. +delete from t1; +# We will need the contents of the table again. +rollback; +select * from t1; +a b +1 1 +2 NULL +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +commit; +# +# Switching to connection default +rollback; +begin; +# +# Before this patch, we could wrongly unlock a record +# that was cached and later used in a join. Demonstrate that +# this is no longer the case. +# Sic: this test is also order-dependent (i.e. the +# the bug would show up only if the first record in the union +# is retreived and processed first. +# +# Verify that JT_EQ_REF is used. +explain +select 1 from t1 natural join (select 3 as a, 2 as b union all +select 3 as a, 1 as b) as t2 for update; +id 1 +select_type PRIMARY +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows 2 +Extra +id 1 +select_type PRIMARY +table t1 +type eq_ref +possible_keys PRIMARY +key PRIMARY +key_len 4 +ref t2.a +rows 1 +Extra Using where +id 2 +select_type DERIVED +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id 3 +select_type UNION +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id NULL +select_type UNION RESULT +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra +# Lock the record. +select 1 from t1 natural join (select 3 as a, 2 as b union all +select 3 as a, 1 as b) as t2 for update; +1 +1 +# Switching to connection con1 +# +# We should not be able to delete record (3,1) from t1, +# (previously it was possible). +# +delete from t1 where a=3; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +# Switching to connection default +commit; +set @@session.tx_isolation=default; +drop table t1; +# +# End of 5.1 tests +# diff --git a/mysql-test/t/innodb_bug47777.test b/mysql-test/t/innodb_bug47777.test new file mode 100644 index 00000000000..8f2985b2cf0 --- /dev/null +++ b/mysql-test/t/innodb_bug47777.test @@ -0,0 +1,24 @@ +# This is the test for bug 47777. GEOMETRY +# data is treated as BLOB data in innodb. +# Consequently, its key value generation/storing +# should follow the process for the BLOB +# datatype as well. + +--source include/have_innodb.inc + +create table bug47777(c2 linestring not null, primary key (c2(1))) engine=innodb; + +insert into bug47777 values (geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)')); + +# Verify correct row get inserted. +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); + +# Update table bug47777 should be successful. +update bug47777 set c2=GeomFromText('POINT(1 1)'); + +# Verify the row get updated successfully. The original +# c2 value should be changed to GeomFromText('POINT(1 1)'). +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +select count(*) from bug47777 where c2 = GeomFromText('POINT(1 1)'); + +drop table bug47777; diff --git a/mysql-test/t/innodb_lock_wait_timeout_1-master.opt b/mysql-test/t/innodb_lock_wait_timeout_1-master.opt new file mode 100644 index 00000000000..462f8fbe828 --- /dev/null +++ b/mysql-test/t/innodb_lock_wait_timeout_1-master.opt @@ -0,0 +1 @@ +--innodb_lock_wait_timeout=1 diff --git a/mysql-test/t/innodb_lock_wait_timeout_1.test b/mysql-test/t/innodb_lock_wait_timeout_1.test new file mode 100644 index 00000000000..ecb7aff4598 --- /dev/null +++ b/mysql-test/t/innodb_lock_wait_timeout_1.test @@ -0,0 +1,160 @@ +--source include/have_innodb.inc + +--echo # +--echo # Bug#41756 Strange error messages about locks from InnoDB +--echo # +--disable_warnings +drop table if exists t1; +--enable_warnings +--echo # In the default transaction isolation mode, and/or with +--echo # innodb_locks_unsafe_for_binlog=OFF, handler::unlock_row() +--echo # in InnoDB does nothing. +--echo # Thus in order to reproduce the condition that led to the +--echo # warning, one needs to relax isolation by either +--echo # setting a weaker tx_isolation value, or by turning on +--echo # the unsafe replication switch. +--echo # For testing purposes, choose to tweak the isolation level, +--echo # since it's settable at runtime, unlike +--echo # innodb_locks_unsafe_for_binlog, which is +--echo # only a command-line switch. +--echo # +set @@session.tx_isolation="read-committed"; + +--echo # Prepare data. We need a table with a unique index, +--echo # for join_read_key to be used. The other column +--echo # allows to control what passes WHERE clause filter. +create table t1 (a int primary key, b int) engine=innodb; +--echo # Let's make sure t1 has sufficient amount of rows +--echo # to exclude JT_ALL access method when reading it, +--echo # i.e. make sure that JT_EQ_REF(a) is always preferred. +insert into t1 values (1,1), (2,null), (3,1), (4,1), + (5,1), (6,1), (7,1), (8,1), (9,1), (10,1), + (11,1), (12,1), (13,1), (14,1), (15,1), + (16,1), (17,1), (18,1), (19,1), (20,1); +--echo # +--echo # Demonstrate that for the SELECT statement +--echo # used later in the test JT_EQ_REF access method is used. +--echo # +--vertical_results +explain +select 1 from t1 natural join (select 2 as a, 1 as b union all + select 2 as a, 2 as b) as t2 for update; +--horizontal_results +--echo # +--echo # Demonstrate that the reported SELECT statement +--echo # no longer produces warnings. +--echo # +select 1 from t1 natural join (select 2 as a, 1 as b union all + select 2 as a, 2 as b) as t2 for update; +commit; +--echo # +--echo # Demonstrate that due to lack of inter-sweep "reset" function, +--echo # we keep some non-matching records locked, even though we know +--echo # we could unlock them. +--echo # To do that, show that if there is only one distinct value +--echo # for a in t2 (a=2), we will keep record (2,null) in t1 locked. +--echo # But if we add another value for "a" to t2, say 6, +--echo # join_read_key cache will be pruned at least once, +--echo # and thus record (2, null) in t1 will get unlocked. +--echo # +begin; +select 1 from t1 natural join (select 2 as a, 1 as b union all + select 2 as a, 2 as b) as t2 for update; +connect (con1,localhost,root,,); +--echo # +--echo # Switching to connection con1 +connection con1; +--echo # We should be able to delete all records from t1 except (2, null), +--echo # since they were not locked. +begin; +--echo # Delete in series of 3 records so that full scan +--echo # is not used and we're not blocked on record (2,null) +delete from t1 where a in (1,3,4); +delete from t1 where a in (5,6,7); +delete from t1 where a in (8,9,10); +delete from t1 where a in (11,12,13); +delete from t1 where a in (14,15,16); +delete from t1 where a in (17,18); +delete from t1 where a in (19,20); +--echo # +--echo # Record (2, null) is locked. This is actually unnecessary, +--echo # because the previous select returned no rows. +--echo # Just demonstrate the effect. +--echo # +--error ER_LOCK_WAIT_TIMEOUT +delete from t1; +rollback; +--echo # +--echo # Switching to connection default +connection default; +--echo # +--echo # Show that the original contents of t1 is intact: +select * from t1; +commit; +--echo # +--echo # Have a one more record in t2 to show that +--echo # if join_read_key cache is purned, the current +--echo # row under the cursor is unlocked (provided, this row didn't +--echo # match the partial WHERE clause, of course). +--echo # Sic: the result of this test dependent on the order of retrieval +--echo # of records --echo # from the derived table, if ! +--echo # We use DELETE to disable the JOIN CACHE. This DELETE modifies no +--echo # records. It also should leave no InnoDB row locks. +--echo # +begin; +delete t1.* from t1 natural join (select 2 as a, 2 as b union all + select 0 as a, 0 as b) as t2; +--echo # Demonstrate that nothing was deleted form t1 +select * from t1; +--echo # +--echo # Switching to connection con1 +connection con1; +begin; +--echo # Since there is another distinct record in the derived table +--echo # the previous matching record in t1 -- (2,null) -- was unlocked. +delete from t1; +--echo # We will need the contents of the table again. +rollback; +select * from t1; +commit; +--echo # +--echo # Switching to connection default +connection default; +rollback; +begin; +--echo # +--echo # Before this patch, we could wrongly unlock a record +--echo # that was cached and later used in a join. Demonstrate that +--echo # this is no longer the case. +--echo # Sic: this test is also order-dependent (i.e. the +--echo # the bug would show up only if the first record in the union +--echo # is retreived and processed first. +--echo # +--echo # Verify that JT_EQ_REF is used. +--vertical_results +explain +select 1 from t1 natural join (select 3 as a, 2 as b union all + select 3 as a, 1 as b) as t2 for update; +--horizontal_results +--echo # Lock the record. +select 1 from t1 natural join (select 3 as a, 2 as b union all + select 3 as a, 1 as b) as t2 for update; +--echo # Switching to connection con1 +connection con1; +--echo # +--echo # We should not be able to delete record (3,1) from t1, +--echo # (previously it was possible). +--echo # +--error ER_LOCK_WAIT_TIMEOUT +delete from t1 where a=3; +--echo # Switching to connection default +connection default; +commit; + +disconnect con1; +set @@session.tx_isolation=default; +drop table t1; + +--echo # +--echo # End of 5.1 tests +--echo # From c360a20a40690adbc7ecb6cd10bf0e241441aae6 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 23:24:18 +0100 Subject: [PATCH 090/344] Patch adjustments --- mysql-test/r/range.result | 6 +++--- mysql-test/t/range.test | 5 ++--- storage/innodb_plugin/handler/ha_innodb.cc | 5 ++++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 3ed2c3f53d0..3b4870ad89c 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -1216,6 +1216,9 @@ select 'In following EXPLAIN the access method should be ref, #rows~=500 (and no Z In following EXPLAIN the access method should be ref, #rows~=500 (and not 2) explain select * from t2 where a=1000 and b<11; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref a a 5 const 502 Using where +drop table t1, t2; # # Bug #47123: Endless 100% CPU loop with STRAIGHT_JOIN # @@ -1224,9 +1227,6 @@ INSERT INTO t1 VALUES (1), (NULL); SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL); a DROP TABLE t1; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ref a a 5 const 502 Using where -drop table t1, t2; # # Bug#47925: regression of range optimizer and date comparison in 5.1.39! # diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index 272df5f272e..5f53fafc5b4 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -1043,6 +1043,8 @@ alter table t2 add index (a,b); select 'In following EXPLAIN the access method should be ref, #rows~=500 (and not 2)' Z; explain select * from t2 where a=1000 and b<11; +drop table t1, t2; + --echo # --echo # Bug #47123: Endless 100% CPU loop with STRAIGHT_JOIN --echo # @@ -1052,9 +1054,6 @@ INSERT INTO t1 VALUES (1), (NULL); SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL); DROP TABLE t1; - -drop table t1, t2; - --echo # --echo # Bug#47925: regression of range optimizer and date comparison in 5.1.39! --echo # diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 682004407c7..f01ff4450c8 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -3704,7 +3704,10 @@ ha_innobase::store_key_val_for_row( } else if (mysql_type == MYSQL_TYPE_TINY_BLOB || mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB - || mysql_type == MYSQL_TYPE_LONG_BLOB) { + || mysql_type == MYSQL_TYPE_LONG_BLOB + /* MYSQL_TYPE_GEOMETRY data is treated + as BLOB data in innodb. */ + || mysql_type == MYSQL_TYPE_GEOMETRY) { CHARSET_INFO* cs; ulint key_len; From eeaedab28a7c93a500c66a7c9e91220fa2cbf6e2 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 25 Nov 2009 23:43:37 +0100 Subject: [PATCH 091/344] Patch adjustments --- storage/innodb_plugin/handler/ha_innodb.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index f01ff4450c8..3fb81be031d 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -8679,6 +8679,7 @@ ha_innobase::get_auto_increment( AUTOINC counter after attempting to insert the row. */ if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { ulonglong need; + ulonglong current; ulonglong next_value; ulonglong col_max_value; @@ -8687,11 +8688,12 @@ ha_innobase::get_auto_increment( col_max_value = innobase_get_int_col_max_value( table->next_number_field); + current = *first_value > col_max_value ? autoinc : *first_value; need = *nb_reserved_values * increment; /* Compute the last value in the interval */ next_value = innobase_next_autoinc( - *first_value, need, offset, col_max_value); + current, need, offset, col_max_value); prebuilt->autoinc_last_value = next_value; From 2ac344ecf662f6b5d901825850e3b5568ab91174 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 27 Nov 2009 11:59:44 +0200 Subject: [PATCH 092/344] Bug #48872 : Privileges for stored functions ignored if function name is mixed case Transcode the procedure name to lowercase when searching for it in the hash. This is the missing part of the fix for bug #41049. --- mysql-test/r/sp-security.result | 61 +++++++++++++++++++++++++++++++++ mysql-test/t/sp-security.test | 57 ++++++++++++++++++++++++++++++ sql/sql_acl.cc | 13 ++++--- 3 files changed, 126 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index 106d08c8c12..17758218e35 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -519,4 +519,65 @@ DROP USER mysqltest_u1@localhost; DROP PROCEDURE p_suid; DROP FUNCTION f_suid; DROP TABLE t1; +# +# Bug #48872 : Privileges for stored functions ignored if function name +# is mixed case +# +CREATE DATABASE B48872; +USE B48872; +CREATE TABLE `TestTab` (id INT); +INSERT INTO `TestTab` VALUES (1),(2); +CREATE FUNCTION `f_Test`() RETURNS INT RETURN 123; +CREATE FUNCTION `f_Test_denied`() RETURNS INT RETURN 123; +CREATE USER 'tester'; +CREATE USER 'Tester'; +GRANT SELECT ON TABLE `TestTab` TO 'tester'; +GRANT EXECUTE ON FUNCTION `f_Test` TO 'tester'; +GRANT EXECUTE ON FUNCTION `f_Test_denied` TO 'Tester'; +SELECT f_Test(); +f_Test() +123 +SELECT * FROM TestTab; +id +1 +2 +SELECT * FROM TestTab; +id +1 +2 +SELECT `f_Test`(); +`f_Test`() +123 +SELECT `F_TEST`(); +`F_TEST`() +123 +SELECT f_Test(); +f_Test() +123 +SELECT F_TEST(); +F_TEST() +123 +SELECT * FROM TestTab; +ERROR 42000: SELECT command denied to user 'Tester'@'localhost' for table 'TestTab' +SELECT `f_Test`(); +ERROR 42000: execute command denied to user 'Tester'@'%' for routine 'B48872.f_Test' +SELECT `F_TEST`(); +ERROR 42000: execute command denied to user 'Tester'@'%' for routine 'B48872.f_Test' +SELECT f_Test(); +ERROR 42000: execute command denied to user 'Tester'@'%' for routine 'B48872.f_Test' +SELECT F_TEST(); +ERROR 42000: execute command denied to user 'Tester'@'%' for routine 'B48872.f_Test' +SELECT `f_Test_denied`(); +`f_Test_denied`() +123 +SELECT `F_TEST_DENIED`(); +`F_TEST_DENIED`() +123 +DROP TABLE `TestTab`; +DROP FUNCTION `f_Test`; +DROP FUNCTION `f_Test_denied`; +USE test; +DROP USER 'tester'; +DROP USER 'Tester'; +DROP DATABASE B48872; End of 5.0 tests. diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index b8181fcb89b..42c8ecd85ec 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -889,6 +889,63 @@ DROP PROCEDURE p_suid; DROP FUNCTION f_suid; DROP TABLE t1; +--echo # +--echo # Bug #48872 : Privileges for stored functions ignored if function name +--echo # is mixed case +--echo # + +CREATE DATABASE B48872; +USE B48872; +CREATE TABLE `TestTab` (id INT); +INSERT INTO `TestTab` VALUES (1),(2); +CREATE FUNCTION `f_Test`() RETURNS INT RETURN 123; +CREATE FUNCTION `f_Test_denied`() RETURNS INT RETURN 123; +CREATE USER 'tester'; +CREATE USER 'Tester'; +GRANT SELECT ON TABLE `TestTab` TO 'tester'; +GRANT EXECUTE ON FUNCTION `f_Test` TO 'tester'; +GRANT EXECUTE ON FUNCTION `f_Test_denied` TO 'Tester'; + +SELECT f_Test(); +SELECT * FROM TestTab; + +CONNECT (con_tester,localhost,tester,,B48872); +CONNECT (con_tester_denied,localhost,Tester,,B48872); +CONNECTION con_tester; + +SELECT * FROM TestTab; +SELECT `f_Test`(); +SELECT `F_TEST`(); +SELECT f_Test(); +SELECT F_TEST(); + +CONNECTION con_tester_denied; + +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM TestTab; +--error ER_PROCACCESS_DENIED_ERROR +SELECT `f_Test`(); +--error ER_PROCACCESS_DENIED_ERROR +SELECT `F_TEST`(); +--error ER_PROCACCESS_DENIED_ERROR +SELECT f_Test(); +--error ER_PROCACCESS_DENIED_ERROR +SELECT F_TEST(); +SELECT `f_Test_denied`(); +SELECT `F_TEST_DENIED`(); + +CONNECTION default; +DISCONNECT con_tester; +DISCONNECT con_tester_denied; +DROP TABLE `TestTab`; +DROP FUNCTION `f_Test`; +DROP FUNCTION `f_Test_denied`; + +USE test; +DROP USER 'tester'; +DROP USER 'Tester'; +DROP DATABASE B48872; + --echo End of 5.0 tests. # Wait till all disconnects are completed diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index d04a81e2b0a..f29baad9a84 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2280,14 +2280,17 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, const char *host,const char* ip, const char *db, const char *user, const char *tname, - bool exact) + bool exact, bool name_tolower) { - char helping [NAME_LEN*2+USERNAME_LENGTH+3]; + char helping [NAME_LEN*2+USERNAME_LENGTH+3], *name_ptr; 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; + name_ptr= strmov(strmov(helping, user) + 1, db) + 1; + len = (uint) (strmov(name_ptr, tname) - helping) + 1; + if (name_tolower) + my_casedn_str(files_charset_info, name_ptr); for (grant_name= (GRANT_NAME*) hash_first(name_hash, (byte*) helping, len, &state); grant_name ; @@ -2320,7 +2323,7 @@ routine_hash_search(const char *host, const char *ip, const char *db, { return (GRANT_TABLE*) name_hash_search(proc ? &proc_priv_hash : &func_priv_hash, - host, ip, db, user, tname, exact); + host, ip, db, user, tname, exact, TRUE); } @@ -2329,7 +2332,7 @@ table_hash_search(const char *host, const char *ip, const char *db, const char *user, const char *tname, bool exact) { return (GRANT_TABLE*) name_hash_search(&column_priv_hash, host, ip, db, - user, tname, exact); + user, tname, exact, FALSE); } From 95e420c636978d3788830500d46efcb2f180ce73 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Fri, 27 Nov 2009 13:34:39 +0000 Subject: [PATCH 093/344] BUG#48506 crash in CREATE TABLE IF NOT EXISTS LIKE with RBL When binlogging the statement, the server always handle the existing object as a table, even though it is a view. However a view is handled differently in other parts of the code thus leading the statement to crash in RBL if the view exists. This happens because the underlying tables for the view are not opened when we try to call store_create_info() on the view in order to build a CREATE TABLE statement. This patch will only address the crash problem, other binlogging problems related to CREATE TABLE IF NOT EXISTS LIKE when the existing object is a view will be solved by BUG 47442. --- .../suite/rpl/r/rpl_row_create_table.result | 26 ++++++++++++++ .../suite/rpl/t/rpl_row_create_table.test | 36 +++++++++++++++++++ sql/sql_table.cc | 18 +++++++--- 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_row_create_table.result b/mysql-test/suite/rpl/r/rpl_row_create_table.result index b7122adea2a..4c2b9ebeaee 100644 --- a/mysql-test/suite/rpl/r/rpl_row_create_table.result +++ b/mysql-test/suite/rpl/r/rpl_row_create_table.result @@ -476,4 +476,30 @@ master-bin.000001 # Table_map # # table_id: # (mysqltest1.with_select) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT DROP DATABASE mysqltest1; +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 TEMPORARY TABLE t7(c1 INT); +CREATE TABLE t5(c1 INT); +CREATE TABLE t4(c1 INT); +CREATE VIEW bug48506_t1 AS SELECT 1; +CREATE VIEW bug48506_t2 AS SELECT * FROM t4; +CREATE VIEW bug48506_t3 AS SELECT t5.c1 AS A, t4.c1 AS B FROM t5, t4; +CREATE TABLE bug48506_t4(c1 INT); +DROP VIEW bug48506_t1, bug48506_t2, bug48506_t3; +DROP TABLE bug48506_t4; +CREATE TABLE IF NOT EXISTS bug48506_t1 LIKE t7; +CREATE TABLE IF NOT EXISTS bug48506_t2 LIKE t7; +CREATE TABLE IF NOT EXISTS bug48506_t3 LIKE t7; +CREATE TABLE IF NOT EXISTS bug48506_t4 LIKE t7; +SHOW TABLES LIKE 'bug48506%'; +Tables_in_test (bug48506%) +bug48506_t4 +DROP VIEW IF EXISTS bug48506_t1, bug48506_t2, bug48506_t3; +DROP TEMPORARY TABLES t7; +DROP TABLES t4, t5; +DROP TABLES IF EXISTS bug48506_t4; end of the tests diff --git a/mysql-test/suite/rpl/t/rpl_row_create_table.test b/mysql-test/suite/rpl/t/rpl_row_create_table.test index 319f9546a81..54dcbd24419 100644 --- a/mysql-test/suite/rpl/t/rpl_row_create_table.test +++ b/mysql-test/suite/rpl/t/rpl_row_create_table.test @@ -292,4 +292,40 @@ connection master; DROP DATABASE mysqltest1; sync_slave_with_master; +# +# BUG#48506: crash in CREATE TABLE IF NOT EXISTS LIKE +# with RBL +# + +source include/master-slave-reset.inc; + +connection master; +CREATE TEMPORARY TABLE t7(c1 INT); +CREATE TABLE t5(c1 INT); +CREATE TABLE t4(c1 INT); +CREATE VIEW bug48506_t1 AS SELECT 1; +CREATE VIEW bug48506_t2 AS SELECT * FROM t4; +CREATE VIEW bug48506_t3 AS SELECT t5.c1 AS A, t4.c1 AS B FROM t5, t4; +CREATE TABLE bug48506_t4(c1 INT); +--disable_warnings +sync_slave_with_master; +DROP VIEW bug48506_t1, bug48506_t2, bug48506_t3; +DROP TABLE bug48506_t4; + +connection master; +CREATE TABLE IF NOT EXISTS bug48506_t1 LIKE t7; +CREATE TABLE IF NOT EXISTS bug48506_t2 LIKE t7; +CREATE TABLE IF NOT EXISTS bug48506_t3 LIKE t7; +CREATE TABLE IF NOT EXISTS bug48506_t4 LIKE t7; +--enable_warnings +sync_slave_with_master; + +SHOW TABLES LIKE 'bug48506%'; + +connection master; +DROP VIEW IF EXISTS bug48506_t1, bug48506_t2, bug48506_t3; +DROP TEMPORARY TABLES t7; +DROP TABLES t4, t5; +DROP TABLES IF EXISTS bug48506_t4; +source include/master-slave-end.inc; --echo end of the tests diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ec50c4ec1a5..869ae42c98c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5419,12 +5419,20 @@ binlog: } VOID(pthread_mutex_unlock(&LOCK_open)); - IF_DBUG(int result=) - store_create_info(thd, table, &query, - create_info, FALSE /* show_database */); + /* + The condition avoids a crash as described in BUG#48506. Other + binlogging problems related to CREATE TABLE IF NOT EXISTS LIKE + when the existing object is a view will be solved by BUG 47442. + */ + if (!table->view) + { + IF_DBUG(int result=) + store_create_info(thd, table, &query, + create_info, FALSE /* show_database */); - DBUG_ASSERT(result == 0); // store_create_info() always return 0 - write_bin_log(thd, TRUE, query.ptr(), query.length()); + DBUG_ASSERT(result == 0); // store_create_info() always return 0 + write_bin_log(thd, TRUE, query.ptr(), query.length()); + } } else // Case 1 write_bin_log(thd, TRUE, thd->query(), thd->query_length()); From 514d33c866f598c506d9dcf067ce2be164167fe9 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 27 Nov 2009 15:46:54 +0200 Subject: [PATCH 094/344] Addendum to Bug #27884: fixed test incompatibility on windows. --- mysql-test/t/mysql.test | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 0cdb0ddb653..dcdf3eeaeb6 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -359,7 +359,10 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug31060.sql; # # Bug #27884: mysql --html does not quote HTML special characters in output # ---exec $MYSQL --html test -e "select '< & >' as \`<\`" +--write_file $MYSQLTEST_VARDIR/tmp/bug27884.sql +SELECT '< & >' AS `<`; +EOF +--exec $MYSQL --html test < $MYSQLTEST_VARDIR/tmp/bug27884.sql --echo --echo End of 5.0 tests From 88893ddfe5b598321ea67892df61ff6d728bf526 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 27 Nov 2009 17:55:08 +0400 Subject: [PATCH 095/344] Fixes for bug47671.test: - embedded server doesn't support external clients - removed unnecessary command line options --- mysql-test/t/bug47671.test | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/bug47671.test b/mysql-test/t/bug47671.test index 3efff39ff58..df5b4586dc0 100644 --- a/mysql-test/t/bug47671.test +++ b/mysql-test/t/bug47671.test @@ -1,6 +1,9 @@ +# Embedded server doesn't support external clients +--source include/not_embedded.inc + --echo # --echo # Bug#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39 --echo # --echo # Extract only charset information from 'status' command output using regex --replace_regex /.*mysql.*// /Connection.*// /Current.*// /SSL.*// /Using.*// /Server version.*// /Protocol.*// /UNIX.*// /Uptime.*// /Threads.*// ---exec $MYSQL -u root test -e "status"; +--exec $MYSQL -e "status"; From d877f0a04575982c4a813b831b8c74b80cccf770 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 27 Nov 2009 16:36:22 +0200 Subject: [PATCH 096/344] added the missing remove of the temp file --- mysql-test/t/mysql.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index dcdf3eeaeb6..d213e031d18 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -364,5 +364,6 @@ SELECT '< & >' AS `<`; EOF --exec $MYSQL --html test < $MYSQLTEST_VARDIR/tmp/bug27884.sql --echo +remove_file $MYSQLTEST_VARDIR/tmp/bug27884.sql; --echo End of 5.0 tests From b7ed14638fd36d68d2fbabb861e5467d6751cbab Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 27 Nov 2009 18:07:31 +0200 Subject: [PATCH 097/344] Addendum to bug #48872: disable output in the test case because errors are dependent on the case mode --- mysql-test/r/sp-security.result | 5 ----- mysql-test/t/sp-security.test | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index 17758218e35..1451f8e88fd 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -558,15 +558,10 @@ SELECT F_TEST(); F_TEST() 123 SELECT * FROM TestTab; -ERROR 42000: SELECT command denied to user 'Tester'@'localhost' for table 'TestTab' SELECT `f_Test`(); -ERROR 42000: execute command denied to user 'Tester'@'%' for routine 'B48872.f_Test' SELECT `F_TEST`(); -ERROR 42000: execute command denied to user 'Tester'@'%' for routine 'B48872.f_Test' SELECT f_Test(); -ERROR 42000: execute command denied to user 'Tester'@'%' for routine 'B48872.f_Test' SELECT F_TEST(); -ERROR 42000: execute command denied to user 'Tester'@'%' for routine 'B48872.f_Test' SELECT `f_Test_denied`(); `f_Test_denied`() 123 diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index 42c8ecd85ec..3d41d90404d 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -921,6 +921,7 @@ SELECT F_TEST(); CONNECTION con_tester_denied; +--disable_result_log --error ER_TABLEACCESS_DENIED_ERROR SELECT * FROM TestTab; --error ER_PROCACCESS_DENIED_ERROR @@ -931,6 +932,7 @@ SELECT `F_TEST`(); SELECT f_Test(); --error ER_PROCACCESS_DENIED_ERROR SELECT F_TEST(); +--enable_result_log SELECT `f_Test_denied`(); SELECT `F_TEST_DENIED`(); From b9f9fe2e1a8ce599140d38cfd8f7d58b5344e36e Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 28 Nov 2009 12:43:16 +0800 Subject: [PATCH 098/344] Bug #43913 rpl_cross_version can't pass on conflicts complainig clash with --slave-load-tm The 'slave_patternload_file' is assigned to the real path of the load data file when initializing the object of Relay_log_info. But the path of the load data file is not formatted to real path when executing event from relay log. So the error will be encountered if the path of the load data file is a symbolic link. Actually the global 'opt_secure_file_priv' is not formatted to real path when loading data from file. So the same thing will happen too. To fix these errors, the path of the load data file should be formatted to real path when executing event from relay log. And the 'opt_secure_file_priv' should be formatted to real path when loading data infile. mysql-test/suite/rpl/r/rpl_loaddata_symlink.result: Test result for bug#43913. mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh: Added the test file to create a link from $MYSQLTEST_VARDIR/std_data to $MYSQLTEST_VARDIR/std_data_master_link mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh: Added the test file to create a link from $MYSQLTEST_VARDIR/std_data to $MYSQLTEST_VARDIR/std_data_slave_link mysql-test/suite/rpl/t/rpl_loaddata_symlink.test: Added the test file to verify if loading data infile will work fine if the path of the load data file is a symbolic link. sql/rpl_rli.cc: Added call 'my_realpath' function for avoiding sometimes the 'fn_format' function can't format real path rightly. --- .../suite/rpl/r/rpl_loaddata_symlink.result | 17 ++++++++++++++++ .../rpl/t/rpl_loaddata_symlink-master.opt | 1 + .../rpl/t/rpl_loaddata_symlink-master.sh | 1 + .../rpl/t/rpl_loaddata_symlink-slave.opt | 1 + .../suite/rpl/t/rpl_loaddata_symlink-slave.sh | 1 + .../suite/rpl/t/rpl_loaddata_symlink.test | 20 +++++++++++++++++++ sql/rpl_rli.cc | 3 ++- sql/sql_load.cc | 17 ++++++++++------ 8 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_loaddata_symlink.result create mode 100644 mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt create mode 100644 mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh create mode 100644 mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt create mode 100644 mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh create mode 100644 mysql-test/suite/rpl/t/rpl_loaddata_symlink.test diff --git a/mysql-test/suite/rpl/r/rpl_loaddata_symlink.result b/mysql-test/suite/rpl/r/rpl_loaddata_symlink.result new file mode 100644 index 00000000000..c7806f5ecce --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_loaddata_symlink.result @@ -0,0 +1,17 @@ +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 not null auto_increment, b int, primary key(a) ); +load data infile '../../std_data/rpl_loaddata.dat' into table t1; +select * from t1; +a b +1 10 +2 15 +select * from t1; +a b +1 10 +2 15 +drop table t1; diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt new file mode 100644 index 00000000000..719832a2862 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt @@ -0,0 +1 @@ +--secure-file-priv=$MYSQLTEST_VARDIR/std_data_master_link diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh new file mode 100644 index 00000000000..066f72926af --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh @@ -0,0 +1 @@ +ln -s $MYSQLTEST_VARDIR/std_data $MYSQLTEST_VARDIR/std_data_master_link diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt new file mode 100644 index 00000000000..a112e81a714 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt @@ -0,0 +1 @@ +--slave-load-tmpdir=$MYSQLTEST_VARDIR/std_data_slave_link diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh new file mode 100644 index 00000000000..218209a2542 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh @@ -0,0 +1 @@ +ln -s $MYSQLTEST_VARDIR/std_data $MYSQLTEST_VARDIR/std_data_slave_link diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink.test b/mysql-test/suite/rpl/t/rpl_loaddata_symlink.test new file mode 100644 index 00000000000..d3ee2766314 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink.test @@ -0,0 +1,20 @@ +# +# BUG#43913 +# This test verifies if loading data infile will work fine +# if the path of the load data file is a symbolic link. +# +--source include/master-slave.inc +--source include/have_binlog_format_statement.inc + +create table t1(a int not null auto_increment, b int, primary key(a) ); +load data infile '../../std_data/rpl_loaddata.dat' into table t1; +select * from t1; + +sync_slave_with_master; +connection slave; +select * from t1; + +connection master; +drop table t1; +sync_slave_with_master; + diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index a9ed736b453..a26717d7acf 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -105,7 +105,8 @@ int init_relay_log_info(Relay_log_info* rli, rli->tables_to_lock_count= 0; char pattern[FN_REFLEN]; - if (fn_format(pattern, PREFIX_SQL_LOAD, slave_load_tmpdir, "", + (void) my_realpath(pattern, slave_load_tmpdir, 0); + if (fn_format(pattern, PREFIX_SQL_LOAD, pattern, "", MY_SAFE_PATH | MY_RETURN_REAL_PATH) == NullS) { pthread_mutex_unlock(&rli->data_lock); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 5500439b619..8109ca4313e 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -304,7 +304,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, else { (void) fn_format(name, ex->file_name, mysql_real_data_home, "", - MY_RELATIVE_PATH | MY_UNPACK_FILENAME); + MY_RELATIVE_PATH | MY_UNPACK_FILENAME | + MY_RETURN_REAL_PATH); #if !defined(__WIN__) && ! defined(__NETWARE__) MY_STAT stat_info; if (!my_stat(name,&stat_info,MYF(MY_WME))) @@ -347,12 +348,16 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, DBUG_ASSERT(FALSE); #endif } - else if (opt_secure_file_priv && - strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv))) + else if (opt_secure_file_priv) { - /* Read only allowed from within dir specified by secure_file_priv */ - my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv"); - DBUG_RETURN(TRUE); + char secure_file_real_path[FN_REFLEN]; + (void) my_realpath(secure_file_real_path, opt_secure_file_priv, 0); + if (strncmp(secure_file_real_path, name, strlen(secure_file_real_path))) + { + /* Read only allowed from within dir specified by secure_file_priv */ + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv"); + DBUG_RETURN(TRUE); + } } } From 181a29f20ac077aca69bee493eab946c6fb444f2 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 10:54:26 +0530 Subject: [PATCH 099/344] Additional Fix for BUG#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39 Fix for failure on windows PB2 because of the result content mismatch. In windows additional information about TCP port was causing failures. Added to regex. --- mysql-test/t/bug47671.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/bug47671.test b/mysql-test/t/bug47671.test index df5b4586dc0..c3f66a9f502 100644 --- a/mysql-test/t/bug47671.test +++ b/mysql-test/t/bug47671.test @@ -5,5 +5,5 @@ --echo # Bug#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39 --echo # --echo # Extract only charset information from 'status' command output using regex ---replace_regex /.*mysql.*// /Connection.*// /Current.*// /SSL.*// /Using.*// /Server version.*// /Protocol.*// /UNIX.*// /Uptime.*// /Threads.*// +--replace_regex /.*mysql.*// /Connection.*// /Current.*// /SSL.*// /Using.*// /Server version.*// /Protocol.*// /UNIX.*// /Uptime.*// /Threads.*// /TCP.*// --exec $MYSQL -e "status"; From ca79b2bcb96119fc49d025f26cb2bc87608afdb9 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 13:56:45 +0530 Subject: [PATCH 100/344] Applying InnoDB snapshot 5.1-ss6242, part 1. Fixes BUG#32430 1. BUG#32430 - 'show innodb status' causes errors Invalid (old?) table or database name in logs 2. White space fixup Detailed revision comments: r6136 | marko | 2009-11-04 12:28:10 +0200 (Wed, 04 Nov 2009) | 15 lines branches/5.1: Port r6134 from branches/zip: ------------------------------------------------------------------------ r6134 | marko | 2009-11-04 07:57:29 +0000 (Wed, 04 Nov 2009) | 5 lines branches/zip: innobase_convert_identifier(): Convert table names with explain_filename() to address Bug #32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs. rb://134 approved by Sunny Bains ------------------------------------------------------------------------ innobase_print_identifier(): Replace with innobase_convert_name(). innobase_convert_identifier(): New function, called by innobase_convert_name(). r6152 | vasil | 2009-11-10 15:30:20 +0200 (Tue, 10 Nov 2009) | 4 lines branches/5.1: White space fixup. --- storage/innobase/handler/ha_innodb.cc | 179 ++++++++++++++++------- storage/innobase/include/ha_prototypes.h | 25 ++-- storage/innobase/ut/ut0ut.c | 28 ++-- 3 files changed, 152 insertions(+), 80 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 41d76c5ec55..784cbb6536f 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1499,70 +1499,148 @@ innobase_invalidate_query_cache( #endif } -/********************************************************************* -Display an SQL identifier. */ -extern "C" -void -innobase_print_identifier( -/*======================*/ - FILE* f, /* in: output stream */ - trx_t* trx, /* in: transaction */ - ibool table_id,/* in: TRUE=print a table name, - FALSE=print other identifier */ - const char* name, /* in: name to print */ - ulint namelen)/* in: length of name */ +/*****************************************************************//** +Convert an SQL identifier to the MySQL system_charset_info (UTF-8) +and quote it if needed. +@return pointer to the end of buf */ +static +char* +innobase_convert_identifier( +/*========================*/ + char* buf, /*!< out: buffer for converted identifier */ + ulint buflen, /*!< in: length of buf, in bytes */ + const char* id, /*!< in: identifier to convert */ + ulint idlen, /*!< in: length of id, in bytes */ + void* thd, /*!< in: MySQL connection thread, or NULL */ + ibool file_id)/*!< in: TRUE=id is a table or database name; + FALSE=id is an UTF-8 string */ { - const char* s = name; - char* qname = NULL; + char nz[NAME_LEN + 1]; +#if MYSQL_VERSION_ID >= 50141 + char nz2[NAME_LEN + 1 + EXPLAIN_FILENAME_MAX_EXTRA_LENGTH]; +#else /* MYSQL_VERSION_ID >= 50141 */ + char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix]; +#endif /* MYSQL_VERSION_ID >= 50141 */ + + const char* s = id; int q; - if (table_id) { - /* Decode the table name. The filename_to_tablename() - function expects a NUL-terminated string. The input and - output strings buffers must not be shared. The function - only produces more output when the name contains other - characters than [0-9A-Z_a-z]. */ - char* temp_name = (char*) my_malloc((uint) namelen + 1, MYF(MY_WME)); - uint qnamelen = (uint) (namelen - + (1 + sizeof srv_mysql50_table_name_prefix)); + if (file_id) { + /* Decode the table name. The MySQL function expects + a NUL-terminated string. The input and output strings + buffers must not be shared. */ - if (temp_name) { - qname = (char*) my_malloc(qnamelen, MYF(MY_WME)); - if (qname) { - memcpy(temp_name, name, namelen); - temp_name[namelen] = 0; - s = qname; - namelen = filename_to_tablename(temp_name, - qname, qnamelen); - } - my_free(temp_name, MYF(0)); + if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) { + idlen = (sizeof nz) - 1; } + + memcpy(nz, id, idlen); + nz[idlen] = 0; + + s = nz2; +#if MYSQL_VERSION_ID >= 50141 + idlen = explain_filename((THD*) thd, nz, nz2, sizeof nz2, + EXPLAIN_PARTITIONS_AS_COMMENT); + goto no_quote; +#else /* MYSQL_VERSION_ID >= 50141 */ + idlen = filename_to_tablename(nz, nz2, sizeof nz2); +#endif /* MYSQL_VERSION_ID >= 50141 */ } - if (!trx || !trx->mysql_thd) { - + /* See if the identifier needs to be quoted. */ + if (UNIV_UNLIKELY(!thd)) { q = '"'; } else { - q = get_quote_char_for_identifier((THD*) trx->mysql_thd, - s, (int) namelen); + q = get_quote_char_for_identifier((THD*) thd, s, (int) idlen); } if (q == EOF) { - fwrite(s, 1, namelen, f); - } else { - const char* e = s + namelen; - putc(q, f); - while (s < e) { - int c = *s++; - if (c == q) { - putc(c, f); - } - putc(c, f); +#if MYSQL_VERSION_ID >= 50141 +no_quote: +#endif /* MYSQL_VERSION_ID >= 50141 */ + if (UNIV_UNLIKELY(idlen > buflen)) { + idlen = buflen; } - putc(q, f); + memcpy(buf, s, idlen); + return(buf + idlen); } - my_free(qname, MYF(MY_ALLOW_ZERO_PTR)); + /* Quote the identifier. */ + if (buflen < 2) { + return(buf); + } + + *buf++ = q; + buflen--; + + for (; idlen; idlen--) { + int c = *s++; + if (UNIV_UNLIKELY(c == q)) { + if (UNIV_UNLIKELY(buflen < 3)) { + break; + } + + *buf++ = c; + *buf++ = c; + buflen -= 2; + } else { + if (UNIV_UNLIKELY(buflen < 2)) { + break; + } + + *buf++ = c; + buflen--; + } + } + + *buf++ = q; + return(buf); +} + +/*****************************************************************//** +Convert a table or index name to the MySQL system_charset_info (UTF-8) +and quote it if needed. +@return pointer to the end of buf */ +extern "C" +char* +innobase_convert_name( +/*==================*/ + char* buf, /*!< out: buffer for converted identifier */ + ulint buflen, /*!< in: length of buf, in bytes */ + const char* id, /*!< in: identifier to convert */ + ulint idlen, /*!< in: length of id, in bytes */ + void* thd, /*!< in: MySQL connection thread, or NULL */ + ibool table_id)/*!< in: TRUE=id is a table or database name; + FALSE=id is an index name */ +{ + char* s = buf; + const char* bufend = buf + buflen; + + if (table_id) { + const char* slash = (const char*) memchr(id, '/', idlen); + if (!slash) { + + goto no_db_name; + } + + /* Print the database name and table name separately. */ + s = innobase_convert_identifier(s, bufend - s, id, slash - id, + thd, TRUE); + if (UNIV_LIKELY(s < bufend)) { + *s++ = '.'; + s = innobase_convert_identifier(s, bufend - s, + slash + 1, idlen + - (slash - id) - 1, + thd, TRUE); + } + } else { +no_db_name: + s = innobase_convert_identifier(buf, buflen, id, idlen, + thd, table_id); + } + + return(s); + } /************************************************************************** @@ -8194,8 +8272,7 @@ innobase_xa_prepare( executing XA PREPARE and XA COMMIT commands. In this case we cannot know how many minutes or hours will be between XA PREPARE and XA COMMIT, and we don't want - to block for undefined period of time. - */ + to block for undefined period of time. */ pthread_mutex_lock(&prepare_commit_mutex); trx->active_trans = 2; } diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 6bfc43579b3..ce790814818 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -24,18 +24,21 @@ innobase_convert_string( CHARSET_INFO* from_cs, uint* errors); -/********************************************************************* -Display an SQL identifier. */ +/*****************************************************************//** +Convert a table or index name to the MySQL system_charset_info (UTF-8) +and quote it if needed. +@return pointer to the end of buf */ -void -innobase_print_identifier( -/*======================*/ - FILE* f, /* in: output stream */ - trx_t* trx, /* in: transaction */ - ibool table_id,/* in: TRUE=print a table name, - FALSE=print other identifier */ - const char* name, /* in: name to print */ - ulint namelen);/* in: length of name */ +char* +innobase_convert_name( +/*==================*/ + char* buf, /*!< out: buffer for converted identifier */ + ulint buflen, /*!< in: length of buf, in bytes */ + const char* id, /*!< in: identifier to convert */ + ulint idlen, /*!< in: length of id, in bytes */ + void* thd, /*!< in: MySQL connection thread, or NULL */ + ibool table_id);/*!< in: TRUE=id is a table or database name; + FALSE=id is an index name */ /********************************************************************** Returns true if the thread is the replication thread on the slave diff --git a/storage/innobase/ut/ut0ut.c b/storage/innobase/ut/ut0ut.c index 6b5bcef1830..3b26d83bbb9 100644 --- a/storage/innobase/ut/ut0ut.c +++ b/storage/innobase/ut/ut0ut.c @@ -19,6 +19,7 @@ Created 5/11/1994 Heikki Tuuri #include "ut0sort.h" #include "trx0trx.h" #include "ha_prototypes.h" +#include "mysql_com.h" /* NAME_LEN */ ibool ut_always_false = FALSE; @@ -484,26 +485,17 @@ ut_print_namel( const char* name, /* in: name to print */ ulint namelen)/* in: length of name */ { -#ifdef UNIV_HOTBACKUP - fwrite(name, 1, namelen, f); -#else - if (table_id) { - char* slash = memchr(name, '/', namelen); - if (!slash) { + /* 2 * NAME_LEN for database and table name, + and some slack for the #mysql50# prefix and quotes */ + char buf[3 * NAME_LEN]; + const char* bufend; - goto no_db_name; - } + bufend = innobase_convert_name(buf, sizeof buf, + name, namelen, + trx ? trx->mysql_thd : NULL, + table_id); - /* Print the database name and table name separately. */ - innobase_print_identifier(f, trx, TRUE, name, slash - name); - putc('.', f); - innobase_print_identifier(f, trx, TRUE, slash + 1, - namelen - (slash - name) - 1); - } else { -no_db_name: - innobase_print_identifier(f, trx, table_id, name, namelen); - } -#endif + fwrite(buf, 1, bufend - buf, f); } /************************************************************************** From 188875062769e053970ae8b33649488fbcd94dae Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 14:10:31 +0530 Subject: [PATCH 101/344] Applying InnoDB snapshot 5.1-ss6242, part 2. Fixes BUG#3139 1. BUG#3139 - Mysql crashes: "windows error 995" after several selects on a large DB Detailed revision comments: r6154 | calvin | 2009-11-11 02:51:17 +0200 (Wed, 11 Nov 2009) | 17 lines branches/5.1: fix bug#3139: Mysql crashes: 'windows error 995' after several selects on a large DB During stress environment, Windows AIO may fail with error code ERROR_OPERATION_ABORTED. InnoDB does not handle the error, rather crashes. The cause of the error is unknown, but likely due to faulty hardware or driver. This patch introduces a new error code OS_FILE_OPERATION_ABORTED, which maps to Windows ERROR_OPERATION_ABORTED (995). When the error is detected during AIO, the InnoDB will issue a synchronous retry (read/write). This patch has been extensively tested by MySQL support. Approved by: Marko rb://196 --- storage/innobase/include/os0file.h | 2 ++ storage/innobase/os/os0file.c | 54 +++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 9eb44d3f4a8..e09e1e00408 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -96,6 +96,8 @@ log. */ to become available again */ #define OS_FILE_SHARING_VIOLATION 76 #define OS_FILE_ERROR_NOT_SPECIFIED 77 + /* 78 is used in the plugin */ +#define OS_FILE_OPERATION_ABORTED 79 /* Types for aio operations */ #define OS_FILE_READ 10 diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index 8fd959512c1..085f62daacc 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -257,6 +257,13 @@ os_file_get_last_error( " software or another instance\n" "InnoDB: of MySQL." " Please close it to get rid of this error.\n"); + } else if (err == ERROR_OPERATION_ABORTED) { + fprintf(stderr, + "InnoDB: The error means that the I/O" + " operation has been aborted\n" + "InnoDB: because of either a thread exit" + " or an application request.\n" + "InnoDB: Retry attempt is made.\n"); } else { fprintf(stderr, "InnoDB: Some operating system error numbers" @@ -278,6 +285,8 @@ os_file_get_last_error( } else if (err == ERROR_SHARING_VIOLATION || err == ERROR_LOCK_VIOLATION) { return(OS_FILE_SHARING_VIOLATION); + } else if (err == ERROR_OPERATION_ABORTED) { + return(OS_FILE_OPERATION_ABORTED); } else { return(100 + err); } @@ -402,6 +411,10 @@ os_file_handle_error_cond_exit( os_thread_sleep(10000000); /* 10 sec */ return(TRUE); + } else if (err == OS_FILE_OPERATION_ABORTED) { + + os_thread_sleep(100000); /* 100 ms */ + return(TRUE); } else { if (name) { fprintf(stderr, "InnoDB: File name %s\n", name); @@ -3692,6 +3705,7 @@ os_aio_windows_handle( ibool ret_val; BOOL ret; DWORD len; + BOOL retry = FALSE; if (segment == ULINT_UNDEFINED) { array = os_aio_sync_array; @@ -3745,14 +3759,52 @@ os_aio_windows_handle( ut_a(TRUE == os_file_flush(slot->file)); } # endif /* UNIV_DO_FLUSH */ + } else if (os_file_handle_error(slot->name, "Windows aio")) { + + retry = TRUE; } else { - os_file_handle_error(slot->name, "Windows aio"); ret_val = FALSE; } os_mutex_exit(array->mutex); + if (retry) { + /* retry failed read/write operation synchronously. + No need to hold array->mutex. */ + + switch (slot->type) { + case OS_FILE_WRITE: + ret = WriteFile(slot->file, slot->buf, + slot->len, &len, + &(slot->control)); + + break; + case OS_FILE_READ: + ret = ReadFile(slot->file, slot->buf, + slot->len, &len, + &(slot->control)); + + break; + default: + ut_error; + } + + if (!ret && GetLastError() == ERROR_IO_PENDING) { + /* aio was queued successfully! + We want a synchronous i/o operation on a + file where we also use async i/o: in Windows + we must use the same wait mechanism as for + async i/o */ + + ret = GetOverlappedResult(slot->file, + &(slot->control), + &len, TRUE); + } + + ret_val = ret && len == slot->len; + } + os_aio_array_free_slot(array, slot); return(ret_val); From 3431bede10e13eac085482b004aead4d4640ecfc Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 14:20:08 +0530 Subject: [PATCH 102/344] Applying InnoDB snapshot 5.1-ss6242, part 3. Fixes BUG#48469 1. BUG#4869 - when innodb tablespace is configured too small, crash and corruption! Detailed revision comments: r6187 | jyang | 2009-11-18 05:27:30 +0200 (Wed, 18 Nov 2009) | 9 lines branches/5.1: Fix bug #48469 "when innodb tablespace is configured too small, crash and corruption!". Function btr_create() did not check the return status of fseg_create(), and continue the index creation even there is no sufficient space. rb://205 Approved by Marko r6200 | vasil | 2009-11-19 12:14:23 +0200 (Thu, 19 Nov 2009) | 4 lines branches/5.1: White space fixup - indent under the opening ( r6203 | jyang | 2009-11-19 15:12:22 +0200 (Thu, 19 Nov 2009) | 8 lines branches/5.1: Use btr_free_root() instead of fseg_free() for the fix of bug #48469, because fseg_free() is not defined in the zip branch. And we could save one mini-trasaction started by fseg_free(). Approved by Marko. --- storage/innobase/btr/btr0btr.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index 6e8b43aeb8d..5e8831b5d5e 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/innobase/btr/btr0btr.c @@ -709,8 +709,15 @@ btr_create( } else { /* It is a non-ibuf tree: create a file segment for leaf pages */ - fseg_create(space, page_no, PAGE_HEADER + PAGE_BTR_SEG_LEAF, - mtr); + if (!fseg_create(space, page_no, + PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { + /* Not enough space for new segment, free root + segment before return. */ + btr_free_root(space, page_no, mtr); + + return(FIL_NULL); + } + /* The fseg create acquires a second latch on the page, therefore we must declare it: */ #ifdef UNIV_SYNC_DEBUG From 2df31d44e14976291fdb7383af9dcd97122a3eae Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 14:23:52 +0530 Subject: [PATCH 103/344] Applying InnoDB snapshot 5.1-ss6242, part 4. Fixes BUG#48526 1. BUG#48526 - Data type for float and double is incorrectly reported in InnoDB table monitor Detailed revision comments: r6188 | jyang | 2009-11-18 07:14:23 +0200 (Wed, 18 Nov 2009) | 8 lines branches/5.1: Fix bug #48526 "Data type for float and double is incorrectly reported in InnoDB table monitor". Certain datatypes are not printed correctly in dtype_print(). rb://204 Approved by Marko. --- storage/innobase/data/data0type.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/storage/innobase/data/data0type.c b/storage/innobase/data/data0type.c index 305000d7c0a..a3cfe691404 100644 --- a/storage/innobase/data/data0type.c +++ b/storage/innobase/data/data0type.c @@ -252,6 +252,22 @@ dtype_print( fputs("DATA_SYS", stderr); break; + case DATA_FLOAT: + fputs("DATA_FLOAT", stderr); + break; + + case DATA_DOUBLE: + fputs("DATA_DOUBLE", stderr); + break; + + case DATA_DECIMAL: + fputs("DATA_DECIMAL", stderr); + break; + + case DATA_VARMYSQL: + fputs("DATA_VARMYSQL", stderr); + break; + default: fprintf(stderr, "type %lu", (ulong) mtype); break; From 96a121d35d1a6d76c3d2e242a46d3f2511bce36c Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 14:33:57 +0530 Subject: [PATCH 104/344] Applying InnoDB snapshot 5.1-ss6242, part 5. Fixes BUG#45961 1. BUG#45961 - DDL on partitioned innodb tables leaves data dictionary in an inconsistent state 2. Fix formatting Detailed revision comments: r6205 | jyang | 2009-11-20 07:55:48 +0200 (Fri, 20 Nov 2009) | 11 lines branches/5.1: Add a special case to handle the Duplicated Key error and return DB_ERROR instead. This is to avoid a possible SIGSEGV by mysql error handling re-entering the storage layer for dup key info without proper table handle. This is to prevent a server crash when error situation in bug #45961 "DDL on partitioned innodb tables leaves data dictionary in an inconsistent state" happens. rb://157 approved by Sunny Bains. r6206 | jyang | 2009-11-20 09:38:43 +0200 (Fri, 20 Nov 2009) | 3 lines branches/5.1: Non-functional change, fix formatting. --- storage/innobase/handler/ha_innodb.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 784cbb6536f..55c335e25b1 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -662,6 +662,12 @@ convert_error_code_to_mysql( } else if (error == (int) DB_DUPLICATE_KEY) { + /* Be cautious with returning this error, since + mysql could re-enter the storage layer to get + duplicated key info, the operation requires a + valid table handle and/or transaction information, + which might not always be available in the error + handling stage. */ return(HA_ERR_FOUND_DUPP_KEY); } else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) { @@ -6038,6 +6044,24 @@ ha_innobase::rename_table( innobase_commit_low(trx); trx_free_for_mysql(trx); + /* Add a special case to handle the Duplicated Key error + and return DB_ERROR instead. + This is to avoid a possible SIGSEGV error from mysql error + handling code. Currently, mysql handles the Duplicated Key + error by re-entering the storage layer and getting dup key + info by calling get_dup_key(). This operation requires a valid + table handle ('row_prebuilt_t' structure) which could no + longer be available in the error handling stage. The suggested + solution is to report a 'table exists' error message (since + the dup key error here is due to an existing table whose name + is the one we are trying to rename to) and return the generic + error code. */ + if (error == (int) DB_DUPLICATE_KEY) { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to); + + error = DB_ERROR; + } + error = convert_error_code_to_mysql(error, NULL); DBUG_RETURN(error); From 2faa75ed26bbd0644775907e9a959a17ad4e4ff6 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 14:38:41 +0530 Subject: [PATCH 105/344] Applying InnoDB snapshot 5.1-ss6242, part 6. Fixes BUG#48482 1. BUG#48482 - innodb-autoinc.test fails with results difference 2. enable the disabled test Detailed revision comments: r6230 | sunny | 2009-11-24 23:52:43 +0200 (Tue, 24 Nov 2009) | 3 lines branches/5.1: Fix autoinc failing test results. (this should be skipped when merging 5.1 into zip) --- mysql-test/r/innodb-autoinc.result | 8 ++++---- mysql-test/t/disabled.def | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index a40a13dbe9f..abb8f3da072 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -875,11 +875,11 @@ ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; SELECT * FROM t1; d1 1 -3 +2 SELECT * FROM t1; d1 1 -3 +2 INSERT INTO t1 VALUES(null); Got one of the listed errors ALTER TABLE t1 AUTO_INCREMENT = 3; @@ -888,13 +888,13 @@ Table Create Table t1 CREATE TABLE `t1` ( `d1` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`d1`) -) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 INSERT INTO t1 VALUES(null); SELECT * FROM t1; d1 1 +2 3 -4 DROP TABLE t1; SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; SHOW VARIABLES LIKE "%auto_inc%"; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index ad7617b9403..ac89c1493cd 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -13,5 +13,4 @@ kill : Bug#37780 2008-12-03 HHunger need some changes to be query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes -innodb-autoinc : Bug#48482 2009-11-02 svoj innodb-autoinc.test fails with results difference rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2 From 4b3114b60d10e4cedb0c98fe06f7e2ff023c3dbd Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 15:11:38 +0530 Subject: [PATCH 106/344] Applying InnoDB snapshot 5.1-ss6242, part 7. Fixes BUG#49032 1. BUG#49032 - auto_increment field does not initialize to last value in InnoDB Storage Engine 2. Fix whitespace issues and fix tests and make read float/double arg const Detailed revision comments: r6231 | sunny | 2009-11-25 10:26:27 +0200 (Wed, 25 Nov 2009) | 7 lines branches/5.1: Fix BUG#49032 - auto_increment field does not initialize to last value in InnoDB Storage Engine. We use the appropriate function to read the column value for non-integer autoinc column types, namely float and double. rb://208. Approved by Marko. r6232 | sunny | 2009-11-25 10:27:39 +0200 (Wed, 25 Nov 2009) | 2 lines branches/5.1: This is an interim fix, fix white space errors. r6233 | sunny | 2009-11-25 10:28:35 +0200 (Wed, 25 Nov 2009) | 2 lines branches/5.1: This is an interim fix, fix tests and make read float/double arg const. r6234 | sunny | 2009-11-25 10:29:03 +0200 (Wed, 25 Nov 2009) | 2 lines branches/5.1: This is an interim fix, fix whitepsace issues. --- mysql-test/r/innodb-autoinc.result | 25 +++++++++++++++++++++++++ mysql-test/t/innodb-autoinc.test | 19 +++++++++++++++++++ storage/innobase/include/mach0data.h | 8 ++++---- storage/innobase/include/mach0data.ic | 8 ++++---- storage/innobase/row/row0sel.c | 25 ++++++++++++++++++++++--- 5 files changed, 74 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index abb8f3da072..ea759ec328c 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -1126,3 +1126,28 @@ SELECT * FROM T1; c1 c2 10 0 DROP TABLE T1; +DROP TABLE IF EXISTS T1; +Warnings: +Note 1051 Unknown table 'T1' +CREATE TABLE T1(C1 DOUBLE AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +INSERT INTO T1(C2) VALUES ('innodb'); +SHOW CREATE TABLE T1; +Table Create Table +T1 CREATE TABLE `T1` ( + `C1` double NOT NULL AUTO_INCREMENT, + `C2` char(10) DEFAULT NULL, + PRIMARY KEY (`C1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +DROP TABLE T1; +CREATE TABLE T1(C1 FLOAT AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +INSERT INTO T1(C2) VALUES ('innodb'); +SHOW CREATE TABLE T1; +Table Create Table +T1 CREATE TABLE `T1` ( + `C1` float NOT NULL AUTO_INCREMENT, + `C2` char(10) DEFAULT NULL, + PRIMARY KEY (`C1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +DROP TABLE T1; diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index 3f45bb9d003..468f345724f 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -620,3 +620,22 @@ SHOW CREATE TABLE T1; INSERT INTO T1 (c2) values (0); SELECT * FROM T1; DROP TABLE T1; + +## +# 49032: Use the correct function to read the AUTOINC column value +# +DROP TABLE IF EXISTS T1; +CREATE TABLE T1(C1 DOUBLE AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +# Restart the server +-- source include/restart_mysqld.inc +INSERT INTO T1(C2) VALUES ('innodb'); +SHOW CREATE TABLE T1; +DROP TABLE T1; +CREATE TABLE T1(C1 FLOAT AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +# Restart the server +-- source include/restart_mysqld.inc +INSERT INTO T1(C2) VALUES ('innodb'); +SHOW CREATE TABLE T1; +DROP TABLE T1; diff --git a/storage/innobase/include/mach0data.h b/storage/innobase/include/mach0data.h index 25b619b3f12..d6e040ba9ca 100644 --- a/storage/innobase/include/mach0data.h +++ b/storage/innobase/include/mach0data.h @@ -266,8 +266,8 @@ UNIV_INLINE double mach_double_read( /*=============*/ - /* out: double read */ - byte* b); /* in: pointer to memory from where to read */ + /* out: double read */ + const byte* b); /* in: pointer to memory from where to read */ /************************************************************* Writes a double. It is stored in a little-endian format. */ UNIV_INLINE @@ -282,8 +282,8 @@ UNIV_INLINE float mach_float_read( /*============*/ - /* out: float read */ - byte* b); /* in: pointer to memory from where to read */ + /* out: float read */ + const byte* b); /* in: pointer to memory from where to read */ /************************************************************* Writes a float. It is stored in a little-endian format. */ UNIV_INLINE diff --git a/storage/innobase/include/mach0data.ic b/storage/innobase/include/mach0data.ic index ec15c10c661..dc7918c287b 100644 --- a/storage/innobase/include/mach0data.ic +++ b/storage/innobase/include/mach0data.ic @@ -504,8 +504,8 @@ UNIV_INLINE double mach_double_read( /*=============*/ - /* out: double read */ - byte* b) /* in: pointer to memory from where to read */ + /* out: double read */ + const byte* b) /* in: pointer to memory from where to read */ { double d; ulint i; @@ -553,8 +553,8 @@ UNIV_INLINE float mach_float_read( /*============*/ - /* out: float read */ - byte* b) /* in: pointer to memory from where to read */ + /* out: float read */ + const byte* b) /* in: pointer to memory from where to read */ { float d; ulint i; diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 1746fb39f43..38902bca905 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -4514,6 +4514,7 @@ row_search_autoinc_read_column( dict_index_t* index, /* in: index to read from */ const rec_t* rec, /* in: current rec */ ulint col_no, /* in: column number */ + ulint mtype, /*!< in: column main type */ ibool unsigned_type) /* in: signed or unsigned flag */ { ulint len; @@ -4535,9 +4536,26 @@ row_search_autoinc_read_column( data = rec_get_nth_field((rec_t*)rec, offsets, col_no, &len); ut_a(len != UNIV_SQL_NULL); - ut_a(len <= sizeof value); - value = mach_read_int_type(data, len, unsigned_type); + switch (mtype) { + case DATA_INT: + ut_a(len <= sizeof value); + value = mach_read_int_type(data, len, unsigned_type); + break; + + case DATA_FLOAT: + ut_a(len == sizeof(float)); + value = mach_float_read(data); + break; + + case DATA_DOUBLE: + ut_a(len == sizeof(double)); + value = mach_double_read(data); + break; + + default: + ut_error; + } if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -4625,7 +4643,8 @@ row_search_max_autoinc( dfield->col->prtype & DATA_UNSIGNED); *value = row_search_autoinc_read_column( - index, rec, i, unsigned_type); + index, rec, i, + dfield->col->mtype, unsigned_type); } } From cde05f0645cb3912bf7739c1bc8e0c8595b8a6b9 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 15:16:45 +0530 Subject: [PATCH 107/344] Applying InnoDB snapshot 5.1-ss6242, part 8. Fixes BUG#47720 1. BUG#47720 - REPLACE INTO Autoincrement column with negative values. Detailed revision comments: r6235 | sunny | 2009-11-26 01:14:42 +0200 (Thu, 26 Nov 2009) | 9 lines branches/5.1: Fix Bug#47720 - REPLACE INTO Autoincrement column with negative values. This bug is similiar to the negative autoinc filter patch from earlier, with the additional handling of filtering out the negative column values set explicitly by the user. rb://184 Approved by Heikki. --- mysql-test/r/innodb-autoinc.result | 39 +++++++++++++++++++++++++++ mysql-test/t/innodb-autoinc.test | 18 +++++++++++++ storage/innobase/handler/ha_innodb.cc | 29 +++++++++++--------- 3 files changed, 74 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index ea759ec328c..2e0d2c1d776 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -1151,3 +1151,42 @@ T1 CREATE TABLE `T1` ( PRIMARY KEY (`C1`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 DROP TABLE T1; +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1 (c1 INT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 SET c1 = 1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 +INSERT INTO t1 SET c1 = 2; +INSERT INTO t1 SET c1 = -1; +SELECT * FROM t1; +c1 +-1 +1 +2 +INSERT INTO t1 SET c1 = -1; +Got one of the listed errors +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +REPLACE INTO t1 VALUES (-1); +SELECT * FROM t1; +c1 +-1 +1 +2 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index 468f345724f..4fa5ab022ad 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -639,3 +639,21 @@ INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); INSERT INTO T1(C2) VALUES ('innodb'); SHOW CREATE TABLE T1; DROP TABLE T1; + +## +# 47720: REPLACE INTO Autoincrement column with negative values +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (c1 INT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 SET c1 = 1; +SHOW CREATE TABLE t1; +INSERT INTO t1 SET c1 = 2; +INSERT INTO t1 SET c1 = -1; +SELECT * FROM t1; +-- error ER_DUP_ENTRY,1062 +INSERT INTO t1 SET c1 = -1; +SHOW CREATE TABLE t1; +REPLACE INTO t1 VALUES (-1); +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 55c335e25b1..f17635c69cc 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4060,24 +4060,29 @@ no_commit: update the table upper limit. Note: last_value will be 0 if get_auto_increment() was not called.*/ - if (auto_inc <= col_max_value - && auto_inc >= prebuilt->autoinc_last_value) { + if (auto_inc >= prebuilt->autoinc_last_value) { set_max_autoinc: - ut_a(prebuilt->autoinc_increment > 0); + /* This should filter out the negative + values set explicitly by the user. */ + if (auto_inc <= col_max_value) { + ut_a(prebuilt->autoinc_increment > 0); - ulonglong need; - ulonglong offset; + ulonglong need; + ulonglong offset; - offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + offset = prebuilt->autoinc_offset; + need = prebuilt->autoinc_increment; - auto_inc = innobase_next_autoinc( - auto_inc, need, offset, col_max_value); + auto_inc = innobase_next_autoinc( + auto_inc, + need, offset, col_max_value); - err = innobase_set_max_autoinc(auto_inc); + err = innobase_set_max_autoinc( + auto_inc); - if (err != DB_SUCCESS) { - error = err; + if (err != DB_SUCCESS) { + error = err; + } } } break; From cefd968dddcbd333fad186daeebeb17ef907d154 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 16:24:20 +0530 Subject: [PATCH 108/344] Applying Innodb Snapshot 5.1-ss6242, part 9. 1. Enabling the disabled test for BUG#32430 for builtin innodb 2. Disabling the innodb-autoinc.test for innodb plugin. --- mysql-test/lib/mtr_cases.pm | 2 ++ mysql-test/t/disabled.def | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index bf73b45ecdf..1f018f27f7b 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -520,6 +520,8 @@ sub collect_one_suite($) next if ($test->{'name'} eq 'sys_vars.innodb_thread_concurrency_basic'); # Can't work with InnoPlug. Test framework needs to be re-designed. next if ($test->{'name'} eq 'main.innodb_bug46000'); + # Fails with innodb plugin + next if ($test->{'name'} eq 'main.innodb-autoinc'); # Copy test options my $new_test= My::Test->new(); while (my ($key, $value) = each(%$test)) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index ac89c1493cd..c136a2d5162 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,6 +11,5 @@ ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically -partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2 From 732e5a263444178370ab0b4c6410e138d09218e7 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Mon, 30 Nov 2009 12:30:28 +0100 Subject: [PATCH 109/344] Bug #20837 Apparent change of isolation level during transaction SET TRANSACTION ISOLATION LEVEL is used to temporarily set the trans.iso.level for the next transaction. After the transaction, the iso.level is (re-)set to value of the session variable 'tx_isolation'. The bug is caused by setting the thd->variables.tx_isolation field to the value of the session variable upon each statement commit. It should only be set at the end of the full transaction. The fix has been to remove the setting of the variable in ha_autocommit_or_rollback if we're in a transaction, as it will be correctly set in either ha_rollback or ha_commit_one_phase. If, on the other hand, we're in autocommit mode, tx_isolation will be explicitly set here. mysql-test/t/innodb_mysql.test: "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED" sets the trans.isolation for the next transaction. We test that @@tx_isolation keeps this value during the transaction, and is only reset back to the session value at the end of the transaction. --- mysql-test/r/innodb_mysql.result | 31 +++++++++++++++++++++++++++++++ mysql-test/t/innodb_mysql.test | 26 ++++++++++++++++++++++++++ sql/handler.cc | 10 ++++++++-- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 402ab3c1b16..2d93cbb47b3 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -2273,4 +2273,35 @@ END| DROP PROCEDURE p1; DROP VIEW v1; DROP TABLE t1,t2; +# +# Bug #20837 Apparent change of isolation +# level during transaction +# +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +CREATE TABLE t1 (s1 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +COMMIT; +SET @@autocommit = 0; +COMMIT; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +START TRANSACTION; +SELECT * FROM t1; +s1 +1 +2 +Should be READ UNCOMMITTED +SELECT @@tx_isolation; +@@tx_isolation +READ-UNCOMMITTED +INSERT INTO t1 VALUES (-1); +Should be READ UNCOMMITTED +SELECT @@tx_isolation; +@@tx_isolation +READ-UNCOMMITTED +COMMIT; +Should now be REPEATABLE READ +SELECT @@tx_isolation; +@@tx_isolation +REPEATABLE-READ +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index a2a1113598d..0462536371e 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -536,4 +536,30 @@ DROP PROCEDURE p1; DROP VIEW v1; DROP TABLE t1,t2; + +--echo # +--echo # Bug #20837 Apparent change of isolation +--echo # level during transaction +--echo # + +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +CREATE TABLE t1 (s1 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +COMMIT; + +SET @@autocommit = 0; +COMMIT; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +START TRANSACTION; +SELECT * FROM t1; +--echo Should be READ UNCOMMITTED +SELECT @@tx_isolation; +INSERT INTO t1 VALUES (-1); +--echo Should be READ UNCOMMITTED +SELECT @@tx_isolation; +COMMIT; +--echo Should now be REPEATABLE READ +SELECT @@tx_isolation; +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/handler.cc b/sql/handler.cc index 216228ed509..f6cdaca05bd 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1369,8 +1369,14 @@ int ha_autocommit_or_rollback(THD *thd, int error) if (thd->transaction_rollback_request && !thd->in_sub_stmt) (void) ha_rollback(thd); } - - thd->variables.tx_isolation=thd->session_tx_isolation; + } + else if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + { + /* + If we're in autocommit mode, reset tx_isolation + to the default value + */ + thd->variables.tx_isolation= thd->session_tx_isolation; } #endif DBUG_RETURN(error); From a1092e9b66c47e4077e90c2b5aa9ec49b473dcd7 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 17:02:05 +0530 Subject: [PATCH 110/344] Applying InnoDB Plugin 1.0.6 snapshot,part 1. Fixes BUG#45992 and BUG#46656 Detailed revision comments: r6130 | marko | 2009-11-02 11:42:56 +0200 (Mon, 02 Nov 2009) | 9 lines branches/zip: Free all resources at shutdown. Set pointers to NULL, so that Valgrind will not complain about freed data structures that are reachable via pointers. This addresses Bug #45992 and Bug #46656. This patch is mostly based on changes copied from branches/embedded-1.0, mainly c5432, c3439, c3134, c2994, c2978, but also some other code was copied. Some added cleanup code is specific to MySQL/InnoDB. rb://199 approved by Sunny Bains --- storage/innodb_plugin/ChangeLog | 19 +++ storage/innodb_plugin/btr/btr0sea.c | 15 +++ storage/innodb_plugin/buf/buf0buf.c | 6 +- storage/innodb_plugin/dict/dict0dict.c | 71 +++++++++++ storage/innodb_plugin/fil/fil0fil.c | 55 ++++++++- storage/innodb_plugin/ibuf/ibuf0ibuf.c | 21 ++++ storage/innodb_plugin/include/btr0sea.h | 6 + storage/innodb_plugin/include/dict0dict.h | 7 ++ storage/innodb_plugin/include/fil0fil.h | 15 +-- storage/innodb_plugin/include/ibuf0ibuf.h | 6 + storage/innodb_plugin/include/lock0lock.h | 6 + storage/innodb_plugin/include/log0log.h | 21 +++- storage/innodb_plugin/include/log0recv.h | 18 +++ storage/innodb_plugin/include/mem0mem.h | 7 ++ storage/innodb_plugin/include/mem0pool.h | 7 ++ storage/innodb_plugin/include/os0file.h | 7 ++ storage/innodb_plugin/include/pars0pars.h | 6 + storage/innodb_plugin/include/srv0srv.h | 2 +- storage/innodb_plugin/include/thr0loc.h | 6 + storage/innodb_plugin/include/trx0i_s.h | 7 ++ storage/innodb_plugin/include/trx0purge.h | 6 + storage/innodb_plugin/include/trx0rseg.h | 7 ++ storage/innodb_plugin/include/trx0sys.h | 6 + storage/innodb_plugin/include/trx0undo.h | 7 ++ storage/innodb_plugin/include/usr0sess.h | 12 +- storage/innodb_plugin/lock/lock0lock.c | 17 +++ storage/innodb_plugin/log/log0log.c | 126 ++++++++++++++++++-- storage/innodb_plugin/log/log0recv.c | 139 +++++++++++++++++++--- storage/innodb_plugin/mem/mem0dbg.c | 11 ++ storage/innodb_plugin/mem/mem0pool.c | 12 ++ storage/innodb_plugin/os/os0file.c | 57 +++++++++ storage/innodb_plugin/os/os0sync.c | 4 + storage/innodb_plugin/os/os0thread.c | 1 + storage/innodb_plugin/pars/lexyy.c | 13 ++ storage/innodb_plugin/pars/pars0lex.l | 13 ++ storage/innodb_plugin/que/que0que.c | 8 ++ storage/innodb_plugin/srv/srv0srv.c | 17 ++- storage/innodb_plugin/srv/srv0start.c | 105 ++++++++-------- storage/innodb_plugin/sync/sync0arr.c | 20 +--- storage/innodb_plugin/sync/sync0sync.c | 5 + storage/innodb_plugin/thr/thr0loc.c | 31 +++++ storage/innodb_plugin/trx/trx0i_s.c | 37 ++++++ storage/innodb_plugin/trx/trx0purge.c | 38 ++++++ storage/innodb_plugin/trx/trx0rseg.c | 43 +++++++ storage/innodb_plugin/trx/trx0sys.c | 78 ++++++++++++ storage/innodb_plugin/trx/trx0undo.c | 2 +- storage/innodb_plugin/usr/usr0sess.c | 37 +----- storage/innodb_plugin/ut/ut0mem.c | 2 + 48 files changed, 1003 insertions(+), 159 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 70225ffd9d9..7c886a8d155 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,22 @@ +2009-01-01 The InnoDB Team + + * btr/btr0sea.c, buf/buf0buf.c, dict/dict0dict.c, fil/fil0fil.c, + ibuf/ibuf0ibuf.c, include/btr0sea.h, include/dict0dict.h, + include/fil0fil.h, include/ibuf0ibuf.h, include/lock0lock.h, + include/log0log.h, include/log0recv.h, include/mem0mem.h, + include/mem0pool.h, include/os0file.h, include/pars0pars.h, + include/srv0srv.h, include/thr0loc.h, include/trx0i_s.h, + include/trx0purge.h, include/trx0rseg.h, include/trx0sys.h, + include/trx0undo.h, include/usr0sess.h, lock/lock0lock.c, + log/log0log.c, log/log0recv.c, mem/mem0dbg.c, mem/mem0pool.c, + os/os0file.c, os/os0sync.c, os/os0thread.c, pars/lexyy.c, + pars/pars0lex.l, que/que0que.c, srv/srv0srv.c, srv/srv0start.c, + sync/sync0arr.c, sync/sync0sync.c, thr/thr0loc.c, trx/trx0i_s.c, + trx/trx0purge.c, trx/trx0rseg.c, trx/trx0sys.c, trx/trx0undo.c, + usr/usr0sess.c, ut/ut0mem.c: + Fix Bug #45992 innodb memory not freed after shutdown + Fix Bug #46656 InnoDB plugin: memory leaks (Valgrind) + 2009-10-29 The InnoDB Team * handler/ha_innodb.cc, mysql-test/innodb-autoinc.result, diff --git a/storage/innodb_plugin/btr/btr0sea.c b/storage/innodb_plugin/btr/btr0sea.c index 0a80c61a58d..ef7afeb1039 100644 --- a/storage/innodb_plugin/btr/btr0sea.c +++ b/storage/innodb_plugin/btr/btr0sea.c @@ -175,6 +175,21 @@ btr_search_sys_create( btr_search_sys->hash_index = ha_create(hash_size, 0, 0); } +/*****************************************************************//** +Frees the adaptive search system at a database shutdown. */ +UNIV_INTERN +void +btr_search_sys_free(void) +/*=====================*/ +{ + mem_free(btr_search_latch_temp); + btr_search_latch_temp = NULL; + mem_heap_free(btr_search_sys->hash_index->heap); + hash_table_free(btr_search_sys->hash_index); + mem_free(btr_search_sys); + btr_search_sys = NULL; +} + /********************************************************************//** Disable the adaptive hash search system and empty the index. */ UNIV_INTERN diff --git a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c index ff31457d200..111d396fbc5 100644 --- a/storage/innodb_plugin/buf/buf0buf.c +++ b/storage/innodb_plugin/buf/buf0buf.c @@ -1020,7 +1020,11 @@ buf_pool_free(void) os_mem_free_large(chunk->mem, chunk->mem_size); } - buf_pool->n_chunks = 0; + mem_free(buf_pool->chunks); + hash_table_free(buf_pool->page_hash); + hash_table_free(buf_pool->zip_hash); + mem_free(buf_pool); + buf_pool = NULL; } /********************************************************************//** diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c index aedaf7cec1d..58ed35a4313 100644 --- a/storage/innodb_plugin/dict/dict0dict.c +++ b/storage/innodb_plugin/dict/dict0dict.c @@ -4652,6 +4652,26 @@ dict_ind_init(void) dict_ind_redundant->cached = dict_ind_compact->cached = TRUE; } +/**********************************************************************//** +Frees dict_ind_redundant and dict_ind_compact. */ +static +void +dict_ind_free(void) +/*===============*/ +{ + dict_table_t* table; + + table = dict_ind_compact->table; + dict_mem_index_free(dict_ind_compact); + dict_ind_compact = NULL; + dict_mem_table_free(table); + + table = dict_ind_redundant->table; + dict_mem_index_free(dict_ind_redundant); + dict_ind_redundant = NULL; + dict_mem_table_free(table); +} + #ifndef UNIV_HOTBACKUP /**********************************************************************//** Get index by name @@ -4777,4 +4797,55 @@ dict_table_check_for_dup_indexes( } } #endif /* UNIV_DEBUG */ + +/************************************************************************** +Closes the data dictionary module. */ +UNIV_INTERN +void +dict_close(void) +/*============*/ +{ + ulint i; + + /* Free the hash elements. We don't remove them from the table + because we are going to destroy the table anyway. */ + for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) { + dict_table_t* table; + + table = HASH_GET_FIRST(dict_sys->table_hash, i); + + while (table) { + dict_table_t* prev_table = table; + + table = HASH_GET_NEXT(name_hash, prev_table); +#ifdef UNIV_DEBUG + ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N); +#endif + /* Acquire only because it's a pre-condition. */ + mutex_enter(&dict_sys->mutex); + + dict_table_remove_from_cache(prev_table); + + mutex_exit(&dict_sys->mutex); + } + } + + hash_table_free(dict_sys->table_hash); + + /* The elements are the same instance as in dict_sys->table_hash, + therefore we don't delete the individual elements. */ + hash_table_free(dict_sys->table_id_hash); + + dict_ind_free(); + + mutex_free(&dict_sys->mutex); + + rw_lock_free(&dict_operation_lock); + memset(&dict_operation_lock, 0x0, sizeof(dict_operation_lock)); + + mutex_free(&dict_foreign_err_mutex); + + mem_free(dict_sys); + dict_sys = NULL; +} #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c index ba6f2f8666f..112a0e27d50 100644 --- a/storage/innodb_plugin/fil/fil0fil.c +++ b/storage/innodb_plugin/fil/fil0fil.c @@ -321,6 +321,17 @@ fil_get_space_id_for_table( /*=======================*/ const char* name); /*!< in: table name in the standard 'databasename/tablename' format */ +/*******************************************************************//** +Frees a space object from the tablespace memory cache. Closes the files in +the chain but does not delete them. There must not be any pending i/o's or +flushes on the files. */ +static +ibool +fil_space_free( +/*===========*/ + /* out: TRUE if success */ + ulint id, /* in: space id */ + ibool own_mutex);/* in: TRUE if own system->mutex */ /********************************************************************//** Reads data from a space to a buffer. Remember that the possible incomplete blocks at the end of file are ignored: they are not taken into account when @@ -1144,7 +1155,7 @@ try_again: mutex_exit(&fil_system->mutex); - fil_space_free(namesake_id); + fil_space_free(namesake_id, FALSE); goto try_again; } @@ -1269,17 +1280,21 @@ Frees a space object from the tablespace memory cache. Closes the files in the chain but does not delete them. There must not be any pending i/o's or flushes on the files. @return TRUE if success */ -UNIV_INTERN +static ibool fil_space_free( /*===========*/ - ulint id) /*!< in: space id */ + /* out: TRUE if success */ + ulint id, /* in: space id */ + ibool own_mutex) /* in: TRUE if own system->mutex */ { fil_space_t* space; fil_space_t* namespace; fil_node_t* fil_node; - mutex_enter(&fil_system->mutex); + if (!own_mutex) { + mutex_enter(&fil_system->mutex); + } space = fil_space_get_by_id(id); @@ -1326,7 +1341,9 @@ fil_space_free( ut_a(0 == UT_LIST_GET_LEN(space->chain)); - mutex_exit(&fil_system->mutex); + if (!own_mutex) { + mutex_exit(&fil_system->mutex); + } rw_lock_free(&(space->latch)); @@ -1586,6 +1603,8 @@ fil_close_all_files(void) space = UT_LIST_GET_FIRST(fil_system->space_list); while (space != NULL) { + fil_space_t* prev_space = space; + node = UT_LIST_GET_FIRST(space->chain); while (node != NULL) { @@ -1595,6 +1614,7 @@ fil_close_all_files(void) node = UT_LIST_GET_NEXT(chain, node); } space = UT_LIST_GET_NEXT(space_list, space); + fil_space_free(prev_space->id, TRUE); } mutex_exit(&fil_system->mutex); @@ -2226,7 +2246,7 @@ try_again: #endif /* printf("Deleting tablespace %s id %lu\n", space->name, id); */ - success = fil_space_free(id); + success = fil_space_free(id, FALSE); if (success) { success = os_file_delete(path); @@ -4753,3 +4773,26 @@ fil_page_get_type( return(mach_read_from_2(page + FIL_PAGE_TYPE)); } + +/******************************************************************** +Initializes the tablespace memory cache. */ +UNIV_INTERN +void +fil_close(void) +/*===========*/ +{ + /* The mutex should already have been freed. */ + ut_ad(fil_system->mutex.magic_n == 0); + + hash_table_free(fil_system->spaces); + + hash_table_free(fil_system->name_hash); + + ut_a(UT_LIST_GET_LEN(fil_system->LRU) == 0); + ut_a(UT_LIST_GET_LEN(fil_system->unflushed_spaces) == 0); + ut_a(UT_LIST_GET_LEN(fil_system->space_list) == 0); + + mem_free(fil_system); + + fil_system = NULL; +} diff --git a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c index 37c68391477..08986fac0ef 100644 --- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c +++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c @@ -389,6 +389,27 @@ ibuf_count_set( } #endif +/******************************************************************//** +Closes insert buffer and frees the data structures. */ +UNIV_INTERN +void +ibuf_close(void) +/*============*/ +{ + mutex_free(&ibuf_pessimistic_insert_mutex); + memset(&ibuf_pessimistic_insert_mutex, + 0x0, sizeof(ibuf_pessimistic_insert_mutex)); + + mutex_free(&ibuf_mutex); + memset(&ibuf_mutex, 0x0, sizeof(ibuf_mutex)); + + mutex_free(&ibuf_bitmap_mutex); + memset(&ibuf_bitmap_mutex, 0x0, sizeof(ibuf_mutex)); + + mem_free(ibuf); + ibuf = NULL; +} + /******************************************************************//** Updates the size information of the ibuf, assuming the segment size has not changed. */ diff --git a/storage/innodb_plugin/include/btr0sea.h b/storage/innodb_plugin/include/btr0sea.h index 631b3bd386c..f98ba386f9c 100644 --- a/storage/innodb_plugin/include/btr0sea.h +++ b/storage/innodb_plugin/include/btr0sea.h @@ -41,6 +41,12 @@ void btr_search_sys_create( /*==================*/ ulint hash_size); /*!< in: hash index hash table size */ +/*****************************************************************//** +Frees the adaptive search system at a database shutdown. */ +UNIV_INTERN +void +btr_search_sys_free(void); +/*=====================*/ /********************************************************************//** Disable the adaptive hash search system and empty the index. */ diff --git a/storage/innodb_plugin/include/dict0dict.h b/storage/innodb_plugin/include/dict0dict.h index d425241a3a2..12396556c2d 100644 --- a/storage/innodb_plugin/include/dict0dict.h +++ b/storage/innodb_plugin/include/dict0dict.h @@ -1151,6 +1151,13 @@ void dict_ind_init(void); /*===============*/ +/**********************************************************************//** +Closes the data dictionary module. */ +UNIV_INTERN +void +dict_close(void); +/*============*/ + #ifndef UNIV_NONINL #include "dict0dict.ic" #endif diff --git a/storage/innodb_plugin/include/fil0fil.h b/storage/innodb_plugin/include/fil0fil.h index a36deaf16ce..74d0fbcdacd 100644 --- a/storage/innodb_plugin/include/fil0fil.h +++ b/storage/innodb_plugin/include/fil0fil.h @@ -224,15 +224,6 @@ fil_space_create( 0 for uncompressed tablespaces */ ulint purpose);/*!< in: FIL_TABLESPACE, or FIL_LOG if log */ /*******************************************************************//** -Frees a space object from a the tablespace memory cache. Closes the files in -the chain but does not delete them. -@return TRUE if success */ -UNIV_INTERN -ibool -fil_space_free( -/*===========*/ - ulint id); /*!< in: space id */ -/*******************************************************************//** Returns the size of the space in pages. The tablespace must be cached in the memory cache. @return space size, 0 if space not found */ @@ -278,6 +269,12 @@ fil_init( ulint hash_size, /*!< in: hash table size */ ulint max_n_open); /*!< in: max number of open files */ /*******************************************************************//** +Initializes the tablespace memory cache. */ +UNIV_INTERN +void +fil_close(void); +/*===========*/ +/*******************************************************************//** Opens all log files and system tablespace data files. They stay open until the database server shutdown. This should be called at a server startup after the space objects for the log and the system tablespace have been created. The diff --git a/storage/innodb_plugin/include/ibuf0ibuf.h b/storage/innodb_plugin/include/ibuf0ibuf.h index 21330997df3..8aa21fb9d95 100644 --- a/storage/innodb_plugin/include/ibuf0ibuf.h +++ b/storage/innodb_plugin/include/ibuf0ibuf.h @@ -356,6 +356,12 @@ void ibuf_print( /*=======*/ FILE* file); /*!< in: file where to print */ +/******************************************************************//** +Closes insert buffer and frees the data structures. */ +UNIV_INTERN +void +ibuf_close(void); +/*============*/ #define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO #define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO diff --git a/storage/innodb_plugin/include/lock0lock.h b/storage/innodb_plugin/include/lock0lock.h index aeabe39e1a9..82e4c9bd976 100644 --- a/storage/innodb_plugin/include/lock0lock.h +++ b/storage/innodb_plugin/include/lock0lock.h @@ -59,6 +59,12 @@ lock_sys_create( /*============*/ ulint n_cells); /*!< in: number of slots in lock hash table */ /*********************************************************************//** +Closes the lock system at database shutdown. */ +UNIV_INTERN +void +lock_sys_close(void); +/*================*/ +/*********************************************************************//** Checks if some transaction has an implicit x-lock on a record in a clustered index. @return transaction which has the x-lock, or NULL */ diff --git a/storage/innodb_plugin/include/log0log.h b/storage/innodb_plugin/include/log0log.h index 299b4a05b40..135aeb69e2d 100644 --- a/storage/innodb_plugin/include/log0log.h +++ b/storage/innodb_plugin/include/log0log.h @@ -572,6 +572,18 @@ UNIV_INTERN void log_refresh_stats(void); /*===================*/ +/********************************************************** +Shutdown the log system but do not release all the memory. */ +UNIV_INTERN +void +log_shutdown(void); +/*==============*/ +/********************************************************** +Free the log system data structures. */ +UNIV_INTERN +void +log_mem_free(void); +/*==============*/ extern log_t* log_sys; @@ -584,7 +596,7 @@ extern log_t* log_sys; #define LOG_RECOVER 98887331 /* The counting of lsn's starts from this value: this must be non-zero */ -#define LOG_START_LSN ((ib_uint64_t) (16 * OS_FILE_LOG_BLOCK_SIZE)) +#define LOG_START_LSN ((ib_uint64_t) (16 * OS_FILE_LOG_BLOCK_SIZE)) #define LOG_BUFFER_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE) #define LOG_ARCHIVE_BUF_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE / 4) @@ -721,9 +733,12 @@ struct log_group_struct{ ulint lsn_offset; /*!< the offset of the above lsn */ ulint n_pending_writes;/*!< number of currently pending flush writes for this log group */ + byte** file_header_bufs_ptr;/*!< unaligned buffers */ byte** file_header_bufs;/*!< buffers for each file header in the group */ +#ifdef UNIV_LOG_ARCHIVE /*-----------------------------*/ + byte** archive_file_header_bufs_ptr;/*!< unaligned buffers */ byte** archive_file_header_bufs;/*!< buffers for each file header in the group */ ulint archive_space_id;/*!< file space which @@ -742,10 +757,12 @@ struct log_group_struct{ completion function then sets the new value to ..._file_no */ ulint next_archived_offset; /*!< like the preceding field */ +#endif /* UNIV_LOG_ARCHIVE */ /*-----------------------------*/ ib_uint64_t scanned_lsn; /*!< used only in recovery: recovery scan succeeded up to this lsn in this log group */ + byte* checkpoint_buf_ptr;/*!< unaligned checkpoint header */ byte* checkpoint_buf; /*!< checkpoint header is written from this buffer to the group */ UT_LIST_NODE_T(log_group_t) @@ -763,6 +780,7 @@ struct log_struct{ #ifndef UNIV_HOTBACKUP mutex_t mutex; /*!< mutex protecting the log */ #endif /* !UNIV_HOTBACKUP */ + byte* buf_ptr; /* unaligned log buffer */ byte* buf; /*!< log buffer */ ulint buf_size; /*!< log buffer size in bytes */ ulint max_buf_free; /*!< recommended maximum value of @@ -899,6 +917,7 @@ struct log_struct{ should wait for this without owning the log mutex */ #endif /* !UNIV_HOTBACKUP */ + byte* checkpoint_buf_ptr;/* unaligned checkpoint header */ byte* checkpoint_buf; /*!< checkpoint header is read to this buffer */ /* @} */ diff --git a/storage/innodb_plugin/include/log0recv.h b/storage/innodb_plugin/include/log0recv.h index 6de735be945..a3d2bd050f5 100644 --- a/storage/innodb_plugin/include/log0recv.h +++ b/storage/innodb_plugin/include/log0recv.h @@ -239,6 +239,18 @@ UNIV_INTERN void recv_sys_create(void); /*=================*/ +/**********************************************************//** +Release recovery system mutexes. */ +UNIV_INTERN +void +recv_sys_close(void); +/*================*/ +/********************************************************//** +Frees the recovery system memory. */ +UNIV_INTERN +void +recv_sys_mem_free(void); +/*===================*/ /********************************************************//** Inits the recovery system for a recovery operation. */ UNIV_INTERN @@ -246,6 +258,12 @@ void recv_sys_init( /*==========*/ ulint available_memory); /*!< in: available memory in bytes */ +/********************************************************//** +Reset the state of the recovery system variables. */ +UNIV_INTERN +void +recv_sys_var_init(void); +/*===================*/ /*******************************************************************//** Empties the hash table of stored log records, applying them to appropriate pages. */ diff --git a/storage/innodb_plugin/include/mem0mem.h b/storage/innodb_plugin/include/mem0mem.h index a092b024219..98f8748e529 100644 --- a/storage/innodb_plugin/include/mem0mem.h +++ b/storage/innodb_plugin/include/mem0mem.h @@ -82,6 +82,13 @@ void mem_init( /*=====*/ ulint size); /*!< in: common pool size in bytes */ +/******************************************************************//** +Closes the memory system. */ +UNIV_INTERN +void +mem_close(void); +/*===========*/ + /**************************************************************//** Use this macro instead of the corresponding function! Macro for memory heap creation. */ diff --git a/storage/innodb_plugin/include/mem0pool.h b/storage/innodb_plugin/include/mem0pool.h index 18f988241d6..5e93bf88a47 100644 --- a/storage/innodb_plugin/include/mem0pool.h +++ b/storage/innodb_plugin/include/mem0pool.h @@ -62,6 +62,13 @@ mem_pool_create( /*============*/ ulint size); /*!< in: pool size in bytes */ /********************************************************************//** +Frees a memory pool. */ +UNIV_INTERN +void +mem_pool_free( +/*==========*/ + mem_pool_t* pool); /*!< in, own: memory pool */ +/********************************************************************//** Allocates memory from a pool. NOTE: This low-level function should only be used in mem0mem.*! @return own: allocated memory buffer */ diff --git a/storage/innodb_plugin/include/os0file.h b/storage/innodb_plugin/include/os0file.h index 8535ef092c3..c06b28187d7 100644 --- a/storage/innodb_plugin/include/os0file.h +++ b/storage/innodb_plugin/include/os0file.h @@ -620,6 +620,13 @@ os_aio_init( ulint n_write_segs, /*rec_hash); + mem_free(lock_sys); + lock_sys = NULL; +} + /*********************************************************************//** Gets the size of a lock struct. @return size in bytes */ diff --git a/storage/innodb_plugin/log/log0log.c b/storage/innodb_plugin/log/log0log.c index a23dd20772a..d5b696074b3 100644 --- a/storage/innodb_plugin/log/log0log.c +++ b/storage/innodb_plugin/log/log0log.c @@ -771,8 +771,6 @@ void log_init(void) /*==========*/ { - byte* buf; - log_sys = mem_alloc(sizeof(log_t)); mutex_create(&log_sys->mutex, SYNC_LOG); @@ -787,8 +785,8 @@ log_init(void) ut_a(LOG_BUFFER_SIZE >= 16 * OS_FILE_LOG_BLOCK_SIZE); ut_a(LOG_BUFFER_SIZE >= 4 * UNIV_PAGE_SIZE); - buf = mem_alloc(LOG_BUFFER_SIZE + OS_FILE_LOG_BLOCK_SIZE); - log_sys->buf = ut_align(buf, OS_FILE_LOG_BLOCK_SIZE); + log_sys->buf_ptr = mem_alloc(LOG_BUFFER_SIZE + OS_FILE_LOG_BLOCK_SIZE); + log_sys->buf = ut_align(log_sys->buf_ptr, OS_FILE_LOG_BLOCK_SIZE); log_sys->buf_size = LOG_BUFFER_SIZE; @@ -833,9 +831,9 @@ log_init(void) rw_lock_create(&log_sys->checkpoint_lock, SYNC_NO_ORDER_CHECK); - log_sys->checkpoint_buf - = ut_align(mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE), - OS_FILE_LOG_BLOCK_SIZE); + log_sys->checkpoint_buf_ptr = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE); + log_sys->checkpoint_buf = ut_align(log_sys->checkpoint_buf_ptr, + OS_FILE_LOG_BLOCK_SIZE); memset(log_sys->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE); /*----------------------------*/ @@ -918,23 +916,33 @@ log_group_init( group->lsn_offset = LOG_FILE_HDR_SIZE; group->n_pending_writes = 0; + group->file_header_bufs_ptr = mem_alloc(sizeof(byte*) * n_files); group->file_header_bufs = mem_alloc(sizeof(byte*) * n_files); #ifdef UNIV_LOG_ARCHIVE + group->archive_file_header_bufs_ptr = mem_alloc( + sizeof(byte*) * n_files); group->archive_file_header_bufs = mem_alloc(sizeof(byte*) * n_files); #endif /* UNIV_LOG_ARCHIVE */ for (i = 0; i < n_files; i++) { - *(group->file_header_bufs + i) = ut_align( - mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE), + group->file_header_bufs_ptr[i] = mem_alloc( + LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); + + group->file_header_bufs[i] = ut_align( + group->file_header_bufs_ptr[i], OS_FILE_LOG_BLOCK_SIZE); memset(*(group->file_header_bufs + i), '\0', LOG_FILE_HDR_SIZE); #ifdef UNIV_LOG_ARCHIVE - *(group->archive_file_header_bufs + i) = ut_align( - mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE), + group->archive_file_header_bufs_ptr[i] = mem_alloc( + LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); + + group->archive_file_header_bufs[i] = ut_align( + group->archive_file_header_bufs_ptr[i], OS_FILE_LOG_BLOCK_SIZE); + memset(*(group->archive_file_header_bufs + i), '\0', LOG_FILE_HDR_SIZE); #endif /* UNIV_LOG_ARCHIVE */ @@ -947,8 +955,9 @@ log_group_init( group->archived_offset = 0; #endif /* UNIV_LOG_ARCHIVE */ - group->checkpoint_buf = ut_align( - mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE), OS_FILE_LOG_BLOCK_SIZE); + group->checkpoint_buf_ptr = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE); + group->checkpoint_buf = ut_align(group->checkpoint_buf_ptr, + OS_FILE_LOG_BLOCK_SIZE); memset(group->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE); @@ -3364,4 +3373,95 @@ log_refresh_stats(void) log_sys->n_log_ios_old = log_sys->n_log_ios; log_sys->last_printout_time = time(NULL); } + +/********************************************************************** +Closes a log group. */ +static +void +log_group_close( +/*===========*/ + log_group_t* group) /* in,own: log group to close */ +{ + ulint i; + + for (i = 0; i < group->n_files; i++) { + mem_free(group->file_header_bufs_ptr[i]); +#ifdef UNIV_LOG_ARCHIVE + mem_free(group->archive_file_header_bufs_ptr[i]); +#endif /* UNIV_LOG_ARCHIVE */ + } + + mem_free(group->file_header_bufs_ptr); + mem_free(group->file_header_bufs); + +#ifdef UNIV_LOG_ARCHIVE + mem_free(group->archive_file_header_bufs_ptr); + mem_free(group->archive_file_header_bufs); +#endif /* UNIV_LOG_ARCHIVE */ + + mem_free(group->checkpoint_buf_ptr); + + mem_free(group); +} + +/********************************************************** +Shutdown the log system but do not release all the memory. */ +UNIV_INTERN +void +log_shutdown(void) +/*==============*/ +{ + log_group_t* group; + + group = UT_LIST_GET_FIRST(log_sys->log_groups); + + while (UT_LIST_GET_LEN(log_sys->log_groups) > 0) { + log_group_t* prev_group = group; + + group = UT_LIST_GET_NEXT(log_groups, group); + UT_LIST_REMOVE(log_groups, log_sys->log_groups, prev_group); + + log_group_close(prev_group); + } + + mem_free(log_sys->buf_ptr); + log_sys->buf_ptr = NULL; + log_sys->buf = NULL; + mem_free(log_sys->checkpoint_buf_ptr); + log_sys->checkpoint_buf_ptr = NULL; + log_sys->checkpoint_buf = NULL; + + os_event_free(log_sys->no_flush_event); + os_event_free(log_sys->one_flushed_event); + + rw_lock_free(&log_sys->checkpoint_lock); + + mutex_free(&log_sys->mutex); + +#ifdef UNIV_LOG_ARCHIVE + rw_lock_free(&log_sys->archive_lock); + os_event_create(log_sys->archiving_on); +#endif /* UNIV_LOG_ARCHIVE */ + +#ifdef UNIV_LOG_DEBUG + recv_sys_debug_free(); +#endif + + recv_sys_close(); +} + +/********************************************************** +Free the log system data structures. */ +UNIV_INTERN +void +log_mem_free(void) +/*==============*/ +{ + if (log_sys != NULL) { + recv_sys_mem_free(); + mem_free(log_sys); + + log_sys = NULL; + } +} #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innodb_plugin/log/log0recv.c b/storage/innodb_plugin/log/log0recv.c index 81dcc9cd4f8..ddbc71d4b71 100644 --- a/storage/innodb_plugin/log/log0recv.c +++ b/storage/innodb_plugin/log/log0recv.c @@ -69,15 +69,15 @@ UNIV_INTERN recv_sys_t* recv_sys = NULL; /** TRUE when applying redo log records during crash recovery; FALSE otherwise. Note that this is FALSE while a background thread is rolling back incomplete transactions. */ -UNIV_INTERN ibool recv_recovery_on = FALSE; +UNIV_INTERN ibool recv_recovery_on; #ifdef UNIV_LOG_ARCHIVE /** TRUE when applying redo log records from an archived log file */ -UNIV_INTERN ibool recv_recovery_from_backup_on = FALSE; +UNIV_INTERN ibool recv_recovery_from_backup_on; #endif /* UNIV_LOG_ARCHIVE */ #ifndef UNIV_HOTBACKUP /** TRUE when recv_init_crash_recovery() has been called. */ -UNIV_INTERN ibool recv_needed_recovery = FALSE; +UNIV_INTERN ibool recv_needed_recovery; # ifdef UNIV_DEBUG /** TRUE if writing to the redo log (mtr_commit) is forbidden. Protected by log_sys->mutex. */ @@ -87,7 +87,7 @@ UNIV_INTERN ibool recv_no_log_write = FALSE; /** TRUE if buf_page_is_corrupted() should check if the log sequence number (FIL_PAGE_LSN) is in the future. Initially FALSE, and set by recv_recovery_from_checkpoint_start_func(). */ -UNIV_INTERN ibool recv_lsn_checks_on = FALSE; +UNIV_INTERN ibool recv_lsn_checks_on; /** There are two conditions under which we scan the logs, the first is normal startup and the second is when we do a recovery from an @@ -97,7 +97,7 @@ startup. If we find log entries that were written after the last checkpoint we know that the server was not cleanly shutdown. We must then initialize the crash recovery environment before attempting to store these entries in the log hash table. */ -static ibool recv_log_scan_is_startup_type = FALSE; +static ibool recv_log_scan_is_startup_type; /** If the following is TRUE, the buffer pool file pages must be invalidated after recovery and no ibuf operations are allowed; this becomes TRUE if @@ -108,7 +108,7 @@ buffer pool before the pages have been recovered to the up-to-date state. TRUE means that recovery is running and no operations on the log files are allowed yet: the variable name is misleading. */ -UNIV_INTERN ibool recv_no_ibuf_operations = FALSE; +UNIV_INTERN ibool recv_no_ibuf_operations; /** TRUE when the redo log is being backed up */ # define recv_is_making_a_backup FALSE /** TRUE when recovering from a backed up redo log file */ @@ -116,30 +116,30 @@ UNIV_INTERN ibool recv_no_ibuf_operations = FALSE; #else /* !UNIV_HOTBACKUP */ # define recv_needed_recovery FALSE /** TRUE when the redo log is being backed up */ -UNIV_INTERN ibool recv_is_making_a_backup = FALSE; +UNIV_INTERN ibool recv_is_making_a_backup = FALSE; /** TRUE when recovering from a backed up redo log file */ UNIV_INTERN ibool recv_is_from_backup = FALSE; # define buf_pool_get_curr_size() (5 * 1024 * 1024) #endif /* !UNIV_HOTBACKUP */ /** The following counter is used to decide when to print info on log scan */ -static ulint recv_scan_print_counter = 0; +static ulint recv_scan_print_counter; /** The type of the previous parsed redo log record */ -static ulint recv_previous_parsed_rec_type = 999999; +static ulint recv_previous_parsed_rec_type; /** The offset of the previous parsed redo log record */ -static ulint recv_previous_parsed_rec_offset = 0; +static ulint recv_previous_parsed_rec_offset; /** The 'multi' flag of the previous parsed redo log record */ -static ulint recv_previous_parsed_rec_is_multi = 0; +static ulint recv_previous_parsed_rec_is_multi; /** Maximum page number encountered in the redo log */ -UNIV_INTERN ulint recv_max_parsed_page_no = 0; +UNIV_INTERN ulint recv_max_parsed_page_no; /** This many frames must be left free in the buffer pool when we scan the log and store the scanned log records in the buffer pool: we will use these free frames to read in pages when we start applying the log records to the database. */ -UNIV_INTERN ulint recv_n_pool_free_frames = 256; +UNIV_INTERN ulint recv_n_pool_free_frames; /** The maximum lsn we see for a page during the recovery process. If this is bigger than the lsn we are able to scan up to, that is an indication that @@ -170,7 +170,8 @@ recv_sys_create(void) return; } - recv_sys = mem_alloc(sizeof(recv_sys_t)); + recv_sys = mem_alloc(sizeof(*recv_sys)); + memset(recv_sys, 0x0, sizeof(*recv_sys)); mutex_create(&recv_sys->mutex, SYNC_RECV); @@ -179,6 +180,106 @@ recv_sys_create(void) } /********************************************************//** +Release recovery system mutexes. */ +UNIV_INTERN +void +recv_sys_close(void) +/*================*/ +{ + if (recv_sys != NULL) { + if (recv_sys->addr_hash != NULL) { + hash_table_free(recv_sys->addr_hash); + } + + if (recv_sys->heap != NULL) { + mem_heap_free(recv_sys->heap); + } + + if (recv_sys->buf != NULL) { + ut_free(recv_sys->buf); + } + + if (recv_sys->last_block_buf_start != NULL) { + mem_free(recv_sys->last_block_buf_start); + } + + mutex_free(&recv_sys->mutex); + + mem_free(recv_sys); + recv_sys = NULL; + } +} + +/********************************************************//** +Frees the recovery system memory. */ +UNIV_INTERN +void +recv_sys_mem_free(void) +/*===================*/ +{ + if (recv_sys != NULL) { + if (recv_sys->addr_hash != NULL) { + hash_table_free(recv_sys->addr_hash); + } + + if (recv_sys->heap != NULL) { + mem_heap_free(recv_sys->heap); + } + + if (recv_sys->buf != NULL) { + ut_free(recv_sys->buf); + } + + if (recv_sys->last_block_buf_start != NULL) { + mem_free(recv_sys->last_block_buf_start); + } + + mem_free(recv_sys); + recv_sys = NULL; + } +} + +/************************************************************ +Reset the state of the recovery system variables. */ +UNIV_INTERN +void +recv_sys_var_init(void) +/*===================*/ +{ + recv_lsn_checks_on = FALSE; + + recv_n_pool_free_frames = 256; + + recv_recovery_on = FALSE; + +#ifdef UNIV_LOG_ARCHIVE + recv_recovery_from_backup_on = FALSE; +#endif /* UNIV_LOG_ARCHIVE */ + + recv_needed_recovery = FALSE; + + recv_lsn_checks_on = FALSE; + + recv_log_scan_is_startup_type = FALSE; + + recv_no_ibuf_operations = FALSE; + + recv_scan_print_counter = 0; + + recv_previous_parsed_rec_type = 999999; + + recv_previous_parsed_rec_offset = 0; + + recv_previous_parsed_rec_is_multi = 0; + + recv_max_parsed_page_no = 0; + + recv_n_pool_free_frames = 256; + + recv_max_page_lsn = 0; +} + +/************************************************************ Inits the recovery system for a recovery operation. */ UNIV_INTERN void @@ -253,8 +354,8 @@ recv_sys_empty_hash(void) Frees the recovery system. */ static void -recv_sys_free(void) -/*===============*/ +recv_sys_debug_free(void) +/*=====================*/ { mutex_enter(&(recv_sys->mutex)); @@ -263,8 +364,10 @@ recv_sys_free(void) ut_free(recv_sys->buf); mem_free(recv_sys->last_block_buf_start); - recv_sys->addr_hash = NULL; + recv_sys->buf = NULL; recv_sys->heap = NULL; + recv_sys->addr_hash = NULL; + recv_sys->last_block_buf_start = NULL; mutex_exit(&(recv_sys->mutex)); } @@ -3149,7 +3252,7 @@ recv_recovery_from_checkpoint_finish(void) recv_recovery_on = FALSE; #ifndef UNIV_LOG_DEBUG - recv_sys_free(); + recv_sys_debug_free(); #endif /* Roll back any recovered data dictionary transactions, so that the data dictionary tables will be free of any locks. diff --git a/storage/innodb_plugin/mem/mem0dbg.c b/storage/innodb_plugin/mem/mem0dbg.c index a20eb2ad7d2..01eda20ec45 100644 --- a/storage/innodb_plugin/mem/mem0dbg.c +++ b/storage/innodb_plugin/mem/mem0dbg.c @@ -170,6 +170,17 @@ mem_init( mem_comm_pool = mem_pool_create(size); } + +/******************************************************************//** +Closes the memory system. */ +UNIV_INTERN +void +mem_close(void) +/*===========*/ +{ + mem_pool_free(mem_comm_pool); + mem_comm_pool = NULL; +} #endif /* !UNIV_HOTBACKUP */ #ifdef UNIV_MEM_DEBUG diff --git a/storage/innodb_plugin/mem/mem0pool.c b/storage/innodb_plugin/mem/mem0pool.c index c8fea97a6a3..c4f8af607e0 100644 --- a/storage/innodb_plugin/mem/mem0pool.c +++ b/storage/innodb_plugin/mem/mem0pool.c @@ -260,6 +260,18 @@ mem_pool_create( return(pool); } +/********************************************************************//** +Frees a memory pool. */ +UNIV_INTERN +void +mem_pool_free( +/*==========*/ + mem_pool_t* pool) /*!< in, own: memory pool */ +{ + ut_free(pool->buf); + ut_free(pool); +} + /********************************************************************//** Fills the specified free list. @return TRUE if we were able to insert a block to the free list */ diff --git a/storage/innodb_plugin/os/os0file.c b/storage/innodb_plugin/os/os0file.c index 0cb76d1796f..a3d0b0a10d0 100644 --- a/storage/innodb_plugin/os/os0file.c +++ b/storage/innodb_plugin/os/os0file.c @@ -3029,6 +3029,34 @@ os_aio_array_create( return(array); } +/************************************************************************//** +Frees an aio wait array. */ +static +void +os_aio_array_free( +/*==============*/ + os_aio_array_t* array) /*!< in, own: array to free */ +{ +#ifdef WIN_ASYNC_IO + ulint i; + + for (i = 0; i < array->n_slots; i++) { + os_aio_slot_t* slot = os_aio_array_get_nth_slot(array, i); + os_event_free(slot->event); + } +#endif /* WIN_ASYNC_IO */ + +#ifdef __WIN__ + ut_free(array->native_events); +#endif /* __WIN__ */ + os_mutex_free(array->mutex); + os_event_free(array->not_full); + os_event_free(array->is_empty); + + ut_free(array->slots); + ut_free(array); +} + /*********************************************************************** Initializes the asynchronous io system. Creates one array each for ibuf and log i/o. Also creates one array each for read and write where each @@ -3099,6 +3127,35 @@ os_aio_init( } +/*********************************************************************** +Frees the asynchronous io system. */ +UNIV_INTERN +void +os_aio_free(void) +/*=============*/ +{ + ulint i; + + os_aio_array_free(os_aio_ibuf_array); + os_aio_ibuf_array = NULL; + os_aio_array_free(os_aio_log_array); + os_aio_log_array = NULL; + os_aio_array_free(os_aio_read_array); + os_aio_read_array = NULL; + os_aio_array_free(os_aio_write_array); + os_aio_write_array = NULL; + os_aio_array_free(os_aio_sync_array); + os_aio_sync_array = NULL; + + for (i = 0; i < os_aio_n_segments; i++) { + os_event_free(os_aio_segment_wait_events[i]); + } + + ut_free(os_aio_segment_wait_events); + os_aio_segment_wait_events = 0; + os_aio_n_segments = 0; +} + #ifdef WIN_ASYNC_IO /************************************************************************//** Wakes up all async i/o threads in the array in Windows async i/o at diff --git a/storage/innodb_plugin/os/os0sync.c b/storage/innodb_plugin/os/os0sync.c index 4ec340b72b5..60467242e14 100644 --- a/storage/innodb_plugin/os/os0sync.c +++ b/storage/innodb_plugin/os/os0sync.c @@ -86,6 +86,9 @@ os_sync_init(void) UT_LIST_INIT(os_event_list); UT_LIST_INIT(os_mutex_list); + os_sync_mutex = NULL; + os_sync_mutex_inited = FALSE; + os_sync_mutex = os_mutex_create(NULL); os_sync_mutex_inited = TRUE; @@ -713,6 +716,7 @@ os_fast_mutex_free( os_mutex_enter(os_sync_mutex); } + ut_ad(os_fast_mutex_count > 0); os_fast_mutex_count--; if (UNIV_LIKELY(os_sync_mutex_inited)) { diff --git a/storage/innodb_plugin/os/os0thread.c b/storage/innodb_plugin/os/os0thread.c index 9a2d95cb166..34818ada804 100644 --- a/storage/innodb_plugin/os/os0thread.c +++ b/storage/innodb_plugin/os/os0thread.c @@ -233,6 +233,7 @@ os_thread_exit( #ifdef __WIN__ ExitThread((DWORD)exit_value); #else + pthread_detach(pthread_self()); pthread_exit(exit_value); #endif } diff --git a/storage/innodb_plugin/pars/lexyy.c b/storage/innodb_plugin/pars/lexyy.c index 37d892e51e3..815395ea316 100644 --- a/storage/innodb_plugin/pars/lexyy.c +++ b/storage/innodb_plugin/pars/lexyy.c @@ -2778,3 +2778,16 @@ static void yyfree (void * ptr ) + +/********************************************************************** +Release any resources used by the lexer. */ +UNIV_INTERN +void +pars_lexer_close(void) +/*==================*/ +{ + yylex_destroy(); + free(stringbuf); + stringbuf = NULL; + stringbuf_len_alloc = stringbuf_len = 0; +} diff --git a/storage/innodb_plugin/pars/pars0lex.l b/storage/innodb_plugin/pars/pars0lex.l index 4abff65e98b..55ed17f82e1 100644 --- a/storage/innodb_plugin/pars/pars0lex.l +++ b/storage/innodb_plugin/pars/pars0lex.l @@ -661,3 +661,16 @@ In the state 'id', only two actions are possible (defined below). */ } %% + +/********************************************************************** +Release any resources used by the lexer. */ +UNIV_INTERN +void +pars_lexer_close(void) +/*==================*/ +{ + yylex_destroy(); + free(stringbuf); + stringbuf = NULL; + stringbuf_len_alloc = stringbuf_len = 0; +} diff --git a/storage/innodb_plugin/que/que0que.c b/storage/innodb_plugin/que/que0que.c index 54b1e7535fa..2fe046fa9b8 100644 --- a/storage/innodb_plugin/que/que0que.c +++ b/storage/innodb_plugin/que/que0que.c @@ -518,6 +518,7 @@ que_graph_free_recursive( upd_node_t* upd; tab_node_t* cre_tab; ind_node_t* cre_ind; + purge_node_t* purge; if (node == NULL) { @@ -579,6 +580,13 @@ que_graph_free_recursive( mem_heap_free(ins->entry_sys_heap); break; + case QUE_NODE_PURGE: + purge = node; + + mem_heap_free(purge->heap); + + break; + case QUE_NODE_UPDATE: upd = node; diff --git a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c index d638b23692e..639da1ed2f3 100644 --- a/storage/innodb_plugin/srv/srv0srv.c +++ b/storage/innodb_plugin/srv/srv0srv.c @@ -1006,13 +1006,26 @@ srv_init(void) } /*********************************************************************//** -Frees the OS fast mutex created in srv_init(). */ +Frees the data structures created in srv_init(). */ UNIV_INTERN void srv_free(void) /*==========*/ { os_fast_mutex_free(&srv_conc_mutex); + mem_free(srv_conc_slots); + srv_conc_slots = NULL; + + mem_free(srv_sys->threads); + mem_free(srv_sys); + srv_sys = NULL; + + mem_free(kernel_mutex_temp); + kernel_mutex_temp = NULL; + mem_free(srv_mysql_table); + srv_mysql_table = NULL; + + trx_i_s_cache_free(trx_i_s_cache); } /*********************************************************************//** @@ -1024,6 +1037,8 @@ srv_general_init(void) /*==================*/ { ut_mem_init(); + /* Reset the system variables in the recovery module. */ + recv_sys_var_init(); os_sync_init(); sync_init(); mem_init(srv_mem_pool_size); diff --git a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c index 796541a9f1a..d5f6120ca31 100644 --- a/storage/innodb_plugin/srv/srv0start.c +++ b/storage/innodb_plugin/srv/srv0start.c @@ -103,6 +103,7 @@ Created 2/16/1996 Heikki Tuuri # include "row0row.h" # include "row0mysql.h" # include "btr0pcur.h" +# include "thr0loc.h" # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */ /** Log sequence number immediately after startup */ @@ -495,6 +496,8 @@ io_handler_thread( mutex_exit(&ios_mutex); } + thr_local_free(os_thread_get_curr_id()); + /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. The thread actually never comes here because it is exited in an @@ -531,32 +534,6 @@ srv_normalize_path_for_win( #endif } -/*********************************************************************//** -Adds a slash or a backslash to the end of a string if it is missing -and the string is not empty. -@return string which has the separator if the string is not empty */ -UNIV_INTERN -char* -srv_add_path_separator_if_needed( -/*=============================*/ - char* str) /*!< in: null-terminated character string */ -{ - char* out_str; - ulint len = ut_strlen(str); - - if (len == 0 || str[len - 1] == SRV_PATH_SEPARATOR) { - - return(str); - } - - out_str = ut_malloc(len + 2); - memcpy(out_str, str, len); - out_str[len] = SRV_PATH_SEPARATOR; - out_str[len + 1] = 0; - - return(out_str); -} - #ifndef UNIV_HOTBACKUP /*********************************************************************//** Calculates the low 32 bits when a file size which is given as a number @@ -605,19 +582,24 @@ open_or_create_log_file( ulint size; ulint size_high; char name[10000]; + ulint dirnamelen; UT_NOT_USED(create_new_db); *log_file_created = FALSE; srv_normalize_path_for_win(srv_log_group_home_dirs[k]); - srv_log_group_home_dirs[k] = srv_add_path_separator_if_needed( - srv_log_group_home_dirs[k]); - ut_a(strlen(srv_log_group_home_dirs[k]) - < (sizeof name) - 10 - sizeof "ib_logfile"); - sprintf(name, "%s%s%lu", srv_log_group_home_dirs[k], - "ib_logfile", (ulong) i); + dirnamelen = strlen(srv_log_group_home_dirs[k]); + ut_a(dirnamelen < (sizeof name) - 10 - sizeof "ib_logfile"); + memcpy(name, srv_log_group_home_dirs[k], dirnamelen); + + /* Add a path separator if needed. */ + if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) { + name[dirnamelen++] = SRV_PATH_SEPARATOR; + } + + sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i); files[i] = os_file_create(name, OS_FILE_CREATE, OS_FILE_NORMAL, OS_LOG_FILE, &ret); @@ -780,14 +762,22 @@ open_or_create_data_files( *create_new_db = FALSE; srv_normalize_path_for_win(srv_data_home); - srv_data_home = srv_add_path_separator_if_needed(srv_data_home); for (i = 0; i < srv_n_data_files; i++) { - srv_normalize_path_for_win(srv_data_file_names[i]); + ulint dirnamelen; - ut_a(strlen(srv_data_home) + strlen(srv_data_file_names[i]) + srv_normalize_path_for_win(srv_data_file_names[i]); + dirnamelen = strlen(srv_data_home); + + ut_a(dirnamelen + strlen(srv_data_file_names[i]) < (sizeof name) - 1); - sprintf(name, "%s%s", srv_data_home, srv_data_file_names[i]); + memcpy(name, srv_data_home, dirnamelen); + /* Add a path separator if needed. */ + if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) { + name[dirnamelen++] = SRV_PATH_SEPARATOR; + } + + strcpy(name + dirnamelen, srv_data_file_names[i]); if (srv_data_file_is_raw_partition[i] == 0) { @@ -1009,7 +999,7 @@ skip_size_check: return(DB_SUCCESS); } -/****************************************************************//** +/******************************************************************** Starts InnoDB and creates a new database if database files are not found and the user wants. @return DB_SUCCESS or error code */ @@ -1120,7 +1110,7 @@ innobase_start_or_create_for_mysql(void) if (srv_start_has_been_called) { fprintf(stderr, - "InnoDB: Error:startup called second time" + "InnoDB: Error: startup called second time" " during the process lifetime.\n" "InnoDB: In the MySQL Embedded Server Library" " you cannot call server_init()\n" @@ -1959,8 +1949,10 @@ innobase_shutdown_for_mysql(void) /* All the threads have exited or are just exiting; NOTE that the threads may not have completed their exit yet. Should we use pthread_join() to make sure - they have exited? Now we just sleep 0.1 seconds and - hope that is enough! */ + they have exited? If we did, we would have to + remove the pthread_detach() from + os_thread_exit(). Now we just sleep 0.1 + seconds and hope that is enough! */ os_mutex_exit(os_sync_mutex); @@ -1999,37 +1991,41 @@ innobase_shutdown_for_mysql(void) srv_misc_tmpfile = 0; } + /* This must be disabled before closing the buffer pool + and closing the data dictionary. */ + btr_search_disable(); + + ibuf_close(); + log_shutdown(); + lock_sys_close(); + thr_local_close(); trx_sys_file_format_close(); + trx_sys_close(); mutex_free(&srv_monitor_file_mutex); mutex_free(&srv_dict_tmpfile_mutex); mutex_free(&srv_misc_tmpfile_mutex); + dict_close(); + btr_search_sys_free(); /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside them */ + os_aio_free(); sync_close(); + srv_free(); + fil_close(); /* 4. Free the os_conc_mutex and all os_events and os_mutexes */ - srv_free(); os_sync_free(); - /* Check that all read views are closed except read view owned - by a purge. */ - - if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) { - fprintf(stderr, - "InnoDB: Error: all read views were not closed" - " before shutdown:\n" - "InnoDB: %lu read views open \n", - UT_LIST_GET_LEN(trx_sys->view_list) - 1); - } - - /* 5. Free all allocated memory and the os_fast_mutex created in - ut0mem.c */ + /* 5. Free all allocated memory */ + pars_lexer_close(); + log_mem_free(); buf_pool_free(); ut_free_all_mem(); + mem_close(); if (os_thread_count != 0 || os_event_count != 0 @@ -2060,6 +2056,7 @@ innobase_shutdown_for_mysql(void) } srv_was_started = FALSE; + srv_start_has_been_called = FALSE; return((int) DB_SUCCESS); } diff --git a/storage/innodb_plugin/sync/sync0arr.c b/storage/innodb_plugin/sync/sync0arr.c index d78ee8f3191..ed9e25bf2f2 100644 --- a/storage/innodb_plugin/sync/sync0arr.c +++ b/storage/innodb_plugin/sync/sync0arr.c @@ -227,24 +227,21 @@ sync_array_create( SYNC_ARRAY_MUTEX: determines the type of mutex protecting the data structure */ { + ulint sz; sync_array_t* arr; - sync_cell_t* cell_array; - sync_cell_t* cell; - ulint i; ut_a(n_cells > 0); /* Allocate memory for the data structures */ arr = ut_malloc(sizeof(sync_array_t)); + memset(arr, 0x0, sizeof(*arr)); - cell_array = ut_malloc(sizeof(sync_cell_t) * n_cells); + sz = sizeof(sync_cell_t) * n_cells; + arr->array = ut_malloc(sz); + memset(arr->array, 0x0, sz); arr->n_cells = n_cells; - arr->n_reserved = 0; - arr->array = cell_array; arr->protection = protection; - arr->sg_count = 0; - arr->res_count = 0; /* Then create the mutex to protect the wait array complex */ if (protection == SYNC_ARRAY_OS_MUTEX) { @@ -255,13 +252,6 @@ sync_array_create( ut_error; } - for (i = 0; i < n_cells; i++) { - cell = sync_array_get_nth_cell(arr, i); - cell->wait_object = NULL; - cell->waiting = FALSE; - cell->signal_count = 0; - } - return(arr); } diff --git a/storage/innodb_plugin/sync/sync0sync.c b/storage/innodb_plugin/sync/sync0sync.c index 5ad143075a7..569fc6328c4 100644 --- a/storage/innodb_plugin/sync/sync0sync.c +++ b/storage/innodb_plugin/sync/sync0sync.c @@ -1377,7 +1377,12 @@ sync_close(void) mutex_free(&mutex_list_mutex); #ifdef UNIV_SYNC_DEBUG mutex_free(&sync_thread_mutex); + + /* Switch latching order checks on in sync0sync.c */ + sync_order_checks_on = FALSE; #endif /* UNIV_SYNC_DEBUG */ + + sync_initialized = FALSE; } /*******************************************************************//** diff --git a/storage/innodb_plugin/thr/thr0loc.c b/storage/innodb_plugin/thr/thr0loc.c index 49275be1d7d..59a234a6b72 100644 --- a/storage/innodb_plugin/thr/thr0loc.c +++ b/storage/innodb_plugin/thr/thr0loc.c @@ -246,3 +246,34 @@ thr_local_init(void) mutex_create(&thr_local_mutex, SYNC_THR_LOCAL); } + +/******************************************************************** +Close the thread local storage module. */ +UNIV_INTERN +void +thr_local_close(void) +/*=================*/ +{ + ulint i; + + ut_a(thr_local_hash != NULL); + + /* Free the hash elements. We don't remove them from the table + because we are going to destroy the table anyway. */ + for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) { + thr_local_t* local; + + local = HASH_GET_FIRST(thr_local_hash, i); + + while (local) { + thr_local_t* prev_local = local; + + local = HASH_GET_NEXT(hash, prev_local); + ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N); + mem_free(prev_local); + } + } + + hash_table_free(thr_local_hash); + thr_local_hash = NULL; +} diff --git a/storage/innodb_plugin/trx/trx0i_s.c b/storage/innodb_plugin/trx/trx0i_s.c index 0d809806edc..12562b40726 100644 --- a/storage/innodb_plugin/trx/trx0i_s.c +++ b/storage/innodb_plugin/trx/trx0i_s.c @@ -237,6 +237,27 @@ table_cache_init( } } +/*******************************************************************//** +Frees a table cache. */ +static +void +table_cache_free( +/*=============*/ + i_s_table_cache_t* table_cache) /*!< in/out: table cache */ +{ + ulint i; + + for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) { + + /* the memory is actually allocated in + table_cache_create_empty_row() */ + if (table_cache->chunks[i].base) { + mem_free(table_cache->chunks[i].base); + table_cache->chunks[i].base = NULL; + } + } +} + /*******************************************************************//** Returns an empty row from a table cache. The row is allocated if no more empty rows are available. The number of used rows is incremented. @@ -1251,6 +1272,22 @@ trx_i_s_cache_init( cache->is_truncated = FALSE; } +/*******************************************************************//** +Free the INFORMATION SCHEMA trx related cache. */ +UNIV_INTERN +void +trx_i_s_cache_free( +/*===============*/ + trx_i_s_cache_t* cache) /*!< in, own: cache to free */ +{ + hash_table_free(cache->locks_hash); + ha_storage_free(cache->storage); + table_cache_free(&cache->innodb_trx); + table_cache_free(&cache->innodb_locks); + table_cache_free(&cache->innodb_lock_waits); + memset(cache, 0, sizeof *cache); +} + /*******************************************************************//** Issue a shared/read lock on the tables cache. */ UNIV_INTERN diff --git a/storage/innodb_plugin/trx/trx0purge.c b/storage/innodb_plugin/trx/trx0purge.c index cd79fd1c315..abbfa3d7f81 100644 --- a/storage/innodb_plugin/trx/trx0purge.c +++ b/storage/innodb_plugin/trx/trx0purge.c @@ -249,6 +249,44 @@ trx_purge_sys_create(void) purge_sys->heap); } +/************************************************************************ +Frees the global purge system control structure. */ +UNIV_INTERN +void +trx_purge_sys_close(void) +/*======================*/ +{ + ut_ad(!mutex_own(&kernel_mutex)); + + que_graph_free(purge_sys->query); + + ut_a(purge_sys->sess->trx->is_purge); + purge_sys->sess->trx->conc_state = TRX_NOT_STARTED; + sess_close(purge_sys->sess); + purge_sys->sess = NULL; + + if (purge_sys->view != NULL) { + /* Because acquiring the kernel mutex is a pre-condition + of read_view_close(). We don't really need it here. */ + mutex_enter(&kernel_mutex); + + read_view_close(purge_sys->view); + purge_sys->view = NULL; + + mutex_exit(&kernel_mutex); + } + + trx_undo_arr_free(purge_sys->arr); + + rw_lock_free(&purge_sys->latch); + mutex_free(&purge_sys->mutex); + + mem_heap_free(purge_sys->heap); + mem_free(purge_sys); + + purge_sys = NULL; +} + /*================ UNDO LOG HISTORY LIST =============================*/ /********************************************************************//** diff --git a/storage/innodb_plugin/trx/trx0rseg.c b/storage/innodb_plugin/trx/trx0rseg.c index 580762e8716..8d754788e2a 100644 --- a/storage/innodb_plugin/trx/trx0rseg.c +++ b/storage/innodb_plugin/trx/trx0rseg.c @@ -132,6 +132,49 @@ trx_rseg_header_create( } /***********************************************************************//** +Free's an instance of the rollback segment in memory. */ +UNIV_INTERN +void +trx_rseg_mem_free( +/*==============*/ + trx_rseg_t* rseg) /* in, own: instance to free */ +{ + trx_undo_t* undo; + + mutex_free(&rseg->mutex); + + /* There can't be any active transactions. */ + ut_a(UT_LIST_GET_LEN(rseg->update_undo_list) == 0); + ut_a(UT_LIST_GET_LEN(rseg->insert_undo_list) == 0); + + undo = UT_LIST_GET_FIRST(rseg->update_undo_cached); + + while (undo != NULL) { + trx_undo_t* prev_undo = undo; + + undo = UT_LIST_GET_NEXT(undo_list, undo); + UT_LIST_REMOVE(undo_list, rseg->update_undo_cached, prev_undo); + + trx_undo_mem_free(prev_undo); + } + + undo = UT_LIST_GET_FIRST(rseg->insert_undo_cached); + + while (undo != NULL) { + trx_undo_t* prev_undo = undo; + + undo = UT_LIST_GET_NEXT(undo_list, undo); + UT_LIST_REMOVE(undo_list, rseg->insert_undo_cached, prev_undo); + + trx_undo_mem_free(prev_undo); + } + + trx_sys_set_nth_rseg(trx_sys, rseg->id, NULL); + + mem_free(rseg); +} + +/*************************************************************************** Creates and initializes a rollback segment object. The values for the fields are read from the header. The object is inserted to the rseg list of the trx system object and a pointer is inserted in the rseg diff --git a/storage/innodb_plugin/trx/trx0sys.c b/storage/innodb_plugin/trx/trx0sys.c index ef10119587d..79e5af1c677 100644 --- a/storage/innodb_plugin/trx/trx0sys.c +++ b/storage/innodb_plugin/trx/trx0sys.c @@ -40,6 +40,7 @@ Created 3/26/1996 Heikki Tuuri #include "trx0purge.h" #include "log0log.h" #include "os0file.h" +#include "read0read.h" /** The file format tag structure with id and name. */ struct file_format_struct { @@ -1533,3 +1534,80 @@ trx_sys_file_format_id_to_name( } #endif /* !UNIV_HOTBACKUP */ + +/********************************************************************* +Shutdown/Close the transaction system. */ +UNIV_INTERN +void +trx_sys_close(void) +/*===============*/ +{ + trx_rseg_t* rseg; + read_view_t* view; + + ut_ad(trx_sys != NULL); + + /* Check that all read views are closed except read view owned + by a purge. */ + + if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) { + fprintf(stderr, + "InnoDB: Error: all read views were not closed" + " before shutdown:\n" + "InnoDB: %lu read views open \n", + UT_LIST_GET_LEN(trx_sys->view_list) - 1); + } + + sess_close(trx_dummy_sess); + trx_dummy_sess = NULL; + + trx_purge_sys_close(); + + mutex_enter(&kernel_mutex); + + /* Free the double write data structures. */ + ut_a(trx_doublewrite != NULL); + ut_free(trx_doublewrite->write_buf_unaligned); + trx_doublewrite->write_buf_unaligned = NULL; + + mem_free(trx_doublewrite->buf_block_arr); + trx_doublewrite->buf_block_arr = NULL; + + mutex_free(&trx_doublewrite->mutex); + mem_free(trx_doublewrite); + trx_doublewrite = NULL; + + /* There can't be any active transactions. */ + rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); + + while (rseg != NULL) { + trx_rseg_t* prev_rseg = rseg; + + rseg = UT_LIST_GET_NEXT(rseg_list, prev_rseg); + UT_LIST_REMOVE(rseg_list, trx_sys->rseg_list, prev_rseg); + + trx_rseg_mem_free(prev_rseg); + } + + view = UT_LIST_GET_FIRST(trx_sys->view_list); + + while (view != NULL) { + read_view_t* prev_view = view; + + view = UT_LIST_GET_NEXT(view_list, prev_view); + + /* Views are allocated from the trx_sys->global_read_view_heap. + So, we simply remove the element here. */ + UT_LIST_REMOVE(view_list, trx_sys->view_list, prev_view); + } + + ut_a(UT_LIST_GET_LEN(trx_sys->trx_list) == 0); + ut_a(UT_LIST_GET_LEN(trx_sys->rseg_list) == 0); + ut_a(UT_LIST_GET_LEN(trx_sys->view_list) == 0); + ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0); + + mem_free(trx_sys); + + trx_sys = NULL; + mutex_exit(&kernel_mutex); +} diff --git a/storage/innodb_plugin/trx/trx0undo.c b/storage/innodb_plugin/trx/trx0undo.c index 9af96f14526..3bb1b1cdf6c 100644 --- a/storage/innodb_plugin/trx/trx0undo.c +++ b/storage/innodb_plugin/trx/trx0undo.c @@ -1522,7 +1522,7 @@ trx_undo_mem_init_for_reuse( /********************************************************************//** Frees an undo log memory copy. */ -static +UNIV_INTERN void trx_undo_mem_free( /*==============*/ diff --git a/storage/innodb_plugin/usr/usr0sess.c b/storage/innodb_plugin/usr/usr0sess.c index 990991a2c06..8087dcb4170 100644 --- a/storage/innodb_plugin/usr/usr0sess.c +++ b/storage/innodb_plugin/usr/usr0sess.c @@ -31,14 +31,6 @@ Created 6/25/1996 Heikki Tuuri #include "trx0trx.h" -/*********************************************************************//** -Closes a session, freeing the memory occupied by it. */ -static -void -sess_close( -/*=======*/ - sess_t* sess); /*!< in, own: session object */ - /*********************************************************************//** Opens a session. @return own: session object */ @@ -64,35 +56,16 @@ sess_open(void) /*********************************************************************//** Closes a session, freeing the memory occupied by it. */ -static +UNIV_INTERN void sess_close( /*=======*/ sess_t* sess) /*!< in, own: session object */ { - ut_ad(mutex_own(&kernel_mutex)); - ut_ad(sess->trx == NULL); + ut_ad(!mutex_own(&kernel_mutex)); + ut_a(UT_LIST_GET_LEN(sess->graphs) == 0); + + trx_free_for_background(sess->trx); mem_free(sess); } - -/*********************************************************************//** -Closes a session, freeing the memory occupied by it, if it is in a state -where it should be closed. -@return TRUE if closed */ -UNIV_INTERN -ibool -sess_try_close( -/*===========*/ - sess_t* sess) /*!< in, own: session object */ -{ - ut_ad(mutex_own(&kernel_mutex)); - - if (UT_LIST_GET_LEN(sess->graphs) == 0) { - sess_close(sess); - - return(TRUE); - } - - return(FALSE); -} diff --git a/storage/innodb_plugin/ut/ut0mem.c b/storage/innodb_plugin/ut/ut0mem.c index edb63c95700..35a325b9ccd 100644 --- a/storage/innodb_plugin/ut/ut0mem.c +++ b/storage/innodb_plugin/ut/ut0mem.c @@ -433,6 +433,8 @@ ut_free_all_mem(void) " total allocated memory is %lu\n", (ulong) ut_total_allocated_memory); } + + ut_mem_block_list_inited = FALSE; } #endif /* !UNIV_HOTBACKUP */ From 54e01f3ce12e33db9a77e4ff98d5ee33550af57d Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 17:12:51 +0530 Subject: [PATCH 111/344] Applying InnoDB Plugin 1.0.6 snapshot, part 2. Fixes BUG#32430 Enable partition_innodb_plugin.test for BUG#32430 applied revisions: r6134, r6137, r6153 Detailed revision comments: r6134 | marko | 2009-11-04 09:57:29 +0200 (Wed, 04 Nov 2009) | 5 lines branches/zip: innobase_convert_identifier(): Convert table names with explain_filename() to address Bug #32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs. rb://134 approved by Sunny Bains r6137 | marko | 2009-11-04 15:24:28 +0200 (Wed, 04 Nov 2009) | 1 line branches/zip: dict_index_too_big_for_undo(): Correct a typo. r6153 | vasil | 2009-11-10 15:33:22 +0200 (Tue, 10 Nov 2009) | 145 lines branches/zip: Merge r6125:6152 from branches/5.1: (everything except the last white-space change was skipped as it is already in branches/zip) ------------------------------------------------------------------------ r6127 | vasil | 2009-10-30 11:18:25 +0200 (Fri, 30 Oct 2009) | 18 lines Changed paths: M /branches/5.1/Makefile.am M /branches/5.1/mysql-test/innodb-autoinc.result M /branches/5.1/mysql-test/innodb-autoinc.test branches/5.1: Backport c6121 from branches/zip: ------------------------------------------------------------------------ r6121 | sunny | 2009-10-30 01:42:11 +0200 (Fri, 30 Oct 2009) | 7 lines Changed paths: M /branches/zip/mysql-test/innodb-autoinc.result branches/zip: This test has been problematic for sometime now. The underlying bug is that the data dictionaries get out of sync. In the AUTOINC code we try and apply salve to the symptoms. In the past MySQL made some unrelated change and the dictionaries stopped getting out of sync and this test started to fail. Now, it seems they have reverted that changed and the test is passing again. I suspect this is not he last time that this test will change. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r6129 | vasil | 2009-10-30 17:14:22 +0200 (Fri, 30 Oct 2009) | 4 lines Changed paths: M /branches/5.1/Makefile.am branches/5.1: Revert a change to Makefile.am that sneaked unnoticed in c6127. ------------------------------------------------------------------------ r6136 | marko | 2009-11-04 12:28:10 +0200 (Wed, 04 Nov 2009) | 15 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc M /branches/5.1/include/ha_prototypes.h M /branches/5.1/ut/ut0ut.c branches/5.1: Port r6134 from branches/zip: ------------------------------------------------------------------------ r6134 | marko | 2009-11-04 07:57:29 +0000 (Wed, 04 Nov 2009) | 5 lines branches/zip: innobase_convert_identifier(): Convert table names with explain_filename() to address Bug #32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs. rb://134 approved by Sunny Bains ------------------------------------------------------------------------ innobase_print_identifier(): Replace with innobase_convert_name(). innobase_convert_identifier(): New function, called by innobase_convert_name(). ------------------------------------------------------------------------ r6149 | vasil | 2009-11-09 11:15:01 +0200 (Mon, 09 Nov 2009) | 5 lines Changed paths: M /branches/5.1/CMakeLists.txt branches/5.1: Followup to r5700: Adjust the changes so they are the same as in the BZR repository. ------------------------------------------------------------------------ r6150 | vasil | 2009-11-09 11:43:31 +0200 (Mon, 09 Nov 2009) | 58 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: Merge a part of r2911.5.5 from MySQL: (the other part of this was merged in c5700) ------------------------------------------------------------ revno: 2911.5.5 committer: Vladislav Vaintroub branch nick: 5.1-innodb_plugin timestamp: Wed 2009-06-10 10:59:49 +0200 message: Backport WL#3653 to 5.1 to enable bundled innodb plugin. Remove custom DLL loader code from innodb plugin code, use symbols exported from mysqld. removed: storage/innodb_plugin/handler/handler0vars.h storage/innodb_plugin/handler/win_delay_loader.cc added: storage/mysql_storage_engine.cmake win/create_def_file.js modified: CMakeLists.txt include/m_ctype.h include/my_global.h include/my_sys.h include/mysql/plugin.h libmysqld/CMakeLists.txt mysql-test/mysql-test-run.pl mysql-test/t/plugin.test mysql-test/t/plugin_load-master.opt mysys/charset.c sql/CMakeLists.txt sql/handler.h sql/mysql_priv.h sql/mysqld.cc sql/sql_class.cc sql/sql_class.h sql/sql_list.h sql/sql_profile.h storage/Makefile.am storage/archive/CMakeLists.txt storage/blackhole/CMakeLists.txt storage/csv/CMakeLists.txt storage/example/CMakeLists.txt storage/federated/CMakeLists.txt storage/heap/CMakeLists.txt storage/innobase/CMakeLists.txt storage/innobase/handler/ha_innodb.cc storage/innodb_plugin/CMakeLists.txt storage/innodb_plugin/handler/ha_innodb.cc storage/innodb_plugin/handler/handler0alter.cc storage/innodb_plugin/handler/i_s.cc storage/innodb_plugin/plug.in storage/myisam/CMakeLists.txt storage/myisammrg/CMakeLists.txt win/Makefile.am win/configure.js ------------------------------------------------------------------------ r6152 | vasil | 2009-11-10 15:30:20 +0200 (Tue, 10 Nov 2009) | 4 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: White space fixup. ------------------------------------------------------------------------ --- mysql-test/t/disabled.def | 1 - storage/innodb_plugin/ChangeLog | 8 +++++++- storage/innodb_plugin/dict/dict0dict.c | 2 +- storage/innodb_plugin/handler/ha_innodb.cc | 22 +++++++++++++++++----- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index c136a2d5162..06d3dbb4e57 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,5 +11,4 @@ ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically -partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2 diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 7c886a8d155..682d369b854 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,4 +1,10 @@ -2009-01-01 The InnoDB Team +2009-11-04 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#32430 'show innodb status' causes errors + Invalid (old?) table or database name in logs + +2009-11-02 The InnoDB Team * btr/btr0sea.c, buf/buf0buf.c, dict/dict0dict.c, fil/fil0fil.c, ibuf/ibuf0ibuf.c, include/btr0sea.h, include/dict0dict.h, diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c index 58ed35a4313..2e524a5a2e3 100644 --- a/storage/innodb_plugin/dict/dict0dict.c +++ b/storage/innodb_plugin/dict/dict0dict.c @@ -1200,7 +1200,7 @@ dict_index_too_big_for_undo( = TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE + 2 /* next record pointer */ + 1 /* type_cmpl */ - + 11 /* trx->undo_no */ - 11 /* table->id */ + + 11 /* trx->undo_no */ + 11 /* table->id */ + 1 /* rec_get_info_bits() */ + 11 /* DB_TRX_ID */ + 11 /* DB_ROLL_PTR */ diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index ac710ea2b15..1ea22b60760 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -1707,15 +1707,19 @@ innobase_convert_identifier( FALSE=id is an UTF-8 string */ { char nz[NAME_LEN + 1]; +#if MYSQL_VERSION_ID >= 50141 + char nz2[NAME_LEN + 1 + EXPLAIN_FILENAME_MAX_EXTRA_LENGTH]; +#else /* MYSQL_VERSION_ID >= 50141 */ char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix]; +#endif /* MYSQL_VERSION_ID >= 50141 */ const char* s = id; int q; if (file_id) { - /* Decode the table name. The filename_to_tablename() - function expects a NUL-terminated string. The input and - output strings buffers must not be shared. */ + /* Decode the table name. The MySQL function expects + a NUL-terminated string. The input and output strings + buffers must not be shared. */ if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) { idlen = (sizeof nz) - 1; @@ -1725,7 +1729,13 @@ innobase_convert_identifier( nz[idlen] = 0; s = nz2; +#if MYSQL_VERSION_ID >= 50141 + idlen = explain_filename((THD*) thd, nz, nz2, sizeof nz2, + EXPLAIN_PARTITIONS_AS_COMMENT); + goto no_quote; +#else /* MYSQL_VERSION_ID >= 50141 */ idlen = filename_to_tablename(nz, nz2, sizeof nz2); +#endif /* MYSQL_VERSION_ID >= 50141 */ } /* See if the identifier needs to be quoted. */ @@ -1736,6 +1746,9 @@ innobase_convert_identifier( } if (q == EOF) { +#if MYSQL_VERSION_ID >= 50141 +no_quote: +#endif /* MYSQL_VERSION_ID >= 50141 */ if (UNIV_UNLIKELY(idlen > buflen)) { idlen = buflen; } @@ -9148,8 +9161,7 @@ innobase_xa_prepare( executing XA PREPARE and XA COMMIT commands. In this case we cannot know how many minutes or hours will be between XA PREPARE and XA COMMIT, and we don't want - to block for undefined period of time. - */ + to block for undefined period of time. */ pthread_mutex_lock(&prepare_commit_mutex); trx->active_trans = 2; } From e50e69409b2e6bdbe0cde89d6ab464446d48e320 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 17:26:21 +0530 Subject: [PATCH 112/344] Applying InnoDB Plugin 1.0.6 snapshot, part 3. Fixes BUG#47167 applied revisions: r6157 Detailed revision comments: r6157 | jyang | 2009-11-11 14:27:09 +0200 (Wed, 11 Nov 2009) | 10 lines branches/zip: Fix an issue that a local variable defined in innodb_file_format_check_validate() is being referenced across function in innodb_file_format_check_update(). In addition, fix "set global innodb_file_format_check = DEFAULT" call. Bug #47167: "set global innodb_file_format_check" cannot set value by User-Defined Variable." rb://169 approved by Sunny Bains and Marko. --- .../suite/innodb/r/innodb_bug47167.result | 24 ++++++ .../suite/innodb/r/innodb_file_format.result | 2 - .../suite/innodb/t/innodb_bug47167.test | 46 +++++++++++ storage/innodb_plugin/handler/ha_innodb.cc | 78 ++++++++++++------- 4 files changed, 118 insertions(+), 32 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_bug47167.result create mode 100644 mysql-test/suite/innodb/t/innodb_bug47167.test diff --git a/mysql-test/suite/innodb/r/innodb_bug47167.result b/mysql-test/suite/innodb/r/innodb_bug47167.result new file mode 100644 index 00000000000..cbec363d78f --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug47167.result @@ -0,0 +1,24 @@ +set @old_innodb_file_format_check=@@innodb_file_format_check; +select @old_innodb_file_format_check; +@old_innodb_file_format_check +Antelope +set global innodb_file_format_check = Barracuda; +select @@innodb_file_format_check; +@@innodb_file_format_check +Barracuda +set global innodb_file_format_check = DEFAULT; +select @@innodb_file_format_check; +@@innodb_file_format_check +Barracuda +set global innodb_file_format_check = @old_innodb_file_format_check; +select @@innodb_file_format_check; +@@innodb_file_format_check +Antelope +set global innodb_file_format_check = cheetah; +ERROR HY000: Incorrect arguments to SET +set global innodb_file_format_check = Bear; +ERROR HY000: Incorrect arguments to SET +set global innodb_file_format_check = on; +ERROR HY000: Incorrect arguments to SET +set global innodb_file_format_check = off; +ERROR HY000: Incorrect arguments to SET diff --git a/mysql-test/suite/innodb/r/innodb_file_format.result b/mysql-test/suite/innodb/r/innodb_file_format.result index fbc67ada1bb..36f176c616a 100644 --- a/mysql-test/suite/innodb/r/innodb_file_format.result +++ b/mysql-test/suite/innodb/r/innodb_file_format.result @@ -31,8 +31,6 @@ select @@innodb_file_format_check; @@innodb_file_format_check Barracuda set global innodb_file_format_check=default; -Warnings: -Warning 1210 Ignoring SET innodb_file_format=on select @@innodb_file_format_check; @@innodb_file_format_check Barracuda diff --git a/mysql-test/suite/innodb/t/innodb_bug47167.test b/mysql-test/suite/innodb/t/innodb_bug47167.test new file mode 100644 index 00000000000..df056b91ff9 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug47167.test @@ -0,0 +1,46 @@ +# This is the unit test for bug *47167. +# It tests setting the global variable +# "innodb_file_format_check" with a +# user-Defined Variable. + +--source include/have_innodb.inc +-- source suite/innodb/include/have_innodb_plugin.inc + +# Save the value (Antelope) in 'innodb_file_format_check' to +# 'old_innodb_file_format_check' +set @old_innodb_file_format_check=@@innodb_file_format_check; + +# @old_innodb_file_format_check shall have the value of 'Antelope' +select @old_innodb_file_format_check; + +# Reset the value in 'innodb_file_format_check' to 'Barracuda' +set global innodb_file_format_check = Barracuda; + +select @@innodb_file_format_check; + +# Set 'innodb_file_format_check' to its default value, which +# is the latest file format supported in the current release. +set global innodb_file_format_check = DEFAULT; + +select @@innodb_file_format_check; + +# Put the saved value back to 'innodb_file_format_check' +set global innodb_file_format_check = @old_innodb_file_format_check; + +# Check whether 'innodb_file_format_check' get its original value. +select @@innodb_file_format_check; + +# Following are negative tests, all should fail. +--disable_warnings +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = cheetah; + +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = Bear; + +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = on; + +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = off; +--enable_warnings diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 1ea22b60760..51d981d372c 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -269,10 +269,10 @@ innobase_file_format_check_on_off( /************************************************************//** Validate the file format check config parameters, as a side effect it sets the srv_check_file_format_at_startup variable. -@return true if valid config value */ +@return the format_id if valid config value, otherwise, return -1 */ static -bool -innobase_file_format_check_validate( +int +innobase_file_format_validate_and_set( /*================================*/ const char* format_check); /*!< in: parameter value */ /****************************************************************//** @@ -2146,8 +2146,8 @@ mem_free_and_error: /* Did the user specify a format name that we support ? As a side effect it will update the variable srv_check_file_format_at_startup */ - if (!innobase_file_format_check_validate( - innobase_file_format_check)) { + if (innobase_file_format_validate_and_set( + innobase_file_format_check) < 0) { sql_print_error("InnoDB: invalid " "innodb_file_format_check value: " @@ -9503,25 +9503,24 @@ innobase_file_format_check_on_off( /************************************************************//** Validate the file format check config parameters, as a side effect it sets the srv_check_file_format_at_startup variable. -@return true if valid config value */ +@return the format_id if valid config value, otherwise, return -1 */ static -bool -innobase_file_format_check_validate( +int +innobase_file_format_validate_and_set( /*================================*/ const char* format_check) /*!< in: parameter value */ { uint format_id; - bool ret = true; format_id = innobase_file_format_name_lookup(format_check); if (format_id < DICT_TF_FORMAT_MAX + 1) { srv_check_file_format_at_startup = format_id; - } else { - ret = false; - } - return(ret); + return((int) format_id); + } else { + return(-1); + } } /*************************************************************//** @@ -9556,7 +9555,11 @@ innodb_file_format_name_validate( if (format_id <= DICT_TF_FORMAT_MAX) { - *static_cast(save) = file_format_input; + /* Save a pointer to the name in the + 'file_format_name_map' constant array. */ + *static_cast(save) = + trx_sys_file_format_id_to_name(format_id); + return(0); } } @@ -9619,6 +9622,7 @@ innodb_file_format_check_validate( const char* file_format_input; char buff[STRING_BUFFER_USUAL_SIZE]; int len = sizeof(buff); + int format_id; ut_a(save != NULL); ut_a(value != NULL); @@ -9631,24 +9635,35 @@ innodb_file_format_check_validate( message if they did so. */ if (innobase_file_format_check_on_off(file_format_input)) { - sql_print_warning( + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, "InnoDB: invalid innodb_file_format_check " "value; on/off can only be set at startup or " "in the configuration file"); - } else if (innobase_file_format_check_validate( - file_format_input)) { - - *static_cast(save) = file_format_input; - - return(0); - } else { - sql_print_warning( - "InnoDB: invalid innodb_file_format_check " - "value; can be any format up to %s " - "or its equivalent numeric id", - trx_sys_file_format_id_to_name( - DICT_TF_FORMAT_MAX)); + format_id = innobase_file_format_validate_and_set( + file_format_input); + + if (format_id >= 0) { + /* Save a pointer to the name in the + 'file_format_name_map' constant array. */ + *static_cast(save) = + trx_sys_file_format_id_to_name( + (uint)format_id); + + return(0); + + } else { + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: invalid innodb_file_format_check " + "value; can be any format up to %s " + "or its equivalent numeric id", + trx_sys_file_format_id_to_name( + DICT_TF_FORMAT_MAX)); + } } } @@ -9918,12 +9933,15 @@ static MYSQL_SYSVAR_STR(file_format, innobase_file_format_name, innodb_file_format_name_validate, innodb_file_format_name_update, "Antelope"); +/* If a new file format is introduced, the file format +name needs to be updated accordingly. Please refer to +file_format_name_map[] defined in trx0sys.c for the next +file format name. */ static MYSQL_SYSVAR_STR(file_format_check, innobase_file_format_check, PLUGIN_VAR_OPCMDARG, "The highest file format in the tablespace.", innodb_file_format_check_validate, - innodb_file_format_check_update, - "on"); + innodb_file_format_check_update, "Barracuda"); static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit, PLUGIN_VAR_OPCMDARG, From 0278748ed8875e58eb72a6b2049682ff4e5c9caf Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 17:34:09 +0530 Subject: [PATCH 113/344] Applying InnoDB Plugin 1.0.6 snapshot, part 4. Fixes BUG#3139 applied revisions: r6160 Detailed revision comments: r6160 | vasil | 2009-11-11 15:33:49 +0200 (Wed, 11 Nov 2009) | 72 lines branches/zip: Merge r6152:6159 from branches/5.1: (r6158 was skipped as an equivallent change has already been merged from MySQL) ------------------------------------------------------------------------ r6154 | calvin | 2009-11-11 02:51:17 +0200 (Wed, 11 Nov 2009) | 17 lines Changed paths: M /branches/5.1/include/os0file.h M /branches/5.1/os/os0file.c branches/5.1: fix bug#3139: Mysql crashes: 'windows error 995' after several selects on a large DB During stress environment, Windows AIO may fail with error code ERROR_OPERATION_ABORTED. InnoDB does not handle the error, rather crashes. The cause of the error is unknown, but likely due to faulty hardware or driver. This patch introduces a new error code OS_FILE_OPERATION_ABORTED, which maps to Windows ERROR_OPERATION_ABORTED (995). When the error is detected during AIO, the InnoDB will issue a synchronous retry (read/write). This patch has been extensively tested by MySQL support. Approved by: Marko rb://196 ------------------------------------------------------------------------ r6158 | vasil | 2009-11-11 14:52:14 +0200 (Wed, 11 Nov 2009) | 37 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc M /branches/5.1/handler/ha_innodb.h branches/5.1: Merge a change from MySQL: (this has been reviewed by Calvin and Marko, and Calvin says Luis has incorporated Marko's suggestions) ------------------------------------------------------------ revno: 3092.5.1 committer: Luis Soares branch nick: mysql-5.1-bugteam timestamp: Thu 2009-09-24 15:52:52 +0100 message: BUG#42829: binlogging enabled for all schemas regardless of binlog-db-db / binlog-ignore-db InnoDB will return an error if statement based replication is used along with transaction isolation level READ-COMMITTED (or weaker), even if the statement in question is filtered out according to the binlog-do-db rules set. In this case, an error should not be printed. This patch addresses this issue by extending the existing check in external_lock to take into account the filter rules before deciding to print an error. Furthermore, it also changes decide_logging_format to take into consideration whether the statement is filtered out from binlog before decision is made. added: mysql-test/suite/binlog/r/binlog_stm_do_db.result mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt mysql-test/suite/binlog/t/binlog_stm_do_db.test modified: sql/sql_base.cc sql/sql_class.cc storage/innobase/handler/ha_innodb.cc storage/innobase/handler/ha_innodb.h storage/innodb_plugin/handler/ha_innodb.cc storage/innodb_plugin/handler/ha_innodb.h ------------------------------------------------------------------------ --- storage/innodb_plugin/include/os0file.h | 1 + storage/innodb_plugin/os/os0file.c | 54 ++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/storage/innodb_plugin/include/os0file.h b/storage/innodb_plugin/include/os0file.h index c06b28187d7..16568579f31 100644 --- a/storage/innodb_plugin/include/os0file.h +++ b/storage/innodb_plugin/include/os0file.h @@ -158,6 +158,7 @@ log. */ #define OS_FILE_SHARING_VIOLATION 76 #define OS_FILE_ERROR_NOT_SPECIFIED 77 #define OS_FILE_INSUFFICIENT_RESOURCE 78 +#define OS_FILE_OPERATION_ABORTED 79 /* @} */ /** Types for aio operations @{ */ diff --git a/storage/innodb_plugin/os/os0file.c b/storage/innodb_plugin/os/os0file.c index a3d0b0a10d0..37edad442db 100644 --- a/storage/innodb_plugin/os/os0file.c +++ b/storage/innodb_plugin/os/os0file.c @@ -323,6 +323,13 @@ os_file_get_last_error( "InnoDB: The error means that there are no" " sufficient system resources or quota to" " complete the operation.\n"); + } else if (err == ERROR_OPERATION_ABORTED) { + fprintf(stderr, + "InnoDB: The error means that the I/O" + " operation has been aborted\n" + "InnoDB: because of either a thread exit" + " or an application request.\n" + "InnoDB: Retry attempt is made.\n"); } else { fprintf(stderr, "InnoDB: Some operating system error numbers" @@ -347,6 +354,8 @@ os_file_get_last_error( } else if (err == ERROR_WORKING_SET_QUOTA || err == ERROR_NO_SYSTEM_RESOURCES) { return(OS_FILE_INSUFFICIENT_RESOURCE); + } else if (err == ERROR_OPERATION_ABORTED) { + return(OS_FILE_OPERATION_ABORTED); } else { return(100 + err); } @@ -467,6 +476,10 @@ os_file_handle_error_cond_exit( return(TRUE); } else if (err == OS_FILE_INSUFFICIENT_RESOURCE) { + os_thread_sleep(100000); /* 100 ms */ + return(TRUE); + } else if (err == OS_FILE_OPERATION_ABORTED) { + os_thread_sleep(100000); /* 100 ms */ return(TRUE); } else { @@ -3766,6 +3779,7 @@ os_aio_windows_handle( ibool ret_val; BOOL ret; DWORD len; + BOOL retry = FALSE; if (segment == ULINT_UNDEFINED) { array = os_aio_sync_array; @@ -3819,14 +3833,52 @@ os_aio_windows_handle( ut_a(TRUE == os_file_flush(slot->file)); } #endif /* UNIV_DO_FLUSH */ + } else if (os_file_handle_error(slot->name, "Windows aio")) { + + retry = TRUE; } else { - os_file_handle_error(slot->name, "Windows aio"); ret_val = FALSE; } os_mutex_exit(array->mutex); + if (retry) { + /* retry failed read/write operation synchronously. + No need to hold array->mutex. */ + + switch (slot->type) { + case OS_FILE_WRITE: + ret = WriteFile(slot->file, slot->buf, + slot->len, &len, + &(slot->control)); + + break; + case OS_FILE_READ: + ret = ReadFile(slot->file, slot->buf, + slot->len, &len, + &(slot->control)); + + break; + default: + ut_error; + } + + if (!ret && GetLastError() == ERROR_IO_PENDING) { + /* aio was queued successfully! + We want a synchronous i/o operation on a + file where we also use async i/o: in Windows + we must use the same wait mechanism as for + async i/o */ + + ret = GetOverlappedResult(slot->file, + &(slot->control), + &len, TRUE); + } + + ret_val = ret && len == slot->len; + } + os_aio_array_free_slot(array, slot); return(ret_val); From f77d7aaebb80a21df0e271d841ba0d6935069a65 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 17:41:36 +0530 Subject: [PATCH 114/344] Applying InnoDB Plugin 1.0.6 snapshot, part 5. applied revisions: r6161, r6162, r6163 Detailed revision comments: r6161 | vasil | 2009-11-11 15:36:16 +0200 (Wed, 11 Nov 2009) | 4 lines branches/zip: Add changelog entry for r6160. r6162 | vasil | 2009-11-11 16:00:12 +0200 (Wed, 11 Nov 2009) | 4 lines branches/zip: Add ChangeLog for r6157. r6163 | calvin | 2009-11-11 17:53:20 +0200 (Wed, 11 Nov 2009) | 8 lines branches/zip: Exclude thd_binlog_filter_ok() when building with older version of MySQL. thd_binlog_filter_ok() is introduced in MySQL 5.1.41. But the plugin can be built with MySQL prior to 5.1.41. Approved by Heikki (on IM). --- storage/innodb_plugin/ChangeLog | 13 +++++++++++++ storage/innodb_plugin/handler/ha_innodb.cc | 5 ++++- storage/innodb_plugin/handler/ha_innodb.h | 2 ++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 682d369b854..5363cbf45c0 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,16 @@ +2009-11-11 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb_bug47167.result, + mysql-test/innodb_bug47167.test, mysql-test/innodb_file_format.result: + Fix Bug#47167 "set global innodb_file_format_check" cannot set value + by User-Defined Variable + +2009-11-11 The InnoDB Team + + * include/os0file.h, os/os0file.c: + Fix Bug#3139 Mysql crashes: 'windows error 995' after several selects + on a large DB + 2009-11-04 The InnoDB Team * handler/ha_innodb.cc: diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 51d981d372c..44cc73497c2 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -7912,7 +7912,10 @@ ha_innobase::external_lock( ulong const tx_isolation = thd_tx_isolation(ha_thd()); if (tx_isolation <= ISO_READ_COMMITTED && binlog_format == BINLOG_FORMAT_STMT - && thd_binlog_filter_ok(thd)) +#if MYSQL_VERSION_ID > 50140 + && thd_binlog_filter_ok(thd) +#endif /* MYSQL_VERSION_ID > 50140 */ + ) { char buf[256]; my_snprintf(buf, sizeof(buf), diff --git a/storage/innodb_plugin/handler/ha_innodb.h b/storage/innodb_plugin/handler/ha_innodb.h index 4779651ee27..31e88ed8530 100644 --- a/storage/innodb_plugin/handler/ha_innodb.h +++ b/storage/innodb_plugin/handler/ha_innodb.h @@ -258,12 +258,14 @@ int thd_binlog_format(const MYSQL_THD thd); */ void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all); +#if MYSQL_VERSION_ID > 50140 /** Check if binary logging is filtered for thread's current db. @param thd Thread handle @retval 1 the query is not filtered, 0 otherwise. */ bool thd_binlog_filter_ok(const MYSQL_THD thd); +#endif /* MYSQL_VERSION_ID > 50140 */ } typedef struct trx_struct trx_t; From 444c6d0d73afae6efb1f7d8976b34f5b9a711bfc Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 17:54:54 +0530 Subject: [PATCH 115/344] Applying InnoDB Plugin 1.0.6 snapshot, part 6. Add Testcase for BUG#46676 1. add testcase for BUG#46676 2. Allow CREATE INDEX to be interrupted 3. ha_innobase::change_active_index(): When the history is missing, report it to the client, not to the error log 4. ChangeLog entries appplied revisions:r6169, r6170, r6175, r6177, r6179 Detailed revision comments: r6169 | calvin | 2009-11-12 14:40:43 +0200 (Thu, 12 Nov 2009) | 6 lines branches/zip: add test case for bug#46676 This crash is reproducible with InnoDB plugin 1.0.4 + MySQL 5.1.37. But no longer reproducible after MySQL 5.1.38 (with plugin 1.0.5). Add test case to catch future regression. r6170 | marko | 2009-11-12 15:49:08 +0200 (Thu, 12 Nov 2009) | 4 lines branches/zip: Allow CREATE INDEX to be interrupted. (Issue #354) rb://183 approved by Heikki Tuuri r6175 | vasil | 2009-11-16 20:07:39 +0200 (Mon, 16 Nov 2009) | 4 lines branches/zip: Wrap line at 78th char in the ChangeLog r6177 | calvin | 2009-11-16 20:20:38 +0200 (Mon, 16 Nov 2009) | 2 lines branches/zip: add an entry to ChangeLog for r6065 r6179 | marko | 2009-11-17 10:19:34 +0200 (Tue, 17 Nov 2009) | 2 lines branches/zip: ha_innobase::change_active_index(): When the history is missing, report it to the client, not to the error log. --- .../suite/innodb/r/innodb_bug46676.result | 9 +++++++ .../suite/innodb/t/innodb_bug46676.test | 16 ++++++++++++ storage/innodb_plugin/ChangeLog | 13 ++++++++++ storage/innodb_plugin/handler/ha_innodb.cc | 19 ++++++++++---- storage/innodb_plugin/include/db0err.h | 1 + storage/innodb_plugin/row/row0merge.c | 25 +++++++++++++++++-- storage/innodb_plugin/row/row0mysql.c | 1 + 7 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_bug46676.result create mode 100644 mysql-test/suite/innodb/t/innodb_bug46676.test diff --git a/mysql-test/suite/innodb/r/innodb_bug46676.result b/mysql-test/suite/innodb/r/innodb_bug46676.result new file mode 100644 index 00000000000..996799ce931 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug46676.result @@ -0,0 +1,9 @@ +SET foreign_key_checks=0; +CREATE TABLE t1 (id int, foreign key (id) references t2(id)) ENGINE=INNODB; +CREATE TABLE t2 (id int, foreign key (id) references t1(id)) ENGINE=INNODB; +SET foreign_key_checks=1; +SELECT COUNT(*) FROM information_schema.key_column_usage WHERE REFERENCED_TABLE_NAME in ('t1', 't2'); +COUNT(*) +2 +SET foreign_key_checks=0; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/innodb/t/innodb_bug46676.test b/mysql-test/suite/innodb/t/innodb_bug46676.test new file mode 100644 index 00000000000..440666c4226 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug46676.test @@ -0,0 +1,16 @@ +# This is the test for bug 46676: mysqld got exception 0xc0000005 +# It is reproducible with InnoDB plugin 1.0.4 + MySQL 5.1.37. +# But no longer reproducible after MySQL 5.1.38 (with plugin 1.0.5). + +--source include/have_innodb.inc + +SET foreign_key_checks=0; +CREATE TABLE t1 (id int, foreign key (id) references t2(id)) ENGINE=INNODB; +CREATE TABLE t2 (id int, foreign key (id) references t1(id)) ENGINE=INNODB; +SET foreign_key_checks=1; + +# Server crashes +SELECT COUNT(*) FROM information_schema.key_column_usage WHERE REFERENCED_TABLE_NAME in ('t1', 't2'); + +SET foreign_key_checks=0; +DROP TABLE t1, t2; diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 5363cbf45c0..840548aed21 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,10 @@ +2009-11-12 The InnoDB Team + + * handler/ha_innodb.cc, include/db0err.h, row/row0merge.c, + row/row0mysql.c: + Allow CREATE INDEX to be interrupted. + Also, when CHECK TABLE is interrupted, report ER_QUERY_INTERRUPTED. + 2009-11-11 The InnoDB Team * handler/ha_innodb.cc, mysql-test/innodb_bug47167.result, @@ -104,6 +111,12 @@ Fix Bug#47058 Failure to compile innodb_plugin on solaris 10u7 + spro cc/CC 5.10 +2009-10-13 The InnoDB Team + + * buf/buf0flu.c: + Call fsync() on datafiles after a batch of pages is written to disk + even when skip_innodb_doublewrite is set. + 2009-10-05 The InnoDB Team * buf/buf0buf.c: diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 44cc73497c2..7b5b66eaf26 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -785,6 +785,9 @@ convert_error_code_to_mysql( case DB_SUCCESS: return(0); + case DB_INTERRUPTED: + my_error(ER_QUERY_INTERRUPTED, MYF(0)); + /* fall through */ case DB_ERROR: default: return(-1); /* unspecified error */ @@ -5238,8 +5241,10 @@ ha_innobase::change_active_index( prebuilt->index); if (UNIV_UNLIKELY(!prebuilt->index_usable)) { - sql_print_warning("InnoDB: insufficient history for index %u", - keynr); + push_warning_printf(user_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_TABLE_DEF_CHANGED, + "InnoDB: insufficient history for index %u", + keynr); /* The caller seems to ignore this. Thus, we must check this again in row_search_for_mysql(). */ DBUG_RETURN(2); @@ -7361,11 +7366,15 @@ ha_innobase::check( ret = row_check_table_for_mysql(prebuilt); - if (ret == DB_SUCCESS) { + switch (ret) { + case DB_SUCCESS: return(HA_ADMIN_OK); + case DB_INTERRUPTED: + my_error(ER_QUERY_INTERRUPTED, MYF(0)); + return(-1); + default: + return(HA_ADMIN_CORRUPT); } - - return(HA_ADMIN_CORRUPT); } /*************************************************************//** diff --git a/storage/innodb_plugin/include/db0err.h b/storage/innodb_plugin/include/db0err.h index 23898583b72..747e9b5364e 100644 --- a/storage/innodb_plugin/include/db0err.h +++ b/storage/innodb_plugin/include/db0err.h @@ -32,6 +32,7 @@ enum db_err { /* The following are error codes */ DB_ERROR, + DB_INTERRUPTED, DB_OUT_OF_MEMORY, DB_OUT_OF_FILE_SPACE, DB_LOCK_WAIT, diff --git a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c index a303a2f3278..25f041c0885 100644 --- a/storage/innodb_plugin/row/row0merge.c +++ b/storage/innodb_plugin/row/row0merge.c @@ -1200,6 +1200,12 @@ row_merge_read_clustered_index( in order to release the latch on the old page. */ if (btr_pcur_is_after_last_on_page(&pcur)) { + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + i = 0; + err = DB_INTERRUPTED; + goto err_exit; + } + btr_pcur_store_position(&pcur, &mtr); mtr_commit(&mtr); mtr_start(&mtr); @@ -1557,6 +1563,7 @@ static __attribute__((nonnull)) ulint row_merge( /*======*/ + trx_t* trx, /*!< in: transaction */ const dict_index_t* index, /*!< in: index being created */ merge_file_t* file, /*!< in/out: file containing index entries */ @@ -1590,6 +1597,10 @@ row_merge( for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) { ulint ahalf; /*!< arithmetic half the input file */ + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + return(DB_INTERRUPTED); + } + error = row_merge_blocks(index, file, block, &foffs0, &foffs1, &of, table); @@ -1617,6 +1628,10 @@ row_merge( /* Copy the last blocks, if there are any. */ while (foffs0 < ihalf) { + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + return(DB_INTERRUPTED); + } + if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) { return(DB_CORRUPTION); } @@ -1625,6 +1640,10 @@ row_merge( ut_ad(foffs0 == ihalf); while (foffs1 < file->offset) { + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + return(DB_INTERRUPTED); + } + if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) { return(DB_CORRUPTION); } @@ -1653,6 +1672,7 @@ static ulint row_merge_sort( /*===========*/ + trx_t* trx, /*!< in: transaction */ const dict_index_t* index, /*!< in: index being created */ merge_file_t* file, /*!< in/out: file containing index entries */ @@ -1671,7 +1691,8 @@ row_merge_sort( do { ulint error; - error = row_merge(index, file, &half, block, tmpfd, table); + error = row_merge(trx, index, file, &half, + block, tmpfd, table); if (error != DB_SUCCESS) { return(error); @@ -2490,7 +2511,7 @@ row_merge_build_indexes( sorting and inserting. */ for (i = 0; i < n_indexes; i++) { - error = row_merge_sort(indexes[i], &merge_files[i], + error = row_merge_sort(trx, indexes[i], &merge_files[i], block, &tmpfd, table); if (error == DB_SUCCESS) { diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index 540a4450045..9c17f9a2b24 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -4157,6 +4157,7 @@ row_check_table_for_mysql( } if (trx_is_interrupted(prebuilt->trx)) { + ret = DB_INTERRUPTED; break; } From d813b4304844a9bf430dc08c550b3f91cb8af18b Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 18:19:13 +0530 Subject: [PATCH 116/344] Applying InnoDB Plugin 1.0.6 snapshot, part 7 Fixes several test cases. applied revisions: r6181, r6182, r6183, r6184 r6183 - changes are made only to tests in innodb suite which is only innodb-consistent-master.opt Detailed revision comments: r6181 | vasil | 2009-11-17 12:21:41 +0200 (Tue, 17 Nov 2009) | 33 lines branches/zip: At the end of innodb-index.test: restore the environment as it was before the test was started to silence this warning: MTR's internal check of the test case 'main.innodb-index' failed. This means that the test case does not preserve the state that existed before the test case was executed. Most likely the test case did not do a proper clean-up. This is the diff of the states of the servers before and after the test case was executed: mysqltest: Logging to '/tmp/autotest.sh-20091117_033000-zip.btyZwu/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.log'. mysqltest: Results saved in '/tmp/autotest.sh-20091117_033000-zip.btyZwu/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.result'. mysqltest: Connecting to server localhost:13000 (socket /tmp/autotest.sh-20091117_033000-zip.btyZwu/mysql-5.1/mysql-test/var/tmp/mysqld.1.sock) as 'root', connection 'default', attempt 0 ... mysqltest: ... Connected. mysqltest: Start processing test commands from './include/check-testcase.test' ... mysqltest: ... Done processing test commands. --- /tmp/autotest.sh-20091117_033000-zip.btyZwu/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.result 2009-11-17 13:10:40.000000000 +0300 +++ /tmp/autotest.sh-20091117_033000-zip.btyZwu/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.reject 2009-11-17 13:10:54.000000000 +0300 @@ -84,7 +84,7 @@ INNODB_DOUBLEWRITE ON INNODB_FAST_SHUTDOWN 1 INNODB_FILE_FORMAT Antelope -INNODB_FILE_FORMAT_CHECK Antelope +INNODB_FILE_FORMAT_CHECK Barracuda INNODB_FILE_PER_TABLE OFF INNODB_FLUSH_LOG_AT_TRX_COMMIT 1 INNODB_FLUSH_METHOD mysqltest: Result content mismatch not ok r6182 | marko | 2009-11-17 13:49:15 +0200 (Tue, 17 Nov 2009) | 1 line branches/zip: Set svn:eol-style on mysql-test files. r6183 | marko | 2009-11-17 13:51:16 +0200 (Tue, 17 Nov 2009) | 1 line branches/zip: Prepend loose_ to plugin-only mysql-test options. r6184 | marko | 2009-11-17 13:52:01 +0200 (Tue, 17 Nov 2009) | 1 line branches/zip: innodb-index.test: Restore innodb_file_format_check. --- mysql-test/suite/innodb/r/innodb-index.result | 1 + mysql-test/suite/innodb/t/innodb-consistent-master.opt | 2 +- mysql-test/suite/innodb/t/innodb-index.test | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result index a7d66b15300..67fbe0dce02 100644 --- a/mysql-test/suite/innodb/r/innodb-index.result +++ b/mysql-test/suite/innodb/r/innodb-index.result @@ -968,6 +968,7 @@ create index t1u on t1 (u(1)); drop table t1; set global innodb_file_per_table=0; set global innodb_file_format=Antelope; +set global innodb_file_format_check=Antelope; SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; CREATE TABLE t1( diff --git a/mysql-test/suite/innodb/t/innodb-consistent-master.opt b/mysql-test/suite/innodb/t/innodb-consistent-master.opt index e76299453d3..cb48f1aaf60 100644 --- a/mysql-test/suite/innodb/t/innodb-consistent-master.opt +++ b/mysql-test/suite/innodb/t/innodb-consistent-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/suite/innodb/t/innodb-index.test b/mysql-test/suite/innodb/t/innodb-index.test index 54aff3a42c0..b5dd2e037e7 100644 --- a/mysql-test/suite/innodb/t/innodb-index.test +++ b/mysql-test/suite/innodb/t/innodb-index.test @@ -1,5 +1,7 @@ -- source include/have_innodb.inc +let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; + create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb; insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak'); commit; @@ -398,6 +400,7 @@ create index t1u on t1 (u(1)); drop table t1; eval set global innodb_file_per_table=$per_table; eval set global innodb_file_format=$format; +eval set global innodb_file_format_check=$format; # # Test to check whether CREATE INDEX handles implicit foreign key @@ -532,3 +535,10 @@ disconnect a; disconnect b; DROP TABLE t1; + +# +# restore environment to the state it was before this test execution +# + +-- disable_query_log +eval SET GLOBAL innodb_file_format_check=$innodb_file_format_check_orig; From 1e26b2c26b4eccf359f7e3cb325604a087f5b9d3 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 18:43:34 +0530 Subject: [PATCH 117/344] Applying InnoDB Plugin 1.0.6 snapshot, part 8. Fixes BUG#48782 applied revisions: r6185, r6186, r6189, r6194 r6185 - only code changes incorporated, changesets which change innodb tests in the main mysql suite are discarded r61889 - Fixes BUG#48782 Detailed revision comments: r6185 | marko | 2009-11-17 16:44:20 +0200 (Tue, 17 Nov 2009) | 16 lines branches/zip: Report duplicate table names to the client connection, not to the error log. This change will allow innodb-index.test to be re-enabled. It was previously disabled, because mysql-test-run does not like output in the error log. row_create_table_for_mysql(): Do not output anything to the error log when reporting DB_DUPLICATE_KEY. Let the caller report the error. Add a TODO comment that the dict_table_t object is apparently not freed when an error occurs. create_table_def(): Convert InnoDB table names to the character set of the client connection for reporting. Use my_error(ER_WRONG_COLUMN_NAME) for reporting reserved column names. Report my_error(ER_TABLE_EXISTS_ERROR) when row_create_table_for_mysql() returns DB_DUPLICATE_KEY. rb://206 r6186 | vasil | 2009-11-17 16:48:14 +0200 (Tue, 17 Nov 2009) | 4 lines branches/zip: Add ChangeLog entry for r6185. r6189 | marko | 2009-11-18 11:36:18 +0200 (Wed, 18 Nov 2009) | 5 lines branches/zip: ha_innobase::add_index(): When creating the primary key and the table is being locked by another transaction, do not attempt to drop the table. (Bug #48782) Approved by Sunny Bains over IM r6194 | vasil | 2009-11-19 09:24:45 +0200 (Thu, 19 Nov 2009) | 5 lines branches/zip: Increment version number from 1.0.5 to 1.0.6 since 1.0.5 was just released by MySQL and we will soon release 1.0.6. --- mysql-test/lib/mtr_cases.pm | 2 ++ storage/innodb_plugin/ChangeLog | 15 +++++++++++ storage/innodb_plugin/handler/ha_innodb.cc | 21 +++++++-------- .../innodb_plugin/handler/handler0alter.cc | 4 ++- storage/innodb_plugin/include/univ.i | 2 +- storage/innodb_plugin/row/row0mysql.c | 27 ++----------------- 6 files changed, 33 insertions(+), 38 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 1f018f27f7b..ef3c2a43e87 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -522,6 +522,8 @@ sub collect_one_suite($) next if ($test->{'name'} eq 'main.innodb_bug46000'); # Fails with innodb plugin next if ($test->{'name'} eq 'main.innodb-autoinc'); + # Fails with innodb plugin: r6185 Testcases changes not included + next if ($test->{'name'} eq 'main.innodb_bug44369'); # Copy test options my $new_test= My::Test->new(); while (my ($key, $value) = each(%$test)) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 840548aed21..47c20fd9851 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,18 @@ +2009-11-18 The InnoDB Team + + * handler/handler0alter.cc: + Fix Bug#48782 On lock wait timeout, CREATE INDEX (creating primary key) + attempts DROP TABLE + +2009-11-17 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb.result, + mysql-test/innodb.test, mysql-test/innodb_bug44369.result, + mysql-test/innodb_bug44369.test, mysql-test/patches/innodb-index.diff, + row/row0mysql.c: + Report duplicate table names to the client connection, not to the + error log. + 2009-11-12 The InnoDB Team * handler/ha_innodb.cc, include/db0err.h, row/row0merge.c, diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 7b5b66eaf26..cc84bbf209d 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -5731,17 +5731,8 @@ create_table_def( /* First check whether the column to be added has a system reserved name. */ if (dict_col_name_is_reserved(field->field_name)){ - push_warning_printf( - (THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_CANT_CREATE_TABLE, - "Error creating table '%s' with " - "column name '%s'. '%s' is a " - "reserved name. Please try to " - "re-create the table with a " - "different column name.", - table->name, (char*) field->field_name, - (char*) field->field_name); + my_error(ER_WRONG_COLUMN_NAME, MYF(0), + field->field_name); dict_mem_table_free(table); trx_commit_for_mysql(trx); @@ -5763,6 +5754,14 @@ create_table_def( error = row_create_table_for_mysql(table, trx); + if (error == DB_DUPLICATE_KEY) { + char buf[100]; + innobase_convert_identifier(buf, sizeof buf, + table_name, strlen(table_name), + trx->mysql_thd, TRUE); + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), buf); + } + error_ret: error = convert_error_code_to_mysql(error, flags, NULL); diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc index 37aed06b28a..f32cb1d4093 100644 --- a/storage/innodb_plugin/handler/handler0alter.cc +++ b/storage/innodb_plugin/handler/handler0alter.cc @@ -882,7 +882,9 @@ error: /* fall through */ default: if (new_primary) { - row_merge_drop_table(trx, indexed_table); + if (indexed_table != innodb_table) { + row_merge_drop_table(trx, indexed_table); + } } else { if (!dict_locked) { row_mysql_lock_data_dictionary(trx); diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i index 5d0361658af..2081e136590 100644 --- a/storage/innodb_plugin/include/univ.i +++ b/storage/innodb_plugin/include/univ.i @@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 1 #define INNODB_VERSION_MINOR 0 -#define INNODB_VERSION_BUGFIX 5 +#define INNODB_VERSION_BUGFIX 6 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index 9c17f9a2b24..181c39de881 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -1880,6 +1880,8 @@ err_exit: if (UNIV_UNLIKELY(err != DB_SUCCESS)) { trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, NULL); + /* TO DO: free table? The code below will dereference + table->name, though. */ } switch (err) { @@ -1898,31 +1900,6 @@ err_exit: break; case DB_DUPLICATE_KEY: - ut_print_timestamp(stderr); - fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, TRUE, table->name); - fputs(" already exists in InnoDB internal\n" - "InnoDB: data dictionary. Have you deleted" - " the .frm file\n" - "InnoDB: and not used DROP TABLE?" - " Have you used DROP DATABASE\n" - "InnoDB: for InnoDB tables in" - " MySQL version <= 3.23.43?\n" - "InnoDB: See the Restrictions section" - " of the InnoDB manual.\n" - "InnoDB: You can drop the orphaned table" - " inside InnoDB by\n" - "InnoDB: creating an InnoDB table with" - " the same name in another\n" - "InnoDB: database and copying the .frm file" - " to the current database.\n" - "InnoDB: Then MySQL thinks the table exists," - " and DROP TABLE will\n" - "InnoDB: succeed.\n" - "InnoDB: You can look for further help from\n" - "InnoDB: " REFMAN "innodb-troubleshooting.html\n", - stderr); - /* We may also get err == DB_ERROR if the .ibd file for the table already exists */ From 699af6da3a7fac5db59dd134f936cc304e0d3c6c Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 19:05:20 +0530 Subject: [PATCH 118/344] Applying InnoDB Plugin 1.0.6 snapshot, part 9. Fixes BUG#48526, BUG#48317 applied revisions: r6197, r6198, r6199 r6197 - BUG#48317 r6199 - BUG#48526 Detailed revision comments: r6197 | calvin | 2009-11-19 09:32:55 +0200 (Thu, 19 Nov 2009) | 6 lines branches/zip: merge the fix of bug#48317 (CMake file) Due to MySQL changes to the CMake, it is no longer able to build InnoDB plugin as a static library on Windows. The fix is proposed by Vlad of MySQL. r6198 | vasil | 2009-11-19 09:44:31 +0200 (Thu, 19 Nov 2009) | 4 lines branches/zip: Add ChangeLog entry for r6197. r6199 | vasil | 2009-11-19 12:10:12 +0200 (Thu, 19 Nov 2009) | 31 lines branches/zip: Merge r6159:6198 from branches/5.1: ------------------------------------------------------------------------ r6187 | jyang | 2009-11-18 05:27:30 +0200 (Wed, 18 Nov 2009) | 9 lines Changed paths: M /branches/5.1/btr/btr0btr.c branches/5.1: Fix bug #48469 "when innodb tablespace is configured too small, crash and corruption!". Function btr_create() did not check the return status of fseg_create(), and continue the index creation even there is no sufficient space. rb://205 Approved by Marko ------------------------------------------------------------------------ r6188 | jyang | 2009-11-18 07:14:23 +0200 (Wed, 18 Nov 2009) | 8 lines Changed paths: M /branches/5.1/data/data0type.c branches/5.1: Fix bug #48526 "Data type for float and double is incorrectly reported in InnoDB table monitor". Certain datatypes are not printed correctly in dtype_print(). rb://204 Approved by Marko. ------------------------------------------------------------------------ --- storage/innodb_plugin/CMakeLists.txt | 12 +++++++++++- storage/innodb_plugin/ChangeLog | 17 +++++++++++++++++ storage/innodb_plugin/btr/btr0btr.c | 12 ++++++++++-- storage/innodb_plugin/data/data0type.c | 16 ++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/storage/innodb_plugin/CMakeLists.txt b/storage/innodb_plugin/CMakeLists.txt index 25cd212a473..21d83ea2b5f 100644 --- a/storage/innodb_plugin/CMakeLists.txt +++ b/storage/innodb_plugin/CMakeLists.txt @@ -81,4 +81,14 @@ SET(INNODB_PLUGIN_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c ut/ut0list.c ut/ut0wqueue.c) ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION) -MYSQL_STORAGE_ENGINE(INNODB_PLUGIN) + +IF (MYSQL_VERSION_ID GREATER "50137") + MYSQL_STORAGE_ENGINE(INNOBASE) + # Use ha_innodb for plugin name, if plugin is built + GET_TARGET_PROPERTY(LIB_LOCATION ha_innobase LOCATION) + IF(LIB_LOCATION) + SET_TARGET_PROPERTIES(ha_innobase PROPERTIES OUTPUT_NAME ha_innodb) + ENDIF(LIB_LOCATION) +ELSE (MYSQL_VERSION_ID GREATER "50137") + IF (NOT SOURCE_SUBLIBS) + ADD_DEFINITIONS(-D_WIN32 -DMYSQL_SERVER) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 47c20fd9851..b801a3c23b2 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,20 @@ +2009-11-19 The InnoDB Team + + * btr/btr0btr.c: + Fix Bug#48469 when innodb tablespace is configured too small, crash + and corruption! + +2009-11-19 The InnoDB Team + + * data/data0type.c: + Fix Bug#48526 Data type for float and double is incorrectly reported + in InnoDB table monitor + +2009-11-19 The InnoDB Team + + * CMakeLists.txt: + Fix Bug#48317 cannot build innodb as static library + 2009-11-18 The InnoDB Team * handler/handler0alter.cc: diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c index 94b34ecece1..9f06a41aa1e 100644 --- a/storage/innodb_plugin/btr/btr0btr.c +++ b/storage/innodb_plugin/btr/btr0btr.c @@ -790,8 +790,16 @@ btr_create( } else { /* It is a non-ibuf tree: create a file segment for leaf pages */ - fseg_create(space, page_no, - PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr); + if (!fseg_create(space, page_no, + PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { + /* Not enough space for new segment, free root + segment before return. */ + fseg_free(space, page_no, + PAGE_HEADER + PAGE_BTR_SEG_TOP); + + return(FIL_NULL); + } + /* The fseg create acquires a second latch on the page, therefore we must declare it: */ buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW); diff --git a/storage/innodb_plugin/data/data0type.c b/storage/innodb_plugin/data/data0type.c index 8429775e7d8..e834fd2ec55 100644 --- a/storage/innodb_plugin/data/data0type.c +++ b/storage/innodb_plugin/data/data0type.c @@ -237,6 +237,22 @@ dtype_print( fputs("DATA_SYS", stderr); break; + case DATA_FLOAT: + fputs("DATA_FLOAT", stderr); + break; + + case DATA_DOUBLE: + fputs("DATA_DOUBLE", stderr); + break; + + case DATA_DECIMAL: + fputs("DATA_DECIMAL", stderr); + break; + + case DATA_VARMYSQL: + fputs("DATA_VARMYSQL", stderr); + break; + default: fprintf(stderr, "type %lu", (ulong) mtype); break; From 3606e59cfefbc3f0ed64c45e55bd1289abb9bf64 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 19:12:26 +0530 Subject: [PATCH 119/344] Applying InnoDB Plugin 1.0.6 snapshot, Fixes BUG#48469 applied revisions: r6201, r6202, r6207, r6208, r6210 r6202 - port fix for BUG#48469 to plugin Detailed revision comments: r6201 | marko | 2009-11-19 14:09:11 +0200 (Thu, 19 Nov 2009) | 2 lines branches/zip: ha_innobase::add_index(): Clarify the comment on orphaned tables when creating a primary key. r6202 | jyang | 2009-11-19 15:01:00 +0200 (Thu, 19 Nov 2009) | 8 lines branches/zip: Function fseg_free() is no longer defined in branches/zip. To port fix for bug #48469 to zip, we can use btr_free_root() which frees the page, and also does not require mini-transaction. Approved by Marko. r6207 | vasil | 2009-11-20 10:19:14 +0200 (Fri, 20 Nov 2009) | 54 lines branches/zip: Merge r6198:6206 from branches/5.1: (r6203 was skipped as it is already in branches/zip) ------------------------------------------------------------------------ r6200 | vasil | 2009-11-19 12:14:23 +0200 (Thu, 19 Nov 2009) | 4 lines Changed paths: M /branches/5.1/btr/btr0btr.c branches/5.1: White space fixup - indent under the opening ( ------------------------------------------------------------------------ r6203 | jyang | 2009-11-19 15:12:22 +0200 (Thu, 19 Nov 2009) | 8 lines Changed paths: M /branches/5.1/btr/btr0btr.c branches/5.1: Use btr_free_root() instead of fseg_free() for the fix of bug #48469, because fseg_free() is not defined in the zip branch. And we could save one mini-trasaction started by fseg_free(). Approved by Marko. ------------------------------------------------------------------------ r6205 | jyang | 2009-11-20 07:55:48 +0200 (Fri, 20 Nov 2009) | 11 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: Add a special case to handle the Duplicated Key error and return DB_ERROR instead. This is to avoid a possible SIGSEGV by mysql error handling re-entering the storage layer for dup key info without proper table handle. This is to prevent a server crash when error situation in bug #45961 "DDL on partitioned innodb tables leaves data dictionary in an inconsistent state" happens. rb://157 approved by Sunny Bains. ------------------------------------------------------------------------ r6206 | jyang | 2009-11-20 09:38:43 +0200 (Fri, 20 Nov 2009) | 5 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: Fix a minor code formating issue for the parenthesis iplacement of the if condition in rename_table(). ------------------------------------------------------------------------ r6208 | vasil | 2009-11-20 10:49:24 +0200 (Fri, 20 Nov 2009) | 4 lines branches/zip: Add ChangeLog entry for c6207. r6210 | vasil | 2009-11-20 23:39:48 +0200 (Fri, 20 Nov 2009) | 3 lines branches/zip: Whitespace fixup. --- storage/innodb_plugin/ChangeLog | 7 ++++++ storage/innodb_plugin/btr/btr0btr.c | 3 +-- storage/innodb_plugin/handler/ha_innodb.cc | 24 +++++++++++++++++++ .../innodb_plugin/handler/handler0alter.cc | 9 +++---- storage/innodb_plugin/trx/trx0i_s.c | 2 +- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index b801a3c23b2..1a6e07fd147 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,10 @@ +2009-11-20 The InnoDB Team + + * handler/ha_innodb.cc: + Add a workaround to prevent a crash due to Bug#45961 DDL on + partitioned innodb tables leaves data dictionary in an inconsistent + state + 2009-11-19 The InnoDB Team * btr/btr0btr.c: diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c index 9f06a41aa1e..086b3a0a599 100644 --- a/storage/innodb_plugin/btr/btr0btr.c +++ b/storage/innodb_plugin/btr/btr0btr.c @@ -794,8 +794,7 @@ btr_create( PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { /* Not enough space for new segment, free root segment before return. */ - fseg_free(space, page_no, - PAGE_HEADER + PAGE_BTR_SEG_TOP); + btr_free_root(space, zip_size, page_no, mtr); return(FIL_NULL); } diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index cc84bbf209d..0dc845f83e0 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -793,6 +793,12 @@ convert_error_code_to_mysql( return(-1); /* unspecified error */ case DB_DUPLICATE_KEY: + /* Be cautious with returning this error, since + mysql could re-enter the storage layer to get + duplicated key info, the operation requires a + valid table handle and/or transaction information, + which might not always be available in the error + handling stage. */ return(HA_ERR_FOUND_DUPP_KEY); case DB_FOREIGN_DUPLICATE_KEY: @@ -6815,6 +6821,24 @@ ha_innobase::rename_table( innobase_commit_low(trx); trx_free_for_mysql(trx); + /* Add a special case to handle the Duplicated Key error + and return DB_ERROR instead. + This is to avoid a possible SIGSEGV error from mysql error + handling code. Currently, mysql handles the Duplicated Key + error by re-entering the storage layer and getting dup key + info by calling get_dup_key(). This operation requires a valid + table handle ('row_prebuilt_t' structure) which could no + longer be available in the error handling stage. The suggested + solution is to report a 'table exists' error message (since + the dup key error here is due to an existing table whose name + is the one we are trying to rename to) and return the generic + error code. */ + if (error == (int) DB_DUPLICATE_KEY) { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to); + + error = DB_ERROR; + } + error = convert_error_code_to_mysql(error, 0, NULL); DBUG_RETURN(error); diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc index f32cb1d4093..a5008991400 100644 --- a/storage/innodb_plugin/handler/handler0alter.cc +++ b/storage/innodb_plugin/handler/handler0alter.cc @@ -765,10 +765,11 @@ err_exit: ut_ad(error == DB_SUCCESS); /* Commit the data dictionary transaction in order to release - the table locks on the system tables. Unfortunately, this - means that if MySQL crashes while creating a new primary key - inside row_merge_build_indexes(), indexed_table will not be - dropped on crash recovery. Thus, it will become orphaned. */ + the table locks on the system tables. This means that if + MySQL crashes while creating a new primary key inside + row_merge_build_indexes(), indexed_table will not be dropped + by trx_rollback_active(). It will have to be recovered or + dropped by the database administrator. */ trx_commit_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); diff --git a/storage/innodb_plugin/trx/trx0i_s.c b/storage/innodb_plugin/trx/trx0i_s.c index 12562b40726..ef2e6850d6c 100644 --- a/storage/innodb_plugin/trx/trx0i_s.c +++ b/storage/innodb_plugin/trx/trx0i_s.c @@ -60,7 +60,7 @@ Created July 17, 2007 Vasil Dimov /** @brief The maximum number of chunks to allocate for a table cache. The rows of a table cache are stored in a set of chunks. When a new -row is added a new chunk is allocated if necessary. Assuming that the +row is added a new chunk is allocated if necessary. Assuming that the first one is 1024 rows (TABLE_CACHE_INITIAL_ROWSNUM) and each subsequent is N/2 where N is the number of rows we have allocated till now, then 39th chunk would accommodate 1677416425 rows and all chunks From f5b71849196e8d95a8688d31180179597ffae3ec Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Dec 2009 16:27:21 +0800 Subject: [PATCH 120/344] Updated experimental test list for rpl.rpl_cross_version and rpl.rpl_get_master_version_and_clock. --- mysql-test/collections/default.experimental | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index a0fa2a30a69..9fc39a8d780 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -18,8 +18,8 @@ main.plugin_load @solaris # Bug#42144 ndb.* # joro : NDB tests marked as experimental as agreed with bochklin -rpl.rpl_cross_version* # Bug #43913 2009-10-26 joro rpl_cross_version can't pass on conflicts complainig clash with --slave-load-tm -rpl.rpl_get_master_version_and_clock* # Bug#46931 2009-08-26 alik rpl.rpl_get_master_version_and_clock fails on hpux11.31 +rpl.rpl_cross_version* # Bug#48340 2009-12-01 Daogang rpl_cross_version: Found warnings/errors in server log file! +rpl.rpl_get_master_version_and_clock* # Bug #49191 2009-12-01 Daogang rpl_get_master_version_and_clock failed on PB2: COM_REGISTER_SLAVE failed rpl.rpl_innodb_bug28430* @solaris # Bug#46029 rpl.rpl_row_create_table* # Bug#45576: rpl_row_create_table fails on PB2 rpl.rpl_trigger* # Bug#47810 2009-10-04 joro rpl.rpl_trigger.test fails with valgrind errors with the innodb plugin From 248a74eaa10738a0e71e1fe1b11d7c236fe0f521 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 1 Dec 2009 11:19:51 +0200 Subject: [PATCH 121/344] Revert of the push of bug #20837 due to failing regression tests. --- mysql-test/r/innodb_mysql.result | 31 ------------------------------- mysql-test/t/innodb_mysql.test | 26 -------------------------- sql/handler.cc | 10 ++-------- 3 files changed, 2 insertions(+), 65 deletions(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 2d93cbb47b3..402ab3c1b16 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -2273,35 +2273,4 @@ END| DROP PROCEDURE p1; DROP VIEW v1; DROP TABLE t1,t2; -# -# Bug #20837 Apparent change of isolation -# level during transaction -# -SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; -CREATE TABLE t1 (s1 INT) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1),(2); -COMMIT; -SET @@autocommit = 0; -COMMIT; -SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -START TRANSACTION; -SELECT * FROM t1; -s1 -1 -2 -Should be READ UNCOMMITTED -SELECT @@tx_isolation; -@@tx_isolation -READ-UNCOMMITTED -INSERT INTO t1 VALUES (-1); -Should be READ UNCOMMITTED -SELECT @@tx_isolation; -@@tx_isolation -READ-UNCOMMITTED -COMMIT; -Should now be REPEATABLE READ -SELECT @@tx_isolation; -@@tx_isolation -REPEATABLE-READ -DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 0462536371e..a2a1113598d 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -536,30 +536,4 @@ DROP PROCEDURE p1; DROP VIEW v1; DROP TABLE t1,t2; - ---echo # ---echo # Bug #20837 Apparent change of isolation ---echo # level during transaction ---echo # - -SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; -CREATE TABLE t1 (s1 INT) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1),(2); -COMMIT; - -SET @@autocommit = 0; -COMMIT; -SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -START TRANSACTION; -SELECT * FROM t1; ---echo Should be READ UNCOMMITTED -SELECT @@tx_isolation; -INSERT INTO t1 VALUES (-1); ---echo Should be READ UNCOMMITTED -SELECT @@tx_isolation; -COMMIT; ---echo Should now be REPEATABLE READ -SELECT @@tx_isolation; -DROP TABLE t1; - --echo End of 5.1 tests diff --git a/sql/handler.cc b/sql/handler.cc index f6cdaca05bd..216228ed509 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1369,14 +1369,8 @@ int ha_autocommit_or_rollback(THD *thd, int error) if (thd->transaction_rollback_request && !thd->in_sub_stmt) (void) ha_rollback(thd); } - } - else if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) - { - /* - If we're in autocommit mode, reset tx_isolation - to the default value - */ - thd->variables.tx_isolation= thd->session_tx_isolation; + + thd->variables.tx_isolation=thd->session_tx_isolation; } #endif DBUG_RETURN(error); From f1eb8d937e26c660a76ba4e32f709f614edfb102 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 1 Dec 2009 11:21:15 +0200 Subject: [PATCH 122/344] Bug #45576: moving the test from experimental to disabled. --- mysql-test/collections/default.experimental | 1 - mysql-test/suite/rpl/t/disabled.def | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index a0fa2a30a69..0ee9fd81d1c 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -21,7 +21,6 @@ ndb.* # joro : NDB tests marked as experiment rpl.rpl_cross_version* # Bug #43913 2009-10-26 joro rpl_cross_version can't pass on conflicts complainig clash with --slave-load-tm rpl.rpl_get_master_version_and_clock* # Bug#46931 2009-08-26 alik rpl.rpl_get_master_version_and_clock fails on hpux11.31 rpl.rpl_innodb_bug28430* @solaris # Bug#46029 -rpl.rpl_row_create_table* # Bug#45576: rpl_row_create_table fails on PB2 rpl.rpl_trigger* # Bug#47810 2009-10-04 joro rpl.rpl_trigger.test fails with valgrind errors with the innodb plugin rpl_ndb.* # joro : NDB tests marked as experimental as agreed with bochklin diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/t/disabled.def index 8cae44a3607..d2cb1ce9518 100644 --- a/mysql-test/suite/rpl/t/disabled.def +++ b/mysql-test/suite/rpl/t/disabled.def @@ -10,3 +10,4 @@ # ############################################################################## +rpl_row_create_table : Bug#45576 2009-12-01 joro rpl_row_create_table fails on PB2 From ee136e3fa5d4d229b36eb079d1b4bb894d3084ff Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Tue, 1 Dec 2009 14:24:44 +0400 Subject: [PATCH 123/344] Bug #38883 (reopened): thd_security_context is not thread safe, crashes? The bug 38816 changed the lock that protects THD::query from LOCK_thread_count to LOCK_thd_data, but didn't update the associated InnoDB functions. 1. The innobase_mysql_prepare_print_arbitrary_thd and the innobase_mysql_end_print_arbitrary_thd InnoDB functions have been removed, since now we have a per-thread mutex: now we don't need to wrap several inter-thread access tries to THD::query with a single global LOCK_thread_count lock, so we can simplify the code. 2. The innobase_mysql_print_thd function has been modified to lock LOCK_thd_data in direct way. --- innobase/include/trx0trx.h | 4 +--- innobase/lock/lock0lock.c | 33 -------------------------------- innobase/trx/trx0trx.c | 4 +--- sql/ha_innodb.cc | 39 ++++++++------------------------------ 4 files changed, 10 insertions(+), 70 deletions(-) diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index cf9d1788ad8..5ed9f0b8c97 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -348,9 +348,7 @@ trx_commit_step( /************************************************************************** Prints info about a transaction to the given file. The caller must own the -kernel mutex and must have called -innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL -or InnoDB cannot meanwhile change the info printed here. */ +kernel mutex. */ void trx_print( diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index e0f3f58f737..acf76a08f16 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -18,31 +18,6 @@ Created 5/7/1996 Heikki Tuuri #include "trx0sys.h" -/* 2 function prototypes copied from ha_innodb.cc: */ - -/***************************************************************** -If you want to print a thd that is not associated with the current thread, -you must call this function before reserving the InnoDB kernel_mutex, to -protect MySQL from setting thd->query NULL. If you print a thd of the current -thread, we know that MySQL cannot modify thd->query, and it is not necessary -to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release -the kernel_mutex. -NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this -function! */ - -void -innobase_mysql_prepare_print_arbitrary_thd(void); -/*============================================*/ - -/***************************************************************** -Relases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd(). -NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this -function! */ - -void -innobase_mysql_end_print_arbitrary_thd(void); -/*========================================*/ - /* Restricts the length of search we will do in the waits-for graph of transactions */ #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 @@ -4231,11 +4206,6 @@ lock_print_info_summary( /*====================*/ FILE* file) /* in: file where to print */ { - /* We must protect the MySQL thd->query field with a MySQL mutex, and - because the MySQL mutex must be reserved before the kernel_mutex of - InnoDB, we call innobase_mysql_prepare_print_arbitrary_thd() here. */ - - innobase_mysql_prepare_print_arbitrary_thd(); lock_mutex_enter_kernel(); if (lock_deadlock_found) { @@ -4322,7 +4292,6 @@ loop: if (trx == NULL) { lock_mutex_exit_kernel(); - innobase_mysql_end_print_arbitrary_thd(); ut_ad(lock_validate()); @@ -4387,7 +4356,6 @@ loop: if (load_page_first) { lock_mutex_exit_kernel(); - innobase_mysql_end_print_arbitrary_thd(); mtr_start(&mtr); @@ -4397,7 +4365,6 @@ loop: load_page_first = FALSE; - innobase_mysql_prepare_print_arbitrary_thd(); lock_mutex_enter_kernel(); goto loop; diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 70fd73f2488..d0e64b84eeb 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -1701,9 +1701,7 @@ trx_mark_sql_stat_end( /************************************************************************** Prints info about a transaction to the given file. The caller must own the -kernel mutex and must have called -innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL -or InnoDB cannot meanwhile change the info printed here. */ +kernel mutex. */ void trx_print( diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 6586bf818c1..cf6827585f7 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -554,35 +554,6 @@ convert_error_code_to_mysql( } } -/***************************************************************** -If you want to print a thd that is not associated with the current thread, -you must call this function before reserving the InnoDB kernel_mutex, to -protect MySQL from setting thd->query NULL. If you print a thd of the current -thread, we know that MySQL cannot modify thd->query, and it is not necessary -to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release -the kernel_mutex. -NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this -function! */ -extern "C" -void -innobase_mysql_prepare_print_arbitrary_thd(void) -/*============================================*/ -{ - VOID(pthread_mutex_lock(&LOCK_thread_count)); -} - -/***************************************************************** -Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd(). -NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this -function! */ -extern "C" -void -innobase_mysql_end_print_arbitrary_thd(void) -/*========================================*/ -{ - VOID(pthread_mutex_unlock(&LOCK_thread_count)); -} - /***************************************************************** Prints info of a THD object (== user session thread) to the given file. NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for @@ -596,11 +567,11 @@ innobase_mysql_print_thd( uint max_query_len) /* in: max query length to print, or 0 to use the default max length */ { - const THD* thd; + THD* thd; const Security_context *sctx; const char* s; - thd = (const THD*) input_thd; + thd = (THD*) input_thd; /* We probably want to have original user as part of debug output. */ sctx = &thd->main_security_ctx; @@ -627,6 +598,10 @@ innobase_mysql_print_thd( fputs(s, f); } + /* We have to quarantine an access to thd->query and + thd->query_length with thd->LOCK_thd_data mutex. */ + VOID(pthread_mutex_lock(&thd->LOCK_thd_data)); + if ((s = thd->query)) { /* 3100 is chosen because currently 3000 is the maximum max_query_len we ever give this. */ @@ -671,6 +646,8 @@ innobase_mysql_print_thd( } } + VOID(pthread_mutex_unlock(&thd->LOCK_thd_data)); + putc('\n', f); } From 9128418ebb7f683365d0a56c3ad7d4e8a96dcdf4 Mon Sep 17 00:00:00 2001 From: Satya B Date: Tue, 1 Dec 2009 17:37:56 +0530 Subject: [PATCH 124/344] Addition to Innodb Plugin 1.0.6 snapshot the last IF ELSE part which decides the plugin name is not relevant as we still have to substitute the occurences of INNOBASE with INNODB_PLUGIN. Remove the last IF ELSE part in CMakeLists.txt as it doesn't make sense in 5.1. --- storage/innodb_plugin/CMakeLists.txt | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/storage/innodb_plugin/CMakeLists.txt b/storage/innodb_plugin/CMakeLists.txt index 21d83ea2b5f..ad483779152 100644 --- a/storage/innodb_plugin/CMakeLists.txt +++ b/storage/innodb_plugin/CMakeLists.txt @@ -81,14 +81,4 @@ SET(INNODB_PLUGIN_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c ut/ut0list.c ut/ut0wqueue.c) ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION) - -IF (MYSQL_VERSION_ID GREATER "50137") - MYSQL_STORAGE_ENGINE(INNOBASE) - # Use ha_innodb for plugin name, if plugin is built - GET_TARGET_PROPERTY(LIB_LOCATION ha_innobase LOCATION) - IF(LIB_LOCATION) - SET_TARGET_PROPERTIES(ha_innobase PROPERTIES OUTPUT_NAME ha_innodb) - ENDIF(LIB_LOCATION) -ELSE (MYSQL_VERSION_ID GREATER "50137") - IF (NOT SOURCE_SUBLIBS) - ADD_DEFINITIONS(-D_WIN32 -DMYSQL_SERVER) +MYSQL_STORAGE_ENGINE(INNOBASE) From 7853f553be39b2e3470fd72bf60b4b814dea63f0 Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Tue, 1 Dec 2009 21:28:45 +0300 Subject: [PATCH 125/344] Bug#48508: Crash on prepared statement re-execution. Actually there is two different bugs. The first one caused crash on queries with WHERE condition over views containing WHERE condition. A wrong check for prepared statement phase led to items for view fields being allocated in the execution memory and freed at the end of execution. Thus the optimized WHERE condition refers to unallocated memory on the second execution and server crashed. The second one caused by the Item_cond::compile function not saving changes it made to the item tree. Thus on the next execution changes weren't reverted and server crashed on dereferencing of unallocated space. The new helper function called is_stmt_prepare_or_first_stmt_execute is added to the Query_arena class. The find_field_in_view function now uses is_stmt_prepare_or_first_stmt_execute() to check whether newly created view items should be freed at the end of the query execution. The Item_cond::compile function now saves changes it makes to item tree. mysql-test/r/ps.result: Added a test case for the bug#48508. mysql-test/t/ps.test: Added a test case for the bug#48508. sql/item_cmpfunc.cc: Bug#48508: Crash on prepared statement re-execution. The Item_cond::compile function now saves changes it makes to item tree. sql/sql_base.cc: Bug#48508: Crash on prepared statement re-execution. The find_field_in_view function now uses is_stmt_prepare_or_first_stmt_execute() to check whether newly created view items should be freed at the end of the query execution. sql/sql_class.h: Bug#48508: Crash on prepared statement re-execution. The Query_arena::is_stmt_prepare_or_first_sp_execute function now correctly do its check. --- mysql-test/r/ps.result | 23 +++++++++++++++++++++++ mysql-test/t/ps.test | 21 +++++++++++++++++++++ sql/item_cmpfunc.cc | 2 +- sql/sql_base.cc | 3 ++- sql/sql_class.h | 2 ++ 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 43c50998e20..e7894388494 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1891,4 +1891,27 @@ execute stmt using @arg; ? -12345.5432100000 deallocate prepare stmt; +# +# Bug#48508: Crash on prepared statement re-execution. +# +create table t1(b int); +insert into t1 values (0); +create view v1 AS select 1 as a from t1 where b; +prepare stmt from "select * from v1 where a"; +execute stmt; +a +execute stmt; +a +drop table t1; +drop view v1; +create table t1(a bigint); +create table t2(b tinyint); +insert into t2 values (null); +prepare stmt from "select 1 from t1 join t2 on a xor b where b > 1 and a =1"; +execute stmt; +1 +execute stmt; +1 +drop table t1,t2; +# End of 5.0 tests. diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index d9e593fd76f..6134efb5c5c 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1973,4 +1973,25 @@ select @arg; execute stmt using @arg; deallocate prepare stmt; +--echo # +--echo # Bug#48508: Crash on prepared statement re-execution. +--echo # +create table t1(b int); +insert into t1 values (0); +create view v1 AS select 1 as a from t1 where b; +prepare stmt from "select * from v1 where a"; +execute stmt; +execute stmt; +drop table t1; +drop view v1; + +create table t1(a bigint); +create table t2(b tinyint); +insert into t2 values (null); +prepare stmt from "select 1 from t1 join t2 on a xor b where b > 1 and a =1"; +execute stmt; +execute stmt; +drop table t1,t2; +--echo # + --echo End of 5.0 tests. diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 8c655cdc369..d03c68b3560 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -3907,7 +3907,7 @@ Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, byte *arg_v= *arg_p; Item *new_item= item->compile(analyzer, &arg_v, transformer, arg_t); if (new_item && new_item != item) - li.replace(new_item); + current_thd->change_item_tree(li.ref(), new_item); } return Item_func::transform(transformer, arg_t); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 178c3e12e23..88d1e8879d1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3481,7 +3481,8 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, if (!my_strcasecmp(system_charset_info, field_it.name(), name)) { // in PS use own arena or data will be freed after prepare - if (register_tree_change && thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) + if (register_tree_change && + thd->stmt_arena->is_stmt_prepare_or_first_stmt_execute()) arena= thd->activate_stmt_arena_if_needed(&backup); /* create_item() may, or may not create a new Item, depending on diff --git a/sql/sql_class.h b/sql/sql_class.h index b41a5d5c6b7..ac058bca4f9 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -759,6 +759,8 @@ public: { return state == INITIALIZED_FOR_SP; } inline bool is_stmt_prepare_or_first_sp_execute() const { return (int)state < (int)PREPARED; } + inline bool is_stmt_prepare_or_first_stmt_execute() const + { return (int)state <= (int)PREPARED; } inline bool is_first_stmt_execute() const { return state == PREPARED; } inline bool is_stmt_execute() const { return state == PREPARED || state == EXECUTED; } From 61b5d08f20621c8cf6fe970fe059802173146864 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 2 Dec 2009 09:58:30 +0200 Subject: [PATCH 126/344] tree name change to -main --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 557df1b1ffe..f79c1cd6319 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.0-bugteam" +tree_name = "mysql-5.0" From d24b879474e16e99b738d831ec9a3f2a4a341fd6 Mon Sep 17 00:00:00 2001 From: Satya B Date: Wed, 2 Dec 2009 15:17:49 +0530 Subject: [PATCH 127/344] Disable the test case innodb-autonic.test until BUG#49267 is fixed Add the test to disabled list and remove from the experimental list. --- mysql-test/collections/default.experimental | 1 - mysql-test/t/disabled.def | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index 49a0fd8c58c..5f3b7251ce1 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -13,7 +13,6 @@ funcs_1.ndb* # joro : NDB tests marked as experiment funcs_2.ndb_charset # joro : NDB tests marked as experimental as agreed with bochklin main.ctype_gbk_binlog @solaris # Bug#46010: main.ctype_gbk_binlog fails sporadically : Table 't2' already exists -main.innodb-autoinc* # Bug#47809 2009-10-04 joro innodb-autoinc.test fails with valgrind errors with the innodb plugin main.plugin_load @solaris # Bug#42144 ndb.* # joro : NDB tests marked as experimental as agreed with bochklin diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 06d3dbb4e57..378b810fcbb 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -12,3 +12,4 @@ kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2 +innodb-autoinc : Bug#49267 2009-12-02 test fails on windows because of different case mode From d7abca9ac38fc36eb3ff7f96409c0cabe5f5c03e Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 2 Dec 2009 15:17:08 +0400 Subject: [PATCH 128/344] Bug#48766 SHOW CREATE FUNCTION returns extra data in return clause Problem: SHOW CREATE FUNCTION and SELECT DTD_IDENTIFIER FROM I_S.ROUTINES returned wrong values in case of ENUM return data type and UCS2 character set. Fix: the string to collect returned data type was incorrectly set to "binary" character set, therefore UCS2 values where returned with extra '\0' characters. Setting string character set to creation_ctx->get_client_cs() in sp_find_routine(), and to system_charset_info in sp_create_routine fixes the problem. Adding tests: - the original test with Latin letters - an extra test with non-Latin letters --- mysql-test/r/sp-ucs2.result | 26 ++++++++++++++++++++++++++ mysql-test/t/sp-ucs2.test | 29 +++++++++++++++++++++++++++++ sql/sp.cc | 2 ++ 3 files changed, 57 insertions(+) diff --git a/mysql-test/r/sp-ucs2.result b/mysql-test/r/sp-ucs2.result index ce6be5b0a65..1c266e38d97 100644 --- a/mysql-test/r/sp-ucs2.result +++ b/mysql-test/r/sp-ucs2.result @@ -12,3 +12,29 @@ a foo string drop function bug17615| drop table t3| +SET NAMES utf8; +DROP FUNCTION IF EXISTS bug48766; +CREATE FUNCTION bug48766 () +RETURNS ENUM( 'w' ) CHARACTER SET ucs2 +RETURN 0; +SHOW CREATE FUNCTION bug48766; +Function sql_mode Create Function character_set_client collation_connection Database Collation +bug48766 CREATE DEFINER=`root`@`localhost` FUNCTION `bug48766`() RETURNS enum('w') CHARSET ucs2 +RETURN 0 utf8 utf8_general_ci latin1_swedish_ci +SELECT DTD_IDENTIFIER FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_NAME='bug48766'; +DTD_IDENTIFIER +enum('w') CHARSET ucs2 +DROP FUNCTION bug48766; +CREATE FUNCTION bug48766 () +RETURNS ENUM('а','б','в','г') CHARACTER SET ucs2 +RETURN 0; +SHOW CREATE FUNCTION bug48766; +Function sql_mode Create Function character_set_client collation_connection Database Collation +bug48766 CREATE DEFINER=`root`@`localhost` FUNCTION `bug48766`() RETURNS enum('а','б','в','г') CHARSET ucs2 +RETURN 0 utf8 utf8_general_ci latin1_swedish_ci +SELECT DTD_IDENTIFIER FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_NAME='bug48766'; +DTD_IDENTIFIER +enum('а','б','в','г') CHARSET ucs2 +DROP FUNCTION bug48766; diff --git a/mysql-test/t/sp-ucs2.test b/mysql-test/t/sp-ucs2.test index 7dd88b04871..7d6b62dfea0 100644 --- a/mysql-test/t/sp-ucs2.test +++ b/mysql-test/t/sp-ucs2.test @@ -26,3 +26,32 @@ drop table t3| delimiter ;| + +# +# Bug#48766 SHOW CREATE FUNCTION returns extra data in return clause +# +SET NAMES utf8; +--disable_warnings +DROP FUNCTION IF EXISTS bug48766; +--enable_warnings +# +# Test that Latin letters are not prepended with extra '\0'. +# +CREATE FUNCTION bug48766 () + RETURNS ENUM( 'w' ) CHARACTER SET ucs2 + RETURN 0; +SHOW CREATE FUNCTION bug48766; +SELECT DTD_IDENTIFIER FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_NAME='bug48766'; +DROP FUNCTION bug48766; +# +# Test non-Latin characters +# +CREATE FUNCTION bug48766 () + RETURNS ENUM('а','б','в','г') CHARACTER SET ucs2 + RETURN 0; +SHOW CREATE FUNCTION bug48766; +SELECT DTD_IDENTIFIER FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_NAME='bug48766'; + +DROP FUNCTION bug48766; diff --git a/sql/sp.cc b/sql/sp.cc index d3c5dfb96d0..6fad1d70ffd 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -900,6 +900,7 @@ sp_create_routine(THD *thd, int type, sp_head *sp) DBUG_PRINT("enter", ("type: %d name: %.*s",type, (int) sp->m_name.length, sp->m_name.str)); String retstr(64); + retstr.set_charset(system_charset_info); DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || type == TYPE_ENUM_FUNCTION); @@ -1403,6 +1404,7 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, 64 -- size of "returns" column of mysql.proc. */ String retstr(64); + retstr.set_charset(sp->get_creation_ctx()->get_client_cs()); DBUG_PRINT("info", ("found: 0x%lx", (ulong)sp)); if (sp->m_first_free_instance) From 755e84f683d813b13c502f0b134c54e3fcdc3e06 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Dec 2009 18:52:19 +0100 Subject: [PATCH 129/344] Raise version number after cloning 5.1.42 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 79138561dcb..8107884ec3c 100644 --- a/configure.in +++ b/configure.in @@ -10,7 +10,7 @@ AC_CANONICAL_SYSTEM # # When changing major version number please also check switch statement # in mysqlbinlog::check_master_version(). -AM_INIT_AUTOMAKE(mysql, 5.1.42) +AM_INIT_AUTOMAKE(mysql, 5.1.43) AM_CONFIG_HEADER([include/config.h:config.h.in]) # Request support for automake silent-rules if available. From 7622134333ef91e5e88e981288aaf09f7202d54a Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 3 Dec 2009 13:22:34 +0400 Subject: [PATCH 130/344] Bug#44131 Binary-mode "order by" returns records in incorrect order for UTF-8 strings Problem: Item_char_typecast reported wrong max_length when casting to BINARY, which lead, in particular, in wrong "ORDER BY BINARY(char_column)" results. Fix: making Item_char_typecast report correct max_length. @ mysql-test/r/ctype_utf16.result Fixing old incorrect test result. @ mysql-test/r/ctype_utf32.result Fixing old incorrect test result. @ mysql-test/r/ctype_utf8.result Adding new test @ mysql-test/t/ctype_utf8.test Adding new test @ sql/item_timefunc.cc Making Item_char_typecast report correct max_length when cast is done to BINARY. --- mysql-test/r/ctype_utf8.result | 18 ++++++++++++++++++ mysql-test/t/ctype_utf8.test | 10 ++++++++++ sql/item_timefunc.cc | 6 +++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 6f4ae965ca0..4c21e66a39c 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1848,6 +1848,24 @@ select hex(_utf8 B'001111111111'); ERROR HY000: Invalid utf8 character string: 'FF' select (_utf8 X'616263FF'); ERROR HY000: Invalid utf8 character string: 'FF' +# +# Bug#44131 Binary-mode "order by" returns records in incorrect order for UTF-8 strings +# +CREATE TABLE t1 (id int not null primary key, name varchar(10)) character set utf8; +INSERT INTO t1 VALUES +(2,'一二三01'),(3,'一二三09'),(4,'一二三02'),(5,'一二三08'), +(6,'一二三11'),(7,'一二三91'),(8,'一二三21'),(9,'一二三81'); +SELECT * FROM t1 ORDER BY BINARY(name); +id name +2 一二三01 +4 一二三02 +5 一二三08 +3 一二三09 +6 一二三11 +8 一二三21 +9 一二三81 +7 一二三91 +DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL); INSERT INTO t1 VALUES (70000, 1092), (70001, 1085), (70002, 1065); SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) FROM t1 GROUP BY b; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index f0c769251cf..23c83310886 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1440,6 +1440,16 @@ select hex(_utf8 B'001111111111'); --error ER_INVALID_CHARACTER_STRING select (_utf8 X'616263FF'); +--echo # +--echo # Bug#44131 Binary-mode "order by" returns records in incorrect order for UTF-8 strings +--echo # +CREATE TABLE t1 (id int not null primary key, name varchar(10)) character set utf8; +INSERT INTO t1 VALUES +(2,'一二三01'),(3,'一二三09'),(4,'一二三02'),(5,'一二三08'), +(6,'一二三11'),(7,'一二三91'),(8,'一二三21'),(9,'一二三81'); +SELECT * FROM t1 ORDER BY BINARY(name); +DROP TABLE t1; + # # Bug #36772: When using UTF8, CONVERT with GROUP BY returns truncated results # diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index b293145cc27..ded4d28ca29 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2554,9 +2554,9 @@ void Item_char_typecast::fix_length_and_dec() from_cs != &my_charset_bin && cast_cs != &my_charset_bin); collation.set(cast_cs, DERIVATION_IMPLICIT); - char_length= (cast_length >= 0) ? - cast_length : - args[0]->max_length / args[0]->collation.collation->mbmaxlen; + char_length= (cast_length >= 0) ? cast_length : + args[0]->max_length / + (cast_cs == &my_charset_bin ? 1 : args[0]->collation.collation->mbmaxlen); max_length= char_length * cast_cs->mbmaxlen; } From 9091535c5fc914aecaa51acf6e558ccd9800fd88 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 3 Dec 2009 14:07:46 +0200 Subject: [PATCH 131/344] Bug #48985: show create table crashes if previous access to the table was killed When checking for an error after removing the special view error handler the code was not taking into account that open_tables() may fail because of the current statement being killed. Added a check for thd->killed. Added a client program to test it. --- mysql-test/r/show_check.result | 6 ++++++ mysql-test/t/show_check.test | 22 ++++++++++++++++++++++ sql/sql_show.cc | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index e6550bee954..ec0a70ff581 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1454,4 +1454,10 @@ GRANT PROCESS ON *.* TO test_u@localhost; SHOW ENGINE MYISAM MUTEX; SHOW ENGINE MYISAM STATUS; DROP USER test_u@localhost; +# +# Bug #48985: show create table crashes if previous access to the table +# was killed +# +SHOW CREATE TABLE non_existent; +ERROR 70100: Query execution was interrupted End of 5.1 tests diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 0ce807ae73e..d46261f38d2 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -1207,6 +1207,28 @@ connection default; DROP USER test_u@localhost; +--echo # +--echo # Bug #48985: show create table crashes if previous access to the table +--echo # was killed +--echo # + +connect(con1,localhost,root,,); +CONNECTION con1; +LET $ID= `SELECT connection_id()`; + +CONNECTION default; +--disable_query_log +eval KILL QUERY $ID; +--enable_query_log + +CONNECTION con1; +--error ER_QUERY_INTERRUPTED +SHOW CREATE TABLE non_existent; + +CONNECTION default; +DISCONNECT con1; + + --echo End of 5.1 tests # Wait till all disconnects are completed diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2c1f360104b..e55000c0f65 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -719,7 +719,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) thd->push_internal_handler(&view_error_suppressor); bool error= open_normal_and_derived_tables(thd, table_list, 0); thd->pop_internal_handler(); - if (error && thd->main_da.is_error()) + if (error && (thd->killed || thd->main_da.is_error())) DBUG_RETURN(TRUE); } From 8fa282cc68b4f7abac8b327935cb449f7c2e7558 Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Thu, 3 Dec 2009 16:15:20 +0300 Subject: [PATCH 132/344] Bug#48508: Crash on prepared statement re-execution. Test case cleanup. mysql-test/r/ps.result: Test case cleanup for bug#48508. mysql-test/t/ps.test: Test case cleanup for bug#48508. --- mysql-test/r/ps.result | 2 ++ mysql-test/t/ps.test | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index e7894388494..8a19b9b17e1 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1902,6 +1902,7 @@ execute stmt; a execute stmt; a +deallocate prepare stmt; drop table t1; drop view v1; create table t1(a bigint); @@ -1912,6 +1913,7 @@ execute stmt; 1 execute stmt; 1 +deallocate prepare stmt; drop table t1,t2; # End of 5.0 tests. diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 6134efb5c5c..8f8e943913f 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1982,6 +1982,7 @@ create view v1 AS select 1 as a from t1 where b; prepare stmt from "select * from v1 where a"; execute stmt; execute stmt; +deallocate prepare stmt; drop table t1; drop view v1; @@ -1991,6 +1992,7 @@ insert into t2 values (null); prepare stmt from "select 1 from t1 join t2 on a xor b where b > 1 and a =1"; execute stmt; execute stmt; +deallocate prepare stmt; drop table t1,t2; --echo # From 699a87110d397def13d783bc89c37f9b012f175a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Dec 2009 17:15:47 +0100 Subject: [PATCH 133/344] This is a patch for bug#41569. "mysql_upgrade (ver 5.1) add 3 fields to mysql.proc table but does not set values". mysql_upgrade (ver 5.1) adds 3 fields (character_set_client, collation_connection and db_collation) to the mysql.proc table, but does not set any values. When we run stored procedures, which were created with mysql 5.0, a warning is logged into the error log. The solution to this is for mysql_upgrade to set default best guess values for these fields. A warning is also written during upgrade, to make the user aware that default values are set. client/mysql_upgrade.c: Result lines which start with "WARNING" are passed through to the output. This way we have a way of triggering WARNING-messages during upgrade directly from the .sql-script. mysql-test/r/mysql_upgrade.result: Expected result of the test. mysql-test/t/mysql_upgrade.test: Added a test-case for the bug. scripts/mysql_system_tables_fix.sql: The new fields are populated, and warnings are written. --- client/mysql_upgrade.c | 4 +++ mysql-test/r/mysql_upgrade.result | 42 +++++++++++++++++++++++++++++ mysql-test/t/mysql_upgrade.test | 17 ++++++++++++ scripts/mysql_system_tables_fix.sql | 30 +++++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 52c3636219d..81dcdaa71f1 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -778,6 +778,10 @@ static int run_sql_fix_privilege_tables(void) found_real_errors++; print_line(line); } + else if (strncmp(line, "WARNING", 7) == 0) + { + print_line(line); + } } while ((line= get_line(line)) && *line); } diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index 384442f8c31..72917988594 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -127,3 +127,45 @@ mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK set GLOBAL sql_mode=default; +# +# Bug #41569 mysql_upgrade (ver 5.1) add 3 fields to mysql.proc table +# but does not set values. +# +CREATE PROCEDURE testproc() BEGIN END; +UPDATE mysql.proc SET character_set_client = NULL WHERE name LIKE 'testproc'; +UPDATE mysql.proc SET collation_connection = NULL WHERE name LIKE 'testproc'; +UPDATE mysql.proc SET db_collation = NULL WHERE name LIKE 'testproc'; +WARNING: NULL values of the 'character_set_client' column ('mysql.proc' table) have been updated with a default value (latin1). Please verify if necessary. +WARNING: NULL values of the 'collation_connection' column ('mysql.proc' table) have been updated with a default value (latin1_swedish_ci). Please verify if necessary. +WARNING: NULL values of the 'db_collation' column ('mysql.proc' table) have been updated with default values. Please verify if necessary. +mtr.global_suppressions OK +mtr.test_suppressions OK +mysql.columns_priv OK +mysql.db OK +mysql.event OK +mysql.func OK +mysql.general_log +Error : You can't use locks with log tables. +status : OK +mysql.help_category OK +mysql.help_keyword OK +mysql.help_relation OK +mysql.help_topic OK +mysql.host OK +mysql.ndb_binlog_index OK +mysql.plugin OK +mysql.proc OK +mysql.procs_priv OK +mysql.servers OK +mysql.slow_log +Error : You can't use locks with log tables. +status : OK +mysql.tables_priv OK +mysql.time_zone OK +mysql.time_zone_leap_second OK +mysql.time_zone_name OK +mysql.time_zone_transition OK +mysql.time_zone_transition_type OK +mysql.user OK +CALL testproc(); +DROP PROCEDURE testproc; diff --git a/mysql-test/t/mysql_upgrade.test b/mysql-test/t/mysql_upgrade.test index d1f97d7287e..937c9d7a212 100644 --- a/mysql-test/t/mysql_upgrade.test +++ b/mysql-test/t/mysql_upgrade.test @@ -89,3 +89,20 @@ DROP USER mysqltest1@'%'; set GLOBAL sql_mode='STRICT_ALL_TABLES,ANSI_QUOTES,NO_ZERO_DATE'; --exec $MYSQL_UPGRADE --skip-verbose --force 2>&1 eval set GLOBAL sql_mode=default; + + +--echo # +--echo # Bug #41569 mysql_upgrade (ver 5.1) add 3 fields to mysql.proc table +--echo # but does not set values. +--echo # + +# Create a stored procedure and set the fields in question to null. +# When running mysql_upgrade, a warning should be written. + +CREATE PROCEDURE testproc() BEGIN END; +UPDATE mysql.proc SET character_set_client = NULL WHERE name LIKE 'testproc'; +UPDATE mysql.proc SET collation_connection = NULL WHERE name LIKE 'testproc'; +UPDATE mysql.proc SET db_collation = NULL WHERE name LIKE 'testproc'; +--exec $MYSQL_UPGRADE --skip-verbose --force 2>&1 +CALL testproc(); +DROP PROCEDURE testproc; diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 1844860c84d..4260aee9142 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -415,18 +415,48 @@ ALTER TABLE proc ADD character_set_client ALTER TABLE proc MODIFY character_set_client char(32) collate utf8_bin DEFAULT NULL; +SELECT CASE WHEN COUNT(*) > 0 THEN +CONCAT ("WARNING: NULL values of the 'character_set_client' column ('mysql.proc' table) have been updated with a default value (", @@character_set_client, "). Please verify if necessary.") +ELSE NULL +END +AS value FROM proc WHERE character_set_client IS NULL; + +UPDATE proc SET character_set_client = @@character_set_client + WHERE character_set_client IS NULL; + ALTER TABLE proc ADD collation_connection char(32) collate utf8_bin DEFAULT NULL AFTER character_set_client; ALTER TABLE proc MODIFY collation_connection char(32) collate utf8_bin DEFAULT NULL; +SELECT CASE WHEN COUNT(*) > 0 THEN +CONCAT ("WARNING: NULL values of the 'collation_connection' column ('mysql.proc' table) have been updated with a default value (", @@collation_connection, "). Please verify if necessary.") +ELSE NULL +END +AS value FROM proc WHERE collation_connection IS NULL; + +UPDATE proc SET collation_connection = @@collation_connection + WHERE collation_connection IS NULL; + ALTER TABLE proc ADD db_collation char(32) collate utf8_bin DEFAULT NULL AFTER collation_connection; ALTER TABLE proc MODIFY db_collation char(32) collate utf8_bin DEFAULT NULL; +SELECT CASE WHEN COUNT(*) > 0 THEN +CONCAT ("WARNING: NULL values of the 'db_collation' column ('mysql.proc' table) have been updated with default values. Please verify if necessary.") +ELSE NULL +END +AS value FROM proc WHERE db_collation IS NULL; + +UPDATE proc AS p SET db_collation = + ( SELECT DEFAULT_COLLATION_NAME + FROM INFORMATION_SCHEMA.SCHEMATA + WHERE SCHEMA_NAME = p.db) + WHERE db_collation IS NULL; + ALTER TABLE proc ADD body_utf8 longblob DEFAULT NULL AFTER db_collation; ALTER TABLE proc MODIFY body_utf8 longblob DEFAULT NULL; From 43d8e02f596f3e87ff45710566aa39cfaf863852 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 3 Dec 2009 23:38:09 +0400 Subject: [PATCH 134/344] Bug #38883: thd_security_context is not thread safe, crashes? After-push minor code cleanup for WL 2360: unnecessary external reference to LOCK_thread_count has been removed from ha_innodb.cc. --- storage/innobase/handler/ha_innodb.cc | 6 ------ storage/innodb_plugin/handler/ha_innodb.cc | 3 --- 2 files changed, 9 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 30b4fc13012..2467e7b19b5 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -40,12 +40,6 @@ have disabled the InnoDB inlining in this file. */ #include "ha_innodb.h" #include -#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; -#endif /* MYSQL_SERVER */ - /** to protect innobase_open_files */ static pthread_mutex_t innobase_share_mutex; /** to force correct commit order in binlog */ diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index b51e9186fe4..47b8203091c 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -110,9 +110,6 @@ extern "C" { # ifndef MYSQL_PLUGIN_IMPORT # define MYSQL_PLUGIN_IMPORT /* nothing */ # endif /* MYSQL_PLUGIN_IMPORT */ -/* 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 MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count; #if MYSQL_VERSION_ID < 50124 /* this is defined in mysql_priv.h inside #ifdef MYSQL_SERVER From a4c50983f4bb06209969421dc044bfbc2932f025 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Fri, 4 Dec 2009 14:40:42 +0000 Subject: [PATCH 135/344] BUG#45292 orphan binary log created when starting server twice This patch fixes three bugs as follows. First, aborting the server while purging binary logs might generate orphan files due to how the purge operation was implemented: (purge routine - sql/log.cc - MYSQL_BIN_LOG::purge_logs) 1 - register the files to be removed in a temporary buffer. 2 - update the log-bin.index. 3 - flush the log-bin.index. 4 - erase the files whose names where register in the temporary buffer in step 1. Thus a failure while executing step 4 would generate an orphan file. Second, a similar issue might happen while creating a new binary as follows: (create routine - sql/log.cc - MYSQL_BIN_LOG::open) 1 - open the new log-bin. 2 - update the log-bin.index. Thus a failure while executing step 1 would generate an orphan file. To fix these issues, we record the files to be purged or created before really removing or adding them. So if a failure happens such records can be used to automatically remove dangling files. The new steps might be outlined as follows: (purge routine - sql/log.cc - MYSQL_BIN_LOG::purge_logs) 1 - register the files to be removed in the log-bin.~rec~ placed in the data directory. 2 - update the log-bin.index. 3 - flush the log-bin.index. 4 - delete the log-bin.~rec~. (create routine - sql/log.cc - MYSQL_BIN_LOG::open) 1 - register the file to be created in the log-bin.~rec~ placed in the data directory. 2 - open the new log-bin. 3 - update the log-bin.index. 4 - delete the log-bin.~rec~. (recovery routine - sql/log.cc - MYSQL_BIN_LOG::open_index_file) 1 - open the log-bin.index. 2 - open the log-bin.~rec~. 3 - for each file in log-bin.~rec~. 3.1 Check if the file is in the log-bin.index and if so ignore it. 3.2 Otherwise, delete it. The third issue can be described as follows. The purge operation was allowing to remove a file in use thus leading to the loss of data and possible inconsistencies between the master and slave. Roughly, the routine was only taking into account the dump threads and so if a slave was not connect the file might be delete even though it was in use. --- mysql-test/suite/binlog/r/binlog_index.result | 113 ++++- mysql-test/suite/binlog/t/binlog_index.test | 165 ++++++- sql/log.cc | 440 +++++++++++++----- sql/log.h | 26 +- sql/mysqld.cc | 4 +- sql/rpl_rli.cc | 4 +- 6 files changed, 628 insertions(+), 124 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_index.result b/mysql-test/suite/binlog/r/binlog_index.result index d49ceb00501..06d8baf23bf 100644 --- a/mysql-test/suite/binlog/r/binlog_index.result +++ b/mysql-test/suite/binlog/r/binlog_index.result @@ -1,3 +1,8 @@ +call mtr.add_suppression('Attempting backtrace'); +call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); +call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file'); +call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.'); +call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.'); flush logs; flush logs; flush logs; @@ -21,7 +26,6 @@ flush logs; *** must be a warning master-bin.000001 was not found *** Warnings: Warning 1612 Being purged log master-bin.000001 was not found -Warning 1612 Being purged log master-bin.000001 was not found *** must show one record, of the active binlog, left in the index file after PURGE *** show binary logs; Log_name File_size @@ -37,4 +41,111 @@ Level Code Message Error 1377 a problem with deleting master-bin.000001; consider examining correspondence of your binlog index file to the actual binlog files Error 1377 Fatal error during log purge reset master; +# crash_purge_before_update_index +flush logs; +SET SESSION debug="+d,crash_purge_before_update_index"; +purge binary logs TO 'master-bin.000002'; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000001 +master-bin.000002 +master-bin.000003 + +# crash_purge_non_critical_after_update_index +flush logs; +SET SESSION debug="+d,crash_purge_non_critical_after_update_index"; +purge binary logs TO 'master-bin.000004'; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000004 +master-bin.000005 + +# crash_purge_critical_after_update_index +flush logs; +SET SESSION debug="+d,crash_purge_critical_after_update_index"; +purge binary logs TO 'master-bin.000006'; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 + +# crash_create_non_critical_before_update_index +SET SESSION debug="+d,crash_create_non_critical_before_update_index"; +flush logs; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 +master-bin.000008 + +# crash_create_critical_before_update_index +SET SESSION debug="+d,crash_create_critical_before_update_index"; +flush logs; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 +master-bin.000008 +master-bin.000009 + +# crash_create_after_update_index +SET SESSION debug="+d,crash_create_after_update_index"; +flush logs; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 +master-bin.000008 +master-bin.000009 +master-bin.000010 +master-bin.000011 + +# +# This should put the server in unsafe state and stop +# accepting any command. If we inject a fault at this +# point and continue the execution the server crashes. +# Besides the flush command does not report an error. +# +# fault_injection_registering_index +SET SESSION debug="+d,fault_injection_registering_index"; +flush logs; +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 +master-bin.000008 +master-bin.000009 +master-bin.000010 +master-bin.000011 +master-bin.000012 + +# fault_injection_updating_index +SET SESSION debug="+d,fault_injection_updating_index"; +flush logs; +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 +master-bin.000008 +master-bin.000009 +master-bin.000010 +master-bin.000011 +master-bin.000012 +master-bin.000013 + +SET SESSION debug=""; End of tests diff --git a/mysql-test/suite/binlog/t/binlog_index.test b/mysql-test/suite/binlog/t/binlog_index.test index 13287465b88..8e54c028dbd 100644 --- a/mysql-test/suite/binlog/t/binlog_index.test +++ b/mysql-test/suite/binlog/t/binlog_index.test @@ -3,6 +3,15 @@ # source include/have_log_bin.inc; source include/not_embedded.inc; +call mtr.add_suppression('Attempting backtrace'); +call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); +call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file'); +call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.'); +call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.'); +let $old=`select @@debug`; + +let $MYSQLD_DATADIR= `select @@datadir`; +let $INDEX=$MYSQLD_DATADIR/master-bin.index; # # testing purge binary logs TO @@ -13,7 +22,6 @@ flush logs; flush logs; source include/show_binary_logs.inc; -let $MYSQLD_DATADIR= `select @@datadir`; remove_file $MYSQLD_DATADIR/master-bin.000001; # there must be a warning with file names @@ -66,4 +74,159 @@ rmdir $MYSQLD_DATADIR/master-bin.000001; --disable_warnings reset master; --enable_warnings + +--echo # crash_purge_before_update_index +flush logs; + +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_purge_before_update_index"; +--error 2013 +purge binary logs TO 'master-bin.000002'; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +file_exists $MYSQLD_DATADIR/master-bin.000001; +file_exists $MYSQLD_DATADIR/master-bin.000002; +file_exists $MYSQLD_DATADIR/master-bin.000003; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # crash_purge_non_critical_after_update_index +flush logs; + +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_purge_non_critical_after_update_index"; +--error 2013 +purge binary logs TO 'master-bin.000004'; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000001; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000002; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000003; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # crash_purge_critical_after_update_index +flush logs; + +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_purge_critical_after_update_index"; +--error 2013 +purge binary logs TO 'master-bin.000006'; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000004; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000005; +file_exists $MYSQLD_DATADIR/master-bin.000006; +file_exists $MYSQLD_DATADIR/master-bin.000007; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000008; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # crash_create_non_critical_before_update_index +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_create_non_critical_before_update_index"; +--error 2013 +flush logs; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +file_exists $MYSQLD_DATADIR/master-bin.000008; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000009; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # crash_create_critical_before_update_index +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_create_critical_before_update_index"; +--error 2013 +flush logs; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +file_exists $MYSQLD_DATADIR/master-bin.000009; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000010; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000011; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # crash_create_after_update_index +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_create_after_update_index"; +--error 2013 +flush logs; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +file_exists $MYSQLD_DATADIR/master-bin.000010; +file_exists $MYSQLD_DATADIR/master-bin.000011; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # +--echo # This should put the server in unsafe state and stop +--echo # accepting any command. If we inject a fault at this +--echo # point and continue the execution the server crashes. +--echo # Besides the flush command does not report an error. +--echo # + +--echo # fault_injection_registering_index +SET SESSION debug="+d,fault_injection_registering_index"; +flush logs; +--source include/restart_mysqld.inc + +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # fault_injection_updating_index +SET SESSION debug="+d,fault_injection_updating_index"; +flush logs; +--source include/restart_mysqld.inc + +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +eval SET SESSION debug="$old"; + --echo End of tests diff --git a/sql/log.cc b/sql/log.cc index b4c9e5eb4cc..f795cdab2ca 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1897,6 +1897,22 @@ void MYSQL_LOG::init(enum_log_type log_type_arg, } +bool MYSQL_LOG::init_and_set_log_file_name(const char *log_name, + const char *new_name, + enum_log_type log_type_arg, + enum cache_type io_cache_type_arg) +{ + init(log_type_arg, io_cache_type_arg); + + if (new_name && !strmov(log_file_name, new_name)) + return TRUE; + else if (!new_name && generate_new_name(log_file_name, log_name)) + return TRUE; + + return FALSE; +} + + /* Open a (new) log file. @@ -1929,17 +1945,14 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, write_error= 0; - init(log_type_arg, io_cache_type_arg); - if (!(name= my_strdup(log_name, MYF(MY_WME)))) { name= (char *)log_name; // for the error message goto err; } - if (new_name) - strmov(log_file_name, new_name); - else if (generate_new_name(log_file_name, name)) + if (init_and_set_log_file_name(name, new_name, + log_type_arg, io_cache_type_arg)) goto err; if (io_cache_type == SEQ_READ_APPEND) @@ -2429,7 +2442,7 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG() */ index_file_name[0] = 0; bzero((char*) &index_file, sizeof(index_file)); - bzero((char*) &purge_temp, sizeof(purge_temp)); + bzero((char*) &purge_index_file, sizeof(purge_index_file)); } /* this is called only once */ @@ -2473,7 +2486,7 @@ void MYSQL_BIN_LOG::init_pthread_objects() bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg, - const char *log_name) + const char *log_name, bool need_mutex) { File index_file_nr= -1; DBUG_ASSERT(!my_b_inited(&index_file)); @@ -2498,7 +2511,8 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg, init_io_cache(&index_file, index_file_nr, IO_SIZE, WRITE_CACHE, my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)), - 0, MYF(MY_WME | MY_WAIT_IF_FULL))) + 0, MYF(MY_WME | MY_WAIT_IF_FULL)) || + DBUG_EVALUATE_IF("fault_injection_openning_index", 1, 0)) { /* TODO: all operations creating/deleting the index file or a log, should @@ -2509,6 +2523,28 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg, my_close(index_file_nr,MYF(0)); return TRUE; } + +#ifdef HAVE_REPLICATION + /* + Sync the index by purging any binary log file that is not registered. + In other words, either purge binary log files that were removed from + the index but not purged from the file system due to a crash or purge + any binary log file that was created but not register in the index + due to a crash. + */ + + if (set_purge_index_file_name(index_file_name_arg) || + open_purge_index_file(FALSE) || + purge_index_entry(NULL, NULL, need_mutex) || + close_purge_index_file() || + DBUG_EVALUATE_IF("fault_injection_recovering_index", 1, 0)) + { + sql_print_error("MYSQL_BIN_LOG::open_index_file failed to sync the index " + "file."); + return TRUE; + } +#endif + return FALSE; } @@ -2533,17 +2569,44 @@ bool MYSQL_BIN_LOG::open(const char *log_name, enum cache_type io_cache_type_arg, bool no_auto_events_arg, ulong max_size_arg, - bool null_created_arg) + bool null_created_arg, + bool need_mutex) { File file= -1; + DBUG_ENTER("MYSQL_BIN_LOG::open"); DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg)); - write_error=0; + if (init_and_set_log_file_name(log_name, new_name, log_type_arg, + io_cache_type_arg)) + { + sql_print_error("MSYQL_BIN_LOG::open failed to generate new file name."); + DBUG_RETURN(1); + } + +#ifdef HAVE_REPLICATION + if (open_purge_index_file(TRUE) || + register_create_index_entry(log_file_name) || + sync_purge_index_file() || + DBUG_EVALUATE_IF("fault_injection_registering_index", 1, 0)) + { + sql_print_error("MSYQL_BIN_LOG::open failed to sync the index file."); + DBUG_RETURN(1); + } + DBUG_EXECUTE_IF("crash_create_non_critical_before_update_index", abort();); +#endif + + write_error= 0; /* open the main log file */ - if (MYSQL_LOG::open(log_name, log_type_arg, new_name, io_cache_type_arg)) + if (MYSQL_LOG::open(log_name, log_type_arg, new_name, + io_cache_type_arg)) + { +#ifdef HAVE_REPLICATION + close_purge_index_file(); +#endif DBUG_RETURN(1); /* all warnings issued */ + } init(no_auto_events_arg, max_size_arg); @@ -2569,9 +2632,6 @@ bool MYSQL_BIN_LOG::open(const char *log_name, write_file_name_to_index_file= 1; } - DBUG_ASSERT(my_b_inited(&index_file) != 0); - reinit_io_cache(&index_file, WRITE_CACHE, - my_b_filelength(&index_file), 0, 0); if (need_start_event && !no_auto_events) { /* @@ -2629,23 +2689,44 @@ bool MYSQL_BIN_LOG::open(const char *log_name, if (write_file_name_to_index_file) { +#ifdef HAVE_REPLICATION + DBUG_EXECUTE_IF("crash_create_critical_before_update_index", abort();); +#endif + + DBUG_ASSERT(my_b_inited(&index_file) != 0); + reinit_io_cache(&index_file, WRITE_CACHE, + my_b_filelength(&index_file), 0, 0); /* As this is a new log file, we write the file name to the index file. As every time we write to the index file, we sync it. */ - if (my_b_write(&index_file, (uchar*) log_file_name, - strlen(log_file_name)) || - my_b_write(&index_file, (uchar*) "\n", 1) || - flush_io_cache(&index_file) || + if (DBUG_EVALUATE_IF("fault_injection_updating_index", 1, 0) || + my_b_write(&index_file, (uchar*) log_file_name, + strlen(log_file_name)) || + my_b_write(&index_file, (uchar*) "\n", 1) || + flush_io_cache(&index_file) || my_sync(index_file.file, MYF(MY_WME))) - goto err; + goto err; + +#ifdef HAVE_REPLICATION + DBUG_EXECUTE_IF("crash_create_after_update_index", abort();); +#endif } } log_state= LOG_OPENED; +#ifdef HAVE_REPLICATION + close_purge_index_file(); +#endif + DBUG_RETURN(0); err: +#ifdef HAVE_REPLICATION + if (is_inited_purge_index_file()) + purge_index_entry(NULL, NULL, need_mutex); + close_purge_index_file(); +#endif sql_print_error("Could not use %s for logging (error %d). \ Turning logging off for the whole duration of the MySQL server process. \ To turn it on again: fix the cause, \ @@ -2902,8 +2983,15 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) name=0; // Protect against free close(LOG_CLOSE_TO_BE_OPENED); - /* First delete all old log files */ + /* + First delete all old log files and then update the index file. + As we first delete the log files and do not use sort of logging, + a crash may lead to an inconsistent state where the index has + references to non-existent files. + We need to invert the steps and use the purge_index_file methods + in order to make the operation safe. + */ if (find_log_pos(&linfo, NullS, 0)) { error=1; @@ -2970,8 +3058,8 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) } if (!thd->slave_thread) need_start_event=1; - if (!open_index_file(index_file_name, 0)) - open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0); + if (!open_index_file(index_file_name, 0, FALSE)) + open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0, FALSE); my_free((uchar*) save_name, MYF(0)); err: @@ -3158,7 +3246,7 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, bool need_update_threads, ulonglong *decrease_log_space) { - int error; + int error= 0; bool exit_loop= 0; LOG_INFO log_info; THD *thd= current_thd; @@ -3169,33 +3257,15 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, pthread_mutex_lock(&LOCK_index); if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/))) { - sql_print_error("MYSQL_LOG::purge_logs was called with file %s not " + sql_print_error("MYSQL_BIN_LOG::purge_logs was called with file %s not " "listed in the index.", to_log); goto err; } - /* - For crash recovery reasons the index needs to be updated before - any files are deleted. Move files to be deleted into a temp file - to be processed after the index is updated. - */ - if (!my_b_inited(&purge_temp)) + if ((error= open_purge_index_file(TRUE))) { - if ((error=open_cached_file(&purge_temp, mysql_tmpdir, TEMP_PREFIX, - DISK_BUFFER_SIZE, MYF(MY_WME)))) - { - sql_print_error("MYSQL_LOG::purge_logs failed to open purge_temp"); - goto err; - } - } - else - { - if ((error=reinit_io_cache(&purge_temp, WRITE_CACHE, 0, 0, 1))) - { - sql_print_error("MYSQL_LOG::purge_logs failed to reinit purge_temp " - "for write"); - goto err; - } + sql_print_error("MYSQL_BIN_LOG::purge_logs failed to sync the index file."); + goto err; } /* @@ -3205,51 +3275,177 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/))) goto err; while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) && + !is_active(log_info.log_file_name) && !log_in_use(log_info.log_file_name)) { - if ((error=my_b_write(&purge_temp, (const uchar*)log_info.log_file_name, - strlen(log_info.log_file_name))) || - (error=my_b_write(&purge_temp, (const uchar*)"\n", 1))) + if ((error= register_purge_index_entry(log_info.log_file_name))) { - sql_print_error("MYSQL_LOG::purge_logs failed to copy %s to purge_temp", + sql_print_error("MYSQL_BIN_LOG::purge_logs failed to copy %s to register file.", log_info.log_file_name); goto err; } if (find_next_log(&log_info, 0) || exit_loop) break; - } + } + + DBUG_EXECUTE_IF("crash_purge_before_update_index", abort();); + + if ((error= sync_purge_index_file())) + { + sql_print_error("MSYQL_BIN_LOG::purge_logs failed to flush register file."); + goto err; + } /* We know how many files to delete. Update index file. */ if ((error=update_log_index(&log_info, need_update_threads))) { - sql_print_error("MSYQL_LOG::purge_logs failed to update the index file"); + sql_print_error("MSYQL_BIN_LOG::purge_logs failed to update the index file"); goto err; } - DBUG_EXECUTE_IF("crash_after_update_index", abort();); + DBUG_EXECUTE_IF("crash_purge_critical_after_update_index", abort();); - /* Switch purge_temp for read. */ - if ((error=reinit_io_cache(&purge_temp, READ_CACHE, 0, 0, 0))) +err: + /* Read each entry from purge_index_file and delete the file. */ + if (is_inited_purge_index_file() && + (error= purge_index_entry(thd, decrease_log_space, FALSE))) + sql_print_error("MSYQL_BIN_LOG::purge_logs failed to process registered files" + " that would be purged."); + close_purge_index_file(); + + DBUG_EXECUTE_IF("crash_purge_non_critical_after_update_index", abort();); + + if (need_mutex) + pthread_mutex_unlock(&LOCK_index); + DBUG_RETURN(error); +} + +int MYSQL_BIN_LOG::set_purge_index_file_name(const char *base_file_name) +{ + int error= 0; + DBUG_ENTER("MYSQL_BIN_LOG::set_purge_index_file_name"); + if (fn_format(purge_index_file_name, base_file_name, mysql_data_home, + ".~rec~", MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH | + MY_REPLACE_EXT)) == NULL) { - sql_print_error("MSYQL_LOG::purge_logs failed to reinit purge_temp " + error= 1; + sql_print_error("MYSQL_BIN_LOG::set_purge_index_file_name failed to set " + "file name."); + } + DBUG_RETURN(error); +} + +int MYSQL_BIN_LOG::open_purge_index_file(bool destroy) +{ + int error= 0; + File file= -1; + + DBUG_ENTER("MYSQL_BIN_LOG::open_purge_index_file"); + + if (destroy) + close_purge_index_file(); + + if (!my_b_inited(&purge_index_file)) + { + if ((file= my_open(purge_index_file_name, O_RDWR | O_CREAT | O_BINARY, + MYF(MY_WME | ME_WAITTANG))) < 0 || + init_io_cache(&purge_index_file, file, IO_SIZE, + (destroy ? WRITE_CACHE : READ_CACHE), + 0, 0, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL))) + { + error= 1; + sql_print_error("MYSQL_BIN_LOG::open_purge_index_file failed to open register " + " file."); + } + } + DBUG_RETURN(error); +} + +int MYSQL_BIN_LOG::close_purge_index_file() +{ + int error= 0; + + DBUG_ENTER("MYSQL_BIN_LOG::close_purge_index_file"); + + if (my_b_inited(&purge_index_file)) + { + end_io_cache(&purge_index_file); + error= my_close(purge_index_file.file, MYF(0)); + } + my_delete(purge_index_file_name, MYF(0)); + bzero((char*) &purge_index_file, sizeof(purge_index_file)); + + DBUG_RETURN(error); +} + +bool MYSQL_BIN_LOG::is_inited_purge_index_file() +{ + DBUG_ENTER("MYSQL_BIN_LOG::is_inited_purge_index_file"); + DBUG_RETURN (my_b_inited(&purge_index_file)); +} + +int MYSQL_BIN_LOG::sync_purge_index_file() +{ + int error= 0; + DBUG_ENTER("MYSQL_BIN_LOG::sync_purge_index_file"); + + if ((error= flush_io_cache(&purge_index_file)) || + (error= my_sync(purge_index_file.file, MYF(MY_WME)))) + DBUG_RETURN(error); + + DBUG_RETURN(error); +} + +int MYSQL_BIN_LOG::register_purge_index_entry(const char *entry) +{ + int error= 0; + DBUG_ENTER("MYSQL_BIN_LOG::register_purge_index_entry"); + + if ((error=my_b_write(&purge_index_file, (const uchar*)entry, strlen(entry))) || + (error=my_b_write(&purge_index_file, (const uchar*)"\n", 1))) + DBUG_RETURN (error); + + DBUG_RETURN(error); +} + +int MYSQL_BIN_LOG::register_create_index_entry(const char *entry) +{ + DBUG_ENTER("MYSQL_BIN_LOG::register_create_index_entry"); + DBUG_RETURN(register_purge_index_entry(entry)); +} + +int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, + bool need_mutex) +{ + MY_STAT s; + int error= 0; + LOG_INFO log_info; + LOG_INFO check_log_info; + + DBUG_ENTER("MYSQL_BIN_LOG:purge_index_entry"); + + DBUG_ASSERT(my_b_inited(&purge_index_file)); + + if ((error=reinit_io_cache(&purge_index_file, READ_CACHE, 0, 0, 0))) + { + sql_print_error("MSYQL_BIN_LOG::purge_index_entry failed to reinit register file " "for read"); goto err; } - /* Read each entry from purge_temp and delete the file. */ for (;;) { uint length; - if ((length=my_b_gets(&purge_temp, log_info.log_file_name, + if ((length=my_b_gets(&purge_index_file, log_info.log_file_name, FN_REFLEN)) <= 1) { - if (purge_temp.error) + if (purge_index_file.error) { - error= purge_temp.error; - sql_print_error("MSYQL_LOG::purge_logs error %d reading from " - "purge_temp", error); + error= purge_index_file.error; + sql_print_error("MSYQL_BIN_LOG::purge_index_entry error %d reading from " + "register file.", error); goto err; } @@ -3260,9 +3456,6 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, /* Get rid of the trailing '\n' */ log_info.log_file_name[length-1]= 0; - ha_binlog_index_purge_file(current_thd, log_info.log_file_name); - - MY_STAT s; if (!my_stat(log_info.log_file_name, &s, MYF(0))) { if (my_errno == ENOENT) @@ -3310,64 +3503,92 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, } else { - DBUG_PRINT("info",("purging %s",log_info.log_file_name)); - if (!my_delete(log_info.log_file_name, MYF(0))) + if ((error= find_log_pos(&check_log_info, log_info.log_file_name, need_mutex))) { - if (decrease_log_space) - *decrease_log_space-= s.st_size; - } - else - { - if (my_errno == ENOENT) - { - if (thd) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), - log_info.log_file_name); - } - sql_print_information("Failed to delete file '%s'", - log_info.log_file_name); - my_errno= 0; - } - else + if (error != LOG_INFO_EOF) { if (thd) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_BINLOG_PURGE_FATAL_ERR, - "a problem with deleting %s; " - "consider examining correspondence " - "of your binlog index file " - "to the actual binlog files", + "a problem with deleting %s and " + "reading the binlog index file", log_info.log_file_name); } else { - sql_print_information("Failed to delete file '%s'; " + sql_print_information("Failed to delete file '%s' and " + "read the binlog index file", + log_info.log_file_name); + } + goto err; + } + + error= 0; + if (!need_mutex) + { + /* + This is to avoid triggering an error in NDB. + */ + ha_binlog_index_purge_file(current_thd, log_info.log_file_name); + } + + DBUG_PRINT("info",("purging %s",log_info.log_file_name)); + if (!my_delete(log_info.log_file_name, MYF(0))) + { + if (decrease_log_space) + *decrease_log_space-= s.st_size; + } + else + { + if (my_errno == ENOENT) + { + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), + log_info.log_file_name); + } + sql_print_information("Failed to delete file '%s'", + log_info.log_file_name); + my_errno= 0; + } + else + { + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_BINLOG_PURGE_FATAL_ERR, + "a problem with deleting %s; " "consider examining correspondence " "of your binlog index file " "to the actual binlog files", log_info.log_file_name); - } - if (my_errno == EMFILE) - { - DBUG_PRINT("info", - ("my_errno: %d, set ret = LOG_INFO_EMFILE", my_errno)); - error= LOG_INFO_EMFILE; + } + else + { + sql_print_information("Failed to delete file '%s'; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + } + if (my_errno == EMFILE) + { + DBUG_PRINT("info", + ("my_errno: %d, set ret = LOG_INFO_EMFILE", my_errno)); + error= LOG_INFO_EMFILE; + goto err; + } + error= LOG_INFO_FATAL; goto err; } - error= LOG_INFO_FATAL; - goto err; } } } } err: - close_cached_file(&purge_temp); - if (need_mutex) - pthread_mutex_unlock(&LOCK_index); DBUG_RETURN(error); } @@ -3407,7 +3628,8 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) goto err; while (strcmp(log_file_name, log_info.log_file_name) && - !log_in_use(log_info.log_file_name)) + !is_active(log_info.log_file_name) && + !log_in_use(log_info.log_file_name)) { if (!my_stat(log_info.log_file_name, &stat_area, MYF(0))) { @@ -3416,14 +3638,6 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) /* It's not fatal if we can't stat a log file that does not exist. */ - if (thd) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), - log_info.log_file_name); - } - sql_print_information("Failed to execute my_stat on file '%s'", - log_info.log_file_name); my_errno= 0; } else @@ -3618,9 +3832,9 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock) */ /* reopen index binlog file, BUG#34582 */ - if (!open_index_file(index_file_name, 0)) - open(old_name, log_type, new_name_ptr, - io_cache_type, no_auto_events, max_size, 1); + if (!open_index_file(index_file_name, 0, FALSE)) + open(old_name, log_type, new_name_ptr, + io_cache_type, no_auto_events, max_size, 1, FALSE); my_free(old_name,MYF(0)); end: @@ -5522,7 +5736,7 @@ int TC_LOG_BINLOG::open(const char *opt_name) if (using_heuristic_recover()) { /* generate a new binlog to mask a corrupted one */ - open(opt_name, LOG_BIN, 0, WRITE_CACHE, 0, max_binlog_size, 0); + open(opt_name, LOG_BIN, 0, WRITE_CACHE, 0, max_binlog_size, 0, TRUE); cleanup(); return 1; } diff --git a/sql/log.h b/sql/log.h index d306d6f7182..8b5dfcb3935 100644 --- a/sql/log.h +++ b/sql/log.h @@ -172,6 +172,10 @@ public: enum_log_type log_type, const char *new_name, enum cache_type io_cache_type_arg); + bool init_and_set_log_file_name(const char *log_name, + const char *new_name, + enum_log_type log_type_arg, + enum cache_type io_cache_type_arg); void init(enum_log_type log_type_arg, enum cache_type io_cache_type_arg); void close(uint exiting); @@ -233,14 +237,15 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG pthread_cond_t update_cond; ulonglong bytes_written; IO_CACHE index_file; + char index_file_name[FN_REFLEN]; /* - purge_temp is a temp file used in purge_logs so that the index file + purge_file is a temp file used in purge_logs so that the index file can be updated before deleting files from disk, yielding better crash recovery. It is created on demand the first time purge_logs is called and then reused for subsequent calls. It is cleaned up in cleanup(). */ - IO_CACHE purge_temp; - char index_file_name[FN_REFLEN]; + IO_CACHE purge_index_file; + char purge_index_file_name[FN_REFLEN]; /* The max size before rotation (usable only if log_type == LOG_BIN: binary logs and relay logs). @@ -349,9 +354,10 @@ public: const char *new_name, enum cache_type io_cache_type_arg, bool no_auto_events_arg, ulong max_size, - bool null_created); + bool null_created, + bool need_mutex); bool open_index_file(const char *index_file_name_arg, - const char *log_name); + const char *log_name, bool need_mutex); /* Use this to start writing a new log file */ void new_file(); @@ -384,6 +390,16 @@ public: ulonglong *decrease_log_space); int purge_logs_before_date(time_t purge_time); int purge_first_log(Relay_log_info* rli, bool included); + int set_purge_index_file_name(const char *base_file_name); + int open_purge_index_file(bool destroy); + bool is_inited_purge_index_file(); + int close_purge_index_file(); + int clean_purge_index_file(); + int sync_purge_index_file(); + int register_purge_index_entry(const char* entry); + int register_create_index_entry(const char* entry); + int purge_index_entry(THD *thd, ulonglong *decrease_log_space, + bool need_mutex); bool reset_logs(THD* thd); void close(uint exiting); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5c643b03798..de532e92fda 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3932,7 +3932,7 @@ a file name for --log-bin-index option", opt_binlog_index_name); my_free(opt_bin_logname, MYF(MY_ALLOW_ZERO_PTR)); opt_bin_logname=my_strdup(buf, MYF(0)); } - if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln)) + if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE)) { unireg_abort(1); } @@ -4096,7 +4096,7 @@ a file name for --log-bin-index option", opt_binlog_index_name); } if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0, - WRITE_CACHE, 0, max_binlog_size, 0)) + WRITE_CACHE, 0, max_binlog_size, 0, TRUE)) unireg_abort(1); #ifdef HAVE_REPLICATION diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index a26717d7acf..66de9357a53 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -182,10 +182,10 @@ a file name for --relay-log-index option", opt_relaylog_index_name); note, that if open() fails, we'll still have index file open but a destructor will take care of that */ - if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln) || + if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln, TRUE) || rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0, (max_relay_log_size ? max_relay_log_size : - max_binlog_size), 1)) + max_binlog_size), 1, TRUE)) { pthread_mutex_unlock(&rli->data_lock); sql_print_error("Failed in open_log() called from init_relay_log_info()"); From 4760c13e029d12cf9bdb2688e23b57b3c3c6fa36 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 4 Dec 2009 14:00:20 -0200 Subject: [PATCH 136/344] Bug#41569: mysql_upgrade (ver 5.1) add 3 fields to mysql.proc table but does not set values Post-merge fix: Redirect stderr to a file as to avoid buffering problems due to redirecting stderr to stdout. mysql-test/r/mysql_upgrade.result: Update test case result. mysql-test/t/mysql_upgrade.test: Redirect stderr to a file, cat and remove. --- mysql-test/r/mysql_upgrade.result | 6 +++--- mysql-test/t/mysql_upgrade.test | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index 72917988594..821ad31871f 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -135,9 +135,6 @@ CREATE PROCEDURE testproc() BEGIN END; UPDATE mysql.proc SET character_set_client = NULL WHERE name LIKE 'testproc'; UPDATE mysql.proc SET collation_connection = NULL WHERE name LIKE 'testproc'; UPDATE mysql.proc SET db_collation = NULL WHERE name LIKE 'testproc'; -WARNING: NULL values of the 'character_set_client' column ('mysql.proc' table) have been updated with a default value (latin1). Please verify if necessary. -WARNING: NULL values of the 'collation_connection' column ('mysql.proc' table) have been updated with a default value (latin1_swedish_ci). Please verify if necessary. -WARNING: NULL values of the 'db_collation' column ('mysql.proc' table) have been updated with default values. Please verify if necessary. mtr.global_suppressions OK mtr.test_suppressions OK mysql.columns_priv OK @@ -169,3 +166,6 @@ mysql.time_zone_transition_type OK mysql.user OK CALL testproc(); DROP PROCEDURE testproc; +WARNING: NULL values of the 'character_set_client' column ('mysql.proc' table) have been updated with a default value (latin1). Please verify if necessary. +WARNING: NULL values of the 'collation_connection' column ('mysql.proc' table) have been updated with a default value (latin1_swedish_ci). Please verify if necessary. +WARNING: NULL values of the 'db_collation' column ('mysql.proc' table) have been updated with default values. Please verify if necessary. diff --git a/mysql-test/t/mysql_upgrade.test b/mysql-test/t/mysql_upgrade.test index 937c9d7a212..24a1d2e1b5d 100644 --- a/mysql-test/t/mysql_upgrade.test +++ b/mysql-test/t/mysql_upgrade.test @@ -103,6 +103,8 @@ CREATE PROCEDURE testproc() BEGIN END; UPDATE mysql.proc SET character_set_client = NULL WHERE name LIKE 'testproc'; UPDATE mysql.proc SET collation_connection = NULL WHERE name LIKE 'testproc'; UPDATE mysql.proc SET db_collation = NULL WHERE name LIKE 'testproc'; ---exec $MYSQL_UPGRADE --skip-verbose --force 2>&1 +--exec $MYSQL_UPGRADE --skip-verbose --force 2> $MYSQLTEST_VARDIR/tmp/41569.txt CALL testproc(); DROP PROCEDURE testproc; +--cat_file $MYSQLTEST_VARDIR/tmp/41569.txt +--remove_file $MYSQLTEST_VARDIR/tmp/41569.txt From e53ecf2dc241a29a2ef732850ff77d4896de4412 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 4 Dec 2009 13:36:58 -0200 Subject: [PATCH 137/344] Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0 The problem was that the multiple evaluations of a ENCODE or DECODE function within a single statement caused the random generator to be reinitialized at each evaluation, even though the parameters were constants. The solution is to initialize the random generator only once if the password (seed) parameter is constant. This patch borrows code and ideas from Georgi Kodinov's patch. mysql-test/r/func_str.result: Add test case result. mysql-test/r/ps.result: Add test case result. mysql-test/t/func_str.test: Add test case for Bug#49141 mysql-test/t/ps.test: Add test case for Bug#49141 sql/item_strfunc.cc: Move seed generation code to a separate method. Seed only once if the password (seed) argument is constant. Remove duplicated code and use a transform method to apply encoding or decoding. sql/item_strfunc.h: Add parameter to signal whether the PRNG is already seeded. Introduce transform method. Combine val_str methods. sql/sql_crypt.cc: Remove method. sql/sql_crypt.h: Seed is supplied as two long integers. --- mysql-test/r/func_str.result | 29 +++++++++++++++ mysql-test/r/ps.result | 19 ++++++++++ mysql-test/t/func_str.test | 34 +++++++++++++++++ mysql-test/t/ps.test | 16 ++++++++ sql/item_strfunc.cc | 71 +++++++++++++++++------------------- sql/item_strfunc.h | 13 ++++++- sql/sql_crypt.cc | 9 +---- sql/sql_crypt.h | 8 ++-- 8 files changed, 149 insertions(+), 50 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 2a2fe50ad0f..d144e84dfdc 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -2558,3 +2558,32 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 2 Using join buffer 2 DERIVED t1 ALL NULL NULL NULL NULL 2 drop table t1; +# +# Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0 +# +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 (a VARCHAR(20), b INT); +CREATE TABLE t2 (a VARCHAR(20), b INT); +INSERT INTO t1 VALUES ('ABC', 1); +INSERT INTO t2 VALUES ('ABC', 1); +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) +FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; +DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) +secret +SELECT DECODE((SELECT ENCODE('secret', 'ABC') FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) +FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; +DECODE((SELECT ENCODE('secret', 'ABC') FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) +secret +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), 'ABC') +FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; +DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), 'ABC') +secret +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +INSERT INTO t1 VALUES ('EDF', 3), ('BCD', 2), ('ABC', 1); +INSERT INTO t2 VALUES ('EDF', 3), ('BCD', 2), ('ABC', 1); +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b LIMIT 1), t2.a) +FROM t2 WHERE t2.b = 1 GROUP BY t2.b; +DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b LIMIT 1), t2.a) +secret +DROP TABLE t1, t2; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index f64d58ff8f4..c26a324d00b 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -2947,4 +2947,23 @@ execute stmt; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation drop table t1; deallocate prepare stmt; +# +# Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0 +# +prepare encode from "select encode(?, ?) into @ciphertext"; +prepare decode from "select decode(?, ?) into @plaintext"; +set @str="abc", @key="cba"; +execute encode using @str, @key; +execute decode using @ciphertext, @key; +select @plaintext; +@plaintext +abc +set @str="bcd", @key="dcb"; +execute encode using @str, @key; +execute decode using @ciphertext, @key; +select @plaintext; +@plaintext +bcd +deallocate prepare encode; +deallocate prepare decode; End of 5.1 tests. diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 66b9eabd385..8942b0a2faf 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1318,3 +1318,37 @@ insert into t1 values (-1),(null); explain select 1 as a from t1,(select decode(f1,f1) as b from t1) a; explain select 1 as a from t1,(select encode(f1,f1) as b from t1) a; drop table t1; + +--echo # +--echo # Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0 +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1 (a VARCHAR(20), b INT); +CREATE TABLE t2 (a VARCHAR(20), b INT); + +INSERT INTO t1 VALUES ('ABC', 1); +INSERT INTO t2 VALUES ('ABC', 1); + +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) + FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; + +SELECT DECODE((SELECT ENCODE('secret', 'ABC') FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) + FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; + +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), 'ABC') + FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; + +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; + +INSERT INTO t1 VALUES ('EDF', 3), ('BCD', 2), ('ABC', 1); +INSERT INTO t2 VALUES ('EDF', 3), ('BCD', 2), ('ABC', 1); + +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b LIMIT 1), t2.a) + FROM t2 WHERE t2.b = 1 GROUP BY t2.b; + +DROP TABLE t1, t2; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 4870f4836df..b0930a42b41 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -3032,5 +3032,21 @@ execute stmt; drop table t1; deallocate prepare stmt; +--echo # +--echo # Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0 +--echo # + +prepare encode from "select encode(?, ?) into @ciphertext"; +prepare decode from "select decode(?, ?) into @plaintext"; +set @str="abc", @key="cba"; +execute encode using @str, @key; +execute decode using @ciphertext, @key; +select @plaintext; +set @str="bcd", @key="dcb"; +execute encode using @str, @key; +execute decode using @ciphertext, @key; +select @plaintext; +deallocate prepare encode; +deallocate prepare decode; --echo End of 5.1 tests. diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 183a628f8e4..b6d3f45f4c2 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1720,68 +1720,65 @@ String *Item_func_encrypt::val_str(String *str) #endif /* HAVE_CRYPT */ } +bool Item_func_encode::seed() +{ + char buf[80]; + ulong rand_nr[2]; + String *key, tmp(buf, sizeof(buf), system_charset_info); + + if (!(key= args[1]->val_str(&tmp))) + return TRUE; + + hash_password(rand_nr, key->ptr(), key->length()); + sql_crypt.init(rand_nr); + + return FALSE; +} + void Item_func_encode::fix_length_and_dec() { max_length=args[0]->max_length; maybe_null=args[0]->maybe_null || args[1]->maybe_null; collation.set(&my_charset_bin); + /* Precompute the seed state if the item is constant. */ + seeded= args[1]->const_item() && + (args[1]->result_type() == STRING_RESULT) && !seed(); } String *Item_func_encode::val_str(String *str) { String *res; - char pw_buff[80]; - String tmp_pw_value(pw_buff, sizeof(pw_buff), system_charset_info); - String *password; DBUG_ASSERT(fixed == 1); if (!(res=args[0]->val_str(str))) { - null_value=1; /* purecov: inspected */ - return 0; /* purecov: inspected */ + null_value= 1; + return NULL; } - if (!(password=args[1]->val_str(& tmp_pw_value))) + if (!seeded && seed()) { - null_value=1; - return 0; + null_value= 1; + return NULL; } - null_value=0; - res=copy_if_not_alloced(str,res,res->length()); - SQL_CRYPT sql_crypt(password->ptr(), password->length()); - sql_crypt.init(); - sql_crypt.encode((char*) res->ptr(),res->length()); - res->set_charset(&my_charset_bin); + null_value= 0; + res= copy_if_not_alloced(str, res, res->length()); + transform(res); + sql_crypt.reinit(); + return res; } -String *Item_func_decode::val_str(String *str) +void Item_func_encode::transform(String *res) { - String *res; - char pw_buff[80]; - String tmp_pw_value(pw_buff, sizeof(pw_buff), system_charset_info); - String *password; - DBUG_ASSERT(fixed == 1); + sql_crypt.encode((char*) res->ptr(),res->length()); + res->set_charset(&my_charset_bin); +} - if (!(res=args[0]->val_str(str))) - { - null_value=1; /* purecov: inspected */ - return 0; /* purecov: inspected */ - } - - if (!(password=args[1]->val_str(& tmp_pw_value))) - { - null_value=1; - return 0; - } - - null_value=0; - res=copy_if_not_alloced(str,res,res->length()); - SQL_CRYPT sql_crypt(password->ptr(), password->length()); - sql_crypt.init(); +void Item_func_decode::transform(String *res) +{ sql_crypt.decode((char*) res->ptr(),res->length()); - return res; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 2cdb45100ae..59241872e63 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -351,12 +351,22 @@ public: class Item_func_encode :public Item_str_func { +private: + /** Whether the PRNG has already been seeded. */ + bool seeded; +protected: + SQL_CRYPT sql_crypt; public: Item_func_encode(Item *a, Item *seed): Item_str_func(a, seed) {} String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "encode"; } +protected: + virtual void transform(String *); +private: + /** Provide a seed for the PRNG sequence. */ + bool seed(); }; @@ -364,8 +374,9 @@ class Item_func_decode :public Item_func_encode { public: Item_func_decode(Item *a, Item *seed): Item_func_encode(a, seed) {} - String *val_str(String *); const char *func_name() const { return "decode"; } +protected: + void transform(String *); }; diff --git a/sql/sql_crypt.cc b/sql/sql_crypt.cc index c4f93cc2a33..3d7d248782b 100644 --- a/sql/sql_crypt.cc +++ b/sql/sql_crypt.cc @@ -28,14 +28,7 @@ #include "mysql_priv.h" -SQL_CRYPT::SQL_CRYPT(const char *password, uint length) -{ - ulong rand_nr[2]; - hash_password(rand_nr,password, length); - crypt_init(rand_nr); -} - -void SQL_CRYPT::crypt_init(ulong *rand_nr) +void SQL_CRYPT::init(ulong *rand_nr) { uint i; randominit(&rand,rand_nr[0],rand_nr[1]); diff --git a/sql/sql_crypt.h b/sql/sql_crypt.h index a5a6bee8a58..2b56c387bd1 100644 --- a/sql/sql_crypt.h +++ b/sql/sql_crypt.h @@ -23,15 +23,15 @@ class SQL_CRYPT :public Sql_alloc struct rand_struct rand,org_rand; char decode_buff[256],encode_buff[256]; uint shift; - void crypt_init(ulong *seed); public: - SQL_CRYPT(const char *seed, uint length); + SQL_CRYPT() {} SQL_CRYPT(ulong *seed) { - crypt_init(seed); + init(seed); } ~SQL_CRYPT() {} - void init() { shift=0; rand=org_rand; } + void init(ulong *seed); + void reinit() { shift=0; rand=org_rand; } void encode(char *str, uint length); void decode(char *str, uint length); }; From f5b51bc1e29d0ae9d8ba9ec7d1c500fe09915e74 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 4 Dec 2009 21:58:40 +0400 Subject: [PATCH 138/344] Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases Building multiple equality predicates containing a constant which is compared as a datetime (with a field) we should take this fact into account and compare the constant with another possible constatns as datetimes as well. E.g. for the SELECT ... WHERE a='2001-01-01' AND a='2001-01-01 00:00:00' we should compare '2001-01-01' with '2001-01-01 00:00:00' as datetimes but not as strings. mysql-test/r/select.result: Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases - test result. mysql-test/t/select.test: Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases - test case. sql/item_cmpfunc.cc: Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases - adding a constant to Item_equal compare it as a datetime value with stored one if there's a date[time] field in a equality predicate. sql/item_cmpfunc.h: Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases - adding a constant to Item_equal compare it as a datetime value with stored one if there's a date[time] field in a equality predicate. sql/sql_select.cc: Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases - adding a constant to Item_equal compare it as a datetime value with stored one if there's a date[time] field in a equality predicate. --- mysql-test/r/select.result | 84 ++++++++++++++++++++++++++++++++++++++ mysql-test/t/select.test | 49 ++++++++++++++++++++++ sql/item_cmpfunc.cc | 46 ++++++++++++++++++--- sql/item_cmpfunc.h | 4 ++ sql/sql_select.cc | 2 +- 5 files changed, 178 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index ff59eadab0c..1b2533eec89 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4456,4 +4456,88 @@ SELECT 1 FROM t2 JOIN t1 ON 1=1 WHERE a != '1' AND NOT a >= b OR NOT ROW(b,a )<> ROW(a,a); 1 DROP TABLE t1,t2; +# +# Bug #49199: Optimizer handles incorrectly: +# field='const1' AND field='const2' in some cases + +CREATE TABLE t1(a DATETIME NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +a +2001-01-01 00:00:00 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1 +DROP TABLE t1; +CREATE TABLE t1(a DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +a +2001-01-01 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01' AS `a` from `test`.`t1` where 1 +DROP TABLE t1; +CREATE TABLE t1(a TIMESTAMP NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +a +2001-01-01 00:00:00 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1 +DROP TABLE t1; +CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +a b +2001-01-01 00:00:00 2001-01-01 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1 +DROP TABLE t1; +CREATE TABLE t1(a DATETIME NOT NULL, b VARCHAR(20) NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +a b +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 0 +SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01'; +a b +2001-01-01 00:00:00 2001-01-01 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1 +DROP TABLE t1; +CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT x.a, y.a, z.a FROM t1 x +JOIN t1 y ON x.a=y.a +JOIN t1 z ON y.a=z.a +WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00'; +a a a +2001-01-01 00:00:00 2001-01-01 00:00:00 2001-01-01 00:00:00 +EXPLAIN EXTENDED SELECT x.a, y.a, z.a FROM t1 x +JOIN t1 y ON x.a=y.a +JOIN t1 z ON y.a=z.a +WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE x system NULL NULL NULL NULL 1 +1 SIMPLE y system NULL NULL NULL NULL 1 +1 SIMPLE z system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a` from `test`.`t1` `x` join `test`.`t1` `y` join `test`.`t1` `z` where 1 End of 5.0 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index a4d3056b66e..eeabd2641d8 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3797,4 +3797,53 @@ SELECT 1 FROM t2 JOIN t1 ON 1=1 DROP TABLE t1,t2; +--echo # +--echo # Bug #49199: Optimizer handles incorrectly: +--echo # field='const1' AND field='const2' in some cases +--echo +CREATE TABLE t1(a DATETIME NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1(a DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1(a TIMESTAMP NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1(a DATETIME NOT NULL, b VARCHAR(20) NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; + +SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01'; +DROP TABLE t1; + +CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT x.a, y.a, z.a FROM t1 x + JOIN t1 y ON x.a=y.a + JOIN t1 z ON y.a=z.a + WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT x.a, y.a, z.a FROM t1 x + JOIN t1 y ON x.a=y.a + JOIN t1 z ON y.a=z.a + WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00'; + + --echo End of 5.0 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d03c68b3560..5c2fb9857d5 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4903,7 +4903,8 @@ Item *Item_bool_rowready_func2::negated_item() } Item_equal::Item_equal(Item_field *f1, Item_field *f2) - : Item_bool_func(), const_item(0), eval_item(0), cond_false(0) + : Item_bool_func(), const_item(0), eval_item(0), cond_false(0), + compare_as_dates(FALSE) { const_item_cache= 0; fields.push_back(f1); @@ -4916,6 +4917,7 @@ Item_equal::Item_equal(Item *c, Item_field *f) const_item_cache= 0; fields.push_back(f); const_item= c; + compare_as_dates= f->is_datetime(); } @@ -4930,9 +4932,45 @@ Item_equal::Item_equal(Item_equal *item_equal) fields.push_back(item); } const_item= item_equal->const_item; + compare_as_dates= item_equal->compare_as_dates; cond_false= item_equal->cond_false; } + +void Item_equal::compare_const(Item *c) +{ + if (compare_as_dates) + { + cmp.set_datetime_cmp_func(&c, &const_item); + cond_false= cmp.compare(); + } + else + { + Item_func_eq *func= new Item_func_eq(c, const_item); + func->set_cmp_func(); + func->quick_fix_field(); + cond_false= !func->val_int(); + } + if (cond_false) + const_item_cache= 1; +} + + +void Item_equal::add(Item *c, Item_field *f) +{ + if (cond_false) + return; + if (!const_item) + { + DBUG_ASSERT(f); + const_item= c; + compare_as_dates= f->is_datetime(); + return; + } + compare_const(c); +} + + void Item_equal::add(Item *c) { if (cond_false) @@ -4942,11 +4980,7 @@ void Item_equal::add(Item *c) const_item= c; return; } - Item_func_eq *func= new Item_func_eq(c, const_item); - func->set_cmp_func(); - func->quick_fix_field(); - if ((cond_false= !func->val_int())) - const_item_cache= 1; + compare_const(c); } void Item_equal::add(Item_field *f) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index db831c7030c..89bc6f9570b 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1477,7 +1477,9 @@ class Item_equal: public Item_bool_func List fields; /* list of equal field items */ Item *const_item; /* optional constant item equal to fields items */ cmp_item *eval_item; + Arg_comparator cmp; bool cond_false; + bool compare_as_dates; public: inline Item_equal() : Item_bool_func(), const_item(0), eval_item(0), cond_false(0) @@ -1486,6 +1488,8 @@ public: Item_equal(Item *c, Item_field *f); Item_equal(Item_equal *item_equal); inline Item* get_const() { return const_item; } + void compare_const(Item *c); + void add(Item *c, Item_field *f); void add(Item *c); void add(Item_field *f); uint members(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index df7c5af3ebc..9f0843fe0db 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7237,7 +7237,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item, already contains a constant and its value is not equal to the value of const_item. */ - item_equal->add(const_item); + item_equal->add(const_item, field_item); } else { From 24e1b16bc280c21de61287f07c3c02bc89387601 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Sat, 5 Dec 2009 22:09:41 +0000 Subject: [PATCH 139/344] Post-push fix for BUG#45292. --- mysql-test/suite/binlog/t/binlog_index.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/binlog/t/binlog_index.test b/mysql-test/suite/binlog/t/binlog_index.test index 8e54c028dbd..6bfa625422c 100644 --- a/mysql-test/suite/binlog/t/binlog_index.test +++ b/mysql-test/suite/binlog/t/binlog_index.test @@ -3,6 +3,7 @@ # source include/have_log_bin.inc; source include/not_embedded.inc; +source include/have_debug.inc; call mtr.add_suppression('Attempting backtrace'); call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file'); From 595719280eeec7dc9dda340d001de72a728b0ed1 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Sun, 6 Dec 2009 01:11:32 +0000 Subject: [PATCH 140/344] BUG#49479: Slave stops with syntax error: LOAD DATA event without escaped field names When in mixed or statement mode, the master logs LOAD DATA queries by resorting to an Execute_load_query_log_event. This event does not contain the original query, but a rewritten version of it, which includes the table field names. However, the rewrite does not escape the field names. If these names match a reserved keyword, then the slave will stop with a syntax error when executing the event. We fix this by escaping the fields names as it happens already for the table name. mysql-test/extra/rpl_tests/rpl_loaddata.test: Added test case for the reported bug. mysql-test/r/mysqlbinlog.result: Changed result to support escaped field name. mysql-test/suite/binlog/r/binlog_killed_simulate.result: Changed result to support escaped field name. mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result: Changed result to support escaped field name. mysql-test/suite/binlog/r/binlog_stm_blackhole.result: Changed result to support escaped field name. mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result: Changed result to support escaped field name. mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result: Changed result to support escaped field name. mysql-test/suite/rpl/r/rpl_loaddata.result: Added result for new test. Changed show slave status positions which are now different because of extra escape character in field names. mysql-test/suite/rpl/r/rpl_loaddata_fatal.result: Changed show slave status positions which are now different because of extra escape character. mysql-test/suite/rpl/r/rpl_loaddata_map.result: Changed result to support escaped field name. mysql-test/suite/rpl/r/rpl_stm_log.result: Changed result to support escaped field name. mysql-test/t/mysqlbinlog.test: Changed positions which is now different because of extra escape character in field names. sql/sql_load.cc: Appended escape characters before and after field names. --- mysql-test/extra/rpl_tests/rpl_loaddata.test | 14 +++++++++ mysql-test/r/mysqlbinlog.result | 30 +++++++++---------- .../binlog/r/binlog_killed_simulate.result | 2 +- .../r/binlog_row_mix_innodb_myisam.result | 2 +- .../binlog/r/binlog_stm_blackhole.result | 2 +- .../r/binlog_stm_mix_innodb_myisam.result | 4 +-- .../suite/rpl/r/rpl_innodb_mixed_dml.result | 2 +- mysql-test/suite/rpl/r/rpl_loaddata.result | 21 +++++++++++-- .../suite/rpl/r/rpl_loaddata_fatal.result | 2 +- .../suite/rpl/r/rpl_loaddata_map.result | 2 +- mysql-test/suite/rpl/r/rpl_stm_log.result | 6 ++-- mysql-test/t/mysqlbinlog.test | 4 +-- sql/sql_load.cc | 6 ++++ 13 files changed, 67 insertions(+), 30 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_loaddata.test b/mysql-test/extra/rpl_tests/rpl_loaddata.test index 7db12600456..649337b2a24 100644 --- a/mysql-test/extra/rpl_tests/rpl_loaddata.test +++ b/mysql-test/extra/rpl_tests/rpl_loaddata.test @@ -219,4 +219,18 @@ source include/diff_tables.inc; -- sync_slave_with_master +# BUG#49479: LOAD DATA INFILE is binlogged without escaping field names +-- source include/master-slave-reset.inc +-- connection master +use test; +CREATE TABLE t1 (`key` TEXT, `text` TEXT); + +LOAD DATA INFILE '../../std_data/loaddata2.dat' REPLACE INTO TABLE `t1` FIELDS TERMINATED BY ','; +SELECT * FROM t1; + +-- sync_slave_with_master +-- connection master +DROP TABLE t1; +-- sync_slave_with_master + # End of 4.1 tests diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index 5f32561798b..9d4fde96d18 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -44,16 +44,16 @@ SET TIMESTAMP=1000000000/*!*/; insert into t2 values () /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (word) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`word`) /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (word) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`word`) /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (word) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`word`) /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (word) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`word`) /*!*/; DELIMITER ; # End of log file @@ -144,16 +144,16 @@ SET TIMESTAMP=1000000000/*!*/; insert into t2 values () /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (word) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`word`) /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (word) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`word`) /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (word) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`word`) /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (word) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`word`) /*!*/; DELIMITER ; # End of log file @@ -359,29 +359,29 @@ SET @@session.collation_database=DEFAULT/*!*/; create table t1 (a varchar(64) character set utf8) /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`) /*!*/; SET TIMESTAMP=1000000000/*!*/; SET @@session.collation_database=7/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`) /*!*/; SET TIMESTAMP=1000000000/*!*/; SET @@session.collation_database=DEFAULT/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`) /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`) /*!*/; SET TIMESTAMP=1000000000/*!*/; SET @@session.collation_database=7/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-a-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-a-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`) /*!*/; SET TIMESTAMP=1000000000/*!*/; SET @@session.collation_database=DEFAULT/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-b-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-b-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`) /*!*/; SET TIMESTAMP=1000000000/*!*/; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-c-0' INTO TABLE `t1` CHARACTER SET koi8r FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a) +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-c-0' INTO TABLE `t1` CHARACTER SET koi8r FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`) /*!*/; SET TIMESTAMP=1000000000/*!*/; drop table t1 diff --git a/mysql-test/suite/binlog/r/binlog_killed_simulate.result b/mysql-test/suite/binlog/r/binlog_killed_simulate.result index df04f5129cf..0e1b5c92d57 100644 --- a/mysql-test/suite/binlog/r/binlog_killed_simulate.result +++ b/mysql-test/suite/binlog/r/binlog_killed_simulate.result @@ -19,7 +19,7 @@ ERROR 70100: Query execution was interrupted show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# -master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t2` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a, b) ;file_id=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t2` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, `b`) ;file_id=# select (@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) is not null; diff --git a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result index 4ccc3b5e797..ef98275041c 100644 --- a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result @@ -929,7 +929,7 @@ master-bin.000001 # User var # # @`b`=_latin1 0x3135 COLLATE latin1_swedish_ci master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# master-bin.000001 # Intvar # # INSERT_ID=10 master-bin.000001 # User var # # @`b`=_latin1 0x3135 COLLATE latin1_swedish_ci -master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a, @b) SET b=((@b) + `bug27417`(2)) ;file_id=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, @b) SET `b`=((@b) + `bug27417`(2)) ;file_id=# master-bin.000001 # Query # # ROLLBACK drop trigger trg_del_t2; drop table t1,t2,t3,t4,t5; diff --git a/mysql-test/suite/binlog/r/binlog_stm_blackhole.result b/mysql-test/suite/binlog/r/binlog_stm_blackhole.result index 434c1b0896f..b2e6ac854cf 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_blackhole.result +++ b/mysql-test/suite/binlog/r/binlog_stm_blackhole.result @@ -127,7 +127,7 @@ master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `test`; create table t2 (a varchar(200)) engine=blackhole master-bin.000001 # Query # # BEGIN master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=581 -master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE `t2` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a) ;file_id=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE `t2` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`) ;file_id=# master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `test`; alter table t1 add b int master-bin.000001 # Query # # use `test`; alter table t1 drop b diff --git a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result index de83c7a873d..e2f29295383 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result @@ -628,7 +628,7 @@ master-bin.000001 # Query # # BEGIN master-bin.000001 # Intvar # # INSERT_ID=10 master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# master-bin.000001 # Intvar # # INSERT_ID=10 -master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a, @b) SET b=((@b) + `bug27417`(2)) ;file_id=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, @b) SET `b`=((@b) + `bug27417`(2)) ;file_id=# master-bin.000001 # Query # # ROLLBACK /* the output must denote there is the query */; drop trigger trg_del_t2; @@ -866,7 +866,7 @@ master-bin.000001 # User var # # @`b`=_latin1 0x3135 COLLATE latin1_swedish_ci master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# master-bin.000001 # Intvar # # INSERT_ID=10 master-bin.000001 # User var # # @`b`=_latin1 0x3135 COLLATE latin1_swedish_ci -master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a, @b) SET b=((@b) + `bug27417`(2)) ;file_id=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, @b) SET `b`=((@b) + `bug27417`(2)) ;file_id=# master-bin.000001 # Query # # ROLLBACK drop trigger trg_del_t2; drop table t1,t2,t3,t4,t5; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index 3a1c2b68b01..fbfebbaa590 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -885,7 +885,7 @@ master-bin.000001 # Query 1 # use `test_rpl`; DELETE FROM t2 master-bin.000001 # Xid 1 # # master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Begin_load_query 1 # ;file_id=#;block_len=# -master-bin.000001 # Execute_load_query 1 # use `test_rpl`; LOAD DATA INFILE 'MYSQLTEST_VARDIR/std_data/rpl_mixed.dat' INTO TABLE `t1` FIELDS TERMINATED BY '|' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (a, b) ;file_id=# +master-bin.000001 # Execute_load_query 1 # use `test_rpl`; LOAD DATA INFILE 'MYSQLTEST_VARDIR/std_data/rpl_mixed.dat' INTO TABLE `t1` FIELDS TERMINATED BY '|' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, `b`) ;file_id=# master-bin.000001 # Xid 1 # # master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Query 1 # use `test_rpl`; DELETE FROM t1 diff --git a/mysql-test/suite/rpl/r/rpl_loaddata.result b/mysql-test/suite/rpl/r/rpl_loaddata.result index ca9c14691b0..5c6a67d6f3c 100644 --- a/mysql-test/suite/rpl/r/rpl_loaddata.result +++ b/mysql-test/suite/rpl/r/rpl_loaddata.result @@ -36,7 +36,7 @@ set global sql_slave_skip_counter=1; start slave; 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 Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 2009 # # master-bin.000001 Yes Yes # 0 0 2009 # None 0 No # No 0 0 +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 2025 # # master-bin.000001 Yes Yes # 0 0 2025 # None 0 No # No 0 0 set sql_log_bin=0; delete from t1; set sql_log_bin=1; @@ -46,7 +46,7 @@ change master to master_user='test'; change master to master_user='root'; 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 Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 2044 # # master-bin.000001 No No # 0 0 2044 # None 0 No # No 0 0 +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 2060 # # master-bin.000001 No No # 0 0 2060 # None 0 No # No 0 0 set global sql_slave_skip_counter=1; start slave; set sql_log_bin=0; @@ -115,3 +115,20 @@ use b48297_db1; Comparing tables master:b48297_db1.t1 and slave:b48297_db1.t1 DROP DATABASE b48297_db1; DROP DATABASE b42897_db2; +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; +use test; +CREATE TABLE t1 (`key` TEXT, `text` TEXT); +LOAD DATA INFILE '../../std_data/loaddata2.dat' REPLACE INTO TABLE `t1` FIELDS TERMINATED BY ','; +SELECT * FROM t1; +key text +Field A 'Field B' +Field 1 'Field 2' +Field 3 'Field 4' +'Field 5' 'Field 6' +Field 6 'Field 7' +DROP TABLE t1; diff --git a/mysql-test/suite/rpl/r/rpl_loaddata_fatal.result b/mysql-test/suite/rpl/r/rpl_loaddata_fatal.result index 35696615b5a..ba0aa847cf7 100644 --- a/mysql-test/suite/rpl/r/rpl_loaddata_fatal.result +++ b/mysql-test/suite/rpl/r/rpl_loaddata_fatal.result @@ -53,7 +53,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 556 +Read_Master_Log_Pos 560 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 diff --git a/mysql-test/suite/rpl/r/rpl_loaddata_map.result b/mysql-test/suite/rpl/r/rpl_loaddata_map.result index 006f84043a4..91624b15ef8 100644 --- a/mysql-test/suite/rpl/r/rpl_loaddata_map.result +++ b/mysql-test/suite/rpl/r/rpl_loaddata_map.result @@ -20,7 +20,7 @@ master-bin.000001 # Query # # use `test`; create table t2 (id int not null prima master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# master-bin.000001 # Append_block # # ;file_id=#;block_len=# master-bin.000001 # Append_block # # ;file_id=#;block_len=# -master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' INTO TABLE `t2` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (id) ;file_id=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' INTO TABLE `t2` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`id`) ;file_id=# ==== Verify results on slave ==== [on slave] select count(*) from t2 /* 5 000 */; diff --git a/mysql-test/suite/rpl/r/rpl_stm_log.result b/mysql-test/suite/rpl/r/rpl_stm_log.result index d73b8990041..47556a33e97 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_log.result +++ b/mysql-test/suite/rpl/r/rpl_stm_log.result @@ -25,7 +25,7 @@ master-bin.000001 # Query 1 # use `test`; insert into t1 values (NULL) master-bin.000001 # Query 1 # use `test`; drop table t1 master-bin.000001 # Query 1 # use `test`; create table t1 (word char(20) not null)ENGINE=MyISAM master-bin.000001 # Begin_load_query 1 # ;file_id=1;block_len=581 -master-bin.000001 # Execute_load_query 1 # use `test`; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' IGNORE 1 LINES (word) ;file_id=1 +master-bin.000001 # Execute_load_query 1 # use `test`; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' IGNORE 1 LINES (`word`) ;file_id=1 show binlog events from 106 limit 1; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=MyISAM @@ -193,7 +193,7 @@ master-bin.000001 # Query # # use `test`; insert into t1 values (NULL) master-bin.000001 # Query # # use `test`; drop table t1 master-bin.000001 # Query # # use `test`; create table t1 (word char(20) not null)ENGINE=MyISAM master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# -master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' IGNORE 1 LINES (word) ;file_id=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' IGNORE 1 LINES (`word`) ;file_id=# master-bin.000001 # Rotate # # master-bin.000002;pos=4 show binlog events in 'master-bin.000002'; Log_name Pos Event_type Server_id End_log_pos Info @@ -218,7 +218,7 @@ slave-bin.000001 # Query 1 # use `test`; insert into t1 values (NULL) slave-bin.000001 # Query 1 # use `test`; drop table t1 slave-bin.000001 # Query 1 # use `test`; create table t1 (word char(20) not null)ENGINE=MyISAM slave-bin.000001 # Begin_load_query 1 # ;file_id=1;block_len=581 -slave-bin.000001 # Execute_load_query 1 # use `test`; LOAD DATA INFILE '../../tmp/SQL_LOAD-2-1-1.data' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' IGNORE 1 LINES (word) ;file_id=1 +slave-bin.000001 # Execute_load_query 1 # use `test`; LOAD DATA INFILE '../../tmp/SQL_LOAD-2-1-1.data' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' IGNORE 1 LINES (`word`) ;file_id=1 slave-bin.000001 # Query 1 # use `test`; create table t3 (a int)ENGINE=MyISAM slave-bin.000001 # Rotate 2 # slave-bin.000002;pos=4 show binlog events in 'slave-bin.000002' from 4; diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 78661b1bbc4..687ad62b17c 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -71,7 +71,7 @@ select "--- --position --" as ""; --enable_query_log --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ ---exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --position=330 $MYSQLD_DATADIR/master-bin.000002 +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --position=332 $MYSQLD_DATADIR/master-bin.000002 # These are tests for remote binlog. @@ -108,7 +108,7 @@ select "--- --position --" as ""; --enable_query_log --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ ---exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --position=330 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --position=332 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 # Bug#7853 mysqlbinlog does not accept input from stdin --disable_query_log diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 8109ca4313e..326a7517ed6 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -640,7 +640,11 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, if (n++) pfields.append(", "); if (item->name) + { + pfields.append("`"); pfields.append(item->name); + pfields.append("`"); + } else item->print(&pfields, QT_ORDINARY); } @@ -660,7 +664,9 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, val= lv++; if (n++) pfields.append(", "); + pfields.append("`"); pfields.append(item->name); + pfields.append("`"); pfields.append("="); val->print(&pfields, QT_ORDINARY); } From 63ff2b4c2e7db9872515cec3d897817ac83d109c Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Sun, 6 Dec 2009 18:11:37 +0100 Subject: [PATCH 141/344] Bug #47391 no stack trace printed to error log on solaris after a crash This patch adds a Solaris-specific version of print_stacktrace() which uses printstack(2), available on all Solaris versions since Solaris 9. (While Solaris 11 adds support for the glibc functions backtrace_*() as of PSARC/2007/162, printstack() is used for consistency over all Solaris versions.) The symbol names are mangled, so use of c++filt may be required as described in the MySQL documentation. sql/stacktrace.c: Added Solaris-specific print_stacktrace(). --- sql/stacktrace.c | 19 +++++++++++++++++++ sql/stacktrace.h | 3 +++ 2 files changed, 22 insertions(+) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 4e6ad68c172..295a7a3e1e2 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -226,6 +226,25 @@ end: stack trace is much more helpful in diagnosing the problem, so please do \n\ resolve it\n"); } + +#elif defined(__sun) + +/* Use Solaris' symbolic stack trace routine. */ +#include + +void print_stacktrace(gptr stack_bottom __attribute__((unused)), + ulong thread_stack __attribute__((unused))) +{ + if (printstack(fileno(stderr)) == -1) + fprintf(stderr, "Error when traversing the stack, stack appears corrupt.\n"); + else + fprintf(stderr, "Please read " + "http://dev.mysql.com/doc/mysql/en/using-stack-trace.html " + "and follow instructions on how to resolve the stack trace. " + "Resolved\nstack trace is much more helpful in diagnosing the " + "problem, so please do \nresolve it\n"); +} + #endif /* TARGET_OS_LINUX */ #endif /* HAVE_STACKTRACE */ diff --git a/sql/stacktrace.h b/sql/stacktrace.h index e5e17cc5b9b..718b545b775 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -35,6 +35,9 @@ void check_thread_lib(void); #define HAVE_STACKTRACE extern void set_exception_pointers(EXCEPTION_POINTERS *ep); #define init_stacktrace() {} +#elif defined(__sun) +#define HAVE_STACKTRACE +#define init_stacktrace() {} #endif #ifdef HAVE_STACKTRACE From c75712caa81a58164019754a3690ddf434d17f61 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Sun, 6 Dec 2009 23:12:11 +0000 Subject: [PATCH 142/344] BUG#49119: Master crashes when executing 'REVOKE ... ON {PROCEDURE|FUNCTION} FROM ...' The master would hit an assertion when binary log was active. This was due to the fact that the thread's diagnostics area was being cleared before writing to the binlog, independently of mysql_routine_grant returning an error or not. When mysql_routine_grant was to return an error, the return value and the diagnostics area contents would mismatch. Consequently, neither my_ok would be called nor an error would be signaled in the diagnostics area, eventually triggering the assertion in net_end_statement. We fix this by not clearing the diagnostics area at binlogging time. --- mysql-test/suite/rpl/r/rpl_do_grant.result | 73 +++++++++++++++ mysql-test/suite/rpl/t/rpl_do_grant.test | 100 +++++++++++++++++++++ sql/sql_acl.cc | 2 +- 3 files changed, 174 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/r/rpl_do_grant.result b/mysql-test/suite/rpl/r/rpl_do_grant.result index 0913b1afdbf..65c60acc651 100644 --- a/mysql-test/suite/rpl/r/rpl_do_grant.result +++ b/mysql-test/suite/rpl/r/rpl_do_grant.result @@ -169,4 +169,77 @@ DROP USER 'create_rout_db'@'localhost'; call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); USE mtr; call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); +######## BUG#49119 ####### +### i) test case from the 'how to repeat section' +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(c1 INT); +CREATE PROCEDURE p1() SELECT * FROM t1 | +REVOKE EXECUTE ON PROCEDURE p1 FROM 'root'@'localhost'; +ERROR 42000: There is no such grant defined for user 'root' on host 'localhost' on routine 'p1' +DROP TABLE t1; +DROP PROCEDURE p1; +### ii) Test case in which REVOKE partially succeeds +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(c1 INT); +CREATE PROCEDURE p1() SELECT * FROM t1 | +CREATE USER 'user49119'@'localhost'; +GRANT EXECUTE ON PROCEDURE p1 TO 'user49119'@'localhost'; +############################################################## +### Showing grants for both users: root and user49119 (master) +SHOW GRANTS FOR 'user49119'@'localhost'; +Grants for user49119@localhost +GRANT USAGE ON *.* TO 'user49119'@'localhost' +GRANT EXECUTE ON PROCEDURE `test`.`p1` TO 'user49119'@'localhost' +SHOW GRANTS FOR CURRENT_USER; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +############################################################## +############################################################## +### Showing grants for both users: root and user49119 (master) +SHOW GRANTS FOR 'user49119'@'localhost'; +Grants for user49119@localhost +GRANT USAGE ON *.* TO 'user49119'@'localhost' +GRANT EXECUTE ON PROCEDURE `test`.`p1` TO 'user49119'@'localhost' +SHOW GRANTS FOR CURRENT_USER; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +############################################################## +## This statement will make the revoke fail because root has no +## execute grant. However, it will still revoke the grant for +## user49119. +REVOKE EXECUTE ON PROCEDURE p1 FROM 'user49119'@'localhost', 'root'@'localhost'; +ERROR 42000: There is no such grant defined for user 'root' on host 'localhost' on routine 'p1' +############################################################## +### Showing grants for both users: root and user49119 (master) +### after revoke statement failure +SHOW GRANTS FOR 'user49119'@'localhost'; +Grants for user49119@localhost +GRANT USAGE ON *.* TO 'user49119'@'localhost' +SHOW GRANTS FOR CURRENT_USER; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +############################################################## +############################################################# +### Showing grants for both users: root and user49119 (slave) +### after revoke statement failure (should match +SHOW GRANTS FOR 'user49119'@'localhost'; +Grants for user49119@localhost +GRANT USAGE ON *.* TO 'user49119'@'localhost' +SHOW GRANTS FOR CURRENT_USER; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +############################################################## +DROP TABLE t1; +DROP PROCEDURE p1; +DROP USER 'user49119'@'localhost'; "End of test" diff --git a/mysql-test/suite/rpl/t/rpl_do_grant.test b/mysql-test/suite/rpl/t/rpl_do_grant.test index a13adf28b95..d6a06f43d18 100644 --- a/mysql-test/suite/rpl/t/rpl_do_grant.test +++ b/mysql-test/suite/rpl/t/rpl_do_grant.test @@ -216,4 +216,104 @@ connection slave; USE mtr; call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); +# BUG#49119: Master crashes when executing 'REVOKE ... ON +# {PROCEDURE|FUNCTION} FROM ...' +# +# The tests are divided into two test cases: +# +# i) a test case that mimics the one in the bug report. +# +# - We show that, despite the fact, that a revoke command fails +# when binlogging is active, the master will not hit an +# assertion. +# +# ii) a test case that partially succeeds on the master will also +# partially succeed on the slave. +# +# - The revoke statement that partially succeeds tries to revoke +# an EXECUTE grant for two users, and only one of the user has +# the specific grant. This will cause mysql to drop one of the +# grants and report error for the statement. The slave should +# also drop the grants that the master succeed and the SQL +# thread should not stop on statement failure. + +-- echo ######## BUG#49119 ####### +-- echo ### i) test case from the 'how to repeat section' +-- source include/master-slave-reset.inc +-- connection master + +CREATE TABLE t1(c1 INT); +DELIMITER |; +CREATE PROCEDURE p1() SELECT * FROM t1 | +DELIMITER ;| +-- error ER_NONEXISTING_PROC_GRANT +REVOKE EXECUTE ON PROCEDURE p1 FROM 'root'@'localhost'; + +-- sync_slave_with_master + +-- connection master +DROP TABLE t1; +DROP PROCEDURE p1; + +-- sync_slave_with_master + +-- echo ### ii) Test case in which REVOKE partially succeeds + +-- connection master +-- source include/master-slave-reset.inc +-- connection master + +CREATE TABLE t1(c1 INT); +DELIMITER |; +CREATE PROCEDURE p1() SELECT * FROM t1 | +DELIMITER ;| + +CREATE USER 'user49119'@'localhost'; +GRANT EXECUTE ON PROCEDURE p1 TO 'user49119'@'localhost'; + +-- echo ############################################################## +-- echo ### Showing grants for both users: root and user49119 (master) +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- sync_slave_with_master + +-- echo ############################################################## +-- echo ### Showing grants for both users: root and user49119 (master) +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- connection master + +-- echo ## This statement will make the revoke fail because root has no +-- echo ## execute grant. However, it will still revoke the grant for +-- echo ## user49119. +-- error ER_NONEXISTING_PROC_GRANT +REVOKE EXECUTE ON PROCEDURE p1 FROM 'user49119'@'localhost', 'root'@'localhost'; + +-- echo ############################################################## +-- echo ### Showing grants for both users: root and user49119 (master) +-- echo ### after revoke statement failure +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- sync_slave_with_master + +-- echo ############################################################# +-- echo ### Showing grants for both users: root and user49119 (slave) +-- echo ### after revoke statement failure (should match +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- connection master +DROP TABLE t1; +DROP PROCEDURE p1; +DROP USER 'user49119'@'localhost'; + +-- sync_slave_with_master + --echo "End of test" diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 77c72066429..3b81a85c368 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3378,7 +3378,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (write_to_binlog) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); From bd308d1256fa7af7128c24f4a5e2abfb8274437a Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 7 Dec 2009 16:38:56 +0200 Subject: [PATCH 143/344] Bug #42760: Select doesn't return desired results when we have null values Part 2 : There was a special optimization on the ref access method for ORDER BY ... DESC that was set without actually looking on the type of the selected index for ORDER BY. Fixed the SELECT ... ORDER BY .. DESC (it uses a different code path compared to the ASC that has been fixed with the previous fix). --- mysql-test/r/order_by.result | 9 +++++++++ mysql-test/t/order_by.test | 9 +++++++++ sql/sql_select.cc | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index f0e5b5fde3d..87b6c3f5455 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -1111,5 +1111,14 @@ id select_type table type possible_keys key key_len ref rows Extra SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c; col 1 +# Must use ref-or-null on the a_c index +EXPLAIN +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c DESC; +id select_type table type possible_keys key key_len ref rows Extra +x x x ref_or_null a_c,a x x x x x +# Must return 1 row +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c DESC; +col +1 DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index d9a6c0f844d..4da279cc8fd 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -778,6 +778,15 @@ SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c; --echo # Must return 1 row SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c; +# part 2 of the problem : DESC test cases +--echo # Must use ref-or-null on the a_c index +--replace_column 1 x 2 x 3 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c DESC; +--echo # Must return 1 row +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c DESC; + + DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9f0843fe0db..f655db0fc32 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12824,7 +12824,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, } DBUG_RETURN(1); } - if (tab->ref.key_parts <= used_key_parts) + if (tab->ref.key_parts <= used_key_parts && tab->type == JT_REF) { /* SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC From 91aa5e248ed2897a7cad0e3060ce1689fee6a5b2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Dec 2009 16:35:00 +0100 Subject: [PATCH 144/344] Raise version number after cloning 5.0.89 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index e14b4014bea..b206dfbd079 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.0.89) +AM_INIT_AUTOMAKE(mysql, 5.0.90) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=89 +NDB_VERSION_BUILD=90 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From d83167f3ca8ca74197e45f29bd29ceaeebedc2d7 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Tue, 8 Dec 2009 16:03:19 +0000 Subject: [PATCH 145/344] Post-push fix for BUG#45292. Disabled execution in valgrind to avoid false positive memory leaks due to fault-injection tests (i.e. call to abort()). --- mysql-test/suite/binlog/t/binlog_index.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/suite/binlog/t/binlog_index.test b/mysql-test/suite/binlog/t/binlog_index.test index 6bfa625422c..9d4a49602a6 100644 --- a/mysql-test/suite/binlog/t/binlog_index.test +++ b/mysql-test/suite/binlog/t/binlog_index.test @@ -3,6 +3,8 @@ # source include/have_log_bin.inc; source include/not_embedded.inc; +# Don't test this under valgrind, memory leaks will occur +--source include/not_valgrind.inc source include/have_debug.inc; call mtr.add_suppression('Attempting backtrace'); call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); From bc2b3d2ccc109768cf918d91e08639b530518ea1 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Wed, 9 Dec 2009 14:13:56 +0800 Subject: [PATCH 146/344] BUG#45520 rpl_killed_ddl fails sporadically in pb2 There are three issues that caused rpl_killed_ddl fails sporadically in pb2: 1) thd->clear_error() was not called before create Query event if operation is executed successfully. 2) DATABASE d2 might do exist because the statement to CREATE or ALTER it was killed 3) because of bug 43353, kill the query that do DROP FUNCTION or DROP PROCEDURE can result in SP not found This patch fixed all above issues by: 1) Called thd->clear_error() if the operation succeeded. 2) Add IF EXISTS to the DROP DATABASE d2 statement 3) Temporarily disabled testing DROP FUNCTION/PROCEDURE IF EXISTS. mysql-test/t/rpl_killed_ddl.test: DATABASE d2 might not exists, add IF EXITS to the DROP statement sql/sql_db.cc: Called thd->clear_error() if the operation succeeded --- mysql-test/r/rpl_killed_ddl.result | 12 +++--------- mysql-test/t/rpl_killed_ddl.test | 23 ++++++++++++++++------- sql/sql_db.cc | 5 +++-- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/rpl_killed_ddl.result b/mysql-test/r/rpl_killed_ddl.result index aa419a8556e..b9ee915bdce 100644 --- a/mysql-test/r/rpl_killed_ddl.result +++ b/mysql-test/r/rpl_killed_ddl.result @@ -53,7 +53,7 @@ source include/diff_master_slave.inc; DROP DATABASE d1; source include/kill_query.inc; source include/diff_master_slave.inc; -DROP DATABASE d2; +DROP DATABASE IF EXISTS d2; source include/kill_query.inc; source include/diff_master_slave.inc; CREATE FUNCTION f2 () RETURNS INT DETERMINISTIC @@ -63,10 +63,7 @@ source include/diff_master_slave.inc; ALTER FUNCTION f1 SQL SECURITY INVOKER; source include/kill_query.inc; source include/diff_master_slave.inc; -DROP FUNCTION IF EXISTS f1; -source include/kill_query.inc; -source include/diff_master_slave.inc; -DROP FUNCTION IF EXISTS f2; +DROP FUNCTION f1; source include/kill_query.inc; source include/diff_master_slave.inc; CREATE PROCEDURE p2 (OUT rows INT) @@ -79,10 +76,7 @@ source include/diff_master_slave.inc; ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows of table t1'; source include/kill_query.inc; source include/diff_master_slave.inc; -DROP PROCEDURE IF EXISTS p1; -source include/kill_query.inc; -source include/diff_master_slave.inc; -DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE p1; source include/kill_query.inc; source include/diff_master_slave.inc; CREATE TABLE t2 (b int); diff --git a/mysql-test/t/rpl_killed_ddl.test b/mysql-test/t/rpl_killed_ddl.test index f4f2f6ac320..7c07d5eecf0 100644 --- a/mysql-test/t/rpl_killed_ddl.test +++ b/mysql-test/t/rpl_killed_ddl.test @@ -123,7 +123,7 @@ source include/kill_query_and_diff_master_slave.inc; send DROP DATABASE d1; source include/kill_query_and_diff_master_slave.inc; -send DROP DATABASE d2; +send DROP DATABASE IF EXISTS d2; source include/kill_query_and_diff_master_slave.inc; ######## FUNCTION ######## @@ -139,13 +139,21 @@ source include/kill_query_and_diff_master_slave.inc; # function f1 probably does not exist because the ALTER query was # killed -send DROP FUNCTION IF EXISTS f1; +send DROP FUNCTION f1; source include/kill_query_and_diff_master_slave.inc; # function f2 probably does not exist because the CREATE query was # killed -send DROP FUNCTION IF EXISTS f2; -source include/kill_query_and_diff_master_slave.inc; +# +# Temporarily disabled. Because of BUG#43353, KILL the query may +# result in function not found, and for 5.1, DROP statements will be +# logged if the function is not found on master, so the following DROP +# FUNCTION statement may be interrupted and not drop the function on +# master, but still get logged and executed on slave and cause +# inconsistence. Also disable the following DROP PROCEDURE IF EXITS +# below. +#send DROP FUNCTION IF EXISTS f2; +#source include/kill_query_and_diff_master_slave.inc; ######## PROCEDURE ######## @@ -163,11 +171,12 @@ source include/kill_query_and_diff_master_slave.inc; send ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows of table t1'; source include/kill_query_and_diff_master_slave.inc; -send DROP PROCEDURE IF EXISTS p1; +send DROP PROCEDURE p1; source include/kill_query_and_diff_master_slave.inc; -send DROP PROCEDURE IF EXISTS p2; -source include/kill_query_and_diff_master_slave.inc; +# Temporarily disabled because of bug#43353, see comment above for DROP FUNCTION IF EXISTS +#send DROP PROCEDURE IF EXISTS p2; +#source include/kill_query_and_diff_master_slave.inc; ######## TABLE ######## diff --git a/sql/sql_db.cc b/sql/sql_db.cc index be538783458..2ad3953625f 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -541,6 +541,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, file. In this case it's best to just continue as if nothing has happened. (This is a very unlikely senario) */ + thd->clear_error(); } if (!silent) @@ -644,6 +645,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0, /* suppress_use */ TRUE, THD::NOT_KILLED); @@ -655,7 +657,6 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) qinfo.db = db; qinfo.db_len = (uint) strlen(db); - thd->clear_error(); /* These DDL methods and logging protected with LOCK_mysql_create_db */ mysql_bin_log.write(&qinfo); } @@ -769,6 +770,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, query, query_length, 0, /* suppress_use */ TRUE, THD::NOT_KILLED); /* @@ -779,7 +781,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) qinfo.db = db; qinfo.db_len = (uint) strlen(db); - thd->clear_error(); /* These DDL methods and logging protected with LOCK_mysql_create_db */ mysql_bin_log.write(&qinfo); } From b3d9f784783482486fa59a2d93da27aede238154 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Wed, 9 Dec 2009 14:27:46 +0800 Subject: [PATCH 147/344] removed rpl_killed_ddl from disabled list --- mysql-test/t/disabled.def | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 7ce67d3fa89..062667c249e 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -25,4 +25,3 @@ loaddata_autocom_ndb : Bug#35148: Error '4009 Cluster Failure' in various tests ndb_autodiscover3 : Bug#35148: Error '4009 Cluster Failure' in various tests on various platforms ndb_autodiscover : Bug#45972: ndb.ndb_autodiscover fails occasionally with pb2 ndb_autodiscover2 : Bug#45972: ndb.ndb_autodiscover fails occasionally with pb2 -rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2 From 9060aa68afa8483883583b3b25e748f17ca6d3a5 Mon Sep 17 00:00:00 2001 From: Olav Sandstaa Date: Wed, 9 Dec 2009 10:16:11 +0100 Subject: [PATCH 148/344] Fix for Bug#49506 Valgrind error in make_cond_for_table_from_pred This fix has been proposed by Sergey Petrunya and has been contributed under SCA by sca@askmonty.org. The cause for this valgrind error is that in the function add_cond_and_fix() in sql_select.cc an Item_cond_and object is created. This is marked as fixed but does not have a correct table_map() attribute. Later, in make_join_select(), if engine_condition_pushdown is in use, this table map is used and results in the valgrind error. The fix is to add a call to update_used_tables() in add_cond_and_fix() so that the table map is updated correctly. This patch is tested by multiple existing tests (e.g. the tests innodb_mysql, innodb, fulltext, compress all produces this valgrind warning/error without this fix). sql/sql_select.cc: In add_cond_and_fix() add a call to update_used_tables() to ensure the table map is updated. --- sql/sql_select.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 569d8183ab6..b2a4958020a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5859,6 +5859,7 @@ inline void add_cond_and_fix(Item **e1, Item *e2) { *e1= res; res->quick_fix_field(); + res->update_used_tables(); } } else From 1285ecd4688295c0aae28b314ef8a4c9ae3b6c14 Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Wed, 9 Dec 2009 18:43:45 +0300 Subject: [PATCH 149/344] Bug#49489: Uninitialized cache led to a wrong result. Arg_comparator uses Item_cache objects to store constants being compared when they're need a type conversion. Because this cache wasn't initialized properly Arg_comparator might produce wrong comparison result. The Arg_comparator::cache_converted_constant function now initializes cache prior to usage. mysql-test/r/select.result: Added a test case for he bug#49489. mysql-test/t/select.test: Added a test case for he bug#49489. sql/item_cmpfunc.cc: Bug#49489: Uninitialized cache led to a wrong result. The Arg_comparator::cache_converted_constant function now initializes cache prior to usage. --- mysql-test/r/select.result | 10 ++++++++++ mysql-test/t/select.test | 9 +++++++++ sql/item_cmpfunc.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index d0b2a575a32..1750051289a 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4609,4 +4609,14 @@ HAVING v <= 't' ORDER BY pk; v DROP TABLE t1; +# +# Bug#49489 Uninitialized cache led to a wrong result. +# +CREATE TABLE t1(c1 DOUBLE(5,4)); +INSERT INTO t1 VALUES (9.1234); +SELECT * FROM t1 WHERE c1 < 9.12345; +c1 +9.1234 +DROP TABLE t1; +# End of test for bug#49489. End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index ac65e5cbaf5..982aec726f7 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3964,4 +3964,13 @@ ORDER BY pk; DROP TABLE t1; +--echo # +--echo # Bug#49489 Uninitialized cache led to a wrong result. +--echo # +CREATE TABLE t1(c1 DOUBLE(5,4)); +INSERT INTO t1 VALUES (9.1234); +SELECT * FROM t1 WHERE c1 < 9.12345; +DROP TABLE t1; +--echo # End of test for bug#49489. + --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5415d6f4f8a..a3c3051d790 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1023,7 +1023,7 @@ Item** Arg_comparator::cache_converted_constant(THD *thd, Item **value, (*value)->const_item() && type != (*value)->result_type()) { Item_cache *cache= Item_cache::get_cache(*value, type); - cache->store(*value); + cache->setup(*value); *cache_item= cache; return cache_item; } From 91689490478f3d8a2fc6280b57d3a922f5e357f5 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Thu, 10 Dec 2009 11:44:19 +0800 Subject: [PATCH 150/344] Post fix for bug#45520 mysql-test/include/kill_query.inc: Error 1034 can be generated when change MyISAM table indexes was interrupted mysql-test/r/rpl_killed_ddl.result: table t4 may not exists because the ALTER above was interrupted mysql-test/t/rpl_killed_ddl.test: table t4 may not exists because the ALTER above was interrupted --- mysql-test/include/kill_query.inc | 2 +- mysql-test/r/rpl_killed_ddl.result | 1 + mysql-test/t/rpl_killed_ddl.test | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/include/kill_query.inc b/mysql-test/include/kill_query.inc index 341c3b93535..b303ed0ec39 100644 --- a/mysql-test/include/kill_query.inc +++ b/mysql-test/include/kill_query.inc @@ -52,7 +52,7 @@ if (`SELECT '$debug_lock' != ''`) # reap the result of the waiting query connection $connection_name; -error 0, 1317, 1307, 1306, 1334, 1305; +error 0, 1317, 1307, 1306, 1334, 1305, 1034; reap; connection master; diff --git a/mysql-test/r/rpl_killed_ddl.result b/mysql-test/r/rpl_killed_ddl.result index b9ee915bdce..59c80d8f6cc 100644 --- a/mysql-test/r/rpl_killed_ddl.result +++ b/mysql-test/r/rpl_killed_ddl.result @@ -94,6 +94,7 @@ source include/diff_master_slave.inc; DROP INDEX i1 on t1; source include/kill_query.inc; source include/diff_master_slave.inc; +CREATE TABLE IF NOT EXISTS t4 (a int); CREATE TRIGGER tr2 BEFORE INSERT ON t4 FOR EACH ROW BEGIN DELETE FROM t1 WHERE a=NEW.a; diff --git a/mysql-test/t/rpl_killed_ddl.test b/mysql-test/t/rpl_killed_ddl.test index 7c07d5eecf0..b0d7258998f 100644 --- a/mysql-test/t/rpl_killed_ddl.test +++ b/mysql-test/t/rpl_killed_ddl.test @@ -203,6 +203,11 @@ source include/kill_query_and_diff_master_slave.inc; ######## TRIGGER ######## +# Make sure table t4 exists +connection master; +CREATE TABLE IF NOT EXISTS t4 (a int); +connection master1; + let $diff_statement= SHOW TRIGGERS LIKE 'v%'; DELIMITER //; From 3246383301e2eacfd14bdb0f5399ab44659002fe Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 10 Dec 2009 10:05:44 +0400 Subject: [PATCH 151/344] Bug #49480: WHERE using YEAR columns returns unexpected results A few problems were found in the fix for bug 43668: 1) Comparison of the YEAR column with NULL always returned TRUE; 2) Comparison of the YEAR column with constants always returned unpredictable result; 3) Unnecessary conversion warnings when comparing a non-integer constant with a NULL value in the YEAR column; The problems described above have been resolved with an exception: zero (i.e. invalid) YEAR column value comparison with 00 or 2000 still fail (it is not a regression and it was not a regression), so MIN/MAX on YEAR column containing zero value still fail. mysql-test/r/type_year.result: Test case for bug #49480. mysql-test/t/type_year.test: Test case for bug #49480. sql/item_cmpfunc.cc: - The get_year_value() function has been modified to make its return value compatible with the get_datetime_value() return value (i.e. to convert numeric values into the YYYY0000000000 (YYYY-00-00 00:00:00) form. - The Arg_comparator::set_cmp_func method has been modified to use the get_year_value function if get_datetime_value() is not applicable. From now only 2 cases have a special processing there: * both comparing items have MYSQL_TYPE_YEAR field type or * one item have is MYSQL_TYPE_YEAR and other one is is_datetime()-compliant. - New helper function try_year_cmp_func() has been added for the better code readability to call from Arg_comparator::set_cmp_func(). - The Arg_comparator::compare_year method has been removed since get_year_value() is compatible with the old Arg_comparator::compare_datetime method that doesn't have problems #1-#3 (see whole patch entry commentary). sql/item_cmpfunc.h: - New helper function try_year_cmp_func() has been added for the better code readability to call from Arg_comparator::set_cmp_func(). - Unnecessary Arg_comparator::year_as_datetime and Arg_comparator::compare_year() declarations have been removed. --- mysql-test/r/type_year.result | 264 ++++++++++++++++++++++++++++++++++ mysql-test/t/type_year.test | 106 ++++++++++++++ sql/item_cmpfunc.cc | 144 +++++++------------ sql/item_cmpfunc.h | 9 +- 4 files changed, 421 insertions(+), 102 deletions(-) diff --git a/mysql-test/r/type_year.result b/mysql-test/r/type_year.result index e52947455c8..56b326327c6 100644 --- a/mysql-test/r/type_year.result +++ b/mysql-test/r/type_year.result @@ -46,3 +46,267 @@ a 2001 drop table t1; End of 5.0 tests +# +# Bug #49480: WHERE using YEAR columns returns unexpected results +# +CREATE TABLE t2(yy YEAR(2), c2 CHAR(4)); +CREATE TABLE t4(yyyy YEAR(4), c4 CHAR(4)); +INSERT INTO t2 (c2) VALUES (NULL),(1970),(1999),(2000),(2001),(2069); +INSERT INTO t4 (c4) SELECT c2 FROM t2; +UPDATE t2 SET yy = c2; +UPDATE t4 SET yyyy = c4; +SELECT * FROM t2; +yy c2 +NULL NULL +70 1970 +99 1999 +00 2000 +01 2001 +69 2069 +SELECT * FROM t4; +yyyy c4 +NULL NULL +1970 1970 +1999 1999 +2000 2000 +2001 2001 +2069 2069 +# Comparison of YEAR(2) with YEAR(4) +SELECT * FROM t2, t4 WHERE yy = yyyy; +yy c2 yyyy c4 +70 1970 1970 1970 +99 1999 1999 1999 +00 2000 2000 2000 +01 2001 2001 2001 +69 2069 2069 2069 +SELECT * FROM t2, t4 WHERE yy <=> yyyy; +yy c2 yyyy c4 +NULL NULL NULL NULL +70 1970 1970 1970 +99 1999 1999 1999 +00 2000 2000 2000 +01 2001 2001 2001 +69 2069 2069 2069 +SELECT * FROM t2, t4 WHERE yy < yyyy; +yy c2 yyyy c4 +70 1970 1999 1999 +70 1970 2000 2000 +99 1999 2000 2000 +70 1970 2001 2001 +99 1999 2001 2001 +00 2000 2001 2001 +70 1970 2069 2069 +99 1999 2069 2069 +00 2000 2069 2069 +01 2001 2069 2069 +SELECT * FROM t2, t4 WHERE yy > yyyy; +yy c2 yyyy c4 +99 1999 1970 1970 +00 2000 1970 1970 +01 2001 1970 1970 +69 2069 1970 1970 +00 2000 1999 1999 +01 2001 1999 1999 +69 2069 1999 1999 +01 2001 2000 2000 +69 2069 2000 2000 +69 2069 2001 2001 +# Comparison of YEAR(2) with YEAR(2) +SELECT * FROM t2 a, t2 b WHERE a.yy = b.yy; +yy c2 yy c2 +70 1970 70 1970 +99 1999 99 1999 +00 2000 00 2000 +01 2001 01 2001 +69 2069 69 2069 +SELECT * FROM t2 a, t2 b WHERE a.yy <=> b.yy; +yy c2 yy c2 +NULL NULL NULL NULL +70 1970 70 1970 +99 1999 99 1999 +00 2000 00 2000 +01 2001 01 2001 +69 2069 69 2069 +SELECT * FROM t2 a, t2 b WHERE a.yy < b.yy; +yy c2 yy c2 +70 1970 99 1999 +70 1970 00 2000 +99 1999 00 2000 +70 1970 01 2001 +99 1999 01 2001 +00 2000 01 2001 +70 1970 69 2069 +99 1999 69 2069 +00 2000 69 2069 +01 2001 69 2069 +# Comparison of YEAR(4) with YEAR(4) +SELECT * FROM t4 a, t4 b WHERE a.yyyy = b.yyyy; +yyyy c4 yyyy c4 +1970 1970 1970 1970 +1999 1999 1999 1999 +2000 2000 2000 2000 +2001 2001 2001 2001 +2069 2069 2069 2069 +SELECT * FROM t4 a, t4 b WHERE a.yyyy <=> b.yyyy; +yyyy c4 yyyy c4 +NULL NULL NULL NULL +1970 1970 1970 1970 +1999 1999 1999 1999 +2000 2000 2000 2000 +2001 2001 2001 2001 +2069 2069 2069 2069 +SELECT * FROM t4 a, t4 b WHERE a.yyyy < b.yyyy; +yyyy c4 yyyy c4 +1970 1970 1999 1999 +1970 1970 2000 2000 +1999 1999 2000 2000 +1970 1970 2001 2001 +1999 1999 2001 2001 +2000 2000 2001 2001 +1970 1970 2069 2069 +1999 1999 2069 2069 +2000 2000 2069 2069 +2001 2001 2069 2069 +# Comparison with constants: +SELECT * FROM t2 WHERE yy = NULL; +yy c2 +SELECT * FROM t4 WHERE yyyy = NULL; +yyyy c4 +SELECT * FROM t2 WHERE yy <=> NULL; +yy c2 +NULL NULL +SELECT * FROM t4 WHERE yyyy <=> NULL; +yyyy c4 +NULL NULL +SELECT * FROM t2 WHERE yy < NULL; +yy c2 +SELECT * FROM t2 WHERE yy > NULL; +yy c2 +SELECT * FROM t2 WHERE yy = NOW(); +yy c2 +SELECT * FROM t4 WHERE yyyy = NOW(); +yyyy c4 +SELECT * FROM t2 WHERE yy = 99; +yy c2 +99 1999 +SELECT * FROM t2 WHERE 99 = yy; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 99; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 'test'; +yy c2 +00 2000 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'test' +SELECT * FROM t4 WHERE yyyy = 'test'; +yyyy c4 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'test' +SELECT * FROM t2 WHERE yy = '1999'; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = '1999'; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1999; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1999; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1999.1; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1999.1; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1998.9; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1998.9; +yyyy c4 +1999 1999 +# Coverage tests for YEAR with zero/2000 constants: +SELECT * FROM t2 WHERE yy = 0; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '0'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '0000'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '2000'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = 2000; +yy c2 +00 2000 +SELECT * FROM t4 WHERE yyyy = 0; +yyyy c4 +SELECT * FROM t4 WHERE yyyy = '0'; +yyyy c4 +2000 2000 +SELECT * FROM t4 WHERE yyyy = '0000'; +yyyy c4 +SELECT * FROM t4 WHERE yyyy = '2000'; +yyyy c4 +2000 2000 +SELECT * FROM t4 WHERE yyyy = 2000; +yyyy c4 +2000 2000 +# Comparison with constants those are out of YEAR range +# (coverage test for backward compatibility) +SELECT COUNT(yy) FROM t2; +COUNT(yy) +5 +SELECT COUNT(yyyy) FROM t4; +COUNT(yyyy) +5 +SELECT COUNT(*) FROM t2 WHERE yy = -1; +COUNT(*) +0 +SELECT COUNT(*) FROM t4 WHERE yyyy > -1; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy > -1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy > -1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy < 2156; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy < 2156; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy < 1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy < 1000000000000000000; +COUNT(*) +5 +SELECT * FROM t2 WHERE yy < 123; +yy c2 +70 1970 +99 1999 +00 2000 +01 2001 +69 2069 +SELECT * FROM t2 WHERE yy > 123; +yy c2 +SELECT * FROM t4 WHERE yyyy < 123; +yyyy c4 +SELECT * FROM t4 WHERE yyyy > 123; +yyyy c4 +1970 1970 +1999 1999 +2000 2000 +2001 2001 +2069 2069 +DROP TABLE t2, t4; +# +End of 5.1 tests diff --git a/mysql-test/t/type_year.test b/mysql-test/t/type_year.test index 0e174a556d6..16fd39a59d8 100644 --- a/mysql-test/t/type_year.test +++ b/mysql-test/t/type_year.test @@ -30,3 +30,109 @@ select * from t1; drop table t1; --echo End of 5.0 tests + +--echo # +--echo # Bug #49480: WHERE using YEAR columns returns unexpected results +--echo # + +CREATE TABLE t2(yy YEAR(2), c2 CHAR(4)); +CREATE TABLE t4(yyyy YEAR(4), c4 CHAR(4)); + +INSERT INTO t2 (c2) VALUES (NULL),(1970),(1999),(2000),(2001),(2069); +INSERT INTO t4 (c4) SELECT c2 FROM t2; +UPDATE t2 SET yy = c2; +UPDATE t4 SET yyyy = c4; + +SELECT * FROM t2; +SELECT * FROM t4; + +--echo # Comparison of YEAR(2) with YEAR(4) + +SELECT * FROM t2, t4 WHERE yy = yyyy; +SELECT * FROM t2, t4 WHERE yy <=> yyyy; +SELECT * FROM t2, t4 WHERE yy < yyyy; +SELECT * FROM t2, t4 WHERE yy > yyyy; + +--echo # Comparison of YEAR(2) with YEAR(2) + +SELECT * FROM t2 a, t2 b WHERE a.yy = b.yy; +SELECT * FROM t2 a, t2 b WHERE a.yy <=> b.yy; +SELECT * FROM t2 a, t2 b WHERE a.yy < b.yy; + +--echo # Comparison of YEAR(4) with YEAR(4) + +SELECT * FROM t4 a, t4 b WHERE a.yyyy = b.yyyy; +SELECT * FROM t4 a, t4 b WHERE a.yyyy <=> b.yyyy; +SELECT * FROM t4 a, t4 b WHERE a.yyyy < b.yyyy; + +--echo # Comparison with constants: + +SELECT * FROM t2 WHERE yy = NULL; +SELECT * FROM t4 WHERE yyyy = NULL; +SELECT * FROM t2 WHERE yy <=> NULL; +SELECT * FROM t4 WHERE yyyy <=> NULL; +SELECT * FROM t2 WHERE yy < NULL; +SELECT * FROM t2 WHERE yy > NULL; + +SELECT * FROM t2 WHERE yy = NOW(); +SELECT * FROM t4 WHERE yyyy = NOW(); + +SELECT * FROM t2 WHERE yy = 99; +SELECT * FROM t2 WHERE 99 = yy; +SELECT * FROM t4 WHERE yyyy = 99; + +SELECT * FROM t2 WHERE yy = 'test'; +SELECT * FROM t4 WHERE yyyy = 'test'; + +SELECT * FROM t2 WHERE yy = '1999'; +SELECT * FROM t4 WHERE yyyy = '1999'; + +SELECT * FROM t2 WHERE yy = 1999; +SELECT * FROM t4 WHERE yyyy = 1999; + +SELECT * FROM t2 WHERE yy = 1999.1; +SELECT * FROM t4 WHERE yyyy = 1999.1; + +SELECT * FROM t2 WHERE yy = 1998.9; +SELECT * FROM t4 WHERE yyyy = 1998.9; + +--echo # Coverage tests for YEAR with zero/2000 constants: + +SELECT * FROM t2 WHERE yy = 0; +SELECT * FROM t2 WHERE yy = '0'; +SELECT * FROM t2 WHERE yy = '0000'; +SELECT * FROM t2 WHERE yy = '2000'; +SELECT * FROM t2 WHERE yy = 2000; + +SELECT * FROM t4 WHERE yyyy = 0; +SELECT * FROM t4 WHERE yyyy = '0'; +SELECT * FROM t4 WHERE yyyy = '0000'; +SELECT * FROM t4 WHERE yyyy = '2000'; +SELECT * FROM t4 WHERE yyyy = 2000; + +--echo # Comparison with constants those are out of YEAR range +--echo # (coverage test for backward compatibility) + +SELECT COUNT(yy) FROM t2; +SELECT COUNT(yyyy) FROM t4; + +SELECT COUNT(*) FROM t2 WHERE yy = -1; +SELECT COUNT(*) FROM t4 WHERE yyyy > -1; +SELECT COUNT(*) FROM t2 WHERE yy > -1000000000000000000; +SELECT COUNT(*) FROM t4 WHERE yyyy > -1000000000000000000; + +SELECT COUNT(*) FROM t2 WHERE yy < 2156; +SELECT COUNT(*) FROM t4 WHERE yyyy < 2156; +SELECT COUNT(*) FROM t2 WHERE yy < 1000000000000000000; +SELECT COUNT(*) FROM t4 WHERE yyyy < 1000000000000000000; + +SELECT * FROM t2 WHERE yy < 123; +SELECT * FROM t2 WHERE yy > 123; +SELECT * FROM t4 WHERE yyyy < 123; +SELECT * FROM t4 WHERE yyyy > 123; + +DROP TABLE t2, t4; + +--echo # + +--echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5415d6f4f8a..ed31c19e676 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -956,40 +956,9 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, if (agg_item_set_converter(coll, owner->func_name(), b, 1, MY_COLL_CMP_CONV, 1)) return 1; - } else if (type != ROW_RESULT && ((*a)->field_type() == MYSQL_TYPE_YEAR || - (*b)->field_type() == MYSQL_TYPE_YEAR)) - { - is_nulls_eq= is_owner_equal_func(); - year_as_datetime= FALSE; - - if ((*a)->is_datetime()) - { - year_as_datetime= TRUE; - get_value_a_func= &get_datetime_value; - } else if ((*a)->field_type() == MYSQL_TYPE_YEAR) - get_value_a_func= &get_year_value; - else - { - /* - Because convert_constant_item is called only for EXECUTE in PS mode - the value of get_value_x_func set in PREPARE might be not - valid for EXECUTE. - */ - get_value_a_func= NULL; - } - - if ((*b)->is_datetime()) - { - year_as_datetime= TRUE; - get_value_b_func= &get_datetime_value; - } else if ((*b)->field_type() == MYSQL_TYPE_YEAR) - get_value_b_func= &get_year_value; - else - get_value_b_func= NULL; - - func= &Arg_comparator::compare_year; - return 0; } + else if (try_year_cmp_func(type)) + return 0; a= cache_converted_constant(thd, a, &a_cache, type); b= cache_converted_constant(thd, b, &b_cache, type); @@ -997,6 +966,45 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, } +/* + Helper function to call from Arg_comparator::set_cmp_func() +*/ + +bool Arg_comparator::try_year_cmp_func(Item_result type) +{ + if (type == ROW_RESULT) + return FALSE; + + bool a_is_year= (*a)->field_type() == MYSQL_TYPE_YEAR; + bool b_is_year= (*b)->field_type() == MYSQL_TYPE_YEAR; + + if (!a_is_year && !b_is_year) + return FALSE; + + if (a_is_year && b_is_year) + { + get_value_a_func= &get_year_value; + get_value_b_func= &get_year_value; + } + else if (a_is_year && (*b)->is_datetime()) + { + get_value_a_func= &get_year_value; + get_value_b_func= &get_datetime_value; + } + else if (b_is_year && (*a)->is_datetime()) + { + get_value_b_func= &get_year_value; + get_value_a_func= &get_datetime_value; + } + else + return FALSE; + + is_nulls_eq= is_owner_equal_func(); + func= &Arg_comparator::compare_datetime; + + return TRUE; +} + /** Convert and cache a constant. @@ -1147,7 +1155,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, /* - Retrieves YEAR value of 19XX form from given item. + Retrieves YEAR value of 19XX-00-00 00:00:00 form from given item. SYNOPSIS get_year_value() @@ -1159,7 +1167,9 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, DESCRIPTION Retrieves the YEAR value of 19XX form from given item for comparison by the - compare_year() function. + compare_datetime() function. + Converts year to DATETIME of form YYYY-00-00 00:00:00 for the compatibility + with the get_datetime_value function result. RETURN obtained value @@ -1186,6 +1196,9 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg, if (value <= 1900) value+= 1900; + /* Convert year to DATETIME of form YYYY-00-00 00:00:00 (YYYY0000000000). */ + value*= 10000000000LL; + return value; } @@ -1615,67 +1628,6 @@ int Arg_comparator::compare_e_row() } -/** - Compare values as YEAR. - - @details - Compare items as YEAR for EQUAL_FUNC and for other comparison functions. - The YEAR values of form 19XX are obtained with help of the get_year_value() - function. - If one of arguments is of DATE/DATETIME type its value is obtained - with help of the get_datetime_value function. In this case YEAR values - prior to comparison are converted to the ulonglong YYYY-00-00 00:00:00 - DATETIME form. - If an argument type neither YEAR nor DATE/DATEIME then val_int function - is used to obtain value for comparison. - - RETURN - If is_nulls_eq is TRUE: - 1 if items are equal or both are null - 0 otherwise - If is_nulls_eq is FALSE: - -1 a < b - 0 a == b or at least one of items is null - 1 a > b - See the table: - is_nulls_eq | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | - a_is_null | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | - b_is_null | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | - result | 1 | 0 | 0 |0/1| 0 | 0 | 0 |-1/0/1| -*/ - -int Arg_comparator::compare_year() -{ - bool a_is_null, b_is_null; - ulonglong val1= get_value_a_func ? - (*get_value_a_func)(thd, &a, &a_cache, *b, &a_is_null) : - (*a)->val_int(); - ulonglong val2= get_value_b_func ? - (*get_value_b_func)(thd, &b, &b_cache, *a, &b_is_null) : - (*b)->val_int(); - if (!(*a)->null_value) - { - if (!(*b)->null_value) - { - if (set_null) - owner->null_value= 0; - /* Convert year to DATETIME of form YYYY-00-00 00:00:00 when necessary. */ - if((*a)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime) - val1*= 10000000000LL; - if((*b)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime) - val2*= 10000000000LL; - - if (val1 < val2) return is_nulls_eq ? 0 : -1; - if (val1 == val2) return is_nulls_eq ? 1 : 0; - return is_nulls_eq ? 0 : 1; - } - } - if (set_null) - owner->null_value= is_nulls_eq ? 0 : 1; - return (is_nulls_eq && (*a)->null_value == (*b)->null_value) ? 1 : 0; -} - - void Item_func_truth::fix_length_and_dec() { maybe_null= 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 52af6a31c0c..d4542dac820 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -42,24 +42,22 @@ class Arg_comparator: public Sql_alloc bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC bool set_null; // TRUE <=> set owner->null_value // when one of arguments is NULL. - bool year_as_datetime; // TRUE <=> convert YEAR value to - // the YYYY-00-00 00:00:00 DATETIME - // format. See compare_year. enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE, CMP_DATE_WITH_STR, CMP_STR_WITH_DATE }; longlong (*get_value_a_func)(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null); longlong (*get_value_b_func)(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null); + bool try_year_cmp_func(Item_result type); public: DTCollation cmp_collation; /* Allow owner function to use string buffers. */ String value1, value2; Arg_comparator(): thd(0), a_cache(0), b_cache(0), set_null(0), - year_as_datetime(0), get_value_a_func(0), get_value_b_func(0) {}; + get_value_a_func(0), get_value_b_func(0) {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), thd(0), - a_cache(0), b_cache(0), set_null(0), year_as_datetime(0), + a_cache(0), b_cache(0), set_null(0), get_value_a_func(0), get_value_b_func(0) {}; int set_compare_func(Item_result_field *owner, Item_result type); @@ -101,7 +99,6 @@ public: int compare_real_fixed(); int compare_e_real_fixed(); int compare_datetime(); // compare args[0] & args[1] as DATETIMEs - int compare_year(); static enum enum_date_cmp_type can_compare_as_dates(Item *a, Item *b, ulonglong *const_val_arg); From 30e51fe8540026f00c2c599098257c1e33c9b94f Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 10 Dec 2009 11:28:38 +0200 Subject: [PATCH 152/344] Bug #49250 : spatial btree index corruption and crash SPATIAL and FULLTEXT indexes don't support algorithm selection. Disabled by creating a special grammar rule for these in the parser. Added some encasulation of duplicate parser code. --- mysql-test/r/fulltext.result | 14 +++++ mysql-test/r/gis.result | 13 +++++ mysql-test/t/fulltext.test | 17 ++++++ mysql-test/t/gis.test | 15 +++++ sql/sql_yacc.yy | 110 +++++++++++++++++++++-------------- 5 files changed, 126 insertions(+), 43 deletions(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index b0197e0aec2..c27915811d6 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -518,3 +518,17 @@ EXECUTE s; MATCH (col) AGAINST('findme') DEALLOCATE PREPARE s; DROP TABLE t1; +# +# Bug #49250 : spatial btree index corruption and crash +# Part two : fulltext syntax check +# +CREATE TABLE t1(col1 TEXT, +FULLTEXT INDEX USING BTREE (col1)); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1))' at line 2 +CREATE TABLE t2(col1 TEXT); +CREATE FULLTEXT INDEX USING BTREE ON t2(col); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE ON t2(col)' at line 1 +ALTER TABLE t2 ADD FULLTEXT INDEX USING BTREE (col1); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1)' at line 1 +DROP TABLE t2; +End of 5.0 tests diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 140c133d75f..158fdb69c10 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -983,4 +983,17 @@ GEOMFROMTEXT( SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); 1 DROP TABLE t1; +# +# Bug #49250 : spatial btree index corruption and crash +# Part one : spatial syntax check +# +CREATE TABLE t1(col1 MULTIPOLYGON NOT NULL, +SPATIAL INDEX USING BTREE (col1)); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1))' at line 2 +CREATE TABLE t2(col1 MULTIPOLYGON NOT NULL); +CREATE SPATIAL INDEX USING BTREE ON t2(col); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE ON t2(col)' at line 1 +ALTER TABLE t2 ADD SPATIAL INDEX USING BTREE (col1); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1)' at line 1 +DROP TABLE t2; End of 5.0 tests diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 9551c98f143..bcd27e51f24 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -455,3 +455,20 @@ EXECUTE s; DEALLOCATE PREPARE s; DROP TABLE t1; +--echo # +--echo # Bug #49250 : spatial btree index corruption and crash +--echo # Part two : fulltext syntax check +--echo # + +--error ER_PARSE_ERROR +CREATE TABLE t1(col1 TEXT, + FULLTEXT INDEX USING BTREE (col1)); +CREATE TABLE t2(col1 TEXT); +--error ER_PARSE_ERROR +CREATE FULLTEXT INDEX USING BTREE ON t2(col); +--error ER_PARSE_ERROR +ALTER TABLE t2 ADD FULLTEXT INDEX USING BTREE (col1); + +DROP TABLE t2; + +--echo End of 5.0 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 701a6cef6be..d2bfe7d90d4 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -669,5 +669,20 @@ SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); DROP TABLE t1; +--echo # +--echo # Bug #49250 : spatial btree index corruption and crash +--echo # Part one : spatial syntax check +--echo # + +--error ER_PARSE_ERROR +CREATE TABLE t1(col1 MULTIPOLYGON NOT NULL, + SPATIAL INDEX USING BTREE (col1)); +CREATE TABLE t2(col1 MULTIPOLYGON NOT NULL); +--error ER_PARSE_ERROR +CREATE SPATIAL INDEX USING BTREE ON t2(col); +--error ER_PARSE_ERROR +ALTER TABLE t2 ADD SPATIAL INDEX USING BTREE (col1); + +DROP TABLE t2; --echo End of 5.0 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2fc85b4bda7..3cd61605033 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -418,6 +418,34 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, DBUG_RETURN(result); } + +static bool add_create_index_prepare (LEX *lex, Table_ident *table) +{ + lex->sql_command= SQLCOM_CREATE_INDEX; + if (!lex->current_select->add_table_to_list(lex->thd, table, NULL, + TL_OPTION_UPDATING)) + return TRUE; + lex->alter_info.reset(); + lex->alter_info.flags= ALTER_ADD_INDEX; + lex->col_list.empty(); + lex->change= NullS; + return FALSE; +} + + +static bool add_create_index (LEX *lex, + Key::Keytype type, const char *name, enum ha_key_alg key_alg, + bool generated= 0) +{ + Key *key= new Key(type, name, key_alg, generated, lex->col_list); + if (key == NULL) + return TRUE; + + lex->alter_info.key_list.push_back(key); + lex->col_list.empty(); + return FALSE; +} + %} %union { int num; @@ -1110,7 +1138,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); option_type opt_var_type opt_var_ident_type %type - key_type opt_unique_or_fulltext constraint_key_type + key_type opt_unique fulltext_or_spatial constraint_key_type + key_type_fulltext_or_spatial %type key_alg opt_btree_or_rtree @@ -1543,27 +1572,25 @@ create: } create2 { Lex->current_select= &Lex->select_lex; } - | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident + | CREATE opt_unique INDEX_SYM ident key_alg ON table_ident { - LEX *lex=Lex; - lex->sql_command= SQLCOM_CREATE_INDEX; - if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL, - TL_OPTION_UPDATING)) - MYSQL_YYABORT; - lex->alter_info.reset(); - lex->alter_info.flags= ALTER_ADD_INDEX; - lex->col_list.empty(); - lex->change=NullS; - } - '(' key_list ')' - { - LEX *lex=Lex; - Key *key= new Key($2, $4.str, $5, 0, lex->col_list); - if (key == NULL) + if (add_create_index_prepare (Lex, $7)) + MYSQL_YYABORT; + } + '(' key_list ')' + { + if (add_create_index (Lex, $2, $4.str, $5)) + MYSQL_YYABORT; + } + | CREATE fulltext_or_spatial INDEX_SYM ident ON table_ident + { + if (add_create_index_prepare (Lex, $6)) + MYSQL_YYABORT; + } + '(' key_list ')' + { + if (add_create_index (Lex, $2, $4.str, HA_KEY_ALG_UNDEF)) MYSQL_YYABORT; - - lex->alter_info.key_list.push_back(key); - lex->col_list.empty(); } | CREATE DATABASE opt_if_not_exists ident { @@ -3133,23 +3160,18 @@ column_def: key_def: key_type opt_ident key_alg '(' key_list ')' key_alg { - LEX *lex=Lex; - Key *key= new Key($1, $2, $7 ? $7 : $3, 0, lex->col_list); - if (key == NULL) + if (add_create_index (Lex, $1, $2, $7 ? $7 : $3)) + MYSQL_YYABORT; + } + | key_type_fulltext_or_spatial opt_ident '(' key_list ')' + { + if (add_create_index (Lex, $1, $2, HA_KEY_ALG_UNDEF)) MYSQL_YYABORT; - lex->alter_info.key_list.push_back(key); - - lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')' key_alg { - LEX *lex=Lex; - const char *key_name= $3 ? $3:$1; - Key *key= new Key($2, key_name, $4, 0, lex->col_list); - if (key == NULL) + if (add_create_index (Lex, $2, $3 ? $3:$1, $4)) MYSQL_YYABORT; - lex->alter_info.key_list.push_back(key); - lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references { @@ -3164,13 +3186,9 @@ key_def: if (key == NULL) MYSQL_YYABORT; lex->alter_info.key_list.push_back(key); - key= new Key(Key::MULTIPLE, key_name, - HA_KEY_ALG_UNDEF, 1, - lex->col_list); - if (key == NULL) + if (add_create_index (lex, Key::MULTIPLE, key_name, + HA_KEY_ALG_UNDEF, 1)) MYSQL_YYABORT; - lex->alter_info.key_list.push_back(key); - lex->col_list.empty(); /* Alloced by sql_alloc */ } | constraint opt_check_constraint { @@ -3630,7 +3648,10 @@ delete_option: key_type: key_or_index { $$= Key::MULTIPLE; } - | FULLTEXT_SYM opt_key_or_index { $$= Key::FULLTEXT; } + ; + +key_type_fulltext_or_spatial: + FULLTEXT_SYM opt_key_or_index { $$= Key::FULLTEXT; } | SPATIAL_SYM opt_key_or_index { #ifdef HAVE_SPATIAL @@ -3660,10 +3681,8 @@ keys_or_index: | INDEX_SYM {} | INDEXES {}; -opt_unique_or_fulltext: - /* empty */ { $$= Key::MULTIPLE; } - | UNIQUE_SYM { $$= Key::UNIQUE; } - | FULLTEXT_SYM { $$= Key::FULLTEXT;} +fulltext_or_spatial: + FULLTEXT_SYM { $$= Key::FULLTEXT;} | SPATIAL_SYM { #ifdef HAVE_SPATIAL @@ -3676,6 +3695,11 @@ opt_unique_or_fulltext: } ; +opt_unique: + /* empty */ { $$= Key::MULTIPLE; } + | UNIQUE_SYM { $$= Key::UNIQUE; } + ; + key_alg: /* empty */ { $$= HA_KEY_ALG_UNDEF; } | USING opt_btree_or_rtree { $$= $2; } From 18d09c0183c022ee19eebb71b8278ef2c5219514 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Dec 2009 09:57:38 +0800 Subject: [PATCH 153/344] Bug #48742 Replication: incorrect help text for --init-slave The help text for --init-slave=name: "Command(s) that are executed when a slave connects to this master". This text indicate that the --init-slave option is set on a master server, and the master server passes the option's argument to slave which connects to it. This is wrong. Actually the --init-slave option just can be set on a slave server, and then the slave server executes the argument each time the SQL thread starts. Correct the help text for --init-slave option as following: "Command(s) that are executed by a slave server each time the SQL thread starts." sql/mysqld.cc: Correct the help text for --init-slave option. --- sql/mysqld.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ce1d562d0ca..b4eb96ab65a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5275,7 +5275,8 @@ Disable with --skip-large-pages.", #endif {"init-rpl-role", OPT_INIT_RPL_ROLE, "Set the replication role.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed when a slave connects to this master", + {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed by a slave server \ +each time the SQL thread starts.", (gptr*) &opt_init_slave, (gptr*) &opt_init_slave, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"innodb", OPT_INNODB, "Enable InnoDB (if this version of MySQL supports it). \ From e3c1ee24fc0128915a3d09ac82c433ab1ae186ee Mon Sep 17 00:00:00 2001 From: V Narayanan Date: Fri, 11 Dec 2009 12:31:16 +0530 Subject: [PATCH 154/344] Bug#49329 example (and other) engines use wrong collation for open tables hash This fix changes the character set used within the IBMDB2I handler to hash table names to information about open tables. Previously, tables with names that differed only in letter case would hash to the same data structure. This caused incorrect behavior or errors when two such tables were in use simultaneously. mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result: Bug#49329 example (and other) engines use wrong collation for open tables hash Result file for the test case. mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test: Bug#49329 example (and other) engines use wrong collation for open tables hash Test case for the bug fix. storage/ibmdb2i/ha_ibmdb2i.cc: Bug#49329 example (and other) engines use wrong collation for open tables hash change the character set used within the IBMDB2I handler to hash table names to information about open tables. --- mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result | 9 +++++++++ mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test | 10 ++++++++++ storage/ibmdb2i/ha_ibmdb2i.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result create mode 100644 mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result new file mode 100644 index 00000000000..d5bfc2579fd --- /dev/null +++ b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result @@ -0,0 +1,9 @@ +create table ABC (i int) engine=ibmdb2i; +insert into ABC values(1); +create table abc (i int) engine=ibmdb2i; +insert into abc values (2); +select * from ABC; +i +1 +drop table ABC; +drop table abc; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test new file mode 100644 index 00000000000..615df284d8f --- /dev/null +++ b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test @@ -0,0 +1,10 @@ +source suite/ibmdb2i/include/have_ibmdb2i.inc; +source include/have_case_sensitive_file_system.inc; + +create table ABC (i int) engine=ibmdb2i; +insert into ABC values(1); +create table abc (i int) engine=ibmdb2i; +insert into abc values (2); +select * from ABC; +drop table ABC; +drop table abc; diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc index 0fc2d1e83dc..39096be7848 100644 --- a/storage/ibmdb2i/ha_ibmdb2i.cc +++ b/storage/ibmdb2i/ha_ibmdb2i.cc @@ -284,7 +284,7 @@ static int ibmdb2i_init_func(void *p) was_ILE_inited = false; ibmdb2i_hton= (handlerton *)p; VOID(pthread_mutex_init(&ibmdb2i_mutex,MY_MUTEX_INIT_FAST)); - (void) hash_init(&ibmdb2i_open_tables,system_charset_info,32,0,0, + (void) hash_init(&ibmdb2i_open_tables,table_alias_charset,32,0,0, (hash_get_key) ibmdb2i_get_key,0,0); ibmdb2i_hton->state= SHOW_OPTION_YES; From 3fded1b6c1294c24b6d0985ea1c22ebac5332c47 Mon Sep 17 00:00:00 2001 From: V Narayanan Date: Fri, 11 Dec 2009 12:46:57 +0530 Subject: [PATCH 155/344] Bug#49521 SHOW CREATE TABLE on IBMDB2I tables has incorrect fk constraint format The fix inserts newline and comma characters as appropriate into the constraint reporting code to match the formatting required by SHOW CREATE TABLE. Additionally, a erroneously duplicated copy of check_if_incompatible_data() was removed from db2i_constraints.cc since the correct version is already in ha_ibmdb2i.cc. storage/ibmdb2i/db2i_constraints.cc: Bug#49521 SHOW CREATE TABLE on IBMDB2I tables has incorrect fk constraint format - Insert newline and comma characters into the constraint reporting code to match the formatting required by SHOW CREATE TABLE. - Remove an erroneous copy of check_if_incompatible_data() from db2i_constraints.cc. --- storage/ibmdb2i/db2i_constraints.cc | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/storage/ibmdb2i/db2i_constraints.cc b/storage/ibmdb2i/db2i_constraints.cc index 9a96eda1173..1fde0dd3d14 100644 --- a/storage/ibmdb2i/db2i_constraints.cc +++ b/storage/ibmdb2i/db2i_constraints.cc @@ -329,7 +329,7 @@ char* ha_ibmdb2i::get_foreign_key_create_info(void) /* Process the constraint name. */ - info.strncat(STRING_WITH_LEN(" CONSTRAINT ")); + info.strncat(STRING_WITH_LEN(",\n CONSTRAINT ")); convNameForCreateInfo(thd, info, FKCstDef->CstName.Name, FKCstDef->CstName.Len); @@ -398,7 +398,6 @@ char* ha_ibmdb2i::get_foreign_key_create_info(void) if ((i+1) < cstCnt) { - info.strcat(','); tempPtr = (char*)cstHdr + cstHdr->CstLen; cstHdr = (constraint_hdr_t*)(tempPtr); } @@ -671,28 +670,3 @@ uint ha_ibmdb2i::referenced_by_foreign_key(void) } DBUG_RETURN(count); } - - -bool ha_ibmdb2i::check_if_incompatible_data(HA_CREATE_INFO *info, - uint table_changes) -{ - DBUG_ENTER("ha_ibmdb2i::check_if_incompatible_data"); - uint i; - /* Check that auto_increment value and field definitions were - not changed. */ - if ((info->used_fields & HA_CREATE_USED_AUTO && - info->auto_increment_value != 0) || - table_changes != IS_EQUAL_YES) - DBUG_RETURN(COMPATIBLE_DATA_NO); - /* Check if any fields were renamed. */ - for (i= 0; i < table->s->fields; i++) - { - Field *field= table->field[i]; - if (field->flags & FIELD_IS_RENAMED) - { - DBUG_PRINT("info", ("Field has been renamed, copy table")); - DBUG_RETURN(COMPATIBLE_DATA_NO); - } - } - DBUG_RETURN(COMPATIBLE_DATA_YES); -} From 794e2063471998a545e266c7268efaf2ba470d31 Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Fri, 11 Dec 2009 19:11:49 +0100 Subject: [PATCH 156/344] Define _WIN32_WINNT to the minimum supported Windows version, 0x0500 i.e Windows 2000. Visual Studio 2003 and 2005 require _WIN32_WINNT >= 0x0500 (Win2000) for TryEnterCriticalSection. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5705a2dfe57..bd597cf29c9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,6 +146,7 @@ IF(MSVC) ENDIF(MSVC) ADD_DEFINITIONS("-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE") +ADD_DEFINITIONS("-D_WIN32_WINNT=0x0500") # This definition is necessary to work around a bug with Intellisense described # here: http://tinyurl.com/2cb428. Syntax highlighting is important for proper From 8969530cffde0c7a466cf3aa8c4b7462d0ace2d2 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Sat, 12 Dec 2009 19:11:25 +0100 Subject: [PATCH 157/344] Bug #45058 init_available_charsets uses double checked locking As documented in the bug report, the double checked locking pattern has inherent issues, and cannot guarantee correct initialization. This patch replaces the logic in init_available_charsets() with the use of pthread_once(3). A wrapper function, my_pthread_once(), is introduced and is used in lieu of direct calls to init_available_charsets(). Related defines MY_PTHREAD_ONCE_* are also introduced. For the Windows platform, the implementation in lp:sysbench is ported. For single-thread use, a simple define calls the function and sets the pthread_once control variable. Charset initialization is modified to use my_pthread_once(). include/my_no_pthread.h: Dummy my_pthread_once() for single thread use. include/my_pthread.h: Declaration for new function my_pthread_once(). mysys/charset.c: Logic in init_available_charsets() is simplified. Using my_pthread_once() for all calls to this func. mysys/my_winthread.c: Windows implementation of my_pthread_once(). --- include/my_no_pthread.h | 8 +++++ include/my_pthread.h | 10 ++++++ include/my_sys.h | 1 - libmysql/libmysql.c | 1 - mysys/charset.c | 77 +++++++++++++---------------------------- mysys/my_init.c | 1 - mysys/my_winthread.c | 32 +++++++++++++++++ netware/libmysqlmain.c | 4 +-- sql/mysqld.cc | 1 - 9 files changed, 77 insertions(+), 58 deletions(-) diff --git a/include/my_no_pthread.h b/include/my_no_pthread.h index b11dbff42f0..511fac407d5 100644 --- a/include/my_no_pthread.h +++ b/include/my_no_pthread.h @@ -47,4 +47,12 @@ #define rw_unlock(A) #define rwlock_destroy(A) +typedef int my_pthread_once_t; +#define MY_PTHREAD_ONCE_INIT 0 +#define MY_PTHREAD_ONCE_DONE 1 + +#define my_pthread_once(C,F) do { \ + if (*(C) != MY_PTHREAD_ONCE_DONE) { F(); *(C)= MY_PTHREAD_ONCE_DONE; } \ + } while(0) + #endif diff --git a/include/my_pthread.h b/include/my_pthread.h index 151cb34faff..e9256610ea7 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -69,6 +69,11 @@ typedef int pthread_mutexattr_t; #define pthread_handler_t EXTERNC void * __cdecl typedef void * (__cdecl *pthread_handler)(void *); +typedef volatile LONG my_pthread_once_t; +#define MY_PTHREAD_ONCE_INIT 0 +#define MY_PTHREAD_ONCE_INPROGRESS 1 +#define MY_PTHREAD_ONCE_DONE 2 + /* Struct and macros to be used in combination with the windows implementation of pthread_cond_timedwait @@ -114,6 +119,7 @@ int pthread_attr_init(pthread_attr_t *connect_att); int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack); int pthread_attr_setprio(pthread_attr_t *connect_att,int priority); int pthread_attr_destroy(pthread_attr_t *connect_att); +int my_pthread_once(my_pthread_once_t *once_control,void (*init_routine)(void)); struct tm *localtime_r(const time_t *timep,struct tm *tmp); struct tm *gmtime_r(const time_t *timep,struct tm *tmp); @@ -210,6 +216,10 @@ extern int my_pthread_getprio(pthread_t thread_id); #define pthread_handler_t EXTERNC void * typedef void *(* pthread_handler)(void *); +#define my_pthread_once_t pthread_once_t +#define MY_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT +#define my_pthread_once(C,F) pthread_once(C,F) + /* Test first for RTS or FSU threads */ #if defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) diff --git a/include/my_sys.h b/include/my_sys.h index b4aac3a17bd..a4ff5c30de7 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -951,7 +951,6 @@ extern my_bool resolve_collation(const char *cl_name, CHARSET_INFO *default_cl, CHARSET_INFO **cl); -extern void free_charsets(void); extern char *get_charsets_dir(char *buf); extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2); extern my_bool init_compiled_charsets(myf flags); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 1264f2765ba..36b1d9cac72 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -211,7 +211,6 @@ void STDCALL mysql_server_end() } else { - free_charsets(); mysql_thread_end(); } diff --git a/mysys/charset.c b/mysys/charset.c index b23ab084e90..d59be4ab6c7 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -321,7 +321,6 @@ static int add_collation(CHARSET_INFO *cs) #define MY_CHARSET_INDEX "Index.xml" const char *charsets_dir= NULL; -static int charset_initialized=0; static my_bool my_read_charset_file(const char *filename, myf myflags) @@ -399,63 +398,37 @@ static void *cs_alloc(size_t size) } -#ifdef __NETWARE__ -my_bool STDCALL init_available_charsets(myf myflags) -#else -static my_bool init_available_charsets(myf myflags) -#endif +static my_pthread_once_t charsets_initialized= MY_PTHREAD_ONCE_INIT; + +static void init_available_charsets(void) { char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)]; - my_bool error=FALSE; - /* - We have to use charset_initialized to not lock on THR_LOCK_charset - inside get_internal_charset... - */ - if (!charset_initialized) + CHARSET_INFO **cs; + + bzero(&all_charsets,sizeof(all_charsets)); + init_compiled_charsets(MYF(0)); + + /* Copy compiled charsets */ + for (cs=all_charsets; + cs < all_charsets+array_elements(all_charsets)-1 ; + cs++) { - CHARSET_INFO **cs; - /* - To make things thread safe we are not allowing other threads to interfere - while we may changing the cs_info_table - */ - pthread_mutex_lock(&THR_LOCK_charset); - if (!charset_initialized) + if (*cs) { - bzero(&all_charsets,sizeof(all_charsets)); - init_compiled_charsets(myflags); - - /* Copy compiled charsets */ - for (cs=all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; - cs++) - { - if (*cs) - { - if (cs[0]->ctype) - if (init_state_maps(*cs)) - *cs= NULL; - } - } - - strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); - error= my_read_charset_file(fname,myflags); - charset_initialized=1; + if (cs[0]->ctype) + if (init_state_maps(*cs)) + *cs= NULL; } - pthread_mutex_unlock(&THR_LOCK_charset); } - return error; -} - - -void free_charsets(void) -{ - charset_initialized=0; + + strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); + my_read_charset_file(fname, MYF(0)); } uint get_collation_number(const char *name) { - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); return get_collation_number_internal(name); } @@ -463,7 +436,7 @@ uint get_collation_number(const char *name) uint get_charset_number(const char *charset_name, uint cs_flags) { CHARSET_INFO **cs; - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); for (cs= all_charsets; cs < all_charsets+array_elements(all_charsets)-1 ; @@ -480,7 +453,7 @@ uint get_charset_number(const char *charset_name, uint cs_flags) const char *get_charset_name(uint charset_number) { CHARSET_INFO *cs; - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); cs=all_charsets[charset_number]; if (cs && (cs->number == charset_number) && cs->name ) @@ -538,7 +511,7 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags) if (cs_number == default_charset_info->number) return default_charset_info; - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); if (!cs_number || cs_number >= array_elements(all_charsets)-1) return NULL; @@ -560,7 +533,7 @@ CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags) { uint cs_number; CHARSET_INFO *cs; - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); cs_number=get_collation_number(cs_name); cs= cs_number ? get_internal_charset(cs_number,flags) : NULL; @@ -585,7 +558,7 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, DBUG_ENTER("get_charset_by_csname"); DBUG_PRINT("enter",("name: '%s'", cs_name)); - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); cs_number= get_charset_number(cs_name, cs_flags); cs= cs_number ? get_internal_charset(cs_number, flags) : NULL; diff --git a/mysys/my_init.c b/mysys/my_init.c index a60927be693..453c72f999f 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -165,7 +165,6 @@ void my_end(int infoflag) my_print_open_files(); } } - free_charsets(); my_error_unregister_all(); my_once_free(); diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index e94369bec32..ef2a20c2ddc 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -137,4 +137,36 @@ int win_pthread_setspecific(void *a,void *b,uint length) return 0; } + +/* + One time initialization. For simplicity, we assume initializer thread + does not exit within init_routine(). +*/ +int my_pthread_once(my_pthread_once_t *once_control, + void (*init_routine)(void)) +{ + LONG state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS, + MY_PTHREAD_ONCE_INIT); + switch(state) + { + case MY_PTHREAD_ONCE_INIT: + /* This is initializer thread */ + (*init_routine)(); + *once_control= MY_PTHREAD_ONCE_DONE; + break; + + case MY_PTHREAD_ONCE_INPROGRESS: + /* init_routine in progress. Wait for its completion */ + while(*once_control == MY_PTHREAD_ONCE_INPROGRESS) + { + Sleep(1); + } + break; + case MY_PTHREAD_ONCE_DONE: + /* Nothing to do */ + break; + } + return 0; +} + #endif diff --git a/netware/libmysqlmain.c b/netware/libmysqlmain.c index 03fdb832176..2b6ea9b7e27 100644 --- a/netware/libmysqlmain.c +++ b/netware/libmysqlmain.c @@ -18,7 +18,7 @@ #include "my_global.h" -my_bool init_available_charsets(myf myflags); +void init_available_charsets(void); /* this function is required so that global memory is allocated against this library nlm, and not against a paticular client */ @@ -31,7 +31,7 @@ int _NonAppStart(void *NLMHandle, void *errorScreen, const char *commandLine, { mysql_server_init(0, NULL, NULL); - init_available_charsets(MYF(0)); + init_available_charsets(); return 0; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9aff751ad2f..b145c5ace10 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1287,7 +1287,6 @@ void clean_up(bool print_message) lex_free(); /* Free some memory */ item_create_cleanup(); set_var_free(); - free_charsets(); if (!opt_noacl) { #ifdef HAVE_DLOPEN From c08e6c8867db16245732101ee8603efc0773c7c4 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sun, 13 Dec 2009 23:29:50 +0300 Subject: [PATCH 158/344] Bug #42849: innodb crash with varying time_zone on partitioned timestamp primary key Since TIMESTAMP values are adjusted by the current time zone settings in both numeric and string contexts, using any expressions involving TIMESTAMP values as a (sub)partitioning function leads to undeterministic behavior of partitioned tables. The effect may vary depending on a storage engine, it can be either incorrect data being retrieved or stored, or an assertion failure. The root cause of this is the fact that the calculated partition ID may differ from a previously calculated ID for the same data due to timezone adjustments of the partitioning expression value. Fixed by disabling any expressions involving TIMESTAMP values to be used in partitioning functions with the follwing two exceptions: 1. Creating or altering into a partitioned table that violates the above rule is not allowed, but opening existing such tables results in a warning rather than an error so that such tables could be fixed. 2. UNIX_TIMESTAMP() is the only way to get a timezone-independent value from a TIMESTAMP column, because it returns the internal representation (a time_t value) of a TIMESTAMP argument verbatim. So UNIX_TIMESTAMP(timestamp_column) is allowed and should be used to fix existing tables if one wants to use TIMESTAMP columns with partitioning. mysql-test/r/partition_bug18198.result: Corrected the error. mysql-test/r/partition_error.result: Corrected error texts. Added test cases for bug #42849. mysql-test/t/partition_bug18198.test: Corrected error code. mysql-test/t/partition_error.test: Corrected error codes. Added test cases for bug #42849. sql/item.h: Added is_timezone_dependent_processor() to Item. sql/item_func.h: Added has_timestamp_args() and the implementation of is_timezone_dependent_processor() for Item_func. sql/item_timefunc.h: Added is_timezone_dependent_processor() to Item_func_unix_timestamp. sql/share/errmsg.txt: Renamed ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR to ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR to better reflect the meaning. Adjusted the error message. sql/sql_partition.cc: Modified fix_fields_part_func() to walk through partitioning expression tree with is_timezone_dependent_processor() and issue a warning/error if it depends on the timezone settings. Changed fix_fields_part_func() to a static function since it is not used anywhere except sql_partition.cc sql/sql_partition.h: Removed the unneeded declaration of fix_fields_part_func() since it is now a static function. sql/sql_yacc.yy: ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR -> ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR. --- mysql-test/r/partition_bug18198.result | 2 +- mysql-test/r/partition_error.result | 310 ++++++++++++++++++++- mysql-test/t/partition_bug18198.test | 2 +- mysql-test/t/partition_error.test | 364 ++++++++++++++++++++++++- sql/item.h | 9 + sql/item_func.h | 23 ++ sql/item_timefunc.h | 10 + sql/share/errmsg.txt | 4 +- sql/sql_partition.cc | 39 ++- sql/sql_partition.h | 3 - sql/sql_yacc.yy | 2 +- 11 files changed, 743 insertions(+), 25 deletions(-) diff --git a/mysql-test/r/partition_bug18198.result b/mysql-test/r/partition_bug18198.result index 18d7d904bb0..ee7bf514807 100644 --- a/mysql-test/r/partition_bug18198.result +++ b/mysql-test/r/partition_bug18198.result @@ -126,7 +126,7 @@ ERROR HY000: This partition function is not allowed create table t1 (col1 date) partition by range(unix_timestamp(col1)) (partition p0 values less than (10), partition p1 values less than (30)); -ERROR HY000: This partition function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed create table t1 (col1 datetime) partition by range(week(col1)) (partition p0 values less than (10), partition p1 values less than (30)); diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 511806d64bd..b692203823d 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -138,7 +138,7 @@ primary key(a,b)) partition by hash (rand(a)) partitions 2 (partition x1, partition x2); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1, partition x2)' at line 6 CREATE TABLE t1 ( @@ -149,7 +149,7 @@ primary key(a,b)) partition by range (rand(a)) partitions 2 (partition x1 values less than (0), partition x2 values less than (2)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1 values less than (0), partition x2 values less than' at line 6 CREATE TABLE t1 ( @@ -160,7 +160,7 @@ primary key(a,b)) partition by list (rand(a)) partitions 2 (partition x1 values in (1), partition x2 values in (2)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1 values in (1), partition x2 values in (2))' at line 6 CREATE TABLE t1 ( @@ -275,7 +275,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by hash (rand(a+b)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 7 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 7 CREATE TABLE t1 ( a int not null, b int not null, @@ -372,7 +372,7 @@ partition by range (3+4) partitions 2 (partition x1 values less than (4) tablespace ts1, partition x2 values less than (8) tablespace ts2); -ERROR HY000: Constant/Random expression in (sub)partitioning function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed CREATE TABLE t1 ( a int not null, b int not null, @@ -542,7 +542,7 @@ partition by list (3+4) partitions 2 (partition x1 values in (4) tablespace ts1, partition x2 values in (8) tablespace ts2); -ERROR HY000: Constant/Random expression in (sub)partitioning function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed CREATE TABLE t1 ( a int not null, b int not null, @@ -634,13 +634,13 @@ partition by range (ascii(v)) ERROR HY000: This partition function is not allowed create table t1 (a int) partition by hash (rand(a)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash(CURTIME() + a); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash (NOW()+a); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash (extract(hour from convert_tz(a, '+00:00', '+00:00'))); ERROR HY000: This partition function is not allowed @@ -651,3 +651,295 @@ ERROR HY000: This partition function is not allowed create table t1 (a char(10)) partition by hash (extractvalue(a,'a')); ERROR HY000: This partition function is not allowed +# +# Bug #42849: innodb crash with varying time_zone on partitioned +# timestamp primary key +# +CREATE TABLE old (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: The PARTITION function returns the wrong type +ALTER TABLE old +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: The PARTITION function returns the wrong type +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL, b TIMESTAMP NOT NULL, PRIMARY KEY(a,b)) +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old ADD COLUMN b DATE; +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP, b date) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP, b TIMESTAMP) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old MODIFY b TIMESTAMP; +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +DROP TABLE old; +End of 5.1 tests diff --git a/mysql-test/t/partition_bug18198.test b/mysql-test/t/partition_bug18198.test index 7f071c6ec9e..720d483e8ed 100644 --- a/mysql-test/t/partition_bug18198.test +++ b/mysql-test/t/partition_bug18198.test @@ -158,7 +158,7 @@ create table t1 (col1 datetime) partition by range(timestampdiff(day,5,col1)) (partition p0 values less than (10), partition p1 values less than (30)); --- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +-- error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR create table t1 (col1 date) partition by range(unix_timestamp(col1)) (partition p0 values less than (10), partition p1 values less than (30)); diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 49632f95dfb..1f011f36257 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -466,7 +466,7 @@ partitions 2 # # Partition by range, constant partition function not allowed # ---error ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR CREATE TABLE t1 ( a int not null, b int not null, @@ -681,7 +681,7 @@ partition by list (a); # # Partition by list, constant partition function not allowed # ---error ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR CREATE TABLE t1 ( a int not null, b int not null, @@ -840,4 +840,364 @@ partition by range (a + (select count(*) from t1)) create table t1 (a char(10)) partition by hash (extractvalue(a,'a')); +--echo # +--echo # Bug #42849: innodb crash with varying time_zone on partitioned +--echo # timestamp primary key +--echo # +# A correctly partitioned table to test that trying to repartition it using +# timezone-dependent expression will throw an error. +CREATE TABLE old (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +# Check that allowed arithmetic/math functions involving TIMESTAMP values result +# in ER_PARTITION_FUNC_NOT_ALLOWED_ERROR when used as a partitioning function + +--error ER_PARTITION_FUNC_NOT_ALLOWED_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_PARTITION_FUNC_NOT_ALLOWED_ERROR +ALTER TABLE old +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +# Check that allowed date/time functions involving TIMESTAMP values result +# in ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR when used as a partitioning function + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL, b TIMESTAMP NOT NULL, PRIMARY KEY(a,b)) +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +ALTER TABLE old ADD COLUMN b DATE; + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b date) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b TIMESTAMP) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +ALTER TABLE old MODIFY b TIMESTAMP; + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +DROP TABLE old; + +--echo End of 5.1 tests diff --git a/sql/item.h b/sql/item.h index 3dfcd7c2612..4135ff2b097 100644 --- a/sql/item.h +++ b/sql/item.h @@ -950,6 +950,15 @@ public: virtual Item *equal_fields_propagator(uchar * arg) { return this; } virtual bool set_no_const_sub(uchar *arg) { return FALSE; } virtual Item *replace_equal_field(uchar * arg) { return this; } + /* + Check if an expression value depends on the current timezone. Used by + partitioning code to reject timezone-dependent expressions in a + (sub)partitioning function. + */ + virtual bool is_timezone_dependent_processor(uchar *bool_arg) + { + return FALSE; + } /* For SP local variable returns pointer to Item representing its diff --git a/sql/item_func.h b/sql/item_func.h index 67049af81a2..738f6544204 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -200,6 +200,29 @@ public: null_value=1; return 0.0; } + bool has_timestamp_args() + { + DBUG_ASSERT(fixed == TRUE); + for (uint i= 0; i < arg_count; i++) + { + if (args[i]->type() == Item::FIELD_ITEM && + args[i]->field_type() == MYSQL_TYPE_TIMESTAMP) + return TRUE; + } + return FALSE; + } + /* + We assume the result of any function that has a TIMESTAMP argument to be + timezone-dependent, since a TIMESTAMP value in both numeric and string + contexts is interpreted according to the current timezone. + The only exception is UNIX_TIMESTAMP() which returns the internal + representation of a TIMESTAMP argument verbatim, and thus does not depend on + the timezone. + */ + virtual bool is_timezone_dependent_processor(uchar *bool_arg) + { + return has_timestamp_args(); + } }; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 9e3c2e8c89f..a7a64090f6c 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -305,6 +305,16 @@ public: Item_func_unix_timestamp(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "unix_timestamp"; } + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} + /* + UNIX_TIMESTAMP() depends on the current timezone + (and thus may not be used as a partitioning function) + when its argument is NOT of the TIMESTAMP type. + */ + bool is_timezone_dependent_processor(uchar *int_arg) + { + return !has_timestamp_args(); + } void fix_length_and_dec() { decimals=0; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 7c92c827c87..cc319667060 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5696,8 +5696,8 @@ ER_PARTITION_WRONG_NO_SUBPART_ERROR eng "Wrong number of subpartitions defined, mismatch with previous setting" ger "Falsche Anzahl von Unterpartitionen definiert, stimmt nicht mit vorherigen Einstellungen überein" swe "Antal subpartitioner definierade och antal subpartitioner är inte lika" -ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR - eng "Constant/Random expression in (sub)partitioning function is not allowed" +ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR + eng "Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed" ger "Konstante oder Random-Ausdrücke in (Unter-)Partitionsfunktionen sind nicht erlaubt" swe "Konstanta uttryck eller slumpmässiga uttryck är inte tillåtna (sub)partitioneringsfunktioner" ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 4a50650b6f4..f3f33ab1dd1 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -869,6 +869,8 @@ int check_signed_flag(partition_info *part_info) part_info Reference to partitioning data structure is_sub_part Is the table subpartitioned as well is_field_to_be_setup Flag if we are to set-up field arrays + is_create_table_ind Indicator of whether openfrm was called as part of + CREATE or ALTER TABLE RETURN VALUE TRUE An error occurred, something was wrong with the @@ -891,8 +893,9 @@ int check_signed_flag(partition_info *part_info) on the field object. */ -bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, - bool is_sub_part, bool is_field_to_be_setup) +static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, + bool is_sub_part, bool is_field_to_be_setup, + bool is_create_table_ind) { partition_info *part_info= table->part_info; uint dir_length, home_dir_length; @@ -982,10 +985,31 @@ bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, thd->where= save_where; if (unlikely(func_expr->const_item())) { - my_error(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0)); + my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0)); clear_field_flag(table); goto end; } + + /* + We don't allow creating partitions with timezone-dependent expressions as + a (sub)partitioning function, but we want to allow such expressions when + opening existing tables for easier maintenance. This exception should be + deprecated at some point in future so that we always throw an error. + */ + if (func_expr->walk(&Item::is_timezone_dependent_processor, + 0, NULL)) + { + if (is_create_table_ind) + { + my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0)); + goto end; + } + else + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, + ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR)); + } + if ((!is_sub_part) && (error= check_signed_flag(part_info))) goto end; result= FALSE; @@ -1593,7 +1617,8 @@ bool fix_partition_func(THD *thd, TABLE *table, else { if (unlikely(fix_fields_part_func(thd, part_info->subpart_expr, - table, TRUE, TRUE))) + table, TRUE, TRUE, + is_create_table_ind))) goto end; if (unlikely(part_info->subpart_expr->result_type() != INT_RESULT)) { @@ -1621,7 +1646,8 @@ bool fix_partition_func(THD *thd, TABLE *table, else { if (unlikely(fix_fields_part_func(thd, part_info->part_expr, - table, FALSE, TRUE))) + table, FALSE, TRUE, + is_create_table_ind))) goto end; if (unlikely(part_info->part_expr->result_type() != INT_RESULT)) { @@ -1635,7 +1661,8 @@ bool fix_partition_func(THD *thd, TABLE *table, { const char *error_str; if (unlikely(fix_fields_part_func(thd, part_info->part_expr, - table, FALSE, TRUE))) + table, FALSE, TRUE, + is_create_table_ind))) goto end; if (part_info->part_type == RANGE_PARTITION) { diff --git a/sql/sql_partition.h b/sql/sql_partition.h index 282e24f1853..b9efbf25a00 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -91,9 +91,6 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool left_endpoint, bool include_endpoint); -bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, - bool is_sub_part, bool is_field_to_be_setup); - bool check_part_func_fields(Field **ptr, bool ok_with_charsets); bool field_is_partition_charset(Field *field); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c40062e5d52..ec6d2cc72cd 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3931,7 +3931,7 @@ part_func_expr: lex->safe_to_cache_query= 1; if (not_corr_func) { - my_parse_error(ER(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR)); + my_parse_error(ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR)); MYSQL_YYABORT; } $$=$1; From 71c54b8c0cb146de893bbf6006b8d21a0ac2a270 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 14 Dec 2009 00:58:16 +0100 Subject: [PATCH 159/344] This is a patch for Bug#48500 5.0 buffer overflow for ER_UPDATE_INFO, or truncated info message in 5.1 5.0.86 has a buffer overflow/crash, and 5.1.40 has a truncated message. errmsg.txt contains this: ER_UPDATE_INFO rum "Linii identificate (matched): %ld Schimbate: %ld Atentionari (warnings): %ld" When that is sprintf'd into a buffer of STRING_BUFFER_USUAL_SIZE size, a buffer overflow can happen. The solution to this is to use MYSQL_ERRMSG_SIZE for the buffer size, instead of STRING_BUFFER_USUAL_SIZE. This will allow longer strings. To avoid potential crashes, we will also use my_snprintf instead of sprintf. sql/sql_update.cc: sing MYSQL_ERRMSG_SIZE instead of STRING_BUFFER_USUAL_SIZE. Using my_snprintf instead of sprintf. --- sql/sql_update.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 06d1bcaa8fb..35ae0febcec 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -600,8 +600,8 @@ int mysql_update(THD *thd, if (error < 0) { - char buff[STRING_BUFFER_USUAL_SIZE]; - sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, + char buff[MYSQL_ERRMSG_SIZE]; + my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, (ulong) thd->cuted_fields); thd->row_count_func= (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; From 97a5d25938945835dd06c24a579bf9d4a2d2f4c2 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Mon, 14 Dec 2009 09:06:46 +0300 Subject: [PATCH 160/344] Post-merge test fix for bug #42849. --- mysql-test/r/partition.result | 12 ++++++------ mysql-test/t/partition.test | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 7e14a0ea7c8..08357795046 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -24,8 +24,8 @@ a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, b varchar(10), PRIMARY KEY (a) ) -PARTITION BY RANGE (to_days(a)) ( -PARTITION p1 VALUES LESS THAN (733407), +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( +PARTITION p1 VALUES LESS THAN (1199134800), PARTITION pmax VALUES LESS THAN MAXVALUE ); INSERT INTO t1 VALUES ('2007-07-30 17:35:48', 'p1'); @@ -37,7 +37,7 @@ a b 2009-07-14 17:35:55 pmax 2009-09-21 17:31:42 pmax ALTER TABLE t1 REORGANIZE PARTITION pmax INTO ( -PARTITION p3 VALUES LESS THAN (733969), +PARTITION p3 VALUES LESS THAN (1247688000), PARTITION pmax VALUES LESS THAN MAXVALUE); SELECT * FROM t1; a b @@ -51,9 +51,9 @@ t1 CREATE TABLE `t1` ( `b` varchar(10) DEFAULT NULL, PRIMARY KEY (`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE (to_days(a)) -(PARTITION p1 VALUES LESS THAN (733407) ENGINE = MyISAM, - PARTITION p3 VALUES LESS THAN (733969) ENGINE = MyISAM, +/*!50100 PARTITION BY RANGE (UNIX_TIMESTAMP(a)) +(PARTITION p1 VALUES LESS THAN (1199134800) ENGINE = MyISAM, + PARTITION p3 VALUES LESS THAN (1247688000) ENGINE = MyISAM, PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */ DROP TABLE t1; create table t1 (a int NOT NULL, b varchar(5) NOT NULL) diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 0ff4b118426..0cbe389dadd 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -53,8 +53,8 @@ CREATE TABLE t1 ( b varchar(10), PRIMARY KEY (a) ) -PARTITION BY RANGE (to_days(a)) ( - PARTITION p1 VALUES LESS THAN (733407), +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( + PARTITION p1 VALUES LESS THAN (1199134800), PARTITION pmax VALUES LESS THAN MAXVALUE ); @@ -64,7 +64,7 @@ INSERT INTO t1 VALUES ('2009-09-21 17:31:42', 'pmax'); SELECT * FROM t1; ALTER TABLE t1 REORGANIZE PARTITION pmax INTO ( - PARTITION p3 VALUES LESS THAN (733969), + PARTITION p3 VALUES LESS THAN (1247688000), PARTITION pmax VALUES LESS THAN MAXVALUE); SELECT * FROM t1; SHOW CREATE TABLE t1; From f0ef41058c80f4c21a243f69ca8686956972e471 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 14 Dec 2009 13:42:26 +0530 Subject: [PATCH 161/344] Fix for BUG#49502 - CMake error compiling 5.1 on Windows When applying innodb snapshot 1.0.6 the storage engine name for innodb plugin under windows was changed from INNODB_PLUGIN to INNOBASE. This is a wrong and changing back the name to INNODB_PLUGIN. storage/innodb_plugin/CMakeLists.txt: Fix for BUG#49502 - CMake error compiling 5.1 on Windows Change the storage engine name to INNODB_PLUGIN in CMakeLists.txt --- storage/innodb_plugin/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innodb_plugin/CMakeLists.txt b/storage/innodb_plugin/CMakeLists.txt index ad483779152..25cd212a473 100644 --- a/storage/innodb_plugin/CMakeLists.txt +++ b/storage/innodb_plugin/CMakeLists.txt @@ -81,4 +81,4 @@ SET(INNODB_PLUGIN_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c ut/ut0list.c ut/ut0wqueue.c) ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION) -MYSQL_STORAGE_ENGINE(INNOBASE) +MYSQL_STORAGE_ENGINE(INNODB_PLUGIN) From f9e48efb917bc8f03882e2141ed66099e51392eb Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 14 Dec 2009 16:11:47 +0100 Subject: [PATCH 162/344] Recommit of patch for bug#49028 for 5.1. Includes both patch from bug#48737 (without test, which should go to next-mr) and test for bug#49028. --- mysql-test/r/ctype_ucs.result | 20 ++++++++++++++++++++ mysql-test/t/ctype_ucs.test | 10 ++++++++++ strings/ctype-ucs2.c | 10 ---------- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 428629e7e9e..abb21b7cee7 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -116,6 +116,26 @@ select binary 'a a' > 'a', binary 'a \0' > 'a', binary 'a\0' > 'a'; binary 'a a' > 'a' binary 'a \0' > 'a' binary 'a\0' > 'a' 1 1 1 SET CHARACTER SET koi8r; +create table t1 (a varchar(2) character set ucs2 collate ucs2_bin, key(a)); +insert into t1 values ('A'),('A'),('B'),('C'),('D'),('A\t'); +insert into t1 values ('A\0'),('A\0'),('A\0'),('A\0'),('AZ'); +select hex(a) from t1 where a like 'A_' order by a; +hex(a) +00410000 +00410000 +00410000 +00410000 +00410009 +0041005A +select hex(a) from t1 ignore key(a) where a like 'A_' order by a; +hex(a) +00410000 +00410000 +00410000 +00410000 +00410009 +0041005A +drop table t1; CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2, word2 CHAR(64) CHARACTER SET ucs2); INSERT INTO t1 VALUES (_koi8r'ò',_koi8r'ò'), (X'2004',X'2004'); SELECT hex(word) FROM t1 ORDER BY word; diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index e247110658b..310576b9478 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -14,6 +14,16 @@ SET character_set_connection=ucs2; SET CHARACTER SET koi8r; +# +# BUG#49028, error in LIKE with ucs2 +# +create table t1 (a varchar(2) character set ucs2 collate ucs2_bin, key(a)); +insert into t1 values ('A'),('A'),('B'),('C'),('D'),('A\t'); +insert into t1 values ('A\0'),('A\0'),('A\0'),('A\0'),('AZ'); +select hex(a) from t1 where a like 'A_' order by a; +select hex(a) from t1 ignore key(a) where a like 'A_' order by a; +drop table t1; + # # Check that 0x20 is only trimmed when it is # a part of real SPACE character, not just a part diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index a1c691a462b..cead55f8a0a 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1602,16 +1602,6 @@ fill_max_and_min: *min_str++= *max_str++ = ptr[1]; } - /* Temporary fix for handling w_one at end of string (key compression) */ - { - char *tmp; - for (tmp= min_str ; tmp-1 > min_org && tmp[-1] == '\0' && tmp[-2]=='\0';) - { - *--tmp=' '; - *--tmp='\0'; - } - } - *min_length= *max_length = (size_t) (min_str - min_org); while (min_str + 1 < min_end) { From 8948664470e7293b0d767e4e4eadacee1f584b9a Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Mon, 14 Dec 2009 18:50:22 +0200 Subject: [PATCH 163/344] correction to the earlier merging: s/return/DBUG_RETURN/ --- sql/rpl_rli.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index f45ab56aa1c..1263b7c52d9 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1033,7 +1033,7 @@ bool Relay_log_info::is_until_satisfied(THD *thd, Log_event *ev) if (until_condition == UNTIL_MASTER_POS) { if (ev && ev->server_id == (uint32) ::server_id && !replicate_same_server_id) - return FALSE; + DBUG_RETURN(FALSE); log_name= group_master_log_name; log_pos= (!ev)? group_master_log_pos : ((thd->options & OPTION_BEGIN || !ev->log_pos) ? From 3718eb790016a052b74989efa5961c570cea6e2e Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Mon, 14 Dec 2009 20:27:43 +0300 Subject: [PATCH 164/344] Post-push fixes for the bug #42849: All tests in the parts suite that use partitioning on a timezone-dependent expression were commented out, since it is not valid anymore. --- .../parts/inc/part_blocked_sql_funcs_main.inc | 14 ++- .../suite/parts/inc/partition_timestamp.inc | 82 +++++++------ .../r/part_blocked_sql_func_innodb.result | 98 ---------------- .../r/part_blocked_sql_func_myisam.result | 98 ---------------- .../parts/r/partition_datetime_innodb.result | 108 ------------------ .../parts/r/partition_datetime_myisam.result | 108 ------------------ 6 files changed, 54 insertions(+), 454 deletions(-) diff --git a/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc b/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc index 1a66a26312a..be02e4e0402 100644 --- a/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc +++ b/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc @@ -152,10 +152,16 @@ let $valsqlfunc = timestampdiff(YEAR,'2002-05-01','2001-01-01'); let $coltype = datetime; --source suite/parts/inc/partition_blocked_sql_funcs.inc -let $sqlfunc = unix_timestamp(col1); -let $valsqlfunc = unix_timestamp ('2002-05-01'); -let $coltype = date; ---source suite/parts/inc/partition_blocked_sql_funcs.inc +################################################################################ +# After the fix for bug #42849 the server behavior does not fit into this test's +# architecture: for UNIX_TIMESTAMP() some of the queries in +# suite/parts/inc/partition_blocked_sql_funcs.inc will fail with a different +# error (ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR) and some will succeed where +################################################################################ +#let $sqlfunc = unix_timestamp(col1); +#let $valsqlfunc = unix_timestamp ('2002-05-01'); +#let $coltype = date; +#--source suite/parts/inc/partition_blocked_sql_funcs.inc let $sqlfunc = week(col1); let $valsqlfunc = week('2002-05-01'); diff --git a/mysql-test/suite/parts/inc/partition_timestamp.inc b/mysql-test/suite/parts/inc/partition_timestamp.inc index d152c82a76f..4cf61c155bc 100644 --- a/mysql-test/suite/parts/inc/partition_timestamp.inc +++ b/mysql-test/suite/parts/inc/partition_timestamp.inc @@ -33,42 +33,48 @@ select count(*) from t2; select * from t2; drop table t2; -eval create table t3 (a timestamp not null, primary key(a)) engine=$engine -partition by range (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values less than (4), -partition quarter2 values less than (7), -partition quarter3 values less than (10), -partition quarter4 values less than (13) -); -show create table t3; -let $count=12; ---echo $count inserts; -while ($count) -{ -eval insert into t3 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); -dec $count; -} -select count(*) from t3; -select * from t3; -drop table t3; +################################################################################ +# The following 2 tests are no longer valid after bug #42849 has been fixed: +# it is not possible to use a timezone-dependent (such as month(timestamp_col) +# or just a timestamp_col in a numeric context) anymore. +################################################################################ -eval create table t4 (a timestamp not null, primary key(a)) engine=$engine -partition by list (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values in (0,1,2,3), -partition quarter2 values in (4,5,6), -partition quarter3 values in (7,8,9), -partition quarter4 values in (10,11,12) -); -show create table t4; -let $count=12; ---echo $count inserts; -while ($count) -{ -eval insert into t4 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); -dec $count; -} -select count(*) from t4; -select * from t4; -drop table t4; +# eval create table t3 (a timestamp not null, primary key(a)) engine=$engine +# partition by range (month(a)) subpartition by key (a) +# subpartitions 3 ( +# partition quarter1 values less than (4), +# partition quarter2 values less than (7), +# partition quarter3 values less than (10), +# partition quarter4 values less than (13) +# ); +# show create table t3; +# let $count=12; +# --echo $count inserts; +# while ($count) +# { +# eval insert into t3 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); +# dec $count; +# } +# select count(*) from t3; +# select * from t3; +# drop table t3; + +# eval create table t4 (a timestamp not null, primary key(a)) engine=$engine +# partition by list (month(a)) subpartition by key (a) +# subpartitions 3 ( +# partition quarter1 values in (0,1,2,3), +# partition quarter2 values in (4,5,6), +# partition quarter3 values in (7,8,9), +# partition quarter4 values in (10,11,12) +# ); +# show create table t4; +# let $count=12; +# --echo $count inserts; +# while ($count) +# { +# eval insert into t4 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); +# dec $count; +# } +# select count(*) from t4; +# select * from t4; +# drop table t4; diff --git a/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result b/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result index 57a7b2189ba..21d9548d658 100644 --- a/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result +++ b/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result @@ -2942,104 +2942,6 @@ drop table if exists t44 ; drop table if exists t55 ; drop table if exists t66 ; ------------------------------------------------------------------------- ---- unix_timestamp(col1) in partition with coltype date -------------------------------------------------------------------------- -must all fail! -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -create table t1 (col1 date) engine='INNODB' -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t2 (col1 date) engine='INNODB' -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t3 (col1 date) engine='INNODB' -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -create table t4 (colint int, col1 date) engine='INNODB' -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t5 (colint int, col1 date) engine='INNODB' -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t6 (colint int, col1 date) engine='INNODB' -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -create table t11 (col1 date) engine='INNODB' ; -create table t22 (col1 date) engine='INNODB' ; -create table t33 (col1 date) engine='INNODB' ; -create table t44 (colint int, col1 date) engine='INNODB' ; -create table t55 (colint int, col1 date) engine='INNODB' ; -create table t66 (colint int, col1 date) engine='INNODB' ; -alter table t11 -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t22 -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t33 -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -alter table t44 -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t55 -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t66 -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -------------------------------------------------------------------------- --- week(col1) in partition with coltype datetime ------------------------------------------------------------------------- must all fail! diff --git a/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result b/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result index 4a67054e82a..cf1a222a6ea 100644 --- a/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result +++ b/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result @@ -2942,104 +2942,6 @@ drop table if exists t44 ; drop table if exists t55 ; drop table if exists t66 ; ------------------------------------------------------------------------- ---- unix_timestamp(col1) in partition with coltype date -------------------------------------------------------------------------- -must all fail! -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -create table t1 (col1 date) engine='MYISAM' -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t2 (col1 date) engine='MYISAM' -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t3 (col1 date) engine='MYISAM' -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -create table t4 (colint int, col1 date) engine='MYISAM' -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t5 (colint int, col1 date) engine='MYISAM' -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t6 (colint int, col1 date) engine='MYISAM' -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -create table t11 (col1 date) engine='MYISAM' ; -create table t22 (col1 date) engine='MYISAM' ; -create table t33 (col1 date) engine='MYISAM' ; -create table t44 (colint int, col1 date) engine='MYISAM' ; -create table t55 (colint int, col1 date) engine='MYISAM' ; -create table t66 (colint int, col1 date) engine='MYISAM' ; -alter table t11 -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t22 -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t33 -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -alter table t44 -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t55 -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t66 -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -------------------------------------------------------------------------- --- week(col1) in partition with coltype datetime ------------------------------------------------------------------------- must all fail! diff --git a/mysql-test/suite/parts/r/partition_datetime_innodb.result b/mysql-test/suite/parts/r/partition_datetime_innodb.result index 67517ff5943..48af3343d9a 100644 --- a/mysql-test/suite/parts/r/partition_datetime_innodb.result +++ b/mysql-test/suite/parts/r/partition_datetime_innodb.result @@ -184,114 +184,6 @@ a 1971-01-01 00:00:58 1971-01-01 00:00:59 drop table t2; -create table t3 (a timestamp not null, primary key(a)) engine='InnoDB' -partition by range (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values less than (4), -partition quarter2 values less than (7), -partition quarter3 values less than (10), -partition quarter4 values less than (13) -); -show create table t3; -Table Create Table -t3 CREATE TABLE `t3` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES LESS THAN (4) ENGINE = InnoDB, - PARTITION quarter2 VALUES LESS THAN (7) ENGINE = InnoDB, - PARTITION quarter3 VALUES LESS THAN (10) ENGINE = InnoDB, - PARTITION quarter4 VALUES LESS THAN (13) ENGINE = InnoDB) */ -12 inserts; -insert into t3 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t3; -count(*) -12 -select * from t3; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t3; -create table t4 (a timestamp not null, primary key(a)) engine='InnoDB' -partition by list (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values in (0,1,2,3), -partition quarter2 values in (4,5,6), -partition quarter3 values in (7,8,9), -partition quarter4 values in (10,11,12) -); -show create table t4; -Table Create Table -t4 CREATE TABLE `t4` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES IN (0,1,2,3) ENGINE = InnoDB, - PARTITION quarter2 VALUES IN (4,5,6) ENGINE = InnoDB, - PARTITION quarter3 VALUES IN (7,8,9) ENGINE = InnoDB, - PARTITION quarter4 VALUES IN (10,11,12) ENGINE = InnoDB) */ -12 inserts; -insert into t4 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t4; -count(*) -12 -select * from t4; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t4; create table t1 (a date not null, primary key(a)) engine='InnoDB' partition by key (a) ( partition pa1 max_rows=20 min_rows=2, diff --git a/mysql-test/suite/parts/r/partition_datetime_myisam.result b/mysql-test/suite/parts/r/partition_datetime_myisam.result index ad542870e65..146f291546e 100644 --- a/mysql-test/suite/parts/r/partition_datetime_myisam.result +++ b/mysql-test/suite/parts/r/partition_datetime_myisam.result @@ -184,114 +184,6 @@ a 1971-01-01 00:00:58 1971-01-01 00:00:59 drop table t2; -create table t3 (a timestamp not null, primary key(a)) engine='MyISAM' -partition by range (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values less than (4), -partition quarter2 values less than (7), -partition quarter3 values less than (10), -partition quarter4 values less than (13) -); -show create table t3; -Table Create Table -t3 CREATE TABLE `t3` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES LESS THAN (4) ENGINE = MyISAM, - PARTITION quarter2 VALUES LESS THAN (7) ENGINE = MyISAM, - PARTITION quarter3 VALUES LESS THAN (10) ENGINE = MyISAM, - PARTITION quarter4 VALUES LESS THAN (13) ENGINE = MyISAM) */ -12 inserts; -insert into t3 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t3; -count(*) -12 -select * from t3; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t3; -create table t4 (a timestamp not null, primary key(a)) engine='MyISAM' -partition by list (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values in (0,1,2,3), -partition quarter2 values in (4,5,6), -partition quarter3 values in (7,8,9), -partition quarter4 values in (10,11,12) -); -show create table t4; -Table Create Table -t4 CREATE TABLE `t4` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES IN (0,1,2,3) ENGINE = MyISAM, - PARTITION quarter2 VALUES IN (4,5,6) ENGINE = MyISAM, - PARTITION quarter3 VALUES IN (7,8,9) ENGINE = MyISAM, - PARTITION quarter4 VALUES IN (10,11,12) ENGINE = MyISAM) */ -12 inserts; -insert into t4 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t4; -count(*) -12 -select * from t4; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t4; create table t1 (a date not null, primary key(a)) engine='MyISAM' partition by key (a) ( partition pa1 max_rows=20 min_rows=2, From e813587b4042c95efa6bfd590b3fdbac47c7e8aa Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Dec 2009 13:14:14 +0800 Subject: [PATCH 165/344] Bug #34628 LOAD DATA CONCURRENT INFILE drops CONCURRENT in binary log 'LOAD DATA CONCURRENT [LOCAL] INFILE ...' statment only is binlogged as 'LOAD DATA [LOCAL] INFILE ...' in SBR and MBR. As a result, if replication is on, queries on slaves will be blocked by the replication SQL thread. This patch write code to write 'CONCURRENT' into the log event if 'CONCURRENT' option is in the original statement in SBR and MBR. --- mysql-test/extra/rpl_tests/rpl_loaddata.test | 60 +++++--- mysql-test/suite/rpl/r/rpl_loaddata.result | 18 +-- .../rpl/r/rpl_loaddata_concurrent.result | 128 ++++++++++++++++++ .../suite/rpl/t/rpl_loaddata_concurrent.test | 12 ++ sql/log_event.cc | 4 + sql/log_event.h | 2 +- 6 files changed, 193 insertions(+), 31 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result create mode 100644 mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test diff --git a/mysql-test/extra/rpl_tests/rpl_loaddata.test b/mysql-test/extra/rpl_tests/rpl_loaddata.test index 7db12600456..948b77959f0 100644 --- a/mysql-test/extra/rpl_tests/rpl_loaddata.test +++ b/mysql-test/extra/rpl_tests/rpl_loaddata.test @@ -21,14 +21,26 @@ connection slave; reset master; connection master; +# MTR is not case-sensitive. +let $lower_stmt_head= load data; +let $UPPER_STMT_HEAD= LOAD DATA; +if (`SELECT '$lock_option' <> ''`) +{ + #if $lock_option is null, an extra blank is added into the statement, + #this will change the result of rpl_loaddata test case. so $lock_option + #is set only when it is not null. + let $lower_stmt_head= load data $lock_option; + let $UPPER_STMT_HEAD= LOAD DATA $lock_option; +} + select last_insert_id(); create table t1(a int not null auto_increment, b int, primary key(a) ); -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; # verify that LAST_INSERT_ID() is set by LOAD DATA INFILE select last_insert_id(); create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60)); -load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60)); insert into t3 select * from t2; @@ -56,7 +68,7 @@ sync_with_master; insert into t1 values(1,10); connection master; -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; save_master_pos; connection slave; @@ -70,9 +82,11 @@ connection slave; set global sql_slave_skip_counter=1; start slave; sync_with_master; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 16 # 23 # 33 # -show slave status; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1); +echo Last_SQL_Errno=$last_error; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +echo Last_SQL_Error; +echo $last_error; # Trigger error again to test CHANGE MASTER @@ -80,7 +94,7 @@ connection master; set sql_log_bin=0; delete from t1; set sql_log_bin=1; -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; save_master_pos; connection slave; # The SQL slave thread should be stopped now. @@ -92,9 +106,11 @@ connection slave; stop slave; change master to master_user='test'; change master to master_user='root'; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 16 # 23 # 33 # -show slave status; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1); +echo Last_SQL_Errno=$last_error; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +echo Last_SQL_Error; +echo $last_error; # Trigger error again to test RESET SLAVE @@ -105,7 +121,7 @@ connection master; set sql_log_bin=0; delete from t1; set sql_log_bin=1; -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; save_master_pos; connection slave; # The SQL slave thread should be stopped now. @@ -114,9 +130,11 @@ connection slave; # RESET SLAVE and see if error is cleared in SHOW SLAVE STATUS. stop slave; reset slave; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 16 # 23 # 33 # -show slave status; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1); +echo Last_SQL_Errno=$last_error; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +echo Last_SQL_Error; +echo $last_error; # Finally, see if logging is done ok on master for a failing LOAD DATA INFILE @@ -125,7 +143,7 @@ reset master; eval create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), unique(day)) engine=$engine_type; # no transactions --error ER_DUP_ENTRY -load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +eval $lower_stmt_head infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; select * from t2; @@ -141,7 +159,7 @@ alter table t2 drop key day; connection master; delete from t2; --error ER_DUP_ENTRY -load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +eval $lower_stmt_head infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; connection slave; @@ -154,7 +172,7 @@ drop table t1, t2; CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB; --error ER_DUP_ENTRY -LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1; +eval $UPPER_STMT_HEAD INFILE "../../std_data/words.dat" INTO TABLE t1; DROP TABLE IF EXISTS t1; @@ -182,17 +200,17 @@ DROP TABLE IF EXISTS t1; -- echo ### assertion: works with cross-referenced database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 -- eval use $db1 -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR -- echo ### assertion: works with fully qualified name on current database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 -- echo ### assertion: works without fully qualified name on current database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1 -- echo ### create connection without default database -- echo ### connect (conn2,localhost,root,,*NO-ONE*); @@ -200,7 +218,7 @@ connect (conn2,localhost,root,,*NO-ONE*); -- connection conn2 -- echo ### assertion: works without stating the default database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 -- echo ### disconnect and switch back to master connection -- disconnect conn2 -- connection master diff --git a/mysql-test/suite/rpl/r/rpl_loaddata.result b/mysql-test/suite/rpl/r/rpl_loaddata.result index ca9c14691b0..a8da9aae68e 100644 --- a/mysql-test/suite/rpl/r/rpl_loaddata.result +++ b/mysql-test/suite/rpl/r/rpl_loaddata.result @@ -34,9 +34,9 @@ insert into t1 values(1,10); load data infile '../../std_data/rpl_loaddata.dat' into table t1; set global sql_slave_skip_counter=1; start slave; -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 Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 2009 # # master-bin.000001 Yes Yes # 0 0 2009 # None 0 No # No 0 0 +Last_SQL_Errno=0 +Last_SQL_Error + set sql_log_bin=0; delete from t1; set sql_log_bin=1; @@ -44,9 +44,9 @@ load data infile '../../std_data/rpl_loaddata.dat' into table t1; stop slave; change master to master_user='test'; change master to master_user='root'; -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 Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 2044 # # master-bin.000001 No No # 0 0 2044 # None 0 No # No 0 0 +Last_SQL_Errno=0 +Last_SQL_Error + set global sql_slave_skip_counter=1; start slave; set sql_log_bin=0; @@ -55,9 +55,9 @@ set sql_log_bin=1; load data infile '../../std_data/rpl_loaddata.dat' into table t1; stop slave; reset slave; -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 Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 4 # # No No # 0 0 0 # None 0 No # No 0 0 +Last_SQL_Errno=0 +Last_SQL_Error + reset master; create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), unique(day)) engine=MyISAM; diff --git a/mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result b/mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result new file mode 100644 index 00000000000..1ea9b33c262 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result @@ -0,0 +1,128 @@ +CREATE TABLE t1 (c1 char(50)); +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (c1 char(50)) +master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (c1) ;file_id=# +master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (c1) ;file_id=# +DROP TABLE t1; +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; +select last_insert_id(); +last_insert_id() +0 +create table t1(a int not null auto_increment, b int, primary key(a) ); +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +select last_insert_id(); +last_insert_id() +1 +create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60)); +load data CONCURRENT infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; +create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60)); +insert into t3 select * from t2; +select * from t1; +a b +1 10 +2 15 +select * from t3; +day id category name +2003-02-22 2461 b a a a @ %  ' " a +2003-03-22 2161 c asdf +2003-03-22 2416 a bbbbb +drop table t1; +drop table t2; +drop table t3; +create table t1(a int, b int, unique(b)); +insert into t1 values(1,10); +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +set global sql_slave_skip_counter=1; +start slave; +Last_SQL_Errno=0 +Last_SQL_Error + +set sql_log_bin=0; +delete from t1; +set sql_log_bin=1; +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +stop slave; +change master to master_user='test'; +change master to master_user='root'; +Last_SQL_Errno=0 +Last_SQL_Error + +set global sql_slave_skip_counter=1; +start slave; +set sql_log_bin=0; +delete from t1; +set sql_log_bin=1; +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +stop slave; +reset slave; +Last_SQL_Errno=0 +Last_SQL_Error + +reset master; +create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), +unique(day)) engine=MyISAM; +load data CONCURRENT infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by +'\n##\n' starting by '>' ignore 1 lines; +ERROR 23000: Duplicate entry '2003-03-22' for key 'day' +select * from t2; +day id category name +2003-02-22 2461 b a a a @ %  ' " a +2003-03-22 2161 c asdf +start slave; +select * from t2; +day id category name +2003-02-22 2461 b a a a @ %  ' " a +2003-03-22 2161 c asdf +alter table t2 drop key day; +delete from t2; +load data CONCURRENT infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by +'\n##\n' starting by '>' ignore 1 lines; +ERROR 23000: Duplicate entry '2003-03-22' for key 'day' +drop table t1, t2; +drop table t1, t2; +CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB; +LOAD DATA CONCURRENT INFILE "../../std_data/words.dat" INTO TABLE t1; +ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY' +DROP TABLE IF EXISTS t1; +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 b48297_db1; +drop database if exists b42897_db2; +create database b48297_db1; +create database b42897_db2; +use b48297_db1; +CREATE TABLE t1 (c1 VARCHAR(256)) engine=MyISAM;; +use b42897_db2; +### assertion: works with cross-referenced database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +use b48297_db1; +### assertion: works with fully qualified name on current database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +### assertion: works without fully qualified name on current database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1; +### create connection without default database +### connect (conn2,localhost,root,,*NO-ONE*); +### assertion: works without stating the default database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +### disconnect and switch back to master connection +use b48297_db1; +Comparing tables master:b48297_db1.t1 and slave:b48297_db1.t1 +DROP DATABASE b48297_db1; +DROP DATABASE b42897_db2; diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test new file mode 100644 index 00000000000..1276b0f3700 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test @@ -0,0 +1,12 @@ +-- source include/not_ndb_default.inc +-- source include/have_log_bin.inc + +CREATE TABLE t1 (c1 char(50)); +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; +-- source include/show_binlog_events.inc +DROP TABLE t1; + +let $lock_option= CONCURRENT; +let $engine_type=MyISAM; +-- source extra/rpl_tests/rpl_loaddata.test diff --git a/sql/log_event.cc b/sql/log_event.cc index 6686a4634f7..9552bfad27f 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -4006,6 +4006,7 @@ uint Load_log_event::get_query_buffer_length() return 5 + db_len + 3 + // "use DB; " 18 + fname_len + 2 + // "LOAD DATA INFILE 'file''" + 11 + // "CONCURRENT " 7 + // LOCAL 9 + // " REPLACE or IGNORE " 13 + table_name_len*2 + // "INTO TABLE `table`" @@ -4033,6 +4034,9 @@ void Load_log_event::print_query(bool need_db, const char *cs, char *buf, pos= strmov(pos, "LOAD DATA "); + if (thd->lex->lock_option == TL_WRITE_CONCURRENT_INSERT) + pos= strmov(pos, "CONCURRENT "); + if (fn_start) *fn_start= pos; diff --git a/sql/log_event.h b/sql/log_event.h index 0b4c63a73af..b3098c04364 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1766,7 +1766,7 @@ private: @verbatim (1) USE db; - (2) LOAD DATA [LOCAL] INFILE 'file_name' + (2) LOAD DATA [CONCURRENT] [LOCAL] INFILE 'file_name' (3) [REPLACE | IGNORE] (4) INTO TABLE 'table_name' (5) [FIELDS From fb7214ae4b3d3c91da9653b34b35c2f61725aa31 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Tue, 15 Dec 2009 14:48:28 +0800 Subject: [PATCH 166/344] bug#49536 - deadlock on rotate_and_purge when using expire_logs_days Problem is that purge_logs implementation in ndb (ndbcluster_binlog_index_purge_file) calls mysql_parse (with (thd->options & OPTION_BIN_LOG) === 0)) but MYSQL_BIN_LOG first takes LOCK_log and then checks thd->options Solution in this patch, changes so that rotate_and_purge does not hold LOCK_log when calling purge_logs_before_date. I think this is safe as other "purge"-function(s) is called wo/ holding LOCK_log, e.g purge_master_logs --- sql/log.cc | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index f795cdab2ca..1adf92e709c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4481,6 +4481,9 @@ bool general_log_write(THD *thd, enum enum_server_command command, void MYSQL_BIN_LOG::rotate_and_purge(uint flags) { +#ifdef HAVE_REPLICATION + bool check_purge= false; +#endif if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) pthread_mutex_lock(&LOCK_log); if ((flags & RP_FORCE_ROTATE) || @@ -4488,16 +4491,24 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags) { new_file_without_locking(); #ifdef HAVE_REPLICATION - if (expire_logs_days) - { - time_t purge_time= my_time(0) - expire_logs_days*24*60*60; - if (purge_time >= 0) - purge_logs_before_date(purge_time); - } + check_purge= true; #endif } if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) pthread_mutex_unlock(&LOCK_log); + +#ifdef HAVE_REPLICATION + /* + NOTE: Run purge_logs wo/ holding LOCK_log + as it otherwise will deadlock in ndbcluster_binlog_index_purge_file + */ + if (check_purge && expire_logs_days) + { + time_t purge_time= my_time(0) - expire_logs_days*24*60*60; + if (purge_time >= 0) + purge_logs_before_date(purge_time); + } +#endif } uint MYSQL_BIN_LOG::next_file_id() From 915cc3e9b0eb8691084b5cc6edaecb77c5551c5c Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 10:37:10 +0200 Subject: [PATCH 167/344] Bug #49480: WHERE using YEAR columns returns unexpected results Merge the fix from 5.1-bugteam to 5.1-main --- mysql-test/r/type_year.result | 264 ++++++++++++++++++++++++++++++++++ mysql-test/t/type_year.test | 106 ++++++++++++++ sql/item_cmpfunc.cc | 144 +++++++------------ sql/item_cmpfunc.h | 9 +- 4 files changed, 421 insertions(+), 102 deletions(-) diff --git a/mysql-test/r/type_year.result b/mysql-test/r/type_year.result index e52947455c8..56b326327c6 100644 --- a/mysql-test/r/type_year.result +++ b/mysql-test/r/type_year.result @@ -46,3 +46,267 @@ a 2001 drop table t1; End of 5.0 tests +# +# Bug #49480: WHERE using YEAR columns returns unexpected results +# +CREATE TABLE t2(yy YEAR(2), c2 CHAR(4)); +CREATE TABLE t4(yyyy YEAR(4), c4 CHAR(4)); +INSERT INTO t2 (c2) VALUES (NULL),(1970),(1999),(2000),(2001),(2069); +INSERT INTO t4 (c4) SELECT c2 FROM t2; +UPDATE t2 SET yy = c2; +UPDATE t4 SET yyyy = c4; +SELECT * FROM t2; +yy c2 +NULL NULL +70 1970 +99 1999 +00 2000 +01 2001 +69 2069 +SELECT * FROM t4; +yyyy c4 +NULL NULL +1970 1970 +1999 1999 +2000 2000 +2001 2001 +2069 2069 +# Comparison of YEAR(2) with YEAR(4) +SELECT * FROM t2, t4 WHERE yy = yyyy; +yy c2 yyyy c4 +70 1970 1970 1970 +99 1999 1999 1999 +00 2000 2000 2000 +01 2001 2001 2001 +69 2069 2069 2069 +SELECT * FROM t2, t4 WHERE yy <=> yyyy; +yy c2 yyyy c4 +NULL NULL NULL NULL +70 1970 1970 1970 +99 1999 1999 1999 +00 2000 2000 2000 +01 2001 2001 2001 +69 2069 2069 2069 +SELECT * FROM t2, t4 WHERE yy < yyyy; +yy c2 yyyy c4 +70 1970 1999 1999 +70 1970 2000 2000 +99 1999 2000 2000 +70 1970 2001 2001 +99 1999 2001 2001 +00 2000 2001 2001 +70 1970 2069 2069 +99 1999 2069 2069 +00 2000 2069 2069 +01 2001 2069 2069 +SELECT * FROM t2, t4 WHERE yy > yyyy; +yy c2 yyyy c4 +99 1999 1970 1970 +00 2000 1970 1970 +01 2001 1970 1970 +69 2069 1970 1970 +00 2000 1999 1999 +01 2001 1999 1999 +69 2069 1999 1999 +01 2001 2000 2000 +69 2069 2000 2000 +69 2069 2001 2001 +# Comparison of YEAR(2) with YEAR(2) +SELECT * FROM t2 a, t2 b WHERE a.yy = b.yy; +yy c2 yy c2 +70 1970 70 1970 +99 1999 99 1999 +00 2000 00 2000 +01 2001 01 2001 +69 2069 69 2069 +SELECT * FROM t2 a, t2 b WHERE a.yy <=> b.yy; +yy c2 yy c2 +NULL NULL NULL NULL +70 1970 70 1970 +99 1999 99 1999 +00 2000 00 2000 +01 2001 01 2001 +69 2069 69 2069 +SELECT * FROM t2 a, t2 b WHERE a.yy < b.yy; +yy c2 yy c2 +70 1970 99 1999 +70 1970 00 2000 +99 1999 00 2000 +70 1970 01 2001 +99 1999 01 2001 +00 2000 01 2001 +70 1970 69 2069 +99 1999 69 2069 +00 2000 69 2069 +01 2001 69 2069 +# Comparison of YEAR(4) with YEAR(4) +SELECT * FROM t4 a, t4 b WHERE a.yyyy = b.yyyy; +yyyy c4 yyyy c4 +1970 1970 1970 1970 +1999 1999 1999 1999 +2000 2000 2000 2000 +2001 2001 2001 2001 +2069 2069 2069 2069 +SELECT * FROM t4 a, t4 b WHERE a.yyyy <=> b.yyyy; +yyyy c4 yyyy c4 +NULL NULL NULL NULL +1970 1970 1970 1970 +1999 1999 1999 1999 +2000 2000 2000 2000 +2001 2001 2001 2001 +2069 2069 2069 2069 +SELECT * FROM t4 a, t4 b WHERE a.yyyy < b.yyyy; +yyyy c4 yyyy c4 +1970 1970 1999 1999 +1970 1970 2000 2000 +1999 1999 2000 2000 +1970 1970 2001 2001 +1999 1999 2001 2001 +2000 2000 2001 2001 +1970 1970 2069 2069 +1999 1999 2069 2069 +2000 2000 2069 2069 +2001 2001 2069 2069 +# Comparison with constants: +SELECT * FROM t2 WHERE yy = NULL; +yy c2 +SELECT * FROM t4 WHERE yyyy = NULL; +yyyy c4 +SELECT * FROM t2 WHERE yy <=> NULL; +yy c2 +NULL NULL +SELECT * FROM t4 WHERE yyyy <=> NULL; +yyyy c4 +NULL NULL +SELECT * FROM t2 WHERE yy < NULL; +yy c2 +SELECT * FROM t2 WHERE yy > NULL; +yy c2 +SELECT * FROM t2 WHERE yy = NOW(); +yy c2 +SELECT * FROM t4 WHERE yyyy = NOW(); +yyyy c4 +SELECT * FROM t2 WHERE yy = 99; +yy c2 +99 1999 +SELECT * FROM t2 WHERE 99 = yy; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 99; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 'test'; +yy c2 +00 2000 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'test' +SELECT * FROM t4 WHERE yyyy = 'test'; +yyyy c4 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'test' +SELECT * FROM t2 WHERE yy = '1999'; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = '1999'; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1999; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1999; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1999.1; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1999.1; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1998.9; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1998.9; +yyyy c4 +1999 1999 +# Coverage tests for YEAR with zero/2000 constants: +SELECT * FROM t2 WHERE yy = 0; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '0'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '0000'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '2000'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = 2000; +yy c2 +00 2000 +SELECT * FROM t4 WHERE yyyy = 0; +yyyy c4 +SELECT * FROM t4 WHERE yyyy = '0'; +yyyy c4 +2000 2000 +SELECT * FROM t4 WHERE yyyy = '0000'; +yyyy c4 +SELECT * FROM t4 WHERE yyyy = '2000'; +yyyy c4 +2000 2000 +SELECT * FROM t4 WHERE yyyy = 2000; +yyyy c4 +2000 2000 +# Comparison with constants those are out of YEAR range +# (coverage test for backward compatibility) +SELECT COUNT(yy) FROM t2; +COUNT(yy) +5 +SELECT COUNT(yyyy) FROM t4; +COUNT(yyyy) +5 +SELECT COUNT(*) FROM t2 WHERE yy = -1; +COUNT(*) +0 +SELECT COUNT(*) FROM t4 WHERE yyyy > -1; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy > -1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy > -1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy < 2156; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy < 2156; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy < 1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy < 1000000000000000000; +COUNT(*) +5 +SELECT * FROM t2 WHERE yy < 123; +yy c2 +70 1970 +99 1999 +00 2000 +01 2001 +69 2069 +SELECT * FROM t2 WHERE yy > 123; +yy c2 +SELECT * FROM t4 WHERE yyyy < 123; +yyyy c4 +SELECT * FROM t4 WHERE yyyy > 123; +yyyy c4 +1970 1970 +1999 1999 +2000 2000 +2001 2001 +2069 2069 +DROP TABLE t2, t4; +# +End of 5.1 tests diff --git a/mysql-test/t/type_year.test b/mysql-test/t/type_year.test index 0e174a556d6..16fd39a59d8 100644 --- a/mysql-test/t/type_year.test +++ b/mysql-test/t/type_year.test @@ -30,3 +30,109 @@ select * from t1; drop table t1; --echo End of 5.0 tests + +--echo # +--echo # Bug #49480: WHERE using YEAR columns returns unexpected results +--echo # + +CREATE TABLE t2(yy YEAR(2), c2 CHAR(4)); +CREATE TABLE t4(yyyy YEAR(4), c4 CHAR(4)); + +INSERT INTO t2 (c2) VALUES (NULL),(1970),(1999),(2000),(2001),(2069); +INSERT INTO t4 (c4) SELECT c2 FROM t2; +UPDATE t2 SET yy = c2; +UPDATE t4 SET yyyy = c4; + +SELECT * FROM t2; +SELECT * FROM t4; + +--echo # Comparison of YEAR(2) with YEAR(4) + +SELECT * FROM t2, t4 WHERE yy = yyyy; +SELECT * FROM t2, t4 WHERE yy <=> yyyy; +SELECT * FROM t2, t4 WHERE yy < yyyy; +SELECT * FROM t2, t4 WHERE yy > yyyy; + +--echo # Comparison of YEAR(2) with YEAR(2) + +SELECT * FROM t2 a, t2 b WHERE a.yy = b.yy; +SELECT * FROM t2 a, t2 b WHERE a.yy <=> b.yy; +SELECT * FROM t2 a, t2 b WHERE a.yy < b.yy; + +--echo # Comparison of YEAR(4) with YEAR(4) + +SELECT * FROM t4 a, t4 b WHERE a.yyyy = b.yyyy; +SELECT * FROM t4 a, t4 b WHERE a.yyyy <=> b.yyyy; +SELECT * FROM t4 a, t4 b WHERE a.yyyy < b.yyyy; + +--echo # Comparison with constants: + +SELECT * FROM t2 WHERE yy = NULL; +SELECT * FROM t4 WHERE yyyy = NULL; +SELECT * FROM t2 WHERE yy <=> NULL; +SELECT * FROM t4 WHERE yyyy <=> NULL; +SELECT * FROM t2 WHERE yy < NULL; +SELECT * FROM t2 WHERE yy > NULL; + +SELECT * FROM t2 WHERE yy = NOW(); +SELECT * FROM t4 WHERE yyyy = NOW(); + +SELECT * FROM t2 WHERE yy = 99; +SELECT * FROM t2 WHERE 99 = yy; +SELECT * FROM t4 WHERE yyyy = 99; + +SELECT * FROM t2 WHERE yy = 'test'; +SELECT * FROM t4 WHERE yyyy = 'test'; + +SELECT * FROM t2 WHERE yy = '1999'; +SELECT * FROM t4 WHERE yyyy = '1999'; + +SELECT * FROM t2 WHERE yy = 1999; +SELECT * FROM t4 WHERE yyyy = 1999; + +SELECT * FROM t2 WHERE yy = 1999.1; +SELECT * FROM t4 WHERE yyyy = 1999.1; + +SELECT * FROM t2 WHERE yy = 1998.9; +SELECT * FROM t4 WHERE yyyy = 1998.9; + +--echo # Coverage tests for YEAR with zero/2000 constants: + +SELECT * FROM t2 WHERE yy = 0; +SELECT * FROM t2 WHERE yy = '0'; +SELECT * FROM t2 WHERE yy = '0000'; +SELECT * FROM t2 WHERE yy = '2000'; +SELECT * FROM t2 WHERE yy = 2000; + +SELECT * FROM t4 WHERE yyyy = 0; +SELECT * FROM t4 WHERE yyyy = '0'; +SELECT * FROM t4 WHERE yyyy = '0000'; +SELECT * FROM t4 WHERE yyyy = '2000'; +SELECT * FROM t4 WHERE yyyy = 2000; + +--echo # Comparison with constants those are out of YEAR range +--echo # (coverage test for backward compatibility) + +SELECT COUNT(yy) FROM t2; +SELECT COUNT(yyyy) FROM t4; + +SELECT COUNT(*) FROM t2 WHERE yy = -1; +SELECT COUNT(*) FROM t4 WHERE yyyy > -1; +SELECT COUNT(*) FROM t2 WHERE yy > -1000000000000000000; +SELECT COUNT(*) FROM t4 WHERE yyyy > -1000000000000000000; + +SELECT COUNT(*) FROM t2 WHERE yy < 2156; +SELECT COUNT(*) FROM t4 WHERE yyyy < 2156; +SELECT COUNT(*) FROM t2 WHERE yy < 1000000000000000000; +SELECT COUNT(*) FROM t4 WHERE yyyy < 1000000000000000000; + +SELECT * FROM t2 WHERE yy < 123; +SELECT * FROM t2 WHERE yy > 123; +SELECT * FROM t4 WHERE yyyy < 123; +SELECT * FROM t4 WHERE yyyy > 123; + +DROP TABLE t2, t4; + +--echo # + +--echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index fd5eca8911a..d99748b87a0 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -956,40 +956,9 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, if (agg_item_set_converter(coll, owner->func_name(), b, 1, MY_COLL_CMP_CONV, 1)) return 1; - } else if (type != ROW_RESULT && ((*a)->field_type() == MYSQL_TYPE_YEAR || - (*b)->field_type() == MYSQL_TYPE_YEAR)) - { - is_nulls_eq= is_owner_equal_func(); - year_as_datetime= FALSE; - - if ((*a)->is_datetime()) - { - year_as_datetime= TRUE; - get_value_a_func= &get_datetime_value; - } else if ((*a)->field_type() == MYSQL_TYPE_YEAR) - get_value_a_func= &get_year_value; - else - { - /* - Because convert_constant_item is called only for EXECUTE in PS mode - the value of get_value_x_func set in PREPARE might be not - valid for EXECUTE. - */ - get_value_a_func= NULL; - } - - if ((*b)->is_datetime()) - { - year_as_datetime= TRUE; - get_value_b_func= &get_datetime_value; - } else if ((*b)->field_type() == MYSQL_TYPE_YEAR) - get_value_b_func= &get_year_value; - else - get_value_b_func= NULL; - - func= &Arg_comparator::compare_year; - return 0; } + else if (try_year_cmp_func(type)) + return 0; a= cache_converted_constant(thd, a, &a_cache, type); b= cache_converted_constant(thd, b, &b_cache, type); @@ -997,6 +966,45 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, } +/* + Helper function to call from Arg_comparator::set_cmp_func() +*/ + +bool Arg_comparator::try_year_cmp_func(Item_result type) +{ + if (type == ROW_RESULT) + return FALSE; + + bool a_is_year= (*a)->field_type() == MYSQL_TYPE_YEAR; + bool b_is_year= (*b)->field_type() == MYSQL_TYPE_YEAR; + + if (!a_is_year && !b_is_year) + return FALSE; + + if (a_is_year && b_is_year) + { + get_value_a_func= &get_year_value; + get_value_b_func= &get_year_value; + } + else if (a_is_year && (*b)->is_datetime()) + { + get_value_a_func= &get_year_value; + get_value_b_func= &get_datetime_value; + } + else if (b_is_year && (*a)->is_datetime()) + { + get_value_b_func= &get_year_value; + get_value_a_func= &get_datetime_value; + } + else + return FALSE; + + is_nulls_eq= is_owner_equal_func(); + func= &Arg_comparator::compare_datetime; + + return TRUE; +} + /** Convert and cache a constant. @@ -1147,7 +1155,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, /* - Retrieves YEAR value of 19XX form from given item. + Retrieves YEAR value of 19XX-00-00 00:00:00 form from given item. SYNOPSIS get_year_value() @@ -1159,7 +1167,9 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, DESCRIPTION Retrieves the YEAR value of 19XX form from given item for comparison by the - compare_year() function. + compare_datetime() function. + Converts year to DATETIME of form YYYY-00-00 00:00:00 for the compatibility + with the get_datetime_value function result. RETURN obtained value @@ -1186,6 +1196,9 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg, if (value <= 1900) value+= 1900; + /* Convert year to DATETIME of form YYYY-00-00 00:00:00 (YYYY0000000000). */ + value*= 10000000000LL; + return value; } @@ -1615,67 +1628,6 @@ int Arg_comparator::compare_e_row() } -/** - Compare values as YEAR. - - @details - Compare items as YEAR for EQUAL_FUNC and for other comparison functions. - The YEAR values of form 19XX are obtained with help of the get_year_value() - function. - If one of arguments is of DATE/DATETIME type its value is obtained - with help of the get_datetime_value function. In this case YEAR values - prior to comparison are converted to the ulonglong YYYY-00-00 00:00:00 - DATETIME form. - If an argument type neither YEAR nor DATE/DATEIME then val_int function - is used to obtain value for comparison. - - RETURN - If is_nulls_eq is TRUE: - 1 if items are equal or both are null - 0 otherwise - If is_nulls_eq is FALSE: - -1 a < b - 0 a == b or at least one of items is null - 1 a > b - See the table: - is_nulls_eq | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | - a_is_null | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | - b_is_null | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | - result | 1 | 0 | 0 |0/1| 0 | 0 | 0 |-1/0/1| -*/ - -int Arg_comparator::compare_year() -{ - bool a_is_null, b_is_null; - ulonglong val1= get_value_a_func ? - (*get_value_a_func)(thd, &a, &a_cache, *b, &a_is_null) : - (*a)->val_int(); - ulonglong val2= get_value_b_func ? - (*get_value_b_func)(thd, &b, &b_cache, *a, &b_is_null) : - (*b)->val_int(); - if (!(*a)->null_value) - { - if (!(*b)->null_value) - { - if (set_null) - owner->null_value= 0; - /* Convert year to DATETIME of form YYYY-00-00 00:00:00 when necessary. */ - if((*a)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime) - val1*= 10000000000LL; - if((*b)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime) - val2*= 10000000000LL; - - if (val1 < val2) return is_nulls_eq ? 0 : -1; - if (val1 == val2) return is_nulls_eq ? 1 : 0; - return is_nulls_eq ? 0 : 1; - } - } - if (set_null) - owner->null_value= is_nulls_eq ? 0 : 1; - return (is_nulls_eq && (*a)->null_value == (*b)->null_value) ? 1 : 0; -} - - void Item_func_truth::fix_length_and_dec() { maybe_null= 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 52af6a31c0c..d4542dac820 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -42,24 +42,22 @@ class Arg_comparator: public Sql_alloc bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC bool set_null; // TRUE <=> set owner->null_value // when one of arguments is NULL. - bool year_as_datetime; // TRUE <=> convert YEAR value to - // the YYYY-00-00 00:00:00 DATETIME - // format. See compare_year. enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE, CMP_DATE_WITH_STR, CMP_STR_WITH_DATE }; longlong (*get_value_a_func)(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null); longlong (*get_value_b_func)(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null); + bool try_year_cmp_func(Item_result type); public: DTCollation cmp_collation; /* Allow owner function to use string buffers. */ String value1, value2; Arg_comparator(): thd(0), a_cache(0), b_cache(0), set_null(0), - year_as_datetime(0), get_value_a_func(0), get_value_b_func(0) {}; + get_value_a_func(0), get_value_b_func(0) {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), thd(0), - a_cache(0), b_cache(0), set_null(0), year_as_datetime(0), + a_cache(0), b_cache(0), set_null(0), get_value_a_func(0), get_value_b_func(0) {}; int set_compare_func(Item_result_field *owner, Item_result type); @@ -101,7 +99,6 @@ public: int compare_real_fixed(); int compare_e_real_fixed(); int compare_datetime(); // compare args[0] & args[1] as DATETIMEs - int compare_year(); static enum enum_date_cmp_type can_compare_as_dates(Item *a, Item *b, ulonglong *const_val_arg); From 838adcf2ff68464a7817d9cadf2fc8f6cbe95beb Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 10:54:53 +0200 Subject: [PATCH 168/344] Bug#49489: Uninitialized cache led to a wrong result. Merge the fix from 5.1-bugteam to 5.1-main --- mysql-test/r/select.result | 10 ++++++++++ mysql-test/t/select.test | 9 +++++++++ sql/item_cmpfunc.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index d0b2a575a32..1750051289a 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4609,4 +4609,14 @@ HAVING v <= 't' ORDER BY pk; v DROP TABLE t1; +# +# Bug#49489 Uninitialized cache led to a wrong result. +# +CREATE TABLE t1(c1 DOUBLE(5,4)); +INSERT INTO t1 VALUES (9.1234); +SELECT * FROM t1 WHERE c1 < 9.12345; +c1 +9.1234 +DROP TABLE t1; +# End of test for bug#49489. End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index ac65e5cbaf5..982aec726f7 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3964,4 +3964,13 @@ ORDER BY pk; DROP TABLE t1; +--echo # +--echo # Bug#49489 Uninitialized cache led to a wrong result. +--echo # +CREATE TABLE t1(c1 DOUBLE(5,4)); +INSERT INTO t1 VALUES (9.1234); +SELECT * FROM t1 WHERE c1 < 9.12345; +DROP TABLE t1; +--echo # End of test for bug#49489. + --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d99748b87a0..419b79377d7 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1031,7 +1031,7 @@ Item** Arg_comparator::cache_converted_constant(THD *thd, Item **value, (*value)->const_item() && type != (*value)->result_type()) { Item_cache *cache= Item_cache::get_cache(*value, type); - cache->store(*value); + cache->setup(*value); *cache_item= cache; return cache_item; } From d2e723bf53dd081fe6098feac66bf8934643a278 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 11:03:24 +0200 Subject: [PATCH 169/344] Bug #48985: show create table crashes if previous access to the table was killed Merge the fix from 5.1-bugteam to 5.1-main --- mysql-test/r/show_check.result | 6 ++++++ mysql-test/t/show_check.test | 22 ++++++++++++++++++++++ sql/sql_show.cc | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index e6550bee954..ec0a70ff581 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1454,4 +1454,10 @@ GRANT PROCESS ON *.* TO test_u@localhost; SHOW ENGINE MYISAM MUTEX; SHOW ENGINE MYISAM STATUS; DROP USER test_u@localhost; +# +# Bug #48985: show create table crashes if previous access to the table +# was killed +# +SHOW CREATE TABLE non_existent; +ERROR 70100: Query execution was interrupted End of 5.1 tests diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 0ce807ae73e..d46261f38d2 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -1207,6 +1207,28 @@ connection default; DROP USER test_u@localhost; +--echo # +--echo # Bug #48985: show create table crashes if previous access to the table +--echo # was killed +--echo # + +connect(con1,localhost,root,,); +CONNECTION con1; +LET $ID= `SELECT connection_id()`; + +CONNECTION default; +--disable_query_log +eval KILL QUERY $ID; +--enable_query_log + +CONNECTION con1; +--error ER_QUERY_INTERRUPTED +SHOW CREATE TABLE non_existent; + +CONNECTION default; +DISCONNECT con1; + + --echo End of 5.1 tests # Wait till all disconnects are completed diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2c1f360104b..e55000c0f65 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -719,7 +719,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) thd->push_internal_handler(&view_error_suppressor); bool error= open_normal_and_derived_tables(thd, table_list, 0); thd->pop_internal_handler(); - if (error && thd->main_da.is_error()) + if (error && (thd->killed || thd->main_da.is_error())) DBUG_RETURN(TRUE); } From 4578a5c61b8c502cdf18bff883f746d3d0bd2b39 Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Tue, 15 Dec 2009 10:05:20 +0100 Subject: [PATCH 170/344] Bug #48995 abort missing DBUG_RETURN or .. in function "check_key_in_view" check_key_in_view() had one code branch which returned with "return TRUE" rather than "DBUG_RETURN(TRUE)". Only affected debug builds. No test case added. --- sql/sql_view.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index ae3af0640a3..eca3922f17a 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1771,7 +1771,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item)) { thd->mark_used_columns= save_mark_used_columns; - return TRUE; + DBUG_RETURN(TRUE); } } thd->mark_used_columns= save_mark_used_columns; From cff23162ec4bfc0c0fa489eb8568de0a3ccdd1ab Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 15 Dec 2009 13:48:29 +0400 Subject: [PATCH 171/344] Bug#49134 5.1 server segfaults with 2byte collation file Problem: add_collation did not check that cs->number is smaller than the number of elements in the array all_charsets[], so server could crash when loading an Index.xml file with a collation ID greater the number of elements (for example when downgrading from 5.5). Fix: adding a condition to check that cs->number is not out of valid range. --- mysql-test/std_data/Index.xml | 7 +++++++ mysys/charset.c | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mysql-test/std_data/Index.xml b/mysql-test/std_data/Index.xml index 3dc647d8195..b8f61d59203 100644 --- a/mysql-test/std_data/Index.xml +++ b/mysql-test/std_data/Index.xml @@ -8,6 +8,13 @@ + + + a + b + + + diff --git a/mysys/charset.c b/mysys/charset.c index d59be4ab6c7..b1b91d716ba 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -220,7 +220,8 @@ copy_uca_collation(CHARSET_INFO *to, CHARSET_INFO *from) static int add_collation(CHARSET_INFO *cs) { if (cs->name && (cs->number || - (cs->number=get_collation_number_internal(cs->name)))) + (cs->number=get_collation_number_internal(cs->name))) && + cs->number < array_elements(all_charsets)) { if (!all_charsets[cs->number]) { From 188c6f8c7474a0c23282451c592df66048734c04 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 14:20:29 +0200 Subject: [PATCH 172/344] Bug #48709: Assertion failed in sql_select.cc:11782: int join_read_key(JOIN_TAB*) The eq_ref access method TABLE_REF (accessed through JOIN_TAB) to save state and to track if this is the first row it finds or not. This state was not reset on subquery re-execution causing an assert. Fixed by resetting the state before the subquery re-execution. --- mysql-test/r/subselect.result | 25 +++++++++++++++++++++++++ mysql-test/t/subselect.test | 26 ++++++++++++++++++++++++++ sql/sql_select.cc | 5 +++++ 3 files changed, 56 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 665473df3ef..f446d8feec3 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4410,6 +4410,31 @@ WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) NULL 0 DROP TABLE t1, st1, st2; +# +# Bug #48709: Assertion failed in sql_select.cc:11782: +# int join_read_key(JOIN_TAB*) +# +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); +# should have eq_ref for t1 +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +id select_type table type possible_keys key key_len ref rows Extra +x x outr ALL x x x x x x +x x t1 eq_ref x x x x x x +x x t2 index x x x x x x +# should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +pk int_key +3 3 +7 3 +DROP TABLE t1,t2; End of 5.0 tests. CREATE TABLE t1 (a INT, b INT); INSERT INTO t1 VALUES (2,22),(1,11),(2,22); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 7f2dba00ba8..a4314c45cba 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3368,6 +3368,32 @@ WHERE a = 230; DROP TABLE t1, st1, st2; +--echo # +--echo # Bug #48709: Assertion failed in sql_select.cc:11782: +--echo # int join_read_key(JOIN_TAB*) +--echo # + +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); + +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); + +--echo # should have eq_ref for t1 +--replace_column 1 x 2 x 5 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +--echo # should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +DROP TABLE t1,t2; + + --echo End of 5.0 tests. # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e6980bb2add..cbee09f1fdb 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1622,6 +1622,11 @@ JOIN::reinit() if (join_tab_save) memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables); + /* need to reset ref access state (see join_read_key) */ + if (join_tab) + for (uint i= 0; i < tables; i++) + join_tab[i].ref.key_err= TRUE; + if (tmp_join) restore_tmp(); From c5e6a11e149600b3c454043706170fad4e7c6ce4 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 15 Dec 2009 21:08:21 +0400 Subject: [PATCH 173/344] Fix for bug#49517: Inconsistent behavior while using NULLable BIGINT and INT columns in comparison Problem: a consequence of the fix for 43668. Some Arg_comparator inner initialization missed, that may lead to unpredictable (wrong) comparison results. Fix: always properly initialize Arg_comparator before its usage. mysql-test/r/select.result: Fix for bug#49517: Inconsistent behavior while using NULLable BIGINT and INT columns in comparison -test result. mysql-test/t/select.test: Fix for bug#49517: Inconsistent behavior while using NULLable BIGINT and INT columns in comparison -test case. sql/item_cmpfunc.cc: Fix for bug#49517: Inconsistent behavior while using NULLable BIGINT and INT columns in comparison - now all Arg_comparator::set_cmp_func() set Arg_comparator::set_null to ensure its proper initialization in all cases (by default it's set to TRUE in constructors). sql/item_cmpfunc.h: Fix for bug#49517: Inconsistent behavior while using NULLable BIGINT and INT columns in comparison - now all Arg_comparator::set_cmp_func() set Arg_comparator::set_null to ensure its proper initialization in all cases (by default it's set to TRUE in constructors). --- mysql-test/r/select.result | 15 +++++++++++++++ mysql-test/t/select.test | 14 ++++++++++++++ sql/item_cmpfunc.cc | 2 +- sql/item_cmpfunc.h | 4 ++-- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 1750051289a..f38af4ceb32 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4619,4 +4619,19 @@ c1 9.1234 DROP TABLE t1; # End of test for bug#49489. +# +# Bug #49517: Inconsistent behavior while using +# NULLable BIGINT and INT columns in comparison +# +CREATE TABLE t1(a BIGINT UNSIGNED NOT NULL, b BIGINT NULL, c INT NULL); +INSERT INTO t1 VALUES(105, NULL, NULL); +SELECT * FROM t1 WHERE b < 102; +a b c +SELECT * FROM t1 WHERE c < 102; +a b c +SELECT * FROM t1 WHERE 102 < b; +a b c +SELECT * FROM t1 WHERE 102 < c; +a b c +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 982aec726f7..e81c298166d 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3973,4 +3973,18 @@ SELECT * FROM t1 WHERE c1 < 9.12345; DROP TABLE t1; --echo # End of test for bug#49489. + +--echo # +--echo # Bug #49517: Inconsistent behavior while using +--echo # NULLable BIGINT and INT columns in comparison +--echo # +CREATE TABLE t1(a BIGINT UNSIGNED NOT NULL, b BIGINT NULL, c INT NULL); +INSERT INTO t1 VALUES(105, NULL, NULL); +SELECT * FROM t1 WHERE b < 102; +SELECT * FROM t1 WHERE c < 102; +SELECT * FROM t1 WHERE 102 < b; +SELECT * FROM t1 WHERE 102 < c; +DROP TABLE t1; + + --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 419b79377d7..e4f26978431 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -895,9 +895,9 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, ulonglong const_value= (ulonglong)-1; thd= current_thd; owner= owner_arg; + set_null= set_null && owner_arg; a= a1; b= a2; - owner= owner_arg; thd= current_thd; if ((cmp_type= can_compare_as_dates(*a, *b, &const_value))) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index d4542dac820..05c9fc96ff5 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -54,10 +54,10 @@ public: /* Allow owner function to use string buffers. */ String value1, value2; - Arg_comparator(): thd(0), a_cache(0), b_cache(0), set_null(0), + Arg_comparator(): thd(0), a_cache(0), b_cache(0), set_null(TRUE), get_value_a_func(0), get_value_b_func(0) {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), thd(0), - a_cache(0), b_cache(0), set_null(0), + a_cache(0), b_cache(0), set_null(TRUE), get_value_a_func(0), get_value_b_func(0) {}; int set_compare_func(Item_result_field *owner, Item_result type); From b72f27895826552f0bfe5019559f35cf634e0ffe Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 19:10:06 +0200 Subject: [PATCH 174/344] Bug #48709: Assertion failed in sql_select.cc:11782: int join_read_key(JOIN_TAB*) The eq_ref access method TABLE_REF (accessed through JOIN_TAB) to save state and to track if this is the first row it finds or not. This state was not reset on subquery re-execution causing an assert. Fixed by resetting the state before the subquery re-execution. --- mysql-test/r/subselect.result | 25 +++++++++++++++++++++++++ mysql-test/t/subselect.test | 26 ++++++++++++++++++++++++++ sql/sql_select.cc | 5 +++++ 3 files changed, 56 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 8c239d5c349..09a650c722b 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4502,4 +4502,29 @@ WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) NULL 0 DROP TABLE t1, st1, st2; +# +# Bug #48709: Assertion failed in sql_select.cc:11782: +# int join_read_key(JOIN_TAB*) +# +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); +# should have eq_ref for t1 +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +id select_type table type possible_keys key key_len ref rows Extra +x x outr ALL x x x x x x +x x t1 eq_ref x x x x x x +x x t2 index x x x x x x +# should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +pk int_key +3 3 +7 3 +DROP TABLE t1,t2; End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 2b5d36da796..bd12742f0f1 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3481,4 +3481,30 @@ WHERE a = 230; DROP TABLE t1, st1, st2; +--echo # +--echo # Bug #48709: Assertion failed in sql_select.cc:11782: +--echo # int join_read_key(JOIN_TAB*) +--echo # + +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); + +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); + +--echo # should have eq_ref for t1 +--replace_column 1 x 2 x 5 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +--echo # should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +DROP TABLE t1,t2; + + --echo End of 5.0 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f655db0fc32..d22a23a10d4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1553,6 +1553,11 @@ JOIN::reinit() if (join_tab_save) memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables); + /* need to reset ref access state (see join_read_key) */ + if (join_tab) + for (uint i= 0; i < tables; i++) + join_tab[i].ref.key_err= TRUE; + if (tmp_join) restore_tmp(); From 0b7768bc8d29c18596467d3da14dc1aefcdf9c6c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Dec 2009 12:25:46 +0800 Subject: [PATCH 175/344] Postfix Only relative log events are showed. --- mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test index 1276b0f3700..494a0db79fa 100644 --- a/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test +++ b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test @@ -1,6 +1,7 @@ -- source include/not_ndb_default.inc -- source include/have_log_bin.inc +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); CREATE TABLE t1 (c1 char(50)); LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; From c7d483155bb74b9129eeb50c2c90f8fc3215f323 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Dec 2009 12:41:15 +0800 Subject: [PATCH 176/344] Bug #46827 rpl_circular_for_4_hosts failed on PB2 This test case tests a circular replication of four hosts. A--->B--->C--->D--->A The replicate is slow and needs more time to replicate all data in the circle. The time it spends to replicate, sometimes, is longer than the time that wait_condition.inc spends to wait that all data has been replicated. This cause sporadical failure of this test case. This patch uses sync_slave_with_master to ensure that all data can be replicated successfully in the circle. --- .../suite/rpl/t/rpl_circular_for_4_hosts.test | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test index a49253f90c1..3633462d68e 100644 --- a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test +++ b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test @@ -233,16 +233,7 @@ COMMIT; --connection master_a --enable_query_log - ---let $wait_condition= SELECT COUNT(*)=400 FROM t2 WHERE c = 1 ---connection master_a ---source include/wait_condition.inc ---connection master_b ---source include/wait_condition.inc ---connection master_c ---source include/wait_condition.inc ---connection master_d ---source include/wait_condition.inc +--source include/circular_rpl_for_4_hosts_sync.inc --connection master_a SELECT 'Master A',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b; @@ -282,15 +273,7 @@ ROLLBACK; --connection master_a --enable_query_log ---let $wait_condition= SELECT COUNT(*)=200 FROM t2 WHERE c = 2 ---connection master_a ---source include/wait_condition.inc ---connection master_b ---source include/wait_condition.inc ---connection master_c ---source include/wait_condition.inc ---connection master_d ---source include/wait_condition.inc +--source include/circular_rpl_for_4_hosts_sync.inc --connection master_a SELECT 'Master A',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b; From adc17cd41e21cb68d63b9962a97ad075da02999f Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 16 Dec 2009 19:31:19 +0200 Subject: [PATCH 177/344] Bug #48866: mysql.test fails under Fedora 12 strmov() is not guaranteed to work correctly on overlapping source and destination buffers. On some OSes it may work, but Fedora 12 has a stpcpy() that's not working correctly on overlapping buffers. Fixed to use the overlap-safe version of strmov instead. Re-vitalized the overlap-safe version of strmov. --- client/mysql.cc | 2 +- include/m_string.h | 9 +++------ strings/strmov.c | 6 +----- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index e4eabe8de33..5ae58baa694 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -4108,7 +4108,7 @@ char *get_arg(char *line, my_bool get_next_arg) if (*ptr == '\\' && ptr[1]) // escaped character { // Remove the backslash - strmov(ptr, ptr+1); + strmov_overlapp(ptr, ptr+1); } else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype)) { diff --git a/include/m_string.h b/include/m_string.h index c26d0fb9260..5411d0483ea 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -108,9 +108,7 @@ extern char NEAR _dig_vec_lower[]; /* Defined in strtod.c */ extern const double log_10[309]; -#ifdef BAD_STRING_COMPILER -#define strmov(A,B) (memccpy(A,B,0,INT_MAX)-1) -#else +#ifndef strmov #define strmov_overlapp(A,B) strmov(A,B) #define strmake_overlapp(A,B,C) strmake(A,B,C) #endif @@ -171,12 +169,11 @@ extern uint strinstr(const char *str,const char *search); extern uint r_strinstr(reg1 my_string str,int from, reg4 my_string search); extern char *strkey(char *dst,char *head,char *tail,char *flags); extern char *strmake(char *dst,const char *src,uint length); -#ifndef strmake_overlapp -extern char *strmake_overlapp(char *dst,const char *src, uint length); -#endif #ifndef strmov extern char *strmov(char *dst,const char *src); +#else +extern char *strmov_overlapp(char *dst,const char *src); #endif extern char *strnmov(char *dst,const char *src,uint n); extern char *strsuff(const char *src,const char *suffix); diff --git a/strings/strmov.c b/strings/strmov.c index 1393411dd8f..eedf22a4ef1 100644 --- a/strings/strmov.c +++ b/strings/strmov.c @@ -24,13 +24,11 @@ #include #include "m_string.h" -#ifdef BAD_STRING_COMPILER +#ifdef strmov #undef strmov #define strmov strmov_overlapp #endif -#ifndef strmov - #if !defined(MC68000) && !defined(DS90) char *strmov(register char *dst, register const char *src) @@ -53,5 +51,3 @@ char *strmov(dst, src) } #endif - -#endif /* strmov */ From ad4bbb281f091709fdf1795fd5588e2cff93dd77 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Wed, 16 Dec 2009 19:52:56 +0000 Subject: [PATCH 178/344] BUG#49638 binlog_index fails in mysql-trunk-merge Calling push_warning/push_warning_printf with a level of WARN_LEVEL_ERROR *is* a bug. We should either use my_error(), or WARN_LEVEL_WARN. --- mysql-test/suite/binlog/r/binlog_index.result | 2 +- sql/log.cc | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_index.result b/mysql-test/suite/binlog/r/binlog_index.result index 06d8baf23bf..52d698e9f96 100644 --- a/mysql-test/suite/binlog/r/binlog_index.result +++ b/mysql-test/suite/binlog/r/binlog_index.result @@ -38,7 +38,7 @@ purge binary logs TO 'master-bin.000002'; ERROR HY000: Fatal error during log purge show warnings; Level Code Message -Error 1377 a problem with deleting master-bin.000001; consider examining correspondence of your binlog index file to the actual binlog files +Warning 1377 a problem with deleting master-bin.000001; consider examining correspondence of your binlog index file to the actual binlog files Error 1377 Fatal error during log purge reset master; # crash_purge_before_update_index diff --git a/sql/log.cc b/sql/log.cc index 1adf92e709c..2fd29588922 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3014,7 +3014,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) } else { - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with deleting %s; " "consider examining correspondence " @@ -3045,7 +3045,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) } else { - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with deleting %s; " "consider examining correspondence " @@ -3481,7 +3481,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, */ if (thd) { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with getting info on being purged %s; " "consider examining correspondence " @@ -3509,7 +3509,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, { if (thd) { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with deleting %s and " "reading the binlog index file", @@ -3557,7 +3557,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, { if (thd) { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with deleting %s; " "consider examining correspondence " @@ -3647,7 +3647,7 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) */ if (thd) { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with getting info on being purged %s; " "consider examining correspondence " From 4338e06f518aa1d5e4c621b80a5b265afb603f61 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Wed, 16 Dec 2009 20:53:56 +0100 Subject: [PATCH 179/344] Bug#47017 rpl_timezone fails on PB-2 with mismatch error The bug is caused by a race condition between the INSERT DELAYED thread and the client thread's FLUSH TABLE. The FLUSH TABLE does not guarantee (as is (wrongly) suggested in the test case) that the INSERT DELAYED is ever executed. The execution of the test case will thus not be deterministic. The fix has been to do a deterministic verification that both threads are complete by checking the content of the table. --- mysql-test/suite/rpl/t/rpl_timezone.test | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_timezone.test b/mysql-test/suite/rpl/t/rpl_timezone.test index 40a2a4444b9..45d1f12b5d5 100644 --- a/mysql-test/suite/rpl/t/rpl_timezone.test +++ b/mysql-test/suite/rpl/t/rpl_timezone.test @@ -179,8 +179,11 @@ insert into t1 values('2008-12-23 19:39:39',1); --connection master1 SET @@session.time_zone='+02:00'; insert delayed into t1 values ('2008-12-23 19:39:39',2); -# Forces table t1 to be closed and flushes the query cache. -# This makes sure that 'delayed insert' is executed before next statement. + +# wait for the delayed insert to be executed +let $wait_condition= SELECT date FROM t1 WHERE a=2; +--source include/wait_condition.inc + flush table t1; flush logs; select * from t1; From 06be03f77cc1dbd3f52232d98fbab2d220d93fc5 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Thu, 17 Dec 2009 09:55:03 +0400 Subject: [PATCH 180/344] Fix for bug#49465: valgrind warnings and incorrect live checksum... Problem: inserting a record we don't set unused null bits in the record buffer if no default field values used. That may lead to wrong live checksum calculation. Fix: set unused null bits in the record buffer in such cases. mysql-test/r/myisam.result: Fix for bug#49465: valgrind warnings and incorrect live checksum... - test result. mysql-test/t/myisam.test: Fix for bug#49465: valgrind warnings and incorrect live checksum... - test case. sql/sql_insert.cc: Fix for bug#49465: valgrind warnings and incorrect live checksum... - set unused null bits to 1 in the record buffer in case we don't call restore_record() before a fill_record() call (when no default values used). --- mysql-test/r/myisam.result | 15 +++++++++++++++ mysql-test/t/myisam.test | 14 ++++++++++++++ sql/sql_insert.cc | 11 ++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 53bb022147e..9c8e5c2863d 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1883,4 +1883,19 @@ CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1; +# +# Bug #49465: valgrind warnings and incorrect live checksum... +# +CREATE TABLE t1( +a VARCHAR(1), b VARCHAR(1), c VARCHAR(1), +f VARCHAR(1), g VARCHAR(1), h VARCHAR(1), +i VARCHAR(1), j VARCHAR(1), k VARCHAR(1)) CHECKSUM=1; +INSERT INTO t1 VALUES('', '', '', '', '', '', '', '', ''); +CHECKSUM TABLE t1 QUICK; +Table Checksum +test.t1 467455460 +CHECKSUM TABLE t1 EXTENDED; +Table Checksum +test.t1 467455460 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 254b0378aa8..d0a480348a3 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1225,4 +1225,18 @@ SELECT a FROM t1; CHECK TABLE t1; DROP TABLE t1; + +--echo # +--echo # Bug #49465: valgrind warnings and incorrect live checksum... +--echo # +CREATE TABLE t1( +a VARCHAR(1), b VARCHAR(1), c VARCHAR(1), +f VARCHAR(1), g VARCHAR(1), h VARCHAR(1), +i VARCHAR(1), j VARCHAR(1), k VARCHAR(1)) CHECKSUM=1; +INSERT INTO t1 VALUES('', '', '', '', '', '', '', '', ''); +CHECKSUM TABLE t1 QUICK; +CHECKSUM TABLE t1 EXTENDED; +DROP TABLE t1; + + --echo End of 5.0 tests diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b0958201795..76d4378a6f1 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -787,12 +787,21 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, restore_record(table,s->default_values); // Get empty record else { + TABLE_SHARE *share= table->s; + /* Fix delete marker. No need to restore rest of record since it will be overwritten by fill_record() anyway (and fill_record() does not use default values in this case). */ - table->record[0][0]= table->s->default_values[0]; + table->record[0][0]= share->default_values[0]; + + /* Fix undefined null_bits. */ + if (share->null_bytes > 1 && share->last_null_bit_pos) + { + table->record[0][share->null_bytes - 1]= + share->default_values[share->null_bytes - 1]; + } } if (fill_record_n_invoke_before_triggers(thd, table->field, *values, 0, table->triggers, From 6863f7dc2d93ef9da13a2c9423eb7d0c92d45636 Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Thu, 17 Dec 2009 10:55:18 +0100 Subject: [PATCH 181/344] Bug#47650: using group by with rollup without indexes returns incorrect results with where An outer join of a const table (outer) and a normal table (inner) with GROUP BY on a field from the outer table would optimize away GROUP BY, and thus trigger the optimization to do away with a temporary table if grouping was performed on columns from the const table, hence executing the query with filesort without temporary table. But this should not be done if there is a non-indexed access to the inner table, since filesort does not handle joins. It expects either ref access, range ditto or table scan. The join condition will thus not be applied. Fixed by always forcing execution with temporary table in the case of ROLLUP with a query involving an outer join. This is a slightly broader class of queries than need fixing, but it is hard to ascertain the position of a ROLLUP field wrt outer join with current query representation. mysql-test/r/join_outer.result: Bug#47650: Test result mysql-test/t/join_outer.test: Bug#47650: Test case sql/sql_select.cc: Bug#47650: Fix --- mysql-test/r/join_outer.result | 35 ++++++++++++++++++++++++++++++++++ mysql-test/t/join_outer.test | 29 ++++++++++++++++++++++++++++ sql/sql_select.cc | 14 +++++++++++++- 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 1e4fc91b8bd..083be3737f7 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1254,3 +1254,38 @@ SELECT * FROM t1 LEFT JOIN t2 ON e<>0 WHERE c=1 AND d<=>NULL; c e d 1 0 NULL DROP TABLE t1,t2; +# +# Bug#47650: using group by with rollup without indexes returns incorrect +# results with where +# +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 ( a INT, b INT ); +INSERT INTO t2 VALUES (1, 1),(1, 2),(1, 3),(2, 4),(2, 5); +EXPLAIN +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 LEFT JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 Using temporary; Using filesort +1 SIMPLE t2 ALL NULL NULL NULL NULL 5 +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 LEFT JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; +a COUNT( t2.b ) SUM( t2.b ) MAX( t2.b ) +1 3 6 3 +NULL 3 6 3 +EXPLAIN +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 Using filesort +1 SIMPLE t2 ALL NULL NULL NULL NULL 5 Using where +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; +a COUNT( t2.b ) SUM( t2.b ) MAX( t2.b ) +1 3 6 3 +NULL 3 6 3 +DROP TABLE t1, t2; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 35aec71ebb8..aeaa69657c6 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -867,3 +867,32 @@ SELECT * FROM t1 LEFT JOIN t2 ON e<>0 WHERE c=1 AND d<=>NULL; DROP TABLE t1,t2; +--echo # +--echo # Bug#47650: using group by with rollup without indexes returns incorrect +--echo # results with where +--echo # +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1); + +CREATE TABLE t2 ( a INT, b INT ); +INSERT INTO t2 VALUES (1, 1),(1, 2),(1, 3),(2, 4),(2, 5); + +EXPLAIN +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 LEFT JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; + +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 LEFT JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; + +EXPLAIN +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; + +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; + +DROP TABLE t1, t2; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cbee09f1fdb..6383fe63012 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7124,7 +7124,19 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, for (order=first_order; order ; order=order->next) { table_map order_tables=order->item[0]->used_tables(); - if (order->item[0]->with_sum_func) + if (order->item[0]->with_sum_func || + /* + If the outer table of an outer join is const (either by itself or + after applying WHERE condition), grouping on a field from such a + table will be optimized away and filesort without temporary table + will be used unless we prevent that now. Filesort is not fit to + handle joins and the join condition is not applied. We can't detect + the case without an expensive test, however, so we force temporary + table for all queries containing more than one table, ROLLUP, and an + outer join. + */ + (join->tables > 1 && join->rollup.state == ROLLUP::STATE_INITED && + join->outer_join)) *simple_order=0; // Must do a temp table to sort else if (!(order_tables & not_const_tables)) { From cf9966f86f3c6245f33342f2f5498a0c5efa96e4 Mon Sep 17 00:00:00 2001 From: Satya B Date: Thu, 17 Dec 2009 16:55:50 +0530 Subject: [PATCH 182/344] Fix for Bug#37408 - Compressed MyISAM files should not require/use mmap() When compressed myisam files are opened, they are always memory mapped sometimes causing memory swapping problems. When we mmap the myisam compressed tables of size greater than the memory available, the kswapd0 process utilization is very high consuming 30-40% of the cpu. This happens only with linux kernels older than 2.6.9 With newer linux kernels, we don't have this problem of high cpu consumption and this option may not be required. The option 'myisam_mmap_size' is added to limit the amount of memory used for memory mapping of myisam files. This option is not dynamic. The default value on 32 bit system is 4294967295 bytes and on 64 bit system it is 18446744073709547520 bytes. Note: Testcase only tests the option variable. The actual bug has be to tested manually. include/my_global.h: Fix for Bug #37408 - Compressed MyISAM files should not require/use mmap() define SIZE_T_MAX include/myisam.h: Fix for Bug #37408 - Compressed MyISAM files should not require/use mmap() declare 'myisam_mmap_size' and 'myisam_mmap_used' variables and the mutex THR_LOCK_myisam_mmap myisam/mi_packrec.c: Fix for Bug #37408 - Compressed MyISAM files should not require/use mmap() add 'myisam_mmap_size' option which limits the memory available to mmap of myisam files myisam/mi_static.c: Fix for Bug #37408 - Compressed MyISAM files should not require/use mmap() declare 'myisam_mmap_size' and 'myisam_mmap_used' variables and the mutex THR_LOCK_myisam_mmap myisam/myisamdef.h: Fix for Bug #37408 - Compressed MyISAM files should not require/use mmap() move MEMMAP_EXTRA_MARGIN to myisam.h so that it can be used in mysqld.cc mysql-test/r/variables.result: Fix for Bug #37408 - Compressed MyISAM files should not require/use mmap() Testcase for BUG#37408 to test the myisam_mmap_size option mysql-test/t/variables.test: Fix for Bug #37408 - Compressed MyISAM files should not require/use mmap() Testcase for BUG#37408 to test the myisam_mmap_size option mysys/my_thr_init.c: Fix for Bug #37408 - Compressed MyISAM files should not require/use mmap() intialize the lock THR_LOCK_myisam_mmap sql/mysqld.cc: Fix for Bug #37408 - Compressed MyISAM files should not require/use mmap() add the 'myisam_mmap_size' option sql/set_var.cc: Fix for Bug #37408 - Compressed MyISAM files should not require/use mmap() add the 'myisam_mmap_size' to the SHOW VARIABLES list --- include/my_global.h | 3 +++ include/myisam.h | 4 ++++ myisam/mi_packrec.c | 35 ++++++++++++++++++++++++++++++++++- myisam/mi_static.c | 3 ++- myisam/myisamdef.h | 1 - mysql-test/r/variables.result | 6 ++++++ mysql-test/t/variables.test | 6 ++++++ mysys/my_thr_init.c | 6 +++++- sql/mysqld.cc | 7 ++++++- sql/set_var.cc | 12 ++++++++++++ 10 files changed, 78 insertions(+), 5 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 6910ae092e1..595c7cd793b 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -793,6 +793,9 @@ typedef SOCKET_SIZE_TYPE size_socket; #define DBL_MAX 1.79769313486231470e+308 #define FLT_MAX ((float)3.40282346638528860e+38) #endif +#ifndef SIZE_T_MAX +#define SIZE_T_MAX (~((size_t) 0)) +#endif #ifndef HAVE_FINITE #define finite(x) (1.0 / fabs(x) > 0.0) diff --git a/include/myisam.h b/include/myisam.h index ad585f79608..acc2d689b75 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -270,6 +270,8 @@ extern ulong myisam_bulk_insert_tree_size, myisam_data_pointer_size; /* usually used to check if a symlink points into the mysql data home */ /* which is normally forbidden */ extern int (*myisam_test_invalid_symlink)(const char *filename); +extern ulonglong myisam_mmap_size, myisam_mmap_used; +extern pthread_mutex_t THR_LOCK_myisam_mmap; /* Prototypes for myisam-functions */ @@ -315,6 +317,8 @@ extern int mi_delete_all_rows(struct st_myisam_info *info); extern ulong _mi_calc_blob_length(uint length , const byte *pos); extern uint mi_get_pointer_length(ulonglong file_length, uint def); +#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for mmap file */ + /* this is used to pass to mysql_myisamchk_table -- by Sasha Pachev */ #define MYISAMCHK_REPAIR 1 /* equivalent to myisamchk -r */ diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index 75cf45d5434..f04c65da505 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -1499,12 +1499,26 @@ my_bool _mi_memmap_file(MI_INFO *info) { byte *file_map; MYISAM_SHARE *share=info->s; + my_bool eom; + DBUG_ENTER("mi_memmap_file"); if (!share->file_map) { my_off_t data_file_length= share->state.state.data_file_length; - if (data_file_length > (my_off_t) (~((size_t) 0)) - MEMMAP_EXTRA_MARGIN) + + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + eom= data_file_length > myisam_mmap_size - myisam_mmap_used - MEMMAP_EXTRA_MARGIN; + if (!eom) + myisam_mmap_used+= data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } + else + eom= data_file_length > myisam_mmap_size - MEMMAP_EXTRA_MARGIN; + + if (eom) { DBUG_PRINT("warning", ("File is too large for mmap")); DBUG_RETURN(0); @@ -1513,6 +1527,12 @@ my_bool _mi_memmap_file(MI_INFO *info) data_file_length + MEMMAP_EXTRA_MARGIN) { DBUG_PRINT("warning",("File isn't extended for memmap")); + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + myisam_mmap_used-= data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } DBUG_RETURN(0); } file_map=(byte*) @@ -1522,6 +1542,12 @@ my_bool _mi_memmap_file(MI_INFO *info) { DBUG_PRINT("warning",("mmap failed: errno: %d",errno)); my_errno=errno; + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + myisam_mmap_used-= data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } DBUG_RETURN(0); } share->file_map= file_map; @@ -1538,6 +1564,13 @@ void _mi_unmap_file(MI_INFO *info) VOID(my_munmap(info->s->file_map, (size_t) info->s->state.state.data_file_length+ MEMMAP_EXTRA_MARGIN)); + + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + myisam_mmap_used-= info->s->state.state.data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } } diff --git a/myisam/mi_static.c b/myisam/mi_static.c index ab7d3dc592b..b6464e452d7 100644 --- a/myisam/mi_static.c +++ b/myisam/mi_static.c @@ -40,7 +40,8 @@ ulong myisam_concurrent_insert= 0; my_off_t myisam_max_temp_length= MAX_FILE_SIZE; ulong myisam_bulk_insert_tree_size=8192*1024; ulong myisam_data_pointer_size=4; - +ulonglong myisam_mmap_size= SIZE_T_MAX, myisam_mmap_used= 0; +pthread_mutex_t THR_LOCK_myisam_mmap; static int always_valid(const char *filename __attribute__((unused))) { diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 4ebd5648d26..13ca945eae8 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -428,7 +428,6 @@ typedef struct st_mi_sort_param #define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1))) #define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint32)) -#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */ #define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */ #define PACK_TYPE_SPACE_FIELDS 2 diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 496f0b69fb8..e24117187d2 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -904,3 +904,9 @@ set global server_id =@my_server_id; set global slow_launch_time =@my_slow_launch_time; set global storage_engine =@my_storage_engine; set global thread_cache_size =@my_thread_cache_size; +# +# BUG#37408 - Compressed MyISAM files should not require/use mmap() +# +# Test 'myisam_mmap_size' option is not dynamic +SET @@myisam_mmap_size= 500M; +ERROR HY000: Variable 'myisam_mmap_size' is a read only variable diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 91f75cf6cd4..cff6a5a0767 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -765,3 +765,9 @@ set global slow_launch_time =@my_slow_launch_time; set global storage_engine =@my_storage_engine; set global thread_cache_size =@my_thread_cache_size; +--echo # +--echo # BUG#37408 - Compressed MyISAM files should not require/use mmap() +--echo # +--echo # Test 'myisam_mmap_size' option is not dynamic +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@myisam_mmap_size= 500M; diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 64fc99952e9..8dcffaebbbb 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -30,7 +30,9 @@ pthread_key(struct st_my_thread_var, THR_KEY_mysys); #endif /* USE_TLS */ pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open, THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap, - THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads; + THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, + THR_LOCK_myisam_mmap; + pthread_cond_t THR_COND_threads; uint THR_thread_count= 0; uint my_thread_end_wait_time= 5; @@ -143,6 +145,7 @@ my_bool my_thread_global_init(void) pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW); pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW); + pthread_mutex_init(&THR_LOCK_myisam_mmap,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST); @@ -208,6 +211,7 @@ void my_thread_global_end(void) pthread_mutex_destroy(&THR_LOCK_lock); pthread_mutex_destroy(&THR_LOCK_isam); pthread_mutex_destroy(&THR_LOCK_myisam); + pthread_mutex_destroy(&THR_LOCK_myisam_mmap); pthread_mutex_destroy(&THR_LOCK_heap); pthread_mutex_destroy(&THR_LOCK_net); pthread_mutex_destroy(&THR_LOCK_charset); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b4eb96ab65a..4b0739cc2d2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4975,7 +4975,8 @@ enum options_mysqld OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE, OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE, OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, - OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE, + OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_MMAP_SIZE, + OPT_MYISAM_SORT_BUFFER_SIZE, OPT_MYISAM_STATS_METHOD, OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT, OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT, @@ -6255,6 +6256,10 @@ The minimum value for this variable is 4096.", (gptr*) &max_system_variables.myisam_max_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE, 0, 1024*1024, 0}, + {"myisam_mmap_size", OPT_MYISAM_MMAP_SIZE, + "Can be used to restrict the total memory used for memory mmaping of myisam files", + (gptr*) &myisam_mmap_size, (gptr*) &myisam_mmap_size, 0, + GET_ULL, REQUIRED_ARG, SIZE_T_MAX, MEMMAP_EXTRA_MARGIN, SIZE_T_MAX, 0, 1, 0}, {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS, "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.", (gptr*) &global_system_variables.myisam_repair_threads, diff --git a/sql/set_var.cc b/sql/set_var.cc index c885f7160e9..4871afd2c56 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -122,6 +122,7 @@ static byte *get_error_count(THD *thd); static byte *get_warning_count(THD *thd); static byte *get_have_innodb(THD *thd); static byte *get_tmpdir(THD *thd); +static byte *get_myisam_mmap_size(THD *thd); /* Variable definition list @@ -623,6 +624,10 @@ sys_var_thd_bool sys_keep_files_on_create("keep_files_on_create", &SV::keep_files_on_create); +static sys_var_readonly sys_myisam_mmap_size("myisam_mmap_size", + OPT_GLOBAL, + SHOW_LONGLONG, + get_myisam_mmap_size); /* @@ -723,6 +728,7 @@ sys_var *sys_variables[]= &sys_multi_range_count, &sys_myisam_data_pointer_size, &sys_myisam_max_sort_file_size, + &sys_myisam_mmap_size, &sys_myisam_repair_threads, &sys_myisam_sort_buffer_size, &sys_myisam_stats_method, @@ -1026,6 +1032,7 @@ struct show_var_st init_vars[]= { {sys_myisam_data_pointer_size.name, (char*) &sys_myisam_data_pointer_size, SHOW_SYS}, {sys_myisam_max_sort_file_size.name, (char*) &sys_myisam_max_sort_file_size, SHOW_SYS}, + {sys_myisam_mmap_size.name, (char*) &sys_myisam_mmap_size, SHOW_SYS}, {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads, SHOW_SYS}, @@ -3181,6 +3188,11 @@ static byte *get_tmpdir(THD *thd) return (byte*)mysql_tmpdir; } +static byte *get_myisam_mmap_size(THD *thd) +{ + return (byte *)&myisam_mmap_size; +} + /**************************************************************************** Main handling of variables: - Initialisation From 522c084631ad581ec8f17b187a689f9b992ca06e Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Thu, 17 Dec 2009 16:34:11 +0200 Subject: [PATCH 183/344] Bug #49740 rpl.rpl_temporary fails in PB2 in mysql-trunk-merge The test allowed random coincidence of connection ids for two concurrent sessions performing CREATE/DROP temp tables. Fixed with correcting the test. The sessions connection ids are not changed from their defaults anymore. --- mysql-test/r/rpl_temporary.result | 2 ++ mysql-test/t/rpl_temporary.test | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result index 1326c7491f5..45e1a2776f7 100644 --- a/mysql-test/r/rpl_temporary.result +++ b/mysql-test/r/rpl_temporary.result @@ -16,8 +16,10 @@ ERROR 42000: Access denied; you need the SUPER privilege for this operation SELECT @@session.sql_select_limit = @save_select_limit; @@session.sql_select_limit = @save_select_limit 1 +SET @save_conn_id= connection_id(); SET @@session.pseudo_thread_id=100; SET @@session.pseudo_thread_id=connection_id(); +SET @@session.pseudo_thread_id=@save_conn_id; SET @@session.sql_log_bin=0; SET @@session.sql_log_bin=1; drop table if exists t1,t2; diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index 4cd538877eb..b85262b565d 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -41,8 +41,10 @@ SET @@session.sql_select_limit=10, @@session.sql_log_bin=0; SELECT @@session.sql_select_limit = @save_select_limit; #shouldn't have changed # Now as root, to be sure it works connection con2; +SET @save_conn_id= connection_id(); SET @@session.pseudo_thread_id=100; SET @@session.pseudo_thread_id=connection_id(); +SET @@session.pseudo_thread_id=@save_conn_id; SET @@session.sql_log_bin=0; SET @@session.sql_log_bin=1; From 06a1df91813ea2c39f7312bcf8af972c7e8a926f Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 17 Dec 2009 15:58:38 -0200 Subject: [PATCH 184/344] Bug#48983: Bad strmake calls (length one too long) The problem is a somewhat common misusage of the strmake function. The strmake(dst, src, len) function writes at most /len/ bytes to the string pointed to by src, not including the trailing null byte. Hence, if /len/ is the exact length of the destination buffer, a one byte buffer overflow can occur if the length of the source string is equal to or greater than /len/. client/mysqldump.c: Make room for the trailing null byte. libmysql/libmysql.c: Add comment, there is enough room in the buffer. Increase buffer length, two strings are concatenated. libmysqld/lib_sql.cc: Make room for the trailing null byte. mysys/default.c: Make room for the trailing null bytes. mysys/mf_pack.c: Make room for the trailing null byte. server-tools/instance-manager/commands.cc: Copy only if overflow isn't possible in both cases. server-tools/instance-manager/listener.cc: Make room for the trailing null byte. sql/log.cc: Make room for the trailing null byte. sql/sp_pcontext.h: Cosmetic fix. sql/sql_acl.cc: MAX_HOSTNAME already specifies space for the trailing null byte. sql/sql_parse.cc: Make room for the trailing null byte. sql/sql_table.cc: Make room for the trailing null byte. --- client/mysqldump.c | 4 ++-- libmysql/libmysql.c | 7 +++++-- libmysqld/lib_sql.cc | 2 +- mysys/default.c | 2 +- mysys/mf_pack.c | 4 ++-- server-tools/instance-manager/commands.cc | 2 +- server-tools/instance-manager/listener.cc | 2 +- sql/log.cc | 8 ++++---- sql/sp_pcontext.h | 2 +- sql/sql_acl.cc | 4 ++-- sql/sql_parse.cc | 2 +- sql/sql_table.cc | 2 +- 12 files changed, 22 insertions(+), 19 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 1918a657316..9bbf718eebf 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -782,7 +782,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), &err_ptr, &err_len); if (err_len) { - strmake(buff, err_ptr, min(sizeof(buff), err_len)); + strmake(buff, err_ptr, min(sizeof(buff) - 1, err_len)); fprintf(stderr, "Invalid mode to --compatible: %s\n", buff); exit(1); } @@ -3452,7 +3452,7 @@ static ulong find_set(TYPELIB *lib, const char *x, uint length, for (; pos != end && *pos != ','; pos++) ; var_len= (uint) (pos - start); - strmake(buff, start, min(sizeof(buff), var_len)); + strmake(buff, start, min(sizeof(buff) - 1, var_len)); find= find_type(buff, lib, var_len); if (!find) { diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index d287679bebb..62feae1b56e 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -712,7 +712,10 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, if (!passwd) passwd=""; - /* Store user into the buffer */ + /* + Store user into the buffer. + Advance position as strmake returns a pointer to the closing NUL. + */ end= strmake(end, user, USERNAME_LENGTH) + 1; /* write scrambled password according to server capabilities */ @@ -1252,7 +1255,7 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild) { MYSQL_RES *result; MYSQL_FIELD *fields; - char buff[257],*end; + char buff[258],*end; DBUG_ENTER("mysql_list_fields"); DBUG_PRINT("enter",("table: '%s' wild: '%s'",table,wild ? wild : "")); diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index b0a47727c7c..644d4702e55 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -73,7 +73,7 @@ void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data) NET *net= &mysql->net; struct embedded_query_result *ei= data->embedded_info; net->last_errno= ei->last_errno; - strmake(net->last_error, ei->info, sizeof(net->last_error)); + strmake(net->last_error, ei->info, sizeof(net->last_error) - 1); memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate)); mysql->server_status= ei->server_status; my_free((gptr) data, MYF(0)); diff --git a/mysys/default.c b/mysys/default.c index 362aa0d4605..0d162dc13d5 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -605,7 +605,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, int recursion_level) { char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext; - char *value, option[4096], tmp[FN_REFLEN]; + char *value, option[4096+2], tmp[FN_REFLEN]; static const char includedir_keyword[]= "includedir"; static const char include_keyword[]= "include"; const int max_recursion_level= 10; diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index d2bac95b391..3053699f457 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -234,7 +234,7 @@ my_bool my_use_symdir=0; /* Set this if you want to use symdirs */ #ifdef USE_SYMDIR void symdirget(char *dir) { - char buff[FN_REFLEN]; + char buff[FN_REFLEN+1]; char *pos=strend(dir); if (dir[0] && pos[-1] != FN_DEVCHAR && my_access(dir, F_OK)) { @@ -246,7 +246,7 @@ void symdirget(char *dir) *pos++=temp; *pos=0; /* Restore old filename */ if (file >= 0) { - if ((length= my_read(file, buff, sizeof(buff), MYF(0))) > 0) + if ((length= my_read(file, buff, sizeof(buff) - 1, MYF(0))) > 0) { for (pos= buff + length ; pos > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ; diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc index bb3763ce8c5..5e8ba5087af 100644 --- a/server-tools/instance-manager/commands.cc +++ b/server-tools/instance-manager/commands.cc @@ -651,7 +651,7 @@ Set_option::Set_option(Instance_map *instance_map_arg, instance_name= instance->options.instance_name; /* add prefix for add_option */ - if ((option_len_arg < MAX_OPTION_LEN - 1) || + if ((option_len_arg < MAX_OPTION_LEN - 1) && (option_value_len_arg < MAX_OPTION_LEN - 1)) { strmake(option, option_arg, option_len_arg); diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index 36f0cbe85e1..653a807e5fc 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -331,7 +331,7 @@ create_unix_socket(struct sockaddr_un &unix_socket_address) unix_socket_address.sun_family= AF_UNIX; strmake(unix_socket_address.sun_path, options.socket_file_name, - sizeof(unix_socket_address.sun_path)); + sizeof(unix_socket_address.sun_path) - 1); unlink(unix_socket_address.sun_path); // in case we have stale socket file /* diff --git a/sql/log.cc b/sql/log.cc index c042651216c..4aeab534b23 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -501,7 +501,7 @@ const char *MYSQL_LOG::generate_name(const char *log_name, { char *p = fn_ext(log_name); uint length=(uint) (p-log_name); - strmake(buff,log_name,min(length,FN_REFLEN)); + strmake(buff, log_name, min(length, FN_REFLEN-1)); return (const char*)buff; } return log_name; @@ -1503,7 +1503,7 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time) if (stat_area.st_mtime < purge_time) strmake(to_log, log_info.log_file_name, - sizeof(log_info.log_file_name)); + sizeof(log_info.log_file_name) - 1); else break; } @@ -2604,11 +2604,11 @@ bool flush_error_log() if (opt_error_log) { char err_renamed[FN_REFLEN], *end; - end= strmake(err_renamed,log_error_file,FN_REFLEN-4); + end= strmake(err_renamed,log_error_file,FN_REFLEN-5); strmov(end, "-old"); VOID(pthread_mutex_lock(&LOCK_error_log)); #ifdef __WIN__ - char err_temp[FN_REFLEN+4]; + char err_temp[FN_REFLEN+5]; /* On Windows is necessary a temporary file for to rename the current error file. diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index db8bed349f2..cd3011b2c37 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -71,7 +71,7 @@ typedef struct sp_label typedef struct sp_cond_type { enum { number, state, warning, notfound, exception } type; - char sqlstate[6]; + char sqlstate[SQLSTATE_LENGTH+1]; uint mysqlerr; } sp_cond_type_t; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f29baad9a84..bf117874552 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -914,7 +914,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, *mqh= acl_user->user_resource; if (acl_user->host.hostname) - strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME); + strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME - 1); else *sctx->priv_host= 0; } @@ -1015,7 +1015,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, sctx->priv_user= acl_user->user ? user : (char *) ""; if (acl_user->host.hostname) - strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME); + strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME - 1); else *sctx->priv_host= 0; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f34aa3c3bad..48df40f2614 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -917,7 +917,7 @@ static int check_connection(THD *thd) vio_keepalive(net->vio, TRUE); { /* buff[] needs to big enough to hold the server_version variable */ - char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64]; + char buff[SERVER_VERSION_LENGTH + 1 + SCRAMBLE_LENGTH + 1 + 64]; ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e32c17bc678..9432c5c3f89 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -742,7 +742,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname, MY_CS_BINSORT,MYF(0)))) { - char tmp[64]; + char tmp[65]; strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4), STRING_WITH_LEN("_bin")); my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp); From f815246486444ca2dc5d408099439e1d973d3a7b Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Fri, 18 Dec 2009 11:48:34 +0100 Subject: [PATCH 185/344] Backport to 5.1 branch (next-mr revid: 2921) Bug#35589 SET PASSWORD caused a crash Bug#35591 FLUSH PRIVILEGES caused a crash A race condition on the privilege hash tables (proc_priv_hash and func_priv_hash) caused one thread to try to delete elements that had already been deleted by another thread. The bug was caused by reading and saving the pointers to the hash tables outside mutex protection. This led to an inconsistency where a thread copied a pointer to a hash, another thread did the same, the first thread then deleted the hash, and the second then crashed when it in turn tried to delete the deleted hash. The fix is to ensure that operations on the shared hash structures happens under mutex protection (moving the locking up a little) --- sql/sql_acl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 3b81a85c368..b30c012e633 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3765,11 +3765,11 @@ static my_bool grant_reload_procs_priv(THD *thd) DBUG_RETURN(TRUE); } + rw_wrlock(&LOCK_grant); /* Save a copy of the current hash if we need to undo the grant load */ old_proc_priv_hash= proc_priv_hash; old_func_priv_hash= func_priv_hash; - rw_wrlock(&LOCK_grant); if ((return_val= grant_load_procs_priv(table.table))) { /* Error; Reverting to old hash */ From 6559a46a245264eafd1f87ec65097f83d77142bd Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 21 Dec 2009 15:41:38 +0530 Subject: [PATCH 186/344] Applying InnoDB snapshot 5.1-ss6344, part 1. Fixes BUG#49267 Detailed revision comments: r6306 | calvin | 2009-12-14 15:12:46 +0200 (Mon, 14 Dec 2009) | 5 lines branches/5.1: fix bug#49267: innodb-autoinc.test fails on windows because of different case mode There is no change to the InnoDB code, only to fix test case by changing "T1" to "t1". --- mysql-test/r/innodb-autoinc.result | 42 +++++++++++++++--------------- mysql-test/t/innodb-autoinc.test | 34 ++++++++++++------------ 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index 2e0d2c1d776..fe87e11c9ec 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -1111,46 +1111,46 @@ c1 c2 3 innodb 4 NULL DROP TABLE t1; -CREATE TABLE T1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) AUTO_INCREMENT=10 ENGINE=InnoDB; -CREATE INDEX i1 on T1(c2); -SHOW CREATE TABLE T1; +CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) AUTO_INCREMENT=10 ENGINE=InnoDB; +CREATE INDEX i1 on t1(c2); +SHOW CREATE TABLE t1; Table Create Table -T1 CREATE TABLE `T1` ( +t1 CREATE TABLE `t1` ( `c1` int(11) NOT NULL AUTO_INCREMENT, `c2` int(11) DEFAULT NULL, PRIMARY KEY (`c1`), KEY `i1` (`c2`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1 -INSERT INTO T1 (c2) values (0); -SELECT * FROM T1; +INSERT INTO t1 (c2) values (0); +SELECT * FROM t1; c1 c2 10 0 -DROP TABLE T1; -DROP TABLE IF EXISTS T1; +DROP TABLE t1; +DROP TABLE IF EXISTS t1; Warnings: -Note 1051 Unknown table 'T1' -CREATE TABLE T1(C1 DOUBLE AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; -INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); -INSERT INTO T1(C2) VALUES ('innodb'); -SHOW CREATE TABLE T1; +Note 1051 Unknown table 't1' +CREATE TABLE t1(C1 DOUBLE AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO t1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +INSERT INTO t1(C2) VALUES ('innodb'); +SHOW CREATE TABLE t1; Table Create Table -T1 CREATE TABLE `T1` ( +t1 CREATE TABLE `t1` ( `C1` double NOT NULL AUTO_INCREMENT, `C2` char(10) DEFAULT NULL, PRIMARY KEY (`C1`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 -DROP TABLE T1; -CREATE TABLE T1(C1 FLOAT AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; -INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); -INSERT INTO T1(C2) VALUES ('innodb'); -SHOW CREATE TABLE T1; +DROP TABLE t1; +CREATE TABLE t1(C1 FLOAT AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO t1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +INSERT INTO t1(C2) VALUES ('innodb'); +SHOW CREATE TABLE t1; Table Create Table -T1 CREATE TABLE `T1` ( +t1 CREATE TABLE `t1` ( `C1` float NOT NULL AUTO_INCREMENT, `C2` char(10) DEFAULT NULL, PRIMARY KEY (`C1`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 -DROP TABLE T1; +DROP TABLE t1; DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index 4fa5ab022ad..84386280a26 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -614,31 +614,31 @@ DROP TABLE t1; # 47125: auto_increment start value is ignored if an index is created # and engine=innodb # -CREATE TABLE T1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) AUTO_INCREMENT=10 ENGINE=InnoDB; -CREATE INDEX i1 on T1(c2); -SHOW CREATE TABLE T1; -INSERT INTO T1 (c2) values (0); -SELECT * FROM T1; -DROP TABLE T1; +CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) AUTO_INCREMENT=10 ENGINE=InnoDB; +CREATE INDEX i1 on t1(c2); +SHOW CREATE TABLE t1; +INSERT INTO t1 (c2) values (0); +SELECT * FROM t1; +DROP TABLE t1; ## # 49032: Use the correct function to read the AUTOINC column value # -DROP TABLE IF EXISTS T1; -CREATE TABLE T1(C1 DOUBLE AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; -INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(C1 DOUBLE AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO t1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); # Restart the server -- source include/restart_mysqld.inc -INSERT INTO T1(C2) VALUES ('innodb'); -SHOW CREATE TABLE T1; -DROP TABLE T1; -CREATE TABLE T1(C1 FLOAT AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; -INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +INSERT INTO t1(C2) VALUES ('innodb'); +SHOW CREATE TABLE t1; +DROP TABLE t1; +CREATE TABLE t1(C1 FLOAT AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO t1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); # Restart the server -- source include/restart_mysqld.inc -INSERT INTO T1(C2) VALUES ('innodb'); -SHOW CREATE TABLE T1; -DROP TABLE T1; +INSERT INTO t1(C2) VALUES ('innodb'); +SHOW CREATE TABLE t1; +DROP TABLE t1; ## # 47720: REPLACE INTO Autoincrement column with negative values From 2f04df4ab040b5821cf552c27741ede58ebec162 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 21 Dec 2009 15:50:32 +0530 Subject: [PATCH 187/344] Applying InnoDB snapshot 5.1-ss6344, part 2. Fixes BUG#41609 but does not address the printouts issue Detailed revision comments: r6310 | marko | 2009-12-15 15:23:54 +0200 (Tue, 15 Dec 2009) | 30 lines branches/5.1: Merge r4922 from branches/zip. This the fix for the first part of Bug #41609 from InnoDB Plugin to the built-in InnoDB in MySQL 5.1. This allows InnoDB Hot Backup to back up a database while the built-in InnoDB in MySQL 5.1 is creating temporary tables. (This fix does not address the printouts about missing .ibd files for temporary tables at InnoDB startup, which was committed to branches/zip in r6252.) rb://219 approved by Sunny Bains. branches/zip: Distinguish temporary tables in MLOG_FILE_CREATE. This addresses Mantis Issue #23 in InnoDB Hot Backup and some of MySQL Bug #41609. In MLOG_FILE_CREATE, we need to distinguish temporary tables, so that InnoDB Hot Backup can work correctly. It turns out that we can do this easily, by using a bit of the previously unused parameter for page number. (The page number parameter of MLOG_FILE_CREATE has been written as 0 ever since MySQL 4.1, which introduced MLOG_FILE_CREATE.) MLOG_FILE_FLAG_TEMP: A flag for indicating a temporary table in the page number parameter of MLOG_FILE_ operations. fil_op_write_log(): Add the parameter log_flags. fil_op_log_parse_or_replay(): Add the parameter log_flags. Do not replay MLOG_FILE_CREATE when MLOG_FILE_FLAG_TEMP is set in log_flags. This only affects ibbackup --apply-log. InnoDB itself never replays file operations. --- storage/innobase/fil/fil0fil.c | 29 +++++++++++++++++------------ storage/innobase/include/fil0fil.h | 10 +++++----- storage/innobase/include/mtr0mtr.h | 6 ++++++ storage/innobase/log/log0recv.c | 7 +++---- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index 42e5166c9e4..3810fefd3cb 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -1740,6 +1740,8 @@ fil_op_write_log( MLOG_FILE_DELETE, or MLOG_FILE_RENAME */ ulint space_id, /* in: space id */ + ulint log_flags, /* in: redo log flags (stored + in the page number field) */ const char* name, /* in: table name in the familiar 'databasename/tablename' format, or the file path in the case of @@ -1760,8 +1762,8 @@ fil_op_write_log( return; } - log_ptr = mlog_write_initial_log_record_for_file_op(type, space_id, 0, - log_ptr, mtr); + log_ptr = mlog_write_initial_log_record_for_file_op( + type, space_id, log_flags, log_ptr, mtr); /* Let us store the strings as null-terminated for easier readability and handling */ @@ -1810,11 +1812,11 @@ fil_op_log_parse_or_replay( not fir completely between ptr and end_ptr */ byte* end_ptr, /* in: buffer end */ ulint type, /* in: the type of this log record */ - ibool do_replay, /* in: TRUE if we want to replay the - operation, and not just parse the log record */ - ulint space_id) /* in: if do_replay is TRUE, the space id of - the tablespace in question; otherwise - ignored */ + ulint space_id, /* in: the space id of the tablespace in + question, or 0 if the log record should + only be parsed but not replayed */ + ulint log_flags) /* in: redo log flags + (stored in the page number parameter) */ { ulint name_len; ulint new_name_len; @@ -1868,7 +1870,7 @@ fil_op_log_parse_or_replay( printf("new name %s\n", new_name); } */ - if (do_replay == FALSE) { + if (!space_id) { return(ptr); } @@ -1917,6 +1919,8 @@ fil_op_log_parse_or_replay( } else if (fil_get_space_id_for_table(name) != ULINT_UNDEFINED) { /* Do nothing */ + } else if (log_flags & MLOG_FILE_FLAG_TEMP) { + /* Temporary table, do nothing */ } else { /* Create the database directory for name, if it does not exist yet */ @@ -2078,7 +2082,7 @@ try_again: to write any log record */ mtr_start(&mtr); - fil_op_write_log(MLOG_FILE_DELETE, id, path, NULL, &mtr); + fil_op_write_log(MLOG_FILE_DELETE, id, 0, path, NULL, &mtr); mtr_commit(&mtr); #endif mem_free(path); @@ -2349,7 +2353,7 @@ retry: mtr_start(&mtr); - fil_op_write_log(MLOG_FILE_RENAME, id, old_name, new_name, + fil_op_write_log(MLOG_FILE_RENAME, id, 0, old_name, new_name, &mtr); mtr_commit(&mtr); } @@ -2525,8 +2529,9 @@ error_exit2: mtr_start(&mtr); - fil_op_write_log(MLOG_FILE_CREATE, *space_id, tablename, - NULL, &mtr); + fil_op_write_log(MLOG_FILE_CREATE, *space_id, + is_temp ? MLOG_FILE_FLAG_TEMP : 0, + tablename, NULL, &mtr); mtr_commit(&mtr); } diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 6b8fd4b03d5..251d6c22547 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -330,11 +330,11 @@ fil_op_log_parse_or_replay( not fir completely between ptr and end_ptr */ byte* end_ptr, /* in: buffer end */ ulint type, /* in: the type of this log record */ - ibool do_replay, /* in: TRUE if we want to replay the - operation, and not just parse the log record */ - ulint space_id); /* in: if do_replay is TRUE, the space id of - the tablespace in question; otherwise - ignored */ + ulint space_id, /* in: the space id of the tablespace in + question, or 0 if the log record should + only be parsed but not replayed */ + ulint log_flags); /* in: redo log flags + (stored in the page number parameter) */ /*********************************************************************** Deletes a single-table tablespace. The tablespace must be cached in the memory cache. */ diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 2a160d27e0c..a6e2976830b 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -134,6 +134,12 @@ flag value must give the length also! */ #define MLOG_BIGGEST_TYPE ((byte)46) /* biggest value (used in asserts) */ +/* Flags for MLOG_FILE operations (stored in the page number +parameter, called log_flags in the functions). The page number +parameter was initially written as 0. */ +#define MLOG_FILE_FLAG_TEMP 1 /* identifies TEMPORARY TABLE in + MLOG_FILE_CREATE */ + /******************************************************************* Starts a mini-transaction and creates a mini-transaction handle and buffer in the memory buffer given by the caller. */ diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c index aef58b7b576..5d309768064 100644 --- a/storage/innobase/log/log0recv.c +++ b/storage/innobase/log/log0recv.c @@ -939,8 +939,7 @@ recv_parse_or_apply_log_rec_body( case MLOG_FILE_CREATE: case MLOG_FILE_RENAME: case MLOG_FILE_DELETE: - ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE, - ULINT_UNDEFINED); + ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, 0, 0); break; default: ptr = NULL; @@ -1938,8 +1937,8 @@ loop: point to the datadir we should use there */ if (NULL == fil_op_log_parse_or_replay( - body, end_ptr, type, TRUE, - space)) { + body, end_ptr, type, + space, page_no)) { fprintf(stderr, "InnoDB: Error: file op" " log record of type %lu" From 83d5ca950ba1b6e1d5cbc2f39352a30ff7bad8b4 Mon Sep 17 00:00:00 2001 From: Satya B Date: Wed, 23 Dec 2009 12:29:34 +0530 Subject: [PATCH 188/344] Applying InnoDB snapshot 5.1-ss6344, Fixes BUG#47814 and also applying 5.1-ss6355 Detailed revision comments: r6324 | jyang | 2009-12-17 06:54:24 +0200 (Thu, 17 Dec 2009) | 8 lines branches/5.1: Fix bug #47814 - Diagnostics are frequently not printed after a long lock wait in InnoDB. Separate out the lock wait timeout check thread from monitor information printing thread. rb://200 Approved by Marko. r6349 | marko | 2009-12-22 11:09:54 +0200 (Tue, 22 Dec 2009) | 3 lines branches/5.1: lock_print_info_summary(): Remove a reference to innobase_mysql_end_print_arbitrary_thd() that should have been removed in r6347 when removing the function. r6350 | marko | 2009-12-22 11:11:09 +0200 (Tue, 22 Dec 2009) | 1 line branches/5.1: Remove an obsolete declaration of LOCK_thread_count. --- storage/innobase/handler/ha_innodb.cc | 4 +- storage/innobase/include/lock0lock.h | 9 +- storage/innobase/include/srv0srv.h | 26 +++- storage/innobase/lock/lock0lock.c | 22 +++- storage/innobase/log/log0log.c | 2 +- storage/innobase/srv/srv0srv.c | 177 ++++++++++++++++++++------ storage/innobase/srv/srv0start.c | 15 ++- 7 files changed, 194 insertions(+), 61 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 2467e7b19b5..a1b8c551845 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7394,8 +7394,8 @@ innodb_show_status( mutex_enter_noninline(&srv_monitor_file_mutex); rewind(srv_monitor_file); - srv_printf_innodb_monitor(srv_monitor_file, - &trx_list_start, &trx_list_end); + srv_printf_innodb_monitor(srv_monitor_file, FALSE, + &trx_list_start, &trx_list_end); flen = ftell(srv_monitor_file); os_file_set_eof(srv_monitor_file); diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 635724bf5a1..beaf17eda01 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -579,10 +579,15 @@ lock_rec_print( /************************************************************************* Prints info of locks for all transactions. */ -void +ibool lock_print_info_summary( /*====================*/ - FILE* file); /* in: file where to print */ + /* out: FALSE if not able to obtain + kernel mutex and exits without + printing info */ + FILE* file, /* in: file where to print */ + ibool nowait);/* in: whether to wait for the kernel + mutex */ /************************************************************************* Prints info of locks for each transaction. */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 67144a41d3d..3dd4bb961f9 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -146,7 +146,8 @@ extern ibool srv_print_innodb_tablespace_monitor; extern ibool srv_print_verbose_log; extern ibool srv_print_innodb_table_monitor; -extern ibool srv_lock_timeout_and_monitor_active; +extern ibool srv_lock_timeout_active; +extern ibool srv_monitor_active; extern ibool srv_error_monitor_active; extern ulong srv_n_spin_wait_rounds; @@ -427,12 +428,21 @@ srv_release_mysql_thread_if_suspended( que_thr_t* thr); /* in: query thread associated with the MySQL OS thread */ /************************************************************************* -A thread which wakes up threads whose lock wait may have lasted too long. -This also prints the info output by various InnoDB monitors. */ +A thread which wakes up threads whose lock wait may have lasted too +long. */ os_thread_ret_t -srv_lock_timeout_and_monitor_thread( -/*================================*/ +srv_lock_timeout_thread( +/*====================*/ + /* out: a dummy parameter */ + void* arg); /* in: a dummy parameter required by + os_thread_create */ +/************************************************************************* +A thread which prints the info output by various InnoDB monitors. */ + +os_thread_ret_t +srv_monitor_thread( +/*===============*/ /* out: a dummy parameter */ void* arg); /* in: a dummy parameter required by os_thread_create */ @@ -449,10 +459,14 @@ srv_error_monitor_thread( /********************************************************************** Outputs to a file the output of the InnoDB Monitor. */ -void +ibool srv_printf_innodb_monitor( /*======================*/ + /* out: FALSE if not all information printed + due to failure to obtain necessary mutex */ FILE* file, /* in: output stream */ + ibool nowait, /* in: whether to wait for kernel + mutex. */ ulint* trx_start, /* out: file position of the start of the list of active transactions */ ulint* trx_end); /* out: file position of the end of diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 80aef45ea35..4cc10931060 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -4192,12 +4192,27 @@ lock_get_n_rec_locks(void) /************************************************************************* Prints info of locks for all transactions. */ -void +ibool lock_print_info_summary( /*====================*/ - FILE* file) /* in: file where to print */ + /* out: FALSE if not able to obtain + kernel mutex and exit without + printing lock info */ + FILE* file, /* in: file where to print */ + ibool nowait) /* in: whether to wait for the kernel + mutex */ { - lock_mutex_enter_kernel(); + + /* if nowait is FALSE, wait on the kernel mutex, + otherwise return immediately if fail to obtain the + mutex. */ + if (!nowait) { + lock_mutex_enter_kernel(); + } else if (mutex_enter_nowait(&kernel_mutex)) { + fputs("FAIL TO OBTAIN KERNEL MUTEX, " + "SKIP LOCK INFO PRINTING\n", file); + return(FALSE); + } if (lock_deadlock_found) { fputs("------------------------\n" @@ -4231,6 +4246,7 @@ lock_print_info_summary( "Total number of lock structs in row lock hash table %lu\n", (ulong) lock_get_n_rec_locks()); #endif /* PRINT_NUM_OF_LOCK_STRUCTS */ + return(TRUE); } /************************************************************************* diff --git a/storage/innobase/log/log0log.c b/storage/innobase/log/log0log.c index b10c348b24d..3300997112b 100644 --- a/storage/innobase/log/log0log.c +++ b/storage/innobase/log/log0log.c @@ -3045,7 +3045,7 @@ loop: if (srv_fast_shutdown < 2 && (srv_error_monitor_active - || srv_lock_timeout_and_monitor_active)) { + || srv_lock_timeout_active || srv_monitor_active)) { mutex_exit(&kernel_mutex); diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index 71e74ab848b..26ea7958d0d 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -64,7 +64,8 @@ ulint srv_fatal_semaphore_wait_threshold = 600; in microseconds, in order to reduce the lagging of the purge thread. */ ulint srv_dml_needed_delay = 0; -ibool srv_lock_timeout_and_monitor_active = FALSE; +ibool srv_lock_timeout_active = FALSE; +ibool srv_monitor_active = FALSE; ibool srv_error_monitor_active = FALSE; const char* srv_main_thread_op_info = ""; @@ -122,6 +123,16 @@ ulint srv_log_file_size = ULINT_MAX; /* size in database pages */ ulint srv_log_buffer_size = ULINT_MAX; /* size in database pages */ ulong srv_flush_log_at_trx_commit = 1; +/* Maximum number of times allowed to conditionally acquire +mutex before switching to blocking wait on the mutex */ +#define MAX_MUTEX_NOWAIT 20 + +/* Check whether the number of failed nonblocking mutex +acquisition attempts exceeds maximum allowed value. If so, +srv_printf_innodb_monitor() will request mutex acquisition +with mutex_enter(), which will wait until it gets the mutex. */ +#define MUTEX_NOWAIT(mutex_skipped) ((mutex_skipped) < MAX_MUTEX_NOWAIT) + byte srv_latin1_ordering[256] /* The sort order table of the latin1 character set. The following table is the MySQL order as of Feb 10th, 2002 */ @@ -1626,10 +1637,13 @@ srv_refresh_innodb_monitor_stats(void) /********************************************************************** Outputs to a file the output of the InnoDB Monitor. */ -void +ibool srv_printf_innodb_monitor( /*======================*/ + /* out: FALSE if not all information printed + due to failure to obtain necessary mutex */ FILE* file, /* in: output stream */ + ibool nowait, /* in: whether to wait for the mutex. */ ulint* trx_start, /* out: file position of the start of the list of active transactions */ ulint* trx_end) /* out: file position of the end of @@ -1638,6 +1652,7 @@ srv_printf_innodb_monitor( double time_elapsed; time_t current_time; ulint n_reserved; + ibool ret; mutex_enter(&srv_innodb_monitor_mutex); @@ -1682,24 +1697,31 @@ srv_printf_innodb_monitor( mutex_exit(&dict_foreign_err_mutex); - lock_print_info_summary(file); - if (trx_start) { - long t = ftell(file); - if (t < 0) { - *trx_start = ULINT_UNDEFINED; - } else { - *trx_start = (ulint) t; - } - } - lock_print_info_all_transactions(file); - if (trx_end) { - long t = ftell(file); - if (t < 0) { - *trx_end = ULINT_UNDEFINED; - } else { - *trx_end = (ulint) t; + /* Only if lock_print_info_summary proceeds correctly, + before we call the lock_print_info_all_transactions + to print all the lock information. */ + ret = lock_print_info_summary(file, nowait); + + if (ret) { + if (trx_start) { + long t = ftell(file); + if (t < 0) { + *trx_start = ULINT_UNDEFINED; + } else { + *trx_start = (ulint) t; + } + } + lock_print_info_all_transactions(file); + if (trx_end) { + long t = ftell(file); + if (t < 0) { + *trx_end = ULINT_UNDEFINED; + } else { + *trx_end = (ulint) t; + } } } + fputs("--------\n" "FILE I/O\n" "--------\n", file); @@ -1804,6 +1826,8 @@ srv_printf_innodb_monitor( "============================\n", file); mutex_exit(&srv_innodb_monitor_mutex); fflush(file); + + return(ret); } /********************************************************************** @@ -1883,26 +1907,23 @@ srv_export_innodb_status(void) } /************************************************************************* -A thread which wakes up threads whose lock wait may have lasted too long. -This also prints the info output by various InnoDB monitors. */ +A thread prints the info output by various InnoDB monitors. */ os_thread_ret_t -srv_lock_timeout_and_monitor_thread( -/*================================*/ +srv_monitor_thread( +/*===============*/ /* out: a dummy parameter */ void* arg __attribute__((unused))) /* in: a dummy parameter required by os_thread_create */ { - srv_slot_t* slot; double time_elapsed; time_t current_time; time_t last_table_monitor_time; time_t last_tablespace_monitor_time; time_t last_monitor_time; - ibool some_waits; - double wait_time; - ulint i; + ulint mutex_skipped; + ibool last_srv_print_monitor; #ifdef UNIV_DEBUG_THREAD_CREATION fprintf(stderr, "Lock timeout thread starts, id %lu\n", @@ -1913,13 +1934,15 @@ srv_lock_timeout_and_monitor_thread( last_table_monitor_time = time(NULL); last_tablespace_monitor_time = time(NULL); last_monitor_time = time(NULL); + mutex_skipped = 0; + last_srv_print_monitor = srv_print_innodb_monitor; loop: - srv_lock_timeout_and_monitor_active = TRUE; + srv_monitor_active = TRUE; - /* When someone is waiting for a lock, we wake up every second - and check if a timeout has passed for a lock wait */ + /* Wake up every 5 seconds to see if we need to print + monitor information. */ - os_thread_sleep(1000000); + os_thread_sleep(5000000); current_time = time(NULL); @@ -1929,14 +1952,40 @@ loop: last_monitor_time = time(NULL); if (srv_print_innodb_monitor) { - srv_printf_innodb_monitor(stderr, NULL, NULL); + /* Reset mutex_skipped counter everytime + srv_print_innodb_monitor changes. This is to + ensure we will not be blocked by kernel_mutex + for short duration information printing, + such as requested by sync_array_print_long_waits() */ + if (!last_srv_print_monitor) { + mutex_skipped = 0; + last_srv_print_monitor = TRUE; + } + + if (!srv_printf_innodb_monitor(stderr, + MUTEX_NOWAIT(mutex_skipped), + NULL, NULL)) { + mutex_skipped++; + } else { + /* Reset the counter */ + mutex_skipped = 0; + } + } else { + last_srv_print_monitor = FALSE; } + if (srv_innodb_status) { mutex_enter(&srv_monitor_file_mutex); rewind(srv_monitor_file); - srv_printf_innodb_monitor(srv_monitor_file, NULL, - NULL); + if (!srv_printf_innodb_monitor(srv_monitor_file, + MUTEX_NOWAIT(mutex_skipped), + NULL, NULL)) { + mutex_skipped++; + } else { + mutex_skipped = 0; + } + os_file_set_eof(srv_monitor_file); mutex_exit(&srv_monitor_file_mutex); } @@ -1989,6 +2038,56 @@ loop: } } + if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) { + goto exit_func; + } + + if (srv_print_innodb_monitor + || srv_print_innodb_lock_monitor + || srv_print_innodb_tablespace_monitor + || srv_print_innodb_table_monitor) { + goto loop; + } + + srv_monitor_active = FALSE; + + goto loop; + +exit_func: + srv_monitor_active = FALSE; + + /* We count the number of threads in os_thread_exit(). A created + thread should always use that to exit and not use return() to exit. */ + + os_thread_exit(NULL); + + OS_THREAD_DUMMY_RETURN; +} + +/************************************************************************* +A thread which wakes up threads whose lock wait may have lasted too long. */ + +os_thread_ret_t +srv_lock_timeout_thread( +/*====================*/ + /* out: a dummy parameter */ + void* arg __attribute__((unused))) + /* in: a dummy parameter required by + os_thread_create */ +{ + srv_slot_t* slot; + ibool some_waits; + double wait_time; + ulint i; + +loop: + /* When someone is waiting for a lock, we wake up every second + and check if a timeout has passed for a lock wait */ + + os_thread_sleep(1000000); + + srv_lock_timeout_active = TRUE; + mutex_enter(&kernel_mutex); some_waits = FALSE; @@ -2033,17 +2132,11 @@ loop: goto exit_func; } - if (some_waits || srv_print_innodb_monitor - || srv_print_innodb_lock_monitor - || srv_print_innodb_tablespace_monitor - || srv_print_innodb_table_monitor) { + if (some_waits) { goto loop; } - /* No one was waiting for a lock and no monitor was active: - suspend this thread */ - - srv_lock_timeout_and_monitor_active = FALSE; + srv_lock_timeout_active = FALSE; #if 0 /* The following synchronisation is disabled, since @@ -2053,7 +2146,7 @@ loop: goto loop; exit_func: - srv_lock_timeout_and_monitor_active = FALSE; + srv_lock_timeout_active = FALSE; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index ea88039f3dd..a7950473a17 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -87,8 +87,8 @@ static os_file_t files[1000]; static mutex_t ios_mutex; static ulint ios; -static ulint n[SRV_MAX_N_IO_THREADS + 5]; -static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5]; +static ulint n[SRV_MAX_N_IO_THREADS + 6]; +static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6]; /* We use this mutex to test the return value of pthread_mutex_trylock on successful locking. HP-UX does NOT return 0, though Linux et al do. */ @@ -1596,15 +1596,20 @@ innobase_start_or_create_for_mysql(void) /* fprintf(stderr, "Max allowed record size %lu\n", page_get_free_space_of_empty() / 2); */ - /* Create the thread which watches the timeouts for lock waits - and prints InnoDB monitor info */ + /* Create the thread which watches the timeouts for lock + waits */ - os_thread_create(&srv_lock_timeout_and_monitor_thread, NULL, + os_thread_create(&srv_lock_timeout_thread, NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS); /* Create the thread which warns of long semaphore waits */ os_thread_create(&srv_error_monitor_thread, NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS); + + /* Create the thread which prints InnoDB monitor info */ + os_thread_create(&srv_monitor_thread, NULL, + thread_ids + 4 + SRV_MAX_N_IO_THREADS); + srv_was_started = TRUE; srv_is_being_started = FALSE; From 877311779d8304bafc3aa24eee2e8af573d7f69f Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 23 Dec 2009 17:44:03 +0400 Subject: [PATCH 189/344] Bug#47649 crash during CALL procedure If first call of the procedure is failed on the open_table stage stmt_arena->state is set to EXECUTED state. On second call(if no errors on open_table stage) it leads to use of worng memory arena in find_field_in_view() function as thd->stmt_arena->is_stmt_prepare_or_first_sp_execute() returns FALSE for EXECUTED state. The item is created not in its own arena and it leads to crash on further calls of the procedure. The fix: change state of arena only if no errors on open_table stage happens. mysql-test/r/sp.result: test result mysql-test/t/sp.test: test case sql/sp_head.cc: If first call of the procedure is failed on the open_table stage stmt_arena->state is set to EXECUTED state. On second call(if no errors on open_table stage) it leads to use of worng memory arena in find_field_in_view() function as thd->stmt_arena->is_stmt_prepare_or_first_sp_execute() returns FALSE for EXECUTED state. The item is created not in its own arena and it leads to crash on further calls of the procedure. The fix: change state of arena only if no errors on open_table stage happens. --- mysql-test/r/sp.result | 16 ++++++++++++++++ mysql-test/t/sp.test | 19 +++++++++++++++++++ sql/sp_head.cc | 11 +++++++++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 83ad7545685..1e6227e7380 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6963,6 +6963,22 @@ CALL p1(); CALL p1(); DROP PROCEDURE p1; DROP TABLE t1; +CREATE TABLE t1 ( f1 integer, primary key (f1)); +CREATE TABLE t2 LIKE t1; +CREATE TEMPORARY TABLE t3 LIKE t1; +CREATE PROCEDURE p1 () BEGIN SELECT f1 FROM t3 AS A WHERE A.f1 IN ( SELECT f1 FROM t3 ) ; +END| +CALL p1; +ERROR HY000: Can't reopen table: 'A' +CREATE VIEW t3 AS SELECT f1 FROM t2 A WHERE A.f1 IN ( SELECT f1 FROM t2 ); +DROP TABLE t3; +CALL p1; +f1 +CALL p1; +f1 +DROP PROCEDURE p1; +DROP TABLE t1, t2; +DROP VIEW t3; # # Bug #46629: Item_in_subselect::val_int(): Assertion `0' # on subquery inside a SP diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 73ba62612b8..5cf050146dd 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -8242,6 +8242,25 @@ while ($tab_count) DROP PROCEDURE p1; DROP TABLE t1; +# +# Bug#47649 crash during CALL procedure +# +CREATE TABLE t1 ( f1 integer, primary key (f1)); +CREATE TABLE t2 LIKE t1; +CREATE TEMPORARY TABLE t3 LIKE t1; +delimiter |; +CREATE PROCEDURE p1 () BEGIN SELECT f1 FROM t3 AS A WHERE A.f1 IN ( SELECT f1 FROM t3 ) ; +END| +delimiter ;| +--error ER_CANT_REOPEN_TABLE +CALL p1; +CREATE VIEW t3 AS SELECT f1 FROM t2 A WHERE A.f1 IN ( SELECT f1 FROM t2 ); +DROP TABLE t3; +CALL p1; +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1, t2; +DROP VIEW t3; --echo # --echo # Bug #46629: Item_in_subselect::val_int(): Assertion `0' diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 51a731138ca..d74e195048f 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2773,8 +2773,15 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, m_lex->mark_as_requiring_prelocking(NULL); } thd->rollback_item_tree_changes(); - /* Update the state of the active arena. */ - thd->stmt_arena->state= Query_arena::EXECUTED; + /* + Update the state of the active arena if no errors on + open_tables stage. + */ + if (!res || !thd->is_error() || + (thd->main_da.sql_errno() != ER_CANT_REOPEN_TABLE && + thd->main_da.sql_errno() != ER_NO_SUCH_TABLE && + thd->main_da.sql_errno() != ER_UPDATE_TABLE_USED)) + thd->stmt_arena->state= Query_arena::EXECUTED; /* Merge here with the saved parent's values From 1f55f5b617d0df650161c58f7d0707abd4ca42e2 Mon Sep 17 00:00:00 2001 From: Satya B Date: Thu, 24 Dec 2009 12:02:29 +0530 Subject: [PATCH 190/344] Bug#49898 - Fix for bug#37408 introduces a linker error the declaration of THR_LOCK_myisam_mmap in mi_static is redundant as it accessible via the extern declaration in include/myisam.h myisam/mi_static.c: Bug#49898 - Fix for bug#37408 introduces a linker error Remove THR_LOCK_myisam_mmap declaration as it is redundant --- myisam/mi_static.c | 1 - 1 file changed, 1 deletion(-) diff --git a/myisam/mi_static.c b/myisam/mi_static.c index b6464e452d7..f75ede48828 100644 --- a/myisam/mi_static.c +++ b/myisam/mi_static.c @@ -41,7 +41,6 @@ my_off_t myisam_max_temp_length= MAX_FILE_SIZE; ulong myisam_bulk_insert_tree_size=8192*1024; ulong myisam_data_pointer_size=4; ulonglong myisam_mmap_size= SIZE_T_MAX, myisam_mmap_used= 0; -pthread_mutex_t THR_LOCK_myisam_mmap; static int always_valid(const char *filename __attribute__((unused))) { From a21a0b47ca46212a528c4402e4b473fe51437422 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 18 Dec 2009 14:00:30 +0200 Subject: [PATCH 191/344] Bug #31145: ALTER TABLE DROP COLUMN, ADD COLUMN crashes (linux) or freezes (win) the server The check for equality was assuming the field object is always created. If it's not it was de-referencing a NULL pointer. Fixed to use the data in the create object instead. --- mysql-test/r/alter_table.result | 7 +++++++ mysql-test/t/alter_table.test | 12 ++++++++++++ sql/field.cc | 3 +-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 06f4e7fbe8a..004e2031fb1 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -1338,4 +1338,11 @@ ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL; affected rows: 0 info: Records: 0 Duplicates: 0 Warnings: 0 DROP TABLE t1; +# +# Bug #31145: ALTER TABLE DROP COLUMN, ADD COLUMN crashes (linux) +# or freezes (win) the server +# +CREATE TABLE t1 (a TEXT, id INT, b INT); +ALTER TABLE t1 DROP COLUMN a, ADD COLUMN c TEXT FIRST; +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 5534aa0a234..4989a6c380c 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -1061,4 +1061,16 @@ ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL; --disable_info DROP TABLE t1; + +--echo # +--echo # Bug #31145: ALTER TABLE DROP COLUMN, ADD COLUMN crashes (linux) +--echo # or freezes (win) the server +--echo # + +CREATE TABLE t1 (a TEXT, id INT, b INT); +ALTER TABLE t1 DROP COLUMN a, ADD COLUMN c TEXT FIRST; + +DROP TABLE t1; + + --echo End of 5.1 tests diff --git a/sql/field.cc b/sql/field.cc index 01ccc338782..d8db3fdbae4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8282,8 +8282,7 @@ uint Field_blob::is_equal(Create_field *new_field) return ((new_field->sql_type == get_blob_type_from_length(max_data_length())) && new_field->charset == field_charset && - ((Field_blob *)new_field->field)->max_data_length() == - max_data_length()); + new_field->pack_length == pack_length()); } From 25be2b28d180e34afb8579311e431a6772f40809 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 18 Dec 2009 17:14:09 -0200 Subject: [PATCH 192/344] Bug#48983: Bad strmake calls (length one too long) MySQL 5.1 specific fixes. --- server-tools/instance-manager/instance_map.cc | 4 ++-- server-tools/instance-manager/options.cc | 4 ++-- server-tools/instance-manager/user_map.cc | 2 +- sql/sql_plugin.cc | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc index b137370b50a..a923c186b5d 100644 --- a/server-tools/instance-manager/instance_map.cc +++ b/server-tools/instance-manager/instance_map.cc @@ -117,13 +117,13 @@ static void parse_option(const char *option_str, while (*ptr == '-') ++ptr; - strmake(option_name_buf, ptr, MAX_OPTION_LEN + 1); + strmake(option_name_buf, ptr, MAX_OPTION_LEN); eq_pos= strchr(ptr, '='); if (eq_pos) { option_name_buf[eq_pos - ptr]= 0; - strmake(option_value_buf, eq_pos + 1, MAX_OPTION_LEN + 1); + strmake(option_value_buf, eq_pos + 1, MAX_OPTION_LEN); } else { diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc index ebca593bb03..6e401bf3ffe 100644 --- a/server-tools/instance-manager/options.cc +++ b/server-tools/instance-manager/options.cc @@ -533,10 +533,10 @@ static int setup_windows_defaults() return 1; } - strmake(base_name, base_name_ptr, FN_REFLEN); + strmake(base_name, base_name_ptr, FN_REFLEN - 1); *base_name_ptr= 0; - strmake(im_name, base_name, FN_REFLEN); + strmake(im_name, base_name, FN_REFLEN - 1); ptr= strrchr(im_name, '.'); if (!ptr) diff --git a/server-tools/instance-manager/user_map.cc b/server-tools/instance-manager/user_map.cc index 49c35c16ca9..85e3f4a2cac 100644 --- a/server-tools/instance-manager/user_map.cc +++ b/server-tools/instance-manager/user_map.cc @@ -25,7 +25,7 @@ User::User(const LEX_STRING *user_name_arg, const char *password) { user_length= (uint8) (strmake(user, user_name_arg->str, - USERNAME_LENGTH + 1) - user); + USERNAME_LENGTH) - user); set_password(password); } diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index bafc601d142..9e35e392d2a 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -2084,7 +2084,7 @@ static int check_func_set(THD *thd, struct st_mysql_sys_var *var, &error, &error_len, ¬_used); if (error_len) { - strmake(buff, error, min(sizeof(buff), error_len)); + strmake(buff, error, min(sizeof(buff) - 1, error_len)); strvalue= buff; goto err; } From b66b3c1635dbda369b1466c7c7ff6103ae09ae66 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 18 Dec 2009 18:32:55 -0200 Subject: [PATCH 193/344] Bug#30331: Table_locks_waited shows inaccurate values Post-merge fix: wait for statement result before disconnecting. Otherwise, the statement might affect unrelated tests. mysql-test/t/lock_multi.test: Reap statement status. --- mysql-test/t/lock_multi.test | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 47b5aa0292b..4df1a0f3478 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -626,9 +626,11 @@ let $wait_condition= --source include/wait_condition.inc let $tlwb= `show status like 'Table_locks_waited'`; unlock tables; +connection waiter; +--reap +connection default; drop table t1; disconnect waiter; -connection default; --disable_query_log eval SET @tlwa= SUBSTRING_INDEX('$tlwa', ' ', -1); eval SET @tlwb= SUBSTRING_INDEX('$tlwb', ' ', -1); From 00e6c3a89e1665c00b6553be28cf689996d6c58a Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Sun, 20 Dec 2009 19:02:15 +0100 Subject: [PATCH 194/344] Bug#43397 mysql headers redefine pthread_mutex_init unnecessarily Changing an instance of the define that was missed in the original commit due to the fact that it was misspelled. --- include/config-win.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config-win.h b/include/config-win.h index af4915440b1..da9b1fc00c3 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -160,7 +160,7 @@ typedef uint rf_SetTimer; #define isnan(X) _isnan(X) #define finite(X) _finite(X) -#ifndef UNDEF_THREAD_HACK +#ifndef MYSQL_CLIENT_NO_THREADS #define THREAD #endif #define VOID_SIGHANDLER From 27aba1b56914694ed8e5615f67dc397680842341 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Mon, 21 Dec 2009 14:14:45 +0800 Subject: [PATCH 195/344] Bug#47638 The rpl_killed_ddl test fails on Windows When the $diff_statement variable for diff_master_slave.inc was put in multiple lines, the rear part of the statement would be missing when being executed on Windows systems. Fixed the problem by always putting the value for $diff_statement in one line. mysql-test/suite/rpl/t/rpl_killed_ddl.test: putting the statement for $diff_statement variable in one line. --- mysql-test/suite/rpl/t/rpl_killed_ddl.test | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_killed_ddl.test b/mysql-test/suite/rpl/t/rpl_killed_ddl.test index 0f2fe5b60fb..61b882efcf3 100644 --- a/mysql-test/suite/rpl/t/rpl_killed_ddl.test +++ b/mysql-test/suite/rpl/t/rpl_killed_ddl.test @@ -158,8 +158,7 @@ source include/kill_query_and_diff_master_slave.inc; ######## EVENT ######## -let $diff_statement= SELECT event_name, event_body, execute_at - FROM information_schema.events where event_name like 'e%'; +let $diff_statement= SELECT event_name, event_body, execute_at FROM information_schema.events where event_name like 'e%'; send CREATE EVENT e2 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY From 007d77afb9ea5fd7b7a369114f8963ab147fd2c5 Mon Sep 17 00:00:00 2001 From: Serge Kozlov Date: Mon, 21 Dec 2009 14:40:08 +0300 Subject: [PATCH 196/344] Bug#8693, Bug#45521. --- mysql-test/t/disabled.def | 2 -- 1 file changed, 2 deletions(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 062667c249e..61e1226c8e3 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -16,11 +16,9 @@ im_daemon_life_cycle : Bug#20294: Instance manager tests fail randomly im_options_set : Bug#20294: Instance manager tests fail randomly im_options_unset : Bug#20294: Instance manager tests fail randomly im_utils : Bug#20294: Instance manager tests fail randomly -rpl_log_pos : Bug#8693 Test 'rpl_log_pos' fails sometimes kill : Bug#29149 Test "kill" fails on Windows ps_7ndb : Bug#38315 "Cluster Failure" in ps_7ndb strict_autoinc_5ndb : Bug#35148 "Error '4009 Cluster Failure' in various tests on various platforms" -rpl_slave_skip : Bug#45521: rpl_slave_skip fails in pb2 loaddata_autocom_ndb : Bug#35148: Error '4009 Cluster Failure' in various tests on various platforms ndb_autodiscover3 : Bug#35148: Error '4009 Cluster Failure' in various tests on various platforms ndb_autodiscover : Bug#45972: ndb.ndb_autodiscover fails occasionally with pb2 From b7f11d10685e8254475cac208d5adb9420fb5075 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Dec 2009 17:26:36 +0100 Subject: [PATCH 197/344] Don't include the `innodb' suite in the list of default test suites. This suite is for the innodb plugin, which we do not use in MariaDB (we instead have XtraDB as default storage engine, which includes the innodb plugin). We have included the same tests in the main suite, so no point in running them twice (and most of them are disabled anyway due to the absense of the innodb plugin). --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 3ef111273a0..428557e6714 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -126,7 +126,7 @@ my $path_config_file; # The generated config file, var/my.cnf # executables will be used by the test suite. our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; -my $DEFAULT_SUITES= "main,binlog,federated,rpl,innodb,maria,parts"; +my $DEFAULT_SUITES= "main,binlog,federated,rpl,maria,parts"; my $opt_suites; our $opt_verbose= 0; # Verbose output, enable with --verbose From 7344b58c32c07df496c208dad5c1e11c304e8aac Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 22 Dec 2009 10:39:29 +0400 Subject: [PATCH 198/344] Fix for bug#49570: Assertion failed: !(order->used & map) on re-execution of prepared statement Problem: some (see eq_ref_table()) ORDER BY/GROUP BY optimization is called before each PS execution. However, we don't properly initialize its stucture every time before the call. Fix: properly initialize the sturture used. mysql-test/r/ps.result: Fix for bug#49570: Assertion failed: !(order->used & map) on re-execution of prepared statement - test result. mysql-test/t/ps.test: Fix for bug#49570: Assertion failed: !(order->used & map) on re-execution of prepared statement - test case. sql/sql_select.cc: Fix for bug#49570: Assertion failed: !(order->used & map) on re-execution of prepared statement - set order->used to 0 before each eq_ref_table() call, as the function relies on that. --- mysql-test/r/ps.result | 22 ++++++++++++++++++++++ mysql-test/t/ps.test | 16 ++++++++++++++++ sql/sql_select.cc | 1 + 3 files changed, 39 insertions(+) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 8a19b9b17e1..6e017ec7253 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1916,4 +1916,26 @@ execute stmt; deallocate prepare stmt; drop table t1,t2; # +# +# Bug #49570: Assertion failed: !(order->used & map) +# on re-execution of prepared statement +# +CREATE TABLE t1(a INT PRIMARY KEY); +INSERT INTO t1 VALUES(0), (1); +PREPARE stmt FROM +"SELECT 1 FROM t1 JOIN t1 t2 USING(a) GROUP BY t2.a, t1.a"; +EXECUTE stmt; +1 +1 +1 +EXECUTE stmt; +1 +1 +1 +EXECUTE stmt; +1 +1 +1 +DEALLOCATE PREPARE stmt; +DROP TABLE t1; End of 5.0 tests. diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 8f8e943913f..e207b0f154a 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1996,4 +1996,20 @@ deallocate prepare stmt; drop table t1,t2; --echo # + +--echo # +--echo # Bug #49570: Assertion failed: !(order->used & map) +--echo # on re-execution of prepared statement +--echo # +CREATE TABLE t1(a INT PRIMARY KEY); +INSERT INTO t1 VALUES(0), (1); +PREPARE stmt FROM + "SELECT 1 FROM t1 JOIN t1 t2 USING(a) GROUP BY t2.a, t1.a"; +EXECUTE stmt; +EXECUTE stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + + --echo End of 5.0 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d22a23a10d4..d8ec5eff5c1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6777,6 +6777,7 @@ static void update_depend_map(JOIN *join, ORDER *order) table_map depend_map; order->item[0]->update_used_tables(); order->depend_map=depend_map=order->item[0]->used_tables(); + order->used= 0; // Not item_sum(), RAND() and no reference to table outside of sub select if (!(order->depend_map & (OUTER_REF_TABLE_BIT | RAND_TABLE_BIT)) && !order->item[0]->with_sum_func) From 081bcb3b8bc861bc5609a4ce92c8eb3528ffc078 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Tue, 22 Dec 2009 13:52:23 +0400 Subject: [PATCH 199/344] Bug#47371 reference by same column name At the end of execution top level join execution we cleanup this join with true argument. It leads to underlying join cleanup(subquery) with true argument too and to tmp_table_param->field array cleanup which is required later. The problem is that Item_func_set_user_var does not set result_filed which leads to unnecessary repeated excution of subquery on final stage. The fix is to set result_field for Item_func_set_user_var. mysql-test/r/count_distinct.result: test result mysql-test/r/user_var.result: test result mysql-test/t/count_distinct.test: test case mysql-test/t/user_var.test: test case sql/item_func.cc: At the end of execution top level join execution we cleanup this join with true argument. It leads to underlying join cleanup(subquery) with true argument too and to tmp_table_param->field array cleanup which is required later. The problem is that Item_func_set_user_var does not set result_filed which leads to unnecessary repeated excution of subquery on final stage. The fix is to set result_field for Item_func_set_user_var. --- mysql-test/r/count_distinct.result | 20 ++++++++++++++++++++ mysql-test/r/user_var.result | 15 +++++++++++++++ mysql-test/t/count_distinct.test | 19 +++++++++++++++++++ mysql-test/t/user_var.test | 20 ++++++++++++++++++++ sql/item_func.cc | 2 +- 5 files changed, 75 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/count_distinct.result b/mysql-test/r/count_distinct.result index a21748359b9..804bc1f4788 100644 --- a/mysql-test/r/count_distinct.result +++ b/mysql-test/r/count_distinct.result @@ -40,6 +40,26 @@ select t2.isbn,city,t1.libname,count(distinct t1.libname) as a from t3 left join isbn city libname a 007 Berkeley Berkeley Public1 2 000 New York New York Public Libra 2 +select t2.isbn,city,@bar:=t1.libname,count(distinct t1.libname) as a +from t3 left join t1 on t3.libname=t1.libname left join t2 +on t3.isbn=t2.isbn group by city having count(distinct +t1.libname) > 1; +isbn city @bar:=t1.libname a +007 Berkeley Berkeley Public1 2 +000 New York New York Public Libra 2 +SELECT @bar; +@bar +Berkeley Public2 +select t2.isbn,city,concat(@bar:=t1.libname),count(distinct t1.libname) as a +from t3 left join t1 on t3.libname=t1.libname left join t2 +on t3.isbn=t2.isbn group by city having count(distinct +t1.libname) > 1; +isbn city concat(@bar:=t1.libname) a +007 Berkeley Berkeley Public1 2 +000 New York New York Public Libra 2 +SELECT @bar; +@bar +Berkeley Public2 drop table t1, t2, t3; create table t1 (f1 int); insert into t1 values (1); diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index bfa95d8f92b..8236dbe94ac 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -363,4 +363,19 @@ SELECT a, b FROM t1 WHERE a=2 AND b=3 GROUP BY a, b; a b 2 3 DROP TABLE t1; +CREATE TABLE t1 (f1 int(11) default NULL, f2 int(11) default NULL); +CREATE TABLE t2 (f1 int(11) default NULL, f2 int(11) default NULL, foo int(11)); +CREATE TABLE t3 (f1 int(11) default NULL, f2 int(11) default NULL); +INSERT INTO t1 VALUES(10, 10); +INSERT INTO t1 VALUES(10, 10); +INSERT INTO t2 VALUES(10, 10, 10); +INSERT INTO t2 VALUES(10, 10, 10); +INSERT INTO t3 VALUES(10, 10); +INSERT INTO t3 VALUES(10, 10); +SELECT MIN(t2.f1), +@bar:= (SELECT MIN(t3.f2) FROM t3 WHERE t3.f2 > foo) +FROM t1,t2 WHERE t1.f1 = t2.f1 ORDER BY t2.f1; +MIN(t2.f1) @bar:= (SELECT MIN(t3.f2) FROM t3 WHERE t3.f2 > foo) +10 NULL +DROP TABLE t1, t2, t3; End of 5.0 tests diff --git a/mysql-test/t/count_distinct.test b/mysql-test/t/count_distinct.test index e63bdabdb95..d0996689aeb 100644 --- a/mysql-test/t/count_distinct.test +++ b/mysql-test/t/count_distinct.test @@ -35,6 +35,25 @@ insert into t1 values ('NYC Lib','New York'); select t2.isbn,city,t1.libname,count(t1.libname) as a from t3 left join t1 on t3.libname=t1.libname left join t2 on t3.isbn=t2.isbn group by city,t1.libname; select t2.isbn,city,t1.libname,count(distinct t1.libname) as a from t3 left join t1 on t3.libname=t1.libname left join t2 on t3.isbn=t2.isbn group by city having count(distinct t1.libname) > 1; select t2.isbn,city,t1.libname,count(distinct t1.libname) as a from t3 left join t1 on t3.libname=t1.libname left join t2 on t3.isbn=t2.isbn group by city having count(distinct concat(t1.libname,'a')) > 1; + +select t2.isbn,city,@bar:=t1.libname,count(distinct t1.libname) as a + from t3 left join t1 on t3.libname=t1.libname left join t2 + on t3.isbn=t2.isbn group by city having count(distinct + t1.libname) > 1; +# +# Wrong result, see bug#49872 +# +SELECT @bar; + +select t2.isbn,city,concat(@bar:=t1.libname),count(distinct t1.libname) as a + from t3 left join t1 on t3.libname=t1.libname left join t2 + on t3.isbn=t2.isbn group by city having count(distinct + t1.libname) > 1; +# +# Wrong result, see bug#49872 +# +SELECT @bar; + drop table t1, t2, t3; # diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index d39b49a0e87..59a5238b35b 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -248,4 +248,24 @@ SELECT @a, @b; SELECT a, b FROM t1 WHERE a=2 AND b=3 GROUP BY a, b; DROP TABLE t1; +# +# Bug#47371: reference by same column name +# +CREATE TABLE t1 (f1 int(11) default NULL, f2 int(11) default NULL); +CREATE TABLE t2 (f1 int(11) default NULL, f2 int(11) default NULL, foo int(11)); +CREATE TABLE t3 (f1 int(11) default NULL, f2 int(11) default NULL); + +INSERT INTO t1 VALUES(10, 10); +INSERT INTO t1 VALUES(10, 10); +INSERT INTO t2 VALUES(10, 10, 10); +INSERT INTO t2 VALUES(10, 10, 10); +INSERT INTO t3 VALUES(10, 10); +INSERT INTO t3 VALUES(10, 10); + +SELECT MIN(t2.f1), +@bar:= (SELECT MIN(t3.f2) FROM t3 WHERE t3.f2 > foo) +FROM t1,t2 WHERE t1.f1 = t2.f1 ORDER BY t2.f1; + +DROP TABLE t1, t2, t3; + --echo End of 5.0 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index d6f315fda50..cb0d6bdbe5f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -610,7 +610,7 @@ void Item_func::signal_divide_by_null() Item *Item_func::get_tmp_table_item(THD *thd) { - if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC) + if (!with_sum_func && !const_item()) return new Item_field(result_field); return copy_or_same(thd); } From 8f0f1d0ddb73283f60adb696f5b46b376aed327e Mon Sep 17 00:00:00 2001 From: Satya B Date: Tue, 22 Dec 2009 18:33:39 +0530 Subject: [PATCH 200/344] Removing rpl.rpl_trigger from experimental list as it is Fixed by BUG#46656 --- mysql-test/collections/default.experimental | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index 2c2e9cab626..3894f2a4368 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -20,7 +20,6 @@ ndb.* # joro : NDB tests marked as experiment rpl.rpl_get_master_version_and_clock* # Bug #49191 2009-12-01 Daogang rpl_get_master_version_and_clock failed on PB2: COM_REGISTER_SLAVE failed rpl.rpl_innodb_bug28430* @solaris # Bug#46029 -rpl.rpl_trigger* # Bug#47810 2009-10-04 joro rpl.rpl_trigger.test fails with valgrind errors with the innodb plugin rpl_ndb.* # joro : NDB tests marked as experimental as agreed with bochklin rpl_ndb.rpl_ndb_log # Bug#38998 From 2d8869d248188c1bf393fc87d9f0e31adf691c2d Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 22 Dec 2009 17:52:15 +0200 Subject: [PATCH 201/344] Bug #49734: Crash on EXPLAIN EXTENDED UNION ... ORDER BY Several problems fixed : 1. Non constant expressions in UNION ... ORDER BY were not correctly cleaned up in st_select_lex_unit::cleanup() causing crashes in EXPLAIN EXTENDED because of fields quoted by these expressions pointing to the already freed temporary table used to calculate the UNION. Fixed by correctly cleaning up expressions of any depth. 2. Subqueries in the order by part of UNION ... ORDER BY ... caused a crash in EXPLAIN EXTENDED because of a transformation attempt made during EXPLAIN EXTENDED execution. Fixed by not doing the transformation when in EXPLAIN. 3. Fulltext functions caused crash when in the ORDER BY part of an un-parenthesized UNION that gets "promoted" to be valid for the whole union, e.g. SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY MATCHES (a) AGAINST ('abc' IN BOOLEAN MODE). This is a case that demonstrates a more general problem of parts of the query being moved to another level. When doing such transformation late in the optimization run when most of the flags about the contents of the query are already aggregated it's possible to "split" the flags so that they correctly reflect the new queries after the transformation. In specific the ST_SELECT_LEX::ftfunc_list is holding all the free text function for all the parts of the second SELECT in the UNION and we don't know what part of that is in the ORDER BY that we're to move to the UNION level and what part is about the other parts of the second SELECT. Fixed by throwing and error when such statements are about to be processed by adding a check for the presence of MATCH() inside the ORDER BY clause that's going to get promoted to UNION. To workaround this new limitation one must parenthesize the UNION SELECTs and provide a real global ORDER BY for the UNION outside of the parenthesis. --- mysql-test/r/fulltext_order_by.result | 6 +-- mysql-test/r/union.result | 63 +++++++++++++++++++++++++++ mysql-test/t/fulltext_order_by.test | 5 ++- mysql-test/t/union.test | 53 ++++++++++++++++++++++ sql/item.h | 17 ++++++++ sql/item_func.h | 5 +++ sql/sql_select.cc | 2 +- sql/sql_union.cc | 31 ++++++++++++- 8 files changed, 175 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/fulltext_order_by.result b/mysql-test/r/fulltext_order_by.result index bc466b5aba7..bd3e79ec5c2 100644 --- a/mysql-test/r/fulltext_order_by.result +++ b/mysql-test/r/fulltext_order_by.result @@ -126,7 +126,7 @@ group by a.text, b.id, b.betreff order by match(b.betreff) against ('+abc' in boolean mode) desc; -ERROR 42S22: Unknown column 'b.betreff' in 'order clause' +ERROR 42000: Incorrect usage/placement of 'MATCH()' select a.text, b.id, b.betreff from t2 a inner join t3 b on a.id = b.forum inner join @@ -142,7 +142,7 @@ where match(c.beitrag) against ('+abc' in boolean mode) order by match(b.betreff) against ('+abc' in boolean mode) desc; -ERROR 42S22: Unknown column 'b.betreff' in 'order clause' +ERROR 42000: Incorrect usage/placement of 'MATCH()' select a.text, b.id, b.betreff from t2 a inner join t3 b on a.id = b.forum inner join @@ -158,7 +158,7 @@ where match(c.beitrag) against ('+abc' in boolean mode) order by match(betreff) against ('+abc' in boolean mode) desc; -text id betreff +ERROR 42000: Incorrect usage/placement of 'MATCH()' (select b.id, b.betreff from t3 b) union (select b.id, b.betreff from t3 b) order by match(betreff) against ('+abc' in boolean mode) desc; diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 44a3812725a..dce32d2ced4 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1588,3 +1588,66 @@ Warnings: Note 1003 select '0' AS `a` from `test`.`t1` union select '0' AS `a` from `test`.`t1` order by `a` DROP TABLE t1; End of 5.0 tests +# +# Bug #49734: Crash on EXPLAIN EXTENDED UNION ... ORDER BY +# +# +CREATE TABLE t1 (a VARCHAR(10), FULLTEXT KEY a (a)); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (1),(2); +# Should not crash +EXPLAIN EXTENDED +SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY a + 12; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 +2 UNION t1 ALL NULL NULL NULL NULL 2 100.00 +NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL Using filesort +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by (`a` + 12) +# Should not crash +SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY a + 12; +a +1 +2 +# Should not crash +EXPLAIN EXTENDED +SELECT * FROM t1 UNION SELECT * FROM t1 +ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE); +ERROR 42000: Incorrect usage/placement of 'MATCH()' +# Should not crash +SELECT * FROM t1 UNION SELECT * FROM t1 +ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE); +ERROR 42000: Incorrect usage/placement of 'MATCH()' +# Should not crash +(SELECT * FROM t1) UNION (SELECT * FROM t1) +ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE); +a +1 +2 +# Should not crash +EXPLAIN EXTENDED +SELECT * FROM t1 UNION SELECT * FROM t1 +ORDER BY (SELECT a FROM t2 WHERE b = 12); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 +2 UNION t1 ALL NULL NULL NULL NULL 2 100.00 +3 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where +NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL Using filesort +Warnings: +Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2 +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by (select `test`.`t1`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`b` = 12)) +# Should not crash +SELECT * FROM t1 UNION SELECT * FROM t1 +ORDER BY (SELECT a FROM t2 WHERE b = 12); +a +1 +2 +# Should not crash +SELECT * FROM t2 UNION SELECT * FROM t2 +ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); +b +1 +2 +DROP TABLE t1,t2; +End of 5.1 tests diff --git a/mysql-test/t/fulltext_order_by.test b/mysql-test/t/fulltext_order_by.test index 074aefbf943..814cd4a5954 100644 --- a/mysql-test/t/fulltext_order_by.test +++ b/mysql-test/t/fulltext_order_by.test @@ -80,7 +80,7 @@ CREATE TABLE t3 ( FULLTEXT KEY betreff (betreff) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=996 ; ---error 1054 +--error ER_CANT_USE_OPTION_HERE select a.text, b.id, b.betreff from t2 a inner join t3 b on a.id = b.forum inner join @@ -100,7 +100,7 @@ group by order by match(b.betreff) against ('+abc' in boolean mode) desc; ---error 1054 +--error ER_CANT_USE_OPTION_HERE select a.text, b.id, b.betreff from t2 a inner join t3 b on a.id = b.forum inner join @@ -117,6 +117,7 @@ where order by match(b.betreff) against ('+abc' in boolean mode) desc; +--error ER_CANT_USE_OPTION_HERE select a.text, b.id, b.betreff from t2 a inner join t3 b on a.id = b.forum inner join diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index ec169838d59..91fc9546bbe 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -1102,3 +1102,56 @@ DROP TABLE t1; --echo End of 5.0 tests + + +--echo # +--echo # Bug #49734: Crash on EXPLAIN EXTENDED UNION ... ORDER BY +--echo # +--echo # + +CREATE TABLE t1 (a VARCHAR(10), FULLTEXT KEY a (a)); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (1),(2); + +--echo # Should not crash +EXPLAIN EXTENDED +SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY a + 12; + +--echo # Should not crash +SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY a + 12; + + +--echo # Should not crash +--error ER_CANT_USE_OPTION_HERE +EXPLAIN EXTENDED +SELECT * FROM t1 UNION SELECT * FROM t1 + ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE); + +--echo # Should not crash +--error ER_CANT_USE_OPTION_HERE +SELECT * FROM t1 UNION SELECT * FROM t1 + ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE); + +--echo # Should not crash +(SELECT * FROM t1) UNION (SELECT * FROM t1) + ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE); + + +--echo # Should not crash +EXPLAIN EXTENDED +SELECT * FROM t1 UNION SELECT * FROM t1 + ORDER BY (SELECT a FROM t2 WHERE b = 12); + +--echo # Should not crash +SELECT * FROM t1 UNION SELECT * FROM t1 + ORDER BY (SELECT a FROM t2 WHERE b = 12); + +--echo # Should not crash +SELECT * FROM t2 UNION SELECT * FROM t2 + ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); + +DROP TABLE t1,t2; + + +--echo End of 5.1 tests diff --git a/sql/item.h b/sql/item.h index b97808ac87f..8f0e5874f3f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -967,6 +967,23 @@ public: return FALSE; } + /** + Find a function of a given type + + @param arg the function type to search (enum Item_func::Functype) + @return + @retval TRUE the function type we're searching for is found + @retval FALSE the function type wasn't found + + @description + This function can be used (together with Item::walk()) to find functions + in an item tree fragment. + */ + virtual bool find_function_processor (uchar *arg) + { + return FALSE; + } + /* For SP local variable returns pointer to Item representing its current value and pointer to current Item otherwise. diff --git a/sql/item_func.h b/sql/item_func.h index 259316b0c41..71168c64e4b 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -212,6 +212,11 @@ public: { return has_timestamp_args(); } + + virtual bool find_function_processor (uchar *arg) + { + return functype() == *(Functype *) arg; + } }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6383fe63012..d50bb888850 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -519,7 +519,7 @@ JOIN::prepare(Item ***rref_pointer_array, thd->lex->allow_sum_func= save_allow_sum_func; } - if (!thd->lex->view_prepare_mode) + if (!thd->lex->view_prepare_mode && !(select_options & SELECT_DESCRIBE)) { Item_subselect *subselect; /* Is it subselect? */ diff --git a/sql/sql_union.cc b/sql/sql_union.cc index cbf94ad7181..1760670f9c8 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -335,6 +335,35 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } } + /* + Disable the usage of fulltext searches in the last union branch. + This is a temporary 5.x limitation because of the way the fulltext + search functions are handled by the optimizer. + This is manifestation of the more general problems of "taking away" + parts of a SELECT statement post-fix_fields(). This is generally not + doable since various flags are collected in various places (e.g. + SELECT_LEX) that carry information about the presence of certain + expressions or constructs in the parts of the query. + When part of the query is taken away it's not clear how to "divide" + the meaning of these accumulated flags and what to carry over to the + recipient query (SELECT_LEX). + */ + if (global_parameters->ftfunc_list->elements && + global_parameters->order_list.elements && + global_parameters != fake_select_lex) + { + ORDER *ord; + Item_func::Functype ft= Item_func::FT_FUNC; + for (ord= (ORDER*)global_parameters->order_list.first; ord; ord= ord->next) + if ((*ord->item)->walk (&Item::find_function_processor, FALSE, + (uchar *) &ft)) + { + my_error (ER_CANT_USE_OPTION_HERE, MYF(0), "MATCH()"); + goto err; + } + } + + create_options= (first_sl->options | thd_arg->options | TMP_TABLE_ALL_COLUMNS); /* @@ -669,7 +698,7 @@ bool st_select_lex_unit::cleanup() { ORDER *ord; for (ord= (ORDER*)global_parameters->order_list.first; ord; ord= ord->next) - (*ord->item)->cleanup(); + (*ord->item)->walk (&Item::cleanup_processor, 0, 0); } } From 28e64daf2ddccbeb754d4204219463eddd44012f Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Tue, 22 Dec 2009 18:59:37 +0100 Subject: [PATCH 202/344] Bug#49742: Partition Pruning not working correctly for RANGE Problem was when calculating the range of partitions for pruning. Solution was to get the calculation correct. I also simplified it a bit for easier understanding. mysql-test/r/partition_pruning.result: Bug#49742: Partition Pruning not working correctly for RANGE Added results. mysql-test/t/partition_pruning.test: Bug#49742: Partition Pruning not working correctly for RANGE Added tests to prevent regressions. sql/sql_partition.cc: Bug#49742: Partition Pruning not working correctly for RANGE Simplified calculation for partition id for ranges. Easier to get right and understand. Added comments. --- mysql-test/r/partition_pruning.result | 612 +++++++++++++++++++++++++- mysql-test/t/partition_pruning.test | 160 +++++++ sql/sql_partition.cc | 47 +- 3 files changed, 793 insertions(+), 26 deletions(-) diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index 3128c57b2cf..cf0474a3f6b 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -1,4 +1,614 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +# +# Bug#49742: Partition Pruning not working correctly for RANGE +# +CREATE TABLE t1 (a INT PRIMARY KEY) +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (1), +PARTITION p1 VALUES LESS THAN (2), +PARTITION p2 VALUES LESS THAN (3), +PARTITION p3 VALUES LESS THAN (4), +PARTITION p4 VALUES LESS THAN (5), +PARTITION p5 VALUES LESS THAN (6), +PARTITION max VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (-1),(0),(1),(2),(3),(4),(5),(6),(7),(8); +SELECT * FROM t1 WHERE a < 1; +a +-1 +0 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index +SELECT * FROM t1 WHERE a < 2; +a +-1 +0 +1 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1 index PRIMARY PRIMARY 4 NULL 3 Using where; Using index +SELECT * FROM t1 WHERE a < 3; +a +-1 +0 +1 +2 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2 index PRIMARY PRIMARY 4 NULL 4 Using where; Using index +SELECT * FROM t1 WHERE a < 4; +a +-1 +0 +1 +2 +3 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3 index PRIMARY PRIMARY 4 NULL 5 Using where; Using index +SELECT * FROM t1 WHERE a < 5; +a +-1 +0 +1 +2 +3 +4 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4 index PRIMARY PRIMARY 4 NULL 6 Using where; Using index +SELECT * FROM t1 WHERE a < 6; +a +-1 +0 +1 +2 +3 +4 +5 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4,p5 index PRIMARY PRIMARY 4 NULL 7 Using where; Using index +SELECT * FROM t1 WHERE a < 7; +a +-1 +0 +1 +2 +3 +4 +5 +6 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 7; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4,p5,max range PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a <= 1; +a +-1 +0 +1 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1 index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a <= 2; +a +-1 +0 +1 +2 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2 index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a <= 3; +a +-1 +0 +1 +2 +3 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3 index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a <= 4; +a +-1 +0 +1 +2 +3 +4 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4 index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a <= 5; +a +-1 +0 +1 +2 +3 +4 +5 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4,p5 index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a <= 6; +a +-1 +0 +1 +2 +3 +4 +5 +6 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4,p5,max range PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a <= 7; +a +-1 +0 +1 +2 +3 +4 +5 +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 7; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4,p5,max range PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a = 1; +a +1 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1 system PRIMARY NULL NULL NULL 1 +SELECT * FROM t1 WHERE a = 2; +a +2 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p2 system PRIMARY NULL NULL NULL 1 +SELECT * FROM t1 WHERE a = 3; +a +3 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p3 system PRIMARY NULL NULL NULL 1 +SELECT * FROM t1 WHERE a = 4; +a +4 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p4 system PRIMARY NULL NULL NULL 1 +SELECT * FROM t1 WHERE a = 5; +a +5 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p5 system PRIMARY NULL NULL NULL 1 +SELECT * FROM t1 WHERE a = 6; +a +6 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max const PRIMARY PRIMARY 4 const 1 Using index +SELECT * FROM t1 WHERE a = 7; +a +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 7; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max const PRIMARY PRIMARY 4 const 1 Using index +SELECT * FROM t1 WHERE a >= 1; +a +1 +2 +3 +4 +5 +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1,p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a >= 2; +a +2 +3 +4 +5 +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a >= 3; +a +3 +4 +5 +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a >= 4; +a +4 +5 +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a >= 5; +a +5 +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a >= 6; +a +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a >= 7; +a +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 7; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max range PRIMARY PRIMARY 4 NULL 2 Using where; Using index +SELECT * FROM t1 WHERE a > 1; +a +2 +3 +4 +5 +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a > 2; +a +3 +4 +5 +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a > 3; +a +4 +5 +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a > 4; +a +5 +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a > 5; +a +6 +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index +SELECT * FROM t1 WHERE a > 6; +a +7 +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max range PRIMARY PRIMARY 4 NULL 2 Using where; Using index +SELECT * FROM t1 WHERE a > 7; +a +8 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 7; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max range PRIMARY PRIMARY 4 NULL 2 Using where; Using index +DROP TABLE t1; +CREATE TABLE t1 (a INT PRIMARY KEY) +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (1), +PARTITION p1 VALUES LESS THAN (2), +PARTITION p2 VALUES LESS THAN (3), +PARTITION p3 VALUES LESS THAN (4), +PARTITION p4 VALUES LESS THAN (5), +PARTITION max VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (-1),(0),(1),(2),(3),(4),(5),(6),(7); +SELECT * FROM t1 WHERE a < 1; +a +-1 +0 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index +SELECT * FROM t1 WHERE a < 2; +a +-1 +0 +1 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1 index PRIMARY PRIMARY 4 NULL 3 Using where; Using index +SELECT * FROM t1 WHERE a < 3; +a +-1 +0 +1 +2 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2 index PRIMARY PRIMARY 4 NULL 4 Using where; Using index +SELECT * FROM t1 WHERE a < 4; +a +-1 +0 +1 +2 +3 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3 index PRIMARY PRIMARY 4 NULL 5 Using where; Using index +SELECT * FROM t1 WHERE a < 5; +a +-1 +0 +1 +2 +3 +4 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4 index PRIMARY PRIMARY 4 NULL 6 Using where; Using index +SELECT * FROM t1 WHERE a < 6; +a +-1 +0 +1 +2 +3 +4 +5 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4,max range PRIMARY PRIMARY 4 NULL 8 Using where; Using index +SELECT * FROM t1 WHERE a <= 1; +a +-1 +0 +1 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1 index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a <= 2; +a +-1 +0 +1 +2 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2 index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a <= 3; +a +-1 +0 +1 +2 +3 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3 index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a <= 4; +a +-1 +0 +1 +2 +3 +4 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4 index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a <= 5; +a +-1 +0 +1 +2 +3 +4 +5 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4,max range PRIMARY PRIMARY 4 NULL 8 Using where; Using index +SELECT * FROM t1 WHERE a <= 6; +a +-1 +0 +1 +2 +3 +4 +5 +6 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3,p4,max range PRIMARY PRIMARY 4 NULL 8 Using where; Using index +SELECT * FROM t1 WHERE a = 1; +a +1 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1 system PRIMARY NULL NULL NULL 1 +SELECT * FROM t1 WHERE a = 2; +a +2 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p2 system PRIMARY NULL NULL NULL 1 +SELECT * FROM t1 WHERE a = 3; +a +3 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p3 system PRIMARY NULL NULL NULL 1 +SELECT * FROM t1 WHERE a = 4; +a +4 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p4 system PRIMARY NULL NULL NULL 1 +SELECT * FROM t1 WHERE a = 5; +a +5 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max const PRIMARY PRIMARY 4 const 1 Using index +SELECT * FROM t1 WHERE a = 6; +a +6 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max const PRIMARY PRIMARY 4 const 1 Using index +SELECT * FROM t1 WHERE a >= 1; +a +1 +2 +3 +4 +5 +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1,p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a >= 2; +a +2 +3 +4 +5 +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a >= 3; +a +3 +4 +5 +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a >= 4; +a +4 +5 +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a >= 5; +a +5 +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a >= 6; +a +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max range PRIMARY PRIMARY 4 NULL 2 Using where; Using index +SELECT * FROM t1 WHERE a > 1; +a +2 +3 +4 +5 +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a > 2; +a +3 +4 +5 +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a > 3; +a +4 +5 +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a > 4; +a +5 +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index +SELECT * FROM t1 WHERE a > 5; +a +6 +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max range PRIMARY PRIMARY 4 NULL 2 Using where; Using index +SELECT * FROM t1 WHERE a > 6; +a +7 +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 max range PRIMARY PRIMARY 4 NULL 2 Using where; Using index +DROP TABLE t1; # test of RANGE and index CREATE TABLE t1 (a DATE, KEY(a)) PARTITION BY RANGE (TO_DAYS(a)) @@ -1816,7 +2426,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p0,p4 ALL NULL NULL NULL NULL 910 Using where explain partitions select * from t2 where (a > 100 AND a < 600); id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t2 p0,p1,p2,p3 ALL NULL NULL NULL NULL 910 Using where +1 SIMPLE t2 p0,p1,p2 ALL NULL NULL NULL NULL 910 Using where explain partitions select * from t2 where b = 4; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p0,p1,p2,p3,p4 ref b b 5 const 76 Using where diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test index 11e65be45fc..315b8393d93 100644 --- a/mysql-test/t/partition_pruning.test +++ b/mysql-test/t/partition_pruning.test @@ -8,6 +8,166 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; --enable_warnings +--echo # +--echo # Bug#49742: Partition Pruning not working correctly for RANGE +--echo # +CREATE TABLE t1 (a INT PRIMARY KEY) +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (1), +PARTITION p1 VALUES LESS THAN (2), +PARTITION p2 VALUES LESS THAN (3), +PARTITION p3 VALUES LESS THAN (4), +PARTITION p4 VALUES LESS THAN (5), +PARTITION p5 VALUES LESS THAN (6), +PARTITION max VALUES LESS THAN MAXVALUE); + +INSERT INTO t1 VALUES (-1),(0),(1),(2),(3),(4),(5),(6),(7),(8); + +SELECT * FROM t1 WHERE a < 1; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 1; +SELECT * FROM t1 WHERE a < 2; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 2; +SELECT * FROM t1 WHERE a < 3; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 3; +SELECT * FROM t1 WHERE a < 4; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 4; +SELECT * FROM t1 WHERE a < 5; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 5; +SELECT * FROM t1 WHERE a < 6; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 6; +SELECT * FROM t1 WHERE a < 7; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 7; +SELECT * FROM t1 WHERE a <= 1; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 1; +SELECT * FROM t1 WHERE a <= 2; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 2; +SELECT * FROM t1 WHERE a <= 3; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 3; +SELECT * FROM t1 WHERE a <= 4; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 4; +SELECT * FROM t1 WHERE a <= 5; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 5; +SELECT * FROM t1 WHERE a <= 6; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 6; +SELECT * FROM t1 WHERE a <= 7; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 7; +SELECT * FROM t1 WHERE a = 1; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 1; +SELECT * FROM t1 WHERE a = 2; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 2; +SELECT * FROM t1 WHERE a = 3; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 3; +SELECT * FROM t1 WHERE a = 4; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 4; +SELECT * FROM t1 WHERE a = 5; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 5; +SELECT * FROM t1 WHERE a = 6; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 6; +SELECT * FROM t1 WHERE a = 7; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 7; +SELECT * FROM t1 WHERE a >= 1; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 1; +SELECT * FROM t1 WHERE a >= 2; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 2; +SELECT * FROM t1 WHERE a >= 3; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 3; +SELECT * FROM t1 WHERE a >= 4; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 4; +SELECT * FROM t1 WHERE a >= 5; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 5; +SELECT * FROM t1 WHERE a >= 6; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 6; +SELECT * FROM t1 WHERE a >= 7; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 7; +SELECT * FROM t1 WHERE a > 1; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 1; +SELECT * FROM t1 WHERE a > 2; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 2; +SELECT * FROM t1 WHERE a > 3; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 3; +SELECT * FROM t1 WHERE a > 4; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 4; +SELECT * FROM t1 WHERE a > 5; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 5; +SELECT * FROM t1 WHERE a > 6; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 6; +SELECT * FROM t1 WHERE a > 7; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 7; +DROP TABLE t1; + +CREATE TABLE t1 (a INT PRIMARY KEY) +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (1), +PARTITION p1 VALUES LESS THAN (2), +PARTITION p2 VALUES LESS THAN (3), +PARTITION p3 VALUES LESS THAN (4), +PARTITION p4 VALUES LESS THAN (5), +PARTITION max VALUES LESS THAN MAXVALUE); + +INSERT INTO t1 VALUES (-1),(0),(1),(2),(3),(4),(5),(6),(7); + +SELECT * FROM t1 WHERE a < 1; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 1; +SELECT * FROM t1 WHERE a < 2; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 2; +SELECT * FROM t1 WHERE a < 3; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 3; +SELECT * FROM t1 WHERE a < 4; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 4; +SELECT * FROM t1 WHERE a < 5; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 5; +SELECT * FROM t1 WHERE a < 6; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 6; +SELECT * FROM t1 WHERE a <= 1; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 1; +SELECT * FROM t1 WHERE a <= 2; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 2; +SELECT * FROM t1 WHERE a <= 3; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 3; +SELECT * FROM t1 WHERE a <= 4; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 4; +SELECT * FROM t1 WHERE a <= 5; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 5; +SELECT * FROM t1 WHERE a <= 6; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 6; +SELECT * FROM t1 WHERE a = 1; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 1; +SELECT * FROM t1 WHERE a = 2; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 2; +SELECT * FROM t1 WHERE a = 3; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 3; +SELECT * FROM t1 WHERE a = 4; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 4; +SELECT * FROM t1 WHERE a = 5; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 5; +SELECT * FROM t1 WHERE a = 6; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 6; +SELECT * FROM t1 WHERE a >= 1; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 1; +SELECT * FROM t1 WHERE a >= 2; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 2; +SELECT * FROM t1 WHERE a >= 3; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 3; +SELECT * FROM t1 WHERE a >= 4; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 4; +SELECT * FROM t1 WHERE a >= 5; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 5; +SELECT * FROM t1 WHERE a >= 6; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 6; +SELECT * FROM t1 WHERE a > 1; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 1; +SELECT * FROM t1 WHERE a > 2; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 2; +SELECT * FROM t1 WHERE a > 3; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 3; +SELECT * FROM t1 WHERE a > 4; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 4; +SELECT * FROM t1 WHERE a > 5; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 5; +SELECT * FROM t1 WHERE a > 6; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 6; +DROP TABLE t1; + # # Bug#20577: Partitions: use of to_days() function leads to selection failures # diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index e0697f563ea..2f22432c416 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2878,16 +2878,13 @@ int get_partition_id_range(partition_info *part_info, part_func_value-= 0x8000000000000000ULL; while (max_part_id > min_part_id) { - loc_part_id= (max_part_id + min_part_id + 1) >> 1; + loc_part_id= (max_part_id + min_part_id) / 2; if (range_array[loc_part_id] <= part_func_value) min_part_id= loc_part_id + 1; else - max_part_id= loc_part_id - 1; + max_part_id= loc_part_id; } loc_part_id= max_part_id; - if (part_func_value >= range_array[loc_part_id]) - if (loc_part_id != max_partition) - loc_part_id++; *part_id= (uint32)loc_part_id; if (loc_part_id == max_partition && part_func_value >= range_array[loc_part_id] && @@ -2961,6 +2958,7 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool include_endpoint) { longlong *range_array= part_info->range_int_array; + longlong part_end_val; uint max_partition= part_info->no_parts - 1; uint min_part_id= 0, max_part_id= max_partition, loc_part_id; /* Get the partitioning function value for the endpoint */ @@ -2994,46 +2992,45 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, } } - if (unsigned_flag) part_func_value-= 0x8000000000000000ULL; if (left_endpoint && !include_endpoint) part_func_value++; + + /* + Search for the partition containing part_func_value + (including the right endpoint). + */ while (max_part_id > min_part_id) { - loc_part_id= (max_part_id + min_part_id + 1) >> 1; - if (range_array[loc_part_id] <= part_func_value) + loc_part_id= (max_part_id + min_part_id) / 2; + if (range_array[loc_part_id] < part_func_value) min_part_id= loc_part_id + 1; else - max_part_id= loc_part_id - 1; + max_part_id= loc_part_id; } loc_part_id= max_part_id; - if (loc_part_id < max_partition && - part_func_value >= range_array[loc_part_id+1]) - { - loc_part_id++; - } + + /* Adjust for endpoints */ + part_end_val= range_array[loc_part_id]; if (left_endpoint) { - longlong bound= range_array[loc_part_id]; /* In case of PARTITION p VALUES LESS THAN MAXVALUE the maximum value is in the current partition. */ - if (part_func_value > bound || - (part_func_value == bound && - (!part_info->defined_max_value || loc_part_id < max_partition))) + if (part_func_value == part_end_val && + (loc_part_id < max_partition || !part_info->defined_max_value)) loc_part_id++; } else { - if (loc_part_id < max_partition) - { - if (part_func_value == range_array[loc_part_id]) - loc_part_id += test(include_endpoint); - else if (part_func_value > range_array[loc_part_id]) - loc_part_id++; - } + /* if 'WHERE <= X' and partition is LESS THAN (X) include next partition */ + if (include_endpoint && loc_part_id < max_partition && + part_func_value == part_end_val) + loc_part_id++; + + /* Right endpoint, set end after correct partition */ loc_part_id++; } DBUG_RETURN(loc_part_id); From 5ba1dd04748561ae2a9942f9f228c8c6a52de72b Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 18 Jan 2010 17:50:46 +0200 Subject: [PATCH 203/344] Bug #45989 take 2 : memory leak after explain encounters an error in the query. Fixes a leak after materializing a GROUP BY subquery to a temp table when the subquery has a blob column in the SELECT list. Fixed by correctly destructing temporary buffers after doing the conversion. --- mysql-test/r/subselect.result | 12 ++++++++++++ mysql-test/t/subselect.test | 17 +++++++++++++++++ sql/sql_select.cc | 2 ++ 3 files changed, 31 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index f446d8feec3..99d1f18b010 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4602,4 +4602,16 @@ SELECT 1 FROM t1 GROUP BY 1 1 DROP TABLE t1; +# +# Bug #45989 take 2 : memory leak after explain encounters an +# error in the query +# +CREATE TABLE t1(a LONGTEXT); +INSERT INTO t1 VALUES (repeat('a',@@global.max_allowed_packet)); +INSERT INTO t1 VALUES (repeat('b',@@global.max_allowed_packet)); +EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1, +(SELECT DISTINCTROW a AS away FROM t1 GROUP BY a WITH ROLLUP) AS d1 +WHERE t1.a = d1.a; +ERROR 42S22: Unknown column 'd1.a' in 'where clause' +DROP TABLE t1; End of 5.1 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index a4314c45cba..eca86de1e82 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3585,4 +3585,21 @@ SELECT 1 FROM t1 GROUP BY (SELECT LAST_INSERT_ID() FROM t1 ORDER BY MIN(a) ASC LIMIT 1); DROP TABLE t1; +--echo # +--echo # Bug #45989 take 2 : memory leak after explain encounters an +--echo # error in the query +--echo # + +CREATE TABLE t1(a LONGTEXT); +INSERT INTO t1 VALUES (repeat('a',@@global.max_allowed_packet)); +INSERT INTO t1 VALUES (repeat('b',@@global.max_allowed_packet)); + +--error ER_BAD_FIELD_ERROR +EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1, +(SELECT DISTINCTROW a AS away FROM t1 GROUP BY a WITH ROLLUP) AS d1 +WHERE t1.a = d1.a; + +DROP TABLE t1; + + --echo End of 5.1 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 644f0072b7b..24876ffec14 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5824,6 +5824,8 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table) const_table_map= 0; tmp_table_param.field_count= tmp_table_param.sum_func_count= tmp_table_param.func_count= 0; + if (tmp_table_param.copy_field) + delete [] tmp_table_param.copy_field; tmp_table_param.copy_field= tmp_table_param.copy_field_end=0; first_record= sort_and_group=0; send_records= (ha_rows) 0; From eab2be0aeed0459c505578a716f8b0ae88a8f365 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 18 Jan 2010 17:49:18 +0100 Subject: [PATCH 204/344] Bug#47343: InnoDB fails to clean-up after lock wait timeout on REORGANIZE PARTITION There were several problems which lead to this this, all related to bad error handling. 1) There was several bugs preventing the ddl-log to be used for cleaning up created files on error. 2) The error handling after the copy partition rows did not close and unlock the tables, resulting in deletion of partitions which were in use, which lead InnoDB to put the partition to drop in a background queue. sql/ha_partition.cc: Bug#47343: InnoDB fails to clean-up after lock wait timeout on REORGANIZE PARTITION Better error handling, if partition has been created/opened/locked then make sure it is unlocked and closed before returning error. The delete of the newly created partition is handled by the ddl-log. sql/sql_parse.cc: Bug#47343: InnoDB fails to clean-up after lock wait timeout on REORGANIZE PARTITION Fix a bug found when experimenting, thd could really be NULL here, as mentioned in the function header. sql/sql_partition.cc: Bug#47343: InnoDB fails to clean-up after lock wait timeout on REORGANIZE PARTITION Used the correct .frm shadow name to put into the ddl-log. Really use the ddl-log to handle errors. sql/sql_table.cc: Bug#47343: InnoDB fails to clean-up after lock wait timeout on REORGANIZE PARTITION Fixes of the ddl-log when used as error recovery (no crash). When executing an entry from memory (not read from disk) the name_len was not set correctly. --- mysql-test/r/partition_innodb.result | 44 ++++++++++++++++ mysql-test/t/partition_innodb-master.opt | 1 + mysql-test/t/partition_innodb.test | 45 ++++++++++++++++- sql/ha_partition.cc | 64 +++++++++++++++++------- sql/sql_parse.cc | 2 +- sql/sql_partition.cc | 8 ++- sql/sql_table.cc | 23 +++++++-- 7 files changed, 158 insertions(+), 29 deletions(-) create mode 100644 mysql-test/t/partition_innodb-master.opt diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index b8cfa25349d..f2f6ef138ff 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -274,3 +274,47 @@ CREATE TABLE t1 (a INT) ENGINE=InnoDB PARTITION BY list(a) (PARTITION p1 VALUES IN (1)); CREATE INDEX i1 ON t1 (a); DROP TABLE t1; +# +# Bug#47343: InnoDB fails to clean-up after lock wait timeout on +# REORGANIZE PARTITION +# +CREATE TABLE t1 ( +a INT, +b DATE NOT NULL, +PRIMARY KEY (a, b) +) ENGINE=InnoDB +PARTITION BY RANGE (a) ( +PARTITION pMAX VALUES LESS THAN MAXVALUE +) ; +INSERT INTO t1 VALUES (1, '2001-01-01'), (2, '2002-02-02'), (3, '2003-03-03'); +START TRANSACTION; +SELECT * FROM t1 FOR UPDATE; +a b +1 2001-01-01 +2 2002-02-02 +3 2003-03-03 +# Connection con1 +ALTER TABLE t1 REORGANIZE PARTITION pMAX INTO +(PARTITION p3 VALUES LESS THAN (3), +PARTITION pMAX VALUES LESS THAN MAXVALUE); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SHOW WARNINGS; +Level Code Message +Error 1205 Lock wait timeout exceeded; try restarting transaction +ALTER TABLE t1 REORGANIZE PARTITION pMAX INTO +(PARTITION p3 VALUES LESS THAN (3), +PARTITION pMAX VALUES LESS THAN MAXVALUE); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SHOW WARNINGS; +Level Code Message +Error 1205 Lock wait timeout exceeded; try restarting transaction +t1.frm +t1.par +# Connection default +SELECT * FROM t1; +a b +1 2001-01-01 +2 2002-02-02 +3 2003-03-03 +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/t/partition_innodb-master.opt b/mysql-test/t/partition_innodb-master.opt new file mode 100644 index 00000000000..462f8fbe828 --- /dev/null +++ b/mysql-test/t/partition_innodb-master.opt @@ -0,0 +1 @@ +--innodb_lock_wait_timeout=1 diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index aba28b76f01..b7fe4477a13 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -5,6 +5,8 @@ drop table if exists t1; --enable_warnings +let $MYSQLD_DATADIR= `SELECT @@datadir`; + # # Bug#47029: Crash when reorganize partition with subpartition # @@ -296,6 +298,47 @@ CREATE TABLE t1 (a INT) ENGINE=InnoDB PARTITION BY list(a) (PARTITION p1 VALUES IN (1)); CREATE INDEX i1 ON t1 (a); DROP TABLE t1; -let $MYSQLD_DATADIR= `SELECT @@datadir`; + # Before the fix it should show extra file like #sql-2405_2.par --list_files $MYSQLD_DATADIR/test/ * + +--echo # +--echo # Bug#47343: InnoDB fails to clean-up after lock wait timeout on +--echo # REORGANIZE PARTITION +--echo # +CREATE TABLE t1 ( + a INT, + b DATE NOT NULL, + PRIMARY KEY (a, b) +) ENGINE=InnoDB +PARTITION BY RANGE (a) ( + PARTITION pMAX VALUES LESS THAN MAXVALUE +) ; + +INSERT INTO t1 VALUES (1, '2001-01-01'), (2, '2002-02-02'), (3, '2003-03-03'); + +START TRANSACTION; +SELECT * FROM t1 FOR UPDATE; + +connect (con1, localhost, root,,); +--echo # Connection con1 +--error ER_LOCK_WAIT_TIMEOUT +ALTER TABLE t1 REORGANIZE PARTITION pMAX INTO +(PARTITION p3 VALUES LESS THAN (3), + PARTITION pMAX VALUES LESS THAN MAXVALUE); +SHOW WARNINGS; +--error ER_LOCK_WAIT_TIMEOUT +ALTER TABLE t1 REORGANIZE PARTITION pMAX INTO +(PARTITION p3 VALUES LESS THAN (3), + PARTITION pMAX VALUES LESS THAN MAXVALUE); +SHOW WARNINGS; + +#Contents of the 'test' database directory: +--list_files $MYSQLD_DATADIR/test + +disconnect con1; +connection default; +--echo # Connection default +SELECT * FROM t1; +COMMIT; +DROP TABLE t1; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b854e270029..555a0b97ddd 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1215,17 +1215,28 @@ int ha_partition::prepare_new_partition(TABLE *tbl, partition_element *p_elem) { int error; - bool create_flag= FALSE; DBUG_ENTER("prepare_new_partition"); if ((error= set_up_table_before_create(tbl, part_name, create_info, 0, p_elem))) - goto error; + goto error_create; if ((error= file->ha_create(part_name, tbl, create_info))) - goto error; - create_flag= TRUE; + { + /* + Added for safety, InnoDB reports HA_ERR_FOUND_DUPP_KEY + if the table/partition already exists. + If we return that error code, then print_error would try to + get_dup_key on a non-existing partition. + So return a more reasonable error code. + */ + if (error == HA_ERR_FOUND_DUPP_KEY) + error= HA_ERR_TABLE_EXIST; + goto error_create; + } + DBUG_PRINT("info", ("partition %s created", part_name)); if ((error= file->ha_open(tbl, part_name, m_mode, m_open_test_lock))) - goto error; + goto error_open; + DBUG_PRINT("info", ("partition %s opened", part_name)); /* Note: if you plan to add another call that may return failure, better to do it before external_lock() as cleanup_new_partition() @@ -1233,12 +1244,15 @@ int ha_partition::prepare_new_partition(TABLE *tbl, Otherwise see description for cleanup_new_partition(). */ if ((error= file->ha_external_lock(ha_thd(), m_lock_type))) - goto error; + goto error_external_lock; + DBUG_PRINT("info", ("partition %s external locked", part_name)); DBUG_RETURN(0); -error: - if (create_flag) - VOID(file->ha_delete_table(part_name)); +error_external_lock: + VOID(file->close()); +error_open: + VOID(file->ha_delete_table(part_name)); +error_create: DBUG_RETURN(error); } @@ -1272,19 +1286,23 @@ error: void ha_partition::cleanup_new_partition(uint part_count) { - handler **save_m_file= m_file; DBUG_ENTER("ha_partition::cleanup_new_partition"); - if (m_added_file && m_added_file[0]) + if (m_added_file) { - m_file= m_added_file; + THD *thd= ha_thd(); + handler **file= m_added_file; + while ((part_count > 0) && (*file)) + { + (*file)->ha_external_lock(thd, F_UNLCK); + (*file)->close(); + + /* Leave the (*file)->ha_delete_table(part_name) to the ddl-log */ + + file++; + part_count--; + } m_added_file= NULL; - - external_lock(ha_thd(), F_UNLCK); - /* delete_table also needed, a bit more complex */ - close(); - - m_file= save_m_file; } DBUG_VOID_RETURN; } @@ -1590,7 +1608,15 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, part_elem->part_state= PART_TO_BE_DROPPED; } m_new_file= new_file_array; - DBUG_RETURN(copy_partitions(copied, deleted)); + if ((error= copy_partitions(copied, deleted))) + { + /* + Close and unlock the new temporary partitions. + They will later be deleted through the ddl-log. + */ + cleanup_new_partition(part_count); + } + DBUG_RETURN(error); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index eaea6e55b09..7eabc1887f9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6954,7 +6954,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, /* If the query was killed then this function must fail. */ - return result || thd->killed; + return result || (thd ? thd->killed : 0); } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index e0697f563ea..441adc9ddd9 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -5708,8 +5708,7 @@ static bool write_log_drop_partition(ALTER_PARTITION_PARAM_TYPE *lpt) part_info->first_log_entry= NULL; build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0); - build_table_filename(tmp_path, sizeof(tmp_path) - 1, lpt->db, - lpt->table_name, "#", 0); + build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt); pthread_mutex_lock(&LOCK_gdl); if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path, FALSE)) @@ -5765,8 +5764,7 @@ static bool write_log_add_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0); - build_table_filename(tmp_path, sizeof(tmp_path) - 1, lpt->db, - lpt->table_name, "#", 0); + build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt); pthread_mutex_lock(&LOCK_gdl); if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path, FALSE)) @@ -5991,7 +5989,7 @@ void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt, partition_info *part_info= lpt->part_info; DBUG_ENTER("handle_alter_part_error"); - if (!part_info->first_log_entry && + if (part_info->first_log_entry && execute_ddl_log_entry(current_thd, part_info->first_log_entry->entry_pos)) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3b7354111ba..0e36ecfcb46 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -647,7 +647,7 @@ static bool read_ddl_log_file_entry(uint entry_no) Write one entry from ddl log file SYNOPSIS write_ddl_log_file_entry() - entry_no Entry number to read + entry_no Entry number to write RETURN VALUES TRUE Error FALSE Success @@ -748,10 +748,10 @@ static uint read_ddl_log_header() else successful_open= TRUE; } - entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]); - global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]); if (successful_open) { + entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]); + global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]); global_ddl_log.io_size= uint4korr(&file_entry_buf[DDL_LOG_IO_SIZE_POS]); DBUG_ASSERT(global_ddl_log.io_size <= sizeof(global_ddl_log.file_entry_buf)); @@ -832,6 +832,7 @@ static bool init_ddl_log() goto end; global_ddl_log.io_size= IO_SIZE; + global_ddl_log.name_len= FN_LEN; create_ddl_log_file_name(file_name); if ((global_ddl_log.file_id= my_create(file_name, CREATE_MODE, @@ -884,6 +885,13 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) { DBUG_RETURN(FALSE); } + DBUG_PRINT("ddl_log", + ("execute type %c next %u name '%s' from_name '%s' handler '%s'", + ddl_log_entry->action_type, + ddl_log_entry->next_entry, + ddl_log_entry->name, + ddl_log_entry->from_name, + ddl_log_entry->handler_name)); handler_name.str= (char*)ddl_log_entry->handler_name; handler_name.length= strlen(ddl_log_entry->handler_name); init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); @@ -1091,6 +1099,15 @@ bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry, DBUG_RETURN(TRUE); } error= FALSE; + DBUG_PRINT("ddl_log", + ("write type %c next %u name '%s' from_name '%s' handler '%s'", + (char) global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS], + ddl_log_entry->next_entry, + (char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS], + (char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + + FN_LEN], + (char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + + (2*FN_LEN)])); if (write_ddl_log_file_entry((*active_entry)->entry_pos)) { error= TRUE; From 81391bd00c5b3e577fc88e142406eb288a26a0ff Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Tue, 19 Jan 2010 13:03:40 +0400 Subject: [PATCH 205/344] Bug#49501 Inefficient information_schema check (system collation) added check_length optimization for I_S_NAME comparison sql/event_data_objects.cc: added check_length optimization for I_S_NAME comparison sql/events.cc: added check_length optimization for I_S_NAME comparison sql/mysql_priv.h: added check_length optimization for I_S_NAME comparison sql/repl_failsafe.cc: added check_length optimization for I_S_NAME comparison sql/sql_db.cc: added check_length optimization for I_S_NAME comparison sql/sql_parse.cc: added check_length optimization for I_S_NAME comparison sql/sql_show.cc: added check_length optimization for I_S_NAME comparison sql/sql_view.cc: added check_length optimization for I_S_NAME comparison sql/table.cc: added check_length optimization for I_S_NAME comparison --- sql/event_data_objects.cc | 2 +- sql/events.cc | 15 +++++++++------ sql/mysql_priv.h | 8 ++++++-- sql/repl_failsafe.cc | 2 +- sql/sql_db.cc | 5 ++--- sql/sql_parse.cc | 40 ++++++++++++++++++++++----------------- sql/sql_show.cc | 9 ++++----- sql/sql_view.cc | 4 ++-- sql/table.cc | 5 +---- 9 files changed, 49 insertions(+), 41 deletions(-) diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index f2ec0e8cf64..92e237a17b7 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -1401,7 +1401,7 @@ Event_job_data::execute(THD *thd, bool drop) #endif if (check_access(thd, EVENT_ACL, dbname.str, - 0, 0, 0, is_schema_db(dbname.str))) + 0, 0, 0, is_schema_db(dbname.str, dbname.length))) { /* This aspect of behavior is defined in the worklog, diff --git a/sql/events.cc b/sql/events.cc index 458ad61718d..790e6a61699 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -415,7 +415,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, DBUG_ASSERT(parse_data->expression || parse_data->execute_at); if (check_access(thd, EVENT_ACL, parse_data->dbname.str, 0, 0, 0, - is_schema_db(parse_data->dbname.str))) + is_schema_db(parse_data->dbname.str, + parse_data->dbname.length))) DBUG_RETURN(TRUE); if (check_db_dir_existence(parse_data->dbname.str)) @@ -526,7 +527,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, DBUG_RETURN(TRUE); if (check_access(thd, EVENT_ACL, parse_data->dbname.str, 0, 0, 0, - is_schema_db(parse_data->dbname.str))) + is_schema_db(parse_data->dbname.str, + parse_data->dbname.length))) DBUG_RETURN(TRUE); if (new_dbname) /* It's a rename */ @@ -548,7 +550,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, access it. */ if (check_access(thd, EVENT_ACL, new_dbname->str, 0, 0, 0, - is_schema_db(new_dbname->str))) + is_schema_db(new_dbname->str, new_dbname->length))) DBUG_RETURN(TRUE); /* Check that the target database exists */ @@ -653,7 +655,7 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) DBUG_RETURN(TRUE); if (check_access(thd, EVENT_ACL, dbname.str, 0, 0, 0, - is_schema_db(dbname.str))) + is_schema_db(dbname.str, dbname.length))) DBUG_RETURN(TRUE); /* @@ -811,7 +813,7 @@ Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name) DBUG_RETURN(TRUE); if (check_access(thd, EVENT_ACL, dbname.str, 0, 0, 0, - is_schema_db(dbname.str))) + is_schema_db(dbname.str, dbname.length))) DBUG_RETURN(TRUE); /* @@ -869,7 +871,8 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS) { DBUG_ASSERT(thd->lex->select_lex.db); - if (!is_schema_db(thd->lex->select_lex.db) && // There is no events in I_S + if (!is_schema_db(thd->lex->select_lex.db, // There is no events in I_S + strlen(thd->lex->select_lex.db)) && check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, 0)) DBUG_RETURN(1); db= thd->lex->select_lex.db; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c04b1f5ae38..2be3b8f1f20 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1415,8 +1415,12 @@ bool get_schema_tables_result(JOIN *join, enum enum_schema_table_state executed_place); enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table); -#define is_schema_db(X) \ - !my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.str, (X)) +inline bool is_schema_db(const char *name, size_t len) +{ + return (INFORMATION_SCHEMA_NAME.length == len && + !my_strcasecmp(system_charset_info, + INFORMATION_SCHEMA_NAME.str, name)); +} /* sql_prepare.cc */ diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index c6a05e93bf4..dda84ca8a37 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -905,7 +905,7 @@ bool load_master_data(THD* thd) if (!rpl_filter->db_ok(db) || !rpl_filter->db_ok_with_wild_table(db) || !strcmp(db,"mysql") || - is_schema_db(db)) + is_schema_db(db, strlen(db))) { *cur_table_res = 0; continue; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index e760fae41f6..22ecaa17a0c 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -618,7 +618,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, DBUG_ENTER("mysql_create_db"); /* do not create 'information_schema' db */ - if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.str)) + if (is_schema_db(db, strlen(db))) { my_error(ER_DB_CREATE_EXISTS, MYF(0), db); DBUG_RETURN(-1); @@ -1557,8 +1557,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) } } - if (my_strcasecmp(system_charset_info, new_db_name->str, - INFORMATION_SCHEMA_NAME.str) == 0) + if (is_schema_db(new_db_name->str, new_db_name->length)) { /* Switch the current database to INFORMATION_SCHEMA. */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c3070c4a756..f0fb58e9c3e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1305,8 +1305,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, table_list.alias= table_list.table_name= conv_name.str; packet= arg_end + 1; - if (!my_strcasecmp(system_charset_info, table_list.db, - INFORMATION_SCHEMA_NAME.str)) + if (is_schema_db(table_list.db, table_list.db_length)) { ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, table_list.alias); if (schema_table) @@ -1368,7 +1367,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } if (check_access(thd, CREATE_ACL, db.str , 0, 1, 0, - is_schema_db(db.str))) + is_schema_db(db.str, db.length))) break; general_log_print(thd, command, "%.*s", db.length, db.str); bzero(&create_info, sizeof(create_info)); @@ -1387,7 +1386,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL"); break; } - if (check_access(thd, DROP_ACL, db.str, 0, 1, 0, is_schema_db(db.str))) + if (check_access(thd, DROP_ACL, db.str, 0, 1, 0, + is_schema_db(db.str, db.length))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -2852,7 +2852,7 @@ end_with_restore_list: &first_table->grant.privilege, 0, 0, test(first_table->schema_table)) || check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0, - is_schema_db(select_lex->db))|| + is_schema_db(select_lex->db, strlen(select_lex->db)))|| check_merge_table_access(thd, first_table->db, (TABLE_LIST *) create_info.merge_list.first)) @@ -3590,7 +3590,7 @@ end_with_restore_list: } #endif if (check_access(thd,CREATE_ACL,lex->name.str, 0, 1, 0, - is_schema_db(lex->name.str))) + is_schema_db(lex->name.str, lex->name.length))) break; res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name.str), &create_info, 0); @@ -3625,7 +3625,7 @@ end_with_restore_list: } #endif if (check_access(thd,DROP_ACL,lex->name.str,0,1,0, - is_schema_db(lex->name.str))) + is_schema_db(lex->name.str, lex->name.length))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -3659,9 +3659,12 @@ end_with_restore_list: my_error(ER_WRONG_DB_NAME, MYF(0), db->str); break; } - if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, is_schema_db(db->str)) || - check_access(thd, DROP_ACL, db->str, 0, 1, 0, is_schema_db(db->str)) || - check_access(thd, CREATE_ACL, db->str, 0, 1, 0, is_schema_db(db->str))) + if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, + is_schema_db(db->str, db->length)) || + check_access(thd, DROP_ACL, db->str, 0, 1, 0, + is_schema_db(db->str, db->length)) || + check_access(thd, CREATE_ACL, db->str, 0, 1, 0, + is_schema_db(db->str, db->length))) { res= 1; break; @@ -3704,7 +3707,8 @@ end_with_restore_list: break; } #endif - if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, is_schema_db(db->str))) + if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, + is_schema_db(db->str, db->length))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -3860,7 +3864,8 @@ end_with_restore_list: first_table ? &first_table->grant.privilege : 0, first_table ? 0 : 1, 0, first_table ? (bool) first_table->schema_table : - select_lex->db ? is_schema_db(select_lex->db) : 0)) + select_lex->db ? + is_schema_db(select_lex->db, strlen(select_lex->db)) : 0)) goto error; if (thd->security_ctx->user) // If not replication @@ -4203,7 +4208,8 @@ end_with_restore_list: } if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0, - is_schema_db(lex->sphead->m_db.str))) + is_schema_db(lex->sphead->m_db.str, + lex->sphead->m_db.length))) goto create_sp_error; if (end_active_trans(thd)) @@ -4858,7 +4864,8 @@ create_sp_error: res= mysql_xa_recover(thd); break; case SQLCOM_ALTER_TABLESPACE: - if (check_access(thd, ALTER_ACL, thd->db, 0, 1, 0, thd->db ? is_schema_db(thd->db) : 0)) + if (check_access(thd, ALTER_ACL, thd->db, 0, 1, 0, + thd->db ? is_schema_db(thd->db, thd->db_length) : 0)) break; if (!(res= mysql_alter_tablespace(thd, lex->alter_tablespace_info))) my_ok(thd); @@ -5297,7 +5304,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) if (check_access(thd, SELECT_ACL, dst_db_name, &thd->col_access, FALSE, FALSE, - is_schema_db(dst_db_name))) + is_schema_db(dst_db_name, strlen(dst_db_name)))) return TRUE; if (!thd->col_access && check_grant_db(thd, dst_db_name)) @@ -6262,8 +6269,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES); ptr->derived= table->sel; - if (!ptr->derived && !my_strcasecmp(system_charset_info, ptr->db, - INFORMATION_SCHEMA_NAME.str)) + if (!ptr->derived && is_schema_db(ptr->db, ptr->db_length)) { ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->table_name); if (!schema_table || diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e55000c0f65..d4da29085b5 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -826,8 +826,7 @@ bool mysqld_show_create_db(THD *thd, char *dbname, DBUG_RETURN(TRUE); } #endif - if (!my_strcasecmp(system_charset_info, dbname, - INFORMATION_SCHEMA_NAME.str)) + if (is_schema_db(dbname, strlen(dbname))) { dbname= INFORMATION_SCHEMA_NAME.str; create.default_table_charset= system_charset_info; @@ -2780,8 +2779,8 @@ int make_db_list(THD *thd, List *files, */ if (lookup_field_vals->db_value.str) { - if (!my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.str, - lookup_field_vals->db_value.str)) + if (is_schema_db(lookup_field_vals->db_value.str, + lookup_field_vals->db_value.length)) { *with_i_schema= 1; if (files->push_back(i_s_name_copy)) @@ -5228,7 +5227,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) */ if (thd->lex->sql_command != SQLCOM_SHOW_EVENTS && check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1, - is_schema_db(et.dbname.str))) + is_schema_db(et.dbname.str, et.dbname.length))) DBUG_RETURN(0); /* ->field[0] is EVENT_CATALOG and is by default NULL */ diff --git a/sql/sql_view.cc b/sql/sql_view.cc index eca3922f17a..83cebf1e3da 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -268,11 +268,11 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, table (i.e. user will not get some privileges by view creation) */ if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege, - 0, 0, is_schema_db(view->db)) || + 0, 0, is_schema_db(view->db, view->db_length)) || check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) || (mode != VIEW_CREATE_NEW && (check_access(thd, DROP_ACL, view->db, &view->grant.privilege, - 0, 0, is_schema_db(view->db)) || + 0, 0, is_schema_db(view->db, view->db_length)) || check_grant(thd, DROP_ACL, view, 0, 1, 0)))) goto err; diff --git a/sql/table.cc b/sql/table.cc index 752b6ba0bd4..c06ecf99926 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -212,10 +212,7 @@ TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name) DBUG_ASSERT(db != NULL); DBUG_ASSERT(name != NULL); - if ((db->length == INFORMATION_SCHEMA_NAME.length) && - (my_strcasecmp(system_charset_info, - INFORMATION_SCHEMA_NAME.str, - db->str) == 0)) + if (is_schema_db(db->str, db->length)) { return TABLE_CATEGORY_INFORMATION; } From 2fa49930cab5e070b5abaadbc2ab2b0899bc41b5 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 19 Jan 2010 14:48:41 +0200 Subject: [PATCH 206/344] revert of the fix for bug #45989: pushed by mistake. --- mysql-test/r/subselect.result | 12 ------------ mysql-test/t/subselect.test | 17 ----------------- sql/sql_select.cc | 2 -- 3 files changed, 31 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 99d1f18b010..f446d8feec3 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4602,16 +4602,4 @@ SELECT 1 FROM t1 GROUP BY 1 1 DROP TABLE t1; -# -# Bug #45989 take 2 : memory leak after explain encounters an -# error in the query -# -CREATE TABLE t1(a LONGTEXT); -INSERT INTO t1 VALUES (repeat('a',@@global.max_allowed_packet)); -INSERT INTO t1 VALUES (repeat('b',@@global.max_allowed_packet)); -EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1, -(SELECT DISTINCTROW a AS away FROM t1 GROUP BY a WITH ROLLUP) AS d1 -WHERE t1.a = d1.a; -ERROR 42S22: Unknown column 'd1.a' in 'where clause' -DROP TABLE t1; End of 5.1 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index eca86de1e82..a4314c45cba 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3585,21 +3585,4 @@ SELECT 1 FROM t1 GROUP BY (SELECT LAST_INSERT_ID() FROM t1 ORDER BY MIN(a) ASC LIMIT 1); DROP TABLE t1; ---echo # ---echo # Bug #45989 take 2 : memory leak after explain encounters an ---echo # error in the query ---echo # - -CREATE TABLE t1(a LONGTEXT); -INSERT INTO t1 VALUES (repeat('a',@@global.max_allowed_packet)); -INSERT INTO t1 VALUES (repeat('b',@@global.max_allowed_packet)); - ---error ER_BAD_FIELD_ERROR -EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1, -(SELECT DISTINCTROW a AS away FROM t1 GROUP BY a WITH ROLLUP) AS d1 -WHERE t1.a = d1.a; - -DROP TABLE t1; - - --echo End of 5.1 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 24876ffec14..644f0072b7b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5824,8 +5824,6 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table) const_table_map= 0; tmp_table_param.field_count= tmp_table_param.sum_func_count= tmp_table_param.func_count= 0; - if (tmp_table_param.copy_field) - delete [] tmp_table_param.copy_field; tmp_table_param.copy_field= tmp_table_param.copy_field_end=0; first_record= sort_and_group=0; send_records= (ha_rows) 0; From d2f61748cd0a63d0c9df989d92cb36fc1c7583c5 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 23 Dec 2009 17:11:22 +0200 Subject: [PATCH 207/344] Bug #49512 : subquery with aggregate function crash subselect_single_select_engine::exec() When a subquery doesn't need to be evaluated because it returns only aggregate functions and these aggregates can be calculated from the metadata about the table it was not updating all the relevant members of the JOIN structure to reflect that this is a constant query. This caused problems to the enclosing subquery ('<> SOME' in the test case above) trying to read some data about the tables. Fixed by setting const_tables to the number of tables when the SELECT is optimized away. --- mysql-test/r/subselect.result | 13 +++++++++++++ mysql-test/t/subselect.test | 15 +++++++++++++++ sql/sql_select.cc | 1 + 3 files changed, 29 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index f446d8feec3..dc3cff68731 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4602,4 +4602,17 @@ SELECT 1 FROM t1 GROUP BY 1 1 DROP TABLE t1; +# +# Bug #49512 : subquery with aggregate function crash +# subselect_single_select_engine::exec() +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(); +# should not crash +SELECT 1 FROM t1 WHERE a <> SOME +( +SELECT MAX((SELECT a FROM t1 LIMIT 1)) AS d +FROM t1,t1 a +); +1 +DROP TABLE t1; End of 5.1 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index a4314c45cba..027578fc6bd 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3585,4 +3585,19 @@ SELECT 1 FROM t1 GROUP BY (SELECT LAST_INSERT_ID() FROM t1 ORDER BY MIN(a) ASC LIMIT 1); DROP TABLE t1; +--echo # +--echo # Bug #49512 : subquery with aggregate function crash +--echo # subselect_single_select_engine::exec() + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(); + +--echo # should not crash +SELECT 1 FROM t1 WHERE a <> SOME +( + SELECT MAX((SELECT a FROM t1 LIMIT 1)) AS d + FROM t1,t1 a +); +DROP TABLE t1; + --echo End of 5.1 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 644f0072b7b..d5ce32902c4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -942,6 +942,7 @@ JOIN::optimize() DBUG_PRINT("info",("Select tables optimized away")); zero_result_cause= "Select tables optimized away"; tables_list= 0; // All tables resolved + const_tables= tables; /* Extract all table-independent conditions and replace the WHERE clause with them. All other conditions were computed by opt_sum_query From 416df0eaada5b644931f5b3b15f897a376641a4d Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Thu, 24 Dec 2009 15:20:58 +0000 Subject: [PATCH 208/344] BUG#48738: post-push fix. Multi-platform test improvements, mainly to make the test run gracefully on windows. There was also a syntax error in windows part of the test. --- .../r/binlog_delete_and_flush_index.result | 14 ++- .../t/binlog_delete_and_flush_index.test | 95 ++++--------------- 2 files changed, 29 insertions(+), 80 deletions(-) diff --git a/mysql-test/r/binlog_delete_and_flush_index.result b/mysql-test/r/binlog_delete_and_flush_index.result index 153900f3081..7500c17759c 100644 --- a/mysql-test/r/binlog_delete_and_flush_index.result +++ b/mysql-test/r/binlog_delete_and_flush_index.result @@ -2,7 +2,9 @@ RESET MASTER; CREATE TABLE t1 (a int); ### assertion: index file contains regular entries SET @index=LOAD_FILE('MYSQLD_DATADIR/master-bin.index'); -master-bin.000001 +SELECT @index; +@index +MYSQLD_DATADIR/master-bin.000001 ### assertion: show original binlogs show binary logs; @@ -15,8 +17,10 @@ master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a int) FLUSH LOGS; ### assertion: index file contains renamed binlog and the new one SET @index=LOAD_FILE('MYSQLD_DATADIR/master-bin.index'); -master-bin-b34582.000001 -master-bin.000002 +SELECT @index; +@index +MYSQLD_DATADIR/master-bin-b34582.000001 +MYSQLD_DATADIR/master-bin.000002 ### assertion: original binlog content still exists, despite we ### renamed and changed the index file @@ -39,6 +43,8 @@ master-bin.000002 # ### assertion: assert that not purged binlog file exists ### assertion: show index file contents and these should match show binary logs issued above SET @index=LOAD_FILE('MYSQLD_DATADIR/master-bin.index'); -master-bin.000002 +SELECT @index; +@index +MYSQLD_DATADIR/master-bin.000002 RESET MASTER; diff --git a/mysql-test/t/binlog_delete_and_flush_index.test b/mysql-test/t/binlog_delete_and_flush_index.test index 6784043386d..2899b96e317 100644 --- a/mysql-test/t/binlog_delete_and_flush_index.test +++ b/mysql-test/t/binlog_delete_and_flush_index.test @@ -45,31 +45,10 @@ RESET MASTER; CREATE TABLE t1 (a int); -- echo ### assertion: index file contains regular entries --- replace_regex /[\\\/].*master/MYSQLD_DATADIR\/master/ +-- replace_result $datadir MYSQLD_DATADIR -- eval SET @index=LOAD_FILE('$index') -if (`SELECT convert(@@version_compile_os using latin1) - IN ('Win32','Win64','Windows')`) -{ - -- disable_query_log - -- disable_result_log - -- let $a= `SELECT REPLACE (@index, '$datadir\', '')` - -- enable_result_log - -- enable_query_log - - -- echo $a - -} -if (!`SELECT convert(@@version_compile_os using latin1) - IN ('Win32','Win64','Windows')`) -{ - -- disable_query_log - -- disable_result_log - -- let $a= `SELECT REPLACE (@index, '$datadir/', '')` - -- enable_result_log - -- enable_query_log - - -- echo $a -} +-- replace_result $datadir MYSQLD_DATADIR +SELECT @index; --echo ### assertion: show original binlogs -- source include/show_binary_logs.inc @@ -79,17 +58,23 @@ if (!`SELECT convert(@@version_compile_os using latin1) # action: copy binlogs to other names and change entries in index file -- copy_file $datadir/master-bin.000001 $datadir/master-bin-b34582.000001 --- let newbinfile=$datadir/master-bin-b34582.000001 -let INDEX_FILE=$index; +-- let newbinfile= $datadir/master-bin-b34582.000001 +-- let INDEX_FILE= $index perl; -$newbinfile= $ENV{'newbinfile'}; +use File::Spec; +$newbinfile= File::Spec->rel2abs($ENV{'newbinfile'}); $file= $ENV{'INDEX_FILE'}; open(FILE, ">$file") || die "Unable to open $file."; truncate(FILE,0); -print FILE $newbinfile . "\n"; +print FILE "$newbinfile"; close ($file); EOF +# append a new line (platform independent) +-- append_file $index + +EOF + # action: should cause rotation, and creation of new binlogs FLUSH LOGS; @@ -97,31 +82,10 @@ FLUSH LOGS; -- remove_file $datadir/master-bin.000001 -- echo ### assertion: index file contains renamed binlog and the new one --- replace_regex /[\\\/].*master/MYSQLD_DATADIR\/master/ +-- replace_result $datadir MYSQLD_DATADIR -- eval SET @index=LOAD_FILE('$index') -if (`SELECT convert(@@version_compile_os using latin1) - IN ('Win32','Win64','Windows')`) -{ - -- disable_query_log - -- disable_result_log - -- let $a= `SELECT REPLACE (@index, '$datadir\', '')` - -- enable_result_log - -- enable_query_log - - -- echo $a - -} -if (!`SELECT convert(@@version_compile_os using latin1) - IN ('Win32','Win64','Windows')`) -{ - -- disable_query_log - -- disable_result_log - -- let $a= `SELECT REPLACE (@index, '$datadir/', '')` - -- enable_result_log - -- enable_query_log - - -- echo $a -} +-- replace_result $datadir MYSQLD_DATADIR +SELECT @index; -- echo ### assertion: original binlog content still exists, despite we -- echo ### renamed and changed the index file @@ -147,30 +111,9 @@ DROP TABLE t1; -- file_exists $datadir/$current_binlog -- echo ### assertion: show index file contents and these should match show binary logs issued above --- replace_regex /[\\\/].*master/MYSQLD_DATADIR\/master/ +-- replace_result $datadir MYSQLD_DATADIR -- eval SET @index=LOAD_FILE('$index') -if (`SELECT convert(@@version_compile_os using latin1) - IN ('Win32','Win64','Windows')`) -{ - -- disable_query_log - -- disable_result_log - -- let $a= `SELECT REPLACE (@index, '$datadir\', '')` - -- enable_result_log - -- enable_query_log - - -- echo $a - -} -if (!`SELECT convert(@@version_compile_os using latin1) - IN ('Win32','Win64','Windows')`) -{ - -- disable_query_log - -- disable_result_log - -- let $a= `SELECT REPLACE (@index, '$datadir/', '')` - -- enable_result_log - -- enable_query_log - - -- echo $a -} +-- replace_result $datadir MYSQLD_DATADIR +SELECT @index; RESET MASTER; From 85d78b62ccf99fc93ec40f994658dc394a3e5987 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Sun, 27 Dec 2009 15:54:41 +0200 Subject: [PATCH 209/344] Fix test suite so that it works when doing configure --without-uca Simplify testing of needed characterset Remove ndb from --with-plugins=max build mysqlbug now sends email to maria-developers@lists.launchpad.net client/mysqltest.cc: SKIP now expands variables (for better error messages) mysql-test/include/have_big5.inc: Simplify by using have_collation.inc mysql-test/include/have_collation.inc: Test if '$collation' is supported mysql-test/include/have_cp1250_ch.inc: Simplify by using have_collation.inc mysql-test/include/have_cp1251.inc: Simplify by using have_collation.inc mysql-test/include/have_cp866.inc: Simplify by using have_collation.inc mysql-test/include/have_cp932.inc: Simplify by using have_collation.inc mysql-test/include/have_eucjpms.inc: Simplify by using have_collation.inc mysql-test/include/have_euckr.inc: Simplify by using have_collation.inc mysql-test/include/have_gb2312.inc: Simplify by using have_collation.inc mysql-test/include/have_gbk.inc: Simplify by using have_collation.inc mysql-test/include/have_koi8r.inc: Simplify by using have_collation.inc mysql-test/include/have_latin2_ch.inc: Simplify by using have_collation.inc mysql-test/include/have_sjis.inc: Simplify by using have_collation.inc mysql-test/include/have_tis620.inc: Simplify by using have_collation.inc mysql-test/include/have_ucs2.inc: Simplify by using have_collation.inc mysql-test/include/have_ujis.inc: Simplify by using have_collation.inc mysql-test/include/have_utf8.inc: Simplify by using have_collation.inc mysql-test/r/create-uca.result: Create tests that uses unicode mysql-test/r/create.result: Move test with unicode to create-uca.test mysql-test/r/have_big5.require: Not needed anymore mysql-test/r/have_cp1250_ch.require: Not needed anymore mysql-test/r/have_cp1251.require: Not needed anymore mysql-test/r/have_cp866.require: Not needed anymore mysql-test/r/have_cp932.require: Not needed anymore mysql-test/r/have_eucjpms.require: Not needed anymore mysql-test/r/have_euckr.require: Not needed anymore mysql-test/r/have_gb2312.require: Not needed anymore mysql-test/r/have_gbk.require: Not needed anymore mysql-test/r/have_koi8r.require: Not needed anymore mysql-test/r/have_latin2_ch.require: Not needed anymore mysql-test/r/have_sjis.require: Not needed anymore mysql-test/r/have_tis620.require: Not needed anymore mysql-test/r/have_ucs2.require: Not needed anymore mysql-test/r/have_ujis.require: Not needed anymore mysql-test/r/have_utf8.require: Not needed anymore mysql-test/r/innodb.result: Move tests that depends on unicode to innodb_utf8.test mysql-test/r/innodb_utf8.result: Test moved from innodb.test mysql-test/suite/rpl/t/rpl_ignore_table.test: Test for required collations mysql-test/t/create-uca.test: Create tests that uses unicode mysql-test/t/create.test: Move test with unicode to create-uca.test mysql-test/t/ctype_utf8.test: Test that require unicode mysql-test/t/ddl_i18n_koi8r.test: Test for required collations mysql-test/t/ddl_i18n_utf8.test: Test for required collations mysql-test/t/fulltext.test: Test for required collations mysql-test/t/fulltext2.test: Test for required collations mysql-test/t/innodb.test: Move tests that depends on unicode to innodb_utf8.test mysql-test/t/innodb_utf8.test: Tests that uses unicode mysql-test/t/query_cache_ps_no_prot.test: Test for required collations mysql-test/t/query_cache_ps_ps_prot.test: Test for required collations scripts/mysqlbug.sh: Send emails to maria-developers@lists.launchpad.net storage/ndb/plug.in: Don't include ndb in 'max' builds --- client/mysqltest.cc | 6 ++- mysql-test/include/have_big5.inc | 6 +-- mysql-test/include/have_collation.inc | 3 ++ mysql-test/include/have_cp1250_ch.inc | 6 +-- mysql-test/include/have_cp1251.inc | 9 +--- mysql-test/include/have_cp866.inc | 9 +--- mysql-test/include/have_cp932.inc | 6 +-- mysql-test/include/have_eucjpms.inc | 6 +-- mysql-test/include/have_euckr.inc | 6 +-- mysql-test/include/have_gb2312.inc | 6 +-- mysql-test/include/have_gbk.inc | 6 +-- mysql-test/include/have_koi8r.inc | 9 +--- mysql-test/include/have_latin2_ch.inc | 6 +-- mysql-test/include/have_sjis.inc | 6 +-- mysql-test/include/have_tis620.inc | 6 +-- mysql-test/include/have_ucs2.inc | 6 +-- mysql-test/include/have_ujis.inc | 6 +-- mysql-test/include/have_utf8.inc | 9 +--- mysql-test/r/create-uca.result | 31 +++++++++++++ mysql-test/r/create.result | 46 -------------------- mysql-test/r/have_big5.require | 2 - mysql-test/r/have_cp1250_ch.require | 2 - mysql-test/r/have_cp1251.require | 2 - mysql-test/r/have_cp866.require | 2 - mysql-test/r/have_cp932.require | 2 - mysql-test/r/have_eucjpms.require | 2 - mysql-test/r/have_euckr.require | 2 - mysql-test/r/have_gb2312.require | 2 - mysql-test/r/have_gbk.require | 2 - mysql-test/r/have_koi8r.require | 2 - mysql-test/r/have_latin2_ch.require | 2 - mysql-test/r/have_sjis.require | 2 - mysql-test/r/have_tis620.require | 2 - mysql-test/r/have_ucs2.require | 2 - mysql-test/r/have_ujis.require | 2 - mysql-test/r/have_utf8.require | 2 - mysql-test/r/innodb.result | 9 ---- mysql-test/r/innodb_utf8.result | 10 +++++ mysql-test/suite/rpl/t/rpl_ignore_table.test | 2 + mysql-test/t/create-uca.test | 26 +++++++++++ mysql-test/t/create.test | 46 -------------------- mysql-test/t/ctype_utf8.test | 9 ++++ mysql-test/t/ddl_i18n_koi8r.test | 2 + mysql-test/t/ddl_i18n_utf8.test | 2 + mysql-test/t/fulltext.test | 3 ++ mysql-test/t/fulltext2.test | 3 ++ mysql-test/t/innodb.test | 12 ----- mysql-test/t/innodb_utf8.test | 24 ++++++++++ mysql-test/t/query_cache_ps_no_prot.test | 3 +- mysql-test/t/query_cache_ps_ps_prot.test | 3 +- scripts/mysqlbug.sh | 2 +- storage/ndb/plug.in | 2 +- 52 files changed, 158 insertions(+), 226 deletions(-) create mode 100644 mysql-test/include/have_collation.inc create mode 100644 mysql-test/r/create-uca.result delete mode 100644 mysql-test/r/have_big5.require delete mode 100644 mysql-test/r/have_cp1250_ch.require delete mode 100644 mysql-test/r/have_cp1251.require delete mode 100644 mysql-test/r/have_cp866.require delete mode 100644 mysql-test/r/have_cp932.require delete mode 100644 mysql-test/r/have_eucjpms.require delete mode 100644 mysql-test/r/have_euckr.require delete mode 100644 mysql-test/r/have_gb2312.require delete mode 100644 mysql-test/r/have_gbk.require delete mode 100644 mysql-test/r/have_koi8r.require delete mode 100644 mysql-test/r/have_latin2_ch.require delete mode 100644 mysql-test/r/have_sjis.require delete mode 100644 mysql-test/r/have_tis620.require delete mode 100644 mysql-test/r/have_ucs2.require delete mode 100644 mysql-test/r/have_ujis.require delete mode 100644 mysql-test/r/have_utf8.require create mode 100644 mysql-test/r/innodb_utf8.result create mode 100644 mysql-test/t/create-uca.test create mode 100644 mysql-test/t/innodb_utf8.test diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 8360b33b031..bc5c4ed76b8 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1267,6 +1267,7 @@ void abort_not_supported_test(const char *fmt, ...) DBUG_ENTER("abort_not_supported_test"); /* Print include filestack */ + fflush(stdout); fprintf(stderr, "The test '%s' is not supported by this installation\n", file_stack->file_name); fprintf(stderr, "Detected in file %s at line %d\n", @@ -8098,7 +8099,10 @@ int main(int argc, char **argv) abort_flag= 1; break; case Q_SKIP: - abort_not_supported_test("%s", command->first_argument); + /* Eval the query, thus replacing all environment variables */ + dynstr_set(&ds_res, 0); + do_eval(&ds_res, command->first_argument, command->end, FALSE); + abort_not_supported_test("%s",ds_res.str); break; case Q_RESULT: diff --git a/mysql-test/include/have_big5.inc b/mysql-test/include/have_big5.inc index dad4a0a8eeb..d6ef1202bae 100644 --- a/mysql-test/include/have_big5.inc +++ b/mysql-test/include/have_big5.inc @@ -1,4 +1,2 @@ --- require r/have_big5.require -disable_query_log; -show collation like 'big5_chinese_ci'; -enable_query_log; +let collation=big5_chinese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_collation.inc b/mysql-test/include/have_collation.inc new file mode 100644 index 00000000000..99270fd4d3d --- /dev/null +++ b/mysql-test/include/have_collation.inc @@ -0,0 +1,3 @@ +if (!`SELECT count(*) AS 'true' FROM information_schema.collations WHERE collation_name LIKE '$collation'`) { + skip Test needs character set '$collation'; +} diff --git a/mysql-test/include/have_cp1250_ch.inc b/mysql-test/include/have_cp1250_ch.inc index 426fa658597..93fde6e9fe6 100644 --- a/mysql-test/include/have_cp1250_ch.inc +++ b/mysql-test/include/have_cp1250_ch.inc @@ -1,4 +1,2 @@ --- require r/have_cp1250_ch.require -disable_query_log; -show collation like 'cp1250_czech_cs'; -enable_query_log; +let collation=cp1250_czech_cs; +--source include/have_collation.inc diff --git a/mysql-test/include/have_cp1251.inc b/mysql-test/include/have_cp1251.inc index 2d5f1b3b529..32e9e7220fc 100644 --- a/mysql-test/include/have_cp1251.inc +++ b/mysql-test/include/have_cp1251.inc @@ -1,7 +1,2 @@ ---require r/have_cp1251.require - ---disable_query_log - -SHOW COLLATION LIKE 'cp1251_general_ci'; - ---enable_query_log +let collation=cp1251_general_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_cp866.inc b/mysql-test/include/have_cp866.inc index 27390d87d51..549ea22a0e3 100644 --- a/mysql-test/include/have_cp866.inc +++ b/mysql-test/include/have_cp866.inc @@ -1,7 +1,2 @@ ---require r/have_cp866.require - ---disable_query_log - -SHOW COLLATION LIKE 'cp866_general_ci'; - ---enable_query_log +let collation=cp866_general_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_cp932.inc b/mysql-test/include/have_cp932.inc index ecad979c02a..6e436b8b3f5 100644 --- a/mysql-test/include/have_cp932.inc +++ b/mysql-test/include/have_cp932.inc @@ -1,4 +1,2 @@ --- require r/have_cp932.require -disable_query_log; -show collation like 'cp932_japanese_ci'; -enable_query_log; +let collation=cp932_japanese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_eucjpms.inc b/mysql-test/include/have_eucjpms.inc index 6d96eefcc31..c38af5299c7 100644 --- a/mysql-test/include/have_eucjpms.inc +++ b/mysql-test/include/have_eucjpms.inc @@ -1,4 +1,2 @@ --- require r/have_eucjpms.require -disable_query_log; -show collation like 'eucjpms_japanese_ci'; -enable_query_log; +let collation=eucjpms_japanese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_euckr.inc b/mysql-test/include/have_euckr.inc index 4b4e870cf47..4da1a8363a3 100644 --- a/mysql-test/include/have_euckr.inc +++ b/mysql-test/include/have_euckr.inc @@ -1,4 +1,2 @@ --- require r/have_euckr.require -disable_query_log; -show collation like 'euckr_korean_ci'; -enable_query_log; +let collation=euckr_korean_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_gb2312.inc b/mysql-test/include/have_gb2312.inc index 27591c01b6c..6a9a0588be0 100644 --- a/mysql-test/include/have_gb2312.inc +++ b/mysql-test/include/have_gb2312.inc @@ -1,4 +1,2 @@ --- require r/have_gb2312.require -disable_query_log; -show collation like 'gb2312_chinese_ci'; -enable_query_log; +let collation=gb2312_chinese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_gbk.inc b/mysql-test/include/have_gbk.inc index 72252d6b00d..b8177aa655d 100644 --- a/mysql-test/include/have_gbk.inc +++ b/mysql-test/include/have_gbk.inc @@ -1,4 +1,2 @@ --- require r/have_gbk.require -disable_query_log; -show collation like 'gbk_chinese_ci'; -enable_query_log; +let collation=gbk_chinese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_koi8r.inc b/mysql-test/include/have_koi8r.inc index 1fe163565ba..02647f4555f 100644 --- a/mysql-test/include/have_koi8r.inc +++ b/mysql-test/include/have_koi8r.inc @@ -1,7 +1,2 @@ ---require r/have_koi8r.require - ---disable_query_log - -SHOW COLLATION LIKE 'koi8r_general_ci'; - ---enable_query_log +let collation=koi8r_general_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_latin2_ch.inc b/mysql-test/include/have_latin2_ch.inc index 215715a6aaf..f1e0d4e26aa 100644 --- a/mysql-test/include/have_latin2_ch.inc +++ b/mysql-test/include/have_latin2_ch.inc @@ -1,4 +1,2 @@ --- require r/have_latin2_ch.require -disable_query_log; -show collation like 'latin2_czech_cs'; -enable_query_log; +let collation=latin2_czech_cs; +--source include/have_collation.inc diff --git a/mysql-test/include/have_sjis.inc b/mysql-test/include/have_sjis.inc index ac6531ca868..a25dc51dfa7 100644 --- a/mysql-test/include/have_sjis.inc +++ b/mysql-test/include/have_sjis.inc @@ -1,4 +1,2 @@ --- require r/have_sjis.require -disable_query_log; -show collation like 'sjis_japanese_ci'; -enable_query_log; +let collation=sjis_japanese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_tis620.inc b/mysql-test/include/have_tis620.inc index ad5ba9dea69..d385ff2c621 100644 --- a/mysql-test/include/have_tis620.inc +++ b/mysql-test/include/have_tis620.inc @@ -1,4 +1,2 @@ --- require r/have_tis620.require -disable_query_log; -show collation like 'tis620_thai_ci'; -enable_query_log; +let collation=tis620_thai_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_ucs2.inc b/mysql-test/include/have_ucs2.inc index 324ed52dd02..885e20297aa 100644 --- a/mysql-test/include/have_ucs2.inc +++ b/mysql-test/include/have_ucs2.inc @@ -1,4 +1,2 @@ --- require r/have_ucs2.require -disable_query_log; -show collation like 'ucs2_general_ci'; -enable_query_log; +let collation=ucs2_general_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_ujis.inc b/mysql-test/include/have_ujis.inc index e4b2f50cf93..222c027ca5a 100644 --- a/mysql-test/include/have_ujis.inc +++ b/mysql-test/include/have_ujis.inc @@ -1,4 +1,2 @@ --- require r/have_ujis.require -disable_query_log; -show collation like 'ujis_japanese_ci'; -enable_query_log; +let collation=ujis_japanese_ci; +--source include/have_collation.inc diff --git a/mysql-test/include/have_utf8.inc b/mysql-test/include/have_utf8.inc index 58b74f4072f..177d39abfdc 100644 --- a/mysql-test/include/have_utf8.inc +++ b/mysql-test/include/have_utf8.inc @@ -1,7 +1,2 @@ ---require r/have_utf8.require - ---disable_query_log - -SHOW COLLATION LIKE 'utf8_general_ci'; - ---enable_query_log +let collation=utf8_general_ci; +--source include/have_collation.inc diff --git a/mysql-test/r/create-uca.result b/mysql-test/r/create-uca.result new file mode 100644 index 00000000000..2d2522a36a3 --- /dev/null +++ b/mysql-test/r/create-uca.result @@ -0,0 +1,31 @@ +drop table if exists t1,t2; +CREATE TABLE t1( +c1 INT DEFAULT 12 COMMENT 'column1', +c2 INT NULL COMMENT 'column2', +c3 INT NOT NULL COMMENT 'column3', +c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', +c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b', +c6 VARCHAR(255)) +COLLATE latin1_bin; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) DEFAULT '12' COMMENT 'column1', + `c2` int(11) DEFAULT NULL COMMENT 'column2', + `c3` int(11) NOT NULL COMMENT 'column3', + `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', + `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b', + `c6` varchar(255) COLLATE latin1_bin DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_bin +CREATE TABLE t2 AS SELECT * FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `c1` int(11) DEFAULT '12' COMMENT 'column1', + `c2` int(11) DEFAULT NULL COMMENT 'column2', + `c3` int(11) NOT NULL COMMENT 'column3', + `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', + `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b', + `c6` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1,t2; diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 29686d6e023..dc2cb6786c7 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1792,52 +1792,6 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MEMORY DEFAULT CHARSET=utf8 drop table t1; -# -- -# -- Bug#21380: DEFAULT definition not always transfered by CREATE -# -- TABLE/SELECT to the new table. -# -- - -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t2; - -CREATE TABLE t1( -c1 INT DEFAULT 12 COMMENT 'column1', -c2 INT NULL COMMENT 'column2', -c3 INT NOT NULL COMMENT 'column3', -c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', -c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b', -c6 VARCHAR(255)) -COLLATE latin1_bin; - -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `c1` int(11) DEFAULT '12' COMMENT 'column1', - `c2` int(11) DEFAULT NULL COMMENT 'column2', - `c3` int(11) NOT NULL COMMENT 'column3', - `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', - `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b', - `c6` varchar(255) COLLATE latin1_bin DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_bin - -CREATE TABLE t2 AS SELECT * FROM t1; - -SHOW CREATE TABLE t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `c1` int(11) DEFAULT '12' COMMENT 'column1', - `c2` int(11) DEFAULT NULL COMMENT 'column2', - `c3` int(11) NOT NULL COMMENT 'column3', - `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', - `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b', - `c6` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 - -DROP TABLE t2; -DROP TABLE t1; - -# -- End of test case for Bug#21380. - # -- # -- Bug#18834: ALTER TABLE ADD INDEX on table with two timestamp fields # -- diff --git a/mysql-test/r/have_big5.require b/mysql-test/r/have_big5.require deleted file mode 100644 index 74aacf74b62..00000000000 --- a/mysql-test/r/have_big5.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -big5_chinese_ci big5 1 Yes Yes 1 diff --git a/mysql-test/r/have_cp1250_ch.require b/mysql-test/r/have_cp1250_ch.require deleted file mode 100644 index 2eb834d97e2..00000000000 --- a/mysql-test/r/have_cp1250_ch.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -cp1250_czech_cs cp1250 34 Yes 2 diff --git a/mysql-test/r/have_cp1251.require b/mysql-test/r/have_cp1251.require deleted file mode 100644 index 465e8338084..00000000000 --- a/mysql-test/r/have_cp1251.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -cp1251_general_ci cp1251 51 Yes 0 diff --git a/mysql-test/r/have_cp866.require b/mysql-test/r/have_cp866.require deleted file mode 100644 index da2a3e2f05e..00000000000 --- a/mysql-test/r/have_cp866.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -cp866_general_ci cp866 36 Yes 0 diff --git a/mysql-test/r/have_cp932.require b/mysql-test/r/have_cp932.require deleted file mode 100644 index 988d720ed2c..00000000000 --- a/mysql-test/r/have_cp932.require +++ /dev/null @@ -1,2 +0,0 @@ -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 deleted file mode 100644 index f35621b2c1a..00000000000 --- a/mysql-test/r/have_eucjpms.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -eucjpms_japanese_ci eucjpms 97 Yes Yes 1 diff --git a/mysql-test/r/have_euckr.require b/mysql-test/r/have_euckr.require deleted file mode 100644 index 0771ceec570..00000000000 --- a/mysql-test/r/have_euckr.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -euckr_korean_ci euckr 19 Yes Yes 1 diff --git a/mysql-test/r/have_gb2312.require b/mysql-test/r/have_gb2312.require deleted file mode 100644 index 9bcb7c94a14..00000000000 --- a/mysql-test/r/have_gb2312.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -gb2312_chinese_ci gb2312 24 Yes Yes 1 diff --git a/mysql-test/r/have_gbk.require b/mysql-test/r/have_gbk.require deleted file mode 100644 index e19fead153a..00000000000 --- a/mysql-test/r/have_gbk.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -gbk_chinese_ci gbk 28 Yes Yes 1 diff --git a/mysql-test/r/have_koi8r.require b/mysql-test/r/have_koi8r.require deleted file mode 100644 index b109b9ae520..00000000000 --- a/mysql-test/r/have_koi8r.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -koi8r_general_ci koi8r 7 Yes 0 diff --git a/mysql-test/r/have_latin2_ch.require b/mysql-test/r/have_latin2_ch.require deleted file mode 100644 index 352401bbfe8..00000000000 --- a/mysql-test/r/have_latin2_ch.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -latin2_czech_cs latin2 2 Yes 4 diff --git a/mysql-test/r/have_sjis.require b/mysql-test/r/have_sjis.require deleted file mode 100644 index 72ce8ec88fe..00000000000 --- a/mysql-test/r/have_sjis.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -sjis_japanese_ci sjis 13 Yes Yes 1 diff --git a/mysql-test/r/have_tis620.require b/mysql-test/r/have_tis620.require deleted file mode 100644 index a1bf93ac491..00000000000 --- a/mysql-test/r/have_tis620.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -tis620_thai_ci tis620 18 Yes Yes 4 diff --git a/mysql-test/r/have_ucs2.require b/mysql-test/r/have_ucs2.require deleted file mode 100644 index c53250aeaef..00000000000 --- a/mysql-test/r/have_ucs2.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -ucs2_general_ci ucs2 35 Yes Yes 1 diff --git a/mysql-test/r/have_ujis.require b/mysql-test/r/have_ujis.require deleted file mode 100644 index 43a309ad74e..00000000000 --- a/mysql-test/r/have_ujis.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -ujis_japanese_ci ujis 12 Yes Yes 1 diff --git a/mysql-test/r/have_utf8.require b/mysql-test/r/have_utf8.require deleted file mode 100644 index 71f8ccfff47..00000000000 --- a/mysql-test/r/have_utf8.require +++ /dev/null @@ -1,2 +0,0 @@ -Collation Charset Id Default Compiled Sortlen -utf8_general_ci utf8 33 Yes Yes 1 diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 845083af478..021bf34a132 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -3160,15 +3160,6 @@ ALTER TABLE t2 MODIFY a INT NOT NULL; ERROR HY000: Error on rename of '#sql-temporary' to './test/t2' (errno: 150) DELETE FROM t1; DROP TABLE t2,t1; -CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY) -ENGINE=InnoDB; -INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4); -DELETE FROM t1; -INSERT INTO t1 VALUES ('DDD'); -SELECT * FROM t1; -a -DDD -DROP TABLE t1; CREATE TABLE t1 (id int PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB AUTO_INCREMENT=42; INSERT INTO t1 VALUES (0),(347),(0); diff --git a/mysql-test/r/innodb_utf8.result b/mysql-test/r/innodb_utf8.result new file mode 100644 index 00000000000..cdac7cdb65b --- /dev/null +++ b/mysql-test/r/innodb_utf8.result @@ -0,0 +1,10 @@ +drop table if exists t1; +CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4); +DELETE FROM t1; +INSERT INTO t1 VALUES ('DDD'); +SELECT * FROM t1; +a +DDD +DROP TABLE t1; diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table.test b/mysql-test/suite/rpl/t/rpl_ignore_table.test index 66f96e8f4e8..15c4b193669 100644 --- a/mysql-test/suite/rpl/t/rpl_ignore_table.test +++ b/mysql-test/suite/rpl/t/rpl_ignore_table.test @@ -1,4 +1,6 @@ source include/master-slave.inc; +let collation=utf8_unicode_ci; +--source include/have_collation.inc # # BUG#16487 diff --git a/mysql-test/t/create-uca.test b/mysql-test/t/create-uca.test new file mode 100644 index 00000000000..0acb51f7286 --- /dev/null +++ b/mysql-test/t/create-uca.test @@ -0,0 +1,26 @@ +# Prerequisites +let collation=utf8_unicode_ci; +--source include/have_collation.inc + +# Initial cleanup +--disable_warnings +drop table if exists t1,t2; +--enable_warnings + +# +# Bug#21380: DEFAULT definition not always transfered by CREATE +# TABLE/SELECT to the new table. +# + +CREATE TABLE t1( + c1 INT DEFAULT 12 COMMENT 'column1', + c2 INT NULL COMMENT 'column2', + c3 INT NOT NULL COMMENT 'column3', + c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', + c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b', + c6 VARCHAR(255)) + COLLATE latin1_bin; +SHOW CREATE TABLE t1; +CREATE TABLE t2 AS SELECT * FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t1,t2; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 885803cb90f..57f4c82df87 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -1398,52 +1398,6 @@ drop table t1; ########################################################################### ---echo ---echo # -- ---echo # -- Bug#21380: DEFAULT definition not always transfered by CREATE ---echo # -- TABLE/SELECT to the new table. ---echo # -- ---echo - - ---disable_warnings -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t2; ---enable_warnings - ---echo - -CREATE TABLE t1( - c1 INT DEFAULT 12 COMMENT 'column1', - c2 INT NULL COMMENT 'column2', - c3 INT NOT NULL COMMENT 'column3', - c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', - c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b', - c6 VARCHAR(255)) - COLLATE latin1_bin; - ---echo - -SHOW CREATE TABLE t1; - ---echo - -CREATE TABLE t2 AS SELECT * FROM t1; - ---echo - -SHOW CREATE TABLE t2; - ---echo - -DROP TABLE t2; -DROP TABLE t1; - ---echo ---echo # -- End of test case for Bug#21380. - -########################################################################### - --echo --echo # -- --echo # -- Bug#18834: ALTER TABLE ADD INDEX on table with two timestamp fields diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index bb64319f1e4..e222bc6b836 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -2,6 +2,15 @@ # Tests with the utf8 character set # +let collation=utf8_unicode_ci; +--source include/have_collation.inc + +--disable_warnings +drop table if exists t1,t2,t3,t4; +drop database if exists mysqltest; +--enable_warnings + + --disable_warnings drop table if exists t1,t2; --enable_warnings diff --git a/mysql-test/t/ddl_i18n_koi8r.test b/mysql-test/t/ddl_i18n_koi8r.test index fecef2f95d5..9df9806526c 100644 --- a/mysql-test/t/ddl_i18n_koi8r.test +++ b/mysql-test/t/ddl_i18n_koi8r.test @@ -36,6 +36,8 @@ --source include/have_cp866.inc --source include/have_cp1251.inc --source include/have_koi8r.inc +let collation=utf8_unicode_ci; +--source include/have_collation.inc ########################################################################### diff --git a/mysql-test/t/ddl_i18n_utf8.test b/mysql-test/t/ddl_i18n_utf8.test index 8788d0604f2..1d8c5676dee 100644 --- a/mysql-test/t/ddl_i18n_utf8.test +++ b/mysql-test/t/ddl_i18n_utf8.test @@ -36,6 +36,8 @@ --source include/have_cp866.inc --source include/have_cp1251.inc --source include/have_koi8r.inc +let collation=utf8_unicode_ci; +--source include/have_collation.inc ########################################################################### diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 9db55f6adaa..766e6d12cf4 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -2,6 +2,9 @@ # Test of fulltext index # +let collation=utf8_unicode_ci; +--source include/have_collation.inc + --disable_warnings drop table if exists t1,t2,t3; --enable_warnings diff --git a/mysql-test/t/fulltext2.test b/mysql-test/t/fulltext2.test index 9635e14d427..78c7c859e95 100644 --- a/mysql-test/t/fulltext2.test +++ b/mysql-test/t/fulltext2.test @@ -2,6 +2,9 @@ # test of new fulltext search features # +let collation=utf8_unicode_ci; +--source include/have_collation.inc + # # two-level tree # diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 6eb32b554bb..599c6f10d23 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -2352,18 +2352,6 @@ ALTER TABLE t2 MODIFY a INT NOT NULL; DELETE FROM t1; DROP TABLE t2,t1; -# -# Bug #26835: table corruption after delete+insert -# - -CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY) -ENGINE=InnoDB; -INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4); -DELETE FROM t1; -INSERT INTO t1 VALUES ('DDD'); -SELECT * FROM t1; -DROP TABLE t1; - # # Bug #23313 (AUTO_INCREMENT=# not reported back for InnoDB tables) # Bug #21404 (AUTO_INCREMENT value reset when Adding FKEY (or ALTER?)) diff --git a/mysql-test/t/innodb_utf8.test b/mysql-test/t/innodb_utf8.test new file mode 100644 index 00000000000..e52019588b0 --- /dev/null +++ b/mysql-test/t/innodb_utf8.test @@ -0,0 +1,24 @@ +# +# Tests for innodb that requires not default character sets +# + +--source include/have_innodb.inc +let collation=utf8_unicode_ci; +--source include/have_collation.inc + +# Setup +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# Bug #26835: table corruption after delete+insert +# + +CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4); +DELETE FROM t1; +INSERT INTO t1 VALUES ('DDD'); +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/t/query_cache_ps_no_prot.test b/mysql-test/t/query_cache_ps_no_prot.test index 6f4263eeef9..16533c7194e 100644 --- a/mysql-test/t/query_cache_ps_no_prot.test +++ b/mysql-test/t/query_cache_ps_no_prot.test @@ -11,8 +11,9 @@ # We cannot run on embedded server because we use multiple sessions. --source include/not_embedded.inc - --source include/have_query_cache.inc +let collation=utf8_unicode_ci; +--source include/have_collation.inc # The file with expected results fits only to a run without # ps-protocol/sp-protocol/cursor-protocol/view-protocol. diff --git a/mysql-test/t/query_cache_ps_ps_prot.test b/mysql-test/t/query_cache_ps_ps_prot.test index dc49624788a..d431ce349d2 100644 --- a/mysql-test/t/query_cache_ps_ps_prot.test +++ b/mysql-test/t/query_cache_ps_ps_prot.test @@ -11,8 +11,9 @@ # We cannot run on embedded server because we use multiple sessions. --source include/not_embedded.inc - --source include/have_query_cache.inc +let collation=utf8_unicode_ci; +--source include/have_collation.inc # The file with expected results fits only to a run with "--ps-protocol". if (`SELECT $SP_PROTOCOL + $CURSOR_PROTOCOL + $VIEW_PROTOCOL > 0 diff --git a/scripts/mysqlbug.sh b/scripts/mysqlbug.sh index 64804b5de19..f0534d0e1e9 100644 --- a/scripts/mysqlbug.sh +++ b/scripts/mysqlbug.sh @@ -21,7 +21,7 @@ echo "Finding system information for a MySQL bug report" VERSION="@VERSION@@MYSQL_SERVER_SUFFIX@" COMPILATION_COMMENT="@COMPILATION_COMMENT@" -BUGmysql="mysql@lists.mysql.com" +BUGmysql="maria-developers@lists.launchpad.net" # This is set by configure COMP_CALL_INFO="CC='@SAVE_CC@' CFLAGS='@SAVE_CFLAGS@' CXX='@SAVE_CXX@' CXXFLAGS='@SAVE_CXXFLAGS@' LDFLAGS='@SAVE_LDFLAGS@' ASFLAGS='@SAVE_ASFLAGS@'" COMP_RUN_INFO="CC='@CC@' CFLAGS='@CFLAGS@' CXX='@CXX@' CXXFLAGS='@CXXFLAGS@' LDFLAGS='@LDFLAGS@' ASFLAGS='@ASFLAGS@'" diff --git a/storage/ndb/plug.in b/storage/ndb/plug.in index a7e351417b1..3d3349f7a8b 100644 --- a/storage/ndb/plug.in +++ b/storage/ndb/plug.in @@ -1,5 +1,5 @@ MYSQL_STORAGE_ENGINE(ndbcluster, ndbcluster, [Cluster Storage Engine], - [High Availability Clustered tables], [max]) + [High Availability Clustered tables],) MYSQL_PLUGIN_DIRECTORY(ndbcluster,[storage/ndb]) MYSQL_PLUGIN_STATIC(ndbcluster, [[\$(ndbcluster_libs) \$(ndbcluster_system_libs) \$(NDB_SCI_LIBS)]]) MYSQL_PLUGIN_ACTIONS(ndbcluster,[MYSQL_SETUP_NDBCLUSTER]) From 71061de025de2e9bffaaecdd182ad7f7ccd924d0 Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Wed, 30 Dec 2009 23:06:14 +0100 Subject: [PATCH 210/344] Removed unwanted Perl DBI dependency --- support-files/mysql.spec.sh | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 8209c4560c6..b6d822d8719 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -65,6 +65,19 @@ # See BUG#998 for details. %define _unpackaged_files_terminate_build 0 +# ------------------------------------------------------------------------------ +# RPM build tools now automatically detects Perl module dependencies. This +# detection gives problems as it is broken in some versions, and it also +# give unwanted dependencies from mandatory scripts in our package. +# Might not be possible to disable in all RPM tool versions, but here we +# try. We keep the "AutoReqProv: no" for the "test" sub package, as disabling +# here might fail, and that package has the most problems. +# See http://fedoraproject.org/wiki/Packaging/Perl#Filtering_Requires:_and_Provides +# http://www.wideopen.com/archives/rpm-list/2002-October/msg00343.html +# ------------------------------------------------------------------------------ +%undefine __perl_provides +%undefine __perl_requires + %define see_base For a description of MySQL see the base MySQL RPM or http://www.mysql.com # On SuSE 9 no separate "debuginfo" package is built. To enable basic @@ -205,7 +218,7 @@ They should be used with caution. %endif %package test -Requires: %{name}-client perl-DBI perl +Requires: %{name}-client perl Summary: MySQL - Test suite Group: Applications/Databases Provides: mysql-test From 2b2ce3d6cb01a36cd35191e8670dcb023420c84e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 31 Dec 2009 11:33:10 +0800 Subject: [PATCH 211/344] Bug #49137 Replication failure on SBR/MBR + multi-table DROP TEMPORARY TABLE In statement-based or mixed-mode replication, use DROP TEMPORARY TABLE to drop multiple tables causes different errors on master and slave, when one or more of these tables do not exist. Because when executed on slave, it would automatically add IF EXISTS to the query to ignore all ER_BAD_TABLE_ERROR errors. To fix the problem, do not add IF EXISTS when executing DROP TEMPORARY TABLE on the slave, and clear the ER_BAD_TABLE_ERROR error after execution if the query does not expect any errors. mysql-test/r/rpl_drop_temp.result: Updated for the patch of bug#49137. mysql-test/t/rpl_drop_temp.test: Added the test file to verify if DROP MULTI TEMPORARY TABLE will cause different errors on master and slave, when one or more of these tables do not exist. sql/log_event.cc: Added code to handle above cases which are removed from sql_parse.cc sql/sql_parse.cc: Remove the code to issue the 'Unknown table' error, if the temporary table does not exist when dropping it on slave. The above cases decribed in comments will be handled later in log_event.cc. --- mysql-test/r/rpl_drop_temp.result | 14 +++++++++++++ mysql-test/t/rpl_drop_temp.test | 33 +++++++++++++++++++++++++++++++ sql/log_event.cc | 12 ++++++++++- sql/sql_parse.cc | 11 ----------- 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/rpl_drop_temp.result b/mysql-test/r/rpl_drop_temp.result index fff179d7056..48a21b1702b 100644 --- a/mysql-test/r/rpl_drop_temp.result +++ b/mysql-test/r/rpl_drop_temp.result @@ -18,3 +18,17 @@ show status like 'Slave_open_temp_tables'; Variable_name Value Slave_open_temp_tables 0 drop database mysqltest; +DROP TEMPORARY TABLE IF EXISTS tmp1; +Warnings: +Note 1051 Unknown table 'tmp1' +CREATE TEMPORARY TABLE t1 ( a int ); +DROP TEMPORARY TABLE t1, t2; +ERROR 42S02: Unknown table 't2' +DROP TEMPORARY TABLE tmp2; +ERROR 42S02: Unknown table 'tmp2' +stop slave; +**** On Master **** +CREATE TEMPORARY TABLE tmp3 (a int); +DROP TEMPORARY TABLE tmp3; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; diff --git a/mysql-test/t/rpl_drop_temp.test b/mysql-test/t/rpl_drop_temp.test index c22bcbe63d0..c2dc8b0ea49 100644 --- a/mysql-test/t/rpl_drop_temp.test +++ b/mysql-test/t/rpl_drop_temp.test @@ -20,5 +20,38 @@ connection slave; show status like 'Slave_open_temp_tables'; connection master; drop database mysqltest; +sync_slave_with_master; + +# +# Bug#49137 +# This test verifies if DROP MULTI TEMPORARY TABLE +# will cause different errors on master and slave, +# when one or more of these tables do not exist. +# + +connection master; +DROP TEMPORARY TABLE IF EXISTS tmp1; +CREATE TEMPORARY TABLE t1 ( a int ); +--error 1051 +DROP TEMPORARY TABLE t1, t2; +--error 1051 +DROP TEMPORARY TABLE tmp2; +sync_slave_with_master; + +connection slave; +stop slave; +wait_for_slave_to_stop; + +--echo **** On Master **** +connection master; +CREATE TEMPORARY TABLE tmp3 (a int); +DROP TEMPORARY TABLE tmp3; + +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; + +connection master; +sync_slave_with_master; # End of 4.1 tests diff --git a/sql/log_event.cc b/sql/log_event.cc index 40e29e58ab6..35d53c4fede 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2103,7 +2103,17 @@ START SLAVE; . Query: '%s'", expected_error, thd->query); compare_errors: - /* + /* + In the slave thread, we may sometimes execute some DROP / * 40005 + TEMPORARY * / TABLE that come from parts of binlogs (likely if we + use RESET SLAVE or CHANGE MASTER TO), while the temporary table + has already been dropped. To ignore such irrelevant "table does + not exist errors", we silently clear the error if TEMPORARY was used. + */ + if (thd->lex->drop_temporary && + thd->net.last_errno == ER_BAD_TABLE_ERROR && !expected_error) + thd->clear_error(); + /* If we expected a non-zero error code, and we don't get the same error code, and none of them should be ignored. */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 48df40f2614..61c2d70a563 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4038,17 +4038,6 @@ end_with_restore_list: } else { - /* - If this is a slave thread, we may sometimes execute some - DROP / * 40005 TEMPORARY * / TABLE - that come from parts of binlogs (likely if we use RESET SLAVE or CHANGE - MASTER TO), while the temporary table has already been dropped. - To not generate such irrelevant "table does not exist errors", - we silently add IF EXISTS if TEMPORARY was used. - */ - if (thd->slave_thread) - lex->drop_if_exists= 1; - /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */ thd->transaction.all.modified_non_trans_table= TRUE; } From 7ae95fdef2b5d4880d381d6ed46ad4aa996b03d3 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 4 Jan 2010 14:35:54 +0200 Subject: [PATCH 212/344] Updated test results (missed this one in last patch) --- mysql-test/r/ctype_utf8.result | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 4cfd06149f1..b3084d182a6 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1,3 +1,5 @@ +drop table if exists t1,t2,t3,t4; +drop database if exists mysqltest; drop table if exists t1,t2; set names utf8; select left(_utf8 0xD0B0D0B1D0B2,1); From fa609710375a68c244179e58e53b2980387a84d0 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 4 Jan 2010 20:25:29 +0200 Subject: [PATCH 213/344] Fixed bug in tc.log recovery code that caused crash_commit_before to sometimes crash. --- sql/log.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/log.cc b/sql/log.cc index 9ed594bfb36..6d1a8bf47a8 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5154,8 +5154,8 @@ int TC_LOG_MMAP::open(const char *opt_name) pthread_mutex_init(&pg->lock, MY_MUTEX_INIT_FAST); pthread_cond_init (&pg->cond, 0); pg->start=(my_xid *)(data + i*tc_log_page_size); - pg->end=(my_xid *)(pg->start + tc_log_page_size); pg->size=pg->free=tc_log_page_size/sizeof(my_xid); + pg->end=pg->start + pg->size; } pages[0].size=pages[0].free= (tc_log_page_size-TC_LOG_HEADER_SIZE)/sizeof(my_xid); From ce068186f698872e6d7c7f475ffa2bca664f070d Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 4 Jan 2010 20:31:26 +0200 Subject: [PATCH 214/344] Fixed bug in my_uuid() that caused failures on hpux and ia64 --- mysys/my_uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/my_uuid.c b/mysys/my_uuid.c index d1e8331aaa1..f115806b4e9 100644 --- a/mysys/my_uuid.c +++ b/mysys/my_uuid.c @@ -108,7 +108,7 @@ void my_uuid_init(ulong seed1, ulong seed2) */ /* purecov: begin inspected */ my_rnd_init(&uuid_rand, (ulong) (seed2+ now/2), (ulong) (now+rand())); - for (i=0; i < sizeof(mac); i++) + for (i=0; i < array_elements(uuid_suffix) -2 ; i++) mac[i]= (uchar)(my_rnd(&uuid_rand)*255); /* purecov: end */ } From af27d4e2003a84a28007a99053aefecafd7ecd97 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Tue, 5 Jan 2010 14:25:29 +0800 Subject: [PATCH 215/344] Bug#48776 row based replication breaks with spatial / geometry types, cause crashes! This bug is the same problem as Bug 49836 for 5.1 versions. mysql-test/suite/rpl/r/rpl_geometry.result: Test case for bug 48776 mysql-test/suite/rpl/t/rpl_geometry.test: Test case for bug 48776 sql/rpl_utility.h: Add missing case MYSQL_TYPE_GEOMETRY --- mysql-test/suite/rpl/r/rpl_geometry.result | 18 +++++++++++++++ mysql-test/suite/rpl/t/rpl_geometry.test | 26 ++++++++++++++++++++++ sql/rpl_utility.h | 1 + 3 files changed, 45 insertions(+) create mode 100644 mysql-test/suite/rpl/r/rpl_geometry.result create mode 100644 mysql-test/suite/rpl/t/rpl_geometry.test diff --git a/mysql-test/suite/rpl/r/rpl_geometry.result b/mysql-test/suite/rpl/r/rpl_geometry.result new file mode 100644 index 00000000000..9b48dba4f22 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_geometry.result @@ -0,0 +1,18 @@ +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 varchar(100), +b multipoint not null, +c varchar(256)); +insert into t1 set +a='hello', +b=geomfromtext('multipoint(1 1)'), +c='geometry'; +create table t2 (a int(11) not null auto_increment primary key, +b geometrycollection default null, +c decimal(10,0)); +insert into t2(c) values (null); +drop table t1, t2; diff --git a/mysql-test/suite/rpl/t/rpl_geometry.test b/mysql-test/suite/rpl/t/rpl_geometry.test new file mode 100644 index 00000000000..eac98924b98 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_geometry.test @@ -0,0 +1,26 @@ +source include/master-slave.inc; +source include/have_binlog_format_row.inc; + +# +# Bug#48776, Bug#43784 +# +create table t1(a varchar(100), + b multipoint not null, + c varchar(256)); + +insert into t1 set + a='hello', + b=geomfromtext('multipoint(1 1)'), + c='geometry'; + +create table t2 (a int(11) not null auto_increment primary key, + b geometrycollection default null, + c decimal(10,0)); + +insert into t2(c) values (null); + +sync_slave_with_master; + +connection master; +drop table t1, t2; +source include/master-slave-end.inc; diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h index 1f4ca246ff1..d011e9aade8 100644 --- a/sql/rpl_utility.h +++ b/sql/rpl_utility.h @@ -95,6 +95,7 @@ public: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_DOUBLE: case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_GEOMETRY: { /* These types store a single byte. From f8758031f37840b4b1cea4f4c3aa8736b7d68f88 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Wed, 6 Jan 2010 00:44:31 +0000 Subject: [PATCH 216/344] BUG#50018: binlog corruption when table has many columns For tables with metadata sizes ranging from 251 to 255 the size of the event data (m_data_size) was being improperly calculated in the Table_map_log_event constructor. This was due to the fact that when writing the Table_map_log_event body (in Table_map_log_event::write_data_body) a call to net_store_length is made for packing the m_field_metadata_size. It happens that net_store_length uses *one* byte for storing m_field_metadata_size when it is smaller than 251 but *three* bytes when it exceeds that value. BUG 42749 had already pinpointed and fix this fact, but the fix was incomplete, as the calculation in the Table_map_log_event constructor considers 255 instead of 251 as the threshold to increment m_data_size by three. Thence, the window for having a mismatch between the number of bytes written and the number of bytes accounted in the event length (m_data_size) was left open for m_field_metadata_size values between 251 and 255. We fix this by changing the condition in the Table_map_log_event constructor to match the one in the net_store_length, ie, increment one byte if m_field_metadata_size < 251 and three if it exceeds this value. mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result: Updated result file. mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test: Changes to the original test case: added slave and moved file into the rpl suite. New test case: replicates two tables one with 250 and another with 252 metadata sizes. This exercises the usage of 1 or 3 bytes while packing the m_field_metadata_size. sql/log_event.cc: Made the m_data_size calculation for the table map log event to match the number of bytes used while packing the m_field_metadata_size value (according to net_store_length function in pack.c). --- .../suite/binlog/r/binlog_tbl_metadata.result | 156 ------ .../suite/binlog/t/binlog_tbl_metadata.test | 199 ------- .../suite/rpl/r/rpl_row_tbl_metadata.result | 437 +++++++++++++++ .../suite/rpl/t/rpl_row_tbl_metadata.test | 520 ++++++++++++++++++ sql/log_event.cc | 6 +- 5 files changed, 960 insertions(+), 358 deletions(-) delete mode 100644 mysql-test/suite/binlog/r/binlog_tbl_metadata.result delete mode 100644 mysql-test/suite/binlog/t/binlog_tbl_metadata.test create mode 100644 mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result create mode 100644 mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test diff --git a/mysql-test/suite/binlog/r/binlog_tbl_metadata.result b/mysql-test/suite/binlog/r/binlog_tbl_metadata.result deleted file mode 100644 index a2f185edc85..00000000000 --- a/mysql-test/suite/binlog/r/binlog_tbl_metadata.result +++ /dev/null @@ -1,156 +0,0 @@ -RESET MASTER; -DROP TABLE IF EXISTS `t1`; -CREATE TABLE `t1` ( -`c1` int(11) NOT NULL AUTO_INCREMENT, -`c2` varchar(30) NOT NULL, -`c3` varchar(30) DEFAULT NULL, -`c4` varchar(30) DEFAULT NULL, -`c5` varchar(30) DEFAULT NULL, -`c6` varchar(30) DEFAULT NULL, -`c7` varchar(30) DEFAULT NULL, -`c8` varchar(30) DEFAULT NULL, -`c9` varchar(30) DEFAULT NULL, -`c10` varchar(30) DEFAULT NULL, -`c11` varchar(30) DEFAULT NULL, -`c12` varchar(30) DEFAULT NULL, -`c13` varchar(30) DEFAULT NULL, -`c14` varchar(30) DEFAULT NULL, -`c15` varchar(30) DEFAULT NULL, -`c16` varchar(30) DEFAULT NULL, -`c17` varchar(30) DEFAULT NULL, -`c18` varchar(30) DEFAULT NULL, -`c19` varchar(30) DEFAULT NULL, -`c20` varchar(30) DEFAULT NULL, -`c21` varchar(30) DEFAULT NULL, -`c22` varchar(30) DEFAULT NULL, -`c23` varchar(30) DEFAULT NULL, -`c24` varchar(30) DEFAULT NULL, -`c25` varchar(30) DEFAULT NULL, -`c26` varchar(30) DEFAULT NULL, -`c27` varchar(30) DEFAULT NULL, -`c28` varchar(30) DEFAULT NULL, -`c29` varchar(30) DEFAULT NULL, -`c30` varchar(30) DEFAULT NULL, -`c31` varchar(30) DEFAULT NULL, -`c32` varchar(30) DEFAULT NULL, -`c33` varchar(30) DEFAULT NULL, -`c34` varchar(30) DEFAULT NULL, -`c35` varchar(30) DEFAULT NULL, -`c36` varchar(30) DEFAULT NULL, -`c37` varchar(30) DEFAULT NULL, -`c38` varchar(30) DEFAULT NULL, -`c39` varchar(30) DEFAULT NULL, -`c40` varchar(30) DEFAULT NULL, -`c41` varchar(30) DEFAULT NULL, -`c42` varchar(30) DEFAULT NULL, -`c43` varchar(30) DEFAULT NULL, -`c44` varchar(30) DEFAULT NULL, -`c45` varchar(30) DEFAULT NULL, -`c46` varchar(30) DEFAULT NULL, -`c47` varchar(30) DEFAULT NULL, -`c48` varchar(30) DEFAULT NULL, -`c49` varchar(30) DEFAULT NULL, -`c50` varchar(30) DEFAULT NULL, -`c51` varchar(30) DEFAULT NULL, -`c52` varchar(30) DEFAULT NULL, -`c53` varchar(30) DEFAULT NULL, -`c54` varchar(30) DEFAULT NULL, -`c55` varchar(30) DEFAULT NULL, -`c56` varchar(30) DEFAULT NULL, -`c57` varchar(30) DEFAULT NULL, -`c58` varchar(30) DEFAULT NULL, -`c59` varchar(30) DEFAULT NULL, -`c60` varchar(30) DEFAULT NULL, -`c61` varchar(30) DEFAULT NULL, -`c62` varchar(30) DEFAULT NULL, -`c63` varchar(30) DEFAULT NULL, -`c64` varchar(30) DEFAULT NULL, -`c65` varchar(30) DEFAULT NULL, -`c66` varchar(30) DEFAULT NULL, -`c67` varchar(30) DEFAULT NULL, -`c68` varchar(30) DEFAULT NULL, -`c69` varchar(30) DEFAULT NULL, -`c70` varchar(30) DEFAULT NULL, -`c71` varchar(30) DEFAULT NULL, -`c72` varchar(30) DEFAULT NULL, -`c73` varchar(30) DEFAULT NULL, -`c74` varchar(30) DEFAULT NULL, -`c75` varchar(30) DEFAULT NULL, -`c76` varchar(30) DEFAULT NULL, -`c77` varchar(30) DEFAULT NULL, -`c78` varchar(30) DEFAULT NULL, -`c79` varchar(30) DEFAULT NULL, -`c80` varchar(30) DEFAULT NULL, -`c81` varchar(30) DEFAULT NULL, -`c82` varchar(30) DEFAULT NULL, -`c83` varchar(30) DEFAULT NULL, -`c84` varchar(30) DEFAULT NULL, -`c85` varchar(30) DEFAULT NULL, -`c86` varchar(30) DEFAULT NULL, -`c87` varchar(30) DEFAULT NULL, -`c88` varchar(30) DEFAULT NULL, -`c89` varchar(30) DEFAULT NULL, -`c90` varchar(30) DEFAULT NULL, -`c91` varchar(30) DEFAULT NULL, -`c92` varchar(30) DEFAULT NULL, -`c93` varchar(30) DEFAULT NULL, -`c94` varchar(30) DEFAULT NULL, -`c95` varchar(30) DEFAULT NULL, -`c96` varchar(30) DEFAULT NULL, -`c97` varchar(30) DEFAULT NULL, -`c98` varchar(30) DEFAULT NULL, -`c99` varchar(30) DEFAULT NULL, -`c100` varchar(30) DEFAULT NULL, -`c101` varchar(30) DEFAULT NULL, -`c102` varchar(30) DEFAULT NULL, -`c103` varchar(30) DEFAULT NULL, -`c104` varchar(30) DEFAULT NULL, -`c105` varchar(30) DEFAULT NULL, -`c106` varchar(30) DEFAULT NULL, -`c107` varchar(30) DEFAULT NULL, -`c108` varchar(30) DEFAULT NULL, -`c109` varchar(30) DEFAULT NULL, -`c110` varchar(30) DEFAULT NULL, -`c111` varchar(30) DEFAULT NULL, -`c112` varchar(30) DEFAULT NULL, -`c113` varchar(30) DEFAULT NULL, -`c114` varchar(30) DEFAULT NULL, -`c115` varchar(30) DEFAULT NULL, -`c116` varchar(30) DEFAULT NULL, -`c117` varchar(30) DEFAULT NULL, -`c118` varchar(30) DEFAULT NULL, -`c119` varchar(30) DEFAULT NULL, -`c120` varchar(30) DEFAULT NULL, -`c121` varchar(30) DEFAULT NULL, -`c122` varchar(30) DEFAULT NULL, -`c123` varchar(30) DEFAULT NULL, -`c124` varchar(30) DEFAULT NULL, -`c125` varchar(30) DEFAULT NULL, -`c126` varchar(30) DEFAULT NULL, -`c127` varchar(30) DEFAULT NULL, -`c128` varchar(30) DEFAULT NULL, -`c129` varchar(30) DEFAULT NULL, -`c130` varchar(30) DEFAULT NULL, -`c131` varchar(30) DEFAULT NULL, -`c132` varchar(30) DEFAULT NULL, -`c133` varchar(30) DEFAULT NULL, -`c134` varchar(30) DEFAULT NULL, -`c135` varchar(30) DEFAULT NULL, -`c136` varchar(30) DEFAULT NULL, -`c137` varchar(30) DEFAULT NULL, -`c138` varchar(30) DEFAULT NULL, -`c139` varchar(30) DEFAULT NULL, -`c140` varchar(30) DEFAULT NULL, -`c141` varchar(30) DEFAULT NULL, -`c142` varchar(30) DEFAULT NULL, -`c143` varchar(30) DEFAULT NULL, -`c144` varchar(30) DEFAULT NULL, -`c145` varchar(30) DEFAULT NULL, -`c146` varchar(30) DEFAULT NULL, -PRIMARY KEY (`c1`) -) ENGINE=InnoDB; -LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); -DROP TABLE `t1`; -FLUSH LOGS; -=== Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. diff --git a/mysql-test/suite/binlog/t/binlog_tbl_metadata.test b/mysql-test/suite/binlog/t/binlog_tbl_metadata.test deleted file mode 100644 index 5e847ab5fbd..00000000000 --- a/mysql-test/suite/binlog/t/binlog_tbl_metadata.test +++ /dev/null @@ -1,199 +0,0 @@ -# -# BUG#42749: infinite loop writing to row based binlog - processlist shows -# "freeing items" -# -# WHY -# === -# -# This bug would make table map event to report data_written one byte less -# than what would actually be written in its body. This would cause one byte shorter -# event end_log_pos. The ultimate impact was that it would make fixing the -# position in MYSQL_BIN_LOG::write_cache bogus or end up in an infinite loop. -# -# HOW -# === -# -# Checking that the patch fixes the problem is done as follows: -# i) a table with several fields is created; -# ii) an insert is performed; -# iii) the logs are flushed; -# iv) mysqlbinlog is used to check if it succeeds. -# -# In step iv), before the bug was fixed, the test case would fail with -# mysqlbinlog reporting that it was unable to succeed in reading the event. -# - --- source include/have_log_bin.inc --- source include/have_innodb.inc --- source include/have_binlog_format_row.inc --- connection default - -RESET MASTER; - --- disable_warnings -DROP TABLE IF EXISTS `t1`; --- enable_warnings - -CREATE TABLE `t1` ( - `c1` int(11) NOT NULL AUTO_INCREMENT, - `c2` varchar(30) NOT NULL, - `c3` varchar(30) DEFAULT NULL, - `c4` varchar(30) DEFAULT NULL, - `c5` varchar(30) DEFAULT NULL, - `c6` varchar(30) DEFAULT NULL, - `c7` varchar(30) DEFAULT NULL, - `c8` varchar(30) DEFAULT NULL, - `c9` varchar(30) DEFAULT NULL, - `c10` varchar(30) DEFAULT NULL, - `c11` varchar(30) DEFAULT NULL, - `c12` varchar(30) DEFAULT NULL, - `c13` varchar(30) DEFAULT NULL, - `c14` varchar(30) DEFAULT NULL, - `c15` varchar(30) DEFAULT NULL, - `c16` varchar(30) DEFAULT NULL, - `c17` varchar(30) DEFAULT NULL, - `c18` varchar(30) DEFAULT NULL, - `c19` varchar(30) DEFAULT NULL, - `c20` varchar(30) DEFAULT NULL, - `c21` varchar(30) DEFAULT NULL, - `c22` varchar(30) DEFAULT NULL, - `c23` varchar(30) DEFAULT NULL, - `c24` varchar(30) DEFAULT NULL, - `c25` varchar(30) DEFAULT NULL, - `c26` varchar(30) DEFAULT NULL, - `c27` varchar(30) DEFAULT NULL, - `c28` varchar(30) DEFAULT NULL, - `c29` varchar(30) DEFAULT NULL, - `c30` varchar(30) DEFAULT NULL, - `c31` varchar(30) DEFAULT NULL, - `c32` varchar(30) DEFAULT NULL, - `c33` varchar(30) DEFAULT NULL, - `c34` varchar(30) DEFAULT NULL, - `c35` varchar(30) DEFAULT NULL, - `c36` varchar(30) DEFAULT NULL, - `c37` varchar(30) DEFAULT NULL, - `c38` varchar(30) DEFAULT NULL, - `c39` varchar(30) DEFAULT NULL, - `c40` varchar(30) DEFAULT NULL, - `c41` varchar(30) DEFAULT NULL, - `c42` varchar(30) DEFAULT NULL, - `c43` varchar(30) DEFAULT NULL, - `c44` varchar(30) DEFAULT NULL, - `c45` varchar(30) DEFAULT NULL, - `c46` varchar(30) DEFAULT NULL, - `c47` varchar(30) DEFAULT NULL, - `c48` varchar(30) DEFAULT NULL, - `c49` varchar(30) DEFAULT NULL, - `c50` varchar(30) DEFAULT NULL, - `c51` varchar(30) DEFAULT NULL, - `c52` varchar(30) DEFAULT NULL, - `c53` varchar(30) DEFAULT NULL, - `c54` varchar(30) DEFAULT NULL, - `c55` varchar(30) DEFAULT NULL, - `c56` varchar(30) DEFAULT NULL, - `c57` varchar(30) DEFAULT NULL, - `c58` varchar(30) DEFAULT NULL, - `c59` varchar(30) DEFAULT NULL, - `c60` varchar(30) DEFAULT NULL, - `c61` varchar(30) DEFAULT NULL, - `c62` varchar(30) DEFAULT NULL, - `c63` varchar(30) DEFAULT NULL, - `c64` varchar(30) DEFAULT NULL, - `c65` varchar(30) DEFAULT NULL, - `c66` varchar(30) DEFAULT NULL, - `c67` varchar(30) DEFAULT NULL, - `c68` varchar(30) DEFAULT NULL, - `c69` varchar(30) DEFAULT NULL, - `c70` varchar(30) DEFAULT NULL, - `c71` varchar(30) DEFAULT NULL, - `c72` varchar(30) DEFAULT NULL, - `c73` varchar(30) DEFAULT NULL, - `c74` varchar(30) DEFAULT NULL, - `c75` varchar(30) DEFAULT NULL, - `c76` varchar(30) DEFAULT NULL, - `c77` varchar(30) DEFAULT NULL, - `c78` varchar(30) DEFAULT NULL, - `c79` varchar(30) DEFAULT NULL, - `c80` varchar(30) DEFAULT NULL, - `c81` varchar(30) DEFAULT NULL, - `c82` varchar(30) DEFAULT NULL, - `c83` varchar(30) DEFAULT NULL, - `c84` varchar(30) DEFAULT NULL, - `c85` varchar(30) DEFAULT NULL, - `c86` varchar(30) DEFAULT NULL, - `c87` varchar(30) DEFAULT NULL, - `c88` varchar(30) DEFAULT NULL, - `c89` varchar(30) DEFAULT NULL, - `c90` varchar(30) DEFAULT NULL, - `c91` varchar(30) DEFAULT NULL, - `c92` varchar(30) DEFAULT NULL, - `c93` varchar(30) DEFAULT NULL, - `c94` varchar(30) DEFAULT NULL, - `c95` varchar(30) DEFAULT NULL, - `c96` varchar(30) DEFAULT NULL, - `c97` varchar(30) DEFAULT NULL, - `c98` varchar(30) DEFAULT NULL, - `c99` varchar(30) DEFAULT NULL, - `c100` varchar(30) DEFAULT NULL, - `c101` varchar(30) DEFAULT NULL, - `c102` varchar(30) DEFAULT NULL, - `c103` varchar(30) DEFAULT NULL, - `c104` varchar(30) DEFAULT NULL, - `c105` varchar(30) DEFAULT NULL, - `c106` varchar(30) DEFAULT NULL, - `c107` varchar(30) DEFAULT NULL, - `c108` varchar(30) DEFAULT NULL, - `c109` varchar(30) DEFAULT NULL, - `c110` varchar(30) DEFAULT NULL, - `c111` varchar(30) DEFAULT NULL, - `c112` varchar(30) DEFAULT NULL, - `c113` varchar(30) DEFAULT NULL, - `c114` varchar(30) DEFAULT NULL, - `c115` varchar(30) DEFAULT NULL, - `c116` varchar(30) DEFAULT NULL, - `c117` varchar(30) DEFAULT NULL, - `c118` varchar(30) DEFAULT NULL, - `c119` varchar(30) DEFAULT NULL, - `c120` varchar(30) DEFAULT NULL, - `c121` varchar(30) DEFAULT NULL, - `c122` varchar(30) DEFAULT NULL, - `c123` varchar(30) DEFAULT NULL, - `c124` varchar(30) DEFAULT NULL, - `c125` varchar(30) DEFAULT NULL, - `c126` varchar(30) DEFAULT NULL, - `c127` varchar(30) DEFAULT NULL, - `c128` varchar(30) DEFAULT NULL, - `c129` varchar(30) DEFAULT NULL, - `c130` varchar(30) DEFAULT NULL, - `c131` varchar(30) DEFAULT NULL, - `c132` varchar(30) DEFAULT NULL, - `c133` varchar(30) DEFAULT NULL, - `c134` varchar(30) DEFAULT NULL, - `c135` varchar(30) DEFAULT NULL, - `c136` varchar(30) DEFAULT NULL, - `c137` varchar(30) DEFAULT NULL, - `c138` varchar(30) DEFAULT NULL, - `c139` varchar(30) DEFAULT NULL, - `c140` varchar(30) DEFAULT NULL, - `c141` varchar(30) DEFAULT NULL, - `c142` varchar(30) DEFAULT NULL, - `c143` varchar(30) DEFAULT NULL, - `c144` varchar(30) DEFAULT NULL, - `c145` varchar(30) DEFAULT NULL, - `c146` varchar(30) DEFAULT NULL, - PRIMARY KEY (`c1`) -) ENGINE=InnoDB; - -LOCK TABLES `t1` WRITE; - -INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); - -DROP TABLE `t1`; - -FLUSH LOGS; - --- echo === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. - --- let $MYSQLD_DATADIR= `SELECT @@datadir`; --- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog --- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog diff --git a/mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result b/mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result new file mode 100644 index 00000000000..551ece5da9d --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result @@ -0,0 +1,437 @@ +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; +DROP TABLE IF EXISTS `t1`; +### TABLE with field_metadata_size == 290 +CREATE TABLE `t1` ( +`c1` int(11) NOT NULL AUTO_INCREMENT, +`c2` varchar(30) NOT NULL, +`c3` varchar(30) DEFAULT NULL, +`c4` varchar(30) DEFAULT NULL, +`c5` varchar(30) DEFAULT NULL, +`c6` varchar(30) DEFAULT NULL, +`c7` varchar(30) DEFAULT NULL, +`c8` varchar(30) DEFAULT NULL, +`c9` varchar(30) DEFAULT NULL, +`c10` varchar(30) DEFAULT NULL, +`c11` varchar(30) DEFAULT NULL, +`c12` varchar(30) DEFAULT NULL, +`c13` varchar(30) DEFAULT NULL, +`c14` varchar(30) DEFAULT NULL, +`c15` varchar(30) DEFAULT NULL, +`c16` varchar(30) DEFAULT NULL, +`c17` varchar(30) DEFAULT NULL, +`c18` varchar(30) DEFAULT NULL, +`c19` varchar(30) DEFAULT NULL, +`c20` varchar(30) DEFAULT NULL, +`c21` varchar(30) DEFAULT NULL, +`c22` varchar(30) DEFAULT NULL, +`c23` varchar(30) DEFAULT NULL, +`c24` varchar(30) DEFAULT NULL, +`c25` varchar(30) DEFAULT NULL, +`c26` varchar(30) DEFAULT NULL, +`c27` varchar(30) DEFAULT NULL, +`c28` varchar(30) DEFAULT NULL, +`c29` varchar(30) DEFAULT NULL, +`c30` varchar(30) DEFAULT NULL, +`c31` varchar(30) DEFAULT NULL, +`c32` varchar(30) DEFAULT NULL, +`c33` varchar(30) DEFAULT NULL, +`c34` varchar(30) DEFAULT NULL, +`c35` varchar(30) DEFAULT NULL, +`c36` varchar(30) DEFAULT NULL, +`c37` varchar(30) DEFAULT NULL, +`c38` varchar(30) DEFAULT NULL, +`c39` varchar(30) DEFAULT NULL, +`c40` varchar(30) DEFAULT NULL, +`c41` varchar(30) DEFAULT NULL, +`c42` varchar(30) DEFAULT NULL, +`c43` varchar(30) DEFAULT NULL, +`c44` varchar(30) DEFAULT NULL, +`c45` varchar(30) DEFAULT NULL, +`c46` varchar(30) DEFAULT NULL, +`c47` varchar(30) DEFAULT NULL, +`c48` varchar(30) DEFAULT NULL, +`c49` varchar(30) DEFAULT NULL, +`c50` varchar(30) DEFAULT NULL, +`c51` varchar(30) DEFAULT NULL, +`c52` varchar(30) DEFAULT NULL, +`c53` varchar(30) DEFAULT NULL, +`c54` varchar(30) DEFAULT NULL, +`c55` varchar(30) DEFAULT NULL, +`c56` varchar(30) DEFAULT NULL, +`c57` varchar(30) DEFAULT NULL, +`c58` varchar(30) DEFAULT NULL, +`c59` varchar(30) DEFAULT NULL, +`c60` varchar(30) DEFAULT NULL, +`c61` varchar(30) DEFAULT NULL, +`c62` varchar(30) DEFAULT NULL, +`c63` varchar(30) DEFAULT NULL, +`c64` varchar(30) DEFAULT NULL, +`c65` varchar(30) DEFAULT NULL, +`c66` varchar(30) DEFAULT NULL, +`c67` varchar(30) DEFAULT NULL, +`c68` varchar(30) DEFAULT NULL, +`c69` varchar(30) DEFAULT NULL, +`c70` varchar(30) DEFAULT NULL, +`c71` varchar(30) DEFAULT NULL, +`c72` varchar(30) DEFAULT NULL, +`c73` varchar(30) DEFAULT NULL, +`c74` varchar(30) DEFAULT NULL, +`c75` varchar(30) DEFAULT NULL, +`c76` varchar(30) DEFAULT NULL, +`c77` varchar(30) DEFAULT NULL, +`c78` varchar(30) DEFAULT NULL, +`c79` varchar(30) DEFAULT NULL, +`c80` varchar(30) DEFAULT NULL, +`c81` varchar(30) DEFAULT NULL, +`c82` varchar(30) DEFAULT NULL, +`c83` varchar(30) DEFAULT NULL, +`c84` varchar(30) DEFAULT NULL, +`c85` varchar(30) DEFAULT NULL, +`c86` varchar(30) DEFAULT NULL, +`c87` varchar(30) DEFAULT NULL, +`c88` varchar(30) DEFAULT NULL, +`c89` varchar(30) DEFAULT NULL, +`c90` varchar(30) DEFAULT NULL, +`c91` varchar(30) DEFAULT NULL, +`c92` varchar(30) DEFAULT NULL, +`c93` varchar(30) DEFAULT NULL, +`c94` varchar(30) DEFAULT NULL, +`c95` varchar(30) DEFAULT NULL, +`c96` varchar(30) DEFAULT NULL, +`c97` varchar(30) DEFAULT NULL, +`c98` varchar(30) DEFAULT NULL, +`c99` varchar(30) DEFAULT NULL, +`c100` varchar(30) DEFAULT NULL, +`c101` varchar(30) DEFAULT NULL, +`c102` varchar(30) DEFAULT NULL, +`c103` varchar(30) DEFAULT NULL, +`c104` varchar(30) DEFAULT NULL, +`c105` varchar(30) DEFAULT NULL, +`c106` varchar(30) DEFAULT NULL, +`c107` varchar(30) DEFAULT NULL, +`c108` varchar(30) DEFAULT NULL, +`c109` varchar(30) DEFAULT NULL, +`c110` varchar(30) DEFAULT NULL, +`c111` varchar(30) DEFAULT NULL, +`c112` varchar(30) DEFAULT NULL, +`c113` varchar(30) DEFAULT NULL, +`c114` varchar(30) DEFAULT NULL, +`c115` varchar(30) DEFAULT NULL, +`c116` varchar(30) DEFAULT NULL, +`c117` varchar(30) DEFAULT NULL, +`c118` varchar(30) DEFAULT NULL, +`c119` varchar(30) DEFAULT NULL, +`c120` varchar(30) DEFAULT NULL, +`c121` varchar(30) DEFAULT NULL, +`c122` varchar(30) DEFAULT NULL, +`c123` varchar(30) DEFAULT NULL, +`c124` varchar(30) DEFAULT NULL, +`c125` varchar(30) DEFAULT NULL, +`c126` varchar(30) DEFAULT NULL, +`c127` varchar(30) DEFAULT NULL, +`c128` varchar(30) DEFAULT NULL, +`c129` varchar(30) DEFAULT NULL, +`c130` varchar(30) DEFAULT NULL, +`c131` varchar(30) DEFAULT NULL, +`c132` varchar(30) DEFAULT NULL, +`c133` varchar(30) DEFAULT NULL, +`c134` varchar(30) DEFAULT NULL, +`c135` varchar(30) DEFAULT NULL, +`c136` varchar(30) DEFAULT NULL, +`c137` varchar(30) DEFAULT NULL, +`c138` varchar(30) DEFAULT NULL, +`c139` varchar(30) DEFAULT NULL, +`c140` varchar(30) DEFAULT NULL, +`c141` varchar(30) DEFAULT NULL, +`c142` varchar(30) DEFAULT NULL, +`c143` varchar(30) DEFAULT NULL, +`c144` varchar(30) DEFAULT NULL, +`c145` varchar(30) DEFAULT NULL, +`c146` varchar(30) DEFAULT NULL, +PRIMARY KEY (`c1`) +) ENGINE=InnoDB; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); +DROP TABLE `t1`; +FLUSH LOGS; +=== Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. +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; +### TABLE with field_metadata_size == 250 +CREATE TABLE `t1` ( +`c1` int(11) NOT NULL AUTO_INCREMENT, +`c2` varchar(30) NOT NULL, +`c3` varchar(30) DEFAULT NULL, +`c4` varchar(30) DEFAULT NULL, +`c5` varchar(30) DEFAULT NULL, +`c6` varchar(30) DEFAULT NULL, +`c7` varchar(30) DEFAULT NULL, +`c8` varchar(30) DEFAULT NULL, +`c9` varchar(30) DEFAULT NULL, +`c10` varchar(30) DEFAULT NULL, +`c11` varchar(30) DEFAULT NULL, +`c12` varchar(30) DEFAULT NULL, +`c13` varchar(30) DEFAULT NULL, +`c14` varchar(30) DEFAULT NULL, +`c15` varchar(30) DEFAULT NULL, +`c16` varchar(30) DEFAULT NULL, +`c17` varchar(30) DEFAULT NULL, +`c18` varchar(30) DEFAULT NULL, +`c19` varchar(30) DEFAULT NULL, +`c20` varchar(30) DEFAULT NULL, +`c21` varchar(30) DEFAULT NULL, +`c22` varchar(30) DEFAULT NULL, +`c23` varchar(30) DEFAULT NULL, +`c24` varchar(30) DEFAULT NULL, +`c25` varchar(30) DEFAULT NULL, +`c26` varchar(30) DEFAULT NULL, +`c27` varchar(30) DEFAULT NULL, +`c28` varchar(30) DEFAULT NULL, +`c29` varchar(30) DEFAULT NULL, +`c30` varchar(30) DEFAULT NULL, +`c31` varchar(30) DEFAULT NULL, +`c32` varchar(30) DEFAULT NULL, +`c33` varchar(30) DEFAULT NULL, +`c34` varchar(30) DEFAULT NULL, +`c35` varchar(30) DEFAULT NULL, +`c36` varchar(30) DEFAULT NULL, +`c37` varchar(30) DEFAULT NULL, +`c38` varchar(30) DEFAULT NULL, +`c39` varchar(30) DEFAULT NULL, +`c40` varchar(30) DEFAULT NULL, +`c41` varchar(30) DEFAULT NULL, +`c42` varchar(30) DEFAULT NULL, +`c43` varchar(30) DEFAULT NULL, +`c44` varchar(30) DEFAULT NULL, +`c45` varchar(30) DEFAULT NULL, +`c46` varchar(30) DEFAULT NULL, +`c47` varchar(30) DEFAULT NULL, +`c48` varchar(30) DEFAULT NULL, +`c49` varchar(30) DEFAULT NULL, +`c50` varchar(30) DEFAULT NULL, +`c51` varchar(30) DEFAULT NULL, +`c52` varchar(30) DEFAULT NULL, +`c53` varchar(30) DEFAULT NULL, +`c54` varchar(30) DEFAULT NULL, +`c55` varchar(30) DEFAULT NULL, +`c56` varchar(30) DEFAULT NULL, +`c57` varchar(30) DEFAULT NULL, +`c58` varchar(30) DEFAULT NULL, +`c59` varchar(30) DEFAULT NULL, +`c60` varchar(30) DEFAULT NULL, +`c61` varchar(30) DEFAULT NULL, +`c62` varchar(30) DEFAULT NULL, +`c63` varchar(30) DEFAULT NULL, +`c64` varchar(30) DEFAULT NULL, +`c65` varchar(30) DEFAULT NULL, +`c66` varchar(30) DEFAULT NULL, +`c67` varchar(30) DEFAULT NULL, +`c68` varchar(30) DEFAULT NULL, +`c69` varchar(30) DEFAULT NULL, +`c70` varchar(30) DEFAULT NULL, +`c71` varchar(30) DEFAULT NULL, +`c72` varchar(30) DEFAULT NULL, +`c73` varchar(30) DEFAULT NULL, +`c74` varchar(30) DEFAULT NULL, +`c75` varchar(30) DEFAULT NULL, +`c76` varchar(30) DEFAULT NULL, +`c77` varchar(30) DEFAULT NULL, +`c78` varchar(30) DEFAULT NULL, +`c79` varchar(30) DEFAULT NULL, +`c80` varchar(30) DEFAULT NULL, +`c81` varchar(30) DEFAULT NULL, +`c82` varchar(30) DEFAULT NULL, +`c83` varchar(30) DEFAULT NULL, +`c84` varchar(30) DEFAULT NULL, +`c85` varchar(30) DEFAULT NULL, +`c86` varchar(30) DEFAULT NULL, +`c87` varchar(30) DEFAULT NULL, +`c88` varchar(30) DEFAULT NULL, +`c89` varchar(30) DEFAULT NULL, +`c90` varchar(30) DEFAULT NULL, +`c91` varchar(30) DEFAULT NULL, +`c92` varchar(30) DEFAULT NULL, +`c93` varchar(30) DEFAULT NULL, +`c94` varchar(30) DEFAULT NULL, +`c95` varchar(30) DEFAULT NULL, +`c96` varchar(30) DEFAULT NULL, +`c97` varchar(30) DEFAULT NULL, +`c98` varchar(30) DEFAULT NULL, +`c99` varchar(30) DEFAULT NULL, +`c100` varchar(30) DEFAULT NULL, +`c101` varchar(30) DEFAULT NULL, +`c102` varchar(30) DEFAULT NULL, +`c103` varchar(30) DEFAULT NULL, +`c104` varchar(30) DEFAULT NULL, +`c105` varchar(30) DEFAULT NULL, +`c106` varchar(30) DEFAULT NULL, +`c107` varchar(30) DEFAULT NULL, +`c108` varchar(30) DEFAULT NULL, +`c109` varchar(30) DEFAULT NULL, +`c110` varchar(30) DEFAULT NULL, +`c111` varchar(30) DEFAULT NULL, +`c112` varchar(30) DEFAULT NULL, +`c113` varchar(30) DEFAULT NULL, +`c114` varchar(30) DEFAULT NULL, +`c115` varchar(30) DEFAULT NULL, +`c116` varchar(30) DEFAULT NULL, +`c117` varchar(30) DEFAULT NULL, +`c118` varchar(30) DEFAULT NULL, +`c119` varchar(30) DEFAULT NULL, +`c120` varchar(30) DEFAULT NULL, +`c121` varchar(30) DEFAULT NULL, +`c122` varchar(30) DEFAULT NULL, +`c123` varchar(30) DEFAULT NULL, +`c124` varchar(30) DEFAULT NULL, +`c125` varchar(30) DEFAULT NULL, +`c126` varchar(30) DEFAULT NULL, +PRIMARY KEY (`c1`) +) ENGINE=InnoDB; +### TABLE with field_metadata_size == 251 +CREATE TABLE `t2` ( +`c1` float, +`c2` varchar(30) NOT NULL, +`c3` varchar(30) DEFAULT NULL, +`c4` varchar(30) DEFAULT NULL, +`c5` varchar(30) DEFAULT NULL, +`c6` varchar(30) DEFAULT NULL, +`c7` varchar(30) DEFAULT NULL, +`c8` varchar(30) DEFAULT NULL, +`c9` varchar(30) DEFAULT NULL, +`c10` varchar(30) DEFAULT NULL, +`c11` varchar(30) DEFAULT NULL, +`c12` varchar(30) DEFAULT NULL, +`c13` varchar(30) DEFAULT NULL, +`c14` varchar(30) DEFAULT NULL, +`c15` varchar(30) DEFAULT NULL, +`c16` varchar(30) DEFAULT NULL, +`c17` varchar(30) DEFAULT NULL, +`c18` varchar(30) DEFAULT NULL, +`c19` varchar(30) DEFAULT NULL, +`c20` varchar(30) DEFAULT NULL, +`c21` varchar(30) DEFAULT NULL, +`c22` varchar(30) DEFAULT NULL, +`c23` varchar(30) DEFAULT NULL, +`c24` varchar(30) DEFAULT NULL, +`c25` varchar(30) DEFAULT NULL, +`c26` varchar(30) DEFAULT NULL, +`c27` varchar(30) DEFAULT NULL, +`c28` varchar(30) DEFAULT NULL, +`c29` varchar(30) DEFAULT NULL, +`c30` varchar(30) DEFAULT NULL, +`c31` varchar(30) DEFAULT NULL, +`c32` varchar(30) DEFAULT NULL, +`c33` varchar(30) DEFAULT NULL, +`c34` varchar(30) DEFAULT NULL, +`c35` varchar(30) DEFAULT NULL, +`c36` varchar(30) DEFAULT NULL, +`c37` varchar(30) DEFAULT NULL, +`c38` varchar(30) DEFAULT NULL, +`c39` varchar(30) DEFAULT NULL, +`c40` varchar(30) DEFAULT NULL, +`c41` varchar(30) DEFAULT NULL, +`c42` varchar(30) DEFAULT NULL, +`c43` varchar(30) DEFAULT NULL, +`c44` varchar(30) DEFAULT NULL, +`c45` varchar(30) DEFAULT NULL, +`c46` varchar(30) DEFAULT NULL, +`c47` varchar(30) DEFAULT NULL, +`c48` varchar(30) DEFAULT NULL, +`c49` varchar(30) DEFAULT NULL, +`c50` varchar(30) DEFAULT NULL, +`c51` varchar(30) DEFAULT NULL, +`c52` varchar(30) DEFAULT NULL, +`c53` varchar(30) DEFAULT NULL, +`c54` varchar(30) DEFAULT NULL, +`c55` varchar(30) DEFAULT NULL, +`c56` varchar(30) DEFAULT NULL, +`c57` varchar(30) DEFAULT NULL, +`c58` varchar(30) DEFAULT NULL, +`c59` varchar(30) DEFAULT NULL, +`c60` varchar(30) DEFAULT NULL, +`c61` varchar(30) DEFAULT NULL, +`c62` varchar(30) DEFAULT NULL, +`c63` varchar(30) DEFAULT NULL, +`c64` varchar(30) DEFAULT NULL, +`c65` varchar(30) DEFAULT NULL, +`c66` varchar(30) DEFAULT NULL, +`c67` varchar(30) DEFAULT NULL, +`c68` varchar(30) DEFAULT NULL, +`c69` varchar(30) DEFAULT NULL, +`c70` varchar(30) DEFAULT NULL, +`c71` varchar(30) DEFAULT NULL, +`c72` varchar(30) DEFAULT NULL, +`c73` varchar(30) DEFAULT NULL, +`c74` varchar(30) DEFAULT NULL, +`c75` varchar(30) DEFAULT NULL, +`c76` varchar(30) DEFAULT NULL, +`c77` varchar(30) DEFAULT NULL, +`c78` varchar(30) DEFAULT NULL, +`c79` varchar(30) DEFAULT NULL, +`c80` varchar(30) DEFAULT NULL, +`c81` varchar(30) DEFAULT NULL, +`c82` varchar(30) DEFAULT NULL, +`c83` varchar(30) DEFAULT NULL, +`c84` varchar(30) DEFAULT NULL, +`c85` varchar(30) DEFAULT NULL, +`c86` varchar(30) DEFAULT NULL, +`c87` varchar(30) DEFAULT NULL, +`c88` varchar(30) DEFAULT NULL, +`c89` varchar(30) DEFAULT NULL, +`c90` varchar(30) DEFAULT NULL, +`c91` varchar(30) DEFAULT NULL, +`c92` varchar(30) DEFAULT NULL, +`c93` varchar(30) DEFAULT NULL, +`c94` varchar(30) DEFAULT NULL, +`c95` varchar(30) DEFAULT NULL, +`c96` varchar(30) DEFAULT NULL, +`c97` varchar(30) DEFAULT NULL, +`c98` varchar(30) DEFAULT NULL, +`c99` varchar(30) DEFAULT NULL, +`c100` varchar(30) DEFAULT NULL, +`c101` varchar(30) DEFAULT NULL, +`c102` varchar(30) DEFAULT NULL, +`c103` varchar(30) DEFAULT NULL, +`c104` varchar(30) DEFAULT NULL, +`c105` varchar(30) DEFAULT NULL, +`c106` varchar(30) DEFAULT NULL, +`c107` varchar(30) DEFAULT NULL, +`c108` varchar(30) DEFAULT NULL, +`c109` varchar(30) DEFAULT NULL, +`c110` varchar(30) DEFAULT NULL, +`c111` varchar(30) DEFAULT NULL, +`c112` varchar(30) DEFAULT NULL, +`c113` varchar(30) DEFAULT NULL, +`c114` varchar(30) DEFAULT NULL, +`c115` varchar(30) DEFAULT NULL, +`c116` varchar(30) DEFAULT NULL, +`c117` varchar(30) DEFAULT NULL, +`c118` varchar(30) DEFAULT NULL, +`c119` varchar(30) DEFAULT NULL, +`c120` varchar(30) DEFAULT NULL, +`c121` varchar(30) DEFAULT NULL, +`c122` varchar(30) DEFAULT NULL, +`c123` varchar(30) DEFAULT NULL, +`c124` varchar(30) DEFAULT NULL, +`c125` varchar(30) DEFAULT NULL, +`c126` varchar(30) DEFAULT NULL, +PRIMARY KEY (`c1`) +) ENGINE=InnoDB; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); +LOCK TABLES `t2` WRITE; +INSERT INTO `t2` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); +DROP TABLE `t1`; +DROP TABLE `t2`; +FLUSH LOGS; +=== Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. diff --git a/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test new file mode 100644 index 00000000000..4d7ba1e0a81 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test @@ -0,0 +1,520 @@ +# +# BUG#42749: infinite loop writing to row based binlog - processlist shows +# "freeing items" +# +# BUG#50018: binlog corruption when table has many columns +# +# WHY +# === +# +# This bug would make table map event to report data_written one +# byte less than what would actually be written in its body. This +# would cause one byte shorter event end_log_pos. The ultimate +# impact was that it would make fixing the position in +# MYSQL_BIN_LOG::write_cache bogus or end up in an infinite loop. +# +# HOW +# === +# +# Checking that the patch fixes the problem is done as follows: +# +# i) tables with several fields is created (above and below a 251 +# metadata size threshold) +# ii) an insert is performed; +# iii) the logs are flushed; +# iv) mysqlbinlog is used to check if it succeeds. +# +# In step iv), before the bug was fixed, the test case would fail +# with mysqlbinlog reporting that it was unable to succeed in +# reading the event. + +-- source include/master-slave.inc +-- source include/have_log_bin.inc +-- source include/have_innodb.inc +-- source include/have_binlog_format_row.inc +-- connection default + +RESET MASTER; + +-- disable_warnings +DROP TABLE IF EXISTS `t1`; +-- enable_warnings + +-- echo ### TABLE with field_metadata_size == 290 +CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` varchar(30) NOT NULL, + `c3` varchar(30) DEFAULT NULL, + `c4` varchar(30) DEFAULT NULL, + `c5` varchar(30) DEFAULT NULL, + `c6` varchar(30) DEFAULT NULL, + `c7` varchar(30) DEFAULT NULL, + `c8` varchar(30) DEFAULT NULL, + `c9` varchar(30) DEFAULT NULL, + `c10` varchar(30) DEFAULT NULL, + `c11` varchar(30) DEFAULT NULL, + `c12` varchar(30) DEFAULT NULL, + `c13` varchar(30) DEFAULT NULL, + `c14` varchar(30) DEFAULT NULL, + `c15` varchar(30) DEFAULT NULL, + `c16` varchar(30) DEFAULT NULL, + `c17` varchar(30) DEFAULT NULL, + `c18` varchar(30) DEFAULT NULL, + `c19` varchar(30) DEFAULT NULL, + `c20` varchar(30) DEFAULT NULL, + `c21` varchar(30) DEFAULT NULL, + `c22` varchar(30) DEFAULT NULL, + `c23` varchar(30) DEFAULT NULL, + `c24` varchar(30) DEFAULT NULL, + `c25` varchar(30) DEFAULT NULL, + `c26` varchar(30) DEFAULT NULL, + `c27` varchar(30) DEFAULT NULL, + `c28` varchar(30) DEFAULT NULL, + `c29` varchar(30) DEFAULT NULL, + `c30` varchar(30) DEFAULT NULL, + `c31` varchar(30) DEFAULT NULL, + `c32` varchar(30) DEFAULT NULL, + `c33` varchar(30) DEFAULT NULL, + `c34` varchar(30) DEFAULT NULL, + `c35` varchar(30) DEFAULT NULL, + `c36` varchar(30) DEFAULT NULL, + `c37` varchar(30) DEFAULT NULL, + `c38` varchar(30) DEFAULT NULL, + `c39` varchar(30) DEFAULT NULL, + `c40` varchar(30) DEFAULT NULL, + `c41` varchar(30) DEFAULT NULL, + `c42` varchar(30) DEFAULT NULL, + `c43` varchar(30) DEFAULT NULL, + `c44` varchar(30) DEFAULT NULL, + `c45` varchar(30) DEFAULT NULL, + `c46` varchar(30) DEFAULT NULL, + `c47` varchar(30) DEFAULT NULL, + `c48` varchar(30) DEFAULT NULL, + `c49` varchar(30) DEFAULT NULL, + `c50` varchar(30) DEFAULT NULL, + `c51` varchar(30) DEFAULT NULL, + `c52` varchar(30) DEFAULT NULL, + `c53` varchar(30) DEFAULT NULL, + `c54` varchar(30) DEFAULT NULL, + `c55` varchar(30) DEFAULT NULL, + `c56` varchar(30) DEFAULT NULL, + `c57` varchar(30) DEFAULT NULL, + `c58` varchar(30) DEFAULT NULL, + `c59` varchar(30) DEFAULT NULL, + `c60` varchar(30) DEFAULT NULL, + `c61` varchar(30) DEFAULT NULL, + `c62` varchar(30) DEFAULT NULL, + `c63` varchar(30) DEFAULT NULL, + `c64` varchar(30) DEFAULT NULL, + `c65` varchar(30) DEFAULT NULL, + `c66` varchar(30) DEFAULT NULL, + `c67` varchar(30) DEFAULT NULL, + `c68` varchar(30) DEFAULT NULL, + `c69` varchar(30) DEFAULT NULL, + `c70` varchar(30) DEFAULT NULL, + `c71` varchar(30) DEFAULT NULL, + `c72` varchar(30) DEFAULT NULL, + `c73` varchar(30) DEFAULT NULL, + `c74` varchar(30) DEFAULT NULL, + `c75` varchar(30) DEFAULT NULL, + `c76` varchar(30) DEFAULT NULL, + `c77` varchar(30) DEFAULT NULL, + `c78` varchar(30) DEFAULT NULL, + `c79` varchar(30) DEFAULT NULL, + `c80` varchar(30) DEFAULT NULL, + `c81` varchar(30) DEFAULT NULL, + `c82` varchar(30) DEFAULT NULL, + `c83` varchar(30) DEFAULT NULL, + `c84` varchar(30) DEFAULT NULL, + `c85` varchar(30) DEFAULT NULL, + `c86` varchar(30) DEFAULT NULL, + `c87` varchar(30) DEFAULT NULL, + `c88` varchar(30) DEFAULT NULL, + `c89` varchar(30) DEFAULT NULL, + `c90` varchar(30) DEFAULT NULL, + `c91` varchar(30) DEFAULT NULL, + `c92` varchar(30) DEFAULT NULL, + `c93` varchar(30) DEFAULT NULL, + `c94` varchar(30) DEFAULT NULL, + `c95` varchar(30) DEFAULT NULL, + `c96` varchar(30) DEFAULT NULL, + `c97` varchar(30) DEFAULT NULL, + `c98` varchar(30) DEFAULT NULL, + `c99` varchar(30) DEFAULT NULL, + `c100` varchar(30) DEFAULT NULL, + `c101` varchar(30) DEFAULT NULL, + `c102` varchar(30) DEFAULT NULL, + `c103` varchar(30) DEFAULT NULL, + `c104` varchar(30) DEFAULT NULL, + `c105` varchar(30) DEFAULT NULL, + `c106` varchar(30) DEFAULT NULL, + `c107` varchar(30) DEFAULT NULL, + `c108` varchar(30) DEFAULT NULL, + `c109` varchar(30) DEFAULT NULL, + `c110` varchar(30) DEFAULT NULL, + `c111` varchar(30) DEFAULT NULL, + `c112` varchar(30) DEFAULT NULL, + `c113` varchar(30) DEFAULT NULL, + `c114` varchar(30) DEFAULT NULL, + `c115` varchar(30) DEFAULT NULL, + `c116` varchar(30) DEFAULT NULL, + `c117` varchar(30) DEFAULT NULL, + `c118` varchar(30) DEFAULT NULL, + `c119` varchar(30) DEFAULT NULL, + `c120` varchar(30) DEFAULT NULL, + `c121` varchar(30) DEFAULT NULL, + `c122` varchar(30) DEFAULT NULL, + `c123` varchar(30) DEFAULT NULL, + `c124` varchar(30) DEFAULT NULL, + `c125` varchar(30) DEFAULT NULL, + `c126` varchar(30) DEFAULT NULL, + `c127` varchar(30) DEFAULT NULL, + `c128` varchar(30) DEFAULT NULL, + `c129` varchar(30) DEFAULT NULL, + `c130` varchar(30) DEFAULT NULL, + `c131` varchar(30) DEFAULT NULL, + `c132` varchar(30) DEFAULT NULL, + `c133` varchar(30) DEFAULT NULL, + `c134` varchar(30) DEFAULT NULL, + `c135` varchar(30) DEFAULT NULL, + `c136` varchar(30) DEFAULT NULL, + `c137` varchar(30) DEFAULT NULL, + `c138` varchar(30) DEFAULT NULL, + `c139` varchar(30) DEFAULT NULL, + `c140` varchar(30) DEFAULT NULL, + `c141` varchar(30) DEFAULT NULL, + `c142` varchar(30) DEFAULT NULL, + `c143` varchar(30) DEFAULT NULL, + `c144` varchar(30) DEFAULT NULL, + `c145` varchar(30) DEFAULT NULL, + `c146` varchar(30) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB; + +LOCK TABLES `t1` WRITE; + +INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); + +DROP TABLE `t1`; + +FLUSH LOGS; + +-- sync_slave_with_master +-- connection master + +-- echo === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. + +-- let $MYSQLD_DATADIR= `SELECT @@datadir`; +-- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog +-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog + +-- source include/master-slave-reset.inc +-- connection master + +# Create two tables one with field_metadata_size == 250 +# and another one with field_metadata_size == 252 +# +# Each varchar field takes up to 2 metadata bytes, see: +# +# Field_varstring::do_save_field_metadata (field.cc) +# +# The integer field takes 0 bytes, see: +# +# Field::do_save_field_metadata (field.h) +# +# The float field takes 1 byte, see: +# +# Field_float::do_save_field_metadata (field.cc) +# +# We choose 250 and 252 which are the ones below and above +# the threshold for switching to use 1 or 3 bytes for the +# m_data_size increment. +# + +-- echo ### TABLE with field_metadata_size == 250 + +CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` varchar(30) NOT NULL, + `c3` varchar(30) DEFAULT NULL, + `c4` varchar(30) DEFAULT NULL, + `c5` varchar(30) DEFAULT NULL, + `c6` varchar(30) DEFAULT NULL, + `c7` varchar(30) DEFAULT NULL, + `c8` varchar(30) DEFAULT NULL, + `c9` varchar(30) DEFAULT NULL, + `c10` varchar(30) DEFAULT NULL, + `c11` varchar(30) DEFAULT NULL, + `c12` varchar(30) DEFAULT NULL, + `c13` varchar(30) DEFAULT NULL, + `c14` varchar(30) DEFAULT NULL, + `c15` varchar(30) DEFAULT NULL, + `c16` varchar(30) DEFAULT NULL, + `c17` varchar(30) DEFAULT NULL, + `c18` varchar(30) DEFAULT NULL, + `c19` varchar(30) DEFAULT NULL, + `c20` varchar(30) DEFAULT NULL, + `c21` varchar(30) DEFAULT NULL, + `c22` varchar(30) DEFAULT NULL, + `c23` varchar(30) DEFAULT NULL, + `c24` varchar(30) DEFAULT NULL, + `c25` varchar(30) DEFAULT NULL, + `c26` varchar(30) DEFAULT NULL, + `c27` varchar(30) DEFAULT NULL, + `c28` varchar(30) DEFAULT NULL, + `c29` varchar(30) DEFAULT NULL, + `c30` varchar(30) DEFAULT NULL, + `c31` varchar(30) DEFAULT NULL, + `c32` varchar(30) DEFAULT NULL, + `c33` varchar(30) DEFAULT NULL, + `c34` varchar(30) DEFAULT NULL, + `c35` varchar(30) DEFAULT NULL, + `c36` varchar(30) DEFAULT NULL, + `c37` varchar(30) DEFAULT NULL, + `c38` varchar(30) DEFAULT NULL, + `c39` varchar(30) DEFAULT NULL, + `c40` varchar(30) DEFAULT NULL, + `c41` varchar(30) DEFAULT NULL, + `c42` varchar(30) DEFAULT NULL, + `c43` varchar(30) DEFAULT NULL, + `c44` varchar(30) DEFAULT NULL, + `c45` varchar(30) DEFAULT NULL, + `c46` varchar(30) DEFAULT NULL, + `c47` varchar(30) DEFAULT NULL, + `c48` varchar(30) DEFAULT NULL, + `c49` varchar(30) DEFAULT NULL, + `c50` varchar(30) DEFAULT NULL, + `c51` varchar(30) DEFAULT NULL, + `c52` varchar(30) DEFAULT NULL, + `c53` varchar(30) DEFAULT NULL, + `c54` varchar(30) DEFAULT NULL, + `c55` varchar(30) DEFAULT NULL, + `c56` varchar(30) DEFAULT NULL, + `c57` varchar(30) DEFAULT NULL, + `c58` varchar(30) DEFAULT NULL, + `c59` varchar(30) DEFAULT NULL, + `c60` varchar(30) DEFAULT NULL, + `c61` varchar(30) DEFAULT NULL, + `c62` varchar(30) DEFAULT NULL, + `c63` varchar(30) DEFAULT NULL, + `c64` varchar(30) DEFAULT NULL, + `c65` varchar(30) DEFAULT NULL, + `c66` varchar(30) DEFAULT NULL, + `c67` varchar(30) DEFAULT NULL, + `c68` varchar(30) DEFAULT NULL, + `c69` varchar(30) DEFAULT NULL, + `c70` varchar(30) DEFAULT NULL, + `c71` varchar(30) DEFAULT NULL, + `c72` varchar(30) DEFAULT NULL, + `c73` varchar(30) DEFAULT NULL, + `c74` varchar(30) DEFAULT NULL, + `c75` varchar(30) DEFAULT NULL, + `c76` varchar(30) DEFAULT NULL, + `c77` varchar(30) DEFAULT NULL, + `c78` varchar(30) DEFAULT NULL, + `c79` varchar(30) DEFAULT NULL, + `c80` varchar(30) DEFAULT NULL, + `c81` varchar(30) DEFAULT NULL, + `c82` varchar(30) DEFAULT NULL, + `c83` varchar(30) DEFAULT NULL, + `c84` varchar(30) DEFAULT NULL, + `c85` varchar(30) DEFAULT NULL, + `c86` varchar(30) DEFAULT NULL, + `c87` varchar(30) DEFAULT NULL, + `c88` varchar(30) DEFAULT NULL, + `c89` varchar(30) DEFAULT NULL, + `c90` varchar(30) DEFAULT NULL, + `c91` varchar(30) DEFAULT NULL, + `c92` varchar(30) DEFAULT NULL, + `c93` varchar(30) DEFAULT NULL, + `c94` varchar(30) DEFAULT NULL, + `c95` varchar(30) DEFAULT NULL, + `c96` varchar(30) DEFAULT NULL, + `c97` varchar(30) DEFAULT NULL, + `c98` varchar(30) DEFAULT NULL, + `c99` varchar(30) DEFAULT NULL, + `c100` varchar(30) DEFAULT NULL, + `c101` varchar(30) DEFAULT NULL, + `c102` varchar(30) DEFAULT NULL, + `c103` varchar(30) DEFAULT NULL, + `c104` varchar(30) DEFAULT NULL, + `c105` varchar(30) DEFAULT NULL, + `c106` varchar(30) DEFAULT NULL, + `c107` varchar(30) DEFAULT NULL, + `c108` varchar(30) DEFAULT NULL, + `c109` varchar(30) DEFAULT NULL, + `c110` varchar(30) DEFAULT NULL, + `c111` varchar(30) DEFAULT NULL, + `c112` varchar(30) DEFAULT NULL, + `c113` varchar(30) DEFAULT NULL, + `c114` varchar(30) DEFAULT NULL, + `c115` varchar(30) DEFAULT NULL, + `c116` varchar(30) DEFAULT NULL, + `c117` varchar(30) DEFAULT NULL, + `c118` varchar(30) DEFAULT NULL, + `c119` varchar(30) DEFAULT NULL, + `c120` varchar(30) DEFAULT NULL, + `c121` varchar(30) DEFAULT NULL, + `c122` varchar(30) DEFAULT NULL, + `c123` varchar(30) DEFAULT NULL, + `c124` varchar(30) DEFAULT NULL, + `c125` varchar(30) DEFAULT NULL, + `c126` varchar(30) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB; + +-- echo ### TABLE with field_metadata_size == 251 + +CREATE TABLE `t2` ( + `c1` float, + `c2` varchar(30) NOT NULL, + `c3` varchar(30) DEFAULT NULL, + `c4` varchar(30) DEFAULT NULL, + `c5` varchar(30) DEFAULT NULL, + `c6` varchar(30) DEFAULT NULL, + `c7` varchar(30) DEFAULT NULL, + `c8` varchar(30) DEFAULT NULL, + `c9` varchar(30) DEFAULT NULL, + `c10` varchar(30) DEFAULT NULL, + `c11` varchar(30) DEFAULT NULL, + `c12` varchar(30) DEFAULT NULL, + `c13` varchar(30) DEFAULT NULL, + `c14` varchar(30) DEFAULT NULL, + `c15` varchar(30) DEFAULT NULL, + `c16` varchar(30) DEFAULT NULL, + `c17` varchar(30) DEFAULT NULL, + `c18` varchar(30) DEFAULT NULL, + `c19` varchar(30) DEFAULT NULL, + `c20` varchar(30) DEFAULT NULL, + `c21` varchar(30) DEFAULT NULL, + `c22` varchar(30) DEFAULT NULL, + `c23` varchar(30) DEFAULT NULL, + `c24` varchar(30) DEFAULT NULL, + `c25` varchar(30) DEFAULT NULL, + `c26` varchar(30) DEFAULT NULL, + `c27` varchar(30) DEFAULT NULL, + `c28` varchar(30) DEFAULT NULL, + `c29` varchar(30) DEFAULT NULL, + `c30` varchar(30) DEFAULT NULL, + `c31` varchar(30) DEFAULT NULL, + `c32` varchar(30) DEFAULT NULL, + `c33` varchar(30) DEFAULT NULL, + `c34` varchar(30) DEFAULT NULL, + `c35` varchar(30) DEFAULT NULL, + `c36` varchar(30) DEFAULT NULL, + `c37` varchar(30) DEFAULT NULL, + `c38` varchar(30) DEFAULT NULL, + `c39` varchar(30) DEFAULT NULL, + `c40` varchar(30) DEFAULT NULL, + `c41` varchar(30) DEFAULT NULL, + `c42` varchar(30) DEFAULT NULL, + `c43` varchar(30) DEFAULT NULL, + `c44` varchar(30) DEFAULT NULL, + `c45` varchar(30) DEFAULT NULL, + `c46` varchar(30) DEFAULT NULL, + `c47` varchar(30) DEFAULT NULL, + `c48` varchar(30) DEFAULT NULL, + `c49` varchar(30) DEFAULT NULL, + `c50` varchar(30) DEFAULT NULL, + `c51` varchar(30) DEFAULT NULL, + `c52` varchar(30) DEFAULT NULL, + `c53` varchar(30) DEFAULT NULL, + `c54` varchar(30) DEFAULT NULL, + `c55` varchar(30) DEFAULT NULL, + `c56` varchar(30) DEFAULT NULL, + `c57` varchar(30) DEFAULT NULL, + `c58` varchar(30) DEFAULT NULL, + `c59` varchar(30) DEFAULT NULL, + `c60` varchar(30) DEFAULT NULL, + `c61` varchar(30) DEFAULT NULL, + `c62` varchar(30) DEFAULT NULL, + `c63` varchar(30) DEFAULT NULL, + `c64` varchar(30) DEFAULT NULL, + `c65` varchar(30) DEFAULT NULL, + `c66` varchar(30) DEFAULT NULL, + `c67` varchar(30) DEFAULT NULL, + `c68` varchar(30) DEFAULT NULL, + `c69` varchar(30) DEFAULT NULL, + `c70` varchar(30) DEFAULT NULL, + `c71` varchar(30) DEFAULT NULL, + `c72` varchar(30) DEFAULT NULL, + `c73` varchar(30) DEFAULT NULL, + `c74` varchar(30) DEFAULT NULL, + `c75` varchar(30) DEFAULT NULL, + `c76` varchar(30) DEFAULT NULL, + `c77` varchar(30) DEFAULT NULL, + `c78` varchar(30) DEFAULT NULL, + `c79` varchar(30) DEFAULT NULL, + `c80` varchar(30) DEFAULT NULL, + `c81` varchar(30) DEFAULT NULL, + `c82` varchar(30) DEFAULT NULL, + `c83` varchar(30) DEFAULT NULL, + `c84` varchar(30) DEFAULT NULL, + `c85` varchar(30) DEFAULT NULL, + `c86` varchar(30) DEFAULT NULL, + `c87` varchar(30) DEFAULT NULL, + `c88` varchar(30) DEFAULT NULL, + `c89` varchar(30) DEFAULT NULL, + `c90` varchar(30) DEFAULT NULL, + `c91` varchar(30) DEFAULT NULL, + `c92` varchar(30) DEFAULT NULL, + `c93` varchar(30) DEFAULT NULL, + `c94` varchar(30) DEFAULT NULL, + `c95` varchar(30) DEFAULT NULL, + `c96` varchar(30) DEFAULT NULL, + `c97` varchar(30) DEFAULT NULL, + `c98` varchar(30) DEFAULT NULL, + `c99` varchar(30) DEFAULT NULL, + `c100` varchar(30) DEFAULT NULL, + `c101` varchar(30) DEFAULT NULL, + `c102` varchar(30) DEFAULT NULL, + `c103` varchar(30) DEFAULT NULL, + `c104` varchar(30) DEFAULT NULL, + `c105` varchar(30) DEFAULT NULL, + `c106` varchar(30) DEFAULT NULL, + `c107` varchar(30) DEFAULT NULL, + `c108` varchar(30) DEFAULT NULL, + `c109` varchar(30) DEFAULT NULL, + `c110` varchar(30) DEFAULT NULL, + `c111` varchar(30) DEFAULT NULL, + `c112` varchar(30) DEFAULT NULL, + `c113` varchar(30) DEFAULT NULL, + `c114` varchar(30) DEFAULT NULL, + `c115` varchar(30) DEFAULT NULL, + `c116` varchar(30) DEFAULT NULL, + `c117` varchar(30) DEFAULT NULL, + `c118` varchar(30) DEFAULT NULL, + `c119` varchar(30) DEFAULT NULL, + `c120` varchar(30) DEFAULT NULL, + `c121` varchar(30) DEFAULT NULL, + `c122` varchar(30) DEFAULT NULL, + `c123` varchar(30) DEFAULT NULL, + `c124` varchar(30) DEFAULT NULL, + `c125` varchar(30) DEFAULT NULL, + `c126` varchar(30) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB; + +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); + + +LOCK TABLES `t2` WRITE; +INSERT INTO `t2` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); + +DROP TABLE `t1`; +DROP TABLE `t2`; + +FLUSH LOGS; + +-- sync_slave_with_master + +-- connection master + +-- echo === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. + +-- let $MYSQLD_DATADIR= `SELECT @@datadir`; +-- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog +-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog + +-- source include/master-slave-end.inc diff --git a/sql/log_event.cc b/sql/log_event.cc index c028db3476d..d5a436cb79e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -7925,10 +7925,10 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, plus one or three bytes (see pack.c:net_store_length) for number of elements in the field metadata array. */ - if (m_field_metadata_size > 255) - m_data_size+= m_field_metadata_size + 3; - else + if (m_field_metadata_size < 251) m_data_size+= m_field_metadata_size + 1; + else + m_data_size+= m_field_metadata_size + 3; bzero(m_null_bits, num_null_bytes); for (unsigned int i= 0 ; i < m_table->s->fields ; ++i) From 0a64fbc517eef4550e5b0b75246125391f5deca1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jan 2010 10:36:29 +0800 Subject: [PATCH 217/344] Bug #49137 Replication failure on SBR/MBR + multi-table DROP TEMPORARY TABLE Fixed valgrind failure on PB2. sql/log_event.cc: Added code to fix valgrind failure on PB2. --- sql/log_event.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 35d53c4fede..ad5c4bfeef8 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2110,8 +2110,8 @@ compare_errors: has already been dropped. To ignore such irrelevant "table does not exist errors", we silently clear the error if TEMPORARY was used. */ - if (thd->lex->drop_temporary && - thd->net.last_errno == ER_BAD_TABLE_ERROR && !expected_error) + if (thd->net.last_errno == ER_BAD_TABLE_ERROR && + !expected_error && thd->lex->drop_temporary) thd->clear_error(); /* If we expected a non-zero error code, and we don't get the same error From 98b989d7b1f250f4e245b1ca479bacd9b18ae98e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jan 2010 13:12:40 +0800 Subject: [PATCH 218/344] Bug #49137 Replication failure on SBR/MBR + multi-table DROP TEMPORARY TABLE Fixed valgrind failure on PB2. sql/log_event.cc: Added code to fix valgrind failure on PB2. --- sql/log_event.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index ad5c4bfeef8..76fc2632cd1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2110,8 +2110,8 @@ compare_errors: has already been dropped. To ignore such irrelevant "table does not exist errors", we silently clear the error if TEMPORARY was used. */ - if (thd->net.last_errno == ER_BAD_TABLE_ERROR && - !expected_error && thd->lex->drop_temporary) + if (thd->lex->sql_command == SQLCOM_DROP_TABLE && thd->lex->drop_temporary && + thd->net.last_errno == ER_BAD_TABLE_ERROR && !expected_error) thd->clear_error(); /* If we expected a non-zero error code, and we don't get the same error From 9eca4014e34add68eafb7b8d820d7f7920e0b8e1 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 6 Jan 2010 12:24:51 +0200 Subject: [PATCH 219/344] Addendum to Bug #49734 : fixed an unstable test case. --- mysql-test/r/union.result | 3 --- mysql-test/t/union.test | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index dce32d2ced4..43d7cade227 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1640,9 +1640,6 @@ Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1 # Should not crash SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY (SELECT a FROM t2 WHERE b = 12); -a -1 -2 # Should not crash SELECT * FROM t2 UNION SELECT * FROM t2 ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 91fc9546bbe..c8d5ea0f8e5 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -1144,8 +1144,10 @@ SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY (SELECT a FROM t2 WHERE b = 12); --echo # Should not crash +--disable_result_log SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY (SELECT a FROM t2 WHERE b = 12); +--enable_result_log --echo # Should not crash SELECT * FROM t2 UNION SELECT * FROM t2 From 5b0ab60a4bfb4d5b603cd929b7ceb0d9fd1bac22 Mon Sep 17 00:00:00 2001 From: Aleksandr Kuzminsky Date: Wed, 6 Jan 2010 04:00:14 -0800 Subject: [PATCH 220/344] Synced with extensions-1.0.6 Rev. 135 --- CMakeLists.txt | 82 +- ChangeLog | 316 +++++ Makefile.am | 4 +- Makefile.in | 48 +- README | 5 +- btr/btr0btr.c | 36 +- btr/btr0sea.c | 17 +- buf/buf0buf.c | 322 ++++-- buf/buf0flu.c | 53 +- buf/buf0lru.c | 518 ++++++--- buf/buf0rea.c | 222 +--- data/data0type.c | 16 + dict/dict0crea.c | 2 +- dict/dict0dict.c | 100 +- fil/fil0fil.c | 171 ++- fsp/fsp0fsp.c | 80 +- handler/ha_innodb.cc | 463 +++++--- handler/ha_innodb.h | 27 + handler/handler0alter.cc | 48 +- handler/handler0vars.h | 69 -- handler/i_s.cc | 60 +- handler/innodb_patch_info.h | 2 + handler/win_delay_loader.cc | 1024 ----------------- ibuf/ibuf0ibuf.c | 21 + include/btr0cur.h | 2 +- include/btr0sea.h | 6 + include/buf0buf.h | 132 +-- include/buf0buf.ic | 92 +- include/buf0lru.h | 64 +- include/buf0rea.h | 41 +- include/buf0types.h | 2 + include/db0err.h | 1 + include/dict0crea.h | 2 +- include/dict0dict.h | 9 +- include/dict0mem.h | 2 +- include/fil0fil.h | 31 +- include/fsp0fsp.h | 2 +- include/ibuf0ibuf.h | 6 + include/lock0lock.h | 14 + include/log0log.h | 28 +- include/log0log.ic | 71 +- include/log0recv.h | 56 + include/mem0mem.h | 7 + include/mem0pool.h | 7 + include/mtr0mtr.h | 5 +- include/os0file.h | 9 + include/os0sync.h | 81 +- include/page0page.h | 7 +- include/page0page.ic | 2 +- include/page0zip.h | 12 +- include/pars0pars.h | 6 + include/rem0cmp.h | 2 +- include/rem0rec.ic | 2 +- include/row0ins.h | 2 +- include/row0mysql.h | 6 +- include/srv0srv.h | 21 +- include/sync0sync.h | 2 +- include/thr0loc.h | 6 + include/trx0i_s.h | 7 + include/trx0purge.h | 6 + include/trx0rec.h | 4 +- include/trx0rec.ic | 4 +- include/trx0roll.h | 15 +- include/trx0rseg.h | 7 + include/trx0sys.h | 6 + include/trx0sys.ic | 4 +- include/trx0trx.h | 4 +- include/trx0types.h | 2 +- include/trx0undo.h | 7 + include/univ.i | 70 +- include/usr0sess.h | 12 +- include/ut0auxconf.h | 12 +- include/ut0byte.h | 4 +- include/ut0byte.ic | 4 +- include/ut0ut.h | 20 +- lock/lock0lock.c | 66 +- log/log0log.c | 195 +++- log/log0recv.c | 350 +++++- mem/mem0dbg.c | 11 + mem/mem0mem.c | 20 +- mem/mem0pool.c | 12 + mtr/mtr0mtr.c | 8 +- mysql-test/innodb-analyze.test | 4 +- mysql-test/innodb-autoinc.result | 243 +++- mysql-test/innodb-autoinc.test | 118 ++ mysql-test/innodb-consistent-master.opt | 1 + mysql-test/innodb-consistent.result | 35 + mysql-test/innodb-consistent.test | 58 + mysql-test/innodb-index.result | 12 +- mysql-test/innodb-index.test | 24 +- mysql-test/innodb-master.opt | 2 +- mysql-test/innodb-semi-consistent-master.opt | 2 +- mysql-test/innodb-use-sys-malloc-master.opt | 3 +- mysql-test/innodb-zip.result | 100 +- mysql-test/innodb-zip.test | 48 +- mysql-test/innodb.result | 4 +- mysql-test/innodb.test | 2 +- mysql-test/innodb_bug34300.test | 3 +- mysql-test/innodb_bug36169.result | 2 - mysql-test/innodb_bug36169.test | 8 +- mysql-test/innodb_bug36172.test | 11 +- mysql-test/innodb_bug42101-nonzero-master.opt | 2 +- mysql-test/innodb_bug44369.result | 6 + mysql-test/innodb_bug44369.test | 17 + mysql-test/innodb_bug44571.result | 7 + mysql-test/innodb_bug44571.test | 13 + mysql-test/innodb_bug46000.result | 19 + mysql-test/innodb_bug46000.test | 32 + mysql-test/innodb_bug46676.result | 9 + mysql-test/innodb_bug46676.test | 16 + mysql-test/innodb_bug47167.result | 24 + mysql-test/innodb_bug47167.test | 45 + mysql-test/innodb_bug47777.result | 13 + mysql-test/innodb_bug47777.test | 24 + mysql-test/innodb_file_format.result | 4 +- mysql-test/innodb_file_format.test | 15 +- mysql-test/innodb_information_schema.test | 16 +- mysql-test/patches/disabled.def.diff | 12 +- .../patches/index_merge_innodb-explain.diff | 31 + mysql-test/patches/index_merge_innodb.diff | 57 - mysql-test/patches/information_schema.diff | 74 +- mysql-test/patches/information_schema_db.diff | 24 - mysql-test/patches/innodb_bug46000.diff | 26 - mysql-test/patches/mysqlshow.diff | 46 - os/os0file.c | 242 +++- os/os0proc.c | 1 + os/os0sync.c | 4 + os/os0thread.c | 1 + page/page0cur.c | 2 +- page/page0page.c | 6 +- page/page0zip.c | 65 +- pars/lexyy.c | 13 + pars/pars0lex.l | 13 + plug.in | 153 ++- que/que0que.c | 8 + rem/rem0cmp.c | 6 +- row/row0ins.c | 8 +- row/row0merge.c | 248 +++- row/row0mysql.c | 68 +- scripts/install_innodb_plugins.sql | 1 + scripts/install_innodb_plugins_win.sql | 8 + srv/srv0srv.c | 96 +- srv/srv0start.c | 143 +-- sync/sync0arr.c | 20 +- sync/sync0rw.c | 1 + sync/sync0sync.c | 86 +- thr/thr0loc.c | 33 +- trx/trx0i_s.c | 39 +- trx/trx0purge.c | 38 + trx/trx0rec.c | 4 +- trx/trx0roll.c | 74 +- trx/trx0rseg.c | 43 + trx/trx0sys.c | 92 ++ trx/trx0trx.c | 4 +- trx/trx0undo.c | 2 +- usr/usr0sess.c | 37 +- ut/ut0auxconf_atomic_pthread_t_solaris.c | 26 +- ut/ut0auxconf_have_gcc_atomics.c | 61 + ut/ut0mem.c | 2 + ut/ut0ut.c | 19 + win-plugin/README | 22 - win-plugin/win-plugin.diff | 279 ----- 162 files changed, 5276 insertions(+), 3198 deletions(-) delete mode 100644 handler/handler0vars.h delete mode 100644 handler/win_delay_loader.cc create mode 100644 mysql-test/innodb-consistent-master.opt create mode 100644 mysql-test/innodb-consistent.result create mode 100644 mysql-test/innodb-consistent.test create mode 100644 mysql-test/innodb_bug44369.result create mode 100644 mysql-test/innodb_bug44369.test create mode 100644 mysql-test/innodb_bug44571.result create mode 100644 mysql-test/innodb_bug44571.test create mode 100644 mysql-test/innodb_bug46000.result create mode 100644 mysql-test/innodb_bug46000.test create mode 100644 mysql-test/innodb_bug46676.result create mode 100644 mysql-test/innodb_bug46676.test create mode 100644 mysql-test/innodb_bug47167.result create mode 100644 mysql-test/innodb_bug47167.test create mode 100644 mysql-test/innodb_bug47777.result create mode 100644 mysql-test/innodb_bug47777.test create mode 100644 mysql-test/patches/index_merge_innodb-explain.diff delete mode 100644 mysql-test/patches/index_merge_innodb.diff delete mode 100644 mysql-test/patches/information_schema_db.diff delete mode 100644 mysql-test/patches/innodb_bug46000.diff delete mode 100644 mysql-test/patches/mysqlshow.diff create mode 100644 ut/ut0auxconf_have_gcc_atomics.c delete mode 100644 win-plugin/README delete mode 100644 win-plugin/win-plugin.diff diff --git a/CMakeLists.txt b/CMakeLists.txt index ef1d3db6f73..b26a008f477 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,41 +15,20 @@ # This is the CMakeLists for InnoDB Plugin -# The dynamic plugin requires CMake 2.6.0 or later. Otherwise, the /DELAYLOAD -# property will not be set -CMAKE_MINIMUM_REQUIRED(VERSION 2.6 FATAL_ERROR) -# When PROJECT is defined, a separate .sln file will be generated. -# PROJECT (INNODB_PLUGIN) +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") -MESSAGE(STATUS "Enter InnoDB ...") -MESSAGE(STATUS "INNODB_DYNAMIC_PLUGIN: " ${INNODB_DYNAMIC_PLUGIN}) - -# Print out CMake info -MESSAGE(STATUS "CMAKE_GENERATOR: " ${CMAKE_GENERATOR}) -MESSAGE(STATUS "CMAKE_SOURCE_DIR: " ${CMAKE_SOURCE_DIR}) - -# Print out system information -MESSAGE(STATUS "CMAKE_SYSTEM: " ${CMAKE_SYSTEM}) -MESSAGE(STATUS "CMAKE_SYSTEM_PROCESSOR: " ${CMAKE_SYSTEM_PROCESSOR}) -MESSAGE(STATUS "UNIX: " ${UNIX}) -MESSAGE(STATUS "WIN32: " ${WIN32}) +# Starting at 5.1.38, MySQL CMake files are simplified. But the plugin +# CMakeLists.txt still needs to work with previous versions of MySQL. +IF (MYSQL_VERSION_ID GREATER "50137") + INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") +ENDIF (MYSQL_VERSION_ID GREATER "50137") IF (CMAKE_SIZEOF_VOID_P MATCHES 8) SET(WIN64 TRUE) ENDIF (CMAKE_SIZEOF_VOID_P MATCHES 8) -MESSAGE(STATUS "WIN64: " ${WIN64}) -MESSAGE(STATUS "MSVC: " ${MSVC}) - -# Check type sizes -include(CheckTypeSize) - -# Currently, the checked results are not used. -CHECK_TYPE_SIZE(int SIZEOF_INT) -CHECK_TYPE_SIZE(long SIZEOF_LONG) -CHECK_TYPE_SIZE(void* SIZEOF_VOID_P) - # Include directories under innobase INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/innobase/include ${CMAKE_SOURCE_DIR}/storage/innobase/handler) @@ -63,12 +42,12 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include # Removing compiler optimizations for innodb/mem/* files on 64-bit Windows # due to 64-bit compiler error, See MySQL Bug #19424, #36366, #34297 -IF(MSVC AND $(WIN64)) +IF (MSVC AND $(WIN64)) SET_SOURCE_FILES_PROPERTIES(mem/mem0mem.c mem/mem0pool.c PROPERTIES COMPILE_FLAGS -Od) -ENDIF(MSVC AND $(WIN64)) +ENDIF (MSVC AND $(WIN64)) -SET(INNODB_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c +SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c buf/buf0buddy.c buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c data/data0data.c data/data0type.c dict/dict0boot.c dict/dict0crea.c dict/dict0dict.c dict/dict0load.c dict/dict0mem.c @@ -101,31 +80,20 @@ SET(INNODB_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c usr/usr0sess.c ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c ut/ut0list.c ut/ut0wqueue.c) +ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION) -IF(NOT SOURCE_SUBLIBS) - # INNODB_RW_LOCKS_USE_ATOMICS may be defined only if HAVE_WINDOWS_ATOMICS is defined. - # Windows Interlocked functions require Windows 2000 or newer operating system - ADD_DEFINITIONS(-D_WIN32 -DHAVE_WINDOWS_ATOMICS -DINNODB_RW_LOCKS_USE_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION) - ADD_LIBRARY(innobase STATIC ${INNODB_SOURCES}) - # Require mysqld_error.h, which is built as part of the GenError - ADD_DEPENDENCIES(innobase GenError) - # only set MYSQL_SERVER for the builtin engine, not the plugin - SET_TARGET_PROPERTIES(innobase PROPERTIES COMPILE_FLAGS "-DMYSQL_SERVER") - - # Dynamic plugin ha_innodb.dll - IF(INNODB_DYNAMIC_PLUGIN) - ADD_LIBRARY(ha_innodb SHARED ${INNODB_SOURCES} ha_innodb.def handler/win_delay_loader.cc) +IF (MYSQL_VERSION_ID GREATER "50137") + MYSQL_STORAGE_ENGINE(INNOBASE) + # Use ha_innodb for plugin name, if plugin is built + GET_TARGET_PROPERTY(LIB_LOCATION ha_innobase LOCATION) + IF(LIB_LOCATION) + SET_TARGET_PROPERTIES(ha_innobase PROPERTIES OUTPUT_NAME ha_innodb) + ENDIF(LIB_LOCATION) +ELSE (MYSQL_VERSION_ID GREATER "50137") + IF (NOT SOURCE_SUBLIBS) + ADD_DEFINITIONS(-D_WIN32 -DMYSQL_SERVER) + ADD_LIBRARY(innobase STATIC ${INNOBASE_SOURCES}) # Require mysqld_error.h, which is built as part of the GenError - # Also require mysqld.lib, which is built as part of the mysqld - ADD_DEPENDENCIES(ha_innodb GenError mysqld) - - TARGET_LINK_LIBRARIES(ha_innodb ${CMAKE_SOURCE_DIR}/sql/\$\(OutDir\)/mysqld.lib) - SET_TARGET_PROPERTIES(ha_innodb PROPERTIES OUTPUT_NAME ha_innodb) - SET_TARGET_PROPERTIES(ha_innodb PROPERTIES LINK_FLAGS "/MAP /MAPINFO:EXPORTS") - SET_TARGET_PROPERTIES(ha_innodb PROPERTIES LINK_FLAGS "/ENTRY:\"_DllMainCRTStartup@12\"") - SET_TARGET_PROPERTIES(ha_innodb PROPERTIES COMPILE_FLAGS "-DMYSQL_DYNAMIC_PLUGIN") - SET_TARGET_PROPERTIES(ha_innodb PROPERTIES LINK_FLAGS "/DELAYLOAD:mysqld.exe") - ENDIF(INNODB_DYNAMIC_PLUGIN) -ENDIF(NOT SOURCE_SUBLIBS) - -MESSAGE(STATUS "Exit InnoDB ...") + ADD_DEPENDENCIES(innobase GenError) + ENDIF (NOT SOURCE_SUBLIBS) +ENDIF (MYSQL_VERSION_ID GREATER "50137") diff --git a/ChangeLog b/ChangeLog index 2b04c06f0e8..1a6e07fd147 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,319 @@ +2009-11-20 The InnoDB Team + + * handler/ha_innodb.cc: + Add a workaround to prevent a crash due to Bug#45961 DDL on + partitioned innodb tables leaves data dictionary in an inconsistent + state + +2009-11-19 The InnoDB Team + + * btr/btr0btr.c: + Fix Bug#48469 when innodb tablespace is configured too small, crash + and corruption! + +2009-11-19 The InnoDB Team + + * data/data0type.c: + Fix Bug#48526 Data type for float and double is incorrectly reported + in InnoDB table monitor + +2009-11-19 The InnoDB Team + + * CMakeLists.txt: + Fix Bug#48317 cannot build innodb as static library + +2009-11-18 The InnoDB Team + + * handler/handler0alter.cc: + Fix Bug#48782 On lock wait timeout, CREATE INDEX (creating primary key) + attempts DROP TABLE + +2009-11-17 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb.result, + mysql-test/innodb.test, mysql-test/innodb_bug44369.result, + mysql-test/innodb_bug44369.test, mysql-test/patches/innodb-index.diff, + row/row0mysql.c: + Report duplicate table names to the client connection, not to the + error log. + +2009-11-12 The InnoDB Team + + * handler/ha_innodb.cc, include/db0err.h, row/row0merge.c, + row/row0mysql.c: + Allow CREATE INDEX to be interrupted. + Also, when CHECK TABLE is interrupted, report ER_QUERY_INTERRUPTED. + +2009-11-11 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb_bug47167.result, + mysql-test/innodb_bug47167.test, mysql-test/innodb_file_format.result: + Fix Bug#47167 "set global innodb_file_format_check" cannot set value + by User-Defined Variable + +2009-11-11 The InnoDB Team + + * include/os0file.h, os/os0file.c: + Fix Bug#3139 Mysql crashes: 'windows error 995' after several selects + on a large DB + +2009-11-04 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#32430 'show innodb status' causes errors + Invalid (old?) table or database name in logs + +2009-11-02 The InnoDB Team + + * btr/btr0sea.c, buf/buf0buf.c, dict/dict0dict.c, fil/fil0fil.c, + ibuf/ibuf0ibuf.c, include/btr0sea.h, include/dict0dict.h, + include/fil0fil.h, include/ibuf0ibuf.h, include/lock0lock.h, + include/log0log.h, include/log0recv.h, include/mem0mem.h, + include/mem0pool.h, include/os0file.h, include/pars0pars.h, + include/srv0srv.h, include/thr0loc.h, include/trx0i_s.h, + include/trx0purge.h, include/trx0rseg.h, include/trx0sys.h, + include/trx0undo.h, include/usr0sess.h, lock/lock0lock.c, + log/log0log.c, log/log0recv.c, mem/mem0dbg.c, mem/mem0pool.c, + os/os0file.c, os/os0sync.c, os/os0thread.c, pars/lexyy.c, + pars/pars0lex.l, que/que0que.c, srv/srv0srv.c, srv/srv0start.c, + sync/sync0arr.c, sync/sync0sync.c, thr/thr0loc.c, trx/trx0i_s.c, + trx/trx0purge.c, trx/trx0rseg.c, trx/trx0sys.c, trx/trx0undo.c, + usr/usr0sess.c, ut/ut0mem.c: + Fix Bug #45992 innodb memory not freed after shutdown + Fix Bug #46656 InnoDB plugin: memory leaks (Valgrind) + +2009-10-29 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb-autoinc.result, + mysql-test/innodb-autoinc.test: + Fix Bug#47125 auto_increment start value is ignored if an index is + created and engine=innodb + +2009-10-29 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb_bug47777.result, + mysql-test/innodb_bug47777.test: + Fix Bug#47777 innodb dies with spatial pk: Failing assertion: buf <= + original_buf + buf_len + +2009-10-29 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#38996 Race condition in ANALYZE TABLE + +2009-10-29 The InnoDB Team + + * handler/ha_innodb.cc: + Fix bug#42383: Can't create table 'test.bug39438' + +2009-10-29 The InnoDB Team + + * os/os0proc.c: + Fix Bug#48237 Error handling in os_mem_alloc_large appears to + be incorrect + +2009-10-29 The InnoDB Team + + * buf/buf0buf.c, buf/buf0lru.c, include/buf0buf.h, include/buf0buf.ic: + Fix corruption of the buf_pool->LRU_old list and improve debug + assertions. + +2009-10-28 The InnoDB Team + + * srv/srv0start.c: + Fix Bug#41490 After enlargement of InnoDB page size, the error message + become inaccurate + +2009-10-26 The InnoDB Team + + * row/row0ins.c: + When allocating a data tuple, zero out the system fields in order + to avoid Valgrind warnings about uninitialized fields in + dtuple_validate(). + +2009-10-22 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb-zip.result, + mysql-test/innodb-zip.test, mysql-test/innodb_bug44369.result, + mysql-test/innodb_bug44369.test: + Fix Bug#47233 Innodb calls push_warning(MYSQL_ERROR::WARN_LEVEL_ERROR) + +2009-10-19 The InnoDB Team + + * mysql-test/innodb_information_schema.test: + Fix Bug#47808 innodb_information_schema.test fails when run under + valgrind + +2009-10-15 The InnoDB Team + + * include/page0page.ic: + Fix Bug#47058 Failure to compile innodb_plugin on solaris 10u7 + spro + cc/CC 5.10 + +2009-10-13 The InnoDB Team + + * buf/buf0flu.c: + Call fsync() on datafiles after a batch of pages is written to disk + even when skip_innodb_doublewrite is set. + +2009-10-05 The InnoDB Team + + * buf/buf0buf.c: + Do not invalidate buffer pool while an LRU batch is active. Added code + to buf_pool_invalidate() to wait for the running batches to finish. + +2009-10-01 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#47763 typo in error message: Failed to open table %s after %lu + attemtps. + +2009-10-01 The InnoDB Team + + * fsp/fsp0fsp.c, row/row0merge.c: + Clean up after a crash during DROP INDEX. When InnoDB crashes + while dropping an index, ensure that the index will be completely + dropped during crash recovery. The MySQL .frm file may still + contain the dropped index, but there is little that we can do + about it. + +2009-09-28 The InnoDB Team + + * handler/ha_innodb.cc: + When a secondary index exists in the MySQL .frm file but not in + the InnoDB data dictionary, return an error instead of letting an + assertion fail in index_read. + +2009-09-28 The InnoDB Team + + * btr/btr0btr.c, buf/buf0buf.c, include/page0page.h, + include/page0zip.h, page/page0cur.c, page/page0page.c, + page/page0zip.c: + Do not write to PAGE_INDEX_ID when restoring an uncompressed page + after a compression failure. The field should only be written + when creating a B-tree page. This fix addresses a race condition + in a debug assertion. + +2009-09-28 The InnoDB Team + + * fil/fil0fil.c: + Try to prevent the reuse of tablespace identifiers after InnoDB + has crashed during table creation. Also, refuse to start if files + with duplicate tablespace identifiers are encountered. + +2009-09-25 The InnoDB Team + + * include/os0file.h, os/os0file.c: + Fix Bug#47055 unconditional exit(1) on ERROR_WORKING_SET_QUOTA + 1453 (0x5AD) for InnoDB backend + +2009-09-19 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb-consistent-master.opt, + mysql-test/innodb-consistent.result, + mysql-test/innodb-consistent.test: + Fix Bug#37232 Innodb might get too many read locks for DML with + repeatable-read + +2009-09-19 The InnoDB Team + + * fsp/fsp0fsp.c: + Fix Bug#31183 Tablespace full problems not reported in error log, + error message unclear + +2009-09-17 The InnoDB Team + + * mysql-test/innodb-zip.result, mysql-test/innodb-zip.test: + Make the test pass with zlib 1.2.3.3. Apparently, the definition + of compressBound() has changed between zlib versions, and the + maximum record size of a table with 1K compressed page size has + been reduced by one byte. This is an arbitrary test. In practical + applications, for good write performance, the compressed page size + should be chosen to be bigger than the absolute minimum. + +2009-09-16 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#46256 drop table with unknown collation crashes innodb + +2009-09-16 The InnoDB Team + + * dict/dict0dict.c, handler/ha_innodb.cc, + mysql-test/innodb_bug44369.result, mysql-test/innodb_bug44369.test, + row/row0mysql.c: + Fix Bug#44369 InnoDB: Does not uniformly disallow disallowed column + names + +2009-09-16 The InnoDB Team + + * handler/ha_innodb.cc, include/db0err.h, + mysql-test/innodb_bug46000.result, mysql-test/innodb_bug46000.test: + Fix Bug#46000 using index called GEN_CLUST_INDEX crashes server + +2009-09-02 The InnoDB Team + + * include/lock0lock.h, include/row0mysql.h, lock/lock0lock.c, + row/row0mysql.c: + Fix a regression introduced by the fix for MySQL bug#26316. We check + whether a transaction holds any AUTOINC locks before we acquire + the kernel mutex and release those locks. + +2009-08-27 The InnoDB Team + + * dict/dict0dict.c, include/dict0dict.h, + mysql-test/innodb_bug44571.result, mysql-test/innodb_bug44571.test: + Fix Bug#44571 InnoDB Plugin crashes on ADD INDEX + +2009-08-27 The InnoDB Team + + * row/row0merge.c: + Fix a bug in the merge sort that can corrupt indexes in fast index + creation. Add some consistency checks. Check that the number of + records remains constant in every merge sort pass. + +2009-08-27 The InnoDB Team + + * buf/buf0buf.c, buf/buf0lru.c, buf/buf0rea.c, handler/ha_innodb.cc, + include/buf0buf.h, include/buf0buf.ic, include/buf0lru.h, + include/ut0ut.h, ut/ut0ut.c: + Make it possible to tune the buffer pool LRU eviction policy to be + more resistant against index scans. Introduce the settable global + variables innodb_old_blocks_pct and innodb_old_blocks_time for + controlling the buffer pool eviction policy. The parameter + innodb_old_blocks_pct (5..95) controls the desired amount of "old" + blocks in the LRU list. The default is 37, corresponding to the + old fixed ratio of 3/8. Each time a block is accessed, it will be + moved to the "new" blocks if its first access was at least + innodb_old_blocks_time milliseconds ago (default 0, meaning every + block). The idea is that in index scans, blocks will be accessed + a few times within innodb_old_blocks_time, and they will remain in + the "old" section of the LRU list. Thus, when innodb_old_blocks_time + is nonzero, blocks retrieved for one-time index scans will be more + likely candidates for eviction than blocks that are accessed in + random patterns. + +2009-08-26 The InnoDB Team + + * handler/ha_innodb.cc, os/os0file.c: + Fix Bug#42885 buf_read_ahead_random, buf_read_ahead_linear counters, + thread wakeups + +2009-08-20 The InnoDB Team + + * lock/lock0lock.c: + Fix Bug#46650 Innodb assertion autoinc_lock == lock in + lock_table_remove_low on INSERT SELECT + +2009-08-13 The InnoDB Team + + * handler/handler0alter.cc: + Fix Bug#46657 InnoDB plugin: invalid read in index_merge_innodb test + (Valgrind) + +2009-08-11 The InnoDB Team + + InnoDB Plugin 1.0.4 released + 2009-07-20 The InnoDB Team * buf/buf0rea.c, handler/ha_innodb.cc, include/srv0srv.h, diff --git a/Makefile.am b/Makefile.am index a83d79d21ef..53413dfaeb8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,7 @@ MYSQLLIBdir= $(pkglibdir) pkgplugindir= $(pkglibdir)/plugin INCLUDES= -I$(top_srcdir)/include -I$(top_builddir)/include \ -I$(top_srcdir)/regex \ - -I$(top_srcdir)/storage/innobase/include \ + -I$(srcdir)/include \ -I$(top_srcdir)/sql \ -I$(srcdir) @ZLIB_INCLUDES@ @@ -31,7 +31,6 @@ DEFS= @DEFS@ noinst_HEADERS= \ handler/ha_innodb.h \ - handler/handler0vars.h \ handler/i_s.h \ include/btr0btr.h \ include/btr0btr.ic \ @@ -78,6 +77,7 @@ noinst_HEADERS= \ include/fil0fil.h \ include/fsp0fsp.h \ include/fsp0fsp.ic \ + include/fsp0types.h \ include/fut0fut.h \ include/fut0fut.ic \ include/fut0lst.h \ diff --git a/Makefile.in b/Makefile.in index ee1bb5185cd..cc703bd48c7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -296,15 +296,14 @@ DIFF = @DIFF@ DOT_FRM_VERSION = @DOT_FRM_VERSION@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ DVIS = @DVIS@ -ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ +FGREP = @FGREP@ FIND_PROC = @FIND_PROC@ GETCONF = @GETCONF@ GREP = @GREP@ @@ -326,6 +325,7 @@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_EXTRA_CCFLAGS = @LIB_EXTRA_CCFLAGS@ +LIPO = @LIPO@ LM_CFLAGS = @LM_CFLAGS@ LN = @LN@ LN_CP_F = @LN_CP_F@ @@ -371,7 +371,10 @@ NM = @NM@ NMEDIT = @NMEDIT@ NOINST_LDFLAGS = @NOINST_LDFLAGS@ NON_THREADED_LIBS = @NON_THREADED_LIBS@ +OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ @@ -419,7 +422,7 @@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -457,6 +460,7 @@ libexecdir = @libexecdir@ libmysqld_dirs = @libmysqld_dirs@ localedir = @localedir@ localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ man1_files = @man1_files@ man8_files = @man8_files@ man_dirs = @man_dirs@ @@ -501,6 +505,8 @@ plugin_ibmdb2i_shared_target = @plugin_ibmdb2i_shared_target@ plugin_ibmdb2i_static_target = @plugin_ibmdb2i_static_target@ plugin_innobase_shared_target = @plugin_innobase_shared_target@ plugin_innobase_static_target = @plugin_innobase_static_target@ +plugin_innodb_plugin_shared_target = @plugin_innodb_plugin_shared_target@ +plugin_innodb_plugin_static_target = @plugin_innodb_plugin_static_target@ plugin_myisam_shared_target = @plugin_myisam_shared_target@ plugin_myisam_static_target = @plugin_myisam_static_target@ plugin_myisammrg_shared_target = @plugin_myisammrg_shared_target@ @@ -550,13 +556,12 @@ MYSQLLIBdir = $(pkglibdir) pkgplugindir = $(pkglibdir)/plugin INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ -I$(top_srcdir)/regex \ - -I$(top_srcdir)/storage/innobase/include \ + -I$(srcdir)/include \ -I$(top_srcdir)/sql \ -I$(srcdir) @ZLIB_INCLUDES@ noinst_HEADERS = \ handler/ha_innodb.h \ - handler/handler0vars.h \ handler/i_s.h \ include/btr0btr.h \ include/btr0btr.ic \ @@ -603,6 +608,7 @@ noinst_HEADERS = \ include/fil0fil.h \ include/fsp0fsp.h \ include/fsp0fsp.ic \ + include/fsp0types.h \ include/fut0fut.h \ include/fut0fut.ic \ include/fut0lst.h \ @@ -863,20 +869,22 @@ EXTRA_DIST = CMakeLists.txt plug.in \ custom_checks: echo '' > include/ut0auxconf.h - if $(COMPILE) ut/ut0auxconf_atomic_pthread_t_gcc.c -o ut0auxconf_atomic_pthread_t_gcc ; then \ - echo '#define HAVE_ATOMIC_PTHREAD_T' >> include/ut0auxconf.h ; \ - elif $(COMPILE) ut/ut0auxconf_have_solaris_atomics.c -o ut0auxconf_have_solaris_atomics ; then \ - echo '#define HAVE_SOLARIS_ATOMICS' >> include/ut0auxconf.h ; \ - if $(COMPILE) ut/ut0auxconf_atomic_pthread_t_solaris.c -o ut0auxconf_atomic_pthread_t_solaris ; then \ - echo '#define HAVE_ATOMIC_PTHREAD_T' >> include/ut0auxconf.h ; \ - $(COMPILE) ut/ut0auxconf_sizeof_pthread_t.c -o ut0auxconf_sizeof_pthread_t ; \ - ./ut0auxconf_sizeof_pthread_t >> include/ut0auxconf.h ; \ - fi ; \ - fi - if $(COMPILE) ut/ut0auxconf_pause.c -o ut0auxconf_pause ; then \ - if ./ut0auxconf_pause ; then \ - echo '#define IB_HAVE_PAUSE_INSTRUCTION' >> include/ut0auxconf.h ; \ - fi ; \ + if $(COMPILE) ut/ut0auxconf_have_gcc_atomics.c -o ut0auxconf_have_gcc_atomics && ./ut0auxconf_have_gcc_atomics ; then \ + echo '#define HAVE_IB_GCC_ATOMIC_BUILTINS' >> include/ut0auxconf.h ; \ + fi ; \ + if $(COMPILE) ut/ut0auxconf_atomic_pthread_t_gcc.c -o ut0auxconf_atomic_pthread_t_gcc && ./ut0auxconf_atomic_pthread_t_gcc ; then \ + echo '#define HAVE_IB_ATOMIC_PTHREAD_T_GCC' >> include/ut0auxconf.h ; \ + fi ; \ + if $(COMPILE) ut/ut0auxconf_have_solaris_atomics.c -o ut0auxconf_have_solaris_atomics && ./ut0auxconf_have_solaris_atomics ; then \ + echo '#define HAVE_IB_SOLARIS_ATOMICS' >> include/ut0auxconf.h ; \ + fi ; \ + if $(COMPILE) ut/ut0auxconf_atomic_pthread_t_solaris.c -o ut0auxconf_atomic_pthread_t_solaris && ./ut0auxconf_atomic_pthread_t_solaris ; then \ + echo '#define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS' >> include/ut0auxconf.h ; \ + fi ; \ + $(COMPILE) ut/ut0auxconf_sizeof_pthread_t.c -o ut0auxconf_sizeof_pthread_t ; \ + ./ut0auxconf_sizeof_pthread_t >> include/ut0auxconf.h ; \ + if $(COMPILE) ut/ut0auxconf_pause.c -o ut0auxconf_pause && ./ut0auxconf_pause ; then \ + echo '#define HAVE_IB_PAUSE_INSTRUCTION' >> include/ut0auxconf.h ; \ fi $(MAKE) all-am diff --git a/README b/README index 56aa8058224..c74c93e4663 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is the source of the InnoDB Plugin 1.0.4 for MySQL 5.1 +This is the source of the InnoDB Plugin 1.0.6 for MySQL 5.1 =========================================================== Instructions for compiling the plugin: @@ -14,6 +14,9 @@ Instructions for compiling the plugin: mysql-test suite): cd into the innobase directory and run ./setup.sh 4. Compile MySQL as usual. + If compiling MySQL 5.1.38 or newer, disable the InnoDB Plugin that comes + with MySQL in storage/innodb_plugin with the configure option + --without-plugin-innodb_plugin 5. Enjoy! diff --git a/btr/btr0btr.c b/btr/btr0btr.c index 6ba9b36207b..086b3a0a599 100644 --- a/btr/btr0btr.c +++ b/btr/btr0btr.c @@ -790,14 +790,21 @@ btr_create( } else { /* It is a non-ibuf tree: create a file segment for leaf pages */ - fseg_create(space, page_no, - PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr); + if (!fseg_create(space, page_no, + PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { + /* Not enough space for new segment, free root + segment before return. */ + btr_free_root(space, zip_size, page_no, mtr); + + return(FIL_NULL); + } + /* The fseg create acquires a second latch on the page, therefore we must declare it: */ buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW); } - /* Create a new index page on the the allocated segment page */ + /* Create a new index page on the allocated segment page */ page_zip = buf_block_get_page_zip(block); if (UNIV_LIKELY_NULL(page_zip)) { @@ -1011,7 +1018,26 @@ btr_page_reorganize_low( (!page_zip_compress(page_zip, page, index, NULL))) { /* Restore the old page and exit. */ - buf_frame_copy(page, temp_page); + +#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG + /* Check that the bytes that we skip are identical. */ + ut_a(!memcmp(page, temp_page, PAGE_HEADER)); + ut_a(!memcmp(PAGE_HEADER + PAGE_N_RECS + page, + PAGE_HEADER + PAGE_N_RECS + temp_page, + PAGE_DATA - (PAGE_HEADER + PAGE_N_RECS))); + ut_a(!memcmp(UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + page, + UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + temp_page, + FIL_PAGE_DATA_END)); +#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */ + + memcpy(PAGE_HEADER + page, PAGE_HEADER + temp_page, + PAGE_N_RECS - PAGE_N_DIR_SLOTS); + memcpy(PAGE_DATA + page, PAGE_DATA + temp_page, + UNIV_PAGE_SIZE - PAGE_DATA - FIL_PAGE_DATA_END); + +#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG + ut_a(!memcmp(page, temp_page, UNIV_PAGE_SIZE)); +#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */ goto func_exit; } @@ -1902,7 +1928,7 @@ func_start: n_uniq, &heap); /* If the new record is less than the existing record - the the split in the middle will copy the existing + the split in the middle will copy the existing record to the new node. */ if (cmp_dtuple_rec(tuple, first_rec, offsets) < 0) { split_rec = page_get_middle_rec(page); diff --git a/btr/btr0sea.c b/btr/btr0sea.c index 14f4b94f51b..e59d51e056e 100644 --- a/btr/btr0sea.c +++ b/btr/btr0sea.c @@ -175,6 +175,21 @@ btr_search_sys_create( btr_search_sys->hash_index = ha_create(hash_size, 0, 0); } +/*****************************************************************//** +Frees the adaptive search system at a database shutdown. */ +UNIV_INTERN +void +btr_search_sys_free(void) +/*=====================*/ +{ + mem_free(btr_search_latch_temp); + btr_search_latch_temp = NULL; + mem_heap_free(btr_search_sys->hash_index->heap); + hash_table_free(btr_search_sys->hash_index); + mem_free(btr_search_sys); + btr_search_sys = NULL; +} + /********************************************************************//** Disable the adaptive hash search system and empty the index. */ UNIV_INTERN @@ -957,7 +972,7 @@ btr_search_guess_on_hash( /* Increment the page get statistics though we did not really fix the page: for user info only */ - buf_pool->n_page_gets++; + buf_pool->stat.n_page_gets++; return(TRUE); diff --git a/buf/buf0buf.c b/buf/buf0buf.c index dd17f6faf21..617b0e01b09 100644 --- a/buf/buf0buf.c +++ b/buf/buf0buf.c @@ -51,6 +51,7 @@ Created 11/5/1995 Heikki Tuuri #include "dict0dict.h" #include "log0recv.h" #include "page0zip.h" +#include "trx0trx.h" /* prototypes for new functions added to ha_innodb.cc */ trx_t* innobase_get_trx(); @@ -878,16 +879,35 @@ buf_chunk_not_freed( block = chunk->blocks; for (i = chunk->size; i--; block++) { - mutex_enter(&block->mutex); - - if (buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE - && !buf_flush_ready_for_replace(&block->page)) { + ibool ready; + switch (buf_block_get_state(block)) { + case BUF_BLOCK_ZIP_FREE: + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + /* The uncompressed buffer pool should never + contain compressed block descriptors. */ + ut_error; + break; + case BUF_BLOCK_NOT_USED: + case BUF_BLOCK_READY_FOR_USE: + case BUF_BLOCK_MEMORY: + case BUF_BLOCK_REMOVE_HASH: + /* Skip blocks that are not being used for + file pages. */ + break; + case BUF_BLOCK_FILE_PAGE: + mutex_enter(&block->mutex); + ready = buf_flush_ready_for_replace(&block->page); mutex_exit(&block->mutex); - return(block); - } - mutex_exit(&block->mutex); + if (!ready) { + + return(block); + } + + break; + } } return(NULL); @@ -1018,8 +1038,6 @@ buf_pool_init(void) buf_pool->no_flush[i] = os_event_create(NULL); } - buf_pool->ulint_clock = 1; - /* 3. Initialize LRU fields --------------------------- */ /* All fields are initialized by mem_zalloc(). */ @@ -1057,7 +1075,11 @@ buf_pool_free(void) os_mem_free_large(chunk->mem, chunk->mem_size); } - buf_pool->n_chunks = 0; + mem_free(buf_pool->chunks); + hash_table_free(buf_pool->page_hash); + hash_table_free(buf_pool->zip_hash); + mem_free(buf_pool); + buf_pool = NULL; } /********************************************************************//** @@ -1204,10 +1226,15 @@ buf_relocate( #ifdef UNIV_LRU_DEBUG /* buf_pool->LRU_old must be the first item in the LRU list whose "old" flag is set. */ + ut_a(buf_pool->LRU_old->old); ut_a(!UT_LIST_GET_PREV(LRU, buf_pool->LRU_old) || !UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)->old); ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old) || UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old); + } else { + /* Check that the "old" flag is consistent in + the block and its neighbours. */ + buf_page_set_old(dpage, buf_page_is_old(dpage)); #endif /* UNIV_LRU_DEBUG */ } @@ -1542,36 +1569,9 @@ buf_pool_resize(void) buf_pool_page_hash_rebuild(); } -/********************************************************************//** -Moves the block to the start of the LRU list if there is a danger -that the block would drift out of the buffer pool. */ -UNIV_INLINE -void -buf_block_make_young( -/*=================*/ - buf_page_t* bpage) /*!< in: block to make younger */ -{ - ut_ad(!buf_pool_mutex_own()); - - /* Note that we read freed_page_clock's without holding any mutex: - this is allowed since the result is used only in heuristics */ - - if (buf_page_peek_if_too_old(bpage)) { - - //buf_pool_mutex_enter(); - mutex_enter(&LRU_list_mutex); - /* There has been freeing activity in the LRU list: - best to move to the head of the LRU list */ - - buf_LRU_make_block_young(bpage); - //buf_pool_mutex_exit(); - mutex_exit(&LRU_list_mutex); - } -} - /********************************************************************//** Moves a page to the start of the buffer pool LRU list. This high-level -function can be used to prevent an important page from from slipping out of +function can be used to prevent an important page from slipping out of the buffer pool. */ UNIV_INTERN void @@ -1590,6 +1590,42 @@ buf_page_make_young( mutex_exit(&LRU_list_mutex); } +/********************************************************************//** +Sets the time of the first access of a page and moves a page to the +start of the buffer pool LRU list if it is too old. This high-level +function can be used to prevent an important page from slipping +out of the buffer pool. */ +static +void +buf_page_set_accessed_make_young( +/*=============================*/ + buf_page_t* bpage, /*!< in/out: buffer block of a + file page */ + unsigned access_time) /*!< in: bpage->access_time + read under mutex protection, + or 0 if unknown */ +{ + ut_ad(!buf_pool_mutex_own()); + ut_a(buf_page_in_file(bpage)); + + if (buf_page_peek_if_too_old(bpage)) { + //buf_pool_mutex_enter(); + mutex_enter(&LRU_list_mutex); + buf_LRU_make_block_young(bpage); + //buf_pool_mutex_exit(); + mutex_exit(&LRU_list_mutex); + } else if (!access_time) { + ulint time_ms = ut_time_ms(); + mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); + //buf_pool_mutex_enter(); + if (block_mutex) { + buf_page_set_accessed(bpage, time_ms); + mutex_exit(block_mutex); + } + //buf_pool_mutex_exit(); + } +} + /********************************************************************//** Resets the check_index_page_at_flush field of a page if found in the buffer pool. */ @@ -1729,11 +1765,12 @@ buf_page_get_zip( buf_page_t* bpage; mutex_t* block_mutex; ibool must_read; - trx_t* trx = NULL; - ulint sec; - ulint ms; - ib_uint64_t start_time; - ib_uint64_t finish_time; + unsigned access_time; + trx_t* trx = NULL; + ulint sec; + ulint ms; + ib_uint64_t start_time; + ib_uint64_t finish_time; #ifndef UNIV_LOG_DEBUG ut_ad(!ibuf_inside()); @@ -1741,7 +1778,7 @@ buf_page_get_zip( if (innobase_get_slow_log()) { trx = innobase_get_trx(); } - buf_pool->n_page_gets++; + buf_pool->stat.n_page_gets++; for (;;) { //buf_pool_mutex_enter(); @@ -1811,14 +1848,13 @@ err_exit: got_block: must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ; + access_time = buf_page_is_accessed(bpage); //buf_pool_mutex_exit(); - buf_page_set_accessed(bpage, TRUE); - mutex_exit(block_mutex); - buf_block_make_young(bpage); + buf_page_set_accessed_make_young(bpage, access_time); #ifdef UNIV_DEBUG_FILE_ACCESSES ut_a(!bpage->file_page_was_freed); @@ -1924,7 +1960,7 @@ buf_zip_decompress( switch (fil_page_get_type(frame)) { case FIL_PAGE_INDEX: if (page_zip_decompress(&block->page.zip, - block->frame)) { + block->frame, TRUE)) { return(TRUE); } @@ -2112,7 +2148,7 @@ buf_page_get_gen( mtr_t* mtr) /*!< in: mini-transaction */ { buf_block_t* block; - ibool accessed; + unsigned access_time; ulint fix_type; ibool must_read; mutex_t* block_mutex; @@ -2137,7 +2173,7 @@ buf_page_get_gen( if (innobase_get_slow_log()) { trx = innobase_get_trx(); } - buf_pool->n_page_gets++; + buf_pool->stat.n_page_gets++; loop: block = guess; //buf_pool_mutex_enter(); @@ -2414,17 +2450,17 @@ wait_until_unfixed: UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page); buf_block_buf_fix_inc(block, file, line); - //buf_pool_mutex_exit(); + + //mutex_exit(&block->mutex); /* Check if this is the first access to the page */ - accessed = buf_page_is_accessed(&block->page); - - buf_page_set_accessed(&block->page, TRUE); + access_time = buf_page_is_accessed(&block->page); + //buf_pool_mutex_exit(); mutex_exit(block_mutex); - buf_block_make_young(&block->page); + buf_page_set_accessed_make_young(&block->page, access_time); #ifdef UNIV_DEBUG_FILE_ACCESSES ut_a(!block->page.file_page_was_freed); @@ -2490,7 +2526,7 @@ wait_until_unfixed: mtr_memo_push(mtr, block, fix_type); - if (!accessed) { + if (!access_time) { /* In the case of a first access, try to apply linear read-ahead */ @@ -2524,7 +2560,7 @@ buf_page_optimistic_get_func( ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mini-transaction */ { - ibool accessed; + unsigned access_time; ibool success; ulint fix_type; trx_t* trx = NULL; @@ -2542,14 +2578,16 @@ buf_page_optimistic_get_func( } buf_block_buf_fix_inc(block, file, line); - accessed = buf_page_is_accessed(&block->page); - buf_page_set_accessed(&block->page, TRUE); mutex_exit(&block->mutex); - buf_block_make_young(&block->page); + /* Check if this is the first access to the page. + We do a dirty read on purpose, to avoid mutex contention. + This field is only used for heuristic purposes; it does not + affect correctness. */ - /* Check if this is the first access to the page */ + access_time = buf_page_is_accessed(&block->page); + buf_page_set_accessed_make_young(&block->page, access_time); ut_ad(!ibuf_inside() || ibuf_page(buf_block_get_space(block), @@ -2605,7 +2643,7 @@ buf_page_optimistic_get_func( trx = innobase_get_trx(); } - if (UNIV_UNLIKELY(!accessed)) { + if (UNIV_UNLIKELY(!access_time)) { /* In the case of a first access, try to apply linear read-ahead */ @@ -2618,7 +2656,7 @@ buf_page_optimistic_get_func( ut_a(ibuf_count_get(buf_block_get_space(block), buf_block_get_page_no(block)) == 0); #endif - buf_pool->n_page_gets++; + buf_pool->stat.n_page_gets++; if (innobase_get_slow_log()) { _increment_page_get_statistics(block, trx); @@ -2670,8 +2708,24 @@ buf_page_get_known_nowait( mutex_exit(&block->mutex); - if (mode == BUF_MAKE_YOUNG) { - buf_block_make_young(&block->page); + if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) { + //buf_pool_mutex_enter(); + mutex_enter(&LRU_list_mutex); + buf_LRU_make_block_young(&block->page); + //buf_pool_mutex_exit(); + mutex_exit(&LRU_list_mutex); + } else if (!buf_page_is_accessed(&block->page)) { + /* Above, we do a dirty read on purpose, to avoid + mutex contention. The field buf_page_t::access_time + is only used for heuristic purposes. Writes to the + field must be protected by mutex, however. */ + ulint time_ms = ut_time_ms(); + + //buf_pool_mutex_enter(); + mutex_enter(&block->mutex); + buf_page_set_accessed(&block->page, time_ms); + //buf_pool_mutex_exit(); + mutex_exit(&block->mutex); } ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD)); @@ -2710,7 +2764,7 @@ buf_page_get_known_nowait( || (ibuf_count_get(buf_block_get_space(block), buf_block_get_page_no(block)) == 0)); #endif - buf_pool->n_page_gets++; + buf_pool->stat.n_page_gets++; if (innobase_get_slow_log()) { trx = innobase_get_trx(); @@ -2794,7 +2848,7 @@ buf_page_try_get_func( #endif /* UNIV_DEBUG_FILE_ACCESSES */ buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); - buf_pool->n_page_gets++; + buf_pool->stat.n_page_gets++; #ifdef UNIV_IBUF_COUNT_DEBUG ut_a(ibuf_count_get(buf_block_get_space(block), @@ -2813,10 +2867,10 @@ buf_page_init_low( buf_page_t* bpage) /*!< in: block to init */ { bpage->flush_type = BUF_FLUSH_LRU; - bpage->accessed = FALSE; bpage->io_fix = BUF_IO_NONE; bpage->buf_fix_count = 0; bpage->freed_page_clock = 0; + bpage->access_time = 0; bpage->newest_modification = 0; bpage->oldest_modification = 0; HASH_INVALIDATE(bpage, hash); @@ -3138,6 +3192,7 @@ buf_page_create( buf_frame_t* frame; buf_block_t* block; buf_block_t* free_block = NULL; + ulint time_ms = ut_time_ms(); ut_ad(mtr); ut_ad(space || !zip_size); @@ -3189,7 +3244,7 @@ buf_page_create( buf_LRU_add_block(&block->page, FALSE); buf_block_buf_fix_inc(block, __FILE__, __LINE__); - buf_pool->n_pages_created++; + buf_pool->stat.n_pages_created++; if (zip_size) { void* data; @@ -3226,13 +3281,13 @@ buf_page_create( rw_lock_x_unlock(&block->lock); } + buf_page_set_accessed(&block->page, time_ms); + //buf_pool_mutex_exit(); mutex_exit(&LRU_list_mutex); mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX); - buf_page_set_accessed(&block->page, TRUE); - mutex_exit(&block->mutex); /* Delete possible entries for the page from the insert buffer: @@ -3449,7 +3504,7 @@ corrupt: ut_ad(buf_pool->n_pend_reads > 0); buf_pool->n_pend_reads--; - buf_pool->n_pages_read++; + buf_pool->stat.n_pages_read++; if (uncompressed) { rw_lock_x_unlock_gen(&((buf_block_t*) bpage)->lock, @@ -3474,7 +3529,7 @@ corrupt: BUF_IO_WRITE); } - buf_pool->n_pages_written++; + buf_pool->stat.n_pages_written++; break; @@ -3505,7 +3560,32 @@ void buf_pool_invalidate(void) /*=====================*/ { - ibool freed; + ibool freed; + enum buf_flush i; + + buf_pool_mutex_enter(); + + for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) { + + /* As this function is called during startup and + during redo application phase during recovery, InnoDB + is single threaded (apart from IO helper threads) at + this stage. No new write batch can be in intialization + stage at this point. */ + ut_ad(buf_pool->init_flush[i] == FALSE); + + /* However, it is possible that a write batch that has + been posted earlier is still not complete. For buffer + pool invalidation to proceed we must ensure there is NO + write activity happening. */ + if (buf_pool->n_flush[i] > 0) { + buf_pool_mutex_exit(); + buf_flush_wait_batch_end(i); + buf_pool_mutex_enter(); + } + } + + buf_pool_mutex_exit(); ut_ad(buf_all_freed()); @@ -3521,6 +3601,14 @@ buf_pool_invalidate(void) ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0); ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0); + buf_pool->freed_page_clock = 0; + buf_pool->LRU_old = NULL; + buf_pool->LRU_old_len = 0; + buf_pool->LRU_flush_ended = 0; + + memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat)); + buf_refresh_io_stats(); + //buf_pool_mutex_exit(); mutex_exit(&LRU_list_mutex); } @@ -3800,6 +3888,7 @@ buf_print(void) "n pending decompressions %lu\n" "n pending reads %lu\n" "n pending flush LRU %lu list %lu single page %lu\n" + "pages made young %lu, not young %lu\n" "pages read %lu, created %lu, written %lu\n", (ulong) size, (ulong) UT_LIST_GET_LEN(buf_pool->LRU), @@ -3810,8 +3899,11 @@ buf_print(void) (ulong) buf_pool->n_flush[BUF_FLUSH_LRU], (ulong) buf_pool->n_flush[BUF_FLUSH_LIST], (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE], - (ulong) buf_pool->n_pages_read, buf_pool->n_pages_created, - (ulong) buf_pool->n_pages_written); + (ulong) buf_pool->stat.n_pages_made_young, + (ulong) buf_pool->stat.n_pages_not_made_young, + (ulong) buf_pool->stat.n_pages_read, + (ulong) buf_pool->stat.n_pages_created, + (ulong) buf_pool->stat.n_pages_written); /* Count the number of blocks belonging to each index in the buffer */ @@ -4021,10 +4113,9 @@ buf_print_io( { time_t current_time; double time_elapsed; - ulint size; + ulint n_gets_diff; ut_ad(buf_pool); - size = buf_pool->curr_size; //buf_pool_mutex_enter(); mutex_enter(&LRU_list_mutex); @@ -4037,13 +4128,15 @@ buf_print_io( "Buffer pool size, bytes %lu\n" "Free buffers %lu\n" "Database pages %lu\n" + "Old database pages %lu\n" "Modified db pages %lu\n" "Pending reads %lu\n" "Pending writes: LRU %lu, flush list %lu, single page %lu\n", - (ulong) size, - (ulong) size * UNIV_PAGE_SIZE, + (ulong) buf_pool->curr_size, + (ulong) buf_pool->curr_size * UNIV_PAGE_SIZE, (ulong) UT_LIST_GET_LEN(buf_pool->free), (ulong) UT_LIST_GET_LEN(buf_pool->LRU), + (ulong) buf_pool->LRU_old_len, (ulong) UT_LIST_GET_LEN(buf_pool->flush_list), (ulong) buf_pool->n_pend_reads, (ulong) buf_pool->n_flush[BUF_FLUSH_LRU] @@ -4055,37 +4148,66 @@ buf_print_io( current_time = time(NULL); time_elapsed = 0.001 + difftime(current_time, buf_pool->last_printout_time); - buf_pool->last_printout_time = current_time; fprintf(file, + "Pages made young %lu, not young %lu\n" + "%.2f youngs/s, %.2f non-youngs/s\n" "Pages read %lu, created %lu, written %lu\n" "%.2f reads/s, %.2f creates/s, %.2f writes/s\n", - (ulong) buf_pool->n_pages_read, - (ulong) buf_pool->n_pages_created, - (ulong) buf_pool->n_pages_written, - (buf_pool->n_pages_read - buf_pool->n_pages_read_old) + (ulong) buf_pool->stat.n_pages_made_young, + (ulong) buf_pool->stat.n_pages_not_made_young, + (buf_pool->stat.n_pages_made_young + - buf_pool->old_stat.n_pages_made_young) / time_elapsed, - (buf_pool->n_pages_created - buf_pool->n_pages_created_old) + (buf_pool->stat.n_pages_not_made_young + - buf_pool->old_stat.n_pages_not_made_young) / time_elapsed, - (buf_pool->n_pages_written - buf_pool->n_pages_written_old) + (ulong) buf_pool->stat.n_pages_read, + (ulong) buf_pool->stat.n_pages_created, + (ulong) buf_pool->stat.n_pages_written, + (buf_pool->stat.n_pages_read + - buf_pool->old_stat.n_pages_read) + / time_elapsed, + (buf_pool->stat.n_pages_created + - buf_pool->old_stat.n_pages_created) + / time_elapsed, + (buf_pool->stat.n_pages_written + - buf_pool->old_stat.n_pages_written) / time_elapsed); - if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) { - fprintf(file, "Buffer pool hit rate %lu / 1000\n", + n_gets_diff = buf_pool->stat.n_page_gets - buf_pool->old_stat.n_page_gets; + + if (n_gets_diff) { + fprintf(file, + "Buffer pool hit rate %lu / 1000," + " young-making rate %lu / 1000 not %lu / 1000\n", (ulong) - (1000 - ((1000 * (buf_pool->n_pages_read - - buf_pool->n_pages_read_old)) - / (buf_pool->n_page_gets - - buf_pool->n_page_gets_old)))); + (1000 - ((1000 * (buf_pool->stat.n_pages_read + - buf_pool->old_stat.n_pages_read)) + / (buf_pool->stat.n_page_gets + - buf_pool->old_stat.n_page_gets))), + (ulong) + (1000 * (buf_pool->stat.n_pages_made_young + - buf_pool->old_stat.n_pages_made_young) + / n_gets_diff), + (ulong) + (1000 * (buf_pool->stat.n_pages_not_made_young + - buf_pool->old_stat.n_pages_not_made_young) + / n_gets_diff)); } else { fputs("No buffer pool page gets since the last printout\n", file); } - buf_pool->n_page_gets_old = buf_pool->n_page_gets; - buf_pool->n_pages_read_old = buf_pool->n_pages_read; - buf_pool->n_pages_created_old = buf_pool->n_pages_created; - buf_pool->n_pages_written_old = buf_pool->n_pages_written; + /* Statistics about read ahead algorithm */ + fprintf(file, "Pages read ahead %.2f/s," + " evicted without access %.2f/s\n", + (buf_pool->stat.n_ra_pages_read + - buf_pool->old_stat.n_ra_pages_read) + / time_elapsed, + (buf_pool->stat.n_ra_pages_evicted + - buf_pool->old_stat.n_ra_pages_evicted) + / time_elapsed); /* Print some values to help us with visualizing what is happening with LRU eviction. */ @@ -4097,6 +4219,7 @@ buf_print_io( buf_LRU_stat_sum.io, buf_LRU_stat_cur.io, buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip); + buf_refresh_io_stats(); //buf_pool_mutex_exit(); mutex_exit(&LRU_list_mutex); mutex_exit(&free_list_mutex); @@ -4112,10 +4235,7 @@ buf_refresh_io_stats(void) /*======================*/ { buf_pool->last_printout_time = time(NULL); - buf_pool->n_page_gets_old = buf_pool->n_page_gets; - buf_pool->n_pages_read_old = buf_pool->n_pages_read; - buf_pool->n_pages_created_old = buf_pool->n_pages_created; - buf_pool->n_pages_written_old = buf_pool->n_pages_written; + buf_pool->old_stat = buf_pool->stat; } /*********************************************************************//** diff --git a/buf/buf0flu.c b/buf/buf0flu.c index 6c25f0f55ae..9fb4fe7d9ea 100644 --- a/buf/buf0flu.c +++ b/buf/buf0flu.c @@ -330,6 +330,28 @@ buf_flush_write_complete( } } +/********************************************************************//** +Flush a batch of writes to the datafiles that have already been +written by the OS. */ +static +void +buf_flush_sync_datafiles(void) +/*==========================*/ +{ + /* Wake possible simulated aio thread to actually post the + writes to the operating system */ + os_aio_simulated_wake_handler_threads(); + + /* Wait that all async writes to tablespaces have been posted to + the OS */ + os_aio_wait_until_no_pending_writes(); + + /* Now we flush the data to disk (for example, with fsync) */ + fil_flush_file_spaces(FIL_TABLESPACE); + + return; +} + /********************************************************************//** Flushes possible buffered writes from the doublewrite memory buffer to disk, and also wakes up the aio thread if simulated aio is used. It is very @@ -347,8 +369,8 @@ buf_flush_buffered_writes(void) ulint i; if (!srv_use_doublewrite_buf || trx_doublewrite == NULL) { - os_aio_simulated_wake_handler_threads(); - + /* Sync the writes to the disk. */ + buf_flush_sync_datafiles(); return; } @@ -556,22 +578,10 @@ flush: buf_LRU_stat_inc_io(); } - /* Wake possible simulated aio thread to actually post the - writes to the operating system */ - - os_aio_simulated_wake_handler_threads(); - - /* Wait that all async writes to tablespaces have been posted to - the OS */ - - os_aio_wait_until_no_pending_writes(); - - /* Now we flush the data to disk (for example, with fsync) */ - - fil_flush_file_spaces(FIL_TABLESPACE); + /* Sync the writes to the disk. */ + buf_flush_sync_datafiles(); /* We can now reuse the doublewrite memory buffer: */ - trx_doublewrite->first_free = 0; mutex_exit(&(trx_doublewrite->mutex)); @@ -1048,6 +1058,7 @@ buf_flush_batch( min_n), otherwise ignored */ { buf_page_t* bpage; + buf_page_t* prev_bpage = NULL; ulint page_count = 0; ulint old_page_count; ulint space; @@ -1101,6 +1112,9 @@ flush_next: mutex_enter(&flush_list_mutex); remaining = UT_LIST_GET_LEN(buf_pool->flush_list); bpage = UT_LIST_GET_LAST(buf_pool->flush_list); + if (bpage) { + prev_bpage = UT_LIST_GET_PREV(flush_list, bpage); + } mutex_exit(&flush_list_mutex); if (!bpage || bpage->oldest_modification >= lsn_limit) { @@ -1163,6 +1177,13 @@ flush_next: mutex_enter(&flush_list_mutex); bpage = UT_LIST_GET_PREV(flush_list, bpage); //ut_ad(!bpage || bpage->in_flush_list); /* optimistic */ + if (bpage != prev_bpage) { + /* the search may warp.. retrying */ + bpage = NULL; + } + if (bpage) { + prev_bpage = UT_LIST_GET_PREV(flush_list, bpage); + } mutex_exit(&flush_list_mutex); remaining--; } diff --git a/buf/buf0lru.c b/buf/buf0lru.c index caddb51c983..58e2c23275b 100644 --- a/buf/buf0lru.c +++ b/buf/buf0lru.c @@ -49,18 +49,22 @@ Created 11/5/1995 Heikki Tuuri #include "log0recv.h" #include "srv0srv.h" -/** The number of blocks from the LRU_old pointer onward, including the block -pointed to, must be 3/8 of the whole LRU list length, except that the -tolerance defined below is allowed. Note that the tolerance must be small -enough such that for even the BUF_LRU_OLD_MIN_LEN long LRU list, the -LRU_old pointer is not allowed to point to either end of the LRU list. */ +/** The number of blocks from the LRU_old pointer onward, including +the block pointed to, must be buf_LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV +of the whole LRU list length, except that the tolerance defined below +is allowed. Note that the tolerance must be small enough such that for +even the BUF_LRU_OLD_MIN_LEN long LRU list, the LRU_old pointer is not +allowed to point to either end of the LRU list. */ #define BUF_LRU_OLD_TOLERANCE 20 -/** The whole LRU list length is divided by this number to determine an -initial segment in buf_LRU_get_recent_limit */ - -#define BUF_LRU_INITIAL_RATIO 8 +/** The minimum amount of non-old blocks when the LRU_old list exists +(that is, when there are more than BUF_LRU_OLD_MIN_LEN blocks). +@see buf_LRU_old_adjust_len */ +#define BUF_LRU_NON_OLD_MIN_LEN 5 +#if BUF_LRU_NON_OLD_MIN_LEN >= BUF_LRU_OLD_MIN_LEN +# error "BUF_LRU_NON_OLD_MIN_LEN >= BUF_LRU_OLD_MIN_LEN" +#endif /** When dropping the search hash index entries before deleting an ibd file, we build a local array of pages belonging to that tablespace @@ -107,6 +111,15 @@ UNIV_INTERN buf_LRU_stat_t buf_LRU_stat_sum; /* @} */ +/** @name Heuristics for detecting index scan @{ */ +/** Reserve this much/BUF_LRU_OLD_RATIO_DIV of the buffer pool for +"old" blocks. Protected by buf_pool_mutex. */ +UNIV_INTERN uint buf_LRU_old_ratio; +/** Move blocks to "new" LRU list only if the first access was at +least this many milliseconds ago. Not protected by any mutex or latch. */ +UNIV_INTERN uint buf_LRU_old_threshold_ms; +/* @} */ + /******************************************************************//** Takes a block out of the LRU list and page hash table. If the block is compressed-only (BUF_BLOCK_ZIP_PAGE), @@ -457,45 +470,6 @@ next_page: } } -/******************************************************************//** -Gets the minimum LRU_position field for the blocks in an initial segment -(determined by BUF_LRU_INITIAL_RATIO) of the LRU list. The limit is not -guaranteed to be precise, because the ulint_clock may wrap around. -@return the limit; zero if could not determine it */ -UNIV_INTERN -ulint -buf_LRU_get_recent_limit(void) -/*==========================*/ -{ - const buf_page_t* bpage; - ulint len; - ulint limit; - - //buf_pool_mutex_enter(); - mutex_enter(&LRU_list_mutex); - - len = UT_LIST_GET_LEN(buf_pool->LRU); - - if (len < BUF_LRU_OLD_MIN_LEN) { - /* The LRU list is too short to do read-ahead */ - - //buf_pool_mutex_exit(); - mutex_exit(&LRU_list_mutex); - - return(0); - } - - bpage = UT_LIST_GET_FIRST(buf_pool->LRU); - - limit = buf_page_get_LRU_position(bpage); - len /= BUF_LRU_INITIAL_RATIO; - - //buf_pool_mutex_exit(); - mutex_exit(&LRU_list_mutex); - - return(limit > len ? (limit - len) : 0); -} - /********************************************************************//** Insert a compressed block into buf_pool->zip_clean in the LRU order. */ UNIV_INTERN @@ -638,6 +612,7 @@ restart: bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) { enum buf_lru_free_block_status freed; + unsigned accessed; mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); @@ -654,11 +629,18 @@ restart: ut_ad(buf_page_in_file(bpage)); ut_ad(bpage->in_LRU_list); + accessed = buf_page_is_accessed(bpage); freed = buf_LRU_free_block(bpage, TRUE, NULL, have_LRU_mutex); mutex_exit(block_mutex); switch (freed) { case BUF_LRU_FREED: + /* Keep track of pages that are evicted without + ever being accessed. This gives us a measure of + the effectiveness of readahead */ + if (!accessed) { + ++buf_pool->stat.n_ra_pages_evicted; + } return(TRUE); case BUF_LRU_NOT_FREED: @@ -1036,8 +1018,10 @@ buf_LRU_old_adjust_len(void) ut_a(buf_pool->LRU_old); //ut_ad(buf_pool_mutex_own()); ut_ad(mutex_own(&LRU_list_mutex)); -#if 3 * (BUF_LRU_OLD_MIN_LEN / 8) <= BUF_LRU_OLD_TOLERANCE + 5 -# error "3 * (BUF_LRU_OLD_MIN_LEN / 8) <= BUF_LRU_OLD_TOLERANCE + 5" + ut_ad(buf_LRU_old_ratio >= BUF_LRU_OLD_RATIO_MIN); + ut_ad(buf_LRU_old_ratio <= BUF_LRU_OLD_RATIO_MAX); +#if BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5) +# error "BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)" #endif #ifdef UNIV_LRU_DEBUG /* buf_pool->LRU_old must be the first item in the LRU list @@ -1049,34 +1033,39 @@ buf_LRU_old_adjust_len(void) || UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old); #endif /* UNIV_LRU_DEBUG */ - for (;;) { - old_len = buf_pool->LRU_old_len; - new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8); + old_len = buf_pool->LRU_old_len; + new_len = ut_min(UT_LIST_GET_LEN(buf_pool->LRU) + * buf_LRU_old_ratio / BUF_LRU_OLD_RATIO_DIV, + UT_LIST_GET_LEN(buf_pool->LRU) + - (BUF_LRU_OLD_TOLERANCE + + BUF_LRU_NON_OLD_MIN_LEN)); - ut_ad(buf_pool->LRU_old->in_LRU_list); - ut_a(buf_pool->LRU_old); + for (;;) { + buf_page_t* LRU_old = buf_pool->LRU_old; + + ut_a(LRU_old); + ut_ad(LRU_old->in_LRU_list); #ifdef UNIV_LRU_DEBUG - ut_a(buf_pool->LRU_old->old); + ut_a(LRU_old->old); #endif /* UNIV_LRU_DEBUG */ /* Update the LRU_old pointer if necessary */ - if (old_len < new_len - BUF_LRU_OLD_TOLERANCE) { + if (old_len + BUF_LRU_OLD_TOLERANCE < new_len) { - buf_pool->LRU_old = UT_LIST_GET_PREV( - LRU, buf_pool->LRU_old); + buf_pool->LRU_old = LRU_old = UT_LIST_GET_PREV( + LRU, LRU_old); #ifdef UNIV_LRU_DEBUG - ut_a(!buf_pool->LRU_old->old); + ut_a(!LRU_old->old); #endif /* UNIV_LRU_DEBUG */ - buf_page_set_old(buf_pool->LRU_old, TRUE); - buf_pool->LRU_old_len++; + old_len = ++buf_pool->LRU_old_len; + buf_page_set_old(LRU_old, TRUE); } else if (old_len > new_len + BUF_LRU_OLD_TOLERANCE) { - buf_page_set_old(buf_pool->LRU_old, FALSE); - buf_pool->LRU_old = UT_LIST_GET_NEXT( - LRU, buf_pool->LRU_old); - buf_pool->LRU_old_len--; + buf_pool->LRU_old = UT_LIST_GET_NEXT(LRU, LRU_old); + old_len = --buf_pool->LRU_old_len; + buf_page_set_old(LRU_old, FALSE); } else { return; } @@ -1101,12 +1090,13 @@ buf_LRU_old_init(void) the adjust function to move the LRU_old pointer to the right position */ - bpage = UT_LIST_GET_FIRST(buf_pool->LRU); - - while (bpage != NULL) { + for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); bpage != NULL; + bpage = UT_LIST_GET_PREV(LRU, bpage)) { ut_ad(bpage->in_LRU_list); - buf_page_set_old(bpage, TRUE); - bpage = UT_LIST_GET_NEXT(LRU, bpage); + ut_ad(buf_page_in_file(bpage)); + /* This loop temporarily violates the + assertions of buf_page_set_old(). */ + bpage->old = TRUE; } buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU); @@ -1161,16 +1151,19 @@ buf_LRU_remove_block( if (UNIV_UNLIKELY(bpage == buf_pool->LRU_old)) { - /* Below: the previous block is guaranteed to exist, because - the LRU_old pointer is only allowed to differ by the - tolerance value from strict 3/8 of the LRU list length. */ + /* Below: the previous block is guaranteed to exist, + because the LRU_old pointer is only allowed to differ + by BUF_LRU_OLD_TOLERANCE from strict + buf_LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV of the LRU + list length. */ + buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage); - buf_pool->LRU_old = UT_LIST_GET_PREV(LRU, bpage); - ut_a(buf_pool->LRU_old); + ut_a(prev_bpage); #ifdef UNIV_LRU_DEBUG - ut_a(!buf_pool->LRU_old->old); + ut_a(!prev_bpage->old); #endif /* UNIV_LRU_DEBUG */ - buf_page_set_old(buf_pool->LRU_old, TRUE); + buf_pool->LRU_old = prev_bpage; + buf_page_set_old(prev_bpage, TRUE); buf_pool->LRU_old_len++; } @@ -1181,10 +1174,19 @@ buf_LRU_remove_block( buf_unzip_LRU_remove_block_if_needed(bpage); - /* If the LRU list is so short that LRU_old not defined, return */ + /* If the LRU list is so short that LRU_old is not defined, + clear the "old" flags and return */ if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) { + for (bpage = UT_LIST_GET_FIRST(buf_pool->LRU); bpage != NULL; + bpage = UT_LIST_GET_NEXT(LRU, bpage)) { + /* This loop temporarily violates the + assertions of buf_page_set_old(). */ + bpage->old = FALSE; + } + buf_pool->LRU_old = NULL; + buf_pool->LRU_old_len = 0; return; } @@ -1236,8 +1238,6 @@ buf_LRU_add_block_to_end_low( /*=========================*/ buf_page_t* bpage) /*!< in: control block */ { - buf_page_t* last_bpage; - ut_ad(buf_pool); ut_ad(bpage); //ut_ad(buf_pool_mutex_own()); @@ -1245,31 +1245,18 @@ buf_LRU_add_block_to_end_low( ut_a(buf_page_in_file(bpage)); - last_bpage = UT_LIST_GET_LAST(buf_pool->LRU); - - if (last_bpage) { - bpage->LRU_position = last_bpage->LRU_position; - } else { - bpage->LRU_position = buf_pool_clock_tic(); - } - ut_ad(!bpage->in_LRU_list); UT_LIST_ADD_LAST(LRU, buf_pool->LRU, bpage); bpage->in_LRU_list = TRUE; - buf_page_set_old(bpage, TRUE); - - if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) { - - buf_pool->LRU_old_len++; - } - if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) { ut_ad(buf_pool->LRU_old); /* Adjust the length of the old block list if necessary */ + buf_page_set_old(bpage, TRUE); + buf_pool->LRU_old_len++; buf_LRU_old_adjust_len(); } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) { @@ -1278,6 +1265,8 @@ buf_LRU_add_block_to_end_low( defined: init it */ buf_LRU_old_init(); + } else { + buf_page_set_old(bpage, buf_pool->LRU_old != NULL); } /* If this is a zipped block with decompressed frame as well @@ -1311,7 +1300,6 @@ buf_LRU_add_block_low( UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, bpage); - bpage->LRU_position = buf_pool_clock_tic(); bpage->freed_page_clock = buf_pool->freed_page_clock; } else { #ifdef UNIV_LRU_DEBUG @@ -1326,23 +1314,17 @@ buf_LRU_add_block_low( UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU, buf_pool->LRU_old, bpage); buf_pool->LRU_old_len++; - - /* We copy the LRU position field of the previous block - to the new block */ - - bpage->LRU_position = (buf_pool->LRU_old)->LRU_position; } bpage->in_LRU_list = TRUE; - buf_page_set_old(bpage, old); - if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) { ut_ad(buf_pool->LRU_old); /* Adjust the length of the old block list if necessary */ + buf_page_set_old(bpage, old); buf_LRU_old_adjust_len(); } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) { @@ -1351,6 +1333,8 @@ buf_LRU_add_block_low( defined: init it */ buf_LRU_old_init(); + } else { + buf_page_set_old(bpage, buf_pool->LRU_old != NULL); } /* If this is a zipped block with decompressed frame as well @@ -1384,6 +1368,13 @@ buf_LRU_make_block_young( /*=====================*/ buf_page_t* bpage) /*!< in: control block */ { + //ut_ad(buf_pool_mutex_own()); + ut_ad(mutex_own(&LRU_list_mutex)); + + if (bpage->old) { + buf_pool->stat.n_pages_made_young++; + } + buf_LRU_remove_block(bpage); buf_LRU_add_block_low(bpage, FALSE); } @@ -1580,15 +1571,6 @@ not_freed: buf_pool->LRU_old = b; } -#ifdef UNIV_LRU_DEBUG - ut_a(prev_b->old - || !UT_LIST_GET_NEXT(LRU, b) - || UT_LIST_GET_NEXT(LRU, b)->old); - } else { - ut_a(!prev_b->old - || !UT_LIST_GET_NEXT(LRU, b) - || !UT_LIST_GET_NEXT(LRU, b)->old); -#endif /* UNIV_LRU_DEBUG */ } lru_len = UT_LIST_GET_LEN(buf_pool->LRU); @@ -1604,6 +1586,11 @@ not_freed: defined: init it */ buf_LRU_old_init(); } +#ifdef UNIV_LRU_DEBUG + /* Check that the "old" flag is consistent + in the block and its neighbours. */ + buf_page_set_old(b, buf_page_is_old(b)); +#endif /* UNIV_LRU_DEBUG */ } else { b->in_LRU_list = FALSE; buf_LRU_add_block_low(b, buf_page_is_old(b)); @@ -1994,6 +1981,52 @@ buf_LRU_block_free_hashed_page( buf_LRU_block_free_non_file_page(block, have_page_hash_mutex); } +/**********************************************************************//** +Updates buf_LRU_old_ratio. +@return updated old_pct */ +UNIV_INTERN +uint +buf_LRU_old_ratio_update( +/*=====================*/ + uint old_pct,/*!< in: Reserve this percentage of + the buffer pool for "old" blocks. */ + ibool adjust) /*!< in: TRUE=adjust the LRU list; + FALSE=just assign buf_LRU_old_ratio + during the initialization of InnoDB */ +{ + uint ratio; + + ratio = old_pct * BUF_LRU_OLD_RATIO_DIV / 100; + if (ratio < BUF_LRU_OLD_RATIO_MIN) { + ratio = BUF_LRU_OLD_RATIO_MIN; + } else if (ratio > BUF_LRU_OLD_RATIO_MAX) { + ratio = BUF_LRU_OLD_RATIO_MAX; + } + + if (adjust) { + //buf_pool_mutex_enter(); + mutex_enter(&LRU_list_mutex); + + if (ratio != buf_LRU_old_ratio) { + buf_LRU_old_ratio = ratio; + + if (UT_LIST_GET_LEN(buf_pool->LRU) + >= BUF_LRU_OLD_MIN_LEN) { + buf_LRU_old_adjust_len(); + } + } + + //buf_pool_mutex_exit(); + mutex_exit(&LRU_list_mutex); + } else { + buf_LRU_old_ratio = ratio; + } + + /* the reverse of + ratio = old_pct * BUF_LRU_OLD_RATIO_DIV / 100 */ + return((uint) (ratio * 100 / (double) BUF_LRU_OLD_RATIO_DIV + 0.5)); +} + /********************************************************************//** Update the historical stats that we are collecting for LRU eviction policy at the end of each interval. */ @@ -2032,6 +2065,218 @@ func_exit: memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur); } +/********************************************************************//** +Dump the LRU page list to the specific file. */ +#define LRU_DUMP_FILE "ib_lru_dump" + +UNIV_INTERN +ibool +buf_LRU_file_dump(void) +/*===================*/ +{ + os_file_t dump_file = -1; + ibool success; + byte* buffer_base = NULL; + byte* buffer = NULL; + buf_page_t* bpage; + ulint buffers; + ulint offset; + ibool ret = FALSE; + ulint i; + + for (i = 0; i < srv_n_data_files; i++) { + if (strstr(srv_data_file_names[i], LRU_DUMP_FILE) != NULL) { + fprintf(stderr, + " InnoDB: The name '%s' seems to be used for" + " innodb_data_file_path. Dumping LRU list is not" + " done for safeness.\n", LRU_DUMP_FILE); + goto end; + } + } + + buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE); + buffer = ut_align(buffer_base, UNIV_PAGE_SIZE); + if (!buffer) { + fprintf(stderr, + " InnoDB: cannot allocate buffer.\n"); + goto end; + } + + dump_file = os_file_create(LRU_DUMP_FILE, OS_FILE_OVERWRITE, + OS_FILE_NORMAL, OS_DATA_FILE, &success); + if (!success) { + os_file_get_last_error(TRUE); + fprintf(stderr, + " InnoDB: cannot open %s\n", LRU_DUMP_FILE); + goto end; + } + + mutex_enter(&LRU_list_mutex); + bpage = UT_LIST_GET_LAST(buf_pool->LRU); + + buffers = offset = 0; + while (bpage != NULL) { + if (offset == 0) { + memset(buffer, 0, UNIV_PAGE_SIZE); + } + + mach_write_to_4(buffer + offset * 4, bpage->space); + offset++; + mach_write_to_4(buffer + offset * 4, bpage->offset); + offset++; + + if (offset == UNIV_PAGE_SIZE/4) { + success = os_file_write(LRU_DUMP_FILE, dump_file, buffer, + (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL, + (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)), + UNIV_PAGE_SIZE); + if (!success) { + mutex_exit(&LRU_list_mutex); + fprintf(stderr, + " InnoDB: cannot write page %lu of %s\n", + buffers, LRU_DUMP_FILE); + goto end; + } + buffers++; + offset = 0; + } + + bpage = UT_LIST_GET_PREV(LRU, bpage); + } + mutex_exit(&LRU_list_mutex); + + if (offset == 0) { + memset(buffer, 0, UNIV_PAGE_SIZE); + } + + mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL); + offset++; + mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL); + offset++; + + success = os_file_write(LRU_DUMP_FILE, dump_file, buffer, + (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL, + (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)), + UNIV_PAGE_SIZE); + if (!success) { + goto end; + } + + ret = TRUE; +end: + if (dump_file != -1) + os_file_close(dump_file); + if (buffer_base) + ut_free(buffer_base); + + return(ret); +} +/********************************************************************//** +Read the pages based on the specific file.*/ +UNIV_INTERN +ibool +buf_LRU_file_restore(void) +/*======================*/ +{ + os_file_t dump_file = -1; + ibool success; + byte* buffer_base = NULL; + byte* buffer = NULL; + ulint buffers; + ulint offset; + ulint reads = 0; + ulint req = 0; + ibool terminated = FALSE; + ibool ret = FALSE; + + buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE); + buffer = ut_align(buffer_base, UNIV_PAGE_SIZE); + if (!buffer) { + fprintf(stderr, + " InnoDB: cannot allocate buffer.\n"); + goto end; + } + + dump_file = os_file_create_simple_no_error_handling( + LRU_DUMP_FILE, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success); + if (!success) { + os_file_get_last_error(TRUE); + fprintf(stderr, + " InnoDB: cannot open %s\n", LRU_DUMP_FILE); + goto end; + } + + buffers = 0; + while (!terminated) { + success = os_file_read(dump_file, buffer, + (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL, + (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)), + UNIV_PAGE_SIZE); + if (!success) { + fprintf(stderr, + " InnoDB: cannot read page %lu of %s," + " or meet unexpected terminal.", + buffers, LRU_DUMP_FILE); + goto end; + } + + for (offset = 0; offset < UNIV_PAGE_SIZE/4; offset += 2) { + ulint space_id, zip_size, page_no; + ulint err; + ib_int64_t tablespace_version; + + space_id = mach_read_from_4(buffer + offset * 4); + page_no = mach_read_from_4(buffer + (offset + 1) * 4); + if (space_id == 0xFFFFFFFFUL + || page_no == 0xFFFFFFFFUL) { + terminated = TRUE; + break; + } + + if (offset % 16 == 15) { + os_aio_simulated_wake_handler_threads(); + buf_flush_free_margin(FALSE); + } + + zip_size = fil_space_get_zip_size(space_id); + if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) { + continue; + } + + if (fil_area_is_exist(space_id, zip_size, page_no, 0, + zip_size ? zip_size : UNIV_PAGE_SIZE)) { + + tablespace_version = fil_space_get_version(space_id); + + req++; + reads += buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE + | OS_AIO_SIMULATED_WAKE_LATER, + space_id, zip_size, TRUE, + tablespace_version, page_no, NULL); + buf_LRU_stat_inc_io(); + } + } + + buffers++; + } + + os_aio_simulated_wake_handler_threads(); + buf_flush_free_margin(FALSE); + + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: reading pages based on the dumped LRU list was done." + " (requested: %lu, read: %lu)\n", req, reads); + ret = TRUE; +end: + if (dump_file != -1) + os_file_close(dump_file); + if (buffer_base) + ut_free(buffer_base); + + return(ret); +} + #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /**********************************************************************//** Validates the LRU list. @@ -2045,7 +2290,6 @@ buf_LRU_validate(void) buf_block_t* block; ulint old_len; ulint new_len; - ulint LRU_pos; ut_ad(buf_pool); //buf_pool_mutex_enter(); @@ -2055,7 +2299,11 @@ buf_LRU_validate(void) ut_a(buf_pool->LRU_old); old_len = buf_pool->LRU_old_len; - new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8); + new_len = ut_min(UT_LIST_GET_LEN(buf_pool->LRU) + * buf_LRU_old_ratio / BUF_LRU_OLD_RATIO_DIV, + UT_LIST_GET_LEN(buf_pool->LRU) + - (BUF_LRU_OLD_TOLERANCE + + BUF_LRU_NON_OLD_MIN_LEN)); ut_a(old_len >= new_len - BUF_LRU_OLD_TOLERANCE); ut_a(old_len <= new_len + BUF_LRU_OLD_TOLERANCE); } @@ -2086,28 +2334,24 @@ buf_LRU_validate(void) } if (buf_page_is_old(bpage)) { - old_len++; - } + const buf_page_t* prev + = UT_LIST_GET_PREV(LRU, bpage); + const buf_page_t* next + = UT_LIST_GET_NEXT(LRU, bpage); - if (buf_pool->LRU_old && (old_len == 1)) { - ut_a(buf_pool->LRU_old == bpage); - } + if (!old_len++) { + ut_a(buf_pool->LRU_old == bpage); + } else { + ut_a(!prev || buf_page_is_old(prev)); + } - LRU_pos = buf_page_get_LRU_position(bpage); + ut_a(!next || buf_page_is_old(next)); + } bpage = UT_LIST_GET_NEXT(LRU, bpage); - - if (bpage) { - /* If the following assert fails, it may - not be an error: just the buf_pool clock - has wrapped around */ - ut_a(LRU_pos >= buf_page_get_LRU_position(bpage)); - } } - if (buf_pool->LRU_old) { - ut_a(buf_pool->LRU_old_len == old_len); - } + ut_a(buf_pool->LRU_old_len == old_len); mutex_exit(&LRU_list_mutex); mutex_enter(&free_list_mutex); @@ -2158,9 +2402,6 @@ buf_LRU_print(void) //buf_pool_mutex_enter(); mutex_enter(&LRU_list_mutex); - fprintf(stderr, "Pool ulint clock %lu\n", - (ulong) buf_pool->ulint_clock); - bpage = UT_LIST_GET_FIRST(buf_pool->LRU); while (bpage != NULL) { @@ -2191,18 +2432,16 @@ buf_LRU_print(void) const byte* frame; case BUF_BLOCK_FILE_PAGE: frame = buf_block_get_frame((buf_block_t*) bpage); - fprintf(stderr, "\nLRU pos %lu type %lu" + fprintf(stderr, "\ntype %lu" " index id %lu\n", - (ulong) buf_page_get_LRU_position(bpage), (ulong) fil_page_get_type(frame), (ulong) ut_dulint_get_low( btr_page_get_index_id(frame))); break; case BUF_BLOCK_ZIP_PAGE: frame = bpage->zip.data; - fprintf(stderr, "\nLRU pos %lu type %lu size %lu" + fprintf(stderr, "\ntype %lu size %lu" " index id %lu\n", - (ulong) buf_page_get_LRU_position(bpage), (ulong) fil_page_get_type(frame), (ulong) buf_page_get_zip_size(bpage), (ulong) ut_dulint_get_low( @@ -2210,8 +2449,7 @@ buf_LRU_print(void) break; default: - fprintf(stderr, "\nLRU pos %lu !state %lu!\n", - (ulong) buf_page_get_LRU_position(bpage), + fprintf(stderr, "\n!state %lu!\n", (ulong) buf_page_get_state(bpage)); break; } diff --git a/buf/buf0rea.c b/buf/buf0rea.c index 88ee5eb7431..08aaac788d5 100644 --- a/buf/buf0rea.c +++ b/buf/buf0rea.c @@ -38,14 +38,6 @@ Created 11/5/1995 Heikki Tuuri #include "srv0start.h" #include "srv0srv.h" -/** The size in blocks of the area where the random read-ahead algorithm counts -the accessed pages when deciding whether to read-ahead */ -#define BUF_READ_AHEAD_RANDOM_AREA BUF_READ_AHEAD_AREA - -/** There must be at least this many pages in buf_pool in the area to start -a random read-ahead */ -#define BUF_READ_AHEAD_RANDOM_THRESHOLD (1 + BUF_READ_AHEAD_RANDOM_AREA / 2) - /** The linear read-ahead area size */ #define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA @@ -62,8 +54,9 @@ flag is cleared and the x-lock released by an i/o-handler thread. @return 1 if a read request was queued, 0 if the page already resided in buf_pool, or if the page is in the doublewrite buffer blocks in which case it is never read into the pool, or if the tablespace does -not exist or is being dropped */ -static +not exist or is being dropped +@return 1 if read request is issued. 0 if it is not */ +UNIV_INTERN ulint buf_read_page_low( /*==============*/ @@ -205,186 +198,14 @@ not_to_recover: return(1); } -/********************************************************************//** -Applies a random read-ahead in buf_pool if there are at least a threshold -value of accessed pages from the random read-ahead area. Does not read any -page, not even the one at the position (space, offset), if the read-ahead -mechanism is not activated. NOTE 1: the calling thread may own latches on -pages: to avoid deadlocks this function must be written such that it cannot -end up waiting for these latches! NOTE 2: the calling thread must want -access to the page given: this rule is set to prevent unintended read-aheads -performed by ibuf routines, a situation which could result in a deadlock if -the OS does not support asynchronous i/o. -@return number of page read requests issued; NOTE that if we read ibuf -pages, it may happen that the page at the given page number does not -get read even if we return a positive value! */ -static -ulint -buf_read_ahead_random( -/*==================*/ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ - ulint offset, /*!< in: page number of a page which the current thread - wants to access */ - trx_t* trx) -{ - ib_int64_t tablespace_version; - ulint recent_blocks = 0; - ulint count; - ulint LRU_recent_limit; - ulint ibuf_mode; - ulint low, high; - ulint err; - ulint i; - ulint buf_read_ahead_random_area; - -// /* We have currently disabled random readahead */ -// return(0); - - if (!(srv_read_ahead & 1)) { - return(0); - } - - if (srv_startup_is_before_trx_rollback_phase) { - /* No read-ahead to avoid thread deadlocks */ - return(0); - } - - if (ibuf_bitmap_page(zip_size, offset) - || trx_sys_hdr_page(space, offset)) { - - /* If it is an ibuf bitmap page or trx sys hdr, we do - no read-ahead, as that could break the ibuf page access - order */ - - return(0); - } - - /* Remember the tablespace version before we ask te tablespace size - below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we - do not try to read outside the bounds of the tablespace! */ - - tablespace_version = fil_space_get_version(space); - - buf_read_ahead_random_area = BUF_READ_AHEAD_RANDOM_AREA; - - low = (offset / buf_read_ahead_random_area) - * buf_read_ahead_random_area; - high = (offset / buf_read_ahead_random_area + 1) - * buf_read_ahead_random_area; - if (high > fil_space_get_size(space)) { - - high = fil_space_get_size(space); - } - - /* Get the minimum LRU_position field value for an initial segment - of the LRU list, to determine which blocks have recently been added - to the start of the list. */ - - LRU_recent_limit = buf_LRU_get_recent_limit(); - - //buf_pool_mutex_enter(); - mutex_enter(&buf_pool_mutex); - - if (buf_pool->n_pend_reads - > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) { - //buf_pool_mutex_exit(); - mutex_exit(&buf_pool_mutex); - - return(0); - } - mutex_exit(&buf_pool_mutex); - - /* Count how many blocks in the area have been recently accessed, - that is, reside near the start of the LRU list. */ - - rw_lock_s_lock(&page_hash_latch); - for (i = low; i < high; i++) { - const buf_page_t* bpage = buf_page_hash_get(space, i); - - if (bpage - && buf_page_is_accessed(bpage) - && (buf_page_get_LRU_position(bpage) > LRU_recent_limit)) { - - recent_blocks++; - - if (recent_blocks >= BUF_READ_AHEAD_RANDOM_THRESHOLD) { - - //buf_pool_mutex_exit(); - rw_lock_s_unlock(&page_hash_latch); - goto read_ahead; - } - } - } - - //buf_pool_mutex_exit(); - rw_lock_s_unlock(&page_hash_latch); - /* Do nothing */ - return(0); - -read_ahead: - /* Read all the suitable blocks within the area */ - - if (ibuf_inside()) { - ibuf_mode = BUF_READ_IBUF_PAGES_ONLY; - } else { - ibuf_mode = BUF_READ_ANY_PAGE; - } - - count = 0; - - for (i = low; i < high; i++) { - /* It is only sensible to do read-ahead in the non-sync aio - mode: hence FALSE as the first parameter */ - - if (!ibuf_bitmap_page(zip_size, i)) { - count += buf_read_page_low( - &err, FALSE, - ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, - space, zip_size, FALSE, - tablespace_version, i, trx); - if (err == DB_TABLESPACE_DELETED) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Warning: in random" - " readahead trying to access\n" - "InnoDB: tablespace %lu page %lu,\n" - "InnoDB: but the tablespace does not" - " exist or is just being dropped.\n", - (ulong) space, (ulong) i); - } - } - } - - /* In simulated aio we wake the aio handler threads only after - queuing all aio requests, in native aio the following call does - nothing: */ - - os_aio_simulated_wake_handler_threads(); - -#ifdef UNIV_DEBUG - if (buf_debug_prints && (count > 0)) { - fprintf(stderr, - "Random read-ahead space %lu offset %lu pages %lu\n", - (ulong) space, (ulong) offset, - (ulong) count); - } -#endif /* UNIV_DEBUG */ - - ++srv_read_ahead_rnd; - return(count); -} - /********************************************************************//** High-level function which reads a page asynchronously from a file to the buffer buf_pool if it is not already there. Sets the io_fix flag and sets an exclusive lock on the buffer frame. The flag is cleared and the x-lock -released by the i/o-handler thread. Does a random read-ahead if it seems -sensible. -@return number of page read requests issued: this can be greater than -1 if read-ahead occurred */ +released by the i/o-handler thread. +@return TRUE if page has been read in, FALSE in case of failure */ UNIV_INTERN -ulint +ibool buf_read_page( /*==========*/ ulint space, /*!< in: space id */ @@ -394,20 +215,17 @@ buf_read_page( { ib_int64_t tablespace_version; ulint count; - ulint count2; ulint err; tablespace_version = fil_space_get_version(space); - count = buf_read_ahead_random(space, zip_size, offset, trx); - /* We do the i/o in the synchronous aio mode to save thread switches: hence TRUE */ - count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, - zip_size, FALSE, - tablespace_version, offset, trx); - srv_buf_pool_reads+= count2; + count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, + zip_size, FALSE, + tablespace_version, offset, trx); + srv_buf_pool_reads += count; if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); fprintf(stderr, @@ -424,14 +242,14 @@ buf_read_page( /* Increment number of I/O operations used for LRU policy. */ buf_LRU_stat_inc_io(); - return(count + count2); + return(count > 0); } /********************************************************************//** Applies linear read-ahead if in the buf_pool the page is a border page of a linear read-ahead area and all the pages in the area have been accessed. Does not read any page if the read-ahead mechanism is not activated. Note -that the the algorithm looks at the 'natural' adjacent successor and +that the algorithm looks at the 'natural' adjacent successor and predecessor of the page, which on the leaf level of a B-tree are the next and previous page in the chain of leaves. To know these, the page specified in (space, offset) must already be present in the buf_pool. Thus, the @@ -561,9 +379,17 @@ buf_read_ahead_linear( fail_count++; } else if (pred_bpage) { - int res = (ut_ulint_cmp( - buf_page_get_LRU_position(bpage), - buf_page_get_LRU_position(pred_bpage))); + /* Note that buf_page_is_accessed() returns + the time of the first access. If some blocks + of the extent existed in the buffer pool at + the time of a linear access pattern, the first + access times may be nonmonotonic, even though + the latest access times were linear. The + threshold (srv_read_ahead_factor) should help + a little against this. */ + int res = ut_ulint_cmp( + buf_page_is_accessed(bpage), + buf_page_is_accessed(pred_bpage)); /* Accesses not in the right order */ if (res != 0 && res != asc_or_desc) { fail_count++; @@ -709,7 +535,7 @@ buf_read_ahead_linear( LRU policy decision. */ buf_LRU_stat_inc_io(); - ++srv_read_ahead_seq; + buf_pool->stat.n_ra_pages_read += count; return(count); } diff --git a/data/data0type.c b/data/data0type.c index 8429775e7d8..e834fd2ec55 100644 --- a/data/data0type.c +++ b/data/data0type.c @@ -237,6 +237,22 @@ dtype_print( fputs("DATA_SYS", stderr); break; + case DATA_FLOAT: + fputs("DATA_FLOAT", stderr); + break; + + case DATA_DOUBLE: + fputs("DATA_DOUBLE", stderr); + break; + + case DATA_DECIMAL: + fputs("DATA_DECIMAL", stderr); + break; + + case DATA_VARMYSQL: + fputs("DATA_VARMYSQL", stderr); + break; + default: fprintf(stderr, "type %lu", (ulong) mtype); break; diff --git a/dict/dict0crea.c b/dict/dict0crea.c index 10e3ff409f3..f548d89bc68 100644 --- a/dict/dict0crea.c +++ b/dict/dict0crea.c @@ -1387,7 +1387,7 @@ dict_create_add_foreign_field_to_dictionary( Add a single foreign key definition to the data dictionary tables in the database. We also generate names to constraints that were not named by the user. A generated constraint has a name of the format -databasename/tablename_ibfk_, where the numbers start from 1, and +databasename/tablename_ibfk_NUMBER, where the numbers start from 1, and are given locally for this table, that is, the number is not global, as in the old format constraints < 4.0.18 it used to be. @return error code or DB_SUCCESS */ diff --git a/dict/dict0dict.c b/dict/dict0dict.c index 050182bc831..3f5dd2930e3 100644 --- a/dict/dict0dict.c +++ b/dict/dict0dict.c @@ -82,9 +82,10 @@ static char dict_ibfk[] = "_ibfk_"; /*******************************************************************//** Tries to find column names for the index and sets the col field of the -index. */ +index. +@return TRUE if the column names were found */ static -void +ibool dict_index_find_cols( /*=================*/ dict_table_t* table, /*!< in: table */ @@ -1261,7 +1262,7 @@ dict_index_too_big_for_undo( = TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE + 2 /* next record pointer */ + 1 /* type_cmpl */ - + 11 /* trx->undo_no */ - 11 /* table->id */ + + 11 /* trx->undo_no */ + 11 /* table->id */ + 1 /* rec_get_info_bits() */ + 11 /* DB_TRX_ID */ + 11 /* DB_ROLL_PTR */ @@ -1440,7 +1441,11 @@ dict_index_too_big_for_tree( goto add_field_size; } + if (srv_relax_table_creation) { + field_max_size = dict_col_get_min_size(col); + } else { field_max_size = dict_col_get_max_size(col); + } field_ext_max_size = field_max_size < 256 ? 1 : 2; if (field->prefix_len) { @@ -1493,7 +1498,7 @@ add_field_size: /**********************************************************************//** Adds an index to the dictionary cache. -@return DB_SUCCESS or DB_TOO_BIG_RECORD */ +@return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */ UNIV_INTERN ulint dict_index_add_to_cache( @@ -1519,7 +1524,10 @@ dict_index_add_to_cache( ut_a(!dict_index_is_clust(index) || UT_LIST_GET_LEN(table->indexes) == 0); - dict_index_find_cols(table, index); + if (!dict_index_find_cols(table, index)) { + + return(DB_CORRUPTION); + } /* Build the cache internal representation of the index, containing also the added system fields */ @@ -1732,9 +1740,10 @@ dict_index_remove_from_cache( /*******************************************************************//** Tries to find column names for the index and sets the col field of the -index. */ +index. +@return TRUE if the column names were found */ static -void +ibool dict_index_find_cols( /*=================*/ dict_table_t* table, /*!< in: table */ @@ -1759,17 +1768,21 @@ dict_index_find_cols( } } +#ifdef UNIV_DEBUG /* It is an error not to find a matching column. */ fputs("InnoDB: Error: no matching column for ", stderr); ut_print_name(stderr, NULL, FALSE, field->name); fputs(" in ", stderr); dict_index_name_print(stderr, NULL, index); fputs("!\n", stderr); - ut_error; +#endif /* UNIV_DEBUG */ + return(FALSE); found: ; } + + return(TRUE); } #endif /* !UNIV_HOTBACKUP */ @@ -4711,6 +4724,26 @@ dict_ind_init(void) dict_ind_redundant->cached = dict_ind_compact->cached = TRUE; } +/**********************************************************************//** +Frees dict_ind_redundant and dict_ind_compact. */ +static +void +dict_ind_free(void) +/*===============*/ +{ + dict_table_t* table; + + table = dict_ind_compact->table; + dict_mem_index_free(dict_ind_compact); + dict_ind_compact = NULL; + dict_mem_table_free(table); + + table = dict_ind_redundant->table; + dict_mem_index_free(dict_ind_redundant); + dict_ind_redundant = NULL; + dict_mem_table_free(table); +} + #ifndef UNIV_HOTBACKUP /**********************************************************************//** Get index by name @@ -4836,4 +4869,55 @@ dict_table_check_for_dup_indexes( } } #endif /* UNIV_DEBUG */ + +/************************************************************************** +Closes the data dictionary module. */ +UNIV_INTERN +void +dict_close(void) +/*============*/ +{ + ulint i; + + /* Free the hash elements. We don't remove them from the table + because we are going to destroy the table anyway. */ + for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) { + dict_table_t* table; + + table = HASH_GET_FIRST(dict_sys->table_hash, i); + + while (table) { + dict_table_t* prev_table = table; + + table = HASH_GET_NEXT(name_hash, prev_table); +#ifdef UNIV_DEBUG + ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N); +#endif + /* Acquire only because it's a pre-condition. */ + mutex_enter(&dict_sys->mutex); + + dict_table_remove_from_cache(prev_table); + + mutex_exit(&dict_sys->mutex); + } + } + + hash_table_free(dict_sys->table_hash); + + /* The elements are the same instance as in dict_sys->table_hash, + therefore we don't delete the individual elements. */ + hash_table_free(dict_sys->table_id_hash); + + dict_ind_free(); + + mutex_free(&dict_sys->mutex); + + rw_lock_free(&dict_operation_lock); + memset(&dict_operation_lock, 0x0, sizeof(dict_operation_lock)); + + mutex_free(&dict_foreign_err_mutex); + + mem_free(dict_sys); + dict_sys = NULL; +} #endif /* !UNIV_HOTBACKUP */ diff --git a/fil/fil0fil.c b/fil/fil0fil.c index e06dc1906c6..2293d140b2b 100644 --- a/fil/fil0fil.c +++ b/fil/fil0fil.c @@ -325,6 +325,17 @@ fil_get_space_id_for_table( /*=======================*/ const char* name); /*!< in: table name in the standard 'databasename/tablename' format */ +/*******************************************************************//** +Frees a space object from the tablespace memory cache. Closes the files in +the chain but does not delete them. There must not be any pending i/o's or +flushes on the files. */ +static +ibool +fil_space_free( +/*===========*/ + /* out: TRUE if success */ + ulint id, /* in: space id */ + ibool own_mutex);/* in: TRUE if own system->mutex */ /********************************************************************//** Reads data from a space to a buffer. Remember that the possible incomplete blocks at the end of file are ignored: they are not taken into account when @@ -598,6 +609,11 @@ fil_node_create( UT_LIST_ADD_LAST(chain, space->chain, node); + if (id < SRV_LOG_SPACE_FIRST_ID && fil_system->max_assigned_id < id) { + + fil_system->max_assigned_id = id; + } + mutex_exit(&fil_system->mutex); } @@ -617,12 +633,10 @@ fil_node_open_file( ulint size_high; ibool ret; ibool success; -#ifndef UNIV_HOTBACKUP byte* buf2; byte* page; ulint space_id; ulint flags; -#endif /* !UNIV_HOTBACKUP */ ut_ad(mutex_own(&(system->mutex))); ut_a(node->n_pending == 0); @@ -658,9 +672,12 @@ fil_node_open_file( size_bytes = (((ib_int64_t)size_high) << 32) + (ib_int64_t)size_low; #ifdef UNIV_HOTBACKUP - node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE); - /* TODO: adjust to zip_size, like below? */ -#else + if (space->id == 0) { + node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE); + os_file_close(node->handle); + goto add_size; + } +#endif /* UNIV_HOTBACKUP */ ut_a(space->purpose != FIL_LOG); ut_a(space->id != 0); @@ -739,7 +756,10 @@ fil_node_open_file( (size_bytes / dict_table_flags_to_zip_size(flags)); } -#endif + +#ifdef UNIV_HOTBACKUP +add_size: +#endif /* UNIV_HOTBACKUP */ space->size += node->size; } @@ -959,7 +979,7 @@ close_more: " while the maximum\n" "InnoDB: allowed value would be %lu.\n" "InnoDB: You may need to raise the value of" - " innodb_max_files_open in\n" + " innodb_open_files in\n" "InnoDB: my.cnf.\n", (ulong) fil_system->n_open, (ulong) fil_system->max_n_open); @@ -1139,7 +1159,7 @@ try_again: mutex_exit(&fil_system->mutex); - fil_space_free(namesake_id); + fil_space_free(namesake_id, FALSE); goto try_again; } @@ -1264,17 +1284,21 @@ Frees a space object from the tablespace memory cache. Closes the files in the chain but does not delete them. There must not be any pending i/o's or flushes on the files. @return TRUE if success */ -UNIV_INTERN +static ibool fil_space_free( /*===========*/ - ulint id) /*!< in: space id */ + /* out: TRUE if success */ + ulint id, /* in: space id */ + ibool own_mutex) /* in: TRUE if own system->mutex */ { fil_space_t* space; fil_space_t* namespace; fil_node_t* fil_node; - mutex_enter(&fil_system->mutex); + if (!own_mutex) { + mutex_enter(&fil_system->mutex); + } space = fil_space_get_by_id(id); @@ -1321,7 +1345,9 @@ fil_space_free( ut_a(0 == UT_LIST_GET_LEN(space->chain)); - mutex_exit(&fil_system->mutex); + if (!own_mutex) { + mutex_exit(&fil_system->mutex); + } rw_lock_free(&(space->latch)); @@ -1539,7 +1565,7 @@ fil_open_log_and_system_tablespace_files(void) fprintf(stderr, "InnoDB: Warning: you must" " raise the value of" - " innodb_max_open_files in\n" + " innodb_open_files in\n" "InnoDB: my.cnf! Remember that" " InnoDB keeps all log files" " and all system\n" @@ -1581,6 +1607,8 @@ fil_close_all_files(void) space = UT_LIST_GET_FIRST(fil_system->space_list); while (space != NULL) { + fil_space_t* prev_space = space; + node = UT_LIST_GET_FIRST(space->chain); while (node != NULL) { @@ -1590,6 +1618,7 @@ fil_close_all_files(void) node = UT_LIST_GET_NEXT(chain, node); } space = UT_LIST_GET_NEXT(space_list, space); + fil_space_free(prev_space->id, TRUE); } mutex_exit(&fil_system->mutex); @@ -2221,7 +2250,7 @@ try_again: #endif /* printf("Deleting tablespace %s id %lu\n", space->name, id); */ - success = fil_space_free(id); + success = fil_space_free(id, FALSE); if (success) { success = os_file_delete(path); @@ -2927,7 +2956,6 @@ fil_open_single_table_tablespace( byte* page; ulint space_id; ulint space_flags; - ibool ret = TRUE; filepath = fil_make_ibd_name(name, FALSE); @@ -3328,7 +3356,7 @@ skip_write: (ulong) space_id, (ulong) space_flags, (ulong) id, (ulong) flags); - ret = FALSE; + success = FALSE; goto func_exit; } @@ -3348,7 +3376,7 @@ func_exit: os_file_close(file); mem_free(filepath); - return(ret); + return(success); } #endif /* !UNIV_HOTBACKUP */ @@ -3564,7 +3592,7 @@ fil_load_single_table_tablespace( fprintf(stderr, "InnoDB: Renaming tablespace %s of id %lu,\n" "InnoDB: to %s_ibbackup_old_vers_\n" - "InnoDB: because its size %lld is too small" + "InnoDB: because its size %" PRId64 " is too small" " (< 4 pages 16 kB each),\n" "InnoDB: or the space id in the file header" " is not sensible.\n" @@ -3626,7 +3654,17 @@ fil_load_single_table_tablespace( if (!success) { - goto func_exit; + if (srv_force_recovery > 0) { + fprintf(stderr, + "InnoDB: innodb_force_recovery" + " was set to %lu. Continuing crash recovery\n" + "InnoDB: even though the tablespace creation" + " of this table failed.\n", + srv_force_recovery); + goto func_exit; + } + + exit(1); } /* We do not use the size information we have about the file, because @@ -4705,6 +4743,78 @@ _fil_io( return(DB_SUCCESS); } +/********************************************************************//** +Confirm whether the parameters are valid or not */ +UNIV_INTERN +ibool +fil_area_is_exist( +/*==============*/ + ulint space_id, /*!< in: space id */ + ulint zip_size, /*!< in: compressed page size in bytes; + 0 for uncompressed pages */ + ulint block_offset, /*!< in: offset in number of blocks */ + ulint byte_offset, /*!< in: remainder of offset in bytes; in + aio this must be divisible by the OS block + size */ + ulint len) /*!< in: how many bytes to read or write; this + must not cross a file boundary; in aio this + must be a block size multiple */ +{ + fil_space_t* space; + fil_node_t* node; + + /* Reserve the fil_system mutex and make sure that we can open at + least one file while holding it, if the file is not already open */ + + fil_mutex_enter_and_prepare_for_io(space_id); + + space = fil_space_get_by_id(space_id); + + if (!space) { + mutex_exit(&fil_system->mutex); + return(FALSE); + } + + node = UT_LIST_GET_FIRST(space->chain); + + for (;;) { + if (UNIV_UNLIKELY(node == NULL)) { + mutex_exit(&fil_system->mutex); + return(FALSE); + } + + if (space->id != 0 && node->size == 0) { + /* We do not know the size of a single-table tablespace + before we open the file */ + + break; + } + + if (node->size > block_offset) { + /* Found! */ + break; + } else { + block_offset -= node->size; + node = UT_LIST_GET_NEXT(chain, node); + } + } + + /* Open file if closed */ + fil_node_prepare_for_io(node, fil_system, space); + fil_node_complete_io(node, fil_system, OS_FILE_READ); + + /* Check that at least the start offset is within the bounds of a + single-table tablespace */ + if (UNIV_UNLIKELY(node->size <= block_offset) + && space->id != 0 && space->purpose == FIL_TABLESPACE) { + mutex_exit(&fil_system->mutex); + return(FALSE); + } + + mutex_exit(&fil_system->mutex); + return(TRUE); +} + #ifndef UNIV_HOTBACKUP /**********************************************************************//** Waits for an aio operation to complete. This function is used to write the @@ -5064,6 +5174,29 @@ fil_page_get_type( return(mach_read_from_2(page + FIL_PAGE_TYPE)); } +/******************************************************************** +Initializes the tablespace memory cache. */ +UNIV_INTERN +void +fil_close(void) +/*===========*/ +{ + /* The mutex should already have been freed. */ + ut_ad(fil_system->mutex.magic_n == 0); + + hash_table_free(fil_system->spaces); + + hash_table_free(fil_system->name_hash); + + ut_a(UT_LIST_GET_LEN(fil_system->LRU) == 0); + ut_a(UT_LIST_GET_LEN(fil_system->unflushed_spaces) == 0); + ut_a(UT_LIST_GET_LEN(fil_system->space_list) == 0); + + mem_free(fil_system); + + fil_system = NULL; +} + /************************************************************************* Return local hash table informations. */ diff --git a/fsp/fsp0fsp.c b/fsp/fsp0fsp.c index ce14723ba18..3cc4318fc06 100644 --- a/fsp/fsp0fsp.c +++ b/fsp/fsp0fsp.c @@ -232,6 +232,9 @@ the extent are free and which contain old tuple version to clean. */ #define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE) #ifndef UNIV_HOTBACKUP +/* Flag to indicate if we have printed the tablespace full error. */ +static ibool fsp_tbs_full_error_printed = FALSE; + /**********************************************************************//** Returns an extent to the free list of a space. */ static @@ -1099,7 +1102,7 @@ fsp_header_inc_size( /**********************************************************************//** Gets the current free limit of the system tablespace. The free limit -means the place of the first page which has never been put to the the +means the place of the first page which has never been put to the free list for allocation. The space above that address is initialized to zero. Sets also the global variable log_fsp_current_free_limit. @return free limit in megabytes */ @@ -1218,6 +1221,19 @@ fsp_try_extend_data_file( if (space == 0 && !srv_auto_extend_last_data_file) { + /* We print the error message only once to avoid + spamming the error log. Note that we don't need + to reset the flag to FALSE as dealing with this + error requires server restart. */ + if (fsp_tbs_full_error_printed == FALSE) { + fprintf(stderr, + "InnoDB: Error: Data file(s) ran" + " out of space.\n" + "Please add another data file or" + " use \'autoextend\' for the last" + " data file.\n"); + fsp_tbs_full_error_printed = TRUE; + } return(FALSE); } @@ -1832,6 +1848,8 @@ fsp_seg_inode_page_find_used( if (!ut_dulint_is_zero(mach_read_from_8(inode + FSEG_ID))) { /* This is used */ + ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) + == FSEG_MAGIC_N_VALUE); return(i); } } @@ -1863,6 +1881,9 @@ fsp_seg_inode_page_find_free( return(i); } + + ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) + == FSEG_MAGIC_N_VALUE); } return(ULINT_UNDEFINED); @@ -1981,6 +2002,8 @@ fsp_alloc_seg_inode( page + FSEG_INODE_PAGE_NODE, mtr); } + ut_ad(ut_dulint_is_zero(mach_read_from_8(inode + FSEG_ID)) + || mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); return(inode); } @@ -2018,7 +2041,7 @@ fsp_free_seg_inode( } mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr); - mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr); + mlog_write_ulint(inode + FSEG_MAGIC_N, 0xfa051ce3, MLOG_4BYTES, mtr); if (ULINT_UNDEFINED == fsp_seg_inode_page_find_used(page, zip_size, mtr)) { @@ -2034,11 +2057,11 @@ fsp_free_seg_inode( /**********************************************************************//** Returns the file segment inode, page x-latched. -@return segment inode, page x-latched */ +@return segment inode, page x-latched; NULL if the inode is free */ static fseg_inode_t* -fseg_inode_get( -/*===========*/ +fseg_inode_try_get( +/*===============*/ fseg_header_t* header, /*!< in: segment header */ ulint space, /*!< in: space id */ ulint zip_size,/*!< in: compressed page size in bytes @@ -2054,8 +2077,34 @@ fseg_inode_get( inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr); - ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); + if (UNIV_UNLIKELY + (ut_dulint_is_zero(mach_read_from_8(inode + FSEG_ID)))) { + inode = NULL; + } else { + ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) + == FSEG_MAGIC_N_VALUE); + } + + return(inode); +} + +/**********************************************************************//** +Returns the file segment inode, page x-latched. +@return segment inode, page x-latched */ +static +fseg_inode_t* +fseg_inode_get( +/*===========*/ + fseg_header_t* header, /*!< in: segment header */ + ulint space, /*!< in: space id */ + ulint zip_size,/*!< in: compressed page size in bytes + or 0 for uncompressed pages */ + mtr_t* mtr) /*!< in: mtr handle */ +{ + fseg_inode_t* inode + = fseg_inode_try_get(header, space, zip_size, mtr); + ut_a(inode); return(inode); } @@ -2073,6 +2122,7 @@ fseg_get_nth_frag_page_no( ut_ad(inode && mtr); ut_ad(n < FSEG_FRAG_ARR_N_SLOTS); ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); return(mach_read_from_4(inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE)); } @@ -2091,6 +2141,7 @@ fseg_set_nth_frag_page_no( ut_ad(inode && mtr); ut_ad(n < FSEG_FRAG_ARR_N_SLOTS); ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); mlog_write_ulint(inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE, page_no, MLOG_4BYTES, mtr); @@ -2451,6 +2502,8 @@ fseg_fill_free_list( xdes_set_state(descr, XDES_FSEG, mtr); seg_id = mtr_read_dulint(inode + FSEG_ID, mtr); + ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) + == FSEG_MAGIC_N_VALUE); mlog_write_dulint(descr + XDES_ID, seg_id, mtr); flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr); @@ -2479,6 +2532,7 @@ fseg_alloc_free_extent( fil_addr_t first; ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); + ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); if (flst_get_len(inode + FSEG_FREE, mtr) > 0) { /* Segment free list is not empty, allocate from it */ @@ -3136,6 +3190,8 @@ fseg_mark_page_used( ut_ad(seg_inode && mtr); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); + ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) + == FSEG_MAGIC_N_VALUE); descr = xdes_get_descriptor(space, zip_size, page, mtr); @@ -3373,6 +3429,8 @@ fseg_free_extent( ut_a(xdes_get_state(descr, mtr) == XDES_FSEG); ut_a(0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, mtr), mtr_read_dulint(seg_inode + FSEG_ID, mtr))); + ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) + == FSEG_MAGIC_N_VALUE); first_page_in_extent = page - (page % FSP_EXTENT_SIZE); @@ -3463,7 +3521,13 @@ fseg_free_step( ut_a(descr); ut_a(xdes_get_bit(descr, XDES_FREE_BIT, header_page % FSP_EXTENT_SIZE, mtr) == FALSE); - inode = fseg_inode_get(header, space, zip_size, mtr); + inode = fseg_inode_try_get(header, space, zip_size, mtr); + + if (UNIV_UNLIKELY(inode == NULL)) { + fprintf(stderr, "double free of inode from %u:%u\n", + (unsigned) space, (unsigned) header_page); + return(TRUE); + } descr = fseg_get_first_extent(inode, space, zip_size, mtr); @@ -3587,6 +3651,7 @@ fseg_get_first_extent( ut_ad(inode && mtr); ut_ad(space == page_get_space_id(page_align(inode))); + ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); first = fil_addr_null; @@ -3801,6 +3866,7 @@ fseg_print_low( (ulong) reserved, (ulong) used, (ulong) n_full, (ulong) n_frag, (ulong) n_free, (ulong) n_not_full, (ulong) n_used); + ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); } #ifdef UNIV_BTR_PRINT diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index c2f2113d571..d53c7aa91d5 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -82,6 +82,7 @@ int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, /* Include necessary InnoDB headers */ extern "C" { #include "univ.i" +#include "buf0lru.h" #include "btr0sea.h" #include "os0file.h" #include "os0thread.h" @@ -114,7 +115,6 @@ extern "C" { #include "ha_innodb.h" #include "i_s.h" -#include "handler0vars.h" #ifdef MYSQL_SERVER // Defined in trx0sys.c @@ -125,9 +125,12 @@ extern ib_int64_t trx_sys_mysql_relay_log_pos; #endif /* MYSQL_SERVER */ #ifndef MYSQL_SERVER -/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t +# ifndef MYSQL_PLUGIN_IMPORT +# define MYSQL_PLUGIN_IMPORT /* nothing */ +# endif /* MYSQL_PLUGIN_IMPORT */ +/* 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; +extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count; #if MYSQL_VERSION_ID < 50124 /* this is defined in mysql_priv.h inside #ifdef MYSQL_SERVER @@ -144,19 +147,16 @@ static ulong commit_threads = 0; static pthread_mutex_t commit_threads_m; static pthread_cond_t commit_cond; static pthread_mutex_t commit_cond_m; +static pthread_mutex_t analyze_mutex; static bool innodb_inited = 0; #define INSIDE_HA_INNOBASE_CC /* In the Windows plugin, the return value of current_thd is undefined. Map it to NULL. */ -#if defined MYSQL_DYNAMIC_PLUGIN && defined __WIN__ -# undef current_thd -# define current_thd NULL -# define EQ_CURRENT_THD(thd) TRUE -#else /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */ -# define EQ_CURRENT_THD(thd) ((thd) == current_thd) -#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */ + +#define EQ_CURRENT_THD(thd) ((thd) == current_thd) + static struct handlerton* innodb_hton_ptr; @@ -176,6 +176,10 @@ static ulong innobase_write_io_threads; static my_bool innobase_thread_concurrency_timer_based; static long long innobase_buffer_pool_size, innobase_log_file_size; +/** Percentage of the buffer pool to reserve for 'old' blocks. +Connected to buf_LRU_old_ratio. */ +static uint innobase_old_blocks_pct; + /* The default values for the following char* start-up parameters are determined in innobase_init below: */ @@ -190,9 +194,7 @@ file formats in the configuration file, but can only be set to any of the supported file formats during runtime. */ static char* innobase_file_format_check = NULL; -/* The following has a misleading name: starting from 4.0.5, this also -affects Windows: */ -static char* innobase_unix_file_flush_method = NULL; +static char* innobase_file_flush_method = NULL; /* Below we have boolean-valued start-up parameters, and their default values */ @@ -206,6 +208,7 @@ static my_bool innobase_use_doublewrite = TRUE; static my_bool innobase_use_checksums = TRUE; static my_bool innobase_extra_undoslots = FALSE; static my_bool innobase_fast_recovery = FALSE; +static my_bool innobase_recovery_stats = TRUE; static my_bool innobase_locks_unsafe_for_binlog = FALSE; static my_bool innobase_overwrite_relay_log_info = FALSE; static my_bool innobase_rollback_on_timeout = FALSE; @@ -241,15 +244,19 @@ static void free_share(INNOBASE_SHARE *share); static int innobase_close_connection(handlerton *hton, THD* thd); static int innobase_commit(handlerton *hton, THD* thd, bool all); static int innobase_rollback(handlerton *hton, THD* thd, bool all); -static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd, +static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd, void *savepoint); static int innobase_savepoint(handlerton *hton, THD* thd, void *savepoint); -static int innobase_release_savepoint(handlerton *hton, THD* thd, +static int innobase_release_savepoint(handlerton *hton, THD* thd, void *savepoint); static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root); +/* "GEN_CLUST_INDEX" is the name reserved for Innodb default +system primary index. */ +static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX"; + /** @brief Initialize the default value of innodb_commit_concurrency. Once InnoDB is running, the innodb_commit_concurrency must not change @@ -285,10 +292,10 @@ innobase_file_format_check_on_off( /************************************************************//** Validate the file format check config parameters, as a side effect it sets the srv_check_file_format_at_startup variable. -@return true if valid config value */ +@return the format_id if valid config value, otherwise, return -1 */ static -bool -innobase_file_format_check_validate( +int +innobase_file_format_validate_and_set( /*================================*/ const char* format_check); /*!< in: parameter value */ /****************************************************************//** @@ -299,27 +306,8 @@ innobase_alter_table_flags( /*=======================*/ uint flags); -/*********************************************************************** -This function checks each index name for a table against reserved -system default primary index name 'GEN_CLUST_INDEX'. If a name matches, -this function pushes an error message to the client, and returns true. */ -static -bool -innobase_index_name_is_reserved( -/*============================*/ - /* out: true if index name matches a - reserved name */ - const trx_t* trx, /* in: InnoDB transaction handle */ - const TABLE* form, /* in: information on table - columns and indexes */ - const char* norm_name); /* in: table name */ - static const char innobase_hton_name[]= "InnoDB"; -/* "GEN_CLUST_INDEX" is the name reserved for Innodb default -system primary index. */ -static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX"; - /*************************************************************//** Check for a valid value of innobase_commit_concurrency. @return 0 for valid innodb_commit_concurrency */ @@ -538,10 +526,10 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG}, {"buffer_pool_pages_total", (char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG}, - {"buffer_pool_read_ahead_rnd", - (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG}, - {"buffer_pool_read_ahead_seq", - (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG}, + {"buffer_pool_read_ahead", + (char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG}, + {"buffer_pool_read_ahead_evicted", + (char*) &export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG}, {"buffer_pool_read_requests", (char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG}, {"buffer_pool_reads", @@ -822,11 +810,20 @@ convert_error_code_to_mysql( case DB_SUCCESS: return(0); + case DB_INTERRUPTED: + my_error(ER_QUERY_INTERRUPTED, MYF(0)); + /* fall through */ case DB_ERROR: default: return(-1); /* unspecified error */ case DB_DUPLICATE_KEY: + /* Be cautious with returning this error, since + mysql could re-enter the storage layer to get + duplicated key info, the operation requires a + valid table handle and/or transaction information, + which might not always be available in the error + handling stage. */ return(HA_ERR_FOUND_DUPP_KEY); case DB_FOREIGN_DUPLICATE_KEY: @@ -913,8 +910,14 @@ convert_error_code_to_mysql( return(ER_PRIMARY_CANT_HAVE_NULL); case DB_TOO_MANY_CONCURRENT_TRXS: + /* New error code HA_ERR_TOO_MANY_CONCURRENT_TRXS is only + available in 5.1.38 and later, but the plugin should still + work with previous versions of MySQL. */ +#ifdef HA_ERR_TOO_MANY_CONCURRENT_TRXS return(HA_ERR_TOO_MANY_CONCURRENT_TRXS); - +#else /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */ + return(HA_ERR_RECORD_FILE_FULL); +#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */ case DB_UNSUPPORTED: return(HA_ERR_UNSUPPORTED); } @@ -988,8 +991,9 @@ innobase_get_cset_width( *mbminlen = cs->mbminlen; *mbmaxlen = cs->mbmaxlen; } else { - if (current_thd - && (thd_sql_command(current_thd) == SQLCOM_DROP_TABLE)) { + THD* thd = current_thd; + + if (thd && thd_sql_command(thd) == SQLCOM_DROP_TABLE) { /* Fix bug#46256: allow tables to be dropped if the collation is not found, but issue a warning. */ @@ -1001,7 +1005,7 @@ innobase_get_cset_width( } } else { - ut_a(cset == 0); + ut_a(cset == 0); } *mbminlen = *mbmaxlen = 0; @@ -1773,15 +1777,19 @@ innobase_convert_identifier( FALSE=id is an UTF-8 string */ { char nz[NAME_LEN + 1]; +#if MYSQL_VERSION_ID >= 50141 + char nz2[NAME_LEN + 1 + EXPLAIN_FILENAME_MAX_EXTRA_LENGTH]; +#else /* MYSQL_VERSION_ID >= 50141 */ char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix]; +#endif /* MYSQL_VERSION_ID >= 50141 */ const char* s = id; int q; if (file_id) { - /* Decode the table name. The filename_to_tablename() - function expects a NUL-terminated string. The input and - output strings buffers must not be shared. */ + /* Decode the table name. The MySQL function expects + a NUL-terminated string. The input and output strings + buffers must not be shared. */ if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) { idlen = (sizeof nz) - 1; @@ -1791,7 +1799,13 @@ innobase_convert_identifier( nz[idlen] = 0; s = nz2; +#if MYSQL_VERSION_ID >= 50141 + idlen = explain_filename((THD*) thd, nz, nz2, sizeof nz2, + EXPLAIN_PARTITIONS_AS_COMMENT); + goto no_quote; +#else /* MYSQL_VERSION_ID >= 50141 */ idlen = filename_to_tablename(nz, nz2, sizeof nz2); +#endif /* MYSQL_VERSION_ID >= 50141 */ } /* See if the identifier needs to be quoted. */ @@ -1802,6 +1816,9 @@ innobase_convert_identifier( } if (q == EOF) { +#if MYSQL_VERSION_ID >= 50141 +no_quote: +#endif /* MYSQL_VERSION_ID >= 50141 */ if (UNIV_UNLIKELY(idlen > buflen)) { idlen = buflen; } @@ -2284,8 +2301,8 @@ mem_free_and_error: /* Did the user specify a format name that we support ? As a side effect it will update the variable srv_check_file_format_at_startup */ - if (!innobase_file_format_check_validate( - innobase_file_format_check)) { + if (innobase_file_format_validate_and_set( + innobase_file_format_check) < 0) { sql_print_error("InnoDB: invalid " "innodb_file_format_check value: " @@ -2326,7 +2343,7 @@ innobase_change_buffering_inited_ok: /* --------------------------------------------------*/ - srv_file_flush_method_str = innobase_unix_file_flush_method; + srv_file_flush_method_str = innobase_file_flush_method; srv_n_log_groups = (ulint) innobase_mirrored_log_groups; srv_n_log_files = (ulint) innobase_log_files_in_group; @@ -2354,6 +2371,7 @@ innobase_change_buffering_inited_ok: srv_force_recovery = (ulint) innobase_force_recovery; srv_fast_recovery = (ibool) innobase_fast_recovery; + srv_recovery_stats = (ibool) innobase_recovery_stats; srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite; srv_use_checksums = (ibool) innobase_use_checksums; @@ -2389,6 +2407,9 @@ innobase_change_buffering_inited_ok: ut_a(0 == strcmp(my_charset_latin1.name, "latin1_swedish_ci")); srv_latin1_ordering = my_charset_latin1.sort_order; + innobase_old_blocks_pct = buf_LRU_old_ratio_update( + innobase_old_blocks_pct, FALSE); + innobase_commit_concurrency_init_default(); /* Since we in this module access directly the fields of a trx @@ -2478,6 +2499,7 @@ skip_overwrite: pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST); pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST); pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&analyze_mutex, MY_MUTEX_INIT_FAST); pthread_cond_init(&commit_cond, NULL); innodb_inited= 1; #ifdef MYSQL_DYNAMIC_PLUGIN @@ -2532,6 +2554,7 @@ innobase_end( pthread_mutex_destroy(&prepare_commit_mutex); pthread_mutex_destroy(&commit_threads_m); pthread_mutex_destroy(&commit_cond_m); + pthread_mutex_destroy(&analyze_mutex); pthread_cond_destroy(&commit_cond); } @@ -2568,7 +2591,10 @@ innobase_alter_table_flags( { return(HA_ONLINE_ADD_INDEX_NO_WRITES | HA_ONLINE_DROP_INDEX_NO_WRITES - | HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES + /* Current InnoDB doesn't sort unique indexes along mysqld's order + It is dangerous to use index. So it is disabled until + the bug http://bugs.mysql.com/47622 */ + /* | HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES */ | HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES | HA_ONLINE_ADD_PK_INDEX_NO_WRITES); } @@ -2732,6 +2758,19 @@ retry: } } + /* The following calls to read the MySQL binary log + file name and the position return consistent results: + 1) Other InnoDB transactions cannot intervene between + these calls as we are holding prepare_commit_mutex. + 2) Binary logging of other engines is not relevant + to InnoDB as all InnoDB requires is that committing + InnoDB transactions appear in the same order in the + MySQL binary log as they appear in InnoDB logs. + 3) A MySQL log file rotation cannot happen because + MySQL protects against this by having a counter of + transactions in prepared state and it only allows + a rotation when the counter drops to zero. See + LOCK_prep_xids and COND_prep_xids in log.cc. */ trx->mysql_log_file_name = mysql_bin_log_file_name(); trx->mysql_log_offset = (ib_int64_t) mysql_bin_log_file_pos(); @@ -2817,6 +2856,8 @@ innobase_rollback( innobase_release_stat_resources(trx); + trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */ + /* If we had reserved the auto-inc lock for some table (if we come here to roll back the latest SQL statement) we release it now before a possibly lengthy rollback */ @@ -3378,7 +3419,7 @@ retry: if (is_part) { sql_print_error("Failed to open table %s after " - "%lu attemtps.\n", norm_name, + "%lu attempts.\n", norm_name, retries); } @@ -3977,7 +4018,10 @@ ha_innobase::store_key_val_for_row( } else if (mysql_type == MYSQL_TYPE_TINY_BLOB || mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB - || mysql_type == MYSQL_TYPE_LONG_BLOB) { + || mysql_type == MYSQL_TYPE_LONG_BLOB + /* MYSQL_TYPE_GEOMETRY data is treated + as BLOB data in innodb. */ + || mysql_type == MYSQL_TYPE_GEOMETRY) { CHARSET_INFO* cs; ulint key_len; @@ -5279,6 +5323,11 @@ ha_innobase::index_read( index = prebuilt->index; + if (UNIV_UNLIKELY(index == NULL)) { + prebuilt->index_usable = FALSE; + DBUG_RETURN(HA_ERR_CRASHED); + } + /* Note that if the index for which the search template is built is not necessarily prebuilt->index, but can also be the clustered index */ @@ -5438,6 +5487,7 @@ ha_innobase::change_active_index( if (UNIV_UNLIKELY(!prebuilt->index)) { sql_print_warning("InnoDB: change_active_index(%u) failed", keynr); + prebuilt->index_usable = FALSE; DBUG_RETURN(1); } @@ -5445,8 +5495,10 @@ ha_innobase::change_active_index( prebuilt->index); if (UNIV_UNLIKELY(!prebuilt->index_usable)) { - sql_print_warning("InnoDB: insufficient history for index %u", - keynr); + push_warning_printf(user_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_TABLE_DEF_CHANGED, + "InnoDB: insufficient history for index %u", + keynr); /* The caller seems to ignore this. Thus, we must check this again in row_search_for_mysql(). */ DBUG_RETURN(2); @@ -5901,7 +5953,7 @@ create_table_def( number fits in one byte in prtype */ push_warning_printf( (THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_CANT_CREATE_TABLE, "In InnoDB, charset-collation codes" " must be below 256." @@ -5933,17 +5985,8 @@ create_table_def( /* First check whether the column to be added has a system reserved name. */ if (dict_col_name_is_reserved(field->field_name)){ - push_warning_printf( - (THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_CANT_CREATE_TABLE, - "Error creating table '%s' with " - "column name '%s'. '%s' is a " - "reserved name. Please try to " - "re-create the table with a " - "different column name.", - table->name, (char*) field->field_name, - (char*) field->field_name); + my_error(ER_WRONG_COLUMN_NAME, MYF(0), + field->field_name); dict_mem_table_free(table); trx_commit_for_mysql(trx); @@ -5965,6 +6008,14 @@ create_table_def( error = row_create_table_for_mysql(table, trx); + if (error == DB_DUPLICATE_KEY) { + char buf[100]; + innobase_convert_identifier(buf, sizeof buf, + table_name, strlen(table_name), + trx->mysql_thd, TRUE); + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), buf); + } + error_ret: error = convert_error_code_to_mysql(error, flags, NULL); @@ -6169,7 +6220,7 @@ create_options_are_valid( /* Valid value. */ break; default: - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: invalid" " KEY_BLOCK_SIZE = %lu." @@ -6183,7 +6234,7 @@ create_options_are_valid( /* If KEY_BLOCK_SIZE was specified, check for its dependencies. */ if (kbs_specified && !srv_file_per_table) { - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: KEY_BLOCK_SIZE" " requires innodb_file_per_table."); @@ -6191,7 +6242,7 @@ create_options_are_valid( } if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) { - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: KEY_BLOCK_SIZE" " requires innodb_file_format >" @@ -6215,7 +6266,7 @@ create_options_are_valid( if (!srv_file_per_table) { push_warning_printf( thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: ROW_FORMAT=%s" " requires innodb_file_per_table.", @@ -6227,7 +6278,7 @@ create_options_are_valid( if (srv_file_format < DICT_TF_FORMAT_ZIP) { push_warning_printf( thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: ROW_FORMAT=%s" " requires innodb_file_format >" @@ -6244,7 +6295,7 @@ create_options_are_valid( && form->s->row_type == ROW_TYPE_DYNAMIC) { push_warning_printf( thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: cannot specify" " ROW_FORMAT = DYNAMIC with" @@ -6268,7 +6319,7 @@ create_options_are_valid( if (kbs_specified) { push_warning_printf( thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: cannot specify" " ROW_FORMAT = %s with" @@ -6281,7 +6332,7 @@ create_options_are_valid( default: push_warning(thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: invalid ROW_FORMAT specifier."); ret = FALSE; @@ -6345,13 +6396,15 @@ ha_innobase::create( 1. /: for normal table creation 2. full path: for temp table creation, or sym link - When srv_file_per_table is on, check for full path pattern, i.e. + When srv_file_per_table is on and mysqld_embedded is off, + check for full path pattern, i.e. X:\dir\..., X is a driver letter, or \\dir1\dir2\..., UNC path returns error if it is in full path format, but not creating a temp. table. Currently InnoDB does not support symbolic link on Windows. */ if (srv_file_per_table + && !mysqld_embedded && (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) { if ((name[1] == ':') @@ -6555,7 +6608,8 @@ ha_innobase::create( /* Check for name conflicts (with reserved name) for any user indices to be created. */ - if (innobase_index_name_is_reserved(trx, form, norm_name)) { + if (innobase_index_name_is_reserved(trx, form->key_info, + form->s->keys)) { error = -1; goto cleanup; } @@ -6642,18 +6696,22 @@ ha_innobase::create( setup at this stage and so we use thd. */ /* We need to copy the AUTOINC value from the old table if - this is an ALTER TABLE. */ + this is an ALTER TABLE or CREATE INDEX because CREATE INDEX + does a table copy too. */ if (((create_info->used_fields & HA_CREATE_USED_AUTO) - || thd_sql_command(thd) == SQLCOM_ALTER_TABLE) - && create_info->auto_increment_value != 0) { + || thd_sql_command(thd) == SQLCOM_ALTER_TABLE + || thd_sql_command(thd) == SQLCOM_CREATE_INDEX) + && create_info->auto_increment_value > 0) { - /* Query was ALTER TABLE...AUTO_INCREMENT = x; or - CREATE TABLE ...AUTO_INCREMENT = x; Find out a table - definition from the dictionary and get the current value - of the auto increment field. Set a new value to the - auto increment field if the value is greater than the - maximum value in the column. */ + /* Query was one of : + CREATE TABLE ...AUTO_INCREMENT = x; or + ALTER TABLE...AUTO_INCREMENT = x; or + CREATE INDEX x on t(...); + Find out a table definition from the dictionary and get + the current value of the auto increment field. Set a new + value to the auto increment field if the value is greater + than the maximum value in the column. */ auto_inc_value = create_info->auto_increment_value; @@ -7011,6 +7069,24 @@ ha_innobase::rename_table( innobase_commit_low(trx); trx_free_for_mysql(trx); + /* Add a special case to handle the Duplicated Key error + and return DB_ERROR instead. + This is to avoid a possible SIGSEGV error from mysql error + handling code. Currently, mysql handles the Duplicated Key + error by re-entering the storage layer and getting dup key + info by calling get_dup_key(). This operation requires a valid + table handle ('row_prebuilt_t' structure) which could no + longer be available in the error handling stage. The suggested + solution is to report a 'table exists' error message (since + the dup key error here is due to an existing table whose name + is the one we are trying to rename to) and return the generic + error code. */ + if (error == (int) DB_DUPLICATE_KEY) { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to); + + error = DB_ERROR; + } + error = convert_error_code_to_mysql(error, 0, NULL); DBUG_RETURN(error); @@ -7509,9 +7585,15 @@ ha_innobase::analyze( THD* thd, /*!< in: connection thread handle */ HA_CHECK_OPT* check_opt) /*!< in: currently ignored */ { + /* Serialize ANALYZE TABLE inside InnoDB, see + Bug#38996 Race condition in ANALYZE TABLE */ + pthread_mutex_lock(&analyze_mutex); + /* Simply call ::info() with all the flags */ info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); + pthread_mutex_unlock(&analyze_mutex); + return(0); } @@ -7557,11 +7639,15 @@ ha_innobase::check( ret = row_check_table_for_mysql(prebuilt); - if (ret == DB_SUCCESS) { + switch (ret) { + case DB_SUCCESS: return(HA_ADMIN_OK); + case DB_INTERRUPTED: + my_error(ER_QUERY_INTERRUPTED, MYF(0)); + return(-1); + default: + return(HA_ADMIN_CORRUPT); } - - return(HA_ADMIN_CORRUPT); } /*************************************************************//** @@ -8106,8 +8192,12 @@ ha_innobase::external_lock( { ulong const binlog_format= thd_binlog_format(thd); ulong const tx_isolation = thd_tx_isolation(ha_thd()); - if (tx_isolation <= ISO_READ_COMMITTED && - binlog_format == BINLOG_FORMAT_STMT) + if (tx_isolation <= ISO_READ_COMMITTED + && binlog_format == BINLOG_FORMAT_STMT +#if MYSQL_VERSION_ID > 50140 + && thd_binlog_filter_ok(thd) +#endif /* MYSQL_VERSION_ID > 50140 */ + ) { char buf[256]; my_snprintf(buf, sizeof(buf), @@ -8772,6 +8862,7 @@ ha_innobase::store_lock( && isolation_level != TRX_ISO_SERIALIZABLE && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) && (sql_command == SQLCOM_INSERT_SELECT + || sql_command == SQLCOM_REPLACE_SELECT || sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_CREATE_TABLE)) { @@ -8779,10 +8870,11 @@ ha_innobase::store_lock( option set or this session is using READ COMMITTED isolation level and isolation level of the transaction is not set to serializable and MySQL is doing - INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or - CREATE ... SELECT... without FOR UPDATE or - IN SHARE MODE in select, then we use consistent - read for select. */ + INSERT INTO...SELECT or REPLACE INTO...SELECT + or UPDATE ... = (SELECT ...) or CREATE ... + SELECT... without FOR UPDATE or IN SHARE + MODE in select, then we use consistent read + for select. */ prebuilt->select_lock_type = LOCK_NONE; prebuilt->stored_select_lock_type = LOCK_NONE; @@ -9002,6 +9094,7 @@ ha_innobase::get_auto_increment( AUTOINC counter after attempting to insert the row. */ if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { ulonglong need; + ulonglong current; ulonglong next_value; ulonglong col_max_value; @@ -9010,11 +9103,12 @@ ha_innobase::get_auto_increment( col_max_value = innobase_get_int_col_max_value( table->next_number_field); + current = *first_value > col_max_value ? autoinc : *first_value; need = *nb_reserved_values * increment; /* Compute the last value in the interval */ next_value = innobase_next_autoinc( - *first_value, need, offset, col_max_value); + current, need, offset, col_max_value); prebuilt->autoinc_last_value = next_value; @@ -9373,8 +9467,7 @@ innobase_xa_prepare( executing XA PREPARE and XA COMMIT commands. In this case we cannot know how many minutes or hours will be between XA PREPARE and XA COMMIT, and we don't want - to block for undefined period of time. - */ + to block for undefined period of time. */ pthread_mutex_lock(&prepare_commit_mutex); trx->active_trans = 2; } @@ -9619,6 +9712,20 @@ ha_innobase::check_if_incompatible_data( return(COMPATIBLE_DATA_NO); } + /* Renaming column asynchronizes dictionary between mysqld and InnoDB... + If not synchronized, treat as COMPATIBLE_DATA_NO + until the bug http://bugs.mysql.com/47621 is fixed officialily */ + { + uint i; + for (i = 0; i < table->s->fields; i++) { + if (table->field[i]->flags & FIELD_IN_ADD_INDEX + && innobase_strcasecmp(table->field[i]->field_name, + dict_table_get_col_name(prebuilt->table, i))) { + return(COMPATIBLE_DATA_NO); + } + } + } + /* Check if a column participating in a foreign key is being renamed. There is no mechanism for updating InnoDB foreign key definitions. */ if (foreign_key_column_is_being_renamed(prebuilt, table)) { @@ -9716,25 +9823,24 @@ innobase_file_format_check_on_off( /************************************************************//** Validate the file format check config parameters, as a side effect it sets the srv_check_file_format_at_startup variable. -@return true if valid config value */ +@return the format_id if valid config value, otherwise, return -1 */ static -bool -innobase_file_format_check_validate( +int +innobase_file_format_validate_and_set( /*================================*/ const char* format_check) /*!< in: parameter value */ { uint format_id; - bool ret = true; format_id = innobase_file_format_name_lookup(format_check); if (format_id < DICT_TF_FORMAT_MAX + 1) { srv_check_file_format_at_startup = format_id; - } else { - ret = false; - } - return(ret); + return((int) format_id); + } else { + return(-1); + } } /*************************************************************//** @@ -9769,7 +9875,11 @@ innodb_file_format_name_validate( if (format_id <= DICT_TF_FORMAT_MAX) { - *static_cast(save) = file_format_input; + /* Save a pointer to the name in the + 'file_format_name_map' constant array. */ + *static_cast(save) = + trx_sys_file_format_id_to_name(format_id); + return(0); } } @@ -9832,6 +9942,7 @@ innodb_file_format_check_validate( const char* file_format_input; char buff[STRING_BUFFER_USUAL_SIZE]; int len = sizeof(buff); + int format_id; ut_a(save != NULL); ut_a(value != NULL); @@ -9844,24 +9955,35 @@ innodb_file_format_check_validate( message if they did so. */ if (innobase_file_format_check_on_off(file_format_input)) { - sql_print_warning( + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, "InnoDB: invalid innodb_file_format_check " "value; on/off can only be set at startup or " "in the configuration file"); - } else if (innobase_file_format_check_validate( - file_format_input)) { - - *static_cast(save) = file_format_input; - - return(0); - } else { - sql_print_warning( - "InnoDB: invalid innodb_file_format_check " - "value; can be any format up to %s " - "or its equivalent numeric id", - trx_sys_file_format_id_to_name( - DICT_TF_FORMAT_MAX)); + format_id = innobase_file_format_validate_and_set( + file_format_input); + + if (format_id >= 0) { + /* Save a pointer to the name in the + 'file_format_name_map' constant array. */ + *static_cast(save) = + trx_sys_file_format_id_to_name( + (uint)format_id); + + return(0); + + } else { + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: invalid innodb_file_format_check " + "value; can be any format up to %s " + "or its equivalent numeric id", + trx_sys_file_format_id_to_name( + DICT_TF_FORMAT_MAX)); + } } } @@ -9942,6 +10064,25 @@ innodb_adaptive_hash_index_update( } } +/****************************************************************//** +Update the system variable innodb_old_blocks_pct using the "saved" +value. This function is registered as a callback with MySQL. */ +static +void +innodb_old_blocks_pct_update( +/*=========================*/ + THD* thd, /*!< in: thread handle */ + struct st_mysql_sys_var* var, /*!< in: pointer to + system variable */ + void* var_ptr,/*!< out: where the + formal string goes */ + const void* save) /*!< in: immediate result + from check function */ +{ + innobase_old_blocks_pct = buf_LRU_old_ratio_update( + *static_cast(save), TRUE); +} + /*************************************************************//** Check if it is a valid value of innodb_change_buffering. This function is registered as a callback with MySQL. @@ -10018,36 +10159,39 @@ static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff) /*********************************************************************** This function checks each index name for a table against reserved system default primary index name 'GEN_CLUST_INDEX'. If a name matches, -this function pushes an error message to the client, and returns true. */ -static +this function pushes an warning message to the client, and returns true. */ +extern "C" UNIV_INTERN bool innobase_index_name_is_reserved( /*============================*/ /* out: true if an index name matches the reserved name */ const trx_t* trx, /* in: InnoDB transaction handle */ - const TABLE* form, /* in: information on table - columns and indexes */ - const char* norm_name) /* in: table name */ + const KEY* key_info, /* in: Indexes to be created */ + ulint num_of_keys) /* in: Number of indexes to + be created. */ { - KEY* key; + const KEY* key; uint key_num; /* index number */ - for (key_num = 0; key_num < form->s->keys; key_num++) { - key = form->key_info + key_num; + for (key_num = 0; key_num < num_of_keys; key_num++) { + key = &key_info[key_num]; if (innobase_strcasecmp(key->name, innobase_index_reserve_name) == 0) { /* Push warning to mysql */ push_warning_printf((THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_CANT_CREATE_TABLE, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_NAME_FOR_INDEX, "Cannot Create Index with name " "'%s'. The name is reserved " "for the system default primary " "index.", innobase_index_reserve_name); + my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), + innobase_index_reserve_name); + return(true); } } @@ -10085,12 +10229,17 @@ static MYSQL_SYSVAR_BOOL(extra_undoslots, innobase_extra_undoslots, static MYSQL_SYSVAR_BOOL(fast_recovery, innobase_fast_recovery, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, "Enable to use speed hack of recovery avoiding flush list sorting.", + NULL, NULL, TRUE); + +static MYSQL_SYSVAR_BOOL(recovery_stats, innobase_recovery_stats, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Output statistics of recovery process after it.", NULL, NULL, FALSE); static MYSQL_SYSVAR_ULONG(use_purge_thread, srv_use_purge_thread, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "Number of purge devoted threads. #### over 1 is EXPERIMENTAL ####", - NULL, NULL, 0, 0, 64, 0); + NULL, NULL, 1, 0, 64, 0); static MYSQL_SYSVAR_BOOL(overwrite_relay_log_info, innobase_overwrite_relay_log_info, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, @@ -10132,12 +10281,15 @@ static MYSQL_SYSVAR_STR(file_format, innobase_file_format_name, innodb_file_format_name_validate, innodb_file_format_name_update, "Antelope"); +/* If a new file format is introduced, the file format +name needs to be updated accordingly. Please refer to +file_format_name_map[] defined in trx0sys.c for the next +file format name. */ static MYSQL_SYSVAR_STR(file_format_check, innobase_file_format_check, PLUGIN_VAR_OPCMDARG, "The highest file format in the tablespace.", innodb_file_format_check_validate, - innodb_file_format_check_update, - "on"); + innodb_file_format_check_update, "Barracuda"); static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit, PLUGIN_VAR_OPCMDARG, @@ -10146,7 +10298,7 @@ static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit, " or 2 (write at commit, flush once per second).", NULL, NULL, 1, 0, 2, 0); -static MYSQL_SYSVAR_STR(flush_method, innobase_unix_file_flush_method, +static MYSQL_SYSVAR_STR(flush_method, innobase_file_flush_method, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "With which method to flush data.", NULL, NULL, NULL); @@ -10187,7 +10339,7 @@ static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct, static MYSQL_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing, PLUGIN_VAR_NOCMDARG, "Attempt flushing dirty pages to avoid IO bursts at checkpoints.", - NULL, NULL, TRUE); + NULL, NULL, FALSE); static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag, PLUGIN_VAR_RQCMDARG, @@ -10283,7 +10435,7 @@ static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter, NULL, NULL, 500L, 1L, ~0L, 0); static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR, "Number of file I/O threads in InnoDB.", NULL, NULL, 4, 4, 64, 0); @@ -10322,6 +10474,18 @@ static MYSQL_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups, "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.", NULL, NULL, 1, 1, 10, 0); +static MYSQL_SYSVAR_UINT(old_blocks_pct, innobase_old_blocks_pct, + PLUGIN_VAR_RQCMDARG, + "Percentage of the buffer pool to reserve for 'old' blocks.", + NULL, innodb_old_blocks_pct_update, 100 * 3 / 8, 5, 95, 0); + +static MYSQL_SYSVAR_UINT(old_blocks_time, buf_LRU_old_threshold_ms, + PLUGIN_VAR_RQCMDARG, + "Move blocks to the 'new' end of the buffer pool if the first access" + " was at least this many milliseconds ago." + " The timeout is disabled if 0 (the default).", + NULL, NULL, 0, 0, UINT_MAX32, 0); + static MYSQL_SYSVAR_LONG(open_files, innobase_open_files, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "How many files at the maximum InnoDB keeps open at the same time.", @@ -10400,13 +10564,18 @@ static MYSQL_SYSVAR_LONGLONG(ibuf_max_size, srv_ibuf_max_size, static MYSQL_SYSVAR_ULONG(ibuf_active_contract, srv_ibuf_active_contract, PLUGIN_VAR_RQCMDARG, "Enable/Disable active_contract of insert buffer. 0:disable 1:enable", - NULL, NULL, 0, 0, 1, 0); + NULL, NULL, 1, 0, 1, 0); static MYSQL_SYSVAR_ULONG(ibuf_accel_rate, srv_ibuf_accel_rate, PLUGIN_VAR_RQCMDARG, "Tunes amount of insert buffer processing of background, in addition to innodb_io_capacity. (in percentage)", NULL, NULL, 100, 100, 999999999, 0); +static MYSQL_SYSVAR_ULONG(checkpoint_age_target, srv_checkpoint_age_target, + PLUGIN_VAR_RQCMDARG, + "Control soft limit of checkpoint age. (0 : not control)", + NULL, NULL, 0, 0, ~0UL, 0); + static MYSQL_SYSVAR_ULONG(flush_neighbor_pages, srv_flush_neighbor_pages, PLUGIN_VAR_RQCMDARG, "Enable/Disable flushing also neighbor pages. 0:disable 1:enable", @@ -10442,7 +10611,7 @@ TYPELIB read_ahead_typelib= }; static MYSQL_SYSVAR_ENUM(read_ahead, srv_read_ahead, PLUGIN_VAR_RQCMDARG, - "Control read ahead activity. (none, random, [linear], both)", + "Control read ahead activity (none, random, [linear], both). [from 1.0.5: random read ahead is ignored]", NULL, innodb_read_ahead_update, 2, &read_ahead_typelib); static @@ -10473,8 +10642,8 @@ TYPELIB adaptive_checkpoint_typelib= }; static MYSQL_SYSVAR_ENUM(adaptive_checkpoint, srv_adaptive_checkpoint, PLUGIN_VAR_RQCMDARG, - "Enable/Disable flushing along modified age. ([none], reflex, estimate)", - NULL, innodb_adaptive_checkpoint_update, 0, &adaptive_checkpoint_typelib); + "Enable/Disable flushing along modified age. (none, reflex, [estimate])", + NULL, innodb_adaptive_checkpoint_update, 2, &adaptive_checkpoint_typelib); static MYSQL_SYSVAR_ULONG(enable_unsafe_group_commit, srv_enable_unsafe_group_commit, PLUGIN_VAR_RQCMDARG, @@ -10496,6 +10665,11 @@ static MYSQL_SYSVAR_ULONG(dict_size_limit, srv_dict_size_limit, "Limit the allocated memory for dictionary cache. (0: unlimited)", NULL, NULL, 0, 0, LONG_MAX, 0); +static MYSQL_SYSVAR_ULONG(relax_table_creation, srv_relax_table_creation, + PLUGIN_VAR_RQCMDARG, + "Relax limitation of column size at table creation as builtin InnoDB.", + NULL, NULL, 0, 0, 1, 0); + static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(autoextend_increment), @@ -10508,6 +10682,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(doublewrite), MYSQL_SYSVAR(extra_undoslots), MYSQL_SYSVAR(fast_recovery), + MYSQL_SYSVAR(recovery_stats), MYSQL_SYSVAR(fast_shutdown), MYSQL_SYSVAR(file_io_threads), MYSQL_SYSVAR(read_io_threads), @@ -10532,6 +10707,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(adaptive_flushing), MYSQL_SYSVAR(max_purge_lag), MYSQL_SYSVAR(mirrored_log_groups), + MYSQL_SYSVAR(old_blocks_pct), + MYSQL_SYSVAR(old_blocks_time), MYSQL_SYSVAR(open_files), MYSQL_SYSVAR(overwrite_relay_log_info), MYSQL_SYSVAR(rollback_on_timeout), @@ -10558,6 +10735,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(ibuf_max_size), MYSQL_SYSVAR(ibuf_active_contract), MYSQL_SYSVAR(ibuf_accel_rate), + MYSQL_SYSVAR(checkpoint_age_target), MYSQL_SYSVAR(flush_neighbor_pages), MYSQL_SYSVAR(read_ahead), MYSQL_SYSVAR(adaptive_checkpoint), @@ -10570,6 +10748,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(io_capacity), MYSQL_SYSVAR(use_purge_thread), + MYSQL_SYSVAR(relax_table_creation), NULL }; diff --git a/handler/ha_innodb.h b/handler/ha_innodb.h index cc98003f8ff..31e88ed8530 100644 --- a/handler/ha_innodb.h +++ b/handler/ha_innodb.h @@ -257,6 +257,15 @@ int thd_binlog_format(const MYSQL_THD thd); @param all TRUE <=> rollback main transaction. */ void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all); + +#if MYSQL_VERSION_ID > 50140 +/** + Check if binary logging is filtered for thread's current db. + @param thd Thread handle + @retval 1 the query is not filtered, 0 otherwise. +*/ +bool thd_binlog_filter_ok(const MYSQL_THD thd); +#endif /* MYSQL_VERSION_ID > 50140 */ } typedef struct trx_struct trx_t; @@ -282,3 +291,21 @@ trx_t* innobase_trx_allocate( /*==================*/ MYSQL_THD thd); /*!< in: user thread handle */ + + +/*********************************************************************//** +This function checks each index name for a table against reserved +system default primary index name 'GEN_CLUST_INDEX'. If a name +matches, this function pushes an warning message to the client, +and returns true. */ +extern "C" +bool +innobase_index_name_is_reserved( +/*============================*/ + /* out: true if the index name + matches the reserved name */ + const trx_t* trx, /* in: InnoDB transaction handle */ + const KEY* key_info, /* in: Indexes to be created */ + ulint num_of_keys); /* in: Number of indexes to + be created. */ + diff --git a/handler/handler0alter.cc b/handler/handler0alter.cc index c85e61d307b..a5008991400 100644 --- a/handler/handler0alter.cc +++ b/handler/handler0alter.cc @@ -35,7 +35,6 @@ extern "C" { } #include "ha_innodb.h" -#include "handler0vars.h" /*************************************************************//** Copies an InnoDB column to a MySQL field. This function is @@ -629,7 +628,7 @@ ha_innobase::add_index( ulint num_created = 0; ibool dict_locked = FALSE; ulint new_primary; - ulint error; + int error; DBUG_ENTER("ha_innobase::add_index"); ut_a(table); @@ -657,36 +656,23 @@ ha_innobase::add_index( innodb_table = indexed_table = dict_table_get(prebuilt->table->name, FALSE); - /* Check that index keys are sensible */ - - error = innobase_check_index_keys(key_info, num_of_keys); + /* Check if the index name is reserved. */ + if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) { + error = -1; + } else { + /* Check that index keys are sensible */ + error = innobase_check_index_keys(key_info, num_of_keys); + } if (UNIV_UNLIKELY(error)) { err_exit: mem_heap_free(heap); - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); trx_free_for_mysql(trx); trx_commit_for_mysql(prebuilt->trx); DBUG_RETURN(error); } - /* Check for name conflicts (with reserved name) for - any user indices to be created. */ - if (innobase_strcasecmp(key_info->name, - "GEN_CLUST_INDEX") == 0) { - /* Push warning to mysql */ - push_warning_printf((THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_CANT_CREATE_TABLE, - "Cannot Create Index with name " - "'%s'. The name is reserved " - "for the system default primary " - "index.", - "GEN_CLUST_INDEX"); - error = ER_CANT_CREATE_TABLE; - goto err_exit; - } - /* Create table containing all indexes to be built in this alter table add index so that they are in the correct order in the table. */ @@ -779,10 +765,11 @@ err_exit: ut_ad(error == DB_SUCCESS); /* Commit the data dictionary transaction in order to release - the table locks on the system tables. Unfortunately, this - means that if MySQL crashes while creating a new primary key - inside row_merge_build_indexes(), indexed_table will not be - dropped on crash recovery. Thus, it will become orphaned. */ + the table locks on the system tables. This means that if + MySQL crashes while creating a new primary key inside + row_merge_build_indexes(), indexed_table will not be dropped + by trx_rollback_active(). It will have to be recovered or + dropped by the database administrator. */ trx_commit_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); @@ -819,7 +806,7 @@ error_handling: alter table t drop index b, add index (b); The fix will have to parse the SQL and note that the index - being added has the same name as the the one being dropped and + being added has the same name as the one being dropped and ignore that in the dup index check.*/ //dict_table_check_for_dup_indexes(prebuilt->table); #endif @@ -881,6 +868,7 @@ error_handling: indexed_table->n_mysql_handles_opened++; error = row_merge_drop_table(trx, innodb_table); + innodb_table = indexed_table; goto convert_error; case DB_TOO_BIG_RECORD: @@ -895,7 +883,9 @@ error: /* fall through */ default: if (new_primary) { - row_merge_drop_table(trx, indexed_table); + if (indexed_table != innodb_table) { + row_merge_drop_table(trx, indexed_table); + } } else { if (!dict_locked) { row_mysql_lock_data_dictionary(trx); diff --git a/handler/handler0vars.h b/handler/handler0vars.h deleted file mode 100644 index e0f8f75e34d..00000000000 --- a/handler/handler0vars.h +++ /dev/null @@ -1,69 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2008, 2009, Innobase Oy. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA - -*****************************************************************************/ - -/*******************************************************************//** -@file handler/handler0vars.h -This file contains accessor functions for dynamic plugin on Windows. -***********************************************************************/ - -#if defined __WIN__ && defined MYSQL_DYNAMIC_PLUGIN -/*******************************************************************//** -This is a list of externals that can not be resolved by delay loading. -They have to be resolved indirectly via their addresses in the .map file. -All of them are external variables. */ -extern CHARSET_INFO* wdl_my_charset_bin; -extern CHARSET_INFO* wdl_my_charset_latin1; -extern CHARSET_INFO* wdl_my_charset_filename; -extern CHARSET_INFO** wdl_system_charset_info; -extern CHARSET_INFO** wdl_default_charset_info; -extern CHARSET_INFO** wdl_all_charsets; -extern system_variables* wdl_global_system_variables; -extern char* wdl_mysql_real_data_home; -extern char** wdl_mysql_data_home; -extern char** wdl_tx_isolation_names; -extern char** wdl_binlog_format_names; -extern char* wdl_reg_ext; -extern pthread_mutex_t* wdl_LOCK_thread_count; -extern key_map* wdl_key_map_full; -extern MY_TMPDIR* wdl_mysql_tmpdir_list; -extern bool* wdl_mysqld_embedded; -extern uint* wdl_lower_case_table_names; -extern ulong* wdl_specialflag; -extern int* wdl_my_umask; - -#define my_charset_bin (*wdl_my_charset_bin) -#define my_charset_latin1 (*wdl_my_charset_latin1) -#define my_charset_filename (*wdl_my_charset_filename) -#define system_charset_info (*wdl_system_charset_info) -#define default_charset_info (*wdl_default_charset_info) -#define all_charsets (wdl_all_charsets) -#define global_system_variables (*wdl_global_system_variables) -#define mysql_real_data_home (wdl_mysql_real_data_home) -#define mysql_data_home (*wdl_mysql_data_home) -#define tx_isolation_names (wdl_tx_isolation_names) -#define binlog_format_names (wdl_binlog_format_names) -#define reg_ext (wdl_reg_ext) -#define LOCK_thread_count (*wdl_LOCK_thread_count) -#define key_map_full (*wdl_key_map_full) -#define mysql_tmpdir_list (*wdl_mysql_tmpdir_list) -#define mysqld_embedded (*wdl_mysqld_embedded) -#define lower_case_table_names (*wdl_lower_case_table_names) -#define specialflag (*wdl_specialflag) -#define my_umask (*wdl_my_umask) - -#endif diff --git a/handler/i_s.cc b/handler/i_s.cc index 4b61971f8b0..8a834b97b85 100644 --- a/handler/i_s.cc +++ b/handler/i_s.cc @@ -47,6 +47,7 @@ extern "C" { #include "trx0rseg.h" /* for trx_rseg_struct */ #include "trx0sys.h" /* for trx_sys */ #include "dict0dict.h" /* for dict_sys */ +#include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */ /* from buf0buf.c */ struct buf_chunk_struct{ ulint mem_size; /* allocated size of the chunk */ @@ -56,7 +57,6 @@ struct buf_chunk_struct{ buf_block_t* blocks; /* array of buffer control blocks */ }; } -#include "handler0vars.h" static const char plugin_author[] = "Innobase Oy"; @@ -84,14 +84,16 @@ do { \ #define STRUCT_FLD(name, value) value #endif -static const ST_FIELD_INFO END_OF_ST_FIELD_INFO = - {STRUCT_FLD(field_name, NULL), - STRUCT_FLD(field_length, 0), - STRUCT_FLD(field_type, MYSQL_TYPE_NULL), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, 0), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}; +/* Don't use a static const variable here, as some C++ compilers (notably +HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */ +#define END_OF_ST_FIELD_INFO \ + {STRUCT_FLD(field_name, NULL), \ + STRUCT_FLD(field_length, 0), \ + STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \ + STRUCT_FLD(value, 0), \ + STRUCT_FLD(field_flags, 0), \ + STRUCT_FLD(old_name, ""), \ + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)} /* Use the following types mapping: @@ -511,7 +513,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_index_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, - {STRUCT_FLD(field_name, "accessed"), + {STRUCT_FLD(field_name, "access_time"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), STRUCT_FLD(value, 0), @@ -728,7 +730,7 @@ i_s_innodb_buffer_pool_pages_fill( field_store_string(table->field[0], page_type); table->field[1]->store(block->page.space); table->field[2]->store(block->page.offset); - table->field[3]->store(block->page.LRU_position); + table->field[3]->store(0); table->field[4]->store(block->page.buf_fix_count); table->field[5]->store(block->page.flush_type); @@ -817,11 +819,11 @@ i_s_innodb_buffer_pool_pages_index_fill( table->field[5]->store(page_get_n_recs(frame)); table->field[6]->store(page_get_data_size(frame)); table->field[7]->store(block->is_hashed); - table->field[8]->store(block->page.accessed); + table->field[8]->store(block->page.access_time); table->field[9]->store(block->page.newest_modification != 0); table->field[10]->store(block->page.oldest_modification != 0); table->field[11]->store(block->page.old); - table->field[12]->store(block->page.LRU_position); + table->field[12]->store(0); table->field[13]->store(block->page.buf_fix_count); table->field[14]->store(block->page.flush_type); @@ -915,7 +917,7 @@ i_s_innodb_buffer_pool_pages_blob_fill( table->field[4]->store(block->page.offset); } - table->field[5]->store(block->page.LRU_position); + table->field[5]->store(0); table->field[6]->store(block->page.buf_fix_count); table->field[7]->store(block->page.flush_type); @@ -3047,6 +3049,36 @@ nomatch: "Hello!"); goto end_func; } + else if (!strncasecmp("XTRA_LRU_DUMP", ptr, 13)) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_DUMP'" + " was detected.\n"); + + if (buf_LRU_file_dump()) { + field_store_string(i_s_table->field[0], + "XTRA_LRU_DUMP was succeeded."); + } else { + field_store_string(i_s_table->field[0], + "XTRA_LRU_DUMP was failed."); + } + + goto end_func; + } + else if (!strncasecmp("XTRA_LRU_RESTORE", ptr, 16)) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_RESTORE'" + " was detected.\n"); + + if (buf_LRU_file_restore()) { + field_store_string(i_s_table->field[0], + "XTRA_LRU_RESTORE was succeeded."); + } else { + field_store_string(i_s_table->field[0], + "XTRA_LRU_RESTORE was failed."); + } + + goto end_func; + } field_store_string(i_s_table->field[0], "Undefined XTRA_* command."); diff --git a/handler/innodb_patch_info.h b/handler/innodb_patch_info.h index 184fd65af63..253f6360aa0 100644 --- a/handler/innodb_patch_info.h +++ b/handler/innodb_patch_info.h @@ -41,5 +41,7 @@ struct innodb_enhancement { {"innodb_admin_command_base","XtraDB specific command interface through i_s","","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_show_lock_name","Show mutex/lock name instead of crated file/line","","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_extend_slow","Extended statistics in slow.log","It is InnoDB-part only. It needs to patch also to mysqld.","http://www.percona.com/docs/wiki/percona-xtradb"}, +{"innodb_relax_table_creation","Relax limitation of column size at table creation as builtin InnoDB.","","http://www.percona.com/docs/wiki/percona-xtradb"}, +{"innodb_lru_dump_restore","Dump and restore command for content of buffer pool","","http://www.percona.com/docs/wiki/percona-xtradb"}, {NULL, NULL, NULL, NULL} }; diff --git a/handler/win_delay_loader.cc b/handler/win_delay_loader.cc deleted file mode 100644 index 9b92f6a9cf2..00000000000 --- a/handler/win_delay_loader.cc +++ /dev/null @@ -1,1024 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2008, 2009, Innobase Oy. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA - -*****************************************************************************/ - -/*******************************************************************//** -@file handler/win_delay_loader.cc -This file contains functions that implement the delay loader on Windows. - -This is a customized version of delay loader with limited functionalities. -It does not support: - -* (manual) unloading -* multiple delay loaded DLLs -* multiple loading of the same DLL - -This delay loader is used only by the InnoDB plugin. Other components (DLLs) -can still use the default delay loader, provided by MSVC. - -Several acronyms used by Microsoft: - * IAT: import address table - * INT: import name table - * RVA: Relative Virtual Address - -See http://msdn.microsoft.com/en-us/magazine/bb985992.aspx for details of -PE format. -***********************************************************************/ -#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) -# define WIN32_LEAN_AND_MEAN -# include -# include -# include - -extern "C" { -# include "univ.i" -# include "hash0hash.h" -} - -/*******************************************************************//** -This following contains a list of externals that can not be resolved by -delay loading. They have to be resolved indirectly via their addresses -in the .map file. All of them are external variables. */ -CHARSET_INFO* wdl_my_charset_bin; -CHARSET_INFO* wdl_my_charset_latin1; -CHARSET_INFO* wdl_my_charset_filename; -CHARSET_INFO** wdl_system_charset_info; -CHARSET_INFO** wdl_default_charset_info; -CHARSET_INFO** wdl_all_charsets; -system_variables* wdl_global_system_variables; -char* wdl_mysql_real_data_home; -char** wdl_mysql_data_home; -char** wdl_tx_isolation_names; -char** wdl_binlog_format_names; -char* wdl_reg_ext; -pthread_mutex_t* wdl_LOCK_thread_count; -key_map* wdl_key_map_full; -MY_TMPDIR* wdl_mysql_tmpdir_list; -bool* wdl_mysqld_embedded; -uint* wdl_lower_case_table_names; -ulong* wdl_specialflag; -int* wdl_my_umask; - -/*******************************************************************//** -The preferred load-address defined in PE (portable executable format). */ -#if defined(_M_IA64) -#pragma section(".base", long, read) -extern "C" -__declspec(allocate(".base")) -const IMAGE_DOS_HEADER __ImageBase; -#else -extern "C" -const IMAGE_DOS_HEADER __ImageBase; -#endif - -/*******************************************************************//** -A template function for converting a relative address (RVA) to an -absolute address (VA). This is due to the pointers in the delay -descriptor (ImgDelayDescr in delayimp.h) have been changed from -VAs to RVAs to work on both 32- and 64-bit platforms. -@return absolute virtual address */ -template -X PFromRva( -/*=======*/ - RVA rva) /*!< in: relative virtual address */ -{ - return X(PBYTE(&__ImageBase) + rva); -} - -/*******************************************************************//** -Convert to the old format for convenience. The structure as well as its -element names follow the definition of ImgDelayDescr in delayimp.h. */ -struct InternalImgDelayDescr -{ - DWORD grAttrs; /*!< attributes */ - LPCSTR szName; /*!< pointer to dll name */ - HMODULE* phmod; /*!< address of module handle */ - PImgThunkData pIAT; /*!< address of the IAT */ - PCImgThunkData pINT; /*!< address of the INT */ - PCImgThunkData pBoundIAT; /*!< address of the optional bound IAT */ - PCImgThunkData pUnloadIAT; /*!< address of optional copy of - original IAT */ - DWORD dwTimeStamp; /*!< 0 if not bound, - otherwise date/time stamp of DLL - bound to (Old BIND) */ -}; - -typedef struct map_hash_chain_struct map_hash_chain_t; - -struct map_hash_chain_struct { - char* symbol; /*!< pointer to a symbol */ - ulint value; /*!< address of the symbol */ - map_hash_chain_t* next; /*!< pointer to the next cell - in the same folder. */ - map_hash_chain_t* chain; /*!< a linear chain used for - cleanup. */ -}; - -static HMODULE my_hmod = 0; -static struct hash_table_struct* m_htbl = NULL ; -static map_hash_chain_t* chain_header = NULL; -static ibool wdl_init = FALSE; -const ulint MAP_HASH_CELLS_NUM = 10000; - -#ifndef DBUG_OFF -/*******************************************************************//** -In the dynamic plugin, it is required to call the following dbug functions -in the server: - _db_pargs_ - _db_doprnt_ - _db_enter_ - _db_return_ - _db_dump_ - -The plugin will get those function pointers during the initialization. */ -typedef void (__cdecl* pfn_db_enter_)( - const char* _func_, - const char* _file_, - uint _line_, - const char** _sfunc_, - const char** _sfile_, - uint* _slevel_, - char***); - -typedef void (__cdecl* pfn_db_return_)( - uint _line_, - const char** _sfunc_, - const char** _sfile_, - uint* _slevel_); - -typedef void (__cdecl* pfn_db_pargs_)( - uint _line_, - const char* keyword); - -typedef void (__cdecl* pfn_db_doprnt_)( - const char* format, - ...); - -typedef void (__cdecl* pfn_db_dump_)( - uint _line_, - const char* keyword, - const unsigned char* memory, - size_t length); - -static pfn_db_enter_ wdl_db_enter_; -static pfn_db_return_ wdl_db_return_; -static pfn_db_pargs_ wdl_db_pargs_; -static pfn_db_doprnt_ wdl_db_doprnt_; -static pfn_db_dump_ wdl_db_dump_; -#endif /* !DBUG_OFF */ - -/*************************************************************//** -Creates a hash table with >= n array cells. The actual number of cells is -chosen to be a prime number slightly bigger than n. - -This is the same function as hash_create in hash0hash.c, except the -memory allocation. This function is invoked before the engine is -initialized, and buffer pools are not ready yet. -@return own: created hash table */ -static -hash_table_t* -wdl_hash_create( -/*============*/ - ulint n) /*!< in: number of array cells */ -{ - hash_cell_t* array; - ulint prime; - hash_table_t* table; - - prime = ut_find_prime(n); - - table = (hash_table_t*) malloc(sizeof(hash_table_t)); - if (table == NULL) { - return(NULL); - } - - array = (hash_cell_t*) malloc(sizeof(hash_cell_t) * prime); - if (array == NULL) { - free(table); - return(NULL); - } - - table->array = array; - table->n_cells = prime; - table->n_mutexes = 0; - table->mutexes = NULL; - table->heaps = NULL; - table->heap = NULL; - table->magic_n = HASH_TABLE_MAGIC_N; - - /* Initialize the cell array */ - hash_table_clear(table); - - return(table); -} - -/*************************************************************//** -Frees a hash table. */ -static -void -wdl_hash_table_free( -/*================*/ - hash_table_t* table) /*!< in, own: hash table */ -{ - ut_a(table != NULL); - ut_a(table->mutexes == NULL); - - free(table->array); - free(table); -} - -/*******************************************************************//** -Function for calculating the count of imports given the base of the IAT. -@return number of imports */ -static -ulint -wdl_import_count( -/*=============*/ - PCImgThunkData pitd_base) /*!< in: base of the IAT */ -{ - ulint ret = 0; - PCImgThunkData pitd = pitd_base; - - while (pitd->u1.Function) { - pitd++; - ret++; - } - - return(ret); -} - -/*******************************************************************//** -Read Mapfile to a hashtable for faster access -@return TRUE if the mapfile is loaded successfully. */ -static -ibool -wdl_load_mapfile( -/*=============*/ - const char* filename) /*!< in: name of the mapfile. */ -{ - FILE* fp; - const size_t nSize = 256; - char tmp_buf[nSize]; - char* func_name; - char* func_addr; - ulint load_addr = 0; - ibool valid_load_addr = FALSE; -#ifdef _WIN64 - const char* tmp_string = " Preferred load address is %16llx"; -#else - const char* tmp_string = " Preferred load address is %08x"; -#endif - - fp = fopen(filename, "r"); - if (fp == NULL) { - - return(FALSE); - } - - /* Check whether to create the hashtable */ - if (m_htbl == NULL) { - - m_htbl = wdl_hash_create(MAP_HASH_CELLS_NUM); - - if (m_htbl == NULL) { - - fclose(fp); - return(FALSE); - } - } - - /* Search start of symbol list and get the preferred load address */ - while (fgets(tmp_buf, sizeof(tmp_buf), fp)) { - - if (sscanf(tmp_buf, tmp_string, &load_addr) == 1) { - - valid_load_addr = TRUE; - } - - if (strstr(tmp_buf, "Rva+Base") != NULL) { - - break; - } - } - - if (valid_load_addr == FALSE) { - - /* No "Preferred load address", the map file is wrong. */ - fclose(fp); - return(FALSE); - } - - /* Read symbol list */ - while (fgets(tmp_buf, sizeof(tmp_buf), fp)) - { - map_hash_chain_t* map_cell; - ulint map_fold; - - if (*tmp_buf == 0) { - - continue; - } - - func_name = strtok(tmp_buf, " "); - func_name = strtok(NULL, " "); - func_addr = strtok(NULL, " "); - - if (func_name && func_addr) { - - ut_snprintf(tmp_buf, nSize, "0x%s", func_addr); - if (*func_name == '_') { - - func_name++; - } - - map_cell = (map_hash_chain_t*) - malloc(sizeof(map_hash_chain_t)); - if (map_cell == NULL) { - return(FALSE); - } - - /* Chain all cells together */ - map_cell->chain = chain_header; - chain_header = map_cell; - - map_cell->symbol = strdup(func_name); - map_cell->value = (ulint) _strtoui64(tmp_buf, NULL, 0) - - load_addr; - map_fold = ut_fold_string(map_cell->symbol); - - HASH_INSERT(map_hash_chain_t, - next, - m_htbl, - map_fold, - map_cell); - } - } - - fclose(fp); - - return(TRUE); -} - -/*************************************************************//** -Cleanup.during DLL unload */ -static -void -wdl_cleanup(void) -/*=============*/ -{ - while (chain_header != NULL) { - map_hash_chain_t* tmp; - - tmp = chain_header->chain; - free(chain_header->symbol); - free(chain_header); - chain_header = tmp; - } - - if (m_htbl != NULL) { - - wdl_hash_table_free(m_htbl); - } -} - -/*******************************************************************//** -Load the mapfile mysqld.map. -@return the module handle */ -static -HMODULE -wdl_get_mysqld_mapfile(void) -/*========================*/ -{ - char file_name[MAX_PATH]; - char* ext; - ulint err; - - if (my_hmod == 0) { - - size_t nSize = MAX_PATH - strlen(".map") -1; - - /* First find out the name of current executable */ - my_hmod = GetModuleHandle(NULL); - if (my_hmod == 0) { - - return(my_hmod); - } - - err = GetModuleFileName(my_hmod, file_name, nSize); - if (err == 0) { - - my_hmod = 0; - return(my_hmod); - } - - ext = strrchr(file_name, '.'); - if (ext != NULL) { - - *ext = 0; - strcat(file_name, ".map"); - - err = wdl_load_mapfile(file_name); - if (err == 0) { - - my_hmod = 0; - } - } else { - - my_hmod = 0; - } - } - - return(my_hmod); -} - -/*******************************************************************//** -Retrieves the address of an exported function. It follows the convention -of GetProcAddress(). -@return address of exported function. */ -static -FARPROC -wdl_get_procaddr_from_map( -/*======================*/ - HANDLE m_handle, /*!< in: module handle */ - const char* import_proc) /*!< in: procedure name */ -{ - map_hash_chain_t* hash_chain; - ulint map_fold; - - map_fold = ut_fold_string(import_proc); - HASH_SEARCH( - next, - m_htbl, - map_fold, - map_hash_chain_t*, - hash_chain, - , - (ut_strcmp(hash_chain->symbol, import_proc) == 0)); - - if (hash_chain == NULL) { - -#ifdef _WIN64 - /* On Win64, the leading '_' may not be taken out. In this - case, search again without the leading '_'. */ - if (*import_proc == '_') { - - import_proc++; - } - - map_fold = ut_fold_string(import_proc); - HASH_SEARCH( - next, - m_htbl, - map_fold, - map_hash_chain_t*, - hash_chain, - , - (ut_strcmp(hash_chain->symbol, import_proc) == 0)); - - if (hash_chain == NULL) { -#endif - if (wdl_init == TRUE) { - - sql_print_error( - "InnoDB: the procedure pointer of %s" - " is not found.", - import_proc); - } - - return(0); -#ifdef _WIN64 - } -#endif - } - - return((FARPROC) ((ulint) m_handle + hash_chain->value)); -} - -/*******************************************************************//** -Retrieves the address of an exported variable. -Note: It does not follow the Windows call convention FARPROC. -@return address of exported variable. */ -static -void* -wdl_get_varaddr_from_map( -/*=====================*/ - HANDLE m_handle, /*!< in: module handle */ - const char* import_variable) /*!< in: variable name */ -{ - map_hash_chain_t* hash_chain; - ulint map_fold; - - map_fold = ut_fold_string(import_variable); - HASH_SEARCH( - next, - m_htbl, - map_fold, - map_hash_chain_t*, - hash_chain, - , - (ut_strcmp(hash_chain->symbol, import_variable) == 0)); - - if (hash_chain == NULL) { - -#ifdef _WIN64 - /* On Win64, the leading '_' may not be taken out. In this - case, search again without the leading '_'. */ - if (*import_variable == '_') { - - import_variable++; - } - - map_fold = ut_fold_string(import_variable); - HASH_SEARCH( - next, - m_htbl, - map_fold, - map_hash_chain_t*, - hash_chain, - , - (ut_strcmp(hash_chain->symbol, import_variable) == 0)); - - if (hash_chain == NULL) { -#endif - if (wdl_init == TRUE) { - - sql_print_error( - "InnoDB: the variable address of %s" - " is not found.", - import_variable); - } - - return(0); -#ifdef _WIN64 - } -#endif - } - - return((void*) ((ulint) m_handle + hash_chain->value)); -} - -/*******************************************************************//** -Bind all unresolved external variables from the MySQL executable. -@return TRUE if successful */ -static -bool -wdl_get_external_variables(void) -/*============================*/ -{ - HMODULE hmod = wdl_get_mysqld_mapfile(); - - if (hmod == 0) { - - return(FALSE); - } - -#define GET_SYM(sym, var, type) \ - var = (type*) wdl_get_varaddr_from_map(hmod, sym); \ - if (var == NULL) return(FALSE) -#ifdef _WIN64 -#define GET_SYM2(sym1, sym2, var, type) \ - var = (type*) wdl_get_varaddr_from_map(hmod, sym1); \ - if (var == NULL) return(FALSE) -#else -#define GET_SYM2(sym1, sym2, var, type) \ - var = (type*) wdl_get_varaddr_from_map(hmod, sym2); \ - if (var == NULL) return(FALSE) -#endif // (_WIN64) -#define GET_C_SYM(sym, type) GET_SYM(#sym, wdl_##sym, type) -#define GET_PROC_ADDR(sym) \ - wdl##sym = (pfn##sym) wdl_get_procaddr_from_map(hmod, #sym) - - GET_C_SYM(my_charset_bin, CHARSET_INFO); - GET_C_SYM(my_charset_latin1, CHARSET_INFO); - GET_C_SYM(my_charset_filename, CHARSET_INFO); - GET_C_SYM(default_charset_info, CHARSET_INFO*); - GET_C_SYM(all_charsets, CHARSET_INFO*); - GET_C_SYM(my_umask, int); - - GET_SYM("?global_system_variables@@3Usystem_variables@@A", - wdl_global_system_variables, struct system_variables); - GET_SYM("?mysql_real_data_home@@3PADA", - wdl_mysql_real_data_home, char); - GET_SYM("?reg_ext@@3PADA", wdl_reg_ext, char); - GET_SYM("?LOCK_thread_count@@3U_RTL_CRITICAL_SECTION@@A", - wdl_LOCK_thread_count, pthread_mutex_t); - GET_SYM("?key_map_full@@3V?$Bitmap@$0EA@@@A", - wdl_key_map_full, key_map); - GET_SYM("?mysql_tmpdir_list@@3Ust_my_tmpdir@@A", - wdl_mysql_tmpdir_list, MY_TMPDIR); - GET_SYM("?mysqld_embedded@@3_NA", - wdl_mysqld_embedded, bool); - GET_SYM("?lower_case_table_names@@3IA", - wdl_lower_case_table_names, uint); - GET_SYM("?specialflag@@3KA", wdl_specialflag, ulong); - - GET_SYM2("?system_charset_info@@3PEAUcharset_info_st@@EA", - "?system_charset_info@@3PAUcharset_info_st@@A", - wdl_system_charset_info, CHARSET_INFO*); - GET_SYM2("?mysql_data_home@@3PEADEA", - "?mysql_data_home@@3PADA", - wdl_mysql_data_home, char*); - GET_SYM2("?tx_isolation_names@@3PAPEBDA", - "?tx_isolation_names@@3PAPBDA", - wdl_tx_isolation_names, char*); - GET_SYM2("?binlog_format_names@@3PAPEBDA", - "?binlog_format_names@@3PAPBDA", - wdl_binlog_format_names, char*); - -#ifndef DBUG_OFF - GET_PROC_ADDR(_db_enter_); - GET_PROC_ADDR(_db_return_); - GET_PROC_ADDR(_db_pargs_); - GET_PROC_ADDR(_db_doprnt_); - GET_PROC_ADDR(_db_dump_); - - /* If any of the dbug functions is not available, just make them - all invalid. This is the case when working with a non-debug - version of the server. */ - if (wdl_db_enter_ == NULL || wdl_db_return_ == NULL - || wdl_db_pargs_ == NULL || wdl_db_doprnt_ == NULL - || wdl_db_dump_ == NULL) { - - wdl_db_enter_ = NULL; - wdl_db_return_ = NULL; - wdl_db_pargs_ = NULL; - wdl_db_doprnt_ = NULL; - wdl_db_dump_ = NULL; - } -#endif /* !DBUG_OFF */ - - wdl_init = TRUE; - return(TRUE); - -#undef GET_SYM -#undef GET_SYM2 -#undef GET_C_SYM -#undef GET_PROC_ADDR -} - -/*******************************************************************//** -The DLL Delayed Loading Helper Function for resolving externals. - -The function may fail due to one of the three reasons: - -* Invalid parameter, which happens if the attributes in pidd aren't - specified correctly. -* Failed to load the map file mysqld.map. -* Failed to find an external name in the map file mysqld.map. - -Note: this function is called by run-time as well as __HrLoadAllImportsForDll. -So, it has to follow Windows call convention. -@return the address of the imported function */ -extern "C" -FARPROC WINAPI -__delayLoadHelper2( -/*===============*/ - PCImgDelayDescr pidd, /*!< in: a const pointer to a - ImgDelayDescr, see delayimp.h. */ - FARPROC* iat_entry) /*!< in/out: A pointer to the slot in - the delay load import address table - to be updated with the address of the - imported function. */ -{ - ulint iIAT, iINT; - HMODULE hmod; - PCImgThunkData pitd; - FARPROC fun = NULL; - - /* Set up data used for the hook procs */ - InternalImgDelayDescr idd = { - pidd->grAttrs, - PFromRva(pidd->rvaDLLName), - PFromRva(pidd->rvaHmod), - PFromRva(pidd->rvaIAT), - PFromRva(pidd->rvaINT), - PFromRva(pidd->rvaBoundIAT), - PFromRva(pidd->rvaUnloadIAT), - pidd->dwTimeStamp - }; - - DelayLoadInfo dli = { - sizeof(DelayLoadInfo), - pidd, - iat_entry, - idd.szName, - {0}, - 0, - 0, - 0 - }; - - /* Check the Delay Load Attributes, log an error of invalid - parameter, which happens if the attributes in pidd are not - specified correctly. */ - if ((idd.grAttrs & dlattrRva) == 0) { - - sql_print_error("InnoDB: invalid parameter for delay loader."); - return(0); - } - - hmod = *idd.phmod; - - /* Calculate the index for the IAT entry in the import address table. - The INT entries are ordered the same as the IAT entries so the - calculation can be done on the IAT side. */ - iIAT = (PCImgThunkData) iat_entry - idd.pIAT; - iINT = iIAT; - - pitd = &(idd.pINT[iINT]); - - dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pitd->u1.Ordinal); - - if (dli.dlp.fImportByName) { - - dli.dlp.szProcName = (LPCSTR) (PFromRva - ((RVA) ((UINT_PTR) pitd->u1.AddressOfData))->Name); - } else { - - dli.dlp.dwOrdinal = (ulint) IMAGE_ORDINAL(pitd->u1.Ordinal); - } - - /* Now, load the mapfile, if it has not been done yet */ - if (hmod == 0) { - - hmod = wdl_get_mysqld_mapfile(); - } - - if (hmod == 0) { - /* LoadLibrary failed. */ - PDelayLoadInfo rgpdli[1] = {&dli}; - - dli.dwLastError = ::GetLastError(); - - sql_print_error( - "InnoDB: failed to load mysqld.map with error %d.", - dli.dwLastError); - - return(0); - } - - /* Store the library handle. */ - idd.phmod = &hmod; - - /* Go for the procedure now. */ - dli.hmodCur = hmod; - - if (pidd->rvaBoundIAT && pidd->dwTimeStamp) { - - /* Bound imports exist, check the timestamp from the target - image */ - PIMAGE_NT_HEADERS pinh; - - pinh = (PIMAGE_NT_HEADERS) ((byte*) hmod - + ((PIMAGE_DOS_HEADER) hmod)->e_lfanew); - - if (pinh->Signature == IMAGE_NT_SIGNATURE - && pinh->FileHeader.TimeDateStamp == idd.dwTimeStamp - && (DWORD) hmod == pinh->OptionalHeader.ImageBase) { - - /* We have a decent address in the bound IAT. */ - fun = (FARPROC) (UINT_PTR) - idd.pBoundIAT[iIAT].u1.Function; - - if (fun) { - - *iat_entry = fun; - return(fun); - } - } - } - - fun = wdl_get_procaddr_from_map(hmod, dli.dlp.szProcName); - - if (fun == 0) { - - return(0); - } - - *iat_entry = fun; - return(fun); -} - -/*******************************************************************//** -Unload a DLL that was delay loaded. This function is called by run-time. -@return TRUE is returned if the DLL is found and the IAT matches the -original one. */ -extern "C" -BOOL WINAPI -__FUnloadDelayLoadedDLL2( -/*=====================*/ - LPCSTR module_name) /*!< in: DLL name */ -{ - return(TRUE); -} - -/**************************************************************//** -Load all imports from a DLL that was specified with the /delayload linker -option. -Note: this function is called by run-time. So, it has to follow Windows call -convention. -@return S_OK if the DLL matches, otherwise ERROR_MOD_NOT_FOUND is returned. */ -extern "C" -HRESULT WINAPI -__HrLoadAllImportsForDll( -/*=====================*/ - LPCSTR module_name) /*!< in: DLL name */ -{ - PIMAGE_NT_HEADERS img; - PCImgDelayDescr pidd; - IMAGE_DATA_DIRECTORY* image_data; - LPCSTR current_module; - HRESULT ret = ERROR_MOD_NOT_FOUND; - HMODULE hmod = (HMODULE) &__ImageBase; - - img = (PIMAGE_NT_HEADERS) ((byte*) hmod - + ((PIMAGE_DOS_HEADER) hmod)->e_lfanew); - image_data = - &img->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]; - - /* Scan the delay load IAT/INT for the DLL */ - if (image_data->Size) { - - pidd = PFromRva(image_data->VirtualAddress); - - /* Check all of the listed DLLs we want to load. */ - while (pidd->rvaDLLName) { - - current_module = PFromRva(pidd->rvaDLLName); - - if (stricmp(module_name, current_module) == 0) { - - /* Found it, break out with pidd and - current_module set appropriately */ - break; - } - - /* To the next delay import descriptor */ - pidd++; - } - - if (pidd->rvaDLLName) { - - /* Found a matching DLL, now process it. */ - FARPROC* iat_entry; - size_t count; - - iat_entry = PFromRva(pidd->rvaIAT); - count = wdl_import_count((PCImgThunkData) iat_entry); - - /* now load all the imports from the DLL */ - while (count > 0) { - - /* No need to check the return value */ - __delayLoadHelper2(pidd, iat_entry); - iat_entry++; - count--; - } - - ret = S_OK; - } - } - - return ret; -} - -/**************************************************************//** -The main function of a DLL -@return TRUE if the call succeeds */ -BOOL -WINAPI -DllMain( -/*====*/ - HINSTANCE hinstDLL, /*!< in: handle to the DLL module */ - DWORD fdwReason, /*!< Reason code that indicates why the - DLL entry-point function is being - called.*/ - LPVOID lpvReserved) /*!< in: additional parameter based on - fdwReason */ -{ - BOOL success = TRUE; - - switch (fdwReason) { - - case DLL_PROCESS_ATTACH: - success = wdl_get_external_variables(); - break; - - case DLL_PROCESS_DETACH: - wdl_cleanup(); - break; - } - - return(success); -} - -#ifndef DBUG_OFF -/**************************************************************//** -Process entry point to user function. It makes the call to _db_enter_ -in mysqld.exe. The DBUG functions are defined in my_dbug.h. */ -extern "C" UNIV_INTERN -void -_db_enter_( - const char* _func_, /*!< in: current function name */ - const char* _file_, /*!< in: current file name */ - uint _line_, /*!< in: current source line number */ - const char** _sfunc_, /*!< out: previous _func_ */ - const char** _sfile_, /*!< out: previous _file_ */ - uint* _slevel_, /*!< out: previous nesting level */ - char*** _sframep_) /*!< out: previous frame pointer */ -{ - if (wdl_db_enter_ != NULL) { - - wdl_db_enter_(_func_, _file_, _line_, _sfunc_, _sfile_, - _slevel_, _sframep_); - } -} - -/**************************************************************//** -Process exit from user function. It makes the call to _db_return_() -in the server. */ -extern "C" UNIV_INTERN -void -_db_return_( - uint _line_, /*!< in: current source line number */ - const char** _sfunc_, /*!< out: previous _func_ */ - const char** _sfile_, /*!< out: previous _file_ */ - uint* _slevel_) /*!< out: previous level */ -{ - if (wdl_db_return_ != NULL) { - - wdl_db_return_(_line_, _sfunc_, _sfile_, _slevel_); - } -} - -/**************************************************************//** -Log arguments for subsequent use. It makes the call to _db_pargs_() -in the server. */ -extern "C" UNIV_INTERN -void -_db_pargs_( - uint _line_, /*!< in: current source line number */ - const char* keyword) /*!< in: keyword for current macro */ -{ - if (wdl_db_pargs_ != NULL) { - - wdl_db_pargs_(_line_, keyword); - } -} - -/**************************************************************//** -Handle print of debug lines. It saves the text into a buffer first, -then makes the call to _db_doprnt_() in the server. The text is -truncated to the size of buffer. */ -extern "C" UNIV_INTERN -void -_db_doprnt_( - const char* format, /*!< in: the format string */ - ...) /*!< in: list of arguments */ -{ - va_list argp; - char buffer[512]; - - if (wdl_db_doprnt_ != NULL) { - - va_start(argp, format); - /* it is ok to ignore the trunction. */ - _vsnprintf(buffer, sizeof(buffer), format, argp); - wdl_db_doprnt_(buffer); - va_end(argp); - } -} - -/**************************************************************//** -Dump a string in hex. It makes the call to _db_dump_() in the server. */ -extern "C" UNIV_INTERN -void -_db_dump_( - uint _line_, /*!< in: current source line - number */ - const char* keyword, /*!< in: keyword list */ - const unsigned char* memory, /*!< in: memory to dump */ - size_t length) /*!< in: bytes to dump */ -{ - if (wdl_db_dump_ != NULL) { - - wdl_db_dump_(_line_, keyword, memory, length); - } -} - -#endif /* !DBUG_OFF */ -#endif /* defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) */ diff --git a/ibuf/ibuf0ibuf.c b/ibuf/ibuf0ibuf.c index a32efbd061f..94f3751dd04 100644 --- a/ibuf/ibuf0ibuf.c +++ b/ibuf/ibuf0ibuf.c @@ -389,6 +389,27 @@ ibuf_count_set( } #endif +/******************************************************************//** +Closes insert buffer and frees the data structures. */ +UNIV_INTERN +void +ibuf_close(void) +/*============*/ +{ + mutex_free(&ibuf_pessimistic_insert_mutex); + memset(&ibuf_pessimistic_insert_mutex, + 0x0, sizeof(ibuf_pessimistic_insert_mutex)); + + mutex_free(&ibuf_mutex); + memset(&ibuf_mutex, 0x0, sizeof(ibuf_mutex)); + + mutex_free(&ibuf_bitmap_mutex); + memset(&ibuf_bitmap_mutex, 0x0, sizeof(ibuf_mutex)); + + mem_free(ibuf); + ibuf = NULL; +} + /******************************************************************//** Updates the size information of the ibuf, assuming the segment size has not changed. */ diff --git a/include/btr0cur.h b/include/btr0cur.h index b2d43ae3254..480a3877e54 100644 --- a/include/btr0cur.h +++ b/include/btr0cur.h @@ -618,7 +618,7 @@ enum btr_cur_method { hash_node, and might be necessary to update */ BTR_CUR_BINARY, /*!< success using the binary search */ - BTR_CUR_INSERT_TO_IBUF, /*!< performed the intended insert to + BTR_CUR_INSERT_TO_IBUF /*!< performed the intended insert to the insert buffer */ }; diff --git a/include/btr0sea.h b/include/btr0sea.h index 5c50829e874..7f4842d0897 100644 --- a/include/btr0sea.h +++ b/include/btr0sea.h @@ -41,6 +41,12 @@ void btr_search_sys_create( /*==================*/ ulint hash_size); /*!< in: hash index hash table size */ +/*****************************************************************//** +Frees the adaptive search system at a database shutdown. */ +UNIV_INTERN +void +btr_search_sys_free(void); +/*=====================*/ /********************************************************************//** Disable the adaptive hash search system and empty the index. */ diff --git a/include/buf0buf.h b/include/buf0buf.h index 8063f9ec2c8..ddd08c49a12 100644 --- a/include/buf0buf.h +++ b/include/buf0buf.h @@ -346,7 +346,7 @@ buf_page_release( mtr_t* mtr); /*!< in: mtr */ /********************************************************************//** Moves a page to the start of the buffer pool LRU list. This high-level -function can be used to prevent an important page from from slipping out of +function can be used to prevent an important page from slipping out of the buffer pool. */ UNIV_INTERN void @@ -707,15 +707,6 @@ buf_page_belongs_to_unzip_LRU( /*==========================*/ const buf_page_t* bpage) /*!< in: pointer to control block */ __attribute__((pure)); -/*********************************************************************//** -Determine the approximate LRU list position of a block. -@return LRU list position */ -UNIV_INLINE -ulint -buf_page_get_LRU_position( -/*======================*/ - const buf_page_t* bpage) /*!< in: control block */ - __attribute__((pure)); /*********************************************************************//** Gets the mutex of a block. @@ -825,14 +816,14 @@ buf_page_set_old( buf_page_t* bpage, /*!< in/out: control block */ ibool old); /*!< in: old */ /*********************************************************************//** -Determine if a block has been accessed in the buffer pool. -@return TRUE if accessed */ +Determine the time of first access of a block in the buffer pool. +@return ut_time_ms() at the time of first access, 0 if not accessed */ UNIV_INLINE -ibool +unsigned buf_page_is_accessed( /*=================*/ const buf_page_t* bpage) /*!< in: control block */ - __attribute__((pure)); + __attribute__((nonnull, pure)); /*********************************************************************//** Flag a block accessed. */ UNIV_INLINE @@ -840,7 +831,8 @@ void buf_page_set_accessed( /*==================*/ buf_page_t* bpage, /*!< in/out: control block */ - ibool accessed); /*!< in: accessed */ + ulint time_ms) /*!< in: ut_time_ms() */ + __attribute__((nonnull)); /*********************************************************************//** Gets the buf_block_t handle of a buffered file block if an uncompressed page frame exists, or NULL. @@ -1026,14 +1018,6 @@ buf_block_hash_get( /*===============*/ ulint space, /*!< in: space id */ ulint offset);/*!< in: offset of the page within space */ -/*******************************************************************//** -Increments the pool clock by one and returns its new value. Remember that -in the 32 bit version the clock wraps around at 4 billion! -@return new clock value */ -UNIV_INLINE -ulint -buf_pool_clock_tic(void); -/*====================*/ /*********************************************************************//** Gets the current length of the free list of buffer blocks. @return length of the free list */ @@ -1073,16 +1057,10 @@ struct buf_page_struct{ flushed to disk, this tells the flush_type. @see enum buf_flush */ - unsigned accessed:1; /*!< TRUE if the page has been accessed - while in the buffer pool: read-ahead - may read in pages which have not been - accessed yet; a thread is allowed to - read this for heuristic purposes - without holding any mutex or latch */ unsigned io_fix:2; /*!< type of pending I/O operation; also protected by buf_pool_mutex @see enum buf_io_fix */ - unsigned buf_fix_count:24;/*!< count of how manyfold this block + unsigned buf_fix_count:25;/*!< count of how manyfold this block is currently bufferfixed */ /* @} */ #endif /* !UNIV_HOTBACKUP */ @@ -1112,7 +1090,16 @@ struct buf_page_struct{ - BUF_BLOCK_FILE_PAGE: flush_list - BUF_BLOCK_ZIP_DIRTY: flush_list - BUF_BLOCK_ZIP_PAGE: zip_clean - - BUF_BLOCK_ZIP_FREE: zip_free[] */ + - BUF_BLOCK_ZIP_FREE: zip_free[] + + The contents of the list node + is undefined if !in_flush_list + && state == BUF_BLOCK_FILE_PAGE, + or if state is one of + BUF_BLOCK_MEMORY, + BUF_BLOCK_REMOVE_HASH or + BUF_BLOCK_READY_IN_USE. */ + /* resplit for optimistic use */ UT_LIST_NODE_T(buf_page_t) free; UT_LIST_NODE_T(buf_page_t) flush_list; @@ -1155,18 +1142,8 @@ struct buf_page_struct{ debugging */ //#endif /* UNIV_DEBUG */ unsigned old:1; /*!< TRUE if the block is in the old - blocks in the LRU list */ - unsigned LRU_position:31;/*!< value which monotonically - decreases (or may stay - constant if old==TRUE) toward - the end of the LRU list, if - buf_pool->ulint_clock has not - wrapped around: NOTE that this - value can only be used in - heuristic algorithms, because - of the possibility of a - wrap-around! */ - unsigned freed_page_clock:32;/*!< the value of + blocks in buf_pool->LRU_old */ + unsigned freed_page_clock:31;/*!< the value of buf_pool->freed_page_clock when this block was the last time put to the head of the @@ -1174,6 +1151,9 @@ struct buf_page_struct{ to read this for heuristic purposes without holding any mutex or latch */ + unsigned access_time:32; /*!< time of first access, or + 0 if the block was never accessed + in the buffer pool */ /* @} */ # ifdef UNIV_DEBUG_FILE_ACCESSES ibool file_page_was_freed; @@ -1318,6 +1298,31 @@ Compute the hash fold value for blocks in buf_pool->zip_hash. */ #define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b)) /* @} */ +/** @brief The buffer pool statistics structure. */ +struct buf_pool_stat_struct{ + ulint n_page_gets; /*!< number of page gets performed; + also successful searches through + the adaptive hash index are + counted as page gets; this field + is NOT protected by the buffer + pool mutex */ + ulint n_pages_read; /*!< number read operations */ + ulint n_pages_written;/*!< number write operations */ + ulint n_pages_created;/*!< number of pages created + in the pool with no read */ + ulint n_ra_pages_read;/*!< number of pages read in + as part of read ahead */ + ulint n_ra_pages_evicted;/*!< number of read ahead + pages that are evicted without + being accessed */ + ulint n_pages_made_young; /*!< number of pages made young, in + calls to buf_LRU_make_block_young() */ + ulint n_pages_not_made_young; /*!< number of pages not made + young because the first access + was not long enough ago, in + buf_page_peek_if_too_old() */ +}; + /** @brief The buffer pool structure. NOTE! The definition appears here only for other modules of this @@ -1342,28 +1347,16 @@ struct buf_pool_struct{ ulint n_pend_reads; /*!< number of pending read operations */ ulint n_pend_unzip; /*!< number of pending decompressions */ - time_t last_printout_time; /*!< when buf_print was last time + time_t last_printout_time; + /*!< when buf_print_io was last time called */ - ulint n_pages_read; /*!< number read operations */ - ulint n_pages_written;/*!< number write operations */ - ulint n_pages_created;/*!< number of pages created - in the pool with no read */ - ulint n_page_gets; /*!< number of page gets performed; - also successful searches through - the adaptive hash index are - counted as page gets; this field - is NOT protected by the buffer - pool mutex */ - ulint n_page_gets_old;/*!< n_page_gets when buf_print was - last time called: used to calculate - hit rate */ - ulint n_pages_read_old;/*!< n_pages_read when buf_print was - last time called */ - ulint n_pages_written_old;/*!< number write operations */ - ulint n_pages_created_old;/*!< number of pages created in - the pool with no read */ + buf_pool_stat_t stat; /*!< current statistics */ + buf_pool_stat_t old_stat; /*!< old statistics */ + /* @} */ + /** @name Page flushing algorithm fields */ + /* @{ */ UT_LIST_BASE_NODE_T(buf_page_t) flush_list; @@ -1379,10 +1372,6 @@ struct buf_pool_struct{ /*!< this is in the set state when there is no flush batch of the given type running */ - ulint ulint_clock; /*!< a sequence number used to count - time. NOTE! This counter wraps - around at 4 billion (if ulint == - 32 bits)! */ ulint freed_page_clock;/*!< a sequence number used to count the number of buffer blocks removed from the end of @@ -1406,17 +1395,18 @@ struct buf_pool_struct{ block list */ UT_LIST_BASE_NODE_T(buf_page_t) LRU; /*!< base node of the LRU list */ - buf_page_t* LRU_old; /*!< pointer to the about 3/8 oldest - blocks in the LRU list; NULL if LRU - length less than BUF_LRU_OLD_MIN_LEN; + buf_page_t* LRU_old; /*!< pointer to the about + buf_LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV + oldest blocks in the LRU list; + NULL if LRU length less than + BUF_LRU_OLD_MIN_LEN; NOTE: when LRU_old != NULL, its length should always equal LRU_old_len */ ulint LRU_old_len; /*!< length of the LRU list from the block to which LRU_old points onward, including that block; see buf0lru.c for the restrictions - on this value; not defined if - LRU_old == NULL; + on this value; 0 if LRU_old == NULL; NOTE: LRU_old_len must be adjusted whenever LRU_old shrinks or grows! */ diff --git a/include/buf0buf.ic b/include/buf0buf.ic index 014b69a5dc2..3688b1a7aa4 100644 --- a/include/buf0buf.ic +++ b/include/buf0buf.ic @@ -72,9 +72,30 @@ buf_page_peek_if_too_old( /*=====================*/ const buf_page_t* bpage) /*!< in: block to make younger */ { - return(buf_pool->freed_page_clock - >= buf_page_get_freed_page_clock(bpage) - + 1 + (buf_pool->curr_size / 4)); + if (UNIV_UNLIKELY(buf_pool->freed_page_clock == 0)) { + /* If eviction has not started yet, do not update the + statistics or move blocks in the LRU list. This is + either the warm-up phase or an in-memory workload. */ + return(FALSE); + } else if (buf_LRU_old_threshold_ms && bpage->old) { + unsigned access_time = buf_page_is_accessed(bpage); + + if (access_time > 0 + && (ut_time_ms() - access_time) + >= buf_LRU_old_threshold_ms) { + return(TRUE); + } + + buf_pool->stat.n_pages_not_made_young++; + return(FALSE); + } else { + /* FIXME: bpage->freed_page_clock is 31 bits */ + return((buf_pool->freed_page_clock & ((1UL << 31) - 1)) + > ((ulint) bpage->freed_page_clock + + (buf_pool->curr_size + * (BUF_LRU_OLD_RATIO_DIV - buf_LRU_old_ratio) + / (BUF_LRU_OLD_RATIO_DIV * 4)))); + } } /*********************************************************************//** @@ -125,23 +146,6 @@ try_again: return(lsn); } - -/*******************************************************************//** -Increments the buf_pool clock by one and returns its new value. Remember -that in the 32 bit version the clock wraps around at 4 billion! -@return new clock value */ -UNIV_INLINE -ulint -buf_pool_clock_tic(void) -/*====================*/ -{ - //ut_ad(buf_pool_mutex_own()); - ut_ad(mutex_own(&LRU_list_mutex)); - - buf_pool->ulint_clock++; - - return(buf_pool->ulint_clock); -} #endif /* !UNIV_HOTBACKUP */ /*********************************************************************//** @@ -287,21 +291,6 @@ buf_page_belongs_to_unzip_LRU( && buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); } -/*********************************************************************//** -Determine the approximate LRU list position of a block. -@return LRU list position */ -UNIV_INLINE -ulint -buf_page_get_LRU_position( -/*======================*/ - const buf_page_t* bpage) /*!< in: control block */ -{ - ut_ad(buf_page_in_file(bpage)); - //ut_ad(buf_pool_mutex_own()); /* This is used in optimistic */ - - return(bpage->LRU_position); -} - /*********************************************************************//** Gets the mutex of a block. @return pointer to mutex protecting bpage */ @@ -508,10 +497,19 @@ buf_page_set_old( ut_ad(bpage->in_LRU_list); #ifdef UNIV_LRU_DEBUG - if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage) - && UT_LIST_GET_PREV(LRU, bpage)->old - == UT_LIST_GET_NEXT(LRU, bpage)->old) { - ut_a(UT_LIST_GET_PREV(LRU, bpage)->old == old); + ut_a((buf_pool->LRU_old_len == 0) == (buf_pool->LRU_old == NULL)); + /* If a block is flagged "old", the LRU_old list must exist. */ + ut_a(!old || buf_pool->LRU_old); + + if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)) { + const buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); + const buf_page_t* next = UT_LIST_GET_NEXT(LRU, bpage); + if (prev->old == next->old) { + ut_a(prev->old == old); + } else { + ut_a(!prev->old); + ut_a(buf_pool->LRU_old == (old ? bpage : next)); + } } #endif /* UNIV_LRU_DEBUG */ @@ -519,17 +517,17 @@ buf_page_set_old( } /*********************************************************************//** -Determine if a block has been accessed in the buffer pool. -@return TRUE if accessed */ +Determine the time of first access of a block in the buffer pool. +@return ut_time_ms() at the time of first access, 0 if not accessed */ UNIV_INLINE -ibool +unsigned buf_page_is_accessed( /*=================*/ const buf_page_t* bpage) /*!< in: control block */ { ut_ad(buf_page_in_file(bpage)); - return(bpage->accessed); + return(bpage->access_time); } /*********************************************************************//** @@ -539,12 +537,16 @@ void buf_page_set_accessed( /*==================*/ buf_page_t* bpage, /*!< in/out: control block */ - ibool accessed) /*!< in: accessed */ + ulint time_ms) /*!< in: ut_time_ms() */ { ut_a(buf_page_in_file(bpage)); + //ut_ad(buf_pool_mutex_own()); ut_ad(mutex_own(buf_page_get_mutex(bpage))); - bpage->accessed = accessed; + if (!bpage->access_time) { + /* Make this the time of the first access. */ + bpage->access_time = time_ms; + } } /*********************************************************************//** diff --git a/include/buf0lru.h b/include/buf0lru.h index cde88824b64..0a7d01c95cf 100644 --- a/include/buf0lru.h +++ b/include/buf0lru.h @@ -69,7 +69,7 @@ These are low-level functions #########################################################################*/ /** Minimum LRU list length for which the LRU_old pointer is defined */ -#define BUF_LRU_OLD_MIN_LEN 80 +#define BUF_LRU_OLD_MIN_LEN 512 /* 8 megabytes of 16k pages */ /** Maximum LRU list search length in buf_flush_LRU_recommendation() */ #define BUF_LRU_FREE_SEARCH_LEN (5 + 2 * BUF_READ_AHEAD_AREA) @@ -84,15 +84,6 @@ void buf_LRU_invalidate_tablespace( /*==========================*/ ulint id); /*!< in: space id */ -/******************************************************************//** -Gets the minimum LRU_position field for the blocks in an initial segment -(determined by BUF_LRU_INITIAL_RATIO) of the LRU list. The limit is not -guaranteed to be precise, because the ulint_clock may wrap around. -@return the limit; zero if could not determine it */ -UNIV_INTERN -ulint -buf_LRU_get_recent_limit(void); -/*==========================*/ /********************************************************************//** Insert a compressed block into buf_pool->zip_clean in the LRU order. */ UNIV_INTERN @@ -203,6 +194,18 @@ void buf_LRU_make_block_old( /*===================*/ buf_page_t* bpage); /*!< in: control block */ +/**********************************************************************//** +Updates buf_LRU_old_ratio. +@return updated old_pct */ +UNIV_INTERN +uint +buf_LRU_old_ratio_update( +/*=====================*/ + uint old_pct,/*!< in: Reserve this percentage of + the buffer pool for "old" blocks. */ + ibool adjust);/*!< in: TRUE=adjust the LRU list; + FALSE=just assign buf_LRU_old_ratio + during the initialization of InnoDB */ /********************************************************************//** Update the historical stats that we are collecting for LRU eviction policy at the end of each interval. */ @@ -210,6 +213,18 @@ UNIV_INTERN void buf_LRU_stat_update(void); /*=====================*/ +/********************************************************************//** +Dump the LRU page list to the specific file. */ +UNIV_INTERN +ibool +buf_LRU_file_dump(void); +/*===================*/ +/********************************************************************//** +Read the pages based on the specific file.*/ +UNIV_INTERN +ibool +buf_LRU_file_restore(void); +/*======================*/ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /**********************************************************************//** @@ -229,6 +244,35 @@ buf_LRU_print(void); /*===============*/ #endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ +/** @name Heuristics for detecting index scan @{ */ +/** Reserve this much/BUF_LRU_OLD_RATIO_DIV of the buffer pool for +"old" blocks. Protected by buf_pool_mutex. */ +extern uint buf_LRU_old_ratio; +/** The denominator of buf_LRU_old_ratio. */ +#define BUF_LRU_OLD_RATIO_DIV 1024 +/** Maximum value of buf_LRU_old_ratio. +@see buf_LRU_old_adjust_len +@see buf_LRU_old_ratio_update */ +#define BUF_LRU_OLD_RATIO_MAX BUF_LRU_OLD_RATIO_DIV +/** Minimum value of buf_LRU_old_ratio. +@see buf_LRU_old_adjust_len +@see buf_LRU_old_ratio_update +The minimum must exceed +(BUF_LRU_OLD_TOLERANCE + 5) * BUF_LRU_OLD_RATIO_DIV / BUF_LRU_OLD_MIN_LEN. */ +#define BUF_LRU_OLD_RATIO_MIN 51 + +#if BUF_LRU_OLD_RATIO_MIN >= BUF_LRU_OLD_RATIO_MAX +# error "BUF_LRU_OLD_RATIO_MIN >= BUF_LRU_OLD_RATIO_MAX" +#endif +#if BUF_LRU_OLD_RATIO_MAX > BUF_LRU_OLD_RATIO_DIV +# error "BUF_LRU_OLD_RATIO_MAX > BUF_LRU_OLD_RATIO_DIV" +#endif + +/** Move blocks to "new" LRU list only if the first access was at +least this many milliseconds ago. Not protected by any mutex or latch. */ +extern uint buf_LRU_old_threshold_ms; +/* @} */ + /** @brief Statistics for selecting the LRU list for eviction. These statistics are not 'of' LRU but 'for' LRU. We keep count of I/O diff --git a/include/buf0rea.h b/include/buf0rea.h index e19f50124e5..71f62ff7b49 100644 --- a/include/buf0rea.h +++ b/include/buf0rea.h @@ -30,16 +30,45 @@ Created 11/5/1995 Heikki Tuuri #include "trx0types.h" #include "buf0types.h" +/********************************************************************//** +Low-level function which reads a page asynchronously from a file to the +buffer buf_pool if it is not already there, in which case does nothing. +Sets the io_fix flag and sets an exclusive lock on the buffer frame. The +flag is cleared and the x-lock released by an i/o-handler thread. +@return 1 if a read request was queued, 0 if the page already resided +in buf_pool, or if the page is in the doublewrite buffer blocks in +which case it is never read into the pool, or if the tablespace does +not exist or is being dropped +@return 1 if read request is issued. 0 if it is not */ +UNIV_INTERN +ulint +buf_read_page_low( +/*==============*/ + ulint* err, /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are + trying to read from a non-existent tablespace, or a + tablespace which is just now being dropped */ + ibool sync, /*!< in: TRUE if synchronous aio is desired */ + ulint mode, /*!< in: BUF_READ_IBUF_PAGES_ONLY, ..., + ORed to OS_AIO_SIMULATED_WAKE_LATER (see below + at read-ahead functions) */ + ulint space, /*!< in: space id */ + ulint zip_size,/*!< in: compressed page size, or 0 */ + ibool unzip, /*!< in: TRUE=request uncompressed page */ + ib_int64_t tablespace_version, /*!< in: if the space memory object has + this timestamp different from what we are giving here, + treat the tablespace as dropped; this is a timestamp we + use to stop dangling page reads from a tablespace + which we have DISCARDed + IMPORTed back */ + ulint offset, /*!< in: page number */ + trx_t* trx); /********************************************************************//** High-level function which reads a page asynchronously from a file to the buffer buf_pool if it is not already there. Sets the io_fix flag and sets an exclusive lock on the buffer frame. The flag is cleared and the x-lock -released by the i/o-handler thread. Does a random read-ahead if it seems -sensible. -@return number of page read requests issued: this can be greater than -1 if read-ahead occurred */ +released by the i/o-handler thread. +@return TRUE if page has been read in, FALSE in case of failure */ UNIV_INTERN -ulint +ibool buf_read_page( /*==========*/ ulint space, /*!< in: space id */ @@ -50,7 +79,7 @@ buf_read_page( Applies linear read-ahead if in the buf_pool the page is a border page of a linear read-ahead area and all the pages in the area have been accessed. Does not read any page if the read-ahead mechanism is not activated. Note -that the the algorithm looks at the 'natural' adjacent successor and +that the algorithm looks at the 'natural' adjacent successor and predecessor of the page, which on the leaf level of a B-tree are the next and previous page in the chain of leaves. To know these, the page specified in (space, offset) must already be present in the buf_pool. Thus, the diff --git a/include/buf0types.h b/include/buf0types.h index e7167d716a0..bfae6477135 100644 --- a/include/buf0types.h +++ b/include/buf0types.h @@ -34,6 +34,8 @@ typedef struct buf_block_struct buf_block_t; typedef struct buf_chunk_struct buf_chunk_t; /** Buffer pool comprising buf_chunk_t */ typedef struct buf_pool_struct buf_pool_t; +/** Buffer pool statistics struct */ +typedef struct buf_pool_stat_struct buf_pool_stat_t; /** A buffer frame. @see page_t */ typedef byte buf_frame_t; diff --git a/include/db0err.h b/include/db0err.h index 23898583b72..747e9b5364e 100644 --- a/include/db0err.h +++ b/include/db0err.h @@ -32,6 +32,7 @@ enum db_err { /* The following are error codes */ DB_ERROR, + DB_INTERRUPTED, DB_OUT_OF_MEMORY, DB_OUT_OF_FILE_SPACE, DB_LOCK_WAIT, diff --git a/include/dict0crea.h b/include/dict0crea.h index 3107d771d88..cce1246b789 100644 --- a/include/dict0crea.h +++ b/include/dict0crea.h @@ -110,7 +110,7 @@ dict_create_or_check_foreign_constraint_tables(void); Adds foreign key definitions to data dictionary tables in the database. We look at table->foreign_list, and also generate names to constraints that were not named by the user. A generated constraint has a name of the format -databasename/tablename_ibfk_, where the numbers start from 1, and are +databasename/tablename_ibfk_NUMBER, where the numbers start from 1, and are given locally for this table, that is, the number is not global, as in the old format constraints < 4.0.18 it used to be. @return error code or DB_SUCCESS */ diff --git a/include/dict0dict.h b/include/dict0dict.h index 0842e307cda..3d49b6a98a4 100644 --- a/include/dict0dict.h +++ b/include/dict0dict.h @@ -712,7 +712,7 @@ dict_index_find_on_id_low( dulint id); /*!< in: index id */ /**********************************************************************//** Adds an index to the dictionary cache. -@return DB_SUCCESS or error code */ +@return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */ UNIV_INTERN ulint dict_index_add_to_cache( @@ -1157,6 +1157,13 @@ void dict_ind_init(void); /*===============*/ +/**********************************************************************//** +Closes the data dictionary module. */ +UNIV_INTERN +void +dict_close(void); +/*============*/ + #ifndef UNIV_NONINL #include "dict0dict.ic" #endif diff --git a/include/dict0mem.h b/include/dict0mem.h index 1ee906fbf57..2d001111938 100644 --- a/include/dict0mem.h +++ b/include/dict0mem.h @@ -317,7 +317,7 @@ struct dict_foreign_struct{ char* id; /*!< id of the constraint as a null-terminated string */ unsigned n_fields:10; /*!< number of indexes' first fields - for which the the foreign key + for which the foreign key constraint is defined: we allow the indexes to contain more fields than mentioned in the constraint, as long diff --git a/include/fil0fil.h b/include/fil0fil.h index edf10b1dd5c..805948f5b5d 100644 --- a/include/fil0fil.h +++ b/include/fil0fil.h @@ -224,15 +224,6 @@ fil_space_create( 0 for uncompressed tablespaces */ ulint purpose);/*!< in: FIL_TABLESPACE, or FIL_LOG if log */ /*******************************************************************//** -Frees a space object from a the tablespace memory cache. Closes the files in -the chain but does not delete them. -@return TRUE if success */ -UNIV_INTERN -ibool -fil_space_free( -/*===========*/ - ulint id); /*!< in: space id */ -/*******************************************************************//** Returns the size of the space in pages. The tablespace must be cached in the memory cache. @return space size, 0 if space not found */ @@ -278,6 +269,12 @@ fil_init( ulint hash_size, /*!< in: hash table size */ ulint max_n_open); /*!< in: max number of open files */ /*******************************************************************//** +Initializes the tablespace memory cache. */ +UNIV_INTERN +void +fil_close(void); +/*===========*/ +/*******************************************************************//** Opens all log files and system tablespace data files. They stay open until the database server shutdown. This should be called at a server startup after the space objects for the log and the system tablespace have been created. The @@ -647,6 +644,22 @@ _fil_io( void* message, /*!< in: message for aio handler if non-sync aio used, else ignored */ trx_t* trx); +/********************************************************************//** +Confirm whether the parameters are valid or not */ +UNIV_INTERN +ibool +fil_area_is_exist( +/*==============*/ + ulint space_id, /*!< in: space id */ + ulint zip_size, /*!< in: compressed page size in bytes; + 0 for uncompressed pages */ + ulint block_offset, /*!< in: offset in number of blocks */ + ulint byte_offset, /*!< in: remainder of offset in bytes; in + aio this must be divisible by the OS block + size */ + ulint len); /*!< in: how many bytes to read or write; this + must not cross a file boundary; in aio this + must be a block size multiple */ /**********************************************************************//** Waits for an aio operation to complete. This function is used to write the handler for completed requests. The aio array of pending requests is divided diff --git a/include/fsp0fsp.h b/include/fsp0fsp.h index 5f7dc58eedc..7abd3914eda 100644 --- a/include/fsp0fsp.h +++ b/include/fsp0fsp.h @@ -42,7 +42,7 @@ fsp_init(void); /*==========*/ /**********************************************************************//** Gets the current free limit of the system tablespace. The free limit -means the place of the first page which has never been put to the the +means the place of the first page which has never been put to the free list for allocation. The space above that address is initialized to zero. Sets also the global variable log_fsp_current_free_limit. @return free limit in megabytes */ diff --git a/include/ibuf0ibuf.h b/include/ibuf0ibuf.h index 21330997df3..8aa21fb9d95 100644 --- a/include/ibuf0ibuf.h +++ b/include/ibuf0ibuf.h @@ -356,6 +356,12 @@ void ibuf_print( /*=======*/ FILE* file); /*!< in: file where to print */ +/******************************************************************//** +Closes insert buffer and frees the data structures. */ +UNIV_INTERN +void +ibuf_close(void); +/*============*/ #define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO #define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO diff --git a/include/lock0lock.h b/include/lock0lock.h index fa5db831d4f..82e4c9bd976 100644 --- a/include/lock0lock.h +++ b/include/lock0lock.h @@ -59,6 +59,12 @@ lock_sys_create( /*============*/ ulint n_cells); /*!< in: number of slots in lock hash table */ /*********************************************************************//** +Closes the lock system at database shutdown. */ +UNIV_INTERN +void +lock_sys_close(void); +/*================*/ +/*********************************************************************//** Checks if some transaction has an implicit x-lock on a record in a clustered index. @return transaction which has the x-lock, or NULL */ @@ -630,6 +636,14 @@ lock_number_of_rows_locked( /*=======================*/ trx_t* trx); /*!< in: transaction */ /*******************************************************************//** +Check if a transaction holds any autoinc locks. +@return TRUE if the transaction holds any AUTOINC locks. */ +UNIV_INTERN +ibool +lock_trx_holds_autoinc_locks( +/*=========================*/ + const trx_t* trx); /*!< in: transaction */ +/*******************************************************************//** Release all the transaction's autoinc locks. */ UNIV_INTERN void diff --git a/include/log0log.h b/include/log0log.h index 059f548a085..135aeb69e2d 100644 --- a/include/log0log.h +++ b/include/log0log.h @@ -118,10 +118,9 @@ UNIV_INLINE ib_uint64_t log_reserve_and_write_fast( /*=======================*/ - byte* str, /*!< in: string */ + const void* str, /*!< in: string */ ulint len, /*!< in: string length */ - ib_uint64_t* start_lsn,/*!< out: start lsn of the log record */ - ibool* success);/*!< out: TRUE if success */ + ib_uint64_t* start_lsn);/*!< out: start lsn of the log record */ /***********************************************************************//** Releases the log mutex. */ UNIV_INLINE @@ -283,7 +282,7 @@ log_make_checkpoint_at( later lsn, if IB_ULONGLONG_MAX, makes a checkpoint at the latest lsn */ ibool write_always); /*!< in: the function normally checks if - the the new checkpoint would have a + the new checkpoint would have a greater lsn than the previous one: if not, then no physical write is done; by setting this parameter TRUE, a @@ -573,6 +572,18 @@ UNIV_INTERN void log_refresh_stats(void); /*===================*/ +/********************************************************** +Shutdown the log system but do not release all the memory. */ +UNIV_INTERN +void +log_shutdown(void); +/*==============*/ +/********************************************************** +Free the log system data structures. */ +UNIV_INTERN +void +log_mem_free(void); +/*==============*/ extern log_t* log_sys; @@ -585,7 +596,7 @@ extern log_t* log_sys; #define LOG_RECOVER 98887331 /* The counting of lsn's starts from this value: this must be non-zero */ -#define LOG_START_LSN ((ib_uint64_t) (16 * OS_FILE_LOG_BLOCK_SIZE)) +#define LOG_START_LSN ((ib_uint64_t) (16 * OS_FILE_LOG_BLOCK_SIZE)) #define LOG_BUFFER_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE) #define LOG_ARCHIVE_BUF_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE / 4) @@ -722,9 +733,12 @@ struct log_group_struct{ ulint lsn_offset; /*!< the offset of the above lsn */ ulint n_pending_writes;/*!< number of currently pending flush writes for this log group */ + byte** file_header_bufs_ptr;/*!< unaligned buffers */ byte** file_header_bufs;/*!< buffers for each file header in the group */ +#ifdef UNIV_LOG_ARCHIVE /*-----------------------------*/ + byte** archive_file_header_bufs_ptr;/*!< unaligned buffers */ byte** archive_file_header_bufs;/*!< buffers for each file header in the group */ ulint archive_space_id;/*!< file space which @@ -743,10 +757,12 @@ struct log_group_struct{ completion function then sets the new value to ..._file_no */ ulint next_archived_offset; /*!< like the preceding field */ +#endif /* UNIV_LOG_ARCHIVE */ /*-----------------------------*/ ib_uint64_t scanned_lsn; /*!< used only in recovery: recovery scan succeeded up to this lsn in this log group */ + byte* checkpoint_buf_ptr;/*!< unaligned checkpoint header */ byte* checkpoint_buf; /*!< checkpoint header is written from this buffer to the group */ UT_LIST_NODE_T(log_group_t) @@ -764,6 +780,7 @@ struct log_struct{ #ifndef UNIV_HOTBACKUP mutex_t mutex; /*!< mutex protecting the log */ #endif /* !UNIV_HOTBACKUP */ + byte* buf_ptr; /* unaligned log buffer */ byte* buf; /*!< log buffer */ ulint buf_size; /*!< log buffer size in bytes */ ulint max_buf_free; /*!< recommended maximum value of @@ -900,6 +917,7 @@ struct log_struct{ should wait for this without owning the log mutex */ #endif /* !UNIV_HOTBACKUP */ + byte* checkpoint_buf_ptr;/* unaligned checkpoint header */ byte* checkpoint_buf; /*!< checkpoint header is read to this buffer */ /* @} */ diff --git a/include/log0log.ic b/include/log0log.ic index d071985982a..36d151a3064 100644 --- a/include/log0log.ic +++ b/include/log0log.ic @@ -27,6 +27,7 @@ Created 12/9/1995 Heikki Tuuri #include "mach0data.h" #include "mtr0mtr.h" +#ifdef UNIV_LOG_DEBUG /******************************************************//** Checks by parsing that the catenated log segment for a single mtr is consistent. */ @@ -34,11 +35,12 @@ UNIV_INTERN ibool log_check_log_recs( /*===============*/ - byte* buf, /*!< in: pointer to the start of + const byte* buf, /*!< in: pointer to the start of the log segment in the log_sys->buf log buffer */ ulint len, /*!< in: segment length in bytes */ ib_uint64_t buf_start_lsn); /*!< in: buffer start lsn */ +#endif /* UNIV_LOG_DEBUG */ /************************************************************//** Gets a log block flush bit. @@ -305,55 +307,76 @@ UNIV_INLINE ib_uint64_t log_reserve_and_write_fast( /*=======================*/ - byte* str, /*!< in: string */ + const void* str, /*!< in: string */ ulint len, /*!< in: string length */ - ib_uint64_t* start_lsn,/*!< out: start lsn of the log record */ - ibool* success)/*!< out: TRUE if success */ + ib_uint64_t* start_lsn)/*!< out: start lsn of the log record */ { - log_t* log = log_sys; ulint data_len; - ib_uint64_t lsn; +#ifdef UNIV_LOG_LSN_DEBUG + /* length of the LSN pseudo-record */ + ulint lsn_len = 1 + + mach_get_compressed_size(log_sys->lsn >> 32) + + mach_get_compressed_size(log_sys->lsn & 0xFFFFFFFFUL); +#endif /* UNIV_LOG_LSN_DEBUG */ - *success = TRUE; + mutex_enter(&log_sys->mutex); - mutex_enter(&(log->mutex)); - - data_len = len + log->buf_free % OS_FILE_LOG_BLOCK_SIZE; + data_len = len +#ifdef UNIV_LOG_LSN_DEBUG + + lsn_len +#endif /* UNIV_LOG_LSN_DEBUG */ + + log_sys->buf_free % OS_FILE_LOG_BLOCK_SIZE; if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { /* The string does not fit within the current log block or the log block would become full */ - *success = FALSE; - - mutex_exit(&(log->mutex)); + mutex_exit(&log_sys->mutex); return(0); } - *start_lsn = log->lsn; + *start_lsn = log_sys->lsn; - ut_memcpy(log->buf + log->buf_free, str, len); +#ifdef UNIV_LOG_LSN_DEBUG + { + /* Write the LSN pseudo-record. */ + byte* b = &log_sys->buf[log_sys->buf_free]; + *b++ = MLOG_LSN | (MLOG_SINGLE_REC_FLAG & *(const byte*) str); + /* Write the LSN in two parts, + as a pseudo page number and space id. */ + b += mach_write_compressed(b, log_sys->lsn >> 32); + b += mach_write_compressed(b, log_sys->lsn & 0xFFFFFFFFUL); + ut_a(b - lsn_len == &log_sys->buf[log_sys->buf_free]); - log_block_set_data_len((byte*) ut_align_down(log->buf + log->buf_free, + memcpy(b, str, len); + len += lsn_len; + } +#else /* UNIV_LOG_LSN_DEBUG */ + memcpy(log_sys->buf + log_sys->buf_free, str, len); +#endif /* UNIV_LOG_LSN_DEBUG */ + + log_block_set_data_len((byte*) ut_align_down(log_sys->buf + + log_sys->buf_free, OS_FILE_LOG_BLOCK_SIZE), data_len); #ifdef UNIV_LOG_DEBUG - log->old_buf_free = log->buf_free; - log->old_lsn = log->lsn; + log_sys->old_buf_free = log_sys->buf_free; + log_sys->old_lsn = log_sys->lsn; #endif - log->buf_free += len; + log_sys->buf_free += len; - ut_ad(log->buf_free <= log->buf_size); + ut_ad(log_sys->buf_free <= log_sys->buf_size); - lsn = log->lsn += len; + log_sys->lsn += len; #ifdef UNIV_LOG_DEBUG - log_check_log_recs(log->buf + log->old_buf_free, - log->buf_free - log->old_buf_free, log->old_lsn); + log_check_log_recs(log_sys->buf + log_sys->old_buf_free, + log_sys->buf_free - log_sys->old_buf_free, + log_sys->old_lsn); #endif - return(lsn); + return(log_sys->lsn); } /***********************************************************************//** diff --git a/include/log0recv.h b/include/log0recv.h index 8468c213bdb..ac6b19a3f6a 100644 --- a/include/log0recv.h +++ b/include/log0recv.h @@ -239,6 +239,18 @@ UNIV_INTERN void recv_sys_create(void); /*=================*/ +/**********************************************************//** +Release recovery system mutexes. */ +UNIV_INTERN +void +recv_sys_close(void); +/*================*/ +/********************************************************//** +Frees the recovery system memory. */ +UNIV_INTERN +void +recv_sys_mem_free(void); +/*===================*/ /********************************************************//** Inits the recovery system for a recovery operation. */ UNIV_INTERN @@ -246,6 +258,12 @@ void recv_sys_init( /*==========*/ ulint available_memory); /*!< in: available memory in bytes */ +/********************************************************//** +Reset the state of the recovery system variables. */ +UNIV_INTERN +void +recv_sys_var_init(void); +/*===================*/ /*******************************************************************//** Empties the hash table of stored log records, applying them to appropriate pages. */ @@ -412,6 +430,39 @@ struct recv_sys_struct{ hash_table_t* addr_hash;/*!< hash table of file addresses of pages */ ulint n_addrs;/*!< number of not processed hashed file addresses in the hash table */ + +/* If you modified the following defines at original file, + You should also modify them. */ +/* defined in os0file.c */ +#define OS_AIO_MERGE_N_CONSECUTIVE 64 +/* defined in log0recv.c */ +#define RECV_READ_AHEAD_AREA 32 + time_t stats_recv_start_time; + ulint stats_recv_turns; + + ulint stats_read_requested_pages; + ulint stats_read_in_area[RECV_READ_AHEAD_AREA]; + + ulint stats_read_io_pages; + ulint stats_read_io_consecutive[OS_AIO_MERGE_N_CONSECUTIVE]; + ulint stats_write_io_pages; + ulint stats_write_io_consecutive[OS_AIO_MERGE_N_CONSECUTIVE]; + + ulint stats_doublewrite_check_pages; + ulint stats_doublewrite_overwrite_pages; + + ulint stats_recover_pages_with_read; + ulint stats_recover_pages_without_read; + + ulint stats_log_recs; + ulint stats_log_len_sum; + + ulint stats_applied_log_recs; + ulint stats_applied_log_len_sum; + ulint stats_pages_already_new; + + ib_uint64_t stats_oldest_modified_lsn; + ib_uint64_t stats_newest_modified_lsn; }; /** The recovery system */ @@ -433,6 +484,11 @@ are allowed yet: the variable name is misleading. */ extern ibool recv_no_ibuf_operations; /** TRUE when recv_init_crash_recovery() has been called. */ extern ibool recv_needed_recovery; +#ifdef UNIV_DEBUG +/** TRUE if writing to the redo log (mtr_commit) is forbidden. +Protected by log_sys->mutex. */ +extern ibool recv_no_log_write; +#endif /* UNIV_DEBUG */ /** TRUE if buf_page_is_corrupted() should check if the log sequence number (FIL_PAGE_LSN) is in the future. Initially FALSE, and set by diff --git a/include/mem0mem.h b/include/mem0mem.h index a092b024219..98f8748e529 100644 --- a/include/mem0mem.h +++ b/include/mem0mem.h @@ -82,6 +82,13 @@ void mem_init( /*=====*/ ulint size); /*!< in: common pool size in bytes */ +/******************************************************************//** +Closes the memory system. */ +UNIV_INTERN +void +mem_close(void); +/*===========*/ + /**************************************************************//** Use this macro instead of the corresponding function! Macro for memory heap creation. */ diff --git a/include/mem0pool.h b/include/mem0pool.h index 18f988241d6..5e93bf88a47 100644 --- a/include/mem0pool.h +++ b/include/mem0pool.h @@ -62,6 +62,13 @@ mem_pool_create( /*============*/ ulint size); /*!< in: pool size in bytes */ /********************************************************************//** +Frees a memory pool. */ +UNIV_INTERN +void +mem_pool_free( +/*==========*/ + mem_pool_t* pool); /*!< in, own: memory pool */ +/********************************************************************//** Allocates memory from a pool. NOTE: This low-level function should only be used in mem0mem.*! @return own: allocated memory buffer */ diff --git a/include/mtr0mtr.h b/include/mtr0mtr.h index 69a2c03f4cb..bc3f1951be9 100644 --- a/include/mtr0mtr.h +++ b/include/mtr0mtr.h @@ -106,6 +106,9 @@ For 1 - 8 bytes, the flag value must give the length also! @{ */ #define MLOG_IBUF_BITMAP_INIT ((byte)27) /*!< initialize an ibuf bitmap page */ /*#define MLOG_FULL_PAGE ((byte)28) full contents of a page */ +#ifdef UNIV_LOG_LSN_DEBUG +# define MLOG_LSN ((byte)28) /* current LSN */ +#endif #define MLOG_INIT_FILE_PAGE ((byte)29) /*!< this means that a file page is taken into use and the prior @@ -118,7 +121,7 @@ For 1 - 8 bytes, the flag value must give the length also! @{ */ #define MLOG_WRITE_STRING ((byte)30) /*!< write a string to a page */ #define MLOG_MULTI_REC_END ((byte)31) /*!< if a single mtr writes - log records for several pages, + several log records, this log record ends the sequence of these records */ #define MLOG_DUMMY_RECORD ((byte)32) /*!< dummy log record used to diff --git a/include/os0file.h b/include/os0file.h index 4dda4476d9e..3eff5216867 100644 --- a/include/os0file.h +++ b/include/os0file.h @@ -158,6 +158,8 @@ log. */ to become available again */ #define OS_FILE_SHARING_VIOLATION 76 #define OS_FILE_ERROR_NOT_SPECIFIED 77 +#define OS_FILE_INSUFFICIENT_RESOURCE 78 +#define OS_FILE_OPERATION_ABORTED 79 /* @} */ /** Types for aio operations @{ */ @@ -624,6 +626,13 @@ os_aio_init( ulint n_write_segs, /*= 10 use Solaris atomics */ -#elif defined(HAVE_SOLARIS_ATOMICS) + #include + /**********************************************************//** Returns true if swapped, ptr is pointer to target, old_val is value to compare to, new_val is the value to swap in. */ + # define os_compare_and_swap_ulint(ptr, old_val, new_val) \ (atomic_cas_ulong(ptr, old_val, new_val) == old_val) + # define os_compare_and_swap_lint(ptr, old_val, new_val) \ ((lint)atomic_cas_ulong((ulong_t*) ptr, old_val, new_val) == old_val) -# ifdef INNODB_RW_LOCKS_USE_ATOMICS -# if SIZEOF_PTHREAD_T == 4 + +# ifdef HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS +# if SIZEOF_PTHREAD_T == 4 # define os_compare_and_swap_thread_id(ptr, old_val, new_val) \ ((pthread_t)atomic_cas_32(ptr, old_val, new_val) == old_val) # elif SIZEOF_PTHREAD_T == 8 @@ -331,21 +361,35 @@ compare to, new_val is the value to swap in. */ # else # error "SIZEOF_PTHREAD_T != 4 or 8" # endif /* SIZEOF_PTHREAD_T CHECK */ -# endif /* INNODB_RW_LOCKS_USE_ATOMICS */ +# define INNODB_RW_LOCKS_USE_ATOMICS +# define IB_ATOMICS_STARTUP_MSG \ + "Mutexes and rw_locks use Solaris atomic functions" +# else /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */ +# define IB_ATOMICS_STARTUP_MSG \ + "Mutexes use Solaris atomic functions, rw_locks do not" +# endif /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */ /**********************************************************//** Returns the resulting value, ptr is pointer to target, amount is the amount of increment. */ + # define os_atomic_increment_lint(ptr, amount) \ atomic_add_long_nv((ulong_t*) ptr, amount) + # define os_atomic_increment_ulint(ptr, amount) \ atomic_add_long_nv(ptr, amount) + /**********************************************************//** Returns the old value of *ptr, atomically sets *ptr to new_val */ + # define os_atomic_test_and_set_byte(ptr, new_val) \ atomic_swap_uchar(ptr, new_val) -/* On Windows, use Windows atomics / interlocked */ + #elif defined(HAVE_WINDOWS_ATOMICS) + +#define HAVE_ATOMIC_BUILTINS + +/* On Windows, use Windows atomics / interlocked */ # ifdef _WIN64 # define win_cmp_and_xchg InterlockedCompareExchange64 # define win_xchg_and_add InterlockedExchangeAdd64 @@ -353,31 +397,46 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */ # define win_cmp_and_xchg InterlockedCompareExchange # define win_xchg_and_add InterlockedExchangeAdd # endif + /**********************************************************//** Returns true if swapped, ptr is pointer to target, old_val is value to compare to, new_val is the value to swap in. */ + # define os_compare_and_swap_ulint(ptr, old_val, new_val) \ (win_cmp_and_xchg(ptr, new_val, old_val) == old_val) + # define os_compare_and_swap_lint(ptr, old_val, new_val) \ (win_cmp_and_xchg(ptr, new_val, old_val) == old_val) -# ifdef INNODB_RW_LOCKS_USE_ATOMICS -# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \ + +/* windows thread objects can always be passed to windows atomic functions */ +# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \ (InterlockedCompareExchange(ptr, new_val, old_val) == old_val) -# endif /* INNODB_RW_LOCKS_USE_ATOMICS */ +# define INNODB_RW_LOCKS_USE_ATOMICS +# define IB_ATOMICS_STARTUP_MSG \ + "Mutexes and rw_locks use Windows interlocked functions" + /**********************************************************//** Returns the resulting value, ptr is pointer to target, amount is the amount of increment. */ + # define os_atomic_increment_lint(ptr, amount) \ (win_xchg_and_add(ptr, amount) + amount) + # define os_atomic_increment_ulint(ptr, amount) \ ((ulint) (win_xchg_and_add(ptr, amount) + amount)) + /**********************************************************//** Returns the old value of *ptr, atomically sets *ptr to new_val. InterlockedExchange() operates on LONG, and the LONG will be clobbered */ + # define os_atomic_test_and_set_byte(ptr, new_val) \ ((byte) InterlockedExchange(ptr, new_val)) -#endif /* HAVE_GCC_ATOMIC_BUILTINS */ + +#else +# define IB_ATOMICS_STARTUP_MSG \ + "Mutexes and rw_locks use InnoDB's own implementation" +#endif #ifndef UNIV_NONINL #include "os0sync.ic" diff --git a/include/page0page.h b/include/page0page.h index a4fe069d022..3899499fb6a 100644 --- a/include/page0page.h +++ b/include/page0page.h @@ -76,8 +76,11 @@ typedef byte page_header_t; header which are set in a page create */ /*----*/ #define PAGE_LEVEL 26 /* level of the node in an index tree; the - leaf level is the level 0 */ -#define PAGE_INDEX_ID 28 /* index id where the page belongs */ + leaf level is the level 0. This field should + not be written to after page creation. */ +#define PAGE_INDEX_ID 28 /* index id where the page belongs. + This field should not be written to after + page creation. */ #define PAGE_BTR_SEG_LEAF 36 /* file segment header for the leaf pages in a B-tree: defined only on the root page of a B-tree, but not in the root of an ibuf tree */ diff --git a/include/page0page.ic b/include/page0page.ic index 318ec1cc1f2..8f794410f20 100644 --- a/include/page0page.ic +++ b/include/page0page.ic @@ -907,7 +907,7 @@ page_get_data_size( /************************************************************//** Allocates a block of memory from the free list of an index page. */ -UNIV_INTERN +UNIV_INLINE void page_mem_alloc_free( /*================*/ diff --git a/include/page0zip.h b/include/page0zip.h index 9aaa066306b..574809e5227 100644 --- a/include/page0zip.h +++ b/include/page0zip.h @@ -127,8 +127,12 @@ page_zip_decompress( /*================*/ page_zip_des_t* page_zip,/*!< in: data, ssize; out: m_start, m_end, m_nonempty, n_blobs */ - page_t* page) /*!< out: uncompressed page, may be trashed */ - __attribute__((nonnull)); + page_t* page, /*!< out: uncompressed page, may be trashed */ + ibool all) /*!< in: TRUE=decompress the whole page; + FALSE=verify but do not copy some + page header fields that should not change + after page creation */ + __attribute__((nonnull(1,2))); #ifdef UNIV_DEBUG /**********************************************************************//** @@ -385,8 +389,8 @@ IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a non-clustered index, the caller must update the insert buffer free bits in the same mini-transaction in such a way that the modification will be redo-logged. -@return TRUE on success, FALSE on failure; page and page_zip will be -left intact on failure. */ +@return TRUE on success, FALSE on failure; page_zip will be left +intact on failure, but page will be overwritten. */ UNIV_INTERN ibool page_zip_reorganize( diff --git a/include/pars0pars.h b/include/pars0pars.h index a7de7f2292e..fe5d76ebbb0 100644 --- a/include/pars0pars.h +++ b/include/pars0pars.h @@ -583,6 +583,12 @@ pars_info_get_bound_id( pars_info_t* info, /*!< in: info struct */ const char* name); /*!< in: bound id name to find */ +/******************************************************************//** +Release any resources used by the lexer. */ +UNIV_INTERN +void +pars_lexer_close(void); +/*==================*/ /** Extra information supplied for pars_sql(). */ struct pars_info_struct { diff --git a/include/rem0cmp.h b/include/rem0cmp.h index 9d2950bbb01..421308af49b 100644 --- a/include/rem0cmp.h +++ b/include/rem0cmp.h @@ -89,7 +89,7 @@ cmp_dfield_dfield( /*************************************************************//** This function is used to compare a data tuple to a physical record. Only dtuple->n_fields_cmp first fields are taken into account for -the the data tuple! If we denote by n = n_fields_cmp, then rec must +the data tuple! If we denote by n = n_fields_cmp, then rec must have either m >= n fields, or it must differ from dtuple in some of the m fields rec has. If rec has an externally stored field we do not compare it but return with value 0 if such a comparison should be diff --git a/include/rem0rec.ic b/include/rem0rec.ic index 9fe736f9b0b..8e5bd9a7fcd 100644 --- a/include/rem0rec.ic +++ b/include/rem0rec.ic @@ -65,7 +65,7 @@ most significant bytes and bits are written below less significant. - offset_of_this_record) mod 64Ki, where mod is the modulo as a non-negative number; - we can calculate the the offset of the next + we can calculate the offset of the next record with the formula: relative_offset + offset_of_this_record mod UNIV_PAGE_SIZE diff --git a/include/row0ins.h b/include/row0ins.h index 530622e6225..9f93565ddb7 100644 --- a/include/row0ins.h +++ b/include/row0ins.h @@ -45,7 +45,7 @@ row_ins_check_foreign_constraint( /*=============================*/ ibool check_ref,/*!< in: TRUE If we want to check that the referenced table is ok, FALSE if we - want to to check the foreign key table */ + want to check the foreign key table */ dict_foreign_t* foreign,/*!< in: foreign constraint; NOTE that the tables mentioned in it must be in the dictionary cache if they exist at all */ diff --git a/include/row0mysql.h b/include/row0mysql.h index 97028622505..b05241f00f8 100644 --- a/include/row0mysql.h +++ b/include/row0mysql.h @@ -177,7 +177,9 @@ row_update_prebuilt_trx( in MySQL handle */ trx_t* trx); /*!< in: transaction handle */ /*********************************************************************//** -Unlocks AUTO_INC type locks that were possibly reserved by a trx. */ +Unlocks AUTO_INC type locks that were possibly reserved by a trx. This +function should be called at the the end of an SQL statement, by the +connection thread that owns the transaction (trx->mysql_thd). */ UNIV_INTERN void row_unlock_table_autoinc_for_mysql( @@ -754,8 +756,6 @@ struct row_prebuilt_struct { store it here so that we can return it to MySQL */ /*----------------------*/ - UT_LIST_NODE_T(row_prebuilt_t) prebuilts; - /*!< list node of table->prebuilts */ ulint magic_n2; /*!< this should be the same as magic_n */ }; diff --git a/include/srv0srv.h b/include/srv0srv.h index 4700ca11f7a..ee8ce669b1e 100644 --- a/include/srv0srv.h +++ b/include/srv0srv.h @@ -136,6 +136,7 @@ extern ulint* srv_data_file_is_raw_partition; extern ibool srv_extra_undoslots; extern ibool srv_fast_recovery; +extern ibool srv_recovery_stats; extern ulint srv_use_purge_thread; @@ -238,12 +239,14 @@ extern ulong srv_replication_delay; extern long long srv_ibuf_max_size; extern ulint srv_ibuf_active_contract; extern ulint srv_ibuf_accel_rate; +extern ulint srv_checkpoint_age_target; extern ulint srv_flush_neighbor_pages; extern ulint srv_enable_unsafe_group_commit; extern ulint srv_read_ahead; extern ulint srv_adaptive_checkpoint; extern ulint srv_expand_import; +extern ulint srv_relax_table_creation; extern ulint srv_extra_rsegments; extern ulint srv_dict_size_limit; @@ -348,10 +351,6 @@ extern ulint srv_buf_pool_flushed; /** Number of buffer pool reads that led to the reading of a disk page */ extern ulint srv_buf_pool_reads; -/** Number of sequential read-aheads */ -extern ulint srv_read_ahead_seq; -/** Number of random read-aheads */ -extern ulint srv_read_ahead_rnd; /** Status variables to be passed to MySQL */ typedef struct export_var_struct export_struc; @@ -450,7 +449,7 @@ void srv_init(void); /*==========*/ /*********************************************************************//** -Frees the OS fast mutex created in srv_boot(). */ +Frees the data structures created in srv_init(). */ UNIV_INTERN void srv_free(void); @@ -656,13 +655,13 @@ struct export_var_struct{ #ifdef UNIV_DEBUG ulint innodb_buffer_pool_pages_latched; /*!< Latched pages */ #endif /* UNIV_DEBUG */ - ulint innodb_buffer_pool_read_requests; /*!< buf_pool->n_page_gets */ + ulint innodb_buffer_pool_read_requests; /*!< buf_pool->stat.n_page_gets */ ulint innodb_buffer_pool_reads; /*!< srv_buf_pool_reads */ ulint innodb_buffer_pool_wait_free; /*!< srv_buf_pool_wait_free */ ulint innodb_buffer_pool_pages_flushed; /*!< srv_buf_pool_flushed */ ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */ - ulint innodb_buffer_pool_read_ahead_seq;/*!< srv_read_ahead_seq */ - ulint innodb_buffer_pool_read_ahead_rnd;/*!< srv_read_ahead_rnd */ + ulint innodb_buffer_pool_read_ahead; /*!< srv_read_ahead */ + ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/ ulint innodb_dblwr_pages_written; /*!< srv_dblwr_pages_written */ ulint innodb_dblwr_writes; /*!< srv_dblwr_writes */ ibool innodb_have_atomic_builtins; /*!< HAVE_ATOMIC_BUILTINS */ @@ -674,9 +673,9 @@ struct export_var_struct{ ulint innodb_os_log_pending_writes; /*!< srv_os_log_pending_writes */ ulint innodb_os_log_pending_fsyncs; /*!< fil_n_pending_log_flushes */ ulint innodb_page_size; /*!< UNIV_PAGE_SIZE */ - ulint innodb_pages_created; /*!< buf_pool->n_pages_created */ - ulint innodb_pages_read; /*!< buf_pool->n_pages_read */ - ulint innodb_pages_written; /*!< buf_pool->n_pages_written */ + ulint innodb_pages_created; /*!< buf_pool->stat.n_pages_created */ + ulint innodb_pages_read; /*!< buf_pool->stat.n_pages_read */ + ulint innodb_pages_written; /*!< buf_pool->stat.n_pages_written */ ulint innodb_row_lock_waits; /*!< srv_n_lock_wait_count */ ulint innodb_row_lock_current_waits; /*!< srv_n_lock_wait_current_count */ ib_int64_t innodb_row_lock_time; /*!< srv_n_lock_wait_time diff --git a/include/sync0sync.h b/include/sync0sync.h index a6697638081..c653e44b5bd 100644 --- a/include/sync0sync.h +++ b/include/sync0sync.h @@ -513,7 +513,7 @@ struct mutex_struct { os_fast_mutex; /*!< We use this OS mutex in place of lock_word when atomic operations are not enabled */ #endif - ulint waiters; /*!< This ulint is set to 1 if there are (or + volatile ulint waiters; /*!< This ulint is set to 1 if there are (or may be) threads waiting in the global wait array for this mutex to be released. Otherwise, this is 0. */ diff --git a/include/thr0loc.h b/include/thr0loc.h index 34c5232238d..293d1ebd57f 100644 --- a/include/thr0loc.h +++ b/include/thr0loc.h @@ -39,6 +39,12 @@ UNIV_INTERN void thr_local_init(void); /*================*/ + /****************************************************************//** +Close the thread local storage module. */ +UNIV_INTERN +void +thr_local_close(void); +/*=================*/ /*******************************************************************//** Creates a local storage struct for the calling new thread. */ UNIV_INTERN diff --git a/include/trx0i_s.h b/include/trx0i_s.h index 9bf032de9f9..7bd4e1b88c8 100644 --- a/include/trx0i_s.h +++ b/include/trx0i_s.h @@ -141,6 +141,13 @@ void trx_i_s_cache_init( /*===============*/ trx_i_s_cache_t* cache); /*!< out: cache to init */ +/*******************************************************************//** +Free the INFORMATION SCHEMA trx related cache. */ +UNIV_INTERN +void +trx_i_s_cache_free( +/*===============*/ + trx_i_s_cache_t* cache); /*!< in/out: cache to free */ /*******************************************************************//** Issue a shared/read lock on the tables cache. */ diff --git a/include/trx0purge.h b/include/trx0purge.h index d9a470f4036..ae5bc6f90be 100644 --- a/include/trx0purge.h +++ b/include/trx0purge.h @@ -71,6 +71,12 @@ void trx_purge_sys_create(void); /*======================*/ /********************************************************************//** +Frees the global purge system control structure. */ +UNIV_INTERN +void +trx_purge_sys_close(void); +/*======================*/ +/************************************************************************ Adds the update undo log as the first log in the history list. Removes the update undo log segment from the rseg slot if it is too big for reuse. */ UNIV_INTERN diff --git a/include/trx0rec.h b/include/trx0rec.h index 0ae82c33afe..a6e56e963c6 100644 --- a/include/trx0rec.h +++ b/include/trx0rec.h @@ -44,8 +44,8 @@ UNIV_INLINE trx_undo_rec_t* trx_undo_rec_copy( /*==============*/ - trx_undo_rec_t* undo_rec, /*!< in: undo log record */ - mem_heap_t* heap); /*!< in: heap where copied */ + const trx_undo_rec_t* undo_rec, /*!< in: undo log record */ + mem_heap_t* heap); /*!< in: heap where copied */ /**********************************************************************//** Reads the undo log record type. @return record type */ diff --git a/include/trx0rec.ic b/include/trx0rec.ic index 037b5d4f6cf..e7e41d6d9f6 100644 --- a/include/trx0rec.ic +++ b/include/trx0rec.ic @@ -100,8 +100,8 @@ UNIV_INLINE trx_undo_rec_t* trx_undo_rec_copy( /*==============*/ - trx_undo_rec_t* undo_rec, /*!< in: undo log record */ - mem_heap_t* heap) /*!< in: heap where copied */ + const trx_undo_rec_t* undo_rec, /*!< in: undo log record */ + mem_heap_t* heap) /*!< in: heap where copied */ { ulint len; diff --git a/include/trx0roll.h b/include/trx0roll.h index ddca9e9e4ef..1dee5655c8c 100644 --- a/include/trx0roll.h +++ b/include/trx0roll.h @@ -133,6 +133,17 @@ trx_rollback( Rollback or clean up any incomplete transactions which were encountered in crash recovery. If the transaction already was committed, then we clean up a possible insert undo log. If the +transaction was not yet committed, then we roll it back. */ +UNIV_INTERN +void +trx_rollback_or_clean_recovered( +/*============================*/ + ibool all); /*!< in: FALSE=roll back dictionary transactions; + TRUE=roll back all non-PREPARED transactions */ +/*******************************************************************//** +Rollback or clean up any incomplete transactions which were +encountered in crash recovery. If the transaction already was +committed, then we clean up a possible insert undo log. If the transaction was not yet committed, then we roll it back. Note: this is done in a background thread. @return a dummy parameter */ @@ -208,9 +219,9 @@ int trx_general_rollback_for_mysql( /*===========================*/ trx_t* trx, /*!< in: transaction handle */ - ibool partial,/*!< in: TRUE if partial rollback requested */ trx_savept_t* savept);/*!< in: pointer to savepoint undo number, if - partial rollback requested */ + partial rollback requested, or NULL for + complete rollback */ /*******************************************************************//** Rolls back a transaction back to a named savepoint. Modifications after the savepoint are undone but InnoDB does NOT release the corresponding locks diff --git a/include/trx0rseg.h b/include/trx0rseg.h index f0f7a47279e..0d7dc60329f 100644 --- a/include/trx0rseg.h +++ b/include/trx0rseg.h @@ -125,6 +125,13 @@ trx_rseg_create( ulint max_size, /*!< in: max size in pages */ ulint* id, /*!< out: rseg id */ mtr_t* mtr); /*!< in: mtr */ +/*************************************************************************** +Free's an instance of the rollback segment in memory. */ +UNIV_INTERN +void +trx_rseg_mem_free( +/*==============*/ + trx_rseg_t* rseg); /* in, own: instance to free */ /* Real max value may be 4076 in usual. But reserve 4 slot for safety or etc... */ diff --git a/include/trx0sys.h b/include/trx0sys.h index 1f3f11926f8..8789d575bca 100644 --- a/include/trx0sys.h +++ b/include/trx0sys.h @@ -344,6 +344,12 @@ void trx_sys_file_format_tag_init(void); /*==============================*/ /*****************************************************************//** +Shutdown/Close the transaction system. */ +UNIV_INTERN +void +trx_sys_close(void); +/*===============*/ +/*****************************************************************//** Get the name representation of the file format from its id. @return pointer to the name */ UNIV_INTERN diff --git a/include/trx0sys.ic b/include/trx0sys.ic index 1c7c732751b..820d31d0692 100644 --- a/include/trx0sys.ic +++ b/include/trx0sys.ic @@ -34,11 +34,11 @@ typedef byte trx_sysf_rseg_t; /* Rollback segment specification slot offsets */ /*-------------------------------------------------------------*/ -#define TRX_SYS_RSEG_SPACE 0 /* space where the the segment +#define TRX_SYS_RSEG_SPACE 0 /* space where the segment header is placed; starting with MySQL/InnoDB 5.1.7, this is UNIV_UNDEFINED if the slot is unused */ -#define TRX_SYS_RSEG_PAGE_NO 4 /* page number where the the segment +#define TRX_SYS_RSEG_PAGE_NO 4 /* page number where the segment header is placed; this is FIL_NULL if the slot is unused */ /*-------------------------------------------------------------*/ diff --git a/include/trx0trx.h b/include/trx0trx.h index 2d8987284e5..3b845e498d0 100644 --- a/include/trx0trx.h +++ b/include/trx0trx.h @@ -179,7 +179,7 @@ trx_commit_off_kernel( /****************************************************************//** Cleans up a transaction at database startup. The cleanup is needed if the transaction already got to the middle of a commit when the database -crashed, andf we cannot roll it back. */ +crashed, and we cannot roll it back. */ UNIV_INTERN void trx_cleanup_at_db_startup( @@ -360,7 +360,7 @@ enum trx_dict_op { operation modes in crash recovery. */ TRX_DICT_OP_TABLE = 1, /** The transaction is creating or dropping an index in an - existing table. In crash recovery, the the data dictionary + existing table. In crash recovery, the data dictionary must be locked, but the table must not be dropped. */ TRX_DICT_OP_INDEX = 2 }; diff --git a/include/trx0types.h b/include/trx0types.h index 08cc9622d02..24cf57d53d5 100644 --- a/include/trx0types.h +++ b/include/trx0types.h @@ -70,7 +70,7 @@ typedef struct trx_named_savept_struct trx_named_savept_t; enum trx_rb_ctx { RB_NONE = 0, /*!< no rollback */ RB_NORMAL, /*!< normal rollback */ - RB_RECOVERY, /*!< rolling back an incomplete transaction, + RB_RECOVERY /*!< rolling back an incomplete transaction, in crash recovery */ }; diff --git a/include/trx0undo.h b/include/trx0undo.h index 4db10eaa92e..a084f2394b5 100644 --- a/include/trx0undo.h +++ b/include/trx0undo.h @@ -333,6 +333,13 @@ trx_undo_parse_discard_latest( byte* end_ptr,/*!< in: buffer end */ page_t* page, /*!< in: page or NULL */ mtr_t* mtr); /*!< in: mtr or NULL */ +/************************************************************************ +Frees an undo log memory copy. */ +UNIV_INTERN +void +trx_undo_mem_free( +/*==============*/ + trx_undo_t* undo); /* in: the undo object to be freed */ /* Types of an undo log segment */ #define TRX_UNDO_INSERT 1 /* contains undo entries for inserts */ diff --git a/include/univ.i b/include/univ.i index 19ef867eeb8..f002215d7b6 100644 --- a/include/univ.i +++ b/include/univ.i @@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 1 #define INNODB_VERSION_MINOR 0 -#define INNODB_VERSION_BUGFIX 4 +#define INNODB_VERSION_BUGFIX 6 #ifndef PERCONA_INNODB_VERSION #define PERCONA_INNODB_VERSION unknown @@ -55,7 +55,7 @@ Created 1/20/1994 Heikki Tuuri /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; -calculated in in make_version_string() in sql/sql_show.cc like this: +calculated in make_version_string() in sql/sql_show.cc like this: "version >> 8" . "version & 0xff" because the version is shown with only one dot, we skip the last component, i.e. we show M.N.P as M.N */ @@ -71,7 +71,7 @@ component, i.e. we show M.N.P as M.N */ _INNODB_VERSION(INNODB_VERSION_MAJOR, \ INNODB_VERSION_MINOR, \ INNODB_VERSION_BUGFIX, \ - PERCONA_INNODB_VERSION) + PERCONA_INNODB_VERSION) #define REFMAN "http://dev.mysql.com/doc/refman/5.1/en/" @@ -85,17 +85,25 @@ the virtual method table (vtable) in GCC 3. */ # define ha_innobase ha_innodb #endif /* MYSQL_DYNAMIC_PLUGIN */ +/* if any of the following macros is defined at this point this means +that the code from the "right" plug.in was executed and we do not +need to include ut0auxconf.h which would either define the same macros +or will be empty */ +#if !defined(HAVE_IB_GCC_ATOMIC_BUILTINS) \ + && !defined(HAVE_IB_ATOMIC_PTHREAD_T_GCC) \ + && !defined(HAVE_IB_SOLARIS_ATOMICS) \ + && !defined(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS) \ + && !defined(SIZEOF_PTHREAD_T) \ + && !defined(HAVE_IB_PAUSE_INSTRUCTION) +# include "ut0auxconf.h" +#endif + #if (defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)) && !defined(MYSQL_SERVER) && !defined(__WIN__) # undef __WIN__ # define __WIN__ # include -# if defined(HAVE_WINDOWS_ATOMICS) -/* If atomics are defined we use them in InnoDB mutex implementation */ -# define HAVE_ATOMIC_BUILTINS -# endif /* HAVE_WINDOWS_ATOMICS */ - # ifdef _NT_ # define __NT__ # endif @@ -118,45 +126,17 @@ if we are compiling on Windows. */ # include /* mmap() for os0proc.c */ # endif -# undef PACKAGE -# undef VERSION - /* Include the header file generated by GNU autoconf */ # ifndef __WIN__ -#ifndef UNIV_HOTBACKUP -# include "config.h" -#endif /* UNIV_HOTBACKUP */ +# ifndef UNIV_HOTBACKUP +# include "config.h" +# endif /* UNIV_HOTBACKUP */ # endif # ifdef HAVE_SCHED_H # include # endif -# if defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_SOLARIS_ATOMICS) \ - || defined(HAVE_WINDOWS_ATOMICS) -/* If atomics are defined we use them in InnoDB mutex implementation */ -# define HAVE_ATOMIC_BUILTINS -# endif /* (HAVE_GCC_ATOMIC_BUILTINS) || (HAVE_SOLARIS_ATOMICS) - || (HAVE_WINDOWS_ATOMICS) */ - -/* For InnoDB rw_locks to work with atomics we need the thread_id -to be no more than machine word wide. The following enables using -atomics for InnoDB rw_locks where these conditions are met. */ -#ifdef HAVE_ATOMIC_BUILTINS -/* if HAVE_ATOMIC_PTHREAD_T is defined at this point that means that -the code from plug.in has defined it and we do not need to include -ut0auxconf.h which would either define HAVE_ATOMIC_PTHREAD_T or will -be empty */ -# ifndef HAVE_ATOMIC_PTHREAD_T -# include "ut0auxconf.h" -# endif /* HAVE_ATOMIC_PTHREAD_T */ -/* now HAVE_ATOMIC_PTHREAD_T is eventually defined either by plug.in or -from Makefile.in->ut0auxconf.h */ -# ifdef HAVE_ATOMIC_PTHREAD_T -# define INNODB_RW_LOCKS_USE_ATOMICS -# endif /* HAVE_ATOMIC_PTHREAD_T */ -#endif /* HAVE_ATOMIC_BUILTINS */ - /* We only try to do explicit inlining of functions with gcc and Sun Studio */ @@ -203,12 +183,18 @@ command. Not tested on Windows. */ debugging without UNIV_DEBUG */ #define UNIV_DEBUG /* Enable ut_ad() assertions and disable UNIV_INLINE */ +#define UNIV_DEBUG_LOCK_VALIDATE /* Enable + ut_ad(lock_rec_validate_page()) + assertions. */ #define UNIV_DEBUG_FILE_ACCESSES /* Debug .ibd file access (field file_page_was_freed in buf_page_t) */ #define UNIV_LRU_DEBUG /* debug the buffer pool LRU */ #define UNIV_HASH_DEBUG /* debug HASH_ macros */ #define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */ +#define UNIV_LOG_LSN_DEBUG /* write LSN to the redo log; +this will break redo log file compatibility, but it may be useful when +debugging redo log application problems. */ #define UNIV_MEM_DEBUG /* detect memory leaks etc */ #define UNIV_IBUF_DEBUG /* debug the insert buffer */ #define UNIV_IBUF_COUNT_DEBUG /* debug the insert buffer; @@ -258,7 +244,7 @@ by one. */ /* Linkage specifier for non-static InnoDB symbols (variables and functions) that are only referenced from within InnoDB, not from MySQL */ -#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(UNIV_HOTBACKUP) +#if defined(__GNUC__) && (__GNUC__ >= 4) || defined(__INTEL_COMPILER) # define UNIV_INTERN __attribute__((visibility ("hidden"))) #else # define UNIV_INTERN @@ -415,7 +401,9 @@ it is read. */ /* Minimize cache-miss latency by moving data at addr into a cache before it is read or written. */ # define UNIV_PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 3) -#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) +/* Sun Studio includes sun_prefetch.h as of version 5.9 */ +#elif (defined(__SUNPRO_C) && __SUNPRO_C >= 0x590) \ + || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590) # include #if __SUNPRO_C >= 0x550 # undef UNIV_INTERN diff --git a/include/usr0sess.h b/include/usr0sess.h index 7638a0c69e2..2c288f7d455 100644 --- a/include/usr0sess.h +++ b/include/usr0sess.h @@ -44,14 +44,12 @@ sess_t* sess_open(void); /*============*/ /*********************************************************************//** -Closes a session, freeing the memory occupied by it, if it is in a state -where it should be closed. -@return TRUE if closed */ +Closes a session, freeing the memory occupied by it. */ UNIV_INTERN -ibool -sess_try_close( -/*===========*/ - sess_t* sess); /*!< in, own: session object */ +void +sess_close( +/*=======*/ + sess_t* sess); /* in, own: session object */ /* The session handle. All fields are protected by the kernel mutex */ struct sess_struct{ diff --git a/include/ut0auxconf.h b/include/ut0auxconf.h index 88fb26f1863..16bcc308392 100644 --- a/include/ut0auxconf.h +++ b/include/ut0auxconf.h @@ -1,14 +1,14 @@ /* Do not remove this file even though it is empty. This file is included in univ.i and will cause compilation failure if not present. -A custom check has been added in the generated +A custom checks have been added in the generated storage/innobase/Makefile.in that is shipped with the InnoDB Plugin -source archive. This check tries to compile a test program and if -successful then adds "#define HAVE_ATOMIC_PTHREAD_T" to this file. -This is a hack that has been developed in order to check for pthread_t -atomicity without the need to regenerate the ./configure script that is +source archive. These checks eventually define some macros and put +them in this file. +This is a hack that has been developed in order to deploy new compile +time checks without the need to regenerate the ./configure script that is distributed in the MySQL 5.1 official source archives. If by any chance Makefile.in and ./configure are regenerated and thus -the hack from Makefile.in wiped away then the "real" check from plug.in +the hack from Makefile.in wiped away then the "real" checks from plug.in will take over. */ diff --git a/include/ut0byte.h b/include/ut0byte.h index a2687e62f08..f55e2888c60 100644 --- a/include/ut0byte.h +++ b/include/ut0byte.h @@ -219,8 +219,8 @@ UNIV_INLINE void* ut_align( /*=====*/ - void* ptr, /*!< in: pointer */ - ulint align_no); /*!< in: align by this number */ + const void* ptr, /*!< in: pointer */ + ulint align_no); /*!< in: align by this number */ /*********************************************************//** The following function rounds down a pointer to the nearest aligned address. diff --git a/include/ut0byte.ic b/include/ut0byte.ic index e3beed65138..3dd51890cb4 100644 --- a/include/ut0byte.ic +++ b/include/ut0byte.ic @@ -319,8 +319,8 @@ UNIV_INLINE void* ut_align( /*=====*/ - void* ptr, /*!< in: pointer */ - ulint align_no) /*!< in: align by this number */ + const void* ptr, /*!< in: pointer */ + ulint align_no) /*!< in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); diff --git a/include/ut0ut.h b/include/ut0ut.h index 80094321041..197b8401428 100644 --- a/include/ut0ut.h +++ b/include/ut0ut.h @@ -34,6 +34,11 @@ Created 1/20/1994 Heikki Tuuri #define ut0ut_h #include "univ.i" + +#ifndef UNIV_HOTBACKUP +# include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */ +#endif /* UNIV_HOTBACKUP */ + #include #ifndef MYSQL_SERVER #include @@ -47,7 +52,8 @@ Created 1/20/1994 Heikki Tuuri /** Time stamp */ typedef time_t ib_time_t; -#if defined(IB_HAVE_PAUSE_INSTRUCTION) +#ifndef UNIV_HOTBACKUP +#if defined(HAVE_IB_PAUSE_INSTRUCTION) # ifdef WIN32 /* In the Win32 API, the x86 PAUSE instruction is executed by calling the YieldProcessor macro defined in WinNT.h. It is a CPU architecture- @@ -84,6 +90,7 @@ do { \ os_thread_sleep(2000 /* 2 ms */); \ } \ } while (0) +#endif /* !UNIV_HOTBACKUP */ /********************************************************//** Gets the high 32 bits in a ulint. That is makes a shift >> 32, @@ -216,6 +223,7 @@ UNIV_INTERN ib_time_t ut_time(void); /*=========*/ +#ifndef UNIV_HOTBACKUP /**********************************************************//** Returns system time. Upon successful completion, the value 0 is returned; otherwise the @@ -239,6 +247,16 @@ ullint ut_time_us( /*=======*/ ullint* tloc); /*!< out: us since epoch, if non-NULL */ +/**********************************************************//** +Returns the number of milliseconds since some epoch. The +value may wrap around. It should only be used for heuristic +purposes. +@return ms since epoch */ +UNIV_INTERN +ulint +ut_time_ms(void); +/*============*/ +#endif /* !UNIV_HOTBACKUP */ /**********************************************************//** Returns the difference of two times in seconds. diff --git a/lock/lock0lock.c b/lock/lock0lock.c index ea414676b73..d1a37b13cd0 100644 --- a/lock/lock0lock.c +++ b/lock/lock0lock.c @@ -214,7 +214,7 @@ a waiting s-lock request on the next record? If this s-lock was placed by a read cursor moving in the ascending order in the index, we cannot do the insert immediately, because when we finally commit our transaction, the read cursor should see also the new inserted record. So we should -move the read cursor backward from the the next record for it to pass over +move the read cursor backward from the next record for it to pass over the new inserted record. This move backward may be too cumbersome to implement. If we in this situation just enqueue a second x-lock request for our transaction on the next record, then the deadlock mechanism @@ -360,10 +360,9 @@ ibool lock_rec_validate_page( /*===================*/ ulint space, /*!< in: space id */ + ulint zip_size,/*!< in: compressed page size in bytes + or 0 for uncompressed pages */ ulint page_no);/*!< in: page number */ - -/* Define the following in order to enable lock_rec_validate_page() checks. */ -# undef UNIV_DEBUG_LOCK_VALIDATE #endif /* UNIV_DEBUG */ /* The lock system */ @@ -578,6 +577,23 @@ lock_sys_create( ut_a(lock_latest_err_file); } +/*********************************************************************//** +Closes the lock system at database shutdown. */ +UNIV_INTERN +void +lock_sys_close(void) +/*================*/ +{ + if (lock_latest_err_file != NULL) { + fclose(lock_latest_err_file); + lock_latest_err_file = NULL; + } + + hash_table_free(lock_sys->rec_hash); + mem_free(lock_sys); + lock_sys = NULL; +} + /*********************************************************************//** Gets the size of a lock struct. @return size in bytes */ @@ -2628,6 +2644,7 @@ lock_move_reorganize_page( #ifdef UNIV_DEBUG_LOCK_VALIDATE ut_ad(lock_rec_validate_page(buf_block_get_space(block), + buf_block_get_zip_size(block), buf_block_get_page_no(block))); #endif } @@ -2717,8 +2734,10 @@ lock_move_rec_list_end( #ifdef UNIV_DEBUG_LOCK_VALIDATE ut_ad(lock_rec_validate_page(buf_block_get_space(block), + buf_block_get_zip_size(block), buf_block_get_page_no(block))); ut_ad(lock_rec_validate_page(buf_block_get_space(new_block), + buf_block_get_zip_size(block), buf_block_get_page_no(new_block))); #endif } @@ -2828,6 +2847,7 @@ lock_move_rec_list_start( #ifdef UNIV_DEBUG_LOCK_VALIDATE ut_ad(lock_rec_validate_page(buf_block_get_space(block), + buf_block_get_zip_size(block), buf_block_get_page_no(block))); #endif } @@ -3580,7 +3600,8 @@ lock_table_remove_low( and lock_grant()). Therefore it can be empty and we need to check for that. */ - if (!ib_vector_is_empty(trx->autoinc_locks)) { + if (!lock_get_wait(lock) + && !ib_vector_is_empty(trx->autoinc_locks)) { lock_t* autoinc_lock; autoinc_lock = ib_vector_pop(trx->autoinc_locks); @@ -3655,8 +3676,10 @@ lock_table_enqueue_waiting( if (lock_deadlock_occurs(lock, trx)) { - lock_reset_lock_and_trx_wait(lock); + /* The order here is important, we don't want to + lose the state of the lock before calling remove. */ lock_table_remove_low(lock); + lock_reset_lock_and_trx_wait(lock); return(DB_DEADLOCK); } @@ -4639,6 +4662,10 @@ lock_rec_queue_validate( next function call: we have to release lock table mutex to obey the latching order */ + /* If this thread is holding the file space latch + (fil_space_t::latch), the following check WILL break + latching order and may cause a deadlock of threads. */ + impl_trx = lock_sec_rec_some_has_impl_off_kernel( rec, index, offsets); @@ -4696,6 +4723,8 @@ ibool lock_rec_validate_page( /*===================*/ ulint space, /*!< in: space id */ + ulint zip_size,/*!< in: compressed page size in bytes + or 0 for uncompressed pages */ ulint page_no)/*!< in: page number */ { dict_index_t* index; @@ -4706,7 +4735,6 @@ lock_rec_validate_page( ulint nth_lock = 0; ulint nth_bit = 0; ulint i; - ulint zip_size; mtr_t mtr; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; @@ -4717,7 +4745,6 @@ lock_rec_validate_page( mtr_start(&mtr); - zip_size = fil_space_get_zip_size(space); ut_ad(zip_size != ULINT_UNDEFINED); block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, &mtr); buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); @@ -4762,6 +4789,11 @@ loop: lock_mutex_exit_kernel(); + /* If this thread is holding the file space + latch (fil_space_t::latch), the following + check WILL break the latching order and may + cause a deadlock of threads. */ + lock_rec_queue_validate(block, rec, index, offsets); lock_mutex_enter_kernel(); @@ -4852,7 +4884,9 @@ lock_validate(void) lock_mutex_exit_kernel(); - lock_rec_validate_page(space, page_no); + lock_rec_validate_page(space, + fil_space_get_zip_size(space), + page_no); lock_mutex_enter_kernel(); @@ -5375,6 +5409,20 @@ lock_release_autoinc_last_lock( lock_table_dequeue(lock); } +/*******************************************************************//** +Check if a transaction holds any autoinc locks. +@return TRUE if the transaction holds any AUTOINC locks. */ +UNIV_INTERN +ibool +lock_trx_holds_autoinc_locks( +/*=========================*/ + const trx_t* trx) /*!< in: transaction */ +{ + ut_a(trx->autoinc_locks != NULL); + + return(!ib_vector_is_empty(trx->autoinc_locks)); +} + /*******************************************************************//** Release all the transaction's autoinc locks. */ UNIV_INTERN diff --git a/log/log0log.c b/log/log0log.c index 09956bff215..5d54b75b725 100644 --- a/log/log0log.c +++ b/log/log0log.c @@ -241,6 +241,7 @@ log_reserve_and_open( ut_a(len < log->buf_size / 2); loop: mutex_enter(&(log->mutex)); + ut_ad(!recv_no_log_write); /* Calculate an upper limit for the space the string may take in the log buffer */ @@ -309,6 +310,7 @@ log_write_low( ut_ad(mutex_own(&(log->mutex))); part_loop: + ut_ad(!recv_no_log_write); /* Calculate a part length */ data_len = (log->buf_free % OS_FILE_LOG_BLOCK_SIZE) + str_len; @@ -361,6 +363,33 @@ part_loop: srv_log_write_requests++; } +/************************************************************//** +*/ +UNIV_INLINE +ulint +log_max_modified_age_async() +{ + if (srv_checkpoint_age_target) { + return(ut_min(log_sys->max_modified_age_async, + srv_checkpoint_age_target + - srv_checkpoint_age_target / 8)); + } else { + return(log_sys->max_modified_age_async); + } +} + +UNIV_INLINE +ulint +log_max_checkpoint_age_async() +{ + if (srv_checkpoint_age_target) { + return(ut_min(log_sys->max_checkpoint_age_async, + srv_checkpoint_age_target)); + } else { + return(log_sys->max_checkpoint_age_async); + } +} + /************************************************************//** Closes the log. @return lsn */ @@ -377,6 +406,7 @@ log_close(void) ib_uint64_t checkpoint_age; ut_ad(mutex_own(&(log->mutex))); + ut_ad(!recv_no_log_write); lsn = log->lsn; @@ -429,7 +459,7 @@ log_close(void) } } - if (checkpoint_age <= log->max_modified_age_async) { + if (checkpoint_age <= log_max_modified_age_async()) { goto function_exit; } @@ -437,8 +467,8 @@ log_close(void) oldest_lsn = buf_pool_get_oldest_modification(); if (!oldest_lsn - || lsn - oldest_lsn > log->max_modified_age_async - || checkpoint_age > log->max_checkpoint_age_async) { + || lsn - oldest_lsn > log_max_modified_age_async() + || checkpoint_age > log_max_checkpoint_age_async()) { log->check_flush_or_checkpoint = TRUE; } @@ -668,8 +698,6 @@ log_calc_max_ages(void) ulint archive_margin; ulint smallest_archive_margin; - ut_ad(!mutex_own(&(log_sys->mutex))); - mutex_enter(&(log_sys->mutex)); group = UT_LIST_GET_FIRST(log_sys->log_groups); @@ -770,8 +798,6 @@ void log_init(void) /*==========*/ { - byte* buf; - log_sys = mem_alloc(sizeof(log_t)); mutex_create(&log_sys->mutex, SYNC_LOG); @@ -786,8 +812,8 @@ log_init(void) ut_a(LOG_BUFFER_SIZE >= 16 * OS_FILE_LOG_BLOCK_SIZE); ut_a(LOG_BUFFER_SIZE >= 4 * UNIV_PAGE_SIZE); - buf = mem_alloc(LOG_BUFFER_SIZE + OS_FILE_LOG_BLOCK_SIZE); - log_sys->buf = ut_align(buf, OS_FILE_LOG_BLOCK_SIZE); + log_sys->buf_ptr = mem_alloc(LOG_BUFFER_SIZE + OS_FILE_LOG_BLOCK_SIZE); + log_sys->buf = ut_align(log_sys->buf_ptr, OS_FILE_LOG_BLOCK_SIZE); log_sys->buf_size = LOG_BUFFER_SIZE; @@ -832,9 +858,9 @@ log_init(void) rw_lock_create(&log_sys->checkpoint_lock, SYNC_NO_ORDER_CHECK); - log_sys->checkpoint_buf - = ut_align(mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE), - OS_FILE_LOG_BLOCK_SIZE); + log_sys->checkpoint_buf_ptr = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE); + log_sys->checkpoint_buf = ut_align(log_sys->checkpoint_buf_ptr, + OS_FILE_LOG_BLOCK_SIZE); memset(log_sys->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE); /*----------------------------*/ @@ -917,23 +943,33 @@ log_group_init( group->lsn_offset = LOG_FILE_HDR_SIZE; group->n_pending_writes = 0; + group->file_header_bufs_ptr = mem_alloc(sizeof(byte*) * n_files); group->file_header_bufs = mem_alloc(sizeof(byte*) * n_files); #ifdef UNIV_LOG_ARCHIVE + group->archive_file_header_bufs_ptr = mem_alloc( + sizeof(byte*) * n_files); group->archive_file_header_bufs = mem_alloc(sizeof(byte*) * n_files); #endif /* UNIV_LOG_ARCHIVE */ for (i = 0; i < n_files; i++) { - *(group->file_header_bufs + i) = ut_align( - mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE), + group->file_header_bufs_ptr[i] = mem_alloc( + LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); + + group->file_header_bufs[i] = ut_align( + group->file_header_bufs_ptr[i], OS_FILE_LOG_BLOCK_SIZE); memset(*(group->file_header_bufs + i), '\0', LOG_FILE_HDR_SIZE); #ifdef UNIV_LOG_ARCHIVE - *(group->archive_file_header_bufs + i) = ut_align( - mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE), + group->archive_file_header_bufs_ptr[i] = mem_alloc( + LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); + + group->archive_file_header_bufs[i] = ut_align( + group->archive_file_header_bufs_ptr[i], OS_FILE_LOG_BLOCK_SIZE); + memset(*(group->archive_file_header_bufs + i), '\0', LOG_FILE_HDR_SIZE); #endif /* UNIV_LOG_ARCHIVE */ @@ -946,8 +982,9 @@ log_group_init( group->archived_offset = 0; #endif /* UNIV_LOG_ARCHIVE */ - group->checkpoint_buf = ut_align( - mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE), OS_FILE_LOG_BLOCK_SIZE); + group->checkpoint_buf_ptr = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE); + group->checkpoint_buf = ut_align(group->checkpoint_buf_ptr, + OS_FILE_LOG_BLOCK_SIZE); memset(group->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE); @@ -1117,6 +1154,7 @@ log_io_complete( } mutex_enter(&(log_sys->mutex)); + ut_ad(!recv_no_log_write); ut_a(group->n_pending_writes > 0); ut_a(log_sys->n_pending_writes > 0); @@ -1148,6 +1186,7 @@ log_group_file_header_flush( ulint dest_offset; ut_ad(mutex_own(&(log_sys->mutex))); + ut_ad(!recv_no_log_write); ut_a(nth_file < group->n_files); buf = *(group->file_header_bufs + nth_file); @@ -1219,6 +1258,7 @@ log_group_write_buf( ulint i; ut_ad(mutex_own(&(log_sys->mutex))); + ut_ad(!recv_no_log_write); ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0); ut_a(((ulint) start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0); @@ -1361,6 +1401,7 @@ loop: #endif mutex_enter(&(log_sys->mutex)); + ut_ad(!recv_no_log_write); if (flush_to_disk && log_sys->flushed_to_disk_lsn >= lsn) { @@ -1974,6 +2015,7 @@ log_checkpoint( mutex_enter(&(log_sys->mutex)); + ut_ad(!recv_no_log_write); oldest_lsn = log_buf_pool_get_oldest_modification(); mutex_exit(&(log_sys->mutex)); @@ -2047,7 +2089,7 @@ log_make_checkpoint_at( later lsn, if IB_ULONGLONG_MAX, makes a checkpoint at the latest lsn */ ibool write_always) /*!< in: the function normally checks if - the the new checkpoint would have a + the new checkpoint would have a greater lsn than the previous one: if not, then no physical write is done; by setting this parameter TRUE, a @@ -2086,6 +2128,7 @@ loop: do_checkpoint = FALSE; mutex_enter(&(log->mutex)); + ut_ad(!recv_no_log_write); if (log->check_flush_or_checkpoint == FALSE) { mutex_exit(&(log->mutex)); @@ -2103,10 +2146,10 @@ loop: sync = TRUE; advance = 2 * (age - log->max_modified_age_sync); - } else if (age > log->max_modified_age_async) { + } else if (age > log_max_modified_age_async()) { /* A flush is not urgent: we do an asynchronous preflush */ - advance = age - log->max_modified_age_async; + advance = age - log_max_modified_age_async(); } else { advance = 0; } @@ -2120,7 +2163,7 @@ loop: do_checkpoint = TRUE; - } else if (checkpoint_age > log->max_checkpoint_age_async) { + } else if (checkpoint_age > log_max_checkpoint_age_async()) { /* A checkpoint is not urgent: do it asynchronously */ do_checkpoint = TRUE; @@ -3035,6 +3078,7 @@ loop: #endif /* UNIV_LOG_ARCHIVE */ mutex_enter(&(log_sys->mutex)); + ut_ad(!recv_no_log_write); if (log_sys->check_flush_or_checkpoint) { @@ -3244,6 +3288,7 @@ loop: ut_a(lsn == log_sys->lsn); } +#ifdef UNIV_LOG_DEBUG /******************************************************//** Checks by parsing that the catenated log segment for a single mtr is consistent. */ @@ -3251,7 +3296,7 @@ UNIV_INTERN ibool log_check_log_recs( /*===============*/ - byte* buf, /*!< in: pointer to the start of + const byte* buf, /*!< in: pointer to the start of the log segment in the log_sys->buf log buffer */ ulint len, /*!< in: segment length in bytes */ @@ -3259,8 +3304,8 @@ log_check_log_recs( { ib_uint64_t contiguous_lsn; ib_uint64_t scanned_lsn; - byte* start; - byte* end; + const byte* start; + const byte* end; byte* buf1; byte* scan_buf; @@ -3293,6 +3338,7 @@ log_check_log_recs( return(TRUE); } +#endif /* UNIV_LOG_DEBUG */ /******************************************************//** Peeks the current lsn. @@ -3336,10 +3382,12 @@ log_print( log_sys->last_checkpoint_lsn); fprintf(file, - "Max checkpoint age %lu\n" - "Modified age %lu\n" - "Checkpoint age %lu\n", + "Max checkpoint age %lu\n" + "Checkpoint age target %lu\n" + "Modified age %lu\n" + "Checkpoint age %lu\n", (ulong) log_sys->max_checkpoint_age, + (ulong) log_max_checkpoint_age_async(), (ulong) (log_sys->lsn - log_buf_pool_get_oldest_modification()), (ulong) (log_sys->lsn - log_sys->last_checkpoint_lsn)); @@ -3373,4 +3421,95 @@ log_refresh_stats(void) log_sys->n_log_ios_old = log_sys->n_log_ios; log_sys->last_printout_time = time(NULL); } + +/********************************************************************** +Closes a log group. */ +static +void +log_group_close( +/*===========*/ + log_group_t* group) /* in,own: log group to close */ +{ + ulint i; + + for (i = 0; i < group->n_files; i++) { + mem_free(group->file_header_bufs_ptr[i]); +#ifdef UNIV_LOG_ARCHIVE + mem_free(group->archive_file_header_bufs_ptr[i]); +#endif /* UNIV_LOG_ARCHIVE */ + } + + mem_free(group->file_header_bufs_ptr); + mem_free(group->file_header_bufs); + +#ifdef UNIV_LOG_ARCHIVE + mem_free(group->archive_file_header_bufs_ptr); + mem_free(group->archive_file_header_bufs); +#endif /* UNIV_LOG_ARCHIVE */ + + mem_free(group->checkpoint_buf_ptr); + + mem_free(group); +} + +/********************************************************** +Shutdown the log system but do not release all the memory. */ +UNIV_INTERN +void +log_shutdown(void) +/*==============*/ +{ + log_group_t* group; + + group = UT_LIST_GET_FIRST(log_sys->log_groups); + + while (UT_LIST_GET_LEN(log_sys->log_groups) > 0) { + log_group_t* prev_group = group; + + group = UT_LIST_GET_NEXT(log_groups, group); + UT_LIST_REMOVE(log_groups, log_sys->log_groups, prev_group); + + log_group_close(prev_group); + } + + mem_free(log_sys->buf_ptr); + log_sys->buf_ptr = NULL; + log_sys->buf = NULL; + mem_free(log_sys->checkpoint_buf_ptr); + log_sys->checkpoint_buf_ptr = NULL; + log_sys->checkpoint_buf = NULL; + + os_event_free(log_sys->no_flush_event); + os_event_free(log_sys->one_flushed_event); + + rw_lock_free(&log_sys->checkpoint_lock); + + mutex_free(&log_sys->mutex); + +#ifdef UNIV_LOG_ARCHIVE + rw_lock_free(&log_sys->archive_lock); + os_event_create(log_sys->archiving_on); +#endif /* UNIV_LOG_ARCHIVE */ + +#ifdef UNIV_LOG_DEBUG + recv_sys_debug_free(); +#endif + + recv_sys_close(); +} + +/********************************************************** +Free the log system data structures. */ +UNIV_INTERN +void +log_mem_free(void) +/*==============*/ +{ + if (log_sys != NULL) { + recv_sys_mem_free(); + mem_free(log_sys); + + log_sys = NULL; + } +} #endif /* !UNIV_HOTBACKUP */ diff --git a/log/log0recv.c b/log/log0recv.c index 60ca47f1207..77902b48a6f 100644 --- a/log/log0recv.c +++ b/log/log0recv.c @@ -69,20 +69,25 @@ UNIV_INTERN recv_sys_t* recv_sys = NULL; /** TRUE when applying redo log records during crash recovery; FALSE otherwise. Note that this is FALSE while a background thread is rolling back incomplete transactions. */ -UNIV_INTERN ibool recv_recovery_on = FALSE; +UNIV_INTERN ibool recv_recovery_on; #ifdef UNIV_LOG_ARCHIVE /** TRUE when applying redo log records from an archived log file */ -UNIV_INTERN ibool recv_recovery_from_backup_on = FALSE; +UNIV_INTERN ibool recv_recovery_from_backup_on; #endif /* UNIV_LOG_ARCHIVE */ #ifndef UNIV_HOTBACKUP /** TRUE when recv_init_crash_recovery() has been called. */ -UNIV_INTERN ibool recv_needed_recovery = FALSE; +UNIV_INTERN ibool recv_needed_recovery; +# ifdef UNIV_DEBUG +/** TRUE if writing to the redo log (mtr_commit) is forbidden. +Protected by log_sys->mutex. */ +UNIV_INTERN ibool recv_no_log_write = FALSE; +# endif /* UNIV_DEBUG */ /** TRUE if buf_page_is_corrupted() should check if the log sequence number (FIL_PAGE_LSN) is in the future. Initially FALSE, and set by recv_recovery_from_checkpoint_start_func(). */ -UNIV_INTERN ibool recv_lsn_checks_on = FALSE; +UNIV_INTERN ibool recv_lsn_checks_on; /** There are two conditions under which we scan the logs, the first is normal startup and the second is when we do a recovery from an @@ -92,7 +97,7 @@ startup. If we find log entries that were written after the last checkpoint we know that the server was not cleanly shutdown. We must then initialize the crash recovery environment before attempting to store these entries in the log hash table. */ -static ibool recv_log_scan_is_startup_type = FALSE; +static ibool recv_log_scan_is_startup_type; /** If the following is TRUE, the buffer pool file pages must be invalidated after recovery and no ibuf operations are allowed; this becomes TRUE if @@ -103,7 +108,7 @@ buffer pool before the pages have been recovered to the up-to-date state. TRUE means that recovery is running and no operations on the log files are allowed yet: the variable name is misleading. */ -UNIV_INTERN ibool recv_no_ibuf_operations = FALSE; +UNIV_INTERN ibool recv_no_ibuf_operations; /** TRUE when the redo log is being backed up */ # define recv_is_making_a_backup FALSE /** TRUE when recovering from a backed up redo log file */ @@ -111,30 +116,30 @@ UNIV_INTERN ibool recv_no_ibuf_operations = FALSE; #else /* !UNIV_HOTBACKUP */ # define recv_needed_recovery FALSE /** TRUE when the redo log is being backed up */ -UNIV_INTERN ibool recv_is_making_a_backup = FALSE; +UNIV_INTERN ibool recv_is_making_a_backup = FALSE; /** TRUE when recovering from a backed up redo log file */ UNIV_INTERN ibool recv_is_from_backup = FALSE; # define buf_pool_get_curr_size() (5 * 1024 * 1024) #endif /* !UNIV_HOTBACKUP */ /** The following counter is used to decide when to print info on log scan */ -static ulint recv_scan_print_counter = 0; +static ulint recv_scan_print_counter; /** The type of the previous parsed redo log record */ -static ulint recv_previous_parsed_rec_type = 999999; +static ulint recv_previous_parsed_rec_type; /** The offset of the previous parsed redo log record */ -static ulint recv_previous_parsed_rec_offset = 0; +static ulint recv_previous_parsed_rec_offset; /** The 'multi' flag of the previous parsed redo log record */ -static ulint recv_previous_parsed_rec_is_multi = 0; +static ulint recv_previous_parsed_rec_is_multi; /** Maximum page number encountered in the redo log */ -UNIV_INTERN ulint recv_max_parsed_page_no = 0; +UNIV_INTERN ulint recv_max_parsed_page_no; /** This many frames must be left free in the buffer pool when we scan the log and store the scanned log records in the buffer pool: we will use these free frames to read in pages when we start applying the log records to the database. */ -UNIV_INTERN ulint recv_n_pool_free_frames = 1024; +UNIV_INTERN ulint recv_n_pool_free_frames; /** The maximum lsn we see for a page during the recovery process. If this is bigger than the lsn we are able to scan up to, that is an indication that @@ -165,15 +170,119 @@ recv_sys_create(void) return; } - recv_sys = mem_alloc(sizeof(recv_sys_t)); + recv_sys = mem_alloc(sizeof(*recv_sys)); + memset(recv_sys, 0x0, sizeof(*recv_sys)); mutex_create(&recv_sys->mutex, SYNC_RECV); recv_sys->heap = NULL; recv_sys->addr_hash = NULL; + + recv_sys->stats_recv_start_time = time(NULL); + recv_sys->stats_oldest_modified_lsn = IB_ULONGLONG_MAX; } /********************************************************//** +Release recovery system mutexes. */ +UNIV_INTERN +void +recv_sys_close(void) +/*================*/ +{ + if (recv_sys != NULL) { + if (recv_sys->addr_hash != NULL) { + hash_table_free(recv_sys->addr_hash); + } + + if (recv_sys->heap != NULL) { + mem_heap_free(recv_sys->heap); + } + + if (recv_sys->buf != NULL) { + ut_free(recv_sys->buf); + } + + if (recv_sys->last_block_buf_start != NULL) { + mem_free(recv_sys->last_block_buf_start); + } + + mutex_free(&recv_sys->mutex); + + mem_free(recv_sys); + recv_sys = NULL; + } +} + +/********************************************************//** +Frees the recovery system memory. */ +UNIV_INTERN +void +recv_sys_mem_free(void) +/*===================*/ +{ + if (recv_sys != NULL) { + if (recv_sys->addr_hash != NULL) { + hash_table_free(recv_sys->addr_hash); + } + + if (recv_sys->heap != NULL) { + mem_heap_free(recv_sys->heap); + } + + if (recv_sys->buf != NULL) { + ut_free(recv_sys->buf); + } + + if (recv_sys->last_block_buf_start != NULL) { + mem_free(recv_sys->last_block_buf_start); + } + + mem_free(recv_sys); + recv_sys = NULL; + } +} + +/************************************************************ +Reset the state of the recovery system variables. */ +UNIV_INTERN +void +recv_sys_var_init(void) +/*===================*/ +{ + recv_lsn_checks_on = FALSE; + + recv_n_pool_free_frames = 1024; + + recv_recovery_on = FALSE; + +#ifdef UNIV_LOG_ARCHIVE + recv_recovery_from_backup_on = FALSE; +#endif /* UNIV_LOG_ARCHIVE */ + + recv_needed_recovery = FALSE; + + recv_lsn_checks_on = FALSE; + + recv_log_scan_is_startup_type = FALSE; + + recv_no_ibuf_operations = FALSE; + + recv_scan_print_counter = 0; + + recv_previous_parsed_rec_type = 999999; + + recv_previous_parsed_rec_offset = 0; + + recv_previous_parsed_rec_is_multi = 0; + + recv_max_parsed_page_no = 0; + + recv_n_pool_free_frames = 1024; + + recv_max_page_lsn = 0; +} + +/************************************************************ Inits the recovery system for a recovery operation. */ UNIV_INTERN void @@ -248,8 +357,8 @@ recv_sys_empty_hash(void) Frees the recovery system. */ static void -recv_sys_free(void) -/*===============*/ +recv_sys_debug_free(void) +/*=====================*/ { mutex_enter(&(recv_sys->mutex)); @@ -258,8 +367,10 @@ recv_sys_free(void) ut_free(recv_sys->buf); mem_free(recv_sys->last_block_buf_start); - recv_sys->addr_hash = NULL; + recv_sys->buf = NULL; recv_sys->heap = NULL; + recv_sys->addr_hash = NULL; + recv_sys->last_block_buf_start = NULL; mutex_exit(&(recv_sys->mutex)); } @@ -853,6 +964,11 @@ recv_parse_or_apply_log_rec_body( } switch (type) { +#ifdef UNIV_LOG_LSN_DEBUG + case MLOG_LSN: + /* The LSN is checked in recv_parse_log_rec(). */ + break; +#endif /* UNIV_LOG_LSN_DEBUG */ case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES: #ifdef UNIV_DEBUG if (page && page_type == FIL_PAGE_TYPE_ALLOCATED @@ -1223,6 +1339,11 @@ recv_add_to_hash_table( len = rec_end - body; + if (srv_recovery_stats) { + recv_sys->stats_log_recs++; + recv_sys->stats_log_len_sum += len; + } + recv = mem_heap_alloc(recv_sys->heap, sizeof(recv_t)); recv->type = type; recv->len = rec_end - body; @@ -1269,7 +1390,7 @@ recv_add_to_hash_table( sizeof(recv_data_t) + len); *prev_field = recv_data; - ut_memcpy(((byte*)recv_data) + sizeof(recv_data_t), body, len); + memcpy(recv_data + 1, body, len); prev_field = &(recv_data->next); @@ -1327,12 +1448,14 @@ recv_recover_page_func( buf_block_t* block) /*!< in/out: buffer block */ { page_t* page; + page_zip_des_t* page_zip; recv_addr_t* recv_addr; recv_t* recv; byte* buf; ib_uint64_t start_lsn; ib_uint64_t end_lsn; ib_uint64_t page_lsn; + ib_uint64_t page_lsn_orig; ib_uint64_t page_newest_lsn; ibool modification_to_page; #ifndef UNIV_HOTBACKUP @@ -1372,12 +1495,21 @@ recv_recover_page_func( recv_addr->state = RECV_BEING_PROCESSED; + if (srv_recovery_stats) { + if (just_read_in) { + recv_sys->stats_recover_pages_with_read++; + } else { + recv_sys->stats_recover_pages_without_read++; + } + } + mutex_exit(&(recv_sys->mutex)); mtr_start(&mtr); mtr_set_log_mode(&mtr, MTR_LOG_NONE); page = block->frame; + page_zip = buf_block_get_page_zip(block); #ifndef UNIV_HOTBACKUP if (just_read_in) { @@ -1400,6 +1532,7 @@ recv_recover_page_func( /* Read the newest modification lsn from the page */ page_lsn = mach_read_ull(page + FIL_PAGE_LSN); + page_lsn_orig = page_lsn; #ifndef UNIV_HOTBACKUP /* It may be that the page has been modified in the buffer @@ -1419,6 +1552,21 @@ recv_recover_page_func( modification_to_page = FALSE; start_lsn = end_lsn = 0; + if (srv_recovery_stats) { + mutex_enter(&(recv_sys->mutex)); + if (page_lsn_orig && recv_sys->stats_oldest_modified_lsn > page_lsn_orig) { + recv_sys->stats_oldest_modified_lsn = page_lsn_orig; + } + if (page_lsn_orig && recv_sys->stats_newest_modified_lsn < page_lsn_orig) { + recv_sys->stats_newest_modified_lsn = page_lsn_orig; + } + if (UT_LIST_GET_LAST(recv_addr->rec_list)->start_lsn + < page_lsn_orig) { + recv_sys->stats_pages_already_new++; + } + mutex_exit(&(recv_sys->mutex)); + } + recv = UT_LIST_GET_FIRST(recv_addr->rec_list); while (recv) { @@ -1438,13 +1586,19 @@ recv_recover_page_func( if (recv->type == MLOG_INIT_FILE_PAGE) { page_lsn = page_newest_lsn; - mach_write_ull(page + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM, 0); - mach_write_ull(page + FIL_PAGE_LSN, 0); + memset(FIL_PAGE_LSN + page, 0, 8); + memset(UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + + page, 0, 8); + + if (page_zip) { + memset(FIL_PAGE_LSN + page_zip->data, 0, 8); + } } if (recv->start_lsn >= page_lsn) { + ib_uint64_t end_lsn; + if (!modification_to_page) { modification_to_page = TRUE; @@ -1466,11 +1620,24 @@ recv_recover_page_func( recv_parse_or_apply_log_rec_body(recv->type, buf, buf + recv->len, block, &mtr); - mach_write_ull(page + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM, - recv->start_lsn + recv->len); - mach_write_ull(page + FIL_PAGE_LSN, - recv->start_lsn + recv->len); + + if (srv_recovery_stats) { + mutex_enter(&(recv_sys->mutex)); + recv_sys->stats_applied_log_recs++; + recv_sys->stats_applied_log_len_sum += recv->len; + mutex_exit(&(recv_sys->mutex)); + } + + end_lsn = recv->start_lsn + recv->len; + mach_write_ull(FIL_PAGE_LSN + page, end_lsn); + mach_write_ull(UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + + page, end_lsn); + + if (page_zip) { + mach_write_ull(FIL_PAGE_LSN + + page_zip->data, end_lsn); + } } if (recv->len > RECV_DATA_BLOCK_SIZE) { @@ -1561,6 +1728,13 @@ recv_read_in_area( } } + if (srv_recovery_stats && n) { + mutex_enter(&(recv_sys->mutex)); + recv_sys->stats_read_requested_pages += n; + recv_sys->stats_read_in_area[n - 1]++; + mutex_exit(&(recv_sys->mutex)); + } + buf_read_recv_pages(FALSE, space, zip_size, page_nos, n); /* fprintf(stderr, "Recv pages at %lu n %lu\n", page_nos[0], n); @@ -1688,6 +1862,7 @@ loop: /* Flush all the file pages to disk and invalidate them in the buffer pool */ + ut_d(recv_no_log_write = TRUE); mutex_exit(&(recv_sys->mutex)); mutex_exit(&(log_sys->mutex)); @@ -1701,6 +1876,7 @@ loop: mutex_enter(&(log_sys->mutex)); mutex_enter(&(recv_sys->mutex)); + ut_d(recv_no_log_write = FALSE); recv_no_ibuf_operations = FALSE; } @@ -1712,6 +1888,10 @@ loop: if (has_printed) { fprintf(stderr, "InnoDB: Apply batch completed\n"); + + if (srv_recovery_stats) { + recv_sys->stats_recv_turns++; + } } mutex_exit(&(recv_sys->mutex)); @@ -1912,6 +2092,17 @@ recv_parse_log_rec( return(0); } +#ifdef UNIV_LOG_LSN_DEBUG + if (*type == MLOG_LSN) { + ib_uint64_t lsn = (ib_uint64_t) *space << 32 | *page_no; +# ifdef UNIV_LOG_DEBUG + ut_a(lsn == log_sys->old_lsn); +# else /* UNIV_LOG_DEBUG */ + ut_a(lsn == recv_sys->recovered_lsn); +# endif /* UNIV_LOG_DEBUG */ + } +#endif /* UNIV_LOG_LSN_DEBUG */ + /* Check that page_no is sensible */ if (UNIV_UNLIKELY(*page_no > 0x8FFFFFFFUL)) { @@ -2169,6 +2360,12 @@ loop: #endif /* In normal mysqld crash recovery we do not try to replay file operations */ +#ifdef UNIV_LOG_LSN_DEBUG + } else if (type == MLOG_LSN) { + /* Do not add these records to the hash table. + The page number and space id fields are misused + for something else. */ +#endif /* UNIV_LOG_LSN_DEBUG */ } else { recv_add_to_hash_table(type, space, page_no, body, ptr + len, old_lsn, @@ -2200,11 +2397,11 @@ loop: = recv_sys->recovered_offset + total_len; recv_previous_parsed_rec_is_multi = 1; - if ((!store_to_hash) && (type != MLOG_MULTI_REC_END)) { #ifdef UNIV_LOG_DEBUG + if ((!store_to_hash) && (type != MLOG_MULTI_REC_END)) { recv_check_incomplete_log_recs(ptr, len); -#endif /* UNIV_LOG_DEBUG */ } +#endif /* UNIV_LOG_DEBUG */ #ifdef UNIV_DEBUG if (log_debug_writes) { @@ -2268,7 +2465,11 @@ loop: break; } - if (store_to_hash) { + if (store_to_hash +#ifdef UNIV_LOG_LSN_DEBUG + && type != MLOG_LSN +#endif /* UNIV_LOG_LSN_DEBUG */ + ) { recv_add_to_hash_table(type, space, page_no, body, ptr + len, old_lsn, @@ -2417,8 +2618,7 @@ recv_scan_log_recs( scanned_lsn = start_lsn; more_data = FALSE; - while (log_block < buf + len && !finished) { - + do { no = log_block_get_hdr_no(log_block); /* fprintf(stderr, "Log block header no %lu\n", no); @@ -2548,10 +2748,11 @@ recv_scan_log_recs( /* Log data for this group ends here */ finished = TRUE; + break; } else { log_block += OS_FILE_LOG_BLOCK_SIZE; } - } + } while (log_block < buf + len && !finished); *group_scanned_lsn = scanned_lsn; @@ -3078,6 +3279,84 @@ recv_recovery_from_checkpoint_finish(void) } #endif /* UNIV_DEBUG */ + if (recv_needed_recovery && srv_recovery_stats) { + FILE* file = stderr; + ulint i; + + fprintf(stderr, + "InnoDB: Applying log records was done. Its statistics are followings.\n"); + + fprintf(stderr, + "============================================================\n" + "-------------------\n" + "RECOVERY STATISTICS\n" + "-------------------\n"); + fprintf(stderr, + "Recovery time: %g sec. (%lu turns)\n", + difftime(time(NULL), recv_sys->stats_recv_start_time), + recv_sys->stats_recv_turns); + + fprintf(stderr, + "\n" + "Data page IO statistics\n" + " Requested pages: %lu\n" + " Read pages: %lu\n" + " Written pages: %lu\n" + " (Dirty blocks): %lu\n", + recv_sys->stats_read_requested_pages, + recv_sys->stats_read_io_pages, + recv_sys->stats_write_io_pages, + UT_LIST_GET_LEN(buf_pool->flush_list)); + + fprintf(stderr, + " Grouping IO [times]:\n" + "\tnumber of pages,\n" + "\t\tread request neighbors (in %d pages chunk),\n" + "\t\t\tcombined read IO,\n" + "\t\t\t\tcombined write IO\n", + RECV_READ_AHEAD_AREA); + for (i = 0; i < ut_max(RECV_READ_AHEAD_AREA, + OS_AIO_MERGE_N_CONSECUTIVE); i++) { + fprintf(stderr, + "\t%3lu,\t%lu,\t%lu,\t%lu\n", i + 1, + (i < RECV_READ_AHEAD_AREA) ? + recv_sys->stats_read_in_area[i] : 0, + (i < OS_AIO_MERGE_N_CONSECUTIVE) ? + recv_sys->stats_read_io_consecutive[i] : 0, + (i < OS_AIO_MERGE_N_CONSECUTIVE) ? + recv_sys->stats_write_io_consecutive[i] : 0); + } + + fprintf(stderr, + "\n" + "Recovery process statistics\n" + " Checked pages by doublewrite buffer: %lu\n" + " Overwritten pages from doublewrite: %lu\n" + " Recovered pages by io_thread: %lu\n" + " Recovered pages by main thread: %lu\n" + " Parsed log records to apply: %lu\n" + " Sum of the length: %lu\n" + " Applied log records: %lu\n" + " Sum of the length: %lu\n" + " Pages which are already new enough: %lu (It may not be accurate, if turns > 1)\n" + " Oldest page's LSN: %llu\n" + " Newest page's LSN: %llu\n", + recv_sys->stats_doublewrite_check_pages, + recv_sys->stats_doublewrite_overwrite_pages, + recv_sys->stats_recover_pages_with_read, + recv_sys->stats_recover_pages_without_read, + recv_sys->stats_log_recs, + recv_sys->stats_log_len_sum, + recv_sys->stats_applied_log_recs, + recv_sys->stats_applied_log_len_sum, + recv_sys->stats_pages_already_new, + recv_sys->stats_oldest_modified_lsn, + recv_sys->stats_newest_modified_lsn); + + fprintf(stderr, + "============================================================\n"); + } + if (recv_needed_recovery) { trx_sys_print_mysql_master_log_pos(); trx_sys_print_mysql_binlog_offset(); @@ -3104,8 +3383,13 @@ recv_recovery_from_checkpoint_finish(void) recv_recovery_on = FALSE; #ifndef UNIV_LOG_DEBUG - recv_sys_free(); + recv_sys_debug_free(); #endif + /* Roll back any recovered data dictionary transactions, so + that the data dictionary tables will be free of any locks. + The data dictionary latch should guarantee that there is at + most one data dictionary transaction active at a time. */ + trx_rollback_or_clean_recovered(FALSE); /* Drop partially created indexes. */ row_merge_drop_temp_indexes(); diff --git a/mem/mem0dbg.c b/mem/mem0dbg.c index a20eb2ad7d2..01eda20ec45 100644 --- a/mem/mem0dbg.c +++ b/mem/mem0dbg.c @@ -170,6 +170,17 @@ mem_init( mem_comm_pool = mem_pool_create(size); } + +/******************************************************************//** +Closes the memory system. */ +UNIV_INTERN +void +mem_close(void) +/*===========*/ +{ + mem_pool_free(mem_comm_pool); + mem_comm_pool = NULL; +} #endif /* !UNIV_HOTBACKUP */ #ifdef UNIV_MEM_DEBUG diff --git a/mem/mem0mem.c b/mem/mem0mem.c index e0dc8716f13..ccb2fd8a7b4 100644 --- a/mem/mem0mem.c +++ b/mem/mem0mem.c @@ -475,16 +475,18 @@ mem_heap_block_free( len = block->len; block->magic_n = MEM_FREED_BLOCK_MAGIC_N; +#ifndef UNIV_HOTBACKUP + if (!srv_use_sys_malloc) { #ifdef UNIV_MEM_DEBUG - /* In the debug version we set the memory to a random combination - of hex 0xDE and 0xAD. */ + /* In the debug version we set the memory to a random + combination of hex 0xDE and 0xAD. */ - mem_erase_buf((byte*)block, len); + mem_erase_buf((byte*)block, len); #else /* UNIV_MEM_DEBUG */ - UNIV_MEM_ASSERT_AND_FREE(block, len); + UNIV_MEM_ASSERT_AND_FREE(block, len); #endif /* UNIV_MEM_DEBUG */ -#ifndef UNIV_HOTBACKUP + } if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) { ut_ad(!buf_block); @@ -495,6 +497,14 @@ mem_heap_block_free( buf_block_free(buf_block); } #else /* !UNIV_HOTBACKUP */ +#ifdef UNIV_MEM_DEBUG + /* In the debug version we set the memory to a random + combination of hex 0xDE and 0xAD. */ + + mem_erase_buf((byte*)block, len); +#else /* UNIV_MEM_DEBUG */ + UNIV_MEM_ASSERT_AND_FREE(block, len); +#endif /* UNIV_MEM_DEBUG */ ut_free(block); #endif /* !UNIV_HOTBACKUP */ } diff --git a/mem/mem0pool.c b/mem/mem0pool.c index c8fea97a6a3..c4f8af607e0 100644 --- a/mem/mem0pool.c +++ b/mem/mem0pool.c @@ -260,6 +260,18 @@ mem_pool_create( return(pool); } +/********************************************************************//** +Frees a memory pool. */ +UNIV_INTERN +void +mem_pool_free( +/*==========*/ + mem_pool_t* pool) /*!< in, own: memory pool */ +{ + ut_free(pool->buf); + ut_free(pool); +} + /********************************************************************//** Fills the specified free list. @return TRUE if we were able to insert a block to the free list */ diff --git a/mtr/mtr0mtr.c b/mtr/mtr0mtr.c index b10f0d075ed..44d11fe5b1d 100644 --- a/mtr/mtr0mtr.c +++ b/mtr/mtr0mtr.c @@ -35,6 +35,7 @@ Created 11/26/1995 Heikki Tuuri #include "log0log.h" #ifndef UNIV_HOTBACKUP +# include "log0recv.h" /*****************************************************************//** Releases the item in the slot given. */ UNIV_INLINE @@ -147,7 +148,6 @@ mtr_log_reserve_and_write( dyn_array_t* mlog; dyn_block_t* block; ulint data_size; - ibool success; byte* first_data; ut_ad(mtr); @@ -166,8 +166,8 @@ mtr_log_reserve_and_write( if (mlog->heap == NULL) { mtr->end_lsn = log_reserve_and_write_fast( first_data, dyn_block_get_used(mlog), - &(mtr->start_lsn), &success); - if (success) { + &mtr->start_lsn); + if (mtr->end_lsn) { return; } @@ -214,6 +214,8 @@ mtr_commit( ut_d(mtr->state = MTR_COMMITTING); #ifndef UNIV_HOTBACKUP + /* This is a dirty read, for debugging. */ + ut_ad(!recv_no_log_write); write_log = mtr->modifications && mtr->n_log_recs; if (write_log) { diff --git a/mysql-test/innodb-analyze.test b/mysql-test/innodb-analyze.test index de5a486a355..9bdb9db697c 100644 --- a/mysql-test/innodb-analyze.test +++ b/mysql-test/innodb-analyze.test @@ -11,7 +11,7 @@ -- disable_result_log -- enable_warnings -SET @old_innodb_stats_sample_pages=@@innodb_stats_sample_pages; +let $sample_pages=`select @@innodb_stats_sample_pages`; SET GLOBAL innodb_stats_sample_pages=0; # check that the value has been adjusted to 1 @@ -62,4 +62,4 @@ SET GLOBAL innodb_stats_sample_pages=16; ANALYZE TABLE innodb_analyze; DROP TABLE innodb_analyze; -SET GLOBAL innodb_stats_sample_pages=@old_innodb_stats_sample_pages; +EVAL SET GLOBAL innodb_stats_sample_pages=$sample_pages; diff --git a/mysql-test/innodb-autoinc.result b/mysql-test/innodb-autoinc.result index d2e8eb19e0c..abb8f3da072 100644 --- a/mysql-test/innodb-autoinc.result +++ b/mysql-test/innodb-autoinc.result @@ -867,6 +867,7 @@ INSERT INTO t2 SELECT NULL FROM t1; Got one of the listed errors DROP TABLE t1; DROP TABLE t2; +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; INSERT INTO t1 VALUES (null); INSERT INTO t1 VALUES (null); @@ -874,18 +875,254 @@ ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; SELECT * FROM t1; d1 1 -3 +2 SELECT * FROM t1; d1 1 -3 +2 INSERT INTO t1 VALUES(null); Got one of the listed errors ALTER TABLE t1 AUTO_INCREMENT = 3; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `d1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`d1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 INSERT INTO t1 VALUES(null); SELECT * FROM t1; d1 1 +2 3 -4 DROP TABLE t1; +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +SHOW VARIABLES LIKE "%auto_inc%"; +Variable_name Value +auto_increment_increment 1 +auto_increment_offset 1 +CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-127, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` tinyint(4) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-127 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-127, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` tinyint(3) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 SMALLINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-32767, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` smallint(6) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-32767 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-32757, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` smallint(5) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 MEDIUMINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-8388607, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` mediumint(9) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-8388607 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 MEDIUMINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-8388607, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-2147483647 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(10) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bigint(20) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-9223372036854775807 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE T1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) AUTO_INCREMENT=10 ENGINE=InnoDB; +CREATE INDEX i1 on T1(c2); +SHOW CREATE TABLE T1; +Table Create Table +T1 CREATE TABLE `T1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` int(11) DEFAULT NULL, + PRIMARY KEY (`c1`), + KEY `i1` (`c2`) +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1 +INSERT INTO T1 (c2) values (0); +SELECT * FROM T1; +c1 c2 +10 0 +DROP TABLE T1; diff --git a/mysql-test/innodb-autoinc.test b/mysql-test/innodb-autoinc.test index 61c42f45733..558de6a1060 100644 --- a/mysql-test/innodb-autoinc.test +++ b/mysql-test/innodb-autoinc.test @@ -482,6 +482,7 @@ DROP TABLE t2; # 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from # the index (PRIMARY) # This test requires a restart of the server +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; INSERT INTO t1 VALUES (null); INSERT INTO t1 VALUES (null); @@ -495,6 +496,123 @@ SELECT * FROM t1; -- error ER_AUTOINC_READ_FAILED,1467 INSERT INTO t1 VALUES(null); ALTER TABLE t1 AUTO_INCREMENT = 3; +SHOW CREATE TABLE t1; INSERT INTO t1 VALUES(null); SELECT * FROM t1; DROP TABLE t1; + +# If the user has specified negative values for an AUTOINC column then +# InnoDB should ignore those values when setting the table's max value. +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +SHOW VARIABLES LIKE "%auto_inc%"; +# TINYINT +CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-127, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-127, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# SMALLINT +# +CREATE TABLE t1 (c1 SMALLINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-32767, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-32757, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# MEDIUMINT +# +CREATE TABLE t1 (c1 MEDIUMINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-8388607, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 MEDIUMINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-8388607, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# INT +# +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# BIGINT +# +CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# End negative number check + +## +# 47125: auto_increment start value is ignored if an index is created +# and engine=innodb +# +CREATE TABLE T1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) AUTO_INCREMENT=10 ENGINE=InnoDB; +CREATE INDEX i1 on T1(c2); +SHOW CREATE TABLE T1; +INSERT INTO T1 (c2) values (0); +SELECT * FROM T1; +DROP TABLE T1; diff --git a/mysql-test/innodb-consistent-master.opt b/mysql-test/innodb-consistent-master.opt new file mode 100644 index 00000000000..cb48f1aaf60 --- /dev/null +++ b/mysql-test/innodb-consistent-master.opt @@ -0,0 +1 @@ +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/innodb-consistent.result b/mysql-test/innodb-consistent.result new file mode 100644 index 00000000000..9115791b99c --- /dev/null +++ b/mysql-test/innodb-consistent.result @@ -0,0 +1,35 @@ +drop table if exists t1; +set session transaction isolation level read committed; +create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1; +create table t2 like t1; +insert into t2 values (1),(2),(3),(4),(5),(6),(7); +set autocommit=0; +begin; +replace into t1 select * from t2; +set session transaction isolation level read committed; +set autocommit=0; +delete from t2 where a=5; +commit; +delete from t2; +commit; +commit; +begin; +insert into t1 select * from t2; +set session transaction isolation level read committed; +set autocommit=0; +delete from t2 where a=5; +commit; +delete from t2; +commit; +commit; +select * from t1; +a +1 +2 +3 +4 +5 +6 +7 +drop table t1; +drop table t2; diff --git a/mysql-test/innodb-consistent.test b/mysql-test/innodb-consistent.test new file mode 100644 index 00000000000..5a7f4dc392d --- /dev/null +++ b/mysql-test/innodb-consistent.test @@ -0,0 +1,58 @@ +-- source include/not_embedded.inc +-- source include/have_innodb.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +# REPLACE INTO ... SELECT and INSERT INTO ... SELECT should do +# a consistent read of the source table. + +connect (a,localhost,root,,); +connect (b,localhost,root,,); +connection a; +set session transaction isolation level read committed; +create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1; +create table t2 like t1; +insert into t2 values (1),(2),(3),(4),(5),(6),(7); +set autocommit=0; + +# REPLACE INTO ... SELECT case +begin; +# this should not result in any locks on t2. +replace into t1 select * from t2; + +connection b; +set session transaction isolation level read committed; +set autocommit=0; +# should not cuase a lock wait. +delete from t2 where a=5; +commit; +delete from t2; +commit; +connection a; +commit; + +# INSERT INTO ... SELECT case +begin; +# this should not result in any locks on t2. +insert into t1 select * from t2; + +connection b; +set session transaction isolation level read committed; +set autocommit=0; +# should not cuase a lock wait. +delete from t2 where a=5; +commit; +delete from t2; +commit; +connection a; +commit; + +select * from t1; +drop table t1; +drop table t2; + +connection default; +disconnect a; +disconnect b; diff --git a/mysql-test/innodb-index.result b/mysql-test/innodb-index.result index f2c90c54df8..93a4123809d 100644 --- a/mysql-test/innodb-index.result +++ b/mysql-test/innodb-index.result @@ -46,6 +46,13 @@ t1 CREATE TABLE `t1` ( KEY `d2` (`d`), KEY `b` (`b`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 +CREATE TABLE `t1#1`(a INT PRIMARY KEY) ENGINE=InnoDB; +alter table t1 add unique index (c), add index (d); +ERROR HY000: Table 'test.t1#1' already exists +rename table `t1#1` to `t1#2`; +alter table t1 add unique index (c), add index (d); +ERROR HY000: Table 'test.t1#2' already exists +drop table `t1#2`; alter table t1 add unique index (c), add index (d); show create table t1; Table Create Table @@ -620,7 +627,7 @@ drop table t1; create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb; insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,3,'ac','ac'),(4,4,'afe','afe'),(5,4,'affe','affe'); alter table t1 add unique index (b), add unique index (c), add unique index (d); -ERROR 23000: Duplicate entry '4' for key 'b' +ERROR 23000: Duplicate entry 'ac' for key 'c' alter table t1 add unique index (c), add unique index (b), add index (d); ERROR 23000: Duplicate entry 'ac' for key 'c' show create table t1; @@ -961,6 +968,7 @@ create index t1u on t1 (u(1)); drop table t1; set global innodb_file_per_table=0; set global innodb_file_format=Antelope; +set global innodb_file_format_check=Antelope; SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; CREATE TABLE t1( @@ -1125,7 +1133,6 @@ t2 CREATE TABLE `t2` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t2; DROP TABLE t1; -call mtr.add_suppression("InnoDB: insufficient history for index"); CREATE TABLE t1 (a INT, b CHAR(1)) ENGINE=InnoDB; INSERT INTO t1 VALUES (3,'a'),(3,'b'),(1,'c'),(0,'d'),(1,'e'); BEGIN; @@ -1162,4 +1169,3 @@ a b 3 a 3 b DROP TABLE t1; -set global innodb_file_format_check=Antelope; diff --git a/mysql-test/innodb-index.test b/mysql-test/innodb-index.test index 1ec1a503c63..64ee52dd722 100644 --- a/mysql-test/innodb-index.test +++ b/mysql-test/innodb-index.test @@ -1,4 +1,7 @@ -- source include/have_innodb.inc + +let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; + create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb; insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak'); commit; @@ -16,6 +19,16 @@ show create table t1; alter table t1 add index (b); show create table t1; +# Check how existing tables interfere with temporary tables. +CREATE TABLE `t1#1`(a INT PRIMARY KEY) ENGINE=InnoDB; + +--error 156 +alter table t1 add unique index (c), add index (d); +rename table `t1#1` to `t1#2`; +--error 156 +alter table t1 add unique index (c), add index (d); +drop table `t1#2`; + alter table t1 add unique index (c), add index (d); show create table t1; explain select * from t1 force index(c) order by c; @@ -387,6 +400,7 @@ create index t1u on t1 (u(1)); drop table t1; eval set global innodb_file_per_table=$per_table; eval set global innodb_file_format=$format; +eval set global innodb_file_format_check=$format; # # Test to check whether CREATE INDEX handles implicit foreign key @@ -499,8 +513,6 @@ SHOW CREATE TABLE t2; DROP TABLE t2; DROP TABLE t1; -call mtr.add_suppression("InnoDB: insufficient history for index"); - connect (a,localhost,root,,); connect (b,localhost,root,,); connection a; @@ -523,4 +535,10 @@ disconnect a; disconnect b; DROP TABLE t1; -set global innodb_file_format_check=Antelope; + +# +# restore environment to the state it was before this test execution +# + +-- disable_query_log +eval SET GLOBAL innodb_file_format_check=$innodb_file_format_check_orig; diff --git a/mysql-test/innodb-master.opt b/mysql-test/innodb-master.opt index 4901efb416c..72c88068345 100644 --- a/mysql-test/innodb-master.opt +++ b/mysql-test/innodb-master.opt @@ -1 +1 @@ ---binlog_cache_size=32768 --innodb_lock_wait_timeout=1 +--binlog_cache_size=32768 --loose_innodb_lock_wait_timeout=1 diff --git a/mysql-test/innodb-semi-consistent-master.opt b/mysql-test/innodb-semi-consistent-master.opt index e76299453d3..cb48f1aaf60 100644 --- a/mysql-test/innodb-semi-consistent-master.opt +++ b/mysql-test/innodb-semi-consistent-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/innodb-use-sys-malloc-master.opt b/mysql-test/innodb-use-sys-malloc-master.opt index 889834add01..fc8582b5887 100644 --- a/mysql-test/innodb-use-sys-malloc-master.opt +++ b/mysql-test/innodb-use-sys-malloc-master.opt @@ -1,2 +1 @@ ---innodb-use-sys-malloc=true ---innodb-use-sys-malloc=true +--loose-innodb-use-sys-malloc=true diff --git a/mysql-test/innodb-zip.result b/mysql-test/innodb-zip.result index c81401743a5..21396d81ba8 100644 --- a/mysql-test/innodb-zip.result +++ b/mysql-test/innodb-zip.result @@ -141,7 +141,7 @@ drop table t1; CREATE TABLE t1(c TEXT, PRIMARY KEY (c(440))) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII; ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs -CREATE TABLE t1(c TEXT, PRIMARY KEY (c(439))) +CREATE TABLE t1(c TEXT, PRIMARY KEY (c(438))) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII; INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512)); DROP TABLE t1; @@ -196,15 +196,15 @@ drop table t1; set innodb_strict_mode = on; create table t1 (id int primary key) engine = innodb key_block_size = 0; ERROR HY000: Can't create table 'test.t1' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 0. Valid values are [1, 2, 4, 8, 16] +Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 0. Valid values are [1, 2, 4, 8, 16] Error 1005 Can't create table 'test.t1' (errno: 1478) create table t2 (id int primary key) engine = innodb key_block_size = 9; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] +Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] Error 1005 Can't create table 'test.t2' (errno: 1478) create table t3 (id int primary key) engine = innodb key_block_size = 1; create table t4 (id int primary key) engine = innodb key_block_size = 2; @@ -233,30 +233,30 @@ key_block_size = 8 row_format = compressed; create table t2 (id int primary key) engine = innodb key_block_size = 8 row_format = redundant; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t2' (errno: 1478) create table t3 (id int primary key) engine = innodb key_block_size = 8 row_format = compact; ERROR HY000: Can't create table 'test.t3' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t3' (errno: 1478) create table t4 (id int primary key) engine = innodb key_block_size = 8 row_format = dynamic; ERROR HY000: Can't create table 'test.t4' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t4' (errno: 1478) create table t5 (id int primary key) engine = innodb key_block_size = 8 row_format = default; ERROR HY000: Can't create table 'test.t5' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t5' (errno: 1478) SELECT table_schema, table_name, row_format FROM information_schema.tables WHERE engine='innodb'; @@ -266,26 +266,26 @@ drop table t1; create table t1 (id int primary key) engine = innodb key_block_size = 9 row_format = redundant; ERROR HY000: Can't create table 'test.t1' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] -Error 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] +Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t1' (errno: 1478) create table t2 (id int primary key) engine = innodb key_block_size = 9 row_format = compact; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] -Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] +Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t2' (errno: 1478) create table t2 (id int primary key) engine = innodb key_block_size = 9 row_format = dynamic; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] -Error 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] +Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t2' (errno: 1478) SELECT table_schema, table_name, row_format FROM information_schema.tables WHERE engine='innodb'; @@ -293,45 +293,45 @@ table_schema table_name row_format set global innodb_file_per_table = off; create table t1 (id int primary key) engine = innodb key_block_size = 1; ERROR HY000: Can't create table 'test.t1' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. Error 1005 Can't create table 'test.t1' (errno: 1478) create table t2 (id int primary key) engine = innodb key_block_size = 2; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. Error 1005 Can't create table 'test.t2' (errno: 1478) create table t3 (id int primary key) engine = innodb key_block_size = 4; ERROR HY000: Can't create table 'test.t3' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. Error 1005 Can't create table 'test.t3' (errno: 1478) create table t4 (id int primary key) engine = innodb key_block_size = 8; ERROR HY000: Can't create table 'test.t4' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. Error 1005 Can't create table 'test.t4' (errno: 1478) create table t5 (id int primary key) engine = innodb key_block_size = 16; ERROR HY000: Can't create table 'test.t5' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. Error 1005 Can't create table 'test.t5' (errno: 1478) create table t6 (id int primary key) engine = innodb row_format = compressed; ERROR HY000: Can't create table 'test.t6' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table. Error 1005 Can't create table 'test.t6' (errno: 1478) create table t7 (id int primary key) engine = innodb row_format = dynamic; ERROR HY000: Can't create table 'test.t7' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table. +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table. Error 1005 Can't create table 'test.t7' (errno: 1478) create table t8 (id int primary key) engine = innodb row_format = compact; create table t9 (id int primary key) engine = innodb row_format = redundant; @@ -345,45 +345,45 @@ set global innodb_file_per_table = on; set global innodb_file_format = `0`; create table t1 (id int primary key) engine = innodb key_block_size = 1; ERROR HY000: Can't create table 'test.t1' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t1' (errno: 1478) create table t2 (id int primary key) engine = innodb key_block_size = 2; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t2' (errno: 1478) create table t3 (id int primary key) engine = innodb key_block_size = 4; ERROR HY000: Can't create table 'test.t3' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t3' (errno: 1478) create table t4 (id int primary key) engine = innodb key_block_size = 8; ERROR HY000: Can't create table 'test.t4' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t4' (errno: 1478) create table t5 (id int primary key) engine = innodb key_block_size = 16; ERROR HY000: Can't create table 'test.t5' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t5' (errno: 1478) create table t6 (id int primary key) engine = innodb row_format = compressed; ERROR HY000: Can't create table 'test.t6' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t6' (errno: 1478) create table t7 (id int primary key) engine = innodb row_format = dynamic; ERROR HY000: Can't create table 'test.t7' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t7' (errno: 1478) create table t8 (id int primary key) engine = innodb row_format = compact; create table t9 (id int primary key) engine = innodb row_format = redundant; diff --git a/mysql-test/innodb-zip.test b/mysql-test/innodb-zip.test index ddc39d44487..fdb9b89e37a 100644 --- a/mysql-test/innodb-zip.test +++ b/mysql-test/innodb-zip.test @@ -105,7 +105,7 @@ drop table t1; --error ER_TOO_BIG_ROWSIZE CREATE TABLE t1(c TEXT, PRIMARY KEY (c(440))) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII; -CREATE TABLE t1(c TEXT, PRIMARY KEY (c(439))) +CREATE TABLE t1(c TEXT, PRIMARY KEY (c(438))) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII; INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512)); DROP TABLE t1; @@ -174,11 +174,11 @@ set innodb_strict_mode = on; --error ER_CANT_CREATE_TABLE create table t1 (id int primary key) engine = innodb key_block_size = 0; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 9; -show errors; +show warnings; create table t3 (id int primary key) engine = innodb key_block_size = 1; @@ -204,22 +204,22 @@ key_block_size = 8 row_format = compressed; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 8 row_format = redundant; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t3 (id int primary key) engine = innodb key_block_size = 8 row_format = compact; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t4 (id int primary key) engine = innodb key_block_size = 8 row_format = dynamic; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t5 (id int primary key) engine = innodb key_block_size = 8 row_format = default; -show errors; +show warnings; SELECT table_schema, table_name, row_format FROM information_schema.tables WHERE engine='innodb'; @@ -229,17 +229,17 @@ drop table t1; --error ER_CANT_CREATE_TABLE create table t1 (id int primary key) engine = innodb key_block_size = 9 row_format = redundant; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 9 row_format = compact; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 9 row_format = dynamic; -show errors; +show warnings; SELECT table_schema, table_name, row_format FROM information_schema.tables WHERE engine='innodb'; @@ -249,25 +249,25 @@ set global innodb_file_per_table = off; --error ER_CANT_CREATE_TABLE create table t1 (id int primary key) engine = innodb key_block_size = 1; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 2; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t3 (id int primary key) engine = innodb key_block_size = 4; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t4 (id int primary key) engine = innodb key_block_size = 8; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t5 (id int primary key) engine = innodb key_block_size = 16; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t6 (id int primary key) engine = innodb row_format = compressed; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t7 (id int primary key) engine = innodb row_format = dynamic; -show errors; +show warnings; create table t8 (id int primary key) engine = innodb row_format = compact; create table t9 (id int primary key) engine = innodb row_format = redundant; @@ -281,25 +281,25 @@ set global innodb_file_format = `0`; --error ER_CANT_CREATE_TABLE create table t1 (id int primary key) engine = innodb key_block_size = 1; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 2; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t3 (id int primary key) engine = innodb key_block_size = 4; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t4 (id int primary key) engine = innodb key_block_size = 8; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t5 (id int primary key) engine = innodb key_block_size = 16; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t6 (id int primary key) engine = innodb row_format = compressed; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t7 (id int primary key) engine = innodb row_format = dynamic; -show errors; +show warnings; create table t8 (id int primary key) engine = innodb row_format = compact; create table t9 (id int primary key) engine = innodb row_format = redundant; diff --git a/mysql-test/innodb.result b/mysql-test/innodb.result index bdae7633fd1..6cdaeb5dd3c 100644 --- a/mysql-test/innodb.result +++ b/mysql-test/innodb.result @@ -1970,7 +1970,7 @@ explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref v v 13 const # Using where; Using index alter table t1 add unique(v); -ERROR 23000: Duplicate entry 'v' for key 'v_2' +ERROR 23000: Duplicate entry '{ ' for key 'v_2' alter table t1 add key(v); select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a'; qq @@ -3088,7 +3088,7 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction commit; drop table t1, t2, t3, t5, t6, t8, t9; CREATE TABLE t1 (DB_ROW_ID int) engine=innodb; -ERROR HY000: Can't create table 'test.t1' (errno: -1) +ERROR 42000: Incorrect column name 'DB_ROW_ID' CREATE TABLE t1 ( a BIGINT(20) NOT NULL, PRIMARY KEY (a) diff --git a/mysql-test/innodb.test b/mysql-test/innodb.test index f46a3a70b56..fe588316535 100644 --- a/mysql-test/innodb.test +++ b/mysql-test/innodb.test @@ -2264,7 +2264,7 @@ disconnect j; drop table t1, t2, t3, t5, t6, t8, t9; # bug 18934, "InnoDB crashes when table uses column names like DB_ROW_ID" ---error 1005 +--error ER_WRONG_COLUMN_NAME CREATE TABLE t1 (DB_ROW_ID int) engine=innodb; # diff --git a/mysql-test/innodb_bug34300.test b/mysql-test/innodb_bug34300.test index 14918f55490..68c385fd72a 100644 --- a/mysql-test/innodb_bug34300.test +++ b/mysql-test/innodb_bug34300.test @@ -9,6 +9,7 @@ -- disable_result_log # set packet size and reconnect +let $max_packet=`select @@global.max_allowed_packet`; SET @@global.max_allowed_packet=16777216; --connect (newconn, localhost, root,,) @@ -30,4 +31,4 @@ ALTER TABLE bug34300 ADD COLUMN (f10 INT); SELECT f4, f8 FROM bug34300; DROP TABLE bug34300; -SET @@global.max_allowed_packet=1048576; +EVAL SET @@global.max_allowed_packet=$max_packet; diff --git a/mysql-test/innodb_bug36169.result b/mysql-test/innodb_bug36169.result index 0f43ab23f7a..aa80e4d7aa4 100644 --- a/mysql-test/innodb_bug36169.result +++ b/mysql-test/innodb_bug36169.result @@ -1,4 +1,2 @@ -set @old_innodb_file_format=@@innodb_file_format; -set @old_innodb_file_per_table=@@innodb_file_per_table; SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_per_table=ON; diff --git a/mysql-test/innodb_bug36169.test b/mysql-test/innodb_bug36169.test index 22a2f6ddada..5bf55193b5c 100644 --- a/mysql-test/innodb_bug36169.test +++ b/mysql-test/innodb_bug36169.test @@ -4,9 +4,9 @@ # -- source include/have_innodb.inc -set @old_innodb_file_format=@@innodb_file_format; -set @old_innodb_file_per_table=@@innodb_file_per_table; +let $file_format=`select @@innodb_file_format`; +let $file_per_table=`select @@innodb_file_per_table`; SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_per_table=ON; @@ -1155,5 +1155,5 @@ DROP TABLE IF EXISTS table4; DROP TABLE IF EXISTS table5; DROP TABLE IF EXISTS table6; -set global innodb_file_format=@old_innodb_file_format; -set global innodb_file_per_table=@old_innodb_file_per_table; +EVAL SET GLOBAL innodb_file_format=$file_format; +EVAL SET GLOBAL innodb_file_per_table=$file_per_table; diff --git a/mysql-test/innodb_bug36172.test b/mysql-test/innodb_bug36172.test index d2e79a90710..c6c4e6fae47 100644 --- a/mysql-test/innodb_bug36172.test +++ b/mysql-test/innodb_bug36172.test @@ -13,9 +13,10 @@ SET storage_engine=InnoDB; -- disable_query_log -- disable_result_log -set @old_innodb_file_per_table=@@innodb_file_per_table; -set @old_innodb_file_format=@@innodb_file_format; +let $file_format=`select @@innodb_file_format`; +let $file_format_check=`select @@innodb_file_format_check`; +let $file_per_table=`select @@innodb_file_per_table`; SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_per_table=on; @@ -26,6 +27,6 @@ CHECK TABLE table0 EXTENDED; INSERT IGNORE INTO `table0` SET `col19` = '19940127002709', `col20` = 2383927.9055146948, `col21` = 4293243420.5621204000, `col22` = '20511211123705', `col23` = 4289899778.6573381000, `col24` = 4293449279.0540481000, `col25` = 'emphysemic', `col26` = 'dentally', `col27` = '2347406', `col28` = 'eruct', `col30` = 1222, `col31` = 4294372994.9941406000, `col32` = 4291385574.1173744000, `col33` = 'borrowing\'s', `col34` = 'septics', `col35` = 'ratter\'s', `col36` = 'Kaye', `col37` = 'Florentia', `col38` = 'allium', `col39` = 'barkeep', `col40` = '19510407003441', `col41` = 4293559200.4215522000, `col42` = 22482, `col43` = 'decussate', `col44` = 'Brom\'s', `col45` = 'violated', `col46` = 4925506.4635456400, `col47` = 930549, `col48` = '51296066', `col49` = 'voluminously', `col50` = '29306676', `col51` = -88, `col52` = -2153690, `col53` = 4290250202.1464887000, `col54` = 'expropriation', `col55` = 'Aberdeen\'s', `col56` = 20343, `col58` = '19640415171532', `col59` = 'extern', `col60` = 'Ubana', `col61` = 4290487961.8539081000, `col62` = '2147', `col63` = -24271, `col64` = '20750801194548', `col65` = 'Cunaxa\'s', `col66` = 'pasticcio', `col67` = 2795817, `col68` = 'Indore\'s', `col70` = 6864127, `col71` = '1817832', `col72` = '20540506114211', `col73` = '20040101012300', `col74` = 'rationalized', `col75` = '45522', `col76` = 'indene', `col77` = -6964559, `col78` = 4247535.5266884370, `col79` = '20720416124357', `col80` = '2143', `col81` = 4292060102.4466386000, `col82` = 'striving', `col83` = 'boneblack\'s', `col84` = 'redolent', `col85` = 6489697.9009369183, `col86` = 4287473465.9731131000, `col87` = 7726015, `col88` = 'perplexed', `col89` = '17153791', `col90` = 5478587.1108127078, `col91` = 4287091404.7004304000, `col92` = 'Boulez\'s', `col93` = '2931278'; CHECK TABLE table0 EXTENDED; DROP TABLE table0; -set global innodb_file_per_table=@old_innodb_file_per_table; -set global innodb_file_format=@old_innodb_file_format; -set global innodb_file_format_check=Antelope; +EVAL SET GLOBAL innodb_file_format=$file_format; +EVAL SET GLOBAL innodb_file_format_check=$file_format_check; +EVAL SET GLOBAL innodb_file_per_table=$file_per_table; diff --git a/mysql-test/innodb_bug42101-nonzero-master.opt b/mysql-test/innodb_bug42101-nonzero-master.opt index d71dbe17d5b..455d66a06b8 100644 --- a/mysql-test/innodb_bug42101-nonzero-master.opt +++ b/mysql-test/innodb_bug42101-nonzero-master.opt @@ -1 +1 @@ ---innodb_commit_concurrency=1 +--loose_innodb_commit_concurrency=1 diff --git a/mysql-test/innodb_bug44369.result b/mysql-test/innodb_bug44369.result new file mode 100644 index 00000000000..ff25c774aa2 --- /dev/null +++ b/mysql-test/innodb_bug44369.result @@ -0,0 +1,6 @@ +create table bug44369 (DB_ROW_ID int) engine=innodb; +ERROR 42000: Incorrect column name 'DB_ROW_ID' +create table bug44369 (db_row_id int) engine=innodb; +ERROR 42000: Incorrect column name 'db_row_id' +create table bug44369 (db_TRX_Id int) engine=innodb; +ERROR 42000: Incorrect column name 'db_TRX_Id' diff --git a/mysql-test/innodb_bug44369.test b/mysql-test/innodb_bug44369.test new file mode 100644 index 00000000000..f5d85cd5815 --- /dev/null +++ b/mysql-test/innodb_bug44369.test @@ -0,0 +1,17 @@ +# This is the test for bug 44369. We should +# block table creation with columns match +# some innodb internal reserved key words, +# both case sensitively and insensitely. + +--source include/have_innodb.inc + +# This create table operation should fail. +--error ER_WRONG_COLUMN_NAME +create table bug44369 (DB_ROW_ID int) engine=innodb; + +# This create should fail as well +--error ER_WRONG_COLUMN_NAME +create table bug44369 (db_row_id int) engine=innodb; + +--error ER_WRONG_COLUMN_NAME +create table bug44369 (db_TRX_Id int) engine=innodb; diff --git a/mysql-test/innodb_bug44571.result b/mysql-test/innodb_bug44571.result new file mode 100644 index 00000000000..955b55ac673 --- /dev/null +++ b/mysql-test/innodb_bug44571.result @@ -0,0 +1,7 @@ +CREATE TABLE bug44571 (foo INT) ENGINE=InnoDB; +ALTER TABLE bug44571 CHANGE foo bar INT; +ALTER TABLE bug44571 ADD INDEX bug44571b (foo); +ERROR 42000: Key column 'foo' doesn't exist in table +ALTER TABLE bug44571 ADD INDEX bug44571b (bar); +CREATE INDEX bug44571c ON bug44571 (bar); +DROP TABLE bug44571; diff --git a/mysql-test/innodb_bug44571.test b/mysql-test/innodb_bug44571.test new file mode 100644 index 00000000000..f5d79e3070a --- /dev/null +++ b/mysql-test/innodb_bug44571.test @@ -0,0 +1,13 @@ +# +# Bug#44571 InnoDB Plugin crashes on ADD INDEX +# http://bugs.mysql.com/44571 +# +-- source include/have_innodb.inc + +CREATE TABLE bug44571 (foo INT) ENGINE=InnoDB; +ALTER TABLE bug44571 CHANGE foo bar INT; +-- error ER_KEY_COLUMN_DOES_NOT_EXITS +ALTER TABLE bug44571 ADD INDEX bug44571b (foo); +ALTER TABLE bug44571 ADD INDEX bug44571b (bar); +CREATE INDEX bug44571c ON bug44571 (bar); +DROP TABLE bug44571; diff --git a/mysql-test/innodb_bug46000.result b/mysql-test/innodb_bug46000.result new file mode 100644 index 00000000000..c8e3db8d641 --- /dev/null +++ b/mysql-test/innodb_bug46000.result @@ -0,0 +1,19 @@ +create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb; +ERROR 42000: Incorrect index name 'GEN_CLUST_INDEX' +create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb; +ERROR 42000: Incorrect index name 'GEN_CLUST_INDEX' +show warnings; +Level Code Message +Warning 1280 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index. +Error 1280 Incorrect index name 'GEN_CLUST_INDEX' +Error 1005 Can't create table 'test.bug46000' (errno: -1) +create table bug46000(id int) engine=innodb; +create index GEN_CLUST_INDEX on bug46000(id); +ERROR 42000: Incorrect index name 'GEN_CLUST_INDEX' +show warnings; +Level Code Message +Warning 1280 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index. +Error 1280 Incorrect index name 'GEN_CLUST_INDEX' +Error 1030 Got error -1 from storage engine +create index idx on bug46000(id); +drop table bug46000; diff --git a/mysql-test/innodb_bug46000.test b/mysql-test/innodb_bug46000.test new file mode 100644 index 00000000000..5a3c666326e --- /dev/null +++ b/mysql-test/innodb_bug46000.test @@ -0,0 +1,32 @@ +# This is the test for bug 46000. We shall +# block any index creation with the name of +# "GEN_CLUST_INDEX", which is the reserved +# name for innodb default primary index. + +--source include/have_innodb.inc + +# This 'create table' operation should fail because of +# using the reserve name as its index name. +--error ER_WRONG_NAME_FOR_INDEX +create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb; + +# Mixed upper/lower case of the reserved key words +--error ER_WRONG_NAME_FOR_INDEX +create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb; + +show warnings; + +create table bug46000(id int) engine=innodb; + +# This 'create index' operation should fail. +--error ER_WRONG_NAME_FOR_INDEX +create index GEN_CLUST_INDEX on bug46000(id); + +show warnings; + +# This 'create index' operation should succeed, no +# temp table left from last failed create index +# operation. +create index idx on bug46000(id); + +drop table bug46000; diff --git a/mysql-test/innodb_bug46676.result b/mysql-test/innodb_bug46676.result new file mode 100644 index 00000000000..996799ce931 --- /dev/null +++ b/mysql-test/innodb_bug46676.result @@ -0,0 +1,9 @@ +SET foreign_key_checks=0; +CREATE TABLE t1 (id int, foreign key (id) references t2(id)) ENGINE=INNODB; +CREATE TABLE t2 (id int, foreign key (id) references t1(id)) ENGINE=INNODB; +SET foreign_key_checks=1; +SELECT COUNT(*) FROM information_schema.key_column_usage WHERE REFERENCED_TABLE_NAME in ('t1', 't2'); +COUNT(*) +2 +SET foreign_key_checks=0; +DROP TABLE t1, t2; diff --git a/mysql-test/innodb_bug46676.test b/mysql-test/innodb_bug46676.test new file mode 100644 index 00000000000..440666c4226 --- /dev/null +++ b/mysql-test/innodb_bug46676.test @@ -0,0 +1,16 @@ +# This is the test for bug 46676: mysqld got exception 0xc0000005 +# It is reproducible with InnoDB plugin 1.0.4 + MySQL 5.1.37. +# But no longer reproducible after MySQL 5.1.38 (with plugin 1.0.5). + +--source include/have_innodb.inc + +SET foreign_key_checks=0; +CREATE TABLE t1 (id int, foreign key (id) references t2(id)) ENGINE=INNODB; +CREATE TABLE t2 (id int, foreign key (id) references t1(id)) ENGINE=INNODB; +SET foreign_key_checks=1; + +# Server crashes +SELECT COUNT(*) FROM information_schema.key_column_usage WHERE REFERENCED_TABLE_NAME in ('t1', 't2'); + +SET foreign_key_checks=0; +DROP TABLE t1, t2; diff --git a/mysql-test/innodb_bug47167.result b/mysql-test/innodb_bug47167.result new file mode 100644 index 00000000000..cbec363d78f --- /dev/null +++ b/mysql-test/innodb_bug47167.result @@ -0,0 +1,24 @@ +set @old_innodb_file_format_check=@@innodb_file_format_check; +select @old_innodb_file_format_check; +@old_innodb_file_format_check +Antelope +set global innodb_file_format_check = Barracuda; +select @@innodb_file_format_check; +@@innodb_file_format_check +Barracuda +set global innodb_file_format_check = DEFAULT; +select @@innodb_file_format_check; +@@innodb_file_format_check +Barracuda +set global innodb_file_format_check = @old_innodb_file_format_check; +select @@innodb_file_format_check; +@@innodb_file_format_check +Antelope +set global innodb_file_format_check = cheetah; +ERROR HY000: Incorrect arguments to SET +set global innodb_file_format_check = Bear; +ERROR HY000: Incorrect arguments to SET +set global innodb_file_format_check = on; +ERROR HY000: Incorrect arguments to SET +set global innodb_file_format_check = off; +ERROR HY000: Incorrect arguments to SET diff --git a/mysql-test/innodb_bug47167.test b/mysql-test/innodb_bug47167.test new file mode 100644 index 00000000000..88e927c01bd --- /dev/null +++ b/mysql-test/innodb_bug47167.test @@ -0,0 +1,45 @@ +# This is the unit test for bug *47167. +# It tests setting the global variable +# "innodb_file_format_check" with a +# user-Defined Variable. + +--source include/have_innodb.inc + +# Save the value (Antelope) in 'innodb_file_format_check' to +# 'old_innodb_file_format_check' +set @old_innodb_file_format_check=@@innodb_file_format_check; + +# @old_innodb_file_format_check shall have the value of 'Antelope' +select @old_innodb_file_format_check; + +# Reset the value in 'innodb_file_format_check' to 'Barracuda' +set global innodb_file_format_check = Barracuda; + +select @@innodb_file_format_check; + +# Set 'innodb_file_format_check' to its default value, which +# is the latest file format supported in the current release. +set global innodb_file_format_check = DEFAULT; + +select @@innodb_file_format_check; + +# Put the saved value back to 'innodb_file_format_check' +set global innodb_file_format_check = @old_innodb_file_format_check; + +# Check whether 'innodb_file_format_check' get its original value. +select @@innodb_file_format_check; + +# Following are negative tests, all should fail. +--disable_warnings +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = cheetah; + +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = Bear; + +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = on; + +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = off; +--enable_warnings diff --git a/mysql-test/innodb_bug47777.result b/mysql-test/innodb_bug47777.result new file mode 100644 index 00000000000..fbba47edcfc --- /dev/null +++ b/mysql-test/innodb_bug47777.result @@ -0,0 +1,13 @@ +create table bug47777(c2 linestring not null, primary key (c2(1))) engine=innodb; +insert into bug47777 values (geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)')); +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +count(*) +1 +update bug47777 set c2=GeomFromText('POINT(1 1)'); +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +count(*) +0 +select count(*) from bug47777 where c2 = GeomFromText('POINT(1 1)'); +count(*) +1 +drop table bug47777; diff --git a/mysql-test/innodb_bug47777.test b/mysql-test/innodb_bug47777.test new file mode 100644 index 00000000000..8f2985b2cf0 --- /dev/null +++ b/mysql-test/innodb_bug47777.test @@ -0,0 +1,24 @@ +# This is the test for bug 47777. GEOMETRY +# data is treated as BLOB data in innodb. +# Consequently, its key value generation/storing +# should follow the process for the BLOB +# datatype as well. + +--source include/have_innodb.inc + +create table bug47777(c2 linestring not null, primary key (c2(1))) engine=innodb; + +insert into bug47777 values (geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)')); + +# Verify correct row get inserted. +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); + +# Update table bug47777 should be successful. +update bug47777 set c2=GeomFromText('POINT(1 1)'); + +# Verify the row get updated successfully. The original +# c2 value should be changed to GeomFromText('POINT(1 1)'). +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +select count(*) from bug47777 where c2 = GeomFromText('POINT(1 1)'); + +drop table bug47777; diff --git a/mysql-test/innodb_file_format.result b/mysql-test/innodb_file_format.result index fbc67ada1bb..86d60706084 100644 --- a/mysql-test/innodb_file_format.result +++ b/mysql-test/innodb_file_format.result @@ -1,4 +1,3 @@ -call mtr.add_suppression("InnoDB: invalid innodb_file_format_check value"); select @@innodb_file_format; @@innodb_file_format Antelope @@ -31,8 +30,6 @@ select @@innodb_file_format_check; @@innodb_file_format_check Barracuda set global innodb_file_format_check=default; -Warnings: -Warning 1210 Ignoring SET innodb_file_format=on select @@innodb_file_format_check; @@innodb_file_format_check Barracuda @@ -43,3 +40,4 @@ ERROR HY000: Incorrect arguments to SET select @@innodb_file_format_check; @@innodb_file_format_check Barracuda +set global innodb_file_format_check=antelope; diff --git a/mysql-test/innodb_file_format.test b/mysql-test/innodb_file_format.test index 3bd1dd2fa6f..d63c9b0228f 100644 --- a/mysql-test/innodb_file_format.test +++ b/mysql-test/innodb_file_format.test @@ -1,10 +1,5 @@ -- source include/have_innodb.inc -call mtr.add_suppression("InnoDB: invalid innodb_file_format_check value"); - -let $format=`select @@innodb_file_format`; -let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; - select @@innodb_file_format; select @@innodb_file_format_check; set global innodb_file_format=antelope; @@ -31,12 +26,4 @@ set global innodb_file_format=on; --error ER_WRONG_ARGUMENTS set global innodb_file_format=off; select @@innodb_file_format_check; - -# -# restore environment to the state it was before this test execution -# - --- disable_query_log -eval set global innodb_file_format=$format; -eval set global innodb_file_format_check=$innodb_file_format_check_orig; --- enable_query_log +set global innodb_file_format_check=antelope; diff --git a/mysql-test/innodb_information_schema.test b/mysql-test/innodb_information_schema.test index eaed653854a..fc1d38d8d14 100644 --- a/mysql-test/innodb_information_schema.test +++ b/mysql-test/innodb_information_schema.test @@ -109,14 +109,18 @@ SELECT * FROM ```t'\"_str` WHERE c1 = '3' FOR UPDATE; -- send SELECT * FROM ```t'\"_str` WHERE c1 = '4' FOR UPDATE; -# Give time to the above 2 queries to execute before continuing. -# Without this sleep it sometimes happens that the SELECT from innodb_locks -# executes before some of them, resulting in less than expected number -# of rows being selected from innodb_locks. --- sleep 0.1 - -- enable_result_log -- connection con_verify_innodb_locks +# Wait for the above queries to execute before continuing. +# Without this, it sometimes happens that the SELECT from innodb_locks +# executes before some of them, resulting in less than expected number +# of rows being selected from innodb_locks. If there is a bug and there +# are no 14 rows in innodb_locks then this test will fail with timeout. +let $count = 14; +let $table = INFORMATION_SCHEMA.INNODB_LOCKS; +-- source include/wait_until_rows_count.inc +# the above enables the query log, re-disable it +-- disable_query_log SELECT lock_mode, lock_type, lock_table, lock_index, lock_rec, lock_data FROM INFORMATION_SCHEMA.INNODB_LOCKS ORDER BY lock_data; diff --git a/mysql-test/patches/disabled.def.diff b/mysql-test/patches/disabled.def.diff index b8b3ed2d02d..58466e2b6db 100644 --- a/mysql-test/patches/disabled.def.diff +++ b/mysql-test/patches/disabled.def.diff @@ -1,8 +1,8 @@ ---- mysql-test/t/disabled.def.orig 2009-10-25 05:54:05.000000000 +0000 -+++ mysql-test/t/disabled.def 2009-10-25 05:54:25.000000000 +0000 -@@ -14,3 +14,5 @@ +--- mysql-test/t/disabled.def.orig 2009-12-16 13:21:00.000000000 -0500 ++++ mysql-test/t/disabled.def 2010-01-03 11:58:54.000000000 -0500 +@@ -13,3 +13,5 @@ query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically - partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes - partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes + rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2 + innodb-autoinc : Bug#49267 2009-12-02 test fails on windows because of different case mode +read_many_rows_innodb : Bug#433409 2009-09-20 the test fails on 5.1.37 https://bugs.launchpad.net/bugs/433409 -+innodb-zip : Bug#47495 2009-09-21 the test fails on ubuntu ++log_tables-big : Bug#48646 2009-12-12 mysql-test main.log_tables-big fails on 5.1.40 diff --git a/mysql-test/patches/index_merge_innodb-explain.diff b/mysql-test/patches/index_merge_innodb-explain.diff new file mode 100644 index 00000000000..d1ed8afc778 --- /dev/null +++ b/mysql-test/patches/index_merge_innodb-explain.diff @@ -0,0 +1,31 @@ +InnoDB's estimate for the index cardinality depends on a pseudo random +number generator (it picks up random pages to sample). After an +optimization that was made in r2625 the following EXPLAINs started +returning a different number of rows (3 instead of 4). + +This patch adjusts the result file. + +This patch cannot be proposed to MySQL because the failures occur only +in this tree and do not occur in the standard InnoDB 5.1. Furthermore, +the file index_merge2.inc is used by other engines too. + +--- mysql-test/r/index_merge_innodb.result.orig 2008-09-30 18:32:13.000000000 +0300 ++++ mysql-test/r/index_merge_innodb.result 2008-09-30 18:33:01.000000000 +0300 +@@ -111,7 +111,7 @@ + explain select count(*) from t1 where + key1a = 2 and key1b is null and key2a = 2 and key2b is null; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 4 Using intersect(i1,i2); Using where; Using index ++1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 3 Using intersect(i1,i2); Using where; Using index + select count(*) from t1 where + key1a = 2 and key1b is null and key2a = 2 and key2b is null; + count(*) +@@ -119,7 +119,7 @@ + explain select count(*) from t1 where + key1a = 2 and key1b is null and key3a = 2 and key3b is null; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 4 Using intersect(i1,i3); Using where; Using index ++1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 3 Using intersect(i1,i3); Using where; Using index + select count(*) from t1 where + key1a = 2 and key1b is null and key3a = 2 and key3b is null; + count(*) diff --git a/mysql-test/patches/index_merge_innodb.diff b/mysql-test/patches/index_merge_innodb.diff deleted file mode 100644 index 3abfd0df523..00000000000 --- a/mysql-test/patches/index_merge_innodb.diff +++ /dev/null @@ -1,57 +0,0 @@ ---- mysql-test/r/index_merge_innodb.result.orig 2009-09-19 20:51:58.000000000 +0000 -+++ mysql-test/r/index_merge_innodb.result 2009-09-19 20:52:25.000000000 +0000 -@@ -111,7 +111,7 @@ - explain select count(*) from t1 where - key1a = 2 and key1b is null and key2a = 2 and key2b is null; - id select_type table type possible_keys key key_len ref rows Extra --1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 4 Using intersect(i1,i2); Using where; Using index -+1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL REF Using intersect(i1,i2); Using where; Using index - select count(*) from t1 where - key1a = 2 and key1b is null and key2a = 2 and key2b is null; - count(*) -@@ -119,7 +119,7 @@ - explain select count(*) from t1 where - key1a = 2 and key1b is null and key3a = 2 and key3b is null; - id select_type table type possible_keys key key_len ref rows Extra --1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 4 Using intersect(i1,i3); Using where; Using index -+1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL REF Using intersect(i1,i3); Using where; Using index - select count(*) from t1 where - key1a = 2 and key1b is null and key3a = 2 and key3b is null; - count(*) ---- mysql-test/include/index_merge2.inc.orig 2009-09-19 20:50:04.000000000 +0000 -+++ mysql-test/include/index_merge2.inc 2009-09-19 21:03:11.000000000 +0000 -@@ -122,12 +122,14 @@ - analyze table t1; - select count(*) from t1; - -+--replace_column 9 REF - explain select count(*) from t1 where - key1a = 2 and key1b is null and key2a = 2 and key2b is null; - - select count(*) from t1 where - key1a = 2 and key1b is null and key2a = 2 and key2b is null; - -+--replace_column 9 REF - explain select count(*) from t1 where - key1a = 2 and key1b is null and key3a = 2 and key3b is null; - ---- mysql-test/r/index_merge_myisam.result.orig 2009-09-20 07:00:29.000000000 +0000 -+++ mysql-test/r/index_merge_myisam.result 2009-09-20 07:00:48.000000000 +0000 -@@ -945,7 +945,7 @@ - explain select count(*) from t1 where - key1a = 2 and key1b is null and key2a = 2 and key2b is null; - id select_type table type possible_keys key key_len ref rows Extra --1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 2 Using intersect(i1,i2); Using where; Using index -+1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL REF Using intersect(i1,i2); Using where; Using index - select count(*) from t1 where - key1a = 2 and key1b is null and key2a = 2 and key2b is null; - count(*) -@@ -953,7 +953,7 @@ - explain select count(*) from t1 where - key1a = 2 and key1b is null and key3a = 2 and key3b is null; - id select_type table type possible_keys key key_len ref rows Extra --1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 2 Using intersect(i1,i3); Using where; Using index -+1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL REF Using intersect(i1,i3); Using where; Using index - select count(*) from t1 where - key1a = 2 and key1b is null and key3a = 2 and key3b is null; - count(*) diff --git a/mysql-test/patches/information_schema.diff b/mysql-test/patches/information_schema.diff index 38111fbbe98..a91eac75cff 100644 --- a/mysql-test/patches/information_schema.diff +++ b/mysql-test/patches/information_schema.diff @@ -1,5 +1,5 @@ ---- mysql-test/r/information_schema.result.orig 2009-11-09 11:19:50.000000000 -0800 -+++ mysql-test/r/information_schema.result 2009-11-09 11:21:21.000000000 -0800 +--- mysql-test/r/information_schema.result.orig 2009-12-04 16:08:19.000000000 +0900 ++++ mysql-test/r/information_schema.result 2009-12-04 16:09:12.000000000 +0900 @@ -71,6 +71,21 @@ TRIGGERS USER_PRIVILEGES @@ -130,3 +130,73 @@ create table t1(f1 int); create view v1 as select f1+1 as a from t1; create table t2 (f1 int, f2 int); +--- mysql-test/r/information_schema_db.result.orig 2009-12-04 16:08:03.000000000 +0900 ++++ mysql-test/r/information_schema_db.result 2009-12-04 16:09:28.000000000 +0900 +@@ -33,6 +33,21 @@ + TRIGGERS + USER_PRIVILEGES + VIEWS ++INNODB_BUFFER_POOL_PAGES_INDEX ++INNODB_RSEG ++INNODB_LOCKS ++INNODB_BUFFER_POOL_PAGES ++XTRADB_ENHANCEMENTS ++INNODB_TRX ++XTRADB_ADMIN_COMMAND ++INNODB_LOCK_WAITS ++INNODB_CMP_RESET ++INNODB_CMP ++INNODB_CMPMEM_RESET ++INNODB_TABLE_STATS ++INNODB_CMPMEM ++INNODB_INDEX_STATS ++INNODB_BUFFER_POOL_PAGES_BLOB + show tables from INFORMATION_SCHEMA like 'T%'; + Tables_in_information_schema (T%) + TABLES +--- mysql-test/r/mysqlshow.result.orig 2009-12-04 16:07:43.000000000 +0900 ++++ mysql-test/r/mysqlshow.result 2009-12-04 16:09:40.000000000 +0900 +@@ -107,6 +107,21 @@ + | TRIGGERS | + | USER_PRIVILEGES | + | VIEWS | ++| INNODB_BUFFER_POOL_PAGES_INDEX | ++| INNODB_RSEG | ++| INNODB_LOCKS | ++| INNODB_BUFFER_POOL_PAGES | ++| XTRADB_ENHANCEMENTS | ++| INNODB_TRX | ++| XTRADB_ADMIN_COMMAND | ++| INNODB_LOCK_WAITS | ++| INNODB_CMP_RESET | ++| INNODB_CMP | ++| INNODB_CMPMEM_RESET | ++| INNODB_TABLE_STATS | ++| INNODB_CMPMEM | ++| INNODB_INDEX_STATS | ++| INNODB_BUFFER_POOL_PAGES_BLOB | + +---------------------------------------+ + Database: INFORMATION_SCHEMA + +---------------------------------------+ +@@ -140,6 +155,21 @@ + | TRIGGERS | + | USER_PRIVILEGES | + | VIEWS | ++| INNODB_BUFFER_POOL_PAGES_INDEX | ++| INNODB_RSEG | ++| INNODB_LOCKS | ++| INNODB_BUFFER_POOL_PAGES | ++| XTRADB_ENHANCEMENTS | ++| INNODB_TRX | ++| XTRADB_ADMIN_COMMAND | ++| INNODB_LOCK_WAITS | ++| INNODB_CMP_RESET | ++| INNODB_CMP | ++| INNODB_CMPMEM_RESET | ++| INNODB_TABLE_STATS | ++| INNODB_CMPMEM | ++| INNODB_INDEX_STATS | ++| INNODB_BUFFER_POOL_PAGES_BLOB | + +---------------------------------------+ + Wildcard: inf_rmation_schema + +--------------------+ diff --git a/mysql-test/patches/information_schema_db.diff b/mysql-test/patches/information_schema_db.diff deleted file mode 100644 index 1f93612b318..00000000000 --- a/mysql-test/patches/information_schema_db.diff +++ /dev/null @@ -1,24 +0,0 @@ ---- mysql-test/r/information_schema_db.result.orig 2009-11-09 14:40:34.000000000 -0800 -+++ mysql-test/r/information_schema_db.result 2009-11-09 14:41:37.000000000 -0800 -@@ -33,6 +33,21 @@ - TRIGGERS - USER_PRIVILEGES - VIEWS -+INNODB_BUFFER_POOL_PAGES_INDEX -+INNODB_RSEG -+INNODB_LOCKS -+INNODB_BUFFER_POOL_PAGES -+XTRADB_ENHANCEMENTS -+INNODB_TRX -+XTRADB_ADMIN_COMMAND -+INNODB_LOCK_WAITS -+INNODB_CMP_RESET -+INNODB_CMP -+INNODB_CMPMEM_RESET -+INNODB_TABLE_STATS -+INNODB_CMPMEM -+INNODB_INDEX_STATS -+INNODB_BUFFER_POOL_PAGES_BLOB - show tables from INFORMATION_SCHEMA like 'T%'; - Tables_in_information_schema (T%) - TABLES diff --git a/mysql-test/patches/innodb_bug46000.diff b/mysql-test/patches/innodb_bug46000.diff deleted file mode 100644 index d57cbde387e..00000000000 --- a/mysql-test/patches/innodb_bug46000.diff +++ /dev/null @@ -1,26 +0,0 @@ ---- mysql-test/r/innodb_bug46000.result.orig 2009-10-07 03:21:43.000000000 +0900 -+++ mysql-test/r/innodb_bug46000.result 2009-10-28 14:08:55.000000000 +0900 -@@ -8,10 +8,10 @@ - Error 1005 Can't create table 'test.bug46000' (errno: -1) - create table bug46000(id int) engine=innodb; - create index GEN_CLUST_INDEX on bug46000(id); --ERROR HY000: Can't create table '#sql-temporary' (errno: -1) -+ERROR HY000: Got error 1005 from storage engine - show errors; - Level Code Message - Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index. --Error 1005 Can't create table '#sql-temporary' (errno: -1) -+Error 1030 Got error 1005 from storage engine - create index idx on bug46000(id); - drop table bug46000; ---- mysql-test/t/innodb_bug46000.test.orig 2009-10-07 03:21:12.000000000 +0900 -+++ mysql-test/t/innodb_bug46000.test 2009-10-28 14:08:37.000000000 +0900 -@@ -20,7 +20,7 @@ - - # This 'create index' operation should fail. - --replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/ ----error ER_CANT_CREATE_TABLE -+--error ER_GET_ERRNO - create index GEN_CLUST_INDEX on bug46000(id); - - --replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/ diff --git a/mysql-test/patches/mysqlshow.diff b/mysql-test/patches/mysqlshow.diff deleted file mode 100644 index 78965e75da4..00000000000 --- a/mysql-test/patches/mysqlshow.diff +++ /dev/null @@ -1,46 +0,0 @@ ---- mysql-test/r/mysqlshow.result.orig 2009-11-09 15:17:43.000000000 -0800 -+++ mysql-test/r/mysqlshow.result 2009-11-09 15:17:53.000000000 -0800 -@@ -107,6 +107,21 @@ - | TRIGGERS | - | USER_PRIVILEGES | - | VIEWS | -+| INNODB_BUFFER_POOL_PAGES_INDEX | -+| INNODB_RSEG | -+| INNODB_LOCKS | -+| INNODB_BUFFER_POOL_PAGES | -+| XTRADB_ENHANCEMENTS | -+| INNODB_TRX | -+| XTRADB_ADMIN_COMMAND | -+| INNODB_LOCK_WAITS | -+| INNODB_CMP_RESET | -+| INNODB_CMP | -+| INNODB_CMPMEM_RESET | -+| INNODB_TABLE_STATS | -+| INNODB_CMPMEM | -+| INNODB_INDEX_STATS | -+| INNODB_BUFFER_POOL_PAGES_BLOB | - +---------------------------------------+ - Database: INFORMATION_SCHEMA - +---------------------------------------+ -@@ -140,6 +155,21 @@ - | TRIGGERS | - | USER_PRIVILEGES | - | VIEWS | -+| INNODB_BUFFER_POOL_PAGES_INDEX | -+| INNODB_RSEG | -+| INNODB_LOCKS | -+| INNODB_BUFFER_POOL_PAGES | -+| XTRADB_ENHANCEMENTS | -+| INNODB_TRX | -+| XTRADB_ADMIN_COMMAND | -+| INNODB_LOCK_WAITS | -+| INNODB_CMP_RESET | -+| INNODB_CMP | -+| INNODB_CMPMEM_RESET | -+| INNODB_TABLE_STATS | -+| INNODB_CMPMEM | -+| INNODB_INDEX_STATS | -+| INNODB_BUFFER_POOL_PAGES_BLOB | - +---------------------------------------+ - Wildcard: inf_rmation_schema - +--------------------+ diff --git a/os/os0file.c b/os/os0file.c index 980c44df82a..d3b3edea29f 100644 --- a/os/os0file.c +++ b/os/os0file.c @@ -56,6 +56,8 @@ Created 10/21/1995 Heikki Tuuri #include "fil0fil.h" #include "buf0buf.h" #include "trx0sys.h" +#include "trx0trx.h" +#include "log0recv.h" #ifndef UNIV_HOTBACKUP # include "os0sync.h" # include "os0thread.h" @@ -89,7 +91,9 @@ UNIV_INTERN ibool os_do_not_call_flush_at_each_write = FALSE; /* We do not call os_file_flush in every os_file_write. */ #endif /* UNIV_DO_FLUSH */ -#ifndef UNIV_HOTBACKUP +#ifdef UNIV_HOTBACKUP +# define os_aio_use_native_aio FALSE +#else /* UNIV_HOTBACKUP */ /* We use these mutexes to protect lseek + file i/o operation, if the OS does not provide an atomic pread or pwrite, or similar */ #define OS_FILE_N_SEEK_MUTEXES 16 @@ -236,7 +240,7 @@ static ulint os_aio_n_segments = ULINT_UNDEFINED; /** If the following is TRUE, read i/o handler threads try to wait until a batch of new read requests have been posted */ static volatile ibool os_aio_recommend_sleep_for_read_threads = FALSE; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_HOTBACKUP */ UNIV_INTERN ulint os_n_file_reads = 0; UNIV_INTERN ulint os_bytes_read_since_printout = 0; @@ -353,6 +357,19 @@ os_file_get_last_error( " software or another instance\n" "InnoDB: of MySQL." " Please close it to get rid of this error.\n"); + } else if (err == ERROR_WORKING_SET_QUOTA + || err == ERROR_NO_SYSTEM_RESOURCES) { + fprintf(stderr, + "InnoDB: The error means that there are no" + " sufficient system resources or quota to" + " complete the operation.\n"); + } else if (err == ERROR_OPERATION_ABORTED) { + fprintf(stderr, + "InnoDB: The error means that the I/O" + " operation has been aborted\n" + "InnoDB: because of either a thread exit" + " or an application request.\n" + "InnoDB: Retry attempt is made.\n"); } else { fprintf(stderr, "InnoDB: Some operating system error numbers" @@ -374,6 +391,11 @@ os_file_get_last_error( } else if (err == ERROR_SHARING_VIOLATION || err == ERROR_LOCK_VIOLATION) { return(OS_FILE_SHARING_VIOLATION); + } else if (err == ERROR_WORKING_SET_QUOTA + || err == ERROR_NO_SYSTEM_RESOURCES) { + return(OS_FILE_INSUFFICIENT_RESOURCE); + } else if (err == ERROR_OPERATION_ABORTED) { + return(OS_FILE_OPERATION_ABORTED); } else { return(100 + err); } @@ -492,6 +514,14 @@ os_file_handle_error_cond_exit( os_thread_sleep(10000000); /* 10 sec */ return(TRUE); + } else if (err == OS_FILE_INSUFFICIENT_RESOURCE) { + + os_thread_sleep(100000); /* 100 ms */ + return(TRUE); + } else if (err == OS_FILE_OPERATION_ABORTED) { + + os_thread_sleep(100000); /* 100 ms */ + return(TRUE); } else { if (name) { fprintf(stderr, "InnoDB: File name %s\n", name); @@ -855,6 +885,23 @@ next_file: ret = stat(full_path, &statinfo); if (ret) { + + if (errno == ENOENT) { + /* readdir() returned a file that does not exist, + it must have been deleted in the meantime. Do what + would have happened if the file was deleted before + readdir() - ignore and go to the next entry. + If this is the last entry then info->name will still + contain the name of the deleted file when this + function returns, but this is not an issue since the + caller shouldn't be looking at info when end of + directory is returned. */ + + ut_free(full_path); + + goto next_file; + } + os_file_handle_error_no_exit(full_path, "stat"); ut_free(full_path); @@ -1283,6 +1330,7 @@ try_again: } #endif #ifdef UNIV_NON_BUFFERED_IO +# ifndef UNIV_HOTBACKUP if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) { /* Do not use unbuffered i/o to log files because value 2 denotes that we do not flush the log at every @@ -1291,10 +1339,14 @@ try_again: == SRV_WIN_IO_UNBUFFERED) { attributes = attributes | FILE_FLAG_NO_BUFFERING; } -#endif +# else /* !UNIV_HOTBACKUP */ + attributes = attributes | FILE_FLAG_NO_BUFFERING; +# endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_NON_BUFFERED_IO */ } else if (purpose == OS_FILE_NORMAL) { attributes = 0; #ifdef UNIV_NON_BUFFERED_IO +# ifndef UNIV_HOTBACKUP if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) { /* Do not use unbuffered i/o to log files because value 2 denotes that we do not flush the log at every @@ -1303,7 +1355,10 @@ try_again: == SRV_WIN_IO_UNBUFFERED) { attributes = attributes | FILE_FLAG_NO_BUFFERING; } -#endif +# else /* !UNIV_HOTBACKUP */ + attributes = attributes | FILE_FLAG_NO_BUFFERING; +# endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_NON_BUFFERED_IO */ } else { attributes = 0; ut_error; @@ -2064,11 +2119,13 @@ _os_file_pread( trx_t* trx) { off_t offs; +#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD) ssize_t n_bytes; - ulint sec; - ulint ms; - ib_uint64_t start_time; - ib_uint64_t finish_time; +#endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */ + ulint sec; + ulint ms; + ib_uint64_t start_time; + ib_uint64_t finish_time; ut_a((offset & 0xFFFFFFFFUL) == offset); @@ -2123,16 +2180,20 @@ _os_file_pread( { off_t ret_offset; ssize_t ret; +#ifndef UNIV_HOTBACKUP ulint i; +#endif /* !UNIV_HOTBACKUP */ os_mutex_enter(os_file_count_mutex); os_n_pending_reads++; os_mutex_exit(os_file_count_mutex); +#ifndef UNIV_HOTBACKUP /* Protect the seek / read operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; os_mutex_enter(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ ret_offset = lseek(file, offs, SEEK_SET); @@ -2142,7 +2203,9 @@ _os_file_pread( ret = read(file, buf, (ssize_t)n); } +#ifndef UNIV_HOTBACKUP os_mutex_exit(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ os_mutex_enter(os_file_count_mutex); os_n_pending_reads--; @@ -2227,16 +2290,20 @@ os_file_pwrite( #else { off_t ret_offset; +# ifndef UNIV_HOTBACKUP ulint i; +# endif /* !UNIV_HOTBACKUP */ os_mutex_enter(os_file_count_mutex); os_n_pending_writes++; os_mutex_exit(os_file_count_mutex); +# ifndef UNIV_HOTBACKUP /* Protect the seek / write operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; os_mutex_enter(os_file_seek_mutexes[i]); +# endif /* UNIV_HOTBACKUP */ ret_offset = lseek(file, offs, SEEK_SET); @@ -2262,7 +2329,9 @@ os_file_pwrite( # endif /* UNIV_DO_FLUSH */ func_exit: +# ifndef UNIV_HOTBACKUP os_mutex_exit(os_file_seek_mutexes[i]); +# endif /* !UNIV_HOTBACKUP */ os_mutex_enter(os_file_count_mutex); os_n_pending_writes--; @@ -2297,7 +2366,9 @@ _os_file_read( DWORD low; DWORD high; ibool retry; +#ifndef UNIV_HOTBACKUP ulint i; +#endif /* !UNIV_HOTBACKUP */ ut_a((offset & 0xFFFFFFFFUL) == offset); @@ -2316,16 +2387,20 @@ try_again: os_n_pending_reads++; os_mutex_exit(os_file_count_mutex); +#ifndef UNIV_HOTBACKUP /* Protect the seek / read operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; os_mutex_enter(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ ret2 = SetFilePointer(file, low, &high, FILE_BEGIN); if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) { +#ifndef UNIV_HOTBACKUP os_mutex_exit(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ os_mutex_enter(os_file_count_mutex); os_n_pending_reads--; @@ -2336,7 +2411,9 @@ try_again: ret = ReadFile(file, buf, (DWORD) n, &len, NULL); +#ifndef UNIV_HOTBACKUP os_mutex_exit(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ os_mutex_enter(os_file_count_mutex); os_n_pending_reads--; @@ -2345,7 +2422,7 @@ try_again: if (ret && len == n) { return(TRUE); } -#else +#else /* __WIN__ */ ibool retry; ssize_t ret; @@ -2364,7 +2441,7 @@ try_again: "InnoDB: Was only able to read %ld.\n", (ulong)n, (ulong)offset_high, (ulong)offset, (long)ret); -#endif +#endif /* __WIN__ */ #ifdef __WIN__ error_handling: #endif @@ -2413,7 +2490,9 @@ os_file_read_no_error_handling( DWORD low; DWORD high; ibool retry; +#ifndef UNIV_HOTBACKUP ulint i; +#endif /* !UNIV_HOTBACKUP */ ut_a((offset & 0xFFFFFFFFUL) == offset); @@ -2432,16 +2511,20 @@ try_again: os_n_pending_reads++; os_mutex_exit(os_file_count_mutex); +#ifndef UNIV_HOTBACKUP /* Protect the seek / read operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; os_mutex_enter(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ ret2 = SetFilePointer(file, low, &high, FILE_BEGIN); if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) { +#ifndef UNIV_HOTBACKUP os_mutex_exit(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ os_mutex_enter(os_file_count_mutex); os_n_pending_reads--; @@ -2452,7 +2535,9 @@ try_again: ret = ReadFile(file, buf, (DWORD) n, &len, NULL); +#ifndef UNIV_HOTBACKUP os_mutex_exit(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ os_mutex_enter(os_file_count_mutex); os_n_pending_reads--; @@ -2461,7 +2546,7 @@ try_again: if (ret && len == n) { return(TRUE); } -#else +#else /* __WIN__ */ ibool retry; ssize_t ret; @@ -2474,7 +2559,7 @@ try_again: return(TRUE); } -#endif +#endif /* __WIN__ */ #ifdef __WIN__ error_handling: #endif @@ -2533,9 +2618,11 @@ os_file_write( DWORD ret2; DWORD low; DWORD high; - ulint i; ulint n_retries = 0; ulint err; +#ifndef UNIV_HOTBACKUP + ulint i; +#endif /* !UNIV_HOTBACKUP */ ut_a((offset & 0xFFFFFFFF) == offset); @@ -2552,16 +2639,20 @@ retry: os_n_pending_writes++; os_mutex_exit(os_file_count_mutex); +#ifndef UNIV_HOTBACKUP /* Protect the seek / write operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; os_mutex_enter(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ ret2 = SetFilePointer(file, low, &high, FILE_BEGIN); if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) { +#ifndef UNIV_HOTBACKUP os_mutex_exit(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ os_mutex_enter(os_file_count_mutex); os_n_pending_writes--; @@ -2595,7 +2686,9 @@ retry: } # endif /* UNIV_DO_FLUSH */ +#ifndef UNIV_HOTBACKUP os_mutex_exit(os_file_seek_mutexes[i]); +#endif /* !UNIV_HOTBACKUP */ os_mutex_enter(os_file_count_mutex); os_n_pending_writes--; @@ -3021,6 +3114,34 @@ os_aio_array_create( return(array); } +/************************************************************************//** +Frees an aio wait array. */ +static +void +os_aio_array_free( +/*==============*/ + os_aio_array_t* array) /*!< in, own: array to free */ +{ +#ifdef WIN_ASYNC_IO + ulint i; + + for (i = 0; i < array->n_slots; i++) { + os_aio_slot_t* slot = os_aio_array_get_nth_slot(array, i); + os_event_free(slot->event); + } +#endif /* WIN_ASYNC_IO */ + +#ifdef __WIN__ + ut_free(array->native_events); +#endif /* __WIN__ */ + os_mutex_free(array->mutex); + os_event_free(array->not_full); + os_event_free(array->is_empty); + + ut_free(array->slots); + ut_free(array); +} + /*********************************************************************** Initializes the asynchronous io system. Creates one array each for ibuf and log i/o. Also creates one array each for read and write where each @@ -3094,6 +3215,35 @@ os_aio_init( } +/*********************************************************************** +Frees the asynchronous io system. */ +UNIV_INTERN +void +os_aio_free(void) +/*=============*/ +{ + ulint i; + + os_aio_array_free(os_aio_ibuf_array); + os_aio_ibuf_array = NULL; + os_aio_array_free(os_aio_log_array); + os_aio_log_array = NULL; + os_aio_array_free(os_aio_read_array); + os_aio_read_array = NULL; + os_aio_array_free(os_aio_write_array); + os_aio_write_array = NULL; + os_aio_array_free(os_aio_sync_array); + os_aio_sync_array = NULL; + + for (i = 0; i < os_aio_n_segments; i++) { + os_event_free(os_aio_segment_wait_events[i]); + } + + ut_free(os_aio_segment_wait_events); + os_aio_segment_wait_events = 0; + os_aio_n_segments = 0; +} + #ifdef WIN_ASYNC_IO /************************************************************************//** Wakes up all async i/o threads in the array in Windows async i/o at @@ -3466,9 +3616,21 @@ void os_aio_simulated_put_read_threads_to_sleep(void) /*============================================*/ { + +/* The idea of putting background IO threads to sleep is only for +Windows when using simulated AIO. Windows XP seems to schedule +background threads too eagerly to allow for coalescing during +readahead requests. */ +#ifdef __WIN__ os_aio_array_t* array; ulint g; + if (os_aio_use_native_aio) { + /* We do not use simulated aio: do nothing */ + + return; + } + os_aio_recommend_sleep_for_read_threads = TRUE; for (g = 0; g < os_aio_n_segments; g++) { @@ -3479,6 +3641,7 @@ os_aio_simulated_put_read_threads_to_sleep(void) os_event_reset(os_aio_segment_wait_events[g]); } } +#endif /* __WIN__ */ } /*******************************************************************//** @@ -3719,6 +3882,7 @@ os_aio_windows_handle( ibool ret_val; BOOL ret; DWORD len; + BOOL retry = FALSE; if (segment == ULINT_UNDEFINED) { array = os_aio_sync_array; @@ -3772,14 +3936,52 @@ os_aio_windows_handle( ut_a(TRUE == os_file_flush(slot->file)); } #endif /* UNIV_DO_FLUSH */ + } else if (os_file_handle_error(slot->name, "Windows aio")) { + + retry = TRUE; } else { - os_file_handle_error(slot->name, "Windows aio"); ret_val = FALSE; } os_mutex_exit(array->mutex); + if (retry) { + /* retry failed read/write operation synchronously. + No need to hold array->mutex. */ + + switch (slot->type) { + case OS_FILE_WRITE: + ret = WriteFile(slot->file, slot->buf, + slot->len, &len, + &(slot->control)); + + break; + case OS_FILE_READ: + ret = ReadFile(slot->file, slot->buf, + slot->len, &len, + &(slot->control)); + + break; + default: + ut_error; + } + + if (!ret && GetLastError() == ERROR_IO_PENDING) { + /* aio was queued successfully! + We want a synchronous i/o operation on a + file where we also use async i/o: in Windows + we must use the same wait mechanism as for + async i/o */ + + ret = GetOverlappedResult(slot->file, + &(slot->control), + &len, TRUE); + } + + ret_val = ret && len == slot->len; + } + os_aio_array_free_slot(array, slot); return(ret_val); @@ -4058,6 +4260,18 @@ consecutive_loop: } } + if (srv_recovery_stats && recv_recovery_is_on() && n_consecutive) { + mutex_enter(&(recv_sys->mutex)); + if (slot->type == OS_FILE_READ) { + recv_sys->stats_read_io_pages += n_consecutive; + recv_sys->stats_read_io_consecutive[n_consecutive - 1]++; + } else if (slot->type == OS_FILE_WRITE) { + recv_sys->stats_write_io_pages += n_consecutive; + recv_sys->stats_write_io_consecutive[n_consecutive - 1]++; + } + mutex_exit(&(recv_sys->mutex)); + } + os_mutex_enter(array->mutex); /* Mark the i/os done in slots */ diff --git a/os/os0proc.c b/os/os0proc.c index a0ea9a1b258..48922886f23 100644 --- a/os/os0proc.c +++ b/os/os0proc.c @@ -97,6 +97,7 @@ os_mem_alloc_large( fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to" " attach shared memory segment, errno %d\n", errno); + ptr = NULL; } /* Remove the shared memory segment so that it will be diff --git a/os/os0sync.c b/os/os0sync.c index 4ec340b72b5..60467242e14 100644 --- a/os/os0sync.c +++ b/os/os0sync.c @@ -86,6 +86,9 @@ os_sync_init(void) UT_LIST_INIT(os_event_list); UT_LIST_INIT(os_mutex_list); + os_sync_mutex = NULL; + os_sync_mutex_inited = FALSE; + os_sync_mutex = os_mutex_create(NULL); os_sync_mutex_inited = TRUE; @@ -713,6 +716,7 @@ os_fast_mutex_free( os_mutex_enter(os_sync_mutex); } + ut_ad(os_fast_mutex_count > 0); os_fast_mutex_count--; if (UNIV_LIKELY(os_sync_mutex_inited)) { diff --git a/os/os0thread.c b/os/os0thread.c index 9a2d95cb166..34818ada804 100644 --- a/os/os0thread.c +++ b/os/os0thread.c @@ -233,6 +233,7 @@ os_thread_exit( #ifdef __WIN__ ExitThread((DWORD)exit_value); #else + pthread_detach(pthread_self()); pthread_exit(exit_value); #endif } diff --git a/page/page0cur.c b/page/page0cur.c index 65f3ba67439..f10f16a7dd9 100644 --- a/page/page0cur.c +++ b/page/page0cur.c @@ -1195,7 +1195,7 @@ page_cur_insert_rec_zip_reorg( } /* Out of space: restore the page */ - if (!page_zip_decompress(page_zip, page)) { + if (!page_zip_decompress(page_zip, page, FALSE)) { ut_error; /* Memory corrupted? */ } ut_ad(page_validate(page, index)); diff --git a/page/page0page.c b/page/page0page.c index f056ef77bdc..ab2ba60570e 100644 --- a/page/page0page.c +++ b/page/page0page.c @@ -45,7 +45,7 @@ Created 2/2/1994 Heikki Tuuri ============== The index page consists of a page header which contains the page's -id and other information. On top of it are the the index records +id and other information. On top of it are the index records in a heap linked into a one way linear list according to alphabetic order. Just below page end is an array of pointers which we call page directory, @@ -679,7 +679,7 @@ page_copy_rec_list_end( if (UNIV_UNLIKELY (!page_zip_decompress(new_page_zip, - new_page))) { + new_page, FALSE))) { ut_error; } ut_ad(page_validate(new_page, index)); @@ -792,7 +792,7 @@ page_copy_rec_list_start( if (UNIV_UNLIKELY (!page_zip_decompress(new_page_zip, - new_page))) { + new_page, FALSE))) { ut_error; } ut_ad(page_validate(new_page, index)); diff --git a/page/page0zip.c b/page/page0zip.c index 92ba0ec768a..aa5e39ff04a 100644 --- a/page/page0zip.c +++ b/page/page0zip.c @@ -47,8 +47,10 @@ Created June 2005 by Marko Makela # define buf_LRU_stat_inc_unzip() ((void) 0) #endif /* !UNIV_HOTBACKUP */ +#ifndef UNIV_HOTBACKUP /** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */ UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1]; +#endif /* !UNIV_HOTBACKUP */ /* Please refer to ../include/page0zip.ic for a description of the compressed page format. */ @@ -1144,7 +1146,9 @@ page_zip_compress( ulint* offsets = NULL; ulint n_blobs = 0; byte* storage;/* storage of uncompressed columns */ +#ifndef UNIV_HOTBACKUP ullint usec = ut_time_us(NULL); +#endif /* !UNIV_HOTBACKUP */ #ifdef PAGE_ZIP_COMPRESS_DBG FILE* logfile = NULL; #endif @@ -1208,7 +1212,9 @@ page_zip_compress( } } #endif /* PAGE_ZIP_COMPRESS_DBG */ +#ifndef UNIV_HOTBACKUP page_zip_stat[page_zip->ssize - 1].compressed++; +#endif /* !UNIV_HOTBACKUP */ if (UNIV_UNLIKELY(n_dense * PAGE_ZIP_DIR_SLOT_SIZE >= page_zip_get_size(page_zip))) { @@ -1345,8 +1351,10 @@ err_exit: fclose(logfile); } #endif /* PAGE_ZIP_COMPRESS_DBG */ +#ifndef UNIV_HOTBACKUP page_zip_stat[page_zip->ssize - 1].compressed_usec += ut_time_us(NULL) - usec; +#endif /* !UNIV_HOTBACKUP */ return(FALSE); } @@ -1404,12 +1412,14 @@ err_exit: fclose(logfile); } #endif /* PAGE_ZIP_COMPRESS_DBG */ +#ifndef UNIV_HOTBACKUP { page_zip_stat_t* zip_stat = &page_zip_stat[page_zip->ssize - 1]; zip_stat->compressed_ok++; zip_stat->compressed_usec += ut_time_us(NULL) - usec; } +#endif /* !UNIV_HOTBACKUP */ return(TRUE); } @@ -2811,7 +2821,11 @@ page_zip_decompress( /*================*/ page_zip_des_t* page_zip,/*!< in: data, ssize; out: m_start, m_end, m_nonempty, n_blobs */ - page_t* page) /*!< out: uncompressed page, may be trashed */ + page_t* page, /*!< out: uncompressed page, may be trashed */ + ibool all) /*!< in: TRUE=decompress the whole page; + FALSE=verify but do not copy some + page header fields that should not change + after page creation */ { z_stream d_stream; dict_index_t* index = NULL; @@ -2820,7 +2834,9 @@ page_zip_decompress( ulint trx_id_col = ULINT_UNDEFINED; mem_heap_t* heap; ulint* offsets; +#ifndef UNIV_HOTBACKUP ullint usec = ut_time_us(NULL); +#endif /* !UNIV_HOTBACKUP */ ut_ad(page_zip_simple_validate(page_zip)); UNIV_MEM_ASSERT_W(page, UNIV_PAGE_SIZE); @@ -2839,13 +2855,36 @@ page_zip_decompress( heap = mem_heap_create(n_dense * (3 * sizeof *recs) + UNIV_PAGE_SIZE); recs = mem_heap_alloc(heap, n_dense * (2 * sizeof *recs)); + if (all) { + /* Copy the page header. */ + memcpy(page, page_zip->data, PAGE_DATA); + } else { + /* Check that the bytes that we skip are identical. */ +#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG + ut_a(!memcmp(FIL_PAGE_TYPE + page, + FIL_PAGE_TYPE + page_zip->data, + PAGE_HEADER - FIL_PAGE_TYPE)); + ut_a(!memcmp(PAGE_HEADER + PAGE_LEVEL + page, + PAGE_HEADER + PAGE_LEVEL + page_zip->data, + PAGE_DATA - (PAGE_HEADER + PAGE_LEVEL))); +#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */ + + /* Copy the mutable parts of the page header. */ + memcpy(page, page_zip->data, FIL_PAGE_TYPE); + memcpy(PAGE_HEADER + page, PAGE_HEADER + page_zip->data, + PAGE_LEVEL - PAGE_N_DIR_SLOTS); + +#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG + /* Check that the page headers match after copying. */ + ut_a(!memcmp(page, page_zip->data, PAGE_DATA)); +#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */ + } + #ifdef UNIV_ZIP_DEBUG - /* Clear the page. */ - memset(page, 0x55, UNIV_PAGE_SIZE); + /* Clear the uncompressed page, except the header. */ + memset(PAGE_DATA + page, 0x55, UNIV_PAGE_SIZE - PAGE_DATA); #endif /* UNIV_ZIP_DEBUG */ - UNIV_MEM_INVALID(page, UNIV_PAGE_SIZE); - /* Copy the page header. */ - memcpy(page, page_zip->data, PAGE_DATA); + UNIV_MEM_INVALID(PAGE_DATA + page, UNIV_PAGE_SIZE - PAGE_DATA); /* Copy the page directory. */ if (UNIV_UNLIKELY(!page_zip_dir_decode(page_zip, page, recs, @@ -2976,12 +3015,14 @@ err_exit: page_zip_fields_free(index); mem_heap_free(heap); +#ifndef UNIV_HOTBACKUP { page_zip_stat_t* zip_stat = &page_zip_stat[page_zip->ssize - 1]; zip_stat->decompressed++; zip_stat->decompressed_usec += ut_time_us(NULL) - usec; } +#endif /* !UNIV_HOTBACKUP */ /* Update the stat counter for LRU policy. */ buf_LRU_stat_inc_unzip(); @@ -3084,7 +3125,7 @@ page_zip_validate_low( #endif /* UNIV_DEBUG_VALGRIND */ temp_page_zip = *page_zip; - valid = page_zip_decompress(&temp_page_zip, temp_page); + valid = page_zip_decompress(&temp_page_zip, temp_page, TRUE); if (!valid) { fputs("page_zip_validate(): failed to decompress\n", stderr); goto func_exit; @@ -4362,8 +4403,8 @@ IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a non-clustered index, the caller must update the insert buffer free bits in the same mini-transaction in such a way that the modification will be redo-logged. -@return TRUE on success, FALSE on failure; page and page_zip will be -left intact on failure. */ +@return TRUE on success, FALSE on failure; page_zip will be left +intact on failure, but page will be overwritten. */ UNIV_INTERN ibool page_zip_reorganize( @@ -4428,9 +4469,6 @@ page_zip_reorganize( if (UNIV_UNLIKELY(!page_zip_compress(page_zip, page, index, mtr))) { - /* Restore the old page and exit. */ - buf_frame_copy(page, temp_page); - #ifndef UNIV_HOTBACKUP buf_block_free(temp_block); #endif /* !UNIV_HOTBACKUP */ @@ -4591,7 +4629,8 @@ corrupt: memcpy(page_zip->data + page_zip_get_size(page_zip) - trailer_size, ptr + 8 + size, trailer_size); - if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, page))) { + if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, page, + TRUE))) { goto corrupt; } diff --git a/pars/lexyy.c b/pars/lexyy.c index 37d892e51e3..815395ea316 100644 --- a/pars/lexyy.c +++ b/pars/lexyy.c @@ -2778,3 +2778,16 @@ static void yyfree (void * ptr ) + +/********************************************************************** +Release any resources used by the lexer. */ +UNIV_INTERN +void +pars_lexer_close(void) +/*==================*/ +{ + yylex_destroy(); + free(stringbuf); + stringbuf = NULL; + stringbuf_len_alloc = stringbuf_len = 0; +} diff --git a/pars/pars0lex.l b/pars/pars0lex.l index 4abff65e98b..55ed17f82e1 100644 --- a/pars/pars0lex.l +++ b/pars/pars0lex.l @@ -661,3 +661,16 @@ In the state 'id', only two actions are possible (defined below). */ } %% + +/********************************************************************** +Release any resources used by the lexer. */ +UNIV_INTERN +void +pars_lexer_close(void) +/*==================*/ +{ + yylex_destroy(); + free(stringbuf); + stringbuf = NULL; + stringbuf_len_alloc = stringbuf_len = 0; +} diff --git a/plug.in b/plug.in index 63071207c78..09a95ecc157 100644 --- a/plug.in +++ b/plug.in @@ -38,19 +38,11 @@ MYSQL_PLUGIN_ACTIONS(innobase, [ irix*|osf*|sysv5uw7*|openbsd*) CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";; *solaris*|*SunOS*) - # Begin Solaris atomic function checks - AC_CHECK_FUNCS(atomic_cas_ulong atomic_cas_32 \ - atomic_cas_64 atomic_add_long, - AC_DEFINE( - [HAVE_SOLARIS_ATOMICS], - [1], - [Define to 1 if Solaris supports \ - atomic functions.])) - ### End Solaris atomic function checks - CFLAGS="$CFLAGS -DUNIV_SOLARIS";; esac + INNODB_DYNAMIC_CFLAGS="-DMYSQL_DYNAMIC_PLUGIN" + case "$target_cpu" in x86_64) # The AMD64 ABI forbids absolute addresses in shared libraries @@ -61,7 +53,60 @@ MYSQL_PLUGIN_ACTIONS(innobase, [ ;; esac AC_SUBST(INNODB_DYNAMIC_CFLAGS) + + AC_MSG_CHECKING(whether GCC atomic builtins are available) + # either define HAVE_IB_GCC_ATOMIC_BUILTINS or not + AC_TRY_RUN( + [ + int main() + { + long x; + long y; + long res; + char c; + + x = 10; + y = 123; + res = __sync_bool_compare_and_swap(&x, x, y); + if (!res || x != y) { + return(1); + } + + x = 10; + y = 123; + res = __sync_bool_compare_and_swap(&x, x + 1, y); + if (res || x != 10) { + return(1); + } + + x = 10; + y = 123; + res = __sync_add_and_fetch(&x, y); + if (res != 123 + 10 || x != 123 + 10) { + return(1); + } + + c = 10; + res = __sync_lock_test_and_set(&c, 123); + if (res != 10 || c != 123) { + return(1); + } + + return(0); + } + ], + [ + AC_DEFINE([HAVE_IB_GCC_ATOMIC_BUILTINS], [1], + [GCC atomic builtins are available]) + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_RESULT(no) + ] + ) + AC_MSG_CHECKING(whether pthread_t can be used by GCC atomic builtins) + # either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not AC_TRY_RUN( [ #include @@ -82,47 +127,73 @@ MYSQL_PLUGIN_ACTIONS(innobase, [ } ], [ - AC_DEFINE([HAVE_ATOMIC_PTHREAD_T], [1], + AC_DEFINE([HAVE_IB_ATOMIC_PTHREAD_T_GCC], [1], [pthread_t can be used by GCC atomic builtins]) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ] - ) + ) - # Try using solaris atomics on SunOS if GCC atomics are not available - AC_CHECK_DECLS( - [HAVE_ATOMIC_PTHREAD_T], + AC_MSG_CHECKING(whether Solaris libc atomic functions are available) + # either define HAVE_IB_SOLARIS_ATOMICS or not + AC_CHECK_FUNCS(atomic_add_long \ + atomic_cas_32 \ + atomic_cas_64 \ + atomic_cas_ulong, + + AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1], + [Define to 1 if Solaris libc atomic functions \ + are available]) + ) + + AC_MSG_CHECKING(whether pthread_t can be used by Solaris libc atomic functions) + # either define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS or not + AC_TRY_RUN( [ - AC_MSG_NOTICE(no need to check pthread_t size) + #include + #include + + int main(int argc, char** argv) { + pthread_t x1; + pthread_t x2; + pthread_t x3; + + memset(&x1, 0x0, sizeof(x1)); + memset(&x2, 0x0, sizeof(x2)); + memset(&x3, 0x0, sizeof(x3)); + + if (sizeof(pthread_t) == 4) { + + atomic_cas_32(&x1, x2, x3); + + } else if (sizeof(pthread_t) == 8) { + + atomic_cas_64(&x1, x2, x3); + + } else { + + return(1); + } + + return(0); + } ], [ - AC_CHECK_DECLS( - [HAVE_SOLARIS_ATOMICS], - [ - AC_MSG_CHECKING(checking if pthread_t size is integral) - AC_TRY_RUN( - [ - #include - int main() - { - pthread_t x = 0; - return(0); - } - ], - [ - AC_DEFINE([HAVE_ATOMIC_PTHREAD_T], [1], + AC_DEFINE([HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS], [1], [pthread_t can be used by solaris atomics]) - AC_MSG_RESULT(yes) - # size of pthread_t is needed for typed solaris atomics - AC_CHECK_SIZEOF([pthread_t], [], [#include ]) - ], - [ - AC_MSG_RESULT(no) - ]) - ]) - ]) + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_RESULT(no) + ] + ) + + # this is needed to know which one of atomic_cas_32() or atomic_cas_64() + # to use in the source + AC_CHECK_SIZEOF([pthread_t], [], [#include ]) + # Check for x86 PAUSE instruction AC_MSG_CHECKING(for x86 PAUSE instruction) # We have to actually try running the test program, because of a bug @@ -139,7 +210,7 @@ MYSQL_PLUGIN_ACTIONS(innobase, [ } ], [ - AC_DEFINE([IB_HAVE_PAUSE_INSTRUCTION], [1], [Does x86 PAUSE instruction exist]) + AC_DEFINE([HAVE_IB_PAUSE_INSTRUCTION], [1], [Does x86 PAUSE instruction exist]) AC_MSG_RESULT(yes) ], [ diff --git a/que/que0que.c b/que/que0que.c index 54b1e7535fa..2fe046fa9b8 100644 --- a/que/que0que.c +++ b/que/que0que.c @@ -518,6 +518,7 @@ que_graph_free_recursive( upd_node_t* upd; tab_node_t* cre_tab; ind_node_t* cre_ind; + purge_node_t* purge; if (node == NULL) { @@ -579,6 +580,13 @@ que_graph_free_recursive( mem_heap_free(ins->entry_sys_heap); break; + case QUE_NODE_PURGE: + purge = node; + + mem_heap_free(purge->heap); + + break; + case QUE_NODE_UPDATE: upd = node; diff --git a/rem/rem0cmp.c b/rem/rem0cmp.c index 3924ed69b82..45230f1d7b1 100644 --- a/rem/rem0cmp.c +++ b/rem/rem0cmp.c @@ -36,7 +36,7 @@ Created 7/1/1994 Heikki Tuuri The records are put into alphabetical order in the following way: let F be the first field where two records disagree. -If there is a character in some position n where the the +If there is a character in some position n where the records disagree, the order is determined by comparison of the characters at position n, possibly after collating transformation. If there is no such character, @@ -76,7 +76,7 @@ cmp_debug_dtuple_rec_with_match( /*************************************************************//** This function is used to compare two data fields for which the data type is such that we must use MySQL code to compare them. The prototype here -must be a copy of the the one in ha_innobase.cc! +must be a copy of the one in ha_innobase.cc! @return 1, 0, -1, if a is greater, equal, less than b, respectively */ extern int @@ -399,7 +399,7 @@ next_byte: /*************************************************************//** This function is used to compare a data tuple to a physical record. Only dtuple->n_fields_cmp first fields are taken into account for -the the data tuple! If we denote by n = n_fields_cmp, then rec must +the data tuple! If we denote by n = n_fields_cmp, then rec must have either m >= n fields, or it must differ from dtuple in some of the m fields rec has. If rec has an externally stored field we do not compare it but return with value 0 if such a comparison should be diff --git a/row/row0ins.c b/row/row0ins.c index 930c9ec1fc7..fe51fce82c4 100644 --- a/row/row0ins.c +++ b/row/row0ins.c @@ -141,7 +141,7 @@ row_ins_alloc_sys_fields( dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); - ptr = mem_heap_alloc(heap, DATA_ROW_ID_LEN); + ptr = mem_heap_zalloc(heap, DATA_ROW_ID_LEN); dfield_set_data(dfield, ptr, DATA_ROW_ID_LEN); @@ -152,7 +152,7 @@ row_ins_alloc_sys_fields( col = dict_table_get_sys_col(table, DATA_TRX_ID); dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); - ptr = mem_heap_alloc(heap, DATA_TRX_ID_LEN); + ptr = mem_heap_zalloc(heap, DATA_TRX_ID_LEN); dfield_set_data(dfield, ptr, DATA_TRX_ID_LEN); @@ -163,7 +163,7 @@ row_ins_alloc_sys_fields( col = dict_table_get_sys_col(table, DATA_ROLL_PTR); dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); - ptr = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN); + ptr = mem_heap_zalloc(heap, DATA_ROLL_PTR_LEN); dfield_set_data(dfield, ptr, DATA_ROLL_PTR_LEN); } @@ -1191,7 +1191,7 @@ row_ins_check_foreign_constraint( /*=============================*/ ibool check_ref,/*!< in: TRUE if we want to check that the referenced table is ok, FALSE if we - want to to check the foreign key table */ + want to check the foreign key table */ dict_foreign_t* foreign,/*!< in: foreign constraint; NOTE that the tables mentioned in it must be in the dictionary cache if they exist at all */ diff --git a/row/row0merge.c b/row/row0merge.c index 05a45dc647c..25f041c0885 100644 --- a/row/row0merge.c +++ b/row/row0merge.c @@ -60,9 +60,19 @@ Completed by Sunny Bains and Marko Makela #ifdef UNIV_DEBUG /** Set these in order ot enable debug printout. */ /* @{ */ +/** Log the outcome of each row_merge_cmp() call, comparing records. */ static ibool row_merge_print_cmp; +/** Log each record read from temporary file. */ static ibool row_merge_print_read; +/** Log each record write to temporary file. */ static ibool row_merge_print_write; +/** Log each row_merge_blocks() call, merging two blocks of records to +a bigger one. */ +static ibool row_merge_print_block; +/** Log each block read from temporary file. */ +static ibool row_merge_print_block_read; +/** Log each block read from temporary file. */ +static ibool row_merge_print_block_write; /* @} */ #endif /* UNIV_DEBUG */ @@ -109,8 +119,9 @@ typedef struct row_merge_buf_struct row_merge_buf_t; /** Information about temporary files used in merge sort */ struct merge_file_struct { - int fd; /*!< file descriptor */ - ulint offset; /*!< file offset */ + int fd; /*!< file descriptor */ + ulint offset; /*!< file offset (end of file) */ + ib_uint64_t n_rec; /*!< number of records in the file */ }; /** Information about temporary files used in merge sort */ @@ -682,6 +693,13 @@ row_merge_read( ib_uint64_t ofs = ((ib_uint64_t) offset) * sizeof *buf; ibool success; +#ifdef UNIV_DEBUG + if (row_merge_print_block_read) { + fprintf(stderr, "row_merge_read fd=%d ofs=%lu\n", + fd, (ulong) offset); + } +#endif /* UNIV_DEBUG */ + success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf, (ulint) (ofs & 0xFFFFFFFF), (ulint) (ofs >> 32), @@ -709,6 +727,13 @@ row_merge_write( ib_uint64_t ofs = ((ib_uint64_t) offset) * sizeof(row_merge_block_t); +#ifdef UNIV_DEBUG + if (row_merge_print_block_write) { + fprintf(stderr, "row_merge_write fd=%d ofs=%lu\n", + fd, (ulong) offset); + } +#endif /* UNIV_DEBUG */ + return(UNIV_LIKELY(os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf, (ulint) (ofs & 0xFFFFFFFF), (ulint) (ofs >> 32), @@ -718,7 +743,7 @@ row_merge_write( /********************************************************************//** Read a merge record. @return pointer to next record, or NULL on I/O error or end of list */ -static +static __attribute__((nonnull)) const byte* row_merge_read_rec( /*===============*/ @@ -1070,7 +1095,7 @@ row_merge_cmp( Reads clustered index of the table and create temporary files containing the index entries for the indexes to be built. @return DB_SUCCESS or error */ -static +static __attribute__((nonnull)) ulint row_merge_read_clustered_index( /*===========================*/ @@ -1175,6 +1200,12 @@ row_merge_read_clustered_index( in order to release the latch on the old page. */ if (btr_pcur_is_after_last_on_page(&pcur)) { + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + i = 0; + err = DB_INTERRUPTED; + goto err_exit; + } + btr_pcur_store_position(&pcur, &mtr); mtr_commit(&mtr); mtr_start(&mtr); @@ -1233,6 +1264,7 @@ row_merge_read_clustered_index( if (UNIV_LIKELY (row && row_merge_buf_add(buf, row, ext))) { + file->n_rec++; continue; } @@ -1274,14 +1306,19 @@ err_exit: UNIV_MEM_INVALID(block[0], sizeof block[0]); merge_buf[i] = row_merge_buf_empty(buf); - /* Try writing the record again, now that - the buffer has been written out and emptied. */ + if (UNIV_LIKELY(row != NULL)) { + /* Try writing the record again, now + that the buffer has been written out + and emptied. */ - if (UNIV_UNLIKELY - (row && !row_merge_buf_add(buf, row, ext))) { - /* An empty buffer should have enough - room for at least one record. */ - ut_error; + if (UNIV_UNLIKELY + (!row_merge_buf_add(buf, row, ext))) { + /* An empty buffer should have enough + room for at least one record. */ + ut_error; + } + + file->n_rec++; } } @@ -1320,7 +1357,7 @@ func_exit: b2 = row_merge_write_rec(&block[2], &buf[2], b2, \ of->fd, &of->offset, \ mrec##N, offsets##N); \ - if (UNIV_UNLIKELY(!b2)) { \ + if (UNIV_UNLIKELY(!b2 || ++of->n_rec > file->n_rec)) { \ goto corrupt; \ } \ b##N = row_merge_read_rec(&block[N], &buf[N], \ @@ -1336,14 +1373,14 @@ func_exit: } while (0) /*************************************************************//** -Merge two blocks of linked lists on disk and write a bigger block. +Merge two blocks of records on disk and write a bigger block. @return DB_SUCCESS or error code */ static ulint row_merge_blocks( /*=============*/ const dict_index_t* index, /*!< in: index being created */ - merge_file_t* file, /*!< in/out: file containing + const merge_file_t* file, /*!< in: file containing index entries */ row_merge_block_t* block, /*!< in/out: 3 buffers */ ulint* foffs0, /*!< in/out: offset of first @@ -1366,6 +1403,17 @@ row_merge_blocks( ulint* offsets0;/* offsets of mrec0 */ ulint* offsets1;/* offsets of mrec1 */ +#ifdef UNIV_DEBUG + if (row_merge_print_block) { + fprintf(stderr, + "row_merge_blocks fd=%d ofs=%lu + fd=%d ofs=%lu" + " = fd=%d ofs=%lu\n", + file->fd, (ulong) *foffs0, + file->fd, (ulong) *foffs1, + of->fd, (ulong) of->offset); + } +#endif /* UNIV_DEBUG */ + heap = row_merge_heap_create(index, &offsets0, &offsets1); /* Write a record and read the next record. Split the output @@ -1437,17 +1485,89 @@ done1: return(b2 ? DB_SUCCESS : DB_CORRUPTION); } +/*************************************************************//** +Copy a block of index entries. +@return TRUE on success, FALSE on failure */ +static __attribute__((nonnull)) +ibool +row_merge_blocks_copy( +/*==================*/ + const dict_index_t* index, /*!< in: index being created */ + const merge_file_t* file, /*!< in: input file */ + row_merge_block_t* block, /*!< in/out: 3 buffers */ + ulint* foffs0, /*!< in/out: input file offset */ + merge_file_t* of) /*!< in/out: output file */ +{ + mem_heap_t* heap; /*!< memory heap for offsets0, offsets1 */ + + mrec_buf_t buf[3]; /*!< buffer for handling + split mrec in block[] */ + const byte* b0; /*!< pointer to block[0] */ + byte* b2; /*!< pointer to block[2] */ + const mrec_t* mrec0; /*!< merge rec, points to block[0] */ + ulint* offsets0;/* offsets of mrec0 */ + ulint* offsets1;/* dummy offsets */ + +#ifdef UNIV_DEBUG + if (row_merge_print_block) { + fprintf(stderr, + "row_merge_blocks_copy fd=%d ofs=%lu" + " = fd=%d ofs=%lu\n", + file->fd, (ulong) foffs0, + of->fd, (ulong) of->offset); + } +#endif /* UNIV_DEBUG */ + + heap = row_merge_heap_create(index, &offsets0, &offsets1); + + /* Write a record and read the next record. Split the output + file in two halves, which can be merged on the following pass. */ + + if (!row_merge_read(file->fd, *foffs0, &block[0])) { +corrupt: + mem_heap_free(heap); + return(FALSE); + } + + b0 = block[0]; + b2 = block[2]; + + b0 = row_merge_read_rec(&block[0], &buf[0], b0, index, file->fd, + foffs0, &mrec0, offsets0); + if (UNIV_UNLIKELY(!b0 && mrec0)) { + + goto corrupt; + } + + if (mrec0) { + /* append all mrec0 to output */ + for (;;) { + ROW_MERGE_WRITE_GET_NEXT(0, goto done0); + } + } +done0: + + /* The file offset points to the beginning of the last page + that has been read. Update it to point to the next block. */ + (*foffs0)++; + + mem_heap_free(heap); + return(row_merge_write_eof(&block[2], b2, of->fd, &of->offset) + != NULL); +} + /*************************************************************//** Merge disk files. @return DB_SUCCESS or error code */ -static +static __attribute__((nonnull)) ulint row_merge( /*======*/ + trx_t* trx, /*!< in: transaction */ const dict_index_t* index, /*!< in: index being created */ merge_file_t* file, /*!< in/out: file containing index entries */ - ulint half, /*!< in: half the file */ + ulint* half, /*!< in/out: half the file */ row_merge_block_t* block, /*!< in/out: 3 buffers */ int* tmpfd, /*!< in/out: temporary file handle */ TABLE* table) /*!< in/out: MySQL table, for @@ -1458,43 +1578,87 @@ row_merge( ulint foffs1; /*!< second input offset */ ulint error; /*!< error code */ merge_file_t of; /*!< output file */ + const ulint ihalf = *half; + /*!< half the input file */ + ulint ohalf; /*!< half the output file */ UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]); - ut_ad(half > 0); + ut_ad(ihalf < file->offset); of.fd = *tmpfd; of.offset = 0; + of.n_rec = 0; /* Merge blocks to the output file. */ + ohalf = 0; foffs0 = 0; - foffs1 = half; + foffs1 = ihalf; + + for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) { + ulint ahalf; /*!< arithmetic half the input file */ + + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + return(DB_INTERRUPTED); + } - for (; foffs0 < half && foffs1 < file->offset; foffs0++, foffs1++) { error = row_merge_blocks(index, file, block, &foffs0, &foffs1, &of, table); if (error != DB_SUCCESS) { return(error); } + + /* Record the offset of the output file when + approximately half the output has been generated. In + this way, the next invocation of row_merge() will + spend most of the time in this loop. The initial + estimate is ohalf==0. */ + ahalf = file->offset / 2; + ut_ad(ohalf <= of.offset); + + /* Improve the estimate until reaching half the input + file size, or we can not get any closer to it. All + comparands should be non-negative when !(ohalf < ahalf) + because ohalf <= of.offset. */ + if (ohalf < ahalf || of.offset - ahalf < ohalf - ahalf) { + ohalf = of.offset; + } } - /* Copy the last block, if there is one. */ - while (foffs0 < half) { - if (!row_merge_read(file->fd, foffs0++, block) - || !row_merge_write(of.fd, of.offset++, block)) { + /* Copy the last blocks, if there are any. */ + + while (foffs0 < ihalf) { + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + return(DB_INTERRUPTED); + } + + if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) { return(DB_CORRUPTION); } } + + ut_ad(foffs0 == ihalf); + while (foffs1 < file->offset) { - if (!row_merge_read(file->fd, foffs1++, block) - || !row_merge_write(of.fd, of.offset++, block)) { + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + return(DB_INTERRUPTED); + } + + if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) { return(DB_CORRUPTION); } } + ut_ad(foffs1 == file->offset); + + if (UNIV_UNLIKELY(of.n_rec != file->n_rec)) { + return(DB_CORRUPTION); + } + /* Swap file descriptors for the next pass. */ *tmpfd = file->fd; *file = of; + *half = ohalf; UNIV_MEM_INVALID(block[0], 3 * sizeof block[0]); @@ -1508,6 +1672,7 @@ static ulint row_merge_sort( /*===========*/ + trx_t* trx, /*!< in: transaction */ const dict_index_t* index, /*!< in: index being created */ merge_file_t* file, /*!< in/out: file containing index entries */ @@ -1517,20 +1682,26 @@ row_merge_sort( reporting erroneous key value if applicable */ { - ulint blksz; /*!< block size */ + ulint half = file->offset / 2; - for (blksz = 1; blksz < file->offset; blksz *= 2) { - ulint half; + /* The file should always contain at least one byte (the end + of file marker). Thus, it must be at least one block. */ + ut_ad(file->offset > 0); + + do { ulint error; - ut_ad(ut_is_2pow(blksz)); - half = ut_2pow_round((file->offset + (blksz - 1)) / 2, blksz); - error = row_merge(index, file, half, block, tmpfd, table); + error = row_merge(trx, index, file, &half, + block, tmpfd, table); if (error != DB_SUCCESS) { return(error); } - } + + /* half > 0 should hold except when the file consists + of one block. No need to merge further then. */ + ut_ad(half > 0 || file->offset == 1); + } while (half < file->offset && half > 0); return(DB_SUCCESS); } @@ -1797,7 +1968,15 @@ row_merge_drop_index( static const char str1[] = "PROCEDURE DROP_INDEX_PROC () IS\n" "BEGIN\n" + /* Rename the index, so that it will be dropped by + row_merge_drop_temp_indexes() at crash recovery + if the server crashes before this trx is committed. */ + "UPDATE SYS_INDEXES SET NAME=CONCAT('" + TEMP_INDEX_PREFIX_STR "', NAME) WHERE ID = :indexid;\n" + "COMMIT WORK;\n" + /* Drop the field definitions of the index. */ "DELETE FROM SYS_FIELDS WHERE INDEX_ID = :indexid;\n" + /* Drop the index definition and the B-tree. */ "DELETE FROM SYS_INDEXES WHERE ID = :indexid\n" " AND TABLE_ID = :tableid;\n" "END;\n"; @@ -1909,6 +2088,7 @@ row_merge_file_create( { merge_file->fd = innobase_mysql_tmpfile(); merge_file->offset = 0; + merge_file->n_rec = 0; } /*********************************************************************//** @@ -2129,7 +2309,7 @@ row_merge_rename_tables( if (err != DB_SUCCESS) { err_exit: trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); trx->error_state = DB_SUCCESS; } @@ -2331,7 +2511,7 @@ row_merge_build_indexes( sorting and inserting. */ for (i = 0; i < n_indexes; i++) { - error = row_merge_sort(indexes[i], &merge_files[i], + error = row_merge_sort(trx, indexes[i], &merge_files[i], block, &tmpfd, table); if (error == DB_SUCCESS) { diff --git a/row/row0mysql.c b/row/row0mysql.c index 8d480191d03..8585b816911 100644 --- a/row/row0mysql.c +++ b/row/row0mysql.c @@ -510,7 +510,7 @@ handle_new_error: switch (err) { case DB_LOCK_WAIT_TIMEOUT: if (row_rollback_on_timeout) { - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); break; } /* fall through */ @@ -526,7 +526,7 @@ handle_new_error: /* Roll back the latest, possibly incomplete insertion or update */ - trx_general_rollback_for_mysql(trx, TRUE, savept); + trx_general_rollback_for_mysql(trx, savept); } /* MySQL will roll back the latest SQL statement */ break; @@ -548,7 +548,7 @@ handle_new_error: /* Roll back the whole transaction; this resolution was added to version 3.23.43 */ - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); break; case DB_MUST_GET_MORE_FILE_SPACE: @@ -869,18 +869,22 @@ row_update_statistics_if_needed( } /*********************************************************************//** -Unlocks AUTO_INC type locks that were possibly reserved by a trx. */ +Unlocks AUTO_INC type locks that were possibly reserved by a trx. This +function should be called at the the end of an SQL statement, by the +connection thread that owns the transaction (trx->mysql_thd). */ UNIV_INTERN void row_unlock_table_autoinc_for_mysql( /*===============================*/ trx_t* trx) /*!< in/out: transaction */ { - mutex_enter(&kernel_mutex); + if (lock_trx_holds_autoinc_locks(trx)) { + mutex_enter(&kernel_mutex); - lock_release_autoinc_locks(trx); + lock_release_autoinc_locks(trx); - mutex_exit(&kernel_mutex); + mutex_exit(&kernel_mutex); + } } /*********************************************************************//** @@ -1878,7 +1882,9 @@ err_exit: if (UNIV_UNLIKELY(err != DB_SUCCESS)) { trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); + /* TO DO: free table? The code below will dereference + table->name, though. */ } switch (err) { @@ -1897,31 +1903,6 @@ err_exit: break; case DB_DUPLICATE_KEY: - ut_print_timestamp(stderr); - fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, TRUE, table->name); - fputs(" already exists in InnoDB internal\n" - "InnoDB: data dictionary. Have you deleted" - " the .frm file\n" - "InnoDB: and not used DROP TABLE?" - " Have you used DROP DATABASE\n" - "InnoDB: for InnoDB tables in" - " MySQL version <= 3.23.43?\n" - "InnoDB: See the Restrictions section" - " of the InnoDB manual.\n" - "InnoDB: You can drop the orphaned table" - " inside InnoDB by\n" - "InnoDB: creating an InnoDB table with" - " the same name in another\n" - "InnoDB: database and copying the .frm file" - " to the current database.\n" - "InnoDB: Then MySQL thinks the table exists," - " and DROP TABLE will\n" - "InnoDB: succeed.\n" - "InnoDB: You can look for further help from\n" - "InnoDB: " REFMAN "innodb-troubleshooting.html\n", - stderr); - /* We may also get err == DB_ERROR if the .ibd file for the table already exists */ @@ -2046,7 +2027,7 @@ error_handling: trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); row_drop_table_for_mysql(table_name, trx, FALSE); @@ -2067,7 +2048,7 @@ Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function should be called after the indexes for a table have been created. Each foreign key constraint must be accompanied with indexes in -bot participating tables. The indexes are allowed to contain more +both participating tables. The indexes are allowed to contain more fields than mentioned in the constraint. Check also that foreign key constraints which reference this table are ok. @return error code or DB_SUCCESS */ @@ -2114,7 +2095,7 @@ row_table_add_foreign_constraints( trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); row_drop_table_for_mysql(name, trx, FALSE); @@ -2481,7 +2462,7 @@ row_discard_tablespace_for_mysql( if (err != DB_SUCCESS) { trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); trx->error_state = DB_SUCCESS; } else { dict_table_change_id_in_cache(table, new_id); @@ -2490,7 +2471,7 @@ row_discard_tablespace_for_mysql( if (!success) { trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); trx->error_state = DB_SUCCESS; err = DB_ERROR; @@ -2942,7 +2923,7 @@ next_rec: if (err != DB_SUCCESS) { trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); trx->error_state = DB_SUCCESS; ut_print_timestamp(stderr); fputs(" InnoDB: Unable to assign a new identifier to table ", @@ -3583,7 +3564,7 @@ row_delete_constraint( if ((err == DB_SUCCESS) && !strchr(id, '/')) { /* Old format < 4.0.18 constraints have constraint ids - _. We only try deleting them if the + NUMBER_NUMBER. We only try deleting them if the constraint name does not contain a '/' character, otherwise deleting a new format constraint named 'foo/bar' from database 'baz' would remove constraint 'bar' from database @@ -3847,7 +3828,7 @@ end: "InnoDB: succeed.\n", stderr); } trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); trx->error_state = DB_SUCCESS; } else { /* The following call will also rename the .ibd data file if @@ -3856,7 +3837,7 @@ end: if (!dict_table_rename_in_cache(table, new_name, !new_is_tmp)) { trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); trx->error_state = DB_SUCCESS; goto funct_exit; } @@ -3896,7 +3877,7 @@ end: ut_a(dict_table_rename_in_cache(table, old_name, FALSE)); trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_general_rollback_for_mysql(trx, NULL); trx->error_state = DB_SUCCESS; } } @@ -4156,6 +4137,7 @@ row_check_table_for_mysql( } if (trx_is_interrupted(prebuilt->trx)) { + ret = DB_INTERRUPTED; break; } diff --git a/scripts/install_innodb_plugins.sql b/scripts/install_innodb_plugins.sql index b2e5e3f6de0..5a555a652f7 100644 --- a/scripts/install_innodb_plugins.sql +++ b/scripts/install_innodb_plugins.sql @@ -14,3 +14,4 @@ INSTALL PLUGIN INNODB_BUFFER_POOL_PAGES_INDEX SONAME 'ha_innodb.so'; INSTALL PLUGIN innodb_rseg SONAME 'ha_innodb.so'; INSTALL PLUGIN innodb_table_stats SONAME 'ha_innodb.so'; INSTALL PLUGIN innodb_index_stats SONAME 'ha_innodb.so'; +INSTALL PLUGIN xtradb_admin_command SONAME 'ha_innodb.so'; diff --git a/scripts/install_innodb_plugins_win.sql b/scripts/install_innodb_plugins_win.sql index 8c94b4e240d..7cda3335694 100644 --- a/scripts/install_innodb_plugins_win.sql +++ b/scripts/install_innodb_plugins_win.sql @@ -7,3 +7,11 @@ INSTALL PLUGIN innodb_cmp SONAME 'ha_innodb.dll'; INSTALL PLUGIN innodb_cmp_reset SONAME 'ha_innodb.dll'; INSTALL PLUGIN innodb_cmpmem SONAME 'ha_innodb.dll'; INSTALL PLUGIN innodb_cmpmem_reset SONAME 'ha_innodb.dll'; +INSTALL PLUGIN XTRADB_ENHANCEMENTS SONAME 'ha_innodb.dll'; +INSTALL PLUGIN INNODB_BUFFER_POOL_PAGES SONAME 'ha_innodb.dll'; +INSTALL PLUGIN INNODB_BUFFER_POOL_PAGES_BLOB SONAME 'ha_innodb.dll'; +INSTALL PLUGIN INNODB_BUFFER_POOL_PAGES_INDEX SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_rseg SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_table_stats SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_index_stats SONAME 'ha_innodb.dll'; +INSTALL PLUGIN xtradb_admin_command SONAME 'ha_innodb.dll'; diff --git a/srv/srv0srv.c b/srv/srv0srv.c index 9a1a6998199..85817588e08 100644 --- a/srv/srv0srv.c +++ b/srv/srv0srv.c @@ -102,6 +102,7 @@ Created 10/8/1995 Heikki Tuuri #include "row0mysql.h" #include "ha_prototypes.h" #include "trx0i_s.h" +#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */ /* prototypes for new functions added to ha_innodb.cc */ ibool innobase_get_slow_log(); @@ -164,6 +165,7 @@ UNIV_INTERN ulint* srv_data_file_sizes = NULL; UNIV_INTERN ibool srv_extra_undoslots = FALSE; UNIV_INTERN ibool srv_fast_recovery = FALSE; +UNIV_INTERN ibool srv_recovery_stats = FALSE; UNIV_INTERN ulint srv_use_purge_thread = 0; @@ -305,12 +307,6 @@ UNIV_INTERN ulint srv_buf_pool_flushed = 0; reading of a disk page */ UNIV_INTERN ulint srv_buf_pool_reads = 0; -/** Number of sequential read-aheads */ -UNIV_INTERN ulint srv_read_ahead_seq = 0; - -/** Number of random read-aheads */ -UNIV_INTERN ulint srv_read_ahead_rnd = 0; - /* structure to pass status variables to MySQL */ UNIV_INTERN export_struc export_vars; @@ -401,6 +397,7 @@ UNIV_INTERN ulint srv_ibuf_active_contract = 0; /* 0:disable 1:enable */ UNIV_INTERN ulint srv_ibuf_accel_rate = 100; #define PCT_IBUF_IO(pct) ((ulint) (srv_io_capacity * srv_ibuf_accel_rate * ((double) pct / 10000.0))) +UNIV_INTERN ulint srv_checkpoint_age_target = 0; UNIV_INTERN ulint srv_flush_neighbor_pages = 1; /* 0:disable 1:enable */ UNIV_INTERN ulint srv_enable_unsafe_group_commit = 0; /* 0:disable 1:enable */ @@ -408,6 +405,7 @@ UNIV_INTERN ulint srv_read_ahead = 3; /* 1: random 2: linear 3: Both */ UNIV_INTERN ulint srv_adaptive_checkpoint = 0; /* 0: none 1: reflex 2: estimate */ UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */ +UNIV_INTERN ulint srv_relax_table_creation = 0; /* 0:disable 1:enable */ UNIV_INTERN ulint srv_extra_rsegments = 0; /* extra rseg for users */ UNIV_INTERN ulint srv_dict_size_limit = 0; @@ -496,8 +494,6 @@ static ulint srv_main_background_loops = 0; static ulint srv_main_flush_loops = 0; /* Log writes involving flush. */ static ulint srv_log_writes_and_flush = 0; -/* Log writes not including flush. */ -static ulint srv_log_buffer_writes = 0; /* This is only ever touched by the master thread. It records the time when the last flush of log file has happened. The master @@ -646,7 +642,7 @@ future, but at the moment we plan to implement a more coarse solution, which could be called a global priority inheritance. If a thread has to wait for a long time, say 300 milliseconds, for a resource, we just guess that it may be waiting for a resource owned by a background -thread, and boost the the priority of all runnable background threads +thread, and boost the priority of all runnable background threads to the normal level. The background threads then themselves adjust their fixed priority back to background after releasing all resources they had (or, at some fixed points in their program code). @@ -746,9 +742,8 @@ srv_print_master_thread_info( srv_main_1_second_loops, srv_main_sleeps, srv_main_10_second_loops, srv_main_background_loops, srv_main_flush_loops); - fprintf(file, "srv_master_thread log flush and writes: %lu " - " log writes only: %lu\n", - srv_log_writes_and_flush, srv_log_buffer_writes); + fprintf(file, "srv_master_thread log flush and writes: %lu\n", + srv_log_writes_and_flush); } /*********************************************************************//** @@ -1046,13 +1041,26 @@ srv_init(void) } /*********************************************************************//** -Frees the OS fast mutex created in srv_init(). */ +Frees the data structures created in srv_init(). */ UNIV_INTERN void srv_free(void) /*==========*/ { os_fast_mutex_free(&srv_conc_mutex); + mem_free(srv_conc_slots); + srv_conc_slots = NULL; + + mem_free(srv_sys->threads); + mem_free(srv_sys); + srv_sys = NULL; + + mem_free(kernel_mutex_temp); + kernel_mutex_temp = NULL; + mem_free(srv_mysql_table); + srv_mysql_table = NULL; + + trx_i_s_cache_free(trx_i_s_cache); } /*********************************************************************//** @@ -1064,6 +1072,8 @@ srv_general_init(void) /*==================*/ { ut_mem_init(); + /* Reset the system variables in the recovery module. */ + recv_sys_var_init(); os_sync_init(); sync_init(); mem_init(srv_mem_pool_size); @@ -1079,7 +1089,7 @@ UNIV_INTERN ulong srv_max_purge_lag = 0; Puts an OS thread to wait if there are too many concurrent threads (>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */ -#ifdef INNODB_RW_LOCKS_USE_ATOMICS +#ifdef HAVE_ATOMIC_BUILTINS static void enter_innodb_with_tickets(trx_t* trx) { @@ -1105,12 +1115,12 @@ srv_conc_enter_innodb_timer_based(trx_t* trx) } retry: if (srv_conc_n_threads < (lint) srv_thread_concurrency) { - conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1); + conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1); if (conc_n_threads <= (lint) srv_thread_concurrency) { enter_innodb_with_tickets(trx); return; } - __sync_add_and_fetch(&srv_conc_n_threads, -1); + os_atomic_increment_lint(&srv_conc_n_threads, -1); } if (!has_yielded) { @@ -1121,7 +1131,7 @@ retry: if (trx->has_search_latch || NULL != UT_LIST_GET_FIRST(trx->trx_locks)) { - conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1); + conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1); enter_innodb_with_tickets(trx); return; } @@ -1132,7 +1142,7 @@ retry: trx->op_info = ""; has_slept++; } - conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1); + conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1); enter_innodb_with_tickets(trx); return; } @@ -1140,7 +1150,7 @@ retry: static void srv_conc_exit_innodb_timer_based(trx_t* trx) { - __sync_add_and_fetch(&srv_conc_n_threads, -1); + os_atomic_increment_lint(&srv_conc_n_threads, -1); trx->declared_to_be_inside_innodb = FALSE; trx->n_tickets_to_enter_innodb = 0; return; @@ -1181,7 +1191,7 @@ srv_conc_enter_innodb( return; } -#ifdef INNODB_RW_LOCKS_USE_ATOMICS +#ifdef HAVE_ATOMIC_BUILTINS if (srv_thread_concurrency_timer_based) { srv_conc_enter_innodb_timer_based(trx); return; @@ -1345,9 +1355,9 @@ srv_conc_force_enter_innodb( } ut_ad(srv_conc_n_threads >= 0); -#ifdef INNODB_RW_LOCKS_USE_ATOMICS +#ifdef HAVE_ATOMIC_BUILTINS if (srv_thread_concurrency_timer_based) { - __sync_add_and_fetch(&srv_conc_n_threads, 1); + os_atomic_increment_lint(&srv_conc_n_threads, 1); trx->declared_to_be_inside_innodb = TRUE; trx->n_tickets_to_enter_innodb = 1; return; @@ -1386,7 +1396,7 @@ srv_conc_force_exit_innodb( return; } -#ifdef INNODB_RW_LOCKS_USE_ATOMICS +#ifdef HAVE_ATOMIC_BUILTINS if (srv_thread_concurrency_timer_based) { srv_conc_exit_innodb_timer_based(trx); return; @@ -2102,14 +2112,16 @@ srv_export_innodb_status(void) export_vars.innodb_data_writes = os_n_file_writes; export_vars.innodb_data_written = srv_data_written; export_vars.innodb_dict_tables= (dict_sys ? UT_LIST_GET_LEN(dict_sys->table_LRU) : 0); - export_vars.innodb_buffer_pool_read_requests = buf_pool->n_page_gets; + export_vars.innodb_buffer_pool_read_requests = buf_pool->stat.n_page_gets; export_vars.innodb_buffer_pool_write_requests = srv_buf_pool_write_requests; export_vars.innodb_buffer_pool_wait_free = srv_buf_pool_wait_free; export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed; export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads; - export_vars.innodb_buffer_pool_read_ahead_rnd = srv_read_ahead_rnd; - export_vars.innodb_buffer_pool_read_ahead_seq = srv_read_ahead_seq; + export_vars.innodb_buffer_pool_read_ahead + = buf_pool->stat.n_ra_pages_read; + export_vars.innodb_buffer_pool_read_ahead_evicted + = buf_pool->stat.n_ra_pages_evicted; export_vars.innodb_buffer_pool_pages_data = UT_LIST_GET_LEN(buf_pool->LRU); export_vars.innodb_buffer_pool_pages_dirty @@ -2140,9 +2152,9 @@ srv_export_innodb_status(void) export_vars.innodb_log_writes = srv_log_writes; export_vars.innodb_dblwr_pages_written = srv_dblwr_pages_written; export_vars.innodb_dblwr_writes = srv_dblwr_writes; - export_vars.innodb_pages_created = buf_pool->n_pages_created; - export_vars.innodb_pages_read = buf_pool->n_pages_read; - export_vars.innodb_pages_written = buf_pool->n_pages_written; + export_vars.innodb_pages_created = buf_pool->stat.n_pages_created; + export_vars.innodb_pages_read = buf_pool->stat.n_pages_read; + export_vars.innodb_pages_written = buf_pool->stat.n_pages_written; export_vars.innodb_row_lock_waits = srv_n_lock_wait_count; export_vars.innodb_row_lock_current_waits = srv_n_lock_wait_current_count; @@ -2509,12 +2521,6 @@ srv_sync_log_buffer_in_background(void) log_buffer_sync_in_background(TRUE); srv_last_log_flush_time = current_time; srv_log_writes_and_flush++; - } else { - /* Actually we don't need to write logs here. - We are just being extra safe here by forcing - the log buffer to log file. */ - log_buffer_sync_in_background(FALSE); - srv_log_buffer_writes++; } } @@ -2572,8 +2578,8 @@ loop: srv_main_thread_op_info = "reserving kernel mutex"; - n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read - + buf_pool->n_pages_written; + n_ios_very_old = log_sys->n_log_ios + buf_pool->stat.n_pages_read + + buf_pool->stat.n_pages_written; mutex_enter(&kernel_mutex); /* Store the user activity counter at the start of this loop */ @@ -2593,8 +2599,8 @@ loop: skip_sleep = FALSE; for (i = 0; i < 10; i++) { - n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read - + buf_pool->n_pages_written; + n_ios_old = log_sys->n_log_ios + buf_pool->stat.n_pages_read + + buf_pool->stat.n_pages_written; srv_main_thread_op_info = "sleeping"; srv_main_1_second_loops++; @@ -2646,8 +2652,8 @@ loop: n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes; - n_ios = log_sys->n_log_ios + buf_pool->n_pages_read - + buf_pool->n_pages_written; + n_ios = log_sys->n_log_ios + buf_pool->stat.n_pages_read + + buf_pool->stat.n_pages_written; if (n_pend_ios < SRV_PEND_IO_THRESHOLD && (n_ios - n_ios_old < SRV_RECENT_IO_ACTIVITY)) { srv_main_thread_op_info = "doing insert buffer merge"; @@ -2663,6 +2669,8 @@ loop: /* Try to keep the number of modified pages in the buffer pool under the limit wished by the user */ + srv_main_thread_op_info = + "flushing buffer pool pages"; n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, PCT_IO(100), IB_ULONGLONG_MAX); @@ -2685,6 +2693,8 @@ loop: ulint n_flush = buf_flush_get_desired_flush_rate(); if (n_flush) { + srv_main_thread_op_info = + "flushing buffer pool pages"; n_flush = ut_min(PCT_IO(100), n_flush); n_pages_flushed = buf_flush_batch( @@ -2856,8 +2866,8 @@ retry_flush_batch: are not required, and may be disabled. */ n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes; - n_ios = log_sys->n_log_ios + buf_pool->n_pages_read - + buf_pool->n_pages_written; + n_ios = log_sys->n_log_ios + buf_pool->stat.n_pages_read + + buf_pool->stat.n_pages_written; srv_main_10_second_loops++; if (n_pend_ios < SRV_PEND_IO_THRESHOLD diff --git a/srv/srv0start.c b/srv/srv0start.c index 6f29b22e811..5b5599b893d 100644 --- a/srv/srv0start.c +++ b/srv/srv0start.c @@ -103,6 +103,8 @@ Created 2/16/1996 Heikki Tuuri # include "row0row.h" # include "row0mysql.h" # include "btr0pcur.h" +# include "thr0loc.h" +# include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */ /** Log sequence number immediately after startup */ UNIV_INTERN ib_uint64_t srv_start_lsn; @@ -494,6 +496,8 @@ io_handler_thread( mutex_exit(&ios_mutex); } + thr_local_free(os_thread_get_curr_id()); + /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. The thread actually never comes here because it is exited in an @@ -530,32 +534,6 @@ srv_normalize_path_for_win( #endif } -/*********************************************************************//** -Adds a slash or a backslash to the end of a string if it is missing -and the string is not empty. -@return string which has the separator if the string is not empty */ -UNIV_INTERN -char* -srv_add_path_separator_if_needed( -/*=============================*/ - char* str) /*!< in: null-terminated character string */ -{ - char* out_str; - ulint len = ut_strlen(str); - - if (len == 0 || str[len - 1] == SRV_PATH_SEPARATOR) { - - return(str); - } - - out_str = ut_malloc(len + 2); - memcpy(out_str, str, len); - out_str[len] = SRV_PATH_SEPARATOR; - out_str[len + 1] = 0; - - return(out_str); -} - #ifndef UNIV_HOTBACKUP /*********************************************************************//** Calculates the low 32 bits when a file size which is given as a number @@ -604,19 +582,24 @@ open_or_create_log_file( ulint size; ulint size_high; char name[10000]; + ulint dirnamelen; UT_NOT_USED(create_new_db); *log_file_created = FALSE; srv_normalize_path_for_win(srv_log_group_home_dirs[k]); - srv_log_group_home_dirs[k] = srv_add_path_separator_if_needed( - srv_log_group_home_dirs[k]); - ut_a(strlen(srv_log_group_home_dirs[k]) - < (sizeof name) - 10 - sizeof "ib_logfile"); - sprintf(name, "%s%s%lu", srv_log_group_home_dirs[k], - "ib_logfile", (ulong) i); + dirnamelen = strlen(srv_log_group_home_dirs[k]); + ut_a(dirnamelen < (sizeof name) - 10 - sizeof "ib_logfile"); + memcpy(name, srv_log_group_home_dirs[k], dirnamelen); + + /* Add a path separator if needed. */ + if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) { + name[dirnamelen++] = SRV_PATH_SEPARATOR; + } + + sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i); files[i] = os_file_create(name, OS_FILE_CREATE, OS_FILE_NORMAL, OS_LOG_FILE, &ret); @@ -779,14 +762,22 @@ open_or_create_data_files( *create_new_db = FALSE; srv_normalize_path_for_win(srv_data_home); - srv_data_home = srv_add_path_separator_if_needed(srv_data_home); for (i = 0; i < srv_n_data_files; i++) { - srv_normalize_path_for_win(srv_data_file_names[i]); + ulint dirnamelen; - ut_a(strlen(srv_data_home) + strlen(srv_data_file_names[i]) + srv_normalize_path_for_win(srv_data_file_names[i]); + dirnamelen = strlen(srv_data_home); + + ut_a(dirnamelen + strlen(srv_data_file_names[i]) < (sizeof name) - 1); - sprintf(name, "%s%s", srv_data_home, srv_data_file_names[i]); + memcpy(name, srv_data_home, dirnamelen); + /* Add a path separator if needed. */ + if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) { + name[dirnamelen++] = SRV_PATH_SEPARATOR; + } + + strcpy(name + dirnamelen, srv_data_file_names[i]); if (srv_data_file_is_raw_partition[i] == 0) { @@ -1008,7 +999,7 @@ skip_size_check: return(DB_SUCCESS); } -/****************************************************************//** +/******************************************************************** Starts InnoDB and creates a new database if database files are not found and the user wants. @return DB_SUCCESS or error code */ @@ -1096,6 +1087,10 @@ innobase_start_or_create_for_mysql(void) "InnoDB: !!!!!!!! UNIV_SEARCH_DEBUG switched on !!!!!!!!!\n"); #endif +#ifdef UNIV_LOG_LSN_DEBUG + fprintf(stderr, + "InnoDB: !!!!!!!! UNIV_LOG_LSN_DEBUG switched on !!!!!!!!!\n"); +#endif /* UNIV_LOG_LSN_DEBUG */ #ifdef UNIV_MEM_DEBUG fprintf(stderr, "InnoDB: !!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!\n"); @@ -1106,34 +1101,7 @@ innobase_start_or_create_for_mysql(void) "InnoDB: The InnoDB memory heap is disabled\n"); } -#ifdef HAVE_GCC_ATOMIC_BUILTINS -# ifdef INNODB_RW_LOCKS_USE_ATOMICS - fprintf(stderr, - "InnoDB: Mutexes and rw_locks use GCC atomic builtins.\n"); -# else /* INNODB_RW_LOCKS_USE_ATOMICS */ - fprintf(stderr, - "InnoDB: Mutexes use GCC atomic builtins, rw_locks do not.\n"); -# endif /* INNODB_RW_LOCKS_USE_ATOMICS */ -#elif defined(HAVE_SOLARIS_ATOMICS) -# ifdef INNODB_RW_LOCKS_USE_ATOMICS - fprintf(stderr, - "InnoDB: Mutexes and rw_locks use Solaris atomic functions.\n"); -# else - fprintf(stderr, - "InnoDB: Mutexes use Solaris atomic functions.\n"); -# endif /* INNODB_RW_LOCKS_USE_ATOMICS */ -#elif HAVE_WINDOWS_ATOMICS -# ifdef INNODB_RW_LOCKS_USE_ATOMICS - fprintf(stderr, - "InnoDB: Mutexes and rw_locks use Windows interlocked functions.\n"); -# else - fprintf(stderr, - "InnoDB: Mutexes use Windows interlocked functions.\n"); -# endif /* INNODB_RW_LOCKS_USE_ATOMICS */ -#else /* HAVE_GCC_ATOMIC_BUILTINS */ - fprintf(stderr, - "InnoDB: Neither mutexes nor rw_locks use GCC atomic builtins.\n"); -#endif /* HAVE_GCC_ATOMIC_BUILTINS */ + fprintf(stderr, "InnoDB: %s\n", IB_ATOMICS_STARTUP_MSG); /* Since InnoDB does not currently clean up all its internal data structures in MySQL Embedded Server Library server_end(), we @@ -1142,7 +1110,7 @@ innobase_start_or_create_for_mysql(void) if (srv_start_has_been_called) { fprintf(stderr, - "InnoDB: Error:startup called second time" + "InnoDB: Error: startup called second time" " during the process lifetime.\n" "InnoDB: In the MySQL Embedded Server Library" " you cannot call server_init()\n" @@ -1409,7 +1377,7 @@ innobase_start_or_create_for_mysql(void) sum_of_new_sizes += srv_data_file_sizes[i]; } - if (sum_of_new_sizes < 640) { + if (sum_of_new_sizes < 10485760 / UNIV_PAGE_SIZE) { fprintf(stderr, "InnoDB: Error: tablespace size must be" " at least 10 MB\n"); @@ -1862,7 +1830,7 @@ innobase_start_or_create_for_mysql(void) /* Actually, we did not change the undo log format between 4.0 and 4.1.1, and we would not need to run purge to completion. Note also that the purge algorithm in 4.1.1 - can process the the history list again even after a full + can process the history list again even after a full purge, because our algorithm does not cut the end of the history list in all cases so that it would become empty after a full purge. That mean that we may purge 4.0 type @@ -2014,8 +1982,10 @@ innobase_shutdown_for_mysql(void) /* All the threads have exited or are just exiting; NOTE that the threads may not have completed their exit yet. Should we use pthread_join() to make sure - they have exited? Now we just sleep 0.1 seconds and - hope that is enough! */ + they have exited? If we did, we would have to + remove the pthread_detach() from + os_thread_exit(). Now we just sleep 0.1 + seconds and hope that is enough! */ os_mutex_exit(os_sync_mutex); @@ -2054,37 +2024,41 @@ innobase_shutdown_for_mysql(void) srv_misc_tmpfile = 0; } + /* This must be disabled before closing the buffer pool + and closing the data dictionary. */ + btr_search_disable(); + + ibuf_close(); + log_shutdown(); + lock_sys_close(); + thr_local_close(); trx_sys_file_format_close(); + trx_sys_close(); mutex_free(&srv_monitor_file_mutex); mutex_free(&srv_dict_tmpfile_mutex); mutex_free(&srv_misc_tmpfile_mutex); + dict_close(); + btr_search_sys_free(); /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside them */ + os_aio_free(); sync_close(); + srv_free(); + fil_close(); /* 4. Free the os_conc_mutex and all os_events and os_mutexes */ - srv_free(); os_sync_free(); - /* Check that all read views are closed except read view owned - by a purge. */ - - if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) { - fprintf(stderr, - "InnoDB: Error: all read views were not closed" - " before shutdown:\n" - "InnoDB: %lu read views open \n", - UT_LIST_GET_LEN(trx_sys->view_list) - 1); - } - - /* 5. Free all allocated memory and the os_fast_mutex created in - ut0mem.c */ + /* 5. Free all allocated memory */ + pars_lexer_close(); + log_mem_free(); buf_pool_free(); ut_free_all_mem(); + mem_close(); if (os_thread_count != 0 || os_event_count != 0 @@ -2115,6 +2089,7 @@ innobase_shutdown_for_mysql(void) } srv_was_started = FALSE; + srv_start_has_been_called = FALSE; return((int) DB_SUCCESS); } diff --git a/sync/sync0arr.c b/sync/sync0arr.c index 0e30fd054a8..cfa52cdcc88 100644 --- a/sync/sync0arr.c +++ b/sync/sync0arr.c @@ -227,24 +227,21 @@ sync_array_create( SYNC_ARRAY_MUTEX: determines the type of mutex protecting the data structure */ { + ulint sz; sync_array_t* arr; - sync_cell_t* cell_array; - sync_cell_t* cell; - ulint i; ut_a(n_cells > 0); /* Allocate memory for the data structures */ arr = ut_malloc(sizeof(sync_array_t)); + memset(arr, 0x0, sizeof(*arr)); - cell_array = ut_malloc(sizeof(sync_cell_t) * n_cells); + sz = sizeof(sync_cell_t) * n_cells; + arr->array = ut_malloc(sz); + memset(arr->array, 0x0, sz); arr->n_cells = n_cells; - arr->n_reserved = 0; - arr->array = cell_array; arr->protection = protection; - arr->sg_count = 0; - arr->res_count = 0; /* Then create the mutex to protect the wait array complex */ if (protection == SYNC_ARRAY_OS_MUTEX) { @@ -255,13 +252,6 @@ sync_array_create( ut_error; } - for (i = 0; i < n_cells; i++) { - cell = sync_array_get_nth_cell(arr, i); - cell->wait_object = NULL; - cell->waiting = FALSE; - cell->signal_count = 0; - } - return(arr); } diff --git a/sync/sync0rw.c b/sync/sync0rw.c index b07bd21dcac..07eac403dfe 100644 --- a/sync/sync0rw.c +++ b/sync/sync0rw.c @@ -38,6 +38,7 @@ Created 9/11/1995 Heikki Tuuri #include "os0thread.h" #include "mem0mem.h" #include "srv0srv.h" +#include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */ /* IMPLEMENTATION OF THE RW_LOCK diff --git a/sync/sync0sync.c b/sync/sync0sync.c index 9302f6bebf2..272492cb3e4 100644 --- a/sync/sync0sync.c +++ b/sync/sync0sync.c @@ -39,6 +39,7 @@ Created 9/5/1995 Heikki Tuuri #include "buf0buf.h" #include "srv0srv.h" #include "buf0types.h" +#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */ /* REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX @@ -253,7 +254,7 @@ mutex_create_func( mutex->lock_word = 0; #endif mutex->event = os_event_create(NULL); - mutex_set_waiters(mutex, 0); + mutex->waiters = 0; #ifdef UNIV_DEBUG mutex->magic_n = MUTEX_MAGIC_N; #endif /* UNIV_DEBUG */ @@ -426,10 +427,18 @@ mutex_set_waiters( the value is stored to memory */ ut_ad(mutex); +#ifdef INNODB_RW_LOCKS_USE_ATOMICS + if (n) { + os_compare_and_swap_ulint(&mutex->waiters, 0, 1); + } else { + os_compare_and_swap_ulint(&mutex->waiters, 1, 0); + } +#else ptr = &(mutex->waiters); *ptr = n; /* Here we assume that the write of a single word in memory is atomic */ +#endif } /******************************************************************//** @@ -851,7 +860,8 @@ sync_thread_levels_g( /*=================*/ sync_level_t* arr, /*!< in: pointer to level array for an OS thread */ - ulint limit) /*!< in: level limit */ + ulint limit, /*!< in: level limit */ + ulint warn) /*!< in: TRUE=display a diagnostic message */ { sync_level_t* slot; rw_lock_t* lock; @@ -865,6 +875,11 @@ sync_thread_levels_g( if (slot->latch != NULL) { if (slot->level <= limit) { + if (!warn) { + + return(FALSE); + } + lock = slot->latch; mutex = slot->latch; @@ -1107,7 +1122,7 @@ sync_thread_add_level( case SYNC_DICT_HEADER: case SYNC_TRX_I_S_RWLOCK: case SYNC_TRX_I_S_LAST_READ: - if (!sync_thread_levels_g(array, level)) { + if (!sync_thread_levels_g(array, level, TRUE)) { fprintf(stderr, "InnoDB: sync_thread_levels_g(array, %lu)" " does not hold!\n", level); @@ -1118,36 +1133,44 @@ sync_thread_add_level( /* Either the thread must own the buffer pool mutex (buf_pool_mutex), or it is allowed to latch only ONE buffer block (block->mutex or buf_pool_zip_mutex). */ - if (!sync_thread_levels_g(array, level)) { - ut_a(sync_thread_levels_g(array, level - 1)); + if (!sync_thread_levels_g(array, level, FALSE)) { + ut_a(sync_thread_levels_g(array, level - 1, TRUE)); ut_a(sync_thread_levels_contain(array, SYNC_BUF_LRU_LIST)); } break; case SYNC_REC_LOCK: - ut_a((sync_thread_levels_contain(array, SYNC_KERNEL) - && sync_thread_levels_g(array, SYNC_REC_LOCK - 1)) - || sync_thread_levels_g(array, SYNC_REC_LOCK)); + if (sync_thread_levels_contain(array, SYNC_KERNEL)) { + ut_a(sync_thread_levels_g(array, SYNC_REC_LOCK - 1, + TRUE)); + } else { + ut_a(sync_thread_levels_g(array, SYNC_REC_LOCK, TRUE)); + } break; case SYNC_IBUF_BITMAP: /* Either the thread must own the master mutex to all the bitmap pages, or it is allowed to latch only ONE bitmap page. */ - ut_a((sync_thread_levels_contain(array, SYNC_IBUF_BITMAP_MUTEX) - && sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1)) - || sync_thread_levels_g(array, SYNC_IBUF_BITMAP)); + if (sync_thread_levels_contain(array, + SYNC_IBUF_BITMAP_MUTEX)) { + ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1, + TRUE)); + } else { + ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP, + TRUE)); + } break; case SYNC_FSP_PAGE: ut_a(sync_thread_levels_contain(array, SYNC_FSP)); break; case SYNC_FSP: ut_a(sync_thread_levels_contain(array, SYNC_FSP) - || sync_thread_levels_g(array, SYNC_FSP)); + || sync_thread_levels_g(array, SYNC_FSP, TRUE)); break; case SYNC_TRX_UNDO_PAGE: ut_a(sync_thread_levels_contain(array, SYNC_TRX_UNDO) || sync_thread_levels_contain(array, SYNC_RSEG) || sync_thread_levels_contain(array, SYNC_PURGE_SYS) - || sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE)); + || sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE, TRUE)); break; case SYNC_RSEG_HEADER: ut_a(sync_thread_levels_contain(array, SYNC_RSEG)); @@ -1159,37 +1182,41 @@ sync_thread_add_level( case SYNC_TREE_NODE: ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE) || sync_thread_levels_contain(array, SYNC_DICT_OPERATION) - || sync_thread_levels_g(array, SYNC_TREE_NODE - 1)); + || sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE)); break; case SYNC_TREE_NODE_NEW: ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE) || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); break; case SYNC_INDEX_TREE: - ut_a((sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) - && sync_thread_levels_contain(array, SYNC_FSP) - && sync_thread_levels_g(array, SYNC_FSP_PAGE - 1)) - || sync_thread_levels_g(array, SYNC_TREE_NODE - 1)); + if (sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) + && sync_thread_levels_contain(array, SYNC_FSP)) { + ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1, + TRUE)); + } else { + ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1, + TRUE)); + } break; case SYNC_IBUF_MUTEX: - ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1)); + ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1, TRUE)); break; case SYNC_IBUF_PESS_INSERT_MUTEX: - ut_a(sync_thread_levels_g(array, SYNC_FSP - 1) - && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); + ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE)); + ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); break; case SYNC_IBUF_HEADER: - ut_a(sync_thread_levels_g(array, SYNC_FSP - 1) - && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) - && !sync_thread_levels_contain( - array, SYNC_IBUF_PESS_INSERT_MUTEX)); + ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE)); + ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); + ut_a(!sync_thread_levels_contain(array, + SYNC_IBUF_PESS_INSERT_MUTEX)); break; case SYNC_DICT: #ifdef UNIV_DEBUG ut_a(buf_debug_prints - || sync_thread_levels_g(array, SYNC_DICT)); + || sync_thread_levels_g(array, SYNC_DICT, TRUE)); #else /* UNIV_DEBUG */ - ut_a(sync_thread_levels_g(array, SYNC_DICT)); + ut_a(sync_thread_levels_g(array, SYNC_DICT, TRUE)); #endif /* UNIV_DEBUG */ break; default: @@ -1365,7 +1392,12 @@ sync_close(void) mutex_free(&mutex_list_mutex); #ifdef UNIV_SYNC_DEBUG mutex_free(&sync_thread_mutex); + + /* Switch latching order checks on in sync0sync.c */ + sync_order_checks_on = FALSE; #endif /* UNIV_SYNC_DEBUG */ + + sync_initialized = FALSE; } /*******************************************************************//** diff --git a/thr/thr0loc.c b/thr/thr0loc.c index ecc7d720dd5..5b9e83be920 100644 --- a/thr/thr0loc.c +++ b/thr/thr0loc.c @@ -63,7 +63,7 @@ struct thr_local_struct{ os_thread_t handle; /*!< operating system handle to the thread */ ulint slot_no;/*!< the index of the slot in the thread table for this thread */ - ibool in_ibuf;/*!< TRUE if the the thread is doing an ibuf + ibool in_ibuf;/*!< TRUE if the thread is doing an ibuf operation */ hash_node_t hash; /*!< hash chain node */ ulint magic_n;/*!< magic number (THR_LOCAL_MAGIC_N) */ @@ -250,6 +250,37 @@ thr_local_init(void) mutex_create(&thr_local_mutex, SYNC_THR_LOCAL); } +/******************************************************************** +Close the thread local storage module. */ +UNIV_INTERN +void +thr_local_close(void) +/*=================*/ +{ + ulint i; + + ut_a(thr_local_hash != NULL); + + /* Free the hash elements. We don't remove them from the table + because we are going to destroy the table anyway. */ + for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) { + thr_local_t* local; + + local = HASH_GET_FIRST(thr_local_hash, i); + + while (local) { + thr_local_t* prev_local = local; + + local = HASH_GET_NEXT(hash, prev_local); + ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N); + mem_free(prev_local); + } + } + + hash_table_free(thr_local_hash); + thr_local_hash = NULL; +} + /************************************************************************* Return local hash table informations. */ diff --git a/trx/trx0i_s.c b/trx/trx0i_s.c index 0d809806edc..ef2e6850d6c 100644 --- a/trx/trx0i_s.c +++ b/trx/trx0i_s.c @@ -60,7 +60,7 @@ Created July 17, 2007 Vasil Dimov /** @brief The maximum number of chunks to allocate for a table cache. The rows of a table cache are stored in a set of chunks. When a new -row is added a new chunk is allocated if necessary. Assuming that the +row is added a new chunk is allocated if necessary. Assuming that the first one is 1024 rows (TABLE_CACHE_INITIAL_ROWSNUM) and each subsequent is N/2 where N is the number of rows we have allocated till now, then 39th chunk would accommodate 1677416425 rows and all chunks @@ -237,6 +237,27 @@ table_cache_init( } } +/*******************************************************************//** +Frees a table cache. */ +static +void +table_cache_free( +/*=============*/ + i_s_table_cache_t* table_cache) /*!< in/out: table cache */ +{ + ulint i; + + for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) { + + /* the memory is actually allocated in + table_cache_create_empty_row() */ + if (table_cache->chunks[i].base) { + mem_free(table_cache->chunks[i].base); + table_cache->chunks[i].base = NULL; + } + } +} + /*******************************************************************//** Returns an empty row from a table cache. The row is allocated if no more empty rows are available. The number of used rows is incremented. @@ -1251,6 +1272,22 @@ trx_i_s_cache_init( cache->is_truncated = FALSE; } +/*******************************************************************//** +Free the INFORMATION SCHEMA trx related cache. */ +UNIV_INTERN +void +trx_i_s_cache_free( +/*===============*/ + trx_i_s_cache_t* cache) /*!< in, own: cache to free */ +{ + hash_table_free(cache->locks_hash); + ha_storage_free(cache->storage); + table_cache_free(&cache->innodb_trx); + table_cache_free(&cache->innodb_locks); + table_cache_free(&cache->innodb_lock_waits); + memset(cache, 0, sizeof *cache); +} + /*******************************************************************//** Issue a shared/read lock on the tables cache. */ UNIV_INTERN diff --git a/trx/trx0purge.c b/trx/trx0purge.c index 62fbd1c1446..41e16b35e85 100644 --- a/trx/trx0purge.c +++ b/trx/trx0purge.c @@ -275,6 +275,44 @@ trx_purge_sys_create(void) } } +/************************************************************************ +Frees the global purge system control structure. */ +UNIV_INTERN +void +trx_purge_sys_close(void) +/*======================*/ +{ + ut_ad(!mutex_own(&kernel_mutex)); + + que_graph_free(purge_sys->query); + + ut_a(purge_sys->sess->trx->is_purge); + purge_sys->sess->trx->conc_state = TRX_NOT_STARTED; + sess_close(purge_sys->sess); + purge_sys->sess = NULL; + + if (purge_sys->view != NULL) { + /* Because acquiring the kernel mutex is a pre-condition + of read_view_close(). We don't really need it here. */ + mutex_enter(&kernel_mutex); + + read_view_close(purge_sys->view); + purge_sys->view = NULL; + + mutex_exit(&kernel_mutex); + } + + trx_undo_arr_free(purge_sys->arr); + + rw_lock_free(&purge_sys->latch); + mutex_free(&purge_sys->mutex); + + mem_heap_free(purge_sys->heap); + mem_free(purge_sys); + + purge_sys = NULL; +} + /*================ UNDO LOG HISTORY LIST =============================*/ /********************************************************************//** diff --git a/trx/trx0rec.c b/trx/trx0rec.c index 36911c9df85..5097cf18dcd 100644 --- a/trx/trx0rec.c +++ b/trx/trx0rec.c @@ -1333,7 +1333,7 @@ trx_undo_get_undo_rec_low( ulint rseg_id; ulint page_no; ulint offset; - page_t* undo_page; + const page_t* undo_page; trx_rseg_t* rseg; ibool is_insert; mtr_t mtr; @@ -1572,7 +1572,7 @@ trx_undo_prev_version_build( /* We have to set the appropriate extern storage bits in the old version of the record: the extern bits in rec for those - fields that update does NOT update, as well as the the bits for + fields that update does NOT update, as well as the bits for those fields that update updates to become externally stored fields. Store the info: */ diff --git a/trx/trx0roll.c b/trx/trx0roll.c index 51d17192d5b..c925478cdf4 100644 --- a/trx/trx0roll.c +++ b/trx/trx0roll.c @@ -66,9 +66,9 @@ int trx_general_rollback_for_mysql( /*===========================*/ trx_t* trx, /*!< in: transaction handle */ - ibool partial,/*!< in: TRUE if partial rollback requested */ trx_savept_t* savept) /*!< in: pointer to savepoint undo number, if - partial rollback requested */ + partial rollback requested, or NULL for + complete rollback */ { mem_heap_t* heap; que_thr_t* thr; @@ -85,9 +85,8 @@ trx_general_rollback_for_mysql( roll_node = roll_node_create(heap); - roll_node->partial = partial; - - if (partial) { + if (savept) { + roll_node->partial = TRUE; roll_node->savept = *savept; } @@ -145,7 +144,7 @@ trx_rollback_for_mysql( the transaction object does not have an InnoDB session object, and we set a dummy session that we use for all MySQL transactions. */ - err = trx_general_rollback_for_mysql(trx, FALSE, NULL); + err = trx_general_rollback_for_mysql(trx, NULL); trx->op_info = ""; @@ -170,8 +169,7 @@ trx_rollback_last_sql_stat_for_mysql( trx->op_info = "rollback of SQL statement"; - err = trx_general_rollback_for_mysql(trx, TRUE, - &(trx->last_sql_stat_start)); + err = trx_general_rollback_for_mysql(trx, &trx->last_sql_stat_start); /* The following call should not be needed, but we play safe: */ trx_mark_sql_stat_end(trx); @@ -282,7 +280,7 @@ trx_rollback_to_savepoint_for_mysql( trx->op_info = "rollback to a savepoint"; - err = trx_general_rollback_for_mysql(trx, TRUE, &(savep->savept)); + err = trx_general_rollback_for_mysql(trx, &savep->savept); /* Store the current undo_no of the transaction so that we know where to roll back if we have to roll back the next SQL statement: */ @@ -534,28 +532,26 @@ trx_rollback_active( Rollback or clean up any incomplete transactions which were encountered in crash recovery. If the transaction already was committed, then we clean up a possible insert undo log. If the -transaction was not yet committed, then we roll it back. -Note: this is done in a background thread. -@return a dummy parameter */ +transaction was not yet committed, then we roll it back. */ UNIV_INTERN -os_thread_ret_t -trx_rollback_or_clean_all_recovered( -/*================================*/ - void* arg __attribute__((unused))) - /*!< in: a dummy parameter required by - os_thread_create */ +void +trx_rollback_or_clean_recovered( +/*============================*/ + ibool all) /*!< in: FALSE=roll back dictionary transactions; + TRUE=roll back all non-PREPARED transactions */ { trx_t* trx; mutex_enter(&kernel_mutex); - if (UT_LIST_GET_FIRST(trx_sys->trx_list)) { + if (!UT_LIST_GET_FIRST(trx_sys->trx_list)) { + goto leave_function; + } + if (all) { fprintf(stderr, "InnoDB: Starting in background the rollback" " of uncommitted transactions\n"); - } else { - goto leave_function; } mutex_exit(&kernel_mutex); @@ -584,18 +580,42 @@ loop: goto loop; case TRX_ACTIVE: - mutex_exit(&kernel_mutex); - trx_rollback_active(trx); - goto loop; + if (all || trx_get_dict_operation(trx) + != TRX_DICT_OP_NONE) { + mutex_exit(&kernel_mutex); + trx_rollback_active(trx); + goto loop; + } } } - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Rollback of non-prepared transactions completed\n"); + if (all) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Rollback of non-prepared" + " transactions completed\n"); + } leave_function: mutex_exit(&kernel_mutex); +} + +/*******************************************************************//** +Rollback or clean up any incomplete transactions which were +encountered in crash recovery. If the transaction already was +committed, then we clean up a possible insert undo log. If the +transaction was not yet committed, then we roll it back. +Note: this is done in a background thread. +@return a dummy parameter */ +UNIV_INTERN +os_thread_ret_t +trx_rollback_or_clean_all_recovered( +/*================================*/ + void* arg __attribute__((unused))) + /*!< in: a dummy parameter required by + os_thread_create */ +{ + trx_rollback_or_clean_recovered(TRUE); /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/trx/trx0rseg.c b/trx/trx0rseg.c index 580762e8716..8d754788e2a 100644 --- a/trx/trx0rseg.c +++ b/trx/trx0rseg.c @@ -132,6 +132,49 @@ trx_rseg_header_create( } /***********************************************************************//** +Free's an instance of the rollback segment in memory. */ +UNIV_INTERN +void +trx_rseg_mem_free( +/*==============*/ + trx_rseg_t* rseg) /* in, own: instance to free */ +{ + trx_undo_t* undo; + + mutex_free(&rseg->mutex); + + /* There can't be any active transactions. */ + ut_a(UT_LIST_GET_LEN(rseg->update_undo_list) == 0); + ut_a(UT_LIST_GET_LEN(rseg->insert_undo_list) == 0); + + undo = UT_LIST_GET_FIRST(rseg->update_undo_cached); + + while (undo != NULL) { + trx_undo_t* prev_undo = undo; + + undo = UT_LIST_GET_NEXT(undo_list, undo); + UT_LIST_REMOVE(undo_list, rseg->update_undo_cached, prev_undo); + + trx_undo_mem_free(prev_undo); + } + + undo = UT_LIST_GET_FIRST(rseg->insert_undo_cached); + + while (undo != NULL) { + trx_undo_t* prev_undo = undo; + + undo = UT_LIST_GET_NEXT(undo_list, undo); + UT_LIST_REMOVE(undo_list, rseg->insert_undo_cached, prev_undo); + + trx_undo_mem_free(prev_undo); + } + + trx_sys_set_nth_rseg(trx_sys, rseg->id, NULL); + + mem_free(rseg); +} + +/*************************************************************************** Creates and initializes a rollback segment object. The values for the fields are read from the header. The object is inserted to the rseg list of the trx system object and a pointer is inserted in the rseg diff --git a/trx/trx0sys.c b/trx/trx0sys.c index 81c614c8323..8ea34a8c81c 100644 --- a/trx/trx0sys.c +++ b/trx/trx0sys.c @@ -39,7 +39,9 @@ Created 3/26/1996 Heikki Tuuri #include "srv0srv.h" #include "trx0purge.h" #include "log0log.h" +#include "log0recv.h" #include "os0file.h" +#include "read0read.h" /** The file format tag structure with id and name. */ struct file_format_struct { @@ -552,6 +554,12 @@ trx_sys_doublewrite_init_or_restore_pages( zip_size ? zip_size : UNIV_PAGE_SIZE, read_buf, NULL); + if (srv_recovery_stats && recv_recovery_is_on()) { + mutex_enter(&(recv_sys->mutex)); + recv_sys->stats_doublewrite_check_pages++; + mutex_exit(&(recv_sys->mutex)); + } + /* Check if the page is corrupt */ if (UNIV_UNLIKELY @@ -599,6 +607,13 @@ trx_sys_doublewrite_init_or_restore_pages( zip_size, page_no, 0, zip_size ? zip_size : UNIV_PAGE_SIZE, page, NULL); + + if (srv_recovery_stats && recv_recovery_is_on()) { + mutex_enter(&(recv_sys->mutex)); + recv_sys->stats_doublewrite_overwrite_pages++; + mutex_exit(&(recv_sys->mutex)); + } + fprintf(stderr, "InnoDB: Recovered the page from" " the doublewrite buffer.\n"); @@ -1592,3 +1607,80 @@ trx_sys_file_format_id_to_name( } #endif /* !UNIV_HOTBACKUP */ + +/********************************************************************* +Shutdown/Close the transaction system. */ +UNIV_INTERN +void +trx_sys_close(void) +/*===============*/ +{ + trx_rseg_t* rseg; + read_view_t* view; + + ut_ad(trx_sys != NULL); + + /* Check that all read views are closed except read view owned + by a purge. */ + + if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) { + fprintf(stderr, + "InnoDB: Error: all read views were not closed" + " before shutdown:\n" + "InnoDB: %lu read views open \n", + UT_LIST_GET_LEN(trx_sys->view_list) - 1); + } + + sess_close(trx_dummy_sess); + trx_dummy_sess = NULL; + + trx_purge_sys_close(); + + mutex_enter(&kernel_mutex); + + /* Free the double write data structures. */ + ut_a(trx_doublewrite != NULL); + ut_free(trx_doublewrite->write_buf_unaligned); + trx_doublewrite->write_buf_unaligned = NULL; + + mem_free(trx_doublewrite->buf_block_arr); + trx_doublewrite->buf_block_arr = NULL; + + mutex_free(&trx_doublewrite->mutex); + mem_free(trx_doublewrite); + trx_doublewrite = NULL; + + /* There can't be any active transactions. */ + rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); + + while (rseg != NULL) { + trx_rseg_t* prev_rseg = rseg; + + rseg = UT_LIST_GET_NEXT(rseg_list, prev_rseg); + UT_LIST_REMOVE(rseg_list, trx_sys->rseg_list, prev_rseg); + + trx_rseg_mem_free(prev_rseg); + } + + view = UT_LIST_GET_FIRST(trx_sys->view_list); + + while (view != NULL) { + read_view_t* prev_view = view; + + view = UT_LIST_GET_NEXT(view_list, prev_view); + + /* Views are allocated from the trx_sys->global_read_view_heap. + So, we simply remove the element here. */ + UT_LIST_REMOVE(view_list, trx_sys->view_list, prev_view); + } + + ut_a(UT_LIST_GET_LEN(trx_sys->trx_list) == 0); + ut_a(UT_LIST_GET_LEN(trx_sys->rseg_list) == 0); + ut_a(UT_LIST_GET_LEN(trx_sys->view_list) == 0); + ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0); + + mem_free(trx_sys); + + trx_sys = NULL; + mutex_exit(&kernel_mutex); +} diff --git a/trx/trx0trx.c b/trx/trx0trx.c index b7fedf58c2a..69bc5c6b18b 100644 --- a/trx/trx0trx.c +++ b/trx/trx0trx.c @@ -846,7 +846,7 @@ trx_commit_off_kernel( in exactly the same order as commit lsn's, if the transactions have different rollback segments. To get exactly the same order we should hold the kernel mutex up to this point, - adding to to the contention of the kernel mutex. However, if + adding to the contention of the kernel mutex. However, if a transaction T2 is able to see modifications made by a transaction T1, T2 will always get a bigger transaction number and a bigger commit lsn than T1. */ @@ -993,7 +993,7 @@ trx_commit_off_kernel( /****************************************************************//** Cleans up a transaction at database startup. The cleanup is needed if the transaction already got to the middle of a commit when the database -crashed, andf we cannot roll it back. */ +crashed, and we cannot roll it back. */ UNIV_INTERN void trx_cleanup_at_db_startup( diff --git a/trx/trx0undo.c b/trx/trx0undo.c index 99672d4eb81..063a2f2b8a6 100644 --- a/trx/trx0undo.c +++ b/trx/trx0undo.c @@ -1560,7 +1560,7 @@ trx_undo_mem_init_for_reuse( /********************************************************************//** Frees an undo log memory copy. */ -static +UNIV_INTERN void trx_undo_mem_free( /*==============*/ diff --git a/usr/usr0sess.c b/usr/usr0sess.c index 990991a2c06..8087dcb4170 100644 --- a/usr/usr0sess.c +++ b/usr/usr0sess.c @@ -31,14 +31,6 @@ Created 6/25/1996 Heikki Tuuri #include "trx0trx.h" -/*********************************************************************//** -Closes a session, freeing the memory occupied by it. */ -static -void -sess_close( -/*=======*/ - sess_t* sess); /*!< in, own: session object */ - /*********************************************************************//** Opens a session. @return own: session object */ @@ -64,35 +56,16 @@ sess_open(void) /*********************************************************************//** Closes a session, freeing the memory occupied by it. */ -static +UNIV_INTERN void sess_close( /*=======*/ sess_t* sess) /*!< in, own: session object */ { - ut_ad(mutex_own(&kernel_mutex)); - ut_ad(sess->trx == NULL); + ut_ad(!mutex_own(&kernel_mutex)); + ut_a(UT_LIST_GET_LEN(sess->graphs) == 0); + + trx_free_for_background(sess->trx); mem_free(sess); } - -/*********************************************************************//** -Closes a session, freeing the memory occupied by it, if it is in a state -where it should be closed. -@return TRUE if closed */ -UNIV_INTERN -ibool -sess_try_close( -/*===========*/ - sess_t* sess) /*!< in, own: session object */ -{ - ut_ad(mutex_own(&kernel_mutex)); - - if (UT_LIST_GET_LEN(sess->graphs) == 0) { - sess_close(sess); - - return(TRUE); - } - - return(FALSE); -} diff --git a/ut/ut0auxconf_atomic_pthread_t_solaris.c b/ut/ut0auxconf_atomic_pthread_t_solaris.c index a18a537d1d4..310603c7503 100644 --- a/ut/ut0auxconf_atomic_pthread_t_solaris.c +++ b/ut/ut0auxconf_atomic_pthread_t_solaris.c @@ -17,18 +17,38 @@ Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ /***************************************************************************** -If this program compiles, then pthread_t objects can be used as arguments -to Solaris libc atomic functions. +If this program compiles and returns 0, then pthread_t objects can be used as +arguments to Solaris libc atomic functions. Created April 18, 2009 Vasil Dimov *****************************************************************************/ #include +#include int main(int argc, char** argv) { - pthread_t x = 0; + pthread_t x1; + pthread_t x2; + pthread_t x3; + + memset(&x1, 0x0, sizeof(x1)); + memset(&x2, 0x0, sizeof(x2)); + memset(&x3, 0x0, sizeof(x3)); + + if (sizeof(pthread_t) == 4) { + + atomic_cas_32(&x1, x2, x3); + + } else if (sizeof(pthread_t) == 8) { + + atomic_cas_64(&x1, x2, x3); + + } else { + + return(1); + } return(0); } diff --git a/ut/ut0auxconf_have_gcc_atomics.c b/ut/ut0auxconf_have_gcc_atomics.c new file mode 100644 index 00000000000..da5c13d7d79 --- /dev/null +++ b/ut/ut0auxconf_have_gcc_atomics.c @@ -0,0 +1,61 @@ +/***************************************************************************** + +Copyright (c) 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/***************************************************************************** +If this program compiles and returns 0, then GCC atomic funcions are available. + +Created September 12, 2009 Vasil Dimov +*****************************************************************************/ + +int +main(int argc, char** argv) +{ + long x; + long y; + long res; + char c; + + x = 10; + y = 123; + res = __sync_bool_compare_and_swap(&x, x, y); + if (!res || x != y) { + return(1); + } + + x = 10; + y = 123; + res = __sync_bool_compare_and_swap(&x, x + 1, y); + if (res || x != 10) { + return(1); + } + + x = 10; + y = 123; + res = __sync_add_and_fetch(&x, y); + if (res != 123 + 10 || x != 123 + 10) { + return(1); + } + + c = 10; + res = __sync_lock_test_and_set(&c, 123); + if (res != 10 || c != 123) { + return(1); + } + + return(0); +} diff --git a/ut/ut0mem.c b/ut/ut0mem.c index edb63c95700..35a325b9ccd 100644 --- a/ut/ut0mem.c +++ b/ut/ut0mem.c @@ -433,6 +433,8 @@ ut_free_all_mem(void) " total allocated memory is %lu\n", (ulong) ut_total_allocated_memory); } + + ut_mem_block_list_inited = FALSE; } #endif /* !UNIV_HOTBACKUP */ diff --git a/ut/ut0ut.c b/ut/ut0ut.c index e4cc226fbad..498873e290a 100644 --- a/ut/ut0ut.c +++ b/ut/ut0ut.c @@ -132,6 +132,7 @@ ut_time(void) return(time(NULL)); } +#ifndef UNIV_HOTBACKUP /**********************************************************//** Returns system time. Upon successful completion, the value 0 is returned; otherwise the @@ -199,6 +200,24 @@ ut_time_us( return(us); } +/**********************************************************//** +Returns the number of milliseconds since some epoch. The +value may wrap around. It should only be used for heuristic +purposes. +@return ms since epoch */ +UNIV_INTERN +ulint +ut_time_ms(void) +/*============*/ +{ + struct timeval tv; + + ut_gettimeofday(&tv, NULL); + + return((ulint) tv.tv_sec * 1000 + tv.tv_usec / 1000); +} +#endif /* !UNIV_HOTBACKUP */ + /**********************************************************//** Returns the difference of two times in seconds. @return time2 - time1 expressed in seconds */ diff --git a/win-plugin/README b/win-plugin/README deleted file mode 100644 index 00f4e996a3f..00000000000 --- a/win-plugin/README +++ /dev/null @@ -1,22 +0,0 @@ -This directory contains patches that need to be applied to the MySQL -source tree in order to build the dynamic plugin on Windows -- -HA_INNODB.DLL. Please note the followings when adding the patches: - -* The patch must be applied from the mysql top-level source directory. - patch -p0 < win-plugin.diff -* The patch filenames end in ".diff". -* All patches here are expected to apply cleanly to the latest MySQL 5.1 - tree when storage/innobase is replaced with this InnoDB branch. - -When applying the patch, the following files will be modified: - - * CMakeLists.txt - * sql/CMakeLists.txt - * win/configure.js - -Also, two new files will be added: - - * sql/mysqld.def - * sql/mysqld_x64.def - -You can get "patch" utility for Windows from http://unxutils.sourceforge.net/ diff --git a/win-plugin/win-plugin.diff b/win-plugin/win-plugin.diff deleted file mode 100644 index 4b3354ac4de..00000000000 --- a/win-plugin/win-plugin.diff +++ /dev/null @@ -1,279 +0,0 @@ -diff -Nur CMakeLists.txt.orig CMakeLists.txt ---- CMakeLists.txt.orig 2008-10-03 12:25:41 -05:00 -+++ CMakeLists.txt 2008-09-26 17:32:51 -05:00 -@@ -254,9 +254,9 @@ - IF(WITH_FEDERATED_STORAGE_ENGINE) - ADD_SUBDIRECTORY(storage/federated) - ENDIF(WITH_FEDERATED_STORAGE_ENGINE) --IF(WITH_INNOBASE_STORAGE_ENGINE) -+IF(WITH_INNOBASE_STORAGE_ENGINE OR INNODB_DYNAMIC_PLUGIN) - ADD_SUBDIRECTORY(storage/innobase) --ENDIF(WITH_INNOBASE_STORAGE_ENGINE) -+ENDIF(WITH_INNOBASE_STORAGE_ENGINE OR INNODB_DYNAMIC_PLUGIN) - ADD_SUBDIRECTORY(sql) - ADD_SUBDIRECTORY(server-tools/instance-manager) - ADD_SUBDIRECTORY(libmysql) - -diff -Nur sql/CMakeLists.txt.orig sql/CMakeLists.txt ---- sql/CMakeLists.txt.orig 2008-10-03 12:25:41 -05:00 -+++ sql/CMakeLists.txt 2008-09-24 03:58:19 -05:00 -@@ -98,6 +98,15 @@ - LINK_FLAGS "/PDB:${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb") - ENDIF(cmake_version EQUAL 20406) - -+# Checks for 64-bit version -+IF(CMAKE_SIZEOF_VOID_P MATCHES 8) -+SET_TARGET_PROPERTIES(mysqld PROPERTIES -+ LINK_FLAGS "/def:\"${PROJECT_SOURCE_DIR}/sql/mysqld_x64.def\"") -+ELSE(CMAKE_SIZEOF_VOID_P MATCHES 8) -+SET_TARGET_PROPERTIES(mysqld PROPERTIES -+ LINK_FLAGS "/def:\"${PROJECT_SOURCE_DIR}/sql/mysqld.def\"") -+ENDIF(CMAKE_SIZEOF_VOID_P MATCHES 8) -+ - IF(EMBED_MANIFESTS) - MYSQL_EMBED_MANIFEST("mysqld" "asInvoker") - ENDIF(EMBED_MANIFESTS) - -diff -Nur sql/mysqld.def.orig sql/mysqld.def ---- sql/mysqld.def.orig 1969-12-31 18:00:00 -06:00 -+++ sql/mysqld.def 2009-04-09 02:20:32 -05:00 -@@ -0,0 +1,111 @@ -+EXPORTS -+ ?use_hidden_primary_key@handler@@UAEXXZ -+ ?get_dynamic_partition_info@handler@@UAEXPAUPARTITION_INFO@@I@Z -+ ?read_first_row@handler@@UAEHPAEI@Z -+ ?read_range_next@handler@@UAEHXZ -+ ?read_range_first@handler@@UAEHPBUst_key_range@@0_N1@Z -+ ?read_multi_range_first@handler@@UAEHPAPAUst_key_multi_range@@PAU2@I_NPAUst_handler_buffer@@@Z -+ ?read_multi_range_next@handler@@UAEHPAPAUst_key_multi_range@@@Z -+ ?index_read_idx_map@handler@@UAEHPAEIPBEKW4ha_rkey_function@@@Z -+ ?print_error@handler@@UAEXHH@Z -+ ?clone@handler@@UAEPAV1@PAUst_mem_root@@@Z -+ ?get_auto_increment@handler@@UAEX_K00PA_K1@Z -+ ?index_next_same@handler@@UAEHPAEPBEI@Z -+ ?get_error_message@handler@@UAE_NHPAVString@@@Z -+ ?ha_thd@handler@@IBEPAVTHD@@XZ -+ ?update_auto_increment@handler@@QAEHXZ -+ ?ha_statistic_increment@handler@@IBEXPQsystem_status_var@@K@Z -+ ?trans_register_ha@@YAXPAVTHD@@_NPAUhandlerton@@@Z -+ ?cmp@Field_blob@@QAEHPBEI0I@Z -+ ?set_time@Field_timestamp@@QAEXXZ -+ ?sql_print_error@@YAXPBDZZ -+ ?sql_print_warning@@YAXPBDZZ -+ ?check_global_access@@YA_NPAVTHD@@K@Z -+ ?schema_table_store_record@@YA_NPAVTHD@@PAUst_table@@@Z -+ ?get_quote_char_for_identifier@@YAHPAVTHD@@PBDI@Z -+ ?copy@String@@QAE_NXZ -+ ?copy@String@@QAE_NABV1@@Z -+ ?copy@String@@QAE_NPBDIPAUcharset_info_st@@@Z -+ ?copy_and_convert@@YAIPADIPAUcharset_info_st@@PBDI1PAI@Z -+ ?filename_to_tablename@@YAIPBDPADI@Z -+ ?strconvert@@YAIPAUcharset_info_st@@PBD0PADIPAI@Z -+ ?calculate_key_len@@YAIPAUst_table@@IPBEK@Z -+ ?sql_alloc@@YAPAXI@Z -+ ?localtime_to_TIME@@YAXPAUst_mysql_time@@PAUtm@@@Z -+ ?push_warning@@YAPAVMYSQL_ERROR@@PAVTHD@@W4enum_warning_level@1@IPBD@Z -+ ?push_warning_printf@@YAXPAVTHD@@W4enum_warning_level@MYSQL_ERROR@@IPBDZZ -+ ?drop_table@handler@@EAEXPBD@Z -+ ?column_bitmaps_signal@handler@@UAEXXZ -+ ?delete_table@handler@@MAEHPBD@Z -+ ?rename_table@handler@@MAEHPBD0@Z -+ ?key_map_empty@@3V?$Bitmap@$0EA@@@B -+ ?THR_THD@@3PAVTHD@@A -+ ?end_of_list@@3Ulist_node@@A -+ ?mysql_tmpdir_list@@3Ust_my_tmpdir@@A -+ mysql_query_cache_invalidate4 -+ thd_query -+ thd_sql_command -+ thd_get_thread_id -+ thd_get_xid -+ thd_slave_thread -+ thd_non_transactional_update -+ thd_mark_transaction_to_rollback -+ thd_security_context -+ thd_charset -+ thd_test_options -+ thd_ha_data -+ thd_killed -+ thd_tx_isolation -+ thd_tablespace_op -+ thd_sql_command -+ thd_memdup -+ thd_make_lex_string -+ thd_in_lock_tables -+ thd_binlog_format -+ _my_hash_init -+ my_hash_free -+ my_tmpdir -+ check_if_legal_filename -+ my_filename -+ my_sync_dir_by_file -+ alloc_root -+ thr_lock_data_init -+ thr_lock_init -+ thr_lock_delete -+ my_multi_malloc -+ get_charset -+ unpack_filename -+ my_hash_insert -+ my_hash_search -+ my_hash_delete -+ mysql_bin_log_file_pos -+ mysql_bin_log_file_name -+ mysqld_embedded -+ my_thread_name -+ my_malloc -+ my_no_flags_free -+ _sanity -+ _mymalloc -+ _myfree -+ _my_strdup -+ _my_thread_var -+ my_error -+ pthread_cond_init -+ pthread_cond_signal -+ pthread_cond_wait -+ pthread_cond_destroy -+ localtime_r -+ my_strdup -+ deflate -+ deflateEnd -+ deflateReset -+ deflateInit2_ -+ inflateEnd -+ inflateInit_ -+ inflate -+ compressBound -+ inflateInit2_ -+ adler32 -+ longlong2str -+ strend -+ my_snprintf - -diff -Nur sql/mysqld_x64.def.orig sql/mysqld_x64.def ---- sql/mysqld_x64.def.orig 1969-12-31 18:00:00 -06:00 -+++ sql/mysqld_x64.def 2009-04-09 02:22:04 -05:00 -@@ -0,0 +1,111 @@ -+EXPORTS -+ ?use_hidden_primary_key@handler@@UEAAXXZ -+ ?get_dynamic_partition_info@handler@@UEAAXPEAUPARTITION_INFO@@I@Z -+ ?read_first_row@handler@@UEAAHPEAEI@Z -+ ?read_range_next@handler@@UEAAHXZ -+ ?read_range_first@handler@@UEAAHPEBUst_key_range@@0_N1@Z -+ ?read_multi_range_first@handler@@UEAAHPEAPEAUst_key_multi_range@@PEAU2@I_NPEAUst_handler_buffer@@@Z -+ ?read_multi_range_next@handler@@UEAAHPEAPEAUst_key_multi_range@@@Z -+ ?index_read_idx_map@handler@@UEAAHPEAEIPEBEKW4ha_rkey_function@@@Z -+ ?print_error@handler@@UEAAXHH@Z -+ ?clone@handler@@UEAAPEAV1@PEAUst_mem_root@@@Z -+ ?get_auto_increment@handler@@UEAAX_K00PEA_K1@Z -+ ?index_next_same@handler@@UEAAHPEAEPEBEI@Z -+ ?get_error_message@handler@@UEAA_NHPEAVString@@@Z -+ ?ha_thd@handler@@IEBAPEAVTHD@@XZ -+ ?update_auto_increment@handler@@QEAAHXZ -+ ?ha_statistic_increment@handler@@IEBAXPEQsystem_status_var@@K@Z -+ ?trans_register_ha@@YAXPEAVTHD@@_NPEAUhandlerton@@@Z -+ ?cmp@Field_blob@@QEAAHPEBEI0I@Z -+ ?set_time@Field_timestamp@@QEAAXXZ -+ ?sql_print_error@@YAXPEBDZZ -+ ?sql_print_warning@@YAXPEBDZZ -+ ?check_global_access@@YA_NPEAVTHD@@K@Z -+ ?schema_table_store_record@@YA_NPEAVTHD@@PEAUst_table@@@Z -+ ?get_quote_char_for_identifier@@YAHPEAVTHD@@PEBDI@Z -+ ?copy@String@@QEAA_NXZ -+ ?copy@String@@QEAA_NAEBV1@@Z -+ ?copy@String@@QEAA_NPEBDIPEAUcharset_info_st@@@Z -+ ?copy_and_convert@@YAIPEADIPEAUcharset_info_st@@PEBDI1PEAI@Z -+ ?filename_to_tablename@@YAIPEBDPEADI@Z -+ ?strconvert@@YAIPEAUcharset_info_st@@PEBD0PEADIPEAI@Z -+ ?calculate_key_len@@YAIPEAUst_table@@IPEBEK@Z -+ ?sql_alloc@@YAPEAX_K@Z -+ ?localtime_to_TIME@@YAXPEAUst_mysql_time@@PEAUtm@@@Z -+ ?push_warning@@YAPEAVMYSQL_ERROR@@PEAVTHD@@W4enum_warning_level@1@IPEBD@Z -+ ?push_warning_printf@@YAXPEAVTHD@@W4enum_warning_level@MYSQL_ERROR@@IPEBDZZ -+ ?drop_table@handler@@EEAAXPEBD@Z -+ ?column_bitmaps_signal@handler@@UEAAXXZ -+ ?delete_table@handler@@MEAAHPEBD@Z -+ ?rename_table@handler@@MEAAHPEBD0@Z -+ ?key_map_empty@@3V?$Bitmap@$0EA@@@B -+ ?THR_THD@@3PEAVTHD@@EA -+ ?end_of_list@@3Ulist_node@@A -+ ?mysql_tmpdir_list@@3Ust_my_tmpdir@@A -+ mysql_query_cache_invalidate4 -+ thd_query -+ thd_sql_command -+ thd_get_thread_id -+ thd_get_xid -+ thd_slave_thread -+ thd_non_transactional_update -+ thd_mark_transaction_to_rollback -+ thd_security_context -+ thd_charset -+ thd_test_options -+ thd_ha_data -+ thd_killed -+ thd_tx_isolation -+ thd_tablespace_op -+ thd_sql_command -+ thd_memdup -+ thd_make_lex_string -+ thd_in_lock_tables -+ thd_binlog_format -+ _my_hash_init -+ my_hash_free -+ my_tmpdir -+ check_if_legal_filename -+ my_filename -+ my_sync_dir_by_file -+ alloc_root -+ thr_lock_data_init -+ thr_lock_init -+ thr_lock_delete -+ my_multi_malloc -+ get_charset -+ unpack_filename -+ my_hash_insert -+ my_hash_search -+ my_hash_delete -+ mysql_bin_log_file_pos -+ mysql_bin_log_file_name -+ mysqld_embedded -+ my_thread_name -+ my_malloc -+ my_no_flags_free -+ _sanity -+ _mymalloc -+ _myfree -+ _my_strdup -+ _my_thread_var -+ my_error -+ pthread_cond_init -+ pthread_cond_signal -+ pthread_cond_wait -+ pthread_cond_destroy -+ localtime_r -+ my_strdup -+ deflate -+ deflateEnd -+ deflateReset -+ deflateInit2_ -+ inflateEnd -+ inflateInit_ -+ inflate -+ compressBound -+ inflateInit2_ -+ adler32 -+ longlong2str -+ strend -+ my_snprintf - -diff -Nur win/configure.js.orig win/configure.js ---- win/configure.js.orig 2008-09-26 21:18:37 -05:00 -+++ win/configure.js 2008-10-01 11:21:27 -05:00 -@@ -50,6 +50,7 @@ - case "EMBED_MANIFESTS": - case "EXTRA_DEBUG": - case "WITH_EMBEDDED_SERVER": -+ case "INNODB_DYNAMIC_PLUGIN": - configfile.WriteLine("SET (" + args.Item(i) + " TRUE)"); - break; - case "MYSQL_SERVER_SUFFIX": From b96f268acc3a693b673fceccc62311e169496731 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 6 Jan 2010 23:27:53 +0200 Subject: [PATCH 221/344] Removed compiler warnings Fixed sporadic test failure for suit/pbxt/t/lock_multi.test Fixed sporadic test faulure for suit/rpl/t/do_grant.test OpenSolaris 5.11-x86 now compiles (tested with 32 bit) BUILD/compile-solaris-amd64-debug-forte: Added execute bit BUILD/compile-solaris-x86-32: Added execute bit BUILD/compile-solaris-x86-32-debug: Added execute bit BUILD/compile-solaris-x86-32-debug-forte: Added execute bit BUILD/compile-solaris-x86-forte-32: Added execute bit extra/libevent/devpoll.c: Removed compiler warning extra/libevent/evbuffer.c: Removed compiler warning extra/libevent/select.c: Removed compiler warning mysql-test/mysql-test-run.pl: Fixed sporadic test faulure for suit/rpl/t/do_grant.test (Seen on OpenSolaris) mysql-test/suite/pbxt/r/lock_multi.result: Fixed sporadic test failure for suit/pbxt/t/lock_multi.test (seen in buildbot) This was done by merging the test with main/lock_multi.test mysql-test/suite/pbxt/t/lock_multi.test: Fixed sporadic test failure for suit/pbxt/t/lock_multi.test (seen in buildbot) This was done by merging the test with main/lock_multi.test mysys/my_sync.c: Removed compiler warnings sql/ha_ndbcluster.cc: Fixed linking error on OpenSolaris when compiling without ndb Bug #34866 Can't compile on Solaris 9/Sparc with gcc storage/archive/azlib.h: Removed compiler warning about redefined symbols storage/maria/ma_blockrec.c: Removed compiler warning storage/maria/ma_loghandler.c: Removed compiler warning storage/maria/ma_test3.c: Removed compiler warning storage/myisam/mi_test3.c: Removed compiler warning storage/pbxt/src/ha_pbxt.cc: Removed compiler warning thr_main -> thr_main_pbxt storage/pbxt/src/restart_xt.cc: thr_main -> thr_main_pbxt storage/pbxt/src/thread_xt.cc: thr_main -> thr_main_pbxt This was needed as thr_main() is an internal thread function on OpenSolaris() storage/pbxt/src/thread_xt.h: thr_main -> thr_main_pbxt storage/xtradb/srv/srv0srv.c: Use compatiblity macro to get code to work on OpenSolaris support-files/compiler_warnings.supp: Ignore compiler warning from yassl --- BUILD/compile-solaris-amd64-debug-forte | 0 BUILD/compile-solaris-x86-32 | 0 BUILD/compile-solaris-x86-32-debug | 0 BUILD/compile-solaris-x86-32-debug-forte | 0 BUILD/compile-solaris-x86-forte-32 | 0 extra/libevent/devpoll.c | 4 +- extra/libevent/evbuffer.c | 7 +- extra/libevent/select.c | 4 +- mysql-test/mysql-test-run.pl | 1 + mysql-test/suite/pbxt/r/lock_multi.result | 138 +++++-- mysql-test/suite/pbxt/t/lock_multi.test | 463 ++++++++++++++++++---- mysys/my_sync.c | 6 +- sql/ha_ndbcluster.cc | 2 + storage/archive/azlib.h | 3 +- storage/maria/ma_blockrec.c | 4 +- storage/maria/ma_loghandler.c | 4 +- storage/maria/ma_test3.c | 4 +- storage/myisam/mi_test3.c | 5 +- storage/pbxt/src/ha_pbxt.cc | 4 +- storage/pbxt/src/restart_xt.cc | 2 +- storage/pbxt/src/thread_xt.cc | 6 +- storage/pbxt/src/thread_xt.h | 2 +- storage/xtradb/srv/srv0srv.c | 13 +- support-files/compiler_warnings.supp | 3 + 24 files changed, 544 insertions(+), 131 deletions(-) mode change 100644 => 100755 BUILD/compile-solaris-amd64-debug-forte mode change 100644 => 100755 BUILD/compile-solaris-x86-32 mode change 100644 => 100755 BUILD/compile-solaris-x86-32-debug mode change 100644 => 100755 BUILD/compile-solaris-x86-32-debug-forte mode change 100644 => 100755 BUILD/compile-solaris-x86-forte-32 diff --git a/BUILD/compile-solaris-amd64-debug-forte b/BUILD/compile-solaris-amd64-debug-forte old mode 100644 new mode 100755 diff --git a/BUILD/compile-solaris-x86-32 b/BUILD/compile-solaris-x86-32 old mode 100644 new mode 100755 diff --git a/BUILD/compile-solaris-x86-32-debug b/BUILD/compile-solaris-x86-32-debug old mode 100644 new mode 100755 diff --git a/BUILD/compile-solaris-x86-32-debug-forte b/BUILD/compile-solaris-x86-32-debug-forte old mode 100644 new mode 100755 diff --git a/BUILD/compile-solaris-x86-forte-32 b/BUILD/compile-solaris-x86-forte-32 old mode 100644 new mode 100755 diff --git a/extra/libevent/devpoll.c b/extra/libevent/devpoll.c index 20813380b20..6d8bc82c641 100644 --- a/extra/libevent/devpoll.c +++ b/extra/libevent/devpoll.c @@ -185,7 +185,9 @@ devpoll_init(struct event_base *base) } static int -devpoll_recalc(struct event_base *base, void *arg, int max) +devpoll_recalc(struct event_base *base __attribute__((unused)), + void *arg __attribute__((unused)), + int max) { struct devpollop *devpollop = arg; diff --git a/extra/libevent/evbuffer.c b/extra/libevent/evbuffer.c index abd6a942431..758143c8225 100644 --- a/extra/libevent/evbuffer.c +++ b/extra/libevent/evbuffer.c @@ -25,12 +25,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include - #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include + #ifdef HAVE_SYS_TIME_H #include #endif @@ -75,7 +75,8 @@ bufferevent_add(struct event *ev, int timeout) */ void -bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now, +bufferevent_read_pressure_cb(struct evbuffer *buf, + size_t old __attribute__((unused)), size_t now, void *arg) { struct bufferevent *bufev = arg; /* diff --git a/extra/libevent/select.c b/extra/libevent/select.c index 54078777ac3..b8bd1a1c361 100644 --- a/extra/libevent/select.c +++ b/extra/libevent/select.c @@ -266,7 +266,7 @@ select_add(void *arg, struct event *ev) * of the fd_sets for select(2) */ if (sop->event_fds < ev->ev_fd) { - int fdsz = sop->event_fdsz; + unsigned int fdsz = sop->event_fdsz; if (fdsz < sizeof(fd_mask)) fdsz = sizeof(fd_mask); @@ -275,7 +275,7 @@ select_add(void *arg, struct event *ev) (howmany(ev->ev_fd + 1, NFDBITS) * sizeof(fd_mask))) fdsz *= 2; - if (fdsz != sop->event_fdsz) { + if (fdsz != (unsigned int) sop->event_fdsz) { if (select_resize(sop, fdsz)) { check_selectop(sop); return (-1); diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 46a46dc9631..eceb6a15cef 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -4010,6 +4010,7 @@ sub extract_warning_lines ($) { qr/Slave I\/O: error reconnecting to master '.*' - retry-time: [1-3] retries/, qr/Error reading packet/, qr/Slave: Can't drop database.* database doesn't exist/, + qr/Slave: Operation DROP USER failed for 'create_rout_db'/, ); my $matched_lines= []; diff --git a/mysql-test/suite/pbxt/r/lock_multi.result b/mysql-test/suite/pbxt/r/lock_multi.result index 3bb11bdf6ea..731ccedeecb 100644 --- a/mysql-test/suite/pbxt/r/lock_multi.result +++ b/mysql-test/suite/pbxt/r/lock_multi.result @@ -1,22 +1,4 @@ drop table if exists t1,t2; -create table t1(n int); -insert into t1 values (1); -lock tables t1 write; -update low_priority t1 set n = 4; -select n from t1; -unlock tables; -n -1 -drop table t1; -create table t1(n int); -insert into t1 values (1); -lock tables t1 read; -update low_priority t1 set n = 4; -select n from t1; -unlock tables; -n -1 -drop table t1; create table t1 (a int, b int); create table t2 (c int, d int); insert into t1 values(1,1); @@ -43,6 +25,7 @@ insert t1 select * from t2; drop table t2; ERROR 42S02: Table 'test.t2' doesn't exist drop table t1; +End of 4.1 tests create table t1(a int); lock tables t1 write; show columns from t1; @@ -50,10 +33,10 @@ Field Type Null Key Default Extra a int(11) YES NULL unlock tables; drop table t1; -use mysql; +USE mysql; LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE; FLUSH TABLES; -use mysql; +USE mysql; SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1; OPTIMIZE TABLES columns_priv, db, host, user; Table Op Msg_type Msg_text @@ -63,7 +46,8 @@ mysql.host optimize status OK mysql.user optimize status OK UNLOCK TABLES; Select_priv -use test; +N +USE test; use test; CREATE TABLE t1 (c1 int); LOCK TABLE t1 WRITE; @@ -90,7 +74,115 @@ DROP DATABASE mysqltest_1; ERROR HY000: Can't drop database 'mysqltest_1'; database doesn't exist create table t1 (f1 int(12) unsigned not null auto_increment, primary key(f1)) engine=innodb; lock tables t1 write; -alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; // -alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; // +alter table t1 auto_increment=0; +alter table t1 auto_increment=0; unlock tables; drop table t1; +create table t1 (a int); +create table t2 like t1; +# con1 +lock tables t1 write; +# con2 +flush tables with read lock; +# con5 +# global read lock is taken +# con3 +select * from t2 for update; +# waiting for release of read lock +# con4 +# would hang and later cause a deadlock +flush tables t2; +# clean up +unlock tables; +unlock tables; +a +drop table t1,t2; +# +# Lightweight version: +# Ensure that the wait for a GRL is done before opening tables. +# +create table t1 (a int); +create table t2 like t1; +# +# UPDATE +# +# default +flush tables with read lock; +# con1 +update t2 set a = 1; +# default +# statement is waiting for release of read lock +# con2 +flush table t2; +# default +unlock tables; +# con1 +# +# LOCK TABLES .. WRITE +# +# default +flush tables with read lock; +# con1 +lock tables t2 write; +# default +# statement is waiting for release of read lock +# con2 +flush table t2; +# default +unlock tables; +# con1 +unlock tables; +drop table t1,t2; +End of 5.0 tests +create table t1 (i int); +lock table t1 read; +update t1 set i= 10; +select * from t1; +Timeout in wait_condition.inc for select count(*) = 1 from information_schema.processlist +where state = "Locked" and info = "select * from t1" +kill query ID; +i +ERROR 70100: Query execution was interrupted +unlock tables; +drop table t1; +drop table if exists t1; +create table t1 (i int); +connection: default +lock tables t1 write; +connection: flush +flush tables with read lock;; +connection: default +alter table t1 add column j int; +connection: insert +insert into t1 values (1,2);; +connection: default +unlock tables; +connection: flush +select * from t1; +i j +unlock tables; +select * from t1; +i j +1 2 +drop table t1; +drop table if exists t1; +create table t1 (i int); +connection: default +lock tables t1 write; +connection: flush +flush tables with read lock;; +connection: default +flush tables; +unlock tables; +drop table t1; +drop table if exists t1,t2; +create table t1 (a int); +flush status; +lock tables t1 read; +insert into t1 values(1);; +unlock tables; +drop table t1; +select @tlwa < @tlwb; +@tlwa < @tlwb +1 +End of 5.1 tests diff --git a/mysql-test/suite/pbxt/t/lock_multi.test b/mysql-test/suite/pbxt/t/lock_multi.test index 57d4729657b..1104620b6b5 100644 --- a/mysql-test/suite/pbxt/t/lock_multi.test +++ b/mysql-test/suite/pbxt/t/lock_multi.test @@ -1,4 +1,8 @@ -- source include/not_embedded.inc + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + --disable_warnings drop table if exists t1,t2; --enable_warnings @@ -9,42 +13,6 @@ connect (locker,localhost,root,,); connect (reader,localhost,root,,); connect (writer,localhost,root,,); -connection locker; -create table t1(n int); -insert into t1 values (1); -lock tables t1 write; -connection writer; -send update low_priority t1 set n = 4; -connection reader; ---sleep 2 -send select n from t1; -connection locker; ---sleep 2 -unlock tables; -connection writer; -reap; -connection reader; -reap; -drop table t1; - -connection locker; -create table t1(n int); -insert into t1 values (1); -lock tables t1 read; -connection writer; -send update low_priority t1 set n = 4; -connection reader; ---sleep 2 -send select n from t1; -connection locker; ---sleep 2 -unlock tables; -connection writer; -reap; -connection reader; -reap; -drop table t1; - # # Test problem when using locks with multi-updates # It should not block when multi-update is reading on a read-locked table @@ -58,32 +26,33 @@ insert into t1 values(2,2); insert into t2 values(1,2); lock table t1 read; connection writer; ---sleep 2 -send update t1,t2 set c=a where b=d; +update t1,t2 set c=a where b=d; connection reader; ---sleep 2 select c from t2; -connection writer; -reap; connection locker; drop table t1; drop table t2; # -# Test problem when using locks on many tables and droping a table that +# Test problem when using locks on many tables and dropping a table that # is to-be-locked by another thread # - +# connection locker; create table t1 (a int); create table t2 (a int); lock table t1 write, t2 write; connection reader; -send insert t1 select * from t2; +send +insert t1 select * from t2; connection locker; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Locked" and info = "insert t1 select * from t2"; +--source include/wait_condition.inc drop table t2; connection reader; ---error 1146 +--error ER_NO_SUCH_TABLE reap; connection locker; drop table t1; @@ -97,20 +66,26 @@ create table t1 (a int); create table t2 (a int); lock table t1 write, t2 write, t1 as t1_2 write, t2 as t2_2 write; connection reader; -send insert t1 select * from t2; +send +insert t1 select * from t2; connection locker; +# Sleep a bit till the insert of connection reader is in work and hangs +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Locked" and info = "insert t1 select * from t2"; +--source include/wait_condition.inc drop table t2; connection reader; ---error 1146 +--error ER_NO_SUCH_TABLE reap; connection locker; drop table t1; -# End of 4.1 tests +--echo End of 4.1 tests # -# BUG#9998 - MySQL client hangs on USE "database" +# Bug#9998 MySQL client hangs on USE "database" # create table t1(a int); lock tables t1 write; @@ -121,21 +96,30 @@ unlock tables; drop table t1; # -# Bug#16986 - Deadlock condition with MyISAM tables +# Bug#16986 Deadlock condition with MyISAM tables # + +# Need a matching user in mysql.user for multi-table select +--source include/add_anonymous_users.inc + connection locker; -use mysql; +USE mysql; LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE; FLUSH TABLES; ---sleep 1 # connection reader; -use mysql; -#NOTE: This must be a multi-table select, otherwise the deadlock will not occur -send SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1; ---sleep 1 +USE mysql; +# Note: This must be a multi-table select, otherwise the deadlock will not occur +send +SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1; # connection locker; +# Sleep a bit till the select of connection reader is in work and hangs +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table" and info = + "SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1"; +--source include/wait_condition.inc # Make test case independent from earlier grants. --replace_result "Table is already up to date" "OK" OPTIMIZE TABLES columns_priv, db, host, user; @@ -143,7 +127,7 @@ UNLOCK TABLES; # connection reader; reap; -use test; +USE test; # connection locker; use test; @@ -158,11 +142,16 @@ LOCK TABLE t1 WRITE; # # This waits until t1 is unlocked. connection locker; -send FLUSH TABLES WITH READ LOCK; ---sleep 1 +send +FLUSH TABLES WITH READ LOCK; # -# This must not block. connection writer; +# Sleep a bit till the flush of connection locker is in work and hangs +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Flushing tables" and info = "FLUSH TABLES WITH READ LOCK"; +--source include/wait_condition.inc +# This must not block. CREATE TABLE t2 (c1 int); UNLOCK TABLES; # @@ -182,12 +171,17 @@ LOCK TABLE t1 WRITE; # # This waits until t1 is unlocked. connection locker; -send FLUSH TABLES WITH READ LOCK; ---sleep 1 +send +FLUSH TABLES WITH READ LOCK; # # This must not block. connection writer; ---error 1100 +# Sleep a bit till the flush of connection locker is in work and hangs +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Flushing tables" and info = "FLUSH TABLES WITH READ LOCK"; +--source include/wait_condition.inc +--error ER_TABLE_NOT_LOCKED CREATE TABLE t2 AS SELECT * FROM t1; UNLOCK TABLES; # @@ -199,8 +193,10 @@ UNLOCK TABLES; connection default; DROP TABLE t1; +--source include/delete_anonymous_users.inc + # -# Bug#19815 - CREATE/RENAME/DROP DATABASE can deadlock on a global read lock +# Bug#19815 CREATE/RENAME/DROP DATABASE can deadlock on a global read lock # connect (con1,localhost,root,,); connect (con2,localhost,root,,); @@ -212,12 +208,18 @@ FLUSH TABLES WITH READ LOCK; # With bug in place: acquire LOCK_mysql_create_table and # wait in wait_if_global_read_lock(). connection con2; -send DROP DATABASE mysqltest_1; ---sleep 1 +send +DROP DATABASE mysqltest_1; # # With bug in place: try to acquire LOCK_mysql_create_table... # When fixed: Reject dropping db because of the read lock. connection con1; +# Wait a bit so that the session con2 is in state "Waiting for release of readlock" +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for release of readlock" + and info = "DROP DATABASE mysqltest_1"; +--source include/wait_condition.inc --error ER_CANT_UPDATE_WITH_READLOCK DROP DATABASE mysqltest_1; UNLOCK TABLES; @@ -234,7 +236,7 @@ disconnect con2; DROP DATABASE mysqltest_1; # -# Bug #17264: MySQL Server freeze +# Bug#17264 MySQL Server freeze # connection locker; # Disable warnings to allow test to run also without InnoDB @@ -243,17 +245,22 @@ create table t1 (f1 int(12) unsigned not null auto_increment, primary key(f1)) e --enable_warnings lock tables t1 write; connection writer; ---sleep 2 -delimiter //; -send alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; // -delimiter ;// +send +alter table t1 auto_increment=0; connection reader; ---sleep 2 -delimiter //; -send alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; // -delimiter ;// +# Wait till connection writer is blocked +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Locked" and info = "alter table t1 auto_increment=0"; +--source include/wait_condition.inc +send +alter table t1 auto_increment=0; connection locker; ---sleep 2 +# Wait till connection reader is blocked +let $wait_condition= + select count(*) = 2 from information_schema.processlist + where state = "Locked" and info = "alter table t1 auto_increment=0"; +--source include/wait_condition.inc unlock tables; connection writer; reap; @@ -262,8 +269,310 @@ reap; connection locker; drop table t1; +# +# Bug#43230: SELECT ... FOR UPDATE can hang with FLUSH TABLES WITH READ LOCK indefinitely +# + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +connect (con3,localhost,root,,); +connect (con4,localhost,root,,); +connect (con5,localhost,root,,); + +create table t1 (a int); +create table t2 like t1; + +connection con1; +--echo # con1 +lock tables t1 write; +connection con2; +--echo # con2 +send flush tables with read lock; +connection con5; +--echo # con5 +let $show_statement= SHOW PROCESSLIST; +let $field= State; +let $condition= = 'Flushing tables'; +--source include/wait_show_condition.inc +--echo # global read lock is taken +connection con3; +--echo # con3 +send select * from t2 for update; +connection con5; +let $show_statement= SHOW PROCESSLIST; +let $field= State; +let $condition= = 'Waiting for release of readlock'; +--source include/wait_show_condition.inc +--echo # waiting for release of read lock +connection con4; +--echo # con4 +--echo # would hang and later cause a deadlock +flush tables t2; +connection con1; +--echo # clean up +unlock tables; +connection con2; +--reap +unlock tables; +connection con3; +--reap +connection default; +disconnect con5; +disconnect con4; +disconnect con3; +disconnect con2; +disconnect con1; + +drop table t1,t2; + +--echo # +--echo # Lightweight version: +--echo # Ensure that the wait for a GRL is done before opening tables. +--echo # + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); + +create table t1 (a int); +create table t2 like t1; + +--echo # +--echo # UPDATE +--echo # + +connection default; +--echo # default +flush tables with read lock; +connection con1; +--echo # con1 +send update t2 set a = 1; +connection default; +--echo # default +let $show_statement= SHOW PROCESSLIST; +let $field= State; +let $condition= = 'Waiting for release of readlock'; +--source include/wait_show_condition.inc +--echo # statement is waiting for release of read lock +connection con2; +--echo # con2 +flush table t2; +connection default; +--echo # default +unlock tables; +connection con1; +--echo # con1 +--reap + +--echo # +--echo # LOCK TABLES .. WRITE +--echo # + +connection default; +--echo # default +flush tables with read lock; +connection con1; +--echo # con1 +send lock tables t2 write; +connection default; +--echo # default +let $show_statement= SHOW PROCESSLIST; +let $field= State; +let $condition= = 'Waiting for release of readlock'; +--source include/wait_show_condition.inc +--echo # statement is waiting for release of read lock +connection con2; +--echo # con2 +flush table t2; +connection default; +--echo # default +unlock tables; +connection con1; +--echo # con1 +--reap +unlock tables; + +connection default; +disconnect con2; +disconnect con1; + +drop table t1,t2; + + +--echo End of 5.0 tests + + +# +# Bug#21281 Pending write lock is incorrectly removed when its +# statement being KILLed +# +create table t1 (i int); +connection locker; +lock table t1 read; +connection writer; +send +update t1 set i= 10; +connection reader; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Locked" and info = "update t1 set i= 10"; +--source include/wait_condition.inc +send +select * from t1; +connection default; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Locked" and info = "select * from t1"; +--source include/wait_condition.inc +let $ID= `select id from information_schema.processlist where state = "Locked" and info = "update t1 set i= 10"`; +--replace_result $ID ID +eval kill query $ID; +connection reader; +--reap +connection writer; +--error ER_QUERY_INTERRUPTED +--reap +connection locker; +unlock tables; +connection default; +drop table t1; + +# Disconnect sessions used in many subtests above +disconnect locker; +disconnect reader; +disconnect writer; + +# +# Bug#32395 Alter table under a impending global read lock causes a server crash +# + +# +# Test ALTER TABLE under LOCK TABLES and FLUSH TABLES WITH READ LOCK +# + +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (i int); +connect (flush,localhost,root,,test,,); +connection default; +--echo connection: default +lock tables t1 write; +connection flush; +--echo connection: flush +--send flush tables with read lock; +connection default; +--echo connection: default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Flushing tables"; +--source include/wait_condition.inc +alter table t1 add column j int; +connect (insert,localhost,root,,test,,); +connection insert; +--echo connection: insert +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Flushing tables"; +--source include/wait_condition.inc +--send insert into t1 values (1,2); +--echo connection: default +connection default; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for release of readlock"; +--source include/wait_condition.inc +unlock tables; +connection flush; +--echo connection: flush +--reap +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for release of readlock"; +--source include/wait_condition.inc +select * from t1; +unlock tables; +connection insert; +--reap +connection default; +let $wait_condition= + select count(*) = 1 from t1; +--source include/wait_condition.inc +select * from t1; +drop table t1; +disconnect flush; +disconnect insert; + +# +# Test that FLUSH TABLES under LOCK TABLES protects write locked tables +# from a impending FLUSH TABLES WITH READ LOCK +# + +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (i int); +connect (flush,localhost,root,,test,,); +connection default; +--echo connection: default +lock tables t1 write; +connection flush; +--echo connection: flush +--send flush tables with read lock; +connection default; +--echo connection: default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Flushing tables"; +--source include/wait_condition.inc +flush tables; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Flushing tables"; +--source include/wait_condition.inc +unlock tables; +let $wait_condition= + select count(*) = 0 from information_schema.processlist + where state = "Flushing tables"; +--source include/wait_condition.inc +connection flush; +--reap +connection default; +disconnect flush; +drop table t1; + +# +# Bug#30331 Table_locks_waited shows inaccurate values +# + +--disable_warnings +drop table if exists t1,t2; +--enable_warnings +create table t1 (a int); +flush status; +lock tables t1 read; +let $tlwa= `show status like 'Table_locks_waited'`; +connect (waiter,localhost,root,,); +connection waiter; +--send insert into t1 values(1); +connection default; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Locked" and info = "insert into t1 values(1)"; +--source include/wait_condition.inc +let $tlwb= `show status like 'Table_locks_waited'`; +unlock tables; +drop table t1; +disconnect waiter; +connection default; --disable_query_log +eval SET @tlwa= SUBSTRING_INDEX('$tlwa', ' ', -1); +eval SET @tlwb= SUBSTRING_INDEX('$tlwb', ' ', -1); drop database pbxt; --enable_query_log -# End of 5.0 tests +select @tlwa < @tlwb; + +--echo End of 5.1 tests + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc diff --git a/mysys/my_sync.c b/mysys/my_sync.c index 1b8420c034e..f3503f29a95 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -100,7 +100,8 @@ static const char cur_dir_name[]= {FN_CURLIB, 0}; RETURN 0 if ok, !=0 if error */ -int my_sync_dir(const char *dir_name, myf my_flags) +int my_sync_dir(const char *dir_name __attribute__((unused)), + myf my_flags __attribute__((unused))) { #ifdef NEED_EXPLICIT_SYNC_DIR DBUG_ENTER("my_sync_dir"); @@ -141,7 +142,8 @@ int my_sync_dir(const char *dir_name, myf my_flags) RETURN 0 if ok, !=0 if error */ -int my_sync_dir_by_file(const char *file_name, myf my_flags) +int my_sync_dir_by_file(const char *file_name __attribute__((unused)), + myf my_flags __attribute__((unused))) { #ifdef NEED_EXPLICIT_SYNC_DIR char dir_name[FN_REFLEN]; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index a3b04ca51da..35ca65683d6 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -10565,4 +10565,6 @@ mysql_declare_plugin(ndbcluster) } mysql_declare_plugin_end; +#else +int Sun_ar_require_a_symbol_here= 0; #endif diff --git a/storage/archive/azlib.h b/storage/archive/azlib.h index d7abb40b2ae..29a6329fb0a 100644 --- a/storage/archive/azlib.h +++ b/storage/archive/azlib.h @@ -33,10 +33,9 @@ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). */ -#include - #include "../../mysys/mysys_priv.h" #include +#include #ifdef __cplusplus extern "C" { diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 694c8b7b5ff..e4e43bcfcfe 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -6094,7 +6094,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, DBUG_RETURN(0); } - if (((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != page_type)) + if (((uint) (buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != page_type)) { /* This is a page that has been freed before and now should be @@ -6241,7 +6241,7 @@ uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn, Note that in case the page is not anymore a head or tail page a future redo will fix the bitmap. */ - if ((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) == page_type) + if ((uint) (buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) == page_type) { empty_space= uint2korr(buff+EMPTY_SPACE_OFFSET); if (_ma_bitmap_set(info, page, page_type == HEAD_PAGE, diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index c5efab506f1..536336d795d 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -2823,8 +2823,8 @@ static my_bool translog_page_validator(uchar *page, data->was_recovered= 0; - if (uint3korr(page) != page_no || - uint3korr(page + 3) != data->number) + if ((pgcache_page_no_t) uint3korr(page) != page_no || + (uint32) uint3korr(page + 3) != data->number) { DBUG_PRINT("error", ("Page (%lu,0x%lx): " "page address written in the page is incorrect: " diff --git a/storage/maria/ma_test3.c b/storage/maria/ma_test3.c index 8dd631380a0..040d6fa78c2 100644 --- a/storage/maria/ma_test3.c +++ b/storage/maria/ma_test3.c @@ -180,7 +180,7 @@ void start_test(int id) if (pagecacheing && rnd(2) == 0) init_pagecache(maria_pagecache, 65536L, 0, 0, MARIA_KEY_BLOCK_LENGTH, MY_WME); - printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout); + printf("Process %d, pid: %ld\n",id,(long) getpid()); fflush(stdout); for (error=i=0 ; i < tests && !error; i++) { @@ -362,7 +362,7 @@ int test_write(MARIA_HA *file,int id,int lock_type) maria_extra(file,HA_EXTRA_WRITE_CACHE,0); } - sprintf((char*) record.id,"%7d",getpid()); + sprintf((char*) record.id,"%7ld", (long) getpid()); strnmov((char*) record.text,"Testing...", sizeof(record.text)); tries=(uint) rnd(100)+10; diff --git a/storage/myisam/mi_test3.c b/storage/myisam/mi_test3.c index 93f2b10fd3e..e792612a313 100644 --- a/storage/myisam/mi_test3.c +++ b/storage/myisam/mi_test3.c @@ -178,7 +178,8 @@ void start_test(int id) } if (key_cacheing && rnd(2) == 0) init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0); - printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout); + printf("Process %d, pid: %ld\n", id, (long) getpid()); + fflush(stdout); for (error=i=0 ; i < tests && !error; i++) { @@ -362,7 +363,7 @@ int test_write(MI_INFO *file,int id,int lock_type) mi_extra(file,HA_EXTRA_WRITE_CACHE,0); } - sprintf((char*) record.id,"%7d",getpid()); + sprintf((char*) record.id,"%7ld",(long) getpid()); strnmov((char*) record.text,"Testing...", sizeof(record.text)); tries=(uint) rnd(100)+10; diff --git a/storage/pbxt/src/ha_pbxt.cc b/storage/pbxt/src/ha_pbxt.cc index b088ad8daf2..3d4584e60b1 100644 --- a/storage/pbxt/src/ha_pbxt.cc +++ b/storage/pbxt/src/ha_pbxt.cc @@ -1294,7 +1294,7 @@ static int pbxt_init(void *p) #6 0x000debe1 in THD::THD at sql_class.cc:631 #7 0x00e207a4 in myxt_create_thread at myxt_xt.cc:2666 #8 0x00e3134b in tabc_fr_run_thread at tabcache_xt.cc:982 - #9 0x00e422ca in thr_main at thread_xt.cc:1006 + #9 0x00e422ca in thr_main_pbxt at thread_xt.cc:1006 #10 0x91ff7c55 in _pthread_start #11 0x91ff7b12 in thread_start * @@ -1557,7 +1557,7 @@ static int pbxt_prepare(handlerton *hton, THD *thd, bool all) return err; } -static XTThreadPtr ha_temp_open_global_database(handlerton *hton, THD **ret_thd, int *temp_thread, char *thread_name, int *err) +static XTThreadPtr ha_temp_open_global_database(handlerton *hton, THD **ret_thd, int *temp_thread, const char *thread_name, int *err) { THD *thd; XTThreadPtr self = NULL; diff --git a/storage/pbxt/src/restart_xt.cc b/storage/pbxt/src/restart_xt.cc index b34fdd76679..472c5ad0478 100644 --- a/storage/pbxt/src/restart_xt.cc +++ b/storage/pbxt/src/restart_xt.cc @@ -3314,7 +3314,7 @@ static void *xn_xres_run_recovery_thread(XTThreadPtr self) * #7 0x000c0db2 in THD::~THD at sql_class.cc:934 * #8 0x003b025b in myxt_destroy_thread at myxt_xt.cc:2999 * #9 0x003b66b5 in xn_xres_run_recovery_thread at restart_xt.cc:3196 - * #10 0x003cbfbb in thr_main at thread_xt.cc:1020 + * #10 0x003cbfbb in thr_main_pbxt at thread_xt.cc:1020 * myxt_destroy_thread(mysql_thread, TRUE); */ diff --git a/storage/pbxt/src/thread_xt.cc b/storage/pbxt/src/thread_xt.cc index 14c2a5e3b09..c31e23e69df 100644 --- a/storage/pbxt/src/thread_xt.cc +++ b/storage/pbxt/src/thread_xt.cc @@ -1013,7 +1013,7 @@ static xtBool thr_setup_signals(void) typedef void *(*ThreadMainFunc)(XTThreadPtr self); -extern "C" void *thr_main(void *data) +extern "C" void *thr_main_pbxt(void *data) { ThreadDataPtr td = (ThreadDataPtr) data; XTThreadPtr self = td->td_thr; @@ -1503,10 +1503,10 @@ xtPublic pthread_t xt_run_thread(XTThreadPtr self, XTThreadPtr child, void *(*st pthread_attr_t attr = { 0, 0, 0 }; attr.priority = THREAD_PRIORITY_NORMAL; - err = pthread_create(&child_thread, &attr, thr_main, &data); + err = pthread_create(&child_thread, &attr, thr_main_pbxt, &data); } #else - err = pthread_create(&child_thread, NULL, thr_main, &data); + err = pthread_create(&child_thread, NULL, thr_main_pbxt, &data); #endif if (err) { xt_free_thread(child); diff --git a/storage/pbxt/src/thread_xt.h b/storage/pbxt/src/thread_xt.h index 001f4adc33f..7fcf6105a59 100644 --- a/storage/pbxt/src/thread_xt.h +++ b/storage/pbxt/src/thread_xt.h @@ -536,7 +536,7 @@ extern struct XTThread **xt_thr_array; * Function prototypes */ -extern "C" void *thr_main(void *data); +extern "C" void *thr_main_pbxt(void *data); void xt_get_now(char *buffer, size_t len); xtBool xt_init_logging(void); diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index 5768249fc8d..acd3386d863 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -81,6 +81,7 @@ Created 10/8/1995 Heikki Tuuri #include "ut0mem.h" #include "ut0ut.h" #include "os0proc.h" +#include "os0sync.h" #include "mem0mem.h" #include "mem0pool.h" #include "sync0sync.h" @@ -1102,12 +1103,12 @@ srv_conc_enter_innodb_timer_based(trx_t* trx) } retry: if (srv_conc_n_threads < (lint) srv_thread_concurrency) { - conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1); + conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1); if (conc_n_threads <= (lint) srv_thread_concurrency) { enter_innodb_with_tickets(trx); return; } - __sync_add_and_fetch(&srv_conc_n_threads, -1); + os_atomic_increment_lint(&srv_conc_n_threads, -1); } if (!has_yielded) { @@ -1118,7 +1119,7 @@ retry: if (trx->has_search_latch || NULL != UT_LIST_GET_FIRST(trx->trx_locks)) { - conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1); + conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1); enter_innodb_with_tickets(trx); return; } @@ -1129,7 +1130,7 @@ retry: trx->op_info = ""; has_slept++; } - conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1); + conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1); enter_innodb_with_tickets(trx); return; } @@ -1137,7 +1138,7 @@ retry: static void srv_conc_exit_innodb_timer_based(trx_t* trx) { - __sync_add_and_fetch(&srv_conc_n_threads, -1); + os_atomic_increment_lint(&srv_conc_n_threads, -1); trx->declared_to_be_inside_innodb = FALSE; trx->n_tickets_to_enter_innodb = 0; return; @@ -1326,7 +1327,7 @@ srv_conc_force_enter_innodb( ut_ad(srv_conc_n_threads >= 0); #ifdef INNODB_RW_LOCKS_USE_ATOMICS if (srv_thread_concurrency_timer_based) { - __sync_add_and_fetch(&srv_conc_n_threads, 1); + os_atomic_increment_lint(&srv_conc_n_threads, 1); trx->declared_to_be_inside_innodb = TRUE; trx->n_tickets_to_enter_innodb = 1; return; diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index 9f3048ad996..968952c6dfd 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -88,6 +88,9 @@ storage/maria/ma_pagecache.c: .*'info_check_pin' defined but not used # storage/pbxt/ : typedef.*was ignored in this declaration +# +# Yassl +include/runtime.hpp: .*pure_error.* # # Groff warnings on OpenSUSE. From 951e92b2640793e4bfe4d02b8220266945326c0d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jan 2010 13:02:18 +0100 Subject: [PATCH 222/344] Add BUILD/compile-bintar, which builds MariaDB with correct options for a binary tarball release. BUILD/Makefile.am: Add BUILD/compile-bintar to source tarball. BUILD/SETUP.sh: Move common code to separate file to enable sharing. BUILD/compile-bintar: Add script to build with correct flags and ./configure options for bintar package. BUILD/util.sh: Move common code to separate file to enable sharing. --- BUILD/Makefile.am | 1 + BUILD/SETUP.sh | 10 ++---- BUILD/compile-bintar | 81 ++++++++++++++++++++++++++++++++++++++++++++ BUILD/util.sh | 40 ++++++++++++++++++++++ 4 files changed, 124 insertions(+), 8 deletions(-) create mode 100755 BUILD/compile-bintar create mode 100644 BUILD/util.sh diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am index 8343f1e2f27..06e3d22c9f6 100644 --- a/BUILD/Makefile.am +++ b/BUILD/Makefile.am @@ -34,6 +34,7 @@ EXTRA_DIST = FINISH.sh \ compile-amd64-max \ compile-amd64-max-sci \ compile-amd64-valgrind-max \ + compile-bintar \ compile-darwin-mwcc \ compile-dist \ compile-hpux11-parisc2-aCC \ diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 51a7d263131..2b3630217d4 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -86,15 +86,9 @@ set -e # path=`dirname $0` . "$path/check-cpu" +. "$path/util.sh" -export AM_MAKEFLAGS -# Default to a parallel build, but only if AM_MAKEFLAGS is not set. -# (So buildbots can easily disable this behaviour if required.) -if test -z "$AM_MAKEFLAGS" -then - AM_MAKEFLAGS="-j 6" -fi - +get_make_parallel_flag # SSL library to use.--with-ssl will select our bundled yaSSL # implementation of SSL. To use openSSl you will nee too point out diff --git a/BUILD/compile-bintar b/BUILD/compile-bintar new file mode 100755 index 00000000000..8777cfb2670 --- /dev/null +++ b/BUILD/compile-bintar @@ -0,0 +1,81 @@ +#!/bin/bash +# +# MariaDB SQL server. +# Copyright (C) 2010 Kristian Nielsen and Monty Program AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +# This script's purpose is to build the binary tarball packages for MariaDB +# (currently only on Linux systems). +# +# Thus BUILD/compile-bintar from the appropriate source tarball will reproduce +# such a release, provided the build environment (gcc version etc.) matches +# (use scripts/make_binary_distribution after running this script to actually +# create the binary tarball package). +# +# Note that packages are built from source tarballs not bzr checkouts. +# Therefore, this script assumes autotools have already been run. +# +# We link libc dynamically, otherwise we get lots of problems loading +# .so files at runtime (either system stuff like NSS, or server +# plugins). +# +# We link libgcc statically (and avoid linking libstdc++ at all by +# CXX=gcc), to avoid reduce nasty library version dependencies. + +test -f Makefile && make distclean + +path=`dirname $0` +. $path/util.sh + +SYSTEM_TYPE="$(uname -o)" +MACHINE_TYPE="$(uname -m)" + +# We cannot have a slash '/' in tarfile name. +SYSTEM_TYPE="$(echo ${SYSTEM_TYPE} | sed -e 's/GNU\///')" + +# Get correct options for architecture into CPUOPT. +get_cpuopt +# Get correct -j option into AM_MAKEFLAGS +get_make_parallel_flag + +# Use gcc rather than g++ to avoid linking libstdc++.so (which we don't need). +COMP="gcc -static-libgcc" +FLAGS="-O2 -fno-omit-frame-pointer -g -pipe -Wall $CPUOPT" + +# Don't press on in case of error. +set -e + +CC="$COMP" CXX="$COMP" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" \ + ./configure \ + --prefix=/usr/local/mysql \ + --exec-prefix=/usr/local/mysql \ + --libexecdir=/usr/local/mysql/bin \ + --localstatedir=/usr/local/mysql/data \ + \ + --with-comment="(MariaDB - http://mariadb.com/)" \ + --with-system-type="${SYSTEM_TYPE}" \ + --with-machine-type="${MACHINE_TYPE}" \ + \ + --enable-shared --enable-static \ + --with-client-ldflags=-static --with-mysqld-ldflags=-static \ + --enable-thread-safe-client --enable-local-infile --with-big-tables \ + --without-docs --with-extra-charsets=all \ + --with-libwrap --with-ssl --with-readline --with-libevent --with-zlib-dir=bundled \ + --with-partition --with-embedded-server \ + --with-plugins=max-no-ndb \ + --without-plugin-innodb_plugin + +make $AM_MAKEFLAGS diff --git a/BUILD/util.sh b/BUILD/util.sh new file mode 100644 index 00000000000..63b42db1f83 --- /dev/null +++ b/BUILD/util.sh @@ -0,0 +1,40 @@ +# MariaDB SQL server. +# Copyright (C) 2010 Kristian Nielsen and Monty Program AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Setting cpu options. +get_cpuopt () { + case "$(gcc -dumpmachine)" in + x86_64-*) + # gcc barfs on -march=... on x64 + CPUOPT="-m64 -mtune=generic" + ;; + *) + # we'd use i586 to not trip up mobile/lowpower devices + CPUOPT="-m32 -march=i586 -mtune=generic" + ;; + esac + return 0 +} + +# Default to a parallel build, but only if AM_MAKEFLAGS is not set. +# (So buildbots can easily disable this behaviour if required.) +get_make_parallel_flag () { + if test -z "$AM_MAKEFLAGS" + then + AM_MAKEFLAGS="-j 6" + fi + return 0 +} From 5b60ec399bb620dd7ff35c73422b80073b8f5330 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jan 2010 14:00:06 +0100 Subject: [PATCH 223/344] Revert earlier change that removes warnings, but breaks Windows compilation. --- extra/libevent/devpoll.c | 4 +--- extra/libevent/evbuffer.c | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/extra/libevent/devpoll.c b/extra/libevent/devpoll.c index 6d8bc82c641..20813380b20 100644 --- a/extra/libevent/devpoll.c +++ b/extra/libevent/devpoll.c @@ -185,9 +185,7 @@ devpoll_init(struct event_base *base) } static int -devpoll_recalc(struct event_base *base __attribute__((unused)), - void *arg __attribute__((unused)), - int max) +devpoll_recalc(struct event_base *base, void *arg, int max) { struct devpollop *devpollop = arg; diff --git a/extra/libevent/evbuffer.c b/extra/libevent/evbuffer.c index 758143c8225..6fe791380ea 100644 --- a/extra/libevent/evbuffer.c +++ b/extra/libevent/evbuffer.c @@ -75,8 +75,7 @@ bufferevent_add(struct event *ev, int timeout) */ void -bufferevent_read_pressure_cb(struct evbuffer *buf, - size_t old __attribute__((unused)), size_t now, +bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now, void *arg) { struct bufferevent *bufev = arg; /* From acb7de23306ce0b311344d679e8c63160ad32a49 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jan 2010 14:03:54 +0100 Subject: [PATCH 224/344] Add forgotten file to `make dist`. --- BUILD/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am index 06e3d22c9f6..6cf86f40535 100644 --- a/BUILD/Makefile.am +++ b/BUILD/Makefile.am @@ -81,7 +81,8 @@ EXTRA_DIST = FINISH.sh \ compile-solaris-x86-32 \ compile-solaris-x86-32-debug \ compile-solaris-x86-32-debug-forte \ - compile-solaris-x86-forte-32 + compile-solaris-x86-forte-32 \ + util.sh # Don't update the files from bitkeeper %::SCCS/s.% From 585303295fba0ecb01da868adc59de7a04a0d484 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Thu, 7 Jan 2010 17:45:54 +0000 Subject: [PATCH 225/344] BUG#50018: binlog corruption when table has many columns Some improvements on the test case as suggested during review. --- .../suite/rpl/r/rpl_row_tbl_metadata.result | 309 ++------------ .../suite/rpl/t/rpl_row_tbl_metadata.test | 402 +++++------------- 2 files changed, 150 insertions(+), 561 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result b/mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result index 551ece5da9d..711d0d063aa 100644 --- a/mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result +++ b/mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result @@ -4,7 +4,6 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -RESET MASTER; DROP TABLE IF EXISTS `t1`; ### TABLE with field_metadata_size == 290 CREATE TABLE `t1` ( @@ -157,9 +156,11 @@ CREATE TABLE `t1` ( PRIMARY KEY (`c1`) ) ENGINE=InnoDB; LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); -DROP TABLE `t1`; +INSERT INTO `t1`(c2) VALUES ('1'); FLUSH LOGS; +### assertion: the slave replicated event successfully and tables match +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE `t1`; === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. stop slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; @@ -167,271 +168,39 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -### TABLE with field_metadata_size == 250 -CREATE TABLE `t1` ( -`c1` int(11) NOT NULL AUTO_INCREMENT, -`c2` varchar(30) NOT NULL, -`c3` varchar(30) DEFAULT NULL, -`c4` varchar(30) DEFAULT NULL, -`c5` varchar(30) DEFAULT NULL, -`c6` varchar(30) DEFAULT NULL, -`c7` varchar(30) DEFAULT NULL, -`c8` varchar(30) DEFAULT NULL, -`c9` varchar(30) DEFAULT NULL, -`c10` varchar(30) DEFAULT NULL, -`c11` varchar(30) DEFAULT NULL, -`c12` varchar(30) DEFAULT NULL, -`c13` varchar(30) DEFAULT NULL, -`c14` varchar(30) DEFAULT NULL, -`c15` varchar(30) DEFAULT NULL, -`c16` varchar(30) DEFAULT NULL, -`c17` varchar(30) DEFAULT NULL, -`c18` varchar(30) DEFAULT NULL, -`c19` varchar(30) DEFAULT NULL, -`c20` varchar(30) DEFAULT NULL, -`c21` varchar(30) DEFAULT NULL, -`c22` varchar(30) DEFAULT NULL, -`c23` varchar(30) DEFAULT NULL, -`c24` varchar(30) DEFAULT NULL, -`c25` varchar(30) DEFAULT NULL, -`c26` varchar(30) DEFAULT NULL, -`c27` varchar(30) DEFAULT NULL, -`c28` varchar(30) DEFAULT NULL, -`c29` varchar(30) DEFAULT NULL, -`c30` varchar(30) DEFAULT NULL, -`c31` varchar(30) DEFAULT NULL, -`c32` varchar(30) DEFAULT NULL, -`c33` varchar(30) DEFAULT NULL, -`c34` varchar(30) DEFAULT NULL, -`c35` varchar(30) DEFAULT NULL, -`c36` varchar(30) DEFAULT NULL, -`c37` varchar(30) DEFAULT NULL, -`c38` varchar(30) DEFAULT NULL, -`c39` varchar(30) DEFAULT NULL, -`c40` varchar(30) DEFAULT NULL, -`c41` varchar(30) DEFAULT NULL, -`c42` varchar(30) DEFAULT NULL, -`c43` varchar(30) DEFAULT NULL, -`c44` varchar(30) DEFAULT NULL, -`c45` varchar(30) DEFAULT NULL, -`c46` varchar(30) DEFAULT NULL, -`c47` varchar(30) DEFAULT NULL, -`c48` varchar(30) DEFAULT NULL, -`c49` varchar(30) DEFAULT NULL, -`c50` varchar(30) DEFAULT NULL, -`c51` varchar(30) DEFAULT NULL, -`c52` varchar(30) DEFAULT NULL, -`c53` varchar(30) DEFAULT NULL, -`c54` varchar(30) DEFAULT NULL, -`c55` varchar(30) DEFAULT NULL, -`c56` varchar(30) DEFAULT NULL, -`c57` varchar(30) DEFAULT NULL, -`c58` varchar(30) DEFAULT NULL, -`c59` varchar(30) DEFAULT NULL, -`c60` varchar(30) DEFAULT NULL, -`c61` varchar(30) DEFAULT NULL, -`c62` varchar(30) DEFAULT NULL, -`c63` varchar(30) DEFAULT NULL, -`c64` varchar(30) DEFAULT NULL, -`c65` varchar(30) DEFAULT NULL, -`c66` varchar(30) DEFAULT NULL, -`c67` varchar(30) DEFAULT NULL, -`c68` varchar(30) DEFAULT NULL, -`c69` varchar(30) DEFAULT NULL, -`c70` varchar(30) DEFAULT NULL, -`c71` varchar(30) DEFAULT NULL, -`c72` varchar(30) DEFAULT NULL, -`c73` varchar(30) DEFAULT NULL, -`c74` varchar(30) DEFAULT NULL, -`c75` varchar(30) DEFAULT NULL, -`c76` varchar(30) DEFAULT NULL, -`c77` varchar(30) DEFAULT NULL, -`c78` varchar(30) DEFAULT NULL, -`c79` varchar(30) DEFAULT NULL, -`c80` varchar(30) DEFAULT NULL, -`c81` varchar(30) DEFAULT NULL, -`c82` varchar(30) DEFAULT NULL, -`c83` varchar(30) DEFAULT NULL, -`c84` varchar(30) DEFAULT NULL, -`c85` varchar(30) DEFAULT NULL, -`c86` varchar(30) DEFAULT NULL, -`c87` varchar(30) DEFAULT NULL, -`c88` varchar(30) DEFAULT NULL, -`c89` varchar(30) DEFAULT NULL, -`c90` varchar(30) DEFAULT NULL, -`c91` varchar(30) DEFAULT NULL, -`c92` varchar(30) DEFAULT NULL, -`c93` varchar(30) DEFAULT NULL, -`c94` varchar(30) DEFAULT NULL, -`c95` varchar(30) DEFAULT NULL, -`c96` varchar(30) DEFAULT NULL, -`c97` varchar(30) DEFAULT NULL, -`c98` varchar(30) DEFAULT NULL, -`c99` varchar(30) DEFAULT NULL, -`c100` varchar(30) DEFAULT NULL, -`c101` varchar(30) DEFAULT NULL, -`c102` varchar(30) DEFAULT NULL, -`c103` varchar(30) DEFAULT NULL, -`c104` varchar(30) DEFAULT NULL, -`c105` varchar(30) DEFAULT NULL, -`c106` varchar(30) DEFAULT NULL, -`c107` varchar(30) DEFAULT NULL, -`c108` varchar(30) DEFAULT NULL, -`c109` varchar(30) DEFAULT NULL, -`c110` varchar(30) DEFAULT NULL, -`c111` varchar(30) DEFAULT NULL, -`c112` varchar(30) DEFAULT NULL, -`c113` varchar(30) DEFAULT NULL, -`c114` varchar(30) DEFAULT NULL, -`c115` varchar(30) DEFAULT NULL, -`c116` varchar(30) DEFAULT NULL, -`c117` varchar(30) DEFAULT NULL, -`c118` varchar(30) DEFAULT NULL, -`c119` varchar(30) DEFAULT NULL, -`c120` varchar(30) DEFAULT NULL, -`c121` varchar(30) DEFAULT NULL, -`c122` varchar(30) DEFAULT NULL, -`c123` varchar(30) DEFAULT NULL, -`c124` varchar(30) DEFAULT NULL, -`c125` varchar(30) DEFAULT NULL, -`c126` varchar(30) DEFAULT NULL, -PRIMARY KEY (`c1`) -) ENGINE=InnoDB; -### TABLE with field_metadata_size == 251 -CREATE TABLE `t2` ( -`c1` float, -`c2` varchar(30) NOT NULL, -`c3` varchar(30) DEFAULT NULL, -`c4` varchar(30) DEFAULT NULL, -`c5` varchar(30) DEFAULT NULL, -`c6` varchar(30) DEFAULT NULL, -`c7` varchar(30) DEFAULT NULL, -`c8` varchar(30) DEFAULT NULL, -`c9` varchar(30) DEFAULT NULL, -`c10` varchar(30) DEFAULT NULL, -`c11` varchar(30) DEFAULT NULL, -`c12` varchar(30) DEFAULT NULL, -`c13` varchar(30) DEFAULT NULL, -`c14` varchar(30) DEFAULT NULL, -`c15` varchar(30) DEFAULT NULL, -`c16` varchar(30) DEFAULT NULL, -`c17` varchar(30) DEFAULT NULL, -`c18` varchar(30) DEFAULT NULL, -`c19` varchar(30) DEFAULT NULL, -`c20` varchar(30) DEFAULT NULL, -`c21` varchar(30) DEFAULT NULL, -`c22` varchar(30) DEFAULT NULL, -`c23` varchar(30) DEFAULT NULL, -`c24` varchar(30) DEFAULT NULL, -`c25` varchar(30) DEFAULT NULL, -`c26` varchar(30) DEFAULT NULL, -`c27` varchar(30) DEFAULT NULL, -`c28` varchar(30) DEFAULT NULL, -`c29` varchar(30) DEFAULT NULL, -`c30` varchar(30) DEFAULT NULL, -`c31` varchar(30) DEFAULT NULL, -`c32` varchar(30) DEFAULT NULL, -`c33` varchar(30) DEFAULT NULL, -`c34` varchar(30) DEFAULT NULL, -`c35` varchar(30) DEFAULT NULL, -`c36` varchar(30) DEFAULT NULL, -`c37` varchar(30) DEFAULT NULL, -`c38` varchar(30) DEFAULT NULL, -`c39` varchar(30) DEFAULT NULL, -`c40` varchar(30) DEFAULT NULL, -`c41` varchar(30) DEFAULT NULL, -`c42` varchar(30) DEFAULT NULL, -`c43` varchar(30) DEFAULT NULL, -`c44` varchar(30) DEFAULT NULL, -`c45` varchar(30) DEFAULT NULL, -`c46` varchar(30) DEFAULT NULL, -`c47` varchar(30) DEFAULT NULL, -`c48` varchar(30) DEFAULT NULL, -`c49` varchar(30) DEFAULT NULL, -`c50` varchar(30) DEFAULT NULL, -`c51` varchar(30) DEFAULT NULL, -`c52` varchar(30) DEFAULT NULL, -`c53` varchar(30) DEFAULT NULL, -`c54` varchar(30) DEFAULT NULL, -`c55` varchar(30) DEFAULT NULL, -`c56` varchar(30) DEFAULT NULL, -`c57` varchar(30) DEFAULT NULL, -`c58` varchar(30) DEFAULT NULL, -`c59` varchar(30) DEFAULT NULL, -`c60` varchar(30) DEFAULT NULL, -`c61` varchar(30) DEFAULT NULL, -`c62` varchar(30) DEFAULT NULL, -`c63` varchar(30) DEFAULT NULL, -`c64` varchar(30) DEFAULT NULL, -`c65` varchar(30) DEFAULT NULL, -`c66` varchar(30) DEFAULT NULL, -`c67` varchar(30) DEFAULT NULL, -`c68` varchar(30) DEFAULT NULL, -`c69` varchar(30) DEFAULT NULL, -`c70` varchar(30) DEFAULT NULL, -`c71` varchar(30) DEFAULT NULL, -`c72` varchar(30) DEFAULT NULL, -`c73` varchar(30) DEFAULT NULL, -`c74` varchar(30) DEFAULT NULL, -`c75` varchar(30) DEFAULT NULL, -`c76` varchar(30) DEFAULT NULL, -`c77` varchar(30) DEFAULT NULL, -`c78` varchar(30) DEFAULT NULL, -`c79` varchar(30) DEFAULT NULL, -`c80` varchar(30) DEFAULT NULL, -`c81` varchar(30) DEFAULT NULL, -`c82` varchar(30) DEFAULT NULL, -`c83` varchar(30) DEFAULT NULL, -`c84` varchar(30) DEFAULT NULL, -`c85` varchar(30) DEFAULT NULL, -`c86` varchar(30) DEFAULT NULL, -`c87` varchar(30) DEFAULT NULL, -`c88` varchar(30) DEFAULT NULL, -`c89` varchar(30) DEFAULT NULL, -`c90` varchar(30) DEFAULT NULL, -`c91` varchar(30) DEFAULT NULL, -`c92` varchar(30) DEFAULT NULL, -`c93` varchar(30) DEFAULT NULL, -`c94` varchar(30) DEFAULT NULL, -`c95` varchar(30) DEFAULT NULL, -`c96` varchar(30) DEFAULT NULL, -`c97` varchar(30) DEFAULT NULL, -`c98` varchar(30) DEFAULT NULL, -`c99` varchar(30) DEFAULT NULL, -`c100` varchar(30) DEFAULT NULL, -`c101` varchar(30) DEFAULT NULL, -`c102` varchar(30) DEFAULT NULL, -`c103` varchar(30) DEFAULT NULL, -`c104` varchar(30) DEFAULT NULL, -`c105` varchar(30) DEFAULT NULL, -`c106` varchar(30) DEFAULT NULL, -`c107` varchar(30) DEFAULT NULL, -`c108` varchar(30) DEFAULT NULL, -`c109` varchar(30) DEFAULT NULL, -`c110` varchar(30) DEFAULT NULL, -`c111` varchar(30) DEFAULT NULL, -`c112` varchar(30) DEFAULT NULL, -`c113` varchar(30) DEFAULT NULL, -`c114` varchar(30) DEFAULT NULL, -`c115` varchar(30) DEFAULT NULL, -`c116` varchar(30) DEFAULT NULL, -`c117` varchar(30) DEFAULT NULL, -`c118` varchar(30) DEFAULT NULL, -`c119` varchar(30) DEFAULT NULL, -`c120` varchar(30) DEFAULT NULL, -`c121` varchar(30) DEFAULT NULL, -`c122` varchar(30) DEFAULT NULL, -`c123` varchar(30) DEFAULT NULL, -`c124` varchar(30) DEFAULT NULL, -`c125` varchar(30) DEFAULT NULL, -`c126` varchar(30) DEFAULT NULL, -PRIMARY KEY (`c1`) -) ENGINE=InnoDB; -LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); -LOCK TABLES `t2` WRITE; -INSERT INTO `t2` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); -DROP TABLE `t1`; -DROP TABLE `t2`; +### action: generating several tables with different metadata +### sizes (resorting to perl) +### testing table with 249 field metadata size. +### testing table with 250 field metadata size. +### testing table with 251 field metadata size. +### testing table with 252 field metadata size. +### testing table with 253 field metadata size. +### testing table with 254 field metadata size. +### testing table with 255 field metadata size. +### testing table with 256 field metadata size. +### testing table with 257 field metadata size. +### testing table with 258 field metadata size. FLUSH LOGS; -=== Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. +### assertion: the slave replicated event successfully and tables match for t10 +Comparing tables master:test.t10 and slave:test.t10 +### assertion: the slave replicated event successfully and tables match for t9 +Comparing tables master:test.t9 and slave:test.t9 +### assertion: the slave replicated event successfully and tables match for t8 +Comparing tables master:test.t8 and slave:test.t8 +### assertion: the slave replicated event successfully and tables match for t7 +Comparing tables master:test.t7 and slave:test.t7 +### assertion: the slave replicated event successfully and tables match for t6 +Comparing tables master:test.t6 and slave:test.t6 +### assertion: the slave replicated event successfully and tables match for t5 +Comparing tables master:test.t5 and slave:test.t5 +### assertion: the slave replicated event successfully and tables match for t4 +Comparing tables master:test.t4 and slave:test.t4 +### assertion: the slave replicated event successfully and tables match for t3 +Comparing tables master:test.t3 and slave:test.t3 +### assertion: the slave replicated event successfully and tables match for t2 +Comparing tables master:test.t2 and slave:test.t2 +### assertion: the slave replicated event successfully and tables match for t1 +Comparing tables master:test.t1 and slave:test.t1 +### assertion: check that binlog is not corrupt. Using mysqlbinlog to +### detect failure. Before the patch mysqlbinlog would find +### a corrupted event, thence would fail. diff --git a/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test index 4d7ba1e0a81..022988d7ee3 100644 --- a/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test +++ b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test @@ -2,7 +2,6 @@ # BUG#42749: infinite loop writing to row based binlog - processlist shows # "freeing items" # -# BUG#50018: binlog corruption when table has many columns # # WHY # === @@ -18,8 +17,7 @@ # # Checking that the patch fixes the problem is done as follows: # -# i) tables with several fields is created (above and below a 251 -# metadata size threshold) +# i) one table with m_field_metadata sized at 290 # ii) an insert is performed; # iii) the logs are flushed; # iv) mysqlbinlog is used to check if it succeeds. @@ -29,12 +27,8 @@ # reading the event. -- source include/master-slave.inc --- source include/have_log_bin.inc -- source include/have_innodb.inc -- source include/have_binlog_format_row.inc --- connection default - -RESET MASTER; -- disable_warnings DROP TABLE IF EXISTS `t1`; @@ -192,13 +186,20 @@ CREATE TABLE `t1` ( ) ENGINE=InnoDB; LOCK TABLES `t1` WRITE; +INSERT INTO `t1`(c2) VALUES ('1'); +FLUSH LOGS; -INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); +-- sync_slave_with_master +-- connection master + +-- echo ### assertion: the slave replicated event successfully and tables match +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc DROP TABLE `t1`; -FLUSH LOGS; - +-- connection master -- sync_slave_with_master -- connection master @@ -208,313 +209,132 @@ FLUSH LOGS; -- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog -- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog +############################################################# +# BUG#50018: binlog corruption when table has many columns +# +# Same test from BUG#42749, but now we generate some SQL which +# creates and inserts into tables with metadata size from 249 +# to 258. +# +# The test works as follows: +# 1. SQL for several CREATE TABLE and INSERTS are generated +# into a file. +# 2. This file is then "sourced" +# 3. The slave is synchronized with the master +# 4. FLUSH LOGS on master +# 5. Compare tables on master and slave. +# 6. run mysqlbinlog on master's binary log +# +# Steps #5 and #6 assert that binary log is not corrupted +# in both cases: when slave is replaying events and when +# mysqlbinlog is used to read the binary log + -- source include/master-slave-reset.inc -- connection master -# Create two tables one with field_metadata_size == 250 -# and another one with field_metadata_size == 252 +# Create several tables with field_metadata_size ranging +# from 249 to 258 (so that we cover 251 and 255 range). +# This should exercise the switch between using 1 or 3 +# bytes to pack m_field_metadata_size. # # Each varchar field takes up to 2 metadata bytes, see: # # Field_varstring::do_save_field_metadata (field.cc) # -# The integer field takes 0 bytes, see: -# -# Field::do_save_field_metadata (field.h) -# # The float field takes 1 byte, see: # # Field_float::do_save_field_metadata (field.cc) # -# We choose 250 and 252 which are the ones below and above -# the threshold for switching to use 1 or 3 bytes for the -# m_data_size increment. -# --- echo ### TABLE with field_metadata_size == 250 +-- let $generated_sql= $MYSQLTEST_VARDIR/tmp/b50018.sql +-- let B50018_FILE= $generated_sql -CREATE TABLE `t1` ( - `c1` int(11) NOT NULL AUTO_INCREMENT, - `c2` varchar(30) NOT NULL, - `c3` varchar(30) DEFAULT NULL, - `c4` varchar(30) DEFAULT NULL, - `c5` varchar(30) DEFAULT NULL, - `c6` varchar(30) DEFAULT NULL, - `c7` varchar(30) DEFAULT NULL, - `c8` varchar(30) DEFAULT NULL, - `c9` varchar(30) DEFAULT NULL, - `c10` varchar(30) DEFAULT NULL, - `c11` varchar(30) DEFAULT NULL, - `c12` varchar(30) DEFAULT NULL, - `c13` varchar(30) DEFAULT NULL, - `c14` varchar(30) DEFAULT NULL, - `c15` varchar(30) DEFAULT NULL, - `c16` varchar(30) DEFAULT NULL, - `c17` varchar(30) DEFAULT NULL, - `c18` varchar(30) DEFAULT NULL, - `c19` varchar(30) DEFAULT NULL, - `c20` varchar(30) DEFAULT NULL, - `c21` varchar(30) DEFAULT NULL, - `c22` varchar(30) DEFAULT NULL, - `c23` varchar(30) DEFAULT NULL, - `c24` varchar(30) DEFAULT NULL, - `c25` varchar(30) DEFAULT NULL, - `c26` varchar(30) DEFAULT NULL, - `c27` varchar(30) DEFAULT NULL, - `c28` varchar(30) DEFAULT NULL, - `c29` varchar(30) DEFAULT NULL, - `c30` varchar(30) DEFAULT NULL, - `c31` varchar(30) DEFAULT NULL, - `c32` varchar(30) DEFAULT NULL, - `c33` varchar(30) DEFAULT NULL, - `c34` varchar(30) DEFAULT NULL, - `c35` varchar(30) DEFAULT NULL, - `c36` varchar(30) DEFAULT NULL, - `c37` varchar(30) DEFAULT NULL, - `c38` varchar(30) DEFAULT NULL, - `c39` varchar(30) DEFAULT NULL, - `c40` varchar(30) DEFAULT NULL, - `c41` varchar(30) DEFAULT NULL, - `c42` varchar(30) DEFAULT NULL, - `c43` varchar(30) DEFAULT NULL, - `c44` varchar(30) DEFAULT NULL, - `c45` varchar(30) DEFAULT NULL, - `c46` varchar(30) DEFAULT NULL, - `c47` varchar(30) DEFAULT NULL, - `c48` varchar(30) DEFAULT NULL, - `c49` varchar(30) DEFAULT NULL, - `c50` varchar(30) DEFAULT NULL, - `c51` varchar(30) DEFAULT NULL, - `c52` varchar(30) DEFAULT NULL, - `c53` varchar(30) DEFAULT NULL, - `c54` varchar(30) DEFAULT NULL, - `c55` varchar(30) DEFAULT NULL, - `c56` varchar(30) DEFAULT NULL, - `c57` varchar(30) DEFAULT NULL, - `c58` varchar(30) DEFAULT NULL, - `c59` varchar(30) DEFAULT NULL, - `c60` varchar(30) DEFAULT NULL, - `c61` varchar(30) DEFAULT NULL, - `c62` varchar(30) DEFAULT NULL, - `c63` varchar(30) DEFAULT NULL, - `c64` varchar(30) DEFAULT NULL, - `c65` varchar(30) DEFAULT NULL, - `c66` varchar(30) DEFAULT NULL, - `c67` varchar(30) DEFAULT NULL, - `c68` varchar(30) DEFAULT NULL, - `c69` varchar(30) DEFAULT NULL, - `c70` varchar(30) DEFAULT NULL, - `c71` varchar(30) DEFAULT NULL, - `c72` varchar(30) DEFAULT NULL, - `c73` varchar(30) DEFAULT NULL, - `c74` varchar(30) DEFAULT NULL, - `c75` varchar(30) DEFAULT NULL, - `c76` varchar(30) DEFAULT NULL, - `c77` varchar(30) DEFAULT NULL, - `c78` varchar(30) DEFAULT NULL, - `c79` varchar(30) DEFAULT NULL, - `c80` varchar(30) DEFAULT NULL, - `c81` varchar(30) DEFAULT NULL, - `c82` varchar(30) DEFAULT NULL, - `c83` varchar(30) DEFAULT NULL, - `c84` varchar(30) DEFAULT NULL, - `c85` varchar(30) DEFAULT NULL, - `c86` varchar(30) DEFAULT NULL, - `c87` varchar(30) DEFAULT NULL, - `c88` varchar(30) DEFAULT NULL, - `c89` varchar(30) DEFAULT NULL, - `c90` varchar(30) DEFAULT NULL, - `c91` varchar(30) DEFAULT NULL, - `c92` varchar(30) DEFAULT NULL, - `c93` varchar(30) DEFAULT NULL, - `c94` varchar(30) DEFAULT NULL, - `c95` varchar(30) DEFAULT NULL, - `c96` varchar(30) DEFAULT NULL, - `c97` varchar(30) DEFAULT NULL, - `c98` varchar(30) DEFAULT NULL, - `c99` varchar(30) DEFAULT NULL, - `c100` varchar(30) DEFAULT NULL, - `c101` varchar(30) DEFAULT NULL, - `c102` varchar(30) DEFAULT NULL, - `c103` varchar(30) DEFAULT NULL, - `c104` varchar(30) DEFAULT NULL, - `c105` varchar(30) DEFAULT NULL, - `c106` varchar(30) DEFAULT NULL, - `c107` varchar(30) DEFAULT NULL, - `c108` varchar(30) DEFAULT NULL, - `c109` varchar(30) DEFAULT NULL, - `c110` varchar(30) DEFAULT NULL, - `c111` varchar(30) DEFAULT NULL, - `c112` varchar(30) DEFAULT NULL, - `c113` varchar(30) DEFAULT NULL, - `c114` varchar(30) DEFAULT NULL, - `c115` varchar(30) DEFAULT NULL, - `c116` varchar(30) DEFAULT NULL, - `c117` varchar(30) DEFAULT NULL, - `c118` varchar(30) DEFAULT NULL, - `c119` varchar(30) DEFAULT NULL, - `c120` varchar(30) DEFAULT NULL, - `c121` varchar(30) DEFAULT NULL, - `c122` varchar(30) DEFAULT NULL, - `c123` varchar(30) DEFAULT NULL, - `c124` varchar(30) DEFAULT NULL, - `c125` varchar(30) DEFAULT NULL, - `c126` varchar(30) DEFAULT NULL, - PRIMARY KEY (`c1`) -) ENGINE=InnoDB; +-- echo ### action: generating several tables with different metadata +-- echo ### sizes (resorting to perl) +-- perl +my $file= $ENV{'B50018_FILE'}; +open(FILE, ">", "$file") or die "Unable to open bug 50018 generated SQL file: $!" ; --- echo ### TABLE with field_metadata_size == 251 +my $tables= ""; +my $ntables= 10; +my $base_ncols= 124; -CREATE TABLE `t2` ( - `c1` float, - `c2` varchar(30) NOT NULL, - `c3` varchar(30) DEFAULT NULL, - `c4` varchar(30) DEFAULT NULL, - `c5` varchar(30) DEFAULT NULL, - `c6` varchar(30) DEFAULT NULL, - `c7` varchar(30) DEFAULT NULL, - `c8` varchar(30) DEFAULT NULL, - `c9` varchar(30) DEFAULT NULL, - `c10` varchar(30) DEFAULT NULL, - `c11` varchar(30) DEFAULT NULL, - `c12` varchar(30) DEFAULT NULL, - `c13` varchar(30) DEFAULT NULL, - `c14` varchar(30) DEFAULT NULL, - `c15` varchar(30) DEFAULT NULL, - `c16` varchar(30) DEFAULT NULL, - `c17` varchar(30) DEFAULT NULL, - `c18` varchar(30) DEFAULT NULL, - `c19` varchar(30) DEFAULT NULL, - `c20` varchar(30) DEFAULT NULL, - `c21` varchar(30) DEFAULT NULL, - `c22` varchar(30) DEFAULT NULL, - `c23` varchar(30) DEFAULT NULL, - `c24` varchar(30) DEFAULT NULL, - `c25` varchar(30) DEFAULT NULL, - `c26` varchar(30) DEFAULT NULL, - `c27` varchar(30) DEFAULT NULL, - `c28` varchar(30) DEFAULT NULL, - `c29` varchar(30) DEFAULT NULL, - `c30` varchar(30) DEFAULT NULL, - `c31` varchar(30) DEFAULT NULL, - `c32` varchar(30) DEFAULT NULL, - `c33` varchar(30) DEFAULT NULL, - `c34` varchar(30) DEFAULT NULL, - `c35` varchar(30) DEFAULT NULL, - `c36` varchar(30) DEFAULT NULL, - `c37` varchar(30) DEFAULT NULL, - `c38` varchar(30) DEFAULT NULL, - `c39` varchar(30) DEFAULT NULL, - `c40` varchar(30) DEFAULT NULL, - `c41` varchar(30) DEFAULT NULL, - `c42` varchar(30) DEFAULT NULL, - `c43` varchar(30) DEFAULT NULL, - `c44` varchar(30) DEFAULT NULL, - `c45` varchar(30) DEFAULT NULL, - `c46` varchar(30) DEFAULT NULL, - `c47` varchar(30) DEFAULT NULL, - `c48` varchar(30) DEFAULT NULL, - `c49` varchar(30) DEFAULT NULL, - `c50` varchar(30) DEFAULT NULL, - `c51` varchar(30) DEFAULT NULL, - `c52` varchar(30) DEFAULT NULL, - `c53` varchar(30) DEFAULT NULL, - `c54` varchar(30) DEFAULT NULL, - `c55` varchar(30) DEFAULT NULL, - `c56` varchar(30) DEFAULT NULL, - `c57` varchar(30) DEFAULT NULL, - `c58` varchar(30) DEFAULT NULL, - `c59` varchar(30) DEFAULT NULL, - `c60` varchar(30) DEFAULT NULL, - `c61` varchar(30) DEFAULT NULL, - `c62` varchar(30) DEFAULT NULL, - `c63` varchar(30) DEFAULT NULL, - `c64` varchar(30) DEFAULT NULL, - `c65` varchar(30) DEFAULT NULL, - `c66` varchar(30) DEFAULT NULL, - `c67` varchar(30) DEFAULT NULL, - `c68` varchar(30) DEFAULT NULL, - `c69` varchar(30) DEFAULT NULL, - `c70` varchar(30) DEFAULT NULL, - `c71` varchar(30) DEFAULT NULL, - `c72` varchar(30) DEFAULT NULL, - `c73` varchar(30) DEFAULT NULL, - `c74` varchar(30) DEFAULT NULL, - `c75` varchar(30) DEFAULT NULL, - `c76` varchar(30) DEFAULT NULL, - `c77` varchar(30) DEFAULT NULL, - `c78` varchar(30) DEFAULT NULL, - `c79` varchar(30) DEFAULT NULL, - `c80` varchar(30) DEFAULT NULL, - `c81` varchar(30) DEFAULT NULL, - `c82` varchar(30) DEFAULT NULL, - `c83` varchar(30) DEFAULT NULL, - `c84` varchar(30) DEFAULT NULL, - `c85` varchar(30) DEFAULT NULL, - `c86` varchar(30) DEFAULT NULL, - `c87` varchar(30) DEFAULT NULL, - `c88` varchar(30) DEFAULT NULL, - `c89` varchar(30) DEFAULT NULL, - `c90` varchar(30) DEFAULT NULL, - `c91` varchar(30) DEFAULT NULL, - `c92` varchar(30) DEFAULT NULL, - `c93` varchar(30) DEFAULT NULL, - `c94` varchar(30) DEFAULT NULL, - `c95` varchar(30) DEFAULT NULL, - `c96` varchar(30) DEFAULT NULL, - `c97` varchar(30) DEFAULT NULL, - `c98` varchar(30) DEFAULT NULL, - `c99` varchar(30) DEFAULT NULL, - `c100` varchar(30) DEFAULT NULL, - `c101` varchar(30) DEFAULT NULL, - `c102` varchar(30) DEFAULT NULL, - `c103` varchar(30) DEFAULT NULL, - `c104` varchar(30) DEFAULT NULL, - `c105` varchar(30) DEFAULT NULL, - `c106` varchar(30) DEFAULT NULL, - `c107` varchar(30) DEFAULT NULL, - `c108` varchar(30) DEFAULT NULL, - `c109` varchar(30) DEFAULT NULL, - `c110` varchar(30) DEFAULT NULL, - `c111` varchar(30) DEFAULT NULL, - `c112` varchar(30) DEFAULT NULL, - `c113` varchar(30) DEFAULT NULL, - `c114` varchar(30) DEFAULT NULL, - `c115` varchar(30) DEFAULT NULL, - `c116` varchar(30) DEFAULT NULL, - `c117` varchar(30) DEFAULT NULL, - `c118` varchar(30) DEFAULT NULL, - `c119` varchar(30) DEFAULT NULL, - `c120` varchar(30) DEFAULT NULL, - `c121` varchar(30) DEFAULT NULL, - `c122` varchar(30) DEFAULT NULL, - `c123` varchar(30) DEFAULT NULL, - `c124` varchar(30) DEFAULT NULL, - `c125` varchar(30) DEFAULT NULL, - `c126` varchar(30) DEFAULT NULL, - PRIMARY KEY (`c1`) -) ENGINE=InnoDB; +for my $i (1..$ntables) +{ + my $ncols= $base_ncols + $i; + my $metadata_size= $ncols_variable * 2 + 1; -LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); + print FILE "-- echo ### testing table with " . ($base_ncols*2 + $i) . " field metadata size.\n"; + print FILE "CREATE TABLE t$i (\n"; + for my $n (1..$base_ncols) + { + print FILE "c$n VARCHAR(30) NOT NULL DEFAULT 'BUG#50018',\n"; + } + for my $n (1..$i) + { + print FILE "c" . ($base_ncols+$n) . " FLOAT NOT NULL DEFAULT 0"; + if ($n < $i) + { + print FILE ",\n"; + } + } -LOCK TABLES `t2` WRITE; -INSERT INTO `t2` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); + print FILE ") Engine=InnoDB;\n"; -DROP TABLE `t1`; -DROP TABLE `t2`; + $tables.= " t$i WRITE"; + if ($i < $ntables) + { + $tables .=","; + } + + print FILE "LOCK TABLES t$i WRITE;\n"; + print FILE "INSERT INTO t$i(c". ($base_ncols+1) . ") VALUES (50018);\n"; +} + +close(FILE); + +EOF + +## we don't need this in the result file +## however, for debugging purposes you +## may want to reactivate query logging +-- disable_query_log +-- source $generated_sql +UNLOCK TABLES; +-- enable_query_log + +-- sync_slave_with_master +-- connection master FLUSH LOGS; --- sync_slave_with_master +-- let $ntables=10 +while($ntables) +{ + -- echo ### assertion: the slave replicated event successfully and tables match for t$ntables + -- let $diff_table_1=master:test.t$ntables + -- let $diff_table_2=slave:test.t$ntables + -- source include/diff_tables.inc --- connection master + -- connection master + -- disable_query_log + -- eval DROP TABLE t$ntables + -- enable_query_log + -- sync_slave_with_master + -- connection master --- echo === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. + -- dec $ntables +} +-- echo ### assertion: check that binlog is not corrupt. Using mysqlbinlog to +-- echo ### detect failure. Before the patch mysqlbinlog would find +-- echo ### a corrupted event, thence would fail. -- let $MYSQLD_DATADIR= `SELECT @@datadir`; --- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog --- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog +-- exec $MYSQL_BINLOG -v --hex $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog +## clean up +## For debugging purposes you might want not to remove these +-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog +-- remove_file $generated_sql -- source include/master-slave-end.inc From c1043021c81a4394b5aa9961d7106c437275b040 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Jan 2010 13:42:23 +0800 Subject: [PATCH 226/344] BUG #28421 Infinite loop on slave relay logs Manually deleteing one or more entries from 'master-bin.index', will cause master infinitely loop to send one binlog file. When starting a dump session, master opens index file and search the binlog file which is being requested by the slave. The position of the binlog file in the index file is recorded. it will be used to find the next binlog file when current binlog file has dumped completely. As only the position is used, it may not get the correct file if some entries has been removed manually from the index file. the master will reopen the current binlog file which has been dump completely and redump it if it can not get the next binlog file's name from index file. It obviously is a logical error. Even though it is allowed to manually change index file, but it is not recommended. so after this patch, master sends a fatal error to slave and close the dump session if a new binlog file has been generated and master can not get it from the index file. --- mysql-test/include/truncate_file.inc | 16 ++++ .../rpl/r/rpl_manual_change_index_file.result | 25 ++++++ .../rpl/t/rpl_manual_change_index_file.test | 85 +++++++++++++++++++ sql/sql_repl.cc | 9 +- 4 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 mysql-test/include/truncate_file.inc create mode 100644 mysql-test/suite/rpl/r/rpl_manual_change_index_file.result create mode 100644 mysql-test/suite/rpl/t/rpl_manual_change_index_file.test diff --git a/mysql-test/include/truncate_file.inc b/mysql-test/include/truncate_file.inc new file mode 100644 index 00000000000..c82108681bd --- /dev/null +++ b/mysql-test/include/truncate_file.inc @@ -0,0 +1,16 @@ +# truncate a giving file, all contents of the file are be cleared + +if (`SELECT 'x$file' = 'x'`) +{ + --echo Please assign a file name to $file!! + exit; +} + +let TRUNCATE_FILE= $file; + +perl; +use Env; +Env::import('TRUNCATE_FILE'); +open FILE, '>', $TRUNCATE_FILE || die "Can not open file $file"; +close FILE; +EOF diff --git a/mysql-test/suite/rpl/r/rpl_manual_change_index_file.result b/mysql-test/suite/rpl/r/rpl_manual_change_index_file.result new file mode 100644 index 00000000000..9061abca477 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_manual_change_index_file.result @@ -0,0 +1,25 @@ +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; +FLUSH LOGS; +CREATE TABLE t1(c1 INT); +FLUSH LOGS; +call mtr.add_suppression('Got fatal error 1236 from master when reading data from binary log: .*could not find next log'); +Last_IO_Error +Got fatal error 1236 from master when reading data from binary log: 'could not find next log' +CREATE TABLE t2(c1 INT); +FLUSH LOGS; +CREATE TABLE t3(c1 INT); +FLUSH LOGS; +CREATE TABLE t4(c1 INT); +START SLAVE IO_THREAD; +SHOW TABLES; +Tables_in_test +t1 +t2 +t3 +t4 +DROP TABLE t1, t2, t3, t4; diff --git a/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test b/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test new file mode 100644 index 00000000000..ba3dbd174f4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test @@ -0,0 +1,85 @@ +source include/master-slave.inc; + +# +# BUG#28421 Infinite loop on slave relay logs +# +# That, manually deleteing one or more entries from 'master-bin.index', will +# cause master infinitely loop to send one binlog file. +# +# Manually changing index file is a illegal action, so when this happen, we +# send a fatal error to slave and close the dump session. + +FLUSH LOGS; +# Now, 2 entries in index file. +# ./master-bin.000001 +# ./master-bin.000002 + +CREATE TABLE t1(c1 INT); +# Now, the current dump file(master-bin.000002) is the second line of index +# file +sync_slave_with_master; +# Now, all events has been replicate to slave. As current dump file +# (master-bin.000002) is the last binlog file, so master is waiting for new +# events. + +connection master; +# Delete './master-bin.000001' from index file. +let $MYSQLD_DATADIR= `SELECT @@DATADIR`; +#remove_file $MYSQLD_DATADIR/master-bin.index; +let $file= $MYSQLD_DATADIR/master-bin.index; +source include/truncate_file.inc; + +if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`) +{ +append_file $MYSQLD_DATADIR/master-bin.index; +./master-bin.000002 +EOF +sleep 0.00000001; +} + +if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) IN ('Win32', 'Win64', 'Windows')`) +{ +append_file $MYSQLD_DATADIR/master-bin.index; +.\master-bin.000002 +EOF +sleep 0.00000001; +} + +# Now, only 1 entry in index file. +# ./master-bin.000002 + +# Generate master-bin.000003, but it is in the second line. +FLUSH LOGS; +# Now, 2 entries in index file. +# ./master-bin.000002 +# ./master-bin.000003 + +# Now, master know that new binlog file(master-bin.000003) has been generated. +# It expects that the new binlog file is in third line of index file, but +# there is no third line in index file. It is so strange that master sends an +# error to slave. +call mtr.add_suppression('Got fatal error 1236 from master when reading data from binary log: .*could not find next log'); +connection slave; +source include/wait_for_slave_io_to_stop.inc; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_IO_Error, 1); +echo Last_IO_Error; +echo $last_error; + +connection master; +CREATE TABLE t2(c1 INT); +FLUSH LOGS; +CREATE TABLE t3(c1 INT); +FLUSH LOGS; +CREATE TABLE t4(c1 INT); + +connection slave; +START SLAVE IO_THREAD; +source include/wait_for_slave_io_to_start.inc; + +connection master; +sync_slave_with_master; +SHOW TABLES; + +connection master; +DROP TABLE t1, t2, t3, t4; +source include/master-slave-end.inc; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index b8f2e1e39bf..de038f8dc2c 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -711,11 +711,14 @@ impossible position"; thd_proc_info(thd, "Finished reading one binlog; switching to next binlog"); switch (mysql_bin_log.find_next_log(&linfo, 1)) { - case LOG_INFO_EOF: - loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); - break; case 0: break; + case LOG_INFO_EOF: + if (mysql_bin_log.is_active(log_file_name)) + { + loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); + break; + } default: errmsg = "could not find next log"; my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; From 4ae5679f4720c8c4a5d04b0c4c4661cad1076b2c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Jan 2010 23:32:40 +0800 Subject: [PATCH 227/344] Postfix Recover the right contents of the index file at the end of the test case. --- .../rpl/t/rpl_manual_change_index_file.test | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test b/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test index ba3dbd174f4..ecdf10ac2c2 100644 --- a/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test +++ b/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test @@ -25,7 +25,6 @@ sync_slave_with_master; connection master; # Delete './master-bin.000001' from index file. let $MYSQLD_DATADIR= `SELECT @@DATADIR`; -#remove_file $MYSQLD_DATADIR/master-bin.index; let $file= $MYSQLD_DATADIR/master-bin.index; source include/truncate_file.inc; @@ -45,8 +44,7 @@ EOF sleep 0.00000001; } -# Now, only 1 entry in index file. -# ./master-bin.000002 +# Now, only 1 entry in index file. ./master-bin.000002 # Generate master-bin.000003, but it is in the second line. FLUSH LOGS; @@ -66,6 +64,29 @@ echo Last_IO_Error; echo $last_error; connection master; + +source include/truncate_file.inc; + +if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`) +{ +append_file $MYSQLD_DATADIR/master-bin.index; +./master-bin.000001 +./master-bin.000002 +./master-bin.000003 +EOF +sleep 0.00000001; +} + +if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) IN ('Win32', 'Win64', 'Windows')`) +{ +append_file $MYSQLD_DATADIR/master-bin.index; +.\master-bin.000001 +.\master-bin.000002 +.\master-bin.000003 +EOF +sleep 0.00000001; +} + CREATE TABLE t2(c1 INT); FLUSH LOGS; CREATE TABLE t3(c1 INT); From b4d7a2440ce7ddb71101ac82ed2382a639007446 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Sat, 9 Jan 2010 11:04:51 +0200 Subject: [PATCH 228/344] Fixed bug where mysqlbinlog hold up multiple connections to MySQL when using mysqlbinlog -R file1 file2 ... --- client/mysqlbinlog.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index f55dc75df5d..68846136431 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1378,6 +1378,10 @@ static int parse_args(int *argc, char*** argv) */ static Exit_status safe_connect() { + /* Close and old connections to MySQL */ + if (mysql) + mysql_close(mysql); + mysql= mysql_init(NULL); if (!mysql) From 0855019e3ae0c8d1d20c49a8be317050c093b4dc Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jan 2010 14:15:28 +0100 Subject: [PATCH 229/344] Fix multiple test suite failures in Buildbot due to races in the test cases or missing server features not properly checked mysql-test/r/func_misc.result: Move test that requires query cache from main.func_misc to main.query_cache. mysql-test/r/mysqltest.result: Fix test failure due to race. This test case creates > 300 connections in a tight loop, and depending on thread scheduling and load, even though each connection is immediately disconnected before connecting the next one, the server max connections may still be exceeded due to server not being able to free old connections as fast as new ones are made. mysql-test/r/query_cache.result: Move test that requires query cache from main.func_misc to main.query_cache. Move test that requires query cache from main.variables to main.query_cache. mysql-test/r/query_cache_notembedded.result: Move test that requires query cache from main.sp_notembedded to main.query_cache_notembedded. mysql-test/r/sp_notembedded.result: Move test that requires query cache from main.sp_notembedded to main.query_cache_notembedded. mysql-test/r/udf.result: Move test in main.udf that requires query cache to separate file. mysql-test/r/udf_query_cache.result: Move test in main.udf that requires query cache to separate file. mysql-test/r/variables.result: Move test that requires query cache from main.variables to main.query_cache. mysql-test/suite/funcs_1/datadict/processlist_val.inc: Fix race where result file may show state "cleaning up" in the small window between setting COMMAND to 'Sleep' and clearing STATE. mysql-test/suite/rpl/r/rpl_temporary.result: Fix race with suppression of warning message by fixing the test to not generate the warning message in the first place. Problem was a race between creating an anonymous account and resetting the slave. If the slave reset happens before replicating the account, the subsequest deletion of the account will fail to replicate correctly due to missing row. mysql-test/suite/rpl/t/rpl_temporary.test: Fix race with suppression of warning message by fixing the test to not generate the warning message in the first place. Problem was a race between creating an anonymous account and resetting the slave. If the slave reset happens before replicating the account, the subsequest deletion of the account will fail to replicate correctly due to missing row. mysql-test/t/func_misc.test: Move test that requires query cache from main.func_misc to main.query_cache. Move test that requires query cache from main.variables to main.query_cache. mysql-test/t/mysqltest.test: Fix test failure due to race. This test case creates > 300 connections in a tight loop, and depending on thread scheduling and load, even though each connection is immediately disconnected before connecting the next one, the server max connections may still be exceeded due to server not being able to free old connections as fast as new ones are made. mysql-test/t/query_cache.test: Move test that requires query cache to main.query_cache. mysql-test/t/query_cache_notembedded.test: Move test that requires query cache from main.sp_notembedded to main.query_cache_notembedded. mysql-test/t/sp_notembedded.test: Move test that requires query cache from main.sp_notembedded to main.query_cache_notembedded. mysql-test/t/udf.test: Move test in main.udf that requires query cache to separate file. mysql-test/t/udf_query_cache-master.opt: Move test in main.udf that requires query cache to separate file. mysql-test/t/udf_query_cache.test: Move test in main.udf that requires query cache to separate file. mysql-test/t/variables.test: Move test that requires query cache from main.variables to main.query_cache. tests/mysql_client_test.c: In tests that require query cache, skip the test if query cache not available. Do this dynamically rather than using HAVE_QUERY_CACHE, as there is no guarantee that the server we run against was compiled with same preprocessor #define as the mysql_client_test program (and since it is trivial to check dynamically). --- mysql-test/r/func_misc.result | 89 -------- mysql-test/r/mysqltest.result | 1 + mysql-test/r/query_cache.result | 98 +++++++++ mysql-test/r/query_cache_notembedded.result | 52 +++++ mysql-test/r/sp_notembedded.result | 52 ----- mysql-test/r/udf.result | 23 -- mysql-test/r/udf_query_cache.result | 24 ++ mysql-test/r/variables.result | 10 - .../funcs_1/datadict/processlist_val.inc | 2 +- mysql-test/suite/rpl/r/rpl_temporary.result | 5 +- mysql-test/suite/rpl/t/rpl_temporary.test | 14 +- mysql-test/t/func_misc.test | 192 ---------------- mysql-test/t/mysqltest.test | 12 + mysql-test/t/query_cache.test | 205 ++++++++++++++++++ mysql-test/t/query_cache_notembedded.test | 47 ++++ mysql-test/t/sp_notembedded.test | 46 ---- mysql-test/t/udf.test | 23 -- mysql-test/t/udf_query_cache-master.opt | 1 + mysql-test/t/udf_query_cache.test | 35 +++ mysql-test/t/variables.test | 10 - tests/mysql_client_test.c | 46 +++- 21 files changed, 528 insertions(+), 459 deletions(-) create mode 100644 mysql-test/r/udf_query_cache.result create mode 100644 mysql-test/t/udf_query_cache-master.opt create mode 100644 mysql-test/t/udf_query_cache.test diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index d939d72f7ef..828d4bafc53 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -104,95 +104,6 @@ t1 CREATE TABLE `t1` ( `length(uuid())` int(10) NOT NULL DEFAULT '0' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; -#------------------------------------------------------------------------ -# Tests for Bug#6760 and Bug#12689 -SET @row_count = 4; -SET @sleep_time_per_result_row = 1; -SET @max_acceptable_delay = 2; -SET @@global.query_cache_size = 1024 * 64; -DROP TEMPORARY TABLE IF EXISTS t_history; -DROP TABLE IF EXISTS t1; -CREATE TEMPORARY TABLE t_history (attempt SMALLINT, -start_ts DATETIME, end_ts DATETIME, -start_cached INTEGER, end_cached INTEGER); -CREATE TABLE t1 (f1 BIGINT); -INSERT INTO t_history -SET attempt = 4 - 4 + 1, start_ts = NOW(), -start_cached = 0; -SELECT *, SLEEP(@sleep_time_per_result_row) FROM t1; -f1 SLEEP(@sleep_time_per_result_row) -1 0 -1 0 -1 0 -1 0 -UPDATE t_history SET end_ts = NOW() -WHERE attempt = 4 - 4 + 1; -UPDATE t_history SET end_cached = 0 -WHERE attempt = 4 - 4 + 1; -INSERT INTO t_history -SET attempt = 4 - 3 + 1, start_ts = NOW(), -start_cached = 0; -SELECT *, SLEEP(@sleep_time_per_result_row) FROM t1; -f1 SLEEP(@sleep_time_per_result_row) -1 0 -1 0 -1 0 -1 0 -UPDATE t_history SET end_ts = NOW() -WHERE attempt = 4 - 3 + 1; -UPDATE t_history SET end_cached = 0 -WHERE attempt = 4 - 3 + 1; -INSERT INTO t_history -SET attempt = 4 - 2 + 1, start_ts = NOW(), -start_cached = 0; -SELECT *, SLEEP(@sleep_time_per_result_row) FROM t1; -f1 SLEEP(@sleep_time_per_result_row) -1 0 -1 0 -1 0 -1 0 -UPDATE t_history SET end_ts = NOW() -WHERE attempt = 4 - 2 + 1; -UPDATE t_history SET end_cached = 0 -WHERE attempt = 4 - 2 + 1; -INSERT INTO t_history -SET attempt = 4 - 1 + 1, start_ts = NOW(), -start_cached = 0; -SELECT *, SLEEP(@sleep_time_per_result_row) FROM t1; -f1 SLEEP(@sleep_time_per_result_row) -1 0 -1 0 -1 0 -1 0 -UPDATE t_history SET end_ts = NOW() -WHERE attempt = 4 - 1 + 1; -UPDATE t_history SET end_cached = 0 -WHERE attempt = 4 - 1 + 1; -# Test 1: Does the query with SLEEP need a reasonable time? -SELECT COUNT(*) >= 4 - 1 INTO @aux1 FROM t_history -WHERE TIMEDIFF(end_ts,start_ts) - @sleep_time_per_result_row * @row_count -BETWEEN 0 AND @max_acceptable_delay; -SELECT @aux1 AS "Expect 1"; -Expect 1 -1 -# Test 2: Does the query with SLEEP need a reasonable time even in case -# of the non first execution? -SELECT COUNT(*) >= 4 - 1 - 1 INTO @aux2 FROM t_history -WHERE TIMEDIFF(end_ts,start_ts) - @sleep_time_per_result_row * @row_count -BETWEEN 0 AND @max_acceptable_delay -AND attempt > 1; -SELECT @aux2 AS "Expect 1"; -Expect 1 -1 -# Test 3: The query with SLEEP must be not cached. -SELECT COUNT(*) = 4 INTO @aux3 FROM t_history -WHERE end_cached = start_cached; -SELECT @aux3 AS "Expect 1"; -Expect 1 -1 -DROP TABLE t1; -DROP TEMPORARY TABLE t_history; -SET @@global.query_cache_size = default; create table t1 select INET_ATON('255.255.0.1') as `a`; show create table t1; Table Create Table diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 2e3a9489593..7d903a17d2e 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -1,3 +1,4 @@ +SET GLOBAL max_connections = 1000; select 0 as "before_use_test" ; before_use_test 0 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index a410f7b2dcf..2380ecc5969 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1302,6 +1302,15 @@ drop procedure f3; drop procedure f4; drop table t1; set GLOBAL query_cache_size=0; +set GLOBAL query_cache_size=100000; +set SESSION query_cache_size=10000; +ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL +set global query_cache_limit=100; +set global query_cache_size=100; +set global query_cache_type=demand; +set GLOBAL query_cache_type=default; +set GLOBAL query_cache_limit=default; +set GLOBAL query_cache_size=default; End of 4.1 tests SET GLOBAL query_cache_size=102400; create table t1(a int); @@ -1707,6 +1716,95 @@ Variable_name Value Qcache_hits 2 DROP TABLE t1; SET GLOBAL query_cache_size= default; +#------------------------------------------------------------------------ +# Tests for Bug#6760 and Bug#12689 +SET @row_count = 4; +SET @sleep_time_per_result_row = 1; +SET @max_acceptable_delay = 2; +SET @@global.query_cache_size = 1024 * 64; +DROP TEMPORARY TABLE IF EXISTS t_history; +DROP TABLE IF EXISTS t1; +CREATE TEMPORARY TABLE t_history (attempt SMALLINT, +start_ts DATETIME, end_ts DATETIME, +start_cached INTEGER, end_cached INTEGER); +CREATE TABLE t1 (f1 BIGINT); +INSERT INTO t_history +SET attempt = 4 - 4 + 1, start_ts = NOW(), +start_cached = 0; +SELECT *, SLEEP(@sleep_time_per_result_row) FROM t1; +f1 SLEEP(@sleep_time_per_result_row) +1 0 +1 0 +1 0 +1 0 +UPDATE t_history SET end_ts = NOW() +WHERE attempt = 4 - 4 + 1; +UPDATE t_history SET end_cached = 0 +WHERE attempt = 4 - 4 + 1; +INSERT INTO t_history +SET attempt = 4 - 3 + 1, start_ts = NOW(), +start_cached = 0; +SELECT *, SLEEP(@sleep_time_per_result_row) FROM t1; +f1 SLEEP(@sleep_time_per_result_row) +1 0 +1 0 +1 0 +1 0 +UPDATE t_history SET end_ts = NOW() +WHERE attempt = 4 - 3 + 1; +UPDATE t_history SET end_cached = 0 +WHERE attempt = 4 - 3 + 1; +INSERT INTO t_history +SET attempt = 4 - 2 + 1, start_ts = NOW(), +start_cached = 0; +SELECT *, SLEEP(@sleep_time_per_result_row) FROM t1; +f1 SLEEP(@sleep_time_per_result_row) +1 0 +1 0 +1 0 +1 0 +UPDATE t_history SET end_ts = NOW() +WHERE attempt = 4 - 2 + 1; +UPDATE t_history SET end_cached = 0 +WHERE attempt = 4 - 2 + 1; +INSERT INTO t_history +SET attempt = 4 - 1 + 1, start_ts = NOW(), +start_cached = 0; +SELECT *, SLEEP(@sleep_time_per_result_row) FROM t1; +f1 SLEEP(@sleep_time_per_result_row) +1 0 +1 0 +1 0 +1 0 +UPDATE t_history SET end_ts = NOW() +WHERE attempt = 4 - 1 + 1; +UPDATE t_history SET end_cached = 0 +WHERE attempt = 4 - 1 + 1; +# Test 1: Does the query with SLEEP need a reasonable time? +SELECT COUNT(*) >= 4 - 1 INTO @aux1 FROM t_history +WHERE TIMEDIFF(end_ts,start_ts) - @sleep_time_per_result_row * @row_count +BETWEEN 0 AND @max_acceptable_delay; +SELECT @aux1 AS "Expect 1"; +Expect 1 +1 +# Test 2: Does the query with SLEEP need a reasonable time even in case +# of the non first execution? +SELECT COUNT(*) >= 4 - 1 - 1 INTO @aux2 FROM t_history +WHERE TIMEDIFF(end_ts,start_ts) - @sleep_time_per_result_row * @row_count +BETWEEN 0 AND @max_acceptable_delay +AND attempt > 1; +SELECT @aux2 AS "Expect 1"; +Expect 1 +1 +# Test 3: The query with SLEEP must be not cached. +SELECT COUNT(*) = 4 INTO @aux3 FROM t_history +WHERE end_cached = start_cached; +SELECT @aux3 AS "Expect 1"; +Expect 1 +1 +DROP TABLE t1; +DROP TEMPORARY TABLE t_history; +SET @@global.query_cache_size = default; End of 5.0 tests SET GLOBAL query_cache_size=1024*1024*512; CREATE TABLE t1 (a ENUM('rainbow')); diff --git a/mysql-test/r/query_cache_notembedded.result b/mysql-test/r/query_cache_notembedded.result index d9bf7a6d814..2dfa7d7aa38 100644 --- a/mysql-test/r/query_cache_notembedded.result +++ b/mysql-test/r/query_cache_notembedded.result @@ -382,3 +382,55 @@ set GLOBAL query_cache_type=default; set GLOBAL query_cache_limit=default; set GLOBAL query_cache_min_res_unit=default; set GLOBAL query_cache_size=default; +drop table if exists t1| +create table t1 ( +id char(16) not null default '', +data int not null +)| +drop procedure if exists bug3583| +drop procedure if exists bug3583| +create procedure bug3583() +begin +declare c int; +select * from t1; +select count(*) into c from t1; +select c; +end| +insert into t1 values ("x", 3), ("y", 5)| +set @x = @@query_cache_size| +set global query_cache_size = 10*1024*1024| +flush status| +flush query cache| +show status like 'Qcache_hits'| +Variable_name Value +Qcache_hits 0 +call bug3583()| +id data +x 3 +y 5 +c +2 +show status like 'Qcache_hits'| +Variable_name Value +Qcache_hits 0 +call bug3583()| +id data +x 3 +y 5 +c +2 +call bug3583()| +id data +x 3 +y 5 +c +2 +show status like 'Qcache_hits'| +Variable_name Value +Qcache_hits 2 +set global query_cache_size = @x| +flush status| +flush query cache| +delete from t1| +drop procedure bug3583| +drop table t1| diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result index 831616f491b..af73d637590 100644 --- a/mysql-test/r/sp_notembedded.result +++ b/mysql-test/r/sp_notembedded.result @@ -25,58 +25,6 @@ call bug4902_2()| show warnings| Level Code Message drop procedure bug4902_2| -drop table if exists t1| -create table t1 ( -id char(16) not null default '', -data int not null -)| -drop procedure if exists bug3583| -drop procedure if exists bug3583| -create procedure bug3583() -begin -declare c int; -select * from t1; -select count(*) into c from t1; -select c; -end| -insert into t1 values ("x", 3), ("y", 5)| -set @x = @@query_cache_size| -set global query_cache_size = 10*1024*1024| -flush status| -flush query cache| -show status like 'Qcache_hits'| -Variable_name Value -Qcache_hits 0 -call bug3583()| -id data -x 3 -y 5 -c -2 -show status like 'Qcache_hits'| -Variable_name Value -Qcache_hits 0 -call bug3583()| -id data -x 3 -y 5 -c -2 -call bug3583()| -id data -x 3 -y 5 -c -2 -show status like 'Qcache_hits'| -Variable_name Value -Qcache_hits 2 -set global query_cache_size = @x| -flush status| -flush query cache| -delete from t1| -drop procedure bug3583| -drop table t1| drop procedure if exists bug6807| create procedure bug6807() begin diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index 601b364fbbe..393a2f54b05 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -311,29 +311,6 @@ drop function f3; drop function metaphon; drop function myfunc_double; drop function myfunc_int; -CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; -create table t1 (a char); -set GLOBAL query_cache_size=1355776; -reset query cache; -select metaphon('MySQL') from t1; -metaphon('MySQL') -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 0 -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 0 -select metaphon('MySQL') from t1; -metaphon('MySQL') -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 0 -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 0 -drop table t1; -drop function metaphon; -set GLOBAL query_cache_size=default; DROP DATABASE IF EXISTS mysqltest; CREATE DATABASE mysqltest; USE mysqltest; diff --git a/mysql-test/r/udf_query_cache.result b/mysql-test/r/udf_query_cache.result new file mode 100644 index 00000000000..01dac554142 --- /dev/null +++ b/mysql-test/r/udf_query_cache.result @@ -0,0 +1,24 @@ +drop table if exists t1; +CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +create table t1 (a char); +set GLOBAL query_cache_size=1355776; +reset query cache; +select metaphon('MySQL') from t1; +metaphon('MySQL') +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +select metaphon('MySQL') from t1; +metaphon('MySQL') +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +drop table t1; +drop function metaphon; +set GLOBAL query_cache_size=default; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 4582ccddd81..49c19e9b455 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -19,8 +19,6 @@ set @my_myisam_max_sort_file_size =@@global.myisam_max_sort_file_size; set @my_net_buffer_length =@@global.net_buffer_length; set @my_net_write_timeout =@@global.net_write_timeout; set @my_net_read_timeout =@@global.net_read_timeout; -set @my_query_cache_limit =@@global.query_cache_limit; -set @my_query_cache_type =@@global.query_cache_type; set @my_rpl_recovery_rank =@@global.rpl_recovery_rank; set @my_server_id =@@global.server_id; set @my_slow_launch_time =@@global.slow_launch_time; @@ -215,7 +213,6 @@ storage_engine MRG_MYISAM select * from information_schema.global_variables where variable_name like 'storage_engine'; VARIABLE_NAME VARIABLE_VALUE STORAGE_ENGINE MRG_MYISAM -set GLOBAL query_cache_size=100000; set GLOBAL myisam_max_sort_file_size=2000000; show global variables like 'myisam_max_sort_file_size'; Variable_name Value @@ -423,8 +420,6 @@ ERROR 42000: Variable 'big_tables' can't be set to the value of '2' show local variables like 'storage_engine'; Variable_name Value storage_engine MEMORY -set SESSION query_cache_size=10000; -ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL set GLOBAL storage_engine=DEFAULT; ERROR 42000: Variable 'storage_engine' doesn't have a default value set character_set_client=UNKNOWN_CHARACTER_SET; @@ -529,9 +524,6 @@ Warnings: Warning 1292 Truncated incorrect net_buffer_length value: '100' set net_read_timeout=100; set net_write_timeout=100; -set global query_cache_limit=100; -set global query_cache_size=100; -set global query_cache_type=demand; set read_buffer_size=100; Warnings: Warning 1292 Truncated incorrect read_buffer_size value: '100' @@ -1047,8 +1039,6 @@ set global myisam_max_sort_file_size =@my_myisam_max_sort_file_size; set global net_buffer_length =@my_net_buffer_length; set global net_write_timeout =@my_net_write_timeout; set global net_read_timeout =@my_net_read_timeout; -set global query_cache_limit =@my_query_cache_limit; -set global query_cache_type =@my_query_cache_type; set global rpl_recovery_rank =@my_rpl_recovery_rank; set global server_id =@my_server_id; set global slow_launch_time =@my_slow_launch_time; diff --git a/mysql-test/suite/funcs_1/datadict/processlist_val.inc b/mysql-test/suite/funcs_1/datadict/processlist_val.inc index 9936b7c580b..a2ab02c963f 100644 --- a/mysql-test/suite/funcs_1/datadict/processlist_val.inc +++ b/mysql-test/suite/funcs_1/datadict/processlist_val.inc @@ -238,7 +238,7 @@ echo # Poll till all connections of 'test_user' are in a state with COMMAND = 'Sleep' ; let $wait_condition= SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST - WHERE USER = 'test_user' AND COMMAND = 'Sleep'; + WHERE USER = 'test_user' AND COMMAND = 'Sleep' AND STATE = ''; --source include/wait_condition.inc echo # ----- switch to connection con2 (user = test_user) ----- diff --git a/mysql-test/suite/rpl/r/rpl_temporary.result b/mysql-test/suite/rpl/r/rpl_temporary.result index 631eb0677b0..79c5abbd478 100644 --- a/mysql-test/suite/rpl/r/rpl_temporary.result +++ b/mysql-test/suite/rpl/r/rpl_temporary.result @@ -4,7 +4,8 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -call mtr.add_suppression("Slave: Can\'t find record in \'user\' Error_code: 1032"); +SET sql_log_bin = 0; +SET sql_log_bin = 1; reset master; DROP TABLE IF EXISTS t1; CREATE TEMPORARY TABLE t1 (a char(1)); @@ -127,6 +128,8 @@ select * from t1; a 1 drop table t1; +SET sql_log_bin = 0; +SET sql_log_bin = 1; -- Bug#43748 -- make a user on the slave that can list but not kill system threads. FLUSH PRIVILEGES; diff --git a/mysql-test/suite/rpl/t/rpl_temporary.test b/mysql-test/suite/rpl/t/rpl_temporary.test index a59e4f2fd21..56d8ab97c3f 100644 --- a/mysql-test/suite/rpl/t/rpl_temporary.test +++ b/mysql-test/suite/rpl/t/rpl_temporary.test @@ -1,8 +1,11 @@ -# Test need anonymous user when connection are made as "zedjzlcsjhd" -source include/add_anonymous_users.inc; - -- source include/master-slave.inc +# Test need anonymous user when connection are made as "zedjzlcsjhd" +# But we only need it on the master, not the slave. +SET sql_log_bin = 0; +source include/add_anonymous_users.inc; +SET sql_log_bin = 1; + # Clean up old slave's binlogs. # The slave is started with --log-slave-updates # and this test does SHOW BINLOG EVENTS on the slave's @@ -17,9 +20,6 @@ source include/add_anonymous_users.inc; save_master_pos; connection slave; -# Add suppression for expected warning(s) in slaves error log -call mtr.add_suppression("Slave: Can\'t find record in \'user\' Error_code: 1032"); - sync_with_master; reset master; @@ -291,7 +291,9 @@ drop table t1; --remove_file $MYSQLTEST_VARDIR/tmp/bug14157.sql # Delete the anonymous users +SET sql_log_bin = 0; source include/delete_anonymous_users.inc; +SET sql_log_bin = 1; diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 98a5ad8d80c..afce01cac5c 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -102,198 +102,6 @@ create table t1 as select uuid(), length(uuid()); show create table t1; drop table t1; -# -# Bug#6760: Add SLEEP() function (feature request) -# -# Logics of original test: -# Reveal that a query with SLEEP does not need less time than estimated. -# -# Bug#12689: SLEEP() gets incorrectly cached/optimized-away -# -# Description from bug report (slightly modified) -# -# Bug 1 (happened all time): -# SELECT * FROM t1 WHERE SLEEP(1) will only result in a sleep of 1 -# second, regardless of the number of rows in t1. -# Bug 2 (happened all time): -# Such a query will also get cached by the query cache, but should not. -# -# Notes (mleich, 2008-05) -# ======================= -# -# Experiments around -# Bug#36345 Test 'func_misc' fails on RHAS3 x86_64 -# showed that the tests for both bugs could produce in case of parallel -# artificial system time (like via ntpd) -# - decreases false alarm -# - increases false success -# -# We try here to circumvent these issues by reimplementation of the tests -# and sophisticated scripting, although the cause of the problems is a massive -# error within the setup of the testing environment. -# Tests relying on or checking derivates of the system time must never meet -# parallel manipulations of system time. -# -# Results of experiments with/without manipulation of system time, -# information_schema.processlist content, high load on testing box -# ---------------------------------------------------------------- -# Definition: Predicted_cumulative_sleep_time = -# #_of_result_rows * sleep_time_per_result_row -# -# 1. Total (real sleep time) ~= predicted_cumulative_sleep_time !! -# 2. The state of a session within the PROCESSLIST changes to 'User sleep' -# if the sessions runs a statement containing the sleep function and the -# processing of the statement is just within the phase where the sleep -# is done. (*) -# 3. NOW() and processlist.time behave "synchronous" to system time and -# show also the "jumps" caused by system time manipulations. (*) -# 4. processlist.time is unsigned, the "next" value below 0 is ~ 4G (*) -# 5. Current processlist.time ~= current real sleep time if the system time -# was not manipulated. (*) -# 6. High system load can cause delays of <= 2 seconds. -# 7. Thanks to Davi for excellent hints and ideas. -# -# (*) -# - information_schema.processlist is not available before MySQL 5.1. -# - Observation of processlist content requires a -# - "worker" session sending the query with "send" and pulling results -# with "reap" -# - session observing the processlist parallel to the worker session -# "send" and "reap" do not work in case of an embedded server. -# Conclusion: Tests based on processlist have too many restrictions. -# -# Solutions for subtests based on TIMEDIFF of values filled via NOW() -# ------------------------------------------------------------------- -# Run the following sequence three times -# 1. SELECT -# 2. Query with SLEEP -# 3. SELECT -# If TIMEDIFF(,) is at least two times within a -# reasonable range assume that we did not met errors we were looking for. -# -# It is extreme unlikely that we have two system time changes within the -# < 30 seconds runtime. Even if the unlikely happens, there are so -# frequent runs of this test on this or another testing box which will -# catch the problem. -# - ---echo #------------------------------------------------------------------------ ---echo # Tests for Bug#6760 and Bug#12689 -# Number of rows within the intended result set. -SET @row_count = 4; -# Parameter within SLEEP function -SET @sleep_time_per_result_row = 1; -# Maximum acceptable delay caused by high load on testing box -SET @max_acceptable_delay = 2; -# TIMEDIFF = time for query with sleep (mostly the time caused by SLEEP) -# + time for delays caused by high load on testing box -# Ensure that at least a reasonable fraction of TIMEDIFF belongs to the SLEEP -# by appropriate setting of variables. -# Ensure that any "judging" has a base of minimum three attempts. -# (Test 2 uses all attempts except the first one.) -if (!` SELECT (@sleep_time_per_result_row * @row_count - @max_acceptable_delay > - @sleep_time_per_result_row) AND (@row_count - 1 >= 3)`) -{ - --echo # Have to abort because of error in plausibility check - --echo ###################################################### - --vertical_results - SELECT @sleep_time_per_result_row * @row_count - @max_acceptable_delay > - @sleep_time_per_result_row AS must_be_1, - @row_count - 1 >= 3 AS must_be_also_1, - @sleep_time_per_result_row, @row_count, @max_acceptable_delay; - exit; -} -SET @@global.query_cache_size = 1024 * 64; ---disable_warnings -DROP TEMPORARY TABLE IF EXISTS t_history; -DROP TABLE IF EXISTS t1; ---enable_warnings -CREATE TEMPORARY TABLE t_history (attempt SMALLINT, -start_ts DATETIME, end_ts DATETIME, -start_cached INTEGER, end_cached INTEGER); -CREATE TABLE t1 (f1 BIGINT); -let $num = `SELECT @row_count`; ---disable_query_log -begin; -while ($num) -{ - INSERT INTO t1 VALUES (1); - dec $num; -} -commit; ---enable_query_log - -let $loops = 4; -let $num = $loops; -while ($num) -{ - let $Qcache_queries_in_cache = - query_get_value(SHOW STATUS LIKE 'Qcache_queries_in_cache', Value, 1); - eval - INSERT INTO t_history - SET attempt = $loops - $num + 1, start_ts = NOW(), - start_cached = $Qcache_queries_in_cache; - SELECT *, SLEEP(@sleep_time_per_result_row) FROM t1; - # - # Do not determine Qcache_queries_in_cache before updating end_ts. The SHOW - # might cost too much time on an overloaded box. - eval - UPDATE t_history SET end_ts = NOW() - WHERE attempt = $loops - $num + 1; - let $Qcache_queries_in_cache = - query_get_value(SHOW STATUS LIKE 'Qcache_queries_in_cache', Value, 1); - eval - UPDATE t_history SET end_cached = $Qcache_queries_in_cache - WHERE attempt = $loops - $num + 1; - # DEBUG eval SELECT * FROM t_history WHERE attempt = $loops - $num + 1; - dec $num; -} - -# 1. The majority of queries with SLEEP must need a reasonable time -# -> SLEEP has an impact on runtime -# = Replacement for original Bug#6760 test -# -> total runtime is clear more needed than for one result row needed -# = Replacement for one of the original Bug#12689 tests ---echo # Test 1: Does the query with SLEEP need a reasonable time? -eval SELECT COUNT(*) >= $loops - 1 INTO @aux1 FROM t_history -WHERE TIMEDIFF(end_ts,start_ts) - @sleep_time_per_result_row * @row_count - BETWEEN 0 AND @max_acceptable_delay; -SELECT @aux1 AS "Expect 1"; -# -# 2. The majority of queries (the first one must be ignored) with SLEEP must -# need a reasonable time -# -> If we assume that the result of a cached query will be sent back -# immediate, without any sleep, than the query with SLEEP cannot be cached -# (current and intended behaviour for queries with SLEEP). -# -> It could be also not excluded that the query was cached but the server -# honoured somehow the SLEEP. Such a behaviour would be also acceptable. -# = Replacement for one of the original Bug#12689 tests ---echo # Test 2: Does the query with SLEEP need a reasonable time even in case ---echo # of the non first execution? -eval SELECT COUNT(*) >= $loops - 1 - 1 INTO @aux2 FROM t_history -WHERE TIMEDIFF(end_ts,start_ts) - @sleep_time_per_result_row * @row_count - BETWEEN 0 AND @max_acceptable_delay - AND attempt > 1; -SELECT @aux2 AS "Expect 1"; -# -# 3. The query with SLEEP should be not cached. -# -> SHOW STATUS Qcache_queries_in_cache must be not incremented after -# the execution of the query with SLEEP ---echo # Test 3: The query with SLEEP must be not cached. -eval SELECT COUNT(*) = $loops INTO @aux3 FROM t_history -WHERE end_cached = start_cached; -SELECT @aux3 AS "Expect 1"; -# -# Dump the content of t_history if one of the tests failed. -if (`SELECT @aux1 + @aux2 + @aux3 <> 3`) -{ - --echo # Some tests failed, dumping the content of t_history - SELECT * FROM t_history; -} -DROP TABLE t1; -DROP TEMPORARY TABLE t_history; -SET @@global.query_cache_size = default; - # # Bug #21466: INET_ATON() returns signed, not unsigned # diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index bcf33aa8c27..c86ebda3a24 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -9,6 +9,14 @@ # Save the initial number of concurrent sessions --source include/count_sessions.inc +# Some tests below connect/disconnect rapidly in a loop. This causes a race +# where mysqld may not have time to register the previous disconnects before +# new connects, and eventually we run out of connections. So we need to +# increase the maximum. +let $saved_max_connections = `SELECT @@global.max_connections`; +SET GLOBAL max_connections = 1000; + + # ============================================================================ # # Test of mysqltest itself @@ -2319,3 +2327,7 @@ disconnect $y; connection default; # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc + +--disable_query_log +--eval SET GLOBAL max_connections = $saved_max_connections +--enable_query_log diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 3d9045d3aa6..de8467b509d 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -882,6 +882,19 @@ drop procedure f4; drop table t1; set GLOBAL query_cache_size=0; +# Tests moved from main.variables due to needing query cache in server. +set GLOBAL query_cache_size=100000; +--error ER_GLOBAL_VARIABLE +set SESSION query_cache_size=10000; +set global query_cache_limit=100; +set global query_cache_size=100; +set global query_cache_type=demand; + +set GLOBAL query_cache_type=default; +set GLOBAL query_cache_limit=default; +set GLOBAL query_cache_size=default; + + --echo End of 4.1 tests # @@ -1288,6 +1301,198 @@ SHOW STATUS LIKE "Qcache_hits"; DROP TABLE t1; SET GLOBAL query_cache_size= default; +# +# Bug#6760: Add SLEEP() function (feature request) +# +# Logics of original test: +# Reveal that a query with SLEEP does not need less time than estimated. +# +# Bug#12689: SLEEP() gets incorrectly cached/optimized-away +# +# Description from bug report (slightly modified) +# +# Bug 1 (happened all time): +# SELECT * FROM t1 WHERE SLEEP(1) will only result in a sleep of 1 +# second, regardless of the number of rows in t1. +# Bug 2 (happened all time): +# Such a query will also get cached by the query cache, but should not. +# +# Notes (mleich, 2008-05) +# ======================= +# +# Experiments around +# Bug#36345 Test 'func_misc' fails on RHAS3 x86_64 +# showed that the tests for both bugs could produce in case of parallel +# artificial system time (like via ntpd) +# - decreases false alarm +# - increases false success +# +# We try here to circumvent these issues by reimplementation of the tests +# and sophisticated scripting, although the cause of the problems is a massive +# error within the setup of the testing environment. +# Tests relying on or checking derivates of the system time must never meet +# parallel manipulations of system time. +# +# Results of experiments with/without manipulation of system time, +# information_schema.processlist content, high load on testing box +# ---------------------------------------------------------------- +# Definition: Predicted_cumulative_sleep_time = +# #_of_result_rows * sleep_time_per_result_row +# +# 1. Total (real sleep time) ~= predicted_cumulative_sleep_time !! +# 2. The state of a session within the PROCESSLIST changes to 'User sleep' +# if the sessions runs a statement containing the sleep function and the +# processing of the statement is just within the phase where the sleep +# is done. (*) +# 3. NOW() and processlist.time behave "synchronous" to system time and +# show also the "jumps" caused by system time manipulations. (*) +# 4. processlist.time is unsigned, the "next" value below 0 is ~ 4G (*) +# 5. Current processlist.time ~= current real sleep time if the system time +# was not manipulated. (*) +# 6. High system load can cause delays of <= 2 seconds. +# 7. Thanks to Davi for excellent hints and ideas. +# +# (*) +# - information_schema.processlist is not available before MySQL 5.1. +# - Observation of processlist content requires a +# - "worker" session sending the query with "send" and pulling results +# with "reap" +# - session observing the processlist parallel to the worker session +# "send" and "reap" do not work in case of an embedded server. +# Conclusion: Tests based on processlist have too many restrictions. +# +# Solutions for subtests based on TIMEDIFF of values filled via NOW() +# ------------------------------------------------------------------- +# Run the following sequence three times +# 1. SELECT +# 2. Query with SLEEP +# 3. SELECT +# If TIMEDIFF(,) is at least two times within a +# reasonable range assume that we did not met errors we were looking for. +# +# It is extreme unlikely that we have two system time changes within the +# < 30 seconds runtime. Even if the unlikely happens, there are so +# frequent runs of this test on this or another testing box which will +# catch the problem. +# + +--echo #------------------------------------------------------------------------ +--echo # Tests for Bug#6760 and Bug#12689 +# Number of rows within the intended result set. +SET @row_count = 4; +# Parameter within SLEEP function +SET @sleep_time_per_result_row = 1; +# Maximum acceptable delay caused by high load on testing box +SET @max_acceptable_delay = 2; +# TIMEDIFF = time for query with sleep (mostly the time caused by SLEEP) +# + time for delays caused by high load on testing box +# Ensure that at least a reasonable fraction of TIMEDIFF belongs to the SLEEP +# by appropriate setting of variables. +# Ensure that any "judging" has a base of minimum three attempts. +# (Test 2 uses all attempts except the first one.) +if (!` SELECT (@sleep_time_per_result_row * @row_count - @max_acceptable_delay > + @sleep_time_per_result_row) AND (@row_count - 1 >= 3)`) +{ + --echo # Have to abort because of error in plausibility check + --echo ###################################################### + --vertical_results + SELECT @sleep_time_per_result_row * @row_count - @max_acceptable_delay > + @sleep_time_per_result_row AS must_be_1, + @row_count - 1 >= 3 AS must_be_also_1, + @sleep_time_per_result_row, @row_count, @max_acceptable_delay; + exit; +} +SET @@global.query_cache_size = 1024 * 64; +--disable_warnings +DROP TEMPORARY TABLE IF EXISTS t_history; +DROP TABLE IF EXISTS t1; +--enable_warnings +CREATE TEMPORARY TABLE t_history (attempt SMALLINT, +start_ts DATETIME, end_ts DATETIME, +start_cached INTEGER, end_cached INTEGER); +CREATE TABLE t1 (f1 BIGINT); +let $num = `SELECT @row_count`; +--disable_query_log +begin; +while ($num) +{ + INSERT INTO t1 VALUES (1); + dec $num; +} +commit; +--enable_query_log + +let $loops = 4; +let $num = $loops; +while ($num) +{ + let $Qcache_queries_in_cache = + query_get_value(SHOW STATUS LIKE 'Qcache_queries_in_cache', Value, 1); + eval + INSERT INTO t_history + SET attempt = $loops - $num + 1, start_ts = NOW(), + start_cached = $Qcache_queries_in_cache; + SELECT *, SLEEP(@sleep_time_per_result_row) FROM t1; + # + # Do not determine Qcache_queries_in_cache before updating end_ts. The SHOW + # might cost too much time on an overloaded box. + eval + UPDATE t_history SET end_ts = NOW() + WHERE attempt = $loops - $num + 1; + let $Qcache_queries_in_cache = + query_get_value(SHOW STATUS LIKE 'Qcache_queries_in_cache', Value, 1); + eval + UPDATE t_history SET end_cached = $Qcache_queries_in_cache + WHERE attempt = $loops - $num + 1; + # DEBUG eval SELECT * FROM t_history WHERE attempt = $loops - $num + 1; + dec $num; +} + +# 1. The majority of queries with SLEEP must need a reasonable time +# -> SLEEP has an impact on runtime +# = Replacement for original Bug#6760 test +# -> total runtime is clear more needed than for one result row needed +# = Replacement for one of the original Bug#12689 tests +--echo # Test 1: Does the query with SLEEP need a reasonable time? +eval SELECT COUNT(*) >= $loops - 1 INTO @aux1 FROM t_history +WHERE TIMEDIFF(end_ts,start_ts) - @sleep_time_per_result_row * @row_count + BETWEEN 0 AND @max_acceptable_delay; +SELECT @aux1 AS "Expect 1"; +# +# 2. The majority of queries (the first one must be ignored) with SLEEP must +# need a reasonable time +# -> If we assume that the result of a cached query will be sent back +# immediate, without any sleep, than the query with SLEEP cannot be cached +# (current and intended behaviour for queries with SLEEP). +# -> It could be also not excluded that the query was cached but the server +# honoured somehow the SLEEP. Such a behaviour would be also acceptable. +# = Replacement for one of the original Bug#12689 tests +--echo # Test 2: Does the query with SLEEP need a reasonable time even in case +--echo # of the non first execution? +eval SELECT COUNT(*) >= $loops - 1 - 1 INTO @aux2 FROM t_history +WHERE TIMEDIFF(end_ts,start_ts) - @sleep_time_per_result_row * @row_count + BETWEEN 0 AND @max_acceptable_delay + AND attempt > 1; +SELECT @aux2 AS "Expect 1"; +# +# 3. The query with SLEEP should be not cached. +# -> SHOW STATUS Qcache_queries_in_cache must be not incremented after +# the execution of the query with SLEEP +--echo # Test 3: The query with SLEEP must be not cached. +eval SELECT COUNT(*) = $loops INTO @aux3 FROM t_history +WHERE end_cached = start_cached; +SELECT @aux3 AS "Expect 1"; +# +# Dump the content of t_history if one of the tests failed. +if (`SELECT @aux1 + @aux2 + @aux3 <> 3`) +{ + --echo # Some tests failed, dumping the content of t_history + SELECT * FROM t_history; +} +DROP TABLE t1; +DROP TEMPORARY TABLE t_history; +SET @@global.query_cache_size = default; + --echo End of 5.0 tests # diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test index 095d47f5bdf..d807215348c 100644 --- a/mysql-test/t/query_cache_notembedded.test +++ b/mysql-test/t/query_cache_notembedded.test @@ -274,5 +274,52 @@ set GLOBAL query_cache_limit=default; set GLOBAL query_cache_min_res_unit=default; set GLOBAL query_cache_size=default; +# +# Bug#3583 query cache doesn't work for stored procedures +# +delimiter |; +--disable_warnings +drop table if exists t1| +--enable_warnings +create table t1 ( + id char(16) not null default '', + data int not null +)| +--disable_warnings +drop procedure if exists bug3583| +--enable_warnings +--disable_warnings +drop procedure if exists bug3583| +--enable_warnings +create procedure bug3583() +begin + declare c int; + + select * from t1; + select count(*) into c from t1; + select c; +end| + +insert into t1 values ("x", 3), ("y", 5)| +set @x = @@query_cache_size| +set global query_cache_size = 10*1024*1024| + +flush status| +flush query cache| +show status like 'Qcache_hits'| +call bug3583()| +show status like 'Qcache_hits'| +call bug3583()| +call bug3583()| +show status like 'Qcache_hits'| + +set global query_cache_size = @x| +flush status| +flush query cache| +delete from t1| +drop procedure bug3583| +drop table t1| +delimiter ;| + # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test index f593e184ad2..f8803e28e0a 100644 --- a/mysql-test/t/sp_notembedded.test +++ b/mysql-test/t/sp_notembedded.test @@ -55,52 +55,6 @@ call bug4902_2()| show warnings| drop procedure bug4902_2| -# -# Bug#3583 query cache doesn't work for stored procedures -# ---disable_warnings -drop table if exists t1| ---enable_warnings -create table t1 ( - id char(16) not null default '', - data int not null -)| ---disable_warnings -drop procedure if exists bug3583| ---enable_warnings ---disable_warnings -drop procedure if exists bug3583| ---enable_warnings -create procedure bug3583() -begin - declare c int; - - select * from t1; - select count(*) into c from t1; - select c; -end| - -insert into t1 values ("x", 3), ("y", 5)| -set @x = @@query_cache_size| -set global query_cache_size = 10*1024*1024| - -flush status| -flush query cache| -show status like 'Qcache_hits'| -call bug3583()| -show status like 'Qcache_hits'| -call bug3583()| -call bug3583()| -show status like 'Qcache_hits'| - -set global query_cache_size = @x| -flush status| -flush query cache| -delete from t1| -drop procedure bug3583| -drop table t1| - - # # Bug#6807 Stored procedure crash if CREATE PROCEDURE ... KILL QUERY # diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test index 7bf252040e5..4364b0c820e 100644 --- a/mysql-test/t/udf.test +++ b/mysql-test/t/udf.test @@ -341,29 +341,6 @@ drop function metaphon; drop function myfunc_double; drop function myfunc_int; -# -# Bug #28921: Queries containing UDF functions are cached -# - ---replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB -eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; -create table t1 (a char); - -set GLOBAL query_cache_size=1355776; -reset query cache; - -select metaphon('MySQL') from t1; -show status like "Qcache_hits"; -show status like "Qcache_queries_in_cache"; - -select metaphon('MySQL') from t1; -show status like "Qcache_hits"; -show status like "Qcache_queries_in_cache"; - -drop table t1; -drop function metaphon; -set GLOBAL query_cache_size=default; - # # Bug#28318 CREATE FUNCTION (UDF) requires a schema # diff --git a/mysql-test/t/udf_query_cache-master.opt b/mysql-test/t/udf_query_cache-master.opt new file mode 100644 index 00000000000..7d8786c156a --- /dev/null +++ b/mysql-test/t/udf_query_cache-master.opt @@ -0,0 +1 @@ +$UDF_EXAMPLE_LIB_OPT diff --git a/mysql-test/t/udf_query_cache.test b/mysql-test/t/udf_query_cache.test new file mode 100644 index 00000000000..cb64a2f1665 --- /dev/null +++ b/mysql-test/t/udf_query_cache.test @@ -0,0 +1,35 @@ +--source include/have_udf.inc +--source include/have_query_cache.inc +# +# To run this tests the "sql/udf_example.c" need to be compiled into +# udf_example.so and LD_LIBRARY_PATH should be setup to point out where +# the library are. +# + +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# Bug #28921: Queries containing UDF functions are cached +# + +--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB +eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; +create table t1 (a char); + +set GLOBAL query_cache_size=1355776; +reset query cache; + +select metaphon('MySQL') from t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +select metaphon('MySQL') from t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +drop table t1; +drop function metaphon; +set GLOBAL query_cache_size=default; + diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index c8ee633dab3..593ea3de7c1 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -28,8 +28,6 @@ set @my_myisam_max_sort_file_size =@@global.myisam_max_sort_file_size; set @my_net_buffer_length =@@global.net_buffer_length; set @my_net_write_timeout =@@global.net_write_timeout; set @my_net_read_timeout =@@global.net_read_timeout; -set @my_query_cache_limit =@@global.query_cache_limit; -set @my_query_cache_type =@@global.query_cache_type; set @my_rpl_recovery_rank =@@global.rpl_recovery_rank; set @my_server_id =@@global.server_id; set @my_slow_launch_time =@@global.slow_launch_time; @@ -138,7 +136,6 @@ show local variables like 'storage_engine'; select * from information_schema.session_variables where variable_name like 'storage_engine'; show global variables like 'storage_engine'; select * from information_schema.global_variables where variable_name like 'storage_engine'; -set GLOBAL query_cache_size=100000; set GLOBAL myisam_max_sort_file_size=2000000; show global variables like 'myisam_max_sort_file_size'; @@ -255,8 +252,6 @@ set storage_engine=UNKNOWN_TABLE_TYPE; --error ER_WRONG_VALUE_FOR_VAR set storage_engine=MERGE, big_tables=2; show local variables like 'storage_engine'; ---error ER_GLOBAL_VARIABLE -set SESSION query_cache_size=10000; --error ER_NO_DEFAULT set GLOBAL storage_engine=DEFAULT; --error ER_UNKNOWN_CHARACTER_SET @@ -334,9 +329,6 @@ set myisam_sort_buffer_size=100; set global net_buffer_length=100; set net_read_timeout=100; set net_write_timeout=100; -set global query_cache_limit=100; -set global query_cache_size=100; -set global query_cache_type=demand; set read_buffer_size=100; set read_rnd_buffer_size=100; set global rpl_recovery_rank=100; @@ -822,8 +814,6 @@ set global myisam_max_sort_file_size =@my_myisam_max_sort_file_size; set global net_buffer_length =@my_net_buffer_length; set global net_write_timeout =@my_net_write_timeout; set global net_read_timeout =@my_net_read_timeout; -set global query_cache_limit =@my_query_cache_limit; -set global query_cache_type =@my_query_cache_type; set global rpl_recovery_rank =@my_rpl_recovery_rank; set global server_id =@my_server_id; set global slow_launch_time =@my_slow_launch_time; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 0efe779c7bc..7f5bcaff083 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -2464,6 +2464,34 @@ static uint query_cache_hits(MYSQL *conn) mysql_free_result(r_metadata); +/* + Check that query cache is available in server. +*/ +static my_bool is_query_cache_available() +{ + int rc; + MYSQL_RES *result; + MYSQL_ROW row; + int res= -1; + + rc= mysql_query(mysql, "SHOW VARIABLES LIKE 'have_query_cache'"); + myquery(rc); + + result= mysql_store_result(mysql); + DIE_UNLESS(result); + + row= mysql_fetch_row(result); + DIE_UNLESS(row != NULL); + if (strcmp(row[1], "YES") == 0) + res= 1; + else if (strcmp(row[1], "NO") == 0) + res= 0; + mysql_free_result(result); + + DIE_UNLESS(res == 0 || res == 1); + return res; +} + /* Test that prepared statements make use of the query cache just as normal statements (BUG#735). @@ -2508,6 +2536,12 @@ static void test_ps_query_cache() myheader("test_ps_query_cache"); + if (! is_query_cache_available()) + { + fprintf(stdout, "Skipping test_ps_query_cache: Query cache not available.\n"); + return; + } + rc= mysql_query(mysql, "SET SQL_MODE=''"); myquery(rc); @@ -17863,8 +17897,6 @@ static void test_bug43560(void) Bug#36326: nested transaction and select */ -#ifdef HAVE_QUERY_CACHE - static void test_bug36326() { int rc; @@ -17872,6 +17904,12 @@ static void test_bug36326() DBUG_ENTER("test_bug36326"); myheader("test_bug36326"); + if (! is_query_cache_available()) + { + fprintf(stdout, "Skipping test_bug36326: Query cache not available.\n"); + DBUG_VOID_RETURN; + } + rc= mysql_autocommit(mysql, TRUE); myquery(rc); rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); @@ -17911,8 +17949,6 @@ static void test_bug36326() DBUG_VOID_RETURN; } -#endif - /** Bug#41078: With CURSOR_TYPE_READ_ONLY mysql_stmt_fetch() returns short string value. @@ -18373,9 +18409,7 @@ static struct my_tests_st my_tests[]= { { "test_bug38486", test_bug38486 }, { "test_bug40365", test_bug40365 }, { "test_bug43560", test_bug43560 }, -#ifdef HAVE_QUERY_CACHE { "test_bug36326", test_bug36326 }, -#endif { "test_bug41078", test_bug41078 }, { "test_bug44495", test_bug44495 }, { 0, 0 } From 107f34ed77aad27b1fca24aaf048d1cbb28978b2 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Mon, 11 Jan 2010 18:21:22 +0400 Subject: [PATCH 230/344] Bug #49955: ld error message: undefined reference to `strmov_overlapp' 32bit builds with the --enable-assembler flag (enabled by default) fail with an error message: undefined reference to `strmov_overlapp'. Since the fix for bug 48866 we use a home-grown strmov function instead of the ctpcpy function, but the source file for this function was missed in the Makefile.am. The strings/Makefile.am file has been modified to include strmov.c file into ASSEMBLER_x86 and ASSEMBLER_sparc32 sections. strings/Makefile.am: Bug #49955: ld error message: undefined reference to `strmov_overlapp' The strings/Makefile.am file has been modified to include strmov.c file into ASSEMBLER_x86 and ASSEMBLER_sparc32 sections. --- strings/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/Makefile.am b/strings/Makefile.am index f0d6585dee4..c4712792c69 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -21,13 +21,13 @@ pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X if ASSEMBLER_x86 ASRCS = strings-x86.s longlong2str-x86.s my_strtoll10-x86.s -CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c str_alloc.c longlong2str_asm.c +CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c str_alloc.c longlong2str_asm.c strmov.c else if ASSEMBLER_sparc32 # These file MUST all be on the same line!! Otherwise automake # generats a very broken makefile ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s -CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c +CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c strmov.c else #no assembler ASRCS = From 3c9322e73f5b994b7ec13ed73e99ce4bc94694b8 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Mon, 11 Jan 2010 19:23:36 +0100 Subject: [PATCH 231/344] Implement the change of RPM versioning and file naming: - "release" starts from 1 - "level" ("m2", "rc", ...) is included in the RPM version. --- support-files/Makefile.am | 3 ++- support-files/mysql.spec.sh | 14 ++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/support-files/Makefile.am b/support-files/Makefile.am index 77eddea3227..c78f08a39b3 100644 --- a/support-files/Makefile.am +++ b/support-files/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2000-2001, 2003-2006 MySQL AB +# Copyright (C) 2000-2006 MySQL AB, 2008-2010 Sun Microsystems, Inc. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public @@ -119,6 +119,7 @@ SUFFIXES = .sh -e 's!@''SHARED_LIB_VERSION''@!@SHARED_LIB_VERSION@!' \ -e 's!@''MYSQL_BASE_VERSION''@!@MYSQL_BASE_VERSION@!' \ -e 's!@''MYSQL_NO_DASH_VERSION''@!@MYSQL_NO_DASH_VERSION@!' \ + -e 's!@''MYSQL_U_SCORE_VERSION''@!@MYSQL_U_SCORE_VERSION@!' \ -e 's!@''MYSQL_COPYRIGHT_YEAR''@!@MYSQL_COPYRIGHT_YEAR@!' \ -e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \ -e 's!@''PERL_DBI_VERSION''@!@PERL_DBI_VERSION@!' \ diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 8209c4560c6..6c586d21a3c 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -1,4 +1,4 @@ -# Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +# Copyright 2000-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -51,9 +51,9 @@ %{!?_with_cluster:%define CLUSTER_BUILD 0} %if %{STATIC_BUILD} -%define release 0 +%define release 1 %else -%define release 0.glibc23 +%define release 1.glibc23 %endif %define mysql_license GPL %define mysqld_user mysql @@ -87,7 +87,7 @@ Name: MySQL Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases -Version: @MYSQL_NO_DASH_VERSION@ +Version: @MYSQL_U_SCORE_VERSION@ Release: %{release} License: Copyright 2000-2008 MySQL AB, @MYSQL_COPYRIGHT_YEAR@ Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Under %{mysql_license} license as shown in the Description field. Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/mysql-%{mysql_version}.tar.gz @@ -882,6 +882,12 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Mon Jan 11 2010 Joerg Bruehe + +- Change RPM file naming: + - Suffix like "-m2", "-rc" becomes part of version as "_m2", "_rc". + - Release counts from 1, not 0. + * Mon Aug 24 2009 Jonathan Perkin - Add conditionals for bundled zlib and innodb plugin From 37d9810d01ec1a43a28e518e5a9a913b340d4e24 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jan 2010 23:27:39 +0100 Subject: [PATCH 232/344] Make test case deterministic by replacing sleep with include/wait_condition.inc --- mysql-test/t/trigger.test | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 1e55f9d5993..5ee2a854363 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1789,18 +1789,28 @@ CONNECTION rl_holder; SELECT GET_LOCK('B26162',120); CONNECTION rl_acquirer; +let $rl_acquirer_thread_id = `SELECT @@pseudo_thread_id`; --send SELECT 'rl_acquirer', GET_LOCK('B26162',120), id FROM t2 WHERE id = 1; CONNECTION wl_acquirer; +let $wl_acquirer_thread_id = `SELECT @@pseudo_thread_id`; SET SESSION LOW_PRIORITY_UPDATES=1; SET GLOBAL LOW_PRIORITY_UPDATES=1; #need to wait for rl_acquirer to lock on the B26162 lock -sleep 2; +let $wait_condition= + SELECT STATE = 'User lock' FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE ID = $rl_acquirer_thread_id; +--source include/wait_condition.inc --send INSERT INTO t1 VALUES (5); CONNECTION rl_contender; +# Wait until wl_acquirer is waiting for the read lock on t2 to be released. +let $wait_condition= + SELECT STATE = 'Locked' FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE ID = $wl_acquirer_thread_id; +--source include/wait_condition.inc # must not "see" the row inserted by the INSERT (as it must run before the # INSERT) --send From 03854661c5efa7381b09167abed0d4d4de0248da Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Jan 2010 09:19:48 +0100 Subject: [PATCH 233/344] Move test from main.trigger to main.trigger_notembedded, as it now depends on INFORMATION_SCHEMA.PROCESSLIST (rather than sleeps) to synchronise. --- mysql-test/r/trigger.result | 27 --------- mysql-test/r/trigger_notembedded.result | 27 +++++++++ mysql-test/t/trigger.test | 72 ------------------------ mysql-test/t/trigger_notembedded.test | 73 +++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 99 deletions(-) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 4476735735c..17a1af9d74b 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1448,33 +1448,6 @@ isave 1 2 drop table t1, t2, t3; -CREATE TABLE t1 (id INTEGER); -CREATE TABLE t2 (id INTEGER); -INSERT INTO t2 VALUES (1),(2); -CREATE TRIGGER t1_test AFTER INSERT ON t1 FOR EACH ROW -INSERT INTO t2 VALUES (new.id); -SELECT GET_LOCK('B26162',120); -GET_LOCK('B26162',120) -1 -SELECT 'rl_acquirer', GET_LOCK('B26162',120), id FROM t2 WHERE id = 1; -SET SESSION LOW_PRIORITY_UPDATES=1; -SET GLOBAL LOW_PRIORITY_UPDATES=1; -INSERT INTO t1 VALUES (5); -SELECT 'rl_contender', id FROM t2 WHERE id > 1; -SELECT RELEASE_LOCK('B26162'); -RELEASE_LOCK('B26162') -1 -rl_acquirer GET_LOCK('B26162',120) id -rl_acquirer 1 1 -SELECT RELEASE_LOCK('B26162'); -RELEASE_LOCK('B26162') -1 -rl_contender id -rl_contender 2 -DROP TRIGGER t1_test; -DROP TABLE t1,t2; -SET SESSION LOW_PRIORITY_UPDATES=DEFAULT; -SET GLOBAL LOW_PRIORITY_UPDATES=DEFAULT; Bug#28502 Triggers that update another innodb table will block on X lock unnecessarily diff --git a/mysql-test/r/trigger_notembedded.result b/mysql-test/r/trigger_notembedded.result index d66308a9bd7..14c499692a8 100644 --- a/mysql-test/r/trigger_notembedded.result +++ b/mysql-test/r/trigger_notembedded.result @@ -445,6 +445,33 @@ DROP TABLE t2; DROP TABLE t1; DROP DATABASE mysqltest_db1; USE test; +CREATE TABLE t1 (id INTEGER); +CREATE TABLE t2 (id INTEGER); +INSERT INTO t2 VALUES (1),(2); +CREATE TRIGGER t1_test AFTER INSERT ON t1 FOR EACH ROW +INSERT INTO t2 VALUES (new.id); +SELECT GET_LOCK('B26162',120); +GET_LOCK('B26162',120) +1 +SELECT 'rl_acquirer', GET_LOCK('B26162',120), id FROM t2 WHERE id = 1; +SET SESSION LOW_PRIORITY_UPDATES=1; +SET GLOBAL LOW_PRIORITY_UPDATES=1; +INSERT INTO t1 VALUES (5); +SELECT 'rl_contender', id FROM t2 WHERE id > 1; +SELECT RELEASE_LOCK('B26162'); +RELEASE_LOCK('B26162') +1 +rl_acquirer GET_LOCK('B26162',120) id +rl_acquirer 1 1 +SELECT RELEASE_LOCK('B26162'); +RELEASE_LOCK('B26162') +1 +rl_contender id +rl_contender 2 +DROP TRIGGER t1_test; +DROP TABLE t1,t2; +SET SESSION LOW_PRIORITY_UPDATES=DEFAULT; +SET GLOBAL LOW_PRIORITY_UPDATES=DEFAULT; End of 5.0 tests. drop table if exists t1; create table t1 (i int); diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 5ee2a854363..57b5431fa1b 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1767,78 +1767,6 @@ drop table t1, t2, t3; disconnect addconroot1; disconnect addconroot2; disconnect addconwithoutdb; -# -# Bug #26162: Trigger DML ignores low_priority_updates setting -# -CREATE TABLE t1 (id INTEGER); -CREATE TABLE t2 (id INTEGER); - -INSERT INTO t2 VALUES (1),(2); - -# trigger that produces the high priority insert, but should be low, adding -# LOW_PRIORITY fixes this -CREATE TRIGGER t1_test AFTER INSERT ON t1 FOR EACH ROW - INSERT INTO t2 VALUES (new.id); - -CONNECT (rl_holder, localhost, root,,); -CONNECT (rl_acquirer, localhost, root,,); -CONNECT (wl_acquirer, localhost, root,,); -CONNECT (rl_contender, localhost, root,,); - -CONNECTION rl_holder; -SELECT GET_LOCK('B26162',120); - -CONNECTION rl_acquirer; -let $rl_acquirer_thread_id = `SELECT @@pseudo_thread_id`; ---send -SELECT 'rl_acquirer', GET_LOCK('B26162',120), id FROM t2 WHERE id = 1; - -CONNECTION wl_acquirer; -let $wl_acquirer_thread_id = `SELECT @@pseudo_thread_id`; -SET SESSION LOW_PRIORITY_UPDATES=1; -SET GLOBAL LOW_PRIORITY_UPDATES=1; -#need to wait for rl_acquirer to lock on the B26162 lock -let $wait_condition= - SELECT STATE = 'User lock' FROM INFORMATION_SCHEMA.PROCESSLIST - WHERE ID = $rl_acquirer_thread_id; ---source include/wait_condition.inc ---send -INSERT INTO t1 VALUES (5); - -CONNECTION rl_contender; -# Wait until wl_acquirer is waiting for the read lock on t2 to be released. -let $wait_condition= - SELECT STATE = 'Locked' FROM INFORMATION_SCHEMA.PROCESSLIST - WHERE ID = $wl_acquirer_thread_id; ---source include/wait_condition.inc -# must not "see" the row inserted by the INSERT (as it must run before the -# INSERT) ---send -SELECT 'rl_contender', id FROM t2 WHERE id > 1; - -CONNECTION rl_holder; -#need to wait for wl_acquirer and rl_contender to lock on t2 -sleep 2; -SELECT RELEASE_LOCK('B26162'); - -CONNECTION rl_acquirer; ---reap -SELECT RELEASE_LOCK('B26162'); -CONNECTION wl_acquirer; ---reap -CONNECTION rl_contender; ---reap - -CONNECTION default; -DISCONNECT rl_acquirer; -DISCONNECT wl_acquirer; -DISCONNECT rl_contender; -DISCONNECT rl_holder; - -DROP TRIGGER t1_test; -DROP TABLE t1,t2; -SET SESSION LOW_PRIORITY_UPDATES=DEFAULT; -SET GLOBAL LOW_PRIORITY_UPDATES=DEFAULT; --echo --echo Bug#28502 Triggers that update another innodb table will block --echo on X lock unnecessarily diff --git a/mysql-test/t/trigger_notembedded.test b/mysql-test/t/trigger_notembedded.test index 7a7e6c6bc85..1dee1db0a3a 100644 --- a/mysql-test/t/trigger_notembedded.test +++ b/mysql-test/t/trigger_notembedded.test @@ -875,6 +875,79 @@ DROP TABLE t1; DROP DATABASE mysqltest_db1; USE test; +# +# Bug #26162: Trigger DML ignores low_priority_updates setting +# +CREATE TABLE t1 (id INTEGER); +CREATE TABLE t2 (id INTEGER); + +INSERT INTO t2 VALUES (1),(2); + +# trigger that produces the high priority insert, but should be low, adding +# LOW_PRIORITY fixes this +CREATE TRIGGER t1_test AFTER INSERT ON t1 FOR EACH ROW + INSERT INTO t2 VALUES (new.id); + +CONNECT (rl_holder, localhost, root,,); +CONNECT (rl_acquirer, localhost, root,,); +CONNECT (wl_acquirer, localhost, root,,); +CONNECT (rl_contender, localhost, root,,); + +CONNECTION rl_holder; +SELECT GET_LOCK('B26162',120); + +CONNECTION rl_acquirer; +let $rl_acquirer_thread_id = `SELECT @@pseudo_thread_id`; +--send +SELECT 'rl_acquirer', GET_LOCK('B26162',120), id FROM t2 WHERE id = 1; + +CONNECTION wl_acquirer; +let $wl_acquirer_thread_id = `SELECT @@pseudo_thread_id`; +SET SESSION LOW_PRIORITY_UPDATES=1; +SET GLOBAL LOW_PRIORITY_UPDATES=1; +#need to wait for rl_acquirer to lock on the B26162 lock +let $wait_condition= + SELECT STATE = 'User lock' FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE ID = $rl_acquirer_thread_id; +--source include/wait_condition.inc +--send +INSERT INTO t1 VALUES (5); + +CONNECTION rl_contender; +# Wait until wl_acquirer is waiting for the read lock on t2 to be released. +let $wait_condition= + SELECT STATE = 'Locked' FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE ID = $wl_acquirer_thread_id; +--source include/wait_condition.inc +# must not "see" the row inserted by the INSERT (as it must run before the +# INSERT) +--send +SELECT 'rl_contender', id FROM t2 WHERE id > 1; + +CONNECTION rl_holder; +#need to wait for wl_acquirer and rl_contender to lock on t2 +sleep 2; +SELECT RELEASE_LOCK('B26162'); + +CONNECTION rl_acquirer; +--reap +SELECT RELEASE_LOCK('B26162'); +CONNECTION wl_acquirer; +--reap +CONNECTION rl_contender; +--reap + +CONNECTION default; +DISCONNECT rl_acquirer; +DISCONNECT wl_acquirer; +DISCONNECT rl_contender; +DISCONNECT rl_holder; + +DROP TRIGGER t1_test; +DROP TABLE t1,t2; +SET SESSION LOW_PRIORITY_UPDATES=DEFAULT; +SET GLOBAL LOW_PRIORITY_UPDATES=DEFAULT; + --echo End of 5.0 tests. # From 71465af9d40b85c38cebdeed393925302003785b Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Tue, 12 Jan 2010 12:41:18 +0100 Subject: [PATCH 234/344] Implement the change of RPM versioning and file naming: - "release" starts from 1 - "level" ("m2", "rc", ...) is included in the RPM version. --- configure.in | 13 ++++++++----- support-files/Makefile.am | 3 ++- support-files/mysql.spec.sh | 14 ++++++++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/configure.in b/configure.in index b206dfbd079..405ebddadbe 100644 --- a/configure.in +++ b/configure.in @@ -30,12 +30,14 @@ NDB_VERSION_STATUS="" # Remember that regexps needs to quote [ and ] since this is run through m4 # We take some made up examples # -# VERSION 5.1.40sp1-alpha 5.0.34a -# MYSQL_NO_DASH_VERSION 5.1.40sp1 5.0.34a -# MYSQL_NUMERIC_VERSION 5.1.40 5.0.34 -# MYSQL_BASE_VERSION 5.1 5.0 -# MYSQL_VERSION_ID 50140 50034 +# VERSION 5.1.40sp1-alpha 5.0.34a 5.5.1-m2 +# MYSQL_U_SCORE_VERSION 5.1.40sp1_alpha 5.0.34a 5.5.1_m2 +# MYSQL_NO_DASH_VERSION 5.1.40sp1 5.0.34a 5.5.1 +# MYSQL_NUMERIC_VERSION 5.1.40 5.0.34 5.5.1 +# MYSQL_BASE_VERSION 5.1 5.0 5.5 +# MYSQL_VERSION_ID 50140 50034 50501 # +MYSQL_U_SCORE_VERSION=`echo $VERSION | sed -e "s|-|_|"` MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|-.*$||"` MYSQL_NUMERIC_VERSION=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|[[a-z]][[a-z0-9]]*$||"` MYSQL_BASE_VERSION=`echo $MYSQL_NUMERIC_VERSION | sed -e "s|\.[[^.]]*$||"` @@ -78,6 +80,7 @@ romanian russian serbian slovak spanish swedish ukrainian" ##### ##### +AC_SUBST(MYSQL_U_SCORE_VERSION) AC_SUBST(MYSQL_NO_DASH_VERSION) AC_SUBST(MYSQL_BASE_VERSION) AC_SUBST(MYSQL_VERSION_ID) diff --git a/support-files/Makefile.am b/support-files/Makefile.am index b9d6fde742a..4cb8bb4645d 100644 --- a/support-files/Makefile.am +++ b/support-files/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2000-2001, 2003-2006 MySQL AB +# Copyright (C) 2000-2006 MySQL AB, 2008-2010 Sun Microsystems, Inc. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public @@ -104,6 +104,7 @@ SUFFIXES = .sh -e 's!@''SHARED_LIB_VERSION''@!@SHARED_LIB_VERSION@!' \ -e 's!@''MYSQL_BASE_VERSION''@!@MYSQL_BASE_VERSION@!' \ -e 's!@''MYSQL_NO_DASH_VERSION''@!@MYSQL_NO_DASH_VERSION@!' \ + -e 's!@''MYSQL_U_SCORE_VERSION''@!@MYSQL_U_SCORE_VERSION@!' \ -e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \ -e 's!@''PERL_DBI_VERSION''@!@PERL_DBI_VERSION@!' \ -e 's!@''PERL_DBD_VERSION''@!@PERL_DBD_VERSION@!' \ diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 584c0abc777..98f715da94d 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -1,4 +1,4 @@ -# Copyright (C) 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +# Copyright (C) 2000-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -28,9 +28,9 @@ %{!?_with_yassl:%define YASSL_BUILD 0} %if %{STATIC_BUILD} -%define release 0 +%define release 1 %else -%define release 0.glibc23 +%define release 1.glibc23 %endif %define license GPL %define mysqld_user mysql @@ -64,7 +64,7 @@ Name: MySQL Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases -Version: @MYSQL_NO_DASH_VERSION@ +Version: @MYSQL_U_SCORE_VERSION@ Release: %{release} License: %{license} Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/mysql-%{mysql_version}.tar.gz @@ -818,6 +818,12 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Mon Jan 11 2010 Joerg Bruehe + +- Change RPM file naming: + - Suffix like "-m2", "-rc" becomes part of version as "_m2", "_rc". + - Release counts from 1, not 0. + * Fri Nov 07 2008 Joerg Bruehe - Correct yesterday's fix, so that it also works for the last flag. From c8b5804f295ea109f56f29de8c350133f9070a6a Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Tue, 12 Jan 2010 15:16:26 +0100 Subject: [PATCH 235/344] Bug#48157: crash in Item_field::used_tables MySQL handles the join syntax "JOIN ... USING( field1, ... )" and natural joins by building the same parse tree as a corresponding join with an "ON t1.field1 = t2.field1 ..." expression would produce. This parse tree was not cleaned up properly in the following scenario. If a thread tries to lock some tables and finds that the tables were dropped and re-created while waiting for the lock, it cleans up column references in the statement by means a per-statement free list. But if the statement was part of a stored procedure, column references on the stored procedure's free list weren't cleaned up and thus contained pointers to freed objects. Fixed by adding a call to clean up the current prepared statement's free list. mysql-test/r/sp_sync.result: Bug#48157: Test case mysql-test/t/sp_sync.test: Bug#48157: Test result sql/item.h: Bug#48157: Commented field. sql/sql_parse.cc: Bug#48157: Commented function. sql/sql_update.cc: Bug#48157: fix --- mysql-test/r/sp_sync.result | 23 ++++++++++++++++ mysql-test/t/sp_sync.test | 55 +++++++++++++++++++++++++++++++++++++ sql/item.h | 7 +++++ sql/sql_parse.cc | 6 ++-- sql/sql_update.cc | 6 +++- 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 mysql-test/r/sp_sync.result create mode 100644 mysql-test/t/sp_sync.test diff --git a/mysql-test/r/sp_sync.result b/mysql-test/r/sp_sync.result new file mode 100644 index 00000000000..afa37e70531 --- /dev/null +++ b/mysql-test/r/sp_sync.result @@ -0,0 +1,23 @@ +Tests of syncronization of stored procedure execution. +# +# Bug#48157: crash in Item_field::used_tables +# +CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b; +CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b; +CREATE PROCEDURE p1() +BEGIN +UPDATE t1 JOIN t2 USING( a, b ) SET t1.b = 1, t2.b = 1; +END| +LOCK TABLES t1 WRITE, t2 WRITE; +SET DEBUG_SYNC = 'multi_update_reopen_tables SIGNAL parked WAIT_FOR go'; +CALL p1(); +DROP TABLE t1, t2; +SET DEBUG_SYNC = 'now WAIT_FOR parked'; +CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b; +CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b; +SET DEBUG_SYNC = 'now SIGNAL go'; +# Without the DEBUG_SYNC supplied in the same patch as this test in the +# code, this test statement will hang. +DROP TABLE t1, t2; +DROP PROCEDURE p1; +SET DEBUG_SYNC = 'RESET'; diff --git a/mysql-test/t/sp_sync.test b/mysql-test/t/sp_sync.test new file mode 100644 index 00000000000..98903989cd5 --- /dev/null +++ b/mysql-test/t/sp_sync.test @@ -0,0 +1,55 @@ +--echo Tests of syncronization of stored procedure execution. + +--source include/have_debug_sync.inc + +--echo # +--echo # Bug#48157: crash in Item_field::used_tables +--echo # + +CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b; +CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b; + +DELIMITER |; + +CREATE PROCEDURE p1() +BEGIN + UPDATE t1 JOIN t2 USING( a, b ) SET t1.b = 1, t2.b = 1; +END| + +DELIMITER ;| + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); + +connection con1; +LOCK TABLES t1 WRITE, t2 WRITE; + +connection con2; +LET $ID= `select connection_id()`; +SET DEBUG_SYNC = 'multi_update_reopen_tables SIGNAL parked WAIT_FOR go'; +--send CALL p1() + +connection con1; +let $wait_condition= SELECT 1 FROM information_schema.processlist WHERE ID = $ID AND +state = "Locked"; +--source include/wait_condition.inc +DROP TABLE t1, t2; +SET DEBUG_SYNC = 'now WAIT_FOR parked'; +CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b; +CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b; +SET DEBUG_SYNC = 'now SIGNAL go'; + +connection con2; +--reap + +disconnect con1; +disconnect con2; +connection default; + +--echo # Without the DEBUG_SYNC supplied in the same patch as this test in the +--echo # code, this test statement will hang. +DROP TABLE t1, t2; +DROP PROCEDURE p1; + +SET DEBUG_SYNC = 'RESET'; + diff --git a/sql/item.h b/sql/item.h index 8f0e5874f3f..88e90924fcc 100644 --- a/sql/item.h +++ b/sql/item.h @@ -506,6 +506,13 @@ public: char * name; /* Name from select */ /* Original item name (if it was renamed)*/ char * orig_name; + /** + Intrusive list pointer for free list. If not null, points to the next + Item on some Query_arena's free list. For instance, stored procedures + have their own Query_arena's. + + @see Query_arena::free_list + */ Item *next; uint32 max_length; uint name_length; /* Length of name */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 69c9ddc7806..48743a2d48f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -615,8 +615,10 @@ void free_items(Item *item) DBUG_VOID_RETURN; } -/* This works because items are allocated with sql_alloc() */ - +/** + This works because items are allocated with sql_alloc(). + @note The function also handles null pointers (empty list). +*/ void cleanup_items(Item *item) { DBUG_ENTER("cleanup_items"); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c988d746500..26f40c7fa9f 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -23,6 +23,7 @@ #include "sql_select.h" #include "sp_head.h" #include "sql_trigger.h" +#include "debug_sync.h" /* Return 0 if row hasn't changed */ @@ -1143,8 +1144,11 @@ reopen_tables: items from 'fields' list, so the cleanup above is necessary to. */ cleanup_items(thd->free_list); - + cleanup_items(thd->stmt_arena->free_list); close_tables_for_reopen(thd, &table_list); + + DEBUG_SYNC(thd, "multi_update_reopen_tables"); + goto reopen_tables; } From 2cc3fc27139e9710855a1d2e7d52da8ab3b444b5 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Tue, 12 Jan 2010 19:31:11 +0200 Subject: [PATCH 236/344] Merged patch from Percona to get proper fix for compilation issue of srv0srv.c on Solaris sql/sql_cache.cc: Fixed wrong comment --- sql/sql_cache.cc | 4 ++-- storage/xtradb/srv/srv0srv.c | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index f995b51ae68..a093f42d165 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1306,8 +1306,8 @@ end: to the user. RESULTS - 1 Query was not cached. - 0 The query was cached and user was sent the result. + 0 Query was not cached. + 1 The query was cached and user was sent the result. -1 The query was cached but we didn't have rights to use it. No error is sent to the client yet. diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index acd3386d863..76f3fc5097d 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -81,7 +81,6 @@ Created 10/8/1995 Heikki Tuuri #include "ut0mem.h" #include "ut0ut.h" #include "os0proc.h" -#include "os0sync.h" #include "mem0mem.h" #include "mem0pool.h" #include "sync0sync.h" @@ -103,6 +102,10 @@ Created 10/8/1995 Heikki Tuuri #include "row0mysql.h" #include "ha_prototypes.h" #include "trx0i_s.h" +#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */ + +/* prototypes for new functions added to ha_innodb.cc */ +ibool innobase_get_slow_log(); /* This is set to TRUE if the MySQL user has set it in MySQL; currently affects only FOREIGN KEY definition parsing */ @@ -162,6 +165,7 @@ UNIV_INTERN ulint* srv_data_file_sizes = NULL; UNIV_INTERN ibool srv_extra_undoslots = FALSE; UNIV_INTERN ibool srv_fast_recovery = FALSE; +UNIV_INTERN ibool srv_recovery_stats = FALSE; UNIV_INTERN ibool srv_use_purge_thread = FALSE; @@ -1077,7 +1081,7 @@ UNIV_INTERN ulong srv_max_purge_lag = 0; Puts an OS thread to wait if there are too many concurrent threads (>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */ -#ifdef INNODB_RW_LOCKS_USE_ATOMICS +#ifdef HAVE_ATOMIC_BUILTINS static void enter_innodb_with_tickets(trx_t* trx) { @@ -1175,7 +1179,7 @@ srv_conc_enter_innodb( return; } -#ifdef INNODB_RW_LOCKS_USE_ATOMICS +#ifdef HAVE_ATOMIC_BUILTINS if (srv_thread_concurrency_timer_based) { srv_conc_enter_innodb_timer_based(trx); return; @@ -1325,7 +1329,7 @@ srv_conc_force_enter_innodb( } ut_ad(srv_conc_n_threads >= 0); -#ifdef INNODB_RW_LOCKS_USE_ATOMICS +#ifdef HAVE_ATOMIC_BUILTINS if (srv_thread_concurrency_timer_based) { os_atomic_increment_lint(&srv_conc_n_threads, 1); trx->declared_to_be_inside_innodb = TRUE; @@ -1366,7 +1370,7 @@ srv_conc_force_exit_innodb( return; } -#ifdef INNODB_RW_LOCKS_USE_ATOMICS +#ifdef HAVE_ATOMIC_BUILTINS if (srv_thread_concurrency_timer_based) { srv_conc_exit_innodb_timer_based(trx); return; From 71fd38e488d1d10210c9c5370f56d682d9884814 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Wed, 13 Jan 2010 08:16:36 +0400 Subject: [PATCH 237/344] Bug #50096: CONCAT_WS inside procedure returning wrong data Selecting of the CONCAT_WS(......) result into a user variable may return wrong data. Item_func_concat_ws::val_str contains a number of memory allocation-saving optimization tricks. After the fix for bug 46815 the control flow has been changed to a branch that is commented as "This is quite uncommon!": one of places where we are trying to concatenate strings inplace. However, that "uncommon" place didn't care about PS parameters, that have another trick in Item_sp_variable::val_str(): they use the intermediate Item_sp_variable::str_value field, where they may store a reference to an external argument's buffer. The Item_func_concat_ws::val_str function has been modified to take into account val_str functions (such as Item_sp_variable::val_str) that return a pointer to an internal Item member variable that may reference to a buffer provided. mysql-test/r/func_concat.result: Added test case for bug #50096. mysql-test/t/func_concat.test: Added test case for bug #50096. sql/item_strfunc.cc: Bug #50096: CONCAT_WS inside procedure returning wrong data The Item_func_concat_ws::val_str function has been modified to take into account val_str functions (such as Item_sp_variable::val_str) that return a pointer to an internal Item member variable that may reference to a buffer provided. --- mysql-test/r/func_concat.result | 11 +++++++++++ mysql-test/t/func_concat.test | 13 +++++++++++++ sql/item_strfunc.cc | 4 ++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_concat.result b/mysql-test/r/func_concat.result index 75b4888fbb2..c4c2b46c6c2 100644 --- a/mysql-test/r/func_concat.result +++ b/mysql-test/r/func_concat.result @@ -1,4 +1,5 @@ DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; CREATE TABLE t1 ( number INT NOT NULL, alpha CHAR(6) NOT NULL ); INSERT INTO t1 VALUES (1413006,'idlfmv'), (1413065,'smpsfz'),(1413127,'sljrhx'),(1413304,'qerfnd'); @@ -119,4 +120,14 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index NULL PRIMARY 102 NULL 3 Using index 1 SIMPLE t1 eq_ref PRIMARY,a PRIMARY 318 func,const,const 1 DROP TABLE t1, t2; +# +# Bug #50096: CONCAT_WS inside procedure returning wrong data +# +CREATE PROCEDURE p1(a varchar(255), b int, c int) +SET @query = CONCAT_WS(",", a, b, c); +CALL p1("abcde", "0", "1234"); +SELECT @query; +@query +abcde,0,1234 +DROP PROCEDURE p1; # End of 5.1 tests diff --git a/mysql-test/t/func_concat.test b/mysql-test/t/func_concat.test index 1c7e5823fb2..e24b4354b61 100644 --- a/mysql-test/t/func_concat.test +++ b/mysql-test/t/func_concat.test @@ -4,6 +4,7 @@ --disable_warnings DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; --enable_warnings CREATE TABLE t1 ( number INT NOT NULL, alpha CHAR(6) NOT NULL ); @@ -111,4 +112,16 @@ EXPLAIN SELECT CONCAT('gui_', t2.a), t1.d FROM t2 DROP TABLE t1, t2; +--echo # +--echo # Bug #50096: CONCAT_WS inside procedure returning wrong data +--echo # + +CREATE PROCEDURE p1(a varchar(255), b int, c int) + SET @query = CONCAT_WS(",", a, b, c); + +CALL p1("abcde", "0", "1234"); +SELECT @query; + +DROP PROCEDURE p1; + --echo # End of 5.1 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index b6d3f45f4c2..ecd839d8378 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -677,8 +677,8 @@ String *Item_func_concat_ws::val_str(String *str) res->length() + sep_str->length() + res2->length()) { /* We have room in str; We can't get any errors here */ - if (str == res2) - { // This is quote uncommon! + if (str->ptr() == res2->ptr()) + { // This is quite uncommon! str->replace(0,0,*sep_str); str->replace(0,0,*res); } From 495810cd1f8ceb19e7126daa5ab92660c8f942b0 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Wed, 13 Jan 2010 09:20:45 +0400 Subject: [PATCH 238/344] Fix for bug#50227: Pre-auth buffer-overflow in mySQL through yaSSL Problem: copying issuer's (or subject's) name tags into an internal buffer from incoming stream we didn't check the buffer overflow. That may lead to memory overrun, crash etc. Fix: ensure we don't overrun the buffer. Note: there's no simple test case (exploit needed). extra/yassl/taocrypt/include/asn.hpp: Fix for bug#50227: Pre-auth buffer-overflow in mySQL through yaSSL - CertDecoder::AddTag() introduced. extra/yassl/taocrypt/src/asn.cpp: Fix for bug#50227: Pre-auth buffer-overflow in mySQL through yaSSL - copying data from incoming stream to the issuer_ or subject_ buffers ensure we don't overrun them. - code cleanup. --- extra/yassl/taocrypt/include/asn.hpp | 1 + extra/yassl/taocrypt/src/asn.cpp | 123 +++++++++++++++------------ 2 files changed, 69 insertions(+), 55 deletions(-) diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp index 1c1850cb47e..168b8a8c755 100644 --- a/extra/yassl/taocrypt/include/asn.hpp +++ b/extra/yassl/taocrypt/include/asn.hpp @@ -305,6 +305,7 @@ private: bool ValidateSignature(SignerList*); bool ConfirmSignature(Source&); void GetKey(); + char* AddTag(char*, const char*, const char*, word32, word32); void GetName(NameType); void GetValidity(); void GetDate(DateType); diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index 78200841bda..f87b466502e 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -652,6 +652,23 @@ word32 CertDecoder::GetDigest() } +char *CertDecoder::AddTag(char *ptr, const char *buf_end, + const char *tag_name, word32 tag_name_length, + word32 tag_value_length) +{ + if (ptr + tag_name_length + tag_value_length > buf_end) + return 0; + + memcpy(ptr, tag_name, tag_name_length); + ptr+= tag_name_length; + + memcpy(ptr, source_.get_current(), tag_value_length); + ptr+= tag_value_length; + + return ptr; +} + + // process NAME, either issuer or subject void CertDecoder::GetName(NameType nt) { @@ -659,11 +676,21 @@ void CertDecoder::GetName(NameType nt) SHA sha; word32 length = GetSequence(); // length of all distinguished names - assert (length < ASN_NAME_MAX); + + if (length >= ASN_NAME_MAX) + goto err; length += source_.get_index(); - char* ptr = (nt == ISSUER) ? issuer_ : subject_; - word32 idx = 0; + char *ptr, *buf_end; + + if (nt == ISSUER) { + ptr= issuer_; + buf_end= ptr + sizeof(issuer_) - 1; // 1 byte for trailing 0 + } + else { + ptr= subject_; + buf_end= ptr + sizeof(subject_) - 1; // 1 byte for trailing 0 + } while (source_.get_index() < length) { GetSet(); @@ -685,47 +712,36 @@ void CertDecoder::GetName(NameType nt) byte id = source_.next(); b = source_.next(); // strType word32 strLen = GetLength(source_); - bool copy = false; - if (id == COMMON_NAME) { - memcpy(&ptr[idx], "/CN=", 4); - idx += 4; - copy = true; - } - else if (id == SUR_NAME) { - memcpy(&ptr[idx], "/SN=", 4); - idx += 4; - copy = true; - } - else if (id == COUNTRY_NAME) { - memcpy(&ptr[idx], "/C=", 3); - idx += 3; - copy = true; - } - else if (id == LOCALITY_NAME) { - memcpy(&ptr[idx], "/L=", 3); - idx += 3; - copy = true; - } - else if (id == STATE_NAME) { - memcpy(&ptr[idx], "/ST=", 4); - idx += 4; - copy = true; - } - else if (id == ORG_NAME) { - memcpy(&ptr[idx], "/O=", 3); - idx += 3; - copy = true; - } - else if (id == ORGUNIT_NAME) { - memcpy(&ptr[idx], "/OU=", 4); - idx += 4; - copy = true; - } - - if (copy) { - memcpy(&ptr[idx], source_.get_current(), strLen); - idx += strLen; + switch (id) { + case COMMON_NAME: + if (!(ptr= AddTag(ptr, buf_end, "/CN=", 4, strLen))) + goto err; + break; + case SUR_NAME: + if (!(ptr= AddTag(ptr, buf_end, "/SN=", 4, strLen))) + goto err; + break; + case COUNTRY_NAME: + if (!(ptr= AddTag(ptr, buf_end, "/C=", 3, strLen))) + goto err; + break; + case LOCALITY_NAME: + if (!(ptr= AddTag(ptr, buf_end, "/L=", 3, strLen))) + goto err; + break; + case STATE_NAME: + if (!(ptr= AddTag(ptr, buf_end, "/ST=", 4, strLen))) + goto err; + break; + case ORG_NAME: + if (!(ptr= AddTag(ptr, buf_end, "/O=", 3, strLen))) + goto err; + break; + case ORGUNIT_NAME: + if (!(ptr= AddTag(ptr, buf_end, "/OU=", 4, strLen))) + goto err; + break; } sha.Update(source_.get_current(), strLen); @@ -739,23 +755,20 @@ void CertDecoder::GetName(NameType nt) source_.advance(oidSz + 1); word32 length = GetLength(source_); - if (email) { - memcpy(&ptr[idx], "/emailAddress=", 14); - idx += 14; - - memcpy(&ptr[idx], source_.get_current(), length); - idx += length; - } + if (email && !(ptr= AddTag(ptr, buf_end, "/emailAddress=", 14, length))) + goto err; source_.advance(length); } } - ptr[idx++] = 0; + *ptr= 0; - if (nt == ISSUER) - sha.Final(issuerHash_); - else - sha.Final(subjectHash_); + sha.Final(nt == ISSUER ? issuerHash_ : subjectHash_); + + return; + +err: + source_.SetError(CONTENT_E); } From 4dc7be62a997a0176e300878d4b5e93865606029 Mon Sep 17 00:00:00 2001 From: Sven Sandberg Date: Wed, 13 Jan 2010 10:00:03 +0100 Subject: [PATCH 239/344] BUG#49222: Mark RAND() as unsafe Problem: When RAND() is binlogged in statement mode, the seed is binlogged too, so the replication slave generates the same sequence of random numbers. This makes replication work in many cases, but not in all cases: the order of rows is not guaranteed for, e.g., UPDATE or INSERT...SELECT statements, so the row data will be different if master and slave retrieve the rows in different orders. Fix: Mark RAND() as unsafe. It will generate a warning if binlog_format=STATEMENT and switch to row-logging if binlog_format=ROW. mysql-test/extra/rpl_tests/rpl_row_func003.test: updated test case to ignore new warnings mysql-test/suite/binlog/r/binlog_unsafe.result: updated result file mysql-test/suite/binlog/t/binlog_unsafe.test: Added test for RAND(). Also clarified some old comments. mysql-test/suite/rpl/r/rpl_misc_functions.result: updated result file mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result: updated test case to ignore new warnings mysql-test/suite/rpl/r/rpl_optimize.result: updated result file mysql-test/suite/rpl/r/rpl_row_func003.result: updated result file mysql-test/suite/rpl/t/rpl_misc_functions.test: updated test case to ignore new warnings mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test: updated test case to ignore new warnings mysql-test/suite/rpl/t/rpl_optimize.test: updated test case to ignore new warnings mysql-test/suite/rpl/t/rpl_trigger.test: updated test case to ignore new warnings mysql-test/suite/rpl_ndb/r/rpl_ndb_func003.result: updated result file sql/item_create.cc: Mark RAND() unsafe. --- .../extra/rpl_tests/rpl_row_func003.test | 6 +++++ .../suite/binlog/r/binlog_unsafe.result | 3 +++ mysql-test/suite/binlog/t/binlog_unsafe.test | 24 +++++++++++-------- .../suite/rpl/r/rpl_misc_functions.result | 1 + .../r/rpl_nondeterministic_functions.result | 1 + mysql-test/suite/rpl/r/rpl_optimize.result | 1 + mysql-test/suite/rpl/r/rpl_row_func003.result | 1 + .../suite/rpl/t/rpl_misc_functions.test | 8 +++++++ .../rpl/t/rpl_nondeterministic_functions.test | 4 ++++ mysql-test/suite/rpl/t/rpl_optimize.test | 4 +++- mysql-test/suite/rpl/t/rpl_trigger.test | 2 ++ .../suite/rpl_ndb/r/rpl_ndb_func003.result | 1 + sql/item_create.cc | 10 ++++++++ 13 files changed, 55 insertions(+), 11 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_row_func003.test b/mysql-test/extra/rpl_tests/rpl_row_func003.test index 8ee2d863527..b77465de39e 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_func003.test +++ b/mysql-test/extra/rpl_tests/rpl_row_func003.test @@ -18,6 +18,8 @@ # Vs slave. # ############################################################################# +CALL mtr.add_suppression('Statement may not be safe to log in statement format.'); + # Begin clean up test section connection master; --disable_warnings @@ -43,10 +45,12 @@ RETURN tmp; END| delimiter ;| +--disable_warnings INSERT INTO test.t1 VALUES (null,test.f1()),(null,test.f1()),(null,test.f1()); sleep 6; INSERT INTO test.t1 VALUES (null,test.f1()),(null,test.f1()),(null,test.f1()); sleep 6; +--enable_warnings #Select in this test are used for debugging #select * from test.t1; @@ -56,7 +60,9 @@ sleep 6; connection master; SET AUTOCOMMIT=0; START TRANSACTION; +--disable_warnings INSERT INTO test.t1 VALUES (null,test.f1()); +--enable_warnings ROLLBACK; SET AUTOCOMMIT=1; #select * from test.t1; diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result index 8bbf993a727..6b2a83c9483 100644 --- a/mysql-test/suite/binlog/r/binlog_unsafe.result +++ b/mysql-test/suite/binlog/r/binlog_unsafe.result @@ -379,6 +379,9 @@ Note 1592 Statement may not be safe to log in statement format. INSERT INTO t1 VALUES (VERSION()); Warnings: Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t1 VALUES (RAND()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. DELETE FROM t1; SET TIMESTAMP=1000000; INSERT INTO t1 VALUES diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test index 1acb4d090ca..5e399f3e602 100644 --- a/mysql-test/suite/binlog/t/binlog_unsafe.test +++ b/mysql-test/suite/binlog/t/binlog_unsafe.test @@ -47,6 +47,8 @@ # BUG#34768: nondeterministic INSERT using LIMIT logged in stmt mode if binlog_format=mixed # BUG#41980, SBL, INSERT .. SELECT .. LIMIT = ERROR, even when @@SQL_LOG_BIN is 0 # BUG#42640: mysqld crashes when unsafe statements are executed (STRICT_TRANS_TABLES mode) +# BUG#47995: Mark user functions as unsafe +# BUG#49222: Mare RAND() unsafe # # ==== Related test cases ==== # @@ -391,6 +393,7 @@ SET @@SESSION.SQL_MODE = @save_sql_mode; # # BUG#47995: Mark user functions as unsafe +# BUG#49222: Mare RAND() unsafe # # Test that the system functions that are supposed to be marked unsafe # generate a warning. Each INSERT statement below should generate a @@ -400,27 +403,28 @@ SET @@SESSION.SQL_MODE = @save_sql_mode; CREATE TABLE t1 (a VARCHAR(1000)); INSERT INTO t1 VALUES (CURRENT_USER()); #marked unsafe before BUG#47995 INSERT INTO t1 VALUES (FOUND_ROWS()); #marked unsafe before BUG#47995 -INSERT INTO t1 VALUES (GET_LOCK('tmp', 1)); -INSERT INTO t1 VALUES (IS_FREE_LOCK('tmp')); -INSERT INTO t1 VALUES (IS_USED_LOCK('tmp')); -INSERT INTO t1 VALUES (LOAD_FILE('../../std_data/words2.dat')); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (GET_LOCK('tmp', 1)); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (IS_FREE_LOCK('tmp')); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (IS_USED_LOCK('tmp')); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (LOAD_FILE('../../std_data/words2.dat')); #marked unsafe in BUG#39701 INSERT INTO t1 VALUES (MASTER_POS_WAIT('dummy arg', 4711, 1)); -INSERT INTO t1 VALUES (RELEASE_LOCK('tmp')); +INSERT INTO t1 VALUES (RELEASE_LOCK('tmp')); #marked unsafe in BUG#47995 INSERT INTO t1 VALUES (ROW_COUNT()); #marked unsafe before BUG#47995 INSERT INTO t1 VALUES (SESSION_USER()); #marked unsafe before BUG#47995 -INSERT INTO t1 VALUES (SLEEP(1)); -INSERT INTO t1 VALUES (SYSDATE()); +INSERT INTO t1 VALUES (SLEEP(1)); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (SYSDATE()); #marked unsafe in BUG#47995 INSERT INTO t1 VALUES (SYSTEM_USER()); #marked unsafe before BUG#47995 INSERT INTO t1 VALUES (USER()); #marked unsafe before BUG#47995 INSERT INTO t1 VALUES (UUID()); #marked unsafe before BUG#47995 INSERT INTO t1 VALUES (UUID_SHORT()); #marked unsafe before BUG#47995 -INSERT INTO t1 VALUES (VERSION()); +INSERT INTO t1 VALUES (VERSION()); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (RAND()); #marked unsafe in BUG#49222 DELETE FROM t1; # Since we replicate the TIMESTAMP variable, functions affected by the # TIMESTAMP variable are safe to replicate. So we check that the -# following following functions depend on the TIMESTAMP variable and -# don't generate a warning. +# following following functions that depend on the TIMESTAMP variable +# are not unsafe and don't generate a warning. SET TIMESTAMP=1000000; INSERT INTO t1 VALUES diff --git a/mysql-test/suite/rpl/r/rpl_misc_functions.result b/mysql-test/suite/rpl/r/rpl_misc_functions.result index 28b777822e4..6d69235927e 100644 --- a/mysql-test/suite/rpl/r/rpl_misc_functions.result +++ b/mysql-test/suite/rpl/r/rpl_misc_functions.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CALL mtr.add_suppression('Statement may not be safe to log in statement format.'); create table t1(id int, i int, r1 int, r2 int, p varchar(100)); insert into t1 values(1, connection_id(), 0, 0, ""); insert into t1 values(2, 0, rand()*1000, rand()*1000, ""); diff --git a/mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result b/mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result index c4842a284cd..3b9b741e040 100644 --- a/mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result +++ b/mysql-test/suite/rpl/r/rpl_nondeterministic_functions.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CALL mtr.add_suppression('Statement may not be safe to log in statement format.'); CREATE TABLE t1 (a VARCHAR(1000)); INSERT INTO t1 VALUES (CONNECTION_ID()); INSERT INTO t1 VALUES (CONNECTION_ID()); diff --git a/mysql-test/suite/rpl/r/rpl_optimize.result b/mysql-test/suite/rpl/r/rpl_optimize.result index 79891169fbc..1ae94a3ca36 100644 --- a/mysql-test/suite/rpl/r/rpl_optimize.result +++ b/mysql-test/suite/rpl/r/rpl_optimize.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CALL mtr.add_suppression('Statement may not be safe to log in statement format.'); create table t1 (a int not null auto_increment primary key, b int, key(b)); INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); INSERT INTO t1 (a) SELECT null FROM t1; diff --git a/mysql-test/suite/rpl/r/rpl_row_func003.result b/mysql-test/suite/rpl/r/rpl_row_func003.result index a5fd46a2ce3..94d01b50ce5 100644 --- a/mysql-test/suite/rpl/r/rpl_row_func003.result +++ b/mysql-test/suite/rpl/r/rpl_row_func003.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CALL mtr.add_suppression('Statement may not be safe to log in statement format.'); DROP FUNCTION IF EXISTS test.f1; DROP TABLE IF EXISTS test.t1; CREATE TABLE test.t1 (a INT NOT NULL AUTO_INCREMENT, c CHAR(16),PRIMARY KEY(a))ENGINE=INNODB; diff --git a/mysql-test/suite/rpl/t/rpl_misc_functions.test b/mysql-test/suite/rpl/t/rpl_misc_functions.test index d2e61d579e3..b84042160cd 100644 --- a/mysql-test/suite/rpl/t/rpl_misc_functions.test +++ b/mysql-test/suite/rpl/t/rpl_misc_functions.test @@ -3,12 +3,16 @@ # source include/master-slave.inc; +CALL mtr.add_suppression('Statement may not be safe to log in statement format.'); + create table t1(id int, i int, r1 int, r2 int, p varchar(100)); insert into t1 values(1, connection_id(), 0, 0, ""); # don't put rand and password in the same query, to see if they replicate # independently # Pure rand test +--disable_warnings insert into t1 values(2, 0, rand()*1000, rand()*1000, ""); +--enable_warnings # change the rand suite on the master (we do this because otherwise password() # benefits from the fact that the above rand() is well replicated : # it picks the same sequence element, which hides a possible bug in password() replication. @@ -19,7 +23,9 @@ set sql_log_bin=1; # Pure password test insert into t1 values(3, 0, 0, 0, password('does_this_work?')); # "altogether now" +--disable_warnings insert into t1 values(4, connection_id(), rand()*1000, rand()*1000, password('does_this_still_work?')); +--enable_warnings select * into outfile 'rpl_misc_functions.outfile' from t1; let $MYSQLD_DATADIR= `select @@datadir`; sync_slave_with_master; @@ -73,11 +79,13 @@ DELIMITER ;| # Exercise the functions and procedures then compare the results on # the master to those on the slave. +--disable_warnings CALL test_replication_sp1(); CALL test_replication_sp2(); INSERT INTO t1 (col_a) VALUES (test_replication_sf()); INSERT INTO t1 (col_a) VALUES (test_replication_sf()); INSERT INTO t1 (col_a) VALUES (test_replication_sf()); +--enable_warnings --sync_slave_with_master diff --git a/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test b/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test index a30eb3be374..9ff2e2d081e 100644 --- a/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test +++ b/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test @@ -17,6 +17,8 @@ --source include/master-slave.inc +CALL mtr.add_suppression('Statement may not be safe to log in statement format.'); + CREATE TABLE t1 (a VARCHAR(1000)); # We replicate the connection_id in the query_log_event @@ -41,7 +43,9 @@ INSERT INTO t1 VALUES (UTC_TIMESTAMP()); # We replicate the random seed in a rand_log_event +--disable_warnings INSERT INTO t1 VALUES (RAND()); +--enable_warnings # We replicate the last_insert_id in an intvar_log_event INSERT INTO t1 VALUES (LAST_INSERT_ID()); diff --git a/mysql-test/suite/rpl/t/rpl_optimize.test b/mysql-test/suite/rpl/t/rpl_optimize.test index f4582ba1167..87eb9dce818 100644 --- a/mysql-test/suite/rpl/t/rpl_optimize.test +++ b/mysql-test/suite/rpl/t/rpl_optimize.test @@ -13,6 +13,8 @@ -- source include/not_ndb_default.inc -- source include/master-slave.inc +CALL mtr.add_suppression('Statement may not be safe to log in statement format.'); + create table t1 (a int not null auto_increment primary key, b int, key(b)); INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); INSERT INTO t1 (a) SELECT null FROM t1; @@ -30,8 +32,8 @@ INSERT INTO t1 (a) SELECT null FROM t1; INSERT INTO t1 (a) SELECT null FROM t1; save_master_pos; # a few updates to force OPTIMIZE to do something -update t1 set b=(a/2*rand()); --disable_warnings +update t1 set b=(a/2*rand()); delete from t1 order by b limit 10000; --enable_warnings diff --git a/mysql-test/suite/rpl/t/rpl_trigger.test b/mysql-test/suite/rpl/t/rpl_trigger.test index 4b40fbea719..e296da01bad 100644 --- a/mysql-test/suite/rpl/t/rpl_trigger.test +++ b/mysql-test/suite/rpl/t/rpl_trigger.test @@ -40,10 +40,12 @@ insert into t3 values(100,"log",0,0,0); SET @@RAND_SEED1=658490765, @@RAND_SEED2=635893186; # Emulate that we have rows 2-9 deleted on the slave +--disable_warnings insert into t1 values(1,1,rand()),(NULL,2,rand()); insert into t2 (b) values(last_insert_id()); insert into t2 values(3,0),(NULL,0); insert into t2 values(NULL,0),(500,0); +--enable_warnings select a,b, truncate(rand_value,4) from t1; select * from t2; diff --git a/mysql-test/suite/rpl_ndb/r/rpl_ndb_func003.result b/mysql-test/suite/rpl_ndb/r/rpl_ndb_func003.result index ad72a3fb244..7e750f2ce2a 100644 --- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_func003.result +++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_func003.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CALL mtr.add_suppression('Statement may not be safe to log in statement format.'); DROP FUNCTION IF EXISTS test.f1; DROP TABLE IF EXISTS test.t1; CREATE TABLE test.t1 (a INT NOT NULL AUTO_INCREMENT, c CHAR(16),PRIMARY KEY(a))ENGINE=NDB; diff --git a/sql/item_create.cc b/sql/item_create.cc index 53aa8081da1..c309ccc06ca 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -4178,6 +4178,16 @@ Create_func_rand::create_native(THD *thd, LEX_STRING name, if (item_list != NULL) arg_count= item_list->elements; + /* + When RAND() is binlogged, the seed is binlogged too. So the + sequence of random numbers is the same on a replication slave as + on the master. However, if several RAND() values are inserted + into a table, the order in which the rows are modified may differ + between master and slave, because the order is undefined. Hence, + the statement is unsafe to log in statement format. + */ + thd->lex->set_stmt_unsafe(); + switch (arg_count) { case 0: { From c4ec2de72413235d5f4027758d9601b74223b01c Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 13 Jan 2010 12:43:07 +0200 Subject: [PATCH 240/344] version change --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index f044f8e62da..e613cefc614 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.1" +tree_name = "mysql-5.1-bugteam" From b3dd4d9486ca00e555823f81185fe9db83a44db5 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Wed, 13 Jan 2010 12:39:00 +0100 Subject: [PATCH 241/344] Bug#33982 debug assertion and crash reloading grant tables after sighup or kill In certain rare cases when a process was interrupted during a FLUSH PRIVILEGES operation the diagnostic area would be set to an error state but the function responsible for the operation would still signal success. This would lead to a debug assertion error later on when the server would attempt to reset the DA before sending the error message. This patch fixes the issue by assuring that reload_acl_and_cache() always fails if an error condition is raised. The second issue was that a KILL could cause a console error message which referred to a DA state without first making sure that such a state existed. This patch fixes this issue in two different palces by first checking DA state before fetching the error message. sql/sql_acl.cc: * Make sure that there is an error to print before attempting to do so. * Minor style change: change 1 to TRUE for clarity. sql/sql_parse.cc: * Always fail reload_acl_and_cache() if the query was killed. sql/sql_servers.cc: * Make sure that there is an error to print before attempting to do so. --- sql/sql_acl.cc | 15 ++++++++++----- sql/sql_parse.cc | 9 ++++++--- sql/sql_servers.cc | 10 ++++++++-- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7d8f8ea71b3..7ba1a657578 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -310,7 +310,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) { TABLE *table; READ_RECORD read_record_info; - my_bool return_val= 1; + my_bool return_val= TRUE; bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; char tmp_name[NAME_LEN+1]; int password_length; @@ -623,7 +623,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) init_check_host(); initialized=1; - return_val=0; + return_val= FALSE; end: thd->variables.sql_mode= old_sql_mode; @@ -674,7 +674,7 @@ my_bool acl_reload(THD *thd) DYNAMIC_ARRAY old_acl_hosts,old_acl_users,old_acl_dbs; MEM_ROOT old_mem; bool old_initialized; - my_bool return_val= 1; + my_bool return_val= TRUE; DBUG_ENTER("acl_reload"); if (thd->locked_tables) @@ -701,8 +701,13 @@ my_bool acl_reload(THD *thd) if (simple_open_n_lock_tables(thd, tables)) { - sql_print_error("Fatal error: Can't open and lock privilege tables: %s", - thd->main_da.message()); + /* + Execution might have been interrupted; only print the error message + if an error condition has been raised. + */ + if (thd->main_da.is_error()) + sql_print_error("Fatal error: Can't open and lock privilege tables: %s", + thd->main_da.message()); goto end; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 69c9ddc7806..2c466d31e7c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6787,13 +6787,13 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, thd->store_globals(); lex_start(thd); } - + if (thd) { bool reload_acl_failed= acl_reload(thd); bool reload_grants_failed= grant_reload(thd); bool reload_servers_failed= servers_reload(thd); - + if (reload_acl_failed || reload_grants_failed || reload_servers_failed) { result= 1; @@ -6949,7 +6949,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, if (options & REFRESH_USER_RESOURCES) reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */ *write_to_binlog= tmp_write_to_binlog; - return result; + /* + If the query was killed then this function must fail. + */ + return result || thd->killed; } diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index f8a8dea18ff..1655426bb4a 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -241,8 +241,14 @@ bool servers_reload(THD *thd) if (simple_open_n_lock_tables(thd, tables)) { - sql_print_error("Can't open and lock privilege tables: %s", - thd->main_da.message()); + /* + Execution might have been interrupted; only print the error message + if an error condition has been raised. + */ + if (thd->main_da.is_error()) + sql_print_error("Can't open and lock privilege tables: %s", + thd->main_da.message()); + return_val= FALSE; goto end; } From 7ecd6c6d0269d1b8580f87cbdda1924d7ab0d499 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 14 Jan 2010 10:24:02 +0200 Subject: [PATCH 242/344] version change --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 557df1b1ffe..f79c1cd6319 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.0-bugteam" +tree_name = "mysql-5.0" From 5ae7b3c99634609b2890253590ccf82c5fb4f085 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Thu, 14 Jan 2010 10:49:40 +0000 Subject: [PATCH 243/344] BUG#50018: binlog corruption when table has many columns Small fix in the test case. Changed the UNLOCK tables to happen after each insert. --- mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test index 022988d7ee3..be5ebb661ca 100644 --- a/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test +++ b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test @@ -290,6 +290,7 @@ for my $i (1..$ntables) print FILE "LOCK TABLES t$i WRITE;\n"; print FILE "INSERT INTO t$i(c". ($base_ncols+1) . ") VALUES (50018);\n"; + print FILE "UNLOCK TABLES;"; } close(FILE); @@ -301,7 +302,6 @@ EOF ## may want to reactivate query logging -- disable_query_log -- source $generated_sql -UNLOCK TABLES; -- enable_query_log -- sync_slave_with_master From 32aa612819ff756b284e639de50627b3d6d7fa0d Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Thu, 14 Jan 2010 14:26:51 +0000 Subject: [PATCH 244/344] Fix for BUG#49481 and BUG#49482. BUG#49481: RBR: MyISAM and bit fields may cause slave to stop on delete: cant find record BUG#49482: RBR: Replication may break on deletes when MyISAM tables + char field are used When using MyISAM tables, despite the fact that the null bit is set for some fields, their old value is still in the row. This can cause the comparison of records to fail when the slave is doing an index or range scan. We fix this by avoiding memcmp for MyISAM tables when comparing records. Additionally, when comparing field by field, we first check if both fields are not null and if so, then we compare them. If just one field is null we return failure immediately. If both fields are null, we move on to the next field. --- .../suite/rpl/r/rpl_myisam_null_values.result | 24 +++++++++ .../suite/rpl/t/rpl_myisam_null_values.test | 53 +++++++++++++++++++ sql/log_event.cc | 39 +++++++++++++- sql/log_event_old.cc | 39 +++++++++++++- 4 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_myisam_null_values.result create mode 100644 mysql-test/suite/rpl/t/rpl_myisam_null_values.test diff --git a/mysql-test/suite/rpl/r/rpl_myisam_null_values.result b/mysql-test/suite/rpl/r/rpl_myisam_null_values.result new file mode 100644 index 00000000000..574528a8d79 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_myisam_null_values.result @@ -0,0 +1,24 @@ +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 (c1 BIT, c2 INT); +INSERT INTO `t1` VALUES ( 1, 1 ); +UPDATE t1 SET c1=NULL where c2=1; +Comparing tables master:test.t1 and slave:test.t1 +DELETE FROM t1 WHERE c2=1 LIMIT 1; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; +CREATE TABLE t1 (c1 CHAR); +INSERT INTO t1 ( c1 ) VALUES ( 'w' ) ; +SELECT * FROM t1; +c1 +w +# should trigger switch to row due to LIMIT +UPDATE t1 SET c1=NULL WHERE c1='w' LIMIT 2; +Comparing tables master:test.t1 and slave:test.t1 +DELETE FROM t1 LIMIT 2; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; diff --git a/mysql-test/suite/rpl/t/rpl_myisam_null_values.test b/mysql-test/suite/rpl/t/rpl_myisam_null_values.test new file mode 100644 index 00000000000..d9ec95fc510 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_myisam_null_values.test @@ -0,0 +1,53 @@ +# BUG#49481: RBR: MyISAM and bit fields may cause slave to stop on delete cant find record +# BUG#49482: RBR: Replication may break on deletes when MyISAM tables + char field are used + +-- source include/master-slave.inc +-- source include/have_binlog_format_mixed_or_row.inc + +-- connection master +CREATE TABLE t1 (c1 BIT, c2 INT); +INSERT INTO `t1` VALUES ( 1, 1 ); +UPDATE t1 SET c1=NULL where c2=1; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DELETE FROM t1 WHERE c2=1 LIMIT 1; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DROP TABLE t1; +-- sync_slave_with_master + +-- connection master + +CREATE TABLE t1 (c1 CHAR); + +INSERT INTO t1 ( c1 ) VALUES ( 'w' ) ; +SELECT * FROM t1; +-- echo # should trigger switch to row due to LIMIT +UPDATE t1 SET c1=NULL WHERE c1='w' LIMIT 2; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DELETE FROM t1 LIMIT 2; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DROP TABLE t1; +-- sync_slave_with_master diff --git a/sql/log_event.cc b/sql/log_event.cc index 6b21087b6aa..61f5e93e29e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8724,6 +8724,24 @@ static bool record_compare(TABLE *table) } } + /** + Check if we are using MyISAM. + + If this is a myisam table, then we cannot do a memcmp + right away because some NULL fields can still contain + an old value in the row - they are not shown to the user + because the null bit is set, however, the contents are + not cleared. As such, plain memory comparison cannot be + assured to work. See: BUG#49482 and BUG#49481. + + On top of this, we do not store field contents for null + fields in the binlog, so this is extra important when + comparing records fetched from binlog and from storage + engine. + */ + if (table->file->ht->db_type == DB_TYPE_MYISAM) + goto record_compare_field_by_field; + if (table->s->blob_fields + table->s->varchar_fields == 0) { result= cmp_record(table,record[1]); @@ -8739,14 +8757,33 @@ static bool record_compare(TABLE *table) goto record_compare_exit; } +record_compare_field_by_field: + /* Compare updated fields */ for (Field **ptr=table->field ; *ptr ; ptr++) { - if ((*ptr)->cmp_binary_offset(table->s->rec_buff_length)) + Field *f= *ptr; + + /* if just one of the fields is null then there is no match */ + if ((f->is_null_in_record(table->record[0])) == + !(f->is_null_in_record(table->record[1]))) { result= TRUE; goto record_compare_exit; } + + /* if both fields are not null then we can compare */ + if (!(f->is_null_in_record(table->record[0])) && + !(f->is_null_in_record(table->record[1]))) + { + if (f->cmp_binary_offset(table->s->rec_buff_length)) + { + result= TRUE; + goto record_compare_exit; + } + } + + /* if both fields are null then there is a match. compare next field */ } record_compare_exit: diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 357bc78b1cd..72a6e159535 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -351,6 +351,24 @@ static bool record_compare(TABLE *table) } } + /** + Check if we are using MyISAM. + + If this is a myisam table, then we cannot do a memcmp + right away because some NULL fields can still contain + an old value in the row - they are not shown to the user + because the null bit is set, however, the contents are + not cleared. As such, plain memory comparison cannot be + assured to work. See: BUG#49482 and BUG#49481. + + On top of this, we do not store field contents for null + fields in the binlog, so this is extra important when + comparing records fetched from binlog and from storage + engine. + */ + if (table->file->ht->db_type == DB_TYPE_MYISAM) + goto record_compare_field_by_field; + if (table->s->blob_fields + table->s->varchar_fields == 0) { result= cmp_record(table,record[1]); @@ -366,14 +384,33 @@ static bool record_compare(TABLE *table) goto record_compare_exit; } +record_compare_field_by_field: + /* Compare updated fields */ for (Field **ptr=table->field ; *ptr ; ptr++) { - if ((*ptr)->cmp_binary_offset(table->s->rec_buff_length)) + Field *f= *ptr; + + /* if just one of the fields is null then there is no match */ + if ((f->is_null_in_record(table->record[0])) == + !(f->is_null_in_record(table->record[1]))) { result= TRUE; goto record_compare_exit; } + + /* if both fields are not null then we can compare */ + if (!(f->is_null_in_record(table->record[0])) && + !(f->is_null_in_record(table->record[1]))) + { + if (f->cmp_binary_offset(table->s->rec_buff_length)) + { + result= TRUE; + goto record_compare_exit; + } + } + + /* if both fields are null then there is a match. compare next field */ } record_compare_exit: From e4535de11fe8eaba8ee5013b9bd5fe3b4b713b55 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Thu, 14 Jan 2010 18:32:41 +0200 Subject: [PATCH 245/344] Fixed compile error on windows. --- sql/set_var.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/set_var.cc b/sql/set_var.cc index 166f280be4e..0ec1f04a370 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -58,6 +58,9 @@ #include #include #include +#ifdef WITH_MARIA_STORAGE_ENGINE +#include +#endif #include #include #include "events.h" From d121e6630519a66eec7c953ee0eae623f592ce87 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Thu, 14 Jan 2010 18:51:00 +0200 Subject: [PATCH 246/344] Fix for compiler warnings on windows Fix wrong cast of time() include/my_pthread.h: Safety fix that also removes compiler warnings sql/handler.h: Changed timestamp columns to be of type time_t storage/maria/ma_check.c: Removed wrong cast storage/maria/ma_create.c: Removed wrong cast storage/myisam/mi_check.c: Removed wrong cast storage/myisam/mi_create.c: Removed wrong cast storage/xtradb/handler/ha_innodb.cc: Removed compiler warning on windows --- include/my_pthread.h | 6 +++--- sql/handler.h | 12 ++++++------ storage/maria/ma_check.c | 2 +- storage/maria/ma_create.c | 2 +- storage/myisam/mi_check.c | 2 +- storage/myisam/mi_create.c | 2 +- storage/xtradb/handler/ha_innodb.cc | 2 ++ 7 files changed, 15 insertions(+), 13 deletions(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index 98d843f54d1..d7a5a30bd73 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -543,9 +543,9 @@ void safe_mutex_free_deadlock_data(safe_mutex_t *mp); #else #define my_pthread_mutex_init(A,B,C,D) pthread_mutex_init((A),(B)) #define my_pthread_mutex_lock(A,B) pthread_mutex_lock(A) -#define safe_mutex_assert_owner(mp) -#define safe_mutex_assert_not_owner(mp) -#define safe_mutex_free_deadlock_data(mp) +#define safe_mutex_assert_owner(mp) do {} while(0) +#define safe_mutex_assert_not_owner(mp) do {} while(0) +#define safe_mutex_free_deadlock_data(mp) do {} while(0) #endif /* SAFE_MUTEX */ #if defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) diff --git a/sql/handler.h b/sql/handler.h index db3fb8035f2..d03264a23db 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -891,9 +891,9 @@ typedef struct { ulonglong delete_length; ha_rows records; ulong mean_rec_length; - ulong create_time; - ulong check_time; - ulong update_time; + time_t create_time; + time_t check_time; + time_t update_time; ulonglong check_sum; } PARTITION_INFO; @@ -1060,9 +1060,9 @@ public: ha_rows records; ha_rows deleted; /* Deleted records */ ulong mean_rec_length; /* physical reclength */ - ulong create_time; /* When table was created */ - ulong check_time; - ulong update_time; + time_t create_time; /* When table was created */ + time_t check_time; + time_t update_time; uint block_size; /* index block size */ ha_statistics(): diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 3314a21871a..4f93bf812a3 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -6018,7 +6018,7 @@ int maria_update_state_info(HA_CHECK *param, MARIA_HA *info,uint update) { if (update & UPDATE_TIME) { - share->state.check_time= (long) time((time_t*) 0); + share->state.check_time= time((time_t*) 0); if (!share->state.create_time) share->state.create_time= share->state.check_time; } diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 05b11929d0a..6886dc8f291 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -772,7 +772,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, share.base.min_block_length= share.base.pack_reclength; if (! (flags & HA_DONT_TOUCH_DATA)) - share.state.create_time= (long) time((time_t*) 0); + share.state.create_time= time((time_t*) 0); pthread_mutex_lock(&THR_LOCK_maria); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 5939e7ea786..9fe954273fe 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -4447,7 +4447,7 @@ int update_state_info(HA_CHECK *param, MI_INFO *info,uint update) { if (update & UPDATE_TIME) { - share->state.check_time= (long) time((time_t*) 0); + share->state.check_time= time((time_t*) 0); if (!share->state.create_time) share->state.create_time=share->state.check_time; } diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 3e7045d35a4..1b92d64d529 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -575,7 +575,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) : MI_EXTEND_BLOCK_LENGTH; if (! (flags & HA_DONT_TOUCH_DATA)) - share.state.create_time= (long) time((time_t*) 0); + share.state.create_time= time((time_t*) 0); pthread_mutex_lock(&THR_LOCK_myisam); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index cbcb5651c2e..f723a58c6d9 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -61,7 +61,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma implementation // gcc: Class implementation #endif +#ifndef MYSQL_SERVER #define MYSQL_SERVER +#endif #include #ifdef MYSQL_SERVER From 85c1e30375ec7c3aa9755d44d13bd4e0281c218b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Jan 2010 10:35:35 +0100 Subject: [PATCH 247/344] Raise version number after cloning 5.0.90 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 405ebddadbe..503bf660b2c 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.0.90) +AM_INIT_AUTOMAKE(mysql, 5.0.91) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=90 +NDB_VERSION_BUILD=91 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 7a7147c5b4cca1bfd1bfbecd4883d3968526b162 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 15 Jan 2010 16:09:20 +0200 Subject: [PATCH 248/344] Bug #46175: NULL read_view and consistent read assertion The optimizer must not continue executing the current query if e.g. the storage engine reports an error. This is somewhat hard to implement with Item::val_xxx() because they do not have means to return error code. This is why we need to check the thread's error state after a call to one of the Item::val_xxx() methods. Fixed store_key_item::copy_inner() to return an error state if an error happened during the call to Item::save_in_field() because it calls Item::val_xxx(). Also added similar checks to related places. --- sql/item.cc | 2 +- sql/sql_select.h | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/sql/item.cc b/sql/item.cc index b35a6ae3d6e..68c10c32b50 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5141,7 +5141,7 @@ int Item::save_in_field(Field *field, bool no_conversions) field->set_notnull(); error=field->store(nr, unsigned_flag); } - return error; + return error ? error : (field->table->in_use->is_error() ? 2 : 0); } diff --git a/sql/sql_select.h b/sql/sql_select.h index c9cd3ecba42..dd99d358bac 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -709,6 +709,12 @@ public: my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set); int res= item->save_in_field(to_field, 1); + /* + Item::save_in_field() may call Item::val_xxx(). And if this is a subquery + we need to check for errors executing it and react accordingly + */ + if (!res && table->in_use->is_error()) + res= 2; dbug_tmp_restore_column_map(table->write_set, old_map); null_key= to_field->is_null() || item->null_value; return (err != 0 || res > 2 ? STORE_KEY_FATAL : (store_key_result) res); @@ -742,6 +748,12 @@ protected: if (!err) err= res; } + /* + Item::save_in_field() may call Item::val_xxx(). And if this is a subquery + we need to check for errors executing it and react accordingly + */ + if (!err && to_field->table->in_use->is_error()) + err= 2; } null_key= to_field->is_null() || item->null_value; return (err > 2 ? STORE_KEY_FATAL : (store_key_result) err); From 2fdaf377a2ff60147c2545f7fbc3c1b43635b1f4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Jan 2010 18:03:48 +0100 Subject: [PATCH 249/344] Raise version number after cloning 5.1.43 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 38eb511ac18..e939194697b 100644 --- a/configure.in +++ b/configure.in @@ -10,7 +10,7 @@ AC_CANONICAL_SYSTEM # # When changing major version number please also check switch statement # in mysqlbinlog::check_master_version(). -AM_INIT_AUTOMAKE(mysql, 5.1.43) +AM_INIT_AUTOMAKE(mysql, 5.1.44) AM_CONFIG_HEADER([include/config.h:config.h.in]) # Request support for automake silent-rules if available. From ae8d0b378e472847053ff4c4f1612dd6bd3b1a47 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 15 Jan 2010 20:06:18 +0200 Subject: [PATCH 250/344] Fixed that we use same flags when testing for assembler as by makefiles. Fixed bug in locking by triggers found by test case when compiling without query cache configure.in: Fixed that we use same flags when testing for assembler as by makefiles. sql/sql_yacc.yy: Fixed bug in locking by triggers found by test case when compiling without query cache The idea should be that triggers uses the same lock method (low_priority_locks...) as main tables. --- configure.in | 10 +--------- sql/sql_yacc.yy | 23 +++++------------------ 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/configure.in b/configure.in index 2aac45bf952..127e9ddb4a6 100644 --- a/configure.in +++ b/configure.in @@ -224,14 +224,6 @@ then GXX="no" fi -if test "$ac_cv_prog_gcc" = "yes" -then - AS="$CC -c" - AC_SUBST(AS) -else - AC_PATH_PROG(AS, as, as) -fi - # Still need ranlib for readline; local static use only so no libtool. AC_PROG_RANLIB # We use libtool @@ -688,7 +680,7 @@ AC_ARG_ENABLE(assembler, AC_MSG_CHECKING(if we should use assembler functions) # For now we only support assembler on i386 and sparc systems -AM_CONDITIONAL(ASSEMBLER_x86, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "i386" && $AS strings/strings-x86.s -o checkassembler >/dev/null 2>&1 && test -f checkassembler && (rm -f checkassembler; exit 0;)) +AM_CONDITIONAL(ASSEMBLER_x86, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "i386" && $CCAS $CCASFLAGS -c strings/strings-x86.s -o checkassembler >/dev/null 2>&1 && test -f checkassembler && (rm -f checkassembler; exit 0;)) AM_CONDITIONAL(ASSEMBLER_sparc32, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparc") AM_CONDITIONAL(ASSEMBLER_sparc64, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparcv9") AM_CONDITIONAL(ASSEMBLER, test "$ASSEMBLER_x86_TRUE" = "" -o "$ASSEMBLER_sparc32_TRUE" = "") diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c9a08200479..c89fafef023 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9483,16 +9483,12 @@ replace: insert_lock_option: /* empty */ { -#ifdef HAVE_QUERY_CACHE /* - If it is SP we do not allow insert optimisation whan result of + If it is SP we do not allow insert optimisation when result of insert visible only after the table unlocking but everyone can read table. */ $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT); -#else - $$= TL_WRITE_CONCURRENT_INSERT; -#endif } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; } | DELAYED_SYM { $$= TL_WRITE_DELAYED; } @@ -10515,15 +10511,11 @@ load_data_lock: /* empty */ { $$= TL_WRITE_DEFAULT; } | CONCURRENT { -#ifdef HAVE_QUERY_CACHE /* - Ignore this option in SP to avoid problem with query cache + Ignore this option in SP to avoid problem with query cache and + triggers with non default priority locks */ - if (Lex->sphead != 0) - $$= TL_WRITE_DEFAULT; - else -#endif - $$= TL_WRITE_CONCURRENT_INSERT; + $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT); } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; } ; @@ -12237,12 +12229,7 @@ lock_option: | WRITE_SYM { $$= TL_WRITE_DEFAULT; } | WRITE_SYM CONCURRENT { -#ifdef HAVE_QUERY_CACHE - if (Lex->sphead != 0) - $$= TL_WRITE_DEFAULT; - else -#endif - $$= TL_WRITE_CONCURRENT_INSERT; + $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT); } | LOW_PRIORITY WRITE_SYM { $$= TL_WRITE_LOW_PRIORITY; } From fd3e17318bd57e043ab53620d8cb9744aefcf33c Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 15 Jan 2010 20:15:14 +0200 Subject: [PATCH 251/344] Removed not needed test file (that caused embedded server to fail) --- mysql-test/suite/maria/t/maria2-master.opt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 mysql-test/suite/maria/t/maria2-master.opt diff --git a/mysql-test/suite/maria/t/maria2-master.opt b/mysql-test/suite/maria/t/maria2-master.opt deleted file mode 100644 index cc77ad1f72a..00000000000 --- a/mysql-test/suite/maria/t/maria2-master.opt +++ /dev/null @@ -1 +0,0 @@ ---secure-file-priv="../../std_data" From a9ecb19832dffc6b07e8823942bdd3e7054e929f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Jan 2010 19:44:11 +0100 Subject: [PATCH 252/344] After-merge fix for XtraDB 9: missing DBUG_RETURN. --- storage/xtradb/handler/ha_innodb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index b4c2f7abc16..6c66327b973 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -9729,7 +9729,7 @@ ha_innobase::check_if_incompatible_data( if (table->field[i]->flags & FIELD_IN_ADD_INDEX && innobase_strcasecmp(table->field[i]->field_name, dict_table_get_col_name(prebuilt->table, i))) { - return(COMPATIBLE_DATA_NO); + DBUG_RETURN(COMPATIBLE_DATA_NO); } } } From ea328df58a737f675862cb4e2391b45fbc300636 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Jan 2010 20:48:33 +0100 Subject: [PATCH 253/344] Fix crashes by taking kernel mutex when calling srv_table_reserve_slot() during thread startup. --- storage/xtradb/srv/srv0srv.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index 38176938e62..00352191c2b 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -2559,10 +2559,9 @@ srv_master_thread( srv_main_thread_process_no = os_proc_get_number(); srv_main_thread_id = os_thread_pf(os_thread_get_curr_id()); - srv_table_reserve_slot(SRV_MASTER); - mutex_enter(&kernel_mutex); + srv_table_reserve_slot(SRV_MASTER); srv_n_threads_active[SRV_MASTER]++; mutex_exit(&kernel_mutex); @@ -3167,8 +3166,8 @@ srv_purge_thread( os_thread_pf(os_thread_get_curr_id())); #endif - srv_table_reserve_slot(SRV_PURGE); mutex_enter(&kernel_mutex); + srv_table_reserve_slot(SRV_PURGE); srv_n_threads_active[SRV_PURGE]++; mutex_exit(&kernel_mutex); @@ -3255,8 +3254,8 @@ srv_purge_worker_thread( fprintf(stderr, "Purge worker thread starts, id %lu\n", os_thread_pf(os_thread_get_curr_id())); #endif - srv_table_reserve_slot(SRV_PURGE_WORKER); mutex_enter(&kernel_mutex); + srv_table_reserve_slot(SRV_PURGE_WORKER); srv_n_threads_active[SRV_PURGE_WORKER]++; mutex_exit(&kernel_mutex); From 62eee9346b0f2bed21c26efe6bdee55014a88281 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Jan 2010 22:12:30 +0100 Subject: [PATCH 254/344] Apply to XtraDB MySQL/build-in innodb patches for Bug#49032 and Bug#47720. --- mysql-test/t/innodb-autoinc.test | 6 ++++++ storage/xtradb/handler/ha_innodb.cc | 29 +++++++++++++++++------------ storage/xtradb/row/row0sel.c | 25 ++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index d335f709ba4..16b456e5bfb 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -2,6 +2,8 @@ # embedded server ignores 'delayed', so skip this -- source include/not_embedded.inc +let $file_format_check=`select @@innodb_file_format_check`; + --disable_warnings drop table if exists t1; --enable_warnings @@ -655,3 +657,7 @@ REPLACE INTO t1 VALUES (-1); SELECT * FROM t1; SHOW CREATE TABLE t1; DROP TABLE t1; + +--disable_query_log +EVAL SET GLOBAL innodb_file_format_check=$file_format_check; +--enable_query_log diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 6c66327b973..c28e0c57d2b 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -4742,24 +4742,29 @@ no_commit: update the table upper limit. Note: last_value will be 0 if get_auto_increment() was not called.*/ - if (auto_inc <= col_max_value - && auto_inc >= prebuilt->autoinc_last_value) { + if (auto_inc >= prebuilt->autoinc_last_value) { set_max_autoinc: - ut_a(prebuilt->autoinc_increment > 0); + /* This should filter out the negative + values set explicitly by the user. */ + if (auto_inc <= col_max_value) { + ut_a(prebuilt->autoinc_increment > 0); - ulonglong need; - ulonglong offset; + ulonglong need; + ulonglong offset; - offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + offset = prebuilt->autoinc_offset; + need = prebuilt->autoinc_increment; - auto_inc = innobase_next_autoinc( - auto_inc, need, offset, col_max_value); + auto_inc = innobase_next_autoinc( + auto_inc, + need, offset, col_max_value); - err = innobase_set_max_autoinc(auto_inc); + err = innobase_set_max_autoinc( + auto_inc); - if (err != DB_SUCCESS) { - error = err; + if (err != DB_SUCCESS) { + error = err; + } } } break; diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index 3ef9726588e..ed9ea8fe8c6 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -4616,6 +4616,7 @@ row_search_autoinc_read_column( dict_index_t* index, /*!< in: index to read from */ const rec_t* rec, /*!< in: current rec */ ulint col_no, /*!< in: column number */ + ulint mtype, /*!< in: column main type */ ibool unsigned_type) /*!< in: signed or unsigned flag */ { ulint len; @@ -4632,10 +4633,27 @@ row_search_autoinc_read_column( data = rec_get_nth_field(rec, offsets, col_no, &len); ut_a(len != UNIV_SQL_NULL); - ut_a(len <= sizeof value); /* we assume AUTOINC value cannot be negative */ - value = mach_read_int_type(data, len, unsigned_type); + switch (mtype) { + case DATA_INT: + ut_a(len <= sizeof value); + value = mach_read_int_type(data, len, unsigned_type); + break; + + case DATA_FLOAT: + ut_a(len == sizeof(float)); + value = mach_float_read(data); + break; + + case DATA_DOUBLE: + ut_a(len == sizeof(double)); + value = mach_double_read(data); + break; + + default: + ut_error; + } if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -4721,7 +4739,8 @@ row_search_max_autoinc( dfield->col->prtype & DATA_UNSIGNED); *value = row_search_autoinc_read_column( - index, rec, i, unsigned_type); + index, rec, i, + dfield->col->mtype, unsigned_type); } } From ccdd2c23a6781793ef851f760be934e7ba47fad2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 Jan 2010 06:12:57 +0100 Subject: [PATCH 255/344] Result file updates following merge of MySQL 5.1.42 and XtraDB 9. mysql-test/suite/funcs_1/r/is_columns_is.result: XTRADB_ADMIN_COMMAND table added. Column name change: "accessed" -> "access" (XtraDB 9 change). mysql-test/suite/funcs_1/r/is_tables_is.result: XTRADB_ADMIN_COMMAND table added. mysql-test/suite/pbxt/r/func_group.result: Update results to be correct following fix of Bug#43668. mysql-test/suite/pbxt/r/mysqlshow.result: XTRADB_ADMIN_COMMAND table added. --- .../suite/funcs_1/r/is_columns_is.result | 6 ++- .../suite/funcs_1/r/is_tables_is.result | 46 +++++++++++++++++++ mysql-test/suite/pbxt/r/func_group.result | 2 +- mysql-test/suite/pbxt/r/mysqlshow.result | 6 ++- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/funcs_1/r/is_columns_is.result b/mysql-test/suite/funcs_1/r/is_columns_is.result index b5a67aece35..4ecc6c5211d 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is.result @@ -127,7 +127,7 @@ NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB next_page_no 5 0 NO bigint NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB page_no 2 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB part_len 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB space_id 1 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select -NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX accessed 9 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select +NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX access_time 9 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX data_size 7 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX dirty 11 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX fix_count 14 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select @@ -394,6 +394,7 @@ NULL information_schema VIEWS TABLE_CATALOG 1 NULL YES varchar 512 1536 NULL NUL NULL information_schema VIEWS TABLE_NAME 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select NULL information_schema VIEWS TABLE_SCHEMA 2 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select NULL information_schema VIEWS VIEW_DEFINITION 4 NULL NO longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext select +NULL information_schema XTRADB_ADMIN_COMMAND result_message 1 NO varchar 1024 3072 NULL NULL utf8 utf8_general_ci varchar(1024) select NULL information_schema XTRADB_ENHANCEMENTS comment 3 NO varchar 100 300 NULL NULL utf8 utf8_general_ci varchar(100) select NULL information_schema XTRADB_ENHANCEMENTS description 2 NO varchar 255 765 NULL NULL utf8 utf8_general_ci varchar(255) select NULL information_schema XTRADB_ENHANCEMENTS link 4 NO varchar 255 765 NULL NULL utf8 utf8_general_ci varchar(255) select @@ -589,7 +590,7 @@ NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX page_no bigint NULL NULL NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX n_recs bigint NULL NULL NULL NULL bigint(21) unsigned NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX data_size bigint NULL NULL NULL NULL bigint(21) unsigned NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX hashed bigint NULL NULL NULL NULL bigint(21) unsigned -NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX accessed bigint NULL NULL NULL NULL bigint(21) unsigned +NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX access_time bigint NULL NULL NULL NULL bigint(21) unsigned NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX modified bigint NULL NULL NULL NULL bigint(21) unsigned NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX dirty bigint NULL NULL NULL NULL bigint(21) unsigned NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX old bigint NULL NULL NULL NULL bigint(21) unsigned @@ -848,6 +849,7 @@ NULL information_schema TRIGGERS CREATED datetime NULL NULL NULL NULL datetime 3.0000 information_schema VIEWS SECURITY_TYPE varchar 7 21 utf8 utf8_general_ci varchar(7) 3.0000 information_schema VIEWS CHARACTER_SET_CLIENT varchar 32 96 utf8 utf8_general_ci varchar(32) 3.0000 information_schema VIEWS COLLATION_CONNECTION varchar 32 96 utf8 utf8_general_ci varchar(32) +3.0000 information_schema XTRADB_ADMIN_COMMAND result_message varchar 1024 3072 utf8 utf8_general_ci varchar(1024) 3.0000 information_schema XTRADB_ENHANCEMENTS name varchar 255 765 utf8 utf8_general_ci varchar(255) 3.0000 information_schema XTRADB_ENHANCEMENTS description varchar 255 765 utf8 utf8_general_ci varchar(255) 3.0000 information_schema XTRADB_ENHANCEMENTS comment varchar 100 300 utf8 utf8_general_ci varchar(100) diff --git a/mysql-test/suite/funcs_1/r/is_tables_is.result b/mysql-test/suite/funcs_1/r/is_tables_is.result index bcdf06fbd88..a9f2a78dc54 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_is.result +++ b/mysql-test/suite/funcs_1/r/is_tables_is.result @@ -958,6 +958,29 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG NULL TABLE_SCHEMA information_schema +TABLE_NAME XTRADB_ADMIN_COMMAND +TABLE_TYPE SYSTEM VIEW +ENGINE MEMORY +VERSION 10 +ROW_FORMAT Fixed +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_general_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG NULL +TABLE_SCHEMA information_schema TABLE_NAME XTRADB_ENHANCEMENTS TABLE_TYPE SYSTEM VIEW ENGINE MEMORY @@ -1941,6 +1964,29 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG NULL TABLE_SCHEMA information_schema +TABLE_NAME XTRADB_ADMIN_COMMAND +TABLE_TYPE SYSTEM VIEW +ENGINE MEMORY +VERSION 10 +ROW_FORMAT Fixed +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_general_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG NULL +TABLE_SCHEMA information_schema TABLE_NAME XTRADB_ENHANCEMENTS TABLE_TYPE SYSTEM VIEW ENGINE MEMORY diff --git a/mysql-test/suite/pbxt/r/func_group.result b/mysql-test/suite/pbxt/r/func_group.result index 5da10aa243a..339defca9b5 100644 --- a/mysql-test/suite/pbxt/r/func_group.result +++ b/mysql-test/suite/pbxt/r/func_group.result @@ -885,7 +885,7 @@ cast(sum(distinct df) as signed) 3 select cast(min(df) as signed) from t1; cast(min(df) as signed) -0 +1 select 1e8 * sum(distinct df) from t1; 1e8 * sum(distinct df) 330000000 diff --git a/mysql-test/suite/pbxt/r/mysqlshow.result b/mysql-test/suite/pbxt/r/mysqlshow.result index 56b5d125ef3..e79a53b0736 100644 --- a/mysql-test/suite/pbxt/r/mysqlshow.result +++ b/mysql-test/suite/pbxt/r/mysqlshow.result @@ -113,7 +113,7 @@ Database: information_schema | INNODB_RSEG | | XTRADB_ENHANCEMENTS | | INNODB_BUFFER_POOL_PAGES_INDEX | -| INNODB_INDEX_STATS | +| XTRADB_ADMIN_COMMAND | | INNODB_TRX | | INNODB_CMP_RESET | | INNODB_LOCK_WAITS | @@ -122,6 +122,7 @@ Database: information_schema | INNODB_CMPMEM | | INNODB_TABLE_STATS | | INNODB_BUFFER_POOL_PAGES_BLOB | +| INNODB_INDEX_STATS | +---------------------------------------+ Database: INFORMATION_SCHEMA +---------------------------------------+ @@ -161,7 +162,7 @@ Database: INFORMATION_SCHEMA | INNODB_RSEG | | XTRADB_ENHANCEMENTS | | INNODB_BUFFER_POOL_PAGES_INDEX | -| INNODB_INDEX_STATS | +| XTRADB_ADMIN_COMMAND | | INNODB_TRX | | INNODB_CMP_RESET | | INNODB_LOCK_WAITS | @@ -170,6 +171,7 @@ Database: INFORMATION_SCHEMA | INNODB_CMPMEM | | INNODB_TABLE_STATS | | INNODB_BUFFER_POOL_PAGES_BLOB | +| INNODB_INDEX_STATS | +---------------------------------------+ Wildcard: inf_rmation_schema +--------------------+ From 377d710296c3b0c85ea4cdc018d1d8e08bfa022a Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 Jan 2010 15:44:24 +0800 Subject: [PATCH 256/344] BUG#47418 RBR fails, failure with mixup of base/temporary/view 'CREATE TABLE IF NOT EXISTS ... SELECT' statement were causing 'CREATE TEMPORARY TABLE ...' to be written to the binary log in row-based mode (a.k.a. RBR), when there was a temporary table with the same name. Because the 'CREATE TABLE ... SELECT' statement was executed as 'INSERT ... SELECT' into the temporary table. Since in RBR mode no other statements related to temporary tables are written into binary log, this sometimes broke replication. This patch changes behavior of 'CREATE TABLE [IF NOT EXISTS] ... SELECT ...'. it ignores existence of temporary table with the same name as table being created and is interpreted as attempt to create/insert into base table. This makes behavior of 'CREATE TABLE [IF NOT EXISTS] ... SELECT' consistent with how ordinary 'CREATE TABLE' and 'CREATE TABLE ... LIKE' behave. --- mysql-test/r/create.result | 7 +-- mysql-test/r/ps_ddl.result | 8 +-- .../rpl/r/rpl_create_if_not_exists.result | 34 ++++++++++++ .../suite/rpl/t/rpl_create_if_not_exists.test | 53 +++++++++++++++++++ mysql-test/t/create.test | 9 ++-- mysql-test/t/ps_ddl.test | 9 ++-- sql/sql_parse.cc | 2 + sql/sql_prepare.cc | 2 + 8 files changed, 106 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index b829ef30fb1..cfdf2565c9c 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -820,16 +820,13 @@ i drop table t1; create temporary table t1 (j int); create table if not exists t1 select 1; -Warnings: -Note 1050 Table 't1' already exists select * from t1; j -1 drop temporary table t1; select * from t1; -ERROR 42S02: Table 'test.t1' doesn't exist +1 +1 drop table t1; -ERROR 42S02: Unknown table 't1' create table t1 (i int); insert into t1 values (1), (2); lock tables t1 read; diff --git a/mysql-test/r/ps_ddl.result b/mysql-test/r/ps_ddl.result index c7e8812320c..375f31ef9c4 100644 --- a/mysql-test/r/ps_ddl.result +++ b/mysql-test/r/ps_ddl.result @@ -1695,23 +1695,23 @@ SUCCESS drop table t2; create temporary table t2 (a int); execute stmt; -ERROR 42S01: Table 't2' already exists call p_verify_reprepare_count(1); SUCCESS execute stmt; ERROR 42S01: Table 't2' already exists -call p_verify_reprepare_count(0); +call p_verify_reprepare_count(1); SUCCESS drop temporary table t2; execute stmt; -call p_verify_reprepare_count(1); +ERROR 42S01: Table 't2' already exists +call p_verify_reprepare_count(0); SUCCESS drop table t2; execute stmt; -call p_verify_reprepare_count(0); +call p_verify_reprepare_count(1); SUCCESS drop table t2; diff --git a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result index 12a956a6ce6..fc53aca5136 100644 --- a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result +++ b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result @@ -31,3 +31,37 @@ SHOW EVENTS in mysqltest; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation mysqltest e root@localhost SYSTEM ONE TIME # NULL NULL NULL NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci DROP DATABASE IF EXISTS mysqltest; +-------------BUG#47418------------- +USE test; +DROP TABLE IF EXISTS t3; +CREATE TABLE t3(c1 INTEGER); +INSERT INTO t3 VALUES(33); +CREATE TEMPORARY TABLE t1(c1 INTEGER); +CREATE TEMPORARY TABLE t2(c1 INTEGER); +INSERT INTO t1 VALUES(1); +INSERT INTO t2 VALUES(1); +CREATE TABLE IF NOT EXISTS t1(c1 INTEGER) SELECT c1 FROM t3; +CREATE TABLE t2(c1 INTEGER) SELECT c1 FROM t3; +SELECT * FROM t1; +c1 +1 +SELECT * FROM t2; +c1 +1 +SELECT * FROM t1; +c1 +33 +SELECT * FROM t2; +c1 +33 +DROP TEMPORARY TABLE t1; +DROP TEMPORARY TABLE t2; +SELECT * FROM t1; +c1 +33 +SELECT * FROM t2; +c1 +33 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; diff --git a/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test index 5faf95a4d84..114f71af873 100644 --- a/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test +++ b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test @@ -67,4 +67,57 @@ SHOW EVENTS in mysqltest; connection master; DROP DATABASE IF EXISTS mysqltest; + +# +# BUG#47418 RBR fails, failure with mixup of base/temporary/view TABLE DDL +# +# Before the patch for this bug, 'CREATE TABLE IF NOT EXIST ... SELECT' +# statement was binlogged as a TEMPORARY table if the object existed as +# a temporary table. This was caused by that the temporary table was opened +# and the results of the 'SELECT' was inserted into the temporary table if +# a temporary table existed with the same name. +# +# After the patch for this bug, the base table is created and the results of +# the 'SELECT' are inserted into it, even though a temporary table exists with +# the same name, and the statement is still binlogged as a base table. +# + +echo -------------BUG#47418-------------; +connection master; +USE test; +DROP TABLE IF EXISTS t3; +--enable_warnings +CREATE TABLE t3(c1 INTEGER); +INSERT INTO t3 VALUES(33); + +CREATE TEMPORARY TABLE t1(c1 INTEGER); +CREATE TEMPORARY TABLE t2(c1 INTEGER); +INSERT INTO t1 VALUES(1); +INSERT INTO t2 VALUES(1); + +CREATE TABLE IF NOT EXISTS t1(c1 INTEGER) SELECT c1 FROM t3; +CREATE TABLE t2(c1 INTEGER) SELECT c1 FROM t3; + +# In these two statements, t1 and t2 are the temporary table. there is only +# value '1' in them. The records of t2 are not inserted into them. +SELECT * FROM t1; +SELECT * FROM t2; +sync_slave_with_master; + +# In these two statements, t1 and t2 are the base table. The recoreds of t2 +# are inserted into it when CREATE TABLE ... SELECT was executed. +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; +DROP TEMPORARY TABLE t1; +DROP TEMPORARY TABLE t2; +#In these two statements, t1 and t2 are the base table. +SELECT * FROM t1; +SELECT * FROM t2; + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + source include/master-slave-end.inc; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 5ffa1b93929..692721b5955 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -721,16 +721,15 @@ drop table t1; # Base vs temporary tables dillema (a.k.a. bug#24508 "Inconsistent # results of CREATE TABLE ... SELECT when temporary table exists"). # In this situation we either have to create non-temporary table and -# insert data in it or insert data in temporary table without creation -# of permanent table. Since currently temporary tables always shadow -# permanent tables we adopt second approach. +# insert data in it or insert data in temporary table without creation of +# permanent table. After patch for Bug#47418, we create the base table and +# instert data into it, even though a temporary table exists with the same +# name. create temporary table t1 (j int); create table if not exists t1 select 1; select * from t1; drop temporary table t1; ---error ER_NO_SUCH_TABLE select * from t1; ---error ER_BAD_TABLE_ERROR drop table t1; diff --git a/mysql-test/t/ps_ddl.test b/mysql-test/t/ps_ddl.test index fee235cd36c..1543c757908 100644 --- a/mysql-test/t/ps_ddl.test +++ b/mysql-test/t/ps_ddl.test @@ -1445,18 +1445,19 @@ call p_verify_reprepare_count(0); drop table t2; # Temporary table with name of table to be created exists create temporary table t2 (a int); +# Temporary table and base table are not in the same name space. +execute stmt; +call p_verify_reprepare_count(1); --error ER_TABLE_EXISTS_ERROR execute stmt; call p_verify_reprepare_count(1); +drop temporary table t2; --error ER_TABLE_EXISTS_ERROR execute stmt; call p_verify_reprepare_count(0); -drop temporary table t2; -execute stmt; -call p_verify_reprepare_count(1); drop table t2; execute stmt; -call p_verify_reprepare_count(0); +call p_verify_reprepare_count(1); drop table t2; # View with name of table to be created exists # Attention: diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index eaea6e55b09..c3070c4a756 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2659,6 +2659,8 @@ mysql_execute_command(THD *thd) { lex->link_first_table_back(create_table, link_to_local); create_table->create= TRUE; + /* Base table and temporary table are not in the same name space. */ + create_table->skip_temporary= 1; } if (!(res= open_and_lock_tables(thd, lex->query_tables))) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index e2a24f7da1e..5979f2ca17e 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1596,6 +1596,8 @@ static bool mysql_test_create_table(Prepared_statement *stmt) { lex->link_first_table_back(create_table, link_to_local); create_table->create= TRUE; + /* Base table and temporary table are not in the same name space. */ + create_table->skip_temporary= true; } if (open_normal_and_derived_tables(stmt->thd, lex->query_tables, 0)) From 9ca219eee34e6178fe2a5595660d0dfd7787aa23 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 17 Jan 2010 09:41:43 +0100 Subject: [PATCH 257/344] Fix freed-twice error in XtraDB (from InnoDB plugin 1.0.6). --- storage/xtradb/srv/srv0start.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c index 5b5599b893d..264bf7a7c05 100644 --- a/storage/xtradb/srv/srv0start.c +++ b/storage/xtradb/srv/srv0start.c @@ -2057,8 +2057,8 @@ innobase_shutdown_for_mysql(void) pars_lexer_close(); log_mem_free(); buf_pool_free(); - ut_free_all_mem(); mem_close(); + ut_free_all_mem(); if (os_thread_count != 0 || os_event_count != 0 From 7b33b9f28764f53a0c39e5207c3db1c47940b6ec Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Sun, 17 Jan 2010 13:41:32 +0200 Subject: [PATCH 258/344] Fixed race condition when innobase_shutdown_for_mysql() was called before parser was initialized (as it's initialized on first usage) --- storage/xtradb/pars/lexyy.c | 6 ++++-- storage/xtradb/pars/pars0lex.l | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/storage/xtradb/pars/lexyy.c b/storage/xtradb/pars/lexyy.c index 815395ea316..fc6b5102581 100644 --- a/storage/xtradb/pars/lexyy.c +++ b/storage/xtradb/pars/lexyy.c @@ -2786,8 +2786,10 @@ void pars_lexer_close(void) /*==================*/ { - yylex_destroy(); - free(stringbuf); + if (yy_buffer_stack) + yylex_destroy(); + if (stringbuf) + free(stringbuf); stringbuf = NULL; stringbuf_len_alloc = stringbuf_len = 0; } diff --git a/storage/xtradb/pars/pars0lex.l b/storage/xtradb/pars/pars0lex.l index 55ed17f82e1..7bd39f7514b 100644 --- a/storage/xtradb/pars/pars0lex.l +++ b/storage/xtradb/pars/pars0lex.l @@ -669,8 +669,10 @@ void pars_lexer_close(void) /*==================*/ { - yylex_destroy(); - free(stringbuf); + if (yy_buffer_stack) + yylex_destroy(); + if (stringbuf) + free(stringbuf); stringbuf = NULL; stringbuf_len_alloc = stringbuf_len = 0; } From 159ff4c12c339ccd6c6d9386a2486a535b1e0932 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Jan 2010 13:56:10 +0100 Subject: [PATCH 259/344] Fixes for some randomly occuring test failures in Buildbot. mysql-test/r/innodb-timeout.result: Make test more robust to scheduling delays on the host running the test suite. mysql-test/suite/rpl/r/rpl_relayspace.result: Apply patch from BUG#25228 and tweak timeout value in an attempt to fix random failure of this test in Buildbot (could not repeat locally). mysql-test/suite/rpl/t/rpl_relayspace.test: Apply patch from BUG#25228 and tweak timeout value in an attempt to fix random failure of this test in Buildbot (could not repeat locally). mysql-test/t/innodb-timeout.test: Make test more robust to scheduling delays on the host running the test suite. mysql-test/valgrind.supp: Add suppression for Glibc bug. --- mysql-test/r/innodb-timeout.result | 10 +++++++++- mysql-test/suite/rpl/r/rpl_relayspace.result | 4 ++-- mysql-test/suite/rpl/t/rpl_relayspace.test | 9 +++++++-- mysql-test/t/innodb-timeout.test | 17 +++++++++++------ mysql-test/valgrind.supp | 12 ++++++++++++ 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/innodb-timeout.result b/mysql-test/r/innodb-timeout.result index be9a688cd72..2d34cdb1cda 100644 --- a/mysql-test/r/innodb-timeout.result +++ b/mysql-test/r/innodb-timeout.result @@ -23,6 +23,7 @@ select @@innodb_lock_wait_timeout; create table t1(a int primary key)engine=innodb; begin; insert into t1 values(1),(2),(3); +set innodb_lock_wait_timeout=5; select * from t1 for update; commit; a @@ -31,8 +32,15 @@ a 3 begin; insert into t1 values(4); +set innodb_lock_wait_timeout=2; +set @a= current_timestamp(); select * from t1 for update; -commit; ERROR HY000: Lock wait timeout exceeded; try restarting transaction +set @b= current_timestamp(); +set @c= timestampdiff(SECOND, @a, @b); +select if(@c >= 1 and @c <= 10, 'OK', concat("NOT OK, time passed=", @c)); +if(@c >= 1 and @c <= 10, 'OK', concat("NOT OK, time passed=", @c)) +OK +commit; drop table t1; set global innodb_lock_wait_timeout=50; diff --git a/mysql-test/suite/rpl/r/rpl_relayspace.result b/mysql-test/suite/rpl/r/rpl_relayspace.result index 1f2a739d3e3..bb4e672e7e5 100644 --- a/mysql-test/suite/rpl/r/rpl_relayspace.result +++ b/mysql-test/suite/rpl/r/rpl_relayspace.result @@ -14,6 +14,6 @@ start slave io_thread; stop slave io_thread; reset slave; start slave; -select master_pos_wait('master-bin.001',200,6)=-1; -master_pos_wait('master-bin.001',200,6)=-1 +select master_pos_wait('MASTER_LOG_FILE',200,30)=-1; +master_pos_wait('MASTER_LOG_FILE',200,30)=-1 0 diff --git a/mysql-test/suite/rpl/t/rpl_relayspace.test b/mysql-test/suite/rpl/t/rpl_relayspace.test index 0fc564cdb46..cd04c2ccc0b 100644 --- a/mysql-test/suite/rpl/t/rpl_relayspace.test +++ b/mysql-test/suite/rpl/t/rpl_relayspace.test @@ -2,8 +2,10 @@ # to force the deadlock after one event. source include/master-slave.inc; +let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1); connection slave; stop slave; +source include/wait_for_slave_to_stop.inc; connection master; # This will generate a master's binlog > 10 bytes create table t1 (a int); @@ -20,6 +22,7 @@ source include/wait_for_slave_param.inc; # A bug caused the I/O thread to refuse stopping. stop slave io_thread; +source include/wait_for_slave_io_to_stop.inc; reset slave; start slave; # The I/O thread stops filling the relay log when @@ -29,9 +32,11 @@ start slave; # So we should have a deadlock. # if it is not resolved automatically we'll detect # it with master_pos_wait that waits for farther than 1Ob; -# it will timeout after 10 seconds; +# it will timeout; # also the slave will probably not cooperate to shutdown # (as 2 threads are locked) -select master_pos_wait('master-bin.001',200,6)=-1; +--replace_result $master_log_file MASTER_LOG_FILE +eval select master_pos_wait('$master_log_file',200,30)=-1; + # End of 4.1 tests diff --git a/mysql-test/t/innodb-timeout.test b/mysql-test/t/innodb-timeout.test index f23fe3cff2d..7f7bcecb4ee 100644 --- a/mysql-test/t/innodb-timeout.test +++ b/mysql-test/t/innodb-timeout.test @@ -30,6 +30,7 @@ begin; insert into t1 values(1),(2),(3); connection b; +set innodb_lock_wait_timeout=5; --send select * from t1 for update; @@ -44,16 +45,20 @@ begin; insert into t1 values(4); connection b; ---send +# Test that we get a lock timeout. +# We cannot reliably test that the timeout is exactly 1 seconds due to +# process scheduling differences on the host running the test suite. But we +# can test that we are within reasonable range. +set innodb_lock_wait_timeout=2; +set @a= current_timestamp(); +--error ER_LOCK_WAIT_TIMEOUT select * from t1 for update; +set @b= current_timestamp(); +set @c= timestampdiff(SECOND, @a, @b); +select if(@c >= 1 and @c <= 10, 'OK', concat("NOT OK, time passed=", @c)); connection a; -sleep 2; commit; - -connection b; ---error ER_LOCK_WAIT_TIMEOUT -reap; drop table t1; connection default; diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 6ea2817e240..dcb8a9cbc1b 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -991,3 +991,15 @@ fun:_dl_allocate_tls fun:pthread_create* } + +# +# Bug in Glibc 2.9: http://sourceware.org/bugzilla/show_bug.cgi?id=10391 +# Fixed in latest Glibc, but suppressed here for running tests on hosts +# with older Glibc version. +# +{ + Glibc bug in __libc_res_nsend + Memcheck:Cond + fun:__libc_res_nsend + fun:__libc_res_nquery +} From d1d16f9c3f4310f3ab11fc85b47866d79243a471 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Tue, 19 Jan 2010 00:10:00 +0000 Subject: [PATCH 260/344] Fix for BUG#49481 and BUG#49482 reverted. PB2 run uncovered issue that needs further analysis. --- .../suite/rpl/r/rpl_myisam_null_values.result | 24 --------- .../suite/rpl/t/rpl_myisam_null_values.test | 53 ------------------- sql/log_event.cc | 39 +------------- sql/log_event_old.cc | 39 +------------- 4 files changed, 2 insertions(+), 153 deletions(-) delete mode 100644 mysql-test/suite/rpl/r/rpl_myisam_null_values.result delete mode 100644 mysql-test/suite/rpl/t/rpl_myisam_null_values.test diff --git a/mysql-test/suite/rpl/r/rpl_myisam_null_values.result b/mysql-test/suite/rpl/r/rpl_myisam_null_values.result deleted file mode 100644 index 574528a8d79..00000000000 --- a/mysql-test/suite/rpl/r/rpl_myisam_null_values.result +++ /dev/null @@ -1,24 +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 (c1 BIT, c2 INT); -INSERT INTO `t1` VALUES ( 1, 1 ); -UPDATE t1 SET c1=NULL where c2=1; -Comparing tables master:test.t1 and slave:test.t1 -DELETE FROM t1 WHERE c2=1 LIMIT 1; -Comparing tables master:test.t1 and slave:test.t1 -DROP TABLE t1; -CREATE TABLE t1 (c1 CHAR); -INSERT INTO t1 ( c1 ) VALUES ( 'w' ) ; -SELECT * FROM t1; -c1 -w -# should trigger switch to row due to LIMIT -UPDATE t1 SET c1=NULL WHERE c1='w' LIMIT 2; -Comparing tables master:test.t1 and slave:test.t1 -DELETE FROM t1 LIMIT 2; -Comparing tables master:test.t1 and slave:test.t1 -DROP TABLE t1; diff --git a/mysql-test/suite/rpl/t/rpl_myisam_null_values.test b/mysql-test/suite/rpl/t/rpl_myisam_null_values.test deleted file mode 100644 index d9ec95fc510..00000000000 --- a/mysql-test/suite/rpl/t/rpl_myisam_null_values.test +++ /dev/null @@ -1,53 +0,0 @@ -# BUG#49481: RBR: MyISAM and bit fields may cause slave to stop on delete cant find record -# BUG#49482: RBR: Replication may break on deletes when MyISAM tables + char field are used - --- source include/master-slave.inc --- source include/have_binlog_format_mixed_or_row.inc - --- connection master -CREATE TABLE t1 (c1 BIT, c2 INT); -INSERT INTO `t1` VALUES ( 1, 1 ); -UPDATE t1 SET c1=NULL where c2=1; --- sync_slave_with_master - --- let $diff_table_1=master:test.t1 --- let $diff_table_2=slave:test.t1 --- source include/diff_tables.inc - --- connection master -DELETE FROM t1 WHERE c2=1 LIMIT 1; --- sync_slave_with_master - --- let $diff_table_1=master:test.t1 --- let $diff_table_2=slave:test.t1 --- source include/diff_tables.inc - --- connection master -DROP TABLE t1; --- sync_slave_with_master - --- connection master - -CREATE TABLE t1 (c1 CHAR); - -INSERT INTO t1 ( c1 ) VALUES ( 'w' ) ; -SELECT * FROM t1; --- echo # should trigger switch to row due to LIMIT -UPDATE t1 SET c1=NULL WHERE c1='w' LIMIT 2; --- sync_slave_with_master - --- let $diff_table_1=master:test.t1 --- let $diff_table_2=slave:test.t1 --- source include/diff_tables.inc - --- connection master -DELETE FROM t1 LIMIT 2; --- sync_slave_with_master - --- let $diff_table_1=master:test.t1 --- let $diff_table_2=slave:test.t1 --- source include/diff_tables.inc - --- connection master -DROP TABLE t1; --- sync_slave_with_master diff --git a/sql/log_event.cc b/sql/log_event.cc index 61f5e93e29e..6b21087b6aa 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8724,24 +8724,6 @@ static bool record_compare(TABLE *table) } } - /** - Check if we are using MyISAM. - - If this is a myisam table, then we cannot do a memcmp - right away because some NULL fields can still contain - an old value in the row - they are not shown to the user - because the null bit is set, however, the contents are - not cleared. As such, plain memory comparison cannot be - assured to work. See: BUG#49482 and BUG#49481. - - On top of this, we do not store field contents for null - fields in the binlog, so this is extra important when - comparing records fetched from binlog and from storage - engine. - */ - if (table->file->ht->db_type == DB_TYPE_MYISAM) - goto record_compare_field_by_field; - if (table->s->blob_fields + table->s->varchar_fields == 0) { result= cmp_record(table,record[1]); @@ -8757,33 +8739,14 @@ static bool record_compare(TABLE *table) goto record_compare_exit; } -record_compare_field_by_field: - /* Compare updated fields */ for (Field **ptr=table->field ; *ptr ; ptr++) { - Field *f= *ptr; - - /* if just one of the fields is null then there is no match */ - if ((f->is_null_in_record(table->record[0])) == - !(f->is_null_in_record(table->record[1]))) + if ((*ptr)->cmp_binary_offset(table->s->rec_buff_length)) { result= TRUE; goto record_compare_exit; } - - /* if both fields are not null then we can compare */ - if (!(f->is_null_in_record(table->record[0])) && - !(f->is_null_in_record(table->record[1]))) - { - if (f->cmp_binary_offset(table->s->rec_buff_length)) - { - result= TRUE; - goto record_compare_exit; - } - } - - /* if both fields are null then there is a match. compare next field */ } record_compare_exit: diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 72a6e159535..357bc78b1cd 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -351,24 +351,6 @@ static bool record_compare(TABLE *table) } } - /** - Check if we are using MyISAM. - - If this is a myisam table, then we cannot do a memcmp - right away because some NULL fields can still contain - an old value in the row - they are not shown to the user - because the null bit is set, however, the contents are - not cleared. As such, plain memory comparison cannot be - assured to work. See: BUG#49482 and BUG#49481. - - On top of this, we do not store field contents for null - fields in the binlog, so this is extra important when - comparing records fetched from binlog and from storage - engine. - */ - if (table->file->ht->db_type == DB_TYPE_MYISAM) - goto record_compare_field_by_field; - if (table->s->blob_fields + table->s->varchar_fields == 0) { result= cmp_record(table,record[1]); @@ -384,33 +366,14 @@ static bool record_compare(TABLE *table) goto record_compare_exit; } -record_compare_field_by_field: - /* Compare updated fields */ for (Field **ptr=table->field ; *ptr ; ptr++) { - Field *f= *ptr; - - /* if just one of the fields is null then there is no match */ - if ((f->is_null_in_record(table->record[0])) == - !(f->is_null_in_record(table->record[1]))) + if ((*ptr)->cmp_binary_offset(table->s->rec_buff_length)) { result= TRUE; goto record_compare_exit; } - - /* if both fields are not null then we can compare */ - if (!(f->is_null_in_record(table->record[0])) && - !(f->is_null_in_record(table->record[1]))) - { - if (f->cmp_binary_offset(table->s->rec_buff_length)) - { - result= TRUE; - goto record_compare_exit; - } - } - - /* if both fields are null then there is a match. compare next field */ } record_compare_exit: From 80ac8858d5967f525d9b1b798d43146ae0303b53 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Jan 2010 11:36:52 +0100 Subject: [PATCH 261/344] Fix Windows test failures in binlog tests in certain time zones. On Unix systems TZ can be set to change the time zone for specific processes only. But on Windows this does not fully work. It changes some aspects of time zones in the system but not others (notably localtime() vs. file system time stamps). This causes test failures in Windows in certain time zones (but not all), where PURGE BEFORE DATE statements get the wrong files when TZ is set to +03:00 by default. Fix by only setting TZ in the small number of tests that really need it, and leave it untouched in the rest. Thanks to Alex Budovski for helping with this. mysql-test/include/ps_conv.inc: Explicitly set TIME_ZONE, as mysql-test-run.pl now does not set it. mysql-test/mysql-test-run.pl: Do not set TZ by default, as it causes problems on Windows. mysql-test/suite/binlog/r/binlog_unsafe.result: Explicitly set TIME_ZONE, as mysql-test-run.pl now does not set it. mysql-test/suite/binlog/t/binlog_unsafe.test: Explicitly set TIME_ZONE, as mysql-test-run.pl now does not set it. mysql-test/suite/rpl/r/rpl_mixed_ddl_dml.result: Explicitly set TIME_ZONE, as mysql-test-run.pl now does not set it. mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test: Explicitly set TIME_ZONE, as mysql-test-run.pl now does not set it. mysql-test/t/mysqlbinlog2-master.opt: mysql-test-run.pl no longer sets TZ by default, so set it explicitly for this particular test. --- mysql-test/include/ps_conv.inc | 3 +++ mysql-test/mysql-test-run.pl | 6 ++++-- mysql-test/suite/binlog/r/binlog_unsafe.result | 1 + mysql-test/suite/binlog/t/binlog_unsafe.test | 1 + mysql-test/suite/rpl/r/rpl_mixed_ddl_dml.result | 1 + mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test | 1 + mysql-test/t/mysqlbinlog2-master.opt | 1 + 7 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 mysql-test/t/mysqlbinlog2-master.opt diff --git a/mysql-test/include/ps_conv.inc b/mysql-test/include/ps_conv.inc index 8cbe9450063..9ac943d5bdd 100644 --- a/mysql-test/include/ps_conv.inc +++ b/mysql-test/include/ps_conv.inc @@ -30,6 +30,9 @@ --disable_warnings drop table if exists t5 ; --enable_warnings +--disable_query_log +SET TIME_ZONE= '+03:00'; +--enable_query_log set @arg01= 8; set @arg02= 8.0; set @arg03= 80.00000000000e-1; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index eceb6a15cef..bc2061a506c 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3425,7 +3425,7 @@ sub restart_forced_by_test # Return timezone value of tinfo or default value sub timezone { my ($tinfo)= @_; - return $tinfo->{timezone} || "GMT-3"; + return $tinfo->{timezone} || "DEFAULT"; } @@ -3455,7 +3455,9 @@ sub run_testcase ($$) { # Init variables that can change between each test case # ------------------------------------------------------- my $timezone= timezone($tinfo); - $ENV{'TZ'}= $timezone; + if ($timezone ne 'DEFAULT') { + $ENV{'TZ'}= $timezone; + } mtr_verbose("Setting timezone: $timezone"); if ( ! using_extern() ) diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result index 8bbf993a727..6ef322be67a 100644 --- a/mysql-test/suite/binlog/r/binlog_unsafe.result +++ b/mysql-test/suite/binlog/r/binlog_unsafe.result @@ -380,6 +380,7 @@ INSERT INTO t1 VALUES (VERSION()); Warnings: Note 1592 Statement may not be safe to log in statement format. DELETE FROM t1; +SET TIME_ZONE= '+03:00'; SET TIMESTAMP=1000000; INSERT INTO t1 VALUES (CURDATE()), diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test index 1acb4d090ca..e2902698dd0 100644 --- a/mysql-test/suite/binlog/t/binlog_unsafe.test +++ b/mysql-test/suite/binlog/t/binlog_unsafe.test @@ -422,6 +422,7 @@ DELETE FROM t1; # following following functions depend on the TIMESTAMP variable and # don't generate a warning. +SET TIME_ZONE= '+03:00'; SET TIMESTAMP=1000000; INSERT INTO t1 VALUES (CURDATE()), diff --git a/mysql-test/suite/rpl/r/rpl_mixed_ddl_dml.result b/mysql-test/suite/rpl/r/rpl_mixed_ddl_dml.result index 08d3241c48f..308e6a05151 100644 --- a/mysql-test/suite/rpl/r/rpl_mixed_ddl_dml.result +++ b/mysql-test/suite/rpl/r/rpl_mixed_ddl_dml.result @@ -18,6 +18,7 @@ Server_id Host Port Rpl_recovery_rank Master_id drop table t1; stop slave; create table t2(id int auto_increment primary key, created datetime); +SET TIME_ZONE= '+03:00'; set timestamp=12345; insert into t2 set created=now(); select * from t2; diff --git a/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test b/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test index 6a1f81abed3..3df43607bfe 100644 --- a/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test +++ b/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test @@ -23,6 +23,7 @@ connection master; # Test replication of timestamp create table t2(id int auto_increment primary key, created datetime); +SET TIME_ZONE= '+03:00'; set timestamp=12345; insert into t2 set created=now(); select * from t2; diff --git a/mysql-test/t/mysqlbinlog2-master.opt b/mysql-test/t/mysqlbinlog2-master.opt new file mode 100644 index 00000000000..4d69f3359db --- /dev/null +++ b/mysql-test/t/mysqlbinlog2-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 From 4839c42619304989a44dc8f57a800f311ae93bb4 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Tue, 19 Jan 2010 17:02:51 +0100 Subject: [PATCH 262/344] post-push patch for bug#47343. Missing ha_rnd_end in copy_partitions, found due to a DBUG_ASSERT in mysql-pe sql/ha_partition.cc: Post-push patch for bug#47343 Must call ha_rnd_end since ha_rnd_init has been called. --- sql/ha_partition.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 555a0b97ddd..7b9ecd7d902 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1705,6 +1705,7 @@ int ha_partition::copy_partitions(ulonglong * const copied, } DBUG_RETURN(FALSE); error: + m_reorged_file[reorg_part]->ha_rnd_end(); DBUG_RETURN(result); } From 985c06d0a9bd230cbab2e3cbfb7fbf744ea7ee3e Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Wed, 20 Jan 2010 19:08:16 +0000 Subject: [PATCH 263/344] BUG#46364 MyISAM transbuffer problems (NTM problem) It is well-known that due to concurrency issues, a slave can become inconsistent when a transaction contains updates to both transaction and non-transactional tables in statement and mixed modes. In a nutshell, the current code-base tries to preserve causality among the statements by writing non-transactional statements to the txn-cache which is flushed upon commit. However, modifications done to non-transactional tables on behalf of a transaction become immediately visible to other connections but may not immediately get into the binary log and therefore consistency may be broken. In general, it is impossible to automatically detect causality/dependency among statements by just analyzing the statements sent to the server. This happen because dependency may be hidden in the application code and it is necessary to know a priori all the statements processed in the context of a transaction such as in a procedure. Moreover, even for the few cases that we could automatically address in the server, the computation effort required could make the approach infeasible. So, in this patch we introduce the option - "--binlog-direct-non-transactional-updates" that can be used to bypass the current behavior in order to write directly to binary log statements that change non-transactional tables. mysql-test/extra/rpl_tests/rpl_mixing_engines.inc: Backported this from Celosia to improve the test cases related to the NTM issue. sql/log.cc: Checks the --binlog-direct-non-transactional-updates before choosing to either use the trxn-cache or not. sql/mysqld.cc: Introduces the option --binlog-direct-non-transactional-updates. sql/set_var.cc: Introduces the option --binlog-direct-non-transactional-updates. sql/sql_class.h: Introduces the option --binlog-direct-non-transactional-updates. --- .../extra/rpl_tests/rpl_mixing_engines.inc | 554 +++++++ .../suite/rpl/r/rpl_stm_binlog_direct.result | 1360 +++++++++++++++++ .../rpl/t/rpl_stm_binlog_direct-master.opt | 1 + .../suite/rpl/t/rpl_stm_binlog_direct.test | 230 +++ sql/log.cc | 23 +- sql/mysqld.cc | 7 +- sql/set_var.cc | 2 + sql/sql_class.h | 1 + 8 files changed, 2170 insertions(+), 8 deletions(-) create mode 100644 mysql-test/extra/rpl_tests/rpl_mixing_engines.inc create mode 100644 mysql-test/suite/rpl/r/rpl_stm_binlog_direct.result create mode 100644 mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt create mode 100644 mysql-test/suite/rpl/t/rpl_stm_binlog_direct.test diff --git a/mysql-test/extra/rpl_tests/rpl_mixing_engines.inc b/mysql-test/extra/rpl_tests/rpl_mixing_engines.inc new file mode 100644 index 00000000000..6dde3e079a1 --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_mixing_engines.inc @@ -0,0 +1,554 @@ +################################################################################ +# This is an auxiliary file used by rpl_mixing_engines.test, and that it +# executes SQL statements according to a format string, as specified in +# rpl_mixing_engines.test. In addition, it accepts the special format +# strings 'configure' and 'clean', used before and after everything else. +################################################################################ + +if (`SELECT HEX(@commands) = HEX('configure')`) +{ + connection master; + + SET SQL_LOG_BIN=0; + eval CREATE TABLE nt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE nt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE nt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE nt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE nt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE nt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE tt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval CREATE TABLE tt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval CREATE TABLE tt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval CREATE TABLE tt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval CREATE TABLE tt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval CREATE TABLE tt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval SET SQL_LOG_BIN=1; + + connection slave; + + SET SQL_LOG_BIN=0; + eval CREATE TABLE nt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE nt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE nt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE nt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE nt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE nt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; + eval CREATE TABLE tt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval CREATE TABLE tt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval CREATE TABLE tt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval CREATE TABLE tt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval CREATE TABLE tt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + eval CREATE TABLE tt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = $engine_type; + SET SQL_LOG_BIN=1; + + connection master; + + INSERT INTO nt_1(trans_id, stmt_id) VALUES(1,1); + INSERT INTO nt_2(trans_id, stmt_id) VALUES(1,1); + INSERT INTO nt_3(trans_id, stmt_id) VALUES(1,1); + INSERT INTO nt_4(trans_id, stmt_id) VALUES(1,1); + INSERT INTO nt_5(trans_id, stmt_id) VALUES(1,1); + INSERT INTO nt_6(trans_id, stmt_id) VALUES(1,1); + + INSERT INTO tt_1(trans_id, stmt_id) VALUES(1,1); + INSERT INTO tt_2(trans_id, stmt_id) VALUES(1,1); + INSERT INTO tt_3(trans_id, stmt_id) VALUES(1,1); + INSERT INTO tt_4(trans_id, stmt_id) VALUES(1,1); + INSERT INTO tt_5(trans_id, stmt_id) VALUES(1,1); + INSERT INTO tt_6(trans_id, stmt_id) VALUES(1,1); + + DELIMITER |; + + CREATE PROCEDURE pc_i_tt_5_suc (IN p_trans_id INTEGER, IN p_stmt_id INTEGER) + BEGIN + DECLARE in_stmt_id INTEGER; + SELECT max(stmt_id) INTO in_stmt_id FROM tt_5 WHERE trans_id= p_trans_id; + SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id; + INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id); + INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1); + END| + + CREATE PROCEDURE pc_i_nt_5_suc (IN p_trans_id INTEGER, IN p_stmt_id INTEGER) + BEGIN + DECLARE in_stmt_id INTEGER; + SELECT max(stmt_id) INTO in_stmt_id FROM nt_5 WHERE trans_id= p_trans_id; + SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id; + INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id); + INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1); + END| + + CREATE FUNCTION fc_i_tt_5_suc (p_trans_id INTEGER, p_stmt_id INTEGER) RETURNS VARCHAR(64) + BEGIN + DECLARE in_stmt_id INTEGER; + SELECT max(stmt_id) INTO in_stmt_id FROM tt_5 WHERE trans_id= p_trans_id; + SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id; + INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id); + INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1); + RETURN "fc_i_tt_5_suc"; + END| + + CREATE FUNCTION fc_i_nt_5_suc (p_trans_id INTEGER, p_stmt_id INTEGER) RETURNS VARCHAR(64) + BEGIN + DECLARE in_stmt_id INTEGER; + SELECT max(stmt_id) INTO in_stmt_id FROM nt_5 WHERE trans_id= p_trans_id; + SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id; + INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id); + INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1); + RETURN "fc_i_nt_5_suc"; + END| + + CREATE TRIGGER tr_i_tt_3_to_nt_3 AFTER INSERT ON tt_3 FOR EACH ROW + BEGIN + DECLARE in_stmt_id INTEGER; + SELECT max(stmt_id) INTO in_stmt_id FROM nt_3 WHERE trans_id= NEW.trans_id; + SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id; + INSERT INTO nt_3(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id); + INSERT INTO nt_3(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1); + END| + + CREATE TRIGGER tr_i_nt_4_to_tt_4 AFTER INSERT ON nt_4 FOR EACH ROW + BEGIN + DECLARE in_stmt_id INTEGER; + SELECT max(stmt_id) INTO in_stmt_id FROM tt_4 WHERE trans_id= NEW.trans_id; + SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id; + INSERT INTO tt_4(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id); + INSERT INTO tt_4(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1); + END| + + CREATE TRIGGER tr_i_tt_5_to_tt_6 AFTER INSERT ON tt_5 FOR EACH ROW + BEGIN + DECLARE in_stmt_id INTEGER; + SELECT max(stmt_id) INTO in_stmt_id FROM tt_6 WHERE trans_id= NEW.trans_id; + SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id, 1), 1) INTO in_stmt_id; + INSERT INTO tt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id); + INSERT INTO tt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1); + END| + + CREATE TRIGGER tr_i_nt_5_to_nt_6 AFTER INSERT ON nt_5 FOR EACH ROW + BEGIN + DECLARE in_stmt_id INTEGER; + SELECT max(stmt_id) INTO in_stmt_id FROM nt_6 WHERE trans_id= NEW.trans_id; + SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id; + INSERT INTO nt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id); + INSERT INTO nt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1); + END| + + DELIMITER ;| + + let $pos_trans_command= query_get_value("SHOW MASTER STATUS", Position, 1); + + let $trans_id= 7; + let $tb_id= 1; + let $stmt_id= 1; + let $commands= ''; + + SET @commands= ''; +} + +if (`SELECT HEX(@commands) = HEX('clean')`) +{ + connection master; + + DROP TABLE tt_1; + DROP TABLE tt_2; + DROP TABLE tt_3; + DROP TABLE tt_4; + DROP TABLE tt_5; + DROP TABLE tt_6; + + DROP TABLE nt_1; + DROP TABLE nt_2; + DROP TABLE nt_3; + DROP TABLE nt_4; + DROP TABLE nt_5; + DROP TABLE nt_6; + + DROP PROCEDURE pc_i_tt_5_suc; + DROP PROCEDURE pc_i_nt_5_suc; + DROP FUNCTION fc_i_tt_5_suc; + DROP FUNCTION fc_i_nt_5_suc; + + sync_slave_with_master; + + SET @commands= ''; +} + +while (`SELECT HEX(@commands) != HEX('')`) +{ + --disable_query_log + SET @command= SUBSTRING_INDEX(@commands, ' ', 1); + let $command= `SELECT @command`; + --eval SET @check_commands= '$commands' + if (`SELECT HEX(@check_commands) = HEX('''')`) + { + let $commands= `SELECT @commands`; + } + --echo -b-b-b-b-b-b-b-b-b-b-b- >> $command << -b-b-b-b-b-b-b-b-b-b-b- + let $pos_command= query_get_value("SHOW MASTER STATUS", Position, 1); + --enable_query_log + if (`SELECT HEX(@command) = HEX('B')`) + { + eval BEGIN; + } + if (`SELECT HEX(@command) = HEX('T')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval INSERT INTO tt_1(trans_id, stmt_id) VALUES ($trans_id, $stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('T-trig')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval INSERT INTO tt_5(trans_id, stmt_id) VALUES ($trans_id, $stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('T-func')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval SELECT fc_i_tt_5_suc ($trans_id, $stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('T-proc')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval CALL pc_i_tt_5_suc ($trans_id, $stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('eT')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from tt_1`; + let $old_stmt_id= `SELECT max(stmt_id) from tt_1 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO tt_1(trans_id, stmt_id) VALUES ($old_trans_id, $old_stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('Te')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from tt_1`; + let $old_stmt_id= `SELECT max(stmt_id) from tt_1 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO tt_1(trans_id, stmt_id) VALUES ($trans_id, $stmt_id), ($old_trans_id, $old_stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('Te-trig')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from tt_5`; + let $old_stmt_id= `SELECT max(stmt_id) from tt_5 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO tt_5(trans_id, stmt_id) VALUES ($trans_id, $stmt_id), ($old_trans_id, $old_stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('Te-func')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from tt_1`; + let $old_stmt_id= `SELECT max(stmt_id) from tt_1 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO tt_1(trans_id, stmt_id, info) VALUES ($trans_id, $stmt_id, ''), ($old_trans_id, $old_stmt_id, fc_i_tt_5_suc ($trans_id, $stmt_id)); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('N')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval INSERT INTO nt_1(trans_id, stmt_id) VALUES ($trans_id, $stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('N-trig')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval INSERT INTO nt_5(trans_id, stmt_id) VALUES ($trans_id, $stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('N-func')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval SELECT fc_i_nt_5_suc ($trans_id, $stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('N-proc')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval CALL pc_i_nt_5_suc ($trans_id, $stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('eN')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from nt_1`; + let $old_stmt_id= `SELECT max(stmt_id) from nt_1 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO nt_1(trans_id, stmt_id) VALUES ($old_trans_id, $old_stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('Ne')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from nt_1`; + let $old_stmt_id= `SELECT max(stmt_id) from nt_1 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO nt_1(trans_id, stmt_id) VALUES ($trans_id, $stmt_id), ($old_trans_id, $old_stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('Ne-trig')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from nt_5`; + let $old_stmt_id= `SELECT max(stmt_id) from nt_5 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO nt_5(trans_id, stmt_id) VALUES ($trans_id, $stmt_id), ($old_trans_id, $old_stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('Ne-func')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from nt_1`; + let $old_stmt_id= `SELECT max(stmt_id) from nt_1 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO nt_1(trans_id, stmt_id, info) VALUES ($trans_id, $stmt_id, ''), ($old_trans_id, $old_stmt_id, fc_i_nt_5_suc ($trans_id, $stmt_id)); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('tN')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval INSERT INTO nt_1(trans_id, stmt_id, info) SELECT $trans_id, $stmt_id, COUNT(*) FROM tt_1; + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('tNe')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from nt_1`; + let $old_stmt_id= `SELECT max(stmt_id) from nt_1 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO nt_1(trans_id, stmt_id, info) SELECT $trans_id, $stmt_id, COUNT(*) FROM tt_1 UNION SELECT $old_trans_id, $old_stmt_id, COUNT(*) FROM tt_1; + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('nT')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval INSERT INTO tt_1(trans_id, stmt_id, info) SELECT $trans_id, $stmt_id, COUNT(*) FROM nt_1; + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('nTe')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from tt_1`; + let $old_stmt_id= `SELECT max(stmt_id) from tt_1 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO tt_1(trans_id, stmt_id, info) SELECT $trans_id, $stmt_id, COUNT(*) FROM nt_1 UNION SELECT $old_trans_id, $old_stmt_id, COUNT(*) FROM nt_1; + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('NT')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval UPDATE nt_3, tt_3 SET nt_3.info= "new text $trans_id --> $stmt_id", tt_3.info= "new text $trans_id --> $stmt_id" where nt_3.trans_id = tt_3.trans_id and tt_3.trans_id = 1; + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('NT-trig')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval INSERT INTO nt_4(trans_id, stmt_id) VALUES ($trans_id, $stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('NT-func')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval INSERT INTO nt_5(trans_id, stmt_id, info) VALUES ($trans_id, $stmt_id, fc_i_tt_5_suc($trans_id, $stmt_id)); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('NeT-trig')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from nt_4`; + let $old_stmt_id= `SELECT max(stmt_id) from nt_4 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO nt_4(trans_id, stmt_id) VALUES ($trans_id, $stmt_id), ($old_trans_id, $old_stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('NeT-func')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from nt_5`; + let $old_stmt_id= `SELECT max(stmt_id) from nt_5 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO nt_5(trans_id, stmt_id, info) VALUES ($trans_id, $stmt_id, ''), ($old_trans_id, $old_stmt_id, fc_i_tt_5_suc ($trans_id, $stmt_id)); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('TN')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval UPDATE tt_4, nt_4 SET tt_4.info= "new text $trans_id --> $stmt_id", nt_4.info= "new text $trans_id --> $stmt_id" where nt_4.trans_id = tt_4.trans_id and tt_4.trans_id = 1; + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('TN-trig')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval INSERT INTO tt_3(trans_id, stmt_id) VALUES ($trans_id, $stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('TN-func')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + eval INSERT INTO tt_5(trans_id, stmt_id, info) VALUES ($trans_id, $stmt_id, fc_i_nt_5_suc($trans_id, $stmt_id)); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('TeN-trig')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from tt_3`; + let $old_stmt_id= `SELECT max(stmt_id) from tt_3 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO tt_3(trans_id, stmt_id) VALUES ($trans_id, $stmt_id), ($old_trans_id, $old_stmt_id); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('TeN-func')`) + { + #--echo DEBUG-- (trans_id, stmt_id) --> ($trans_id, $stmt_id) + let $old_trans_id= `SELECT max(trans_id) from tt_5`; + let $old_stmt_id= `SELECT max(stmt_id) from tt_5 where trans_id= $old_trans_id`; + --error ER_DUP_ENTRY, ER_DUP_KEY + eval INSERT INTO tt_5(trans_id, stmt_id, info) VALUES ($trans_id, $stmt_id, ''), ($old_trans_id, $old_stmt_id, fc_i_nt_5_suc ($trans_id, $stmt_id)); + inc $stmt_id; + } + if (`SELECT HEX(@command) = HEX('CS-T->T')`) + { + --eval CREATE TABLE tt_xx_$tb_id (PRIMARY KEY(trans_id, stmt_id)) engine=$engine_type SELECT * FROM tt_1; + } + if (`SELECT HEX(@command) = HEX('CS-N->N')`) + { + --eval CREATE TABLE nt_xx_$tb_id (PRIMARY KEY(trans_id, stmt_id)) engine=MyIsam SELECT * FROM nt_1; + } + if (`SELECT HEX(@command) = HEX('CS-T->N')`) + { + --eval CREATE TABLE tt_xx_$tb_id (PRIMARY KEY(trans_id, stmt_id)) engine=$engine_type SELECT * FROM nt_1; + } + if (`SELECT HEX(@command) = HEX('CS-N->T')`) + { + --eval CREATE TABLE nt_xx_$tb_id (PRIMARY KEY(trans_id, stmt_id)) engine=MyIsam SELECT * FROM tt_1; + } + if (`SELECT HEX(@command) = HEX('CSe-T->T')`) + { + --error ER_DUP_ENTRY, ER_DUP_KEY + --eval CREATE TABLE tt_xx_$tb_id (PRIMARY KEY (stmt_id)) engine=$engine_type SELECT stmt_id FROM tt_1; + } + if (`SELECT HEX(@command) = HEX('CSe-N->N')`) + { + --error ER_DUP_ENTRY, ER_DUP_KEY + --eval CREATE TABLE nt_xx_$tb_id (PRIMARY KEY (stmt_id)) engine=MyIsam SELECT stmt_id FROM nt_1; + } + if (`SELECT HEX(@command) = HEX('CSe-T->N')`) + { + --error ER_DUP_ENTRY, ER_DUP_KEY + --eval CREATE TABLE tt_xx_$tb_id (PRIMARY KEY (stmt_id)) engine=$engine_type SELECT stmt_id FROM nt_1; + } + if (`SELECT HEX(@command) = HEX('CSe-N->T')`) + { + --error ER_DUP_ENTRY, ER_DUP_KEY + --eval CREATE TABLE nt_xx_$tb_id (PRIMARY KEY (stmt_id)) engine=MyIsam SELECT stmt_id FROM tt_1; + } + if (`SELECT HEX(@command) = HEX('CT')`) + { + --eval CREATE TEMPORARY TABLE tt_xx_$tb_id (a int) engine=$engine_type; + } + if (`SELECT HEX(@command) = HEX('IS-T<-N')`) + { + --eval INSERT INTO tt_xx_$tb_id(trans_id, stmt_id, info) SELECT trans_id, stmt_id, USER() FROM nt_1; + } + if (`SELECT HEX(@command) = HEX('ISe-T<-N')`) + { + --error ER_DUP_ENTRY, ER_DUP_KEY + --eval INSERT INTO tt_xx_$tb_id(trans_id, stmt_id, info) SELECT trans_id, trans_id, USER() FROM nt_1; + } + if (`SELECT HEX(@command) = HEX('IS-N<-T')`) + { + --eval INSERT INTO nt_xx_$tb_id(trans_id, stmt_id, info) SELECT trans_id, stmt_id, USER() FROM tt_1; + } + if (`SELECT HEX(@command) = HEX('ISe-N<-T')`) + { + --error ER_DUP_ENTRY, ER_DUP_KEY + --eval INSERT INTO nt_xx_$tb_id(trans_id, stmt_id, info) SELECT trans_id, trans_id, USER() FROM tt_1; + } + if (`SELECT HEX(@command) = HEX('IS-T<-T')`) + { + --eval INSERT INTO tt_xx_$tb_id(trans_id, stmt_id, info) SELECT trans_id, stmt_id, USER() FROM tt_1; + } + if (`SELECT HEX(@command) = HEX('ISe-T<-T')`) + { + --error ER_DUP_ENTRY, ER_DUP_KEY + --eval INSERT INTO tt_xx_$tb_id(trans_id, stmt_id, info) SELECT trans_id, trans_id, USER() FROM tt_1; + } + if (`SELECT HEX(@command) = HEX('IS-N<-N')`) + { + --eval INSERT INTO nt_xx_$tb_id(trans_id, stmt_id, info) SELECT trans_id, stmt_id, USER() FROM nt_1; + } + if (`SELECT HEX(@command) = HEX('ISe-N<-N')`) + { + --error ER_DUP_ENTRY, ER_DUP_KEY + --eval INSERT INTO nt_xx_$tb_id(trans_id, stmt_id, info) SELECT trans_id, trans_id, USER() FROM nt_1; + } + if (`SELECT HEX(@command) = HEX('trunc-CS-T')`) + { + eval TRUNCATE TABLE tt_xx_$tb_id; + } + if (`SELECT HEX(@command) = HEX('trunc-CS-N')`) + { + eval TRUNCATE TABLE nt_xx_$tb_id; + } + if (`SELECT HEX(@command) = HEX('trunc-CT')`) + { + eval TRUNCATE TABLE tt_xx_$tb_id; + } + if (`SELECT HEX(@command) = HEX('drop-CS')`) + { + --disable_warnings + eval DROP TABLE IF EXISTS tt_xx_$tb_id, nt_xx_$tb_id; + inc $tb_id; + --enable_warnings + } + if (`SELECT HEX(@command) = HEX('drop-CT')`) + { + --disable_warnings + eval DROP TEMPORARY TABLE IF EXISTS tt_xx_$tb_id; + inc $tb_id; + --enable_warnings + } + if (`SELECT HEX(@command) = HEX('C')`) + { + --error 0, ER_GET_ERRMSG + eval COMMIT; + } + if (`SELECT HEX(@command) = HEX('R')`) + { + --error 0, ER_GET_ERRMSG + eval ROLLBACK; + } + if (`SELECT HEX(@command) = HEX('S1')`) + { + eval SAVEPOINT s1; + } + if (`SELECT HEX(@command) = HEX('R1')`) + { + eval ROLLBACK TO s1; + } + --disable_query_log + SET @commands= LTRIM(SUBSTRING(@commands, LENGTH(@command) + 1)); + inc $stmt_id; + + let $binlog_start= $pos_command; + --source include/show_binlog_events.inc + --echo -e-e-e-e-e-e-e-e-e-e-e- >> $command << -e-e-e-e-e-e-e-e-e-e-e- + if (`SELECT HEX(@commands) = HEX('')`) + { + let $binlog_start= $pos_trans_command; + --echo -b-b-b-b-b-b-b-b-b-b-b- >> $commands << -b-b-b-b-b-b-b-b-b-b-b- + --source include/show_binlog_events.inc + --echo -e-e-e-e-e-e-e-e-e-e-e- >> $commands << -e-e-e-e-e-e-e-e-e-e-e- + --echo + let $pos_trans_command= query_get_value("SHOW MASTER STATUS", Position, 1); + let $stmt_id= 1; + inc $trans_id; + let $commands= ''; + } +} diff --git a/mysql-test/suite/rpl/r/rpl_stm_binlog_direct.result b/mysql-test/suite/rpl/r/rpl_stm_binlog_direct.result new file mode 100644 index 00000000000..818e383e2f1 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_stm_binlog_direct.result @@ -0,0 +1,1360 @@ +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 @@session.binlog_direct_non_transactional_updates= TRUE; +######################################################################### +# CONFIGURATION +######################################################################### +SET @commands= 'configure'; +SET SQL_LOG_BIN=0; +CREATE TABLE nt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE nt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE nt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE nt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE nt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE nt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE tt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +CREATE TABLE tt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +CREATE TABLE tt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +CREATE TABLE tt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +CREATE TABLE tt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +CREATE TABLE tt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +SET SQL_LOG_BIN=1; +SET SQL_LOG_BIN=0; +CREATE TABLE nt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE nt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE nt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE nt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE nt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE nt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = MyISAM; +CREATE TABLE tt_1 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +CREATE TABLE tt_2 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +CREATE TABLE tt_3 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +CREATE TABLE tt_4 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +CREATE TABLE tt_5 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +CREATE TABLE tt_6 (trans_id INT, stmt_id INT, info VARCHAR(64), PRIMARY KEY(trans_id, stmt_id)) ENGINE = Innodb; +SET SQL_LOG_BIN=1; +INSERT INTO nt_1(trans_id, stmt_id) VALUES(1,1); +INSERT INTO nt_2(trans_id, stmt_id) VALUES(1,1); +INSERT INTO nt_3(trans_id, stmt_id) VALUES(1,1); +INSERT INTO nt_4(trans_id, stmt_id) VALUES(1,1); +INSERT INTO nt_5(trans_id, stmt_id) VALUES(1,1); +INSERT INTO nt_6(trans_id, stmt_id) VALUES(1,1); +INSERT INTO tt_1(trans_id, stmt_id) VALUES(1,1); +INSERT INTO tt_2(trans_id, stmt_id) VALUES(1,1); +INSERT INTO tt_3(trans_id, stmt_id) VALUES(1,1); +INSERT INTO tt_4(trans_id, stmt_id) VALUES(1,1); +INSERT INTO tt_5(trans_id, stmt_id) VALUES(1,1); +INSERT INTO tt_6(trans_id, stmt_id) VALUES(1,1); +CREATE PROCEDURE pc_i_tt_5_suc (IN p_trans_id INTEGER, IN p_stmt_id INTEGER) +BEGIN +DECLARE in_stmt_id INTEGER; +SELECT max(stmt_id) INTO in_stmt_id FROM tt_5 WHERE trans_id= p_trans_id; +SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id; +INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id); +INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1); +END| +CREATE PROCEDURE pc_i_nt_5_suc (IN p_trans_id INTEGER, IN p_stmt_id INTEGER) +BEGIN +DECLARE in_stmt_id INTEGER; +SELECT max(stmt_id) INTO in_stmt_id FROM nt_5 WHERE trans_id= p_trans_id; +SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id; +INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id); +INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1); +END| +CREATE FUNCTION fc_i_tt_5_suc (p_trans_id INTEGER, p_stmt_id INTEGER) RETURNS VARCHAR(64) +BEGIN +DECLARE in_stmt_id INTEGER; +SELECT max(stmt_id) INTO in_stmt_id FROM tt_5 WHERE trans_id= p_trans_id; +SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id; +INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id); +INSERT INTO tt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1); +RETURN "fc_i_tt_5_suc"; +END| +CREATE FUNCTION fc_i_nt_5_suc (p_trans_id INTEGER, p_stmt_id INTEGER) RETURNS VARCHAR(64) +BEGIN +DECLARE in_stmt_id INTEGER; +SELECT max(stmt_id) INTO in_stmt_id FROM nt_5 WHERE trans_id= p_trans_id; +SELECT COALESCE(greatest(in_stmt_id + 1, p_stmt_id), 1) INTO in_stmt_id; +INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id); +INSERT INTO nt_5(trans_id, stmt_id) VALUES (p_trans_id, in_stmt_id + 1); +RETURN "fc_i_nt_5_suc"; +END| +CREATE TRIGGER tr_i_tt_3_to_nt_3 AFTER INSERT ON tt_3 FOR EACH ROW +BEGIN +DECLARE in_stmt_id INTEGER; +SELECT max(stmt_id) INTO in_stmt_id FROM nt_3 WHERE trans_id= NEW.trans_id; +SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id; +INSERT INTO nt_3(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id); +INSERT INTO nt_3(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1); +END| +CREATE TRIGGER tr_i_nt_4_to_tt_4 AFTER INSERT ON nt_4 FOR EACH ROW +BEGIN +DECLARE in_stmt_id INTEGER; +SELECT max(stmt_id) INTO in_stmt_id FROM tt_4 WHERE trans_id= NEW.trans_id; +SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id; +INSERT INTO tt_4(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id); +INSERT INTO tt_4(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1); +END| +CREATE TRIGGER tr_i_tt_5_to_tt_6 AFTER INSERT ON tt_5 FOR EACH ROW +BEGIN +DECLARE in_stmt_id INTEGER; +SELECT max(stmt_id) INTO in_stmt_id FROM tt_6 WHERE trans_id= NEW.trans_id; +SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id, 1), 1) INTO in_stmt_id; +INSERT INTO tt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id); +INSERT INTO tt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1); +END| +CREATE TRIGGER tr_i_nt_5_to_nt_6 AFTER INSERT ON nt_5 FOR EACH ROW +BEGIN +DECLARE in_stmt_id INTEGER; +SELECT max(stmt_id) INTO in_stmt_id FROM nt_6 WHERE trans_id= NEW.trans_id; +SELECT COALESCE(greatest(in_stmt_id + 1, NEW.stmt_id), 1) INTO in_stmt_id; +INSERT INTO nt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id); +INSERT INTO nt_6(trans_id, stmt_id) VALUES (NEW.trans_id, in_stmt_id + 1); +END| +SET @commands= ''; +######################################################################### +# 1 - BINLOG ORDER +######################################################################### + + + + +# +#3) Generates in the binlog what follows: +# --> STMT "N B T C" entries, format S. +# +SET @commands= 'B T N C'; +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (7, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (7, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (7, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (7, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T N C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (7, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (7, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T N C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (8, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_5(trans_id, stmt_id) VALUES (8, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (8, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (8, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T N-trig C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (8, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (8, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T N-trig C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (9, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_nt_5_suc (9, 4); +fc_i_nt_5_suc (9, 4) +fc_i_nt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(9,4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (9, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T N-func C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(9,4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (9, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T N-func C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (10, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_nt_5_suc (10, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',10), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',10), NAME_CONST('in_stmt_id',1) + 1) +-e-e-e-e-e-e-e-e-e-e-e- >> N-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (10, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T N-proc C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',10), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',10), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (10, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T N-proc C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_5(trans_id, stmt_id) VALUES (11, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (11, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (11, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (11, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig N C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (11, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (11, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig N C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_5(trans_id, stmt_id) VALUES (12, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_5(trans_id, stmt_id) VALUES (12, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (12, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (12, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig N-trig C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (12, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (12, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig N-trig C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_5(trans_id, stmt_id) VALUES (13, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_nt_5_suc (13, 4); +fc_i_nt_5_suc (13, 4) +fc_i_nt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(13,4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (13, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig N-func C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(13,4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (13, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig N-func C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_5(trans_id, stmt_id) VALUES (14, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_nt_5_suc (14, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',14), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',14), NAME_CONST('in_stmt_id',1) + 1) +-e-e-e-e-e-e-e-e-e-e-e- >> N-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (14, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig N-proc C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',14), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',14), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (14, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig N-proc C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_tt_5_suc (15, 2); +fc_i_tt_5_suc (15, 2) +fc_i_tt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (15, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (15, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(15,2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-func N C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (15, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(15,2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-func N C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_tt_5_suc (16, 2); +fc_i_tt_5_suc (16, 2) +fc_i_tt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_5(trans_id, stmt_id) VALUES (16, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (16, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(16,2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-func N-trig C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (16, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(16,2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-func N-trig C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_tt_5_suc (17, 2); +fc_i_tt_5_suc (17, 2) +fc_i_tt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_nt_5_suc (17, 4); +fc_i_nt_5_suc (17, 4) +fc_i_nt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(17,4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(17,2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-func N-func C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(17,4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(17,2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-func N-func C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_tt_5_suc (18, 2); +fc_i_tt_5_suc (18, 2) +fc_i_tt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_nt_5_suc (18, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',18), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',18), NAME_CONST('in_stmt_id',1) + 1) +-e-e-e-e-e-e-e-e-e-e-e- >> N-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(18,2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-func N-proc C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',18), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',18), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(18,2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-func N-proc C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_tt_5_suc (19, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (19, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (19, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',19), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',19), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc N C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (19, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',19), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',19), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc N C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_tt_5_suc (20, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_5(trans_id, stmt_id) VALUES (20, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (20, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',20), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',20), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc N-trig C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (20, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',20), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',20), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc N-trig C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_tt_5_suc (21, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_nt_5_suc (21, 4); +fc_i_nt_5_suc (21, 4) +fc_i_nt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(21,4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',21), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',21), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc N-func C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(21,4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',21), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',21), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc N-func C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_tt_5_suc (22, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_nt_5_suc (22, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',22), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',22), NAME_CONST('in_stmt_id',1) + 1) +-e-e-e-e-e-e-e-e-e-e-e- >> N-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',22), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',22), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc N-proc C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',22), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',22), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',22), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',22), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc N-proc C << -e-e-e-e-e-e-e-e-e-e-e- + + + + + +# +#3.e) Generates in the binlog what follows if T-* fails: +# --> STMT "N" entry, format S. +# Otherwise, what follows if N-* fails and a N-Table is changed: +# --> STMT "N B T C" entries, format S. +# +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> eT << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (10, 2); +Got one of the listed errors +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> eT << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (23, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (23, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B eT N C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (23, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> B eT N C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> Te << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (24, 2), (10, 2); +Got one of the listed errors +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> Te << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (24, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (24, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B Te N C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (24, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> B Te N C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (25, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> eN << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (24, 4); +Got one of the listed errors +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> eN << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (25, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T eN C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (25, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T eN C << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (26, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> Ne << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (26, 4), (24, 4); +Got one of the listed errors +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (26, 4), (24, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> Ne << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> C << -b-b-b-b-b-b-b-b-b-b-b- +COMMIT; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (26, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> C << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T Ne C << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (26, 4), (24, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (26, 2) +master-bin.000001 # Xid # # COMMIT /* XID */ +-e-e-e-e-e-e-e-e-e-e-e- >> B T Ne C << -e-e-e-e-e-e-e-e-e-e-e- + + + + + +# +#4) Generates in the binlog what follows: +# --> STMT "N B T R" entries, format S. +# +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (27, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (27, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (27, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (27, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T N R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (27, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (27, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T N R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (28, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_5(trans_id, stmt_id) VALUES (28, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (28, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (28, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T N-trig R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (28, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (28, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T N-trig R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (29, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_nt_5_suc (29, 4); +fc_i_nt_5_suc (29, 4) +fc_i_nt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(29,4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (29, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T N-func R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(29,4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (29, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T N-func R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (30, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_nt_5_suc (30, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',30), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',30), NAME_CONST('in_stmt_id',1) + 1) +-e-e-e-e-e-e-e-e-e-e-e- >> N-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (30, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T N-proc R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',30), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',30), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (30, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T N-proc R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_5(trans_id, stmt_id) VALUES (31, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (31, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (31, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (31, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig N R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (31, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (31, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig N R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_5(trans_id, stmt_id) VALUES (32, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_5(trans_id, stmt_id) VALUES (32, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (32, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (32, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig N-trig R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (32, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (32, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig N-trig R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_5(trans_id, stmt_id) VALUES (33, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_nt_5_suc (33, 4); +fc_i_nt_5_suc (33, 4) +fc_i_nt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(33,4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (33, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig N-func R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(33,4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (33, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig N-func R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_5(trans_id, stmt_id) VALUES (34, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_nt_5_suc (34, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',34), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',34), NAME_CONST('in_stmt_id',1) + 1) +-e-e-e-e-e-e-e-e-e-e-e- >> N-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (34, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-trig N-proc R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',34), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',34), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES (34, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-trig N-proc R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_tt_5_suc (35, 2); +fc_i_tt_5_suc (35, 2) +fc_i_tt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (35, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (35, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(35,2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-func N R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (35, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(35,2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-func N R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_tt_5_suc (36, 2); +fc_i_tt_5_suc (36, 2) +fc_i_tt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_5(trans_id, stmt_id) VALUES (36, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (36, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(36,2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-func N-trig R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (36, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(36,2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-func N-trig R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_tt_5_suc (37, 2); +fc_i_tt_5_suc (37, 2) +fc_i_tt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_nt_5_suc (37, 4); +fc_i_nt_5_suc (37, 4) +fc_i_nt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(37,4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(37,2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-func N-func R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(37,4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(37,2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-func N-func R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_tt_5_suc (38, 2); +fc_i_tt_5_suc (38, 2) +fc_i_tt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_nt_5_suc (38, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',38), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',38), NAME_CONST('in_stmt_id',1) + 1) +-e-e-e-e-e-e-e-e-e-e-e- >> N-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(38,2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-func N-proc R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',38), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',38), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_tt_5_suc`(38,2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-func N-proc R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_tt_5_suc (39, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (39, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (39, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',39), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',39), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc N R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (39, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',39), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',39), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc N R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_tt_5_suc (40, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-trig << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_5(trans_id, stmt_id) VALUES (40, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (40, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-trig << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',40), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',40), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc N-trig R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES (40, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',40), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',40), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc N-trig R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_tt_5_suc (41, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-func << -b-b-b-b-b-b-b-b-b-b-b- +SELECT fc_i_nt_5_suc (41, 4); +fc_i_nt_5_suc (41, 4) +fc_i_nt_5_suc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(41,4) +-e-e-e-e-e-e-e-e-e-e-e- >> N-func << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',41), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',41), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc N-func R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; SELECT `test`.`fc_i_nt_5_suc`(41,4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',41), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',41), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc N-func R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_tt_5_suc (42, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N-proc << -b-b-b-b-b-b-b-b-b-b-b- +CALL pc_i_nt_5_suc (42, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',42), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',42), NAME_CONST('in_stmt_id',1) + 1) +-e-e-e-e-e-e-e-e-e-e-e- >> N-proc << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',42), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',42), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T-proc N-proc R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',42), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO nt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',42), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',42), NAME_CONST('in_stmt_id',1)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_5(trans_id, stmt_id) VALUES ( NAME_CONST('p_trans_id',42), NAME_CONST('in_stmt_id',1) + 1) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T-proc N-proc R << -e-e-e-e-e-e-e-e-e-e-e- + + + + + +# +#4.e) Generates in the binlog what follows if T* fails: +# --> STMT "B N C" entry, format S. +# Otherwise, what follows if N* fails and a N-Table is changed: +# --> STMT "N" entries, format S. +# +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> eT << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (26, 2); +Got one of the listed errors +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> eT << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (43, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (43, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B eT N R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (43, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> B eT N R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> Te << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (44, 2), (26, 2); +Got one of the listed errors +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> Te << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> N << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (44, 4); +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (44, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> N << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B Te N R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (44, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> B Te N R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (45, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> eN << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (44, 4); +Got one of the listed errors +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> eN << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T eN R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B T eN R << -e-e-e-e-e-e-e-e-e-e-e- + +-b-b-b-b-b-b-b-b-b-b-b- >> B << -b-b-b-b-b-b-b-b-b-b-b- +BEGIN; +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> B << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> T << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO tt_1(trans_id, stmt_id) VALUES (46, 2); +Log_name Pos Event_type Server_id End_log_pos Info +-e-e-e-e-e-e-e-e-e-e-e- >> T << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> Ne << -b-b-b-b-b-b-b-b-b-b-b- +INSERT INTO nt_1(trans_id, stmt_id) VALUES (46, 4), (44, 4); +Got one of the listed errors +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (46, 4), (44, 4) +-e-e-e-e-e-e-e-e-e-e-e- >> Ne << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> R << -b-b-b-b-b-b-b-b-b-b-b- +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (46, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> R << -e-e-e-e-e-e-e-e-e-e-e- +-b-b-b-b-b-b-b-b-b-b-b- >> B T Ne R << -b-b-b-b-b-b-b-b-b-b-b- +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1(trans_id, stmt_id) VALUES (46, 4), (44, 4) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1(trans_id, stmt_id) VALUES (46, 2) +master-bin.000001 # Query # # ROLLBACK +-e-e-e-e-e-e-e-e-e-e-e- >> B T Ne R << -e-e-e-e-e-e-e-e-e-e-e- + +################################################################################### +# CHECK CONSISTENCY +################################################################################### +################################################################################### +# CLEAN +################################################################################### diff --git a/mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt b/mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt new file mode 100644 index 00000000000..561902d0bd9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt @@ -0,0 +1 @@ +--binlog-direct-non-transactional-updates diff --git a/mysql-test/suite/rpl/t/rpl_stm_binlog_direct.test b/mysql-test/suite/rpl/t/rpl_stm_binlog_direct.test new file mode 100644 index 00000000000..f0c36c7b40c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_binlog_direct.test @@ -0,0 +1,230 @@ +################################################################################ +# This test case checks if the option "binlog-direct-non-transactional-updates" +# makes non-transactional changes in the statement format to be written to the +# binary log as soon as the statement commits. +# +# In what follows, we use the include file rpl_mixing_engines.inc to generate +# sql commands from a format string. The format string consists of a sequence of +# 'codes' separated by spaces. Before it set of commands, we paste the expected +# sequence in the binary log. The following codes exist: +# +# - Define the scope of a transaction: +# B - Begin. +# C - Commit. +# R - Rollback. +# +# - Change only T-Tables: +# T - Updates a T-Table. +# T-trig - Updates T-Tables through a trigger. +# T-func - Updates T-Tables through a function. +# T-proc - Updates T-Tables through a procedure. +# eT - Fails while updating the first tuple in a T-Table. +# Te - Fails while updating an n-tuple (n > 1) in a T-Table. +# Te-trig - Fails while updating an n-tuple (n > 1) in a T-Table. +# Te-func - Fails while updating an n-tuple (n > 1) in a T-Table. +# +# - Change only N-Tables +# N - Updates a N-Table. +# N-trig - Updates N-Tables through a trigger. +# N-func - Updates N-Tables through a function. +# N-proc - Updates N-Tables through a procedure. +# eN - Fails while updating the first tuple in a N-Table. +# Ne - Fails while updating an n-tuple (n > 1) in a N-Table. +# Ne-trig - Fails while updating an n-tuple (n > 1) in a N-Table. +# Ne-func - Fails while updating an n-tuple (n > 1) in a N-Table. +################################################################################ + +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc +--source include/have_innodb.inc + +set @@session.binlog_direct_non_transactional_updates= TRUE; + +--echo ######################################################################### +--echo # CONFIGURATION +--echo ######################################################################### + +--let $engine_type= Innodb +SET @commands= 'configure'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +--echo ######################################################################### +--echo # 1 - BINLOG ORDER +--echo ######################################################################### +connection master; + +--echo +--echo +--echo +--echo +--echo # +--echo #3) Generates in the binlog what follows: +--echo # --> STMT "N B T C" entries, format S. +--echo # +SET @commands= 'B T N C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T N-trig C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T N-func C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T N-proc C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-trig N C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-trig N-trig C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-trig N-func C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-trig N-proc C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-func N C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-func N-trig C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-func N-func C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-func N-proc C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-proc N C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-proc N-trig C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-proc N-func C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-proc N-proc C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + + +--echo +--echo +--echo +--echo +--echo # +--echo #3.e) Generates in the binlog what follows if T-* fails: +--echo # --> STMT "N" entry, format S. +--echo # Otherwise, what follows if N-* fails and a N-Table is changed: +--echo # --> STMT "N B T C" entries, format S. +--echo # +SET @commands= 'B eT N C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B Te N C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T eN C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T Ne C'; +--source extra/rpl_tests/rpl_mixing_engines.inc + + +--echo +--echo +--echo +--echo +--echo # +--echo #4) Generates in the binlog what follows: +--echo # --> STMT "N B T R" entries, format S. +--echo # +SET @commands= 'B T N R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T N-trig R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T N-func R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T N-proc R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-trig N R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-trig N-trig R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-trig N-func R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-trig N-proc R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-func N R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-func N-trig R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-func N-func R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-func N-proc R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-proc N R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-proc N-trig R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-proc N-func R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T-proc N-proc R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + + +--echo +--echo +--echo +--echo +--echo # +--echo #4.e) Generates in the binlog what follows if T* fails: +--echo # --> STMT "B N C" entry, format S. +--echo # Otherwise, what follows if N* fails and a N-Table is changed: +--echo # --> STMT "N" entries, format S. +--echo # +SET @commands= 'B eT N R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B Te N R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T eN R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + +SET @commands= 'B T Ne R'; +--source extra/rpl_tests/rpl_mixing_engines.inc + + +--echo ################################################################################### +--echo # CHECK CONSISTENCY +--echo ################################################################################### +connection master; +sync_slave_with_master; + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/test-nmt-master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/test-nmt-slave.sql +--diff_files $MYSQLTEST_VARDIR/tmp/test-nmt-master.sql $MYSQLTEST_VARDIR/tmp/test-nmt-slave.sql + +--echo ################################################################################### +--echo # CLEAN +--echo ################################################################################### +SET @commands= 'clean'; +--source extra/rpl_tests/rpl_mixing_engines.inc diff --git a/sql/log.cc b/sql/log.cc index 36d57271a7d..bc9efd75ea2 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4284,12 +4284,20 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) #if defined(USING_TRANSACTIONS) /* Should we write to the binlog cache or to the binlog on disk? + Write to the binlog cache if: - - it is already not empty (meaning we're in a transaction; note that the - present event could be about a non-transactional table, but still we need - to write to the binlog cache in that case to handle updates to mixed - trans/non-trans table types the best possible in binlogging) - - or if the event asks for it (cache_stmt == TRUE). + 1 - a transactional engine/table is updated (stmt_has_updated_trans_table == TRUE); + 2 - or the event asks for it (cache_stmt == TRUE); + 3 - or the cache is already not empty (meaning we're in a transaction; + note that the present event could be about a non-transactional table, but + still we need to write to the binlog cache in that case to handle updates + to mixed trans/non-trans table types). + + Write to the binlog on disk if only a non-transactional engine is + updated and: + 1 - the binlog cache is empty or; + 2 - --binlog-direct-non-transactional-updates is set and we are about to + use the statement format. When using the row format (cache_stmt == TRUE). */ if (opt_using_transactions && thd) { @@ -4300,8 +4308,9 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); IO_CACHE *trans_log= &trx_data->trans_log; my_off_t trans_log_pos= my_b_tell(trans_log); - if (event_info->get_cache_stmt() || trans_log_pos != 0 || - stmt_has_updated_trans_table(thd)) + if (event_info->get_cache_stmt() || stmt_has_updated_trans_table(thd) || + (!thd->variables.binlog_direct_non_trans_update && + trans_log_pos != 0)) { DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu", event_info->get_cache_stmt(), diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7bb357827c8..242acd28ecc 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5727,7 +5727,8 @@ enum options_mysqld OPT_SLAVE_EXEC_MODE, OPT_GENERAL_LOG_FILE, OPT_SLOW_QUERY_LOG_FILE, - OPT_IGNORE_BUILTIN_INNODB + OPT_IGNORE_BUILTIN_INNODB, + OPT_BINLOG_DIRECT_NON_TRANS_UPDATE }; @@ -7071,6 +7072,10 @@ The minimum value for this variable is 4096.", (uchar**) &max_system_variables.net_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT), 0, 1, 0}, + {"binlog-direct-non-transactional-updates", OPT_BINLOG_DIRECT_NON_TRANS_UPDATE, + "Causes updates to non-transactional engines using statement format to be written directly to binary log. Before using this option make sure that there are no dependencies between transactional and non-transactional tables such as in the statement INSERT INTO t_myisam SELECT * FROM t_innodb; otherwise, slaves may diverge from the master.", + (uchar**) &global_system_variables.binlog_direct_non_trans_update, (uchar**) &max_system_variables.binlog_direct_non_trans_update, 0, GET_BOOL, NO_ARG, 0, + 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/sql/set_var.cc b/sql/set_var.cc index 3c6b259045d..e06ad9dcc59 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -181,6 +181,8 @@ static sys_var_long_ptr sys_binlog_cache_size(&vars, "binlog_cache_size", &binlog_cache_size); static sys_var_thd_binlog_format sys_binlog_format(&vars, "binlog_format", &SV::binlog_format); +static sys_var_thd_bool sys_binlog_direct_non_trans_update(&vars, "binlog_direct_non_transactional_updates", + &SV::binlog_direct_non_trans_update); static sys_var_thd_ulong sys_bulk_insert_buff_size(&vars, "bulk_insert_buffer_size", &SV::bulk_insert_buff_size); static sys_var_const_os sys_character_sets_dir(&vars, diff --git a/sql/sql_class.h b/sql/sql_class.h index 8acc03f929d..56d31be79c7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -353,6 +353,7 @@ struct system_variables ulong ndb_index_stat_cache_entries; ulong ndb_index_stat_update_freq; ulong binlog_format; // binlog format for this thd (see enum_binlog_format) + my_bool binlog_direct_non_trans_update; /* In slave thread we need to know in behalf of which thread the query is being run to replicate temp tables properly From 45d2799a15a2bdde386b113cd6fcab915d4984d2 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Wed, 20 Jan 2010 22:21:18 -0200 Subject: [PATCH 264/344] Apply patch on behalf of the NDB team: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3321 Magnus BlÃ¥udd 2010-01-05 BUG#44840 - ndbapi compiler warning - type qualifier ignored for function return type - Remove the "const" - NOTE! This is an ABI incompatible change for some C++ compilers, NdbApi applications using any of the four changed functions may need a recompile if it's using dynamic linking. --- storage/ndb/include/ndbapi/NdbEventOperation.hpp | 8 ++++---- storage/ndb/include/ndbapi/NdbOperation.hpp | 4 ++-- storage/ndb/src/ndbapi/NdbEventOperation.cpp | 8 ++++---- storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp | 8 ++++---- storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp | 8 ++++---- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/storage/ndb/include/ndbapi/NdbEventOperation.hpp b/storage/ndb/include/ndbapi/NdbEventOperation.hpp index 437088d2893..0f98a4debef 100644 --- a/storage/ndb/include/ndbapi/NdbEventOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbEventOperation.hpp @@ -178,22 +178,22 @@ public: /** * Check if table name has changed, for event TE_ALTER */ - const bool tableNameChanged() const; + bool tableNameChanged() const; /** * Check if table frm has changed, for event TE_ALTER */ - const bool tableFrmChanged() const; + bool tableFrmChanged() const; /** * Check if table fragmentation has changed, for event TE_ALTER */ - const bool tableFragmentationChanged() const; + bool tableFragmentationChanged() const; /** * Check if table range partition list name has changed, for event TE_ALTER */ - const bool tableRangeListChanged() const; + bool tableRangeListChanged() const; /** * Retrieve the GCI of the latest retrieved event diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp index 78dbadfd7ab..713c29f028d 100644 --- a/storage/ndb/include/ndbapi/NdbOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbOperation.hpp @@ -779,7 +779,7 @@ public: /** * Get the type of access for this operation */ - const Type getType() const; + Type getType() const; /** @} *********************************************************************/ @@ -1135,7 +1135,7 @@ Return Value Return the Type. Remark: Gets type of access. ******************************************************************************/ inline -const NdbOperation::Type +NdbOperation::Type NdbOperation::getType() const { return m_type; diff --git a/storage/ndb/src/ndbapi/NdbEventOperation.cpp b/storage/ndb/src/ndbapi/NdbEventOperation.cpp index 5c6ed562dcc..1353ca40e95 100644 --- a/storage/ndb/src/ndbapi/NdbEventOperation.cpp +++ b/storage/ndb/src/ndbapi/NdbEventOperation.cpp @@ -96,22 +96,22 @@ NdbEventOperation::hasError() const return m_impl.m_has_error; } -const bool NdbEventOperation::tableNameChanged() const +bool NdbEventOperation::tableNameChanged() const { return m_impl.tableNameChanged(); } -const bool NdbEventOperation::tableFrmChanged() const +bool NdbEventOperation::tableFrmChanged() const { return m_impl.tableFrmChanged(); } -const bool NdbEventOperation::tableFragmentationChanged() const +bool NdbEventOperation::tableFragmentationChanged() const { return m_impl.tableFragmentationChanged(); } -const bool NdbEventOperation::tableRangeListChanged() const +bool NdbEventOperation::tableRangeListChanged() const { return m_impl.tableRangeListChanged(); } diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp index dff953923fe..ed60650e33e 100644 --- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp @@ -658,22 +658,22 @@ NdbEventOperationImpl::stop() DBUG_RETURN(r); } -const bool NdbEventOperationImpl::tableNameChanged() const +bool NdbEventOperationImpl::tableNameChanged() const { return (bool)AlterTableReq::getNameFlag(m_change_mask); } -const bool NdbEventOperationImpl::tableFrmChanged() const +bool NdbEventOperationImpl::tableFrmChanged() const { return (bool)AlterTableReq::getFrmFlag(m_change_mask); } -const bool NdbEventOperationImpl::tableFragmentationChanged() const +bool NdbEventOperationImpl::tableFragmentationChanged() const { return (bool)AlterTableReq::getFragDataFlag(m_change_mask); } -const bool NdbEventOperationImpl::tableRangeListChanged() const +bool NdbEventOperationImpl::tableRangeListChanged() const { return (bool)AlterTableReq::getRangeListFlag(m_change_mask); } diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp index 3d71146588d..c027226584c 100644 --- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp +++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp @@ -361,10 +361,10 @@ public: NdbBlob *getBlobHandle(const NdbColumnImpl *, int n); int readBlobParts(char* buf, NdbBlob* blob, Uint32 part, Uint32 count); int receive_event(); - const bool tableNameChanged() const; - const bool tableFrmChanged() const; - const bool tableFragmentationChanged() const; - const bool tableRangeListChanged() const; + bool tableNameChanged() const; + bool tableFrmChanged() const; + bool tableFragmentationChanged() const; + bool tableRangeListChanged() const; Uint64 getGCI(); Uint32 getAnyValue() const; Uint64 getLatestGCI(); From 9eae1881b384592e8fc13a78000071a08fe7370f Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Wed, 20 Jan 2010 22:22:20 -0200 Subject: [PATCH 265/344] Apply patch on behalf of Magnus: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3325 Magnus BlÃ¥udd 2010-01-05 Bug #49860 new compiler warning ha_archive - fix compiler warning by casting to ulong --- storage/archive/ha_archive.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 4648ca798da..42ff9daa77e 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -1490,7 +1490,7 @@ int ha_archive::info(uint flag) stats.create_time= (ulong) file_stat.st_ctime; stats.update_time= (ulong) file_stat.st_mtime; stats.mean_rec_length= stats.records ? - stats.data_file_length / stats.records : table->s->reclength; + ulong(stats.data_file_length / stats.records) : table->s->reclength; stats.max_data_file_length= MAX_FILE_SIZE; } stats.delete_length= 0; From 132b46e96eb48b8d9d993583ed7b9ecd87e53674 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Thu, 21 Jan 2010 09:10:05 +0100 Subject: [PATCH 266/344] WL#5154 Remove deprecated 4.1 features Several items said to be deprecated in the 4.1 manual have never been removed. This worklog adds deprecation warnings when these items are used, and warns the user that the items will be removed in MySQL 5.6. A couple of previously deprecation decision have been reversed (see single file comments) client/client_priv.h: Macro similar to the one in the server (mysql_priv.h) for printing a deprecation warning message client/mysql.cc: no-auto-rehash will not be deprecated skip-line-numbers will not be deprecated skip-column-names will not be deprecated no-pager is deprecated set-variable is deprecated no-named-commands is deprecated client/mysqladmin.cc: set-variable is deprecated client/mysqlbinlog.cc: position is deprecated client/mysqldump.c: first-slave is deprecated no-set-names is deprecated set-variable is deprecated mysql-test/r/mysqlbinlog.result: Adding the [Warning] to the test case, just to show that the deprecation works. The test case will be changed in Celosia to use --start-position. mysys/my_getopt.c: set-variable (include -O) is deprecated scripts/mysqld_multi.sh: Warning for mysqld_multi sql/mysqld.cc: default-collation is deprecated log-bin-trust-routine-creators is deprecated set-variable is deprecated default-character-set is deprecated safe-show-database is deprecated sql/share/errmsg.txt: Added version number for sql_log_update deprecation message. --- client/client_priv.h | 12 +++++++++++- client/mysql.cc | 17 +++++++++++++---- client/mysqladmin.cc | 3 +++ client/mysqlbinlog.cc | 8 ++++++-- client/mysqldump.c | 11 ++++++++--- mysql-test/r/func_time.result | 10 +++++----- mysql-test/r/mysqlbinlog.result | 3 +++ mysql-test/r/variables.result | 2 +- mysys/my_getopt.c | 9 +++++++++ scripts/mysqld_multi.sh | 3 +++ sql/mysql_priv.h | 4 ++++ sql/mysqld.cc | 22 ++++++++++++++++++++-- sql/set_var.cc | 2 +- sql/share/errmsg.txt | 8 ++++---- sql/sql_yacc.yy | 2 +- 15 files changed, 92 insertions(+), 24 deletions(-) diff --git a/client/client_priv.h b/client/client_priv.h index 06145232995..9d2fc2be141 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -31,6 +31,15 @@ # endif #endif +/* Version numbers for deprecation messages */ +#define VER_CELOSIA "5.6" + +#define WARN_DEPRECATED(Ver,Old,New) \ + do { \ + printf("Warning: The option '%s' is deprecated and will be removed " \ + "in MySQL %s. Please use %s instead.\n", (Old), (Ver), (New)); \ + } while(0); + enum options_client { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET, @@ -49,7 +58,7 @@ enum options_client OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION, OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH, OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_CREATE_OPTIONS, OPT_SERVER_ARG, - OPT_START_POSITION, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME, + OPT_POSITION, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME, OPT_SIGINT_IGNORE, OPT_HEXBLOB, OPT_ORDER_BY_PRIMARY, OPT_COUNT, #ifdef HAVE_NDBCLUSTER_DB OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, @@ -80,5 +89,6 @@ enum options_client OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT, OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE, OPT_WRITE_BINLOG, OPT_DUMP_DATE, + OPT_FIRST_SLAVE, OPT_MAX_CLIENT_OPTION }; diff --git a/client/mysql.cc b/client/mysql.cc index b3854636bb2..b3b73fdb468 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -54,6 +54,9 @@ static char *server_version= NULL; /* Array of options to pass to libemysqld */ #define MAX_SERVER_ARGS 64 +/* Version numbers for deprecation messages */ +#define VER_CELOSIA "5.6" + void* sql_alloc(unsigned size); // Don't use mysqld alloc for these void sql_element_free(void *ptr); #include "sql_string.h" @@ -1343,7 +1346,7 @@ static struct my_option my_long_options[] = (uchar**) &opt_rehash, (uchar**) &opt_rehash, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"no-auto-rehash", 'A', - "No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of mysql and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead.", + "No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of mysql and disables rehashing on reconnect.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"batch", 'B', "Don't use history file. Disable interactive behavior. (Enables --silent)", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -1412,7 +1415,7 @@ static struct my_option my_long_options[] = {"line-numbers", OPT_LINE_NUMBERS, "Write line numbers for errors.", (uchar**) &line_numbers, (uchar**) &line_numbers, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"skip-line-numbers", 'L', "Don't write line number for errors. WARNING: -L is deprecated, use long version of this option instead.", 0, 0, 0, GET_NO_ARG, + {"skip-line-numbers", 'L', "Don't write line number for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"unbuffered", 'n', "Flush buffer after each query.", (uchar**) &unbuffered, (uchar**) &unbuffered, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -1420,7 +1423,7 @@ static struct my_option my_long_options[] = (uchar**) &column_names, (uchar**) &column_names, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"skip-column-names", 'N', - "Don't write column names in results. WARNING: -N is deprecated, use long version of this options instead.", + "Don't write column names in results.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"set-variable", 'O', "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", @@ -1650,7 +1653,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } break; case OPT_NOPAGER: - printf("WARNING: option deprecated; use --disable-pager instead.\n"); + WARN_DEPRECATED(VER_CELOSIA, "--no-pager", "--disable-pager"); opt_nopager= 1; break; case OPT_MYSQL_PROTOCOL: @@ -1696,12 +1699,18 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), if (!(status.line_buff= batch_readline_command(status.line_buff, argument))) return 1; break; + case 'g': + WARN_DEPRECATED(VER_CELOSIA, "-g, --no-named-commands", "--skip-named-commands"); + break; case 'o': if (argument == disabled_my_option) one_database= 0; else one_database= skip_updates= 1; break; + case 'O': + WARN_DEPRECATED(VER_CELOSIA, "-O, --set-variable", "--variable-name=value"); + break; case 'p': if (argument == disabled_my_option) argument= (char*) ""; // Don't require password diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 2b93c149523..04e25fcf1ff 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -282,6 +282,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), charsets_dir = argument; #endif break; + case 'O': + WARN_DEPRECATED(VER_CELOSIA, "--set-variable", "--variable-name=value"); + break; case OPT_MYSQL_PROTOCOL: opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib, opt->name); diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index f55dc75df5d..1c0f6e5f96a 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -41,6 +41,7 @@ #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES) + char server_version[SERVER_VERSION_LENGTH]; ulong server_id = 0; @@ -1060,7 +1061,7 @@ static struct my_option my_long_options[] = "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", (uchar**) &port, (uchar**) &port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"position", 'j', "Deprecated. Use --start-position instead.", + {"position", OPT_POSITION, "Deprecated. Use --start-position instead.", (uchar**) &start_position, (uchar**) &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 */ @@ -1103,7 +1104,7 @@ static struct my_option my_long_options[] = "(you should probably use quotes for your shell to set it properly).", (uchar**) &start_datetime_str, (uchar**) &start_datetime_str, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"start-position", OPT_START_POSITION, + {"start-position", 'j', "Start reading the binlog at position N. Applies to the first binlog " "passed on the command line.", (uchar**) &start_position, (uchar**) &start_position, 0, GET_ULL, @@ -1314,6 +1315,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case 'R': remote_opt= 1; break; + case OPT_POSITION: + WARN_DEPRECATED(VER_CELOSIA, "--position", "--start-position"); + break; case OPT_MYSQL_PROTOCOL: opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib, opt->name); diff --git a/client/mysqldump.c b/client/mysqldump.c index 56d6c12981f..25a8d7b0f6f 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -282,7 +282,7 @@ static struct my_option my_long_options[] = (uchar**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...", (uchar**) &escaped, (uchar**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.", + {"first-slave", OPT_FIRST_SLAVE, "Deprecated, renamed to --lock-all-tables.", (uchar**) &opt_lock_all_tables, (uchar**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"flush-logs", 'F', "Flush logs file in server before starting dump. " @@ -366,8 +366,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-data", 'd', "No row information.", (uchar**) &opt_no_data, (uchar**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"no-set-names", 'N', - "Deprecated. Use --skip-set-charset instead.", + {"no-set-names", 'N',"Suppress the SET NAMES statement", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"opt", OPT_OPTIMIZE, "Same as --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys. Enabled by default, disable with --skip-opt.", @@ -760,6 +759,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case '?': usage(); exit(0); + case 'O': + WARN_DEPRECATED(VER_CELOSIA, "--set-variable", "--variable-name=value"); + break; + case (int) OPT_FIRST_SLAVE: + WARN_DEPRECATED(VER_CELOSIA, "--first-slave", "--lock-all-tables"); + break; case (int) OPT_MASTER_DATA: if (!argument) /* work like in old versions */ opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL; diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 0fa143d95bc..2ac549a5abd 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -682,7 +682,7 @@ select timestampadd(SQL_TSI_FRAC_SECOND, 1, date) from t1; timestampadd(SQL_TSI_FRAC_SECOND, 1, date) 2003-01-02 00:00:00.000001 Warnings: -Warning 1287 The syntax 'FRAC_SECOND' is deprecated and will be removed in MySQL 6.2. Please use MICROSECOND instead +Warning 1287 The syntax 'FRAC_SECOND' is deprecated and will be removed in MySQL 5.6. Please use MICROSECOND instead select timestampdiff(MONTH, '2001-02-01', '2001-05-01') as a; a 3 @@ -717,7 +717,7 @@ select timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05 a 7689538999999 Warnings: -Warning 1287 The syntax 'FRAC_SECOND' is deprecated and will be removed in MySQL 6.2. Please use MICROSECOND instead +Warning 1287 The syntax 'FRAC_SECOND' is deprecated and will be removed in MySQL 5.6. Please use MICROSECOND instead select timestampdiff(SQL_TSI_DAY, '1986-02-01', '1986-03-01') as a1, timestampdiff(SQL_TSI_DAY, '1900-02-01', '1900-03-01') as a2, timestampdiff(SQL_TSI_DAY, '1996-02-01', '1996-03-01') as a3, @@ -1088,7 +1088,7 @@ timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12: id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Warning 1287 The syntax 'FRAC_SECOND' is deprecated and will be removed in MySQL 6.2. Please use MICROSECOND instead +Warning 1287 The syntax 'FRAC_SECOND' is deprecated and will be removed in MySQL 5.6. Please use MICROSECOND instead Note 1003 select timestampdiff(WEEK,'2001-02-01','2001-05-01') AS `a1`,timestampdiff(SECOND_FRAC,'2001-02-01 12:59:59.120000','2001-05-01 12:58:58.119999') AS `a2` select time_format('100:00:00', '%H %k %h %I %l'); time_format('100:00:00', '%H %k %h %I %l') @@ -1287,12 +1287,12 @@ SELECT TIMESTAMPADD(FRAC_SECOND, 1, '2008-02-18'); TIMESTAMPADD(FRAC_SECOND, 1, '2008-02-18') 2008-02-18 00:00:00.000001 Warnings: -Warning 1287 The syntax 'FRAC_SECOND' is deprecated and will be removed in MySQL 6.2. Please use MICROSECOND instead +Warning 1287 The syntax 'FRAC_SECOND' is deprecated and will be removed in MySQL 5.6. Please use MICROSECOND instead SELECT TIMESTAMPDIFF(FRAC_SECOND, '2008-02-17', '2008-02-18'); TIMESTAMPDIFF(FRAC_SECOND, '2008-02-17', '2008-02-18') 86400000000 Warnings: -Warning 1287 The syntax 'FRAC_SECOND' is deprecated and will be removed in MySQL 6.2. Please use MICROSECOND instead +Warning 1287 The syntax 'FRAC_SECOND' is deprecated and will be removed in MySQL 5.6. Please use MICROSECOND instead SELECT DATE_ADD('2008-02-18', INTERVAL 1 FRAC_SECOND); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND)' at line 1 SELECT DATE_SUB('2008-02-18', INTERVAL 1 FRAC_SECOND); diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index 9d4fde96d18..f5c40202101 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -93,6 +93,7 @@ ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; --- --position -- +Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; @@ -193,6 +194,7 @@ ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; --- --position -- +Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; @@ -233,6 +235,7 @@ DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 541b2b2fb86..7f45046fab5 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -566,7 +566,7 @@ set sql_log_bin=1; set sql_log_off=1; set sql_log_update=1; Warnings: -Note 1315 The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored +Note 1315 The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored. This option will be removed in MySQL 5.6. set sql_low_priority_updates=1; set sql_max_join_size=200; select @@sql_max_join_size,@@max_join_size; diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index e561d74f4d1..fc5662812b0 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -146,6 +146,10 @@ int handle_options(int *argc, char ***argv, { /* --set-variable, or -O */ if (*cur_arg == 'O') { + my_getopt_error_reporter(WARNING_LEVEL, + "%s: Option '-O' is deprecated. " + "Use --variable-name=value instead.", + my_progname); must_be_var= 1; if (!(*++cur_arg)) /* If not -Ovar=# */ @@ -165,6 +169,11 @@ int handle_options(int *argc, char ***argv, } else if (!getopt_compare_strings(cur_arg, "-set-variable", 13)) { + my_getopt_error_reporter(WARNING_LEVEL, + "%s: Option '--set-variable' is deprecated. " + "Use --variable-name=value instead.", + my_progname); + must_be_var= 1; if (cur_arg[13] == '=') { diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 430c74874eb..528a1ca2e98 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -68,7 +68,10 @@ sub main # than a correct --defaults-extra-file option unshift @defaults_options, "--defaults-extra-file=$1"; + print "WARNING: --config-file is deprecated and will be removed\n"; + print "in MySQL 5.6. Please use --defaults-extra-file instead\n"; } + } } foreach (@defaults_options) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2be3b8f1f20..76edbf1dea3 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -111,6 +111,10 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); #define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1)) #define all_bits_set(A,B) ((A) & (B) != (B)) +/* Version numbers for deprecation messages */ +#define VER_BETONY "5.5" +#define VER_CELOSIA "5.6" + #define WARN_DEPRECATED(Thd,Ver,Old,New) \ do { \ DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) > 0); \ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 242acd28ecc..db0453dc364 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5603,6 +5603,7 @@ enum options_mysqld OPT_DISCONNECT_SLAVE_EVENT_COUNT, OPT_TC_HEURISTIC_RECOVER, OPT_ABORT_SLAVE_EVENT_COUNT, OPT_LOG_BIN_TRUST_FUNCTION_CREATORS, + OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD, OPT_ENGINE_CONDITION_PUSHDOWN, OPT_NDB_CONNECTSTRING, OPT_NDB_USE_EXACT_COUNT, OPT_NDB_USE_TRANSACTIONS, OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ, @@ -5683,6 +5684,7 @@ enum options_mysqld OPT_EXPIRE_LOGS_DAYS, OPT_GROUP_CONCAT_MAX_LEN, OPT_DEFAULT_COLLATION, + OPT_DEFAULT_COLLATION_OLD, OPT_CHARACTER_SET_CLIENT_HANDSHAKE, OPT_CHARACTER_SET_FILESYSTEM, OPT_LC_TIME_NAMES, @@ -5857,7 +5859,7 @@ struct my_option my_long_options[] = {"default-character-set", 'C', "Set the default character set (deprecated option, use --character-set-server instead).", (uchar**) &default_character_set_name, (uchar**) &default_character_set_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"default-collation", OPT_DEFAULT_COLLATION, "Set the default collation (deprecated option, use --collation-server instead).", + {"default-collation", OPT_DEFAULT_COLLATION_OLD, "Set the default collation (deprecated option, use --collation-server instead).", (uchar**) &default_collation_name, (uchar**) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-storage-engine", OPT_STORAGE_ENGINE, @@ -5988,7 +5990,7 @@ each time the SQL thread starts.", compatibility; the behaviour was also changed to apply only to functions (and triggers). In a future release this old name could be removed. */ - {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS, + {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD, "(deprecated) Use log-bin-trust-function-creators.", (uchar**) &trust_function_creators, (uchar**) &trust_function_creators, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -7905,6 +7907,9 @@ mysqld_get_one_option(int optid, #endif opt_endinfo=1; /* unireg: memory allocation */ break; + case '0': + WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-long-format", "--log-short-format"); + break; case 'a': global_system_variables.sql_mode= fix_sql_mode(MODE_ANSI); global_system_variables.tx_isolation= ISO_SERIALIZABLE; @@ -7913,6 +7918,7 @@ mysqld_get_one_option(int optid, strmake(mysql_home,argument,sizeof(mysql_home)-1); break; case 'C': + WARN_DEPRECATED(NULL, VER_CELOSIA, "--default-character-set", "--character-set-server"); if (default_collation_name == compiled_default_collation_name) default_collation_name= 0; break; @@ -7935,6 +7941,9 @@ mysqld_get_one_option(int optid, case 'L': strmake(language, argument, sizeof(language)-1); break; + case 'O': + WARN_DEPRECATED(NULL, VER_CELOSIA, "--set-variable", "--variable-name=value"); + break; #ifdef HAVE_REPLICATION case OPT_SLAVE_SKIP_ERRORS: init_slave_skip_errors(argument); @@ -7969,6 +7978,15 @@ mysqld_get_one_option(int optid, test_flags= argument ? (uint) atoi(argument) : 0; opt_endinfo=1; break; + case (int) OPT_DEFAULT_COLLATION_OLD: + WARN_DEPRECATED(NULL, VER_CELOSIA, "--default-collation", "--collation-server"); + break; + case (int) OPT_SAFE_SHOW_DB: + WARN_DEPRECATED(NULL, VER_CELOSIA, "--safe-show-database", "GRANT SHOW DATABASES"); + break; + case (int) OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD: + WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-bin-trust-routine-creators", "--log-bin-trust-function-creators"); + break; case (int) OPT_BIG_TABLES: thd_startup_options|=OPTION_BIG_TABLES; break; diff --git a/sql/set_var.cc b/sql/set_var.cc index e06ad9dcc59..2c00d76b0f1 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -4139,7 +4139,7 @@ bool process_key_caches(process_key_cache_t func) void sys_var_trust_routine_creators::warn_deprecated(THD *thd) { - WARN_DEPRECATED(thd, "6.0", "@@log_bin_trust_routine_creators", + WARN_DEPRECATED(thd, VER_CELOSIA, "@@log_bin_trust_routine_creators", "'@@log_bin_trust_function_creators'"); } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 6d1b7aaf1ee..06ce848399b 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5138,11 +5138,11 @@ ER_SP_BADSTATEMENT 0A000 eng "%s is not allowed in stored procedures" ger "%s ist in gespeicherten Prozeduren nicht erlaubt" ER_UPDATE_LOG_DEPRECATED_IGNORED 42000 - eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored" - ger "Das Update-Log ist veraltet und wurde durch das Binär-Log ersetzt. SET SQL_LOG_UPDATE wird ignoriert" + eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored. This option will be removed in MySQL 5.6." + ger "Das Update-Log ist veraltet und wurde durch das Binär-Log ersetzt. SET SQL_LOG_UPDATE wird ignoriert. Diese Option wird in MySQL 5.6 entfernt." ER_UPDATE_LOG_DEPRECATED_TRANSLATED 42000 - eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been translated to SET SQL_LOG_BIN" - ger "Das Update-Log ist veraltet und wurde durch das Binär-Log ersetzt. SET SQL_LOG_UPDATE wurde in SET SQL_LOG_BIN übersetzt" + eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been translated to SET SQL_LOG_BIN. This option will be removed in MySQL 5.6." + ger "Das Update-Log ist veraltet und wurde durch das Binär-Log ersetzt. SET SQL_LOG_UPDATE wurde in SET SQL_LOG_BIN übersetzt. Diese Option wird in MySQL 5.6 entfernt." ER_QUERY_INTERRUPTED 70100 eng "Query execution was interrupted" ger "Ausführung der Abfrage wurde unterbrochen" diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6dc2becf664..8dc08f8425f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8932,7 +8932,7 @@ interval_time_stamp: implementation without changing its resolution. */ - WARN_DEPRECATED(yythd, "6.2", "FRAC_SECOND", "MICROSECOND"); + WARN_DEPRECATED(yythd, VER_CELOSIA, "FRAC_SECOND", "MICROSECOND"); } ; From 1dafac6f35b23757cafe0ac1ef9f6b4edb28947d Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 2 Feb 2010 14:17:21 +0200 Subject: [PATCH 267/344] fixed various pb2 test failures on windows. --- mysql-test/r/bug46080.result | 4 ++-- mysql-test/t/bug46080.test | 4 ++-- sql/event_scheduler.cc | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) mode change 100644 => 100755 mysql-test/r/bug46080.result mode change 100644 => 100755 sql/event_scheduler.cc diff --git a/mysql-test/r/bug46080.result b/mysql-test/r/bug46080.result old mode 100644 new mode 100755 index 2173768cdad..602027be43e --- a/mysql-test/r/bug46080.result +++ b/mysql-test/r/bug46080.result @@ -2,8 +2,8 @@ # Bug #46080: group_concat(... order by) crashes server when # sort_buffer_size cannot allocate # -call mtr.add_suppression("Out of memory at line .*, 'my_alloc.c'"); -call mtr.add_suppression("needed .* byte .*k., memory in use: .* bytes .*k"); +call mtr.add_suppression("Out of memory at line .*, '.*my_alloc.c'"); +call mtr.add_suppression("needed .* byte (.*k)., memory in use: .* bytes (.*k)"); CREATE TABLE t1(a CHAR(255)); INSERT INTO t1 VALUES ('a'); SET @@SESSION.sort_buffer_size=5*16*1000000; diff --git a/mysql-test/t/bug46080.test b/mysql-test/t/bug46080.test index 8b4cee4d8b0..ed4a16fdf51 100644 --- a/mysql-test/t/bug46080.test +++ b/mysql-test/t/bug46080.test @@ -3,8 +3,8 @@ --echo # sort_buffer_size cannot allocate --echo # -call mtr.add_suppression("Out of memory at line .*, 'my_alloc.c'"); -call mtr.add_suppression("needed .* byte .*k., memory in use: .* bytes .*k"); +call mtr.add_suppression("Out of memory at line .*, '.*my_alloc.c'"); +call mtr.add_suppression("needed .* byte (.*k)., memory in use: .* bytes (.*k)"); CREATE TABLE t1(a CHAR(255)); INSERT INTO t1 VALUES ('a'); diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc old mode 100644 new mode 100755 index 8c0025f9ed4..706afb3e0ad --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -235,8 +235,9 @@ event_scheduler_thread(void *arg) if (!res) scheduler->run(thd); + DBUG_LEAVE; // Against gcc warnings my_thread_end(); - DBUG_RETURN(0); // Against gcc warnings + return 0; } From 2db684572ea716de462bf8d79f398dfcc130a8ff Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 2 Feb 2010 11:17:58 -0200 Subject: [PATCH 268/344] Fix for valgrind warning: check whether pointer was initialized. storage/myisammrg/ha_myisammrg.cc: myisam pointer is not relevant if a error was raised. --- storage/myisammrg/ha_myisammrg.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index e265dac2c82..8af776f5c5e 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -380,7 +380,7 @@ static MI_INFO *myisammrg_attach_children_callback(void *callback_param) my_errno= HA_ERR_WRONG_MRG_TABLE_DEF; } DBUG_PRINT("myrg", ("MyISAM handle: 0x%lx my_errno: %d", - (long) myisam, my_errno)); + my_errno ? NULL : (long) myisam, my_errno)); err: DBUG_RETURN(my_errno ? NULL : myisam); From 59f1be1b636e360c410c81de1c41a8c4a254077d Mon Sep 17 00:00:00 2001 From: Alexander Nozdrin Date: Tue, 2 Feb 2010 16:38:44 +0300 Subject: [PATCH 269/344] Revert a patch for Bug#48231, which introduced valgrind warnings. Original revision: ------------------------------------------------------------ revision-id: li-bing.song@sun.com-20100130124925-o6sfex42b6noyc6x parent: joro@sun.com-20100129145427-0n79l9hnk0q43ajk committer: branch nick: mysql-5.1-bugteam timestamp: Sat 2010-01-30 20:49:25 +0800 message: Bug #48321 CURRENT_USER() incorrectly replicated for DROP/RENAME USER; REVOKE/GRANT; ALTER EVENT. The following statements support the CURRENT_USER() where a user is needed. DROP USER RENAME USER CURRENT_USER() ... GRANT ... TO CURRENT_USER() REVOKE ... FROM CURRENT_USER() ALTER DEFINER = CURRENT_USER() EVENT but, When these statements are binlogged, CURRENT_USER() just is binlogged as 'CURRENT_USER()', it is not expanded to the real user name. When slave executes the log event, 'CURRENT_USER()' is expand to the user of slave SQL thread, but SQL thread's user name always NULL. This breaks the replication. After this patch, All above statements are rewritten when they are binlogged. The CURRENT_USER() is expanded to the real user's name and host. ------------------------------------------------------------ --- .../extra/rpl_tests/rpl_current_user.test | 127 -- .../suite/rpl/r/rpl_binlog_grant.result | 42 +- mysql-test/suite/rpl/r/rpl_events.result | 42 - .../suite/rpl/r/rpl_innodb_mixed_dml.result | 4 +- mysql-test/suite/rpl/r/rpl_sp.result | 16 +- mysql-test/suite/rpl/r/rpl_user.result | 1755 +---------------- mysql-test/suite/rpl/t/rpl_binlog_grant.test | 8 +- mysql-test/suite/rpl/t/rpl_events.test | 82 - mysql-test/suite/rpl/t/rpl_user.test | 83 +- sql/events.cc | 79 +- sql/sql_acl.cc | 124 +- sql/sql_lex.h | 25 - sql/sql_yacc.yy | 36 +- 13 files changed, 104 insertions(+), 2319 deletions(-) delete mode 100644 mysql-test/extra/rpl_tests/rpl_current_user.test diff --git a/mysql-test/extra/rpl_tests/rpl_current_user.test b/mysql-test/extra/rpl_tests/rpl_current_user.test deleted file mode 100644 index 7ec38e0c151..00000000000 --- a/mysql-test/extra/rpl_tests/rpl_current_user.test +++ /dev/null @@ -1,127 +0,0 @@ ---let $count=1 -connection master; - -if (`SELECT '$diff_table' = ''`) -{ - let $diff_table= mysql.user; -} - ---echo ---echo ---echo ---echo TEST STATEMENT: '$statement' ---echo -------------------------------------------------------------------------- - -if (`SELECT '$diff_columns' = ''`) -{ - eval CREATE VIEW test.bug48321_v1 AS SELECT user FROM $diff_table - WHERE user LIKE 'bug48321%'; -} - -if (`SELECT '$diff_columns' <> ''`) -{ - eval CREATE VIEW test.bug48321_v1 AS SELECT user, $diff_columns - FROM $diff_table WHERE user LIKE 'bug48321%'; -} - -while (`SELECT $count < 6`) -{ - --echo - --echo TEST STATEMENT: '$statement' - --echo CASE $count: - --echo ------- - - let $user2= 'bug48321_2'@'localhost'; - let $user3= 'bug48321_3'@'localhost'; - - let $user1= CURRENT_USER(); - if (`SELECT '$action'='RENAME'`) - { - let $user1= $user1 TO 'bug48321_4'@'localhost'; - let $user2= $user2 TO 'bug48321_5'@'localhost'; - let $user3= $user3 TO 'bug48321_6'@'localhost'; - } - - if (`SELECT '$action'='GRANT'`) - { - let $user1= $user1 IDENTIFIED BY 'user1'; - let $user3= $user3 IDENTIFIED BY ''; - } - - if (`SELECT $count=1`) - { - --echo # Only CURRENT_USER() in the user list of the test statement. - let $users_list= $user1; - } - - if (`SELECT $count=2`) - { - --echo # Two users are in the test statement, CURRENT_USER is the first one. - let $users_list= $user1, $user2; - } - - if (`SELECT $count=3`) - { - --echo # Two users are in the test statement, CURRENT_USER is the last one. - let $users_list= $user2, $user1; - } - - if (`SELECT $count=4`) - { - --echo # Three users are in the test statement, CURRENT_USER is the second one. - let $users_list= $user2, $user1, $user3; - } - - if (`SELECT $count=5`) - { - --echo # CURRENT_USER is not in the test statement. - let $users_list= $user2, $user3; - } - - --echo users_list= $users_list - --echo - --echo # Connect to master with user1, so user1 always is the current user, - --echo # when test statement is runing. - eval GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; - eval CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - - if (`SELECT '$action'='REVOKE'`) - { - --echo - --echo # Grant some privileges to users at first when testing - --echo # 'REVOKE ...' statement. - eval GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', - 'bug48321_3'@'localhost' WITH GRANT OPTION; - eval GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', - 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - } - - connect (conn1, 127.0.0.1, 'bug48321_1'@'localhost',,); - connection conn1; - --echo - let $temp= `SELECT "$statement"`; - eval $temp; - --echo - - disconnect conn1; - - connection master; - sync_slave_with_master; - - connection master; - let $diff_table_1= master:test.bug48321_v1; - let $diff_table_2= slave:test.bug48321_v1; - source include/diff_tables.inc; - --echo - - --echo # Delete all bug48321% users - connection master; - DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; - DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; - FLUSH PRIVILEGES; - - inc $count; -} -DROP VIEW test.bug48321_v1; diff --git a/mysql-test/suite/rpl/r/rpl_binlog_grant.result b/mysql-test/suite/rpl/r/rpl_binlog_grant.result index adf2175f3bb..4a789f361c6 100644 --- a/mysql-test/suite/rpl/r/rpl_binlog_grant.result +++ b/mysql-test/suite/rpl/r/rpl_binlog_grant.result @@ -17,15 +17,16 @@ show grants for x@y; Grants for x@y GRANT USAGE ON *.* TO 'x'@'y' GRANT SELECT ON `d1`.`t` TO 'x'@'y' -show binlog events from ; +show binlog events; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # drop database if exists d1 -master-bin.000001 # Query # # create database d1 -master-bin.000001 # Query # # use `d1`; create table t (s1 int) engine=innodb -master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `d1`; insert into t values (1) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `d1`; grant select on t to 'x'@'y' +master-bin.000001 4 Format_desc 1 106 Server ver: VERSION, Binlog ver: 4 +master-bin.000001 106 Query 1 193 drop database if exists d1 +master-bin.000001 193 Query 1 272 create database d1 +master-bin.000001 272 Query 1 370 use `d1`; create table t (s1 int) engine=innodb +master-bin.000001 370 Query 1 436 BEGIN +master-bin.000001 436 Query 1 521 use `d1`; insert into t values (1) +master-bin.000001 521 Xid 1 548 COMMIT /* XID */ +master-bin.000001 548 Query 1 633 use `d1`; grant select on t to x@y start transaction; insert into t values (2); revoke select on t from x@y; @@ -37,18 +38,19 @@ s1 show grants for x@y; Grants for x@y GRANT USAGE ON *.* TO 'x'@'y' -show binlog events from ; +show binlog events; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # drop database if exists d1 -master-bin.000001 # Query # # create database d1 -master-bin.000001 # Query # # use `d1`; create table t (s1 int) engine=innodb -master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `d1`; insert into t values (1) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `d1`; grant select on t to 'x'@'y' -master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `d1`; insert into t values (2) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `d1`; revoke select on t from 'x'@'y' +master-bin.000001 4 Format_desc 1 106 Server ver: VERSION, Binlog ver: 4 +master-bin.000001 106 Query 1 193 drop database if exists d1 +master-bin.000001 193 Query 1 272 create database d1 +master-bin.000001 272 Query 1 370 use `d1`; create table t (s1 int) engine=innodb +master-bin.000001 370 Query 1 436 BEGIN +master-bin.000001 436 Query 1 521 use `d1`; insert into t values (1) +master-bin.000001 521 Xid 1 548 COMMIT /* XID */ +master-bin.000001 548 Query 1 633 use `d1`; grant select on t to x@y +master-bin.000001 633 Query 1 699 BEGIN +master-bin.000001 699 Query 1 784 use `d1`; insert into t values (2) +master-bin.000001 784 Xid 1 811 COMMIT /* XID */ +master-bin.000001 811 Query 1 899 use `d1`; revoke select on t from x@y drop user x@y; drop database d1; diff --git a/mysql-test/suite/rpl/r/rpl_events.result b/mysql-test/suite/rpl/r/rpl_events.result index 206ec52718c..b3fd85d7e28 100644 --- a/mysql-test/suite/rpl/r/rpl_events.result +++ b/mysql-test/suite/rpl/r/rpl_events.result @@ -251,45 +251,3 @@ DROP EVENT event44331_1; DROP EVENT event44331_2; DROP EVENT event44331_3; DROP EVENT event44331_4; -DROP VIEW IF EXISTS events_view; -DROP EVENT IF EXISTS event48321_1; -DROP EVENT IF EXISTS event48321_2; -DROP EVENT IF EXISTS event48321_3; -DROP EVENT IF EXISTS event48321_4; -CREATE VIEW events_view AS -SELECT EVENT_SCHEMA, EVENT_NAME, DEFINER FROM INFORMATION_SCHEMA.EVENTS -WHERE EVENT_NAME LIKE 'event48321%'; -CREATE DEFINER=CURRENT_USER() /*!50000 EVENT event48321_1 */ -ON SCHEDULE AT CURRENT_TIMESTAMP -ON COMPLETION PRESERVE DISABLE -DO SELECT 48321 as BUG; -CREATE DEFINER=CURRENT_USER() EVENT event48321_2 -ON SCHEDULE AT CURRENT_TIMESTAMP -ON COMPLETION PRESERVE DISABLE -DO SELECT 48321 as BUG; -CREATE /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 -ON SCHEDULE AT CURRENT_TIMESTAMP -ON COMPLETION PRESERVE DISABLE -DO SELECT 48321 as BUG; -Comparing tables master:test.events_view and slave:test.events_view -ALTER DEFINER=CURRENT_USER() EVENT event48321_1 RENAME TO event48321_4; -ALTER DEFINER=CURRENT_USER() EVENT event48321_2 -ON SCHEDULE AT CURRENT_TIMESTAMP -ON COMPLETION PRESERVE DISABLE -DO SELECT 48321 as BUG; -ALTER /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 -ON SCHEDULE AT CURRENT_TIMESTAMP -ON COMPLETION PRESERVE DISABLE -DO SELECT 48321 as BUG; -Comparing tables master:test.events_view and slave:test.events_view -ALTER /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 -ON SCHEDULE AT CURRENT_TIMESTAMP -ON COMPLETION PRESERVE DISABLE -DO SELECT 48321 as BUG; ALTER EVENT event48321_2 ENABLE | -Comparing tables master:test.events_view and slave:test.events_view -ALTER EVENT event48321_3 ENABLE; -Comparing tables master:test.events_view and slave:test.events_view -DROP EVENT event48321_4; -DROP EVENT event48321_2; -DROP EVENT event48321_3; -DROP VIEW events_view; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index 74ebb3be948..fbfebbaa590 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -750,7 +750,7 @@ test_rpl e2 root@localhost SYSTEM RECURRING NULL 1 # # NULL ENABLED 1 latin1 lat USE test_rpl; SHOW EVENTS; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation -test_rpl e2 root@localhost SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +test_rpl e2 @ SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci ==========MASTER========== SELECT COUNT(*) FROM t1; COUNT(*) @@ -1079,7 +1079,7 @@ master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Query 1 # use `test_rpl`; INSERT INTO t1 VALUES(1, 'test1') master-bin.000001 # Xid 1 # # master-bin.000001 # Query 1 # use `test_rpl`; CREATE DEFINER=`root`@`localhost` EVENT e1 ON SCHEDULE EVERY '1' SECOND COMMENT 'e_second_comment' DO DELETE FROM t1 -master-bin.000001 # Query 1 # use `test_rpl`; ALTER DEFINER=`root`@`localhost` EVENT e1 RENAME TO e2 +master-bin.000001 # Query 1 # use `test_rpl`; ALTER EVENT e1 RENAME TO e2 master-bin.000001 # Query 1 # use `test_rpl`; DROP EVENT e2 master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Query 1 # use `test_rpl`; DELETE FROM t1 diff --git a/mysql-test/suite/rpl/r/rpl_sp.result b/mysql-test/suite/rpl/r/rpl_sp.result index 02a5f33c843..7fedaf4c1ef 100644 --- a/mysql-test/suite/rpl/r/rpl_sp.result +++ b/mysql-test/suite/rpl/r/rpl_sp.result @@ -433,9 +433,9 @@ master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 like t1 master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` PROCEDURE `foo3`() DETERMINISTIC insert into t1 values (15) -master-bin.000001 # Query 1 # use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to 'zedjzlcsjhd'@'127.0.0.1' -master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT on mysqltest1.t1 to 'zedjzlcsjhd'@'127.0.0.1' -master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to 'zedjzlcsjhd'@'127.0.0.1' +master-bin.000001 # Query 1 # use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1 +master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1 +master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1 master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`zedjzlcsjhd`@`127.0.0.1` PROCEDURE `foo4`() DETERMINISTIC begin @@ -510,7 +510,7 @@ select * from t1 master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo master-bin.000001 # Query 1 # use `mysqltest1`; drop function fn1 master-bin.000001 # Query 1 # drop database mysqltest1 -master-bin.000001 # Query 1 # DROP USER 'zedjzlcsjhd'@'127.0.0.1' +master-bin.000001 # Query 1 # drop user "zedjzlcsjhd"@127.0.0.1 master-bin.000001 # Query 1 # use `test`; drop function if exists f1 master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) READS SQL DATA @@ -675,13 +675,13 @@ CREATE DEFINER=`root`@`localhost` PROCEDURE `foo3`() insert into t1 values (15) /*!*/; SET TIMESTAMP=t/*!*/; -grant CREATE ROUTINE, EXECUTE on mysqltest1.* to 'zedjzlcsjhd'@'127.0.0.1' +grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1 /*!*/; SET TIMESTAMP=t/*!*/; -grant SELECT on mysqltest1.t1 to 'zedjzlcsjhd'@'127.0.0.1' +grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1 /*!*/; SET TIMESTAMP=t/*!*/; -grant SELECT, INSERT on mysqltest1.t2 to 'zedjzlcsjhd'@'127.0.0.1' +grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1 /*!*/; SET TIMESTAMP=t/*!*/; CREATE DEFINER=`zedjzlcsjhd`@`127.0.0.1` PROCEDURE `foo4`() @@ -842,7 +842,7 @@ SET TIMESTAMP=t/*!*/; drop database mysqltest1 /*!*/; SET TIMESTAMP=t/*!*/; -DROP USER 'zedjzlcsjhd'@'127.0.0.1' +drop user "zedjzlcsjhd"@127.0.0.1 /*!*/; use test/*!*/; SET TIMESTAMP=t/*!*/; diff --git a/mysql-test/suite/rpl/r/rpl_user.result b/mysql-test/suite/rpl/r/rpl_user.result index b1f1d73cf86..a98e7e9ca55 100644 --- a/mysql-test/suite/rpl/r/rpl_user.result +++ b/mysql-test/suite/rpl/r/rpl_user.result @@ -39,1754 +39,7 @@ show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; create user 'foo'@'fakehost' master-bin.000001 # Query # # use `test`; create user 'foo'@'fakehost', 'bar'@'fakehost' -master-bin.000001 # Query # # use `test`; RENAME USER 'foo'@'fakehost' TO 'foofoo'@'fakehost' -master-bin.000001 # Query # # use `test`; RENAME USER 'not_exist_user1'@'fakehost' TO 'foobar'@'fakehost', 'bar'@'fakehost' TO 'barbar'@'fakehost' -master-bin.000001 # Query # # use `test`; DROP USER 'foofoo'@'fakehost' -master-bin.000001 # Query # # use `test`; DROP USER 'not_exist_user1'@'fakehost', 'barbar'@'fakehost' - - - -TEST STATEMENT: 'RENAME USER $users_list' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user FROM mysql.user -WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'RENAME USER $users_list' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() TO 'bug48321_4'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -RENAME USER CURRENT_USER() TO 'bug48321_4'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'RENAME USER $users_list' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER() TO 'bug48321_4'@'localhost', 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -RENAME USER CURRENT_USER() TO 'bug48321_4'@'localhost', 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'RENAME USER $users_list' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', CURRENT_USER() TO 'bug48321_4'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -RENAME USER 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', CURRENT_USER() TO 'bug48321_4'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'RENAME USER $users_list' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', CURRENT_USER() TO 'bug48321_4'@'localhost', 'bug48321_3'@'localhost' TO 'bug48321_6'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -RENAME USER 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', CURRENT_USER() TO 'bug48321_4'@'localhost', 'bug48321_3'@'localhost' TO 'bug48321_6'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'RENAME USER $users_list' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', 'bug48321_3'@'localhost' TO 'bug48321_6'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -RENAME USER 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', 'bug48321_3'@'localhost' TO 'bug48321_6'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; - - - -TEST STATEMENT: 'DROP USER $users_list' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user FROM mysql.user -WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'DROP USER $users_list' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -DROP USER CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'DROP USER $users_list' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER(), 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -DROP USER CURRENT_USER(), 'bug48321_2'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'DROP USER $users_list' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -DROP USER 'bug48321_2'@'localhost', CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'DROP USER $users_list' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -DROP USER 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'DROP USER $users_list' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -DROP USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; -DROP PROCEDURE IF EXISTS f1; -CREATE PROCEDURE p1() SELECT 1; - - - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv -FROM mysql.user WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER(), 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(), 'bug48321_2'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; - - - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv -FROM mysql.user WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER() /*With comment*/; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER(), 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(), 'bug48321_2'@'localhost' /*With comment*/; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', CURRENT_USER() /*With comment*/; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' /*With comment*/; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' /*With comment*/; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; - - - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv -FROM mysql.user WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER(), 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ CURRENT_USER(), 'bug48321_2'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ 'bug48321_2'@'localhost', CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; - - - -TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv -FROM mysql.user WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER(), 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM CURRENT_USER(), 'bug48321_2'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM 'bug48321_2'@'localhost', CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; - - - -TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Create_routine_priv -FROM mysql.user WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE CREATE ROUTINE ON *.* FROM CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER(), 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE CREATE ROUTINE ON *.* FROM CURRENT_USER(), 'bug48321_2'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE CREATE ROUTINE ON *.* FROM 'bug48321_2'@'localhost', CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE CREATE ROUTINE ON *.* FROM 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE CREATE ROUTINE ON *.* FROM 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; - - - -TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Routine_name, Proc_priv -FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER(), 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(), 'bug48321_2'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM 'bug48321_2'@'localhost', CURRENT_USER(); - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -# Grant some privileges to users at first when testing -# 'REVOKE ...' statement. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', -'bug48321_3'@'localhost' WITH GRANT OPTION; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', -'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; - - - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv, Password -FROM mysql.user WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() IDENTIFIED BY 'user1' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1' WITH GRANT OPTION; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' WITH GRANT OPTION; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' WITH GRANT OPTION; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' WITH GRANT OPTION; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' WITH GRANT OPTION; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; - - - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv, Password -FROM mysql.user WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() IDENTIFIED BY 'user1' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1' /* With Comment */ WITH GRANT OPTION; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' /* With Comment */ WITH GRANT OPTION; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' /* With Comment */ WITH GRANT OPTION; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' /* With Comment */ WITH GRANT OPTION; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' /* With Comment */ WITH GRANT OPTION; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; - - - -TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Password -FROM mysql.user WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() IDENTIFIED BY 'user1' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO CURRENT_USER() IDENTIFIED BY 'user1'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY ''; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY ''; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; - - - -TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Create_routine_priv -FROM mysql.user WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() IDENTIFIED BY 'user1' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT CREATE ROUTINE ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT CREATE ROUTINE ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT CREATE ROUTINE ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT CREATE ROUTINE ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY ''; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT CREATE ROUTINE ON *.* TO 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY ''; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; -DROP PROCEDURE p1; - - - -TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' --------------------------------------------------------------------------- -CREATE VIEW test.bug48321_v1 AS SELECT user, Routine_name, Proc_priv -FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; - -TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' -CASE 1: -------- -# Only CURRENT_USER() in the user list of the test statement. -users_list= CURRENT_USER() IDENTIFIED BY 'user1' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER() IDENTIFIED BY 'user1'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' -CASE 2: -------- -# Two users are in the test statement, CURRENT_USER is the first one. -users_list= CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' -CASE 3: -------- -# Two users are in the test statement, CURRENT_USER is the last one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1'; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' -CASE 4: -------- -# Three users are in the test statement, CURRENT_USER is the second one. -users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY ''; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; - -TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' -CASE 5: -------- -# CURRENT_USER is not in the test statement. -users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' - -# Connect to master with user1, so user1 always is the current user, -# when test statement is runing. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' - WITH GRANT OPTION; -CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' - IDENTIFIED BY 'user3'; - -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY ''; - -Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 - -# Delete all bug48321% users -DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; -DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; -FLUSH PRIVILEGES; -DROP VIEW test.bug48321_v1; +master-bin.000001 # Query # # use `test`; rename user 'foo'@'fakehost' to 'foofoo'@'fakehost' +master-bin.000001 # Query # # use `test`; rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'bar'@'fakehost' to 'barbar'@'fakehost' +master-bin.000001 # Query # # use `test`; drop user 'foofoo'@'fakehost' +master-bin.000001 # Query # # use `test`; drop user 'not_exist_user1'@'fakehost', 'barbar'@'fakehost' diff --git a/mysql-test/suite/rpl/t/rpl_binlog_grant.test b/mysql-test/suite/rpl/t/rpl_binlog_grant.test index 64f4e8b2eeb..31163927ce2 100644 --- a/mysql-test/suite/rpl/t/rpl_binlog_grant.test +++ b/mysql-test/suite/rpl/t/rpl_binlog_grant.test @@ -25,7 +25,9 @@ grant select on t to x@y; # rollback; show grants for x@y; ---source include/show_binlog_events.inc +--replace_result $VERSION VERSION +--replace_regex /\/\* xid=.* \*\//\/* XID *\// +show binlog events; start transaction; insert into t values (2); revoke select on t from x@y; @@ -35,7 +37,9 @@ revoke select on t from x@y; commit; select * from t; show grants for x@y; ---source include/show_binlog_events.inc +--replace_result $VERSION VERSION +--replace_regex /\/\* xid=.* \*\//\/* XID *\// +show binlog events; drop user x@y; drop database d1; --sync_slave_with_master diff --git a/mysql-test/suite/rpl/t/rpl_events.test b/mysql-test/suite/rpl/t/rpl_events.test index 25976f779e3..7720ad6658c 100644 --- a/mysql-test/suite/rpl/t/rpl_events.test +++ b/mysql-test/suite/rpl/t/rpl_events.test @@ -105,85 +105,3 @@ DROP EVENT event44331_2; DROP EVENT event44331_3; DROP EVENT event44331_4; sync_slave_with_master; - -# -# BUG#48321 -# This test verifies if the definer is consistent between master and slave, -# when the event is created or altered with the DEFINER clause that the -# DEFINER is set to CURRENT_USER() -# -connection master; ---disable_warnings -DROP VIEW IF EXISTS events_view; -DROP EVENT IF EXISTS event48321_1; -DROP EVENT IF EXISTS event48321_2; -DROP EVENT IF EXISTS event48321_3; -DROP EVENT IF EXISTS event48321_4; ---enable_warnings - -CREATE VIEW events_view AS - SELECT EVENT_SCHEMA, EVENT_NAME, DEFINER FROM INFORMATION_SCHEMA.EVENTS - WHERE EVENT_NAME LIKE 'event48321%'; -let $diff_table_1= master:test.events_view; -let $diff_table_2= slave:test.events_view; - -CREATE DEFINER=CURRENT_USER() /*!50000 EVENT event48321_1 */ - ON SCHEDULE AT CURRENT_TIMESTAMP - ON COMPLETION PRESERVE DISABLE - DO SELECT 48321 as BUG; - -CREATE DEFINER=CURRENT_USER() EVENT event48321_2 - ON SCHEDULE AT CURRENT_TIMESTAMP - ON COMPLETION PRESERVE DISABLE - DO SELECT 48321 as BUG; - -CREATE /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 - ON SCHEDULE AT CURRENT_TIMESTAMP - ON COMPLETION PRESERVE DISABLE - DO SELECT 48321 as BUG; -sync_slave_with_master; - ---source include/diff_tables.inc - -connection master; -ALTER DEFINER=CURRENT_USER() EVENT event48321_1 RENAME TO event48321_4; - -ALTER DEFINER=CURRENT_USER() EVENT event48321_2 - ON SCHEDULE AT CURRENT_TIMESTAMP - ON COMPLETION PRESERVE DISABLE - DO SELECT 48321 as BUG; - -ALTER /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 - ON SCHEDULE AT CURRENT_TIMESTAMP - ON COMPLETION PRESERVE DISABLE - DO SELECT 48321 as BUG; -sync_slave_with_master; - ---source include/diff_tables.inc - -# Two statements in on query -connection master; -DELIMITER |; -ALTER /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 - ON SCHEDULE AT CURRENT_TIMESTAMP - ON COMPLETION PRESERVE DISABLE - DO SELECT 48321 as BUG; ALTER EVENT event48321_2 ENABLE | -DELIMITER ;| -sync_slave_with_master; - ---source include/diff_tables.inc - -#No Event boday -connection master; -ALTER EVENT event48321_3 ENABLE; -sync_slave_with_master; - ---source include/diff_tables.inc - -connection master; -DROP EVENT event48321_4; -DROP EVENT event48321_2; -DROP EVENT event48321_3; -DROP VIEW events_view; ---source include/master-slave-end.inc - diff --git a/mysql-test/suite/rpl/t/rpl_user.test b/mysql-test/suite/rpl/t/rpl_user.test index 2adb822839a..b8fe41d03c4 100644 --- a/mysql-test/suite/rpl/t/rpl_user.test +++ b/mysql-test/suite/rpl/t/rpl_user.test @@ -54,85 +54,8 @@ drop user 'not_exist_user1'@'fakehost', 'not_exist_user2'@'fakehost'; sync_slave_with_master; select Host,User from mysql.user where Host='fakehost'; +# +# show the binlog events on the master +# connection master; source include/show_binlog_events.inc; - -# -# BUG#48321 -# -let $action= RENAME; -let $statement= RENAME USER \$users_list; -source extra/rpl_tests/rpl_current_user.test; - -let $action= DROP; -let $statement= DROP USER \$users_list; -source extra/rpl_tests/rpl_current_user.test; - ---disable_warnings -DROP PROCEDURE IF EXISTS f1; ---enable_warnings -CREATE PROCEDURE p1() SELECT 1; -#REVOKE ALL PRIVILEGES -let $action= REVOKE; -let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv; -let $statement= REVOKE ALL PRIVILEGES, GRANT OPTION FROM \$users_list; -source extra/rpl_tests/rpl_current_user.test; - -#REVOKE ALL PRIVILEGES with comment -let $action= REVOKE; -let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv; -let $statement= REVOKE ALL PRIVILEGES, GRANT OPTION FROM \$users_list /*With comment*/; -source extra/rpl_tests/rpl_current_user.test; - -#REVOKE ALL PRIVILEGES with comment -let $action= REVOKE; -let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv; -let $statement= REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ \$users_list; -source extra/rpl_tests/rpl_current_user.test; - -let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv; -#REVOKE ON TABLE -let $statement= REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM \$users_list; -source extra/rpl_tests/rpl_current_user.test; - -#REVOKE ON CREATE ROUTINE -let $diff_columns= Create_routine_priv; -let $statement= REVOKE CREATE ROUTINE ON *.* FROM \$users_list; -source extra/rpl_tests/rpl_current_user.test; - -#REVOKE ON ROUTINE -let $diff_table= mysql.procs_priv; -let $diff_columns= Routine_name, Proc_priv; -let $statement= REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM \$users_list; -source extra/rpl_tests/rpl_current_user.test; - -let $diff_table= mysql.user; -#GRANT ALL PRIVILEGES -let $action= GRANT; -let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv, Password; -let $statement= GRANT ALL PRIVILEGES ON *.* TO \$users_list WITH GRANT OPTION; -source extra/rpl_tests/rpl_current_user.test; - -#GRANT ALL PRIVILEGES with comment -let $action= GRANT; -let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv, Password; -let $statement= GRANT ALL PRIVILEGES ON *.* TO \$users_list /* With Comment */ WITH GRANT OPTION; -source extra/rpl_tests/rpl_current_user.test; - -#GRANT ON TABLE -let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Password; -let $statement= GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO \$users_list; -source extra/rpl_tests/rpl_current_user.test; - -#GRANT ON CREATE ROUTINE -let $diff_columns= Create_routine_priv; -let $statement= GRANT CREATE ROUTINE ON *.* TO \$users_list; -source extra/rpl_tests/rpl_current_user.test; - -#GRANT ON ROUTINE -let $diff_table= mysql.procs_priv; -let $diff_columns= Routine_name, Proc_priv; -let $statement= GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO \$users_list; - -DROP PROCEDURE p1; -source extra/rpl_tests/rpl_current_user.test; diff --git a/sql/events.cc b/sql/events.cc index 6c8bdb1ea0f..4c6dd0f35d1 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -341,48 +341,31 @@ common_1_lev_code: } -/* - Binlog '{CREATE|ALTER} EVENT' statements. - Definer part is always rewritten, for definer can be CURRENT_USER() function. - +/** + Create a new query string for removing executable comments + for avoiding leak and keeping consistency of the execution + on master and slave. + @param[in] thd Thread handler - @param[in] create CREATE or ALTER statement + @param[in] buf Query string @return - FASE ok - TRUE error + 0 ok + 1 error */ -static bool event_write_bin_log(THD *thd, bool create) +static int +create_query_string(THD *thd, String *buf) { - String log_query; - if (create) - { - /* Append the "CREATE" part of the query */ - if (log_query.append(STRING_WITH_LEN("CREATE "))) - return TRUE; - } - else - { - /* Append the "ALETR " part of the query */ - if (log_query.append(STRING_WITH_LEN("ALTER "))) - return TRUE; - } - - /* Append definer - If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER - will be written into the binary log as the definer for the SQL thread. - */ - append_definer(thd, &log_query, &(thd->lex->definer->user), - &(thd->lex->definer->host)); - + /* Append the "CREATE" part of the query */ + if (buf->append(STRING_WITH_LEN("CREATE "))) + return 1; + /* Append definer */ + append_definer(thd, buf, &(thd->lex->definer->user), &(thd->lex->definer->host)); /* Append the left part of thd->query after "DEFINER" part */ - if (log_query.append(thd->lex->stmt_definition_begin, - thd->lex->stmt_definition_end - - thd->lex->stmt_definition_begin)) - return TRUE; - - return write_bin_log(thd, TRUE, log_query.c_ptr_safe(), log_query.length()) - != 0; + if (buf->append(thd->lex->stmt_definition_begin)) + return 1; + + return 0; } /** @@ -397,7 +380,8 @@ static bool event_write_bin_log(THD *thd, bool create) @sa Events::drop_event for the notes about locking, pre-locking and Events DDL. - @retval FALSE OK @retval TRUE Error (reported) + @retval FALSE OK + @retval TRUE Error (reported) */ bool @@ -481,7 +465,22 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, binlog the create event unless it's been successfully dropped */ if (!dropped) - ret= event_write_bin_log(thd, TRUE); + { + /* Binlog the create event. */ + DBUG_ASSERT(thd->query() && thd->query_length()); + String log_query; + if (create_query_string(thd, &log_query)) + { + sql_print_error("Event Error: An error occurred while creating query string, " + "before writing it into binary log."); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; + DBUG_RETURN(TRUE); + } + /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER + will be written into the binary log as the definer for the SQL thread. */ + ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); + } } pthread_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ @@ -603,7 +602,9 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, if (event_queue) event_queue->update_event(thd, parse_data->dbname, parse_data->name, new_element); - ret= event_write_bin_log(thd, FALSE); + /* Binlog the alter event. */ + DBUG_ASSERT(thd->query() && thd->query_length()); + ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } } pthread_mutex_unlock(&LOCK_event_metadata); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 70983f69746..a8828d15cae 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -194,7 +194,6 @@ static bool compare_hostname(const acl_host_and_ip *host,const char *hostname, const char *ip); static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); -static bool acl_write_bin_log(THD *thd, List &list, bool clear_error); /* Convert scrambled password to binary form, according to scramble type, @@ -3226,8 +3225,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!result) /* success */ { - if (acl_write_bin_log(thd, user_list, TRUE)) - result= -1; + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -3403,7 +3401,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (write_to_binlog) { - result|= acl_write_bin_log(thd, user_list, FALSE); + if (write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + result= TRUE; } rw_unlock(&LOCK_grant); @@ -3532,7 +3531,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, if (!result) { - result= acl_write_bin_log(thd, list, TRUE); + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -5664,9 +5663,9 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } -static void append_user(String *str, LEX_USER *user, bool comma= TRUE) +static void append_user(String *str, LEX_USER *user) { - if (comma && str->length()) + if (str->length()) str->append(','); str->append('\''); str->append(user->user.str); @@ -5675,65 +5674,6 @@ static void append_user(String *str, LEX_USER *user, bool comma= TRUE) str->append('\''); } -/* - The operations(DROP, RENAME, REVOKE, GRANT) will cause inconsistency between - master and slave, when CURRENT_USER() is used. To solve this problem, we - construct a new binlog statement in which CURRENT_USER() is replaced by - the real user name and host name. - */ -static bool acl_write_bin_log(THD *thd, List &list, bool clear_error) -{ - String log_query; - LEX *lex= thd->lex; - List_iterator user_list(list); - LEX_USER *user, *tmp_user; - - if (!mysql_bin_log.is_open()) - return FALSE; - - if (log_query.append(lex->stmt_begin, lex->stmt_user_begin - lex->stmt_begin)) - return TRUE; - while ((tmp_user= user_list++)) - { - if (!(user= get_current_user(thd, tmp_user))) - continue; - - /* - No User, but a password? - They did GRANT ... TO CURRENT_USER() IDENTIFIED BY ... ! - Get the current user, and shallow-copy the new password to them! - */ - if (!tmp_user->user.str && tmp_user->password.str) - user->password= tmp_user->password; - - if (log_query.append(" ", 1)) - return TRUE; - append_user(&log_query, user, FALSE); - /* Only 'GRANT' have password */ - if (user->password.str) - { - if (log_query.append(STRING_WITH_LEN(" IDENTIFIED BY ")) || - log_query.append(STRING_WITH_LEN("PASSWORD ")) || - log_query.append("'", 1) || - log_query.append(user->password.str, - user->password.length) || - log_query.append("'", 1)) - return TRUE; - } - if (log_query.append(",", 1)) - return TRUE; - } - /* It is binlogged only when at least one user is in the query */ - if (log_query.c_ptr()[log_query.length()-1] == ',') - { - log_query.length(log_query.length()-1); - if (log_query.append(lex->stmt_user_end, lex->stmt_end - lex->stmt_user_end)) - return TRUE; - return write_bin_log(thd, clear_error, log_query.c_ptr_safe(), - log_query.length()) != 0; - } - return FALSE; -} /* Create a list of users. @@ -5840,7 +5780,6 @@ bool mysql_drop_user(THD *thd, List &list) { int result; String wrong_users; - String log_query; LEX_USER *user_name, *tmp_user_name; List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; @@ -5870,7 +5809,6 @@ bool mysql_drop_user(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - log_query.append(STRING_WITH_LEN("DROP USER")); while ((tmp_user_name= user_list++)) { if (!(user_name= get_current_user(thd, tmp_user_name))) @@ -5878,17 +5816,6 @@ bool mysql_drop_user(THD *thd, List &list) result= TRUE; continue; } - - /* - The operation will cause inconsistency between master and slave, when - CURRENT_USER() is used. To solve this problem, we construct a new - binlog statement in which CURRENT_USER() is replaced by the real user - name and host name. - */ - log_query.append(STRING_WITH_LEN(" ")); - append_user(&log_query, user_name, FALSE); - log_query.append(STRING_WITH_LEN(",")); - if (handle_grant_data(tables, 1, user_name, NULL) <= 0) { append_user(&wrong_users, user_name); @@ -5907,13 +5834,7 @@ bool mysql_drop_user(THD *thd, List &list) my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe()); if (some_users_deleted) - { - if (log_query.c_ptr()[log_query.length()-1] == ',') - { - log_query.length(log_query.length()-1); - result|= write_bin_log(thd, FALSE, log_query.c_ptr_safe(), log_query.length()); - } - } + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5941,7 +5862,6 @@ bool mysql_rename_user(THD *thd, List &list) { int result; String wrong_users; - String log_query; LEX_USER *user_from, *tmp_user_from; LEX_USER *user_to, *tmp_user_to; List_iterator user_list(list); @@ -5969,7 +5889,6 @@ bool mysql_rename_user(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - log_query.append(STRING_WITH_LEN("RENAME USER")); while ((tmp_user_from= user_list++)) { if (!(user_from= get_current_user(thd, tmp_user_from))) @@ -5985,18 +5904,6 @@ bool mysql_rename_user(THD *thd, List &list) } DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */ - /* - The operation will cause inconsistency between master and slave, when - CURRENT_USER() is used. To solve this problem, we construct a new - binlog statement in which CURRENT_USER() is replaced by the real user - name and host name. - */ - log_query.append(STRING_WITH_LEN(" ")); - append_user(&log_query, user_from, FALSE); - log_query.append(STRING_WITH_LEN(" TO ")); - append_user(&log_query, user_to, FALSE); - log_query.append(STRING_WITH_LEN(",")); - /* Search all in-memory structures and grant tables for a mention of the new user name. @@ -6018,15 +5925,9 @@ bool mysql_rename_user(THD *thd, List &list) if (result) my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); - - if (some_users_renamed) - { - if (log_query.c_ptr()[log_query.length()-1] == ',') - { - log_query.length(log_query.length()-1); - result|= write_bin_log(thd, FALSE, log_query.c_ptr_safe(), log_query.length()); - } - } + + if (some_users_renamed && mysql_bin_log.is_open()) + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -6216,9 +6117,8 @@ bool mysql_revoke_all(THD *thd, List &list) VOID(pthread_mutex_unlock(&acl_cache->lock)); - int binlog_error= 0; - if (acl_write_bin_log(thd, list, FALSE)) - binlog_error= 1; + int binlog_error= + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 99f5257eb5e..4e4794ef2cf 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1727,8 +1727,6 @@ typedef struct st_lex : public Query_tables_list - CREATE TRIGGER (points to "TRIGGER"); - CREATE PROCEDURE (points to "PROCEDURE"); - CREATE FUNCTION (points to "FUNCTION" or "AGGREGATE"); - - CREATE VIEW(points to "VIEW"); - - CREATE EVENT(points to "EVENT"); This pointer is required to add possibly omitted DEFINER-clause to the DDL-statement before dumping it to the binlog. @@ -1737,29 +1735,6 @@ typedef struct st_lex : public Query_tables_list const char *stmt_definition_end; - /* - stmt_begin is intended to point to the begin of every statement. - It is now used in the following statements: - - GRANT ALL PRIVELEGES ON *.* (points to "GRANT"); - - REVOKE ALL PRIVELEGES ON *.* (points to "REVOKE"); - */ - const char *stmt_begin; - const char *stmt_end; - - /* - stmt_user_begin is intended to point to the begin of the user list in - the following statements: - - GRANT ALL PRIVELEGES ON *.* TO 'username'@'hostname' - (points to "'username'"); - - REVOKE ALL PRIVELEGES ON *.* FROM 'username'@'hostname' - (points to "'username'"); - - these pointers are required to replace the CURRENT_USER() - function by the real user before dumping it to the binlog. - */ - const char *stmt_user_begin; - const char *stmt_user_end; - /** During name resolution search only in the table list given by Name_resolution_context::first_name_resolution_table and diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 92c4de5b462..8dc08f8425f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1562,11 +1562,7 @@ opt_end_of_input: ; verb_clause: - remember_name statement remember_end - { - Lex->stmt_begin= $1; - Lex->stmt_end= $3; - } + statement | begin ; @@ -5747,7 +5743,7 @@ alter: } view_tail {} - | ALTER definer_opt remember_name EVENT_SYM sp_name + | ALTER definer_opt EVENT_SYM sp_name { /* It is safe to use Lex->spname because @@ -5759,8 +5755,7 @@ alter: if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) MYSQL_YYABORT; - Lex->event_parse_data->identifier= $5; - Lex->stmt_definition_begin= $3; + Lex->event_parse_data->identifier= $4; Lex->sql_command= SQLCOM_ALTER_EVENT; } @@ -5770,7 +5765,7 @@ alter: opt_ev_comment opt_ev_sql_stmt { - if (!($7 || $8 || $9 || $10 || $11)) + if (!($6 || $7 || $8 || $9 || $10)) { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; @@ -5831,16 +5826,7 @@ opt_ev_rename_to: ; opt_ev_sql_stmt: - /* empty*/ - { - $$= 0; - /* - Lex->sp_head is not initialized when event body is empty. - So we can not use Lex->sp_head->set_stmt_end() to set - stmt_definition_end. - */ - Lex->stmt_definition_end= (char*) YYLIP->get_cpp_tok_end(); - } + /* empty*/ { $$= 0;} | DO_SYM ev_sql_stmt { $$= 1; } ; @@ -11530,7 +11516,6 @@ user: $$->user = $1; $$->host.str= (char *) "%"; $$->host.length= 1; - Lex->stmt_user_end= YYLIP->get_cpp_ptr(); if (check_string_char_length(&$$->user, ER(ER_USERNAME), USERNAME_CHAR_LENGTH, @@ -11543,7 +11528,6 @@ user: if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) MYSQL_YYABORT; $$->user = $1; $$->host=$3; - Lex->stmt_user_end= YYLIP->get_cpp_ptr(); if (check_string_char_length(&$$->user, ER(ER_USERNAME), USERNAME_CHAR_LENGTH, @@ -11553,7 +11537,6 @@ user: } | CURRENT_USER optional_braces { - Lex->stmt_user_end= YYLIP->get_cpp_ptr(); if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user)))) MYSQL_YYABORT; /* @@ -12744,10 +12727,9 @@ user_list: ; grant_list: - { Lex->stmt_user_begin= YYLIP->get_cpp_ptr(); } grant_user { - if (Lex->users_list.push_back($2)) + if (Lex->users_list.push_back($1)) MYSQL_YYABORT; } | grant_list ',' grant_user @@ -12760,7 +12742,6 @@ grant_list: grant_user: user IDENTIFIED_SYM BY TEXT_STRING { - Lex->stmt_user_end= YYLIP->get_cpp_ptr(); $$=$1; $1->password=$4; if ($4.length) { @@ -12787,10 +12768,7 @@ grant_user: } } | user IDENTIFIED_SYM BY PASSWORD TEXT_STRING - { - Lex->stmt_user_end= YYLIP->get_cpp_ptr(); - $$= $1; $1->password= $5; - } + { $$= $1; $1->password= $5; } | user { $$= $1; $1->password= null_lex_str; } ; From 090c75d2b0e202ca103215fbf1211d7a85defae5 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Tue, 2 Feb 2010 16:34:32 +0100 Subject: [PATCH 270/344] Cleanup fix for WL#5154 that splits commands handling for --default-character-set and --character-set-server such that only the first will give a deprecation warning. Apart from that, the two options should do the same. --- sql/mysqld.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 40026867aaf..ca20299b36e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5733,7 +5733,8 @@ enum options_mysqld OPT_GENERAL_LOG_FILE, OPT_SLOW_QUERY_LOG_FILE, OPT_IGNORE_BUILTIN_INNODB, - OPT_BINLOG_DIRECT_NON_TRANS_UPDATE + OPT_BINLOG_DIRECT_NON_TRANS_UPDATE, + OPT_DEFAULT_CHARACTER_SET_OLD }; @@ -5859,7 +5860,8 @@ struct my_option my_long_options[] = {"debug", '#', "Debug log.", (uchar**) &default_dbug_option, (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"default-character-set", 'C', "Set the default character set (deprecated option, use --character-set-server instead).", + {"default-character-set", OPT_DEFAULT_CHARACTER_SET_OLD, + "Set the default character set (deprecated option, use --character-set-server instead).", (uchar**) &default_character_set_name, (uchar**) &default_character_set_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-collation", OPT_DEFAULT_COLLATION_OLD, "Set the default collation (deprecated option, use --collation-server instead).", @@ -7921,8 +7923,12 @@ mysqld_get_one_option(int optid, case 'b': strmake(mysql_home,argument,sizeof(mysql_home)-1); break; + case OPT_DEFAULT_CHARACTER_SET_OLD: // --default-character-set + WARN_DEPRECATED(NULL, VER_CELOSIA, + "--default-character-set", + "--character-set-server"); + /* Fall through */ case 'C': - WARN_DEPRECATED(NULL, VER_CELOSIA, "--default-character-set", "--character-set-server"); if (default_collation_name == compiled_default_collation_name) default_collation_name= 0; break; From e4b7138561d567041dbb2aa8ed366e3c3d31d58b Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 2 Feb 2010 18:37:56 +0200 Subject: [PATCH 271/344] Bug #49445: Assertion failed: 0, file .\item_row.cc, line 55 with fulltext search and row op. The search for fulltext indexes is searching for some special predicate layouts. While doing so it's not checking for the number of columns of the expressions it tries to calculate. And since row expressions can't return a single scalar value there was a crash. Fixed by checking if the expressions are scalar (in addition to being constant) before calling Item::val_xxx() methods. --- mysql-test/r/fulltext.result | 8 ++++++++ mysql-test/t/fulltext.test | 10 ++++++++++ sql/sql_select.cc | 24 ++++++++++++------------ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 1ef6656e7a4..f65823518d4 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -603,4 +603,12 @@ WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE) count(*) 0 DROP TABLE t1,t2,t3; +# +# Bug #49445: Assertion failed: 0, file .\item_row.cc, line 55 with +# fulltext search and row op +# +CREATE TABLE t1(a CHAR(1),FULLTEXT(a)); +SELECT 1 FROM t1 WHERE MATCH(a) AGAINST ('') AND ROW(a,a) > ROW(1,1); +1 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 3853a224fd5..57a90483ea9 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -545,4 +545,14 @@ SELECT count(*) FROM t1 WHERE DROP TABLE t1,t2,t3; +--echo # +--echo # Bug #49445: Assertion failed: 0, file .\item_row.cc, line 55 with +--echo # fulltext search and row op +--echo # + +CREATE TABLE t1(a CHAR(1),FULLTEXT(a)); +SELECT 1 FROM t1 WHERE MATCH(a) AGAINST ('') AND ROW(a,a) > ROW(1,1); +DROP TABLE t1; + + --echo End of 5.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0e36d35289f..da85ca27339 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3650,20 +3650,20 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array, cond_func=(Item_func_match *)cond; else if (func->arg_count == 2) { - Item_func *arg0=(Item_func *)(func->arguments()[0]), - *arg1=(Item_func *)(func->arguments()[1]); - if (arg1->const_item() && + Item *arg0= func->arguments()[0], + *arg1= func->arguments()[1]; + if (arg1->const_item() && arg1->cols() == 1 && ((functype == Item_func::GE_FUNC && arg1->val_real() > 0) || - (functype == Item_func::GT_FUNC && arg1->val_real() >=0)) && - arg0->type() == Item::FUNC_ITEM && - arg0->functype() == Item_func::FT_FUNC) - cond_func=(Item_func_match *) arg0; - else if (arg0->const_item() && + (functype == Item_func::GT_FUNC && arg1->val_real() >= 0)) && + arg0->type() == Item::FUNC_ITEM && + ((Item_func *) arg0)->functype() == Item_func::FT_FUNC) + cond_func= (Item_func_match *) arg0; + else if (arg0->const_item() && arg0->cols() == 1 && ((functype == Item_func::LE_FUNC && arg0->val_real() > 0) || - (functype == Item_func::LT_FUNC && arg0->val_real() >=0)) && - arg1->type() == Item::FUNC_ITEM && - arg1->functype() == Item_func::FT_FUNC) - cond_func=(Item_func_match *) arg1; + (functype == Item_func::LT_FUNC && arg0->val_real() >= 0)) && + arg1->type() == Item::FUNC_ITEM && + ((Item_func *) arg1)->functype() == Item_func::FT_FUNC) + cond_func= (Item_func_match *) arg1; } } else if (cond->type() == Item::COND_ITEM) From 679de2bb5eb36c900c0f9db189283e73ab4acbcc Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 21 Jan 2010 17:14:10 +0200 Subject: [PATCH 272/344] Bug #50276: Security flaw in INFORMATION_SCHEMA.TABLES check_access() returning false for a database does not guarantee that the access is granted to it. This wrong condition in filling the INFORMATION_SCHEMA tables causes extra tables to be returned to the user even if he has no rights to see them. Fixed by correcting the condition. --- mysql-test/r/information_schema.result | 22 +++++++++++++++++++++ mysql-test/t/information_schema.test | 27 ++++++++++++++++++++++++++ sql/sql_show.cc | 8 ++++---- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 9a75e478264..4ed7e4e700b 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1725,4 +1725,26 @@ SELECT 'OK' AS TEST_RESULT FROM INFORMATION_SCHEMA.PROCESSLIST WHERE time < 0; TEST_RESULT OK SET TIMESTAMP=DEFAULT; +# +# Bug #50276: Security flaw in INFORMATION_SCHEMA.TABLES +# +CREATE DATABASE db1; +USE db1; +CREATE TABLE t1 (id INT); +CREATE USER nonpriv; +USE test; +# connected as nonpriv +# Should return 0 +SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1'; +COUNT(*) +0 +USE INFORMATION_SCHEMA; +# Should return 0 +SELECT COUNT(*) FROM TABLES WHERE TABLE_NAME='t1'; +COUNT(*) +0 +# connected as root +DROP USER nonpriv; +DROP TABLE db1.t1; +DROP DATABASE db1; End of 5.1 tests. diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 392d1062492..f3ce3d87252 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1419,6 +1419,33 @@ SET TIMESTAMP=@@TIMESTAMP + 10000000; SELECT 'OK' AS TEST_RESULT FROM INFORMATION_SCHEMA.PROCESSLIST WHERE time < 0; SET TIMESTAMP=DEFAULT; + +--echo # +--echo # Bug #50276: Security flaw in INFORMATION_SCHEMA.TABLES +--echo # +CREATE DATABASE db1; +USE db1; +CREATE TABLE t1 (id INT); +CREATE USER nonpriv; +USE test; + +connect (nonpriv_con, localhost, nonpriv,,); +connection nonpriv_con; +--echo # connected as nonpriv +--echo # Should return 0 +SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1'; +USE INFORMATION_SCHEMA; +--echo # Should return 0 +SELECT COUNT(*) FROM TABLES WHERE TABLE_NAME='t1'; + +connection default; +--echo # connected as root +disconnect nonpriv_con; +DROP USER nonpriv; +DROP TABLE db1.t1; +DROP DATABASE db1; + + --echo End of 5.1 tests. # Wait till all disconnects are completed diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5ec40d4893c..989606300d8 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3367,11 +3367,11 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) while ((db_name= it++)) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (!check_access(thd,SELECT_ACL, db_name->str, - &thd->col_access, 0, 1, with_i_schema) || + if (!(check_access(thd,SELECT_ACL, db_name->str, + &thd->col_access, 0, 1, with_i_schema) || + (!thd->col_access && check_grant_db(thd, db_name->str))) || sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || - acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0) || - !check_grant_db(thd, db_name->str)) + acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0)) #endif { thd->no_warnings_for_error= 1; From 73f10f0662ce40b5cc6e8bc4d04f6cee45768ae7 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Thu, 21 Jan 2010 17:20:24 +0000 Subject: [PATCH 273/344] BUG#49481: RBR: MyISAM and bit fields may cause slave to stop on delete: cant find record Some engines return data for the record. Despite the fact that the null bit is set for some fields, their old value may still in the row. This can happen when unpacking an AI from the binlog on top of a previous record in which a field is set to NULL, which previously contained a value. Ultimately, this may cause the comparison of records to fail when the slave is doing an index or range scan. We fix this by deploying a call to reset() for each field that is set to null while unpacking a row from the binary log. Furthermore, we also add mixed mode test case to cover the scenario where updating and setting a field to null through a Query event and later searching it through a rows event will succeed. Finally, we also change the reset() method, from Field_bit class, so that it takes into account bits stored among the null bits and not only the ones stored in the record. mysql-test/suite/rpl/t/rpl_set_null_innodb.test: InnoDB test. mysql-test/suite/rpl/t/rpl_set_null_myisam.test: MyISAM test. mysql-test/suite/rpl_ndb/t/rpl_ndb_set_null.test: NDB test. sql/field.h: Changed reset so that it also clears the bits among the null_bits for the Field_bit class. sql/rpl_record.cc: Resetting field after setting it to null when unpacking row. --- mysql-test/extra/rpl_tests/rpl_set_null.test | 86 +++++++++++++++++++ .../suite/rpl/r/rpl_set_null_innodb.result | 35 ++++++++ .../suite/rpl/r/rpl_set_null_myisam.result | 35 ++++++++ .../suite/rpl/t/rpl_set_null_innodb.test | 6 ++ .../suite/rpl/t/rpl_set_null_myisam.test | 5 ++ .../suite/rpl_ndb/r/rpl_ndb_set_null.result | 35 ++++++++ .../suite/rpl_ndb/t/rpl_ndb_set_null.test | 6 ++ sql/field.h | 7 +- sql/rpl_record.cc | 11 +++ 9 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 mysql-test/extra/rpl_tests/rpl_set_null.test create mode 100644 mysql-test/suite/rpl/r/rpl_set_null_innodb.result create mode 100644 mysql-test/suite/rpl/r/rpl_set_null_myisam.result create mode 100644 mysql-test/suite/rpl/t/rpl_set_null_innodb.test create mode 100644 mysql-test/suite/rpl/t/rpl_set_null_myisam.test create mode 100644 mysql-test/suite/rpl_ndb/r/rpl_ndb_set_null.result create mode 100644 mysql-test/suite/rpl_ndb/t/rpl_ndb_set_null.test diff --git a/mysql-test/extra/rpl_tests/rpl_set_null.test b/mysql-test/extra/rpl_tests/rpl_set_null.test new file mode 100644 index 00000000000..f2aba089279 --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_set_null.test @@ -0,0 +1,86 @@ +# Both of the following tests check that comparison of binlog BI +# against SE record will not fail due to remains from previous values +# in the SE record (before a given field was set to null). +# +# In MIXED mode: +# - Insert and update are executed as statements +# - Delete is executed as a row event +# - Assertion: checks that comparison will not fail because the update +# statement will clear the record contents for the nulled +# field. If data was not cleared, some engines may keep +# the value and return it later as garbage - despite the +# fact that field is null. This may cause slave to +# falsely fail in the comparison (memcmp would fail +# because of "garbage" in record data). +# +# In ROW mode: +# - Insert, update and delete are executed as row events. +# - Assertion: checks that comparison will not fail because the update +# rows event will clear the record contents before +# feeding the new value to the SE. This protects against +# SEs that do not clear record contents when storing +# nulled fields. If the engine did not clear the data it +# would cause slave to falsely fail in the comparison +# (memcmp would fail because of "garbage" in record +# data). This scenario is pretty much the same described +# above in MIXED mode, but checks different execution +# path in the slave. + +# BUG#49481: RBR: MyISAM and bit fields may cause slave to stop on +# delete cant find record + +-- source include/master-slave-reset.inc + +-- connection master +-- eval CREATE TABLE t1 (c1 BIT, c2 INT) Engine=$engine +INSERT INTO `t1` VALUES ( 1, 1 ); +UPDATE t1 SET c1=NULL where c2=1; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +# triggers switch to row mode when on mixed +DELETE FROM t1 WHERE c2=1 LIMIT 1; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DROP TABLE t1; +-- sync_slave_with_master + +-- source include/master-slave-reset.inc + +-- connection master + +# BUG#49482: RBR: Replication may break on deletes when MyISAM tables +# + char field are used + +-- eval CREATE TABLE t1 (c1 CHAR) Engine=$engine + +INSERT INTO t1 ( c1 ) VALUES ( 'w' ) ; +SELECT * FROM t1; +UPDATE t1 SET c1=NULL WHERE c1='w'; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +# triggers switch to row mode when on mixed +DELETE FROM t1 LIMIT 2; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DROP TABLE t1; +-- sync_slave_with_master diff --git a/mysql-test/suite/rpl/r/rpl_set_null_innodb.result b/mysql-test/suite/rpl/r/rpl_set_null_innodb.result new file mode 100644 index 00000000000..41600a5fe1b --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_set_null_innodb.result @@ -0,0 +1,35 @@ +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; +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 (c1 BIT, c2 INT) Engine=InnoDB; +INSERT INTO `t1` VALUES ( 1, 1 ); +UPDATE t1 SET c1=NULL where c2=1; +Comparing tables master:test.t1 and slave:test.t1 +DELETE FROM t1 WHERE c2=1 LIMIT 1; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; +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 (c1 CHAR) Engine=InnoDB; +INSERT INTO t1 ( c1 ) VALUES ( 'w' ) ; +SELECT * FROM t1; +c1 +w +UPDATE t1 SET c1=NULL WHERE c1='w'; +Comparing tables master:test.t1 and slave:test.t1 +DELETE FROM t1 LIMIT 2; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; diff --git a/mysql-test/suite/rpl/r/rpl_set_null_myisam.result b/mysql-test/suite/rpl/r/rpl_set_null_myisam.result new file mode 100644 index 00000000000..cbd7010664a --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_set_null_myisam.result @@ -0,0 +1,35 @@ +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; +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 (c1 BIT, c2 INT) Engine=MyISAM; +INSERT INTO `t1` VALUES ( 1, 1 ); +UPDATE t1 SET c1=NULL where c2=1; +Comparing tables master:test.t1 and slave:test.t1 +DELETE FROM t1 WHERE c2=1 LIMIT 1; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; +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 (c1 CHAR) Engine=MyISAM; +INSERT INTO t1 ( c1 ) VALUES ( 'w' ) ; +SELECT * FROM t1; +c1 +w +UPDATE t1 SET c1=NULL WHERE c1='w'; +Comparing tables master:test.t1 and slave:test.t1 +DELETE FROM t1 LIMIT 2; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; diff --git a/mysql-test/suite/rpl/t/rpl_set_null_innodb.test b/mysql-test/suite/rpl/t/rpl_set_null_innodb.test new file mode 100644 index 00000000000..dba79b78fa1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_set_null_innodb.test @@ -0,0 +1,6 @@ +-- source include/have_binlog_format_mixed_or_row.inc +-- source include/master-slave.inc +-- source include/have_innodb.inc + +-- let $engine= InnoDB +-- source extra/rpl_tests/rpl_set_null.test diff --git a/mysql-test/suite/rpl/t/rpl_set_null_myisam.test b/mysql-test/suite/rpl/t/rpl_set_null_myisam.test new file mode 100644 index 00000000000..7b433071553 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_set_null_myisam.test @@ -0,0 +1,5 @@ +-- source include/have_binlog_format_mixed_or_row.inc +-- source include/master-slave.inc + +-- let $engine= MyISAM +-- source extra/rpl_tests/rpl_set_null.test diff --git a/mysql-test/suite/rpl_ndb/r/rpl_ndb_set_null.result b/mysql-test/suite/rpl_ndb/r/rpl_ndb_set_null.result new file mode 100644 index 00000000000..473cd63169c --- /dev/null +++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_set_null.result @@ -0,0 +1,35 @@ +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; +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 (c1 BIT, c2 INT) Engine=NDB; +INSERT INTO `t1` VALUES ( 1, 1 ); +UPDATE t1 SET c1=NULL where c2=1; +Comparing tables master:test.t1 and slave:test.t1 +DELETE FROM t1 WHERE c2=1 LIMIT 1; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; +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 (c1 CHAR) Engine=NDB; +INSERT INTO t1 ( c1 ) VALUES ( 'w' ) ; +SELECT * FROM t1; +c1 +w +UPDATE t1 SET c1=NULL WHERE c1='w'; +Comparing tables master:test.t1 and slave:test.t1 +DELETE FROM t1 LIMIT 2; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_set_null.test b/mysql-test/suite/rpl_ndb/t/rpl_ndb_set_null.test new file mode 100644 index 00000000000..454807d9591 --- /dev/null +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_set_null.test @@ -0,0 +1,6 @@ +-- source include/have_ndb.inc +-- source include/have_binlog_format_mixed_or_row.inc +-- source include/ndb_master-slave.inc + +-- let $engine= NDB +-- source extra/rpl_tests/rpl_set_null.test diff --git a/sql/field.h b/sql/field.h index ae074cc1a30..55604193687 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1926,7 +1926,12 @@ public: uint32 max_display_length() { return field_length; } uint size_of() const { return sizeof(*this); } Item_result result_type () const { return INT_RESULT; } - int reset(void) { bzero(ptr, bytes_in_rec); return 0; } + int reset(void) { + bzero(ptr, bytes_in_rec); + if (bit_ptr && (bit_len > 0)) // reset odd bits among null bits + clr_rec_bits(bit_ptr, bit_ofs, bit_len); + return 0; + } int store(const char *to, uint length, CHARSET_INFO *charset); int store(double nr); int store(longlong nr, bool unsigned_val); diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 8e80620dd2c..f6bf57cde3e 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -231,6 +231,17 @@ unpack_row(Relay_log_info const *rli, { DBUG_PRINT("debug", ("Was NULL; null mask: 0x%x; null bits: 0x%x", null_mask, null_bits)); + /** + Calling reset just in case one is unpacking on top a + record with data. + + This could probably go into set_null() but doing so, + (i) triggers assertion in other parts of the code at + the moment; (ii) it would make us reset the field, + always when setting null, which right now doesn't seem + needed anywhere else except here. + */ + f->reset(); f->set_null(); } else From f42a200e9e1e535dcf647237fcb4ccb65c04965d Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Fri, 22 Jan 2010 10:37:44 +0100 Subject: [PATCH 274/344] Post-commit fix of two tests The WL#5154 commit added a couple of warning messages that was not fixed in the result files for two RPL tests. --- mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result | 2 ++ mysql-test/suite/rpl/r/rpl_sp.result | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result b/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result index 2cb316c6a1f..449407742de 100644 --- a/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result +++ b/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result @@ -152,6 +152,7 @@ c1 c3 c4 c5 5 2006-02-22 00:00:00 Tested in Texas 11 --- Test 2 position test -- +Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; @@ -314,6 +315,7 @@ ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; --- Test 7 reading stdin w/position -- +Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; diff --git a/mysql-test/suite/rpl/r/rpl_sp.result b/mysql-test/suite/rpl/r/rpl_sp.result index 90a362c352b..7fedaf4c1ef 100644 --- a/mysql-test/suite/rpl/r/rpl_sp.result +++ b/mysql-test/suite/rpl/r/rpl_sp.result @@ -195,7 +195,7 @@ set @old_log_bin_trust_routine_creators= @@global.log_bin_trust_routine_creators set @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; set global log_bin_trust_routine_creators=1; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.6. Please use '@@log_bin_trust_function_creators' instead set global log_bin_trust_function_creators=0; set global log_bin_trust_function_creators=1; set @old_log_bin_trust_routine_creators= @@global.log_bin_trust_routine_creators; @@ -559,11 +559,11 @@ end master-bin.000001 # Query 1 # use `mysqltest`; SELECT `mysqltest2`.`f1`() set @@global.log_bin_trust_routine_creators= @old_log_bin_trust_routine_creators; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.6. Please use '@@log_bin_trust_function_creators' instead set @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; set @@global.log_bin_trust_routine_creators= @old_log_bin_trust_routine_creators; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.6. Please use '@@log_bin_trust_function_creators' instead set @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; drop database mysqltest; drop database mysqltest2; From 3cae7d1187795a8089b6f54ac60cf2a0e579cf89 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Jan 2010 17:38:21 +0800 Subject: [PATCH 275/344] Bug #49132 Replication failure on temporary table + DDL In RBR, DDL statement will change binlog format to non row-based format before it is binlogged, but the binlog format was not be restored, and then manipulating a temporary table can not reset binlog format to row-based format rightly. So that the manipulated statement is binlogged with statement-based format. To fix the problem, restore the state of binlog format after the DDL statement is binlogged. mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test: Added the test file to verify if executing DDL statement before trying to manipulate a temporary table causes row-based replication to break with error 'table does not exist'. mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result: Correct the test result, all the above binlog event should be row-based after the bug49132 is fixed IN RBR. mysql-test/suite/ndb/r/ndb_tmp_table_and_DDL.result: Test result for bug#49132 base on ndb engine. mysql-test/suite/ndb/t/ndb_tmp_table_and_DDL.test: Added the test file to verify if executing DDL statement before trying to manipulate a temporary table causes row-based replication to break with error 'table does not exist' base on ndb engine. mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result: Test result for bug#49132 base on myisam engine. mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test: Added the test file to verify if executing DDL statement before trying to manipulate a temporary table causes row-based replication to break with error 'table does not exist' base on myisam engine. sql/event_db_repository.cc: Added code to restore the state of binlog format after the DDL statement is binlogged. sql/events.cc: Added code to restore the state of binlog format after the DDL statement is binlogged. sql/sp.cc: Added code to restore the state of binlog format after the DDL statement is binlogged. sql/sql_acl.cc: Added code to restore the state of binlog format after the DDL statement is binlogged. sql/sql_udf.cc: Added code to restore the state of binlog format after the DDL statement is binlogged. --- .../rpl_tests/rpl_tmp_table_and_DDL.test | 159 ++++++++++++++++++ .../r/binlog_row_mix_innodb_myisam.result | 64 ++++--- .../suite/ndb/r/ndb_tmp_table_and_DDL.result | 90 ++++++++++ .../suite/ndb/t/ndb_tmp_table_and_DDL.test | 11 ++ .../suite/rpl/r/rpl_tmp_table_and_DDL.result | 96 +++++++++++ .../suite/rpl/t/rpl_tmp_table_and_DDL.test | 13 ++ sql/event_db_repository.cc | 7 +- sql/events.cc | 23 ++- sql/sp.cc | 13 ++ sql/sql_acl.cc | 66 ++++++++ sql/sql_udf.cc | 18 +- 11 files changed, 526 insertions(+), 34 deletions(-) create mode 100644 mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test create mode 100644 mysql-test/suite/ndb/r/ndb_tmp_table_and_DDL.result create mode 100644 mysql-test/suite/ndb/t/ndb_tmp_table_and_DDL.test create mode 100644 mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result create mode 100644 mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test diff --git a/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test b/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test new file mode 100644 index 00000000000..9cf287281a0 --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test @@ -0,0 +1,159 @@ +# +# This test verify if executing DDL statement before trying to manipulate +# a temporary table causes row-based replication to break with error 'table +# does not exist'. +# + +# CREATE TABLE when a temporary table is open. +CREATE TEMPORARY TABLE t1 (a INT); +EVAL CREATE TABLE t2 (a INT, b INT) ENGINE= $ENGINE_TYPE; +INSERT INTO t1 VALUES (1); + +# CREATE EVENT when a temporary table is open. +CREATE EVENT e1 ON SCHEDULE EVERY 10 HOUR DO SELECT 1; +INSERT INTO t1 VALUES (1); + +# ALTER EVENT when a temporary table is open. +ALTER EVENT e1 ON SCHEDULE EVERY 20 HOUR DO SELECT 1; +INSERT INTO t1 VALUES (1); + +# DROP EVENT when a temporary table is open. +DROP EVENT IF EXISTS e1; +INSERT INTO t1 VALUES (1); + +# CREATE PROCEDURE when a temporary table is open. +CREATE PROCEDURE p1() SELECT 1; +INSERT INTO t1 VALUES (1); + +# Alter PROCEDURE when a temporary table is open. +ALTER PROCEDURE p1 SQL SECURITY INVOKER; +INSERT INTO t1 VALUES (1); + +# CREATE FUNCTION when a temporary table is open. +CREATE FUNCTION f1() RETURNS INT RETURN 123; +INSERT INTO t1 VALUES (1); + +# ALTER FUNCTION when a temporary table is open. +ALTER FUNCTION f1 SQL SECURITY INVOKER; +INSERT INTO t1 VALUES (1); + +# CREATE DATABASE when a temporary table is open. +CREATE DATABASE mysqltest1; +INSERT INTO t1 VALUES (1); + +# DROP DATABASE when a temporary table is open. +DROP DATABASE mysqltest1; +INSERT INTO t1 VALUES (1); + +# CREATE USER when a temporary table is open. +CREATE USER test_1@localhost; +INSERT INTO t1 VALUES (1); + +# GRANT select on table to user when a temporary table is open. +GRANT SELECT ON t2 TO test_1@localhost; +INSERT INTO t1 VALUES (1); + +# GRANT all on function to user when a temporary table is open. +GRANT ALL ON f1 TO test_1@localhost; +INSERT INTO t1 VALUES (1); + +# GRANT all on procedure to user when a temporary table is open. +GRANT ALL ON p1 TO test_1@localhost; +INSERT INTO t1 VALUES (1); + +# GRANT usage on *.* to user when a temporary table is open. +GRANT USAGE ON *.* TO test_1@localhost; +INSERT INTO t1 VALUES (1); + +# REVOKE ALL PRIVILEGES on function to user when a temporary table is open. +REVOKE ALL PRIVILEGES ON f1 FROM test_1@localhost; +INSERT INTO t1 VALUES (1); + +# REVOKE ALL PRIVILEGES on procedure to user when a temporary table is open. +REVOKE ALL PRIVILEGES ON p1 FROM test_1@localhost; +INSERT INTO t1 VALUES (1); + +# REVOKE ALL PRIVILEGES on table to user when a temporary table is open. +REVOKE ALL PRIVILEGES ON t2 FROM test_1@localhost; +INSERT INTO t1 VALUES (1); + +# REVOKE usage on *.* from user when a temporary table is open. +REVOKE USAGE ON *.* FROM test_1@localhost; +INSERT INTO t1 VALUES (1); + +# RENAME USER when a temporary table is open. +RENAME USER test_1@localhost TO test_2@localhost; +INSERT INTO t1 VALUES (1); + +# DROP USER when a temporary table is open. +DROP USER test_2@localhost; +INSERT INTO t1 VALUES (1); + +# Test ACL statement in sub statement +DELIMITER |; +CREATE PROCEDURE p2() +BEGIN + # CREATE USER when a temporary table is open. + CREATE TEMPORARY TABLE t3 (a INT); + CREATE USER test_2@localhost; + INSERT INTO t1 VALUES (1); + + # GRANT select on table to user when a temporary table is open. + GRANT SELECT ON t2 TO test_2@localhost; + INSERT INTO t1 VALUES (1); + + # GRANT all on function to user when a temporary table is open. + GRANT ALL ON f1 TO test_2@localhost; + INSERT INTO t1 VALUES (1); + + # GRANT all on procedure to user when a temporary table is open. + GRANT ALL ON p1 TO test_2@localhost; + INSERT INTO t1 VALUES (1); + + # GRANT usage on *.* to user when a temporary table is open. + GRANT USAGE ON *.* TO test_2@localhost; + INSERT INTO t1 VALUES (1); + + # REVOKE ALL PRIVILEGES on function to user when a temporary table is open. + REVOKE ALL PRIVILEGES ON f1 FROM test_2@localhost; + INSERT INTO t1 VALUES (1); + + # REVOKE ALL PRIVILEGES on procedure to user when a temporary table is open. + REVOKE ALL PRIVILEGES ON p1 FROM test_2@localhost; + INSERT INTO t1 VALUES (1); + + # REVOKE ALL PRIVILEGES on table to user when a temporary table is open. + REVOKE ALL PRIVILEGES ON t2 FROM test_2@localhost; + INSERT INTO t1 VALUES (1); + + # REVOKE usage on *.* from user when a temporary table is open. + REVOKE USAGE ON *.* FROM test_2@localhost; + INSERT INTO t1 VALUES (1); + + # RENAME USER when a temporary table is open. + RENAME USER test_2@localhost TO test_3@localhost; + INSERT INTO t1 VALUES (1); + + # DROP USER when a temporary table is open. + DROP USER test_3@localhost; + INSERT INTO t1 VALUES (1); + DROP TEMPORARY TABLE t3; +END | +DELIMITER ;| + +# DROP PROCEDURE when a temporary table is open. +DROP PROCEDURE p1; +INSERT INTO t1 VALUES (1); +DROP PROCEDURE p2; +INSERT INTO t1 VALUES (1); + +# DROP FUNCTION when a temporary table is open. +DROP FUNCTION f1; +INSERT INTO t1 VALUES (1); + +# DROP TABLE when a temporary table is open. +DROP TABLE t2; +INSERT INTO t1 VALUES (1); + +DROP TEMPORARY TABLE t1; + diff --git a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result index ef98275041c..87e9b7f8685 100644 --- a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result @@ -772,8 +772,11 @@ insert into t2 values (bug27417(2)); ERROR 23000: Duplicate entry '2' for key 'PRIMARY' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Intvar # # INSERT_ID=3 -master-bin.000001 # Query # # use `test`; insert into t2 values (bug27417(2)) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # ROLLBACK select count(*) from t1 /* must be 3 */; count(*) 3 @@ -787,8 +790,11 @@ count(*) 2 show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Intvar # # INSERT_ID=4 -master-bin.000001 # Query # # use `test`; delete from t2 where a=bug27417(3) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # COMMIT select count(*) from t1 /* must be 5 */; count(*) 5 @@ -810,8 +816,9 @@ ERROR 23000: Duplicate entry '1' for key 'PRIMARY' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN -master-bin.000001 # Intvar # # INSERT_ID=1 -master-bin.000001 # Query # # use `test`; insert into t2 values (bug27417(1)) +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # ROLLBACK select count(*) from t1 /* must be 1 */; count(*) @@ -825,8 +832,10 @@ ERROR 23000: Duplicate entry '2' for key 'PRIMARY' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN -master-bin.000001 # Intvar # # INSERT_ID=2 -master-bin.000001 # Query # # use `test`; insert into t2 select bug27417(1) union select bug27417(2) +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows # # table_id: # +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # ROLLBACK select count(*) from t1 /* must be 2 */; count(*) @@ -838,8 +847,13 @@ update t3 set b=b+bug27417(1); ERROR 23000: Duplicate entry '4' for key 'b' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Intvar # # INSERT_ID=4 -master-bin.000001 # Query # # use `test`; update t3 set b=b+bug27417(1) +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t3) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows # # table_id: # +master-bin.000001 # Update_rows # # table_id: # +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # ROLLBACK select count(*) from t1 /* must be 2 */; count(*) 2 @@ -853,8 +867,9 @@ ERROR 23000: Duplicate entry '2' for key 'PRIMARY' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN -master-bin.000001 # Intvar # # INSERT_ID=6 -master-bin.000001 # Query # # use `test`; UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */ +master-bin.000001 # Table_map # # table_id: # (test.t4) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # ROLLBACK select count(*) from t1 /* must be 4 */; count(*) @@ -869,7 +884,7 @@ UPDATE t3,t4 SET t3.a=t4.a + bug27417(1); ERROR 23000: Duplicate entry '2' for key 'PRIMARY' select count(*) from t1 /* must be 1 */; count(*) -1 +2 drop table t4; delete from t1; delete from t2; @@ -884,8 +899,10 @@ ERROR 23000: Duplicate entry '1' for key 'PRIMARY' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN -master-bin.000001 # Intvar # # INSERT_ID=9 -master-bin.000001 # Query # # use `test`; delete from t2 +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Table_map # # table_id: # (test.t3) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # ROLLBACK select count(*) from t1 /* must be 1 */; count(*) @@ -904,7 +921,11 @@ ERROR 23000: Duplicate entry '1' for key 'PRIMARY' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test`; delete t2.* from t2,t5 where t2.a=t5.a + 1 +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Delete_rows # # table_id: # +master-bin.000001 # Write_rows # # table_id: # +master-bin.000001 # Delete_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # ROLLBACK select count(*) from t1 /* must be 1 */; count(*) @@ -924,12 +945,11 @@ count(*) show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN -master-bin.000001 # Intvar # # INSERT_ID=10 -master-bin.000001 # User var # # @`b`=_latin1 0x3135 COLLATE latin1_swedish_ci -master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# -master-bin.000001 # Intvar # # INSERT_ID=10 -master-bin.000001 # User var # # @`b`=_latin1 0x3135 COLLATE latin1_swedish_ci -master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, @b) SET `b`=((@b) + `bug27417`(2)) ;file_id=# +master-bin.000001 # Table_map # # table_id: # (test.t4) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows # # table_id: # +master-bin.000001 # Write_rows # # table_id: # +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # ROLLBACK drop trigger trg_del_t2; drop table t1,t2,t3,t4,t5; diff --git a/mysql-test/suite/ndb/r/ndb_tmp_table_and_DDL.result b/mysql-test/suite/ndb/r/ndb_tmp_table_and_DDL.result new file mode 100644 index 00000000000..1b0f718ad65 --- /dev/null +++ b/mysql-test/suite/ndb/r/ndb_tmp_table_and_DDL.result @@ -0,0 +1,90 @@ +CREATE TEMPORARY TABLE t1 (a INT); +CREATE TABLE t2 (a INT, b INT) ENGINE= NDB; +INSERT INTO t1 VALUES (1); +CREATE EVENT e1 ON SCHEDULE EVERY 10 HOUR DO SELECT 1; +INSERT INTO t1 VALUES (1); +ALTER EVENT e1 ON SCHEDULE EVERY 20 HOUR DO SELECT 1; +INSERT INTO t1 VALUES (1); +DROP EVENT IF EXISTS e1; +INSERT INTO t1 VALUES (1); +CREATE PROCEDURE p1() SELECT 1; +INSERT INTO t1 VALUES (1); +ALTER PROCEDURE p1 SQL SECURITY INVOKER; +INSERT INTO t1 VALUES (1); +CREATE FUNCTION f1() RETURNS INT RETURN 123; +INSERT INTO t1 VALUES (1); +ALTER FUNCTION f1 SQL SECURITY INVOKER; +INSERT INTO t1 VALUES (1); +CREATE DATABASE mysqltest1; +INSERT INTO t1 VALUES (1); +DROP DATABASE mysqltest1; +INSERT INTO t1 VALUES (1); +CREATE USER test_1@localhost; +INSERT INTO t1 VALUES (1); +GRANT SELECT ON t2 TO test_1@localhost; +INSERT INTO t1 VALUES (1); +GRANT ALL ON f1 TO test_1@localhost; +INSERT INTO t1 VALUES (1); +GRANT ALL ON p1 TO test_1@localhost; +INSERT INTO t1 VALUES (1); +GRANT USAGE ON *.* TO test_1@localhost; +INSERT INTO t1 VALUES (1); +REVOKE ALL PRIVILEGES ON f1 FROM test_1@localhost; +INSERT INTO t1 VALUES (1); +REVOKE ALL PRIVILEGES ON p1 FROM test_1@localhost; +INSERT INTO t1 VALUES (1); +REVOKE ALL PRIVILEGES ON t2 FROM test_1@localhost; +INSERT INTO t1 VALUES (1); +REVOKE USAGE ON *.* FROM test_1@localhost; +INSERT INTO t1 VALUES (1); +RENAME USER test_1@localhost TO test_2@localhost; +INSERT INTO t1 VALUES (1); +DROP USER test_2@localhost; +INSERT INTO t1 VALUES (1); +CREATE PROCEDURE p2() +BEGIN +# CREATE USER when a temporary table is open. +CREATE TEMPORARY TABLE t3 (a INT); +CREATE USER test_2@localhost; +INSERT INTO t1 VALUES (1); +# GRANT select on table to user when a temporary table is open. +GRANT SELECT ON t2 TO test_2@localhost; +INSERT INTO t1 VALUES (1); +# GRANT all on function to user when a temporary table is open. +GRANT ALL ON f1 TO test_2@localhost; +INSERT INTO t1 VALUES (1); +# GRANT all on procedure to user when a temporary table is open. +GRANT ALL ON p1 TO test_2@localhost; +INSERT INTO t1 VALUES (1); +# GRANT usage on *.* to user when a temporary table is open. +GRANT USAGE ON *.* TO test_2@localhost; +INSERT INTO t1 VALUES (1); +# REVOKE ALL PRIVILEGES on function to user when a temporary table is open. +REVOKE ALL PRIVILEGES ON f1 FROM test_2@localhost; +INSERT INTO t1 VALUES (1); +# REVOKE ALL PRIVILEGES on procedure to user when a temporary table is open. +REVOKE ALL PRIVILEGES ON p1 FROM test_2@localhost; +INSERT INTO t1 VALUES (1); +# REVOKE ALL PRIVILEGES on table to user when a temporary table is open. +REVOKE ALL PRIVILEGES ON t2 FROM test_2@localhost; +INSERT INTO t1 VALUES (1); +# REVOKE usage on *.* from user when a temporary table is open. +REVOKE USAGE ON *.* FROM test_2@localhost; +INSERT INTO t1 VALUES (1); +# RENAME USER when a temporary table is open. +RENAME USER test_2@localhost TO test_3@localhost; +INSERT INTO t1 VALUES (1); +# DROP USER when a temporary table is open. +DROP USER test_3@localhost; +INSERT INTO t1 VALUES (1); +DROP TEMPORARY TABLE t3; +END | +DROP PROCEDURE p1; +INSERT INTO t1 VALUES (1); +DROP PROCEDURE p2; +INSERT INTO t1 VALUES (1); +DROP FUNCTION f1; +INSERT INTO t1 VALUES (1); +DROP TABLE t2; +INSERT INTO t1 VALUES (1); +DROP TEMPORARY TABLE t1; diff --git a/mysql-test/suite/ndb/t/ndb_tmp_table_and_DDL.test b/mysql-test/suite/ndb/t/ndb_tmp_table_and_DDL.test new file mode 100644 index 00000000000..748c0ac28e4 --- /dev/null +++ b/mysql-test/suite/ndb/t/ndb_tmp_table_and_DDL.test @@ -0,0 +1,11 @@ +# +# Bug#49132 +# This test verifies if executing DDL statement before trying to manipulate +# a temporary table causes row-based replication to break with error 'table +# does not exist' base on ndb engine. +# + +source include/have_ndb.inc; + +LET $ENGINE_TYPE= NDB; +source extra/rpl_tests/rpl_tmp_table_and_DDL.test; diff --git a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result new file mode 100644 index 00000000000..5729faa9659 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result @@ -0,0 +1,96 @@ +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 TEMPORARY TABLE t1 (a INT); +CREATE TABLE t2 (a INT, b INT) ENGINE= MyISAM; +INSERT INTO t1 VALUES (1); +CREATE EVENT e1 ON SCHEDULE EVERY 10 HOUR DO SELECT 1; +INSERT INTO t1 VALUES (1); +ALTER EVENT e1 ON SCHEDULE EVERY 20 HOUR DO SELECT 1; +INSERT INTO t1 VALUES (1); +DROP EVENT IF EXISTS e1; +INSERT INTO t1 VALUES (1); +CREATE PROCEDURE p1() SELECT 1; +INSERT INTO t1 VALUES (1); +ALTER PROCEDURE p1 SQL SECURITY INVOKER; +INSERT INTO t1 VALUES (1); +CREATE FUNCTION f1() RETURNS INT RETURN 123; +INSERT INTO t1 VALUES (1); +ALTER FUNCTION f1 SQL SECURITY INVOKER; +INSERT INTO t1 VALUES (1); +CREATE DATABASE mysqltest1; +INSERT INTO t1 VALUES (1); +DROP DATABASE mysqltest1; +INSERT INTO t1 VALUES (1); +CREATE USER test_1@localhost; +INSERT INTO t1 VALUES (1); +GRANT SELECT ON t2 TO test_1@localhost; +INSERT INTO t1 VALUES (1); +GRANT ALL ON f1 TO test_1@localhost; +INSERT INTO t1 VALUES (1); +GRANT ALL ON p1 TO test_1@localhost; +INSERT INTO t1 VALUES (1); +GRANT USAGE ON *.* TO test_1@localhost; +INSERT INTO t1 VALUES (1); +REVOKE ALL PRIVILEGES ON f1 FROM test_1@localhost; +INSERT INTO t1 VALUES (1); +REVOKE ALL PRIVILEGES ON p1 FROM test_1@localhost; +INSERT INTO t1 VALUES (1); +REVOKE ALL PRIVILEGES ON t2 FROM test_1@localhost; +INSERT INTO t1 VALUES (1); +REVOKE USAGE ON *.* FROM test_1@localhost; +INSERT INTO t1 VALUES (1); +RENAME USER test_1@localhost TO test_2@localhost; +INSERT INTO t1 VALUES (1); +DROP USER test_2@localhost; +INSERT INTO t1 VALUES (1); +CREATE PROCEDURE p2() +BEGIN +# CREATE USER when a temporary table is open. +CREATE TEMPORARY TABLE t3 (a INT); +CREATE USER test_2@localhost; +INSERT INTO t1 VALUES (1); +# GRANT select on table to user when a temporary table is open. +GRANT SELECT ON t2 TO test_2@localhost; +INSERT INTO t1 VALUES (1); +# GRANT all on function to user when a temporary table is open. +GRANT ALL ON f1 TO test_2@localhost; +INSERT INTO t1 VALUES (1); +# GRANT all on procedure to user when a temporary table is open. +GRANT ALL ON p1 TO test_2@localhost; +INSERT INTO t1 VALUES (1); +# GRANT usage on *.* to user when a temporary table is open. +GRANT USAGE ON *.* TO test_2@localhost; +INSERT INTO t1 VALUES (1); +# REVOKE ALL PRIVILEGES on function to user when a temporary table is open. +REVOKE ALL PRIVILEGES ON f1 FROM test_2@localhost; +INSERT INTO t1 VALUES (1); +# REVOKE ALL PRIVILEGES on procedure to user when a temporary table is open. +REVOKE ALL PRIVILEGES ON p1 FROM test_2@localhost; +INSERT INTO t1 VALUES (1); +# REVOKE ALL PRIVILEGES on table to user when a temporary table is open. +REVOKE ALL PRIVILEGES ON t2 FROM test_2@localhost; +INSERT INTO t1 VALUES (1); +# REVOKE usage on *.* from user when a temporary table is open. +REVOKE USAGE ON *.* FROM test_2@localhost; +INSERT INTO t1 VALUES (1); +# RENAME USER when a temporary table is open. +RENAME USER test_2@localhost TO test_3@localhost; +INSERT INTO t1 VALUES (1); +# DROP USER when a temporary table is open. +DROP USER test_3@localhost; +INSERT INTO t1 VALUES (1); +DROP TEMPORARY TABLE t3; +END | +DROP PROCEDURE p1; +INSERT INTO t1 VALUES (1); +DROP PROCEDURE p2; +INSERT INTO t1 VALUES (1); +DROP FUNCTION f1; +INSERT INTO t1 VALUES (1); +DROP TABLE t2; +INSERT INTO t1 VALUES (1); +DROP TEMPORARY TABLE t1; diff --git a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test new file mode 100644 index 00000000000..56924a2efe9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test @@ -0,0 +1,13 @@ +# +# Bug#49132 +# This test verifies if executing DDL statement before trying to manipulate +# a temporary table causes row-based replication to break with error 'table +# does not exist' base on myisam engine. +# + +source include/master-slave.inc; +source include/have_binlog_format_row.inc; + +LET $ENGINE_TYPE= MyISAM; +source extra/rpl_tests/rpl_tmp_table_and_DDL.test; + diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 9f3863eb2b0..753e9d21b65 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -1045,6 +1045,7 @@ update_timing_fields_for_event(THD *thd, TABLE *table= NULL; Field **fields; int ret= 1; + bool save_binlog_row_based; DBUG_ENTER("Event_db_repository::update_timing_fields_for_event"); @@ -1052,8 +1053,8 @@ update_timing_fields_for_event(THD *thd, Turn off row binlogging of event timing updates. These are not used for RBR of events replicated to the slave. */ - if (thd->current_stmt_binlog_row_based) - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->current_stmt_binlog_row_based; + thd->clear_current_stmt_binlog_row_based(); DBUG_ASSERT(thd->security_ctx->master_access & SUPER_ACL); @@ -1095,6 +1096,8 @@ update_timing_fields_for_event(THD *thd, end: if (table) close_thread_tables(thd); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(test(ret)); } diff --git a/sql/events.cc b/sql/events.cc index 790e6a61699..c3a57578f2b 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -389,6 +389,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists) { int ret; + bool save_binlog_row_based; DBUG_ENTER("Events::create_event"); /* @@ -431,8 +432,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for CREATE EVENT command. */ - if (thd->current_stmt_binlog_row_based) - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->current_stmt_binlog_row_based; + thd->clear_current_stmt_binlog_row_based(); pthread_mutex_lock(&LOCK_event_metadata); @@ -472,6 +473,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, { sql_print_error("Event Error: An error occurred while creating query string, " "before writing it into binary log."); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(TRUE); } /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER @@ -480,6 +483,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, } } pthread_mutex_unlock(&LOCK_event_metadata); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(ret); } @@ -509,6 +514,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, LEX_STRING *new_dbname, LEX_STRING *new_name) { int ret; + bool save_binlog_row_based; Event_queue_element *new_element; DBUG_ENTER("Events::update_event"); @@ -565,8 +571,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for UPDATE EVENT command. */ - if (thd->current_stmt_binlog_row_based) - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->current_stmt_binlog_row_based; + thd->clear_current_stmt_binlog_row_based(); pthread_mutex_lock(&LOCK_event_metadata); @@ -602,6 +608,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, } } pthread_mutex_unlock(&LOCK_event_metadata); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(ret); } @@ -635,6 +643,7 @@ bool Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) { int ret; + bool save_binlog_row_based; DBUG_ENTER("Events::drop_event"); /* @@ -662,8 +671,8 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for DROP EVENT command. */ - if (thd->current_stmt_binlog_row_based) - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->current_stmt_binlog_row_based; + thd->clear_current_stmt_binlog_row_based(); pthread_mutex_lock(&LOCK_event_metadata); /* On error conditions my_error() is called so no need to handle here */ @@ -676,6 +685,8 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } pthread_mutex_unlock(&LOCK_event_metadata); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(ret); } diff --git a/sql/sp.cc b/sql/sp.cc index 6fad1d70ffd..ff76dbf7921 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -896,6 +896,8 @@ sp_create_routine(THD *thd, int type, sp_head *sp) bool store_failed= FALSE; + bool save_binlog_row_based; + DBUG_ENTER("sp_create_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s",type, (int) sp->m_name.length, sp->m_name.str)); @@ -913,6 +915,7 @@ sp_create_routine(THD *thd, int type, sp_head *sp) row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); saved_count_cuted_fields= thd->count_cuted_fields; @@ -1118,6 +1121,8 @@ done: thd->variables.sql_mode= saved_mode; close_thread_tables(thd); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(ret); } @@ -1142,6 +1147,7 @@ sp_drop_routine(THD *thd, int type, sp_name *name) { TABLE *table; int ret; + bool save_binlog_row_based; DBUG_ENTER("sp_drop_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s", type, (int) name->m_name.length, name->m_name.str)); @@ -1154,6 +1160,7 @@ sp_drop_routine(THD *thd, int type, sp_name *name) row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); if (!(table= open_proc_table_for_update(thd))) @@ -1171,6 +1178,8 @@ sp_drop_routine(THD *thd, int type, sp_name *name) } close_thread_tables(thd); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(ret); } @@ -1197,6 +1206,7 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) { TABLE *table; int ret; + bool save_binlog_row_based; DBUG_ENTER("sp_update_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s", type, (int) name->m_name.length, name->m_name.str)); @@ -1208,6 +1218,7 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); if (!(table= open_proc_table_for_update(thd))) @@ -1241,6 +1252,8 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) } close_thread_tables(thd); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(ret); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7ba1a657578..e2c47957e4d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2978,6 +2978,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, TABLE_LIST tables[3]; bool create_new_users=0; char *db_name, *table_name; + bool save_binlog_row_based; DBUG_ENTER("mysql_table_grant"); if (!initialized) @@ -3073,6 +3074,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); #ifdef HAVE_REPLICATION @@ -3088,7 +3090,11 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, */ tables[0].updating= tables[1].updating= tables[2].updating= 1; if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) + { + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(FALSE); + } } #endif @@ -3101,6 +3107,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (simple_open_n_lock_tables(thd,tables)) { // Should never happen close_thread_tables(thd); /* purecov: deadcode */ + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(TRUE); /* purecov: deadcode */ } @@ -3227,6 +3235,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, /* Tables are automatically closed */ thd->lex->restore_backup_query_tables_list(&backup); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(result); } @@ -3255,6 +3265,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, TABLE_LIST tables[2]; bool create_new_users=0, result=0; char *db_name, *table_name; + bool save_binlog_row_based; DBUG_ENTER("mysql_routine_grant"); if (!initialized) @@ -3290,6 +3301,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); #ifdef HAVE_REPLICATION @@ -3305,13 +3317,19 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, */ tables[0].updating= tables[1].updating= 1; if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) + { + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(FALSE); + } } #endif if (simple_open_n_lock_tables(thd,tables)) { // Should never happen close_thread_tables(thd); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(TRUE); } @@ -3387,6 +3405,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, } rw_unlock(&LOCK_grant); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; /* Tables are automatically closed */ DBUG_RETURN(result); @@ -3401,6 +3421,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, char tmp_db[NAME_LEN+1]; bool create_new_users=0; TABLE_LIST tables[2]; + bool save_binlog_row_based; DBUG_ENTER("mysql_grant"); if (!initialized) { @@ -3429,6 +3450,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); #ifdef HAVE_REPLICATION @@ -3444,13 +3466,19 @@ bool mysql_grant(THD *thd, const char *db, List &list, */ tables[0].updating= tables[1].updating= 1; if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) + { + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(FALSE); + } } #endif if (simple_open_n_lock_tables(thd,tables)) { // This should never happen close_thread_tables(thd); /* purecov: deadcode */ + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(TRUE); /* purecov: deadcode */ } @@ -3510,6 +3538,8 @@ bool mysql_grant(THD *thd, const char *db, List &list, if (!result) my_ok(thd); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(result); } @@ -5666,6 +5696,7 @@ bool mysql_create_user(THD *thd, List &list) List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; bool some_users_created= FALSE; + bool save_binlog_row_based; DBUG_ENTER("mysql_create_user"); /* @@ -5673,11 +5704,16 @@ bool mysql_create_user(THD *thd, List &list) row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); /* CREATE USER may be skipped on replication client. */ if ((result= open_grant_tables(thd, tables))) + { + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(result != 1); + } rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); @@ -5720,6 +5756,8 @@ bool mysql_create_user(THD *thd, List &list) rw_unlock(&LOCK_grant); close_thread_tables(thd); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(result); } @@ -5746,6 +5784,7 @@ bool mysql_drop_user(THD *thd, List &list) TABLE_LIST tables[GRANT_TABLES]; bool some_users_deleted= FALSE; ulong old_sql_mode= thd->variables.sql_mode; + bool save_binlog_row_based; DBUG_ENTER("mysql_drop_user"); /* @@ -5753,11 +5792,16 @@ bool mysql_drop_user(THD *thd, List &list) row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); /* DROP USER may be skipped on replication client. */ if ((result= open_grant_tables(thd, tables))) + { + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(result != 1); + } thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH; @@ -5794,6 +5838,8 @@ bool mysql_drop_user(THD *thd, List &list) rw_unlock(&LOCK_grant); close_thread_tables(thd); thd->variables.sql_mode= old_sql_mode; + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(result); } @@ -5820,6 +5866,7 @@ bool mysql_rename_user(THD *thd, List &list) List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; bool some_users_renamed= FALSE; + bool save_binlog_row_based; DBUG_ENTER("mysql_rename_user"); /* @@ -5827,11 +5874,16 @@ bool mysql_rename_user(THD *thd, List &list) row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); /* RENAME USER may be skipped on replication client. */ if ((result= open_grant_tables(thd, tables))) + { + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(result != 1); + } rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); @@ -5878,6 +5930,8 @@ bool mysql_rename_user(THD *thd, List &list) rw_unlock(&LOCK_grant); close_thread_tables(thd); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(result); } @@ -5902,6 +5956,7 @@ bool mysql_revoke_all(THD *thd, List &list) int result; ACL_DB *acl_db; TABLE_LIST tables[GRANT_TABLES]; + bool save_binlog_row_based; DBUG_ENTER("mysql_revoke_all"); /* @@ -5909,10 +5964,15 @@ bool mysql_revoke_all(THD *thd, List &list) row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); if ((result= open_grant_tables(thd, tables))) + { + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(result != 1); + } rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); @@ -6063,6 +6123,8 @@ bool mysql_revoke_all(THD *thd, List &list) if (result) my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0)); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(result); } @@ -6146,6 +6208,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, TABLE_LIST tables[GRANT_TABLES]; HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash; Silence_routine_definer_errors error_handler; + bool save_binlog_row_based; DBUG_ENTER("sp_revoke_privileges"); if ((result= open_grant_tables(thd, tables))) @@ -6162,6 +6225,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, row-based replication. The flag will be reset at the end of the statement. */ + save_binlog_row_based= thd->current_stmt_binlog_row_based; thd->clear_current_stmt_binlog_row_based(); /* Remove procedure access */ @@ -6198,6 +6262,8 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, close_thread_tables(thd); thd->pop_internal_handler(); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(error_handler.has_errors()); } diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index c6b41b59a3f..76cadc79c6f 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -398,6 +398,7 @@ int mysql_create_function(THD *thd,udf_func *udf) TABLE *table; TABLE_LIST tables; udf_func *u_d; + bool save_binlog_row_based; DBUG_ENTER("mysql_create_function"); if (!initialized) @@ -437,8 +438,8 @@ int mysql_create_function(THD *thd,udf_func *udf) Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for CREATE FUNCTION command. */ - if (thd->current_stmt_binlog_row_based) - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->current_stmt_binlog_row_based; + thd->clear_current_stmt_binlog_row_based(); rw_wrlock(&THR_LOCK_udf); if ((hash_search(&udf_hash,(uchar*) udf->name.str, udf->name.length))) @@ -508,12 +509,16 @@ int mysql_create_function(THD *thd,udf_func *udf) /* Binlog the create function. */ write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(0); err: if (new_dl) dlclose(dl); rw_unlock(&THR_LOCK_udf); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(1); } @@ -525,6 +530,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) udf_func *udf; char *exact_name_str; uint exact_name_len; + bool save_binlog_row_based; DBUG_ENTER("mysql_drop_function"); if (!initialized) @@ -540,8 +546,8 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for DROP FUNCTION command. */ - if (thd->current_stmt_binlog_row_based) - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->current_stmt_binlog_row_based; + thd->clear_current_stmt_binlog_row_based(); rw_wrlock(&THR_LOCK_udf); if (!(udf=(udf_func*) hash_search(&udf_hash,(uchar*) udf_name->str, @@ -583,9 +589,13 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) /* Binlog the drop function. */ write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(0); err: rw_unlock(&THR_LOCK_udf); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(1); } From f65b3f7889b48c8f9dea4c066093e0f7b99fde3f Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 22 Jan 2010 13:55:50 +0400 Subject: [PATCH 276/344] Applying InnoDB snapshot, fixes BUG#49238. Detailed revision comments: r6421 | jyang | 2010-01-12 07:59:16 +0200 (Tue, 12 Jan 2010) | 8 lines branches/5.1: Fix bug #49238: Creating/Dropping a temporary table while at 1023 transactions will cause assert. Handle possible DB_TOO_MANY_CONCURRENT_TRXS when deleting metadata in row_drop_table_for_mysql(). rb://220, approved by Marko --- storage/innobase/row/row0mysql.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 4fcb1fbf9f2..f7156403247 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -3245,19 +3245,13 @@ check_next_foreign: "END;\n" , FALSE, trx); - if (err != DB_SUCCESS) { - ut_a(err == DB_OUT_OF_FILE_SPACE); - - err = DB_MUST_GET_MORE_FILE_SPACE; - - row_mysql_handle_errors(&err, trx, NULL, NULL); - - ut_error; - } else { + switch (err) { ibool is_path; const char* name_or_path; mem_heap_t* heap; + case DB_SUCCESS: + heap = mem_heap_create(200); /* Clone the name, in case it has been allocated @@ -3322,7 +3316,27 @@ check_next_foreign: } mem_heap_free(heap); + break; + + case DB_TOO_MANY_CONCURRENT_TRXS: + /* Cannot even find a free slot for the + the undo log. We can directly exit here + and return the DB_TOO_MANY_CONCURRENT_TRXS + error. */ + break; + + case DB_OUT_OF_FILE_SPACE: + err = DB_MUST_GET_MORE_FILE_SPACE; + + row_mysql_handle_errors(&err, trx, NULL, NULL); + + /* Fall through to raise error */ + + default: + /* No other possible error returns */ + ut_error; } + funct_exit: trx_commit_for_mysql(trx); From 9aaa3cc4dfdb5c33e5eb9418df2af7e46f440704 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 22 Jan 2010 13:56:32 +0400 Subject: [PATCH 277/344] Applying InnoDB snapshot Detailed revision comments: r6422 | marko | 2010-01-12 11:34:27 +0200 (Tue, 12 Jan 2010) | 3 lines branches/5.1: Non-functional change: Make innobase_get_int_col_max_value() a static function. It does not access any fields of class ha_innobase. --- storage/innobase/handler/ha_innodb.cc | 9 +++++---- storage/innobase/handler/ha_innodb.h | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a1b8c551845..aca8be74b07 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3652,11 +3652,12 @@ skip_field: /************************************************************************ Get the upper limit of the MySQL integral and floating-point type. */ - +static ulonglong -ha_innobase::innobase_get_int_col_max_value( -/*========================================*/ - const Field* field) +innobase_get_int_col_max_value( +/*===========================*/ + /* out: maximum allowed value for the field */ + const Field* field) /* in: MySQL field */ { ulonglong max_value = 0; diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 9ddb516c3dc..8251af20a44 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -80,7 +80,6 @@ class ha_innobase: public handler ulong innobase_update_autoinc(ulonglong auto_inc); ulong innobase_initialize_autoinc(); dict_index_t* innobase_get_index(uint keynr); - ulonglong innobase_get_int_col_max_value(const Field* field); /* Init values for the class: */ public: From 12665e79e4ddffb23e351e04271c72b4b752c78a Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 22 Jan 2010 13:57:02 +0400 Subject: [PATCH 278/344] Applying InnoDB snapshot, fixes BUG#46193. Detailed revision comments: r6424 | marko | 2010-01-12 12:22:19 +0200 (Tue, 12 Jan 2010) | 16 lines branches/5.1: In innobase_initialize_autoinc(), do not attempt to read the maximum auto-increment value from the table if innodb_force_recovery is set to at least 4, so that writes are disabled. (Bug #46193) innobase_get_int_col_max_value(): Move the function definition before ha_innobase::innobase_initialize_autoinc(), because that function now calls this function. ha_innobase::innobase_initialize_autoinc(): Change the return type to void. Do not attempt to read the maximum auto-increment value from the table if innodb_force_recovery is set to at least 4. Issue ER_AUTOINC_READ_FAILED to the client when the auto-increment value cannot be read. rb://144 by Sunny, revised by Marko --- storage/innobase/handler/ha_innodb.cc | 238 ++++++++++++++------------ storage/innobase/handler/ha_innodb.h | 2 +- 2 files changed, 134 insertions(+), 106 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index aca8be74b07..9b6c2cf9895 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2575,58 +2575,151 @@ normalize_table_name( #endif } +/************************************************************************ +Get the upper limit of the MySQL integral and floating-point type. */ +static +ulonglong +innobase_get_int_col_max_value( +/*===========================*/ + /* out: maximum allowed value for the field */ + const Field* field) /* in: MySQL field */ +{ + ulonglong max_value = 0; + + switch(field->key_type()) { + /* TINY */ + case HA_KEYTYPE_BINARY: + max_value = 0xFFULL; + break; + case HA_KEYTYPE_INT8: + max_value = 0x7FULL; + break; + /* SHORT */ + case HA_KEYTYPE_USHORT_INT: + max_value = 0xFFFFULL; + break; + case HA_KEYTYPE_SHORT_INT: + max_value = 0x7FFFULL; + break; + /* MEDIUM */ + case HA_KEYTYPE_UINT24: + max_value = 0xFFFFFFULL; + break; + case HA_KEYTYPE_INT24: + max_value = 0x7FFFFFULL; + break; + /* LONG */ + case HA_KEYTYPE_ULONG_INT: + max_value = 0xFFFFFFFFULL; + break; + case HA_KEYTYPE_LONG_INT: + max_value = 0x7FFFFFFFULL; + break; + /* BIG */ + case HA_KEYTYPE_ULONGLONG: + max_value = 0xFFFFFFFFFFFFFFFFULL; + break; + case HA_KEYTYPE_LONGLONG: + max_value = 0x7FFFFFFFFFFFFFFFULL; + break; + case HA_KEYTYPE_FLOAT: + /* We use the maximum as per IEEE754-2008 standard, 2^24 */ + max_value = 0x1000000ULL; + break; + case HA_KEYTYPE_DOUBLE: + /* We use the maximum as per IEEE754-2008 standard, 2^53 */ + max_value = 0x20000000000000ULL; + break; + default: + ut_error; + } + + return(max_value); +} + /************************************************************************ Set the autoinc column max value. This should only be called once from ha_innobase::open(). Therefore there's no need for a covering lock. */ -ulong +void ha_innobase::innobase_initialize_autoinc() /*======================================*/ { - dict_index_t* index; ulonglong auto_inc; - const char* col_name; - ulint error = DB_SUCCESS; - dict_table_t* innodb_table = prebuilt->table; - - col_name = table->found_next_number_field->field_name; - index = innobase_get_index(table->s->next_number_index); - - /* Execute SELECT MAX(col_name) FROM TABLE; */ - error = row_search_max_autoinc(index, col_name, &auto_inc); - - if (error == DB_SUCCESS) { - - /* At the this stage we dont' know the increment - or the offset, so use default inrement of 1. */ - ++auto_inc; - - dict_table_autoinc_initialize(innodb_table, auto_inc); - - } else if (error == DB_RECORD_NOT_FOUND) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: MySQL and InnoDB data " - "dictionaries are out of sync.\n" - "InnoDB: Unable to find the AUTOINC column %s in the " - "InnoDB table %s.\n" - "InnoDB: We set the next AUTOINC column value to the " - "maximum possible value,\n" - "InnoDB: in effect disabling the AUTOINC next value " - "generation.\n" - "InnoDB: You can either set the next AUTOINC value " - "explicitly using ALTER TABLE\n" - "InnoDB: or fix the data dictionary by recreating " - "the table.\n", - col_name, index->table->name); + const Field* field = table->found_next_number_field; + if (field != NULL) { + auto_inc = innobase_get_int_col_max_value(field); + } else { + /* We have no idea what's been passed in to us as the + autoinc column. We set it to the MAX_INT of our table + autoinc type. */ auto_inc = 0xFFFFFFFFFFFFFFFFULL; - dict_table_autoinc_initialize(innodb_table, auto_inc); + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Unable to determine the AUTOINC " + "column name\n"); + } - error = DB_SUCCESS; - } /* else other errors are still fatal */ + if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { + /* If the recovery level is set so high that writes + are disabled we force the AUTOINC counter to the MAX + value effectively disabling writes to the table. + Secondly, we avoid reading the table in case the read + results in failure due to a corrupted table/index. - return(ulong(error)); + We will not return an error to the client, so that the + tables can be dumped with minimal hassle. If an error + were returned in this case, the first attempt to read + the table would fail and subsequent SELECTs would succeed. */ + } else if (field == NULL) { + my_error(ER_AUTOINC_READ_FAILED, MYF(0)); + } else { + dict_index_t* index; + const char* col_name; + ulonglong read_auto_inc; + ulint err; + + update_thd(ha_thd()); + col_name = field->field_name; + index = innobase_get_index(table->s->next_number_index); + + /* Execute SELECT MAX(col_name) FROM TABLE; */ + err = row_search_max_autoinc(index, col_name, &read_auto_inc); + + switch (err) { + case DB_SUCCESS: + /* At the this stage we do not know the increment + or the offset, so use a default increment of 1. */ + auto_inc = read_auto_inc + 1; + break; + + case DB_RECORD_NOT_FOUND: + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: MySQL and InnoDB data " + "dictionaries are out of sync.\n" + "InnoDB: Unable to find the AUTOINC column " + "%s in the InnoDB table %s.\n" + "InnoDB: We set the next AUTOINC column " + "value to the maximum possible value,\n" + "InnoDB: in effect disabling the AUTOINC " + "next value generation.\n" + "InnoDB: You can either set the next " + "AUTOINC value explicitly using ALTER TABLE\n" + "InnoDB: or fix the data dictionary by " + "recreating the table.\n", + col_name, index->table->name); + + my_error(ER_AUTOINC_READ_FAILED, MYF(0)); + break; + default: + /* row_search_max_autoinc() should only return + one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */ + ut_error; + } + } + + dict_table_autoinc_initialize(prebuilt->table, auto_inc); } /********************************************************************* @@ -2824,8 +2917,6 @@ retry: /* Only if the table has an AUTOINC column. */ if (prebuilt->table != NULL && table->found_next_number_field != NULL) { - ulint error; - dict_table_autoinc_lock(prebuilt->table); /* Since a table can already be "open" in InnoDB's internal @@ -2834,8 +2925,7 @@ retry: autoinc value from a previous MySQL open. */ if (dict_table_autoinc_read(prebuilt->table) == 0) { - error = innobase_initialize_autoinc(); - ut_a(error == DB_SUCCESS); + innobase_initialize_autoinc(); } dict_table_autoinc_unlock(prebuilt->table); @@ -3650,68 +3740,6 @@ skip_field: } } -/************************************************************************ -Get the upper limit of the MySQL integral and floating-point type. */ -static -ulonglong -innobase_get_int_col_max_value( -/*===========================*/ - /* out: maximum allowed value for the field */ - const Field* field) /* in: MySQL field */ -{ - ulonglong max_value = 0; - - switch(field->key_type()) { - /* TINY */ - case HA_KEYTYPE_BINARY: - max_value = 0xFFULL; - break; - case HA_KEYTYPE_INT8: - max_value = 0x7FULL; - break; - /* SHORT */ - case HA_KEYTYPE_USHORT_INT: - max_value = 0xFFFFULL; - break; - case HA_KEYTYPE_SHORT_INT: - max_value = 0x7FFFULL; - break; - /* MEDIUM */ - case HA_KEYTYPE_UINT24: - max_value = 0xFFFFFFULL; - break; - case HA_KEYTYPE_INT24: - max_value = 0x7FFFFFULL; - break; - /* LONG */ - case HA_KEYTYPE_ULONG_INT: - max_value = 0xFFFFFFFFULL; - break; - case HA_KEYTYPE_LONG_INT: - max_value = 0x7FFFFFFFULL; - break; - /* BIG */ - case HA_KEYTYPE_ULONGLONG: - max_value = 0xFFFFFFFFFFFFFFFFULL; - break; - case HA_KEYTYPE_LONGLONG: - max_value = 0x7FFFFFFFFFFFFFFFULL; - break; - case HA_KEYTYPE_FLOAT: - /* We use the maximum as per IEEE754-2008 standard, 2^24 */ - max_value = 0x1000000ULL; - break; - case HA_KEYTYPE_DOUBLE: - /* We use the maximum as per IEEE754-2008 standard, 2^53 */ - max_value = 0x20000000000000ULL; - break; - default: - ut_error; - } - - return(max_value); -} - /************************************************************************ This special handling is really to overcome the limitations of MySQL's binlogging. We need to eliminate the non-determinism that will arise in diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 8251af20a44..5b3df16875a 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -78,7 +78,7 @@ class ha_innobase: public handler ulong innobase_reset_autoinc(ulonglong auto_inc); ulong innobase_get_autoinc(ulonglong* value); ulong innobase_update_autoinc(ulonglong auto_inc); - ulong innobase_initialize_autoinc(); + void innobase_initialize_autoinc(); dict_index_t* innobase_get_index(uint keynr); /* Init values for the class: */ From 407e6e309e0a32974e5db89da51b288242f1bb00 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 22 Jan 2010 14:02:17 +0400 Subject: [PATCH 279/344] Applying InnoDB snapshot Detailed revision comments: r6488 | sunny | 2010-01-21 02:55:08 +0200 (Thu, 21 Jan 2010) | 2 lines branches/5.1: Factor out test for bug#44030 from innodb-autoinc.test into a separate test/result files. --- mysql-test/r/innodb-autoinc.result | 29 ----------------------------- mysql-test/t/innodb-autoinc.test | 26 -------------------------- 2 files changed, 55 deletions(-) diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index fe87e11c9ec..c03daa3565e 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -868,35 +868,6 @@ Got one of the listed errors DROP TABLE t1; DROP TABLE t2; SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; -CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; -INSERT INTO t1 VALUES (null); -INSERT INTO t1 VALUES (null); -ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; -SELECT * FROM t1; -d1 -1 -2 -SELECT * FROM t1; -d1 -1 -2 -INSERT INTO t1 VALUES(null); -Got one of the listed errors -ALTER TABLE t1 AUTO_INCREMENT = 3; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `d1` int(11) NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`d1`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 -INSERT INTO t1 VALUES(null); -SELECT * FROM t1; -d1 -1 -2 -3 -DROP TABLE t1; -SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index 84386280a26..bb431408937 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -478,32 +478,6 @@ INSERT INTO t2 SELECT c1 FROM t1; INSERT INTO t2 SELECT NULL FROM t1; DROP TABLE t1; DROP TABLE t2; -# -# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from -# the index (PRIMARY) -# This test requires a restart of the server -SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; -CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; -INSERT INTO t1 VALUES (null); -INSERT INTO t1 VALUES (null); -ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; -SELECT * FROM t1; -# Restart the server --- source include/restart_mysqld.inc -# The MySQL and InnoDB data dictionaries should now be out of sync. -# The select should print message to the error log -SELECT * FROM t1; -# MySQL have made a change (http://lists.mysql.com/commits/75268) that no -# longer results in the two data dictionaries being out of sync. If they -# revert their changes then this check for ER_AUTOINC_READ_FAILED will need -# to be enabled. --- error ER_AUTOINC_READ_FAILED,1467 -INSERT INTO t1 VALUES(null); -ALTER TABLE t1 AUTO_INCREMENT = 3; -SHOW CREATE TABLE t1; -INSERT INTO t1 VALUES(null); -SELECT * FROM t1; -DROP TABLE t1; # If the user has specified negative values for an AUTOINC column then # InnoDB should ignore those values when setting the table's max value. From dab7c82fe5ce9152415354c8cac4c216ab49d4a6 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 22 Jan 2010 14:03:18 +0400 Subject: [PATCH 280/344] Applying InnoDB snapshot Detailed revision comments: r6489 | sunny | 2010-01-21 02:57:50 +0200 (Thu, 21 Jan 2010) | 2 lines branches/5.1: Factor out test for bug#44030 from innodb-autoinc.test into a separate test/result files. --- mysql-test/r/innodb-autoinc-44030.result | 30 +++++++++++++++++++++ mysql-test/t/innodb-autoinc-44030.test | 34 ++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 mysql-test/r/innodb-autoinc-44030.result create mode 100644 mysql-test/t/innodb-autoinc-44030.test diff --git a/mysql-test/r/innodb-autoinc-44030.result b/mysql-test/r/innodb-autoinc-44030.result new file mode 100644 index 00000000000..c0695bf0be0 --- /dev/null +++ b/mysql-test/r/innodb-autoinc-44030.result @@ -0,0 +1,30 @@ +drop table if exists t1; +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (null); +INSERT INTO t1 VALUES (null); +ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; +SELECT * FROM t1; +d1 +1 +2 +SELECT * FROM t1; +d1 +1 +2 +INSERT INTO t1 VALUES(null); +Got one of the listed errors +ALTER TABLE t1 AUTO_INCREMENT = 3; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `d1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`d1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES(null); +SELECT * FROM t1; +d1 +1 +2 +3 +DROP TABLE t1; diff --git a/mysql-test/t/innodb-autoinc-44030.test b/mysql-test/t/innodb-autoinc-44030.test new file mode 100644 index 00000000000..1dfdad2bede --- /dev/null +++ b/mysql-test/t/innodb-autoinc-44030.test @@ -0,0 +1,34 @@ +-- source include/have_innodb.inc +# embedded server ignores 'delayed', so skip this +-- source include/not_embedded.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from +# the index (PRIMARY) +# This test requires a restart of the server +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (null); +INSERT INTO t1 VALUES (null); +ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; +SELECT * FROM t1; +# Restart the server +-- source include/restart_mysqld.inc +# The MySQL and InnoDB data dictionaries should now be out of sync. +# The select should print message to the error log +SELECT * FROM t1; +# MySQL have made a change (http://lists.mysql.com/commits/75268) that no +# longer results in the two data dictionaries being out of sync. If they +# revert their changes then this check for ER_AUTOINC_READ_FAILED will need +# to be enabled. +-- error ER_AUTOINC_READ_FAILED,1467 +INSERT INTO t1 VALUES(null); +ALTER TABLE t1 AUTO_INCREMENT = 3; +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(null); +SELECT * FROM t1; +DROP TABLE t1; From b6a739f6d77886b7b3b32de857a7f89ff17984e3 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 22 Jan 2010 14:03:52 +0400 Subject: [PATCH 281/344] Applying InnoDB snapshot Detailed revision comments: r6492 | sunny | 2010-01-21 09:38:35 +0200 (Thu, 21 Jan 2010) | 1 line branches/5.1: Add reference to bug#47621 in the comment. --- mysql-test/t/innodb-autoinc-44030.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/innodb-autoinc-44030.test b/mysql-test/t/innodb-autoinc-44030.test index 1dfdad2bede..af2e3015280 100644 --- a/mysql-test/t/innodb-autoinc-44030.test +++ b/mysql-test/t/innodb-autoinc-44030.test @@ -24,7 +24,7 @@ SELECT * FROM t1; # MySQL have made a change (http://lists.mysql.com/commits/75268) that no # longer results in the two data dictionaries being out of sync. If they # revert their changes then this check for ER_AUTOINC_READ_FAILED will need -# to be enabled. +# to be enabled. Also, see http://bugs.mysql.com/bug.php?id=47621. -- error ER_AUTOINC_READ_FAILED,1467 INSERT INTO t1 VALUES(null); ALTER TABLE t1 AUTO_INCREMENT = 3; From f996e36de9c6f79816057e246b34ad9cc0ff1b76 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 22 Jan 2010 14:20:08 +0400 Subject: [PATCH 282/344] Disabled innodb-autoinc-44030 due to BUG#47621. --- mysql-test/t/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 07462e91696..5f37dbe2cb6 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,3 +11,4 @@ ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically +innodb-autoinc-44030 : BUG#47621 2009-01-22 svoj MySQL and InnoDB dicts getting out of sync From 4a10f7b46c9ebbd9af89f37f64df40981459b788 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 22 Jan 2010 14:58:21 +0400 Subject: [PATCH 283/344] Bug#49501 Inefficient information_schema check (system collation), addon removed wrongly introduced strlen calls sql/events.cc: removed wrongly introduced strlen calls sql/mysql_priv.h: removed wrongly introduced strlen calls sql/repl_failsafe.cc: removed wrongly introduced strlen calls sql/sql_db.cc: removed wrongly introduced strlen calls sql/sql_parse.cc: removed wrongly introduced strlen calls sql/sql_show.cc: removed wrongly introduced strlen calls --- sql/events.cc | 3 +-- sql/mysql_priv.h | 6 ++++++ sql/repl_failsafe.cc | 2 +- sql/sql_db.cc | 2 +- sql/sql_parse.cc | 6 +++--- sql/sql_show.cc | 2 +- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/sql/events.cc b/sql/events.cc index 790e6a61699..3273635666e 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -871,8 +871,7 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS) { DBUG_ASSERT(thd->lex->select_lex.db); - if (!is_schema_db(thd->lex->select_lex.db, // There is no events in I_S - strlen(thd->lex->select_lex.db)) && + if (!is_schema_db(thd->lex->select_lex.db) && // There is no events in I_S check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, 0)) DBUG_RETURN(1); db= thd->lex->select_lex.db; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 76edbf1dea3..abc50cd8063 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1426,6 +1426,12 @@ inline bool is_schema_db(const char *name, size_t len) INFORMATION_SCHEMA_NAME.str, name)); } +inline bool is_schema_db(const char *name) +{ + return !my_strcasecmp(system_charset_info, + INFORMATION_SCHEMA_NAME.str, name); +} + /* sql_prepare.cc */ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length); diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index dda84ca8a37..c6a05e93bf4 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -905,7 +905,7 @@ bool load_master_data(THD* thd) if (!rpl_filter->db_ok(db) || !rpl_filter->db_ok_with_wild_table(db) || !strcmp(db,"mysql") || - is_schema_db(db, strlen(db))) + is_schema_db(db)) { *cur_table_res = 0; continue; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 22ecaa17a0c..a3f9b4baea4 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -618,7 +618,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, DBUG_ENTER("mysql_create_db"); /* do not create 'information_schema' db */ - if (is_schema_db(db, strlen(db))) + if (is_schema_db(db)) { my_error(ER_DB_CREATE_EXISTS, MYF(0), db); DBUG_RETURN(-1); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3c404a984bf..a2a1494141c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2852,7 +2852,7 @@ end_with_restore_list: &first_table->grant.privilege, 0, 0, test(first_table->schema_table)) || check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0, - is_schema_db(select_lex->db, strlen(select_lex->db)))|| + is_schema_db(select_lex->db))|| check_merge_table_access(thd, first_table->db, (TABLE_LIST *) create_info.merge_list.first)) @@ -3865,7 +3865,7 @@ end_with_restore_list: first_table ? 0 : 1, 0, first_table ? (bool) first_table->schema_table : select_lex->db ? - is_schema_db(select_lex->db, strlen(select_lex->db)) : 0)) + is_schema_db(select_lex->db) : 0)) goto error; if (thd->security_ctx->user) // If not replication @@ -5304,7 +5304,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) if (check_access(thd, SELECT_ACL, dst_db_name, &thd->col_access, FALSE, FALSE, - is_schema_db(dst_db_name, strlen(dst_db_name)))) + is_schema_db(dst_db_name))) return TRUE; if (!thd->col_access && check_grant_db(thd, dst_db_name)) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d4da29085b5..5ec40d4893c 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -826,7 +826,7 @@ bool mysqld_show_create_db(THD *thd, char *dbname, DBUG_RETURN(TRUE); } #endif - if (is_schema_db(dbname, strlen(dbname))) + if (is_schema_db(dbname)) { dbname= INFORMATION_SCHEMA_NAME.str; create.default_table_charset= system_charset_info; From d93550cb80deb587843940a0102b18473aae2f5d Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 22 Jan 2010 16:23:27 +0400 Subject: [PATCH 284/344] Applying InnoDB snapshot, fixes BUG#49396. Detailed revision comments: r6471 | calvin | 2010-01-16 01:43:27 +0200 (Sat, 16 Jan 2010) | 4 lines branches/5.1: fix bug#49396: main.innodb test fails in embedded mode Change replace_result by using $MYSQLD_DATADIR. Tested in both embedded mode and normal server mode. --- mysql-test/t/innodb.test | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 42c24324ebc..8dcf494406a 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -15,6 +15,8 @@ -- source include/have_innodb.inc +let $MYSQLD_DATADIR= `select @@datadir`; + # Save the original values of some variables in order to be able to # estimate how much they have changed during the tests. Previously this # test assumed that e.g. rows_deleted is 0 here and after deleting 23 @@ -1699,7 +1701,7 @@ set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; # Embedded server doesn't chdir to data directory ---replace_result $MYSQLTEST_VARDIR . mysqld.1/data/ '' +--replace_result $MYSQLD_DATADIR ./ master-data/ '' -- error 1025 rename table t3 to t1; set foreign_key_checks=1; @@ -2339,7 +2341,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL; # mysqltest first does replace_regex, then replace_result --replace_regex /'[^']*test\/#sql-[0-9a-f_]*'/'#sql-temporary'/ # Embedded server doesn't chdir to data directory ---replace_result $MYSQLTEST_VARDIR . mysqld.1/data/ '' +--replace_result $MYSQLD_DATADIR ./ master-data/ '' --error 1025 ALTER TABLE t2 MODIFY a INT NOT NULL; DELETE FROM t1; From 93089873623bb82cf5ca4c4cf1cf146796dd31dd Mon Sep 17 00:00:00 2001 From: Hakan Kuecuekyilmaz Date: Fri, 22 Jan 2010 22:19:21 +0100 Subject: [PATCH 285/344] Fix for https://bugs.launchpad.net/maria/+bug/509795 Result of reverse_lookup("localhost") is system depended. Therefore we disable the result of it. --- mysql-test/r/udf.result | 2 -- mysql-test/t/udf.test | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index 393a2f54b05..a42c348f6a9 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -38,8 +38,6 @@ ERROR HY000: Can't initialize function 'reverse_lookup'; Wrong number of argumen select reverse_lookup("127.0.0.1"); select reverse_lookup(127,0,0,1); select reverse_lookup("localhost"); -reverse_lookup("localhost") -NULL select avgcost(); ERROR HY000: Can't initialize function 'avgcost'; wrong number of arguments: AVGCOST() requires two arguments select avgcost(100,23.76); diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test index 4364b0c820e..642f77fd741 100644 --- a/mysql-test/t/udf.test +++ b/mysql-test/t/udf.test @@ -56,9 +56,9 @@ select reverse_lookup(); --disable_result_log select reverse_lookup("127.0.0.1"); select reverse_lookup(127,0,0,1); +select reverse_lookup("localhost"); --enable_result_log -select reverse_lookup("localhost"); --error ER_CANT_INITIALIZE_UDF select avgcost(); --error ER_CANT_INITIALIZE_UDF From 2b16517522afad76bc94b07bdaa8af64091e713b Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Sun, 24 Jan 2010 15:03:23 +0800 Subject: [PATCH 286/344] Backport Bug#37148 to 5.1 --- mysql-test/include/binlog_inject_error.inc | 22 ++++ .../suite/binlog/r/binlog_write_error.result | 108 ++++++++++++++++++ .../suite/binlog/t/binlog_write_error.test | 101 ++++++++++++++++ sql/events.cc | 6 +- sql/log.cc | 4 +- sql/log_event.cc | 6 +- sql/log_event_old.cc | 15 ++- sql/mysql_priv.h | 4 +- sql/rpl_injector.cc | 41 ++++--- sql/sp.cc | 13 ++- sql/sp_head.cc | 1 + sql/sql_acl.cc | 25 ++-- sql/sql_base.cc | 18 ++- sql/sql_class.h | 2 +- sql/sql_db.cc | 35 ++++-- sql/sql_delete.cc | 12 +- sql/sql_insert.cc | 51 +++++---- sql/sql_load.cc | 32 +++--- sql/sql_parse.cc | 17 +-- sql/sql_partition.cc | 5 +- sql/sql_rename.cc | 9 +- sql/sql_repl.cc | 13 ++- sql/sql_table.cc | 62 +++++----- sql/sql_tablespace.cc | 4 +- sql/sql_trigger.cc | 2 +- sql/sql_udf.cc | 8 +- sql/sql_update.cc | 7 +- sql/sql_view.cc | 8 +- 28 files changed, 472 insertions(+), 159 deletions(-) create mode 100644 mysql-test/include/binlog_inject_error.inc create mode 100644 mysql-test/suite/binlog/r/binlog_write_error.result create mode 100644 mysql-test/suite/binlog/t/binlog_write_error.test diff --git a/mysql-test/include/binlog_inject_error.inc b/mysql-test/include/binlog_inject_error.inc new file mode 100644 index 00000000000..6465f7943a4 --- /dev/null +++ b/mysql-test/include/binlog_inject_error.inc @@ -0,0 +1,22 @@ +# +# === Name +# +# binlog_inject_error.inc +# +# === Description +# +# Inject binlog write error when running the query, verifies that the +# query is ended with the proper error (ER_ERROR_ON_WRITE). +# +# === Usage +# +# let query= 'CREATE TABLE t1 (a INT)'; +# source include/binlog_inject_error.inc; +# + +SET GLOBAL debug='d,injecting_fault_writing'; +--echo $query; +--replace_regex /(errno: .*)/(errno: #)/ +--error ER_ERROR_ON_WRITE +--eval $query +SET GLOBAL debug=''; diff --git a/mysql-test/suite/binlog/r/binlog_write_error.result b/mysql-test/suite/binlog/r/binlog_write_error.result new file mode 100644 index 00000000000..dd8bdb9715a --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_write_error.result @@ -0,0 +1,108 @@ +# +# Initialization +# +DROP TABLE IF EXISTS t1, t2; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP TRIGGER IF EXISTS tr1; +DROP TRIGGER IF EXISTS tr2; +DROP VIEW IF EXISTS v1, v2; +# +# Test injecting binlog write error when executing queries +# +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE TABLE t1 (a INT); +CREATE TABLE t1 (a INT); +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +INSERT INTO t1 VALUES (1),(2),(3); +SET GLOBAL debug='d,injecting_fault_writing'; +INSERT INTO t1 VALUES (4),(5),(6); +INSERT INTO t1 VALUES (4),(5),(6); +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +UPDATE t1 set a=a+1; +UPDATE t1 set a=a+1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DELETE FROM t1; +DELETE FROM t1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (new.a + 100); +CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (new.a + 100); +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP TRIGGER tr1; +DROP TRIGGER tr1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +ALTER TABLE t1 ADD (b INT); +ALTER TABLE t1 ADD (b INT); +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE VIEW v1 AS SELECT a FROM t1; +CREATE VIEW v1 AS SELECT a FROM t1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP VIEW v1; +DROP VIEW v1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; +CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP PROCEDURE p1; +DROP PROCEDURE p1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP TABLE t1; +DROP TABLE t1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE FUNCTION f1() RETURNS INT return 1; +CREATE FUNCTION f1() RETURNS INT return 1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP FUNCTION f1; +DROP FUNCTION f1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE USER user1; +CREATE USER user1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP USER user1; +DROP USER user1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +# +# Cleanup +# +DROP TABLE IF EXISTS t1, t2; +DROP FUNCTION IF EXISTS f1; +DROP PROCEDURE IF EXISTS p1; +DROP TRIGGER IF EXISTS tr1; +DROP VIEW IF EXISTS v1, v2; diff --git a/mysql-test/suite/binlog/t/binlog_write_error.test b/mysql-test/suite/binlog/t/binlog_write_error.test new file mode 100644 index 00000000000..0e57db3d9a0 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_write_error.test @@ -0,0 +1,101 @@ +# +# === Name === +# +# binlog_write_error.test +# +# === Description === +# +# This test case check if the error of writing binlog file is properly +# reported and handled when executing statements. +# +# === Related Bugs === +# +# BUG#37148 +# + +source include/have_log_bin.inc; +source include/have_debug.inc; + +--echo # +--echo # Initialization +--echo # + +disable_warnings; +DROP TABLE IF EXISTS t1, t2; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP TRIGGER IF EXISTS tr1; +DROP TRIGGER IF EXISTS tr2; +DROP VIEW IF EXISTS v1, v2; +enable_warnings; + +--echo # +--echo # Test injecting binlog write error when executing queries +--echo # + +let $query= CREATE TABLE t1 (a INT); +source include/binlog_inject_error.inc; + +INSERT INTO t1 VALUES (1),(2),(3); + +let $query= INSERT INTO t1 VALUES (4),(5),(6); +source include/binlog_inject_error.inc; + +let $query= UPDATE t1 set a=a+1; +source include/binlog_inject_error.inc; + +let $query= DELETE FROM t1; +source include/binlog_inject_error.inc; + +let $query= CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (new.a + 100); +source include/binlog_inject_error.inc; + +let $query= DROP TRIGGER tr1; +source include/binlog_inject_error.inc; + +let $query= ALTER TABLE t1 ADD (b INT); +source include/binlog_inject_error.inc; + +let $query= CREATE VIEW v1 AS SELECT a FROM t1; +source include/binlog_inject_error.inc; + +let $query= DROP VIEW v1; +source include/binlog_inject_error.inc; + +let $query= CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; +source include/binlog_inject_error.inc; + +let $query= DROP PROCEDURE p1; +source include/binlog_inject_error.inc; + +let $query= DROP TABLE t1; +source include/binlog_inject_error.inc; + +let $query= CREATE FUNCTION f1() RETURNS INT return 1; +source include/binlog_inject_error.inc; + +let $query= DROP FUNCTION f1; +source include/binlog_inject_error.inc; + +let $query= CREATE USER user1; +source include/binlog_inject_error.inc; + +let $query= REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1; +source include/binlog_inject_error.inc; + +let $query= DROP USER user1; +source include/binlog_inject_error.inc; + +--echo # +--echo # Cleanup +--echo # + +disable_warnings; +DROP TABLE IF EXISTS t1, t2; +DROP FUNCTION IF EXISTS f1; +DROP PROCEDURE IF EXISTS p1; +DROP TRIGGER IF EXISTS tr1; +DROP VIEW IF EXISTS v1, v2; +enable_warnings; diff --git a/sql/events.cc b/sql/events.cc index 3273635666e..2770cabae19 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -476,7 +476,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, } /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER will be written into the binary log as the definer for the SQL thread. */ - write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); + ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); } } pthread_mutex_unlock(&LOCK_event_metadata); @@ -598,7 +598,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, new_element); /* Binlog the alter event. */ DBUG_ASSERT(thd->query() && thd->query_length()); - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } } pthread_mutex_unlock(&LOCK_event_metadata); @@ -673,7 +673,7 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) event_queue->drop_event(thd, dbname, name); /* Binlog the drop event. */ DBUG_ASSERT(thd->query() && thd->query_length()); - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } pthread_mutex_unlock(&LOCK_event_metadata); DBUG_RETURN(ret); diff --git a/sql/log.cc b/sql/log.cc index bc9efd75ea2..5544d0010ef 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1464,7 +1464,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))) { if (trx_data->has_incident()) - mysql_bin_log.write_incident(thd, TRUE); + error= mysql_bin_log.write_incident(thd, TRUE); trx_data->reset(); } else // ...statement @@ -4710,7 +4710,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock) Incident_log_event ev(thd, incident, write_error_msg); if (lock) pthread_mutex_lock(&LOCK_log); - ev.write(&log_file); + error= ev.write(&log_file); if (lock) { if (!error && !(error= flush_and_sync())) diff --git a/sql/log_event.cc b/sql/log_event.cc index 6b21087b6aa..5219eae6600 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5864,7 +5864,7 @@ Slave_log_event::Slave_log_event(const char* buf, uint event_len) int Slave_log_event::do_apply_event(Relay_log_info const *rli) { if (mysql_bin_log.is_open()) - mysql_bin_log.write(this); + return mysql_bin_log.write(this); return 0; } #endif /* !MYSQL_CLIENT */ @@ -7611,7 +7611,7 @@ static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd) (assume the last master's transaction is ignored by the slave because of replicate-ignore rules). */ - thd->binlog_flush_pending_rows_event(true); + error= thd->binlog_flush_pending_rows_event(true); /* If this event is not in a transaction, the call below will, if some @@ -7622,7 +7622,7 @@ static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd) are involved, commit the transaction and flush the pending event to the binlog. */ - error= ha_autocommit_or_rollback(thd, 0); + error|= ha_autocommit_or_rollback(thd, error); /* Now what if this is not a transactional engine? we still need to diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 357bc78b1cd..313916c9818 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1541,7 +1541,15 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) NOTE: For this new scheme there should be no pending event: need to add code to assert that is the case. */ - thd->binlog_flush_pending_rows_event(false); + error= thd->binlog_flush_pending_rows_event(false); + if (error) + { + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER(ER_SLAVE_FATAL_ERROR), + "call to binlog_flush_pending_rows_event() failed"); + thd->is_slave_error= 1; + DBUG_RETURN(error); + } TABLE_LIST *tables= rli->tables_to_lock; close_tables_for_reopen(thd, &tables); @@ -1831,7 +1839,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) (assume the last master's transaction is ignored by the slave because of replicate-ignore rules). */ - thd->binlog_flush_pending_rows_event(true); + int binlog_error= thd->binlog_flush_pending_rows_event(true); /* If this event is not in a transaction, the call below will, if some @@ -1842,12 +1850,13 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) are involved, commit the transaction and flush the pending event to the binlog. */ - if ((error= ha_autocommit_or_rollback(thd, 0))) + if ((error= ha_autocommit_or_rollback(thd, binlog_error))) rli->report(ERROR_LEVEL, error, "Error in %s event: commit of row events failed, " "table `%s`.`%s`", get_type_str(), m_table->s->db.str, m_table->s->table_name.str); + error|= binlog_error; /* Now what if this is not a transactional engine? we still need to diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index abc50cd8063..e99effe1dcb 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1036,8 +1036,8 @@ check_and_unset_inject_value(int value) #endif -void write_bin_log(THD *thd, bool clear_error, - char const *query, ulong query_length); +int write_bin_log(THD *thd, bool clear_error, + char const *query, ulong query_length); /* sql_connect.cc */ int check_user(THD *thd, enum enum_server_command command, diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc index 684655d1c3b..666622dbac4 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -58,10 +58,14 @@ injector::transaction::~transaction() my_free(the_memory, MYF(0)); } +/** + @retval 0 transaction committed + @retval 1 transaction rolled back + */ int injector::transaction::commit() { DBUG_ENTER("injector::transaction::commit()"); - m_thd->binlog_flush_pending_rows_event(true); + int error= m_thd->binlog_flush_pending_rows_event(true); /* Cluster replication does not preserve statement or transaction boundaries of the master. Instead, a new @@ -81,9 +85,9 @@ int injector::transaction::commit() is committed by committing the statement transaction explicitly. */ - ha_autocommit_or_rollback(m_thd, 0); - end_trans(m_thd, COMMIT); - DBUG_RETURN(0); + error |= ha_autocommit_or_rollback(m_thd, error); + end_trans(m_thd, error ? ROLLBACK : COMMIT); + DBUG_RETURN(error); } int injector::transaction::use_table(server_id_type sid, table tbl) @@ -109,16 +113,17 @@ int injector::transaction::write_row (server_id_type sid, table tbl, record_type record) { DBUG_ENTER("injector::transaction::write_row(...)"); - - if (int error= check_state(ROW_STATE)) + + int error= 0; + if (error= check_state(ROW_STATE)) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; m_thd->set_server_id(sid); - m_thd->binlog_write_row(tbl.get_table(), tbl.is_transactional(), - cols, colcnt, record); + error= m_thd->binlog_write_row(tbl.get_table(), tbl.is_transactional(), + cols, colcnt, record); m_thd->set_server_id(save_id); - DBUG_RETURN(0); + DBUG_RETURN(error); } @@ -128,15 +133,16 @@ int injector::transaction::delete_row(server_id_type sid, table tbl, { DBUG_ENTER("injector::transaction::delete_row(...)"); - if (int error= check_state(ROW_STATE)) + int error= 0; + if (error= check_state(ROW_STATE)) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; m_thd->set_server_id(sid); - m_thd->binlog_delete_row(tbl.get_table(), tbl.is_transactional(), - cols, colcnt, record); + error= m_thd->binlog_delete_row(tbl.get_table(), tbl.is_transactional(), + cols, colcnt, record); m_thd->set_server_id(save_id); - DBUG_RETURN(0); + DBUG_RETURN(error); } @@ -146,15 +152,16 @@ int injector::transaction::update_row(server_id_type sid, table tbl, { DBUG_ENTER("injector::transaction::update_row(...)"); - if (int error= check_state(ROW_STATE)) + int error= 0; + if (error= check_state(ROW_STATE)) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; m_thd->set_server_id(sid); - m_thd->binlog_update_row(tbl.get_table(), tbl.is_transactional(), - cols, colcnt, before, after); + error= m_thd->binlog_update_row(tbl.get_table(), tbl.is_transactional(), + cols, colcnt, before, after); m_thd->set_server_id(save_id); - DBUG_RETURN(0); + DBUG_RETURN(error); } diff --git a/sql/sp.cc b/sql/sp.cc index 6fad1d70ffd..30896acd913 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1105,9 +1105,10 @@ sp_create_routine(THD *thd, int type, sp_head *sp) /* restore sql_mode when binloging */ thd->variables.sql_mode= saved_mode; /* Such a statement can always go directly to binlog, no trans cache */ - thd->binlog_query(THD::MYSQL_QUERY_TYPE, - log_query.c_ptr(), log_query.length(), - FALSE, FALSE, 0); + if (thd->binlog_query(THD::MYSQL_QUERY_TYPE, + log_query.c_ptr(), log_query.length(), + FALSE, FALSE, 0)) + ret= SP_INTERNAL_ERROR; thd->variables.sql_mode= 0; } @@ -1166,7 +1167,8 @@ sp_drop_routine(THD *thd, int type, sp_name *name) if (ret == SP_OK) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + ret= SP_INTERNAL_ERROR; sp_cache_invalidate(); } @@ -1236,7 +1238,8 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) if (ret == SP_OK) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + ret= SP_INTERNAL_ERROR; sp_cache_invalidate(); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index d74e195048f..45cb4eebb09 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1790,6 +1790,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, "Invoked ROUTINE modified a transactional table but MySQL " "failed to reflect this change in the binary log"); + err_status= TRUE; } reset_dynamic(&thd->user_var_events); /* Forget those values, in case more function calls are binlogged: */ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7ba1a657578..1fd70b4039e 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1659,8 +1659,8 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->host.hostname ? acl_user->host.hostname : "", new_password)); thd->clear_error(); - thd->binlog_query(THD::MYSQL_QUERY_TYPE, buff, query_length, - FALSE, FALSE, 0); + result= thd->binlog_query(THD::MYSQL_QUERY_TYPE, buff, query_length, + FALSE, FALSE, 0); } end: close_thread_tables(thd); @@ -3217,7 +3217,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!result) /* success */ { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -3383,7 +3383,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (write_to_binlog) { - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + if (write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + result= TRUE; } rw_unlock(&LOCK_grant); @@ -3502,7 +3503,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, if (!result) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -5716,7 +5717,7 @@ bool mysql_create_user(THD *thd, List &list) my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr_safe()); if (some_users_created) - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5789,7 +5790,7 @@ bool mysql_drop_user(THD *thd, List &list) my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe()); if (some_users_deleted) - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5874,7 +5875,7 @@ bool mysql_rename_user(THD *thd, List &list) my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); if (some_users_renamed && mysql_bin_log.is_open()) - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -6056,15 +6057,17 @@ bool mysql_revoke_all(THD *thd, List &list) VOID(pthread_mutex_unlock(&acl_cache->lock)); - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + int binlog_error= + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); - if (result) + /* error for writing binary log has already been reported */ + if (result && !binlog_error) my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0)); - DBUG_RETURN(result); + DBUG_RETURN(result || binlog_error); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9bb4ebedd55..a1f34f6a770 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1336,7 +1336,7 @@ void close_thread_tables(THD *thd) handled either before writing a query log event (inside binlog_query()) or when preparing a pending event. */ - thd->binlog_flush_pending_rows_event(TRUE); + (void)thd->binlog_flush_pending_rows_event(TRUE); mysql_unlock_tables(thd, thd->lock); thd->lock=0; } @@ -1550,7 +1550,11 @@ void close_temporary_tables(THD *thd) qinfo.db= db.ptr(); qinfo.db_len= db.length(); thd->variables.character_set_client= cs_save; - mysql_bin_log.write(&qinfo); + if (mysql_bin_log.write(&qinfo)) + { + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, MYF(0), + "Failed to write the DROP statement for temporary tables to binary log"); + } thd->variables.pseudo_thread_id= save_pseudo_thread_id; } else @@ -4031,9 +4035,13 @@ retry: end = strxmov(strmov(query, "DELETE FROM `"), share->db.str,"`.`",share->table_name.str,"`", NullS); int errcode= query_error_code(thd, TRUE); - thd->binlog_query(THD::STMT_QUERY_TYPE, - query, (ulong)(end-query), - FALSE, FALSE, errcode); + if (thd->binlog_query(THD::STMT_QUERY_TYPE, + query, (ulong)(end-query), + FALSE, FALSE, errcode)) + { + my_free(query, MYF(0)); + goto err; + } my_free(query, MYF(0)); } else diff --git a/sql/sql_class.h b/sql/sql_class.h index 56d31be79c7..77b4aa6c1d0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2621,7 +2621,7 @@ public: {} int prepare(List &list, SELECT_LEX_UNIT *u); - void binlog_show_create_table(TABLE **tables, uint count); + int binlog_show_create_table(TABLE **tables, uint count); void store_values(List &values); void send_error(uint errcode,const char *err); bool send_eof(); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index a3f9b4baea4..d5d9830f63d 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -178,13 +178,13 @@ uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length, Helper function to write a query to binlog used by mysql_rm_db() */ -static inline void write_to_binlog(THD *thd, char *query, uint q_len, - char *db, uint db_len) +static inline int write_to_binlog(THD *thd, char *query, uint q_len, + char *db, uint db_len) { Query_log_event qinfo(thd, query, q_len, 0, 0, 0); qinfo.db= db; qinfo.db_len= db_len; - mysql_bin_log.write(&qinfo); + return mysql_bin_log.write(&qinfo); } @@ -747,7 +747,11 @@ not_silent: qinfo.db_len = strlen(db); /* These DDL methods and logging protected with LOCK_mysql_create_db */ - mysql_bin_log.write(&qinfo); + if (mysql_bin_log.write(&qinfo)) + { + error= -1; + goto exit; + } } my_ok(thd, result); } @@ -824,7 +828,8 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) qinfo.db_len = strlen(db); /* These DDL methods and logging protected with LOCK_mysql_create_db */ - mysql_bin_log.write(&qinfo); + if (error= mysql_bin_log.write(&qinfo)) + goto exit; } my_ok(thd, result); @@ -974,7 +979,11 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) qinfo.db_len = strlen(db); /* These DDL methods and logging protected with LOCK_mysql_create_db */ - mysql_bin_log.write(&qinfo); + if (mysql_bin_log.write(&qinfo)) + { + error= -1; + goto exit; + } } thd->clear_error(); thd->server_status|= SERVER_STATUS_DB_DROPPED; @@ -1002,7 +1011,11 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (query_pos + tbl_name_len + 1 >= query_end) { /* These DDL methods and logging protected with LOCK_mysql_create_db */ - write_to_binlog(thd, query, query_pos -1 - query, db, db_len); + if (write_to_binlog(thd, query, query_pos -1 - query, db, db_len)) + { + error= -1; + goto exit; + } query_pos= query_data_start; } @@ -1015,7 +1028,11 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (query_pos != query_data_start) { /* These DDL methods and logging protected with LOCK_mysql_create_db */ - write_to_binlog(thd, query, query_pos -1 - query, db, db_len); + if (write_to_binlog(thd, query, query_pos -1 - query, db, db_len)) + { + error= -1; + goto exit; + } } } @@ -1965,7 +1982,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) Query_log_event qinfo(thd, thd->query(), thd->query_length(), 0, TRUE, errcode); thd->clear_error(); - mysql_bin_log.write(&qinfo); + error|= mysql_bin_log.write(&qinfo); } /* Step9: Let's do "use newdb" if we renamed the current database */ diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 6b9a83e695b..af3fdf11696 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -850,9 +850,10 @@ void multi_delete::abort() if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query(), thd->query_length(), - transactional_tables, FALSE, errcode); + /* possible error of writing binary log is ignored deliberately */ + (void) thd->binlog_query(THD::ROW_QUERY_TYPE, + thd->query(), thd->query_length(), + transactional_tables, FALSE, errcode); } thd->transaction.all.modified_non_trans_table= true; } @@ -1167,8 +1168,9 @@ end: { /* In RBR, the statement is not binlogged if the table is temporary. */ if (!is_temporary_table || !thd->current_stmt_binlog_row_based) - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - my_ok(thd); // This should return record count + error= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (!error) + my_ok(thd); // This should return record count } VOID(pthread_mutex_lock(&LOCK_open)); unlock_table_name(thd, table_list); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9754d5575e8..1f4ca90157f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2743,10 +2743,11 @@ bool Delayed_insert::handle_inserts(void) will be binlogged together as one single Table_map event and one single Rows event. */ - thd.binlog_query(THD::ROW_QUERY_TYPE, - row->query.str, row->query.length, - FALSE, FALSE, errcode); - + if (thd.binlog_query(THD::ROW_QUERY_TYPE, + row->query.str, row->query.length, + FALSE, FALSE, errcode)) + goto err; + thd.time_zone_used = backup_time_zone_used; thd.variables.time_zone = backup_time_zone; } @@ -2814,8 +2815,9 @@ bool Delayed_insert::handle_inserts(void) TODO: Move the logging to last in the sequence of rows. */ - if (thd.current_stmt_binlog_row_based) - thd.binlog_flush_pending_rows_event(TRUE); + if (thd.current_stmt_binlog_row_based && + thd.binlog_flush_pending_rows_event(TRUE)) + goto err; if ((error=table->file->extra(HA_EXTRA_NO_CACHE))) { // This shouldn't happen @@ -3267,16 +3269,21 @@ bool select_insert::send_eof() events are in the transaction cache and will be written when ha_autocommit_or_rollback() is issued below. */ - if (mysql_bin_log.is_open()) + if (mysql_bin_log.is_open() && + (!error || thd->transaction.stmt.modified_non_trans_table)) { int errcode= 0; if (!error) thd->clear_error(); else errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); - thd->binlog_query(THD::ROW_QUERY_TYPE, + if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), thd->query_length(), - trans_table, FALSE, errcode); + trans_table, FALSE, errcode)) + { + table->file->ha_release_auto_increment(); + DBUG_RETURN(1); + } } table->file->ha_release_auto_increment(); @@ -3345,9 +3352,10 @@ void select_insert::abort() { if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), - thd->query_length(), - transactional_table, FALSE, errcode); + /* error of writing binary log is ignored */ + (void) thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), + thd->query_length(), + transactional_table, FALSE, errcode); } if (!thd->current_stmt_binlog_row_based && !can_rollback_data()) thd->transaction.all.modified_non_trans_table= TRUE; @@ -3602,7 +3610,8 @@ select_create::prepare(List &values, SELECT_LEX_UNIT *u) !table->s->tmp_table && !ptr->get_create_info()->table_existed) { - ptr->binlog_show_create_table(tables, count); + if (int error= ptr->binlog_show_create_table(tables, count)) + return error; } return 0; } @@ -3709,7 +3718,7 @@ select_create::prepare(List &values, SELECT_LEX_UNIT *u) DBUG_RETURN(0); } -void +int select_create::binlog_show_create_table(TABLE **tables, uint count) { /* @@ -3748,12 +3757,13 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - thd->binlog_query(THD::STMT_QUERY_TYPE, - query.ptr(), query.length(), - /* is_trans */ TRUE, - /* suppress_use */ FALSE, - errcode); + result= thd->binlog_query(THD::STMT_QUERY_TYPE, + query.ptr(), query.length(), + /* is_trans */ TRUE, + /* suppress_use */ FALSE, + errcode); } + return result; } void select_create::store_values(List &values) @@ -3851,7 +3861,8 @@ void select_create::abort() select_insert::abort(); thd->transaction.stmt.modified_non_trans_table= FALSE; reenable_binlog(thd); - thd->binlog_flush_pending_rows_event(TRUE); + /* possible error of writing binary log is ignored deliberately */ + (void)thd->binlog_flush_pending_rows_event(TRUE); if (m_plock) { diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 326a7517ed6..ee3b442c83a 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -122,7 +122,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, char name[FN_REFLEN]; File file; TABLE *table= NULL; - int error; + int error= 0; String *field_term=ex->field_term,*escaped=ex->escaped; String *enclosed=ex->enclosed; bool is_fifo=0; @@ -504,18 +504,20 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); + /* since there is already an error, the possible error of + writing binary log will be ignored */ if (thd->transaction.stmt.modified_non_trans_table) - write_execute_load_query_log_event(thd, ex, - table_list->db, - table_list->table_name, - handle_duplicates, ignore, - transactional_table, - errcode); + (void) write_execute_load_query_log_event(thd, ex, + table_list->db, + table_list->table_name, + handle_duplicates, ignore, + transactional_table, + errcode); else { Delete_file_log_event d(thd, db, transactional_table); d.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F; - mysql_bin_log.write(&d); + (void) mysql_bin_log.write(&d); } } } @@ -541,7 +543,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, after this point. */ if (thd->current_stmt_binlog_row_based) - thd->binlog_flush_pending_rows_event(true); + error= thd->binlog_flush_pending_rows_event(true); else { /* @@ -553,13 +555,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (lf_info.wrote_create_file) { int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); - write_execute_load_query_log_event(thd, ex, - table_list->db, table_list->table_name, - handle_duplicates, ignore, - transactional_table, - errcode); + error= write_execute_load_query_log_event(thd, ex, + table_list->db, table_list->table_name, + handle_duplicates, ignore, + transactional_table, + errcode); } } + if (error) + goto err; } #endif /*!EMBEDDED_LIBRARY*/ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a2a1494141c..a114d92b124 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2987,7 +2987,7 @@ end_with_restore_list: /* Presumably, REPAIR and binlog writing doesn't require synchronization */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -3019,7 +3019,7 @@ end_with_restore_list: /* Presumably, ANALYZE and binlog writing doesn't require synchronization */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -3042,7 +3042,7 @@ end_with_restore_list: /* Presumably, OPTIMIZE and binlog writing doesn't require synchronization */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -3159,7 +3159,7 @@ end_with_restore_list: if (incident) { Incident_log_event ev(thd, incident); - mysql_bin_log.write(&ev); + (void) mysql_bin_log.write(&ev); /* error is ignored */ mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE); } DBUG_PRINT("debug", ("Just after generate_incident()")); @@ -3988,7 +3988,8 @@ end_with_restore_list: */ if (!lex->no_write_to_binlog && write_to_binlog) { - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + if (res= write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + break; } my_ok(thd); } @@ -4566,12 +4567,12 @@ create_sp_error: case SP_KEY_NOT_FOUND: if (lex->drop_if_exists) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), SP_COM_STRING(lex), lex->spname->m_name.str); - res= FALSE; - my_ok(thd); + if (!res) + my_ok(thd); break; } my_error(ER_SP_DOES_NOT_EXIST, MYF(0), diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 329317f4293..275115e3cbd 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4113,8 +4113,9 @@ static int fast_end_partition(THD *thd, ulonglong copied, } if ((!is_empty) && (!written_bin_log) && - (!thd->lex->no_write_to_binlog)) - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + (!thd->lex->no_write_to_binlog) && + write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + DBUG_RETURN(TRUE); my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO), (ulong) (copied + deleted), diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index dac96f2e9c4..e85e730db5b 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -34,6 +34,7 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list); bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) { bool error= 1; + bool binlog_error= 0; TABLE_LIST *ren_table= 0; int to_table; char *rename_log_table[2]= {NULL, NULL}; @@ -174,11 +175,11 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) */ pthread_mutex_unlock(&LOCK_open); - /* Lets hope this doesn't fail as the result will be messy */ if (!silent && !error) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - my_ok(thd); + binlog_error= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (!binlog_error) + my_ok(thd); } if (!error) @@ -190,7 +191,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) err: start_waiting_global_read_lock(thd); - DBUG_RETURN(error); + DBUG_RETURN(error || binlog_error); } diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index de038f8dc2c..4b10d284611 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1004,8 +1004,8 @@ int reset_slave(THD *thd, Master_info* mi) MY_STAT stat_area; char fname[FN_REFLEN]; int thread_mask= 0, error= 0; - uint sql_errno=0; - const char* errmsg=0; + uint sql_errno=ER_UNKNOWN_ERROR; + const char* errmsg= "Unknown error occured while reseting slave"; DBUG_ENTER("reset_slave"); lock_slave_threads(mi); @@ -1671,7 +1671,8 @@ err: replication events along LOAD DATA processing. @param file pointer to io-cache - @return 0 + @retval 0 success + @retval 1 failure */ int log_loaded_block(IO_CACHE* file) { @@ -1698,7 +1699,8 @@ int log_loaded_block(IO_CACHE* file) Append_block_log_event a(lf_info->thd, lf_info->thd->db, buffer, min(block_len, max_event_size), lf_info->log_delayed); - mysql_bin_log.write(&a); + if (mysql_bin_log.write(&a)) + DBUG_RETURN(1); } else { @@ -1706,7 +1708,8 @@ int log_loaded_block(IO_CACHE* file) buffer, min(block_len, max_event_size), lf_info->log_delayed); - mysql_bin_log.write(&b); + if (mysql_bin_log.write(&b)) + DBUG_RETURN(1); lf_info->wrote_create_file= 1; DBUG_SYNC_POINT("debug_lock.created_file_event",10); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0e36ecfcb46..f5df8481dc4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1748,9 +1748,10 @@ end: file */ -void write_bin_log(THD *thd, bool clear_error, - char const *query, ulong query_length) +int write_bin_log(THD *thd, bool clear_error, + char const *query, ulong query_length) { + int error= 0; if (mysql_bin_log.is_open()) { int errcode= 0; @@ -1758,9 +1759,10 @@ void write_bin_log(THD *thd, bool clear_error, thd->clear_error(); else errcode= query_error_code(thd, TRUE); - thd->binlog_query(THD::STMT_QUERY_TYPE, - query, query_length, FALSE, FALSE, errcode); + error= thd->binlog_query(THD::STMT_QUERY_TYPE, + query, query_length, FALSE, FALSE, errcode); } + return error; } @@ -2106,7 +2108,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, tables). In this case, we can write the original query into the binary log. */ - write_bin_log(thd, !error, thd->query(), thd->query_length()); + error |= write_bin_log(thd, !error, thd->query(), thd->query_length()); } else if (thd->current_stmt_binlog_row_based && tmp_table_deleted) @@ -2128,7 +2130,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, */ built_query.chop(); // Chop of the last comma built_query.append(" /* generated by server */"); - write_bin_log(thd, !error, built_query.ptr(), built_query.length()); + error|= write_bin_log(thd, !error, built_query.ptr(), built_query.length()); } /* @@ -2147,7 +2149,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, */ built_tmp_query.chop(); // Chop of the last comma built_tmp_query.append(" /* generated by server */"); - write_bin_log(thd, !error, built_tmp_query.ptr(), built_tmp_query.length()); + error|= write_bin_log(thd, !error, built_tmp_query.ptr(), built_tmp_query.length()); } } @@ -3556,9 +3558,9 @@ void sp_prepare_create_field(THD *thd, Create_field *sql_field) RETURN VALUES NONE */ -static inline void write_create_table_bin_log(THD *thd, - const HA_CREATE_INFO *create_info, - bool internal_tmp_table) +static inline int write_create_table_bin_log(THD *thd, + const HA_CREATE_INFO *create_info, + bool internal_tmp_table) { /* Don't write statement if: @@ -3571,7 +3573,8 @@ static inline void write_create_table_bin_log(THD *thd, (!thd->current_stmt_binlog_row_based || (thd->current_stmt_binlog_row_based && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + return write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + return 0; } @@ -3837,8 +3840,7 @@ bool mysql_create_table_no_lock(THD *thd, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), alias); - error= 0; - write_create_table_bin_log(thd, create_info, internal_tmp_table); + error= write_create_table_bin_log(thd, create_info, internal_tmp_table); goto err; } my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias); @@ -3959,8 +3961,7 @@ bool mysql_create_table_no_lock(THD *thd, thd->thread_specific_used= TRUE; } - write_create_table_bin_log(thd, create_info, internal_tmp_table); - error= FALSE; + error= write_create_table_bin_log(thd, create_info, internal_tmp_table); unlock_and_end: VOID(pthread_mutex_unlock(&LOCK_open)); @@ -3975,7 +3976,7 @@ warn: ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), alias); create_info->table_existed= 1; // Mark that table existed - write_create_table_bin_log(thd, create_info, internal_tmp_table); + error= write_create_table_bin_log(thd, create_info, internal_tmp_table); goto unlock_and_end; } @@ -5448,18 +5449,20 @@ binlog: create_info, FALSE /* show_database */); DBUG_ASSERT(result == 0); // store_create_info() always return 0 - write_bin_log(thd, TRUE, query.ptr(), query.length()); + if (write_bin_log(thd, TRUE, query.ptr(), query.length())) + goto err; } } else // Case 1 - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + goto err; } /* Case 3 and 4 does nothing under RBR */ } - else - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + else if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + goto err; res= FALSE; @@ -5547,7 +5550,7 @@ mysql_discard_or_import_tablespace(THD *thd, error=1; if (error) goto err; - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + error= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); err: ha_autocommit_or_rollback(thd, error); @@ -6558,11 +6561,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, thd->clear_error(); Query_log_event qinfo(thd, thd->query(), thd->query_length(), 0, FALSE, 0); - mysql_bin_log.write(&qinfo); + if (error= mysql_bin_log.write(&qinfo)) + goto view_err_unlock; } my_ok(thd); } +view_err_unlock: unlock_table_names(thd, table_list, (TABLE_LIST*) 0); view_err: @@ -6810,8 +6815,9 @@ view_err: if (!error) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - my_ok(thd); + error= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (!error) + my_ok(thd); } else if (error > 0) { @@ -7299,8 +7305,9 @@ view_err: if (rename_temporary_table(thd, new_table, new_db, new_name)) goto err1; /* We don't replicate alter table statement on temporary tables */ - if (!thd->current_stmt_binlog_row_based) - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (!thd->current_stmt_binlog_row_based && + write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + DBUG_RETURN(TRUE); goto end_temporary; } @@ -7463,7 +7470,8 @@ view_err: DBUG_ASSERT(!(mysql_bin_log.is_open() && thd->current_stmt_binlog_row_based && (create_info->options & HA_LEX_CREATE_TMP_TABLE))); - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + DBUG_RETURN(TRUE); if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME)) { diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc index fcc442a8f9a..65107f8679e 100644 --- a/sql/sql_tablespace.cc +++ b/sql/sql_tablespace.cc @@ -66,6 +66,6 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) ha_resolve_storage_engine_name(hton), "TABLESPACE or LOGFILE GROUP"); } - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); - DBUG_RETURN(FALSE); + error= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + DBUG_RETURN(error); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index a251a533622..ba0515d38ad 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -507,7 +507,7 @@ end: if (!result) { - write_bin_log(thd, TRUE, stmt_query.ptr(), stmt_query.length()); + result= write_bin_log(thd, TRUE, stmt_query.ptr(), stmt_query.length()); } VOID(pthread_mutex_unlock(&LOCK_open)); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index c6b41b59a3f..3ade9fbc0b1 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -506,8 +506,8 @@ int mysql_create_function(THD *thd,udf_func *udf) rw_unlock(&THR_LOCK_udf); /* Binlog the create function. */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + DBUG_RETURN(1); DBUG_RETURN(0); err: @@ -581,8 +581,8 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) rw_unlock(&THR_LOCK_udf); /* Binlog the drop function. */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + DBUG_RETURN(1); DBUG_RETURN(0); err: rw_unlock(&THR_LOCK_udf); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 26f40c7fa9f..433e2619aca 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1868,9 +1868,10 @@ void multi_update::abort() into repl event. */ int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query(), thd->query_length(), - transactional_tables, FALSE, errcode); + /* the error of binary logging is ignored */ + (void)thd->binlog_query(THD::ROW_QUERY_TYPE, + thd->query(), thd->query_length(), + transactional_tables, FALSE, errcode); } thd->transaction.all.modified_non_trans_table= TRUE; } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 83cebf1e3da..c6d412112c2 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -662,8 +662,9 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, buff.append(views->source.str, views->source.length); int errcode= query_error_code(thd, TRUE); - thd->binlog_query(THD::STMT_QUERY_TYPE, - buff.ptr(), buff.length(), FALSE, FALSE, errcode); + if (thd->binlog_query(THD::STMT_QUERY_TYPE, + buff.ptr(), buff.length(), FALSE, FALSE, errcode)) + res= TRUE; } VOID(pthread_mutex_unlock(&LOCK_open)); @@ -1652,7 +1653,8 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) /* if something goes wrong, bin-log with possible error code, otherwise bin-log with error code cleared. */ - write_bin_log(thd, !something_wrong, thd->query(), thd->query_length()); + if (write_bin_log(thd, !something_wrong, thd->query(), thd->query_length())) + something_wrong= 1; } VOID(pthread_mutex_unlock(&LOCK_open)); From cfa7e83d6deee0acb2c003e94617be115e07814e Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Mon, 25 Jan 2010 17:46:48 +0200 Subject: [PATCH 287/344] Bug #47142 "slave start until" stops 1 event too late in 4.1 to 5.0 replication When replicating from 4.1 master to 5.0 slave START SLAVE UNTIL can stop too late. The necessary in calculating of the beginning of an event the event's length did not correspond to the master's genuine information at the event's execution time. That piece of info was changed at the event's relay-logging due to binlog_version<4 event conversion by IO thread. Fixed with storing the master genuine Query_log_event size into a new status variable at relay-logging of the event. The stored info is extacted at the event execution and participate further to caclulate the correct start position of the event in the until-pos stopping routine. The new status variable's algorithm will be only active when the event comes from the master of version < 5.0 (binlog_version < 4). mysql-test/r/rpl_until.result: results changed. mysql-test/std_data/bug47142_master-bin.000001: a binlog from 4.1 master to replace one of the running 5.x master is added as part of Bug #47142 regression test. mysql-test/t/rpl_until.test: Regression test for Bug #47142 is added. sql/log_event.cc: Storing and extracting the master's genuine size of the event from the status var of the event packet header. The binlog_version<4 query-log-event is a. converted into the modern binlog_version==4 to store the original size of the event into a new status var; the converted representation goes into the relay log. b. the converted event is read out and the stored size is engaged in the start pos calculation. The new status is active only for events that IO thread instantiates for the sake of the conversion. sql/log_event.h: Incrementing the max szie of MAX_SIZE_LOG_EVENT_STATUS because of the new status var; Defining the new status variable to hold the master's genuine event size; Augmenting the Query_log_event with a new member to hold a value to store/extact from the status var of the event packet header. --- mysql-test/r/rpl_until.result | 18 +++++++++ .../std_data/bug47142_master-bin.000001 | Bin 0 -> 386 bytes mysql-test/t/rpl_until.test | 36 +++++++++++++++++ sql/log_event.cc | 37 ++++++++++++++++-- sql/log_event.h | 15 ++++++- 5 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 mysql-test/std_data/bug47142_master-bin.000001 diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index 60b956785ba..476e56878db 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -194,3 +194,21 @@ start slave sql_thread; start slave until master_log_file='master-bin.000001', master_log_pos=776; Warnings: Note 1254 Slave is already running +stop slave; +drop table if exists t1; +Warnings: +Note 1051 Unknown table 't1' +flush logs; +show binary logs; +Log_name File_size +master-bin.000001 # +master-bin.000002 # +reset slave; +start slave until master_log_file='master-bin.000001', master_log_pos=294 /* to stop right before DROP */; +show tables /* t1 must exist */; +Tables_in_test +t1 +drop table t1; +stop slave; +reset slave; +reset master; diff --git a/mysql-test/std_data/bug47142_master-bin.000001 b/mysql-test/std_data/bug47142_master-bin.000001 new file mode 100644 index 0000000000000000000000000000000000000000..d1a089a784a6596f5c92b2ffdd06da90951ad9fc GIT binary patch literal 386 zcmaJ-K}rKb5S(c69et97>@JxQye&Rp4;}=GczlSaDGcYom1G&aJDy?%}ZJu6l57w7# z_LwZsQvbEKE|8C+?Zo*3+kpbibOw6WlePp=FGl#6R3ssU3z$KIgL+OR3clU;9sy literal 0 HcmV?d00001 diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index c404ea7e58b..b533c2192b0 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -84,4 +84,40 @@ start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561; start slave sql_thread; start slave until master_log_file='master-bin.000001', master_log_pos=776; +# +# Bug #47142 "slave start until" stops 1 event too late in 4.1 to 5.0 replication +# +# testing fixes that refine the start position of prior-5.0 master's event +# and by that provide correct execution of +# START SLAVE UNTIL ... master_log_pos= x; +# Keep the test at the end of the file because it manipulates with binlog files +# to substitute the genuine one with a prepared on 4.1 server. +# + +connection slave; +stop slave; + +connection master; +drop table if exists t1; +flush logs; +--source include/show_binary_logs.inc +--remove_file $MYSQLTEST_VARDIR/log/master-bin.000001 +--copy_file $MYSQL_TEST_DIR/std_data/bug47142_master-bin.000001 $MYSQLTEST_VARDIR/log/master-bin.000001 + +connection slave; +reset slave; +start slave until master_log_file='master-bin.000001', master_log_pos=294 /* to stop right before DROP */; +--source include/wait_for_slave_sql_to_stop.inc + +show tables /* t1 must exist */; + +# clean-up of Bug #47142 testing + +drop table t1; # drop on slave only, master does not have t1. +stop slave; +reset slave; + +connection master; +reset master; + # End of 4.1 tests diff --git a/sql/log_event.cc b/sql/log_event.cc index 40e29e58ab6..f32fcb0056c 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1271,10 +1271,22 @@ bool Query_log_event::write(IO_CACHE* file) int8store(start, table_map_for_update); start+= 8; } + if (master_data_written != 0) + { + /* + Q_MASTER_DATA_WRITTEN_CODE only exists in relay logs where the master + has binlog_version<4 and the slave has binlog_version=4. See comment + for master_data_written in log_event.h for details. + */ + *start++= Q_MASTER_DATA_WRITTEN_CODE; + int4store(start, master_data_written); + start+= 4; + } + /* NOTE: When adding new status vars, please don't forget to update - the MAX_SIZE_LOG_EVENT_STATUS in log_event.h and update function - code_name in this file. + the MAX_SIZE_LOG_EVENT_STATUS in log_event.h and update the function + code_name() in this file. Here there could be code like if (command-line-option-which-says-"log_this_variable" && inited) @@ -1354,6 +1366,7 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, auto_increment_offset(thd_arg->variables.auto_increment_offset), lc_time_names_number(thd_arg->variables.lc_time_names->number), charset_database_number(0), + master_data_written(0), table_map_for_update((ulonglong)thd_arg->table_map_for_update) { time_t end_time; @@ -1481,6 +1494,7 @@ code_name(int code) case Q_LC_TIME_NAMES_CODE: return "Q_LC_TIME_NAMES_CODE"; case Q_CHARSET_DATABASE_CODE: return "Q_CHARSET_DATABASE_CODE"; case Q_TABLE_MAP_FOR_UPDATE_CODE: return "Q_TABLE_MAP_FOR_UPDATE_CODE"; + case Q_MASTER_DATA_WRITTEN_CODE: return "Q_MASTER_DATA_WRITTEN_CODE"; } sprintf(buf, "CODE#%d", code); return buf; @@ -1518,7 +1532,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, flags2_inited(0), sql_mode_inited(0), charset_inited(0), auto_increment_increment(1), auto_increment_offset(1), time_zone_len(0), lc_time_names_number(0), charset_database_number(0), - table_map_for_update(0) + table_map_for_update(0), master_data_written(0) { ulong data_len; uint32 tmp; @@ -1574,6 +1588,18 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, DBUG_PRINT("info", ("Query_log_event has status_vars_len: %u", (uint) status_vars_len)); tmp-= 2; + } + else + { + /* + server version < 5.0 / binlog_version < 4 master's event is + relay-logged with storing the original size of the event in + Q_MASTER_DATA_WRITTEN_CODE status variable. + The size is to be restored at reading Q_MASTER_DATA_WRITTEN_CODE-marked + event from the relay log. + */ + DBUG_ASSERT(description_event->binlog_version < 4); + master_data_written= data_written; } /* We have parsed everything we know in the post header for QUERY_EVENT, @@ -1665,6 +1691,11 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, table_map_for_update= uint8korr(pos); pos+= 8; break; + case Q_MASTER_DATA_WRITTEN_CODE: + CHECK_SPACE(pos, end, 4); + data_written= master_data_written= uint4korr(pos); + pos+= 4; + break; default: /* That's why you must write status vars in growing order of code */ DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\ diff --git a/sql/log_event.h b/sql/log_event.h index 45e3d11b48c..10b374199de 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -212,7 +212,8 @@ struct sql_ex_info 1 + 1 + 255 /* type, length, time_zone */ + \ 1 + 2 /* type, lc_time_names_number */ + \ 1 + 2 /* type, charset_database_number */ + \ - 1 + 8 /* type, table_map_for_update */) + 1 + 8 /* type, table_map_for_update */ + \ + 1 + 4 /* type, master_data_written */) #define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \ LOG_EVENT_HEADER_LEN + /* write_header */ \ QUERY_HEADER_LEN + /* write_data */ \ @@ -278,6 +279,9 @@ struct sql_ex_info #define Q_CHARSET_DATABASE_CODE 8 #define Q_TABLE_MAP_FOR_UPDATE_CODE 9 + +#define Q_MASTER_DATA_WRITTEN_CODE 10 + /* Intvar event post-header */ #define I_TYPE_OFFSET 0 @@ -810,6 +814,15 @@ public: statement, for other query statements, this will be zero. */ ulonglong table_map_for_update; + /* + Holds the original length of a Query_log_event that comes from a + master of version < 5.0 (i.e., binlog_version < 4). When the IO + thread writes the relay log, it augments the Query_log_event with a + Q_MASTER_DATA_WRITTEN_CODE status_var that holds the original event + length. This field is initialized to non-zero in the SQL thread when + it reads this augmented event. + */ + uint32 master_data_written; #ifndef MYSQL_CLIENT From c7cb4b3c42ceeabf0e6ce289dccee560896faacc Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 26 Jan 2010 10:47:43 +0200 Subject: [PATCH 288/344] fix a windows test run bug with debug binaries : dbug frame should be exited before destroying the thread local storage. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index db0453dc364..1fcd046f870 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1949,10 +1949,10 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) /* It's safe to broadcast outside a lock (COND... is not deleted here) */ DBUG_PRINT("signal", ("Broadcasting COND_thread_count")); + DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); (void) pthread_cond_broadcast(&COND_thread_count); - DBUG_LEAVE; // Must match DBUG_ENTER() pthread_exit(0); return 0; // Avoid compiler warnings } From 7920e89a47a6cc8f65783528291ce87ba5b19074 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 26 Jan 2010 15:05:19 -0200 Subject: [PATCH 289/344] Bug#49491: Much overhead for MD5() and SHA1() on short strings MySQL's hash functions MD5 and SHA relied on the somewhat slow sprintf function to convert the digests to hex representations. This patch replaces the sprintf with a specific and inline hex conversion function. Patch contributed by Jan Steemann. sql/item_strfunc.cc: Add a hex conversion function. --- sql/item_strfunc.cc | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ecd839d8378..4cdeeef6c78 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -42,6 +42,20 @@ C_MODE_END String my_empty_string("",default_charset_info); +/* + Convert an array of bytes to a hexadecimal representation. + + Used to generate a hexadecimal representation of a message digest. +*/ +static void array_to_hex(char *to, const char *str, uint len) +{ + const char *str_end= str + len; + for (; str != str_end; ++str) + { + *to++= _dig_vec_lower[((uchar) *str) >> 4]; + *to++= _dig_vec_lower[((uchar) *str) & 0x0F]; + } +} bool Item_str_func::fix_fields(THD *thd, Item **ref) @@ -114,12 +128,7 @@ String *Item_func_md5::val_str(String *str) null_value=1; return 0; } - sprintf((char *) str->ptr(), - "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - digest[0], digest[1], digest[2], digest[3], - digest[4], digest[5], digest[6], digest[7], - digest[8], digest[9], digest[10], digest[11], - digest[12], digest[13], digest[14], digest[15]); + array_to_hex((char *) str->ptr(), (const char*) digest, 16); str->length((uint) 32); return str; } @@ -160,15 +169,7 @@ String *Item_func_sha::val_str(String *str) if (!( str->alloc(SHA1_HASH_SIZE*2) || (mysql_sha1_result(&context,digest)))) { - sprintf((char *) str->ptr(), - "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ -%02x%02x%02x%02x%02x%02x%02x%02x", - digest[0], digest[1], digest[2], digest[3], - digest[4], digest[5], digest[6], digest[7], - digest[8], digest[9], digest[10], digest[11], - digest[12], digest[13], digest[14], digest[15], - digest[16], digest[17], digest[18], digest[19]); - + array_to_hex((char *) str->ptr(), (const char*) digest, SHA1_HASH_SIZE); str->length((uint) SHA1_HASH_SIZE*2); null_value=0; return str; From 89b1bb0be8c59eaf77e17e3e51ee9252e76e5c1d Mon Sep 17 00:00:00 2001 From: Matthew Montgomery Date: Tue, 26 Jan 2010 16:39:32 -0600 Subject: [PATCH 290/344] Bug #50642 ssl certs in test suite are expiring soon. --- mysql-test/std_data/client-cert.pem | 59 +++++---- mysql-test/std_data/server-cert.pem | 60 +++++---- mysql-test/std_data/server8k-cert.pem | 169 ++++++++++++++++++-------- 3 files changed, 176 insertions(+), 112 deletions(-) diff --git a/mysql-test/std_data/client-cert.pem b/mysql-test/std_data/client-cert.pem index 9300520793e..854b790c961 100644 --- a/mysql-test/std_data/client-cert.pem +++ b/mysql-test/std_data/client-cert.pem @@ -1,12 +1,13 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 3 (0x3) + Serial Number: + cb:73:4b:30:a0:cb:f7:d9 Signature Algorithm: sha1WithRSAEncryption - Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB + Issuer: C=SE, ST=Uppsala, O=MySQL AB/emailAddress=abstract.mysql.developer@mysql.com Validity - Not Before: Jan 28 11:04:39 2009 GMT - Not After : Jan 28 11:04:39 2010 GMT + Not Before: Jan 26 22:32:38 2010 GMT + Not After : Jan 26 22:32:38 2011 GMT Subject: C=SE, ST=Uppsala, O=MySQL AB/emailAddress=abstract.mysql.developer@mysql.com Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -19,37 +20,33 @@ Certificate: 74:fb:56:1e:37 Exponent: 65537 (0x10001) X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE X509v3 Subject Key Identifier: 58:30:B5:9B:2C:05:94:06:BA:3D:3C:F0:B2:CD:1D:67:65:E3:7F:85 X509v3 Authority Key Identifier: - keyid:F2:E2:EA:55:65:A4:9A:E2:AC:9D:97:F5:45:6C:F6:F7:8C:11:AD:DF - DirName:/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB - serial:95:E9:78:F5:34:50:E4:D5 + keyid:58:30:B5:9B:2C:05:94:06:BA:3D:3C:F0:B2:CD:1D:67:65:E3:7F:85 + DirName:/C=SE/ST=Uppsala/O=MySQL AB/emailAddress=abstract.mysql.developer@mysql.com + serial:CB:73:4B:30:A0:CB:F7:D9 + X509v3 Basic Constraints: + CA:TRUE Signature Algorithm: sha1WithRSAEncryption - 05:19:e3:13:14:fc:c5:28:bf:69:f8:00:b3:25:cb:bd:ca:9f: - 2f:4c:b3:a8:04:11:f0:74:27:bd:82:2c:b4:49:9b:a7:59:f0: - f7:87:d1:e0:ba:99:a2:fe:4b:1d:10:6f:e4:a2:b3:cd:7f:8b: - 68:31:46:ee:cd:9e:e2:47:e1:4c:fa:74:d1:e2:8b:cc:a0:4b: - a8:24:d1:a4:c3:6b:2a:c6:28:cd:41:e0:06:48:e6:cf:f2:3c: - ca:37:95:d7:29:64:6b:91:91:83:e7:ac:c8:0b:87:bc:da:a6: - aa:f1:44:43:c8:74:7b:15:26:91:2e:03:c4:71:50:6c:f8:68: - dc:8c + 59:07:27:11:c3:39:b1:9c:6c:9b:12:9f:c9:e1:69:31:a7:10: + b1:fb:5f:e2:8d:83:9d:c8:f0:8b:ff:10:ee:ba:37:45:75:f7: + dd:e6:d4:bb:f5:13:27:ec:82:2e:0d:83:f4:ce:d0:04:db:88: + 20:80:dd:6e:7b:4e:88:f5:15:d5 -----BEGIN CERTIFICATE----- -MIICfzCCAeigAwIBAgIBAzANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJTRTEQ -MA4GA1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlT -UUwgQUIwHhcNMDkwMTI4MTEwNDM5WhcNMTAwMTI4MTEwNDM5WjBlMQswCQYDVQQG -EwJTRTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIxMTAvBgkq -hkiG9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wXDAN -BgkqhkiG9w0BAQEFAANLADBIAkEA4VIwLNm+ZCiRXXr92ekUNXrSlE6RRuDbn2t5 -9EysbgdhNIZ0YqeoRK/6h4eofUJh/6tQ1Hu/dfrV1bN0+1YeNwIDAQABo4GjMIGg -MAkGA1UdEwQCMAAwHQYDVR0OBBYEFFgwtZssBZQGuj088LLNHWdl43+FMHQGA1Ud -IwRtMGuAFPLi6lVlpJrirJ2X9UVs9veMEa3foUikRjBEMQswCQYDVQQGEwJTRTEQ -MA4GA1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlT -UUwgQUKCCQCV6Xj1NFDk1TANBgkqhkiG9w0BAQUFAAOBgQAFGeMTFPzFKL9p+ACz -Jcu9yp8vTLOoBBHwdCe9giy0SZunWfD3h9Hgupmi/ksdEG/korPNf4toMUbuzZ7i -R+FM+nTR4ovMoEuoJNGkw2sqxijNQeAGSObP8jzKN5XXKWRrkZGD56zIC4e82qaq -8URDyHR7FSaRLgPEcVBs+GjcjA== +MIICjjCCAjigAwIBAgIJAMtzSzCgy/fZMA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNV +BAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQjExMC8G +CSqGSIb3DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNvbTAe +Fw0xMDAxMjYyMjMyMzhaFw0xMTAxMjYyMjMyMzhaMGUxCzAJBgNVBAYTAlNFMRAw +DgYDVQQIEwdVcHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQjExMC8GCSqGSIb3DQEJ +ARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNvbTBcMA0GCSqGSIb3 +DQEBAQUAA0sAMEgCQQDhUjAs2b5kKJFdev3Z6RQ1etKUTpFG4Nufa3n0TKxuB2E0 +hnRip6hEr/qHh6h9QmH/q1DUe791+tXVs3T7Vh43AgMBAAGjgcowgccwHQYDVR0O +BBYEFFgwtZssBZQGuj088LLNHWdl43+FMIGXBgNVHSMEgY8wgYyAFFgwtZssBZQG +uj088LLNHWdl43+FoWmkZzBlMQswCQYDVQQGEwJTRTEQMA4GA1UECBMHVXBwc2Fs +YTERMA8GA1UEChMITXlTUUwgQUIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0Lm15 +c3FsLmRldmVsb3BlckBteXNxbC5jb22CCQDLc0swoMv32TAMBgNVHRMEBTADAQH/ +MA0GCSqGSIb3DQEBBQUAA0EAWQcnEcM5sZxsmxKfyeFpMacQsftf4o2Dncjwi/8Q +7ro3RXX33ebUu/UTJ+yCLg2D9M7QBNuIIIDdbntOiPUV1Q== -----END CERTIFICATE----- diff --git a/mysql-test/std_data/server-cert.pem b/mysql-test/std_data/server-cert.pem index cab54db8b23..3781430c7f6 100644 --- a/mysql-test/std_data/server-cert.pem +++ b/mysql-test/std_data/server-cert.pem @@ -1,12 +1,13 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 1 (0x1) + Serial Number: + a9:86:f7:15:12:8e:ad:5d Signature Algorithm: sha1WithRSAEncryption - Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB + Issuer: C=SE, ST=Uppsala, O=MySQL AB, CN=localhost/emailAddress=abstract.mysql.developer@mysql.com Validity - Not Before: Jan 28 10:55:13 2009 GMT - Not After : Jan 28 10:55:13 2010 GMT + Not Before: Jan 26 22:31:45 2010 GMT + Not After : Jan 26 22:31:45 2011 GMT Subject: C=SE, ST=Uppsala, O=MySQL AB, CN=localhost/emailAddress=abstract.mysql.developer@mysql.com Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -19,37 +20,34 @@ Certificate: 8d:c3:04:98:27 Exponent: 65537 (0x10001) X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE X509v3 Subject Key Identifier: D9:9A:B8:5F:22:EA:04:10:C8:25:7D:82:57:E6:2E:FD:19:29:E7:DA X509v3 Authority Key Identifier: - keyid:F2:E2:EA:55:65:A4:9A:E2:AC:9D:97:F5:45:6C:F6:F7:8C:11:AD:DF - DirName:/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB - serial:95:E9:78:F5:34:50:E4:D5 + keyid:D9:9A:B8:5F:22:EA:04:10:C8:25:7D:82:57:E6:2E:FD:19:29:E7:DA + DirName:/C=SE/ST=Uppsala/O=MySQL AB/CN=localhost/emailAddress=abstract.mysql.developer@mysql.com + serial:A9:86:F7:15:12:8E:AD:5D + X509v3 Basic Constraints: + CA:TRUE Signature Algorithm: sha1WithRSAEncryption - 54:07:2d:21:0b:a5:af:3b:58:23:32:5e:56:7f:ab:58:63:48: - 91:aa:38:90:89:16:f9:cc:bf:a4:0e:78:2b:9f:c5:1b:58:a6: - e6:08:8f:2e:ae:97:03:21:9b:f1:cd:c0:26:8f:1d:d7:28:27: - a0:8e:81:09:1b:1c:0f:c9:a5:41:3a:2d:44:3f:9c:fa:87:ff: - c8:4c:2b:44:f7:1b:c1:3e:4f:01:7f:e9:26:cc:9f:1c:06:b5: - 0b:27:d1:10:90:be:93:0c:9c:e7:b0:d1:ea:27:99:4e:06:14: - 0c:7a:e9:c1:52:c5:33:68:bc:61:0d:db:81:3b:57:48:57:bf: - 42:9a + 58:b5:de:24:8e:29:82:b1:57:23:c4:b4:1b:8c:a7:81:89:21: + 12:a4:a3:06:b8:ca:88:20:ad:53:27:fc:91:36:f3:f0:82:c6: + ca:05:49:03:44:90:51:54:f0:6f:94:0e:b5:05:31:b0:7e:61: + fb:ab:8b:02:5f:f8:f3:7e:28:9c -----BEGIN CERTIFICATE----- -MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJTRTEQ -MA4GA1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlT -UUwgQUIwHhcNMDkwMTI4MTA1NTEzWhcNMTAwMTI4MTA1NTEzWjB5MQswCQYDVQQG -EwJTRTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIxEjAQBgNV -BAMTCWxvY2FsaG9zdDExMC8GCSqGSIb3DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2 -ZWxvcGVyQG15c3FsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC2j+W3tIaD -E4r5v2PLZC25UdHeq3tFH6q1ZnMT+aYH1bp8+pK9N+Kth9s+tmoSZPjuF+MVBi+o -gmi/V43DBJgnAgMBAAGjgaMwgaAwCQYDVR0TBAIwADAdBgNVHQ4EFgQU2Zq4XyLq -BBDIJX2CV+Yu/Rkp59owdAYDVR0jBG0wa4AU8uLqVWWkmuKsnZf1RWz294wRrd+h -SKRGMEQxCzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdV -cHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQoIJAJXpePU0UOTVMA0GCSqGSIb3DQEB -BQUAA4GBAFQHLSELpa87WCMyXlZ/q1hjSJGqOJCJFvnMv6QOeCufxRtYpuYIjy6u -lwMhm/HNwCaPHdcoJ6COgQkbHA/JpUE6LUQ/nPqH/8hMK0T3G8E+TwF/6SbMnxwG -tQsn0RCQvpMMnOew0eonmU4GFAx66cFSxTNovGEN24E7V0hXv0Ka +MIICyjCCAnSgAwIBAgIJAKmG9xUSjq1dMA0GCSqGSIb3DQEBBQUAMHkxCzAJBgNV +BAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQjESMBAG +A1UEAxMJbG9jYWxob3N0MTEwLwYJKoZIhvcNAQkBFiJhYnN0cmFjdC5teXNxbC5k +ZXZlbG9wZXJAbXlzcWwuY29tMB4XDTEwMDEyNjIyMzE0NVoXDTExMDEyNjIyMzE0 +NVoweTELMAkGA1UEBhMCU0UxEDAOBgNVBAgTB1VwcHNhbGExETAPBgNVBAoTCE15 +U1FMIEFCMRIwEAYDVQQDEwlsb2NhbGhvc3QxMTAvBgkqhkiG9w0BCQEWImFic3Ry +YWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wXDANBgkqhkiG9w0BAQEFAANL +ADBIAkEAto/lt7SGgxOK+b9jy2QtuVHR3qt7RR+qtWZzE/mmB9W6fPqSvTfirYfb +PrZqEmT47hfjFQYvqIJov1eNwwSYJwIDAQABo4HeMIHbMB0GA1UdDgQWBBTZmrhf +IuoEEMglfYJX5i79GSnn2jCBqwYDVR0jBIGjMIGggBTZmrhfIuoEEMglfYJX5i79 +GSnn2qF9pHsweTELMAkGA1UEBhMCU0UxEDAOBgNVBAgTB1VwcHNhbGExETAPBgNV +BAoTCE15U1FMIEFCMRIwEAYDVQQDEwlsb2NhbGhvc3QxMTAvBgkqhkiG9w0BCQEW +ImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb22CCQCphvcVEo6tXTAM +BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA0EAWLXeJI4pgrFXI8S0G4yngYkh +EqSjBrjKiCCtUyf8kTbz8ILGygVJA0SQUVTwb5QOtQUxsH5h+6uLAl/4834onA== -----END CERTIFICATE----- diff --git a/mysql-test/std_data/server8k-cert.pem b/mysql-test/std_data/server8k-cert.pem index 3b86effd699..008876f6244 100644 --- a/mysql-test/std_data/server8k-cert.pem +++ b/mysql-test/std_data/server8k-cert.pem @@ -1,12 +1,13 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 4 (0x4) + Serial Number: + c8:e1:81:28:1d:a7:33:f4 Signature Algorithm: sha1WithRSAEncryption - Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB + Issuer: C=SE, ST=Uppsala, O=MySQL AB, CN=server Validity - Not Before: Jan 28 11:12:27 2009 GMT - Not After : Jan 28 11:12:27 2010 GMT + Not Before: Jan 26 22:31:07 2010 GMT + Not After : Jan 26 22:31:07 2011 GMT Subject: C=SE, ST=Uppsala, O=MySQL AB, CN=server Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -83,56 +84,124 @@ Certificate: 74:7f:17:57:d9 Exponent: 65537 (0x10001) X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE X509v3 Subject Key Identifier: 58:12:24:59:A7:3C:29:15:89:5A:C2:12:DB:E7:A5:42:10:21:B7:BA X509v3 Authority Key Identifier: - keyid:F2:E2:EA:55:65:A4:9A:E2:AC:9D:97:F5:45:6C:F6:F7:8C:11:AD:DF - DirName:/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB - serial:95:E9:78:F5:34:50:E4:D5 + keyid:58:12:24:59:A7:3C:29:15:89:5A:C2:12:DB:E7:A5:42:10:21:B7:BA + DirName:/C=SE/ST=Uppsala/O=MySQL AB/CN=server + serial:C8:E1:81:28:1D:A7:33:F4 + X509v3 Basic Constraints: + CA:TRUE Signature Algorithm: sha1WithRSAEncryption - cd:cb:5c:83:35:ea:cb:cb:c3:a8:c3:95:e2:e6:6f:4d:d8:e4: - ee:41:dd:3f:35:82:ac:2f:fd:63:89:4f:3a:19:d7:81:75:b3: - a3:fc:36:b2:12:d5:c6:56:bc:13:60:37:33:6e:a0:d8:ae:7c: - 88:f9:4b:ee:7b:1f:c8:f0:56:19:07:4d:bb:45:52:1c:78:81: - 07:7c:13:86:b8:86:70:85:e4:71:25:58:78:d1:be:de:22:82: - 6d:1a:4b:06:ac:f0:e8:50:87:c7:69:64:c2:61:43:cd:96:06: - a6:7e:09:a9:02:01:2a:a2:40:f3:cd:10:80:48:d0:34:55:40: - b9:ce + 99:ff:b3:de:74:25:33:32:d0:38:a4:a0:92:c7:ee:02:05:92: + 21:1b:65:27:81:63:d2:37:b6:de:cc:0c:a2:b1:a8:8d:0c:ce: + c3:e4:e4:74:18:bf:1f:6e:91:d2:58:34:4a:a5:23:0a:15:09: + 1f:5c:74:82:14:dd:08:3e:c0:ba:21:5c:15:3d:f9:1a:07:7f: + da:cc:d0:56:8c:d6:17:a8:f3:26:43:71:65:a9:94:08:25:04: + a8:6b:a8:27:32:90:90:2b:22:4c:4f:79:3f:81:09:42:86:67: + c3:f9:a8:b0:cc:ff:ed:8f:36:ac:57:ea:e2:f4:b6:9e:83:c1: + e6:cc:6b:f5:4e:28:3c:65:c3:8f:d6:ae:25:07:05:a0:ee:41: + 76:f7:52:05:ca:6b:68:d2:ef:74:d2:cc:a1:8a:46:7d:0d:50: + 34:62:72:76:a7:5d:4b:7a:87:e5:ed:97:b3:fb:75:14:ad:80: + 9e:1e:91:77:47:f2:8c:28:45:68:aa:f8:00:7c:be:72:d2:40: + 0e:b3:5a:33:ac:a5:3a:a8:f7:b5:4a:42:c6:60:83:f2:a8:74: + e4:b9:6b:28:f6:56:10:8c:74:0f:7d:f7:18:7b:31:38:3c:e7: + c0:17:62:d8:e6:88:79:5b:c3:1f:da:bc:85:01:6d:68:d7:b9: + 2b:95:03:0e:ba:07:e4:26:dd:89:09:40:38:4f:f6:95:97:41: + 0b:8b:78:a7:a2:aa:91:d5:73:a3:12:ce:b3:10:3a:be:d5:20: + 9b:87:b9:ad:ce:42:00:14:f7:8f:d0:41:75:e7:97:b8:79:92: + fe:a0:33:58:e9:ec:82:43:56:a7:f7:02:40:00:4e:b8:57:3c: + d1:1f:45:44:09:2d:83:c0:46:47:77:72:ff:1f:7d:31:78:67: + 03:eb:be:74:3e:15:17:59:3e:06:e5:08:61:70:03:41:4c:01: + 50:ef:53:04:5d:7f:c8:27:51:0f:7a:68:d4:a0:38:f6:7e:ab: + 7d:83:ee:b7:dd:83:f0:1a:11:d3:a0:f7:f1:23:8f:ad:ca:1a: + b3:eb:e4:e5:19:44:7e:cb:e3:97:df:3b:bb:89:36:f6:66:42: + 2e:ef:8f:81:db:59:89:a0:81:b6:02:78:c3:db:0a:07:82:36: + 08:b6:82:70:f4:b3:05:66:6e:e1:9f:69:89:b5:c8:12:9b:1c: + bc:b6:2c:3d:74:ae:d5:f8:56:ab:63:e6:bd:06:06:f5:5d:e6: + 25:df:7e:f9:ac:da:69:e6:a5:1b:78:2c:9a:3e:80:ea:1c:c9: + 16:5c:a6:39:f5:d1:d7:2c:c0:20:55:7c:77:a4:43:19:df:52: + c5:80:ff:aa:03:39:ea:2c:71:d9:88:b4:15:04:1a:47:b3:de: + 20:73:85:cd:9d:23:ed:98:06:21:19:0d:08:96:87:e7:a4:84: + a8:97:83:ed:ba:85:d6:60:6c:44:a6:c6:e5:6b:70:c8:83:2d: + f2:c7:ee:dd:96:14:4e:43:51:46:a2:74:c9:4d:35:5d:10:65: + b0:0f:3d:ed:b4:69:8b:a3:dd:23:e7:40:2e:13:58:f8:27:33: + 64:74:57:89:5e:9d:e0:6e:2f:50:e2:fa:d8:18:7f:9a:8e:6c: + aa:4a:fb:c8:9f:b6:78:11:cb:44:ca:7e:20:16:a0:2e:1e:18: + 7a:ac:70:2b:9c:c7:0e:bc:2e:c2:7f:de:b7:a2:0d:57:1a:10: + 05:60:7c:ca:51:7a:64:87:3d:84:29:3c:18:10:8c:9c:59:c1: + 99:e8:6f:2c:24:83:66:ab:bc:f6:eb:b0:e6:05:f5:da:eb:9d: + 85:ea:2c:81:cf:4f:bb:55:4e:70:fb:a0:68:ac:d7:5f:ae:15: + dd:a7:48:63:f0:05:47:a4:f9:cc:32:9a:20:b9:05:32:3a:fe: + fd:75:18:37:49:36:0d:77:cb:bd:64:08:09:0c:9c:6e:4e:71: + 1f:49:6b:11:b6:87:c5:72:3c:d4:9f:a6:06:44:57:b7:42:64: + c1:85:82:5b:44:a3:bb:2b:f8:53:e4:6f:e8:ae:10:db:b9:c3: + 0c:76:01:e9:0f:d5:63:b3:ab:7b:bd:04:26:2c:8f:c4:99:76: + eb:1e:03:0c:e2:b3:cc:69:8d:64:51:2e:a6:d0:f6:50:1e:c1: + f9:b7:f2:d1:6e:6a:3d:3b:d4:a2:72:4f:95:35:ff:c7:52:0f: + fb:11:a9:a7:4c:35:d8:d7:43:98:ff:b1:b9:e4:54:29:7a:d4: + 98:70:51:f8:e0:dc:66:e1:ef:f0:70:57:08:13:82:5c:4c:48: + 91:4f:a7:04:54:6d:eb:27:92:45:40:51:28:6d:a5:29:4a:33: + b3:04:d0:67:d8:35:9c:d4:b2:e0:b0:e7:a3:3a:f4:34:7f:e7: + 7d:d7:42:86:a6:a0:07:7e:3b:de:e3:6f:a0:76:19:f1:70:ea: + 71:af:c4:d3:42:48:c5:fd:3d:2f:20:37:77:7f:e7:23:53:e2: + 23:dc:1f:0e:f6:91:66:a3:6c:82:9d:fd:e5:39:eb:13:9c:9e: + ae:90:45:92:8f:db:f3:7a:3d:9a:86:ba:12:06:43:66:58:df: + fa:92:c8:b8:d7:b7:57:ff:2b:37:71:f0:d1:60:69:9b:58:a3: + 91:64:d3:27:cf:d3:83:f7:53:39:9c:03:d9:a5:f1:16:df:a3: + 03:28:8b:ef:3d:7c:c8:af:50:3b:21:85:33:2e:c5:f1 -----BEGIN CERTIFICATE----- -MIIGJTCCBY6gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJTRTEQ -MA4GA1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlT -UUwgQUIwHhcNMDkwMTI4MTExMjI3WhcNMTAwMTI4MTExMjI3WjBDMQswCQYDVQQG -EwJTRTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIxDzANBgNV -BAMTBnNlcnZlcjCCBCIwDQYJKoZIhvcNAQEBBQADggQPADCCBAoCggQBAMCPIgMk -WWdGFNaPYAlYBgdF8XhxVfHquTCKzcM8ub9lbhjtoLjJGVZvxJAZyGUJ2/+/gqEI -rQFPWqPUPXh+S0oBpH3oewU+fdi5VVhg1hzO6DJiLBlg8+0FmW3JdwcuEW0Lmsdo -OEbo+jGA3+h58PH9qZTD+g31eKxJftUX/eHuRPPHDjAyXakZJeS7IR3+PIRIQPVY -9L8TjIVou+z13cY40bB3H6aOT43ib0l09T+QZY6ZHlmcHLUmJMSx3h77lmXEMRQa -U7heYorHBPe0NqSvB8gnBu3d5vSMYvFlQNCfn6kUyI6LdNZnWtDJTTWh1Xs5OkKf -5ND0xg8uQjBLVrI9bY4tWMVpmTVJlZWZtocpKzLRUAjNJRRIbRCZhWE8QSYhVcwf -z62wL7mJ2E6gGP91HbaXfMX6i9yTF4YKZNQJNdWDNG1cbcaMzbnswpPGwbfMBG8i -4Ae/4NmbL9WgUMz58JWDj/Qwg3KU17VL2syfVDuNeHcLJGwPwpZhli+4X7V6q3pb -l3qprUCL8tbGjYHZlGGPnQPFuRADaIO/BIHMrL00iejUjUMg4rakET0VKoIM1jpq -jGLUk7zDgL8btCsKejTwzR6CPyUP0QSoCgUZsNYWgzmvC0V9yxR+TaqqwjmoRjir -vasqvTRDf9ol3iv7aTv+O4f9mJR2Sr8EozHjOv9vBPr6JOQqiekOv0RMcoWCPIlK -A2MBQZJT0IJgbtj/jKK0Gjsgba50kjBOSONRpstzlwYTAzIjm32ixzqpr5eMUe3+ -+rS0GqOH/M+MjuaAFQP9/n29sXbxX7MJK0xNp3y1crHW2zjAZ6RUvIcJpTm6Gn4/ -dGCtPUu+lFPzZBbHMzXsQQCVtt6ZYqJ6KJpFTfrNpnf23lhyUMh9aTjbBwSE2E05 -91ATQ64tr0WkKjlWPLi32CakNskjqqq4SQshup56K39NKZ8OAB60Xqb6Sf6N5XRX -2LrZkizSrIQd8qakRBy/iEEyftHDL268D10Zpo90K2e63anbaLXOnSVI31QI0B1P -LlskvAUP+1hG+gLKU5MpzxAnwqAY0PXUuTxe345s9Xy5tFTMORZdPNqWs8Ns1HBd -0zCnpr1v3UG8qN5CYFmahSUNKkXDBbRuekpNyowK5Ww0vCCbbUrKyramOqDbww4g -GhIbd93LHX/DDQ3nwf2W0sdogJmg2YozIaOLolqnficGAn/tYBE3NFQXf02QFB5p -Nw268Cvwoy1iech2qOrI5zsfxk/CDNes8HdTXfBQtN+bA8pNQeEYsiUwhh1j5Wex -U81rToMauV4tBRVr1I6xl/wxA1fLvyd/zV8nfmbnPBcJthEqTzPN6xrTb9UVi4vO -aGt+mpXldH8XV9kCAwEAAaOBozCBoDAJBgNVHRMEAjAAMB0GA1UdDgQWBBRYEiRZ -pzwpFYlawhLb56VCECG3ujB0BgNVHSMEbTBrgBTy4upVZaSa4qydl/VFbPb3jBGt -36FIpEYwRDELMAkGA1UEBhMCU0UxEDAOBgNVBAgTB1VwcHNhbGExEDAOBgNVBAcT -B1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCggkAlel49TRQ5NUwDQYJKoZIhvcN -AQEFBQADgYEAzctcgzXqy8vDqMOV4uZvTdjk7kHdPzWCrC/9Y4lPOhnXgXWzo/w2 -shLVxla8E2A3M26g2K58iPlL7nsfyPBWGQdNu0VSHHiBB3wThriGcIXkcSVYeNG+ -3iKCbRpLBqzw6FCHx2lkwmFDzZYGpn4JqQIBKqJA880QgEjQNFVAuc4= +MIIJrzCCBZegAwIBAgIJAMjhgSgdpzP0MA0GCSqGSIb3DQEBBQUAMEMxCzAJBgNV +BAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQjEPMA0G +A1UEAxMGc2VydmVyMB4XDTEwMDEyNjIyMzEwN1oXDTExMDEyNjIyMzEwN1owQzEL +MAkGA1UEBhMCU0UxEDAOBgNVBAgTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFC +MQ8wDQYDVQQDEwZzZXJ2ZXIwggQiMA0GCSqGSIb3DQEBAQUAA4IEDwAwggQKAoIE +AQDAjyIDJFlnRhTWj2AJWAYHRfF4cVXx6rkwis3DPLm/ZW4Y7aC4yRlWb8SQGchl +Cdv/v4KhCK0BT1qj1D14fktKAaR96HsFPn3YuVVYYNYczugyYiwZYPPtBZltyXcH +LhFtC5rHaDhG6PoxgN/oefDx/amUw/oN9XisSX7VF/3h7kTzxw4wMl2pGSXkuyEd +/jyESED1WPS/E4yFaLvs9d3GONGwdx+mjk+N4m9JdPU/kGWOmR5ZnBy1JiTEsd4e ++5ZlxDEUGlO4XmKKxwT3tDakrwfIJwbt3eb0jGLxZUDQn5+pFMiOi3TWZ1rQyU01 +odV7OTpCn+TQ9MYPLkIwS1ayPW2OLVjFaZk1SZWVmbaHKSsy0VAIzSUUSG0QmYVh +PEEmIVXMH8+tsC+5idhOoBj/dR22l3zF+ovckxeGCmTUCTXVgzRtXG3GjM257MKT +xsG3zARvIuAHv+DZmy/VoFDM+fCVg4/0MINylNe1S9rMn1Q7jXh3CyRsD8KWYZYv +uF+1eqt6W5d6qa1Ai/LWxo2B2ZRhj50DxbkQA2iDvwSBzKy9NIno1I1DIOK2pBE9 +FSqCDNY6aoxi1JO8w4C/G7QrCno08M0egj8lD9EEqAoFGbDWFoM5rwtFfcsUfk2q +qsI5qEY4q72rKr00Q3/aJd4r+2k7/juH/ZiUdkq/BKMx4zr/bwT6+iTkKonpDr9E +THKFgjyJSgNjAUGSU9CCYG7Y/4yitBo7IG2udJIwTkjjUabLc5cGEwMyI5t9osc6 +qa+XjFHt/vq0tBqjh/zPjI7mgBUD/f59vbF28V+zCStMTad8tXKx1ts4wGekVLyH +CaU5uhp+P3RgrT1LvpRT82QWxzM17EEAlbbemWKieiiaRU36zaZ39t5YclDIfWk4 +2wcEhNhNOfdQE0OuLa9FpCo5Vjy4t9gmpDbJI6qquEkLIbqeeit/TSmfDgAetF6m ++kn+jeV0V9i62ZIs0qyEHfKmpEQcv4hBMn7Rwy9uvA9dGaaPdCtnut2p22i1zp0l +SN9UCNAdTy5bJLwFD/tYRvoCylOTKc8QJ8KgGND11Lk8Xt+ObPV8ubRUzDkWXTza +lrPDbNRwXdMwp6a9b91BvKjeQmBZmoUlDSpFwwW0bnpKTcqMCuVsNLwgm21Kysq2 +pjqg28MOIBoSG3fdyx1/ww0N58H9ltLHaICZoNmKMyGji6Jap34nBgJ/7WARNzRU +F39NkBQeaTcNuvAr8KMtYnnIdqjqyOc7H8ZPwgzXrPB3U13wULTfmwPKTUHhGLIl +MIYdY+VnsVPNa06DGrleLQUVa9SOsZf8MQNXy78nf81fJ35m5zwXCbYRKk8zzesa +02/VFYuLzmhrfpqV5XR/F1fZAgMBAAGjgaUwgaIwHQYDVR0OBBYEFFgSJFmnPCkV +iVrCEtvnpUIQIbe6MHMGA1UdIwRsMGqAFFgSJFmnPCkViVrCEtvnpUIQIbe6oUek +RTBDMQswCQYDVQQGEwJTRTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlT +UUwgQUIxDzANBgNVBAMTBnNlcnZlcoIJAMjhgSgdpzP0MAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggQBAJn/s950JTMy0DikoJLH7gIFkiEbZSeBY9I3tt7M +DKKxqI0MzsPk5HQYvx9ukdJYNEqlIwoVCR9cdIIU3Qg+wLohXBU9+RoHf9rM0FaM +1heo8yZDcWWplAglBKhrqCcykJArIkxPeT+BCUKGZ8P5qLDM/+2PNqxX6uL0tp6D +webMa/VOKDxlw4/WriUHBaDuQXb3UgXKa2jS73TSzKGKRn0NUDRicnanXUt6h+Xt +l7P7dRStgJ4ekXdH8owoRWiq+AB8vnLSQA6zWjOspTqo97VKQsZgg/KodOS5ayj2 +VhCMdA999xh7MTg858AXYtjmiHlbwx/avIUBbWjXuSuVAw66B+Qm3YkJQDhP9pWX +QQuLeKeiqpHVc6MSzrMQOr7VIJuHua3OQgAU94/QQXXnl7h5kv6gM1jp7IJDVqf3 +AkAATrhXPNEfRUQJLYPARkd3cv8ffTF4ZwPrvnQ+FRdZPgblCGFwA0FMAVDvUwRd +f8gnUQ96aNSgOPZ+q32D7rfdg/AaEdOg9/Ejj63KGrPr5OUZRH7L45ffO7uJNvZm +Qi7vj4HbWYmggbYCeMPbCgeCNgi2gnD0swVmbuGfaYm1yBKbHLy2LD10rtX4Vqtj +5r0GBvVd5iXffvms2mnmpRt4LJo+gOocyRZcpjn10dcswCBVfHekQxnfUsWA/6oD +OeoscdmItBUEGkez3iBzhc2dI+2YBiEZDQiWh+ekhKiXg+26hdZgbESmxuVrcMiD +LfLH7t2WFE5DUUaidMlNNV0QZbAPPe20aYuj3SPnQC4TWPgnM2R0V4leneBuL1Di ++tgYf5qObKpK+8iftngRy0TKfiAWoC4eGHqscCucxw68LsJ/3reiDVcaEAVgfMpR +emSHPYQpPBgQjJxZwZnobywkg2arvPbrsOYF9drrnYXqLIHPT7tVTnD7oGis11+u +Fd2nSGPwBUek+cwymiC5BTI6/v11GDdJNg13y71kCAkMnG5OcR9JaxG2h8VyPNSf +pgZEV7dCZMGFgltEo7sr+FPkb+iuENu5wwx2AekP1WOzq3u9BCYsj8SZduseAwzi +s8xpjWRRLqbQ9lAewfm38tFuaj071KJyT5U1/8dSD/sRqadMNdjXQ5j/sbnkVCl6 +1JhwUfjg3Gbh7/BwVwgTglxMSJFPpwRUbesnkkVAUShtpSlKM7ME0GfYNZzUsuCw +56M69DR/533XQoamoAd+O97jb6B2GfFw6nGvxNNCSMX9PS8gN3d/5yNT4iPcHw72 +kWajbIKd/eU56xOcnq6QRZKP2/N6PZqGuhIGQ2ZY3/qSyLjXt1f/Kzdx8NFgaZtY +o5Fk0yfP04P3UzmcA9ml8RbfowMoi+89fMivUDshhTMuxfE= -----END CERTIFICATE----- From c12c9780cdbe965bcdce0326b14a171d2f2b8635 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Jan 2010 10:52:13 +0800 Subject: [PATCH 291/344] Bug #49191 rpl_get_master_version_and_clock failed on PB2: COM_REGISTER_SLAVE failed The 'rpl_get_master_version_and_clock' test verifies if the slave I/O thread tries to reconnect to master when it tries to get the values of the UNIX_TIMESTAMP, SERVER_ID from master under network disconnection. So the master server is restarted for making the transient network disconnection, during the period the COM_REGISTER_SLAVE failures are produced in server log file when the slave I/O thread tries to register on master. To fix the problem, suppress COM_REGISTER_SLAVE failures in server log file by mtr suppression, because they are expected. mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result: Removed mtr.add_suppression("Get master clock failed with error: ") and mtr.add_suppression("Get master SERVER_ID failed with error: "). Because they are suppressed globally. --- mysql-test/collections/default.experimental | 1 - .../rpl/r/rpl_get_master_version_and_clock.result | 5 ++--- .../suite/rpl/t/rpl_get_master_version_and_clock.test | 11 ++++++----- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index 2e31063a6db..9c4055cd19e 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -17,7 +17,6 @@ main.plugin_load @solaris # Bug#42144 ndb.* # joro : NDB tests marked as experimental as agreed with bochklin -rpl.rpl_get_master_version_and_clock* # Bug #49191 2009-12-01 Daogang rpl_get_master_version_and_clock failed on PB2: COM_REGISTER_SLAVE failed rpl.rpl_innodb_bug28430* @solaris # Bug#46029 rpl_ndb.* # joro : NDB tests marked as experimental as agreed with bochklin diff --git a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result index 5f2a55b5e35..d054cb573d3 100644 --- a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result +++ b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result @@ -4,10 +4,9 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -call mtr.add_suppression("Get master clock failed with error: "); -call mtr.add_suppression("Get master SERVER_ID failed with error: "); -call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again"); +call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: .*"); call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*"); +call mtr.add_suppression("Slave I/O thread .* register on master"); SELECT IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP"); IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP") 1 diff --git a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test index 69c63eaa69f..24309e8a14a 100644 --- a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test +++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test @@ -16,12 +16,13 @@ source include/master-slave.inc; source include/have_debug.inc; -call mtr.add_suppression("Get master clock failed with error: "); -call mtr.add_suppression("Get master SERVER_ID failed with error: "); -call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again"); -call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*"); -#Test case 1: Try to get the value of the UNIX_TIMESTAMP from master under network disconnection + connection slave; +call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: .*"); +call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*"); +call mtr.add_suppression("Slave I/O thread .* register on master"); + +#Test case 1: Try to get the value of the UNIX_TIMESTAMP from master under network disconnection let $debug_saved= `select @@global.debug`; let $debug_lock= "debug_lock.before_get_UNIX_TIMESTAMP"; From 0d09e3a55fd953e7cd3578cfa7ad8cdbc4cd3e03 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 27 Jan 2010 11:38:29 +0100 Subject: [PATCH 292/344] YaSSL cert info buffer overflow fix Apply a diff from [Yassl-commit] yassl/taocrypt/src asn.cpp,1.13,1.14 [Yassl-commit] yassl/taocrypt/include asn.hpp,1.9,1.10 Original patch http://lists.mysql.com/commits/96697 extra/yassl/taocrypt/include/asn.hpp: [Yassl-commit] yassl/taocrypt/include asn.hpp,1.9,1.10 extra/yassl/taocrypt/src/asn.cpp: [Yassl-commit] yassl/taocrypt/src asn.cpp,1.13,1.14 --- extra/yassl/taocrypt/include/asn.hpp | 1 + extra/yassl/taocrypt/src/asn.cpp | 115 +++++++++++++++------------ 2 files changed, 67 insertions(+), 49 deletions(-) diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp index 1c1850cb47e..168b8a8c755 100644 --- a/extra/yassl/taocrypt/include/asn.hpp +++ b/extra/yassl/taocrypt/include/asn.hpp @@ -305,6 +305,7 @@ private: bool ValidateSignature(SignerList*); bool ConfirmSignature(Source&); void GetKey(); + char* AddTag(char*, const char*, const char*, word32, word32); void GetName(NameType); void GetValidity(); void GetDate(DateType); diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index 78200841bda..f44d550e95b 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -652,6 +652,25 @@ word32 CertDecoder::GetDigest() } +// memory length checked add tag to buffer +char* CertDecoder::AddTag(char* ptr, const char* buf_end, const char* tag_name, + word32 tag_name_length, word32 tag_value_length) +{ + if (ptr + tag_name_length + tag_value_length > buf_end) { + source_.SetError(CONTENT_E); + return 0; + } + + memcpy(ptr, tag_name, tag_name_length); + ptr += tag_name_length; + + memcpy(ptr, source_.get_current(), tag_value_length); + ptr += tag_value_length; + + return ptr; +} + + // process NAME, either issuer or subject void CertDecoder::GetName(NameType nt) { @@ -659,11 +678,22 @@ void CertDecoder::GetName(NameType nt) SHA sha; word32 length = GetSequence(); // length of all distinguished names - assert (length < ASN_NAME_MAX); + + if (length >= ASN_NAME_MAX) + return; length += source_.get_index(); - char* ptr = (nt == ISSUER) ? issuer_ : subject_; - word32 idx = 0; + char* ptr; + char* buf_end; + + if (nt == ISSUER) { + ptr = issuer_; + buf_end = ptr + sizeof(issuer_) - 1; // 1 byte for trailing 0 + } + else { + ptr = subject_; + buf_end = ptr + sizeof(subject_) - 1; // 1 byte for trailing 0 + } while (source_.get_index() < length) { GetSet(); @@ -685,47 +715,36 @@ void CertDecoder::GetName(NameType nt) byte id = source_.next(); b = source_.next(); // strType word32 strLen = GetLength(source_); - bool copy = false; - if (id == COMMON_NAME) { - memcpy(&ptr[idx], "/CN=", 4); - idx += 4; - copy = true; - } - else if (id == SUR_NAME) { - memcpy(&ptr[idx], "/SN=", 4); - idx += 4; - copy = true; - } - else if (id == COUNTRY_NAME) { - memcpy(&ptr[idx], "/C=", 3); - idx += 3; - copy = true; - } - else if (id == LOCALITY_NAME) { - memcpy(&ptr[idx], "/L=", 3); - idx += 3; - copy = true; - } - else if (id == STATE_NAME) { - memcpy(&ptr[idx], "/ST=", 4); - idx += 4; - copy = true; - } - else if (id == ORG_NAME) { - memcpy(&ptr[idx], "/O=", 3); - idx += 3; - copy = true; - } - else if (id == ORGUNIT_NAME) { - memcpy(&ptr[idx], "/OU=", 4); - idx += 4; - copy = true; - } - - if (copy) { - memcpy(&ptr[idx], source_.get_current(), strLen); - idx += strLen; + switch (id) { + case COMMON_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/CN=", 4, strLen))) + return; + break; + case SUR_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/SN=", 4, strLen))) + return; + break; + case COUNTRY_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/C=", 3, strLen))) + return; + break; + case LOCALITY_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/L=", 3, strLen))) + return; + break; + case STATE_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/ST=", 4, strLen))) + return; + break; + case ORG_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/O=", 3, strLen))) + return; + break; + case ORGUNIT_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/OU=", 4, strLen))) + return; + break; } sha.Update(source_.get_current(), strLen); @@ -740,17 +759,15 @@ void CertDecoder::GetName(NameType nt) word32 length = GetLength(source_); if (email) { - memcpy(&ptr[idx], "/emailAddress=", 14); - idx += 14; - - memcpy(&ptr[idx], source_.get_current(), length); - idx += length; + if (!(ptr = AddTag(ptr, buf_end, "/emailAddress=", 14, length))) + return; } source_.advance(length); } } - ptr[idx++] = 0; + + *ptr = 0; if (nt == ISSUER) sha.Final(issuerHash_); From 694d50c71efc079c794fc81fb13d49ce5036ce36 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Wed, 27 Jan 2010 11:38:50 +0100 Subject: [PATCH 293/344] Bug#50409 Solaris 8 compatibility broken by assumption about printstack() being present When Bug#47391 was fixed, no assumption was made that support for Solaris 8 was needed. Solaris 8 lacks printstack(), and the build breaks because of this. This patch adds a test for the presence of printstack() to configure.in for 5.0, and uses HAVE_PRINTSTACK to make decisions rather than the __sun define. --- configure.in | 2 +- sql/stacktrace.c | 2 +- sql/stacktrace.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 405ebddadbe..a399ccb2909 100644 --- a/configure.in +++ b/configure.in @@ -2128,7 +2128,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \ shmget shmat shmdt shmctl sigaction sigemptyset sigaddset \ sighold sigset sigthreadmask \ snprintf socket stpcpy strcasecmp strerror strsignal strnlen strpbrk strstr strtol \ - strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr) + strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr printstack) # # diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 295a7a3e1e2..a8648ca4e5a 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -227,7 +227,7 @@ stack trace is much more helpful in diagnosing the problem, so please do \n\ resolve it\n"); } -#elif defined(__sun) +#elif defined(HAVE_PRINTSTACK) /* Use Solaris' symbolic stack trace routine. */ #include diff --git a/sql/stacktrace.h b/sql/stacktrace.h index 718b545b775..1366a6cf996 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -35,7 +35,7 @@ void check_thread_lib(void); #define HAVE_STACKTRACE extern void set_exception_pointers(EXCEPTION_POINTERS *ep); #define init_stacktrace() {} -#elif defined(__sun) +#elif defined(HAVE_PRINTSTACK) #define HAVE_STACKTRACE #define init_stacktrace() {} #endif From 35c6bb89e64fd87a0ce1b51eab8b757dbdfc228d Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Wed, 27 Jan 2010 13:23:28 +0100 Subject: [PATCH 294/344] WL#5182 Remove more deprecated 4.1/5.0 features WL#5182 is a follow-up to WL#5154, deprecating a few more options and system variables. client/client_priv.h: The warning message has been changed to not include a specific version number in the text. client/mysql.cc: --no-tee is deprecated client/mysqldump.c: --all is deprecated -a now points to create-options mysql-test/r/mysqlbinlog.result: Warning text changed mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result: Warning text changed sql/mysql_priv.h: The warning message has been changed to not include a specific version number in the text. sql/mysqld.cc: --use-symbolic-links is deprecated -s now points to --symbolic-links --warnings is deprecated -W now points to --log-warnings myisam_max_extra_sort_file_size is deprecated record_buffer is deprecated --log-update is deprecated --sql-bin-update-same is deprecated --skip-locking is deprecated --skip-symlink is deprecated --enable-locking is deprecated --delay-key-write-for-all-tables is deprecated --- client/client_priv.h | 5 ++- client/mysql.cc | 2 +- client/mysqldump.c | 7 +++- mysql-test/r/mysqlbinlog.result | 6 +-- .../suite/rpl/r/rpl_row_mysqlbinlog.result | 4 +- sql/mysql_priv.h | 2 +- sql/mysqld.cc | 40 ++++++++++++++++--- 7 files changed, 50 insertions(+), 16 deletions(-) diff --git a/client/client_priv.h b/client/client_priv.h index 9d2fc2be141..689f7277c2e 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -37,7 +37,7 @@ #define WARN_DEPRECATED(Ver,Old,New) \ do { \ printf("Warning: The option '%s' is deprecated and will be removed " \ - "in MySQL %s. Please use %s instead.\n", (Old), (Ver), (New)); \ + "in a future release. Please use %s instead.\n", (Old), (New)); \ } while(0); enum options_client @@ -57,7 +57,7 @@ enum options_client OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL, OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION, OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH, - OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_CREATE_OPTIONS, OPT_SERVER_ARG, + OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_SERVER_ARG, OPT_POSITION, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME, OPT_SIGINT_IGNORE, OPT_HEXBLOB, OPT_ORDER_BY_PRIMARY, OPT_COUNT, #ifdef HAVE_NDBCLUSTER_DB @@ -90,5 +90,6 @@ enum options_client OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE, OPT_WRITE_BINLOG, OPT_DUMP_DATE, OPT_FIRST_SLAVE, + OPT_ALL, OPT_MAX_CLIENT_OPTION }; diff --git a/client/mysql.cc b/client/mysql.cc index b3b73fdb468..82a29816b8e 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1630,7 +1630,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), init_tee(argument); break; case OPT_NOTEE: - printf("WARNING: option deprecated; use --disable-tee instead.\n"); + WARN_DEPRECATED(VER_CELOSIA, "--no-tee", "--disable-tee"); if (opt_outfile) end_tee(); break; diff --git a/client/mysqldump.c b/client/mysqldump.c index 25a8d7b0f6f..8a50c57201c 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -179,7 +179,7 @@ HASH ignore_table; static struct my_option my_long_options[] = { - {"all", 'a', "Deprecated. Use --create-options instead.", + {"all", OPT_ALL, "Deprecated. Use --create-options instead.", (uchar**) &create_options, (uchar**) &create_options, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"all-databases", 'A', @@ -230,7 +230,7 @@ static struct my_option my_long_options[] = {"compress", 'C', "Use compression in server/client protocol.", (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"create-options", OPT_CREATE_OPTIONS, + {"create-options", 'a', "Include all MySQL specific create options.", (uchar**) &create_options, (uchar**) &create_options, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, @@ -762,6 +762,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case 'O': WARN_DEPRECATED(VER_CELOSIA, "--set-variable", "--variable-name=value"); break; + case (int) OPT_ALL: + WARN_DEPRECATED(VER_CELOSIA, "--all", "--create-options"); + break; case (int) OPT_FIRST_SLAVE: WARN_DEPRECATED(VER_CELOSIA, "--first-slave", "--lock-all-tables"); break; diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index f5c40202101..b7aa981f834 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -93,7 +93,7 @@ ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; --- --position -- -Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. +Warning: The option '--position' is deprecated and will be removed in a future release. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; @@ -194,7 +194,7 @@ ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; --- --position -- -Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. +Warning: The option '--position' is deprecated and will be removed in a future release. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; @@ -235,7 +235,7 @@ DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; -Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. +Warning: The option '--position' is deprecated and will be removed in a future release. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; diff --git a/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result b/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result index 449407742de..538764da738 100644 --- a/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result +++ b/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result @@ -152,7 +152,7 @@ c1 c3 c4 c5 5 2006-02-22 00:00:00 Tested in Texas 11 --- Test 2 position test -- -Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. +Warning: The option '--position' is deprecated and will be removed in a future release. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; @@ -315,7 +315,7 @@ ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; --- Test 7 reading stdin w/position -- -Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. +Warning: The option '--position' is deprecated and will be removed in a future release. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index e99effe1dcb..34f29e7c458 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -124,7 +124,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); (Old), (Ver), (New)); \ else \ sql_print_warning("The syntax '%s' is deprecated and will be removed " \ - "in MySQL %s. Please use %s instead.", (Old), (Ver), (New)); \ + "in a future release. Please use %s instead.", (Old), (New)); \ } while(0) extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1fcd046f870..40026867aaf 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5711,6 +5711,9 @@ enum options_mysqld OPT_TABLE_LOCK_WAIT_TIMEOUT, OPT_PLUGIN_LOAD, OPT_PLUGIN_DIR, + OPT_SYMBOLIC_LINKS, + OPT_WARNINGS, + OPT_RECORD_BUFFER_OLD, OPT_LOG_OUTPUT, OPT_PORT_OPEN_TIMEOUT, OPT_PROFILING, @@ -6532,7 +6535,7 @@ log and this option does nothing anymore.", {"transaction-isolation", OPT_TX_ISOLATION, "Default transaction isolation level.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"use-symbolic-links", 's', "Enable symbolic link support. Deprecated option; use --symbolic-links instead.", + {"use-symbolic-links", OPT_SYMBOLIC_LINKS, "Enable symbolic link support. Deprecated option; use --symbolic-links instead.", (uchar**) &my_use_symdir, (uchar**) &my_use_symdir, 0, GET_BOOL, NO_ARG, IF_PURIFY(0,1), 0, 0, 0, 0, 0}, {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG, @@ -6542,7 +6545,7 @@ log and this option does nothing anymore.", 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"warnings", 'W', "Deprecated; use --log-warnings instead.", + {"warnings", OPT_WARNINGS, "Deprecated; use --log-warnings instead.", (uchar**) &global_system_variables.log_warnings, (uchar**) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, ULONG_MAX, 0, 0, 0}, @@ -6795,7 +6798,8 @@ The minimum value for this variable is 4096.", (uchar**) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG, 6, 2, 7, 0, 1, 0}, {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, - "Deprecated option", + "This is a deprecated option that does nothing anymore. It will be removed in MySQL " + VER_CELOSIA, (uchar**) &global_system_variables.myisam_max_extra_sort_file_size, (uchar**) &max_system_variables.myisam_max_extra_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH, @@ -6952,8 +6956,8 @@ The minimum value for this variable is 4096.", (uchar**) &max_system_variables.read_rnd_buff_size, 0, GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT_MAX32, MALLOC_OVERHEAD, IO_SIZE, 0}, - {"record_buffer", OPT_RECORD_BUFFER, - "Alias for read_buffer_size", + {"record_buffer", OPT_RECORD_BUFFER_OLD, + "Alias for read_buffer_size. This variable is deprecated and will be removed in a future release.", (uchar**) &global_system_variables.read_buff_size, (uchar**) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT_MAX32, MALLOC_OVERHEAD, IO_SIZE, 0}, @@ -7966,6 +7970,9 @@ mysqld_get_one_option(int optid, print_version(); exit(0); #endif /*EMBEDDED_LIBRARY*/ + case OPT_WARNINGS: + WARN_DEPRECATED(NULL, VER_CELOSIA, "--warnings", "--log-warnings"); + /* Note: fall-through to 'W' */ case 'W': if (!argument) global_system_variables.log_warnings++; @@ -7987,6 +7994,9 @@ mysqld_get_one_option(int optid, case (int) OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD: WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-bin-trust-routine-creators", "--log-bin-trust-function-creators"); break; + case (int) OPT_ENABLE_LOCK: + WARN_DEPRECATED(NULL, VER_CELOSIA, "--enable-locking", "--external-locking"); + break; case (int) OPT_BIG_TABLES: thd_startup_options|=OPTION_BIG_TABLES; break; @@ -7997,6 +8007,7 @@ mysqld_get_one_option(int optid, opt_myisam_log=1; break; case (int) OPT_UPDATE_LOG: + WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-update", "--log-bin"); opt_update_log=1; break; case (int) OPT_BIN_LOG: @@ -8164,8 +8175,18 @@ mysqld_get_one_option(int optid, "give threads different priorities."); break; case (int) OPT_SKIP_LOCK: + WARN_DEPRECATED(NULL, VER_CELOSIA, "--skip-locking", "--skip-external-locking"); opt_external_locking=0; break; + case (int) OPT_SQL_BIN_UPDATE_SAME: + WARN_DEPRECATED(NULL, VER_CELOSIA, "--sql-bin-update-same", "the binary log"); + break; + case (int) OPT_RECORD_BUFFER_OLD: + WARN_DEPRECATED(NULL, VER_CELOSIA, "record_buffer", "read_buffer_size"); + break; + case (int) OPT_SYMBOLIC_LINKS: + WARN_DEPRECATED(NULL, VER_CELOSIA, "--use-symbolic-links", "--symbolic-links"); + break; case (int) OPT_SKIP_HOST_CACHE: opt_specialflag|= SPECIAL_NO_HOST_CACHE; break; @@ -8191,6 +8212,7 @@ mysqld_get_one_option(int optid, test_flags|=TEST_NO_STACKTRACE; break; case (int) OPT_SKIP_SYMLINKS: + WARN_DEPRECATED(NULL, VER_CELOSIA, "--skip-symlink", "--skip-symbolic-links"); my_use_symdir=0; break; case (int) OPT_BIND_ADDRESS: @@ -8266,6 +8288,9 @@ mysqld_get_one_option(int optid, server_id_supplied = 1; break; case OPT_DELAY_KEY_WRITE_ALL: + WARN_DEPRECATED(NULL, VER_CELOSIA, + "--delay-key-write-for-all-tables", + "--delay-key-write=ALL"); if (argument != disabled_my_option) argument= (char*) "ALL"; /* Fall through */ @@ -8281,6 +8306,11 @@ mysqld_get_one_option(int optid, delay_key_write_options= (uint) type-1; } break; + case OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE: + sql_print_warning("--myisam_max_extra_sort_file_size is deprecated and " + "does nothing in this version. It will be removed in " + "a future release."); + break; case OPT_CHARSETS_DIR: strmake(mysql_charsets_dir, argument, sizeof(mysql_charsets_dir)-1); charsets_dir = mysql_charsets_dir; From 29cd733fce232d84758b262121a5dd9b9c0031a6 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Wed, 27 Jan 2010 15:20:03 +0200 Subject: [PATCH 295/344] bug#47142 improving comments --- sql/log_event.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/log_event.h b/sql/log_event.h index 10b374199de..3b62c6aab76 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -820,7 +820,8 @@ public: thread writes the relay log, it augments the Query_log_event with a Q_MASTER_DATA_WRITTEN_CODE status_var that holds the original event length. This field is initialized to non-zero in the SQL thread when - it reads this augmented event. + it reads this augmented event. SQL thread does not write + Q_MASTER_DATA_WRITTEN_CODE to the slave's server binlog. */ uint32 master_data_written; From b13ed2975d2c7be450596b429020b0b91af1dbf9 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Wed, 27 Jan 2010 15:21:41 +0100 Subject: [PATCH 296/344] Bug #49210 Enable MTR timeout configuration through environment variables Define env. vars for both timeout settings This patch is for 5.0 (mtr v1) and should replaces for 5.1 up --- mysql-test/mysql-test-run.pl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index e98e05eadb1..01094f40956 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1077,13 +1077,15 @@ sub command_line_setup () { if ( ! $opt_testcase_timeout ) { - $opt_testcase_timeout= $default_testcase_timeout; + $opt_testcase_timeout= + $ENV{MTR_TESTCASE_TIMEOUT} || $default_testcase_timeout; $opt_testcase_timeout*= 10 if $opt_valgrind; } if ( ! $opt_suite_timeout ) { - $opt_suite_timeout= $default_suite_timeout; + $opt_suite_timeout= + $ENV{MTR_SUITE_TIMEOUT} || $default_suite_timeout; $opt_suite_timeout*= 6 if $opt_valgrind; } From 18761a9223f80e95356dd0a62b09a5586414d054 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Wed, 27 Jan 2010 16:13:39 +0100 Subject: [PATCH 297/344] Bug #49223 Change help description for mysqldump --extended-insert Help message changed to the same as in the 5.1 online documentation. --- client/mysqldump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 8a50c57201c..40e3e75cca2 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -268,7 +268,7 @@ static struct my_option my_long_options[] = (uchar**) &opt_events, (uchar**) &opt_events, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"extended-insert", 'e', - "Allows utilization of the new, much faster INSERT syntax.", + "Use multiple-row INSERT syntax that include several VALUES lists.", (uchar**) &extended_insert, (uchar**) &extended_insert, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"fields-terminated-by", OPT_FTB, From 7c8983e99e459f86f9626e6e26828f6dfaa1814d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Jan 2010 18:41:05 +0100 Subject: [PATCH 298/344] Fix test failures due to previous change of not setting TZ by default. Fix by explicitly setting timezone for a few more tests that need it. (We avoid setting TZ everywhere by default as this breaks some tests on windows). Also add fix of two other windows failures due to non-portable suppressions, thanks to Alex Budovski. mysql-test/mysql-test-run.pl: Don't let --timezone option from one test stray into the next test (mostly to make results more deterministic rather than depend on whatever test happens to run just before). mysql-test/suite/maria/r/maria-recover.result: Fix suppression pattern to also work with Windows \ path separator. mysql-test/suite/maria/t/maria-recover.test: Fix suppression pattern to also work with Windows \ path separator. mysql-test/suite/parts/inc/partition_timestamp.inc: Set timezone explicitly for test that needs it. mysql-test/suite/parts/r/partition_recover_myisam.result: Fix suppression pattern to also work with Windows \ path separator. mysql-test/suite/parts/t/partition_recover_myisam.test: Fix suppression pattern to also work with Windows \ path separator. mysql-test/t/mysqlbinlog_row-master.opt: Set timezone explicitly for test that needs it. mysql-test/t/mysqlbinlog_row_innodb-master.opt: Set timezone explicitly for test that needs it. mysql-test/t/mysqlbinlog_row_myisam-master.opt: Set timezone explicitly for test that needs it. mysql-test/t/mysqlbinlog_row_trans-master.opt: Set timezone explicitly for test that needs it. --- mysql-test/mysql-test-run.pl | 2 ++ mysql-test/suite/maria/r/maria-recover.result | 3 --- mysql-test/suite/maria/t/maria-recover.test | 10 +++++++--- mysql-test/suite/parts/inc/partition_timestamp.inc | 1 + .../suite/parts/r/partition_recover_myisam.result | 2 -- mysql-test/suite/parts/t/partition_recover_myisam.test | 4 +++- mysql-test/t/mysqlbinlog_row-master.opt | 1 + mysql-test/t/mysqlbinlog_row_innodb-master.opt | 1 + mysql-test/t/mysqlbinlog_row_myisam-master.opt | 1 + mysql-test/t/mysqlbinlog_row_trans-master.opt | 1 + 10 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 mysql-test/t/mysqlbinlog_row-master.opt create mode 100644 mysql-test/t/mysqlbinlog_row_innodb-master.opt create mode 100644 mysql-test/t/mysqlbinlog_row_myisam-master.opt create mode 100644 mysql-test/t/mysqlbinlog_row_trans-master.opt diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index bc2061a506c..ecdd57c83e5 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3457,6 +3457,8 @@ sub run_testcase ($$) { my $timezone= timezone($tinfo); if ($timezone ne 'DEFAULT') { $ENV{'TZ'}= $timezone; + } else { + delete($ENV{'TZ'}); } mtr_verbose("Setting timezone: $timezone"); diff --git a/mysql-test/suite/maria/r/maria-recover.result b/mysql-test/suite/maria/r/maria-recover.result index b4f5c21b26b..aee4119304f 100644 --- a/mysql-test/suite/maria/r/maria-recover.result +++ b/mysql-test/suite/maria/r/maria-recover.result @@ -1,6 +1,3 @@ -call mtr.add_suppression("Checking table: '.\/mysqltest\/t_corrupted2'"); -call mtr.add_suppression("Recovering table: '.\/mysqltest\/t_corrupted2'"); -call mtr.add_suppression("Table '.\/mysqltest\/t_corrupted2' is marked as crashed and should be repaired"); select @@global.maria_recover; @@global.maria_recover BACKUP diff --git a/mysql-test/suite/maria/t/maria-recover.test b/mysql-test/suite/maria/t/maria-recover.test index e73cfa67bf0..e9ae0933d4c 100644 --- a/mysql-test/suite/maria/t/maria-recover.test +++ b/mysql-test/suite/maria/t/maria-recover.test @@ -2,9 +2,13 @@ --source include/have_maria.inc -call mtr.add_suppression("Checking table: '.\/mysqltest\/t_corrupted2'"); -call mtr.add_suppression("Recovering table: '.\/mysqltest\/t_corrupted2'"); -call mtr.add_suppression("Table '.\/mysqltest\/t_corrupted2' is marked as crashed and should be repaired"); +--disable_query_log +# Note: \\. matches a single period. We use '.' as directory separator to +# account for Unix and Windows variation. +call mtr.add_suppression("Checking table: '\\..mysqltest.t_corrupted2'"); +call mtr.add_suppression("Recovering table: '\\..mysqltest.t_corrupted2'"); +call mtr.add_suppression("Table '\\..mysqltest.t_corrupted2' is marked as crashed and should be repaired"); +--enable_query_log # Note: we're setting an environment variable (not prefixing it by $), # so that the perl code below can access it. diff --git a/mysql-test/suite/parts/inc/partition_timestamp.inc b/mysql-test/suite/parts/inc/partition_timestamp.inc index 4ec42471de9..13a570c8760 100644 --- a/mysql-test/suite/parts/inc/partition_timestamp.inc +++ b/mysql-test/suite/parts/inc/partition_timestamp.inc @@ -48,6 +48,7 @@ show create table t3; let $count=12; --echo $count inserts; --disable_query_log +SET TIME_ZONE= '+03:00'; begin; while ($count) { diff --git a/mysql-test/suite/parts/r/partition_recover_myisam.result b/mysql-test/suite/parts/r/partition_recover_myisam.result index 49775ee498e..df737ec2853 100644 --- a/mysql-test/suite/parts/r/partition_recover_myisam.result +++ b/mysql-test/suite/parts/r/partition_recover_myisam.result @@ -1,5 +1,3 @@ -call mtr.add_suppression("./test/t1_will_crash"); -call mtr.add_suppression("Got an error from unknown thread, ha_myisam.cc"); CREATE TABLE t1_will_crash (a INT, KEY (a)) ENGINE=MyISAM; INSERT INTO t1_will_crash VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11); FLUSH TABLES; diff --git a/mysql-test/suite/parts/t/partition_recover_myisam.test b/mysql-test/suite/parts/t/partition_recover_myisam.test index fe8a51b17cc..c96cd938f8b 100644 --- a/mysql-test/suite/parts/t/partition_recover_myisam.test +++ b/mysql-test/suite/parts/t/partition_recover_myisam.test @@ -1,7 +1,9 @@ # test the auto-recover (--myisam-recover) of partitioned myisam tables -call mtr.add_suppression("./test/t1_will_crash"); +--disable_query_log +call mtr.add_suppression("..test.t1_will_crash"); call mtr.add_suppression("Got an error from unknown thread, ha_myisam.cc"); +--enable_query_log --source include/have_partition.inc --disable_warnings diff --git a/mysql-test/t/mysqlbinlog_row-master.opt b/mysql-test/t/mysqlbinlog_row-master.opt new file mode 100644 index 00000000000..4d69f3359db --- /dev/null +++ b/mysql-test/t/mysqlbinlog_row-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 diff --git a/mysql-test/t/mysqlbinlog_row_innodb-master.opt b/mysql-test/t/mysqlbinlog_row_innodb-master.opt new file mode 100644 index 00000000000..4d69f3359db --- /dev/null +++ b/mysql-test/t/mysqlbinlog_row_innodb-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 diff --git a/mysql-test/t/mysqlbinlog_row_myisam-master.opt b/mysql-test/t/mysqlbinlog_row_myisam-master.opt new file mode 100644 index 00000000000..4d69f3359db --- /dev/null +++ b/mysql-test/t/mysqlbinlog_row_myisam-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 diff --git a/mysql-test/t/mysqlbinlog_row_trans-master.opt b/mysql-test/t/mysqlbinlog_row_trans-master.opt new file mode 100644 index 00000000000..4d69f3359db --- /dev/null +++ b/mysql-test/t/mysqlbinlog_row_trans-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 From e2efd9338574c87177e0c00273e6e49a32ce2aa6 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 27 Jan 2010 23:53:08 +0200 Subject: [PATCH 299/344] Fixed some compiler warnings and errors in test suite found by buildbot include/ft_global.h: Changed string size to 'size_t' (to avoid compiler warnings later) include/maria.h: Changed string size to 'size_t' (to avoid compiler warnings later) mysql-test/r/show_check.result: Don't use logging to tables, as there is no guarantee in which order tables are showed in 'show open tables' mysql-test/suite/rpl/t/rpl_rotate_logs.test: Use HIGH_PRIORITY inserts to avoid problem with concurrent inserts on the slave. mysql-test/t/show_check-master.opt: Don't use logging to tables, as there is no guarantee in which order tables are showed in 'show open tables' sql/item.cc: Fixed compiler warning storage/maria/ft_maria.c: Changed string size to 'size_t' (to avoid compiler warnings later) storage/myisam/ft_boolean_search.c: Fixed compiler warnings storage/myisam/ft_myisam.c: Changed string size to 'size_t' (to avoid compiler warnings later) storage/myisam/ft_nlq_search.c: Changed string size to 'size_t' (to avoid compiler warnings later) storage/myisam/ft_parser.c: Changed string size to 'size_t' (to avoid compiler warnings) storage/myisam/ft_stopwords.c: Changed string size to 'size_t' (to avoid compiler warnings) storage/myisam/ftdefs.h: Changed string size to 'size_t' (to avoid compiler warnings) --- include/ft_global.h | 3 ++- include/maria.h | 2 +- mysql-test/r/show_check.result | 2 -- mysql-test/suite/rpl/t/rpl_rotate_logs.test | 2 +- mysql-test/t/show_check-master.opt | 2 +- sql/item.cc | 2 +- storage/maria/ft_maria.c | 4 ++-- storage/myisam/ft_boolean_search.c | 9 +++++---- storage/myisam/ft_myisam.c | 4 ++-- storage/myisam/ft_nlq_search.c | 3 ++- storage/myisam/ft_parser.c | 2 +- storage/myisam/ft_stopwords.c | 2 +- storage/myisam/ftdefs.h | 10 ++++++---- 13 files changed, 25 insertions(+), 22 deletions(-) diff --git a/include/ft_global.h b/include/ft_global.h index 8fe5ee5c42e..4a4cf84b119 100644 --- a/include/ft_global.h +++ b/include/ft_global.h @@ -62,7 +62,8 @@ void ft_free_stopwords(void); #define FT_SORTED 2 #define FT_EXPAND 4 /* query expansion */ -FT_INFO *ft_init_search(uint,void *, uint, uchar *, uint,CHARSET_INFO *, uchar *); +FT_INFO *ft_init_search(uint,void *, uint, uchar *, size_t, + CHARSET_INFO *, uchar *); my_bool ft_boolean_check_syntax_string(const uchar *); /* Internal symbols for fulltext between maria and MyISAM */ diff --git a/include/maria.h b/include/maria.h index 3c2fc08d9a8..c961b7d1672 100644 --- a/include/maria.h +++ b/include/maria.h @@ -462,7 +462,7 @@ void maria_versioning(MARIA_HA *info, my_bool versioning); void maria_ignore_trids(MARIA_HA *info); /* fulltext functions */ -FT_INFO *maria_ft_init_search(uint,void *, uint, uchar *, uint, +FT_INFO *maria_ft_init_search(uint,void *, uint, uchar *, size_t, CHARSET_INFO *, uchar *); /* 'Almost-internal' Maria functions */ diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index ec0a70ff581..7a70e439841 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -252,13 +252,11 @@ drop table t1; flush tables; show open tables; Database Table In_use Name_locked -mysql general_log 0 0 create table t1(n int); insert into t1 values (1); show open tables; Database Table In_use Name_locked test t1 0 0 -mysql general_log 0 0 drop table t1; create table t1 (a int not null, b VARCHAR(10), INDEX (b) ) AVG_ROW_LENGTH=10 CHECKSUM=1 COMMENT="test" ENGINE=MYISAM MIN_ROWS=10 MAX_ROWS=100 PACK_KEYS=1 DELAY_KEY_WRITE=1 ROW_FORMAT=fixed; show create table t1; diff --git a/mysql-test/suite/rpl/t/rpl_rotate_logs.test b/mysql-test/suite/rpl/t/rpl_rotate_logs.test index e06099fd707..f67c880bf26 100644 --- a/mysql-test/suite/rpl/t/rpl_rotate_logs.test +++ b/mysql-test/suite/rpl/t/rpl_rotate_logs.test @@ -153,7 +153,7 @@ disable_query_log; while ($1) { #eval means expand $ expressions - eval insert into t3 values($1 + 4); + eval insert HIGH_PRIORITY into t3 values($1 + 4); dec $1; } enable_query_log; diff --git a/mysql-test/t/show_check-master.opt b/mysql-test/t/show_check-master.opt index 6fd0fec0e08..333b1d559e3 100644 --- a/mysql-test/t/show_check-master.opt +++ b/mysql-test/t/show_check-master.opt @@ -1 +1 @@ ---log-output=table --slow-query-log --log-long-format --log-queries-not-using-indexes --myisam-recover="" --general-log --general-log-file="" --slow-query-log-file="" +--log-output=file --slow-query-log --log-long-format --log-queries-not-using-indexes --myisam-recover="" --general-log --general-log-file="foo" --slow-query-log-file="" diff --git a/sql/item.cc b/sql/item.cc index 485f98cbc79..b8215ffe2d1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7119,7 +7119,7 @@ double Item_cache_decimal::val_real() DBUG_ASSERT(fixed); double res; if (!value_cached && !cache_value()) - return NULL; + return 0.0; my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res); return res; } diff --git a/storage/maria/ft_maria.c b/storage/maria/ft_maria.c index 1b082f904d0..b1b24592593 100644 --- a/storage/maria/ft_maria.c +++ b/storage/maria/ft_maria.c @@ -22,8 +22,8 @@ #include "ma_ftdefs.h" FT_INFO *maria_ft_init_search(uint flags, void *info, uint keynr, - uchar *query, uint query_len, CHARSET_INFO *cs, - uchar *record) + uchar *query, size_t query_len, + CHARSET_INFO *cs, uchar *record) { FT_INFO *res; if (flags & FT_BOOL) diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 5df88a230a9..ae494cda385 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -299,7 +299,7 @@ static int ftb_parse_query_internal(MYSQL_FTPARSER_PARAM *param, } -static int _ftb_parse_query(FTB *ftb, uchar *query, uint len, +static int _ftb_parse_query(FTB *ftb, uchar *query, mysql_ft_size_t len, struct st_mysql_ftparser *parser) { MYSQL_FTPARSER_PARAM *param; @@ -540,7 +540,7 @@ static void _ftb_init_index_search(FT_INFO *ftb) FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, uchar *query, - uint query_len, CHARSET_INFO *cs) + mysql_ft_size_t query_len, CHARSET_INFO *cs) { FTB *ftb; FTB_EXPR *ftbe; @@ -679,8 +679,9 @@ static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param, -1 is returned if error occurs. */ -static int _ftb_check_phrase(FTB *ftb, const uchar *document, uint len, - FTB_EXPR *ftbe, struct st_mysql_ftparser *parser) +static int _ftb_check_phrase(FTB *ftb, const uchar *document, + mysql_ft_size_t len, + FTB_EXPR *ftbe, struct st_mysql_ftparser *parser) { MY_FTB_PHRASE_PARAM ftb_param; MYSQL_FTPARSER_PARAM *param; diff --git a/storage/myisam/ft_myisam.c b/storage/myisam/ft_myisam.c index bef3fbfd5f5..7bcc62d5bf5 100644 --- a/storage/myisam/ft_myisam.c +++ b/storage/myisam/ft_myisam.c @@ -23,8 +23,8 @@ #include "ftdefs.h" FT_INFO *ft_init_search(uint flags, void *info, uint keynr, - uchar *query, uint query_len, CHARSET_INFO *cs, - uchar *record) + uchar *query, size_t query_len, + CHARSET_INFO *cs, uchar *record) { FT_INFO *res; if (flags & FT_BOOL) diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index c4d27bcbd8e..90ad2d635b7 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -204,7 +204,8 @@ static int FT_DOC_cmp(void *unused __attribute__((unused)), FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, uchar *query, - uint query_len, uint flags, uchar *record) + mysql_ft_size_t query_len, uint flags, + uchar *record) { TREE wtree; ALL_IN_ONE aio; diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c index e4d500f6d8a..f585038f0b8 100644 --- a/storage/myisam/ft_parser.c +++ b/storage/myisam/ft_parser.c @@ -304,7 +304,7 @@ static int ft_parse_internal(MYSQL_FTPARSER_PARAM *param, } -int ft_parse(TREE *wtree, const uchar *doc, int doclen, +int ft_parse(TREE *wtree, const uchar *doc, mysql_ft_size_t doclen, struct st_mysql_ftparser *parser, MYSQL_FTPARSER_PARAM *param, MEM_ROOT *mem_root) { diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c index db4cd3b32b6..9544c577c70 100644 --- a/storage/myisam/ft_stopwords.c +++ b/storage/myisam/ft_stopwords.c @@ -21,7 +21,7 @@ typedef struct st_ft_stopwords { const char * pos; - uint len; + size_t len; } FT_STOPWORD; static TREE *stopwords3=NULL; diff --git a/storage/myisam/ftdefs.h b/storage/myisam/ftdefs.h index 2b4c46c78ad..b26fa523b42 100644 --- a/storage/myisam/ftdefs.h +++ b/storage/myisam/ftdefs.h @@ -97,8 +97,8 @@ typedef struct st_ft_word { const uchar *pos; - uint len; double weight; + size_t len; } FT_WORD; int is_stopword(const uchar *word, size_t len); @@ -111,7 +111,8 @@ uchar ft_simple_get_word(CHARSET_INFO *, const uchar **, const uchar *, FT_WORD *, my_bool); typedef struct _st_ft_seg_iterator { - uint num, len; + uint num; + mysql_ft_size_t len; HA_KEYSEG *seg; const uchar *rec, *pos; } FT_SEG_ITERATOR; @@ -128,8 +129,9 @@ FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, const uchar *, MEM_ROOT *); uint _mi_ft_parse(TREE *, MI_INFO *, uint, const uchar *, MYSQL_FTPARSER_PARAM *, MEM_ROOT *); -FT_INFO *ft_init_nlq_search(MI_INFO *, uint, uchar *, uint, uint, uchar *); -FT_INFO *ft_init_boolean_search(MI_INFO *, uint, uchar *, uint, CHARSET_INFO *); +FT_INFO *ft_init_nlq_search(MI_INFO *, uint, uchar *, mysql_ft_size_t, uint, + uchar *); +FT_INFO *ft_init_boolean_search(MI_INFO *, uint, uchar *, mysql_ft_size_t, CHARSET_INFO *); extern const struct _ft_vft _ft_vft_nlq; int ft_nlq_read_next(FT_INFO *, char *); From c3a73a8f6d674de1e9efcb498f3343db802d6a6c Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 28 Jan 2010 19:51:40 -0200 Subject: [PATCH 300/344] Fix for compiler warnings: Rename method as to not hide a base. Reorder attributes initialization. Remove unused variable. Rework code to silence a warning due to assignment used as truth value. sql/item_strfunc.cc: Rename method as to not hide a base. sql/item_strfunc.h: Rename method as to not hide a base. sql/log_event.cc: Reorder attributes initialization. sql/rpl_injector.cc: Rework code to silence a warning due to assignment used as truth value. sql/rpl_record.cc: Remove unused variable. sql/sql_db.cc: Rework code to silence a warning due to assignment used as truth value. sql/sql_parse.cc: Rework code to silence a warning due to assignment used as truth value. sql/sql_table.cc: Rework code to silence a warning due to assignment used as truth value. --- sql/item_strfunc.cc | 6 +++--- sql/item_strfunc.h | 4 ++-- sql/log_event.cc | 4 ++-- sql/rpl_injector.cc | 12 ++++++------ sql/rpl_record.cc | 1 - sql/sql_db.cc | 2 +- sql/sql_parse.cc | 2 +- sql/sql_table.cc | 2 +- 8 files changed, 16 insertions(+), 17 deletions(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 4cdeeef6c78..66308215d0b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1765,19 +1765,19 @@ String *Item_func_encode::val_str(String *str) null_value= 0; res= copy_if_not_alloced(str, res, res->length()); - transform(res); + crypto_transform(res); sql_crypt.reinit(); return res; } -void Item_func_encode::transform(String *res) +void Item_func_encode::crypto_transform(String *res) { sql_crypt.encode((char*) res->ptr(),res->length()); res->set_charset(&my_charset_bin); } -void Item_func_decode::transform(String *res) +void Item_func_decode::crypto_transform(String *res) { sql_crypt.decode((char*) res->ptr(),res->length()); } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 59241872e63..5799c768162 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -363,7 +363,7 @@ public: void fix_length_and_dec(); const char *func_name() const { return "encode"; } protected: - virtual void transform(String *); + virtual void crypto_transform(String *); private: /** Provide a seed for the PRNG sequence. */ bool seed(); @@ -376,7 +376,7 @@ public: Item_func_decode(Item *a, Item *seed): Item_func_encode(a, seed) {} const char *func_name() const { return "decode"; } protected: - void transform(String *); + void crypto_transform(String *); }; diff --git a/sql/log_event.cc b/sql/log_event.cc index f03f0fa930a..2da825e63ce 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2386,8 +2386,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, auto_increment_offset(thd_arg->variables.auto_increment_offset), lc_time_names_number(thd_arg->variables.lc_time_names->number), charset_database_number(0), - master_data_written(0), - table_map_for_update((ulonglong)thd_arg->table_map_for_update) + table_map_for_update((ulonglong)thd_arg->table_map_for_update), + master_data_written(0) { time_t end_time; diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc index 666622dbac4..43f4e7d849d 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -114,8 +114,8 @@ int injector::transaction::write_row (server_id_type sid, table tbl, { DBUG_ENTER("injector::transaction::write_row(...)"); - int error= 0; - if (error= check_state(ROW_STATE)) + int error= check_state(ROW_STATE); + if (error) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; @@ -133,8 +133,8 @@ int injector::transaction::delete_row(server_id_type sid, table tbl, { DBUG_ENTER("injector::transaction::delete_row(...)"); - int error= 0; - if (error= check_state(ROW_STATE)) + int error= check_state(ROW_STATE); + if (error) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; @@ -152,8 +152,8 @@ int injector::transaction::update_row(server_id_type sid, table tbl, { DBUG_ENTER("injector::transaction::update_row(...)"); - int error= 0; - if (error= check_state(ROW_STATE)) + int error= check_state(ROW_STATE); + if (error) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 1a48d0e3b0e..3a46bbcd6ee 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -382,7 +382,6 @@ int prepare_record(TABLE *const table, */ for (Field **field_ptr= table->field+skip; *field_ptr; ++field_ptr) { - uint32 const mask= NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG; Field *const f= *field_ptr; if ((f->flags & NO_DEFAULT_VALUE_FLAG) && (f->real_type() != MYSQL_TYPE_ENUM)) diff --git a/sql/sql_db.cc b/sql/sql_db.cc index d5d9830f63d..0e65f97e10b 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -828,7 +828,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) qinfo.db_len = strlen(db); /* These DDL methods and logging protected with LOCK_mysql_create_db */ - if (error= mysql_bin_log.write(&qinfo)) + if ((error= mysql_bin_log.write(&qinfo))) goto exit; } my_ok(thd, result); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a114d92b124..2dd71b2214a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3988,7 +3988,7 @@ end_with_restore_list: */ if (!lex->no_write_to_binlog && write_to_binlog) { - if (res= write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + if ((res= write_bin_log(thd, FALSE, thd->query(), thd->query_length()))) break; } my_ok(thd); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f5df8481dc4..301ab6ceda6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6561,7 +6561,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, thd->clear_error(); Query_log_event qinfo(thd, thd->query(), thd->query_length(), 0, FALSE, 0); - if (error= mysql_bin_log.write(&qinfo)) + if ((error= mysql_bin_log.write(&qinfo))) goto view_err_unlock; } my_ok(thd); From 443003a467ab11b2d34e8d67658338659348325b Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 29 Jan 2010 11:36:28 +0200 Subject: [PATCH 301/344] Bug #49552 : sql_buffer_result cause crash + not found records in multitable delete/subquery SQL_BUFFER_RESULT should not have an effect on non-SELECT statements according to our documentation. Fixed by not passing it through to multi-table DELETE (similarly to how it's done for multi-table UPDATE). --- mysql-test/r/delete.result | 13 +++++++++++++ mysql-test/t/delete.test | 19 ++++++++++++++++++- sql/sql_parse.cc | 4 ++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index 1df19a75854..58278492985 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -337,3 +337,16 @@ END | DELETE IGNORE FROM t1; ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. DROP TABLE t1; +# +# Bug #49552 : sql_buffer_result cause crash + not found records +# in multitable delete/subquery +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SET SESSION SQL_BUFFER_RESULT=1; +DELETE t1 FROM (SELECT SUM(a) a FROM t1) x,t1; +SET SESSION SQL_BUFFER_RESULT=DEFAULT; +SELECT * FROM t1; +a +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index a5dff38c078..2f51fafd6a6 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -357,4 +357,21 @@ END | --error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG DELETE IGNORE FROM t1; -DROP TABLE t1; \ No newline at end of file +DROP TABLE t1; + + +--echo # +--echo # Bug #49552 : sql_buffer_result cause crash + not found records +--echo # in multitable delete/subquery +--echo # + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SET SESSION SQL_BUFFER_RESULT=1; +DELETE t1 FROM (SELECT SUM(a) a FROM t1) x,t1; + +SET SESSION SQL_BUFFER_RESULT=DEFAULT; +SELECT * FROM t1; +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2dd71b2214a..df2c1854914 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3352,9 +3352,9 @@ end_with_restore_list: select_lex->where, 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL, (ORDER *)NULL, - select_lex->options | thd->options | + (select_lex->options | thd->options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | - OPTION_SETUP_TABLES_DONE, + OPTION_SETUP_TABLES_DONE) & ~OPTION_BUFFER_RESULT, del_result, unit, select_lex); res|= thd->is_error(); if (res) From 181f753e8b12c58645495622ad32b5e709120361 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Thu, 28 Jan 2010 12:10:57 +0100 Subject: [PATCH 302/344] Bug #50271: Debug output of JOIN structures is garbled sql/sql_test.cc: Assemble results of all the calls to full_name() first, in order not to garble the tabular output. --- sql/sql_test.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/sql/sql_test.cc b/sql/sql_test.cc index eeb9a21b6f5..5de8301fd05 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -168,6 +168,21 @@ TEST_join(JOIN *join) uint i,ref; DBUG_ENTER("TEST_join"); + /* + Assemble results of all the calls to full_name() first, + in order not to garble the tabular output below. + */ + String ref_key_parts[MAX_TABLES]; + for (i= 0; i < join->tables; i++) + { + JOIN_TAB *tab= join->join_tab + i; + for (ref= 0; ref < tab->ref.key_parts; ref++) + { + ref_key_parts[i].append(tab->ref.items[ref]->full_name()); + ref_key_parts[i].append(" "); + } + } + DBUG_LOCK_FILE; VOID(fputs("\nInfo about JOIN\n",DBUG_FILE)); for (i=0 ; i < join->tables ; i++) @@ -199,13 +214,8 @@ TEST_join(JOIN *join) } if (tab->ref.key_parts) { - VOID(fputs(" refs: ",DBUG_FILE)); - for (ref=0 ; ref < tab->ref.key_parts ; ref++) - { - Item *item=tab->ref.items[ref]; - fprintf(DBUG_FILE,"%s ", item->full_name()); - } - VOID(fputc('\n',DBUG_FILE)); + fprintf(DBUG_FILE, + " refs: %s\n", ref_key_parts[i].ptr()); } } DBUG_UNLOCK_FILE; From a0417475678013914fb91c44be279b4107e3ffdb Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Thu, 28 Jan 2010 16:49:14 +0200 Subject: [PATCH 303/344] Fixed compiler warnings & failing test cases When compiling with debug, don't clear buffer in 'net_clear()' - This allows us to easier find bugs in the protocol and also get repeatable test failures in test cases where someone forgot to do --reap client/mysqltest.cc: Fixed compiler warning mysql-test/t/partition_innodb_semi_consistent.test: Added missing --reap (fixes random failure) sql/net_serv.cc: When compiling with debug, don't clear buffer in 'net_clear()' - This allows us to easier find bugs in the protocol and also get repeatable test failures in test cases where someone forgot to do --reap storage/myisam/ft_boolean_search.c: Fixed compiler warnings storage/myisam/ft_parser.c: Fixed compiler warnings storage/myisam/ft_stopwords.c: Fixed compiler warnings support-files/compiler_warnings.supp: Added a lot of new suppression of not relevant warnings and warnings in systems we are not in charge of unittest/mysys/waiting_threads-t.c: Fixed compiler warnings --- client/mysqltest.cc | 4 +++- mysql-test/t/partition_innodb_semi_consistent.test | 1 + sql/net_serv.cc | 7 ++++++- storage/myisam/ft_boolean_search.c | 6 +++--- storage/myisam/ft_parser.c | 6 +++--- storage/myisam/ft_stopwords.c | 8 ++++---- support-files/compiler_warnings.supp | 10 ++++++++++ unittest/mysys/waiting_threads-t.c | 2 +- 8 files changed, 31 insertions(+), 13 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index bc5c4ed76b8..891dd72edfa 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -657,7 +657,9 @@ public: } while ((bytes= fread(buf, 1, sizeof(buf), m_file)) > 0) - fwrite(buf, 1, bytes, stderr); + if (fwrite(buf, 1, bytes, stderr)) + die("Failed to write to '%s', errno: %d", + m_file_name, errno); if (!lines) { diff --git a/mysql-test/t/partition_innodb_semi_consistent.test b/mysql-test/t/partition_innodb_semi_consistent.test index 6a6a7cf958e..5eda2f142c6 100644 --- a/mysql-test/t/partition_innodb_semi_consistent.test +++ b/mysql-test/t/partition_innodb_semi_consistent.test @@ -187,6 +187,7 @@ SELECT * FROM t1; --echo # Switch to connection con2 connection con2; +--reap SELECT * FROM t1; connection default; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 73892f31ccf..f987067b9b3 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -286,7 +286,12 @@ void net_clear(NET *net, my_bool clear_buffer) #endif DBUG_ENTER("net_clear"); -#if !defined(EMBEDDED_LIBRARY) +/* + We don't do a clear in case of DBUG_OFF to catch bugs + in the protocol handling +*/ + +#if !defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF) if (clear_buffer) { while ((ready= net_data_is_ready(net->vio->sd)) > 0) diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index ae494cda385..3cc47576827 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -321,7 +321,7 @@ static int _ftb_parse_query(FTB *ftb, uchar *query, mysql_ft_size_t len, param->mysql_add_word= ftb_query_add_word; param->mysql_ftparam= (void *)&ftb_param; param->cs= ftb->charset; - param->doc= (char*) query; + param->doc= query; param->length= len; param->flags= 0; param->mode= MYSQL_FTPARSER_FULL_BOOLEAN_INFO; @@ -702,7 +702,7 @@ static int _ftb_check_phrase(FTB *ftb, const uchar *document, param->mysql_add_word= ftb_phrase_add_word; param->mysql_ftparam= (void *)&ftb_param; param->cs= ftb->charset; - param->doc= (char *) document; + param->doc= document; param->length= len; param->flags= 0; param->mode= MYSQL_FTPARSER_WITH_STOPWORDS; @@ -1000,7 +1000,7 @@ float ft_boolean_find_relevance(FT_INFO *ftb, uchar *record, uint length) { if (!ftsi.pos) continue; - param->doc= (char *)ftsi.pos; + param->doc= ftsi.pos; param->length= ftsi.len; if (unlikely(parser->parse(param))) return 0; diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c index f585038f0b8..3c3efbf0906 100644 --- a/storage/myisam/ft_parser.c +++ b/storage/myisam/ft_parser.c @@ -175,7 +175,7 @@ uchar ft_get_word(CHARSET_INFO *cs, const uchar **start, const uchar *end, if ((param->trunc=(doc= ft_min_word_len && !is_stopword((char*) word->pos, + if (((length >= ft_min_word_len && !is_stopword(word->pos, word->len)) || param->trunc) && length < ft_max_word_len) { @@ -298,7 +298,7 @@ static int ft_parse_internal(MYSQL_FTPARSER_PARAM *param, DBUG_ENTER("ft_parse_internal"); while (ft_simple_get_word(wtree->custom_arg, &doc, end, &w, TRUE)) - if (param->mysql_add_word(param, (char*) w.pos, w.len, 0)) + if (param->mysql_add_word(param, w.pos, w.len, 0)) DBUG_RETURN(1); DBUG_RETURN(0); } @@ -319,7 +319,7 @@ int ft_parse(TREE *wtree, const uchar *doc, mysql_ft_size_t doclen, param->mysql_add_word= ft_add_word; param->mysql_ftparam= &my_param; param->cs= wtree->custom_arg; - param->doc= (char*) doc; + param->doc= doc; param->length= doclen; param->mode= MYSQL_FTPARSER_SIMPLE_MODE; DBUG_RETURN(parser->parse(param)); diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c index 9544c577c70..5e550b9dff5 100644 --- a/storage/myisam/ft_stopwords.c +++ b/storage/myisam/ft_stopwords.c @@ -20,7 +20,7 @@ typedef struct st_ft_stopwords { - const char * pos; + const uchar* pos; size_t len; } FT_STOPWORD; @@ -30,15 +30,15 @@ static int FT_STOPWORD_cmp(void* cmp_arg __attribute__((unused)), FT_STOPWORD *w1, FT_STOPWORD *w2) { return ha_compare_text(default_charset_info, - (uchar *)w1->pos,w1->len, - (uchar *)w2->pos,w2->len,0,0); + w1->pos, w1->len, + w2->pos, w2->len, 0, 0); } static void FT_STOPWORD_free(FT_STOPWORD *w, TREE_FREE action, void *arg __attribute__((unused))) { if (action == free_free) - my_free((uchar*) w->pos, MYF(0)); + my_free((void*) w->pos, MYF(0)); } static int ft_add_stopword(const char *w) diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index 9fef92a5f5e..7911d91928b 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -4,6 +4,7 @@ # integer.cpp: .*control reaches end of non-void function.*: 1288-1427 +integer.cpp: .*no return statement in function returning non-void.*: 1288-1427 DictTabInfo.cpp : .*invalid access to non-static.* DictTabInfo.cpp : .*macro was used incorrectly.* DbdihMain.cpp : .*unused variable.* : 6666-7013 @@ -27,13 +28,17 @@ _flex_tmp.c: .*not enough actual parameters for macro 'yywrap'.* pars0lex.l: .*conversion from 'ulint' to 'int', possible loss of data.* btr/btr0cur\.c: .*value computed is not used.*: 3175-3375 include/buf0buf\.ic: unused parameter ‘mtr’ +fil/fil0fil\.c: pointer targets in passing argument.*differ in signedness fil/fil0fil\.c: comparison between signed and unsigned : 3100-3199 fil/fil0fil\.c: unused parameter log/log0recv\.c: unused variable os/os0file\.c: unused parameter +os/os0file\.c: pointer targets in assignment differ in signedness handler/i_s\.cc: unused variable sync/sync0rw\.c: unused parameter sync/sync0sync\.c: unused parameter +sync/sync0sync\.c: unused variable +ut/ut0ut\.c: ignoring return value of # # bdb is not critical to keep up to date @@ -98,10 +103,15 @@ storage/maria/ma_pagecache.c: .*'info_check_pin' defined but not used # I think these are due to mix of C and C++. # storage/pbxt/ : typedef.*was ignored in this declaration +ha_pbxt\.cc : variable.*might be clobbered by.*longjmp # # Yassl include/runtime.hpp: .*pure_error.* +.*/extra/yassl/taocrypt/.*: comparison with string literal +.*/extra/yassl/taocrypt/src/blowfish\.cpp: array subscript is above array bounds +.*/extra/yassl/taocrypt/src/file\.cpp: ignoring return value +.*/extra/yassl/taocrypt/src/integer\.cpp: control reaches end of non-void function # # Groff warnings on OpenSUSE. diff --git a/unittest/mysys/waiting_threads-t.c b/unittest/mysys/waiting_threads-t.c index d6c8dc31025..79dee219efb 100644 --- a/unittest/mysys/waiting_threads-t.c +++ b/unittest/mysys/waiting_threads-t.c @@ -258,7 +258,7 @@ void do_tests() #define test_kill_strategy(X) \ diag("kill strategy: " #X); \ DBUG_EXECUTE("reset_file", \ - { rewind(DBUG_FILE); ftruncate(fileno(DBUG_FILE), 0); }); \ + { rewind(DBUG_FILE); (void) ftruncate(fileno(DBUG_FILE), 0); }); \ DBUG_PRINT("info", ("kill strategy: " #X)); \ kill_strategy=X; \ do_one_test(); From 44d2bf540d38c63b6e2b45b1d9c2a61b2fc41024 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Jan 2010 23:34:22 +0100 Subject: [PATCH 304/344] Add support in bintar build script for OpenSolaris. --- BUILD/util.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/BUILD/util.sh b/BUILD/util.sh index 63b42db1f83..c8559184013 100644 --- a/BUILD/util.sh +++ b/BUILD/util.sh @@ -16,6 +16,8 @@ # Setting cpu options. get_cpuopt () { + case "$(uname -o)" in + *Linux*) case "$(gcc -dumpmachine)" in x86_64-*) # gcc barfs on -march=... on x64 @@ -26,7 +28,13 @@ get_cpuopt () { CPUOPT="-m32 -march=i586 -mtune=generic" ;; esac - return 0 + ;; + *Solaris*) + # ToDo: handle 32-bit build? For now default to 64-bit. + CPUOPT="-D__sun -m64 -mtune=athlon64" + ;; + esac + return 0 } # Default to a parallel build, but only if AM_MAKEFLAGS is not set. From 172af3722ef34876f5e33bdf63c10d46573a2864 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 29 Jan 2010 13:17:57 +0400 Subject: [PATCH 305/344] Fix for bug#49897: crash in ptr_compare when char(0) NOT NULL column is used for ORDER BY Problem: filesort isn't meant for null length sort data (e.g. char(0)), that leads to a server crash. Fix: disregard sort order if sort data record length is 0 (nothing to sort). mysql-test/r/select.result: Fix for bug#49897: crash in ptr_compare when char(0) NOT NULL column is used for ORDER BY - test result. mysql-test/t/select.test: Fix for bug#49897: crash in ptr_compare when char(0) NOT NULL column is used for ORDER BY - test case. sql/filesort.cc: Fix for bug#49897: crash in ptr_compare when char(0) NOT NULL column is used for ORDER BY - assert added as filesort cannot handle null length sort data. sql/sql_select.cc: Fix for bug#49897: crash in ptr_compare when char(0) NOT NULL column is used for ORDER BY - don't sort null length data e.g. in case of ORDER BY CHAR(0). --- mysql-test/r/select.result | 64 ++++++++++++++++++++++++++++++++++++++ mysql-test/t/select.test | 40 ++++++++++++++++++++++++ sql/filesort.cc | 2 ++ sql/sql_select.cc | 13 ++++++++ 4 files changed, 119 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 1b2533eec89..c13df26b2ba 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4540,4 +4540,68 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE z system NULL NULL NULL NULL 1 Warnings: Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a` from `test`.`t1` `x` join `test`.`t1` `y` join `test`.`t1` `z` where 1 +DROP TABLE t1; +# +# Bug #49897: crash in ptr_compare when char(0) NOT NULL +# column is used for ORDER BY +# +SET @old_sort_buffer_size= @@session.sort_buffer_size; +SET @@sort_buffer_size= 40000; +CREATE TABLE t1(a CHAR(0) NOT NULL); +INSERT INTO t1 VALUES (0), (0), (0); +INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12; +INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12; +INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12; +EXPLAIN SELECT a FROM t1 ORDER BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 24492 +SELECT a FROM t1 ORDER BY a; +DROP TABLE t1; +CREATE TABLE t1(a CHAR(0) NOT NULL, b CHAR(0) NOT NULL, c int); +INSERT INTO t1 VALUES (0, 0, 0), (0, 0, 2), (0, 0, 1); +INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12; +INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12; +INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12; +EXPLAIN SELECT a FROM t1 ORDER BY a LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 24492 +SELECT a FROM t1 ORDER BY a LIMIT 5; +a + + + + + +EXPLAIN SELECT * FROM t1 ORDER BY a, b LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 24492 +SELECT * FROM t1 ORDER BY a, b LIMIT 5; +a b c + 0 + 2 + 1 + 0 + 2 +EXPLAIN SELECT * FROM t1 ORDER BY a, b, c LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 24492 Using filesort +SELECT * FROM t1 ORDER BY a, b, c LIMIT 5; +a b c + 0 + 0 + 0 + 0 + 0 +EXPLAIN SELECT * FROM t1 ORDER BY c, a LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 24492 Using filesort +SELECT * FROM t1 ORDER BY c, a LIMIT 5; +a b c + 0 + 0 + 0 + 0 + 0 +SET @@sort_buffer_size= @old_sort_buffer_size; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index eeabd2641d8..8ecadfc9dfb 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3844,6 +3844,46 @@ EXPLAIN EXTENDED SELECT x.a, y.a, z.a FROM t1 x JOIN t1 y ON x.a=y.a JOIN t1 z ON y.a=z.a WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00'; +DROP TABLE t1; +--echo # +--echo # Bug #49897: crash in ptr_compare when char(0) NOT NULL +--echo # column is used for ORDER BY +--echo # +SET @old_sort_buffer_size= @@session.sort_buffer_size; +SET @@sort_buffer_size= 40000; + +CREATE TABLE t1(a CHAR(0) NOT NULL); +--disable_warnings +INSERT INTO t1 VALUES (0), (0), (0); +--enable_warnings +INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12; +INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12; +INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12; +EXPLAIN SELECT a FROM t1 ORDER BY a; +--disable_result_log +SELECT a FROM t1 ORDER BY a; +--enable_result_log +DROP TABLE t1; + +CREATE TABLE t1(a CHAR(0) NOT NULL, b CHAR(0) NOT NULL, c int); +--disable_warnings +INSERT INTO t1 VALUES (0, 0, 0), (0, 0, 2), (0, 0, 1); +--enable_warnings +INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12; +INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12; +INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12; +EXPLAIN SELECT a FROM t1 ORDER BY a LIMIT 5; +SELECT a FROM t1 ORDER BY a LIMIT 5; +EXPLAIN SELECT * FROM t1 ORDER BY a, b LIMIT 5; +SELECT * FROM t1 ORDER BY a, b LIMIT 5; +EXPLAIN SELECT * FROM t1 ORDER BY a, b, c LIMIT 5; +SELECT * FROM t1 ORDER BY a, b, c LIMIT 5; +EXPLAIN SELECT * FROM t1 ORDER BY c, a LIMIT 5; +SELECT * FROM t1 ORDER BY c, a LIMIT 5; + +SET @@sort_buffer_size= @old_sort_buffer_size; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/filesort.cc b/sql/filesort.cc index f56e5b3a771..11be5d7f672 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -134,6 +134,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, error= 1; bzero((char*) ¶m,sizeof(param)); param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset); + /* filesort cannot handle zero-length records. */ + DBUG_ASSERT(param.sort_length); param.ref_length= table->file->ref_length; param.addon_field= 0; param.addon_length= 0; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d8ec5eff5c1..239809f1d4c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -521,13 +521,26 @@ JOIN::prepare(Item ***rref_pointer_array, if (order) { + bool real_order= FALSE; ORDER *ord; for (ord= order; ord; ord= ord->next) { Item *item= *ord->item; + /* + Disregard sort order if there's only "{VAR}CHAR(0) NOT NULL" fields + there. Such fields don't contain any data to sort. + */ + if (!real_order && + (item->type() != Item::Item::FIELD_ITEM || + ((Item_field *) item)->field->maybe_null() || + ((Item_field *) item)->field->sort_length())) + real_order= TRUE; + if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) item->split_sum_func(thd, ref_pointer_array, all_fields); } + if (!real_order) + order= NULL; } if (having && having->with_sum_func) From d468e242b300f95214e05d3aba60cc24bb2f74b3 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 29 Jan 2010 15:55:46 +0200 Subject: [PATCH 306/344] Bug #50642 : ssl certs in test suite are expiring soon. Updated the certs to expire on 2015. Made sure they work with both yassl and openssl. --- mysql-test/r/openssl_1.result | 4 +- mysql-test/std_data/cacert.pem | 24 +-- mysql-test/std_data/client-cert.pem | 83 ++++----- mysql-test/std_data/client-key.pem | 20 ++- mysql-test/std_data/server-cert.pem | 78 ++++----- mysql-test/std_data/server-key.pem | 14 +- mysql-test/std_data/server8k-cert.pem | 243 ++++++++++++-------------- mysql-test/std_data/server8k-key.pem | 194 ++++++++++---------- mysql-test/t/openssl_1.test | 4 +- 9 files changed, 317 insertions(+), 347 deletions(-) diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result index 697fa33e7c7..398202abdbe 100644 --- a/mysql-test/r/openssl_1.result +++ b/mysql-test/r/openssl_1.result @@ -3,8 +3,8 @@ create table t1(f1 int); insert into t1 values (5); grant select on test.* to ssl_user1@localhost require SSL; grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA"; -grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB/emailAddress=abstract.mysql.developer@mysql.com"; -grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB/emailAddress=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB"; +grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB"; +grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB" ISSUER "/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB"; grant select on test.* to ssl_user5@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "xxx"; flush privileges; connect(localhost,ssl_user5,,test,MASTER_PORT,MASTER_SOCKET); diff --git a/mysql-test/std_data/cacert.pem b/mysql-test/std_data/cacert.pem index 5473e4b153e..e44341384e4 100644 --- a/mysql-test/std_data/cacert.pem +++ b/mysql-test/std_data/cacert.pem @@ -1,17 +1,17 @@ -----BEGIN CERTIFICATE----- -MIICrTCCAhagAwIBAgIJAJXpePU0UOTVMA0GCSqGSIb3DQEBBQUAMEQxCzAJBgNV +MIICrTCCAhagAwIBAgIJAMI7xZKjhrDbMA0GCSqGSIb3DQEBBAUAMEQxCzAJBgNV BAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxhMREwDwYD -VQQKEwhNeVNRTCBBQjAeFw0wOTAxMjgxMDQ5NDZaFw0xNDAxMjcxMDQ5NDZaMEQx +VQQKEwhNeVNRTCBBQjAeFw0xMDAxMjkxMTQ3MTBaFw0xNTAxMjgxMTQ3MTBaMEQx CzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxh MREwDwYDVQQKEwhNeVNRTCBBQjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA -4XQHAe5R1+TXC8noZtWf+d5E0v1C59FWpn9SWEUCBjE5UiIwuJvi4Y+7xWGOXLAI -/JzJx5gNXLBiTsE/zh0uX9fKlajLhxB0GN+QU0ZlpQ1BeYipEcNXeI/7cT499f6v -XWabnTflivdCgHSWUOQ20/Lzs6kP6/e6OoZd/DPSjPECAwEAAaOBpjCBozAdBgNV -HQ4EFgQU8uLqVWWkmuKsnZf1RWz294wRrd8wdAYDVR0jBG0wa4AU8uLqVWWkmuKs -nZf1RWz294wRrd+hSKRGMEQxCzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxh -MRAwDgYDVQQHEwdVcHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQoIJAJXpePU0UOTV -MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAMMTE5sDN+Z0ZlV7KvH3g -6+aKvql8dTpRT3hYukeQlWua0nq74WPGVw0c4e/M/vbiMwmJcCYpB9pd4+dHqzSw -aPyoenjY6UF8n7B4quWy3SIUk2LSHeJLW+kzJn2afN9gvipFhdVh/uU2TIyLGOur -Z/vmJX2W7hF1uqPnbfa8Lrw= +wQYsOEfrN4ESP3FjsI8cghE+tZVuyK2gck61lwieVxjgFMtBd65mI5a1y9pmlOI1 +yM4SB2Ppqcuw7/e1CdV1y7lvHrGNt5yqEHbN4QX1gvsN8TQauP/2WILturk4R4Hq +rKg0ZySu7f1Xhl0ed9a48LpaEHD17IcxWEGMMJwAxF0CAwEAAaOBpjCBozAMBgNV +HRMEBTADAQH/MB0GA1UdDgQWBBSvktYQ0ahLnyxyVKqty+WpBbBrDTB0BgNVHSME +bTBrgBSvktYQ0ahLnyxyVKqty+WpBbBrDaFIpEYwRDELMAkGA1UEBhMCU0UxEDAO +BgNVBAgTB1VwcHNhbGExEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FM +IEFCggkAwjvFkqOGsNswDQYJKoZIhvcNAQEEBQADgYEAdKN1PjwMHAKG2Ww1145g +JQGBnKxSFOUaoSvkBi/4ntTM+ysnViWh7WvxyWjR9zU9arfr7aqsDeQxm0XDOqzj +AQ/cQIla2/Li8tXyfc06bisH/IHRaSc2zWqioTKbEwMdVOdrvq4a8V8ic3xYyIWn +7F4WeS07J8LKardSvM0+hOA= -----END CERTIFICATE----- diff --git a/mysql-test/std_data/client-cert.pem b/mysql-test/std_data/client-cert.pem index 9300520793e..ee7f2ab281e 100644 --- a/mysql-test/std_data/client-cert.pem +++ b/mysql-test/std_data/client-cert.pem @@ -1,55 +1,46 @@ Certificate: Data: - Version: 3 (0x2) - Serial Number: 3 (0x3) - Signature Algorithm: sha1WithRSAEncryption + Version: 1 (0x0) + Serial Number: 1048577 (0x100001) + Signature Algorithm: md5WithRSAEncryption Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB Validity - Not Before: Jan 28 11:04:39 2009 GMT - Not After : Jan 28 11:04:39 2010 GMT - Subject: C=SE, ST=Uppsala, O=MySQL AB/emailAddress=abstract.mysql.developer@mysql.com + Not Before: Jan 29 11:50:22 2010 GMT + Not After : Jan 28 11:50:22 2015 GMT + Subject: C=SE, ST=Uppsala, O=MySQL AB Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public Key: (512 bit) - Modulus (512 bit): - 00:e1:52:30:2c:d9:be:64:28:91:5d:7a:fd:d9:e9: - 14:35:7a:d2:94:4e:91:46:e0:db:9f:6b:79:f4:4c: - ac:6e:07:61:34:86:74:62:a7:a8:44:af:fa:87:87: - a8:7d:42:61:ff:ab:50:d4:7b:bf:75:fa:d5:d5:b3: - 74:fb:56:1e:37 + Public-Key: (1024 bit) + Modulus: + 00:cc:9a:37:49:13:66:dc:cf:e3:0b:13:a1:23:ed: + 78:db:4e:bd:11:f6:8c:0d:76:f9:a3:32:56:9a:f8: + a1:21:6a:55:4e:4d:3f:e6:67:9d:26:99:b2:cd:a4: + 9a:d2:2b:59:5c:d7:8a:d3:60:68:f8:18:bd:c5:be: + 15:e1:2a:3c:a3:d4:61:cb:f5:11:94:17:81:81:f7: + 87:8c:f6:6a:d2:ee:d8:e6:77:f6:62:66:4d:2e:16: + 8d:08:81:4a:c9:c6:4b:31:e5:b9:c7:8a:84:96:48: + a7:47:8c:0d:26:90:56:4e:e6:a5:6e:8c:b3:f2:9f: + fc:3d:78:9b:49:6e:86:83:77 Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - X509v3 Subject Key Identifier: - 58:30:B5:9B:2C:05:94:06:BA:3D:3C:F0:B2:CD:1D:67:65:E3:7F:85 - X509v3 Authority Key Identifier: - keyid:F2:E2:EA:55:65:A4:9A:E2:AC:9D:97:F5:45:6C:F6:F7:8C:11:AD:DF - DirName:/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB - serial:95:E9:78:F5:34:50:E4:D5 - - Signature Algorithm: sha1WithRSAEncryption - 05:19:e3:13:14:fc:c5:28:bf:69:f8:00:b3:25:cb:bd:ca:9f: - 2f:4c:b3:a8:04:11:f0:74:27:bd:82:2c:b4:49:9b:a7:59:f0: - f7:87:d1:e0:ba:99:a2:fe:4b:1d:10:6f:e4:a2:b3:cd:7f:8b: - 68:31:46:ee:cd:9e:e2:47:e1:4c:fa:74:d1:e2:8b:cc:a0:4b: - a8:24:d1:a4:c3:6b:2a:c6:28:cd:41:e0:06:48:e6:cf:f2:3c: - ca:37:95:d7:29:64:6b:91:91:83:e7:ac:c8:0b:87:bc:da:a6: - aa:f1:44:43:c8:74:7b:15:26:91:2e:03:c4:71:50:6c:f8:68: - dc:8c + Signature Algorithm: md5WithRSAEncryption + 5e:1f:a3:53:5f:24:13:1c:f8:28:32:b0:7f:69:69:f3:0e:c0: + 34:87:10:03:7d:da:15:8b:bd:19:b8:1a:56:31:e7:85:49:81: + c9:7f:45:20:74:3e:89:c0:e0:26:84:51:cc:04:16:ce:69:99: + 01:e1:26:99:b3:e3:f5:bd:ec:5f:a0:84:e4:38:da:75:78:7b: + 89:9c:d2:cd:60:95:20:ba:8e:e3:7c:e6:df:76:3a:7c:89:77: + 02:94:86:11:3a:c4:61:7d:6f:71:83:21:8a:17:fb:17:e2:ee: + 02:6b:61:c1:b4:52:63:d7:d8:46:b2:c5:9c:6f:38:91:8a:35: + 32:0b -----BEGIN CERTIFICATE----- -MIICfzCCAeigAwIBAgIBAzANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJTRTEQ -MA4GA1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlT -UUwgQUIwHhcNMDkwMTI4MTEwNDM5WhcNMTAwMTI4MTEwNDM5WjBlMQswCQYDVQQG -EwJTRTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIxMTAvBgkq -hkiG9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wXDAN -BgkqhkiG9w0BAQEFAANLADBIAkEA4VIwLNm+ZCiRXXr92ekUNXrSlE6RRuDbn2t5 -9EysbgdhNIZ0YqeoRK/6h4eofUJh/6tQ1Hu/dfrV1bN0+1YeNwIDAQABo4GjMIGg -MAkGA1UdEwQCMAAwHQYDVR0OBBYEFFgwtZssBZQGuj088LLNHWdl43+FMHQGA1Ud -IwRtMGuAFPLi6lVlpJrirJ2X9UVs9veMEa3foUikRjBEMQswCQYDVQQGEwJTRTEQ -MA4GA1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlT -UUwgQUKCCQCV6Xj1NFDk1TANBgkqhkiG9w0BAQUFAAOBgQAFGeMTFPzFKL9p+ACz -Jcu9yp8vTLOoBBHwdCe9giy0SZunWfD3h9Hgupmi/ksdEG/korPNf4toMUbuzZ7i -R+FM+nTR4ovMoEuoJNGkw2sqxijNQeAGSObP8jzKN5XXKWRrkZGD56zIC4e82qaq -8URDyHR7FSaRLgPEcVBs+GjcjA== +MIIB5zCCAVACAxAAATANBgkqhkiG9w0BAQQFADBEMQswCQYDVQQGEwJTRTEQMA4G +A1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwg +QUIwHhcNMTAwMTI5MTE1MDIyWhcNMTUwMTI4MTE1MDIyWjAyMQswCQYDVQQGEwJT +RTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIwgZ8wDQYJKoZI +hvcNAQEBBQADgY0AMIGJAoGBAMyaN0kTZtzP4wsToSPteNtOvRH2jA12+aMyVpr4 +oSFqVU5NP+ZnnSaZss2kmtIrWVzXitNgaPgYvcW+FeEqPKPUYcv1EZQXgYH3h4z2 +atLu2OZ39mJmTS4WjQiBSsnGSzHluceKhJZIp0eMDSaQVk7mpW6Ms/Kf/D14m0lu +hoN3AgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAXh+jU18kExz4KDKwf2lp8w7ANIcQ +A33aFYu9GbgaVjHnhUmByX9FIHQ+icDgJoRRzAQWzmmZAeEmmbPj9b3sX6CE5Dja +dXh7iZzSzWCVILqO43zm33Y6fIl3ApSGETrEYX1vcYMhihf7F+LuAmthwbRSY9fY +RrLFnG84kYo1Mgs= -----END CERTIFICATE----- diff --git a/mysql-test/std_data/client-key.pem b/mysql-test/std_data/client-key.pem index 9ef464d0875..205b5f31cb9 100644 --- a/mysql-test/std_data/client-key.pem +++ b/mysql-test/std_data/client-key.pem @@ -1,9 +1,15 @@ -----BEGIN RSA PRIVATE KEY----- -MIIBOQIBAAJBAOFSMCzZvmQokV16/dnpFDV60pROkUbg259refRMrG4HYTSGdGKn -qESv+oeHqH1CYf+rUNR7v3X61dWzdPtWHjcCAwEAAQJAXYooM8ZlcuEgj+VKU1ee -qyEFIMqJJxqcMk+E/nWCM96WxCP3zHNSrqNfSpI3ld7QzMwhdRz+gFLxT2gGNpIw -MQIhAPxzM/lDihe67X3ADYtDl9ZjA8Pm430x9sXlcxI17tCZAiEA5H1SyFl4mUee -9VnfSC2XGW7lwz72ZygfVX+b7tLWF08CIEh40gzW5MfXM+KLxdea+fXjyursV5ZT -R6KcMiKiNQLRAiAcmHqlzFzFgisotai2Fc6VRkXHG7gmzOSvBJt1VjmpDQIge6jf -2N7whTdvC4ferB+zUlgWQdyvx1c3T4gnt6PYdaY= +MIICXQIBAAKBgQDMmjdJE2bcz+MLE6Ej7XjbTr0R9owNdvmjMlaa+KEhalVOTT/m +Z50mmbLNpJrSK1lc14rTYGj4GL3FvhXhKjyj1GHL9RGUF4GB94eM9mrS7tjmd/Zi +Zk0uFo0IgUrJxksx5bnHioSWSKdHjA0mkFZO5qVujLPyn/w9eJtJboaDdwIDAQAB +AoGASqk/4We2En+93y3jkIO4pXafIe3w/3zZ7caRue1ehx4RUQh5d+95djuB9u7J +HEZ7TpjM7QNyao5EueL6gvbxt0LXFvqAMni7yM9tt/HUYtHHPqYiRtUny9bKYFTm +l8szCCMal/wD9GZU9ByHDNHm7tHUMyMhARNTYSgx+SERFmECQQD/6jJocC4SXf6f +T3LqimWR02lbJ7qCoDgRglsUXh0zjrG+IIiAyE+QOCCx1GMe3Uw6bsIuYwdHT6as +WcdPs04xAkEAzKulvEvLVvN5zfa/DTYRTV7jh6aDleOxjsD5oN/oJXoACnPzVuUL +qQQMNtuAXm6Q1QItrRxpQsSKbY0UQka6JwJBAOSgoNoG5lIIYTKIMvzwGV+XBLeo +HYsXgh+6Wo4uql3mLErUG78ZtWL9kc/tE4R+ZdyKGLaCR/1gXmH5bwN4B/ECQEBb +uUH8k3REG4kojesZlVc+/00ojzgS4UKCa/yqa9VdB6ZBz8MDQydinnShkTwgiGpy +xOoqhO753o2UT0qH8wECQQC99IEJWUnwvExVMkLaZH5NjAFJkb22sjkmuT11tAgU +RQgOMoDOm6driojnOnDWOkx1r1Gy9NgMLooduja4v6cx -----END RSA PRIVATE KEY----- diff --git a/mysql-test/std_data/server-cert.pem b/mysql-test/std_data/server-cert.pem index cab54db8b23..5922fe7ded7 100644 --- a/mysql-test/std_data/server-cert.pem +++ b/mysql-test/std_data/server-cert.pem @@ -1,55 +1,41 @@ Certificate: Data: - Version: 3 (0x2) - Serial Number: 1 (0x1) - Signature Algorithm: sha1WithRSAEncryption + Version: 1 (0x0) + Serial Number: 1048578 (0x100002) + Signature Algorithm: md5WithRSAEncryption Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB Validity - Not Before: Jan 28 10:55:13 2009 GMT - Not After : Jan 28 10:55:13 2010 GMT - Subject: C=SE, ST=Uppsala, O=MySQL AB, CN=localhost/emailAddress=abstract.mysql.developer@mysql.com + Not Before: Jan 29 11:56:49 2010 GMT + Not After : Jan 28 11:56:49 2015 GMT + Subject: C=SE, ST=Uppsala, O=MySQL AB, CN=localhost Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public Key: (512 bit) - Modulus (512 bit): - 00:b6:8f:e5:b7:b4:86:83:13:8a:f9:bf:63:cb:64: - 2d:b9:51:d1:de:ab:7b:45:1f:aa:b5:66:73:13:f9: - a6:07:d5:ba:7c:fa:92:bd:37:e2:ad:87:db:3e:b6: - 6a:12:64:f8:ee:17:e3:15:06:2f:a8:82:68:bf:57: - 8d:c3:04:98:27 + Public-Key: (512 bit) + Modulus: + 00:cd:e4:87:51:9d:72:11:a0:d1:fa:f3:92:8b:13: + 1c:eb:f7:e2:9a:2f:72:a8:d6:65:48:d1:69:af:1b: + c0:4c:13:e5:60:60:51:41:e9:ab:a6:bc:13:bb:0c: + 5e:32:7c:d9:6c:9e:cd:05:24:84:78:db:80:91:2e: + d8:88:2b:c2:ed Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - X509v3 Subject Key Identifier: - D9:9A:B8:5F:22:EA:04:10:C8:25:7D:82:57:E6:2E:FD:19:29:E7:DA - X509v3 Authority Key Identifier: - keyid:F2:E2:EA:55:65:A4:9A:E2:AC:9D:97:F5:45:6C:F6:F7:8C:11:AD:DF - DirName:/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB - serial:95:E9:78:F5:34:50:E4:D5 - - Signature Algorithm: sha1WithRSAEncryption - 54:07:2d:21:0b:a5:af:3b:58:23:32:5e:56:7f:ab:58:63:48: - 91:aa:38:90:89:16:f9:cc:bf:a4:0e:78:2b:9f:c5:1b:58:a6: - e6:08:8f:2e:ae:97:03:21:9b:f1:cd:c0:26:8f:1d:d7:28:27: - a0:8e:81:09:1b:1c:0f:c9:a5:41:3a:2d:44:3f:9c:fa:87:ff: - c8:4c:2b:44:f7:1b:c1:3e:4f:01:7f:e9:26:cc:9f:1c:06:b5: - 0b:27:d1:10:90:be:93:0c:9c:e7:b0:d1:ea:27:99:4e:06:14: - 0c:7a:e9:c1:52:c5:33:68:bc:61:0d:db:81:3b:57:48:57:bf: - 42:9a + Signature Algorithm: md5WithRSAEncryption + 73:ce:9c:6e:39:46:b4:14:be:da:3f:f3:1b:ba:90:bc:23:43: + d7:82:2a:70:4e:a6:d9:5a:65:5c:b7:df:71:df:75:77:c5:80: + a4:af:fa:d2:59:e2:fd:c9:9c:f0:98:95:8e:69:a9:8c:7c:d8: + 6f:48:d2:e3:36:e0:cd:ff:3f:d1:a5:e6:ab:75:09:c4:50:10: + c4:96:dd:bf:3b:de:32:46:da:ca:4a:f1:d6:52:8a:33:2f:ab: + f5:2e:70:3f:d4:9c:be:00:c8:03:f9:39:8a:df:5b:70:3c:40: + ef:03:be:7c:3d:1d:32:32:f3:51:81:e2:83:30:6e:3d:38:9b: + fb:3c -----BEGIN CERTIFICATE----- -MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJTRTEQ -MA4GA1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlT -UUwgQUIwHhcNMDkwMTI4MTA1NTEzWhcNMTAwMTI4MTA1NTEzWjB5MQswCQYDVQQG -EwJTRTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIxEjAQBgNV -BAMTCWxvY2FsaG9zdDExMC8GCSqGSIb3DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2 -ZWxvcGVyQG15c3FsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC2j+W3tIaD -E4r5v2PLZC25UdHeq3tFH6q1ZnMT+aYH1bp8+pK9N+Kth9s+tmoSZPjuF+MVBi+o -gmi/V43DBJgnAgMBAAGjgaMwgaAwCQYDVR0TBAIwADAdBgNVHQ4EFgQU2Zq4XyLq -BBDIJX2CV+Yu/Rkp59owdAYDVR0jBG0wa4AU8uLqVWWkmuKsnZf1RWz294wRrd+h -SKRGMEQxCzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdV -cHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQoIJAJXpePU0UOTVMA0GCSqGSIb3DQEB -BQUAA4GBAFQHLSELpa87WCMyXlZ/q1hjSJGqOJCJFvnMv6QOeCufxRtYpuYIjy6u -lwMhm/HNwCaPHdcoJ6COgQkbHA/JpUE6LUQ/nPqH/8hMK0T3G8E+TwF/6SbMnxwG -tQsn0RCQvpMMnOew0eonmU4GFAx66cFSxTNovGEN24E7V0hXv0Ka +MIIBtzCCASACAxAAAjANBgkqhkiG9w0BAQQFADBEMQswCQYDVQQGEwJTRTEQMA4G +A1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwg +QUIwHhcNMTAwMTI5MTE1NjQ5WhcNMTUwMTI4MTE1NjQ5WjBGMQswCQYDVQQGEwJT +RTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIxEjAQBgNVBAMT +CWxvY2FsaG9zdDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDN5IdRnXIRoNH685KL +Exzr9+KaL3Ko1mVI0WmvG8BME+VgYFFB6aumvBO7DF4yfNlsns0FJIR424CRLtiI +K8LtAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAc86cbjlGtBS+2j/zG7qQvCND14Iq +cE6m2VplXLffcd91d8WApK/60lni/cmc8JiVjmmpjHzYb0jS4zbgzf8/0aXmq3UJ +xFAQxJbdvzveMkbaykrx1lKKMy+r9S5wP9ScvgDIA/k5it9bcDxA7wO+fD0dMjLz +UYHigzBuPTib+zw= -----END CERTIFICATE----- diff --git a/mysql-test/std_data/server-key.pem b/mysql-test/std_data/server-key.pem index 0d8274b77f6..1083495cb96 100644 --- a/mysql-test/std_data/server-key.pem +++ b/mysql-test/std_data/server-key.pem @@ -1,9 +1,9 @@ -----BEGIN RSA PRIVATE KEY----- -MIIBOQIBAAJBALaP5be0hoMTivm/Y8tkLblR0d6re0UfqrVmcxP5pgfVunz6kr03 -4q2H2z62ahJk+O4X4xUGL6iCaL9XjcMEmCcCAwEAAQJASA5VwgNb0CKHiPm0ntOk -hG+54SRX3DmafEy6gRjZIl/bZ/asSLhXUZ+CeohyrQh7BZgYWvykd8pRISL9eKsU -GQIhAOXkUrOtP/EtjyqNluEqZdG+RZi/7p61JS3Ce13Myu+LAiEAy0uMlV34AJpM -b40FPKqlHxw8DD/Dt1iKhNVAg8+LDVUCIFjv7fbJDbW2VG63/Cj8CAwOukoP5rbL -iaicVrHBKrllAiB9+MiaXeopZXNrxDS0jQFYr8Q9yt1aJVFgUkxx4Q9HKQIgZPs0 -KlF3NNNWw78INaAEkyf0IEssnLMsuoCWw0DIOak= +MIIBOwIBAAJBAM3kh1GdchGg0frzkosTHOv34povcqjWZUjRaa8bwEwT5WBgUUHp +q6a8E7sMXjJ82WyezQUkhHjbgJEu2Igrwu0CAwEAAQJBAJuwhFbF3NzRpBbEmnqJ +4GPa1UJMQMLFJF+04tqj/HxJcAIVhOJhGmmtYNw1yjz/ZsPnfJCMz4eFOtdjvGtf +peECIQDmFFg2WLvYo+2m9w9V7z4ZIkg7ixYkI/ObUUctfZkPOQIhAOUWnrvjFrAX +bIvYT/YR50+3ZDLEc51XxNgJnWqWYl1VAiEAnTOFWgyivFC1DgF8PvDp8u5TgCt2 +A1d1GMgd490O+TECIC/WMl0/hTxOF9930vKqOGf//o9PUGkZq8QE9fcM4gtlAiAE +iOcFpnLjtWj57jrhuw214ucnB5rklkQQe+AtcARNkg== -----END RSA PRIVATE KEY----- diff --git a/mysql-test/std_data/server8k-cert.pem b/mysql-test/std_data/server8k-cert.pem index 3b86effd699..06e118cf034 100644 --- a/mysql-test/std_data/server8k-cert.pem +++ b/mysql-test/std_data/server8k-cert.pem @@ -1,138 +1,125 @@ Certificate: Data: - Version: 3 (0x2) - Serial Number: 4 (0x4) - Signature Algorithm: sha1WithRSAEncryption + Version: 1 (0x0) + Serial Number: 1048579 (0x100003) + Signature Algorithm: md5WithRSAEncryption Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB Validity - Not Before: Jan 28 11:12:27 2009 GMT - Not After : Jan 28 11:12:27 2010 GMT + Not Before: Jan 29 12:01:53 2010 GMT + Not After : Jan 28 12:01:53 2015 GMT Subject: C=SE, ST=Uppsala, O=MySQL AB, CN=server Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public Key: (8192 bit) - Modulus (8192 bit): - 00:c0:8f:22:03:24:59:67:46:14:d6:8f:60:09:58: - 06:07:45:f1:78:71:55:f1:ea:b9:30:8a:cd:c3:3c: - b9:bf:65:6e:18:ed:a0:b8:c9:19:56:6f:c4:90:19: - c8:65:09:db:ff:bf:82:a1:08:ad:01:4f:5a:a3:d4: - 3d:78:7e:4b:4a:01:a4:7d:e8:7b:05:3e:7d:d8:b9: - 55:58:60:d6:1c:ce:e8:32:62:2c:19:60:f3:ed:05: - 99:6d:c9:77:07:2e:11:6d:0b:9a:c7:68:38:46:e8: - fa:31:80:df:e8:79:f0:f1:fd:a9:94:c3:fa:0d:f5: - 78:ac:49:7e:d5:17:fd:e1:ee:44:f3:c7:0e:30:32: - 5d:a9:19:25:e4:bb:21:1d:fe:3c:84:48:40:f5:58: - f4:bf:13:8c:85:68:bb:ec:f5:dd:c6:38:d1:b0:77: - 1f:a6:8e:4f:8d:e2:6f:49:74:f5:3f:90:65:8e:99: - 1e:59:9c:1c:b5:26:24:c4:b1:de:1e:fb:96:65:c4: - 31:14:1a:53:b8:5e:62:8a:c7:04:f7:b4:36:a4:af: - 07:c8:27:06:ed:dd:e6:f4:8c:62:f1:65:40:d0:9f: - 9f:a9:14:c8:8e:8b:74:d6:67:5a:d0:c9:4d:35:a1: - d5:7b:39:3a:42:9f:e4:d0:f4:c6:0f:2e:42:30:4b: - 56:b2:3d:6d:8e:2d:58:c5:69:99:35:49:95:95:99: - b6:87:29:2b:32:d1:50:08:cd:25:14:48:6d:10:99: - 85:61:3c:41:26:21:55:cc:1f:cf:ad:b0:2f:b9:89: - d8:4e:a0:18:ff:75:1d:b6:97:7c:c5:fa:8b:dc:93: - 17:86:0a:64:d4:09:35:d5:83:34:6d:5c:6d:c6:8c: - cd:b9:ec:c2:93:c6:c1:b7:cc:04:6f:22:e0:07:bf: - e0:d9:9b:2f:d5:a0:50:cc:f9:f0:95:83:8f:f4:30: - 83:72:94:d7:b5:4b:da:cc:9f:54:3b:8d:78:77:0b: - 24:6c:0f:c2:96:61:96:2f:b8:5f:b5:7a:ab:7a:5b: - 97:7a:a9:ad:40:8b:f2:d6:c6:8d:81:d9:94:61:8f: - 9d:03:c5:b9:10:03:68:83:bf:04:81:cc:ac:bd:34: - 89:e8:d4:8d:43:20:e2:b6:a4:11:3d:15:2a:82:0c: - d6:3a:6a:8c:62:d4:93:bc:c3:80:bf:1b:b4:2b:0a: - 7a:34:f0:cd:1e:82:3f:25:0f:d1:04:a8:0a:05:19: - b0:d6:16:83:39:af:0b:45:7d:cb:14:7e:4d:aa:aa: - c2:39:a8:46:38:ab:bd:ab:2a:bd:34:43:7f:da:25: - de:2b:fb:69:3b:fe:3b:87:fd:98:94:76:4a:bf:04: - a3:31:e3:3a:ff:6f:04:fa:fa:24:e4:2a:89:e9:0e: - bf:44:4c:72:85:82:3c:89:4a:03:63:01:41:92:53: - d0:82:60:6e:d8:ff:8c:a2:b4:1a:3b:20:6d:ae:74: - 92:30:4e:48:e3:51:a6:cb:73:97:06:13:03:32:23: - 9b:7d:a2:c7:3a:a9:af:97:8c:51:ed:fe:fa:b4:b4: - 1a:a3:87:fc:cf:8c:8e:e6:80:15:03:fd:fe:7d:bd: - b1:76:f1:5f:b3:09:2b:4c:4d:a7:7c:b5:72:b1:d6: - db:38:c0:67:a4:54:bc:87:09:a5:39:ba:1a:7e:3f: - 74:60:ad:3d:4b:be:94:53:f3:64:16:c7:33:35:ec: - 41:00:95:b6:de:99:62:a2:7a:28:9a:45:4d:fa:cd: - a6:77:f6:de:58:72:50:c8:7d:69:38:db:07:04:84: - d8:4d:39:f7:50:13:43:ae:2d:af:45:a4:2a:39:56: - 3c:b8:b7:d8:26:a4:36:c9:23:aa:aa:b8:49:0b:21: - ba:9e:7a:2b:7f:4d:29:9f:0e:00:1e:b4:5e:a6:fa: - 49:fe:8d:e5:74:57:d8:ba:d9:92:2c:d2:ac:84:1d: - f2:a6:a4:44:1c:bf:88:41:32:7e:d1:c3:2f:6e:bc: - 0f:5d:19:a6:8f:74:2b:67:ba:dd:a9:db:68:b5:ce: - 9d:25:48:df:54:08:d0:1d:4f:2e:5b:24:bc:05:0f: - fb:58:46:fa:02:ca:53:93:29:cf:10:27:c2:a0:18: - d0:f5:d4:b9:3c:5e:df:8e:6c:f5:7c:b9:b4:54:cc: - 39:16:5d:3c:da:96:b3:c3:6c:d4:70:5d:d3:30:a7: - a6:bd:6f:dd:41:bc:a8:de:42:60:59:9a:85:25:0d: - 2a:45:c3:05:b4:6e:7a:4a:4d:ca:8c:0a:e5:6c:34: - bc:20:9b:6d:4a:ca:ca:b6:a6:3a:a0:db:c3:0e:20: - 1a:12:1b:77:dd:cb:1d:7f:c3:0d:0d:e7:c1:fd:96: - d2:c7:68:80:99:a0:d9:8a:33:21:a3:8b:a2:5a:a7: - 7e:27:06:02:7f:ed:60:11:37:34:54:17:7f:4d:90: - 14:1e:69:37:0d:ba:f0:2b:f0:a3:2d:62:79:c8:76: - a8:ea:c8:e7:3b:1f:c6:4f:c2:0c:d7:ac:f0:77:53: - 5d:f0:50:b4:df:9b:03:ca:4d:41:e1:18:b2:25:30: - 86:1d:63:e5:67:b1:53:cd:6b:4e:83:1a:b9:5e:2d: - 05:15:6b:d4:8e:b1:97:fc:31:03:57:cb:bf:27:7f: - cd:5f:27:7e:66:e7:3c:17:09:b6:11:2a:4f:33:cd: - eb:1a:d3:6f:d5:15:8b:8b:ce:68:6b:7e:9a:95:e5: - 74:7f:17:57:d9 + Public-Key: (8192 bit) + Modulus: + 00:ca:aa:1d:c4:11:ec:91:f0:c7:ff:5f:90:92:fc: + 40:0c:5e:b7:3d:00:c5:20:d5:0f:89:31:07:d7:41: + 4c:8b:60:80:aa:38:14:de:93:6b:9c:74:88:41:68: + b5:02:41:01:2d:86:a2:7a:95:53:5e:7b:67:2f:6c: + 1e:29:51:f9:44:fd:4a:80:be:b2:23:a1:3e:1b:38: + cf:88:c4:71:ee:f8:6b:41:c5:2d:c0:c3:52:ac:59: + 7d:81:34:19:95:32:b8:9a:51:b6:41:36:d4:c4:a1: + ae:84:e6:38:b9:e8:bf:96:be:19:7a:6b:77:4d:e0: + de:e6:b3:b6:6b:bc:3d:dd:68:bc:4b:c4:eb:f5:36: + 93:ed:56:a2:15:50:8a:10:e8:d6:22:ed:6c:b1:cd: + c3:18:c9:f6:0a:e1:de:61:65:62:d6:14:41:8c:b5: + fb:14:68:c1:cf:12:5d:41:21:9d:57:11:43:7d:bb: + 43:2c:21:bb:c3:44:7d:a8:cf:1f:c3:71:75:b5:47: + c2:7d:ce:38:3c:73:64:9e:15:d8:a7:27:cf:bd:40: + c8:45:08:e3:c8:39:a8:0b:8e:c2:5b:7b:f1:47:91: + 12:91:cc:e1:00:e0:94:5b:bd:32:e4:0c:8d:c3:be: + cc:76:32:52:12:69:b0:18:e0:b0:c2:76:34:5a:5f: + 79:d9:f6:81:9d:02:0a:61:69:1c:33:ce:49:fa:76: + 03:1e:07:5b:27:0b:bf:34:9e:34:96:b8:03:9b:50: + 3a:6a:2f:17:7a:14:cf:65:63:00:37:52:a8:73:ce: + 4b:14:40:f4:d2:9a:56:54:33:b8:77:2e:42:5b:8f: + ec:1f:18:f4:ad:ab:8a:4a:8d:6d:70:25:f3:58:e7: + cb:66:51:14:7d:16:f4:eb:6d:56:76:76:51:6e:d6: + 1d:da:d3:8d:c0:64:5a:67:4e:af:e2:bf:33:d1:b8: + f6:2a:fc:57:87:a7:35:5e:80:c9:ac:fc:87:c9:71: + 17:91:bf:b7:4d:a3:ed:3c:1b:27:f4:66:a0:f9:46: + 03:27:cc:ea:80:f6:4b:40:f6:41:94:cd:bd:0a:b3: + ef:26:be:de:6f:69:ae:0f:3f:1c:55:63:33:90:9b: + ed:ca:5a:12:4d:de:4b:06:c2:a2:92:b0:42:3d:31: + af:a4:15:12:15:f8:8a:e9:88:8d:cf:fd:85:66:50: + 6f:11:f1:9f:48:f3:b5:ba:9d:86:68:24:a2:5d:a8: + 7c:54:42:fa:d8:b5:c5:f2:dd:0e:0f:d0:68:e4:54: + 7e:c5:b9:a0:9b:65:2d:77:f4:8f:b9:30:0a:d5:86: + 5c:ed:c9:7c:d1:da:9d:0d:63:50:ee:e5:1e:92:63: + cc:a2:0c:e8:4a:96:02:4d:dc:8f:df:7c:8f:08:18: + a8:30:88:d7:af:89:ad:fc:57:4b:10:f9:f1:cb:48: + e8:b6:3b:c8:3f:fc:c2:d3:d1:4a:10:3c:1b:6b:64: + dc:e5:65:1e:5b:b2:da:b1:e2:24:97:8f:ee:c0:4b: + 8e:18:83:7c:17:a6:3c:45:b3:60:06:23:f2:2f:18: + 13:9e:17:8a:c6:72:79:8c:4d:04:f3:9d:ea:e0:25: + d3:33:8c:1e:11:47:63:1f:a5:45:3f:bd:85:b3:fe: + a5:68:ee:48:b7:0c:a4:c9:7f:72:d0:75:66:9b:6a: + f9:a0:50:f3:a8:59:6d:a3:dd:38:4f:70:2b:bb:ff: + 92:2e:71:ab:ef:e9:00:ed:0d:d1:b4:6f:f0:8e:b2: + 09:fb:4d:61:0d:d9:10:d5:54:11:cd:03:94:84:fd: + a8:68:e4:45:6e:1e:6a:1e:2f:85:a1:6d:f5:b6:c0: + f1:ee:f7:36:e9:fe:c2:f7:ad:cc:13:46:5b:88:42: + f0:2d:1f:b5:0e:7e:b5:2b:e4:8d:ab:b9:87:30:6a: + 3d:12:f4:ad:f3:1c:ac:cc:1a:48:29:2a:96:7b:80: + 00:0b:6e:59:87:bf:a3:ca:70:99:1b:1c:fd:72:3d: + b2:d3:94:4a:cf:55:75:be:1f:40:ec:55:35:48:2d: + 55:f0:00:da:3c:b0:60:ba:11:32:66:54:0b:be:06: + a4:5e:b7:c9:59:bb:4d:f4:92:06:26:48:6e:c2:12: + d4:7c:f0:20:b8:a2:e1:bc:6a:b6:19:0e:37:47:55: + c9:f2:49:0d:96:75:a2:84:64:bf:34:fc:be:b2:41: + e4:f5:88:eb:e1:b7:26:a5:e5:41:c2:20:0c:f6:e2: + a8:a5:e7:76:54:a5:fb:4b:80:05:7d:18:85:7a:ba: + bc:b7:ad:c0:2f:60:85:cc:15:12:1c:2f:0a:9e:f3: + 7c:40:cf:f4:3e:23:d2:95:ca:d0:06:58:52:f0:84: + d8:0f:3d:eb:ff:12:68:94:79:8f:be:40:29:5f:98: + c8:90:6c:05:2f:99:8c:2a:63:78:1f:23:b1:29:c5: + e7:49:c9:b2:92:0f:53:0b:d5:71:28:17:c2:19:bf: + 60:bf:7c:87:a8:ab:c1:f4:0a:c1:b8:d2:68:ee:c1: + ce:a7:13:13:17:6d:24:5d:a2:37:a6:d7:7d:48:8b: + 2b:74:2d:40:2e:ca:19:d5:b6:3e:6c:42:71:fa:cf: + 85:87:f9:de:80:73:8b:89:f4:70:f0:d8:d7:ff:40: + 41:9c:c7:15:6d:9b:6e:4c:b5:52:02:99:79:32:73: + ca:26:a0:ac:31:6f:c4:b0:f5:da:bb:c2:1f:e0:9f: + 44:ba:25:f7:9f Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - X509v3 Subject Key Identifier: - 58:12:24:59:A7:3C:29:15:89:5A:C2:12:DB:E7:A5:42:10:21:B7:BA - X509v3 Authority Key Identifier: - keyid:F2:E2:EA:55:65:A4:9A:E2:AC:9D:97:F5:45:6C:F6:F7:8C:11:AD:DF - DirName:/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB - serial:95:E9:78:F5:34:50:E4:D5 - - Signature Algorithm: sha1WithRSAEncryption - cd:cb:5c:83:35:ea:cb:cb:c3:a8:c3:95:e2:e6:6f:4d:d8:e4: - ee:41:dd:3f:35:82:ac:2f:fd:63:89:4f:3a:19:d7:81:75:b3: - a3:fc:36:b2:12:d5:c6:56:bc:13:60:37:33:6e:a0:d8:ae:7c: - 88:f9:4b:ee:7b:1f:c8:f0:56:19:07:4d:bb:45:52:1c:78:81: - 07:7c:13:86:b8:86:70:85:e4:71:25:58:78:d1:be:de:22:82: - 6d:1a:4b:06:ac:f0:e8:50:87:c7:69:64:c2:61:43:cd:96:06: - a6:7e:09:a9:02:01:2a:a2:40:f3:cd:10:80:48:d0:34:55:40: - b9:ce + Signature Algorithm: md5WithRSAEncryption + 08:75:dc:b9:3f:aa:b6:7e:81:7a:39:d1:ee:ed:44:b6:ce:1b: + 37:c4:4c:19:d0:66:e6:eb:b5:4f:2a:ef:95:58:64:21:55:01: + 12:30:ac:8a:95:d1:06:de:29:46:a4:f1:7d:7f:b0:1e:d2:4e: + fb:f6:fa:9a:74:be:85:62:db:0b:82:90:58:62:c5:5f:f1:80: + 02:9f:c5:fb:f3:6b:b0:b4:3b:04:b1:e5:53:c2:d0:00:a1:1a: + 9d:65:60:6f:73:98:67:e0:9c:c8:12:94:79:59:bf:43:7b:f5: + 77:c8:8f:df:b1:cd:11:1c:01:19:99:c2:22:42:f7:41:ae:b4: + b8:1a -----BEGIN CERTIFICATE----- -MIIGJTCCBY6gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJTRTEQ -MA4GA1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlT -UUwgQUIwHhcNMDkwMTI4MTExMjI3WhcNMTAwMTI4MTExMjI3WjBDMQswCQYDVQQG -EwJTRTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIxDzANBgNV -BAMTBnNlcnZlcjCCBCIwDQYJKoZIhvcNAQEBBQADggQPADCCBAoCggQBAMCPIgMk -WWdGFNaPYAlYBgdF8XhxVfHquTCKzcM8ub9lbhjtoLjJGVZvxJAZyGUJ2/+/gqEI -rQFPWqPUPXh+S0oBpH3oewU+fdi5VVhg1hzO6DJiLBlg8+0FmW3JdwcuEW0Lmsdo -OEbo+jGA3+h58PH9qZTD+g31eKxJftUX/eHuRPPHDjAyXakZJeS7IR3+PIRIQPVY -9L8TjIVou+z13cY40bB3H6aOT43ib0l09T+QZY6ZHlmcHLUmJMSx3h77lmXEMRQa -U7heYorHBPe0NqSvB8gnBu3d5vSMYvFlQNCfn6kUyI6LdNZnWtDJTTWh1Xs5OkKf -5ND0xg8uQjBLVrI9bY4tWMVpmTVJlZWZtocpKzLRUAjNJRRIbRCZhWE8QSYhVcwf -z62wL7mJ2E6gGP91HbaXfMX6i9yTF4YKZNQJNdWDNG1cbcaMzbnswpPGwbfMBG8i -4Ae/4NmbL9WgUMz58JWDj/Qwg3KU17VL2syfVDuNeHcLJGwPwpZhli+4X7V6q3pb -l3qprUCL8tbGjYHZlGGPnQPFuRADaIO/BIHMrL00iejUjUMg4rakET0VKoIM1jpq -jGLUk7zDgL8btCsKejTwzR6CPyUP0QSoCgUZsNYWgzmvC0V9yxR+TaqqwjmoRjir -vasqvTRDf9ol3iv7aTv+O4f9mJR2Sr8EozHjOv9vBPr6JOQqiekOv0RMcoWCPIlK -A2MBQZJT0IJgbtj/jKK0Gjsgba50kjBOSONRpstzlwYTAzIjm32ixzqpr5eMUe3+ -+rS0GqOH/M+MjuaAFQP9/n29sXbxX7MJK0xNp3y1crHW2zjAZ6RUvIcJpTm6Gn4/ -dGCtPUu+lFPzZBbHMzXsQQCVtt6ZYqJ6KJpFTfrNpnf23lhyUMh9aTjbBwSE2E05 -91ATQ64tr0WkKjlWPLi32CakNskjqqq4SQshup56K39NKZ8OAB60Xqb6Sf6N5XRX -2LrZkizSrIQd8qakRBy/iEEyftHDL268D10Zpo90K2e63anbaLXOnSVI31QI0B1P -LlskvAUP+1hG+gLKU5MpzxAnwqAY0PXUuTxe345s9Xy5tFTMORZdPNqWs8Ns1HBd -0zCnpr1v3UG8qN5CYFmahSUNKkXDBbRuekpNyowK5Ww0vCCbbUrKyramOqDbww4g -GhIbd93LHX/DDQ3nwf2W0sdogJmg2YozIaOLolqnficGAn/tYBE3NFQXf02QFB5p -Nw268Cvwoy1iech2qOrI5zsfxk/CDNes8HdTXfBQtN+bA8pNQeEYsiUwhh1j5Wex -U81rToMauV4tBRVr1I6xl/wxA1fLvyd/zV8nfmbnPBcJthEqTzPN6xrTb9UVi4vO -aGt+mpXldH8XV9kCAwEAAaOBozCBoDAJBgNVHRMEAjAAMB0GA1UdDgQWBBRYEiRZ -pzwpFYlawhLb56VCECG3ujB0BgNVHSMEbTBrgBTy4upVZaSa4qydl/VFbPb3jBGt -36FIpEYwRDELMAkGA1UEBhMCU0UxEDAOBgNVBAgTB1VwcHNhbGExEDAOBgNVBAcT -B1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCggkAlel49TRQ5NUwDQYJKoZIhvcN -AQEFBQADgYEAzctcgzXqy8vDqMOV4uZvTdjk7kHdPzWCrC/9Y4lPOhnXgXWzo/w2 -shLVxla8E2A3M26g2K58iPlL7nsfyPBWGQdNu0VSHHiBB3wThriGcIXkcSVYeNG+ -3iKCbRpLBqzw6FCHx2lkwmFDzZYGpn4JqQIBKqJA880QgEjQNFVAuc4= +MIIFfDCCBOUCAxAAAzANBgkqhkiG9w0BAQQFADBEMQswCQYDVQQGEwJTRTEQMA4G +A1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwg +QUIwHhcNMTAwMTI5MTIwMTUzWhcNMTUwMTI4MTIwMTUzWjBDMQswCQYDVQQGEwJT +RTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIxDzANBgNVBAMT +BnNlcnZlcjCCBCIwDQYJKoZIhvcNAQEBBQADggQPADCCBAoCggQBAMqqHcQR7JHw +x/9fkJL8QAxetz0AxSDVD4kxB9dBTItggKo4FN6Ta5x0iEFotQJBAS2GonqVU157 +Zy9sHilR+UT9SoC+siOhPhs4z4jEce74a0HFLcDDUqxZfYE0GZUyuJpRtkE21MSh +roTmOLnov5a+GXprd03g3uaztmu8Pd1ovEvE6/U2k+1WohVQihDo1iLtbLHNwxjJ +9grh3mFlYtYUQYy1+xRowc8SXUEhnVcRQ327Qywhu8NEfajPH8NxdbVHwn3OODxz +ZJ4V2Kcnz71AyEUI48g5qAuOwlt78UeREpHM4QDglFu9MuQMjcO+zHYyUhJpsBjg +sMJ2NFpfedn2gZ0CCmFpHDPOSfp2Ax4HWycLvzSeNJa4A5tQOmovF3oUz2VjADdS +qHPOSxRA9NKaVlQzuHcuQluP7B8Y9K2rikqNbXAl81jny2ZRFH0W9OttVnZ2UW7W +HdrTjcBkWmdOr+K/M9G49ir8V4enNV6Ayaz8h8lxF5G/t02j7TwbJ/RmoPlGAyfM +6oD2S0D2QZTNvQqz7ya+3m9prg8/HFVjM5Cb7cpaEk3eSwbCopKwQj0xr6QVEhX4 +iumIjc/9hWZQbxHxn0jztbqdhmgkol2ofFRC+ti1xfLdDg/QaORUfsW5oJtlLXf0 +j7kwCtWGXO3JfNHanQ1jUO7lHpJjzKIM6EqWAk3cj998jwgYqDCI16+JrfxXSxD5 +8ctI6LY7yD/8wtPRShA8G2tk3OVlHluy2rHiJJeP7sBLjhiDfBemPEWzYAYj8i8Y +E54XisZyeYxNBPOd6uAl0zOMHhFHYx+lRT+9hbP+pWjuSLcMpMl/ctB1Zptq+aBQ +86hZbaPdOE9wK7v/ki5xq+/pAO0N0bRv8I6yCftNYQ3ZENVUEc0DlIT9qGjkRW4e +ah4vhaFt9bbA8e73Nun+wvetzBNGW4hC8C0ftQ5+tSvkjau5hzBqPRL0rfMcrMwa +SCkqlnuAAAtuWYe/o8pwmRsc/XI9stOUSs9Vdb4fQOxVNUgtVfAA2jywYLoRMmZU +C74GpF63yVm7TfSSBiZIbsIS1HzwILii4bxqthkON0dVyfJJDZZ1ooRkvzT8vrJB +5PWI6+G3JqXlQcIgDPbiqKXndlSl+0uABX0YhXq6vLetwC9ghcwVEhwvCp7zfEDP +9D4j0pXK0AZYUvCE2A896/8SaJR5j75AKV+YyJBsBS+ZjCpjeB8jsSnF50nJspIP +UwvVcSgXwhm/YL98h6irwfQKwbjSaO7BzqcTExdtJF2iN6bXfUiLK3QtQC7KGdW2 +PmxCcfrPhYf53oBzi4n0cPDY1/9AQZzHFW2bbky1UgKZeTJzyiagrDFvxLD12rvC +H+CfRLol958CAwEAATANBgkqhkiG9w0BAQQFAAOBgQAIddy5P6q2foF6OdHu7US2 +zhs3xEwZ0Gbm67VPKu+VWGQhVQESMKyKldEG3ilGpPF9f7Ae0k779vqadL6FYtsL +gpBYYsVf8YACn8X782uwtDsEseVTwtAAoRqdZWBvc5hn4JzIEpR5Wb9De/V3yI/f +sc0RHAEZmcIiQvdBrrS4Gg== -----END CERTIFICATE----- diff --git a/mysql-test/std_data/server8k-key.pem b/mysql-test/std_data/server8k-key.pem index 493ad2350c8..faf4b43fa56 100644 --- a/mysql-test/std_data/server8k-key.pem +++ b/mysql-test/std_data/server8k-key.pem @@ -1,99 +1,99 @@ -----BEGIN RSA PRIVATE KEY----- -MIISKAIBAAKCBAEAwI8iAyRZZ0YU1o9gCVgGB0XxeHFV8eq5MIrNwzy5v2VuGO2g -uMkZVm/EkBnIZQnb/7+CoQitAU9ao9Q9eH5LSgGkfeh7BT592LlVWGDWHM7oMmIs -GWDz7QWZbcl3By4RbQuax2g4Ruj6MYDf6Hnw8f2plMP6DfV4rEl+1Rf94e5E88cO -MDJdqRkl5LshHf48hEhA9Vj0vxOMhWi77PXdxjjRsHcfpo5PjeJvSXT1P5Bljpke -WZwctSYkxLHeHvuWZcQxFBpTuF5iiscE97Q2pK8HyCcG7d3m9Ixi8WVA0J+fqRTI -jot01mda0MlNNaHVezk6Qp/k0PTGDy5CMEtWsj1tji1YxWmZNUmVlZm2hykrMtFQ -CM0lFEhtEJmFYTxBJiFVzB/PrbAvuYnYTqAY/3Udtpd8xfqL3JMXhgpk1Ak11YM0 -bVxtxozNuezCk8bBt8wEbyLgB7/g2Zsv1aBQzPnwlYOP9DCDcpTXtUvazJ9UO414 -dwskbA/ClmGWL7hftXqreluXeqmtQIvy1saNgdmUYY+dA8W5EANog78EgcysvTSJ -6NSNQyDitqQRPRUqggzWOmqMYtSTvMOAvxu0Kwp6NPDNHoI/JQ/RBKgKBRmw1haD -Oa8LRX3LFH5NqqrCOahGOKu9qyq9NEN/2iXeK/tpO/47h/2YlHZKvwSjMeM6/28E -+vok5CqJ6Q6/RExyhYI8iUoDYwFBklPQgmBu2P+MorQaOyBtrnSSME5I41Gmy3OX -BhMDMiObfaLHOqmvl4xR7f76tLQao4f8z4yO5oAVA/3+fb2xdvFfswkrTE2nfLVy -sdbbOMBnpFS8hwmlOboafj90YK09S76UU/NkFsczNexBAJW23plionoomkVN+s2m -d/beWHJQyH1pONsHBITYTTn3UBNDri2vRaQqOVY8uLfYJqQ2ySOqqrhJCyG6nnor -f00pnw4AHrRepvpJ/o3ldFfYutmSLNKshB3ypqREHL+IQTJ+0cMvbrwPXRmmj3Qr -Z7rdqdtotc6dJUjfVAjQHU8uWyS8BQ/7WEb6AspTkynPECfCoBjQ9dS5PF7fjmz1 -fLm0VMw5Fl082pazw2zUcF3TMKemvW/dQbyo3kJgWZqFJQ0qRcMFtG56Sk3KjArl -bDS8IJttSsrKtqY6oNvDDiAaEht33csdf8MNDefB/ZbSx2iAmaDZijMho4uiWqd+ -JwYCf+1gETc0VBd/TZAUHmk3DbrwK/CjLWJ5yHao6sjnOx/GT8IM16zwd1Nd8FC0 -35sDyk1B4RiyJTCGHWPlZ7FTzWtOgxq5Xi0FFWvUjrGX/DEDV8u/J3/NXyd+Zuc8 -Fwm2ESpPM83rGtNv1RWLi85oa36aleV0fxdX2QIDAQABAoIEAGv5ltvmLQ/A93xc -x0BWEINRkBa2jrfpo9B5dOnuikWtza/Cx+X2NfQHFlSrcHhfr/JX5BsCb2iVo8DM -CXAgeX1VMHS9wQXuxciaHCZDnqxmxUNDU3EjsYQOKLusRcdL6M+Zuz/ny+7PQ0Qw -/N0yS46Wa9oUjon3RKRvTeSV4HIpFpcP3n/eLjDc/ielWuujnTGcBnjNWegvQROp -5/7221YElGh8U84kbK2l9DtfjwoGoTv11lPvOxXE/scg6em7r9j+y3p3TMzMeDtT -YBC6CA4Oa7GrWLJXROOKOQ0ddtvFNlUsZ02vG2QCbqU2y8mwJrJDI80qNbeKGel3 -SfwkssedtGoOOYHxNczwpyVNHVHrHuMPBe75gbo+5pFxVJ5ymCGWfbLJf73oVsqW -ZimoknvkozW4+mlVlcmo3X73IxTW2U4RlXthYdj9KXsBLRaKVCQJDc934eHWkXHU -GF2U2NonqOVd8YG/FmZQ2ig6EcW97hC6wnsWT2Uc7UNAE2RM4bY0xCUHaQiKTrEs -CI6wpbbTV+XhDu2HmL9G+fsuSIu0RoSOCmr5jQDAVwCNPXFgBgcIxbPZ/UCJ7RHj -GrWPBldAN8ip4osiA+B3XwBabcvwXP2fgBP/eLWN1St3q3tw5xpHpqCuhNuPSqsc -0ntz0oIdJyRR6fXWmRFex4kXQ597z5ozm0uyg8arV3HJFxDC3DI6kKfs86/oqMSW -l+9g+d4x6VrUOCTDk0bjN3T8HQ9ASfy9JVacqk6yuXX7a0WeeT+x9JsvFAjg2KmG -CJUtm5w5siItMDSPpcRE4hlfgh+M7ZKS3PFgH3vvwfPMbC/IC93QoSaFzRJMyobX -ei6PNwqJvL+HADlMfLmehE2w9ycp4Fe1Gw/NW0Ed1S6Ajo45hgXQJSIrzla6eglg -JPsPpQ8b+weZNQ8zvc0KvfRJmZKKEb9dHvFdi68I1kV8aapQsjrMOjwHC2pnCFh/ -axkVc7a59fKUs7L6nAJhCs2sSixTorZz5PvJ6mXhWu72TCzu+kThNnEORrlWPHQl -RFEAFpDDaGSzOMlhb92CWUMPyZU2qtzMzv4QGbP5YqTy121hXuT5OBKCF3eNLihV -aje16k0RMFqqW3Olbm7Mp2P1C6DuwzsUJBnNwB5JzhC79Po88zNAl2d1h+qysKU1 -jxF316nhpWJ2dGJ/sbJ+XpUMd/tVrNFQMA254GFfXycsfBoQOSY5d6GfRwKUDOou -xImbIzGUAaIYdsGKDuKtqs5S21JMJjJ/J5CwjLu9tbpP/jsp22KHCpraHAQCupSp -+SFwWI7tRUXzREuxJixfUOnJFQYOATnMFvvtk1d6v4xoPYCVEhHq8gHqJkTyTi3Y -BPVwT1UCggIBAOEy5gThTrEqSVFUcFJm9bJxtWZt/YhOIJWNNxeaxExHzy5hPpsw -fZXtN4MUCeMSWI4isgIujmltwgOHMjQqsJPISn/1gVrqLmrZ2PnFzko/WA8rMUfd -EUnOOpj2bKpChlRGHi76ZV4XGgoTXyO6mrVUcUgf3reSImdcdQ5IHa7J+lWhCQGb -neZIyDOk41LX1TxjcYkY7vuUgmbBYComXPm2UaY3HN4E/3ElXntj6PrlozL33A56 -z4UPfv2Vv9kl0ydkTJe/WcUN2htqLFCYygF2XLlwbv2SYDCT31PkJUORbScUM46A -DOhlxvLBFcpF+l0RtCtvnrKyFy9yZJKrcLh9x6xVChZ/aQqSptSHjll5IEcVm54Y -Z1TjWizCI4txnaBFV0UCLt1CZrllXnyIksZLS4/dVqUIKmkxPBQUpiD5dmgDcmPB -/LdWzS6k4MH3J3Y3tu3MNPHDwgUtnifSZrsWSYPK0F8J0dMU/mLaS9eOplAH7Eo1 -t7OrrImvitM6tUdErRYilIaoS/6YPmsPST5gY1N4n8Lf4sAE/tY8fwaWRpTVSrIw -CoFwLtHESUOhqfuAOdr1EkDfo/RQTUVdnmWZ+D0j3du8MmsMje4x3f2CjBDXqArl -gNnBQELDmrdif8KELNjlEpTIz0T7wEfquhVQ2dzhFpL7RLAgggD+oEBLAoICAQDa -5WOWrAtaI1cC5C7LFxM2qXTHGRttfAtVxuigJapLqNASJuu59GGRxsCVwhthbNFh -aCMSj+fZK7QNFkaoPwuZCEtzy0ErkVZzxYp3cP6b99mzGoCcuqiHiW5qhEkbxwdC -f3YEsSGqE6j8TPW8feiziqo8q+QPSudI9ngkH1gjgbIrTu9iaxKJcF2CwBxe5tfB -uFBNPIgJAaLPejRKQu17MAV2jDnBDIsZUZnm53IxQ+giIYUBay3cfC1KMJu/AnZ/ -CxETjgqqnzqdFW0b0o49Q6YQa6QXAiSjs+lL/BhjbdA5quVdFmA3CoASFQbihYfM -4vilUg7Y4wXfzS7DyBZdfppIn+HI8PPSMv/lfdsQXecl5TU1fBDPRWYPpTZqm1II -HDCkmGRKet/j4/oobabNRrJ6PJcxNjqeMVv/a72pypDRPIXzNxLb1BkfWDGfgu2R -YAdRNBSJSpdoHDZ+1VO2A+/8gz9Zuiv1WxoX7+u3pCAd+0vCfHiaXiFVc7fI8F+m -rtDmN5p3DD9l1+/v7yd+7eUezwxYecElw5E5MyAJRTYGrim8g7XvF/u9rXvH09VP -TeIE8oJ7XzrxCmtGIxlJs6FmgUbUblOyfPZDUqPnzlo8Ru1H2iKRo2FPiMfij8mh -H3wgFTnZpGDQjw/xop51bxVueXrmOeguS0wmk/8Z6wKCAgEA0y+bPApadJRWS1nn -N69sTBqMZfFR6Eh0ECts9criuTJCXZk+T+SqcTYTb+4T04k52Jk63Aby8HXIkuxv -LTK3gu86xkLiOvMP8o43Bwz0BvbeSuNThLQQ6Wjn1NiLUSOvu0pCNgYFl7YMalR+ -TRBK0y/MSDny762wa8Pt1iXVCDxLcY/h1UstSW8JqDzCHcdgJhCPwWTLgMxleZ1w -5DYzzM2oRjq67I49Sssjjo1ESD2fzUVZbY7IG11L1t1fG3F4UiGiHlCJC92Qo1Lv -Geoezj5EeHay70Mcx5F0xsRWGcZAWXx9WO5GrI39g1uFZro3Lp5SmsVDSwrt6UXa -gR0bSThTTw40tqJnTE34+6ff25JWrbLay+jQxm+q+fxZvwQeMNW2IHYKot4JXWVt -tVWSZzjnNJP6FCvTMfDFCYPPw26OFr7cwCaEKx7QriRazitMK3XWK6zsHalZwudj -wK50PpCJAnno7KdVySCP6v4ST6Rr3POBKJq1ml2tITWo96u/ooUJ2I83QAyFr8zw -BBBCvKdBnl6pW+P/TdmhbiEvcmrs59gaA34/6+DbV0Y++piZwswd9XML2iCgLZY8 -0IcZ6uf4PsXq4Yzcrz0HwM+tAXcyiPzkjstpCUxMShALgFxzuWOgdwpjYXnrviJk -0EyUkzbOCHBhbhcK9CyYHfyrJX8CggIAdWwgJC9eV5glkPN+9osGT4hPkI4zXGPy -YK03FNGfrL59/37JbRNfU6fen3dk4LpTB4Gpbserg6AiEfMlLBPF0O3WK+OYrhpk -2e3Z/YCr1Fb8fUt2Op0W0r4ycQlNfo0ho9ZkJNgwSuAJAm72U4rnTYjREYLT8DAq -KcWtZRM7YLCuNvU9DPqLExcn0n/juDT1AIIy8XvLLamnAM15R2znn/F+vL00Lg7g -f1B60pbNdwgKemSoyL4J+ADU+rtgkPJtRnFVU7walLSd6K4ZvZcRnmOvrZdQitcn -eHmGaLBvFMdPr9+w8mKScnQ7h3eoHdOrqYkIAQcn18jQ2eFjeLrY5IaJlPPPVs+K -u/OHuj/tR7ZXzMhL5skK62U6/qGNs1pmgts8bM8i3aFUgRdGlnFbzTpje5cNM+T3 -RO0NgNL3ByIW1Wc2I+YjQ7FfWKUi2YKOljGBO1pIue09kyevRBKDuVwbXMW7MhLg -idm5AaY+OGDeqbaoSUgkGgrsrr5IlI39gZi9jwG85qe3Spavq3ILKdfL1N8UrFGD -/xIN0TVPtilede7vjKTK79tZu8JYaDWGc+g/mo/M1wmawLrqGNGzOwoVRruKl2In -m9PU9wBZ1HuphDQ4DRdC/AU8qkGhmDOx4bDWEQ/R3KKFHNvhnamyfyR7xqt79gyS -NGNIElnJuskCggIARFaK6yAVmaL74Qu3iiELj8FU9Cw8kPP5HeWUfGxCjlegdH3R -FBtoQlDcQjYzO2uZR94Itg3yk3Dt+xbf7KxUsODwlgLj1UhV4eOXUDTosBFTrbTG -v9gnRVH0Eyu9tF+CMUcCXhq6tnIrQOVv1ozcdXfIpk9gvIbfh4rlo6X0iM8Xge2t -Vo7awq05t4wJBkO1xUtOaw9HabaszK/CU1iNV7cIBmaFF3AEP/KVfOs+kjubc9AF -mqC+LVVClvJPNzm1YA5JZlxmQ0u1xXFqZv0OMoibgY+gSzaiAQz3eKB6vEv4Xv4U -kaF9nEUTEjowpTE6uX9X0mGkXXT2wXmlTjosZFnxRX5IIrRNug30plRra5CNYPGp -3uTmD/D7Nzi1iYitJg3yhrTQmCWiJY3x4Z0xophLkio2nlJ9WoTKf1AwTIATY7fa -pX9bxEKldYXrYZNFlbqBPFgA/36v+JDVfMf2E9yRMCt0LAJ0HUM6zP0ngMv+S1TP -Pu6X0WXR9JeuoaF4uJSty/xwdpST/CkHflFLVsk5n3tNQfWGjqoTSOJMgL9NRY9e -Pc/OshHZHeCVFUSXtcf1pfmmBtT6FHX0L4cgVqA5xO8RYapnLDAFLXq2/dRv3NwW -W9CzZcZKh7jmJw4iSIY5IU1+ThgugWoxlkcmjs/egjBclL8BBfqRIwx/vOE= +MIISKgIBAAKCBAEAyqodxBHskfDH/1+QkvxADF63PQDFINUPiTEH10FMi2CAqjgU +3pNrnHSIQWi1AkEBLYaiepVTXntnL2weKVH5RP1KgL6yI6E+GzjPiMRx7vhrQcUt +wMNSrFl9gTQZlTK4mlG2QTbUxKGuhOY4uei/lr4Zemt3TeDe5rO2a7w93Wi8S8Tr +9TaT7VaiFVCKEOjWIu1ssc3DGMn2CuHeYWVi1hRBjLX7FGjBzxJdQSGdVxFDfbtD +LCG7w0R9qM8fw3F1tUfCfc44PHNknhXYpyfPvUDIRQjjyDmoC47CW3vxR5ESkczh +AOCUW70y5AyNw77MdjJSEmmwGOCwwnY0Wl952faBnQIKYWkcM85J+nYDHgdbJwu/ +NJ40lrgDm1A6ai8XehTPZWMAN1Koc85LFED00ppWVDO4dy5CW4/sHxj0rauKSo1t +cCXzWOfLZlEUfRb0621WdnZRbtYd2tONwGRaZ06v4r8z0bj2KvxXh6c1XoDJrPyH +yXEXkb+3TaPtPBsn9Gag+UYDJ8zqgPZLQPZBlM29CrPvJr7eb2muDz8cVWMzkJvt +yloSTd5LBsKikrBCPTGvpBUSFfiK6YiNz/2FZlBvEfGfSPO1up2GaCSiXah8VEL6 +2LXF8t0OD9Bo5FR+xbmgm2Utd/SPuTAK1YZc7cl80dqdDWNQ7uUekmPMogzoSpYC +TdyP33yPCBioMIjXr4mt/FdLEPnxy0jotjvIP/zC09FKEDwba2Tc5WUeW7LaseIk +l4/uwEuOGIN8F6Y8RbNgBiPyLxgTnheKxnJ5jE0E853q4CXTM4weEUdjH6VFP72F +s/6laO5ItwykyX9y0HVmm2r5oFDzqFlto904T3Aru/+SLnGr7+kA7Q3RtG/wjrIJ ++01hDdkQ1VQRzQOUhP2oaORFbh5qHi+FoW31tsDx7vc26f7C963ME0ZbiELwLR+1 +Dn61K+SNq7mHMGo9EvSt8xyszBpIKSqWe4AAC25Zh7+jynCZGxz9cj2y05RKz1V1 +vh9A7FU1SC1V8ADaPLBguhEyZlQLvgakXrfJWbtN9JIGJkhuwhLUfPAguKLhvGq2 +GQ43R1XJ8kkNlnWihGS/NPy+skHk9Yjr4bcmpeVBwiAM9uKoped2VKX7S4AFfRiF +erq8t63AL2CFzBUSHC8KnvN8QM/0PiPSlcrQBlhS8ITYDz3r/xJolHmPvkApX5jI +kGwFL5mMKmN4HyOxKcXnScmykg9TC9VxKBfCGb9gv3yHqKvB9ArBuNJo7sHOpxMT +F20kXaI3ptd9SIsrdC1ALsoZ1bY+bEJx+s+Fh/negHOLifRw8NjX/0BBnMcVbZtu +TLVSApl5MnPKJqCsMW/EsPXau8If4J9EuiX3nwIDAQABAoIEAElnTjqq502AsV+c +hGfId4ZDdAjjU4LtyJ+/I4DihM/ilxeQEnb/XDWhu4w9WXpEgyGzJvxRQ43wElKJ +zW7X4voK58Yzy5++EhmX/QsjY8TTMz3yJf0wgawtCZkXfsCcS2KRf/qk2nGRwf0e +yaMEWwhFOEMv01lgvjs/Ei55Usrz2Wd0HqaFKxUGkNQ5hJhVTOH/rqPDzAsZc0VD +w+Dw8NhrI8bMTvF4c+IFW8NwYmWbuh87CTxdx30VPJI82ttWJ/UN1bLtU08J2IKt +lPgOIl8ArMjcTGxD/cqZ3Wl3Pc/XCqvGUiSYMwP7Rgh1R4+DdtjEpxdGMmMAVuVI +HPQyqpa4gv+UMqBPish0yjSuM7jXnztINOvg9Vk1sxC5AT9eaRltmiS1s+lVxe+T +43ulf0ccYXJD/WclWSGCwloNFuokPIV+Lgo1pKsp4XDgoxQfkXwH8Q4dEqebY9rT +Tv9FGb1bMbdl22X1oSu2lBltBZaB/QnruV7L2GaQ0tqLKizgBRuvZFSE+DWdMb6d +9mnEB8LWtca/nzogXb5qv4GEMUX4FUAmSf1FnGWZwwDi1DFfJ860RVKf0xokGGQ3 +cm3H/F4veds88Z1hsAu0bG8h/bEAim+Whvag995cFHDD4on41KXW8wX1on9VFA1W +CkaGUPhLRytXDBVCSJkOYYFSJlb2wqONiWe4Tn5hsantCfliTj/GVkgDq2h7dAGR +WyoqTntJAv/xJsUOV9WmGXnWNeZX8BSO3P5dnXnMzhCWQGoprXmWFyJ3TYCJ2+CO +rzkZbtuKvTvGc3sDJgrSVmmg0BrOkH+GyYVlJdTDBmfzoORludDCFHECa8oK7NwY +t3o0eNlG6IqTxl2HIoPneW9nXFQtCXv6tpJjljwjlz5WpJG+kBW6bDedcxZu7olZ +fqtnyZTB2SjzzbGdQ4JvFup8MxNyPvYiqumQXJgkyXFVDl/UFhjWuGe04i8NBJgJ +xORcjfgLrKH1XKVBWPJdh/2YeUKIIvQ9RB4WVqXgGmD/21tgv1bVEMYabh23e/HE +Fe1U2XQPJKxGCEtG6b4zhFP+PeZACS+Vk5IVJYK9n4SepPBPgX/wbJLOcKGpsKjp +yx5WjopMO6T+VUV8HIduuZ+E8+uAILHDmo2Bq+LHblaxd4SkM0+hL2H36imK5CUO +5fLuvHW88LvFtQw6xhP20s+BnmgzE5ZvNG4Iedkjvwe9HmdNDew0UYT5vNJN0ehh +OlraBC++JYwEclrBD9SRvprT63XKDG735pPvzLQi7WKDCBn1/JEgxDIO8nkMewOZ +FU48Mdmkn9wqPeIigQciwl62fuAQCGRG+RXMQqra4A1apqMZQEauTK50VhHDGdbc +ye9LHaECggIBAO9lAzoYS/Lu0ticMt24P8BSbGdxSNIpEyIlTTs+7A0UjpfXsoK9 +4EJWZ7lhgbQh+SCTS662SeC+s8M6bT+3mELxUC5S/N3aCPyfjcM3JaoACkI9+VMn +9otJZjAEwH7cNpMN0Xa8fHCEma3l3XKiVxEJbuJC86S5mpkjeXVnDajAidBtevBd +LWJ9n2yXk+ZKUyI0mjpqItwUxOgQ/MOIvqAu66xyjg08/I1QQTuIrReAA+oaVKhp +c42Ufn26hUhNrQCBAtMAO3VC/chciet6vEMNEM13GqLp4+PcPhRX90gO4+bNrScD +WgiW/jc24CGan8gAenBWC/3l/C6JUsMp+ZYmPozsa0zo6edgiO/f2KXe5nP87wZT +MxaYJgnyXJxMefI79kUHPrhpXZxuiSCEWLhCBN34Lhpr2L491i2g/FJj9i6N3EzE +N3ic5Q63o4QFusjqIm3taQQFoGP2Cgg9owz5WJ0uRz/gtOE3XQiQA7+ozoAXOlTw +pJK5MMtVrEoOLIbVJIpxfDcKDp3yorR8QCQLHgDBmFeNCDmk+7YP33dRIc/AVNLF +q7cecqEc7D8AkXX8Q53GfCEg+uqbdeMQXK4BUE9iwRK9RiFhas/RJe73+Iio3S0L +ekLpnnOfvk744ws+JWsLpsfC/ZE7OxBLPtq2xvGl/RT2G7tCjmpX3CbPAoICAQDY +uOEJks2T105EcMPJjzNHCCqjK6S7qZaWkF3KT1Z0Mu5oUZwwHamsMg4BQJ2mjMrL +fRBKfXQLA6vgE7zysw3F300RDxE1RVow5+JLDQ4bqupp27/M0a8fuwksyOdKHqCV +YHzuTCxbVIFZawTjfOxJVXDHKCFCilfY1LsA+V+oFe3Ej8YYxWXkXA9ZLigpmt3s +Wu6eFcZgF3utzIGjI6eP6lL5bWp6Bh9Avp2xrOvpFwE2m02Y7/Zom6MT4DXvByY2 +KHHQLsasEMpeLuxQXjLeTocwcxBwBFKhX95yFuv31k00VydT+NExtaZeUYi9l19J +WmM4GjFjAqa3uUwMNVv5JfWtKMyk4FOox2XftLvMiIhV95B8hAGxtYr3hPkGg80O +AWPq6OKUD332COXRaHkmL5aQdN3gP5zh9+rH6icLrrZbrQidVRyDw03doRoGrH7i +ixXLyYoW80PHgqUDPohd5bFkZpi2vwXMl1YQ2TfN9TvYFSGme9YCm9ZuypnqauW/ +aAf0FI1MNwS+XDREtzPdFi0me6WxpKL4a2Z3GGNxIFuBjQ/uydWpjxkny9qI3KAp +SgjI3kBUDGq3gf0R+Xo/d4d/4asK9Nv2Fi0X+RfGqioFaTbQl/1zhNdvhP9IcwEJ +DLVQ3UhMdfg285RarC2Sihui0M8Smi9od9Dj6rdWMQKCAgEAiQVRFoRnnDGz/wVQ +W/Wkj6jdoUuG+btG10lwbhOyuj3k6+Yqp4iUfoPENKgpu/eiB1InhGWT3Y5ph7m+ +ZDTqco56bTlUwIqWkDmmw3CiHy6MsKOWPFFoXQry8VMW9sWGex7yoDp8I07SQ2WJ +HZ7rpLW4gMr/d25AnZxfXaJRgCBMAT9YmZFLc88hW99aaPproO1oxTyQnVVJ6uYm +NqjjKv4QKJEc21jn2N5xp+iv4f6Evw65G/fXitbOm5oRxXOoLNyqyCie35wrc+37 +hwumC97DmkasuUiUBoy9/5jl0ZmsOiPJEsZpVvdNpD7FhJZjE++qJPgrPvTPJbe1 +5jz1PUrAjJqZQ9kgYC2x01JVR4NQdlz0VrNyT2FgjFrrRQ7E0bAeYh4meRjd2rat +yC3YNgabkI0HnlnSIfl0yIMXSPUsKDNMP6gjc+aheI4FioBZC7xvXmn/rKynw+9E +iLj2xWtGnBir8VTlUu8EUe1UJ/Qv1cL1wT5HhC95TTjJN03rkHUYyCDyjvIzsZX6 +KMHhWIAAeUBVuO7hIVVcOTXWmw2WA7o7ErTPdy13QN40Hk9t8pEkBn9f9vpQg83d +aMypr3LTC80jY11wcZS3tSEpzCCkYVv91FV4cioTZmytWbg9A+dbNWzi1f22ctTr +FoVrAXaSYie2trOy5bjPmPCW8qMCggIBALQUKymBSkDmTqqf6I+65ajIKGWdBizJ +Jc/F9aj9c6DqER+tcFKq0ym6DdkMj/KsWnXrXXYH+DyOuGpg/EfOcEtS2P6rvmi9 +T8wDYg1qs6ZZxp5fcmgGc7Wx/FWyOj1kZZq5qhV4RgM9nJ1oR4+fZdcpn6RcvAZG +XehWG20byVgpoIAL11cN7zRpKne32rd3b5/NjyjcfxGpcaNgovej0L/MvVV0jV0H +aUCrIu1X+k6cRu3Q7hF+kwkpCcCiNS6AikfGI4wQ0hR3fy/zXXkKTMpcBglEEwyB +Cwf8WSID2d79uvka0hr8TRc5ERyeMzkWZp7U9EzRtufGdDGFTqN2Uw4bdKCFnkYC +AIHl7ciMrN+vM1n7c5uDNMUtTGOPojy/l8tjbFrtWBgfJ1Mg4ZW3cbNBJ6Kw+Qw0 +z28USYoEDp2uduiGRvo0lpUF29Wk37Nb8bLcTygeNxgK2u8Up3iipT0gdt4uQgbX +g0IVHfayB6SjeS57oJJto85XHz7AKlSWroD1OGagDSifLtneU7AlanryymGHrI6H +dsNkuqeLJFYDxQVI6UxJebiCpyxiPxwp9wtX8SS3SEyOZL5GzLn6ypGiCH1CTpW0 +EHHSy3V4DUGOc4w7eMirAnbSkxCfOmBA70NNw/uFY2XlQHKow0T0fImfKIeJagbT +B0GPDYvUpLKBAoICAQCzYnq8xupXK7lvTLaj936qGSe54OC2sj9+UpsFiPxglNY2 +sO5zKWKyY7+rjK6zG2ciGfPEDsZNIqKw1W/KBfR2kRLqkt4bC3fSCvUztx0vtGUe +veXlqiwETdE7RJXoaGJrgJArYJvpOd8PtWGeM+sSJNNrUlGlJnSiZ0CcypqUZgZL +WzGFfLOQYAXCykdB1iZkBqU2C5wktvCb9sVz6G3TmAwSKTENOWWZWmh+W0J4pZFV +ZEyvsxViJRQbwxa0kC0F5J/UtWZknO79/ZFj1H4jiAR45EjWHE+UZAkFwG8BSl54 +EKOx7GDanuRILr0dtbyi4d31nCYXdjs3x2+1N3exw4oKQIvNuF54WoowbNPu0kEb +G+7/kLwcJqRnSV4AiLuMz5aOte7JJSw5tzgZZlAQwJO7IDfrLqodivcXF5yirwiF +dyBpzSDmupy/aTHnCpT+l0H96jRU2awxaeRHZUqZog8gMHsslNVZEFvUFDJ7AUN/ +yyfUzJYjH18pZt0hS7jNb1O7KxZCkWGMiEcxHkgF/UINab5qruNBVKOkJ5vqGhYi +uNkgeGsQtXJcpqMRRiVXJE0kE+26gk+iaYnBJN9jnwy8OEAlYFUHsbCPObe/vPMQ +3RLl+ZoKdFkN/gTiy70wUTRVw+tWk+iAZc7GPX1CqDFOqGZ2t+xdF8hpsMtEww== -----END RSA PRIVATE KEY----- diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test index ad051503fd6..19b8aa236b9 100644 --- a/mysql-test/t/openssl_1.test +++ b/mysql-test/t/openssl_1.test @@ -15,8 +15,8 @@ insert into t1 values (5); grant select on test.* to ssl_user1@localhost require SSL; grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA"; -grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB/emailAddress=abstract.mysql.developer@mysql.com"; -grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB/emailAddress=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB"; +grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB"; +grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB" ISSUER "/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB"; grant select on test.* to ssl_user5@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "xxx"; flush privileges; From e9bce6c9d4bde35306b845e22e9b5ada69c4512f Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 29 Jan 2010 20:42:22 +0200 Subject: [PATCH 307/344] Patch set contributed by Alex Budovski (MCA) Fix for Bug#31173: mysqlslap.exe crashes if called without any parameters .bzrignore: Fixed .bzrignore rules. Many were simply not ignoring what they were meant to. client/mysqlslap.c: Fixed bug for Bug#31173: mysqlslap.exe crashes if called without any parameters The original patch could cause memory leaks and odd problems depending on how connection was made. This code ensures that all mysql_options() are set for each mysql_real_connect(). (This patch by Monty) mysys/my_thr_init.c: Fixed multiply-initialized critical section on Windows, due to code incorrectly checking the wrong field in an attempt to prevent multiple-initialization. sql-common/client.c: Don't use shared memory if it's not set (for example after failed mysql_real_connect). Ensure that mysql_close() resets all resources so that it's safe to call it twice. (Patch by monty, related to Bug#31173: mysqlslap.exe crashes if called without any parameters) sql/CMakeLists.txt: Added page fault counters for SHOW PROFILE on Windows. sql/mysqld.cc: Fixed attempt to set a NULL event. The code now only sets the event if appropriate (i.e. shared memory is being used) sql/sql_profile.cc: Added page fault counters for SHOW PROFILE on Windows. sql/sql_profile.h: Added page fault counters for SHOW PROFILE on Windows. sql/udf_example.def: Some cleanup functions were not exported from udf_example.dll, causing them to never be executed, and as a result multiple-initialization of kernel objects occurred and resources were not being freed correctly. storage/maria/ma_close.c: Condition variable share->key_del_cond was never being destroyed, while its containing heap block was being freed in maria_close(), leaking kernel resources. --- .bzrignore | 12 ++++----- client/mysqlslap.c | 37 +++++++++++++++----------- mysys/my_thr_init.c | 2 +- sql-common/client.c | 18 +++++++++++-- sql/CMakeLists.txt | 2 +- sql/mysqld.cc | 11 +++++--- sql/sql_profile.cc | 57 ++++++++++++++++++++++++++++++++++++++++ sql/sql_profile.h | 8 ++++++ sql/udf_example.def | 2 ++ storage/maria/ma_close.c | 1 + 10 files changed, 121 insertions(+), 29 deletions(-) diff --git a/.bzrignore b/.bzrignore index 73826984b17..34e7c1cd1c1 100644 --- a/.bzrignore +++ b/.bzrignore @@ -40,15 +40,15 @@ *.dsp *.Po *.Plo -*/*.dir/* +*.dir/ */*_pure_*warnings */.deps */.libs/* */.pure -*/debug/* -*/minsizerel/* -*/release/* -*/relwithdebinfo/* +debug/ +MinSizeRel/ +Release/ +RelWithDebInfo/ *~ .*.swp ./CMakeCache.txt @@ -96,7 +96,7 @@ BitKeeper/tmp/gone BitKeeper/tmp BitKeeper/log BitKeeper/etc/SCCS -CMakeFiles/* +CMakeFiles/ COPYING COPYING.LIB Docs/#manual.texi# diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 43d963cc22f..c9c7e057202 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -292,6 +292,25 @@ static int gettimeofday(struct timeval *tp, void *tzp) } #endif +void set_mysql_connect_options(MYSQL *mysql) +{ + if (opt_compress) + mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS); +#ifdef HAVE_OPENSSL + if (opt_use_ssl) + mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, + opt_ssl_capath, opt_ssl_cipher); +#endif + if (opt_protocol) + mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); +#ifdef HAVE_SMEM + if (shared_memory_base_name) + mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); +#endif + mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset); +} + + int main(int argc, char **argv) { MYSQL mysql; @@ -323,20 +342,7 @@ int main(int argc, char **argv) exit(1); } mysql_init(&mysql); - if (opt_compress) - mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); -#ifdef HAVE_OPENSSL - if (opt_use_ssl) - mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, - opt_ssl_capath, opt_ssl_cipher); -#endif - if (opt_protocol) - mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); -#endif - mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); + set_mysql_connect_options(&mysql); if (!opt_only_print) { @@ -1815,6 +1821,7 @@ pthread_handler_t run_task(void *p) my_progname, mysql_error(mysql)); exit(0); } + set_mysql_connect_options(mysql); if (mysql_thread_init()) { @@ -1855,7 +1862,6 @@ limit_not_met: my_progname, mysql_error(mysql)); exit(0); } - if (slap_connect(mysql)) goto end; } @@ -2223,6 +2229,7 @@ slap_connect(MYSQL *mysql) int x, connect_error= 1; for (x= 0; x < 10; x++) { + set_mysql_connect_options(mysql); if (mysql_real_connect(mysql, host, user, opt_password, create_schema_string, opt_mysql_port, diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index e105b48f386..9de8b2764da 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -317,7 +317,7 @@ my_bool my_thread_init(void) /* Skip initialization if the thread specific variable is already initialized */ - if (THR_KEY_mysys.id) + if (THR_KEY_mysys.init) goto end; tmp= &THR_KEY_mysys; #endif diff --git a/sql-common/client.c b/sql-common/client.c index 60a1441a189..e09d94b34be 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1940,7 +1940,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, #if defined(HAVE_SMEM) if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) && - (!host || !strcmp(host,LOCAL_HOST))) + (!host || !strcmp(host,LOCAL_HOST)) && + mysql->options.shared_memory_base_name) { if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) == INVALID_HANDLE_VALUE) @@ -1949,7 +1950,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ("host: '%s' socket: '%s' shared memory: %s have_tcpip: %d", host ? host : "", unix_socket ? unix_socket : "", - (int) mysql->options.shared_memory_base_name, + mysql->options.shared_memory_base_name, (int) have_tcpip)); if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) goto error; @@ -2752,6 +2753,13 @@ void mysql_detach_stmt_list(LIST **stmt_list __attribute__((unused)), } +/* + Close a MySQL connection and free all resources attached to it. + + This function is coded in such that it can be called multiple times + (As some clients call this after mysql_real_connect() fails) +*/ + void STDCALL mysql_close(MYSQL *mysql) { DBUG_ENTER("mysql_close"); @@ -2785,10 +2793,16 @@ void STDCALL mysql_close(MYSQL *mysql) } #endif if (mysql != mysql->master) + { mysql_close(mysql->master); + mysql->master= 0; + } #ifndef MYSQL_SERVER if (mysql->thd) + { (*mysql->methods->free_embedded_thd)(mysql); + mysql->thd= 0; + } #endif if (mysql->free_me) my_free((uchar*) mysql,MYF(0)); diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index e50da7b88d3..e8bc72f15d7 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -97,7 +97,7 @@ SET_TARGET_PROPERTIES(mysqld PROPERTIES ENABLE_EXPORTS TRUE) SET (MYSQLD_CORE_LIBS mysys zlib dbug strings yassl taocrypt vio regex sql libevent) TARGET_LINK_LIBRARIES(mysqld ${MYSQLD_CORE_LIBS} ${MYSQLD_STATIC_ENGINE_LIBS}) -TARGET_LINK_LIBRARIES(mysqld ws2_32.lib) +TARGET_LINK_LIBRARIES(mysqld ws2_32.lib psapi.lib) IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index dce2219aeed..a45950c3af9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1173,11 +1173,14 @@ static void __cdecl kill_server(int sig_ptr) /* Send event to smem_event_connect_request for aborting */ - if (!SetEvent(smem_event_connect_request)) + if (opt_enable_shared_memory) { - DBUG_PRINT("error", - ("Got error: %ld from SetEvent of smem_event_connect_request", - GetLastError())); + if (!SetEvent(smem_event_connect_request)) + { + DBUG_PRINT("error", + ("Got error: %ld from SetEvent of smem_event_connect_request", + GetLastError())); + } } #endif diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index bd871bb41a2..2312f95d8e2 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -131,6 +131,23 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table) #define RUSAGE_USEC(tv) ((tv).tv_sec*1000*1000 + (tv).tv_usec) #define RUSAGE_DIFF_USEC(tv1, tv2) (RUSAGE_USEC((tv1))-RUSAGE_USEC((tv2))) +#ifdef __WIN__ +inline ULONGLONG FileTimeToQuadWord(FILETIME *ft) +{ + ULONGLONG nrv = 0; + nrv |= ft->dwHighDateTime; + nrv <<= 32; + nrv |= ft->dwLowDateTime; + return nrv; +} + + +// Get time difference between to FILETIME objects in seconds. +inline double GetTimeDiffInSeconds(FILETIME *a, FILETIME *b) +{ + return ((FileTimeToQuadWord(a) - FileTimeToQuadWord(b)) / 1e7); +} +#endif /* __WIN__ */ PROF_MEASUREMENT::PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg) @@ -221,6 +238,11 @@ void PROF_MEASUREMENT::collect() time_usecs= (double) my_getsystime() / 10.0; /* 1 sec was 1e7, now is 1e6 */ #ifdef HAVE_GETRUSAGE getrusage(RUSAGE_SELF, &rusage); +#elif defined(__WIN__) + FILETIME ftDummy; + GetProcessTimes(GetCurrentProcess(), &ftDummy, &ftDummy, &ftKernel, &ftUser); + GetProcessIoCounters(GetCurrentProcess(), &io_count); + GetProcessMemoryInfo(GetCurrentProcess(), &mem_count, sizeof(mem_count)); #endif } @@ -586,6 +608,23 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) (1000.0*1000), &cpu_stime_decimal); + table->field[4]->store_decimal(&cpu_utime_decimal); + table->field[5]->store_decimal(&cpu_stime_decimal); + table->field[4]->set_notnull(); + table->field[5]->set_notnull(); +#elif defined(__WIN__) + my_decimal cpu_utime_decimal, cpu_stime_decimal; + + double2my_decimal(E_DEC_FATAL_ERROR, + GetTimeDiffInSeconds(&entry->ftUser, + &previous->ftUser), + &cpu_utime_decimal); + double2my_decimal(E_DEC_FATAL_ERROR, + GetTimeDiffInSeconds(&entry->ftKernel, + &previous->ftKernel), + &cpu_stime_decimal); + + // Store the result. table->field[4]->store_decimal(&cpu_utime_decimal); table->field[5]->store_decimal(&cpu_stime_decimal); table->field[4]->set_notnull(); @@ -612,6 +651,17 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) table->field[9]->store((uint32)(entry->rusage.ru_oublock - previous->rusage.ru_oublock)); table->field[9]->set_notnull(); +#elif defined(__WIN__) + ULONGLONG reads_delta = entry->io_count.ReadOperationCount - + previous->io_count.ReadOperationCount; + ULONGLONG writes_delta = entry->io_count.WriteOperationCount - + previous->io_count.WriteOperationCount; + + table->field[8]->store((uint32)reads_delta); + table->field[8]->set_notnull(); + + table->field[9]->store((uint32)writes_delta); + table->field[9]->set_notnull(); #else /* TODO: Add block IO info for non-BSD systems */ #endif @@ -634,6 +684,13 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) table->field[13]->store((uint32)(entry->rusage.ru_minflt - previous->rusage.ru_minflt), true); table->field[13]->set_notnull(); +#elif defined(__WIN__) + /* Windows APIs don't easily distinguish between hard and soft page + faults, so we just fill the 'major' column and leave the second NULL. + */ + table->field[12]->store((uint32)(entry->mem_count.PageFaultCount - + previous->mem_count.PageFaultCount), true); + table->field[12]->set_notnull(); #else /* TODO: Add page fault info for non-BSD systems */ #endif diff --git a/sql/sql_profile.h b/sql/sql_profile.h index 3ddec4e3811..71237b59d96 100644 --- a/sql/sql_profile.h +++ b/sql/sql_profile.h @@ -36,6 +36,10 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table); #if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) #include "mysql_priv.h" +#ifdef __WIN__ +#include +#endif + #ifdef HAVE_SYS_RESOURCE_H #include #endif @@ -165,6 +169,10 @@ private: char *status; #ifdef HAVE_GETRUSAGE struct rusage rusage; +#elif defined(__WIN__) + FILETIME ftKernel, ftUser; + IO_COUNTERS io_count; + PROCESS_MEMORY_COUNTERS mem_count; #endif char *function; diff --git a/sql/udf_example.def b/sql/udf_example.def index 3d569941cc8..41150b24e8f 100644 --- a/sql/udf_example.def +++ b/sql/udf_example.def @@ -3,8 +3,10 @@ VERSION 1.0 EXPORTS lookup lookup_init + lookup_deinit reverse_lookup reverse_lookup_init + reverse_lookup_deinit metaphon_init metaphon_deinit metaphon diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c index 235b37f7030..e46beec71b4 100644 --- a/storage/maria/ma_close.c +++ b/storage/maria/ma_close.c @@ -177,6 +177,7 @@ int maria_close(register MARIA_HA *info) { (void) pthread_mutex_destroy(&share->intern_lock); (void) pthread_mutex_destroy(&share->close_lock); + (void) pthread_cond_destroy(&share->key_del_cond); my_free((uchar *)share, MYF(0)); /* If share cannot be freed, it's because checkpoint has previously From f327a37cf7537f14a7b3f68d2996fc3101fdba92 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 29 Jan 2010 21:35:56 +0100 Subject: [PATCH 308/344] Support building with system libevent --- config/ac-macros/libevent.m4 | 76 +++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/config/ac-macros/libevent.m4 b/config/ac-macros/libevent.m4 index 58ba2d6ebde..a3479fbf0ca 100644 --- a/config/ac-macros/libevent.m4 +++ b/config/ac-macros/libevent.m4 @@ -14,13 +14,6 @@ AC_DEFUN([MYSQL_USE_BUNDLED_LIBEVENT], [ libevent_libs="\$(top_builddir)/extra/libevent/libevent.a" libevent_includes="-I\$(top_srcdir)/extra/libevent" - libevent_test_option="--mysqld=--thread-handling=pool-of-threads" - AC_SUBST(libevent_libs) - AC_SUBST(libevent_includes) - AC_SUBST(libevent_test_option) - - AC_DEFINE([HAVE_LIBEVENT], [1], [If we want to use libevent and have connection pooling]) - AC_MSG_RESULT([using bundled libevent]) dnl Get the upstream file with the original libevent configure macros. dnl Use builtin include for this, to work around path problems in old versions of aclocal. @@ -39,17 +32,64 @@ AC_DEFUN([MYSQL_CHECK_LIBEVENT], [ AC_CONFIG_FILES(extra/libevent/Makefile) - AC_MSG_CHECKING(for libevent) - AC_ARG_WITH([libevent], - [ --with-libevent use libevent and have connection pooling], - [with_libevent=$withval], - [with_libevent=no] - ) + AC_MSG_NOTICE([checking what libevent library to use]) - if test "$with_libevent" != "no"; then - MYSQL_USE_BUNDLED_LIBEVENT - else - AC_MSG_RESULT([disabled]) + AC_ARG_WITH([libevent], + AC_HELP_STRING([--with-libevent=yes|no|bundled|DIR], + [Use libevent and have connection pooling. + A location of libevent library can be specified. + Given DIR, libevent library is + assumed to be in $DIR/lib and header files + in $DIR/include.]), + [with_libevent=${withval}], + [with_libevent=no]) + + case "$with_libevent" in + "no") + with_libevent=disabled + ;; + "bundled") + MYSQL_USE_BUNDLED_LIBEVENT + ;; + "" | "yes") + libevent_includes="" + libevent_libs="-levent" + AC_CHECK_LIB(event, event_get_version,[with_libevent=system], + [with_libevent=bundled]) + AC_CHECK_HEADER(event.h,,[with_libevent=bundled]) + if test "$with_libevent" = "bundled"; then + MYSQL_USE_BUNDLED_LIBEVENT + fi + ;; + *) + # Test for libevent using all known library file endings + if test \( -f "$with_libevent/lib/libevent.a" -o \ + -f "$with_libevent/lib/libevent.so" -o \ + -f "$with_libevent/lib/libevent.sl" -o \ + -f "$with_libevent/lib/libevent.dylib" \) \ + -a -f "$with_libevent/include/event.h"; then + libevent_includes="-I$with_libevent/include" + libevent_libs="-L$with_libevent/lib -levent" + AC_CHECK_LIB(event, event_get_version,[with_libevent=$with_libevent], + [with_libevent=no], [$libevent_libs]) + else + with_libevent=no + fi + if test "$with_libevent" = "no"; then + AC_MSG_ERROR([libevent headers or binaries were not found]) + fi + ;; + esac + AC_MSG_CHECKING(for libevent) + AC_MSG_RESULT([$with_libevent]) + + if test "$with_libevent" != "disabled"; then + libevent_test_option="--mysqld=--thread-handling=pool-of-threads" + AC_SUBST(libevent_libs) + AC_SUBST(libevent_includes) + AC_SUBST(libevent_test_option) + AC_DEFINE([HAVE_LIBEVENT], [1], [If we want to use libevent and have connection pooling]) fi - AM_CONDITIONAL([HAVE_LIBEVENT], [ test "$with_libevent" != "no" ]) + AM_CONDITIONAL([HAVE_LIBEVENT], [ test "$with_libevent" != "disabled" ]) ]) + From d25273ed223a54b5d983709e07d6ef52ce9c6ef6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 29 Jan 2010 21:37:22 +0100 Subject: [PATCH 309/344] hide nm warnings in configure --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 96bc09a4470..16f16f6b8bc 100644 --- a/configure.in +++ b/configure.in @@ -604,7 +604,7 @@ AC_CHECK_TOOL([NM], [nm]) if test "$TARGET_LINUX" = "true" -a "$static_nss" = "" then - tmp=`$NM ${other_libc_lib:-/usr/lib*}/libc.a | grep _nss_files_getaliasent_r1` + tmp=`$NM ${other_libc_lib:-/usr/lib*}/libc.a 2>&1 | grep _nss_files_getaliasent_r1` if test -n "$tmp" then STATIC_NSS_FLAGS="-lc -lnss_files -lnss_dns -lresolv" From 7cb11859c7ba09709546038078e0617da9fa9537 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 30 Jan 2010 13:39:39 +0100 Subject: [PATCH 310/344] now we force at least libevent-1.4 --- config/ac-macros/libevent.m4 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/ac-macros/libevent.m4 b/config/ac-macros/libevent.m4 index a3479fbf0ca..73fa59a1d3c 100644 --- a/config/ac-macros/libevent.m4 +++ b/config/ac-macros/libevent.m4 @@ -54,9 +54,9 @@ AC_DEFUN([MYSQL_CHECK_LIBEVENT], [ "" | "yes") libevent_includes="" libevent_libs="-levent" - AC_CHECK_LIB(event, event_get_version,[with_libevent=system], + AC_CHECK_LIB(event, evutil_socketpair,[with_libevent=system], [with_libevent=bundled]) - AC_CHECK_HEADER(event.h,,[with_libevent=bundled]) + AC_CHECK_HEADER(evutil.h,,[with_libevent=bundled]) if test "$with_libevent" = "bundled"; then MYSQL_USE_BUNDLED_LIBEVENT fi @@ -67,10 +67,10 @@ AC_DEFUN([MYSQL_CHECK_LIBEVENT], [ -f "$with_libevent/lib/libevent.so" -o \ -f "$with_libevent/lib/libevent.sl" -o \ -f "$with_libevent/lib/libevent.dylib" \) \ - -a -f "$with_libevent/include/event.h"; then + -a -f "$with_libevent/include/evutil.h"; then libevent_includes="-I$with_libevent/include" libevent_libs="-L$with_libevent/lib -levent" - AC_CHECK_LIB(event, event_get_version,[with_libevent=$with_libevent], + AC_CHECK_LIB(event, evutil_socketpair,[with_libevent=$with_libevent], [with_libevent=no], [$libevent_libs]) else with_libevent=no From d9e9a73e8f1355a24b27d64d56d555d045ee0b4c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 30 Jan 2010 20:49:25 +0800 Subject: [PATCH 311/344] Bug #48321 CURRENT_USER() incorrectly replicated for DROP/RENAME USER; REVOKE/GRANT; ALTER EVENT. The following statements support the CURRENT_USER() where a user is needed. DROP USER RENAME USER CURRENT_USER() ... GRANT ... TO CURRENT_USER() REVOKE ... FROM CURRENT_USER() ALTER DEFINER = CURRENT_USER() EVENT but, When these statements are binlogged, CURRENT_USER() just is binlogged as 'CURRENT_USER()', it is not expanded to the real user name. When slave executes the log event, 'CURRENT_USER()' is expand to the user of slave SQL thread, but SQL thread's user name always NULL. This breaks the replication. After this patch, All above statements are rewritten when they are binlogged. The CURRENT_USER() is expanded to the real user's name and host. --- .../extra/rpl_tests/rpl_current_user.test | 127 ++ .../suite/rpl/r/rpl_binlog_grant.result | 42 +- mysql-test/suite/rpl/r/rpl_events.result | 42 + .../suite/rpl/r/rpl_innodb_mixed_dml.result | 4 +- mysql-test/suite/rpl/r/rpl_sp.result | 16 +- mysql-test/suite/rpl/r/rpl_user.result | 1755 ++++++++++++++++- mysql-test/suite/rpl/t/rpl_binlog_grant.test | 8 +- mysql-test/suite/rpl/t/rpl_events.test | 82 + mysql-test/suite/rpl/t/rpl_user.test | 83 +- sql/events.cc | 79 +- sql/sql_acl.cc | 124 +- sql/sql_lex.h | 25 + sql/sql_yacc.yy | 36 +- 13 files changed, 2319 insertions(+), 104 deletions(-) create mode 100644 mysql-test/extra/rpl_tests/rpl_current_user.test diff --git a/mysql-test/extra/rpl_tests/rpl_current_user.test b/mysql-test/extra/rpl_tests/rpl_current_user.test new file mode 100644 index 00000000000..7ec38e0c151 --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_current_user.test @@ -0,0 +1,127 @@ +--let $count=1 +connection master; + +if (`SELECT '$diff_table' = ''`) +{ + let $diff_table= mysql.user; +} + +--echo +--echo +--echo +--echo TEST STATEMENT: '$statement' +--echo -------------------------------------------------------------------------- + +if (`SELECT '$diff_columns' = ''`) +{ + eval CREATE VIEW test.bug48321_v1 AS SELECT user FROM $diff_table + WHERE user LIKE 'bug48321%'; +} + +if (`SELECT '$diff_columns' <> ''`) +{ + eval CREATE VIEW test.bug48321_v1 AS SELECT user, $diff_columns + FROM $diff_table WHERE user LIKE 'bug48321%'; +} + +while (`SELECT $count < 6`) +{ + --echo + --echo TEST STATEMENT: '$statement' + --echo CASE $count: + --echo ------- + + let $user2= 'bug48321_2'@'localhost'; + let $user3= 'bug48321_3'@'localhost'; + + let $user1= CURRENT_USER(); + if (`SELECT '$action'='RENAME'`) + { + let $user1= $user1 TO 'bug48321_4'@'localhost'; + let $user2= $user2 TO 'bug48321_5'@'localhost'; + let $user3= $user3 TO 'bug48321_6'@'localhost'; + } + + if (`SELECT '$action'='GRANT'`) + { + let $user1= $user1 IDENTIFIED BY 'user1'; + let $user3= $user3 IDENTIFIED BY ''; + } + + if (`SELECT $count=1`) + { + --echo # Only CURRENT_USER() in the user list of the test statement. + let $users_list= $user1; + } + + if (`SELECT $count=2`) + { + --echo # Two users are in the test statement, CURRENT_USER is the first one. + let $users_list= $user1, $user2; + } + + if (`SELECT $count=3`) + { + --echo # Two users are in the test statement, CURRENT_USER is the last one. + let $users_list= $user2, $user1; + } + + if (`SELECT $count=4`) + { + --echo # Three users are in the test statement, CURRENT_USER is the second one. + let $users_list= $user2, $user1, $user3; + } + + if (`SELECT $count=5`) + { + --echo # CURRENT_USER is not in the test statement. + let $users_list= $user2, $user3; + } + + --echo users_list= $users_list + --echo + --echo # Connect to master with user1, so user1 always is the current user, + --echo # when test statement is runing. + eval GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; + eval CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + + if (`SELECT '$action'='REVOKE'`) + { + --echo + --echo # Grant some privileges to users at first when testing + --echo # 'REVOKE ...' statement. + eval GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', + 'bug48321_3'@'localhost' WITH GRANT OPTION; + eval GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', + 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + } + + connect (conn1, 127.0.0.1, 'bug48321_1'@'localhost',,); + connection conn1; + --echo + let $temp= `SELECT "$statement"`; + eval $temp; + --echo + + disconnect conn1; + + connection master; + sync_slave_with_master; + + connection master; + let $diff_table_1= master:test.bug48321_v1; + let $diff_table_2= slave:test.bug48321_v1; + source include/diff_tables.inc; + --echo + + --echo # Delete all bug48321% users + connection master; + DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; + DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; + FLUSH PRIVILEGES; + + inc $count; +} +DROP VIEW test.bug48321_v1; diff --git a/mysql-test/suite/rpl/r/rpl_binlog_grant.result b/mysql-test/suite/rpl/r/rpl_binlog_grant.result index 4a789f361c6..adf2175f3bb 100644 --- a/mysql-test/suite/rpl/r/rpl_binlog_grant.result +++ b/mysql-test/suite/rpl/r/rpl_binlog_grant.result @@ -17,16 +17,15 @@ show grants for x@y; Grants for x@y GRANT USAGE ON *.* TO 'x'@'y' GRANT SELECT ON `d1`.`t` TO 'x'@'y' -show binlog events; +show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 4 Format_desc 1 106 Server ver: VERSION, Binlog ver: 4 -master-bin.000001 106 Query 1 193 drop database if exists d1 -master-bin.000001 193 Query 1 272 create database d1 -master-bin.000001 272 Query 1 370 use `d1`; create table t (s1 int) engine=innodb -master-bin.000001 370 Query 1 436 BEGIN -master-bin.000001 436 Query 1 521 use `d1`; insert into t values (1) -master-bin.000001 521 Xid 1 548 COMMIT /* XID */ -master-bin.000001 548 Query 1 633 use `d1`; grant select on t to x@y +master-bin.000001 # Query # # drop database if exists d1 +master-bin.000001 # Query # # create database d1 +master-bin.000001 # Query # # use `d1`; create table t (s1 int) engine=innodb +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `d1`; insert into t values (1) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `d1`; grant select on t to 'x'@'y' start transaction; insert into t values (2); revoke select on t from x@y; @@ -38,19 +37,18 @@ s1 show grants for x@y; Grants for x@y GRANT USAGE ON *.* TO 'x'@'y' -show binlog events; +show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 4 Format_desc 1 106 Server ver: VERSION, Binlog ver: 4 -master-bin.000001 106 Query 1 193 drop database if exists d1 -master-bin.000001 193 Query 1 272 create database d1 -master-bin.000001 272 Query 1 370 use `d1`; create table t (s1 int) engine=innodb -master-bin.000001 370 Query 1 436 BEGIN -master-bin.000001 436 Query 1 521 use `d1`; insert into t values (1) -master-bin.000001 521 Xid 1 548 COMMIT /* XID */ -master-bin.000001 548 Query 1 633 use `d1`; grant select on t to x@y -master-bin.000001 633 Query 1 699 BEGIN -master-bin.000001 699 Query 1 784 use `d1`; insert into t values (2) -master-bin.000001 784 Xid 1 811 COMMIT /* XID */ -master-bin.000001 811 Query 1 899 use `d1`; revoke select on t from x@y +master-bin.000001 # Query # # drop database if exists d1 +master-bin.000001 # Query # # create database d1 +master-bin.000001 # Query # # use `d1`; create table t (s1 int) engine=innodb +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `d1`; insert into t values (1) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `d1`; grant select on t to 'x'@'y' +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `d1`; insert into t values (2) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `d1`; revoke select on t from 'x'@'y' drop user x@y; drop database d1; diff --git a/mysql-test/suite/rpl/r/rpl_events.result b/mysql-test/suite/rpl/r/rpl_events.result index b3fd85d7e28..206ec52718c 100644 --- a/mysql-test/suite/rpl/r/rpl_events.result +++ b/mysql-test/suite/rpl/r/rpl_events.result @@ -251,3 +251,45 @@ DROP EVENT event44331_1; DROP EVENT event44331_2; DROP EVENT event44331_3; DROP EVENT event44331_4; +DROP VIEW IF EXISTS events_view; +DROP EVENT IF EXISTS event48321_1; +DROP EVENT IF EXISTS event48321_2; +DROP EVENT IF EXISTS event48321_3; +DROP EVENT IF EXISTS event48321_4; +CREATE VIEW events_view AS +SELECT EVENT_SCHEMA, EVENT_NAME, DEFINER FROM INFORMATION_SCHEMA.EVENTS +WHERE EVENT_NAME LIKE 'event48321%'; +CREATE DEFINER=CURRENT_USER() /*!50000 EVENT event48321_1 */ +ON SCHEDULE AT CURRENT_TIMESTAMP +ON COMPLETION PRESERVE DISABLE +DO SELECT 48321 as BUG; +CREATE DEFINER=CURRENT_USER() EVENT event48321_2 +ON SCHEDULE AT CURRENT_TIMESTAMP +ON COMPLETION PRESERVE DISABLE +DO SELECT 48321 as BUG; +CREATE /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 +ON SCHEDULE AT CURRENT_TIMESTAMP +ON COMPLETION PRESERVE DISABLE +DO SELECT 48321 as BUG; +Comparing tables master:test.events_view and slave:test.events_view +ALTER DEFINER=CURRENT_USER() EVENT event48321_1 RENAME TO event48321_4; +ALTER DEFINER=CURRENT_USER() EVENT event48321_2 +ON SCHEDULE AT CURRENT_TIMESTAMP +ON COMPLETION PRESERVE DISABLE +DO SELECT 48321 as BUG; +ALTER /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 +ON SCHEDULE AT CURRENT_TIMESTAMP +ON COMPLETION PRESERVE DISABLE +DO SELECT 48321 as BUG; +Comparing tables master:test.events_view and slave:test.events_view +ALTER /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 +ON SCHEDULE AT CURRENT_TIMESTAMP +ON COMPLETION PRESERVE DISABLE +DO SELECT 48321 as BUG; ALTER EVENT event48321_2 ENABLE | +Comparing tables master:test.events_view and slave:test.events_view +ALTER EVENT event48321_3 ENABLE; +Comparing tables master:test.events_view and slave:test.events_view +DROP EVENT event48321_4; +DROP EVENT event48321_2; +DROP EVENT event48321_3; +DROP VIEW events_view; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index fbfebbaa590..74ebb3be948 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -750,7 +750,7 @@ test_rpl e2 root@localhost SYSTEM RECURRING NULL 1 # # NULL ENABLED 1 latin1 lat USE test_rpl; SHOW EVENTS; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation -test_rpl e2 @ SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +test_rpl e2 root@localhost SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci ==========MASTER========== SELECT COUNT(*) FROM t1; COUNT(*) @@ -1079,7 +1079,7 @@ master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Query 1 # use `test_rpl`; INSERT INTO t1 VALUES(1, 'test1') master-bin.000001 # Xid 1 # # master-bin.000001 # Query 1 # use `test_rpl`; CREATE DEFINER=`root`@`localhost` EVENT e1 ON SCHEDULE EVERY '1' SECOND COMMENT 'e_second_comment' DO DELETE FROM t1 -master-bin.000001 # Query 1 # use `test_rpl`; ALTER EVENT e1 RENAME TO e2 +master-bin.000001 # Query 1 # use `test_rpl`; ALTER DEFINER=`root`@`localhost` EVENT e1 RENAME TO e2 master-bin.000001 # Query 1 # use `test_rpl`; DROP EVENT e2 master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Query 1 # use `test_rpl`; DELETE FROM t1 diff --git a/mysql-test/suite/rpl/r/rpl_sp.result b/mysql-test/suite/rpl/r/rpl_sp.result index 7fedaf4c1ef..02a5f33c843 100644 --- a/mysql-test/suite/rpl/r/rpl_sp.result +++ b/mysql-test/suite/rpl/r/rpl_sp.result @@ -433,9 +433,9 @@ master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 like t1 master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` PROCEDURE `foo3`() DETERMINISTIC insert into t1 values (15) -master-bin.000001 # Query 1 # use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1 -master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1 -master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1 +master-bin.000001 # Query 1 # use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to 'zedjzlcsjhd'@'127.0.0.1' +master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT on mysqltest1.t1 to 'zedjzlcsjhd'@'127.0.0.1' +master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to 'zedjzlcsjhd'@'127.0.0.1' master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`zedjzlcsjhd`@`127.0.0.1` PROCEDURE `foo4`() DETERMINISTIC begin @@ -510,7 +510,7 @@ select * from t1 master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo master-bin.000001 # Query 1 # use `mysqltest1`; drop function fn1 master-bin.000001 # Query 1 # drop database mysqltest1 -master-bin.000001 # Query 1 # drop user "zedjzlcsjhd"@127.0.0.1 +master-bin.000001 # Query 1 # DROP USER 'zedjzlcsjhd'@'127.0.0.1' master-bin.000001 # Query 1 # use `test`; drop function if exists f1 master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) READS SQL DATA @@ -675,13 +675,13 @@ CREATE DEFINER=`root`@`localhost` PROCEDURE `foo3`() insert into t1 values (15) /*!*/; SET TIMESTAMP=t/*!*/; -grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1 +grant CREATE ROUTINE, EXECUTE on mysqltest1.* to 'zedjzlcsjhd'@'127.0.0.1' /*!*/; SET TIMESTAMP=t/*!*/; -grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1 +grant SELECT on mysqltest1.t1 to 'zedjzlcsjhd'@'127.0.0.1' /*!*/; SET TIMESTAMP=t/*!*/; -grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1 +grant SELECT, INSERT on mysqltest1.t2 to 'zedjzlcsjhd'@'127.0.0.1' /*!*/; SET TIMESTAMP=t/*!*/; CREATE DEFINER=`zedjzlcsjhd`@`127.0.0.1` PROCEDURE `foo4`() @@ -842,7 +842,7 @@ SET TIMESTAMP=t/*!*/; drop database mysqltest1 /*!*/; SET TIMESTAMP=t/*!*/; -drop user "zedjzlcsjhd"@127.0.0.1 +DROP USER 'zedjzlcsjhd'@'127.0.0.1' /*!*/; use test/*!*/; SET TIMESTAMP=t/*!*/; diff --git a/mysql-test/suite/rpl/r/rpl_user.result b/mysql-test/suite/rpl/r/rpl_user.result index a98e7e9ca55..b1f1d73cf86 100644 --- a/mysql-test/suite/rpl/r/rpl_user.result +++ b/mysql-test/suite/rpl/r/rpl_user.result @@ -39,7 +39,1754 @@ show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; create user 'foo'@'fakehost' master-bin.000001 # Query # # use `test`; create user 'foo'@'fakehost', 'bar'@'fakehost' -master-bin.000001 # Query # # use `test`; rename user 'foo'@'fakehost' to 'foofoo'@'fakehost' -master-bin.000001 # Query # # use `test`; rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'bar'@'fakehost' to 'barbar'@'fakehost' -master-bin.000001 # Query # # use `test`; drop user 'foofoo'@'fakehost' -master-bin.000001 # Query # # use `test`; drop user 'not_exist_user1'@'fakehost', 'barbar'@'fakehost' +master-bin.000001 # Query # # use `test`; RENAME USER 'foo'@'fakehost' TO 'foofoo'@'fakehost' +master-bin.000001 # Query # # use `test`; RENAME USER 'not_exist_user1'@'fakehost' TO 'foobar'@'fakehost', 'bar'@'fakehost' TO 'barbar'@'fakehost' +master-bin.000001 # Query # # use `test`; DROP USER 'foofoo'@'fakehost' +master-bin.000001 # Query # # use `test`; DROP USER 'not_exist_user1'@'fakehost', 'barbar'@'fakehost' + + + +TEST STATEMENT: 'RENAME USER $users_list' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user FROM mysql.user +WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'RENAME USER $users_list' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() TO 'bug48321_4'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +RENAME USER CURRENT_USER() TO 'bug48321_4'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'RENAME USER $users_list' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER() TO 'bug48321_4'@'localhost', 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +RENAME USER CURRENT_USER() TO 'bug48321_4'@'localhost', 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'RENAME USER $users_list' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', CURRENT_USER() TO 'bug48321_4'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +RENAME USER 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', CURRENT_USER() TO 'bug48321_4'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'RENAME USER $users_list' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', CURRENT_USER() TO 'bug48321_4'@'localhost', 'bug48321_3'@'localhost' TO 'bug48321_6'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +RENAME USER 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', CURRENT_USER() TO 'bug48321_4'@'localhost', 'bug48321_3'@'localhost' TO 'bug48321_6'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'RENAME USER $users_list' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', 'bug48321_3'@'localhost' TO 'bug48321_6'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +RENAME USER 'bug48321_2'@'localhost' TO 'bug48321_5'@'localhost', 'bug48321_3'@'localhost' TO 'bug48321_6'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; + + + +TEST STATEMENT: 'DROP USER $users_list' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user FROM mysql.user +WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'DROP USER $users_list' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +DROP USER CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'DROP USER $users_list' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER(), 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +DROP USER CURRENT_USER(), 'bug48321_2'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'DROP USER $users_list' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +DROP USER 'bug48321_2'@'localhost', CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'DROP USER $users_list' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +DROP USER 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'DROP USER $users_list' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +DROP USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; +DROP PROCEDURE IF EXISTS f1; +CREATE PROCEDURE p1() SELECT 1; + + + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv +FROM mysql.user WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER(), 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(), 'bug48321_2'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; + + + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv +FROM mysql.user WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER() /*With comment*/; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER(), 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(), 'bug48321_2'@'localhost' /*With comment*/; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', CURRENT_USER() /*With comment*/; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' /*With comment*/; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM $users_list /*With comment*/' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' /*With comment*/; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; + + + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv +FROM mysql.user WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER(), 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ CURRENT_USER(), 'bug48321_2'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ 'bug48321_2'@'localhost', CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ $users_list' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; + + + +TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv +FROM mysql.user WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER(), 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM CURRENT_USER(), 'bug48321_2'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM 'bug48321_2'@'localhost', CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM $users_list' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; + + + +TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Create_routine_priv +FROM mysql.user WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE CREATE ROUTINE ON *.* FROM CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER(), 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE CREATE ROUTINE ON *.* FROM CURRENT_USER(), 'bug48321_2'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE CREATE ROUTINE ON *.* FROM 'bug48321_2'@'localhost', CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE CREATE ROUTINE ON *.* FROM 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE CREATE ROUTINE ON *.* FROM $users_list' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE CREATE ROUTINE ON *.* FROM 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; + + + +TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Routine_name, Proc_priv +FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER(), 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(), 'bug48321_2'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM 'bug48321_2'@'localhost', CURRENT_USER(); + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM 'bug48321_2'@'localhost', CURRENT_USER(), 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM $users_list' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +# Grant some privileges to users at first when testing +# 'REVOKE ...' statement. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', +'bug48321_3'@'localhost' WITH GRANT OPTION; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_1'@'localhost', +'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM 'bug48321_2'@'localhost', 'bug48321_3'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; + + + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv, Password +FROM mysql.user WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() IDENTIFIED BY 'user1' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1' WITH GRANT OPTION; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' WITH GRANT OPTION; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' WITH GRANT OPTION; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' WITH GRANT OPTION; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list WITH GRANT OPTION' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' WITH GRANT OPTION; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; + + + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv, Password +FROM mysql.user WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() IDENTIFIED BY 'user1' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1' /* With Comment */ WITH GRANT OPTION; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' /* With Comment */ WITH GRANT OPTION; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' /* With Comment */ WITH GRANT OPTION; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' /* With Comment */ WITH GRANT OPTION; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALL PRIVILEGES ON *.* TO $users_list /* With Comment */ WITH GRANT OPTION' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' /* With Comment */ WITH GRANT OPTION; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; + + + +TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Select_priv, Update_priv, Create_priv, Drop_priv, Password +FROM mysql.user WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() IDENTIFIED BY 'user1' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO CURRENT_USER() IDENTIFIED BY 'user1'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY ''; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO $users_list' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY ''; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; + + + +TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Create_routine_priv +FROM mysql.user WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() IDENTIFIED BY 'user1' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT CREATE ROUTINE ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT CREATE ROUTINE ON *.* TO CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT CREATE ROUTINE ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT CREATE ROUTINE ON *.* TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY ''; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT CREATE ROUTINE ON *.* TO $users_list' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT CREATE ROUTINE ON *.* TO 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY ''; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; +DROP PROCEDURE p1; + + + +TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' +-------------------------------------------------------------------------- +CREATE VIEW test.bug48321_v1 AS SELECT user, Routine_name, Proc_priv +FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; + +TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' +CASE 1: +------- +# Only CURRENT_USER() in the user list of the test statement. +users_list= CURRENT_USER() IDENTIFIED BY 'user1' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER() IDENTIFIED BY 'user1'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' +CASE 2: +------- +# Two users are in the test statement, CURRENT_USER is the first one. +users_list= CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_2'@'localhost'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' +CASE 3: +------- +# Two users are in the test statement, CURRENT_USER is the last one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1'; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' +CASE 4: +------- +# Three users are in the test statement, CURRENT_USER is the second one. +users_list= 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY '' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_2'@'localhost', CURRENT_USER() IDENTIFIED BY 'user1', 'bug48321_3'@'localhost' IDENTIFIED BY ''; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; + +TEST STATEMENT: 'GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO $users_list' +CASE 5: +------- +# CURRENT_USER is not in the test statement. +users_list= 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY '' + +# Connect to master with user1, so user1 always is the current user, +# when test statement is runing. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1'@'localhost' + WITH GRANT OPTION; +CREATE USER 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' + IDENTIFIED BY 'user3'; + +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO 'bug48321_2'@'localhost', 'bug48321_3'@'localhost' IDENTIFIED BY ''; + +Comparing tables master:test.bug48321_v1 and slave:test.bug48321_v1 + +# Delete all bug48321% users +DELETE FROM mysql.user WHERE user LIKE 'bug48321%'; +DELETE FROM mysql.procs_priv WHERE user LIKE 'bug48321%'; +FLUSH PRIVILEGES; +DROP VIEW test.bug48321_v1; diff --git a/mysql-test/suite/rpl/t/rpl_binlog_grant.test b/mysql-test/suite/rpl/t/rpl_binlog_grant.test index 31163927ce2..64f4e8b2eeb 100644 --- a/mysql-test/suite/rpl/t/rpl_binlog_grant.test +++ b/mysql-test/suite/rpl/t/rpl_binlog_grant.test @@ -25,9 +25,7 @@ grant select on t to x@y; # rollback; show grants for x@y; ---replace_result $VERSION VERSION ---replace_regex /\/\* xid=.* \*\//\/* XID *\// -show binlog events; +--source include/show_binlog_events.inc start transaction; insert into t values (2); revoke select on t from x@y; @@ -37,9 +35,7 @@ revoke select on t from x@y; commit; select * from t; show grants for x@y; ---replace_result $VERSION VERSION ---replace_regex /\/\* xid=.* \*\//\/* XID *\// -show binlog events; +--source include/show_binlog_events.inc drop user x@y; drop database d1; --sync_slave_with_master diff --git a/mysql-test/suite/rpl/t/rpl_events.test b/mysql-test/suite/rpl/t/rpl_events.test index 7720ad6658c..25976f779e3 100644 --- a/mysql-test/suite/rpl/t/rpl_events.test +++ b/mysql-test/suite/rpl/t/rpl_events.test @@ -105,3 +105,85 @@ DROP EVENT event44331_2; DROP EVENT event44331_3; DROP EVENT event44331_4; sync_slave_with_master; + +# +# BUG#48321 +# This test verifies if the definer is consistent between master and slave, +# when the event is created or altered with the DEFINER clause that the +# DEFINER is set to CURRENT_USER() +# +connection master; +--disable_warnings +DROP VIEW IF EXISTS events_view; +DROP EVENT IF EXISTS event48321_1; +DROP EVENT IF EXISTS event48321_2; +DROP EVENT IF EXISTS event48321_3; +DROP EVENT IF EXISTS event48321_4; +--enable_warnings + +CREATE VIEW events_view AS + SELECT EVENT_SCHEMA, EVENT_NAME, DEFINER FROM INFORMATION_SCHEMA.EVENTS + WHERE EVENT_NAME LIKE 'event48321%'; +let $diff_table_1= master:test.events_view; +let $diff_table_2= slave:test.events_view; + +CREATE DEFINER=CURRENT_USER() /*!50000 EVENT event48321_1 */ + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO SELECT 48321 as BUG; + +CREATE DEFINER=CURRENT_USER() EVENT event48321_2 + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO SELECT 48321 as BUG; + +CREATE /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO SELECT 48321 as BUG; +sync_slave_with_master; + +--source include/diff_tables.inc + +connection master; +ALTER DEFINER=CURRENT_USER() EVENT event48321_1 RENAME TO event48321_4; + +ALTER DEFINER=CURRENT_USER() EVENT event48321_2 + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO SELECT 48321 as BUG; + +ALTER /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO SELECT 48321 as BUG; +sync_slave_with_master; + +--source include/diff_tables.inc + +# Two statements in on query +connection master; +DELIMITER |; +ALTER /*!50000 DEFINER=CURRENT_USER() */ EVENT event48321_3 + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO SELECT 48321 as BUG; ALTER EVENT event48321_2 ENABLE | +DELIMITER ;| +sync_slave_with_master; + +--source include/diff_tables.inc + +#No Event boday +connection master; +ALTER EVENT event48321_3 ENABLE; +sync_slave_with_master; + +--source include/diff_tables.inc + +connection master; +DROP EVENT event48321_4; +DROP EVENT event48321_2; +DROP EVENT event48321_3; +DROP VIEW events_view; +--source include/master-slave-end.inc + diff --git a/mysql-test/suite/rpl/t/rpl_user.test b/mysql-test/suite/rpl/t/rpl_user.test index b8fe41d03c4..2adb822839a 100644 --- a/mysql-test/suite/rpl/t/rpl_user.test +++ b/mysql-test/suite/rpl/t/rpl_user.test @@ -54,8 +54,85 @@ drop user 'not_exist_user1'@'fakehost', 'not_exist_user2'@'fakehost'; sync_slave_with_master; select Host,User from mysql.user where Host='fakehost'; -# -# show the binlog events on the master -# connection master; source include/show_binlog_events.inc; + +# +# BUG#48321 +# +let $action= RENAME; +let $statement= RENAME USER \$users_list; +source extra/rpl_tests/rpl_current_user.test; + +let $action= DROP; +let $statement= DROP USER \$users_list; +source extra/rpl_tests/rpl_current_user.test; + +--disable_warnings +DROP PROCEDURE IF EXISTS f1; +--enable_warnings +CREATE PROCEDURE p1() SELECT 1; +#REVOKE ALL PRIVILEGES +let $action= REVOKE; +let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv; +let $statement= REVOKE ALL PRIVILEGES, GRANT OPTION FROM \$users_list; +source extra/rpl_tests/rpl_current_user.test; + +#REVOKE ALL PRIVILEGES with comment +let $action= REVOKE; +let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv; +let $statement= REVOKE ALL PRIVILEGES, GRANT OPTION FROM \$users_list /*With comment*/; +source extra/rpl_tests/rpl_current_user.test; + +#REVOKE ALL PRIVILEGES with comment +let $action= REVOKE; +let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv; +let $statement= REVOKE ALL PRIVILEGES, GRANT OPTION FROM /*With comment*/ \$users_list; +source extra/rpl_tests/rpl_current_user.test; + +let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv; +#REVOKE ON TABLE +let $statement= REVOKE SELECT, UPDATE, CREATE, DROP ON TABLE *.* FROM \$users_list; +source extra/rpl_tests/rpl_current_user.test; + +#REVOKE ON CREATE ROUTINE +let $diff_columns= Create_routine_priv; +let $statement= REVOKE CREATE ROUTINE ON *.* FROM \$users_list; +source extra/rpl_tests/rpl_current_user.test; + +#REVOKE ON ROUTINE +let $diff_table= mysql.procs_priv; +let $diff_columns= Routine_name, Proc_priv; +let $statement= REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM \$users_list; +source extra/rpl_tests/rpl_current_user.test; + +let $diff_table= mysql.user; +#GRANT ALL PRIVILEGES +let $action= GRANT; +let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv, Password; +let $statement= GRANT ALL PRIVILEGES ON *.* TO \$users_list WITH GRANT OPTION; +source extra/rpl_tests/rpl_current_user.test; + +#GRANT ALL PRIVILEGES with comment +let $action= GRANT; +let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Grant_priv, Password; +let $statement= GRANT ALL PRIVILEGES ON *.* TO \$users_list /* With Comment */ WITH GRANT OPTION; +source extra/rpl_tests/rpl_current_user.test; + +#GRANT ON TABLE +let $diff_columns= Select_priv, Update_priv, Create_priv, Drop_priv, Password; +let $statement= GRANT SELECT, UPDATE, CREATE, DROP ON TABLE *.* TO \$users_list; +source extra/rpl_tests/rpl_current_user.test; + +#GRANT ON CREATE ROUTINE +let $diff_columns= Create_routine_priv; +let $statement= GRANT CREATE ROUTINE ON *.* TO \$users_list; +source extra/rpl_tests/rpl_current_user.test; + +#GRANT ON ROUTINE +let $diff_table= mysql.procs_priv; +let $diff_columns= Routine_name, Proc_priv; +let $statement= GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO \$users_list; + +DROP PROCEDURE p1; +source extra/rpl_tests/rpl_current_user.test; diff --git a/sql/events.cc b/sql/events.cc index 4c6dd0f35d1..6c8bdb1ea0f 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -341,31 +341,48 @@ common_1_lev_code: } -/** - Create a new query string for removing executable comments - for avoiding leak and keeping consistency of the execution - on master and slave. - +/* + Binlog '{CREATE|ALTER} EVENT' statements. + Definer part is always rewritten, for definer can be CURRENT_USER() function. + @param[in] thd Thread handler - @param[in] buf Query string + @param[in] create CREATE or ALTER statement @return - 0 ok - 1 error + FASE ok + TRUE error */ -static int -create_query_string(THD *thd, String *buf) +static bool event_write_bin_log(THD *thd, bool create) { - /* Append the "CREATE" part of the query */ - if (buf->append(STRING_WITH_LEN("CREATE "))) - return 1; - /* Append definer */ - append_definer(thd, buf, &(thd->lex->definer->user), &(thd->lex->definer->host)); + String log_query; + if (create) + { + /* Append the "CREATE" part of the query */ + if (log_query.append(STRING_WITH_LEN("CREATE "))) + return TRUE; + } + else + { + /* Append the "ALETR " part of the query */ + if (log_query.append(STRING_WITH_LEN("ALTER "))) + return TRUE; + } + + /* Append definer + If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER + will be written into the binary log as the definer for the SQL thread. + */ + append_definer(thd, &log_query, &(thd->lex->definer->user), + &(thd->lex->definer->host)); + /* Append the left part of thd->query after "DEFINER" part */ - if (buf->append(thd->lex->stmt_definition_begin)) - return 1; - - return 0; + if (log_query.append(thd->lex->stmt_definition_begin, + thd->lex->stmt_definition_end - + thd->lex->stmt_definition_begin)) + return TRUE; + + return write_bin_log(thd, TRUE, log_query.c_ptr_safe(), log_query.length()) + != 0; } /** @@ -380,8 +397,7 @@ create_query_string(THD *thd, String *buf) @sa Events::drop_event for the notes about locking, pre-locking and Events DDL. - @retval FALSE OK - @retval TRUE Error (reported) + @retval FALSE OK @retval TRUE Error (reported) */ bool @@ -465,22 +481,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, binlog the create event unless it's been successfully dropped */ if (!dropped) - { - /* Binlog the create event. */ - DBUG_ASSERT(thd->query() && thd->query_length()); - String log_query; - if (create_query_string(thd, &log_query)) - { - sql_print_error("Event Error: An error occurred while creating query string, " - "before writing it into binary log."); - /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; - DBUG_RETURN(TRUE); - } - /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER - will be written into the binary log as the definer for the SQL thread. */ - ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); - } + ret= event_write_bin_log(thd, TRUE); } pthread_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ @@ -602,9 +603,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, if (event_queue) event_queue->update_event(thd, parse_data->dbname, parse_data->name, new_element); - /* Binlog the alter event. */ - DBUG_ASSERT(thd->query() && thd->query_length()); - ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + ret= event_write_bin_log(thd, FALSE); } } pthread_mutex_unlock(&LOCK_event_metadata); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index a8828d15cae..70983f69746 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -194,6 +194,7 @@ static bool compare_hostname(const acl_host_and_ip *host,const char *hostname, const char *ip); static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); +static bool acl_write_bin_log(THD *thd, List &list, bool clear_error); /* Convert scrambled password to binary form, according to scramble type, @@ -3225,7 +3226,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!result) /* success */ { - result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (acl_write_bin_log(thd, user_list, TRUE)) + result= -1; } rw_unlock(&LOCK_grant); @@ -3401,8 +3403,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (write_to_binlog) { - if (write_bin_log(thd, FALSE, thd->query(), thd->query_length())) - result= TRUE; + result|= acl_write_bin_log(thd, user_list, FALSE); } rw_unlock(&LOCK_grant); @@ -3531,7 +3532,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, if (!result) { - result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + result= acl_write_bin_log(thd, list, TRUE); } rw_unlock(&LOCK_grant); @@ -5663,9 +5664,9 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } -static void append_user(String *str, LEX_USER *user) +static void append_user(String *str, LEX_USER *user, bool comma= TRUE) { - if (str->length()) + if (comma && str->length()) str->append(','); str->append('\''); str->append(user->user.str); @@ -5674,6 +5675,65 @@ static void append_user(String *str, LEX_USER *user) str->append('\''); } +/* + The operations(DROP, RENAME, REVOKE, GRANT) will cause inconsistency between + master and slave, when CURRENT_USER() is used. To solve this problem, we + construct a new binlog statement in which CURRENT_USER() is replaced by + the real user name and host name. + */ +static bool acl_write_bin_log(THD *thd, List &list, bool clear_error) +{ + String log_query; + LEX *lex= thd->lex; + List_iterator user_list(list); + LEX_USER *user, *tmp_user; + + if (!mysql_bin_log.is_open()) + return FALSE; + + if (log_query.append(lex->stmt_begin, lex->stmt_user_begin - lex->stmt_begin)) + return TRUE; + while ((tmp_user= user_list++)) + { + if (!(user= get_current_user(thd, tmp_user))) + continue; + + /* + No User, but a password? + They did GRANT ... TO CURRENT_USER() IDENTIFIED BY ... ! + Get the current user, and shallow-copy the new password to them! + */ + if (!tmp_user->user.str && tmp_user->password.str) + user->password= tmp_user->password; + + if (log_query.append(" ", 1)) + return TRUE; + append_user(&log_query, user, FALSE); + /* Only 'GRANT' have password */ + if (user->password.str) + { + if (log_query.append(STRING_WITH_LEN(" IDENTIFIED BY ")) || + log_query.append(STRING_WITH_LEN("PASSWORD ")) || + log_query.append("'", 1) || + log_query.append(user->password.str, + user->password.length) || + log_query.append("'", 1)) + return TRUE; + } + if (log_query.append(",", 1)) + return TRUE; + } + /* It is binlogged only when at least one user is in the query */ + if (log_query.c_ptr()[log_query.length()-1] == ',') + { + log_query.length(log_query.length()-1); + if (log_query.append(lex->stmt_user_end, lex->stmt_end - lex->stmt_user_end)) + return TRUE; + return write_bin_log(thd, clear_error, log_query.c_ptr_safe(), + log_query.length()) != 0; + } + return FALSE; +} /* Create a list of users. @@ -5780,6 +5840,7 @@ bool mysql_drop_user(THD *thd, List &list) { int result; String wrong_users; + String log_query; LEX_USER *user_name, *tmp_user_name; List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; @@ -5809,6 +5870,7 @@ bool mysql_drop_user(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); + log_query.append(STRING_WITH_LEN("DROP USER")); while ((tmp_user_name= user_list++)) { if (!(user_name= get_current_user(thd, tmp_user_name))) @@ -5816,6 +5878,17 @@ bool mysql_drop_user(THD *thd, List &list) result= TRUE; continue; } + + /* + The operation will cause inconsistency between master and slave, when + CURRENT_USER() is used. To solve this problem, we construct a new + binlog statement in which CURRENT_USER() is replaced by the real user + name and host name. + */ + log_query.append(STRING_WITH_LEN(" ")); + append_user(&log_query, user_name, FALSE); + log_query.append(STRING_WITH_LEN(",")); + if (handle_grant_data(tables, 1, user_name, NULL) <= 0) { append_user(&wrong_users, user_name); @@ -5834,7 +5907,13 @@ bool mysql_drop_user(THD *thd, List &list) my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe()); if (some_users_deleted) - result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + { + if (log_query.c_ptr()[log_query.length()-1] == ',') + { + log_query.length(log_query.length()-1); + result|= write_bin_log(thd, FALSE, log_query.c_ptr_safe(), log_query.length()); + } + } rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5862,6 +5941,7 @@ bool mysql_rename_user(THD *thd, List &list) { int result; String wrong_users; + String log_query; LEX_USER *user_from, *tmp_user_from; LEX_USER *user_to, *tmp_user_to; List_iterator user_list(list); @@ -5889,6 +5969,7 @@ bool mysql_rename_user(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); + log_query.append(STRING_WITH_LEN("RENAME USER")); while ((tmp_user_from= user_list++)) { if (!(user_from= get_current_user(thd, tmp_user_from))) @@ -5904,6 +5985,18 @@ bool mysql_rename_user(THD *thd, List &list) } DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */ + /* + The operation will cause inconsistency between master and slave, when + CURRENT_USER() is used. To solve this problem, we construct a new + binlog statement in which CURRENT_USER() is replaced by the real user + name and host name. + */ + log_query.append(STRING_WITH_LEN(" ")); + append_user(&log_query, user_from, FALSE); + log_query.append(STRING_WITH_LEN(" TO ")); + append_user(&log_query, user_to, FALSE); + log_query.append(STRING_WITH_LEN(",")); + /* Search all in-memory structures and grant tables for a mention of the new user name. @@ -5925,9 +6018,15 @@ bool mysql_rename_user(THD *thd, List &list) if (result) my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); - - if (some_users_renamed && mysql_bin_log.is_open()) - result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + + if (some_users_renamed) + { + if (log_query.c_ptr()[log_query.length()-1] == ',') + { + log_query.length(log_query.length()-1); + result|= write_bin_log(thd, FALSE, log_query.c_ptr_safe(), log_query.length()); + } + } rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -6117,8 +6216,9 @@ bool mysql_revoke_all(THD *thd, List &list) VOID(pthread_mutex_unlock(&acl_cache->lock)); - int binlog_error= - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + int binlog_error= 0; + if (acl_write_bin_log(thd, list, FALSE)) + binlog_error= 1; rw_unlock(&LOCK_grant); close_thread_tables(thd); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4e4794ef2cf..99f5257eb5e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1727,6 +1727,8 @@ typedef struct st_lex : public Query_tables_list - CREATE TRIGGER (points to "TRIGGER"); - CREATE PROCEDURE (points to "PROCEDURE"); - CREATE FUNCTION (points to "FUNCTION" or "AGGREGATE"); + - CREATE VIEW(points to "VIEW"); + - CREATE EVENT(points to "EVENT"); This pointer is required to add possibly omitted DEFINER-clause to the DDL-statement before dumping it to the binlog. @@ -1735,6 +1737,29 @@ typedef struct st_lex : public Query_tables_list const char *stmt_definition_end; + /* + stmt_begin is intended to point to the begin of every statement. + It is now used in the following statements: + - GRANT ALL PRIVELEGES ON *.* (points to "GRANT"); + - REVOKE ALL PRIVELEGES ON *.* (points to "REVOKE"); + */ + const char *stmt_begin; + const char *stmt_end; + + /* + stmt_user_begin is intended to point to the begin of the user list in + the following statements: + - GRANT ALL PRIVELEGES ON *.* TO 'username'@'hostname' + (points to "'username'"); + - REVOKE ALL PRIVELEGES ON *.* FROM 'username'@'hostname' + (points to "'username'"); + + these pointers are required to replace the CURRENT_USER() + function by the real user before dumping it to the binlog. + */ + const char *stmt_user_begin; + const char *stmt_user_end; + /** During name resolution search only in the table list given by Name_resolution_context::first_name_resolution_table and diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8dc08f8425f..92c4de5b462 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1562,7 +1562,11 @@ opt_end_of_input: ; verb_clause: - statement + remember_name statement remember_end + { + Lex->stmt_begin= $1; + Lex->stmt_end= $3; + } | begin ; @@ -5743,7 +5747,7 @@ alter: } view_tail {} - | ALTER definer_opt EVENT_SYM sp_name + | ALTER definer_opt remember_name EVENT_SYM sp_name { /* It is safe to use Lex->spname because @@ -5755,7 +5759,8 @@ alter: if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) MYSQL_YYABORT; - Lex->event_parse_data->identifier= $4; + Lex->event_parse_data->identifier= $5; + Lex->stmt_definition_begin= $3; Lex->sql_command= SQLCOM_ALTER_EVENT; } @@ -5765,7 +5770,7 @@ alter: opt_ev_comment opt_ev_sql_stmt { - if (!($6 || $7 || $8 || $9 || $10)) + if (!($7 || $8 || $9 || $10 || $11)) { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; @@ -5826,7 +5831,16 @@ opt_ev_rename_to: ; opt_ev_sql_stmt: - /* empty*/ { $$= 0;} + /* empty*/ + { + $$= 0; + /* + Lex->sp_head is not initialized when event body is empty. + So we can not use Lex->sp_head->set_stmt_end() to set + stmt_definition_end. + */ + Lex->stmt_definition_end= (char*) YYLIP->get_cpp_tok_end(); + } | DO_SYM ev_sql_stmt { $$= 1; } ; @@ -11516,6 +11530,7 @@ user: $$->user = $1; $$->host.str= (char *) "%"; $$->host.length= 1; + Lex->stmt_user_end= YYLIP->get_cpp_ptr(); if (check_string_char_length(&$$->user, ER(ER_USERNAME), USERNAME_CHAR_LENGTH, @@ -11528,6 +11543,7 @@ user: if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) MYSQL_YYABORT; $$->user = $1; $$->host=$3; + Lex->stmt_user_end= YYLIP->get_cpp_ptr(); if (check_string_char_length(&$$->user, ER(ER_USERNAME), USERNAME_CHAR_LENGTH, @@ -11537,6 +11553,7 @@ user: } | CURRENT_USER optional_braces { + Lex->stmt_user_end= YYLIP->get_cpp_ptr(); if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user)))) MYSQL_YYABORT; /* @@ -12727,9 +12744,10 @@ user_list: ; grant_list: + { Lex->stmt_user_begin= YYLIP->get_cpp_ptr(); } grant_user { - if (Lex->users_list.push_back($1)) + if (Lex->users_list.push_back($2)) MYSQL_YYABORT; } | grant_list ',' grant_user @@ -12742,6 +12760,7 @@ grant_list: grant_user: user IDENTIFIED_SYM BY TEXT_STRING { + Lex->stmt_user_end= YYLIP->get_cpp_ptr(); $$=$1; $1->password=$4; if ($4.length) { @@ -12768,7 +12787,10 @@ grant_user: } } | user IDENTIFIED_SYM BY PASSWORD TEXT_STRING - { $$= $1; $1->password= $5; } + { + Lex->stmt_user_end= YYLIP->get_cpp_ptr(); + $$= $1; $1->password= $5; + } | user { $$= $1; $1->password= null_lex_str; } ; From 756d0b864fbeeef22427901b9bc150fa24d2af13 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 31 Jan 2010 10:13:21 +0100 Subject: [PATCH 312/344] Fix windows build of embedded server (forgotten dependency). --- libmysqld/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 7d2abb64065..9adf91c997b 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -153,7 +153,7 @@ FILE(WRITE cmake_dummy.c " ") # custom targets to "sql/CMakeLists.txt" and reference them here. ADD_LIBRARY(mysqlserver STATIC ${LIBMYSQLD_SOURCES}) ADD_DEPENDENCIES(mysqlserver GenServerSource GenError) -TARGET_LINK_LIBRARIES(mysqlserver) +TARGET_LINK_LIBRARIES(mysqlserver psapi.lib) # Add any additional libraries requested by engine(s) FOREACH (ENGINE_LIB ${MYSQLD_STATIC_ENGINE_LIBS}) From 1ff667c995a1a597615a9fb4820218d48659ae71 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 1 Feb 2010 13:40:16 +0200 Subject: [PATCH 313/344] fixed a typo in bug #49897. --- sql/sql_select.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 239809f1d4c..eecc2b086a3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -531,7 +531,7 @@ JOIN::prepare(Item ***rref_pointer_array, there. Such fields don't contain any data to sort. */ if (!real_order && - (item->type() != Item::Item::FIELD_ITEM || + (item->type() != Item::FIELD_ITEM || ((Item_field *) item)->field->maybe_null() || ((Item_field *) item)->field->sort_length())) real_order= TRUE; From 9b75c2f268f0e40fe74f38759c8f8551b2637145 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 1 Feb 2010 14:05:21 +0200 Subject: [PATCH 314/344] Made outfile_testdata experimental in 5.1-bugteam, pending the resulution of bug #46895. --- mysql-test/collections/default.experimental | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index 9c4055cd19e..d791686cd62 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -14,6 +14,7 @@ funcs_2.ndb_charset # joro : NDB tests marked as experiment main.ctype_gbk_binlog @solaris # Bug#46010: main.ctype_gbk_binlog fails sporadically : Table 't2' already exists main.plugin_load @solaris # Bug#42144 +main.outfile_loaddata @solaris # joro : Bug #46895 ndb.* # joro : NDB tests marked as experimental as agreed with bochklin From 56b911f893594004c2da92c9a77b2f122fe317d9 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Tue, 2 Feb 2010 15:16:47 +0000 Subject: [PATCH 315/344] BUG#47639: The rpl_binlog_corruption test fails on Windows The test case rpl_binlog_corruption fails on windows because when adding a line to the binary log index file it gets terminated with a CR+LF (which btw, is the normal case in windows, but not on Unixes - LF). This causes mismatch between the relay log names, causing mysqld to report that it cannot find the log file. We fix this by creating the instrumented index file through mysql, ie, using SELECT ... INTO DUMPFILE ..., as opposed on relying on ultimatly OS commands like: -- echo "..." > index. These changes go into the file and make the procedure platform independent: include/setup_fake_relay_log.inc Side note: when using SELECT ... INTO DUMPFILE ..., one needs to check if mysqld is running with secure_file_priv. If it is, we do it in two steps: 1. create the file on the allowed location; 2. move it to the datadir. If it is not, then we just create the file directly on the datadir (so previous step 2. is not needed). --- mysql-test/include/setup_fake_relay_log.inc | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/mysql-test/include/setup_fake_relay_log.inc b/mysql-test/include/setup_fake_relay_log.inc index f88806e1079..5b9e7f72fdd 100644 --- a/mysql-test/include/setup_fake_relay_log.inc +++ b/mysql-test/include/setup_fake_relay_log.inc @@ -69,7 +69,22 @@ let $_fake_relay_log_purge= `SELECT @@global.relay_log_purge`; # Create relay log file. copy_file $fake_relay_log $_fake_relay_log; # Create relay log index. ---exec echo $_fake_filename-fake.000001 > $_fake_relay_index + +if (`SELECT LENGTH(@@secure_file_priv) > 0`) +{ + -- let $_file_priv_dir= `SELECT @@secure_file_priv`; + -- let $_suffix= `SELECT UUID()` + -- let $_tmp_file= $_file_priv_dir/fake-index.$_suffix + + -- eval select '$_fake_filename-fake.000001\n' into dumpfile '$_tmp_file' + -- copy_file $_tmp_file $_fake_relay_index + -- remove_file $_tmp_file +} + +if (`SELECT LENGTH(@@secure_file_priv) = 0`) +{ + -- eval select '$_fake_filename-fake.000001\n' into dumpfile '$_fake_relay_index' +} # Setup replication from existing relay log. eval CHANGE MASTER TO MASTER_HOST='dummy.localdomain', RELAY_LOG_FILE='$_fake_filename-fake.000001', RELAY_LOG_POS=4; From 673ec7b24d1e4c8806d964ef262f39fadc84da70 Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Tue, 2 Feb 2010 23:29:14 +0100 Subject: [PATCH 316/344] Changes to be able to create source TAR packages with longer path names than 99 characters, using the USTAR format of the resulting source TAR. To be able to specify the use of USTAR when creating the source TAR, we needed both to update the GNU autotools version requirements slightly, and update the initiation of the tools to use more modern constructs. --- configure.in | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/configure.in b/configure.in index 38eb511ac18..eeb1da8670a 100644 --- a/configure.in +++ b/configure.in @@ -1,17 +1,23 @@ dnl -*- ksh -*- dnl Process this file with autoconf to produce a configure script. -AC_PREREQ(2.52)dnl Minimum Autoconf version required. +# Minimum Autoconf version required. +AC_PREREQ(2.59) -AC_INIT(sql/mysqld.cc) -AC_CANONICAL_SYSTEM -# The Docs Makefile.am parses this line! -# remember to also update version.c in ndb -# +# Remember to also update version.c in ndb. # When changing major version number please also check switch statement # in mysqlbinlog::check_master_version(). -AM_INIT_AUTOMAKE(mysql, 5.1.43) -AM_CONFIG_HEADER([include/config.h:config.h.in]) +AC_INIT([MySQL Server], [5.1.43], [], [mysql]) +AC_CONFIG_SRCDIR([sql/mysqld.cc]) +AC_CANONICAL_SYSTEM +# USTAR format gives us the possibility to store longer path names in +# TAR files, the path name is split into two parts, a 155 chacater +# first part and a 100 character second part. +AM_INIT_AUTOMAKE([1.9 tar-ustar]) +LT_INIT +LT_PREREQ([1.5.6]) + +AM_CONFIG_HEADER([include/config.h]) # Request support for automake silent-rules if available. # Default to verbose output. One can use the configure-time From 0a90bfe6c019fd1dc3db3090de969077ac311fb5 Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Wed, 3 Feb 2010 14:52:11 +0100 Subject: [PATCH 317/344] Adjuster the parsing of "configure.in" version number line --- win/configure.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/win/configure.js b/win/configure.js index fc5c548c983..38fa8e7afeb 100644 --- a/win/configure.js +++ b/win/configure.js @@ -140,11 +140,11 @@ function GetValue(str, key) function GetVersion(str) { - var key = "AM_INIT_AUTOMAKE(mysql, "; - var pos = str.indexOf(key); //5.0.6-beta) + var key = "AC_INIT([MySQL Server], ["; + var pos = str.indexOf(key); if (pos == -1) return null; pos += key.length; - var end = str.indexOf(")", pos); + var end = str.indexOf("]", pos); if (end == -1) return null; return str.substring(pos, end); } From b8db15fc226063b83e507fcdfec1765088abcada Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 4 Feb 2010 12:13:29 +0200 Subject: [PATCH 318/344] tree name change --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 557df1b1ffe..f79c1cd6319 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.0-bugteam" +tree_name = "mysql-5.0" From d474428c9aef708a4d2af049efcca4886911126f Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Tue, 9 Feb 2010 19:17:04 +0200 Subject: [PATCH 319/344] Added --connect-command="sql-string" to sql-bench test suite. This allows one to send an extra command to the mysql server to setup the environment before starting tests. --- sql-bench/bench-init.pl.sh | 8 ++++++-- sql-bench/server-cfg.sh | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh index 919ddcedf16..2d9927947d2 100644 --- a/sql-bench/bench-init.pl.sh +++ b/sql-bench/bench-init.pl.sh @@ -40,7 +40,7 @@ require "$pwd/server-cfg" || die "Can't read Configuration file: $!\n"; $|=1; # Output data immediately $opt_skip_test=$opt_skip_create=$opt_skip_delete=$opt_verbose=$opt_fast_insert=$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=$opt_log=$opt_use_old_results=$opt_help=$opt_odbc=$opt_small_test=$opt_small_tables=$opt_samll_key_tables=$opt_stage=$opt_old_headers=$opt_die_on_errors=$opt_tcpip=$opt_random=$opt_only_missing_tests=0; -$opt_cmp=$opt_user=$opt_password=$opt_connect_options=""; +$opt_cmp=$opt_user=$opt_password=$opt_connect_options=$opt_connect_command= ""; $opt_server="mysql"; $opt_dir="output"; $opt_host="localhost";$opt_database="test"; $opt_machine=""; $opt_suffix=""; @@ -59,7 +59,7 @@ $log_prog_args=join(" ", skip_arguments(\@ARGV,"comments","cmp","server", "use-old-results","skip-test", "optimization","hw", "machine", "dir", "suffix", "log")); -GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","threads=i","random","old-headers","die-on-errors","create-options=s","hires","tcpip","silent","optimization=s","hw=s","socket=s","connect-options=s","only-missing-tests") || usage(); +GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","threads=i","random","old-headers","die-on-errors","create-options=s","hires","tcpip","silent","optimization=s","hw=s","socket=s","connect-options=s","connect-command=s","only-missing-tests") || usage(); usage() if ($opt_help); $server=get_server($opt_server,$opt_host,$opt_database,$opt_odbc, @@ -595,6 +595,10 @@ All benchmarks takes the following options: Add options, which uses at DBI connect. For example --connect-options=mysql_read_default_file=/etc/my.cnf. +--connect-command='SQL command' + Initialization command to execute when logged in. Useful for setting + up the environment. + EOF exit(0); } diff --git a/sql-bench/server-cfg.sh b/sql-bench/server-cfg.sh index 5ed7fdf482c..3ff1ce99659 100644 --- a/sql-bench/server-cfg.sh +++ b/sql-bench/server-cfg.sh @@ -249,6 +249,11 @@ sub connect die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n"; $dbh->do("SET OPTION LOG_OFF=1,UPDATE_LOG=0"); + if ($main::opt_connect_command ne "") + { + $dbh->do($main::opt_connect_command) or + die "Can't execute connect_command: $main::opt_connect_command error: $DBI::errstr\n"; + } return $dbh; } From d77e3cde5f43426271f7ac64a922e5ddbf6e675d Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 10 Feb 2010 21:06:24 +0200 Subject: [PATCH 320/344] When one does a drop table, the indexes are not flushed to disk before drop anymore (with MyISAM/Maria) myisam-recover options changed from OFF to 'DEFAULT' to get less change of data loss when using MyISAM. (The disadvantage is that changed MyISAM tables will be checked at access time; Use --myisam-recover=OFF for old behavior) Don't call extra(HA_EXTRA_FORCE_REOPEN) in ALTER TABLE if table is locked as this will mark table as crashed! Added assert to detect if we accidently would use MyISAM versioning in MySQL include/my_base.h: Mark NOT_USED as USED, as we now use this as a flag to not call extra() mysql-test/mysql-test-run.pl: Don't write all options when there is something wrong with the arguments mysql-test/r/sp-destruct.result: Add missing flush of mysql.proc (as the test copied live tables) mysql-test/r/variables.result: myisam-recover options changed to 'default' mysql-test/r/view.result: Don't show create time in result mysql-test/suite/maria/t/maria-recovery2-master.opt: Don't run test with myisam-recover (as this produces extra warnings during simulated death) mysql-test/t/sp-destruct.test: Add missing flush of mysql.proc (as the test copied live tables) mysql-test/t/view.test: Don't show create time in result sql/lock.cc: Added marker if table was deleted to argument list sql/mysql_priv.h: Added marker if table was deleted to argument list sql/mysqld.cc: myisam-recover options changed from OFF to 'DEFAULT' to get less change of data loss when using MyISAM Allow one to specify OFF as argument to myisam-recover (was default before but one couldn't specify it) sql/sql_base.cc: Mark if table is going to be deleted sql/sql_delete.cc: Mark if table is going to be deleted sql/sql_table.cc: Mark if table is going to be deleted Don't call extra(HA_EXTRA_FORCE_REOPEN) in ALTER TABLE if table is locked as this will mark table as crashed! sql/table.cc: Signal to handler if table is getting deleted as part of getting droped from table cache. sql/table.h: Added marker if table is going to be deleted. storage/maria/ha_maria.cc: Don't search for transaction handler if file is not transactional or outside of transaction (Fixed possible core dump) storage/maria/ma_blockrec.c: Don't write changed information if table is going to be deleted. storage/maria/ma_close.c: Don't write changed information if table is going to be deleted. storage/maria/ma_extra.c: Mark tables that are deleted as crased, to ensure good behavior on restart if we suddenly crash. storage/maria/ma_locking.c: Cleanup storage/maria/ma_recovery.c: We need trnman to be inited during redo phase (to be able to open tables checked with maria_chk) storage/maria/maria_def.h: Added marker if table is going to be deleted. storage/myisam/mi_close.c: Don't write changed information if table is going to be deleted. storage/myisam/mi_extra.c: Mark tables that are deleted as crased, to ensure good behavior on restart if we suddenly crash. storage/myisam/mi_open.c: Added assert to detect if we accidently would use MyISAM versioning in MySQL storage/myisam/myisamdef.h: Added marker if table is going to be deleted. --- include/my_base.h | 2 +- mysql-test/mysql-test-run.pl | 2 + mysql-test/r/sp-destruct.result | 1 + mysql-test/r/variables.result | 4 +- mysql-test/r/view.result | 14 +++---- .../suite/maria/t/maria-recovery2-master.opt | 2 +- mysql-test/t/sp-destruct.test | 1 + mysql-test/t/view.test | 2 +- sql/lock.cc | 6 ++- sql/mysql_priv.h | 2 +- sql/mysqld.cc | 39 ++++++++++++------- sql/sql_base.cc | 17 ++++++-- sql/sql_delete.cc | 4 ++ sql/sql_table.cc | 26 +++++++++---- sql/table.cc | 4 ++ sql/table.h | 3 +- storage/maria/ha_maria.cc | 5 ++- storage/maria/ma_blockrec.c | 5 ++- storage/maria/ma_close.c | 2 +- storage/maria/ma_extra.c | 6 +++ storage/maria/ma_locking.c | 5 ++- storage/maria/ma_recovery.c | 3 ++ storage/maria/maria_def.h | 1 + storage/myisam/mi_close.c | 5 ++- storage/myisam/mi_extra.c | 7 +++- storage/myisam/mi_open.c | 2 + storage/myisam/myisamdef.h | 1 + 27 files changed, 121 insertions(+), 50 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index 59929fe4d49..f76903dcb6b 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -111,7 +111,7 @@ enum ha_storage_media { enum ha_extra_function { HA_EXTRA_NORMAL=0, /* Optimize for space (def) */ HA_EXTRA_QUICK=1, /* Optimize for speed */ - HA_EXTRA_NOT_USED=2, + HA_EXTRA_NOT_USED=2, /* Should be ignored by handler */ HA_EXTRA_CACHE=3, /* Cache record in HA_rrnd() */ HA_EXTRA_NO_CACHE=4, /* End caching of records (def) */ HA_EXTRA_NO_READCHECK=5, /* No readcheck on update */ diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 8d577d1e788..5ff40b1916c 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -5542,6 +5542,8 @@ sub usage ($) { if ( $message ) { print STDERR "$message\n"; + print STDERR "For full list of options, use $0 --help\n"; + exit; } print <table=table; + table->s->deleting= table_list->deleting; /* Return 1 if table is in use */ DBUG_RETURN(test(remove_table_from_cache(thd, db, table_list->table_name, - check_in_use ? RTFC_NO_FLAG : RTFC_WAIT_OTHER_THREAD_FLAG))); + (check_in_use ? + RTFC_NO_FLAG : + RTFC_WAIT_OTHER_THREAD_FLAG), + table_list->deleting))); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2af7654e381..d11fc4f900b 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1636,7 +1636,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, #define RTFC_WAIT_OTHER_THREAD_FLAG 0x0002 #define RTFC_CHECK_KILLED_FLAG 0x0004 bool remove_table_from_cache(THD *thd, const char *db, const char *table, - uint flags); + uint flags, my_bool deleting); #define NORMAL_PART_NAME 0 #define TEMP_PART_NAME 1 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a45950c3af9..bf09df8a465 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7962,7 +7962,13 @@ static int mysql_init_variables(void) refresh_version= 1L; /* Increments on each reload */ global_query_id= thread_id= 1L; strmov(server_version, MYSQL_SERVER_VERSION); - myisam_recover_options_str= sql_mode_str= "OFF"; + sql_mode_str= ""; + + /* By default, auto-repair MyISAM tables after crash */ + myisam_recover_options_str= "DEFAULT"; + myisam_recover_options= HA_RECOVER_DEFAULT; + ha_open_options|= HA_OPEN_ABORT_IF_CRASHED; + myisam_stats_method_str= "nulls_unequal"; my_bind_addr = htonl(INADDR_ANY); threads.empty(); @@ -8616,26 +8622,31 @@ mysqld_get_one_option(int optid, #endif case OPT_MYISAM_RECOVER: { - if (!argument) - { - myisam_recover_options= HA_RECOVER_DEFAULT; - myisam_recover_options_str= myisam_recover_typelib.type_names[0]; - } - else if (!argument[0]) + if (argument && (!argument[0] || + my_strcasecmp(system_charset_info, argument, "OFF") == 0)) { myisam_recover_options= HA_RECOVER_NONE; myisam_recover_options_str= "OFF"; + ha_open_options&= ~HA_OPEN_ABORT_IF_CRASHED; } else { - myisam_recover_options_str=argument; - myisam_recover_options= - find_bit_type_or_exit(argument, &myisam_recover_typelib, opt->name, - &error); - if (error) - return 1; + if (!argument) + { + myisam_recover_options= HA_RECOVER_DEFAULT; + myisam_recover_options_str= myisam_recover_typelib.type_names[0]; + } + else + { + myisam_recover_options_str=argument; + myisam_recover_options= + find_bit_type_or_exit(argument, &myisam_recover_typelib, opt->name, + &error); + if (error) + return 1; + } + ha_open_options|=HA_OPEN_ABORT_IF_CRASHED; } - ha_open_options|=HA_OPEN_ABORT_IF_CRASHED; break; } case OPT_CONCURRENT_INSERT: diff --git a/sql/sql_base.cc b/sql/sql_base.cc index adcd42719e1..8cc0b1574a3 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -930,7 +930,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, for (TABLE_LIST *table= tables; table; table= table->next_local) { if (remove_table_from_cache(thd, table->db, table->table_name, - RTFC_OWNED_BY_THD_FLAG)) + RTFC_OWNED_BY_THD_FLAG, table->deleting)) found=1; } if (!found) @@ -8404,6 +8404,11 @@ void remove_db_from_cache(const char *db) if (!strcmp(table->s->db.str, db)) { table->s->version= 0L; /* Free when thread is ready */ + /* + This functions only called from DROP DATABASE code, so we are going + to drop all tables so we mark them as deleting + */ + table->s->deleting= TRUE; if (!table->in_use) relink_unused(table); } @@ -8446,7 +8451,7 @@ void flush_tables() */ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, - uint flags) + uint flags, my_bool deleting) { char key[MAX_DBKEY_LENGTH]; uint key_length; @@ -8540,7 +8545,10 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, } } while (unused_tables && !unused_tables->s->version) + { + unused_tables->s->deleting= deleting; VOID(hash_delete(&open_cache,(uchar*) unused_tables)); + } DBUG_PRINT("info", ("Removing table from table_def_cache")); /* Remove table from table definition cache if it's not in use */ @@ -8734,7 +8742,8 @@ int abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt) /* If MERGE child, forward lock handling to parent. */ mysql_lock_abort(lpt->thd, lpt->table->parent ? lpt->table->parent : lpt->table, TRUE); - VOID(remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, flags)); + VOID(remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, flags, + FALSE)); VOID(pthread_mutex_unlock(&LOCK_open)); DBUG_RETURN(0); } @@ -8759,7 +8768,7 @@ void close_open_tables_and_downgrade(ALTER_PARTITION_PARAM_TYPE *lpt) { VOID(pthread_mutex_lock(&LOCK_open)); remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, - RTFC_WAIT_OTHER_THREAD_FLAG); + RTFC_WAIT_OTHER_THREAD_FLAG, FALSE); VOID(pthread_mutex_unlock(&LOCK_open)); /* If MERGE child, forward lock handling to parent. */ mysql_lock_downgrade_write(lpt->thd, lpt->table->parent ? lpt->table->parent : diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 2f8f62408b3..cea9b2857e2 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1088,6 +1088,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) HA_CREATE_INFO create_info; char path[FN_REFLEN + 1]; TABLE *table; + TABLE_LIST *tbl; bool error; uint path_length; bool is_temporary_table= false; @@ -1108,6 +1109,9 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE)) goto trunc_by_del; + for (tbl= table_list; tbl; tbl= tbl->next_local) + tbl->deleting= TRUE; /* to trigger HA_PREPARE_FOR_DROP */ + table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK); create_info.options|= HA_LEX_CREATE_TMP_TABLE; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index dc156fea894..1c72f1986ec 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1880,6 +1880,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, { TABLE_SHARE *share; table->db_type= NULL; + if ((share= get_cached_table_share(table->db, table->table_name))) table->db_type= share->db_type(); @@ -1974,9 +1975,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, { TABLE *locked_table; abort_locked_tables(thd, db, table->table_name); + table->deleting= TRUE; remove_table_from_cache(thd, db, table->table_name, RTFC_WAIT_OTHER_THREAD_FLAG | - RTFC_CHECK_KILLED_FLAG); + RTFC_CHECK_KILLED_FLAG, FALSE); /* If the table was used in lock tables, remember it so that unlock_table_names can free it @@ -4213,9 +4215,10 @@ void wait_while_table_is_used(THD *thd,TABLE *table, /* Wait until all there are no other threads that has this table open */ remove_table_from_cache(thd, table->s->db.str, table->s->table_name.str, - RTFC_WAIT_OTHER_THREAD_FLAG); + RTFC_WAIT_OTHER_THREAD_FLAG, FALSE); /* extra() call must come only after all instances above are closed */ - VOID(table->file->extra(function)); + if (function != HA_EXTRA_NOT_USED) + VOID(table->file->extra(function)); DBUG_VOID_RETURN; } @@ -4717,7 +4720,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, remove_table_from_cache(thd, table->table->s->db.str, table->table->s->table_name.str, RTFC_WAIT_OTHER_THREAD_FLAG | - RTFC_CHECK_KILLED_FLAG); + RTFC_CHECK_KILLED_FLAG, FALSE); thd->exit_cond(old_message); DBUG_EXECUTE_IF("wait_in_mysql_admin_table", wait_for_kill_signal(thd);); if (thd->killed) @@ -4975,7 +4978,8 @@ send_result_message: { pthread_mutex_lock(&LOCK_open); remove_table_from_cache(thd, table->table->s->db.str, - table->table->s->table_name.str, RTFC_NO_FLAG); + table->table->s->table_name.str, + RTFC_NO_FLAG, FALSE); pthread_mutex_unlock(&LOCK_open); } /* May be something modified consequently we have to invalidate cache */ @@ -6738,7 +6742,9 @@ view_err: from concurrent DDL statements. */ VOID(pthread_mutex_lock(&LOCK_open)); - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + wait_while_table_is_used(thd, table, + thd->locked_tables ? HA_EXTRA_NOT_USED : + HA_EXTRA_FORCE_REOPEN); VOID(pthread_mutex_unlock(&LOCK_open)); DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000);); error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); @@ -6746,7 +6752,9 @@ view_err: break; case DISABLE: VOID(pthread_mutex_lock(&LOCK_open)); - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + wait_while_table_is_used(thd, table, + thd->locked_tables ? HA_EXTRA_NOT_USED : + HA_EXTRA_FORCE_REOPEN); VOID(pthread_mutex_unlock(&LOCK_open)); error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); /* COND_refresh will be signaled in close_thread_tables() */ @@ -7192,7 +7200,9 @@ view_err: else { VOID(pthread_mutex_lock(&LOCK_open)); - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + wait_while_table_is_used(thd, table, + thd->locked_tables ? HA_EXTRA_NOT_USED : + HA_EXTRA_FORCE_REOPEN); VOID(pthread_mutex_unlock(&LOCK_open)); thd_proc_info(thd, "manage keys"); alter_table_manage_keys(table, table->file->indexes_are_disabled(), diff --git a/sql/table.cc b/sql/table.cc index 92487a4a34e..8ceda6e7513 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1977,7 +1977,11 @@ int closefrm(register TABLE *table, bool free_share) DBUG_PRINT("enter", ("table: 0x%lx", (long) table)); if (table->db_stat) + { + if (table->s->deleting) + table->file->extra(HA_EXTRA_PREPARE_FOR_DROP); error=table->file->close(); + } my_free((char*) table->alias, MYF(MY_ALLOW_ZERO_PTR)); table->alias= 0; if (table->field) diff --git a/sql/table.h b/sql/table.h index 137b380e0f5..a24e79e26cf 100644 --- a/sql/table.h +++ b/sql/table.h @@ -431,6 +431,7 @@ typedef struct st_table_share bool is_view; bool name_lock, replace_with_name_lock; bool waiting_on_cond; /* Protection against free */ + bool deleting; /* going to delete this table */ ulong table_map_id; /* for row-based replication */ ulonglong table_map_version; @@ -1379,7 +1380,7 @@ struct TABLE_LIST */ bool create; bool internal_tmp_table; - + bool deleting; /* going to delete this table */ /* View creation context. */ diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index dc2ba8c43f4..5ec0a6b748e 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -2255,9 +2255,12 @@ int ha_maria::extra(enum ha_extra_function operation) extern_lock(F_UNLOCK) (which resets file->trn) followed by maria_close() without calling commit/rollback in between. If file->trn is not set we can't remove file->share from the transaction list in the extra() call. + + table->in_use is not set in the case this is a done as part of closefrm() + as part of drop table. */ - if (!file->trn && + if (file->s->now_transactional && !file->trn && table->in_use && (operation == HA_EXTRA_PREPARE_FOR_DROP || operation == HA_EXTRA_PREPARE_FOR_RENAME)) { diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 9097731c227..89701913c9a 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -430,8 +430,9 @@ my_bool _ma_once_end_block_record(MARIA_SHARE *share) if (share->bitmap.file.file >= 0) { if (flush_pagecache_blocks(share->pagecache, &share->bitmap.file, - share->temporary ? FLUSH_IGNORE_CHANGED : - FLUSH_RELEASE)) + ((share->temporary || share->deleting) ? + FLUSH_IGNORE_CHANGED : + FLUSH_RELEASE))) res= 1; /* File must be synced as it is going out of the maria_open_list and so diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c index e46beec71b4..df525d45d14 100644 --- a/storage/maria/ma_close.c +++ b/storage/maria/ma_close.c @@ -79,7 +79,7 @@ int maria_close(register MARIA_HA *info) if ((*share->once_end)(share)) error= my_errno; if (flush_pagecache_blocks(share->pagecache, &share->kfile, - (share->temporary ? + ((share->temporary || share->deleting) ? FLUSH_IGNORE_CHANGED : FLUSH_RELEASE))) error= my_errno; diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index 691e55b2a2a..81f3789523f 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -305,6 +305,12 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, pthread_mutex_unlock(&THR_LOCK_maria); break; case HA_EXTRA_PREPARE_FOR_DROP: + /* Signals about intent to delete this table */ + share->deleting= TRUE; + share->global_changed= FALSE; /* force writing changed flag */ + /* To force repair if reopened */ + _ma_mark_file_changed(info); + /* Fall trough */ case HA_EXTRA_PREPARE_FOR_RENAME: { my_bool do_flush= test(function != HA_EXTRA_PREPARE_FOR_DROP); diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c index e1986a7dfaa..b355d7bc792 100644 --- a/storage/maria/ma_locking.c +++ b/storage/maria/ma_locking.c @@ -387,6 +387,9 @@ int _ma_test_if_changed(register MARIA_HA *info) open_count is not maintained on disk for temporary tables. */ +#define _MA_ALREADY_MARKED_FILE_CHANGED \ + ((share->state.changed & STATE_CHANGED) && share->global_changed) + int _ma_mark_file_changed(MARIA_HA *info) { uchar buff[3]; @@ -394,8 +397,6 @@ int _ma_mark_file_changed(MARIA_HA *info) int error= 1; DBUG_ENTER("_ma_mark_file_changed"); -#define _MA_ALREADY_MARKED_FILE_CHANGED \ - ((share->state.changed & STATE_CHANGED) && share->global_changed) if (_MA_ALREADY_MARKED_FILE_CHANGED) DBUG_RETURN(0); pthread_mutex_lock(&share->intern_lock); /* recheck under mutex */ diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index 65ad767d8ef..7b3065b0208 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -312,11 +312,14 @@ int maria_apply_log(LSN from_lsn, enum maria_apply_log_way apply, now= my_getsystime(); in_redo_phase= TRUE; + trnman_init(max_trid_in_control_file); if (run_redo_phase(from_lsn, apply)) { ma_message_no_user(0, "Redo phase failed"); + trnman_destroy(); goto err; } + trnman_destroy(); if ((uncommitted_trans= end_of_redo_phase(should_run_undo_phase)) == (uint)-1) diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index ad93d566578..1d60beece6b 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -390,6 +390,7 @@ typedef struct st_maria_share my_bool now_transactional; my_bool have_versioning; my_bool key_del_used; /* != 0 if key_del is locked */ + my_bool deleting; /* we are going to delete this table */ #ifdef THREAD THR_LOCK lock; void (*lock_restore_status)(void *); diff --git a/storage/myisam/mi_close.c b/storage/myisam/mi_close.c index 3d860bbead6..fbd24237286 100644 --- a/storage/myisam/mi_close.c +++ b/storage/myisam/mi_close.c @@ -64,8 +64,9 @@ int mi_close(register MI_INFO *info) if (share->kfile >= 0) abort();); if (share->kfile >= 0 && flush_key_blocks(share->key_cache, share->kfile, - share->temporary ? FLUSH_IGNORE_CHANGED : - FLUSH_RELEASE)) + ((share->temporary || share->deleting) ? + FLUSH_IGNORE_CHANGED : + FLUSH_RELEASE))) error=my_errno; if (share->kfile >= 0) { diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c index 9c5dade28ab..64e7a55231d 100644 --- a/storage/myisam/mi_extra.c +++ b/storage/myisam/mi_extra.c @@ -256,8 +256,13 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) share->last_version= 0L; /* Impossible version */ pthread_mutex_unlock(&THR_LOCK_myisam); break; - case HA_EXTRA_PREPARE_FOR_RENAME: case HA_EXTRA_PREPARE_FOR_DROP: + /* Signals about intent to delete this table */ + share->deleting= TRUE; + share->global_changed= FALSE; /* force writing changed flag */ + _mi_mark_file_changed(info); + /* Fall trough */ + case HA_EXTRA_PREPARE_FOR_RENAME: pthread_mutex_lock(&THR_LOCK_myisam); share->last_version= 0L; /* Impossible version */ pthread_mutex_lock(&share->intern_lock); diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index 964501aa979..2ded6a8e8cd 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -58,6 +58,8 @@ MI_INFO *test_if_reopen(char *filename) { MI_INFO *info=(MI_INFO*) pos->data; MYISAM_SHARE *share=info->s; + DBUG_ASSERT(strcmp(share->unique_file_name,filename) || + share->last_version); if (!strcmp(share->unique_file_name,filename) && share->last_version) return info; } diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 680bdbf16dd..48e5d92a9a9 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -221,6 +221,7 @@ typedef struct st_mi_isam_share my_bool changed, /* If changed since lock */ global_changed, /* If changed since open */ not_flushed, temporary, delay_key_write, concurrent_insert; + my_bool deleting; /* we are going to delete this table */ #ifdef THREAD THR_LOCK lock; pthread_mutex_t intern_lock; /* Locking for use with _locking */ From af51917d1e2e47eaee5e39a3d83ce09815ab4d1c Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 10 Feb 2010 23:26:06 +0200 Subject: [PATCH 321/344] Added option --temporary-tables to test speed of temporary tables mysql-test/suite/parts/t/partition_repair_myisam-master.opt: Added missing file from last push sql-bench/bench-init.pl.sh: Added options: --temporary-tables to test speed of temporary tables sql-bench/server-cfg.sh: Added limit for number of temporary tables one can create sql-bench/test-connect.sh: Skip test that doesn't work with temporary tables. sql-bench/test-create.sh: Added limit for number of temporary tables one can create --- .../t/partition_repair_myisam-master.opt | 1 + sql-bench/bench-init.pl.sh | 7 ++- sql-bench/server-cfg.sh | 38 +++++++++++++++- sql-bench/test-connect.sh | 45 +++++++++++-------- sql-bench/test-create.sh | 14 ++++-- 5 files changed, 79 insertions(+), 26 deletions(-) create mode 100644 mysql-test/suite/parts/t/partition_repair_myisam-master.opt diff --git a/mysql-test/suite/parts/t/partition_repair_myisam-master.opt b/mysql-test/suite/parts/t/partition_repair_myisam-master.opt new file mode 100644 index 00000000000..44fc50f599c --- /dev/null +++ b/mysql-test/suite/parts/t/partition_repair_myisam-master.opt @@ -0,0 +1 @@ +--myisam-recover=off diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh index 2d9927947d2..f1d4bd9edec 100644 --- a/sql-bench/bench-init.pl.sh +++ b/sql-bench/bench-init.pl.sh @@ -39,7 +39,7 @@ require "$pwd/server-cfg" || die "Can't read Configuration file: $!\n"; $|=1; # Output data immediately -$opt_skip_test=$opt_skip_create=$opt_skip_delete=$opt_verbose=$opt_fast_insert=$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=$opt_log=$opt_use_old_results=$opt_help=$opt_odbc=$opt_small_test=$opt_small_tables=$opt_samll_key_tables=$opt_stage=$opt_old_headers=$opt_die_on_errors=$opt_tcpip=$opt_random=$opt_only_missing_tests=0; +$opt_skip_test=$opt_skip_create=$opt_skip_delete=$opt_verbose=$opt_fast_insert=$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=$opt_log=$opt_use_old_results=$opt_help=$opt_odbc=$opt_small_test=$opt_small_tables=$opt_samll_key_tables=$opt_stage=$opt_old_headers=$opt_die_on_errors=$opt_tcpip=$opt_random=$opt_only_missing_tests=$opt_temporary_tables=0; $opt_cmp=$opt_user=$opt_password=$opt_connect_options=$opt_connect_command= ""; $opt_server="mysql"; $opt_dir="output"; $opt_host="localhost";$opt_database="test"; @@ -59,7 +59,7 @@ $log_prog_args=join(" ", skip_arguments(\@ARGV,"comments","cmp","server", "use-old-results","skip-test", "optimization","hw", "machine", "dir", "suffix", "log")); -GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","threads=i","random","old-headers","die-on-errors","create-options=s","hires","tcpip","silent","optimization=s","hw=s","socket=s","connect-options=s","connect-command=s","only-missing-tests") || usage(); +GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","threads=i","random","old-headers","die-on-errors","create-options=s","hires","tcpip","silent","optimization=s","hw=s","socket=s","connect-options=s","connect-command=s","only-missing-tests","temporary-tables") || usage(); usage() if ($opt_help); $server=get_server($opt_server,$opt_host,$opt_database,$opt_odbc, @@ -454,6 +454,9 @@ All benchmarks takes the following options: create all MySQL tables as InnoDB tables use: --create-options=ENGINE=InnoDB +--temporary-tables + Use temporary tables for all tests. + --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 3ff1ce99659..76334d76108 100644 --- a/sql-bench/server-cfg.sh +++ b/sql-bench/server-cfg.sh @@ -159,6 +159,7 @@ sub new $limits{'max_index'} = 16; # Max number of keys $limits{'max_index_parts'} = 16; # Max segments/key $limits{'max_tables'} = (($machine || '') =~ "^win") ? 5000 : 65000; + $limits{'max_temporary_tables'}= 400; $limits{'max_text_size'} = 1000000; # Good enough for tests $limits{'multi_drop'} = 1; # Drop table can take many tables $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1' @@ -189,6 +190,7 @@ sub new $self->{'transactions'} = 1; # Transactions enabled $limits{'max_columns'} = 90; # Max number of columns in table $limits{'max_tables'} = 32; # No comments + $limits{'max_temporary_tables'}= $limits{"max_tables"}; } if (defined($main::opt_create_options) && $main::opt_create_options =~ /engine=bdb/i) @@ -200,6 +202,7 @@ sub new { $limits{'working_blobs'} = 0; # Blobs not implemented yet $limits{'max_tables'} = 500; + $limits{'max_temporary_tables'}= $limits{"max_tables"}; $self->{'transactions'} = 1; # Transactions enabled } @@ -270,7 +273,14 @@ sub create my($self,$table_name,$fields,$index,$options) = @_; my($query,@queries); - $query="create table $table_name ("; + if ($main::opt_temporary_tables) + { + $query="create temporary table $table_name ("; + } + else + { + $query="create table $table_name ("; + } foreach $field (@$fields) { # $field =~ s/ decimal/ double(10,2)/i; @@ -393,6 +403,7 @@ sub new $limits{'max_conditions'} = 74; $limits{'max_columns'} = 75; $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; $limits{'max_text_size'} = 32000; $limits{'query_size'} = 65535; $limits{'max_index'} = 5; @@ -622,7 +633,9 @@ sub new $limits{'max_conditions'} = 9999; # This makes Pg real slow $limits{'max_index'} = 64; # Big enough $limits{'max_index_parts'} = 16; - $limits{'max_tables'} = 5000; # 10000 crashes pg 7.0.2 + $limits{'max_tables'} = 65000; + $limits{'max_temporary_tables'}= $limits{"max_tables"}; + $limits{'max_text_size'} = 65000; # Good enough for test $limits{'multi_drop'} = 1; $limits{'order_by_position'} = 1; @@ -873,6 +886,8 @@ sub new $limits{'max_conditions'} = 9999; # Probably big enough $limits{'max_columns'} = 2000; # From crash-me $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; + $limits{'max_text_size'} = 65492; # According to tests $limits{'query_size'} = 65535; # Probably a limit $limits{'max_index'} = 64; # Probably big enough @@ -1104,6 +1119,7 @@ sub new # above this value .... but can handle 2419 columns # maybe something for crash-me ... but how to check ??? $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; $limits{'max_text_size'} = 4095; # max returned .... $limits{'query_size'} = 65535; # Not a limit, big enough $limits{'max_index'} = 64; # Big enough @@ -1374,6 +1390,8 @@ sub new $limits{'max_conditions'} = 9999; # (Actually not a limit) $limits{'max_columns'} = 254; # Max number of columns in table $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; + $limits{'max_text_size'} = 2000; # Limit for blob test-connect $limits{'query_size'} = 65525; # Max size with default buffers. $limits{'max_index'} = 16; # Max number of keys @@ -1647,6 +1665,8 @@ sub new $limits{'max_column_name'} = 18; # max table and column name $limits{'max_columns'} = 994; # Max number of columns in table $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; + $limits{'max_index'} = 64; # Max number of keys $limits{'max_index_parts'} = 15; # Max segments/key $limits{'max_text_size'} = 65535; # Max size with default buffers. ?? @@ -1835,6 +1855,8 @@ sub new $limits{'max_conditions'} = 97; # We get 'Query is too complex' $limits{'max_columns'} = 255; # Max number of columns in table $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; + $limits{'max_text_size'} = 255; # Max size with default buffers. $limits{'query_size'} = 65535; # Not a limit, big enough $limits{'max_index'} = 32; # Max number of keys @@ -2020,6 +2042,8 @@ sub new $limits{'max_conditions'} = 1030; # We get 'Query is too complex' $limits{'max_columns'} = 250; # Max number of columns in table $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; + $limits{'max_text_size'} = 9830; # Max size with default buffers. $limits{'query_size'} = 9830; # Max size with default buffers. $limits{'max_index'} = 64; # Max number of keys @@ -2216,6 +2240,8 @@ sub new $limits{'max_conditions'} = 1030; # We get 'Query is too complex' $limits{'max_columns'} = 250; # Max number of columns in table $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; + $limits{'max_text_size'} = 9830; # Max size with default buffers. $limits{'query_size'} = 9830; # Max size with default buffers. $limits{'max_index'} = 64; # Max number of keys @@ -2448,6 +2474,8 @@ sub new $limits{'max_conditions'} = 50; # (Actually not a limit) $limits{'max_columns'} = 254; # Max number of columns in table $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; + $limits{'max_text_size'} = 2000; # Limit for blob test-connect $limits{'query_size'} = 65525; # Max size with default buffers. $limits{'max_index'} = 16; # Max number of keys @@ -2652,6 +2680,8 @@ sub new $limits{'max_conditions'} = 418; # We get 'Query is too complex' $limits{'max_columns'} = 500; # Max number of columns in table $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; + $limits{'max_text_size'} = 254; # Max size with default buffers. $limits{'query_size'} = 254; # Max size with default buffers. $limits{'max_index'} = 48; # Max number of keys @@ -2830,6 +2860,7 @@ sub new $limits{'max_conditions'} = 9999; # (Actually not a limit) $limits{'max_columns'} = 252; # Max number of columns in table $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; $limits{'max_text_size'} = 15000; # Max size with default buffers. $limits{'query_size'} = 1000000; # Max size with default buffers. $limits{'max_index'} = 32; # Max number of keys @@ -3032,6 +3063,7 @@ sub new $limits{'max_conditions'} = 9999; # (Actually not a limit) $limits{'max_columns'} = 252; # Max number of columns in table $limits{'max_tables'} = 65000; # Should be big enough + $limits{'max_temporary_tables'}= $limits{"max_tables"}; $limits{'max_text_size'} = 15000; # Max size with default buffers. $limits{'query_size'} = 1000000; # Max size with default buffers. $limits{'max_index'} = 65000; # Max number of keys @@ -3228,6 +3260,7 @@ sub new # The following should be 8192, but is smaller because Frontbase crashes.. $limits{'max_columns'} = 150; # Max number of columns in table $limits{'max_tables'} = 5000; # 10000 crashed FrontBase + $limits{'max_temporary_tables'}= $limits{"max_tables"}; $limits{'max_text_size'} = 65000; # Max size with default buffers. $limits{'query_size'} = 8000000; # Max size with default buffers. $limits{'max_index'} = 38; # Max number of keys @@ -3440,6 +3473,7 @@ sub new $limits{'max_conditions'} = 9999; # (Actually not a limit) * $limits{'max_columns'} = 1023; # Max number of columns in table * $limits{'max_tables'} = 65000; # Should be big enough * unlimited actually + $limits{'max_temporary_tables'}= $limits{"max_tables"}; $limits{'max_text_size'} = 15000; # Max size with default buffers. $limits{'query_size'} = 64*1024; # Max size with default buffers. *64 kb by default. May be set by system variable $limits{'max_index'} = 510; # Max number of keys * diff --git a/sql-bench/test-connect.sh b/sql-bench/test-connect.sh index d0f3f0791a4..52566f7bb54 100644 --- a/sql-bench/test-connect.sh +++ b/sql-bench/test-connect.sh @@ -161,41 +161,48 @@ if ($opt_fast && defined($server->{vacuum})) { $server->vacuum(0,\$dbh); } -$dbh->disconnect; +if (!$main::opt_temporary_tables) +{ + $dbh->disconnect; +} # # First test connect/select/disconnect # -print "Testing connect/select 1 row from table/disconnect\n"; - -$loop_time=new Benchmark; -$errors=0; - -for ($i=0 ; $i < $small_loop_count ; $i++) +if (!$main::opt_temporary_tables) { - for ($j=0; $j < $max_test ; $j++) + print "Testing connect/select 1 row from table/disconnect\n"; + + $loop_time=new Benchmark; + $errors=0; + + for ($i=0 ; $i < $small_loop_count ; $i++) { - last if ($dbh = DBI->connect($server->{'data_source'}, $opt_user, $opt_password)); - $errors++; - } - die $DBI::errstr if ($j == $max_test); + for ($j=0; $j < $max_test ; $j++) + { + last if ($dbh = DBI->connect($server->{'data_source'}, $opt_user, $opt_password)); + $errors++; + } + die $DBI::errstr if ($j == $max_test); - $sth = $dbh->do("select a,i,s,$i from bench1") # Select * from table with 1 record + $sth = $dbh->do("select a,i,s,$i from bench1") # Select * from table with 1 record or die $DBI::errstr; - $dbh->disconnect; -} + $dbh->disconnect; + } -$end_time=new Benchmark; -print "Warning: $errors connections didn't work without a time delay\n" if ($errors); -print "Time to connect+select_1_row ($small_loop_count): " . + $end_time=new Benchmark; + print "Warning: $errors connections didn't work without a time delay\n" if ($errors); + print "Time to connect+select_1_row ($small_loop_count): " . timestr(timediff($end_time, $loop_time),"all") . "\n\n"; + $dbh = $server->connect(); +} + # # The same test, but without connect/disconnect # print "Testing select 1 row from table\n"; -$dbh = $server->connect(); $loop_time=new Benchmark; for ($i=0 ; $i < $opt_loop_count ; $i++) diff --git a/sql-bench/test-create.sh b/sql-bench/test-create.sh index 40fd9c49ae8..e2a51f96fff 100644 --- a/sql-bench/test-create.sh +++ b/sql-bench/test-create.sh @@ -47,7 +47,15 @@ if ($opt_small_test) $create_loop_count/=1000; } -$max_tables=min($limits->{'max_tables'},$opt_loop_count); +if ($opt_temporary_tables) +{ + $max_tables=min($limits->{'max_tables'},$opt_loop_count); +} +else +{ + $max_tables=min($limits->{'max_tables'},$opt_loop_count); + $max_tables=400; +} if ($opt_small_test) { @@ -71,7 +79,7 @@ $dbh = $server->connect(); if ($opt_force) # If tables used in this test exist, drop 'em { print "Okay..Let's make sure that our tables don't exist yet.\n\n"; - for ($i=1 ; $i <= $max_tables ; $i++) + for ($i=1 ; $i <= max($max_tables, $create_loop_count) ; $i++) { $dbh->do("drop table bench_$i" . $server->{'drop_attr'}); } @@ -245,7 +253,7 @@ for ($i=2 ; $i <= $keys ; $i++) } $loop_time=new Benchmark; -for ($i=1 ; $i <= $opt_loop_count ; $i++) +for ($i=1 ; $i <= $create_loop_count ; $i++) { do_many($dbh,$server->create("bench_$i", \@fields, \@keys)); $dbh->do("drop table bench_$i" . $server->{'drop_attr'}) or die $DBI::errstr; From 6e0d92419e1d251854ef08dcdf901427ad81ea3e Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Thu, 11 Feb 2010 21:15:24 +0200 Subject: [PATCH 322/344] Fix for LPBug#520243: useability bug of thread pool configuration Now mysqld --help --verbose shows the value for thread-handling Fixed also that mysqld --one-thread works as expected. --- sql/mysqld.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bf09df8a465..5eb18ddda80 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -598,6 +598,7 @@ char *mysqld_unix_port, *opt_mysql_tmpdir; const char **errmesg; /**< Error messages */ const char *myisam_recover_options_str="OFF"; const char *myisam_stats_method_str="nulls_unequal"; +const char *opt_thread_handling= thread_handling_typelib.type_names[0]; /** name of reference on left espression in rewritten IN subquery */ const char *in_left_expr_name= ""; @@ -7290,7 +7291,8 @@ The minimum value for this variable is 4096.", 1024, 0}, {"thread_handling", OPT_THREAD_HANDLING, "Define threads usage for handling queries: " - "one-thread-per-connection or no-threads", 0, 0, + "one-thread-per-connection or no-threads", + (uchar**) &opt_thread_handling, (uchar**) &opt_thread_handling, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT, "1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a key of the underlying table is used in queries with a LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which does not contain a key of the underlying table and the query uses a LIMIT clause (usually get from GUI tools).", @@ -8721,14 +8723,15 @@ mysqld_get_one_option(int optid, break; } case OPT_ONE_THREAD: - global_system_variables.thread_handling= - SCHEDULER_ONE_THREAD_PER_CONNECTION; + global_system_variables.thread_handling= SCHEDULER_NO_THREADS; + opt_thread_handling= thread_handling_typelib.type_names[global_system_variables.thread_handling]; break; case OPT_THREAD_HANDLING: { int id; if (!find_opt_type(argument, &thread_handling_typelib, opt->name, &id)) global_system_variables.thread_handling= id - 1; + opt_thread_handling= thread_handling_typelib.type_names[global_system_variables.thread_handling]; break; } case OPT_FT_BOOLEAN_SYNTAX: From 6e7241caa52151a9cd1a8e5648bd3e8bf6ce973c Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 12 Feb 2010 16:21:13 +0200 Subject: [PATCH 323/344] Fix for LPBUG#516148 Test maria.maria3 fails when --without-maria-tmp-tables is set mysql-test/suite/maria/r/maria3.result: Updated test results mysql-test/suite/maria/t/maria3.test: Don't show maria_used_for_temp_tables, as it's value is depending on configure options --- mysql-test/suite/maria/r/maria3.result | 5 ++--- mysql-test/suite/maria/t/maria3.test | 2 +- storage/maria/ha_maria.cc | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/maria/r/maria3.result b/mysql-test/suite/maria/r/maria3.result index a49b25beb33..58e170cd3c3 100644 --- a/mysql-test/suite/maria/r/maria3.result +++ b/mysql-test/suite/maria/r/maria3.result @@ -301,7 +301,7 @@ check table t1 extended; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; -show variables like 'maria%'; +select lower(variable_name) as Variable_name, Variable_value as Value from information_schema.session_variables where variable_name like "maria%" and variable_name not like "maria_used_for_temp_tables" order by 1; Variable_name Value maria_block_size 8192 maria_checkpoint_interval 30 @@ -309,16 +309,15 @@ maria_force_start_after_recovery_failures 0 maria_log_file_size 4294959104 maria_log_purge_type immediate maria_max_sort_file_size 9223372036853727232 -maria_page_checksum OFF maria_pagecache_age_threshold 300 maria_pagecache_buffer_size 8384512 maria_pagecache_division_limit 100 +maria_page_checksum OFF maria_recover OFF maria_repair_threads 1 maria_sort_buffer_size 8388608 maria_stats_method nulls_unequal maria_sync_log_dir NEWFILE -maria_used_for_temp_tables ON show status like 'maria%'; Variable_name Value Maria_pagecache_blocks_not_flushed # diff --git a/mysql-test/suite/maria/t/maria3.test b/mysql-test/suite/maria/t/maria3.test index a476c75aa44..45765b3b868 100644 --- a/mysql-test/suite/maria/t/maria3.test +++ b/mysql-test/suite/maria/t/maria3.test @@ -259,7 +259,7 @@ drop table t1; # Fix if we are using safemalloc --replace_result 8388572 8388600 -show variables like 'maria%'; +select lower(variable_name) as Variable_name, Variable_value as Value from information_schema.session_variables where variable_name like "maria%" and variable_name not like "maria_used_for_temp_tables" order by 1; --replace_column 2 # show status like 'maria%'; diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 5ec0a6b748e..4e18155b46e 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -3278,11 +3278,11 @@ static struct st_mysql_sys_var* system_variables[]= { MYSQL_SYSVAR(block_size), MYSQL_SYSVAR(checkpoint_interval), MYSQL_SYSVAR(force_start_after_recovery_failures), - MYSQL_SYSVAR(page_checksum), MYSQL_SYSVAR(log_dir_path), MYSQL_SYSVAR(log_file_size), MYSQL_SYSVAR(log_purge_type), MYSQL_SYSVAR(max_sort_file_size), + MYSQL_SYSVAR(page_checksum), MYSQL_SYSVAR(pagecache_age_threshold), MYSQL_SYSVAR(pagecache_buffer_size), MYSQL_SYSVAR(pagecache_division_limit), From 62db6839b82d824567979ef3e05caccd67ed11ec Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Feb 2010 18:39:28 +0100 Subject: [PATCH 324/344] configure.in - Changes to the banner text - Use older AC_PROG_LIBTOOL (Bug#51009) scripts/mysql_install_db.sh - Changes to banner text --- configure.in | 20 +++++++------------- scripts/mysql_install_db.sh | 6 +----- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/configure.in b/configure.in index f2e83abc60c..32326df06aa 100644 --- a/configure.in +++ b/configure.in @@ -14,8 +14,7 @@ AC_CANONICAL_SYSTEM # TAR files, the path name is split into two parts, a 155 chacater # first part and a 100 character second part. AM_INIT_AUTOMAKE([1.9 tar-ustar]) -LT_INIT -LT_PREREQ([1.5.6]) +AC_PROG_LIBTOOL AM_CONFIG_HEADER([include/config.h]) @@ -2912,17 +2911,12 @@ AC_CONFIG_COMMANDS_POST(ac_configure_args="$ac_configure_args CFLAGS='$CFLAGS' C AC_OUTPUT -echo -echo "MySQL has a Web site at http://www.mysql.com/ which carries details on the" -echo "latest release, upcoming features, and other information to make your" -echo "work or play with MySQL more productive. There you can also find" -echo "information about mailing lists for MySQL discussion." -echo -echo "Remember to check the platform specific part of the reference manual for" -echo "hints about installing MySQL on your platform. Also have a look at the" -echo "files in the Docs directory." -echo -# The following text is checked in ./Do-compile to verify that configure +# The first line "Thank you ..." is checked in ./Do-compile to verify that configure # ended sucessfully - don't remove it. +echo echo "Thank you for choosing MySQL!" echo +echo "Remember to check the platform specific part of the reference manual" +echo "for hints about installing MySQL on your platform." +echo "Also have a look at the files in the Docs directory." +echo diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 20b7973cb4e..c5e4a1f1cba 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -410,8 +410,7 @@ else echo "Try 'mysqld --help' if you have problems with paths. Using --log" echo "gives you a log in $ldata that may be helpful." echo - echo "The latest information about MySQL is available on the web at" - echo "http://www.mysql.com/. Please consult the MySQL manual section" + echo "Please consult the MySQL manual section" echo "'Problems running mysql_install_db', and the manual section that" echo "describes problems on your OS. Another information source are the" echo "MySQL email archives available at http://lists.mysql.com/." @@ -470,9 +469,6 @@ then echo echo "Please report any problems with the $scriptdir/mysqlbug script!" echo - echo "The latest information about MySQL is available at http://www.mysql.com/" - echo "Support MySQL by buying support/licenses from http://shop.mysql.com/" - echo fi exit 0 From 84e1866181106f910ef0c1f5531ba7bda4f0e379 Mon Sep 17 00:00:00 2001 From: Hakan Kuecuekyilmaz Date: Wed, 17 Feb 2010 21:10:02 +0100 Subject: [PATCH 325/344] Increased loop counts of sql-bench tests to get run times around 5 minutes on current machines. Tested on a Xeon machine and a new dual core laptop. --- sql-bench/test-ATIS.sh | 2 +- sql-bench/test-alter-table.sh | 2 +- sql-bench/test-big-tables.sh | 2 +- sql-bench/test-connect.sh | 2 +- sql-bench/test-select.sh | 2 +- sql-bench/test-transactions.sh | 4 ++-- sql-bench/test-wisconsin.sh | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sql-bench/test-ATIS.sh b/sql-bench/test-ATIS.sh index 79b38a95506..ee697d4f319 100644 --- a/sql-bench/test-ATIS.sh +++ b/sql-bench/test-ATIS.sh @@ -28,7 +28,7 @@ use Cwd; use DBI; use Benchmark; -$opt_loop_count=100; # Run selects this many times +$opt_loop_count=5000; # Run selects this many times $pwd = cwd(); $pwd = "." if ($pwd eq ''); require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n"; diff --git a/sql-bench/test-alter-table.sh b/sql-bench/test-alter-table.sh index 36db26f4bf3..03d40a01276 100644 --- a/sql-bench/test-alter-table.sh +++ b/sql-bench/test-alter-table.sh @@ -25,7 +25,7 @@ use DBI; use Benchmark; $opt_start_field_count=8; # start with this many fields -$opt_loop_count=100; # How many tests to do +$opt_loop_count=10000; # How many tests to do $opt_row_count=1000; # Rows in the table $opt_field_count=1000; # Add until this many fields. $opt_time_limit=10*60; # Don't wait more than 10 min for some tests diff --git a/sql-bench/test-big-tables.sh b/sql-bench/test-big-tables.sh index 33694a42e17..de2b0830bd3 100644 --- a/sql-bench/test-big-tables.sh +++ b/sql-bench/test-big-tables.sh @@ -25,7 +25,7 @@ use Cwd; use DBI; use Benchmark; -$opt_loop_count=1000; # Change this to make test harder/easier +$opt_loop_count=70000; # Change this to make test harder/easier $opt_field_count=1000; $pwd = cwd(); $pwd = "." if ($pwd eq ''); diff --git a/sql-bench/test-connect.sh b/sql-bench/test-connect.sh index 52566f7bb54..d2b8530ed0d 100644 --- a/sql-bench/test-connect.sh +++ b/sql-bench/test-connect.sh @@ -28,7 +28,7 @@ use Cwd; use DBI; use Benchmark; -$opt_loop_count=100000; # Change this to make test harder/easier +$opt_loop_count=500000; # Change this to make test harder/easier $str_length=65000; # This is the length of blob strings in PART:5 $max_test=20; # How many times to test if the server is busy diff --git a/sql-bench/test-select.sh b/sql-bench/test-select.sh index 41e8205196e..0bcc9426cdf 100644 --- a/sql-bench/test-select.sh +++ b/sql-bench/test-select.sh @@ -26,7 +26,7 @@ use Getopt::Long; use Benchmark; $opt_loop_count=10000; -$opt_medium_loop_count=1000; +$opt_medium_loop_count=7000; $opt_small_loop_count=10; $opt_regions=6; $opt_groups=100; diff --git a/sql-bench/test-transactions.sh b/sql-bench/test-transactions.sh index edbfef0e3ce..f6de5641cbd 100644 --- a/sql-bench/test-transactions.sh +++ b/sql-bench/test-transactions.sh @@ -28,8 +28,8 @@ use Benchmark; $opt_groups=27; # Characters are 'A' -> Z -$opt_loop_count=10000; # Change this to make test harder/easier -$opt_medium_loop_count=100; # Change this to make test harder/easier +$opt_loop_count=500000; # Change this to make test harder/easier +$opt_medium_loop_count=10000; # Change this to make test harder/easier $pwd = cwd(); $pwd = "." if ($pwd eq ''); require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n"; diff --git a/sql-bench/test-wisconsin.sh b/sql-bench/test-wisconsin.sh index 1974461a7c4..0dbd88dd62d 100644 --- a/sql-bench/test-wisconsin.sh +++ b/sql-bench/test-wisconsin.sh @@ -21,7 +21,7 @@ use Cwd; use DBI; use Benchmark; -$opt_loop_count=10; +$opt_loop_count=5000; $pwd = cwd(); $pwd = "." if ($pwd eq ''); require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n"; From 69028d5127fcf964c5ab09f0b84ff9780a3326ad Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Thu, 18 Feb 2010 15:03:52 +0300 Subject: [PATCH 326/344] LPBUG#523593: Running RQG optimizer_no_subquery crashes MariaDB - When analying multiple equalities, take into account that they may not have a single table field that belongs to one of the tables that we're trying to eliminate (and they are not useful for table elimination in that case) mysql-test/r/table_elim.result: LPBUG#523593: Running RQG optimizer_no_subquery crashes MariaDB - Testcase mysql-test/t/table_elim.test: LPBUG#523593: Running RQG optimizer_no_subquery crashes MariaDB - Testcase --- mysql-test/r/table_elim.result | 46 ++++++++++++++++++++++++++++++ mysql-test/t/table_elim.test | 51 ++++++++++++++++++++++++++++++++++ sql/opt_table_elimination.cc | 12 ++++++-- 3 files changed, 107 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/table_elim.result b/mysql-test/r/table_elim.result index 05ec4eed6ba..8f8e514e470 100644 --- a/mysql-test/r/table_elim.result +++ b/mysql-test/r/table_elim.result @@ -418,3 +418,49 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 4 1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 2 Using where drop table t1, t2; +# +# LPBUG#523593: Running RQG optimizer_no_subquery crashes MariaDB +# +CREATE TABLE t1 ( +`pk` int(11) NOT NULL AUTO_INCREMENT, +`col_int_nokey` int(11) DEFAULT NULL, +`col_int_key` int(11) DEFAULT NULL, +`col_date_key` date DEFAULT NULL, +`col_date_nokey` date DEFAULT NULL, +`col_time_key` time DEFAULT NULL, +`col_time_nokey` time DEFAULT NULL, +`col_datetime_key` datetime DEFAULT NULL, +`col_datetime_nokey` datetime DEFAULT NULL, +`col_varchar_key` varchar(1) DEFAULT NULL, +`col_varchar_nokey` varchar(1) DEFAULT NULL, +PRIMARY KEY (`pk`), +KEY `col_int_key` (`col_int_key`), +KEY `col_date_key` (`col_date_key`), +KEY `col_time_key` (`col_time_key`), +KEY `col_datetime_key` (`col_datetime_key`), +KEY `col_varchar_key` (`col_varchar_key`,`col_int_key`) +); +CREATE TABLE t2 LIKE t1; +INSERT INTO t1 VALUES +(10,7,8,NULL,NULL,'01:27:35','01:27:35','2002-02-26 06:14:37','2002-02-26 06:14:37','v','v'), +(11,1,9,'2006-06-14','2006-06-14','19:48:31','19:48:31','1900-01-01 00:00:00','1900-01-01 00:00:00','r','r'); +INSERT INTO t2 SELECT * FROM t1; +SELECT table2.col_int_key AS field1 +FROM ( +t2 AS table1 +RIGHT OUTER JOIN +( +( t1 AS table2 STRAIGHT_JOIN +t1 AS table3 ON ( +(table3.col_varchar_nokey = table2.col_varchar_key ) AND +(table3.pk = table2.col_int_key)) +) +) ON +( +(table3.col_varchar_key = table2.col_varchar_key) OR +(table3.col_int_key = table2.pk) +) +) +HAVING field1 < 216; +field1 +DROP TABLE t1, t2; diff --git a/mysql-test/t/table_elim.test b/mysql-test/t/table_elim.test index 75918703347..244936ed628 100644 --- a/mysql-test/t/table_elim.test +++ b/mysql-test/t/table_elim.test @@ -336,3 +336,54 @@ select t1.* from t1 left join t2 on (t2.pk=3 and t2.b=3) or (t2.pk= 4 and t2.b=3); drop table t1, t2; + +--echo # +--echo # LPBUG#523593: Running RQG optimizer_no_subquery crashes MariaDB +--echo # + +CREATE TABLE t1 ( + `pk` int(11) NOT NULL AUTO_INCREMENT, + `col_int_nokey` int(11) DEFAULT NULL, + `col_int_key` int(11) DEFAULT NULL, + `col_date_key` date DEFAULT NULL, + `col_date_nokey` date DEFAULT NULL, + `col_time_key` time DEFAULT NULL, + `col_time_nokey` time DEFAULT NULL, + `col_datetime_key` datetime DEFAULT NULL, + `col_datetime_nokey` datetime DEFAULT NULL, + `col_varchar_key` varchar(1) DEFAULT NULL, + `col_varchar_nokey` varchar(1) DEFAULT NULL, + PRIMARY KEY (`pk`), + KEY `col_int_key` (`col_int_key`), + KEY `col_date_key` (`col_date_key`), + KEY `col_time_key` (`col_time_key`), + KEY `col_datetime_key` (`col_datetime_key`), + KEY `col_varchar_key` (`col_varchar_key`,`col_int_key`) +); +CREATE TABLE t2 LIKE t1; + +INSERT INTO t1 VALUES + (10,7,8,NULL,NULL,'01:27:35','01:27:35','2002-02-26 06:14:37','2002-02-26 06:14:37','v','v'), + (11,1,9,'2006-06-14','2006-06-14','19:48:31','19:48:31','1900-01-01 00:00:00','1900-01-01 00:00:00','r','r'); +INSERT INTO t2 SELECT * FROM t1; + +SELECT table2.col_int_key AS field1 +FROM ( + t2 AS table1 + RIGHT OUTER JOIN + ( + ( t1 AS table2 STRAIGHT_JOIN + t1 AS table3 ON ( + (table3.col_varchar_nokey = table2.col_varchar_key ) AND + (table3.pk = table2.col_int_key)) + ) + ) ON + ( + (table3.col_varchar_key = table2.col_varchar_key) OR + (table3.col_int_key = table2.pk) + ) +) +HAVING field1 < 216; + +DROP TABLE t1, t2; + diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc index ef2a92f1797..5d952021365 100644 --- a/sql/opt_table_elimination.cc +++ b/sql/opt_table_elimination.cc @@ -1220,8 +1220,16 @@ void build_eq_mods_for_cond(Dep_analysis_context *ctx, bound_item= item; } } - exchange_sort(fvl, compare_field_values, NULL); - add_module_expr(ctx, eq_mod, *and_level, NULL, bound_item, fvl); + /* + Multiple equality is only useful if it includes at least one field from + the table that we could potentially eliminate: + */ + if (fvl->elements) + { + + exchange_sort(fvl, compare_field_values, NULL); + add_module_expr(ctx, eq_mod, *and_level, NULL, bound_item, fvl); + } break; } default: From 2840821cc92c302c9172ef6d47c484b5bdfcc785 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Tue, 23 Feb 2010 14:06:41 +0200 Subject: [PATCH 327/344] Fixed LP#524679: make test ORDER BY date_ord ASC (Problem was missing time_zone setting) --- mysql-test/t/func_if.test | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 4efea8e195e..8142f57c0de 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -5,6 +5,11 @@ drop table if exists t1; --enable_warnings +--disable_query_log +# Set timezone to something specific, to make it possible to use unix_timestamp +set time_zone="+03:00"; +--enable_query_log + # # Simple IF tests # @@ -163,5 +168,9 @@ SELECT * FROM (SELECT MAX(IFNULL(CAST(c AS UNSIGNED), 0)) FROM t1) AS te; DROP TABLE t1; - --echo End of 5.0 tests + +--disable_query_log +# Restore timezone to default +set time_zone= @@global.time_zone; +--enable_query_log From f04cf03f75ffca0b99562c027c1c57340d375f66 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 23 Feb 2010 13:04:58 +0100 Subject: [PATCH 328/344] fix for a possible DoS in the my_net_skip_rest() --- include/mysql.h.pp | 2 +- include/mysql_com.h | 2 +- sql/net_serv.cc | 6 ++++++ sql/sql_connect.cc | 3 ++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/mysql.h.pp b/include/mysql.h.pp index c333cb2bec5..3fb232cea51 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -28,7 +28,7 @@ typedef struct st_net { unsigned int *return_status; unsigned char reading_or_writing; char save_char; - my_bool unused0; + char net_skip_rest_factor; my_bool unused; my_bool compress; my_bool unused1; diff --git a/include/mysql_com.h b/include/mysql_com.h index 41941d01fd2..96eb8f21d3f 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -254,7 +254,7 @@ typedef struct st_net { unsigned int *return_status; unsigned char reading_or_writing; char save_char; - my_bool unused0; /* Please remove with the next incompatible ABI change. */ + char net_skip_rest_factor; my_bool unused; /* Please remove with the next incompatible ABI change */ my_bool compress; my_bool unused1; /* Please remove with the next incompatible ABI change. */ diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 4e1d507de2c..58ccde760c2 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -130,6 +130,7 @@ my_bool my_net_init(NET *net, Vio* vio) net->last_error[0]=0; net->compress=0; net->reading_or_writing=0; net->where_b = net->remain_in_buf=0; + net->net_skip_rest_factor= 0; net->last_errno=0; #ifdef USE_QUERY_CACHE query_cache_init_query(net); @@ -743,6 +744,7 @@ static my_bool net_safe_read(NET *net, uchar *buff, size_t length, static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed, ALARM *alarm_buff) { + longlong limit= net->max_packet_size*net->net_skip_rest_factor; uint32 old=remain; DBUG_ENTER("my_net_skip_rest"); DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain)); @@ -766,11 +768,15 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed, DBUG_RETURN(1); update_statistics(thd_increment_bytes_received(length)); remain -= (uint32) length; + limit-= length; + if (limit < 0) + DBUG_RETURN(1); } if (old != MAX_PACKET_LENGTH) break; if (net_safe_read(net, net->buff, NET_HEADER_SIZE, alarmed)) DBUG_RETURN(1); + limit-= NET_HEADER_SIZE; old=remain= uint3korr(net->buff); net->pkt_nr++; } diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 9f1597433d2..0de2c2d210a 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -474,7 +474,8 @@ check_user(THD *thd, enum enum_server_command command, } } my_ok(thd); - thd->password= test(passwd_len); // remember for error messages + thd->net.net_skip_rest_factor= 2; // skip at most 2*max_packet_size + thd->password= test(passwd_len); // remember for error messages /* Ready to handle queries */ DBUG_RETURN(0); } From 81424b5bdaeb841a56519aa6994194c443b32478 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Sat, 6 Mar 2010 15:09:02 +0300 Subject: [PATCH 329/344] LPBUG#524025 Running RQG outer_join test leads to crash Save no-records constant tables in JOIN::const_table_map before we invoke eliminate_tables(). Failure to do so caused crash when the same table was marked as constant two times mysql-test/r/table_elim.result: LPBUG#524025 Running RQG outer_join test leads to crash - Testcase mysql-test/t/table_elim.test: LPBUG#524025 Running RQG outer_join test leads to crash - Testcase sql/sql_select.cc: LPBUG#524025 Running RQG outer_join test leads to crash Save no-records constant tables in JOIN::const_table_map before we invoke eliminate_tables(). Failure to do so caused crash when the same table was marked as constant two times. --- mysql-test/r/table_elim.result | 73 +++++++++++++++++++++++++++++- mysql-test/t/table_elim.test | 82 +++++++++++++++++++++++++++++++++- sql/sql_select.cc | 6 ++- 3 files changed, 158 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/table_elim.result b/mysql-test/r/table_elim.result index 8f8e514e470..71fe02911fc 100644 --- a/mysql-test/r/table_elim.result +++ b/mysql-test/r/table_elim.result @@ -1,4 +1,4 @@ -drop table if exists t0, t1, t2, t3; +drop table if exists t0, t1, t2, t3, t4, t5, t6; drop view if exists v1, v2; create table t1 (a int); insert into t1 values (0),(1),(2),(3); @@ -464,3 +464,74 @@ t1 AS table3 ON ( HAVING field1 < 216; field1 DROP TABLE t1, t2; +# +# LPBUG#524025 Running RQG outer_join test leads to crash +# +CREATE TABLE t0 ( +pk int(11) NOT NULL AUTO_INCREMENT, +PRIMARY KEY (pk) +); +CREATE TABLE t1 ( +col_int int(11) DEFAULT NULL, +col_int_key int(11) DEFAULT NULL, +pk int(11) NOT NULL AUTO_INCREMENT, +col_varchar_10_latin1 varchar(10) DEFAULT NULL, +PRIMARY KEY (pk) +); +INSERT INTO t1 VALUES (5,5,1,'t'), (NULL,NULL,2,'y'); +CREATE TABLE t2 ( +col_int int(11) DEFAULT NULL +); +INSERT INTO t2 VALUES (8), (4); +CREATE TABLE t3 ( +pk int(11) NOT NULL AUTO_INCREMENT, +PRIMARY KEY (pk) +); +INSERT INTO t3 VALUES (1),(8); +CREATE TABLE t4 ( +pk int(11) NOT NULL AUTO_INCREMENT, +col_varchar_1024_latin1_key varchar(1024) DEFAULT NULL, +col_int int(11) DEFAULT NULL, +PRIMARY KEY (pk) +); +INSERT INTO t4 VALUES (1,'o',1), (2,'w',2); +CREATE TABLE t5 ( +col_varchar_1024_utf8_key varchar(1024) CHARACTER SET utf8 DEFAULT NULL, +col_varchar_1024_latin1_key varchar(1024) DEFAULT NULL, +col_varchar_10_utf8_key varchar(1024) CHARACTER SET utf8 DEFAULT NULL, +pk int(11) NOT NULL AUTO_INCREMENT, +col_int_key int(11) DEFAULT NULL, +PRIMARY KEY (pk) +); +INSERT INTO t5 VALUES ('k','a','z',1,2),('x','a','w',2,7); +CREATE TABLE t6 ( +col_int int(11) DEFAULT NULL, +col_int_key int(11) DEFAULT NULL +); +INSERT INTO t6 VALUES (6,1),(8,3); +SELECT +table3.col_int AS field1, +table1.col_int AS field2, +table1.col_int_key AS field3, +table1.pk AS field4, +table1.col_int AS field5, +table2.col_int AS field6 +FROM +t1 AS table1 +LEFT OUTER JOIN +t4 AS table2 +LEFT JOIN t6 AS table3 +RIGHT JOIN t3 AS table4 +LEFT JOIN t5 AS table5 ON table4.pk = table5.pk +LEFT JOIN t0 AS table6 ON table5.col_int_key = table6.pk +ON table3.col_int_key = table5.pk +ON table2.col_varchar_1024_latin1_key = table5.col_varchar_10_utf8_key +LEFT JOIN t6 AS table7 ON table2.pk = table7.col_int +ON table1.col_varchar_10_latin1 = table5.col_varchar_1024_latin1_key +LEFT JOIN t2 AS table8 ON table3.col_int = table8.col_int +WHERE +table1.col_int_key < table2.pk +HAVING +field4 != 6; +field1 field2 field3 field4 field5 field6 +drop table t0,t1,t2,t3,t4,t5,t6; diff --git a/mysql-test/t/table_elim.test b/mysql-test/t/table_elim.test index 244936ed628..7ad69d5bf37 100644 --- a/mysql-test/t/table_elim.test +++ b/mysql-test/t/table_elim.test @@ -2,7 +2,7 @@ # Table elimination (MWL#17) tests # --disable_warnings -drop table if exists t0, t1, t2, t3; +drop table if exists t0, t1, t2, t3, t4, t5, t6; drop view if exists v1, v2; --enable_warnings @@ -387,3 +387,83 @@ HAVING field1 < 216; DROP TABLE t1, t2; + +--echo # +--echo # LPBUG#524025 Running RQG outer_join test leads to crash +--echo # + +CREATE TABLE t0 ( + pk int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (pk) +); + +CREATE TABLE t1 ( + col_int int(11) DEFAULT NULL, + col_int_key int(11) DEFAULT NULL, + pk int(11) NOT NULL AUTO_INCREMENT, + col_varchar_10_latin1 varchar(10) DEFAULT NULL, + PRIMARY KEY (pk) +); +INSERT INTO t1 VALUES (5,5,1,'t'), (NULL,NULL,2,'y'); + +CREATE TABLE t2 ( + col_int int(11) DEFAULT NULL +); +INSERT INTO t2 VALUES (8), (4); + +CREATE TABLE t3 ( + pk int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (pk) +); +INSERT INTO t3 VALUES (1),(8); + +CREATE TABLE t4 ( + pk int(11) NOT NULL AUTO_INCREMENT, + col_varchar_1024_latin1_key varchar(1024) DEFAULT NULL, + col_int int(11) DEFAULT NULL, + PRIMARY KEY (pk) +); +INSERT INTO t4 VALUES (1,'o',1), (2,'w',2); + +CREATE TABLE t5 ( + col_varchar_1024_utf8_key varchar(1024) CHARACTER SET utf8 DEFAULT NULL, + col_varchar_1024_latin1_key varchar(1024) DEFAULT NULL, + col_varchar_10_utf8_key varchar(1024) CHARACTER SET utf8 DEFAULT NULL, + pk int(11) NOT NULL AUTO_INCREMENT, + col_int_key int(11) DEFAULT NULL, + PRIMARY KEY (pk) +); +INSERT INTO t5 VALUES ('k','a','z',1,2),('x','a','w',2,7); + +CREATE TABLE t6 ( + col_int int(11) DEFAULT NULL, + col_int_key int(11) DEFAULT NULL +); +INSERT INTO t6 VALUES (6,1),(8,3); + +SELECT + table3.col_int AS field1, + table1.col_int AS field2, + table1.col_int_key AS field3, + table1.pk AS field4, + table1.col_int AS field5, + table2.col_int AS field6 +FROM + t1 AS table1 + LEFT OUTER JOIN + t4 AS table2 + LEFT JOIN t6 AS table3 + RIGHT JOIN t3 AS table4 + LEFT JOIN t5 AS table5 ON table4.pk = table5.pk + LEFT JOIN t0 AS table6 ON table5.col_int_key = table6.pk + ON table3.col_int_key = table5.pk + ON table2.col_varchar_1024_latin1_key = table5.col_varchar_10_utf8_key + LEFT JOIN t6 AS table7 ON table2.pk = table7.col_int + ON table1.col_varchar_10_latin1 = table5.col_varchar_1024_latin1_key + LEFT JOIN t2 AS table8 ON table3.col_int = table8.col_int +WHERE + table1.col_int_key < table2.pk +HAVING + field4 != 6; + +drop table t0,t1,t2,t3,t4,t5,t6; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8d184617242..330cdcfff19 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2562,6 +2562,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, JOIN_TAB *stat,*stat_end,*s,**stat_ref; KEYUSE *keyuse,*start_keyuse; table_map outer_join=0; + table_map no_rows_const_tables= 0; SARGABLE_PARAM *sargables= 0; JOIN_TAB *stat_vector[MAX_TABLES+1]; DBUG_ENTER("make_join_statistics"); @@ -2622,6 +2623,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, #endif { // Empty table s->dependent= 0; // Ignore LEFT JOIN depend. + no_rows_const_tables |= table->map; set_position(join,const_count++,s,(KEYUSE*) 0); continue; } @@ -2658,6 +2660,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, !table->fulltext_searched && !join->no_const_tables) { set_position(join,const_count++,s,(KEYUSE*) 0); + no_rows_const_tables |= table->map; } } stat_vector[i]=0; @@ -2703,9 +2706,10 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, ~outer_join, join->select_lex, &sargables)) goto error; - join->const_table_map= 0; + join->const_table_map= no_rows_const_tables; join->const_tables= const_count; eliminate_tables(join); + join->const_table_map &= ~no_rows_const_tables; const_count= join->const_tables; found_const_table_map= join->const_table_map; From f0cf48a0c450d5cb4f3bd4f89a3e0b2135403e56 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 8 Mar 2010 14:57:32 +0100 Subject: [PATCH 330/344] small code cleanup - "good ifdef is no ifdef" --- sql/handler.cc | 11 +++-------- sql/set_var.cc | 6 +++--- sql/sql_plugin.cc | 12 ++---------- sql/sql_plugin.h | 6 +++++- sql/sql_select.cc | 2 +- sql/table.cc | 2 +- 6 files changed, 15 insertions(+), 24 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 198522f2e56..72c78727111 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -82,7 +82,7 @@ static plugin_ref ha_default_plugin(THD *thd) { if (thd->variables.table_plugin) return thd->variables.table_plugin; - return my_plugin_lock(thd, &global_system_variables.table_plugin); + return my_plugin_lock(thd, global_system_variables.table_plugin); } @@ -163,13 +163,8 @@ plugin_ref ha_lock_engine(THD *thd, handlerton *hton) { if (hton) { - st_plugin_int **plugin= hton2plugin + hton->slot; - -#ifdef DBUG_OFF - return my_plugin_lock(thd, plugin); -#else - return my_plugin_lock(thd, &plugin); -#endif + st_plugin_int *plugin= hton2plugin[hton->slot]; + return my_plugin_lock(thd, plugin_int_to_ref(plugin)); } return NULL; } diff --git a/sql/set_var.cc b/sql/set_var.cc index 0ec1f04a370..d58ac9d00b1 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3845,7 +3845,7 @@ uchar *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type, LEX_STRING *engine_name; plugin_ref plugin= thd->variables.*offset; if (type == OPT_GLOBAL) - plugin= my_plugin_lock(thd, &(global_system_variables.*offset)); + plugin= my_plugin_lock(thd, global_system_variables.*offset); hton= plugin_data(plugin, handlerton*); engine_name= hton_name(hton); result= (uchar *) thd->strmake(engine_name->str, engine_name->length); @@ -3866,7 +3866,7 @@ void sys_var_thd_storage_engine::set_default(THD *thd, enum_var_type type) else { value= &(thd->variables.*offset); - new_value= my_plugin_lock(NULL, &(global_system_variables.*offset)); + new_value= my_plugin_lock(NULL, global_system_variables.*offset); } DBUG_ASSERT(new_value); old_value= *value; @@ -3883,7 +3883,7 @@ bool sys_var_thd_storage_engine::update(THD *thd, set_var *var) old_value= *value; if (old_value != var->save_result.plugin) { - *value= my_plugin_lock(NULL, &var->save_result.plugin); + *value= my_plugin_lock(NULL, var->save_result.plugin); plugin_unlock(NULL, old_value); } return 0; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 56d181bdda2..994a09a8177 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -19,14 +19,6 @@ #define REPORT_TO_LOG 1 #define REPORT_TO_USER 2 -#ifdef DBUG_OFF -#define plugin_ref_to_int(A) A -#define plugin_int_to_ref(A) A -#else -#define plugin_ref_to_int(A) (A ? A[0] : NULL) -#define plugin_int_to_ref(A) &(A) -#endif - extern struct st_mysql_plugin *mysqld_builtins[]; /** @@ -658,13 +650,13 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO) } -plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO) +plugin_ref plugin_lock(THD *thd, plugin_ref ptr CALLER_INFO_PROTO) { LEX *lex= thd ? thd->lex : 0; plugin_ref rc; DBUG_ENTER("plugin_lock"); pthread_mutex_lock(&LOCK_plugin); - rc= my_intern_plugin_lock_ci(lex, *ptr); + rc= my_intern_plugin_lock_ci(lex, ptr); pthread_mutex_unlock(&LOCK_plugin); DBUG_RETURN(rc); } diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index 004d0d5abb7..54ef38b3734 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -89,6 +89,8 @@ struct st_plugin_int */ #ifdef DBUG_OFF typedef struct st_plugin_int *plugin_ref; +#define plugin_ref_to_int(A) A +#define plugin_int_to_ref(A) A #define plugin_decl(pi) ((pi)->plugin) #define plugin_dlib(pi) ((pi)->plugin_dl) #define plugin_data(pi,cast) ((cast)((pi)->data)) @@ -97,6 +99,8 @@ typedef struct st_plugin_int *plugin_ref; #define plugin_equals(p1,p2) ((p1) == (p2)) #else typedef struct st_plugin_int **plugin_ref; +#define plugin_ref_to_int(A) (A ? A[0] : NULL) +#define plugin_int_to_ref(A) &(A) #define plugin_decl(pi) ((pi)[0]->plugin) #define plugin_dlib(pi) ((pi)[0]->plugin_dl) #define plugin_data(pi,cast) ((cast)((pi)[0]->data)) @@ -120,7 +124,7 @@ extern bool plugin_is_ready(const LEX_STRING *name, int type); #define my_plugin_lock_by_name_ci(A,B,C) plugin_lock_by_name(A,B,C ORIG_CALLER_INFO) #define my_plugin_lock(A,B) plugin_lock(A,B CALLER_INFO) #define my_plugin_lock_ci(A,B) plugin_lock(A,B ORIG_CALLER_INFO) -extern plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO); +extern plugin_ref plugin_lock(THD *thd, plugin_ref ptr CALLER_INFO_PROTO); extern plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type CALLER_INFO_PROTO); extern void plugin_unlock(THD *thd, plugin_ref plugin); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 330cdcfff19..e085d884ac1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11014,7 +11014,7 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, delete table->file; table->file=0; plugin_unlock(0, table->s->db_plugin); - share.db_plugin= my_plugin_lock(0, &share.db_plugin); + share.db_plugin= my_plugin_lock(0, share.db_plugin); new_table.s= table->s; // Keep old share *table= new_table; *table->s= share; diff --git a/sql/table.cc b/sql/table.cc index 8ceda6e7513..9bc3058a3bc 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -899,7 +899,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, replacing it with a globally locked version of tmp_plugin */ plugin_unlock(NULL, share->db_plugin); - share->db_plugin= my_plugin_lock(NULL, &tmp_plugin); + share->db_plugin= my_plugin_lock(NULL, tmp_plugin); DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)", str_db_type_length, next_chunk + 2, ha_legacy_type(share->db_type()))); From 700e2155f28a16756e8c30587ce9baa4d7d9bf32 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 8 Mar 2010 18:05:09 +0100 Subject: [PATCH 331/344] do not take LOCK_plugin for built-in plugins --- sql/sql_plugin.cc | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 994a09a8177..27d62387a8c 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -622,7 +622,10 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO) { plugin_ref plugin; #ifdef DBUG_OFF - /* built-in plugins don't need ref counting */ + /* + In optimized builds we don't do reference counting for built-in + (plugin->plugin_dl == 0) plugins. + */ if (!pi->plugin_dl) DBUG_RETURN(pi); @@ -655,6 +658,26 @@ plugin_ref plugin_lock(THD *thd, plugin_ref ptr CALLER_INFO_PROTO) LEX *lex= thd ? thd->lex : 0; plugin_ref rc; DBUG_ENTER("plugin_lock"); + +#ifdef DBUG_OFF + /* + In optimized builds we don't do reference counting for built-in + (plugin->plugin_dl == 0) plugins. + + Note that we access plugin->plugin_dl outside of LOCK_plugin, and for + dynamic plugins a 'plugin' could correspond to plugin that was unloaded + meanwhile! But because st_plugin_int is always allocated on + plugin_mem_root, the pointer can never be invalid - the memory is never + freed. + Of course, the memory that 'plugin' points to can be overwritten by + another plugin being loaded, but plugin->plugin_dl can never change + from zero to non-zero or vice versa. + That is, it's always safe to check for plugin->plugin_dl==0 even + without a mutex. + */ + if (! plugin_dlib(ptr)) + DBUG_RETURN(ptr); +#endif pthread_mutex_lock(&LOCK_plugin); rc= my_intern_plugin_lock_ci(lex, ptr); pthread_mutex_unlock(&LOCK_plugin); From c9dffa993a845752a847c4fe36c99cc6adbc35a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Mar 2010 16:03:54 +0100 Subject: [PATCH 332/344] A number of after-merge fixes following merge of MySQL 5.1.44 into MariaDB. Bug#46949: memory leak with failed alter table to create partitions based on extract() Bug#51830: Incorrect partition pruning on range partition (regression) Fixed valgrind failure in select_describe(), read of uninitialized Item_subselect::eliminated. PBXT test file updates to reflect changes done in MySQL. mysql-test/suite/pbxt/r/partition_error.result: Result file update following MySQL 5.1.44 changes. mysql-test/suite/pbxt/r/partition_pruning.result: Result file update following MySQL 5.1.44 changes. mysql-test/suite/pbxt/t/partition_error.test: Test file update following MySQL 5.1.44 changes. sql/item_subselect.cc: Fixed valgrind failure in select_describe(), read of uninitialized Item_subselect::eliminated: - it turns out we can call select_describe() without having fixed subquery items for child subselects. These are not the kind of subqueries that we could eliminate, so the fix is to ensure that item_subselect->eliminated==FALSE even before fix_fields is called. Also added code to reset item_subselect->eliminated back to FALSE in Item::reset() call. sql/item_subselect.h: Fixed valgrind failure in select_describe(), read of uninitialized Item_subselect::eliminated: - it turns out we can call select_describe() without having fixed subquery items for child subselects. These are not the kind of subqueries that we could eliminate, so the fix is to ensure that item_subselect->eliminated==FALSE even before fix_fields is called. Also added code to reset item_subselect->eliminated back to FALSE in Item::reset() call. sql/sql_partition.cc: Fix Bug#51830: Revert part of the patch for Bug#49742, which caused the regression. sql/table.cc: Fix Bug#46949: memory leak in failed ALTER TABLE with partitioning. --- mysql-test/suite/pbxt/r/partition_error.result | 18 +++++++++--------- .../suite/pbxt/r/partition_pruning.result | 2 +- mysql-test/suite/pbxt/t/partition_error.test | 4 ++-- sql/item_subselect.cc | 4 +++- sql/item_subselect.h | 3 +++ sql/sql_partition.cc | 5 +++-- sql/table.cc | 2 +- 7 files changed, 22 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/pbxt/r/partition_error.result b/mysql-test/suite/pbxt/r/partition_error.result index af708fb01b0..a36d0bddabb 100644 --- a/mysql-test/suite/pbxt/r/partition_error.result +++ b/mysql-test/suite/pbxt/r/partition_error.result @@ -107,7 +107,7 @@ primary key(a,b)) partition by hash (rand(a)) partitions 2 (partition x1, partition x2); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1, partition x2)' at line 6 CREATE TABLE t1 ( @@ -118,7 +118,7 @@ primary key(a,b)) partition by range (rand(a)) partitions 2 (partition x1 values less than (0), partition x2 values less than (2)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1 values less than (0), partition x2 values less than' at line 6 CREATE TABLE t1 ( @@ -129,7 +129,7 @@ primary key(a,b)) partition by list (rand(a)) partitions 2 (partition x1 values in (1), partition x2 values in (2)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1 values in (1), partition x2 values in (2))' at line 6 CREATE TABLE t1 ( @@ -244,7 +244,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by hash (rand(a+b)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 7 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 7 CREATE TABLE t1 ( a int not null, b int not null, @@ -341,7 +341,7 @@ partition by range (3+4) partitions 2 (partition x1 values less than (4) tablespace ts1, partition x2 values less than (8) tablespace ts2); -ERROR HY000: Constant/Random expression in (sub)partitioning function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed CREATE TABLE t1 ( a int not null, b int not null, @@ -511,7 +511,7 @@ partition by list (3+4) partitions 2 (partition x1 values in (4) tablespace ts1, partition x2 values in (8) tablespace ts2); -ERROR HY000: Constant/Random expression in (sub)partitioning function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed CREATE TABLE t1 ( a int not null, b int not null, @@ -603,13 +603,13 @@ partition by range (ascii(v)) ERROR HY000: This partition function is not allowed create table t1 (a int) partition by hash (rand(a)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash(CURTIME() + a); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash (NOW()+a); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash (extract(hour from convert_tz(a, '+00:00', '+00:00'))); ERROR HY000: This partition function is not allowed diff --git a/mysql-test/suite/pbxt/r/partition_pruning.result b/mysql-test/suite/pbxt/r/partition_pruning.result index 9938d352ff7..2f43fa6eb86 100644 --- a/mysql-test/suite/pbxt/r/partition_pruning.result +++ b/mysql-test/suite/pbxt/r/partition_pruning.result @@ -527,7 +527,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p0,p4 ALL NULL NULL NULL NULL 910 Using where explain partitions select * from t2 where (a > 100 AND a < 600); id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t2 p0,p1,p2,p3 ALL NULL NULL NULL NULL 910 Using where +1 SIMPLE t2 p0,p1,p2 ALL NULL NULL NULL NULL 910 Using where analyze table t2; Table Op Msg_type Msg_text test.t2 analyze status OK diff --git a/mysql-test/suite/pbxt/t/partition_error.test b/mysql-test/suite/pbxt/t/partition_error.test index 622b4f483b4..5b0c90b9a20 100644 --- a/mysql-test/suite/pbxt/t/partition_error.test +++ b/mysql-test/suite/pbxt/t/partition_error.test @@ -421,7 +421,7 @@ partitions 2 # # Partition by range, constant partition function not allowed # ---error ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR CREATE TABLE t1 ( a int not null, b int not null, @@ -636,7 +636,7 @@ partition by list (a); # # Partition by list, constant partition function not allowed # ---error ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR CREATE TABLE t1 ( a int not null, b int not null, diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 6292a93dd20..aa69bb47949 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -39,7 +39,8 @@ inline Item * and_items(Item* cond, Item *item) Item_subselect::Item_subselect(): Item_result_field(), value_assigned(0), thd(0), substitution(0), engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0), - const_item_cache(1), in_fix_fields(0), engine_changed(0), changed(0), is_correlated(FALSE) + const_item_cache(1), in_fix_fields(0), eliminated(FALSE), + engine_changed(0), changed(0), is_correlated(FALSE) { with_subselect= 1; reset(); @@ -431,6 +432,7 @@ void Item_maxmin_subselect::print(String *str, enum_query_type query_type) void Item_singlerow_subselect::reset() { + eliminated= FALSE; null_value= 1; if (value) value->null_value= 1; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 50f8885f862..8d43f2bd383 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -90,6 +90,7 @@ public: void cleanup(); virtual void reset() { + eliminated= FALSE; null_value= 1; } virtual trans_res select_transformer(JOIN *join); @@ -235,6 +236,7 @@ public: subs_type substype() { return EXISTS_SUBS; } void reset() { + eliminated= FALSE; value= 0; } @@ -306,6 +308,7 @@ public: subs_type substype() { return IN_SUBS; } void reset() { + eliminated= FALSE; value= 0; null_value= 0; was_null= 0; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index c5c5191d176..143073a67b5 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -3019,8 +3019,9 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, In case of PARTITION p VALUES LESS THAN MAXVALUE the maximum value is in the current partition. */ - if (part_func_value == part_end_val && - (loc_part_id < max_partition || !part_info->defined_max_value)) + if (part_func_value > part_end_val || + (part_func_value == part_end_val && + (loc_part_id < max_partition || !part_info->defined_max_value))) loc_part_id++; } else diff --git a/sql/table.cc b/sql/table.cc index 088a22b5203..d3fc85f2be8 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1847,8 +1847,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, { if (work_part_info_used) tmp= fix_partition_func(thd, outparam, is_create_table); - outparam->part_info->item_free_list= part_func_arena.free_list; } + outparam->part_info->item_free_list= part_func_arena.free_list; partititon_err: if (tmp) { From 292f6568fa377420c81e0317a26b804057ce208c Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Tue, 9 Mar 2010 21:22:24 +0200 Subject: [PATCH 333/344] Added count of my_sync calls (to SHOW STATUS) tmp_table_size can now be set to 0 (to disable in memory internal temp tables) Improved speed for internal Maria temp tables: - Don't use packed keys, except with long text fields. - Don't copy key all accessed pages during key search. Some new benchmark tests to sql-bench (for group by) BUILD/compile-pentium64-gcov: Update script to use same pentium_config flags as other tests BUILD/compile-pentium64-gprof: Update script to use same pentium_config flags as other tests include/my_sys.h: Added count of my_sync calls mysql-test/r/variables.result: tmp_table_size can now be set to 0 sql-bench/test-select.sh: Added some new test for GROUP BY on a not key field and group by with different order by sql/mysqld.cc: Added count of my_sync calls tmp_table_size can now be set to 0 (to disable in memory internal temp tables) sql/sql_select.cc: If tmp_table_size is 0, don't use in memory temp tables (good for benchmarking MyISAM/Maria temp tables) Don't pack keys for Maria tables; The 8K page size makes packed keys too slow for temp tables. storage/maria/ma_key_recover.h: Moved definition to maria_def.h storage/maria/ma_page.c: Moved code used to simplify comparing of identical Maria tables to own function (page_cleanup()) Fixed that one can read a page with a read lock. storage/maria/ma_rkey.c: For not exact key reads, cache the page where we found key (to speed up future read-next/read-prev calls) storage/maria/ma_search.c: Moved code to cache last key page to separate function. Instead of copying pages, only get a link to the page. This notable speeds up key searches on bigger tables. storage/maria/ma_write.c: Added comment storage/maria/maria_def.h: Moved page_cleanup() to separate function. --- BUILD/compile-pentium64-gcov | 4 +- BUILD/compile-pentium64-gprof | 2 +- include/my_sys.h | 1 + mysql-test/r/variables.result | 2 - mysys/my_sync.c | 3 + sql-bench/test-select.sh | 27 ++++++++- sql/mysqld.cc | 5 +- sql/sql_select.cc | 7 ++- storage/maria/ma_key_recover.h | 1 - storage/maria/ma_page.c | 24 ++++---- storage/maria/ma_rkey.c | 3 + storage/maria/ma_search.c | 103 +++++++++++++++++++++++---------- storage/maria/ma_write.c | 6 ++ storage/maria/maria_def.h | 7 ++- 14 files changed, 138 insertions(+), 57 deletions(-) diff --git a/BUILD/compile-pentium64-gcov b/BUILD/compile-pentium64-gcov index 5a99b7f8796..0334f0e28f4 100755 --- a/BUILD/compile-pentium64-gcov +++ b/BUILD/compile-pentium64-gcov @@ -9,9 +9,9 @@ export CCACHE_DISABLE export LDFLAGS="$gcov_link_flags" -extra_flags="$pentium64_cflags $debug_cflags $max_cflags $gcov_compile_flags" +extra_flags="$pentium64_cflags $max_cflags $gcov_compile_flags" c_warnings="$c_warnings $debug_extra_warnings" cxx_warnings="$cxx_warnings $debug_extra_warnings" -extra_configs="$pentium64_configs $debug_configs $gcov_configs $max_configs" +extra_configs="$pentium_configs $debug_configs $gcov_configs $max_configs --with-zlib-dir=bundled" . "$path/FINISH.sh" diff --git a/BUILD/compile-pentium64-gprof b/BUILD/compile-pentium64-gprof index f64dee6d196..662396f04ed 100755 --- a/BUILD/compile-pentium64-gprof +++ b/BUILD/compile-pentium64-gprof @@ -4,6 +4,6 @@ path=`dirname $0` . "$path/SETUP.sh" extra_flags="$pentium64_cflags $gprof_compile_flags" -extra_configs="$pentium64_configs $debug_configs $gprof_link_flags" +extra_configs="$pentium_configs $max_configs $gprof_link_flags --with-zlib-dir=bundled" . "$path/FINISH.sh" diff --git a/include/my_sys.h b/include/my_sys.h index fcd319d3e95..e8b48f089b6 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -247,6 +247,7 @@ extern CHARSET_INFO compiled_charsets[]; /* statistics */ extern ulong my_file_opened,my_stream_opened, my_tmp_file_created; extern ulong my_file_total_opened; +extern ulong my_sync_count; extern uint mysys_usage_id; extern my_bool my_init_done; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 1761567224b..bf0cbb6db96 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -575,8 +575,6 @@ set storage_engine=myisam; set global thread_cache_size=100; set timestamp=1, timestamp=default; set tmp_table_size=100; -Warnings: -Warning 1292 Truncated incorrect tmp_table_size value: '100' set tx_isolation="READ-COMMITTED"; set wait_timeout=100; set log_warnings=1; diff --git a/mysys/my_sync.c b/mysys/my_sync.c index f8961202fa3..967a6ae6c78 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -17,6 +17,8 @@ #include "mysys_err.h" #include +ulong my_sync_count; /* Count number of sync calls */ + /* Sync data in file to disk @@ -46,6 +48,7 @@ int my_sync(File fd, myf my_flags) DBUG_ENTER("my_sync"); DBUG_PRINT("my",("fd: %d my_flags: %d", fd, my_flags)); + statistic_increment(my_sync_count,&THR_LOCK_open); do { #if defined(F_FULLFSYNC) diff --git a/sql-bench/test-select.sh b/sql-bench/test-select.sh index 0bcc9426cdf..a3162b29dc3 100644 --- a/sql-bench/test-select.sh +++ b/sql-bench/test-select.sh @@ -68,7 +68,8 @@ do_many($dbh,$server->create("bench1", ["region char(1) NOT NULL", "idn integer(6) NOT NULL", "rev_idn integer(6) NOT NULL", - "grp integer(6) NOT NULL"], + "grp integer(6) NOT NULL", + "grp_no_key integer(6) NOT NULL"], ["primary key (region,idn)", "unique (region,rev_idn)", "unique (region,grp,idn)"])); @@ -105,10 +106,10 @@ for ($id=0,$rev_id=$opt_loop_count-1 ; $id < $opt_loop_count ; $id++,$rev_id--) { $grp=$id*3 % $opt_groups; $region=chr(65+$id%$opt_regions); - do_query($dbh,"$query'$region',$id,$rev_id,$grp)"); + do_query($dbh,"$query'$region',$id,$rev_id,$grp,$grp)"); if ($id == $half_done) { # Test with different insert - $query="insert into bench1 (region,idn,rev_idn,grp) values ("; + $query="insert into bench1 (region,idn,rev_idn,grp,grp_no_key) values ("; } } @@ -323,6 +324,26 @@ if ($limits->{'group_functions'}) $end_time=new Benchmark; print "Time for count_group_on_key_parts ($i:$rows): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; + + $loop_time=new Benchmark; + $rows=0; + for ($i=0 ; $i < $opt_medium_loop_count ; $i++) + { + $rows+=fetch_all_rows($dbh,"select grp_no_key,count(*) from bench1 group by grp_no_key"); + } + $end_time=new Benchmark; + print "Time for count_group ($i:$rows): " . + timestr(timediff($end_time, $loop_time),"all") . "\n"; + + $loop_time=new Benchmark; + $rows=0; + for ($i=0 ; $i < $opt_medium_loop_count ; $i++) + { + $rows+=fetch_all_rows($dbh,"select grp_no_key,count(*) as cnt from bench1 group by grp_no_key order by cnt"); + } + $end_time=new Benchmark; + print "Time for count_group_with_order ($i:$rows): " . + timestr(timediff($end_time, $loop_time),"all") . "\n"; } if ($limits->{'group_distinct_functions'}) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5eb18ddda80..6701dcd28ff 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7273,10 +7273,10 @@ The minimum value for this variable is 4096.", 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"tmp_table_size", OPT_TMP_TABLE_SIZE, "If an internal in-memory temporary table exceeds this size, MySQL will" - " automatically convert it to an on-disk MyISAM table.", + " automatically convert it to an on-disk MyISAM/Maria table.", (uchar**) &global_system_variables.tmp_table_size, (uchar**) &max_system_variables.tmp_table_size, 0, GET_ULL, - REQUIRED_ARG, 16*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0}, + REQUIRED_ARG, 16*1024*1024L, 0, MAX_MEM_TABLE_SIZE, 0, 1, 0}, {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE, "Allocation block size for transactions to be stored in binary log", (uchar**) &global_system_variables.trans_alloc_block_size, @@ -7778,6 +7778,7 @@ SHOW_VAR status_vars[]= { {"Ssl_verify_mode", (char*) &show_ssl_get_verify_mode, SHOW_FUNC}, {"Ssl_version", (char*) &show_ssl_get_version, SHOW_FUNC}, #endif /* HAVE_OPENSSL */ + {"Syncs", (char*) &my_sync_count, SHOW_LONG_NOFLUSH}, {"Table_locks_immediate", (char*) &locks_immediate, SHOW_LONG}, {"Table_locks_waited", (char*) &locks_waited, SHOW_LONG}, #ifdef HAVE_MMAP diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e085d884ac1..ee23b907e5f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10168,7 +10168,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, /* future: storage engine selection can be made dynamic? */ if (blob_count || using_unique_constraint || (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) == - OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM)) + OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM) || + !thd->variables.tmp_table_size) { share->db_plugin= ha_lock_engine(0, TMP_ENGINE_HTON); table->file= get_new_handler(share, &table->mem_root, @@ -10707,7 +10708,7 @@ static bool create_internal_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, { /* Create an unique key */ bzero((char*) &keydef,sizeof(keydef)); - keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY; + keydef.flag=HA_NOSAME; keydef.keysegs= keyinfo->key_parts; keydef.seg= seg; } @@ -10732,7 +10733,7 @@ static bool create_internal_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, seg->type= keyinfo->key_part[i].type; /* Tell handler if it can do suffic space compression */ if (field->real_type() == MYSQL_TYPE_STRING && - keyinfo->key_part[i].length > 4) + keyinfo->key_part[i].length > 32) seg->flag|= HA_SPACE_PACK; } if (!(field->flags & NOT_NULL_FLAG)) diff --git a/storage/maria/ma_key_recover.h b/storage/maria/ma_key_recover.h index 4b4198f3008..b580433c99a 100644 --- a/storage/maria/ma_key_recover.h +++ b/storage/maria/ma_key_recover.h @@ -63,7 +63,6 @@ extern my_bool write_hook_for_undo_key_insert(enum translog_record_type type, extern my_bool write_hook_for_undo_key_delete(enum translog_record_type type, TRN *trn, MARIA_HA *tbl_info, LSN *lsn, void *hook_arg); -void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn); my_bool _ma_log_prefix(MARIA_PAGE *page, uint changed_length, int move_length); my_bool _ma_log_suffix(MARIA_PAGE *page, uint org_length, diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index 54361b8ee3b..acbee2a6f07 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -64,6 +64,15 @@ void _ma_page_setup(MARIA_PAGE *page, MARIA_HA *info, share->base.key_reflength : 0); } +#ifdef IDENTICAL_PAGES_AFTER_RECOVERY +void page_cleanup(MARIA_SHARE *share, MARIA_PAGE *page) +{ + uint length= page->size; + DBUG_ASSERT(length <= block_size - KEYPAGE_CHECKSUM_SIZE); + bzero(page->buff + length, share->block_size - length); +} +#endif + /** Fetch a key-page in memory @@ -102,8 +111,10 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info, if (lock != PAGECACHE_LOCK_LEFT_UNLOCKED) { - DBUG_ASSERT(lock == PAGECACHE_LOCK_WRITE); - page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; + DBUG_ASSERT(lock == PAGECACHE_LOCK_WRITE || PAGECACHE_LOCK_READ); + page_link.unlock= (lock == PAGECACHE_LOCK_WRITE ? + PAGECACHE_LOCK_WRITE_UNLOCK : + PAGECACHE_LOCK_READ_UNLOCK); page_link.changed= 0; push_dynamic(&info->pinned_pages, (void*) &page_link); page->link_offset= info->pinned_pages.elements-1; @@ -209,14 +220,7 @@ my_bool _ma_write_keypage(MARIA_PAGE *page, enum pagecache_page_lock lock, } #endif -#ifdef IDENTICAL_PAGES_AFTER_RECOVERY - { - uint length= page->size; - DBUG_ASSERT(length <= block_size - KEYPAGE_CHECKSUM_SIZE); - bzero(buff + length, block_size - length); - } -#endif - + page_cleanup(share, page); res= pagecache_write(share->pagecache, &share->kfile, (pgcache_page_no_t) (page->pos / block_size), diff --git a/storage/maria/ma_rkey.c b/storage/maria/ma_rkey.c index 9e529aca666..daf1fd5a60c 100644 --- a/storage/maria/ma_rkey.c +++ b/storage/maria/ma_rkey.c @@ -82,6 +82,9 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data, rw_rdlock(&keyinfo->root_lock); nextflag= maria_read_vec[search_flag] | key.flag; + if (search_flag != HA_READ_KEY_EXACT || + ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME)) + nextflag|= SEARCH_SAVE_BUFF; switch (keyinfo->key_alg) { #ifdef HAVE_RTREE_KEYS diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index a50f3c49a26..8df0ebc4bf4 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -18,6 +18,10 @@ #include "ma_fulltext.h" #include "m_ctype.h" +static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, + uint32 nextflag, register my_off_t pos, + MARIA_PINNED_PAGE **res_page_link, + uchar **res_page_buff); static my_bool _ma_get_prev_key(MARIA_KEY *key, MARIA_PAGE *ma_page, uchar *keypos); @@ -57,7 +61,51 @@ int _ma_check_index(MARIA_HA *info, int inx) */ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, - register my_off_t pos) + my_off_t pos) +{ + int error; + MARIA_PINNED_PAGE *page_link; + uchar *page_buff; + + info->page_changed= 1; /* If page not saved */ + if (!(error= _ma_search_no_save(info, key, nextflag, pos, &page_link, + &page_buff))) + { + if (nextflag & SEARCH_SAVE_BUFF) + { + bmove512(info->keyread_buff, page_buff, info->s->block_size); + + /* Save position for a possible read next / previous */ + info->int_keypos= info->keyread_buff + (ulonglong) info->int_keypos; + info->int_maxpos= info->keyread_buff + (ulonglong) info->int_maxpos; + info->int_keytree_version= key->keyinfo->version; + info->last_search_keypage= info->last_keypage; + info->page_changed= 0; + info->keyread_buff_used= 0; + } + } + _ma_unpin_all_pages(info, LSN_IMPOSSIBLE); + return (error); +} + +/** + @breif Search after row by a key + + ret_page_link Will contain pointer to page where we found key + + @note + Position to row is stored in info->lastpos + + @return + @retval 0 ok (key found) + @retval -1 Not found + @retval 1 If one should continue search on higher level +*/ + +static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, + uint32 nextflag, register my_off_t pos, + MARIA_PINNED_PAGE **res_page_link, + uchar **res_page_buff) { my_bool last_key_not_used; int error,flag; @@ -66,6 +114,7 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, uchar lastkey[MARIA_MAX_KEY_BUFF]; MARIA_KEYDEF *keyinfo= key->keyinfo; MARIA_PAGE page; + MARIA_PINNED_PAGE *page_link; DBUG_ENTER("_ma_search"); DBUG_PRINT("enter",("pos: %lu nextflag: %u lastpos: %lu", (ulong) pos, nextflag, (ulong) info->cur_row.lastpos)); @@ -81,10 +130,11 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, } if (_ma_fetch_keypage(&page, info, keyinfo, pos, - PAGECACHE_LOCK_LEFT_UNLOCKED, - DFLT_INIT_HITS, info->keyread_buff, - test(!(nextflag & SEARCH_SAVE_BUFF)))) + PAGECACHE_LOCK_READ, DFLT_INIT_HITS, 0, 0)) goto err; + page_link= dynamic_element(&info->pinned_pages, + info->pinned_pages.elements-1, + MARIA_PINNED_PAGE*); DBUG_DUMP("page", page.buff, page.size); flag= (*keyinfo->bin_search)(key, &page, nextflag, &keypos, lastkey, @@ -98,8 +148,9 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, if (flag) { - if ((error= _ma_search(info, key, nextflag, - _ma_kpos(nod_flag,keypos))) <= 0) + if ((error= _ma_search_no_save(info, key, nextflag, + _ma_kpos(nod_flag,keypos), + res_page_link, res_page_buff)) <= 0) DBUG_RETURN(error); if (flag >0) @@ -118,26 +169,15 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME || (key->flag & SEARCH_PART_KEY) || info->s->base.born_transactional)) { - if ((error= _ma_search(info, key, (nextflag | SEARCH_FIND) & - ~(SEARCH_BIGGER | SEARCH_SMALLER | SEARCH_LAST), - _ma_kpos(nod_flag,keypos))) >= 0 || + if ((error= _ma_search_no_save(info, key, (nextflag | SEARCH_FIND) & + ~(SEARCH_BIGGER | SEARCH_SMALLER | + SEARCH_LAST), + _ma_kpos(nod_flag,keypos), + res_page_link, res_page_buff)) >= 0 || my_errno != HA_ERR_KEY_NOT_FOUND) DBUG_RETURN(error); - info->last_keypage= HA_OFFSET_ERROR; /* Buffer not in mem */ } } - if (pos != info->last_keypage) - { - uchar *old_buff= page.buff; - if (_ma_fetch_keypage(&page, info, keyinfo, pos, - PAGECACHE_LOCK_LEFT_UNLOCKED,DFLT_INIT_HITS, - info->keyread_buff, - test(!(nextflag & SEARCH_SAVE_BUFF)))) - goto err; - /* Restore position if page buffer moved */ - keypos= page.buff + (keypos - old_buff); - maxpos= page.buff + (maxpos - old_buff); - } info->last_key.keyinfo= keyinfo; if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0) @@ -172,16 +212,15 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, } info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key); info->cur_row.trid= _ma_trid_from_key(&info->last_key); - /* Save position for a possible read next / previous */ - info->int_keypos= info->keyread_buff + (keypos - page.buff); - info->int_maxpos= info->keyread_buff + (maxpos - page.buff); - info->int_nod_flag=nod_flag; - info->int_keytree_version=keyinfo->version; - info->last_search_keypage=info->last_keypage; - info->page_changed=0; - /* Set marker that buffer was used (Marker for mi_search_next()) */ - info->keyread_buff_used= (info->keyread_buff != page.buff); + /* Store offset to key */ + info->int_keypos= (uchar*) (keypos - page.buff); + info->int_maxpos= (uchar*) (maxpos - page.buff); + info->int_nod_flag= nod_flag; + info->last_keypage= pos; + *res_page_link= page_link; + *res_page_buff= page.buff; + DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos)); DBUG_RETURN(0); @@ -190,7 +229,7 @@ err: info->cur_row.lastpos= HA_OFFSET_ERROR; info->page_changed=1; DBUG_RETURN (-1); -} /* _ma_search */ +} /* diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 20304618229..3b9ca46899f 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -587,6 +587,12 @@ my_bool _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key, my_off_t *root) /* Search after a position for a key and store it there + TODO: + Change this to use pagecache directly instead of creating a copy + of the page. To do this, we must however change write-key-on-page + algorithm to not overwrite the buffer but instead store any overflow + key in a separate buffer. + @return @retval -1 error @retval 0 ok diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 1d60beece6b..29eb32a4fb2 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -979,6 +979,11 @@ extern ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from); #define page_store_info(share, page) \ _ma_store_keypage_flag((share), (page)->buff, (page)->flag); \ _ma_store_page_used((share), (page)->buff, (page)->size); +#ifdef IDENTICAL_PAGES_AFTER_RECOVERY +void page_cleanup(MARIA_SHARE *share, MARIA_PAGE *page) +#else +#define page_cleanup(A,B) while (0) +#endif extern MARIA_KEY *_ma_make_key(MARIA_HA *info, MARIA_KEY *int_key, uint keynr, uchar *key, const uchar *record, @@ -1197,7 +1202,7 @@ void _ma_tmp_disable_logging_for_table(MARIA_HA *info, my_bool log_incomplete); my_bool _ma_reenable_logging_for_table(MARIA_HA *info, my_bool flush_pages); my_bool write_log_record_for_bulk_insert(MARIA_HA *info); - +void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn); #define MARIA_NO_CRC_NORMAL_PAGE 0xffffffff #define MARIA_NO_CRC_BITMAP_PAGE 0xfffffffe From 0230d51be8e336edbfa2a04c0f5bfdb9feaa6122 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Mar 2010 20:29:05 +0100 Subject: [PATCH 334/344] Fix a buildbot memory leak due to JOIN::destroy() not being called for EXPLAIN query: - When subquery is located in ORDER BY, EXPLAIN will run as follows: select_describe() will run JOIN::prepare()/optimize() for the subquery; then at some point subselect_single_select_engine::prepare() will be called, which will create another join and run join->prepare(). In mainline mysql this is not a problem because subquery's join will be destroyed after the first call. In MariaDB, it won't (table elimination needs to keep JOIN objects around for longer in order to know which tables were eliminated when constructing EXPLAIN EXTENDED warning). Fix the problem of memory leak by calling select_lex->cleanup() in subselect_single_select_engine::prepare(). --- sql/item_subselect.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index aa69bb47949..dad05981af4 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1776,6 +1776,10 @@ int subselect_single_select_engine::prepare() { if (prepared) return 0; + if (select_lex->join) + { + select_lex->cleanup(); + } join= new JOIN(thd, select_lex->item_list, select_lex->options | SELECT_NO_UNLOCK, result); if (!join || !result) From b1a6297986d59c7d4a13ee7df89b4b7c384aa22b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Mar 2010 10:11:02 +0100 Subject: [PATCH 335/344] Fixes for two test failures in Buildbot. - Adjust timing in test case, to avoid test failures caused by high load on machines and consequent race conditions in the test case. - Add another variant of Valgrind suppressions for memory leak in system libraries when unloading dynamic object files. mysql-test/r/information_schema.result: Adjust timing to avoid test failures due to races. mysql-test/t/information_schema.test: Adjust timing to avoid test failures due to races. mysql-test/valgrind.supp: Add another variant of valgrind suppression for leak in system libs. --- mysql-test/r/information_schema.result | 2 +- mysql-test/t/information_schema.test | 2 +- mysql-test/valgrind.supp | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index d8d6f461e90..d28489507b3 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1386,7 +1386,7 @@ who other connection here SELECT IF(`time` > 0, 'OK', `time`) AS time_low, IF(`time` < 1000, 'OK', `time`) AS time_high, -IF(time_ms > 1500, 'OK', time_ms) AS time_ms_low, +IF(time_ms >= 1000, 'OK', time_ms) AS time_ms_low, IF(time_ms < 1000000, 'OK', time_ms) AS time_ms_high FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID=@tid; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 1298bb89754..2d260616d06 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1114,7 +1114,7 @@ eval SET @tid=$ID; --enable_query_log SELECT IF(`time` > 0, 'OK', `time`) AS time_low, IF(`time` < 1000, 'OK', `time`) AS time_high, - IF(time_ms > 1500, 'OK', time_ms) AS time_ms_low, + IF(time_ms >= 1000, 'OK', time_ms) AS time_ms_low, IF(time_ms < 1000000, 'OK', time_ms) AS time_ms_high FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID=@tid; diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index dcb8a9cbc1b..72882acd3cd 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -468,6 +468,26 @@ fun:_ZL13plugin_dl_delPK19st_mysql_lex_string } +{ + dlclose memory loss from plugin variant 8 + Memcheck:Leak + fun:calloc + fun:_dlerror_run + fun:dlclose + fun:_Z15free_plugin_memP12st_plugin_dl + fun:_Z13plugin_dl_delPK19st_mysql_lex_string +} + +{ + dlclose memory loss from plugin variant 9 + Memcheck:Leak + fun:calloc + fun:_dlerror_run + fun:dlclose + fun:_ZL15free_plugin_memP12st_plugin_dl + fun:_ZL13plugin_dl_delPK19st_mysql_lex_string +} + { dlopen / ptread_cancel_init memory loss on Suse Linux 10.3 32/64 bit ver 1 Memcheck:Leak From 3e32ba3ff1068c19dbf0c69de991da426cf7f327 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Mar 2010 11:32:14 +0100 Subject: [PATCH 336/344] Fix some compiler warnings seen in Buildbot. Add some extra error output and code cleanup in an attempt to fix/debug a rare random testsuite problem in check_warnings, where the exit code from mysqltest is somehow corrupted inside mysql-test-run.pl. include/my_global.h: Fix compiler warnings on some platforms. mysql-test/lib/My/SafeProcess.pm: Move dereference of $? subprocess exit code closer to where it is generated, to make the code more robust and on the chance that this will fix the occasional problems in check_warnings we see in Buildbot. mysql-test/mysql-test-run.pl: When check_warnings failed, also log the mysqld server for which it failed. sql/sql_lex.cc: Fix compiler warning about possibly uninitialised value, by rewriting a for() loop that is always executed at least once into a do .. while() loop with an assert. sql/table.cc: Fix compiler warning about uninitialised value. storage/federatedx/ha_federatedx.cc: Fix uninitialised variable. storage/maria/ma_delete.c: Fix compiler warning about uninitialised value. storage/maria/ma_loghandler.c: Fix compiler warning about uninitialised value. storage/myisam/ft_stopwords.c: Fix compiler warning. storage/myisam/mi_write.c: Fix compiler warning about possibly uninitialised value, by rewriting a while() loop that is always executed at least once into a do .. while() loop with an assert. storage/xtradb/btr/btr0cur.c: Fix compiler warning about possibly uninitialised value. support-files/compiler_warnings.supp: Fix warning suppression to cover all cases in yassl. vio/viossl.c: Fix compiler warning. --- include/my_global.h | 6 +++--- mysql-test/lib/My/SafeProcess.pm | 14 ++++++++++---- mysql-test/mysql-test-run.pl | 7 ++++--- sql/sql_lex.cc | 11 +++++++---- sql/table.cc | 2 ++ storage/federatedx/ha_federatedx.cc | 2 +- storage/maria/ma_delete.c | 2 ++ storage/maria/ma_loghandler.c | 1 + storage/myisam/ft_stopwords.c | 2 +- storage/myisam/mi_write.c | 7 +++++-- storage/xtradb/btr/btr0cur.c | 2 +- support-files/compiler_warnings.supp | 2 +- vio/viossl.c | 2 ++ 13 files changed, 40 insertions(+), 20 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 01bd6a9ba9e..6c11a4b461a 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1260,9 +1260,9 @@ do { doubleget_union _tmp; \ } while (0) #define float4get(V,M) do { *((float *) &(V)) = *((const float*) (M)); } while(0) #define float8get(V,M) doubleget((V),(M)) -#define float4store(V,M) memcpy((uchar*) V,(const uchar*) (&M),sizeof(float)) -#define floatstore(T,V) memcpy((uchar*)(T), (const uchar*)(&V),sizeof(float)) -#define floatget(V,M) memcpy((uchar*) &V,(const uchar*) (M),sizeof(float)) +#define float4store(V,M) memcpy((uchar*) V,(uchar*) (&M),sizeof(float)) +#define floatstore(T,V) memcpy((uchar*)(T), (uchar*)(&V),sizeof(float)) +#define floatget(V,M) memcpy((uchar*) &V,(uchar*) (M),sizeof(float)) #define float8store(V,M) doublestore((V),(M)) #else diff --git a/mysql-test/lib/My/SafeProcess.pm b/mysql-test/lib/My/SafeProcess.pm index 7e102b628ca..301392a4d88 100644 --- a/mysql-test/lib/My/SafeProcess.pm +++ b/mysql-test/lib/My/SafeProcess.pm @@ -384,9 +384,9 @@ sub kill { sub _collect { - my ($self)= @_; + my ($self, $exit_code)= @_; - $self->{EXIT_STATUS}= $?; + $self->{EXIT_STATUS}= $exit_code; _verbose("_collect: $self"); # Take the process out of running list @@ -453,6 +453,7 @@ sub wait_one { #_verbose("blocking: $blocking, use_alarm: $use_alarm"); my $retpid; + my $exit_code; eval { # alarm should break the wait @@ -461,6 +462,7 @@ sub wait_one { alarm($timeout) if $use_alarm; $retpid= waitpid($pid, $blocking ? 0 : &WNOHANG); + $exit_code= $?; alarm(0) if $use_alarm; }; @@ -492,7 +494,7 @@ sub wait_one { #warn "wait_one: expected pid $pid but got $retpid" # unless( $retpid == $pid ); - $self->_collect(); + $self->_collect($exit_code); return 0; } @@ -505,6 +507,8 @@ sub wait_one { # sub wait_any { my $ret_pid; + my $exit_code; + if (IS_WIN32PERL) { # Can't wait for -1 => use a polling loop do { @@ -514,6 +518,7 @@ sub wait_any { last if $pid == $ret_pid; } } while ($ret_pid == 0); + $exit_code= $?; } else { @@ -523,6 +528,7 @@ sub wait_any { print STDERR "wait_any, got invalid pid: $ret_pid\n"; return undef; } + $exit_code= $?; } # Look it up in "running" table @@ -532,7 +538,7 @@ sub wait_any { print STDERR "running: ". join(", ", keys(%running)). "\n"; return undef; } - $proc->_collect; + $proc->_collect($exit_code); return $proc; } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 45b65b15211..a06b29815a0 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -4102,7 +4102,7 @@ sub start_check_warnings ($$) { error => $errfile, output => $errfile, args => \$args, - user_data => $errfile, + user_data => [$errfile, $mysqld], verbose => $opt_verbose, ); mtr_verbose("Started $proc"); @@ -4148,7 +4148,7 @@ sub check_warnings ($) { if ( delete $started{$proc->pid()} ) { # One check warning process returned my $res= $proc->exit_status(); - my $err_file= $proc->user_data(); + my ($err_file, $mysqld)= @{$proc->user_data()}; if ( $res == 0 or $res == 62 ){ @@ -4184,7 +4184,8 @@ sub check_warnings ($) { my $report= mtr_grab_file($err_file); $tinfo->{comment}.= "Could not execute 'check-warnings' for ". - "testcase '$tname' (res: $res):\n"; + "testcase '$tname' (res: $res) server: '". + $mysqld->name() .":\n"; $tinfo->{comment}.= $report; $result= 2; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 6d047197992..5a3907d0f7f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1842,13 +1842,15 @@ void st_select_lex_unit::exclude_tree() void st_select_lex::mark_as_dependent(st_select_lex *last, Item *dependency) { SELECT_LEX *next_to_last; + + DBUG_ASSERT(this != last); + /* Mark all selects from resolved to 1 before select where was found table as depended (of select where was found table) */ - for (SELECT_LEX *s= this; - s && s != last; - s= s->outer_select()) + SELECT_LEX *s= this; + do { if (!(s->uncacheable & UNCACHEABLE_DEPENDENT)) { @@ -1866,7 +1868,8 @@ void st_select_lex::mark_as_dependent(st_select_lex *last, Item *dependency) } } next_to_last= s; - } + } while ((s= s->outer_select()) != last && s != 0); + is_correlated= TRUE; this->master_unit()->item->is_correlated= TRUE; if (dependency) diff --git a/sql/table.cc b/sql/table.cc index ef33aef20d5..733aa3e6887 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2053,6 +2053,8 @@ ulong get_form_pos(File file, uchar *head, TYPELIB *save_names) ulong ret_value=0; DBUG_ENTER("get_form_pos"); + LINT_INIT(buf); + names=uint2korr(head+8); a_length=(names+2)*sizeof(char *); /* Room for two extra */ diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index e06f39c073f..2c74b2f6675 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1783,7 +1783,7 @@ int ha_federatedx::open(const char *name, int mode, uint test_if_locked) int ha_federatedx::close(void) { - int retval, error; + int retval= 0, error; THD *thd= current_thd; DBUG_ENTER("ha_federatedx::close"); diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index 5b0a2ac8884..0e9e5caafbf 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -169,6 +169,8 @@ my_bool _ma_ck_delete(MARIA_HA *info, MARIA_KEY *key) MARIA_KEY org_key; DBUG_ENTER("_ma_ck_delete"); + LINT_INIT_STRUCT(org_key); + save_key_data= key->data; if (share->now_transactional) { diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 536336d795d..aff2b638e4e 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -1394,6 +1394,7 @@ LSN translog_get_file_max_lsn_stored(uint32 file) { LOGHANDLER_FILE_INFO info; + LINT_INIT_STRUCT(info); File fd= open_logfile_by_number_no_cache(file); if ((fd < 0) || (translog_read_file_header(&info, fd) | my_close(fd, MYF(MY_WME)))) diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c index 5e550b9dff5..aa209e082e0 100644 --- a/storage/myisam/ft_stopwords.c +++ b/storage/myisam/ft_stopwords.c @@ -45,7 +45,7 @@ static int ft_add_stopword(const char *w) { FT_STOPWORD sw; return !w || - (((sw.len= (uint) strlen(sw.pos=w)) >= ft_min_word_len) && + (((sw.len= (uint) strlen(sw.pos=(const uchar *)w)) >= ft_min_word_len) && (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL)); } diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c index f2528f2ec60..6ad23154b45 100644 --- a/storage/myisam/mi_write.c +++ b/storage/myisam/mi_write.c @@ -735,10 +735,12 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, } end=page+length-key_ref_length; + DBUG_ASSERT(page < end); *key='\0'; length=0; lastpos=page; - while (page < end) + + do { prevpos=lastpos; lastpos=page; last_length=length; @@ -749,7 +751,8 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, my_errno=HA_ERR_CRASHED; DBUG_RETURN(0); } - } + } while (page < end); + *return_key_length=last_length; *after_key=lastpos; DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx end: 0x%lx", diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c index 601e5af3572..55d3e1e8e6b 100644 --- a/storage/xtradb/btr/btr0cur.c +++ b/storage/xtradb/btr/btr0cur.c @@ -3233,7 +3233,7 @@ btr_estimate_number_of_different_key_vals( ulint matched_bytes; ib_int64_t n_recs = 0; ib_int64_t* n_diff; - ib_int64_t* n_not_nulls; + ib_int64_t* n_not_nulls= 0; ullint n_sample_pages; /* number of pages to sample */ ulint not_empty_flag = 0; ulint total_external_size = 0; diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index 7911d91928b..d3806f42b94 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -108,7 +108,7 @@ ha_pbxt\.cc : variable.*might be clobbered by.*longjmp # # Yassl include/runtime.hpp: .*pure_error.* -.*/extra/yassl/taocrypt/.*: comparison with string literal +.*/extra/yassl/.*taocrypt/.*: comparison with string literal .*/extra/yassl/taocrypt/src/blowfish\.cpp: array subscript is above array bounds .*/extra/yassl/taocrypt/src/file\.cpp: ignoring return value .*/extra/yassl/taocrypt/src/integer\.cpp: control reaches end of non-void function diff --git a/vio/viossl.c b/vio/viossl.c index c7449c7feb2..61e4d9406a7 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -75,9 +75,11 @@ report_errors(SSL* ssl) if (ssl) { +#ifndef DBUG_OFF int error= SSL_get_error(ssl, l); DBUG_PRINT("error", ("error: %s (%d)", ERR_error_string(error, buf), error)); +#endif } DBUG_PRINT("info", ("socket_errno: %d", socket_errno)); From 77afc2be46e0a815357795a0ab0977115c8a313d Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 10 Mar 2010 15:39:02 +0200 Subject: [PATCH 337/344] Fix for: Bug#44987 DELETE IGNORE and FK constraint - Now DELETE IGNORE skips over rows with a foreign key constraints (as it was supposed to do) mysql-test/r/foreign_key.result: Test case for Bug#44987 DELETE IGNORE and FK constraint mysql-test/t/foreign_key.test: Test case for Bug#44987 DELETE IGNORE and FK constraint sql/sql_delete.cc: Firx for Bug#44987 DELETE IGNORE and FK constraint Now DELETE IGNORE skips over rows with a foreign key constraints (as it was supposed to do) Bug fix inspired by: Moritz Mertinkat --- mysql-test/r/foreign_key.result | 29 ++++++++++++++++++++++++++++- mysql-test/t/foreign_key.test | 24 +++++++++++++++++++++++- sql/sql_delete.cc | 7 +++++-- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/foreign_key.result b/mysql-test/r/foreign_key.result index ece53db2e9a..411252e0a5d 100644 --- a/mysql-test/r/foreign_key.result +++ b/mysql-test/r/foreign_key.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1,t2; create table t1 ( a int not null references t2, b int not null references t2 (c), @@ -13,3 +13,30 @@ foreign key (a,b) references t3 (c,d) on update set null); create index a on t1 (a); create unique index b on t1 (a,b); drop table t1; +create table t1 (id int primary key) engine = innodb; +create table t2 (id int PRIMARY KEY, FOREIGN KEY (id) REFERENCES t1(id)) engine=innodb; +insert into t1 values (1), (2), (3), (4), (5), (6); +insert into t2 values (3), (5); +delete from t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)) +select * from t1; +id +1 +2 +3 +4 +5 +6 +delete ignore from t1; +Warnings: +Error 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)) +Error 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)) +select row_count(); +row_count() +-1 +select * from t1; +id +3 +5 +drop table t2; +drop table t1; diff --git a/mysql-test/t/foreign_key.test b/mysql-test/t/foreign_key.test index 0a3708e6dc8..e71d4494d31 100644 --- a/mysql-test/t/foreign_key.test +++ b/mysql-test/t/foreign_key.test @@ -2,8 +2,10 @@ # Test syntax of foreign keys # +-- source include/have_innodb.inc + --disable_warnings -drop table if exists t1; +drop table if exists t1,t2; --enable_warnings create table t1 ( @@ -23,3 +25,23 @@ create unique index b on t1 (a,b); drop table t1; # End of 4.1 tests + +# +# Test DELETE IGNORE +# Bug#44987 DELETE IGNORE and FK constraint +# + +create table t1 (id int primary key) engine = innodb; +create table t2 (id int PRIMARY KEY, FOREIGN KEY (id) REFERENCES t1(id)) engine=innodb; +insert into t1 values (1), (2), (3), (4), (5), (6); +insert into t2 values (3), (5); + +--error 1451 +delete from t1; +select * from t1; + +delete ignore from t1; +select row_count(); +select * from t1; +drop table t2; +drop table t1; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index cea9b2857e2..827dfd79cc2 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -335,8 +335,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, InnoDB it can fail in a FOREIGN KEY error or an out-of-tablespace error. */ - error= 1; - break; + if (!select_lex->no_error) + { + error= 1; + break; + } } } else From e14291c1ff343287344f945bf0ad1b4edf5ab8d8 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 10 Mar 2010 21:00:34 +0200 Subject: [PATCH 338/344] Fix for Bug #534626 MyISAM table created in MariaDB not readable by MySQL storage/myisam/mi_create.c: Don't set HA_OPTION_NULL_FIELDS if table is not using CHECKSUM as this makes the table incompatible with MySQL. --- storage/myisam/mi_create.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 1b92d64d529..bbe58143af5 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -175,6 +175,13 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, } } + /* + Don't set HA_OPTION_NULL_FIELDS if no checksums, as this flag makes + that file incompatible with MySQL. This is ok, as this flag is only + used if one specifics table level checksums. + */ + if (!(options & HA_OPTION_CHECKSUM)) + options&= ~HA_OPTION_NULL_FIELDS; if (packed || (flags & HA_PACK_RECORD)) options|=HA_OPTION_PACK_RECORD; /* Must use packed records */ /* We can't use checksum with static length rows */ From edfd875fc1620964d68c9acbd3d36213f1c1663a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 12 Mar 2010 20:03:37 +0100 Subject: [PATCH 339/344] Fix myisam checksum patch to check for HA_OPTION_CHECKSUM after it was set, not before --- storage/myisam/mi_create.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index bbe58143af5..d5ce941bf75 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -175,13 +175,6 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, } } - /* - Don't set HA_OPTION_NULL_FIELDS if no checksums, as this flag makes - that file incompatible with MySQL. This is ok, as this flag is only - used if one specifics table level checksums. - */ - if (!(options & HA_OPTION_CHECKSUM)) - options&= ~HA_OPTION_NULL_FIELDS; if (packed || (flags & HA_PACK_RECORD)) options|=HA_OPTION_PACK_RECORD; /* Must use packed records */ /* We can't use checksum with static length rows */ @@ -199,6 +192,13 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, options|= HA_OPTION_CHECKSUM; min_pack_length++; } + /* + Don't set HA_OPTION_NULL_FIELDS if no checksums, as this flag makes + that file incompatible with MySQL. This is ok, as this flag is only + used if one specifics table level checksums. + */ + if (!(options & HA_OPTION_CHECKSUM)) + options&= ~HA_OPTION_NULL_FIELDS; if (flags & HA_CREATE_DELAY_KEY_WRITE) options|= HA_OPTION_DELAY_KEY_WRITE; if (flags & HA_CREATE_RELIES_ON_SQL_LAYER) From 71b3e46b0160936596195682a731703900fb4fff Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 12 Mar 2010 20:05:21 +0100 Subject: [PATCH 340/344] 1. don't crash on failing to load a plugin with newer MYSQL_PLUGIN_INTERFACE_VERSION 2. don't copy st_mysql_plugin structure unnecessary (sizeof hasn't changed) --- sql/sql_plugin.cc | 56 +++++++++++++++++++++++++---------------------- sql/sql_plugin.h | 3 ++- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 04d1abdeec4..b33d3c0b3ff 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -333,7 +333,7 @@ static inline void free_plugin_mem(struct st_plugin_dl *p) dlclose(p->handle); #endif my_free(p->dl.str, MYF(MY_ALLOW_ZERO_PTR)); - if (p->version != MYSQL_PLUGIN_INTERFACE_VERSION) + if (p->allocated) my_free((uchar*)p->plugins, MYF(MY_ALLOW_ZERO_PTR)); } @@ -454,33 +454,37 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) #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) + if (sizeof_st_plugin != sizeof(st_mysql_plugin)) { - 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)); + for (i= 0; + ((struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info; + i++) + /* no op */; - sym= cur; + cur= (struct st_mysql_plugin*) + my_malloc((i+1)*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.allocated= true; + } } plugin_dl.plugins= (struct st_mysql_plugin *)sym; diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index 54ef38b3734..79ee296ac64 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -63,7 +63,8 @@ struct st_plugin_dl LEX_STRING dl; void *handle; struct st_mysql_plugin *plugins; - int version; + int version; + bool allocated; uint ref_count; /* number of plugins loaded from the library */ }; From 1fbf8458f8fdabf25e42e0d9c2c3eb0b345b152c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 24 Mar 2010 23:12:39 +0100 Subject: [PATCH 341/344] two crashes in the TC_LOG_MMAP: 1. don't forget to initialize page->ptr 2. don't signal active->cond, if active is NULL --- mysql-test/suite/pbxt/r/pbxt_xa.result | 18 ++++++++++++++++++ mysql-test/suite/pbxt/t/pbxt_xa.test | 23 +++++++++++++++++++++++ sql/log.cc | 12 ++++++++++-- 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/pbxt/r/pbxt_xa.result create mode 100644 mysql-test/suite/pbxt/t/pbxt_xa.test diff --git a/mysql-test/suite/pbxt/r/pbxt_xa.result b/mysql-test/suite/pbxt/r/pbxt_xa.result new file mode 100644 index 00000000000..8bcab926998 --- /dev/null +++ b/mysql-test/suite/pbxt/r/pbxt_xa.result @@ -0,0 +1,18 @@ +drop table if exists t1, t2; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb; +CREATE TABLE t2 (b INT PRIMARY KEY) ENGINE=pbxt; +BEGIN; +SELECT @@log_bin; +@@log_bin +0 +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +COMMIT; +select * from t1; +a +1 +select * from t2; +b +2 +drop table t1, t2; +drop database pbxt; diff --git a/mysql-test/suite/pbxt/t/pbxt_xa.test b/mysql-test/suite/pbxt/t/pbxt_xa.test new file mode 100644 index 00000000000..a9d1c5c38e8 --- /dev/null +++ b/mysql-test/suite/pbxt/t/pbxt_xa.test @@ -0,0 +1,23 @@ +-- source include/have_innodb.inc + +--disable_warnings +drop table if exists t1, t2; +--enable_warnings + +# +# bug lp:544173, xa crash with two 2pc-capable storage engines without binlog +# + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb; +CREATE TABLE t2 (b INT PRIMARY KEY) ENGINE=pbxt; +BEGIN; +# verify that binlog is off +SELECT @@log_bin; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +COMMIT; +select * from t1; +select * from t2; +drop table t1, t2; +drop database pbxt; + diff --git a/sql/log.cc b/sql/log.cc index 95b38f7ccd7..6d0314b1d19 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5387,7 +5387,7 @@ int TC_LOG_MMAP::open(const char *opt_name) pg->state=POOL; pthread_mutex_init(&pg->lock, MY_MUTEX_INIT_FAST); pthread_cond_init (&pg->cond, 0); - pg->start=(my_xid *)(data + i*tc_log_page_size); + pg->ptr= pg->start=(my_xid *)(data + i*tc_log_page_size); pg->size=pg->free=tc_log_page_size/sizeof(my_xid); pg->end=pg->start + pg->size; } @@ -5622,7 +5622,15 @@ int TC_LOG_MMAP::sync() /* marking 'syncing' slot free */ pthread_mutex_lock(&LOCK_sync); syncing=0; - pthread_cond_signal(&active->cond); // wake up a new syncer + /* + we check the "active" pointer without LOCK_active. Still, it's safe - + "active" can change from NULL to not NULL any time, but it + will take LOCK_sync before waiting on active->cond. That is, it can never + miss a signal. + And "active" can change to NULL only after LOCK_sync, so this is safe too. + */ + if (active) + pthread_cond_signal(&active->cond); // wake up a new syncer pthread_mutex_unlock(&LOCK_sync); return err; } From 1fec5af772809d4d67ebc3c84286bc4956b80773 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Sun, 28 Mar 2010 21:10:00 +0300 Subject: [PATCH 342/344] Fixed compiler warnings and sporadic failures in test cases mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test: Added missing sync_slave_with_master; Fixes random failures mysql-test/include/default_mysqld.cnf: default-character-set -> character-set-server (removes warning in error files for usage of deprecated options) mysql-test/lib/My/SafeProcess/safe_process.cc: Fixed compiler warning mysql-test/lib/v1/mysql-test-run.pl: default-character-set -> character-set-server (removes warning in error files for usage of deprecated options) mysql-test/suite/rpl/r/rpl_do_grant.result: Updated test results mysql-test/suite/rpl/t/rpl_do_grant.test: Added missing sync_slave_with_master; Fixes random failures Had to explictely do stop slave before DROP USER to avoid failure on slave as the user is already dropped on slave. mysql-test/suite/rpl/t/rpl_name_const.test: Added missing sync_slave_with_master; Fixes random failures mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test: Added missing sync_slave_with_master; Fixes random failures mysql-test/t/bug47671-master.opt: default-character-set -> character-set-server (removes warning in error files for usage of deprecated options) mysql-test/t/ctype_latin1_de-master.opt: default-character-set -> character-set-server (removes warning in error files for usage of deprecated options) mysql-test/t/ctype_ucs2_def-master.opt: default-character-set -> character-set-server (removes warning in error files for usage of deprecated options) sql-common/client.c: Fixed compiler warning sql/item.cc: Renamed function to remove compiler warnings (with gcc) sql/item.h: Renamed function to remove compiler warnings (with gcc) sql/item_cmpfunc.cc: Renamed function to remove compiler warnings (with gcc) sql/item_create.cc: Renamed function to remove compiler warnings (with gcc) sql/item_create.h: Renamed function to remove compiler warnings (with gcc) sql/item_sum.cc: Renamed function to remove compiler warnings (with gcc) sql/item_sum.h: Renamed function to remove compiler warnings (with gcc) sql/set_var.cc: Don't use bit_do_set() / bot_is_set() / bit_do_clear() as this generates compiler warnings (They are also of no use as we know the value can hold the bits) sql/sql_yacc.yy: Renamed function to remove compiler warnings (with gcc) storage/example/ha_example.h: Fixed old read_time() prototype storage/maria/ma_search.c: Added extra variables to remove compiler warnings storage/maria/maria_def.h: Added extra variables to remove compiler warnings storage/myisam/ft_stopwords.c: Added cast to get rid of compiler warning storage/xtradb/fil/fil0fil.c: Added cast to get rid of compiler warning storage/xtradb/include/page0page.h: Added const to get rid of compiler warning storage/xtradb/include/page0page.ic: Added const to get rid of compiler warning support-files/compiler_warnings.supp: Added suppression of strict-aliasing --- .../rpl_tests/rpl_tmp_table_and_DDL.test | 1 + mysql-test/include/default_mysqld.cnf | 2 +- mysql-test/lib/My/SafeProcess/safe_process.cc | 2 +- mysql-test/lib/v1/mysql-test-run.pl | 2 +- mysql-test/suite/rpl/r/rpl_do_grant.result | 5 +- mysql-test/suite/rpl/t/rpl_do_grant.test | 12 +- mysql-test/suite/rpl/t/rpl_name_const.test | 1 + .../suite/rpl/t/rpl_row_basic_11bugs.test | 1 + mysql-test/t/bug47671-master.opt | 2 +- mysql-test/t/ctype_latin1_de-master.opt | 2 +- mysql-test/t/ctype_ucs2_def-master.opt | 2 +- sql-common/client.c | 2 +- sql/item.cc | 2 +- sql/item.h | 2 +- sql/item_cmpfunc.cc | 8 +- sql/item_create.cc | 518 +++++++++--------- sql/item_create.h | 5 +- sql/item_sum.cc | 8 +- sql/item_sum.h | 2 +- sql/set_var.cc | 19 +- sql/sql_yacc.yy | 2 +- storage/example/ha_example.h | 3 +- storage/maria/ma_search.c | 8 +- storage/maria/maria_def.h | 6 +- storage/myisam/ft_stopwords.c | 7 +- storage/xtradb/fil/fil0fil.c | 2 +- storage/xtradb/include/page0page.h | 2 +- storage/xtradb/include/page0page.ic | 2 +- support-files/compiler_warnings.supp | 5 + 29 files changed, 327 insertions(+), 308 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test b/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test index 9cf287281a0..cb1639a04ac 100644 --- a/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test +++ b/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test @@ -157,3 +157,4 @@ INSERT INTO t1 VALUES (1); DROP TEMPORARY TABLE t1; +--sync_slave_with_master diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index ad0090aaf36..c93762f6c25 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -2,7 +2,7 @@ [mysqld] open-files-limit= 1024 local-infile -default-character-set= latin1 +character-set-server= latin1 # Increase default connect_timeout to avoid intermittent # disconnects when test servers are put under load see BUG#28359 diff --git a/mysql-test/lib/My/SafeProcess/safe_process.cc b/mysql-test/lib/My/SafeProcess/safe_process.cc index 50c433b9b39..f9da9560693 100644 --- a/mysql-test/lib/My/SafeProcess/safe_process.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process.cc @@ -159,7 +159,7 @@ int main(int argc, char* const argv[] ) signal(SIGCHLD, handle_signal); signal(SIGABRT, handle_abort); - sprintf(safe_process_name, "safe_process[%d]", own_pid); + sprintf(safe_process_name, "safe_process[%d]", (int) own_pid); message("Started"); diff --git a/mysql-test/lib/v1/mysql-test-run.pl b/mysql-test/lib/v1/mysql-test-run.pl index fe0e1321b8c..998555d76d1 100755 --- a/mysql-test/lib/v1/mysql-test-run.pl +++ b/mysql-test/lib/v1/mysql-test-run.pl @@ -3965,7 +3965,7 @@ sub mysqld_arguments ($$$$) { } } - mtr_add_arg($args, "%s--default-character-set=latin1", $prefix); + mtr_add_arg($args, "%s--character-set-server-set=latin1", $prefix); mtr_add_arg($args, "%s--language=%s", $prefix, $path_language); mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix); diff --git a/mysql-test/suite/rpl/r/rpl_do_grant.result b/mysql-test/suite/rpl/r/rpl_do_grant.result index 65c60acc651..d26a81cb396 100644 --- a/mysql-test/suite/rpl/r/rpl_do_grant.result +++ b/mysql-test/suite/rpl/r/rpl_do_grant.result @@ -165,10 +165,9 @@ USE bug42217_db; DROP FUNCTION upgrade_del_func; DROP FUNCTION upgrade_alter_func; DROP DATABASE bug42217_db; +call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); +stop slave; DROP USER 'create_rout_db'@'localhost'; -call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); -USE mtr; -call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); ######## BUG#49119 ####### ### i) test case from the 'how to repeat section' stop slave; diff --git a/mysql-test/suite/rpl/t/rpl_do_grant.test b/mysql-test/suite/rpl/t/rpl_do_grant.test index 6ae15850cae..8403e108b19 100644 --- a/mysql-test/suite/rpl/t/rpl_do_grant.test +++ b/mysql-test/suite/rpl/t/rpl_do_grant.test @@ -209,12 +209,18 @@ USE bug42217_db; DROP FUNCTION upgrade_del_func; DROP FUNCTION upgrade_alter_func; DROP DATABASE bug42217_db; -DROP USER 'create_rout_db'@'localhost'; call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); + +sync_slave_with_master; + +# Drop the user that was already dropped on the slave connection slave; -USE mtr; -call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); +--disable_warnings +stop slave; +connection master; +DROP USER 'create_rout_db'@'localhost'; +--enable_warnings # BUG#49119: Master crashes when executing 'REVOKE ... ON # {PROCEDURE|FUNCTION} FROM ...' diff --git a/mysql-test/suite/rpl/t/rpl_name_const.test b/mysql-test/suite/rpl/t/rpl_name_const.test index adb71d452ef..d3ef557ddc0 100644 --- a/mysql-test/suite/rpl/t/rpl_name_const.test +++ b/mysql-test/suite/rpl/t/rpl_name_const.test @@ -45,3 +45,4 @@ select * from t1 order by id; connection master; drop table t1; drop procedure test_procedure; +--sync_slave_with_master diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test index 5904585a050..2ee7c62f282 100644 --- a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test +++ b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test @@ -53,6 +53,7 @@ UPDATE t1 SET a=99 WHERE a = 0; SHOW BINLOG EVENTS; DROP TABLE t1; +--sync_slave_with_master # BUG#17620: Replicate (Row Based) Fails when Query Cache enabled on # slave diff --git a/mysql-test/t/bug47671-master.opt b/mysql-test/t/bug47671-master.opt index 0afdf49e022..ad54fbc3467 100644 --- a/mysql-test/t/bug47671-master.opt +++ b/mysql-test/t/bug47671-master.opt @@ -1 +1 @@ ---default-character-set=utf8 --skip-character-set-client-handshake +--character-set-server=utf8 --skip-character-set-client-handshake diff --git a/mysql-test/t/ctype_latin1_de-master.opt b/mysql-test/t/ctype_latin1_de-master.opt index 79fdb1c63dc..063fe5b7792 100644 --- a/mysql-test/t/ctype_latin1_de-master.opt +++ b/mysql-test/t/ctype_latin1_de-master.opt @@ -1 +1 @@ ---default-character-set=latin1 --default-collation=latin1_german2_ci +--character-set-server=latin1 --default-collation=latin1_german2_ci diff --git a/mysql-test/t/ctype_ucs2_def-master.opt b/mysql-test/t/ctype_ucs2_def-master.opt index 84d2a52b639..d42c50f3c7e 100644 --- a/mysql-test/t/ctype_ucs2_def-master.opt +++ b/mysql-test/t/ctype_ucs2_def-master.opt @@ -1 +1 @@ ---default-collation=ucs2_unicode_ci --default-character-set=ucs2,latin1 +--default-collation=ucs2_unicode_ci --character-set-server=ucs2,latin1 diff --git a/sql-common/client.c b/sql-common/client.c index e09d94b34be..d29f6647255 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1863,7 +1863,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, uint port, const char *unix_socket,ulong client_flag) { char buff[NAME_LEN+USERNAME_LENGTH+100]; - char error_string[1024]; char *end,*host_info= NULL; my_socket sock; in_addr_t ip_addr; @@ -2304,6 +2303,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, /* Do the SSL layering. */ struct st_mysql_options *options= &mysql->options; struct st_VioSSLFd *ssl_fd; + char error_string[1024]; /* Send client_flag, max_packet_size - unencrypted otherwise diff --git a/sql/item.cc b/sql/item.cc index 68a9b853af5..cf0d6615999 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7010,7 +7010,7 @@ bool Item_cache_int::cache_value() } -void Item_cache_int::store(Item *item, longlong val_arg) +void Item_cache_int::store_longlong(Item *item, longlong val_arg) { /* An explicit values is given, save it. */ value_cached= TRUE; diff --git a/sql/item.h b/sql/item.h index b8e7bf9f65c..beed859a2c7 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3045,7 +3045,7 @@ public: Item_cache_int(enum_field_types field_type_arg): Item_cache(field_type_arg), value(0) {} - void store(Item *item, longlong val_arg); + void store_longlong(Item *item, longlong val_arg); double val_real(); longlong val_int(); String* val_str(String *str); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index fcd9ebdc938..3431c84b6d1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -879,7 +879,7 @@ get_time_value(THD *thd, Item ***item_arg, Item **cache_arg, Item_cache_int *cache= new Item_cache_int(); /* Mark the cache as non-const to prevent re-caching. */ cache->set_used_tables(1); - cache->store(item, value); + cache->store_longlong(item, value); *cache_arg= cache; *item_arg= cache_arg; } @@ -917,13 +917,13 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, cache->set_used_tables(1); if (!(*a)->is_datetime()) { - cache->store((*a), const_value); + cache->store_longlong((*a), const_value); a_cache= cache; a= (Item **)&a_cache; } else { - cache->store((*b), const_value); + cache->store_longlong((*b), const_value); b_cache= cache; b= (Item **)&b_cache; } @@ -1145,7 +1145,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, Item_cache_int *cache= new Item_cache_int(MYSQL_TYPE_DATETIME); /* Mark the cache as non-const to prevent re-caching. */ cache->set_used_tables(1); - cache->store(item, value); + cache->store_longlong(item, value); *cache_arg= cache; *item_arg= cache_arg; } diff --git a/sql/item_create.cc b/sql/item_create.cc index 89dbdd98262..9a6cde1957d 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -101,7 +101,7 @@ public: @param arg1 The first argument of the function @return An item representing the function call */ - virtual Item *create(THD *thd, Item *arg1) = 0; + virtual Item *create_1_arg(THD *thd, Item *arg1) = 0; protected: /** Constructor. */ @@ -127,7 +127,7 @@ public: @param arg2 The second argument of the function @return An item representing the function call */ - virtual Item *create(THD *thd, Item *arg1, Item *arg2) = 0; + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) = 0; protected: /** Constructor. */ @@ -154,7 +154,7 @@ public: @param arg3 The third argument of the function @return An item representing the function call */ - virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3) = 0; + virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) = 0; protected: /** Constructor. */ @@ -171,8 +171,8 @@ protected: class Create_sp_func : public Create_qfunc { public: - virtual Item *create(THD *thd, LEX_STRING db, LEX_STRING name, - bool use_explicit_name, List *item_list); + virtual Item *create_with_db(THD *thd, LEX_STRING db, LEX_STRING name, + bool use_explicit_name, List *item_list); static Create_sp_func s_singleton; @@ -217,7 +217,7 @@ protected: class Create_func_abs : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_abs s_singleton; @@ -230,7 +230,7 @@ protected: class Create_func_acos : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_acos s_singleton; @@ -243,7 +243,7 @@ protected: class Create_func_addtime : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_addtime s_singleton; @@ -256,7 +256,7 @@ protected: class Create_func_aes_encrypt : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_aes_encrypt s_singleton; @@ -269,7 +269,7 @@ protected: class Create_func_aes_decrypt : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_aes_decrypt s_singleton; @@ -283,7 +283,7 @@ protected: class Create_func_area : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_area s_singleton; @@ -298,7 +298,7 @@ protected: class Create_func_as_wkb : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_as_wkb s_singleton; @@ -313,7 +313,7 @@ protected: class Create_func_as_wkt : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_as_wkt s_singleton; @@ -327,7 +327,7 @@ protected: class Create_func_asin : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_asin s_singleton; @@ -353,7 +353,7 @@ protected: class Create_func_benchmark : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_benchmark s_singleton; @@ -366,7 +366,7 @@ protected: class Create_func_bin : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_bin s_singleton; @@ -379,7 +379,7 @@ protected: class Create_func_bit_count : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_bit_count s_singleton; @@ -392,7 +392,7 @@ protected: class Create_func_bit_length : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_bit_length s_singleton; @@ -405,7 +405,7 @@ protected: class Create_func_ceiling : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_ceiling s_singleton; @@ -419,7 +419,7 @@ protected: class Create_func_centroid : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_centroid s_singleton; @@ -433,7 +433,7 @@ protected: class Create_func_char_length : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_char_length s_singleton; @@ -446,7 +446,7 @@ protected: class Create_func_coercibility : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_coercibility s_singleton; @@ -459,7 +459,7 @@ protected: class Create_func_compress : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_compress s_singleton; @@ -512,7 +512,7 @@ protected: class Create_func_contains : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_contains s_singleton; @@ -526,7 +526,7 @@ protected: class Create_func_conv : public Create_func_arg3 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3); static Create_func_conv s_singleton; @@ -539,7 +539,7 @@ protected: class Create_func_convert_tz : public Create_func_arg3 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3); static Create_func_convert_tz s_singleton; @@ -552,7 +552,7 @@ protected: class Create_func_cos : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_cos s_singleton; @@ -565,7 +565,7 @@ protected: class Create_func_cot : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_cot s_singleton; @@ -578,7 +578,7 @@ protected: class Create_func_crc32 : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_crc32 s_singleton; @@ -592,7 +592,7 @@ protected: class Create_func_crosses : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_crosses s_singleton; @@ -606,7 +606,7 @@ protected: class Create_func_date_format : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_date_format s_singleton; @@ -619,7 +619,7 @@ protected: class Create_func_datediff : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_datediff s_singleton; @@ -632,7 +632,7 @@ protected: class Create_func_dayname : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_dayname s_singleton; @@ -645,7 +645,7 @@ protected: class Create_func_dayofmonth : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_dayofmonth s_singleton; @@ -658,7 +658,7 @@ protected: class Create_func_dayofweek : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_dayofweek s_singleton; @@ -671,7 +671,7 @@ protected: class Create_func_dayofyear : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_dayofyear s_singleton; @@ -684,7 +684,7 @@ protected: class Create_func_decode : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_decode s_singleton; @@ -697,7 +697,7 @@ protected: class Create_func_degrees : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_degrees s_singleton; @@ -737,7 +737,7 @@ protected: class Create_func_dimension : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_dimension s_singleton; @@ -752,7 +752,7 @@ protected: class Create_func_disjoint : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_disjoint s_singleton; @@ -779,7 +779,7 @@ protected: class Create_func_encode : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_encode s_singleton; @@ -806,7 +806,7 @@ protected: class Create_func_endpoint : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_endpoint s_singleton; @@ -821,7 +821,7 @@ protected: class Create_func_envelope : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_envelope s_singleton; @@ -836,7 +836,7 @@ protected: class Create_func_equals : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_equals s_singleton; @@ -850,7 +850,7 @@ protected: class Create_func_exp : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_exp s_singleton; @@ -877,7 +877,7 @@ protected: class Create_func_exteriorring : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_exteriorring s_singleton; @@ -904,7 +904,7 @@ protected: class Create_func_find_in_set : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_find_in_set s_singleton; @@ -917,7 +917,7 @@ protected: class Create_func_floor : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_floor s_singleton; @@ -930,7 +930,7 @@ protected: class Create_func_format : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_format s_singleton; @@ -956,7 +956,7 @@ protected: class Create_func_from_days : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_from_days s_singleton; @@ -1013,7 +1013,7 @@ protected: class Create_func_geometry_type : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_geometry_type s_singleton; @@ -1028,7 +1028,7 @@ protected: class Create_func_geometryn : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_geometryn s_singleton; @@ -1042,7 +1042,7 @@ protected: class Create_func_get_lock : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_get_lock s_singleton; @@ -1056,7 +1056,7 @@ protected: class Create_func_glength : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_glength s_singleton; @@ -1083,7 +1083,7 @@ protected: class Create_func_hex : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_hex s_singleton; @@ -1096,7 +1096,7 @@ protected: class Create_func_ifnull : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_ifnull s_singleton; @@ -1109,7 +1109,7 @@ protected: class Create_func_inet_ntoa : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_inet_ntoa s_singleton; @@ -1122,7 +1122,7 @@ protected: class Create_func_inet_aton : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_inet_aton s_singleton; @@ -1135,7 +1135,7 @@ protected: class Create_func_instr : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_instr s_singleton; @@ -1149,7 +1149,7 @@ protected: class Create_func_interiorringn : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_interiorringn s_singleton; @@ -1164,7 +1164,7 @@ protected: class Create_func_intersects : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_intersects s_singleton; @@ -1178,7 +1178,7 @@ protected: class Create_func_is_free_lock : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_is_free_lock s_singleton; @@ -1191,7 +1191,7 @@ protected: class Create_func_is_used_lock : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_is_used_lock s_singleton; @@ -1205,7 +1205,7 @@ protected: class Create_func_isclosed : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_isclosed s_singleton; @@ -1220,7 +1220,7 @@ protected: class Create_func_isempty : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_isempty s_singleton; @@ -1234,7 +1234,7 @@ protected: class Create_func_isnull : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_isnull s_singleton; @@ -1248,7 +1248,7 @@ protected: class Create_func_issimple : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_issimple s_singleton; @@ -1262,7 +1262,7 @@ protected: class Create_func_last_day : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_last_day s_singleton; @@ -1288,7 +1288,7 @@ protected: class Create_func_lcase : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_lcase s_singleton; @@ -1314,7 +1314,7 @@ protected: class Create_func_length : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_length s_singleton; @@ -1327,7 +1327,7 @@ protected: class Create_func_ln : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_ln s_singleton; @@ -1340,7 +1340,7 @@ protected: class Create_func_load_file : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_load_file s_singleton; @@ -1379,7 +1379,7 @@ protected: class Create_func_log10 : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_log10 s_singleton; @@ -1392,7 +1392,7 @@ protected: class Create_func_log2 : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_log2 s_singleton; @@ -1405,7 +1405,7 @@ protected: class Create_func_lpad : public Create_func_arg3 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3); static Create_func_lpad s_singleton; @@ -1418,7 +1418,7 @@ protected: class Create_func_ltrim : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_ltrim s_singleton; @@ -1431,7 +1431,7 @@ protected: class Create_func_makedate : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_makedate s_singleton; @@ -1444,7 +1444,7 @@ protected: class Create_func_maketime : public Create_func_arg3 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3); static Create_func_maketime s_singleton; @@ -1483,7 +1483,7 @@ protected: class Create_func_md5 : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_md5 s_singleton; @@ -1496,7 +1496,7 @@ protected: class Create_func_monthname : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_monthname s_singleton; @@ -1509,7 +1509,7 @@ protected: class Create_func_name_const : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_name_const s_singleton; @@ -1522,7 +1522,7 @@ protected: class Create_func_nullif : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_nullif s_singleton; @@ -1536,7 +1536,7 @@ protected: class Create_func_numgeometries : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_numgeometries s_singleton; @@ -1551,7 +1551,7 @@ protected: class Create_func_numinteriorring : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_numinteriorring s_singleton; @@ -1566,7 +1566,7 @@ protected: class Create_func_numpoints : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_numpoints s_singleton; @@ -1580,7 +1580,7 @@ protected: class Create_func_oct : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_oct s_singleton; @@ -1593,7 +1593,7 @@ protected: class Create_func_ord : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_ord s_singleton; @@ -1607,7 +1607,7 @@ protected: class Create_func_overlaps : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_overlaps s_singleton; @@ -1621,7 +1621,7 @@ protected: class Create_func_period_add : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_period_add s_singleton; @@ -1634,7 +1634,7 @@ protected: class Create_func_period_diff : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_period_diff s_singleton; @@ -1661,7 +1661,7 @@ protected: class Create_func_pointn : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_pointn s_singleton; @@ -1675,7 +1675,7 @@ protected: class Create_func_pow : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_pow s_singleton; @@ -1688,7 +1688,7 @@ protected: class Create_func_quote : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_quote s_singleton; @@ -1701,7 +1701,7 @@ protected: class Create_func_radians : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_radians s_singleton; @@ -1727,7 +1727,7 @@ protected: class Create_func_release_lock : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_release_lock s_singleton; @@ -1740,7 +1740,7 @@ protected: class Create_func_reverse : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_reverse s_singleton; @@ -1779,7 +1779,7 @@ protected: class Create_func_rpad : public Create_func_arg3 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3); static Create_func_rpad s_singleton; @@ -1792,7 +1792,7 @@ protected: class Create_func_rtrim : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_rtrim s_singleton; @@ -1805,7 +1805,7 @@ protected: class Create_func_sec_to_time : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_sec_to_time s_singleton; @@ -1818,7 +1818,7 @@ protected: class Create_func_sha : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_sha s_singleton; @@ -1831,7 +1831,7 @@ protected: class Create_func_sign : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_sign s_singleton; @@ -1844,7 +1844,7 @@ protected: class Create_func_sin : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_sin s_singleton; @@ -1857,7 +1857,7 @@ protected: class Create_func_sleep : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_sleep s_singleton; @@ -1870,7 +1870,7 @@ protected: class Create_func_soundex : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_soundex s_singleton; @@ -1883,7 +1883,7 @@ protected: class Create_func_space : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_space s_singleton; @@ -1896,7 +1896,7 @@ protected: class Create_func_sqrt : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_sqrt s_singleton; @@ -1910,7 +1910,7 @@ protected: class Create_func_srid : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_srid s_singleton; @@ -1925,7 +1925,7 @@ protected: class Create_func_startpoint : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_startpoint s_singleton; @@ -1939,7 +1939,7 @@ protected: class Create_func_str_to_date : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_str_to_date s_singleton; @@ -1952,7 +1952,7 @@ protected: class Create_func_strcmp : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_strcmp s_singleton; @@ -1965,7 +1965,7 @@ protected: class Create_func_substr_index : public Create_func_arg3 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3); static Create_func_substr_index s_singleton; @@ -1978,7 +1978,7 @@ protected: class Create_func_subtime : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_subtime s_singleton; @@ -1991,7 +1991,7 @@ protected: class Create_func_tan : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_tan s_singleton; @@ -2004,7 +2004,7 @@ protected: class Create_func_time_format : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_time_format s_singleton; @@ -2017,7 +2017,7 @@ protected: class Create_func_time_to_sec : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_time_to_sec s_singleton; @@ -2030,7 +2030,7 @@ protected: class Create_func_timediff : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_timediff s_singleton; @@ -2043,7 +2043,7 @@ protected: class Create_func_to_days : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_to_days s_singleton; @@ -2057,7 +2057,7 @@ protected: class Create_func_touches : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_touches s_singleton; @@ -2071,7 +2071,7 @@ protected: class Create_func_ucase : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_ucase s_singleton; @@ -2084,7 +2084,7 @@ protected: class Create_func_uncompress : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_uncompress s_singleton; @@ -2097,7 +2097,7 @@ protected: class Create_func_uncompressed_length : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_uncompressed_length s_singleton; @@ -2110,7 +2110,7 @@ protected: class Create_func_unhex : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_unhex s_singleton; @@ -2175,7 +2175,7 @@ protected: class Create_func_weekday : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_weekday s_singleton; @@ -2188,7 +2188,7 @@ protected: class Create_func_weekofyear : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_weekofyear s_singleton; @@ -2202,7 +2202,7 @@ protected: class Create_func_within : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_within s_singleton; @@ -2217,7 +2217,7 @@ protected: class Create_func_x : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_x s_singleton; @@ -2231,7 +2231,7 @@ protected: class Create_func_xml_extractvalue : public Create_func_arg2 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2); + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); static Create_func_xml_extractvalue s_singleton; @@ -2244,7 +2244,7 @@ protected: class Create_func_xml_update : public Create_func_arg3 { public: - virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3); static Create_func_xml_update s_singleton; @@ -2258,7 +2258,7 @@ protected: class Create_func_y : public Create_func_arg1 { public: - virtual Item *create(THD *thd, Item *arg1); + virtual Item *create_1_arg(THD *thd, Item *arg1); static Create_func_y s_singleton; @@ -2353,7 +2353,7 @@ Create_qfunc::create(THD *thd, LEX_STRING name, List *item_list) if (thd->lex->copy_db_to(&db.str, &db.length)) return NULL; - return create(thd, db, name, false, item_list); + return create_with_db(thd, db, name, false, item_list); } @@ -2470,8 +2470,8 @@ Create_udf_func::create(THD *thd, udf_func *udf, List *item_list) Create_sp_func Create_sp_func::s_singleton; Item* -Create_sp_func::create(THD *thd, LEX_STRING db, LEX_STRING name, - bool use_explicit_name, List *item_list) +Create_sp_func::create_with_db(THD *thd, LEX_STRING db, LEX_STRING name, + bool use_explicit_name, List *item_list) { int arg_count= 0; Item *func= NULL; @@ -2564,7 +2564,7 @@ Create_func_arg1::create(THD *thd, LEX_STRING name, List *item_list) return NULL; } - return create(thd, param_1); + return create_1_arg(thd, param_1); } @@ -2592,7 +2592,7 @@ Create_func_arg2::create(THD *thd, LEX_STRING name, List *item_list) return NULL; } - return create(thd, param_1, param_2); + return create_2_arg(thd, param_1, param_2); } @@ -2622,14 +2622,14 @@ Create_func_arg3::create(THD *thd, LEX_STRING name, List *item_list) return NULL; } - return create(thd, param_1, param_2, param_3); + return create_3_arg(thd, param_1, param_2, param_3); } Create_func_abs Create_func_abs::s_singleton; Item* -Create_func_abs::create(THD *thd, Item *arg1) +Create_func_abs::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_abs(arg1); } @@ -2638,7 +2638,7 @@ Create_func_abs::create(THD *thd, Item *arg1) Create_func_acos Create_func_acos::s_singleton; Item* -Create_func_acos::create(THD *thd, Item *arg1) +Create_func_acos::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_acos(arg1); } @@ -2647,7 +2647,7 @@ Create_func_acos::create(THD *thd, Item *arg1) Create_func_addtime Create_func_addtime::s_singleton; Item* -Create_func_addtime::create(THD *thd, Item *arg1, Item *arg2) +Create_func_addtime::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_add_time(arg1, arg2, 0, 0); } @@ -2656,7 +2656,7 @@ Create_func_addtime::create(THD *thd, Item *arg1, Item *arg2) Create_func_aes_encrypt Create_func_aes_encrypt::s_singleton; Item* -Create_func_aes_encrypt::create(THD *thd, Item *arg1, Item *arg2) +Create_func_aes_encrypt::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_aes_encrypt(arg1, arg2); } @@ -2665,7 +2665,7 @@ Create_func_aes_encrypt::create(THD *thd, Item *arg1, Item *arg2) Create_func_aes_decrypt Create_func_aes_decrypt::s_singleton; Item* -Create_func_aes_decrypt::create(THD *thd, Item *arg1, Item *arg2) +Create_func_aes_decrypt::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_aes_decrypt(arg1, arg2); } @@ -2675,7 +2675,7 @@ Create_func_aes_decrypt::create(THD *thd, Item *arg1, Item *arg2) Create_func_area Create_func_area::s_singleton; Item* -Create_func_area::create(THD *thd, Item *arg1) +Create_func_area::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_area(arg1); } @@ -2686,7 +2686,7 @@ Create_func_area::create(THD *thd, Item *arg1) Create_func_as_wkb Create_func_as_wkb::s_singleton; Item* -Create_func_as_wkb::create(THD *thd, Item *arg1) +Create_func_as_wkb::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_as_wkb(arg1); } @@ -2697,7 +2697,7 @@ Create_func_as_wkb::create(THD *thd, Item *arg1) Create_func_as_wkt Create_func_as_wkt::s_singleton; Item* -Create_func_as_wkt::create(THD *thd, Item *arg1) +Create_func_as_wkt::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_as_wkt(arg1); } @@ -2707,7 +2707,7 @@ Create_func_as_wkt::create(THD *thd, Item *arg1) Create_func_asin Create_func_asin::s_singleton; Item* -Create_func_asin::create(THD *thd, Item *arg1) +Create_func_asin::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_asin(arg1); } @@ -2753,7 +2753,7 @@ Create_func_atan::create_native(THD *thd, LEX_STRING name, Create_func_benchmark Create_func_benchmark::s_singleton; Item* -Create_func_benchmark::create(THD *thd, Item *arg1, Item *arg2) +Create_func_benchmark::create_2_arg(THD *thd, Item *arg1, Item *arg2) { thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_benchmark(arg1, arg2); @@ -2763,7 +2763,7 @@ Create_func_benchmark::create(THD *thd, Item *arg1, Item *arg2) Create_func_bin Create_func_bin::s_singleton; Item* -Create_func_bin::create(THD *thd, Item *arg1) +Create_func_bin::create_1_arg(THD *thd, Item *arg1) { Item *i10= new (thd->mem_root) Item_int((int32) 10,2); Item *i2= new (thd->mem_root) Item_int((int32) 2,1); @@ -2774,7 +2774,7 @@ Create_func_bin::create(THD *thd, Item *arg1) Create_func_bit_count Create_func_bit_count::s_singleton; Item* -Create_func_bit_count::create(THD *thd, Item *arg1) +Create_func_bit_count::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_bit_count(arg1); } @@ -2783,7 +2783,7 @@ Create_func_bit_count::create(THD *thd, Item *arg1) Create_func_bit_length Create_func_bit_length::s_singleton; Item* -Create_func_bit_length::create(THD *thd, Item *arg1) +Create_func_bit_length::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_bit_length(arg1); } @@ -2792,7 +2792,7 @@ Create_func_bit_length::create(THD *thd, Item *arg1) Create_func_ceiling Create_func_ceiling::s_singleton; Item* -Create_func_ceiling::create(THD *thd, Item *arg1) +Create_func_ceiling::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_ceiling(arg1); } @@ -2802,7 +2802,7 @@ Create_func_ceiling::create(THD *thd, Item *arg1) Create_func_centroid Create_func_centroid::s_singleton; Item* -Create_func_centroid::create(THD *thd, Item *arg1) +Create_func_centroid::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_centroid(arg1); } @@ -2812,7 +2812,7 @@ Create_func_centroid::create(THD *thd, Item *arg1) Create_func_char_length Create_func_char_length::s_singleton; Item* -Create_func_char_length::create(THD *thd, Item *arg1) +Create_func_char_length::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_char_length(arg1); } @@ -2821,7 +2821,7 @@ Create_func_char_length::create(THD *thd, Item *arg1) Create_func_coercibility Create_func_coercibility::s_singleton; Item* -Create_func_coercibility::create(THD *thd, Item *arg1) +Create_func_coercibility::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_coercibility(arg1); } @@ -2873,7 +2873,7 @@ Create_func_concat_ws::create_native(THD *thd, LEX_STRING name, Create_func_compress Create_func_compress::s_singleton; Item* -Create_func_compress::create(THD *thd, Item *arg1) +Create_func_compress::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_compress(arg1); } @@ -2893,7 +2893,7 @@ Create_func_connection_id::create(THD *thd) Create_func_contains Create_func_contains::s_singleton; Item* -Create_func_contains::create(THD *thd, Item *arg1, Item *arg2) +Create_func_contains::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, Item_func::SP_CONTAINS_FUNC); @@ -2904,7 +2904,7 @@ Create_func_contains::create(THD *thd, Item *arg1, Item *arg2) Create_func_conv Create_func_conv::s_singleton; Item* -Create_func_conv::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +Create_func_conv::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) { return new (thd->mem_root) Item_func_conv(arg1, arg2, arg3); } @@ -2913,7 +2913,7 @@ Create_func_conv::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) Create_func_convert_tz Create_func_convert_tz::s_singleton; Item* -Create_func_convert_tz::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +Create_func_convert_tz::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) { return new (thd->mem_root) Item_func_convert_tz(arg1, arg2, arg3); } @@ -2922,7 +2922,7 @@ Create_func_convert_tz::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) Create_func_cos Create_func_cos::s_singleton; Item* -Create_func_cos::create(THD *thd, Item *arg1) +Create_func_cos::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_cos(arg1); } @@ -2931,7 +2931,7 @@ Create_func_cos::create(THD *thd, Item *arg1) Create_func_cot Create_func_cot::s_singleton; Item* -Create_func_cot::create(THD *thd, Item *arg1) +Create_func_cot::create_1_arg(THD *thd, Item *arg1) { Item *i1= new (thd->mem_root) Item_int((char*) "1", 1, 1); Item *i2= new (thd->mem_root) Item_func_tan(arg1); @@ -2942,7 +2942,7 @@ Create_func_cot::create(THD *thd, Item *arg1) Create_func_crc32 Create_func_crc32::s_singleton; Item* -Create_func_crc32::create(THD *thd, Item *arg1) +Create_func_crc32::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_crc32(arg1); } @@ -2952,7 +2952,7 @@ Create_func_crc32::create(THD *thd, Item *arg1) Create_func_crosses Create_func_crosses::s_singleton; Item* -Create_func_crosses::create(THD *thd, Item *arg1, Item *arg2) +Create_func_crosses::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, Item_func::SP_CROSSES_FUNC); @@ -2963,7 +2963,7 @@ Create_func_crosses::create(THD *thd, Item *arg1, Item *arg2) Create_func_date_format Create_func_date_format::s_singleton; Item* -Create_func_date_format::create(THD *thd, Item *arg1, Item *arg2) +Create_func_date_format::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_date_format(arg1, arg2, 0); } @@ -2972,7 +2972,7 @@ Create_func_date_format::create(THD *thd, Item *arg1, Item *arg2) Create_func_datediff Create_func_datediff::s_singleton; Item* -Create_func_datediff::create(THD *thd, Item *arg1, Item *arg2) +Create_func_datediff::create_2_arg(THD *thd, Item *arg1, Item *arg2) { Item *i1= new (thd->mem_root) Item_func_to_days(arg1); Item *i2= new (thd->mem_root) Item_func_to_days(arg2); @@ -2984,7 +2984,7 @@ Create_func_datediff::create(THD *thd, Item *arg1, Item *arg2) Create_func_dayname Create_func_dayname::s_singleton; Item* -Create_func_dayname::create(THD *thd, Item *arg1) +Create_func_dayname::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_dayname(arg1); } @@ -2993,7 +2993,7 @@ Create_func_dayname::create(THD *thd, Item *arg1) Create_func_dayofmonth Create_func_dayofmonth::s_singleton; Item* -Create_func_dayofmonth::create(THD *thd, Item *arg1) +Create_func_dayofmonth::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_dayofmonth(arg1); } @@ -3002,7 +3002,7 @@ Create_func_dayofmonth::create(THD *thd, Item *arg1) Create_func_dayofweek Create_func_dayofweek::s_singleton; Item* -Create_func_dayofweek::create(THD *thd, Item *arg1) +Create_func_dayofweek::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_weekday(arg1, 1); } @@ -3011,7 +3011,7 @@ Create_func_dayofweek::create(THD *thd, Item *arg1) Create_func_dayofyear Create_func_dayofyear::s_singleton; Item* -Create_func_dayofyear::create(THD *thd, Item *arg1) +Create_func_dayofyear::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_dayofyear(arg1); } @@ -3020,7 +3020,7 @@ Create_func_dayofyear::create(THD *thd, Item *arg1) Create_func_decode Create_func_decode::s_singleton; Item* -Create_func_decode::create(THD *thd, Item *arg1, Item *arg2) +Create_func_decode::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_decode(arg1, arg2); } @@ -3029,7 +3029,7 @@ Create_func_decode::create(THD *thd, Item *arg1, Item *arg2) Create_func_degrees Create_func_degrees::s_singleton; Item* -Create_func_degrees::create(THD *thd, Item *arg1) +Create_func_degrees::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_units((char*) "degrees", arg1, 180/M_PI, 0.0); @@ -3114,7 +3114,7 @@ Create_func_des_encrypt::create_native(THD *thd, LEX_STRING name, Create_func_dimension Create_func_dimension::s_singleton; Item* -Create_func_dimension::create(THD *thd, Item *arg1) +Create_func_dimension::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_dimension(arg1); } @@ -3125,7 +3125,7 @@ Create_func_dimension::create(THD *thd, Item *arg1) Create_func_disjoint Create_func_disjoint::s_singleton; Item* -Create_func_disjoint::create(THD *thd, Item *arg1, Item *arg2) +Create_func_disjoint::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, Item_func::SP_DISJOINT_FUNC); @@ -3157,7 +3157,7 @@ Create_func_elt::create_native(THD *thd, LEX_STRING name, Create_func_encode Create_func_encode::s_singleton; Item* -Create_func_encode::create(THD *thd, Item *arg1, Item *arg2) +Create_func_encode::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_encode(arg1, arg2); } @@ -3205,7 +3205,7 @@ Create_func_encrypt::create_native(THD *thd, LEX_STRING name, Create_func_endpoint Create_func_endpoint::s_singleton; Item* -Create_func_endpoint::create(THD *thd, Item *arg1) +Create_func_endpoint::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_spatial_decomp(arg1, Item_func::SP_ENDPOINT); @@ -3217,7 +3217,7 @@ Create_func_endpoint::create(THD *thd, Item *arg1) Create_func_envelope Create_func_envelope::s_singleton; Item* -Create_func_envelope::create(THD *thd, Item *arg1) +Create_func_envelope::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_envelope(arg1); } @@ -3228,7 +3228,7 @@ Create_func_envelope::create(THD *thd, Item *arg1) Create_func_equals Create_func_equals::s_singleton; Item* -Create_func_equals::create(THD *thd, Item *arg1, Item *arg2) +Create_func_equals::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, Item_func::SP_EQUALS_FUNC); @@ -3239,7 +3239,7 @@ Create_func_equals::create(THD *thd, Item *arg1, Item *arg2) Create_func_exp Create_func_exp::s_singleton; Item* -Create_func_exp::create(THD *thd, Item *arg1) +Create_func_exp::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_exp(arg1); } @@ -3302,7 +3302,7 @@ Create_func_export_set::create_native(THD *thd, LEX_STRING name, Create_func_exteriorring Create_func_exteriorring::s_singleton; Item* -Create_func_exteriorring::create(THD *thd, Item *arg1) +Create_func_exteriorring::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_spatial_decomp(arg1, Item_func::SP_EXTERIORRING); @@ -3334,7 +3334,7 @@ Create_func_field::create_native(THD *thd, LEX_STRING name, Create_func_find_in_set Create_func_find_in_set::s_singleton; Item* -Create_func_find_in_set::create(THD *thd, Item *arg1, Item *arg2) +Create_func_find_in_set::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_find_in_set(arg1, arg2); } @@ -3343,7 +3343,7 @@ Create_func_find_in_set::create(THD *thd, Item *arg1, Item *arg2) Create_func_floor Create_func_floor::s_singleton; Item* -Create_func_floor::create(THD *thd, Item *arg1) +Create_func_floor::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_floor(arg1); } @@ -3352,7 +3352,7 @@ Create_func_floor::create(THD *thd, Item *arg1) Create_func_format Create_func_format::s_singleton; Item* -Create_func_format::create(THD *thd, Item *arg1, Item *arg2) +Create_func_format::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_format(arg1, arg2); } @@ -3372,7 +3372,7 @@ Create_func_found_rows::create(THD *thd) Create_func_from_days Create_func_from_days::s_singleton; Item* -Create_func_from_days::create(THD *thd, Item *arg1) +Create_func_from_days::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_from_days(arg1); } @@ -3500,7 +3500,7 @@ Create_func_geometry_from_wkb::create_native(THD *thd, LEX_STRING name, Create_func_geometry_type Create_func_geometry_type::s_singleton; Item* -Create_func_geometry_type::create(THD *thd, Item *arg1) +Create_func_geometry_type::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_geometry_type(arg1); } @@ -3511,7 +3511,7 @@ Create_func_geometry_type::create(THD *thd, Item *arg1) Create_func_geometryn Create_func_geometryn::s_singleton; Item* -Create_func_geometryn::create(THD *thd, Item *arg1, Item *arg2) +Create_func_geometryn::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2, Item_func::SP_GEOMETRYN); @@ -3522,7 +3522,7 @@ Create_func_geometryn::create(THD *thd, Item *arg1, Item *arg2) Create_func_get_lock Create_func_get_lock::s_singleton; Item* -Create_func_get_lock::create(THD *thd, Item *arg1, Item *arg2) +Create_func_get_lock::create_2_arg(THD *thd, Item *arg1, Item *arg2) { thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); @@ -3534,7 +3534,7 @@ Create_func_get_lock::create(THD *thd, Item *arg1, Item *arg2) Create_func_glength Create_func_glength::s_singleton; Item* -Create_func_glength::create(THD *thd, Item *arg1) +Create_func_glength::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_glength(arg1); } @@ -3565,7 +3565,7 @@ Create_func_greatest::create_native(THD *thd, LEX_STRING name, Create_func_hex Create_func_hex::s_singleton; Item* -Create_func_hex::create(THD *thd, Item *arg1) +Create_func_hex::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_hex(arg1); } @@ -3574,7 +3574,7 @@ Create_func_hex::create(THD *thd, Item *arg1) Create_func_ifnull Create_func_ifnull::s_singleton; Item* -Create_func_ifnull::create(THD *thd, Item *arg1, Item *arg2) +Create_func_ifnull::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_ifnull(arg1, arg2); } @@ -3583,7 +3583,7 @@ Create_func_ifnull::create(THD *thd, Item *arg1, Item *arg2) Create_func_inet_ntoa Create_func_inet_ntoa::s_singleton; Item* -Create_func_inet_ntoa::create(THD *thd, Item *arg1) +Create_func_inet_ntoa::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_inet_ntoa(arg1); } @@ -3592,7 +3592,7 @@ Create_func_inet_ntoa::create(THD *thd, Item *arg1) Create_func_inet_aton Create_func_inet_aton::s_singleton; Item* -Create_func_inet_aton::create(THD *thd, Item *arg1) +Create_func_inet_aton::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_inet_aton(arg1); } @@ -3601,7 +3601,7 @@ Create_func_inet_aton::create(THD *thd, Item *arg1) Create_func_instr Create_func_instr::s_singleton; Item* -Create_func_instr::create(THD *thd, Item *arg1, Item *arg2) +Create_func_instr::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_locate(arg1, arg2); } @@ -3611,7 +3611,7 @@ Create_func_instr::create(THD *thd, Item *arg1, Item *arg2) Create_func_interiorringn Create_func_interiorringn::s_singleton; Item* -Create_func_interiorringn::create(THD *thd, Item *arg1, Item *arg2) +Create_func_interiorringn::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2, Item_func::SP_INTERIORRINGN); @@ -3623,7 +3623,7 @@ Create_func_interiorringn::create(THD *thd, Item *arg1, Item *arg2) Create_func_intersects Create_func_intersects::s_singleton; Item* -Create_func_intersects::create(THD *thd, Item *arg1, Item *arg2) +Create_func_intersects::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, Item_func::SP_INTERSECTS_FUNC); @@ -3634,7 +3634,7 @@ Create_func_intersects::create(THD *thd, Item *arg1, Item *arg2) Create_func_is_free_lock Create_func_is_free_lock::s_singleton; Item* -Create_func_is_free_lock::create(THD *thd, Item *arg1) +Create_func_is_free_lock::create_1_arg(THD *thd, Item *arg1) { thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); @@ -3645,7 +3645,7 @@ Create_func_is_free_lock::create(THD *thd, Item *arg1) Create_func_is_used_lock Create_func_is_used_lock::s_singleton; Item* -Create_func_is_used_lock::create(THD *thd, Item *arg1) +Create_func_is_used_lock::create_1_arg(THD *thd, Item *arg1) { thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); @@ -3657,7 +3657,7 @@ Create_func_is_used_lock::create(THD *thd, Item *arg1) Create_func_isclosed Create_func_isclosed::s_singleton; Item* -Create_func_isclosed::create(THD *thd, Item *arg1) +Create_func_isclosed::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_isclosed(arg1); } @@ -3668,7 +3668,7 @@ Create_func_isclosed::create(THD *thd, Item *arg1) Create_func_isempty Create_func_isempty::s_singleton; Item* -Create_func_isempty::create(THD *thd, Item *arg1) +Create_func_isempty::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_isempty(arg1); } @@ -3678,7 +3678,7 @@ Create_func_isempty::create(THD *thd, Item *arg1) Create_func_isnull Create_func_isnull::s_singleton; Item* -Create_func_isnull::create(THD *thd, Item *arg1) +Create_func_isnull::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_isnull(arg1); } @@ -3688,7 +3688,7 @@ Create_func_isnull::create(THD *thd, Item *arg1) Create_func_issimple Create_func_issimple::s_singleton; Item* -Create_func_issimple::create(THD *thd, Item *arg1) +Create_func_issimple::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_issimple(arg1); } @@ -3698,7 +3698,7 @@ Create_func_issimple::create(THD *thd, Item *arg1) Create_func_last_day Create_func_last_day::s_singleton; Item* -Create_func_last_day::create(THD *thd, Item *arg1) +Create_func_last_day::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_last_day(arg1); } @@ -3744,7 +3744,7 @@ Create_func_last_insert_id::create_native(THD *thd, LEX_STRING name, Create_func_lcase Create_func_lcase::s_singleton; Item* -Create_func_lcase::create(THD *thd, Item *arg1) +Create_func_lcase::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_lcase(arg1); } @@ -3774,7 +3774,7 @@ Create_func_least::create_native(THD *thd, LEX_STRING name, Create_func_length Create_func_length::s_singleton; Item* -Create_func_length::create(THD *thd, Item *arg1) +Create_func_length::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_length(arg1); } @@ -3783,7 +3783,7 @@ Create_func_length::create(THD *thd, Item *arg1) Create_func_ln Create_func_ln::s_singleton; Item* -Create_func_ln::create(THD *thd, Item *arg1) +Create_func_ln::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_ln(arg1); } @@ -3792,7 +3792,7 @@ Create_func_ln::create(THD *thd, Item *arg1) Create_func_load_file Create_func_load_file::s_singleton; Item* -Create_func_load_file::create(THD *thd, Item *arg1) +Create_func_load_file::create_1_arg(THD *thd, Item *arg1) { thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); @@ -3881,7 +3881,7 @@ Create_func_log::create_native(THD *thd, LEX_STRING name, Create_func_log10 Create_func_log10::s_singleton; Item* -Create_func_log10::create(THD *thd, Item *arg1) +Create_func_log10::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_log10(arg1); } @@ -3890,7 +3890,7 @@ Create_func_log10::create(THD *thd, Item *arg1) Create_func_log2 Create_func_log2::s_singleton; Item* -Create_func_log2::create(THD *thd, Item *arg1) +Create_func_log2::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_log2(arg1); } @@ -3899,7 +3899,7 @@ Create_func_log2::create(THD *thd, Item *arg1) Create_func_lpad Create_func_lpad::s_singleton; Item* -Create_func_lpad::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +Create_func_lpad::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) { return new (thd->mem_root) Item_func_lpad(arg1, arg2, arg3); } @@ -3908,7 +3908,7 @@ Create_func_lpad::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) Create_func_ltrim Create_func_ltrim::s_singleton; Item* -Create_func_ltrim::create(THD *thd, Item *arg1) +Create_func_ltrim::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_ltrim(arg1); } @@ -3917,7 +3917,7 @@ Create_func_ltrim::create(THD *thd, Item *arg1) Create_func_makedate Create_func_makedate::s_singleton; Item* -Create_func_makedate::create(THD *thd, Item *arg1, Item *arg2) +Create_func_makedate::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_makedate(arg1, arg2); } @@ -3926,7 +3926,7 @@ Create_func_makedate::create(THD *thd, Item *arg1, Item *arg2) Create_func_maketime Create_func_maketime::s_singleton; Item* -Create_func_maketime::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +Create_func_maketime::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) { return new (thd->mem_root) Item_func_maketime(arg1, arg2, arg3); } @@ -4001,7 +4001,7 @@ Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name, Create_func_md5 Create_func_md5::s_singleton; Item* -Create_func_md5::create(THD *thd, Item *arg1) +Create_func_md5::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_md5(arg1); } @@ -4010,7 +4010,7 @@ Create_func_md5::create(THD *thd, Item *arg1) Create_func_monthname Create_func_monthname::s_singleton; Item* -Create_func_monthname::create(THD *thd, Item *arg1) +Create_func_monthname::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_monthname(arg1); } @@ -4019,7 +4019,7 @@ Create_func_monthname::create(THD *thd, Item *arg1) Create_func_name_const Create_func_name_const::s_singleton; Item* -Create_func_name_const::create(THD *thd, Item *arg1, Item *arg2) +Create_func_name_const::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_name_const(arg1, arg2); } @@ -4028,7 +4028,7 @@ Create_func_name_const::create(THD *thd, Item *arg1, Item *arg2) Create_func_nullif Create_func_nullif::s_singleton; Item* -Create_func_nullif::create(THD *thd, Item *arg1, Item *arg2) +Create_func_nullif::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_nullif(arg1, arg2); } @@ -4038,7 +4038,7 @@ Create_func_nullif::create(THD *thd, Item *arg1, Item *arg2) Create_func_numgeometries Create_func_numgeometries::s_singleton; Item* -Create_func_numgeometries::create(THD *thd, Item *arg1) +Create_func_numgeometries::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_numgeometries(arg1); } @@ -4049,7 +4049,7 @@ Create_func_numgeometries::create(THD *thd, Item *arg1) Create_func_numinteriorring Create_func_numinteriorring::s_singleton; Item* -Create_func_numinteriorring::create(THD *thd, Item *arg1) +Create_func_numinteriorring::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_numinteriorring(arg1); } @@ -4060,7 +4060,7 @@ Create_func_numinteriorring::create(THD *thd, Item *arg1) Create_func_numpoints Create_func_numpoints::s_singleton; Item* -Create_func_numpoints::create(THD *thd, Item *arg1) +Create_func_numpoints::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_numpoints(arg1); } @@ -4070,7 +4070,7 @@ Create_func_numpoints::create(THD *thd, Item *arg1) Create_func_oct Create_func_oct::s_singleton; Item* -Create_func_oct::create(THD *thd, Item *arg1) +Create_func_oct::create_1_arg(THD *thd, Item *arg1) { Item *i10= new (thd->mem_root) Item_int((int32) 10,2); Item *i8= new (thd->mem_root) Item_int((int32) 8,1); @@ -4081,7 +4081,7 @@ Create_func_oct::create(THD *thd, Item *arg1) Create_func_ord Create_func_ord::s_singleton; Item* -Create_func_ord::create(THD *thd, Item *arg1) +Create_func_ord::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_ord(arg1); } @@ -4091,7 +4091,7 @@ Create_func_ord::create(THD *thd, Item *arg1) Create_func_overlaps Create_func_overlaps::s_singleton; Item* -Create_func_overlaps::create(THD *thd, Item *arg1, Item *arg2) +Create_func_overlaps::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, Item_func::SP_OVERLAPS_FUNC); @@ -4102,7 +4102,7 @@ Create_func_overlaps::create(THD *thd, Item *arg1, Item *arg2) Create_func_period_add Create_func_period_add::s_singleton; Item* -Create_func_period_add::create(THD *thd, Item *arg1, Item *arg2) +Create_func_period_add::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_period_add(arg1, arg2); } @@ -4111,7 +4111,7 @@ Create_func_period_add::create(THD *thd, Item *arg1, Item *arg2) Create_func_period_diff Create_func_period_diff::s_singleton; Item* -Create_func_period_diff::create(THD *thd, Item *arg1, Item *arg2) +Create_func_period_diff::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_period_diff(arg1, arg2); } @@ -4130,7 +4130,7 @@ Create_func_pi::create(THD *thd) Create_func_pointn Create_func_pointn::s_singleton; Item* -Create_func_pointn::create(THD *thd, Item *arg1, Item *arg2) +Create_func_pointn::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2, Item_func::SP_POINTN); @@ -4141,7 +4141,7 @@ Create_func_pointn::create(THD *thd, Item *arg1, Item *arg2) Create_func_pow Create_func_pow::s_singleton; Item* -Create_func_pow::create(THD *thd, Item *arg1, Item *arg2) +Create_func_pow::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_pow(arg1, arg2); } @@ -4150,7 +4150,7 @@ Create_func_pow::create(THD *thd, Item *arg1, Item *arg2) Create_func_quote Create_func_quote::s_singleton; Item* -Create_func_quote::create(THD *thd, Item *arg1) +Create_func_quote::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_quote(arg1); } @@ -4159,7 +4159,7 @@ Create_func_quote::create(THD *thd, Item *arg1) Create_func_radians Create_func_radians::s_singleton; Item* -Create_func_radians::create(THD *thd, Item *arg1) +Create_func_radians::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_units((char*) "radians", arg1, M_PI/180, 0.0); @@ -4216,7 +4216,7 @@ Create_func_rand::create_native(THD *thd, LEX_STRING name, Create_func_release_lock Create_func_release_lock::s_singleton; Item* -Create_func_release_lock::create(THD *thd, Item *arg1) +Create_func_release_lock::create_1_arg(THD *thd, Item *arg1) { thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); @@ -4227,7 +4227,7 @@ Create_func_release_lock::create(THD *thd, Item *arg1) Create_func_reverse Create_func_reverse::s_singleton; Item* -Create_func_reverse::create(THD *thd, Item *arg1) +Create_func_reverse::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_reverse(arg1); } @@ -4285,7 +4285,7 @@ Create_func_row_count::create(THD *thd) Create_func_rpad Create_func_rpad::s_singleton; Item* -Create_func_rpad::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +Create_func_rpad::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) { return new (thd->mem_root) Item_func_rpad(arg1, arg2, arg3); } @@ -4294,7 +4294,7 @@ Create_func_rpad::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) Create_func_rtrim Create_func_rtrim::s_singleton; Item* -Create_func_rtrim::create(THD *thd, Item *arg1) +Create_func_rtrim::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_rtrim(arg1); } @@ -4303,7 +4303,7 @@ Create_func_rtrim::create(THD *thd, Item *arg1) Create_func_sec_to_time Create_func_sec_to_time::s_singleton; Item* -Create_func_sec_to_time::create(THD *thd, Item *arg1) +Create_func_sec_to_time::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_sec_to_time(arg1); } @@ -4312,7 +4312,7 @@ Create_func_sec_to_time::create(THD *thd, Item *arg1) Create_func_sha Create_func_sha::s_singleton; Item* -Create_func_sha::create(THD *thd, Item *arg1) +Create_func_sha::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_sha(arg1); } @@ -4321,7 +4321,7 @@ Create_func_sha::create(THD *thd, Item *arg1) Create_func_sign Create_func_sign::s_singleton; Item* -Create_func_sign::create(THD *thd, Item *arg1) +Create_func_sign::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_sign(arg1); } @@ -4330,7 +4330,7 @@ Create_func_sign::create(THD *thd, Item *arg1) Create_func_sin Create_func_sin::s_singleton; Item* -Create_func_sin::create(THD *thd, Item *arg1) +Create_func_sin::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_sin(arg1); } @@ -4339,7 +4339,7 @@ Create_func_sin::create(THD *thd, Item *arg1) Create_func_sleep Create_func_sleep::s_singleton; Item* -Create_func_sleep::create(THD *thd, Item *arg1) +Create_func_sleep::create_1_arg(THD *thd, Item *arg1) { thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); @@ -4350,7 +4350,7 @@ Create_func_sleep::create(THD *thd, Item *arg1) Create_func_soundex Create_func_soundex::s_singleton; Item* -Create_func_soundex::create(THD *thd, Item *arg1) +Create_func_soundex::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_soundex(arg1); } @@ -4359,7 +4359,7 @@ Create_func_soundex::create(THD *thd, Item *arg1) Create_func_space Create_func_space::s_singleton; Item* -Create_func_space::create(THD *thd, Item *arg1) +Create_func_space::create_1_arg(THD *thd, Item *arg1) { /** TODO: Fix Bug#23637 @@ -4387,7 +4387,7 @@ Create_func_space::create(THD *thd, Item *arg1) Create_func_sqrt Create_func_sqrt::s_singleton; Item* -Create_func_sqrt::create(THD *thd, Item *arg1) +Create_func_sqrt::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_sqrt(arg1); } @@ -4397,7 +4397,7 @@ Create_func_sqrt::create(THD *thd, Item *arg1) Create_func_srid Create_func_srid::s_singleton; Item* -Create_func_srid::create(THD *thd, Item *arg1) +Create_func_srid::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_srid(arg1); } @@ -4408,7 +4408,7 @@ Create_func_srid::create(THD *thd, Item *arg1) Create_func_startpoint Create_func_startpoint::s_singleton; Item* -Create_func_startpoint::create(THD *thd, Item *arg1) +Create_func_startpoint::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_spatial_decomp(arg1, Item_func::SP_STARTPOINT); @@ -4419,7 +4419,7 @@ Create_func_startpoint::create(THD *thd, Item *arg1) Create_func_str_to_date Create_func_str_to_date::s_singleton; Item* -Create_func_str_to_date::create(THD *thd, Item *arg1, Item *arg2) +Create_func_str_to_date::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_str_to_date(arg1, arg2); } @@ -4428,7 +4428,7 @@ Create_func_str_to_date::create(THD *thd, Item *arg1, Item *arg2) Create_func_strcmp Create_func_strcmp::s_singleton; Item* -Create_func_strcmp::create(THD *thd, Item *arg1, Item *arg2) +Create_func_strcmp::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_strcmp(arg1, arg2); } @@ -4437,7 +4437,7 @@ Create_func_strcmp::create(THD *thd, Item *arg1, Item *arg2) Create_func_substr_index Create_func_substr_index::s_singleton; Item* -Create_func_substr_index::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +Create_func_substr_index::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) { return new (thd->mem_root) Item_func_substr_index(arg1, arg2, arg3); } @@ -4446,7 +4446,7 @@ Create_func_substr_index::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) Create_func_subtime Create_func_subtime::s_singleton; Item* -Create_func_subtime::create(THD *thd, Item *arg1, Item *arg2) +Create_func_subtime::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_add_time(arg1, arg2, 0, 1); } @@ -4455,7 +4455,7 @@ Create_func_subtime::create(THD *thd, Item *arg1, Item *arg2) Create_func_tan Create_func_tan::s_singleton; Item* -Create_func_tan::create(THD *thd, Item *arg1) +Create_func_tan::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_tan(arg1); } @@ -4464,7 +4464,7 @@ Create_func_tan::create(THD *thd, Item *arg1) Create_func_time_format Create_func_time_format::s_singleton; Item* -Create_func_time_format::create(THD *thd, Item *arg1, Item *arg2) +Create_func_time_format::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_date_format(arg1, arg2, 1); } @@ -4473,7 +4473,7 @@ Create_func_time_format::create(THD *thd, Item *arg1, Item *arg2) Create_func_time_to_sec Create_func_time_to_sec::s_singleton; Item* -Create_func_time_to_sec::create(THD *thd, Item *arg1) +Create_func_time_to_sec::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_time_to_sec(arg1); } @@ -4482,7 +4482,7 @@ Create_func_time_to_sec::create(THD *thd, Item *arg1) Create_func_timediff Create_func_timediff::s_singleton; Item* -Create_func_timediff::create(THD *thd, Item *arg1, Item *arg2) +Create_func_timediff::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_timediff(arg1, arg2); } @@ -4491,7 +4491,7 @@ Create_func_timediff::create(THD *thd, Item *arg1, Item *arg2) Create_func_to_days Create_func_to_days::s_singleton; Item* -Create_func_to_days::create(THD *thd, Item *arg1) +Create_func_to_days::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_to_days(arg1); } @@ -4501,7 +4501,7 @@ Create_func_to_days::create(THD *thd, Item *arg1) Create_func_touches Create_func_touches::s_singleton; Item* -Create_func_touches::create(THD *thd, Item *arg1, Item *arg2) +Create_func_touches::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, Item_func::SP_TOUCHES_FUNC); @@ -4512,7 +4512,7 @@ Create_func_touches::create(THD *thd, Item *arg1, Item *arg2) Create_func_ucase Create_func_ucase::s_singleton; Item* -Create_func_ucase::create(THD *thd, Item *arg1) +Create_func_ucase::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_ucase(arg1); } @@ -4521,7 +4521,7 @@ Create_func_ucase::create(THD *thd, Item *arg1) Create_func_uncompress Create_func_uncompress::s_singleton; Item* -Create_func_uncompress::create(THD *thd, Item *arg1) +Create_func_uncompress::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_uncompress(arg1); } @@ -4530,7 +4530,7 @@ Create_func_uncompress::create(THD *thd, Item *arg1) Create_func_uncompressed_length Create_func_uncompressed_length::s_singleton; Item* -Create_func_uncompressed_length::create(THD *thd, Item *arg1) +Create_func_uncompressed_length::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_uncompressed_length(arg1); } @@ -4539,7 +4539,7 @@ Create_func_uncompressed_length::create(THD *thd, Item *arg1) Create_func_unhex Create_func_unhex::s_singleton; Item* -Create_func_unhex::create(THD *thd, Item *arg1) +Create_func_unhex::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_unhex(arg1); } @@ -4620,7 +4620,7 @@ Create_func_version::create(THD *thd) Create_func_weekday Create_func_weekday::s_singleton; Item* -Create_func_weekday::create(THD *thd, Item *arg1) +Create_func_weekday::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_weekday(arg1, 0); } @@ -4629,7 +4629,7 @@ Create_func_weekday::create(THD *thd, Item *arg1) Create_func_weekofyear Create_func_weekofyear::s_singleton; Item* -Create_func_weekofyear::create(THD *thd, Item *arg1) +Create_func_weekofyear::create_1_arg(THD *thd, Item *arg1) { Item *i1= new (thd->mem_root) Item_int((char*) "0", 3, 1); return new (thd->mem_root) Item_func_week(arg1, i1); @@ -4640,7 +4640,7 @@ Create_func_weekofyear::create(THD *thd, Item *arg1) Create_func_within Create_func_within::s_singleton; Item* -Create_func_within::create(THD *thd, Item *arg1, Item *arg2) +Create_func_within::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, Item_func::SP_WITHIN_FUNC); @@ -4652,7 +4652,7 @@ Create_func_within::create(THD *thd, Item *arg1, Item *arg2) Create_func_x Create_func_x::s_singleton; Item* -Create_func_x::create(THD *thd, Item *arg1) +Create_func_x::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_x(arg1); } @@ -4662,7 +4662,7 @@ Create_func_x::create(THD *thd, Item *arg1) Create_func_xml_extractvalue Create_func_xml_extractvalue::s_singleton; Item* -Create_func_xml_extractvalue::create(THD *thd, Item *arg1, Item *arg2) +Create_func_xml_extractvalue::create_2_arg(THD *thd, Item *arg1, Item *arg2) { return new (thd->mem_root) Item_func_xml_extractvalue(arg1, arg2); } @@ -4671,7 +4671,7 @@ Create_func_xml_extractvalue::create(THD *thd, Item *arg1, Item *arg2) Create_func_xml_update Create_func_xml_update::s_singleton; Item* -Create_func_xml_update::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +Create_func_xml_update::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) { return new (thd->mem_root) Item_func_xml_update(arg1, arg2, arg3); } @@ -4681,7 +4681,7 @@ Create_func_xml_update::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) Create_func_y Create_func_y::s_singleton; Item* -Create_func_y::create(THD *thd, Item *arg1) +Create_func_y::create_1_arg(THD *thd, Item *arg1) { return new (thd->mem_root) Item_func_y(arg1); } diff --git a/sql/item_create.h b/sql/item_create.h index a3ba6bd26a6..9f439a3aead 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -91,8 +91,9 @@ public: @param item_list The list of arguments to the function, can be NULL @return An item representing the parsed function call */ - virtual Item* create(THD *thd, LEX_STRING db, LEX_STRING name, - bool use_explicit_name, List *item_list) = 0; + virtual Item *create_with_db(THD *thd, LEX_STRING db, LEX_STRING name, + bool use_explicit_name, + List *item_list) = 0; protected: /** Constructor. */ diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 15b17cbdc1b..6f852e1016c 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -642,7 +642,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) default: DBUG_ASSERT(0); }; - setup(args[0], NULL); + setup_item(args[0], NULL); /* MIN/MAX can return NULL for empty set indepedent of the used column */ maybe_null= 1; unsigned_flag=item->unsigned_flag; @@ -676,7 +676,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) of the original MIN/MAX object and it is saved in this object's cache. */ -void Item_sum_hybrid::setup(Item *item, Item *value_arg) +void Item_sum_hybrid::setup_item(Item *item, Item *value_arg) { value= Item_cache::get_cache(item); value->setup(item); @@ -1646,7 +1646,7 @@ void Item_sum_hybrid::no_rows_in_result() Item *Item_sum_min::copy_or_same(THD* thd) { Item_sum_min *item= new (thd->mem_root) Item_sum_min(thd, this); - item->setup(args[0], value); + item->setup_item(args[0], value); return item; } @@ -1669,7 +1669,7 @@ bool Item_sum_min::add() Item *Item_sum_max::copy_or_same(THD* thd) { Item_sum_max *item= new (thd->mem_root) Item_sum_max(thd, this); - item->setup(args[0], value); + item->setup_item(args[0], value); return item; } diff --git a/sql/item_sum.h b/sql/item_sum.h index ad66d4b7098..110265fd8b4 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -858,7 +858,7 @@ protected: was_values(item->was_values) { } bool fix_fields(THD *, Item **); - void setup(Item *item, Item *value_arg); + void setup_item(Item *item, Item *value_arg); void clear(); double val_real(); longlong val_int(); diff --git a/sql/set_var.cc b/sql/set_var.cc index 2adec7e7f0a..faea858c2b9 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1263,16 +1263,16 @@ uchar *sys_var_set::value_ptr(THD *thd, enum_var_type type, void sys_var_set_slave_mode::set_default(THD *thd, enum_var_type type) { - slave_exec_mode_options= 0; - bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT); + slave_exec_mode_options= (ULL(1) << SLAVE_EXEC_MODE_STRICT); } bool sys_var_set_slave_mode::check(THD *thd, set_var *var) { bool rc= sys_var_set::check(thd, var); if (!rc && - bit_is_set(var->save_result.ulong_value, SLAVE_EXEC_MODE_STRICT) == 1 && - bit_is_set(var->save_result.ulong_value, SLAVE_EXEC_MODE_IDEMPOTENT) == 1) + test_all_bits(var->save_result.ulong_value, + ((ULL(1) << SLAVE_EXEC_MODE_STRICT) | + (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT)))) { rc= true; my_error(ER_SLAVE_AMBIGOUS_EXEC_MODE, MYF(0), ""); @@ -1294,15 +1294,16 @@ void fix_slave_exec_mode(enum_var_type type) DBUG_ENTER("fix_slave_exec_mode"); compile_time_assert(sizeof(slave_exec_mode_options) * CHAR_BIT > SLAVE_EXEC_MODE_LAST_BIT - 1); - if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT) == 1 && - bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT) == 1) + if (test_all_bits(slave_exec_mode_options, + ((ULL(1) << SLAVE_EXEC_MODE_STRICT) | + (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT)))) { sql_print_error("Ambiguous slave modes combination." " STRICT will be used"); - bit_do_clear(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT); + slave_exec_mode_options&= ~(ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT); } - if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT) == 0) - bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT); + if (!(slave_exec_mode_options & (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT))) + slave_exec_mode_options|= (ULL(1)<< SLAVE_EXEC_MODE_STRICT); DBUG_VOID_RETURN; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e0f5cd9a562..fc2e18f28f2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8082,7 +8082,7 @@ function_call_generic: builder= find_qualified_function_builder(thd); DBUG_ASSERT(builder); - item= builder->create(thd, $1, $3, true, $5); + item= builder->create_with_db(thd, $1, $3, true, $5); if (! ($$= item)) { diff --git a/storage/example/ha_example.h b/storage/example/ha_example.h index ec3987ced5d..f67235eefd1 100644 --- a/storage/example/ha_example.h +++ b/storage/example/ha_example.h @@ -155,7 +155,8 @@ public: /** @brief This method will never be called if you do not implement indexes. */ - virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; } + virtual double read_time(uint index, uint ranges, ha_rows rows) + { return (double) rows / 20.0+1; } /* Everything below are methods that we implement in ha_example.cc. diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index 8df0ebc4bf4..a5b9bf18aa9 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -76,8 +76,8 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, bmove512(info->keyread_buff, page_buff, info->s->block_size); /* Save position for a possible read next / previous */ - info->int_keypos= info->keyread_buff + (ulonglong) info->int_keypos; - info->int_maxpos= info->keyread_buff + (ulonglong) info->int_maxpos; + info->int_keypos= info->keyread_buff + info->keypos_offset; + info->int_maxpos= info->keyread_buff + info->maxpos_offset; info->int_keytree_version= key->keyinfo->version; info->last_search_keypage= info->last_keypage; info->page_changed= 0; @@ -214,8 +214,8 @@ static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, info->cur_row.trid= _ma_trid_from_key(&info->last_key); /* Store offset to key */ - info->int_keypos= (uchar*) (keypos - page.buff); - info->int_maxpos= (uchar*) (maxpos - page.buff); + info->keypos_offset= (uint) (keypos - page.buff); + info->maxpos_offset= (uint) (maxpos - page.buff); info->int_nod_flag= nod_flag; info->last_keypage= pos; *res_page_link= page_link; diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 29eb32a4fb2..db6845cb345 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -506,8 +506,10 @@ struct st_maria_handler uchar *first_mbr_key; /* Searhed spatial key */ uchar *rec_buff; /* Temp buffer for recordpack */ uchar *blob_buff; /* Temp buffer for blobs */ - uchar *int_keypos, /* Save position for next/previous */ - *int_maxpos; /* -""- */ + uchar *int_keypos; /* Save position for next/previous */ + uchar *int_maxpos; /* -""- */ + uint keypos_offset; /* Tmp storage for offset int_keypos */ + uint maxpos_offset; /* Tmp storage for offset int_maxpos */ uchar *update_field_data; /* Used by update in rows-in-block */ uint int_nod_flag; /* -""- */ uint32 int_keytree_version; /* -""- */ diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c index aa209e082e0..05948a936a6 100644 --- a/storage/myisam/ft_stopwords.c +++ b/storage/myisam/ft_stopwords.c @@ -44,9 +44,10 @@ static void FT_STOPWORD_free(FT_STOPWORD *w, TREE_FREE action, static int ft_add_stopword(const char *w) { FT_STOPWORD sw; - return !w || - (((sw.len= (uint) strlen(sw.pos=(const uchar *)w)) >= ft_min_word_len) && - (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL)); + return (!w || + (((sw.len= (uint) strlen((char*) (sw.pos=(const uchar *)w))) >= + ft_min_word_len) && + (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL))); } int ft_init_stopwords() diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c index 9fa401a4b3e..5e4546bf989 100644 --- a/storage/xtradb/fil/fil0fil.c +++ b/storage/xtradb/fil/fil0fil.c @@ -3168,7 +3168,7 @@ skip_info: mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id); for (i = 0; (ulint) i < n_index; i++) { - if (offset / UNIV_PAGE_SIZE == root_page[i]) { + if ((ulint) (offset / UNIV_PAGE_SIZE) == root_page[i]) { /* this is index root page */ mach_write_to_4(page + FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF + FSEG_HDR_SPACE, id); diff --git a/storage/xtradb/include/page0page.h b/storage/xtradb/include/page0page.h index 3899499fb6a..e182c8f58be 100644 --- a/storage/xtradb/include/page0page.h +++ b/storage/xtradb/include/page0page.h @@ -517,7 +517,7 @@ UNIV_INLINE rec_t* page_rec_get_next( /*==============*/ - rec_t* rec); /*!< in: pointer to record */ + const rec_t* rec); /*!< in: pointer to record */ /************************************************************//** Gets the pointer to the next record on the page. @return pointer to next record */ diff --git a/storage/xtradb/include/page0page.ic b/storage/xtradb/include/page0page.ic index 8f794410f20..9655e6c7e27 100644 --- a/storage/xtradb/include/page0page.ic +++ b/storage/xtradb/include/page0page.ic @@ -731,7 +731,7 @@ UNIV_INLINE rec_t* page_rec_get_next( /*==============*/ - rec_t* rec) /*!< in: pointer to record */ + const rec_t* rec) /*!< in: pointer to record */ { return((rec_t*) page_rec_get_next_low(rec, page_rec_is_comp(rec))); } diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index d3806f42b94..3037149d0b4 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -65,6 +65,11 @@ db_vrfy.c : .*comparison is always false due to limited range of data type.* # /usr/share/aclocal/audiofile.m4 : .* +# +# Ignore strict-aliasing warnings (for now) +# +.*: break strict-aliasing rules + # # Ignore all conversion warnings on windows 64 # (Is safe as we are not yet supporting strings >= 2G) From 639bdb2891efe9378911a9ce7a1ed3d5859183dc Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 29 Mar 2010 22:07:45 +0300 Subject: [PATCH 343/344] Fixed random failure in test system Removed and suppressed compiler warnings mysql-test/suite/parts/t/rpl_partition.test: Mark as big test (as test takes > 5 minutes) mysql-test/suite/rpl/t/rpl_row_trig003.test: Fixed random failure sql/item_create.cc: Renamed create -> create_builder() to avoid compiler warnings about function hidden by others sql/net_serv.cc: Removed compiler warning support-files/compiler_warnings.supp: Supress some warnings Remove suppresstion from set_var.cc, as this has already been fixed Added missing \ before .c Added suppression of warnings that are due to gcc bug (.*discards qualifiers from pointer target type.*) --- mysql-test/suite/parts/t/rpl_partition.test | 1 + mysql-test/suite/rpl/t/rpl_row_trig003.test | 2 ++ sql/item_create.cc | 32 ++++++++++----------- sql/net_serv.cc | 2 +- support-files/compiler_warnings.supp | 13 +++++---- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/mysql-test/suite/parts/t/rpl_partition.test b/mysql-test/suite/parts/t/rpl_partition.test index c5ee20971b3..f7d1c14cf29 100644 --- a/mysql-test/suite/parts/t/rpl_partition.test +++ b/mysql-test/suite/parts/t/rpl_partition.test @@ -1,6 +1,7 @@ --source include/have_partition.inc --source include/have_innodb.inc --source include/master-slave.inc +--source include/big_test.inc --vertical_results diff --git a/mysql-test/suite/rpl/t/rpl_row_trig003.test b/mysql-test/suite/rpl/t/rpl_row_trig003.test index 5d667e29d69..dada855a89e 100644 --- a/mysql-test/suite/rpl/t/rpl_row_trig003.test +++ b/mysql-test/suite/rpl/t/rpl_row_trig003.test @@ -149,6 +149,8 @@ DROP TABLE IF EXISTS test.t2; DROP TABLE IF EXISTS test.t3; --enable_warnings +sync_slave_with_master; + diff_files $MYSQLTEST_VARDIR/tmp/trg003_master.sql $MYSQLTEST_VARDIR/tmp/trg003_slave.sql; # End of 5.0 test case diff --git a/sql/item_create.cc b/sql/item_create.cc index 9a6cde1957d..6799fbddd3f 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -76,7 +76,7 @@ public: @param thd The current thread @return An item representing the function call */ - virtual Item *create(THD *thd) = 0; + virtual Item *create_builder(THD *thd) = 0; protected: /** Constructor. */ @@ -498,7 +498,7 @@ protected: class Create_func_connection_id : public Create_func_arg0 { public: - virtual Item *create(THD *thd); + virtual Item *create_builder(THD *thd); static Create_func_connection_id s_singleton; @@ -943,7 +943,7 @@ protected: class Create_func_found_rows : public Create_func_arg0 { public: - virtual Item *create(THD *thd); + virtual Item *create_builder(THD *thd); static Create_func_found_rows s_singleton; @@ -1647,7 +1647,7 @@ protected: class Create_func_pi : public Create_func_arg0 { public: - virtual Item *create(THD *thd); + virtual Item *create_builder(THD *thd); static Create_func_pi s_singleton; @@ -1766,7 +1766,7 @@ protected: class Create_func_row_count : public Create_func_arg0 { public: - virtual Item *create(THD *thd); + virtual Item *create_builder(THD *thd); static Create_func_row_count s_singleton; @@ -2136,7 +2136,7 @@ protected: class Create_func_uuid : public Create_func_arg0 { public: - virtual Item *create(THD *thd); + virtual Item *create_builder(THD *thd); static Create_func_uuid s_singleton; @@ -2149,7 +2149,7 @@ protected: class Create_func_uuid_short : public Create_func_arg0 { public: - virtual Item *create(THD *thd); + virtual Item *create_builder(THD *thd); static Create_func_uuid_short s_singleton; @@ -2162,7 +2162,7 @@ protected: class Create_func_version : public Create_func_arg0 { public: - virtual Item *create(THD *thd); + virtual Item *create_builder(THD *thd); static Create_func_version s_singleton; @@ -2538,7 +2538,7 @@ Create_func_arg0::create(THD *thd, LEX_STRING name, List *item_list) return NULL; } - return create(thd); + return create_builder(thd); } @@ -2882,7 +2882,7 @@ Create_func_compress::create_1_arg(THD *thd, Item *arg1) Create_func_connection_id Create_func_connection_id::s_singleton; Item* -Create_func_connection_id::create(THD *thd) +Create_func_connection_id::create_builder(THD *thd) { thd->lex->safe_to_cache_query= 0; return new (thd->mem_root) Item_func_connection_id(); @@ -3361,7 +3361,7 @@ Create_func_format::create_2_arg(THD *thd, Item *arg1, Item *arg2) Create_func_found_rows Create_func_found_rows::s_singleton; Item* -Create_func_found_rows::create(THD *thd) +Create_func_found_rows::create_builder(THD *thd) { thd->lex->set_stmt_unsafe(); thd->lex->safe_to_cache_query= 0; @@ -4120,7 +4120,7 @@ Create_func_period_diff::create_2_arg(THD *thd, Item *arg1, Item *arg2) Create_func_pi Create_func_pi::s_singleton; Item* -Create_func_pi::create(THD *thd) +Create_func_pi::create_builder(THD *thd) { return new (thd->mem_root) Item_static_float_func("pi()", M_PI, 6, 8); } @@ -4274,7 +4274,7 @@ Create_func_round::create_native(THD *thd, LEX_STRING name, Create_func_row_count Create_func_row_count::s_singleton; Item* -Create_func_row_count::create(THD *thd) +Create_func_row_count::create_builder(THD *thd) { thd->lex->set_stmt_unsafe(); thd->lex->safe_to_cache_query= 0; @@ -4584,7 +4584,7 @@ Create_func_unix_timestamp::create_native(THD *thd, LEX_STRING name, Create_func_uuid Create_func_uuid::s_singleton; Item* -Create_func_uuid::create(THD *thd) +Create_func_uuid::create_builder(THD *thd) { thd->lex->set_stmt_unsafe(); thd->lex->safe_to_cache_query= 0; @@ -4595,7 +4595,7 @@ Create_func_uuid::create(THD *thd) Create_func_uuid_short Create_func_uuid_short::s_singleton; Item* -Create_func_uuid_short::create(THD *thd) +Create_func_uuid_short::create_builder(THD *thd) { thd->lex->set_stmt_unsafe(); thd->lex->safe_to_cache_query= 0; @@ -4606,7 +4606,7 @@ Create_func_uuid_short::create(THD *thd) Create_func_version Create_func_version::s_singleton; Item* -Create_func_version::create(THD *thd) +Create_func_version::create_builder(THD *thd) { thd->lex->set_stmt_unsafe(); return new (thd->mem_root) Item_static_string_func("version()", diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 58ccde760c2..5df98662fe7 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -279,7 +279,7 @@ static int net_data_is_ready(my_socket sd) @param clear_buffer if <> 0, then clear all data from comm buff */ -void net_clear(NET *net, my_bool clear_buffer) +void net_clear(NET *net, my_bool clear_buffer __attribute__((unused))) { #if !defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF) size_t count; diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index 3037149d0b4..0a5aa645d3a 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -39,6 +39,7 @@ sync/sync0rw\.c: unused parameter sync/sync0sync\.c: unused parameter sync/sync0sync\.c: unused variable ut/ut0ut\.c: ignoring return value of +srv/srv0srv\.c: value computed is not used # # bdb is not critical to keep up to date @@ -128,18 +129,18 @@ include/runtime.hpp: .*pure_error.* # listener.cc : .*conversion from 'SOCKET' to 'int'.* net_serv.cc : .*conversion from 'SOCKET' to 'int'.* -set_var.cc: right-hand operand of comma has no effect : 1000-1400 - # allow a little moving space for the warning below -mi_packrec.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 560-600 -ma_packrec.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 550-650 +mi_packrec\.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 560-600 +ma_packrec\.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 550-650 # # Wrong compiler warnings # .* : .*no matching operator delete found; memory will not be freed if initialization throws an exception.* -ctype-simple.c : .*unary minus operator applied to unsigned type, result still unsigned.* +ctype-simple\.c : .*unary minus operator applied to unsigned type, result still unsigned.* # Wrong warning due to GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29478 -regexec\.c : .*passing argument 3 of.*matcher.* discards qualifiers from pointer target type.* +regexec\.c : passing argument 3 of.*matcher.* discards qualifiers from pointer target type +libmysql\.c: passing argument 2 of .*memcpy.* discards qualifiers from pointer target type : 3000-4000 +storage/xtradb/dict/dict0dict\.c: passing argument 1 of .*strcpy.* discards qualifiers from pointer target type : 2500-3500 From d904739cc1d98107f67e76a67b0ea6eb2af326ec Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Tue, 30 Mar 2010 15:36:49 +0300 Subject: [PATCH 344/344] Removed compiler warning Disable pbxt for test cases not using pbxt (speeds up test suite) extra/comp_err.c: Added cast to get rid of compiler warning extra/libevent/kqueue.c: Added cast to get rid of compiler warning mysql-test/lib/mtr_cases.pm: Use --skip-pbxt for test cases that doesn't need pbxt Collect default-storage-engine from suite.opt file (should actually be my.cnf file, but that wasn't easy to do) mysql-test/suite/pbxt/t/suite.opt: Added marker for mysql-test-run.pl that this suite require pbxt mysys/mf_keycache.c: Use LINT_INIT() to remove compiler warnings mysys/my_gethostbyname.c: Remove compiler warnings sql/handler.cc: Reset variable that may be used uninitialized sql/item.h: Remove compiler warning sql/mysqld.cc: Use LINT_INIT() to remove compiler warnings sql/sql_class.h: Remove compiler warning sql/sql_table.cc: Ensure variable is always set (to remove compiler warning) sql/sql_view.cc: Use LINT_INIT() to remove compiler warnings storage/maria/ma_loghandler.c: Use LINT_INIT() to remove compiler warnings storage/myisammrg/ha_myisammrg.cc: Fixed wrong type to printf storage/myisammrg/myrg_open.c: Use LINT_INIT() to remove compiler warnings storage/xtradb/include/ut0lst.h: Trivial change of macro to remove compiler warning strings/ctype-ucs2.c: Use LINT_INIT() to remove compiler warnings strings/ctype-utf8.c: Use LINT_INIT() to remove compiler warnings support-files/compiler_warnings.supp: Suppress some not relevant warnings unittest/mysys/waiting_threads-t.c: Don't use ftruncate() as this gives warning about ignored return value --- extra/comp_err.c | 2 +- extra/libevent/kqueue.c | 2 +- mysql-test/lib/mtr_cases.pm | 44 ++++++++++++++++++++++++++-- mysql-test/suite/pbxt/t/suite.opt | 1 + mysys/mf_keycache.c | 6 ++++ mysys/my_gethostbyname.c | 9 ++++-- sql/handler.cc | 2 +- sql/item.h | 3 +- sql/mysqld.cc | 10 +++++++ sql/sql_class.h | 2 ++ sql/sql_table.cc | 8 ++--- sql/sql_view.cc | 4 ++- storage/maria/ma_loghandler.c | 4 +++ storage/myisammrg/ha_myisammrg.cc | 2 +- storage/myisammrg/myrg_open.c | 1 + storage/xtradb/include/ut0lst.h | 2 +- strings/ctype-ucs2.c | 6 ++-- strings/ctype-utf8.c | 4 +-- support-files/compiler_warnings.supp | 11 +++++++ unittest/mysys/waiting_threads-t.c | 2 +- 20 files changed, 102 insertions(+), 23 deletions(-) create mode 100644 mysql-test/suite/pbxt/t/suite.opt diff --git a/extra/comp_err.c b/extra/comp_err.c index 9326444ade9..bca8d3895cb 100644 --- a/extra/comp_err.c +++ b/extra/comp_err.c @@ -660,7 +660,7 @@ static ha_checksum checksum_format_specifier(const char* msg) case 'u': case 'x': case 's': - chksum= my_checksum(chksum, start, (uint) (p + 1 - start)); + chksum= my_checksum(chksum, (uchar*) start, (uint) (p + 1 - start)); start= 0; /* Not in format specifier anymore */ break; diff --git a/extra/libevent/kqueue.c b/extra/libevent/kqueue.c index 775698baa67..eec5a6ab6fb 100644 --- a/extra/libevent/kqueue.c +++ b/extra/libevent/kqueue.c @@ -144,7 +144,7 @@ kq_init(struct event_base *base) */ if (kevent(kq, kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 || - kqueueop->events[0].ident != -1 || + ((int) kqueueop->events[0].ident) != -1 || kqueueop->events[0].flags != EV_ERROR) { event_warn("%s: detected broken kqueue; not using.", __func__); free(kqueueop->changes); diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 220db3d6217..ad8a204db47 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -681,6 +681,8 @@ sub optimize_cases { if ( $default_engine =~ /^ndb/i ); $tinfo->{'innodb_test'}= 1 if ( $default_engine =~ /^innodb/i ); + $tinfo->{'pbxt_test'}= 1 + if ( $default_engine =~ /^pbxt/i ); } } @@ -778,6 +780,8 @@ sub collect_one_test_case { my $disabled= shift; my $suite_opts= shift; + my $local_default_storage_engine= $default_storage_engine; + #print "collect_one_test_case\n"; #print " suitedir: $suitedir\n"; #print " testdir: $testdir\n"; @@ -932,15 +936,26 @@ sub collect_one_test_case { tags_from_test_file($tinfo,"$testdir/${tname}.test"); - if ( defined $default_storage_engine ) + # Get default storage engine from suite.opt file + + if (defined $suite_opts && + "@$suite_opts" =~ "default-storage-engine=\s*([^\s]*)") + { + $local_default_storage_engine= $1; + } + + if ( defined $local_default_storage_engine ) { # Different default engine is used # tag test to require that engine $tinfo->{'ndb_test'}= 1 - if ( $default_storage_engine =~ /^ndb/i ); + if ( $local_default_storage_engine =~ /^ndb/i ); $tinfo->{'innodb_test'}= 1 - if ( $default_storage_engine =~ /^innodb/i ); + if ( $local_default_storage_engine =~ /^innodb/i ); + + $tinfo->{'pbxt_test'}= 1 + if ( $local_default_storage_engine =~ /^pbxt/i ); } @@ -1103,6 +1118,28 @@ sub collect_one_test_case { $tinfo->{template_path}= $config; } + if ( $tinfo->{'pbxt_test'} ) + { + # This is a test that needs pbxt + if ( $::mysqld_variables{'pbxt'} eq "OFF" || + ! exists $::mysqld_variables{'pbxt'} ) + { + # Engine is not supported, skip it + $tinfo->{'skip'}= 1; + return $tinfo; + } + } + else + { + # Only disable engine if it's on by default (to avoid warnings about + # not existing loose options + if ( $::mysqld_variables{'pbxt'} eq "ON") + { + push(@{$tinfo->{'master_opt'}}, "--loose-skip-pbxt"); + push(@{$tinfo->{'slave_opt'}}, "--loose-skip-pbxt"); + } + } + if ( $tinfo->{'example_plugin_test'} ) { if ( !$ENV{'EXAMPLE_PLUGIN'} ) @@ -1156,6 +1193,7 @@ my @tags= ["include/have_log_bin.inc", "need_binlog", 1], ["include/have_innodb.inc", "innodb_test", 1], + ["include/have_pbxt.inc", "pbxt_test", 1], ["include/big_test.inc", "big_test", 1], ["include/have_debug.inc", "need_debug", 1], ["include/have_ndb.inc", "ndb_test", 1], diff --git a/mysql-test/suite/pbxt/t/suite.opt b/mysql-test/suite/pbxt/t/suite.opt new file mode 100644 index 00000000000..3036df38940 --- /dev/null +++ b/mysql-test/suite/pbxt/t/suite.opt @@ -0,0 +1 @@ +--default-storage-engine=pbxt diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 0630d194234..f7b420c3bf2 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -3924,6 +3924,12 @@ restart: uint next_status; uint hash_requests; + LINT_INIT(next_hash_link); + LINT_INIT(next_diskpos); + LINT_INIT(next_file); + LINT_INIT(next_status); + LINT_INIT(hash_requests); + total_found++; found++; KEYCACHE_DBUG_ASSERT(found <= keycache->blocks_used); diff --git a/mysys/my_gethostbyname.c b/mysys/my_gethostbyname.c index 067fdfee9db..985a76faf0d 100644 --- a/mysys/my_gethostbyname.c +++ b/mysys/my_gethostbyname.c @@ -91,9 +91,12 @@ extern pthread_mutex_t LOCK_gethostbyname_r; is finished with the structure. */ -struct hostent *my_gethostbyname_r(const char *name, - struct hostent *result, char *buffer, - int buflen, int *h_errnop) +struct hostent * +my_gethostbyname_r(const char *name, + struct hostent *result __attribute__((unused)), + char *buffer __attribute__((unused)), + int buflen__attribute__((unused)), + int *h_errnop) { struct hostent *hp; pthread_mutex_lock(&LOCK_gethostbyname_r); diff --git a/sql/handler.cc b/sql/handler.cc index 72c78727111..876512ed87f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4129,7 +4129,7 @@ int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, */ int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p) { - int result; + int result= 0; DBUG_ENTER("handler::read_multi_range_next"); /* We should not be called after the last call returned EOF. */ diff --git a/sql/item.h b/sql/item.h index beed859a2c7..8bcfaa286c7 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1077,7 +1077,8 @@ class Field_enumerator { public: virtual void visit_field(Field *field)= 0; - virtual ~Field_enumerator() {}; /* purecov: inspected */ + virtual ~Field_enumerator() {}; /* purecov: inspected */ + Field_enumerator() {} /* Remove gcc warning */ }; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0eeea729adc..6b5783b7e2e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8323,6 +8323,8 @@ mysqld_get_one_option(int optid, case (int) OPT_INIT_RPL_ROLE: { int role; + LINT_INIT(role); + if (!find_opt_type(argument, &rpl_role_typelib, opt->name, &role)) { rpl_status = (role == 1) ? RPL_AUTH_MASTER : RPL_IDLE_SLAVE; @@ -8378,6 +8380,8 @@ mysqld_get_one_option(int optid, case OPT_BINLOG_FORMAT: { int id; + LINT_INIT(id); + if (!find_opt_type(argument, &binlog_format_typelib, opt->name, &id)) { global_system_variables.binlog_format= opt_binlog_format_id= id - 1; @@ -8628,6 +8632,8 @@ mysqld_get_one_option(int optid, else { int type; + LINT_INIT(type); + if (!find_opt_type(argument, &delay_key_write_typelib, opt->name, &type)) delay_key_write_options= (uint) type-1; } @@ -8639,6 +8645,8 @@ mysqld_get_one_option(int optid, case OPT_TX_ISOLATION: { int type; + LINT_INIT(type); + if (!find_opt_type(argument, &tx_isolation_typelib, opt->name, &type)) global_system_variables.tx_isolation= (type-1); break; @@ -8726,6 +8734,7 @@ mysqld_get_one_option(int optid, ulong method_conv; int method; LINT_INIT(method_conv); + LINT_INIT(method); myisam_stats_method_str= argument; if (!find_opt_type(argument, &myisam_stats_method_typelib, @@ -8788,6 +8797,7 @@ mysqld_get_one_option(int optid, case OPT_THREAD_HANDLING: { int id; + LINT_INIT(id); if (!find_opt_type(argument, &thread_handling_typelib, opt->name, &id)) global_system_variables.thread_handling= id - 1; opt_thread_handling= thread_handling_typelib.type_names[global_system_variables.thread_handling]; diff --git a/sql/sql_class.h b/sql/sql_class.h index 841acae0bf8..aa39ddb2b15 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -63,6 +63,7 @@ public: bool report_error(THD *thd); bool is_invalidated() const { return m_invalidated; } void reset_reprepare_observer() { m_invalidated= FALSE; } + Reprepare_observer() {} /* Remove gcc warning */ private: bool m_invalidated; }; @@ -1107,6 +1108,7 @@ public: /* Ignore error */ return TRUE; } + Dummy_error_handler() {} /* Remove gcc warning */ }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6d20ea0d3e5..6b7b3e2c0ab 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5668,6 +5668,10 @@ compare_tables(TABLE *table, */ Alter_info tmp_alter_info(*alter_info, thd->mem_root); uint db_options= 0; /* not used */ + + /* Set default value for return value (to ensure it's always set) */ + *need_copy_table= ALTER_TABLE_DATA_CHANGED; + /* Create the prepared information. */ if (mysql_prepare_create_table(thd, create_info, &tmp_alter_info, @@ -5726,7 +5730,6 @@ compare_tables(TABLE *table, (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar)) { DBUG_PRINT("info", ("Basic checks -> ALTER_TABLE_DATA_CHANGED")); - *need_copy_table= ALTER_TABLE_DATA_CHANGED; DBUG_RETURN(0); } @@ -5756,7 +5759,6 @@ compare_tables(TABLE *table, { DBUG_PRINT("info", ("NULL behaviour difference in field '%s' -> " "ALTER_TABLE_DATA_CHANGED", new_field->field_name)); - *need_copy_table= ALTER_TABLE_DATA_CHANGED; DBUG_RETURN(0); } @@ -5779,7 +5781,6 @@ compare_tables(TABLE *table, { DBUG_PRINT("info", ("!field_is_equal('%s') -> ALTER_TABLE_DATA_CHANGED", new_field->field_name)); - *need_copy_table= ALTER_TABLE_DATA_CHANGED; DBUG_RETURN(0); } // Clear indexed marker @@ -5914,7 +5915,6 @@ compare_tables(TABLE *table, { DBUG_PRINT("info", ("check_if_incompatible_data() -> " "ALTER_TABLE_DATA_CHANGED")); - *need_copy_table= ALTER_TABLE_DATA_CHANGED; DBUG_RETURN(0); } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index c6d412112c2..e1e0b3ff6c4 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1034,10 +1034,12 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, bool parse_status; bool result, view_is_mergeable; TABLE_LIST *UNINIT_VAR(view_main_select_tables); - DBUG_ENTER("mysql_make_view"); DBUG_PRINT("info", ("table: 0x%lx (%s)", (ulong) table, table->table_name)); + LINT_INIT(parse_status); + LINT_INIT(view_select); + if (table->view) { /* diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index aff2b638e4e..5e316e2d776 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -1211,6 +1211,8 @@ static my_bool translog_set_lsn_for_files(uint32 from_file, uint32 to_file, for (file= from_file; file <= to_file; file++) { LOGHANDLER_FILE_INFO info; + LINT_INIT(info.max_lsn); + File fd= open_logfile_by_number_no_cache(file); if ((fd < 0) || ((translog_read_file_header(&info, fd) || @@ -3845,6 +3847,8 @@ my_bool translog_init_with_table(const char *directory, if (!old_log_was_recovered && old_flags == flags) { LOGHANDLER_FILE_INFO info; + LINT_INIT(info.maria_version); + /* Accessing &log_descriptor.open_files without mutex is safe because it is initialization diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 0d4ab20a834..9dac355fd0a 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -382,7 +382,7 @@ static MI_INFO *myisammrg_attach_children_callback(void *callback_param) my_errno= HA_ERR_WRONG_MRG_TABLE_DEF; } DBUG_PRINT("myrg", ("MyISAM handle: 0x%lx my_errno: %d", - my_errno ? NULL : (long) myisam, my_errno)); + my_errno ? 0L : (long) myisam, my_errno)); err: DBUG_RETURN(my_errno ? NULL : myisam); diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c index 7b310dc2eed..32ac719ec4d 100644 --- a/storage/myisammrg/myrg_open.c +++ b/storage/myisammrg/myrg_open.c @@ -239,6 +239,7 @@ MYRG_INFO *myrg_parent_open(const char *parent_name, rc= 1; errpos= 0; bzero((char*) &file_cache, sizeof(file_cache)); + LINT_INIT(m_info); /* Open MERGE meta file. */ if ((fd= my_open(fn_format(parent_name_buff, parent_name, "", MYRG_NAME_EXT, diff --git a/storage/xtradb/include/ut0lst.h b/storage/xtradb/include/ut0lst.h index 261d33963dc..fa7a186dfb1 100644 --- a/storage/xtradb/include/ut0lst.h +++ b/storage/xtradb/include/ut0lst.h @@ -158,7 +158,7 @@ Inserts a NODE2 after NODE1 in a list. /** Invalidate the pointers in a list node. @param NAME list name @param N pointer to the node that was removed */ -# define UT_LIST_REMOVE_CLEAR(NAME, N) while (0) +# define UT_LIST_REMOVE_CLEAR(NAME, N) {} while (0) #endif /*******************************************************************//** diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index bf9c6f9626a..9e37518fb1b 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -203,7 +203,7 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs, my_bool t_is_prefix) { int s_res,t_res; - my_wc_t UNINIT_VAR(s_wc),t_wc; + my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc); const uchar *se=s+slen; const uchar *te=t+tlen; MY_UNICASE_INFO **uni_plane= cs->caseinfo; @@ -317,7 +317,7 @@ static int my_strncasecmp_ucs2(CHARSET_INFO *cs, const char *s, const char *t, size_t len) { int s_res,t_res; - my_wc_t UNINIT_VAR(s_wc),t_wc; + my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc); const char *se=s+len; const char *te=t+len; MY_UNICASE_INFO **uni_plane= cs->caseinfo; @@ -1384,7 +1384,7 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *cs, my_bool t_is_prefix) { int s_res,t_res; - my_wc_t UNINIT_VAR(s_wc),t_wc; + my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc); const uchar *se=s+slen; const uchar *te=t+tlen; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 91f633e45ce..f99c34ec39a 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2310,7 +2310,7 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs, my_bool t_is_prefix) { int s_res,t_res; - my_wc_t UNINIT_VAR(s_wc), t_wc; + my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc); const uchar *se=s+slen; const uchar *te=t+tlen; MY_UNICASE_INFO **uni_plane= cs->caseinfo; @@ -2380,7 +2380,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs, my_bool diff_if_only_endspace_difference) { int s_res, t_res, res; - my_wc_t UNINIT_VAR(s_wc),t_wc; + my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc); const uchar *se= s+slen, *te= t+tlen; MY_UNICASE_INFO **uni_plane= cs->caseinfo; diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index 0a5aa645d3a..fbac70c4ebb 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -71,6 +71,11 @@ db_vrfy.c : .*comparison is always false due to limited range of data type.* # .*: break strict-aliasing rules +# +# Ignore not important declaration warnings +# +.*: only defines private constructors and has no friends + # # Ignore all conversion warnings on windows 64 # (Is safe as we are not yet supporting strings >= 2G) @@ -105,6 +110,11 @@ db_vrfy.c : .*comparison is always false due to limited range of data type.* # storage/maria/ma_pagecache.c: .*'info_check_pin' defined but not used +# +# Pbxt +# +xaction_xt\.cc: may be used uninitialized in this function + # # I think these are due to mix of C and C++. # @@ -118,6 +128,7 @@ include/runtime.hpp: .*pure_error.* .*/extra/yassl/taocrypt/src/blowfish\.cpp: array subscript is above array bounds .*/extra/yassl/taocrypt/src/file\.cpp: ignoring return value .*/extra/yassl/taocrypt/src/integer\.cpp: control reaches end of non-void function +mySTL/algorithm\.hpp: is used uninitialized in this function # # Groff warnings on OpenSUSE. diff --git a/unittest/mysys/waiting_threads-t.c b/unittest/mysys/waiting_threads-t.c index 79dee219efb..e32a83ef172 100644 --- a/unittest/mysys/waiting_threads-t.c +++ b/unittest/mysys/waiting_threads-t.c @@ -258,7 +258,7 @@ void do_tests() #define test_kill_strategy(X) \ diag("kill strategy: " #X); \ DBUG_EXECUTE("reset_file", \ - { rewind(DBUG_FILE); (void) ftruncate(fileno(DBUG_FILE), 0); }); \ + { rewind(DBUG_FILE); my_chsize(fileno(DBUG_FILE), 0, 0, MYF(MY_WME)); }); \ DBUG_PRINT("info", ("kill strategy: " #X)); \ kill_strategy=X; \ do_one_test();