From 575a64c48edcc049ae2ec09bffd72f37adbae3da Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Tue, 11 Sep 2012 20:56:22 +0200 Subject: [PATCH 01/11] Backport this change from MySQL 5.5 to 5.1: Bug #14181049: MYSQL_INSTALL_DB.PL CREATES EMPTY SYSTEM TABLES FOR MYSQL The script is different from what's used on unixes. It was not playing the table insertion script (mysql_system_tables_data.sql), although it was checking for the presence of this script. Fixed by re-enabling the lookup for this file and replaying it at bootstrap time. Note that on the Unixes "SELECT @@hostname" does return a fully qualified name, whereas on Windows it returns only a hostname. So by default we're filtering records in the mysql.user table until we ensure this is fixed. The change was coded in 5.5 by Georgi Kodinov --- scripts/mysql_install_db.pl.in | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/scripts/mysql_install_db.pl.in b/scripts/mysql_install_db.pl.in index c63da6df537..12cd6a21ad1 100644 --- a/scripts/mysql_install_db.pl.in +++ b/scripts/mysql_install_db.pl.in @@ -423,10 +423,11 @@ my $mysqld_install_cmd_line = quote_options($mysqld_bootstrap, "--bootstrap", "--basedir=$opt->{basedir}", "--datadir=$opt->{ldata}", - "--skip-innodb", - "--skip-bdb", - "--skip-ndbcluster", + "--log-warnings=0", + "--loose-skip-innodb", + "--loose-skip-ndbcluster", "--max_allowed_packet=8M", + "--default-storage-engine=MyISAM", "--net_buffer_length=16K", @args, ); @@ -439,6 +440,8 @@ report_verbose_wait($opt,"Installing MySQL system tables..."); open(SQL, $create_system_tables) or error($opt,"can't open $create_system_tables for reading: $!"); +open(SQL2, $fill_system_tables) + or error($opt,"can't open $fill_system_tables for reading: $!"); # FIXME > /dev/null ? if ( open(PIPE, "| $mysqld_install_cmd_line") ) { @@ -452,8 +455,20 @@ if ( open(PIPE, "| $mysqld_install_cmd_line") ) print PIPE $_; } + while ( ) + { + # TODO: make it similar to the above condition when we're sure + # @@hostname returns a fqdn + # When doing a "cross bootstrap" install, no reference to the current + # host should be added to the system tables. So we filter out any + # lines which contain the current host name. + next if /\@current_hostname/; + + print PIPE $_; + } close PIPE; close SQL; + close SQL2; report_verbose($opt,"OK"); From f1d3b0f19011217c13927f44a82e8e17291fbba7 Mon Sep 17 00:00:00 2001 From: Nuno Carvalho Date: Fri, 12 Oct 2012 08:32:10 +0100 Subject: [PATCH 02/11] BUG#14629727: USER_VAR_EVENT IS MISSING RANGE CHECKS This bug had two problems: P1) Reads out of bounds; P2) Writes out of bounds. PROBLEM P1 ---------- User_var_log_event unmarshalling from binlog was not performing range checks when using name_len and val_len variables to walk on event buffer. Added range checks to User_var_log_event unmarshalling to prevent unmarshalling errors. PROBLEM P2 ---------- User_var_log_event value was allocated on thread stack, what caused stack frame errors when User_var_log_event value was bigger than thread stack size. Currently value is allocated on heap memory. --- sql/log_event.cc | 45 ++++++++++++++++++++++++++++++++++++++++----- sql/log_event.h | 4 ++-- sql/mysql_priv.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index c3ba969cf1f..0ad258f7073 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1286,7 +1286,7 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, ev = new Rand_log_event(buf, description_event); break; case USER_VAR_EVENT: - ev = new User_var_log_event(buf, description_event); + ev = new User_var_log_event(buf, event_len, description_event); break; case FORMAT_DESCRIPTION_EVENT: ev = new Format_description_log_event(buf, event_len, description_event); @@ -5685,18 +5685,34 @@ void User_var_log_event::pack_info(Protocol* protocol) User_var_log_event:: -User_var_log_event(const char* buf, +User_var_log_event(const char* buf, uint event_len, const Format_description_log_event* description_event) :Log_event(buf, description_event) #ifndef MYSQL_CLIENT , deferred(false) #endif { + bool error= false; + const char* buf_start= buf; /* The Post-Header is empty. The Variable Data part begins immediately. */ buf+= description_event->common_header_len + description_event->post_header_len[USER_VAR_EVENT-1]; name_len= uint4korr(buf); name= (char *) buf + UV_NAME_LEN_SIZE; + + /* + We don't know yet is_null value, so we must assume that name_len + may have the bigger value possible, is_null= True and there is no + payload for val. + */ + if (0 == name_len || + !valid_buffer_range(name_len, buf_start, name, + event_len - UV_VAL_IS_NULL)) + { + error= true; + goto err; + } + buf+= UV_NAME_LEN_SIZE + name_len; is_null= (bool) *buf; if (is_null) @@ -5708,13 +5724,31 @@ User_var_log_event(const char* buf, } else { + if (!valid_buffer_range(UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE, + buf_start, buf, event_len)) + { + error= true; + goto err; + } + type= (Item_result) buf[UV_VAL_IS_NULL]; charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE); val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE); val= (char *) (buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE); + + if (!valid_buffer_range(val_len, buf_start, val, event_len)) + { + error= true; + goto err; + } } + +err: + if (error) + name= 0; } @@ -5860,8 +5894,9 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) char *hex_str; CHARSET_INFO *cs; - if (!(hex_str= (char *)my_alloca(2*val_len+1+2))) // 2 hex digits / byte - break; // no error, as we are 'void' + hex_str= (char *)my_malloc(2*val_len+1+2,MYF(MY_WME)); // 2 hex digits / byte + if (!hex_str) + return; str_to_hex(hex_str, val, val_len); /* For proper behaviour when mysqlbinlog|mysql, we need to explicitely @@ -5879,7 +5914,7 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) my_b_printf(&cache, ":=_%s %s COLLATE `%s`%s\n", cs->csname, hex_str, cs->name, print_event_info->delimiter); - my_afree(hex_str); + my_free(hex_str, MYF(MY_WME)); } break; case ROW_RESULT: diff --git a/sql/log_event.h b/sql/log_event.h index ba6b9b876aa..c36564fcde8 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2496,7 +2496,7 @@ public: void print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif - User_var_log_event(const char* buf, + User_var_log_event(const char* buf, uint event_len, const Format_description_log_event *description_event); ~User_var_log_event() {} Log_event_type get_type_code() { return USER_VAR_EVENT;} @@ -2510,7 +2510,7 @@ public: bool is_deferred() { return deferred; } void set_deferred() { deferred= true; } #endif - bool is_valid() const { return 1; } + bool is_valid() const { return name != 0; } private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 937617032dd..05a37228e17 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -501,6 +501,50 @@ protected: */ #define MAX_TIME_ZONE_NAME_LENGTH (NAME_LEN + 1) +/* + Check how many bytes are available on buffer. + + @param buf_start Pointer to buffer start. + @param buf_current Pointer to the current position on buffer. + @param buf_len Buffer length. + + @return Number of bytes available on event buffer. +*/ +template T available_buffer(const char* buf_start, + const char* buf_current, + T buf_len) +{ + return buf_len - (buf_current - buf_start); +} +/* Explicit instantion to unsigned int. */ +template unsigned int available_buffer(const char*, + const char*, + unsigned int); + +/* + Check if jump value is within buffer limits. + + @param jump Number of positions we want to advance. + @param buf_start Pointer to buffer start + @param buf_current Pointer to the current position on buffer. + @param buf_len Buffer length. + + @return True If jump value is within buffer limits. + False Otherwise. +*/ +template bool valid_buffer_range(T jump, + const char* buf_start, + const char* buf_current, + T buf_len) +{ + return (jump <= available_buffer(buf_start, buf_current, buf_len)); +} +/* Explicit instantion to unsigned int. */ +template bool valid_buffer_range(unsigned int, + const char*, + const char*, + unsigned int); + /* The rest of the file is included in the server only */ #ifndef MYSQL_CLIENT From 779960205f85a88b11126e6aedd750440fb486c3 Mon Sep 17 00:00:00 2001 From: "Krunal Bauskar krunal.bauskar@oracle.com" Date: Wed, 17 Oct 2012 14:30:32 +0530 Subject: [PATCH 03/11] bug#14765606: ensure select is active before killing it else kill signal is ignored --- .../suite/innodb/r/innodb_bug14704286.result | 20 ++++++++++++++----- .../suite/innodb/t/innodb_bug14704286.test | 12 ++++++++--- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb_bug14704286.result b/mysql-test/suite/innodb/r/innodb_bug14704286.result index 9703955cfa7..9de42cb01c8 100644 --- a/mysql-test/suite/innodb/r/innodb_bug14704286.result +++ b/mysql-test/suite/innodb/r/innodb_bug14704286.result @@ -1,7 +1,5 @@ use test; drop table if exists t1; -Warnings: -Note 1051 Unknown table 't1' create table t1 (id int primary key, value int, value2 int, value3 int, index(value,value2)) engine=innodb; insert into t1 values @@ -19,6 +17,7 @@ update test.t1 set value2=value2+1, value3=value3+1 where id=12; SET i = i + 1; END WHILE; END| +set autocommit=0; CALL update_t1(); select * from t1; id value value2 value3 @@ -33,11 +32,22 @@ id value value2 value3 18 18 18 18 19 19 19 19 20 20 20 20 +set autocommit=1; +select * from t1; +id value value2 value3 +10 10 10 10 +11 11 11 11 +12 12 5012 5012 +13 13 13 13 +14 14 14 14 +15 15 15 15 +16 16 16 16 +17 17 17 17 +18 18 18 18 +19 19 19 19 +20 20 20 20 select * from t1 force index(value) where value=12; kill query @id; ERROR 70100: Query execution was interrupted -select * from t1 where value = 12; -id value value2 value3 -12 12 12 12 drop procedure if exists update_t1; drop table if exists t1; diff --git a/mysql-test/suite/innodb/t/innodb_bug14704286.test b/mysql-test/suite/innodb/t/innodb_bug14704286.test index bdc2ab94b01..fb5e6b829a1 100644 --- a/mysql-test/suite/innodb/t/innodb_bug14704286.test +++ b/mysql-test/suite/innodb/t/innodb_bug14704286.test @@ -4,8 +4,9 @@ # create test-bed to run test # use test; - +--disable_warnings drop table if exists t1; +--enable_warnings create table t1 (id int primary key, value int, value2 int, value3 int, index(value,value2)) engine=innodb; @@ -47,9 +48,11 @@ BEGIN END| delimiter ;| - +set autocommit=0; CALL update_t1(); select * from t1; +set autocommit=1; +select * from t1; # # Now try to fire select query from connection-1 enforcing @@ -65,6 +68,10 @@ select * from t1 force index(value) where value=12; # select is going to take good time so let's kill query. # connection conn3; +let $wait_condition= + select * from information_schema.processlist where state = 'Sending data' and + info = 'select * from t1 force index(value) where value=12'; +--source include/wait_condition.inc let $ignore= `SELECT @id := $ID`; kill query @id; @@ -74,7 +81,6 @@ kill query @id; connection conn1; --error ER_QUERY_INTERRUPTED reap; -select * from t1 where value = 12; # # clean test-bed. From 500d2ebe6f3aa74daefa3dbc9d84b0cba44a620f Mon Sep 17 00:00:00 2001 From: "Krunal Bauskar krunal.bauskar@oracle.com" Date: Wed, 17 Oct 2012 14:48:19 +0530 Subject: [PATCH 04/11] removing .... will re-add using merge. for some reason initial mysql-5.1 version is not connected to mysql-5.5 --- .../suite/innodb/r/innodb_bug14704286.result | 41 --------- .../suite/innodb/t/innodb_bug14704286.test | 90 ------------------- 2 files changed, 131 deletions(-) delete mode 100644 mysql-test/suite/innodb/r/innodb_bug14704286.result delete mode 100644 mysql-test/suite/innodb/t/innodb_bug14704286.test diff --git a/mysql-test/suite/innodb/r/innodb_bug14704286.result b/mysql-test/suite/innodb/r/innodb_bug14704286.result deleted file mode 100644 index f1acbb2685e..00000000000 --- a/mysql-test/suite/innodb/r/innodb_bug14704286.result +++ /dev/null @@ -1,41 +0,0 @@ -use test; -drop table if exists t1; -create table t1 (id int primary key, value int, value2 int, -value3 int, index(value,value2)) engine=innodb; -insert into t1 values -(10,10,10,10),(11,11,11,11),(12,12,12,12),(13,13,13,13),(14,14,14,14), -(15,15,15,15),(16,16,16,16),(17,17,17,17),(18,18,18,18),(19,19,19,19), -(20,20,20,20); -use test; -start transaction with consistent snapshot; -use test; -CREATE PROCEDURE update_t1() -BEGIN -DECLARE i INT DEFAULT 1; -while (i <= 5000) DO -update test.t1 set value2=value2+1, value3=value3+1 where id=12; -SET i = i + 1; -END WHILE; -END| -CALL update_t1(); -select * from t1; -id value value2 value3 -10 10 10 10 -11 11 11 11 -12 12 5012 5012 -13 13 13 13 -14 14 14 14 -15 15 15 15 -16 16 16 16 -17 17 17 17 -18 18 18 18 -19 19 19 19 -20 20 20 20 -select * from t1 force index(value) where value=12; -kill query @id; -ERROR 70100: Query execution was interrupted -select * from t1 where value = 12; -id value value2 value3 -12 12 12 12 -drop procedure if exists update_t1; -drop table if exists t1; diff --git a/mysql-test/suite/innodb/t/innodb_bug14704286.test b/mysql-test/suite/innodb/t/innodb_bug14704286.test deleted file mode 100644 index 68a4fb62c5d..00000000000 --- a/mysql-test/suite/innodb/t/innodb_bug14704286.test +++ /dev/null @@ -1,90 +0,0 @@ ---source include/have_innodb.inc - -# -# create test-bed to run test -# -use test; ---disable_warnings -drop table if exists t1; ---enable_warnings -create table t1 (id int primary key, value int, value2 int, -value3 int, index(value,value2)) engine=innodb; - -insert into t1 values -(10,10,10,10),(11,11,11,11),(12,12,12,12),(13,13,13,13),(14,14,14,14), -(15,15,15,15),(16,16,16,16),(17,17,17,17),(18,18,18,18),(19,19,19,19), -(20,20,20,20); -let $ID= `SELECT @id := CONNECTION_ID()`; - -# -# we need multiple connections as we need to keep one connection -# active with trx requesting consistent read. -# -connect (conn1, localhost, root,,); -connect (conn2, localhost, root,,); -connect (conn3, localhost, root,,); - -# -# start trx with consistent read -# -connection conn1; -use test; - -start transaction with consistent snapshot; - -# -# update table such that secondary index is updated. -# -connection conn2; -use test; -delimiter |; -CREATE PROCEDURE update_t1() -BEGIN - DECLARE i INT DEFAULT 1; - while (i <= 5000) DO - update test.t1 set value2=value2+1, value3=value3+1 where id=12; - SET i = i + 1; - END WHILE; -END| - -delimiter ;| - -CALL update_t1(); -select * from t1; - -# -# Now try to fire select query from connection-1 enforcing -# use of secondary index. -# -connection conn1; -let $ID= `SELECT @id := CONNECTION_ID()`; -#--error ER_QUERY_INTERRUPTED ---send -select * from t1 force index(value) where value=12; - -# -# select is going to take good time so let's kill query. -# -connection conn3; -let $ignore= `SELECT @id := $ID`; -kill query @id; - -# -# reap the value of connection-1 -# -connection conn1; ---error ER_QUERY_INTERRUPTED -reap; -select * from t1 where value = 12; - -# -# clean test-bed. -# -connection default; -disconnect conn1; -disconnect conn2; -disconnect conn3; -drop procedure if exists update_t1; -drop table if exists t1; - - From 52ea152294494a387a27350887aff2d11099544e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 18 Oct 2012 17:03:06 +0300 Subject: [PATCH 05/11] Bug#14758405: ALTER TABLE: ADDING SERIAL NULL DATATYPE: ASSERTION: LEN <= SIZEOF(ULONGLONG) This bug was caught in the WL#6255 ALTER TABLE...ADD COLUMN in MySQL 5.6, but there is a bug in all InnoDB versions that support auto-increment columns. row_search_autoinc_read_column(): When reading the maximum value of the auto-increment column, and the column only contains NULL values, return 0. This corresponds to the case when the table is empty in row_search_max_autoinc(). rb:1415 approved by Sunny Bains --- storage/innobase/row/row0sel.c | 19 ++++++++++++------- storage/innodb_plugin/ChangeLog | 6 ++++++ storage/innodb_plugin/row/row0sel.c | 19 ++++++++++++------- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index c600fa62151..cf3b36fbac2 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -4660,14 +4660,18 @@ row_search_autoinc_read_column( /* TODO: We have to cast away the const of rec for now. This needs to be fixed later.*/ offsets = rec_get_offsets( - (rec_t*) rec, index, offsets, ULINT_UNDEFINED, &heap); + (rec_t*) rec, index, offsets, col_no + 1, &heap); + + if (rec_offs_nth_sql_null(offsets, col_no)) { + /* There is no non-NULL value in the auto-increment column. */ + value = 0; + goto func_exit; + } /* TODO: We have to cast away the const of rec for now. This needs to be fixed later.*/ data = rec_get_nth_field((rec_t*)rec, offsets, col_no, &len); - ut_a(len != UNIV_SQL_NULL); - switch (mtype) { case DATA_INT: ut_a(len <= sizeof value); @@ -4688,15 +4692,16 @@ row_search_autoinc_read_column( ut_error; } - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - /* We assume that the autoinc counter can't be negative. */ if (!unsigned_type && (ib_longlong) value < 0) { value = 0; } +func_exit: + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + return(value); } diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 35795e10dd4..f69f9e16904 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2012-10-18 The InnoDB Team + + * row/row0sel.c: + Fix Bug#14758405: ALTER TABLE: ADDING SERIAL NULL DATATYPE: ASSERTION: + LEN <= SIZEOF(ULONGLONG) + 2012-10-16 The InnoDB Team * dict/dict0dict.c, handler/handler0alter.cc, include/dict0dict.h: diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c index c70a477db1d..d825d799a3c 100644 --- a/storage/innodb_plugin/row/row0sel.c +++ b/storage/innodb_plugin/row/row0sel.c @@ -4833,12 +4833,16 @@ row_search_autoinc_read_column( rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, col_no + 1, &heap); + + if (rec_offs_nth_sql_null(offsets, col_no)) { + /* There is no non-NULL value in the auto-increment column. */ + value = 0; + goto func_exit; + } data = rec_get_nth_field(rec, offsets, col_no, &len); - ut_a(len != UNIV_SQL_NULL); - switch (mtype) { case DATA_INT: ut_a(len <= sizeof value); @@ -4859,14 +4863,15 @@ row_search_autoinc_read_column( ut_error; } - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - if (!unsigned_type && (ib_int64_t) value < 0) { value = 0; } +func_exit: + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + return(value); } From eef1a1957e75a4153e44be26e0e32dee5f6069ad Mon Sep 17 00:00:00 2001 From: Neeraj Bisht Date: Thu, 18 Oct 2012 23:45:15 +0530 Subject: [PATCH 06/11] Bug#13726751 - 8 BYTE MEMORY LEAK IN DO_SAVE_BLOB Problem:- When we execute a query which has subquery with GROUP BY, ORDER BY and have a BLOB column,results a memory leak. Analysis:- In case of subquery, which have GROUP BY on BLOB and a ORDER BY on other field and BLOB is not a key. We allocate a tmp buffer to copy_field to take care of BLOB value.This copy_field value can have copies of its in two join(objects), so while freeing this copy_field we have to take care that it is not deleted twice. The double deletion of tmp_table_param.copy_field is handled by two patches. One by Kostja : revid:sp1r-konstantin@mysql.com-20050627101056-55153 Fix the broken test suite in -debug build. and other by Oleksandr revid:sp1r-bell@sanja.is.com.ua-20060118114857-19905 Excluded posibility of tmp_table_param.copy_field double deletion (BUG#14851). both of this patches are commited in different branch and while merging they both get placed,but there is no need for Kostja patch as Oleksandr patch handle this. sql/sql_select.cc: Bug13726751, tmp_join clean up is not necessary as later in the code we are taking care of cleaning up of tmp_join copy_field. --- sql/sql_select.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bcf601e5142..de9f0ead7a3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7084,15 +7084,8 @@ void JOIN::cleanup(bool full) } } } - /* - We are not using tables anymore - Unlock all tables. We may be in an INSERT .... SELECT statement. - */ if (full) { - if (tmp_join) - tmp_table_param.copy_field= 0; - /* Ensure that the following delete_elements() would not be called twice for the same list. From 6ff71d0dd38e39e67580f598b400fa3fb8888da3 Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Fri, 19 Oct 2012 16:43:48 +0530 Subject: [PATCH 07/11] Bug #14226171 EXCESSIVE ROW LOCKING WITH UPDATE IN 5.5.25 When a DML statement is issued, and if the index merge access method is chosen, then many rows from the storage engine will be locked because of the way the algorithm works. Many rows will be locked, but they will not be part of the final result set. To reduce the excessive locking, the locks of unmatched rows are released by this patch. This patch will affect only transactions with isolation level equal to or less stricter than READ COMMITTED. This is because of the behaviour of ha_innobase::unlock_row(). rb://1296 approved by jorgen and olav. --- sql/opt_range.cc | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ffd66253eaa..ce87bdd5381 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8412,6 +8412,13 @@ int QUICK_INDEX_MERGE_SELECT::get_next() If a Clustered PK scan is present, it is used only to check if row satisfies its condition (and never used for row retrieval). + Locking: to ensure that exclusive locks are only set on records that + are included in the final result we must release the lock + on all rows we read but do not include in the final result. This + must be done on each index that reads the record and the lock + must be released using the same handler (the same quick object) as + used when reading the record. + RETURN 0 - Ok other - Error code if any error occurred. @@ -8421,6 +8428,12 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() { List_iterator_fast quick_it(quick_selects); QUICK_RANGE_SELECT* quick; + + /* quick that reads the given rowid first. This is needed in order + to be able to unlock the row using the same handler object that locked + it */ + QUICK_RANGE_SELECT* quick_with_last_rowid; + int error, cmp; uint last_rowid_count=0; DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::get_next"); @@ -8433,7 +8446,10 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() if (cpk_quick) { while (!error && !cpk_quick->row_in_ranges()) + { + quick->file->unlock_row(); /* row not in range; unlock */ error= quick->get_next(); + } } if (error) DBUG_RETURN(error); @@ -8441,6 +8457,7 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() quick->file->position(quick->record); memcpy(last_rowid, quick->file->ref, head->file->ref_length); last_rowid_count= 1; + quick_with_last_rowid= quick; while (last_rowid_count < quick_selects.elements) { @@ -8453,9 +8470,17 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() do { if ((error= quick->get_next())) + { + quick_with_last_rowid->file->unlock_row(); DBUG_RETURN(error); + } quick->file->position(quick->record); cmp= head->file->cmp_ref(quick->file->ref, last_rowid); + if (cmp < 0) + { + /* This row is being skipped. Release lock on it. */ + quick->file->unlock_row(); + } } while (cmp < 0); /* Ok, current select 'caught up' and returned ref >= cur_ref */ @@ -8466,13 +8491,19 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() { while (!cpk_quick->row_in_ranges()) { + quick->file->unlock_row(); /* row not in range; unlock */ if ((error= quick->get_next())) + { + quick_with_last_rowid->file->unlock_row(); DBUG_RETURN(error); + } } quick->file->position(quick->record); } memcpy(last_rowid, quick->file->ref, head->file->ref_length); + quick_with_last_rowid->file->unlock_row(); last_rowid_count= 1; + quick_with_last_rowid= quick; } else { From 4828c75af1878cc6a970bbdb29fe9da600ee8bc3 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Fri, 19 Oct 2012 20:31:22 +0200 Subject: [PATCH 08/11] Fix formatting in 'INFO_BIN' on Windows - backport. --- cmake/info_macros.cmake.in | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmake/info_macros.cmake.in b/cmake/info_macros.cmake.in index 9e08cffb2bf..9f40a419c61 100644 --- a/cmake/info_macros.cmake.in +++ b/cmake/info_macros.cmake.in @@ -1,4 +1,4 @@ -# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2012, Oracle and/or its affiliates. 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 @@ -82,9 +82,11 @@ MACRO(CREATE_INFO_BIN) FILE(WRITE ${INFO_BIN} "===== Information about the build process: =====\n") IF (WIN32) - EXECUTE_PROCESS(COMMAND cmd /c date /T OUTPUT_VARIABLE TMP_DATE) + EXECUTE_PROCESS(COMMAND cmd /c date /T + OUTPUT_VARIABLE TMP_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) ELSEIF(UNIX) - EXECUTE_PROCESS(COMMAND date "+%Y-%m-%d %H:%M:%S" OUTPUT_VARIABLE TMP_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) + EXECUTE_PROCESS(COMMAND date "+%Y-%m-%d %H:%M:%S" + OUTPUT_VARIABLE TMP_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) ELSE() SET(TMP_DATE "(no date command known for this platform)") ENDIF() From 62503f9cf5af989107e887925816add9b4aec950 Mon Sep 17 00:00:00 2001 From: Nuno Carvalho Date: Sun, 21 Oct 2012 20:28:19 +0100 Subject: [PATCH 09/11] BUG#14629727: USER_VAR_EVENT IS MISSING RANGE CHECKS Moved explicit instantiation of available_buffer and valid_buffer_range template functions to sql/log_event.cc. --- sql/log_event.cc | 16 ++++++++++++++++ sql/mysql_priv.h | 9 --------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 0ad258f7073..58de0d310d7 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -54,6 +54,22 @@ */ #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1) +/* + Explicit instantiation to unsigned int of template available_buffer + function. +*/ +template unsigned int available_buffer(const char*, + const char*, + unsigned int); + +/* + Explicit instantiation to unsigned int of template valid_buffer_range + function. +*/ +template bool valid_buffer_range(unsigned int, + const char*, + const char*, + unsigned int); #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 05a37228e17..4741562cab3 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -516,10 +516,6 @@ template T available_buffer(const char* buf_start, { return buf_len - (buf_current - buf_start); } -/* Explicit instantion to unsigned int. */ -template unsigned int available_buffer(const char*, - const char*, - unsigned int); /* Check if jump value is within buffer limits. @@ -539,11 +535,6 @@ template bool valid_buffer_range(T jump, { return (jump <= available_buffer(buf_start, buf_current, buf_len)); } -/* Explicit instantion to unsigned int. */ -template bool valid_buffer_range(unsigned int, - const char*, - const char*, - unsigned int); /* The rest of the file is included in the server only */ #ifndef MYSQL_CLIENT From d13554b1f90f7bef1d31ef66dc90eb6738a9f90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 22 Oct 2012 22:10:33 +0300 Subject: [PATCH 10/11] Backport from 5.6: Bug#14769820 ASSERT FLEN == LEN IN ALTER TABLE ... ADD UNIQUE KEY A bogus debug assertion failure occurred when reporting a duplicate key on a column prefix of a CHAR column. This is a regression from Bug#14729221 IN-PLACE ALTER TABLE REPORTS '' INSTEAD OF REAL DUPLICATE VALUE FOR PREFIX KEYS. The assertion is only present when UNIV_DEBUG is defined (which it is in debug builds starting from MySQL 5.5). It is a case of overasserting. Fix approved by Inaam Rana on IM. --- storage/innodb_plugin/handler/handler0alter.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc index 7095077b788..0422abb0021 100644 --- a/storage/innodb_plugin/handler/handler0alter.cc +++ b/storage/innodb_plugin/handler/handler0alter.cc @@ -108,13 +108,17 @@ innobase_col_to_mysql( /* These column types should never be shipped to MySQL. */ ut_ad(0); - case DATA_CHAR: case DATA_FIXBINARY: case DATA_FLOAT: case DATA_DOUBLE: case DATA_DECIMAL: /* Above are the valid column types for MySQL data. */ ut_ad(flen == len); + /* fall through */ + case DATA_CHAR: + /* We may have flen > len when there is a shorter + prefix on a CHAR column. */ + ut_ad(flen >= len); #else /* UNIV_DEBUG */ default: #endif /* UNIV_DEBUG */ From 7873a6e4d71a5fe7b8dcfb850d65c81ee7a282c5 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Tue, 23 Oct 2012 13:41:34 +0200 Subject: [PATCH 11/11] Use MESSAGE(STATUS ...) as we don't want any popup from the build system. --- cmake/mysql_version.cmake | 2 +- cmake/package_name.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake index 59ee318f47b..566d5ce416d 100644 --- a/cmake/mysql_version.cmake +++ b/cmake/mysql_version.cmake @@ -54,7 +54,7 @@ MACRO(GET_MYSQL_VERSION) ENDIF() SET(VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}${EXTRA_VERSION}") - MESSAGE("-- MySQL ${VERSION}") + MESSAGE(STATUS "MySQL ${VERSION}") SET(MYSQL_BASE_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}" CACHE INTERNAL "MySQL Base version") SET(MYSQL_NO_DASH_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}") # Use NDBVERSION irregardless of whether this is Cluster or not, if not diff --git a/cmake/package_name.cmake b/cmake/package_name.cmake index d9e0902c921..43ad794e77b 100644 --- a/cmake/package_name.cmake +++ b/cmake/package_name.cmake @@ -123,7 +123,7 @@ IF(NOT VERSION) SET(package_name "mysql${PRODUCT_TAG}-${VERSION}-${SYSTEM_NAME_AND_PROCESSOR}") ENDIF() - MESSAGE("-- Packaging as: ${package_name}") + MESSAGE(STATUS "Packaging as: ${package_name}") # Sometimes package suffix is added (something like "-icc-glibc23") IF(PACKAGE_SUFFIX)