diff --git a/configure.in b/configure.in index efd291f953c..3ec62b836f1 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ dnl dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MySQL Server], [5.1.50], [], [mysql]) +AC_INIT([MySQL Server], [5.1.51], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 766f3b6bfaa..ae48eb1e0ff 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -995,6 +995,7 @@ SELECT 1 FROM 1 1 DROP TABLE t1; +End of 5.0 tests # # Bug #52397: another crash with explain extended and group_concat # @@ -1010,4 +1011,22 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1003 select 1 AS `1` from (select group_concat(`test`.`t1`.`a` order by `test`.`t1`.`a` ASC separator ',') AS `GROUP_CONCAT(t1.a ORDER BY t1.a ASC)` from `test`.`t1` `t2` join `test`.`t1` group by `test`.`t1`.`a`) `d` DROP TABLE t1; -End of 5.0 tests +# +# Bug #54476: crash when group_concat and 'with rollup' in prepared statements +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); +PREPARE stmt FROM "SELECT GROUP_CONCAT(t1.a ORDER BY t1.a) FROM t1 JOIN t1 t2 GROUP BY t1.a WITH ROLLUP"; +EXECUTE stmt; +GROUP_CONCAT(t1.a ORDER BY t1.a) +1,1 +2,2 +1,1,2,2 +EXECUTE stmt; +GROUP_CONCAT(t1.a ORDER BY t1.a) +1,1 +2,2 +1,1,2,2 +DEALLOCATE PREPARE stmt; +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 81dddd0f648..eee56ae7461 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -336,4 +336,19 @@ End of 5.0 tests select connection_id() > 0; connection_id() > 0 1 +# +# Bug #54461: crash with longblob and union or update with subquery +# +CREATE TABLE t1 (a INT, b LONGBLOB); +INSERT INTO t1 VALUES (1, '2'), (2, '3'), (3, '2'); +SELECT DISTINCT LEAST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1; +LEAST(a, (SELECT b FROM t1 LIMIT 1)) +1 +2 +SELECT DISTINCT GREATEST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1; +GREATEST(a, (SELECT b FROM t1 LIMIT 1)) +2 +3 +1 +DROP TABLE t1; End of tests diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index 247f461c760..23619b91fbc 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -2500,6 +2500,14 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range f2,f4 f4 1 NULL 11 Using where DROP TABLE t1; # +# Bug#54117 crash in thr_multi_unlock, temporary table +# +CREATE TEMPORARY TABLE t1(a INT) ENGINE = InnoDB; +LOCK TABLES t1 READ; +ALTER TABLE t1 COMMENT 'test'; +UNLOCK TABLES; +DROP TABLE t1; +# # Bug#55580: segfault in read_view_sees_trx_id # CREATE TABLE t1 (a INT) ENGINE=Innodb; diff --git a/mysql-test/suite/innodb/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test index 25e834cf3f8..d633cb2222e 100644 --- a/mysql-test/suite/innodb/t/innodb_mysql.test +++ b/mysql-test/suite/innodb/t/innodb_mysql.test @@ -733,6 +733,20 @@ ORDER BY f1 DESC LIMIT 5; DROP TABLE t1; + +--echo # +--echo # Bug#54117 crash in thr_multi_unlock, temporary table +--echo # + +CREATE TEMPORARY TABLE t1(a INT) ENGINE = InnoDB; + +LOCK TABLES t1 READ; +ALTER TABLE t1 COMMENT 'test'; +UNLOCK TABLES; + +DROP TABLE t1; + + --echo # --echo # Bug#55580: segfault in read_view_sees_trx_id --echo # diff --git a/mysql-test/suite/rpl/r/rpl_drop.result b/mysql-test/suite/rpl/r/rpl_drop.result index b83594c9bb1..5ebbc4f9ce7 100644 --- a/mysql-test/suite/rpl/r/rpl_drop.result +++ b/mysql-test/suite/rpl/r/rpl_drop.result @@ -8,3 +8,27 @@ drop table if exists t1, t2; create table t1 (a int); drop table t1, t2; ERROR 42S02: Unknown table 't2' +include/stop_slave.inc +SET @old_binlog_format= @@global.binlog_format; +SET GLOBAL binlog_format = ROW; +include/start_slave.inc +SET @old_binlog_format= @@global.binlog_format; +SET binlog_format = ROW; +CREATE TABLE t2(a INT) ENGINE=MYISAM; +CREATE TABLE t3(a INT) ENGINE=INNODB; +CREATE FUNCTION f1() RETURNS INT +BEGIN +insert into t2 values(1); +insert into t3 values(1); +return 1; +END| +CREATE TABLE t1(UNIQUE(a)) ENGINE=MYISAM SELECT 1 AS a UNION ALL SELECT f1(); +ERROR 23000: Duplicate entry '1' for key 'a' +CREATE TABLE t1(UNIQUE(a)) ENGINE=INNODB SELECT 1 AS a UNION ALL SELECT f1(); +ERROR 23000: Duplicate entry '1' for key 'a' +show binlog events in 'master-bin.000001' from ; +Log_name Pos Event_type Server_id End_log_pos Info +DROP FUNCTION f1; +DROP TABLE t2, t3; +SET @@global.binlog_format= @old_binlog_format; +SET @@global.binlog_format= @old_binlog_format; diff --git a/mysql-test/suite/rpl/t/rpl_drop.test b/mysql-test/suite/rpl/t/rpl_drop.test index b38007a755f..336edad6fc5 100644 --- a/mysql-test/suite/rpl/t/rpl_drop.test +++ b/mysql-test/suite/rpl/t/rpl_drop.test @@ -1,6 +1,7 @@ # Testcase for BUG#4552 (DROP on two tables, one of which does not # exist, must be binlogged with a non-zero error code) source include/master-slave.inc; +source include/have_innodb.inc; --disable_warnings drop table if exists t1, t2; --enable_warnings @@ -10,7 +11,57 @@ drop table t1, t2; save_master_pos; connection slave; sync_with_master; - # End of 4.1 tests +# BUG#55625 RBR breaks on failing 'CREATE TABLE' +# A CREATE...SELECT that fails is written to the binary log if a non-transactional +# statement is updated. If the logging format is ROW, the CREATE statement and the +# changes are written to the binary log as distinct events and by consequence the +# created table is not rolled back in the slave. +# To fix the problem, we do not write a CREATE...SELECT that fails to the binary +# log. Howerver, the changes to non-transactional tables are not replicated and +# thus the slave goes out of sync. This should be fixed after BUG#47899. +# +# In the test case, we verify if the binary log contains no information for a +# CREATE...SELECT that fails. +connection slave; +--source include/stop_slave.inc +SET @old_binlog_format= @@global.binlog_format; +SET GLOBAL binlog_format = ROW; +--source include/start_slave.inc + +connection master; +SET @old_binlog_format= @@global.binlog_format; +SET binlog_format = ROW; + +CREATE TABLE t2(a INT) ENGINE=MYISAM; +CREATE TABLE t3(a INT) ENGINE=INNODB; + +delimiter |; +CREATE FUNCTION f1() RETURNS INT +BEGIN + insert into t2 values(1); + insert into t3 values(1); + return 1; +END| +delimiter ;| + +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +let $binlog_file= query_get_value("SHOW MASTER STATUS", File, 1); + +--error 1062 +CREATE TABLE t1(UNIQUE(a)) ENGINE=MYISAM SELECT 1 AS a UNION ALL SELECT f1(); +--error 1062 +CREATE TABLE t1(UNIQUE(a)) ENGINE=INNODB SELECT 1 AS a UNION ALL SELECT f1(); + +--source include/show_binlog_events.inc + +DROP FUNCTION f1; +DROP TABLE t2, t3; +SET @@global.binlog_format= @old_binlog_format; + +--sync_slave_with_master +SET @@global.binlog_format= @old_binlog_format; + +# End of 5.1 tests diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index e832ea316eb..926c1f92855 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -708,6 +708,7 @@ SELECT 1 FROM DROP TABLE t1; +--echo End of 5.0 tests --echo # --echo # Bug #52397: another crash with explain extended and group_concat @@ -719,5 +720,18 @@ EXPLAIN EXTENDED SELECT 1 FROM t1 t2, t1 GROUP BY t1.a) AS d; DROP TABLE t1; +--echo # +--echo # Bug #54476: crash when group_concat and 'with rollup' in prepared statements +--echo # ---echo End of 5.0 tests +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); + +PREPARE stmt FROM "SELECT GROUP_CONCAT(t1.a ORDER BY t1.a) FROM t1 JOIN t1 t2 GROUP BY t1.a WITH ROLLUP"; +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 6590b43f2dc..c6b5ffd5a3f 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -467,4 +467,16 @@ select NAME_CONST('_id',1234) as id; select connection_id() > 0; +--echo # +--echo # Bug #54461: crash with longblob and union or update with subquery +--echo # + +CREATE TABLE t1 (a INT, b LONGBLOB); +INSERT INTO t1 VALUES (1, '2'), (2, '3'), (3, '2'); + +SELECT DISTINCT LEAST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1; +SELECT DISTINCT GREATEST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1; + +DROP TABLE t1; + --echo End of tests diff --git a/sql/item_func.cc b/sql/item_func.cc index 1bec4700bff..1b13297c951 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2243,6 +2243,8 @@ void Item_func_min_max::fix_length_and_dec() max_length= my_decimal_precision_to_length_no_truncation(max_int_part + decimals, decimals, unsigned_flag); + else if (cmp_type == REAL_RESULT) + max_length= float_length(decimals); cached_field_type= agg_field_type(args, arg_count); } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index f92bde9ce87..25b3bd5d91d 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3035,7 +3035,6 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, tree(item->tree), unique_filter(item->unique_filter), table(item->table), - order(item->order), context(item->context), arg_count_order(item->arg_count_order), arg_count_field(item->arg_count_field), @@ -3048,6 +3047,24 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, { quick_group= item->quick_group; result.set_charset(collation.collation); + + /* + Since the ORDER structures pointed to by the elements of the 'order' array + may be modified in find_order_in_list() called from + Item_func_group_concat::setup(), create a copy of those structures so that + such modifications done in this object would not have any effect on the + object being copied. + */ + ORDER *tmp; + if (!(order= (ORDER **) thd->alloc(sizeof(ORDER *) * arg_count_order + + sizeof(ORDER) * arg_count_order))) + return; + tmp= (ORDER *)(order + arg_count_order); + for (uint i= 0; i < arg_count_order; i++, tmp++) + { + memcpy(tmp, item->order[i], sizeof(ORDER)); + order[i]= tmp; + } } diff --git a/sql/log.cc b/sql/log.cc index 614a07e6b63..3f41bf1c929 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1628,6 +1628,19 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) DBUG_RETURN(error); } +/** + Cleanup the cache. + + @param thd The client thread that wants to clean up the cache. +*/ +void MYSQL_BIN_LOG::reset_gathered_updates(THD *thd) +{ + binlog_trx_data *const trx_data= + (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); + + trx_data->reset(); +} + void MYSQL_BIN_LOG::set_write_error(THD *thd) { DBUG_ENTER("MYSQL_BIN_LOG::set_write_error"); diff --git a/sql/log.h b/sql/log.h index 8d3880d9171..8f1ed7ee90c 100644 --- a/sql/log.h +++ b/sql/log.h @@ -356,10 +356,11 @@ public: /* Use this to start writing a new log file */ void new_file(); + void reset_gathered_updates(THD *thd); bool write(Log_event* event_info); // binary log write bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident); - bool write_incident(THD *thd, bool lock); + bool write_incident(THD *thd, bool lock); int write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync); void set_write_error(THD *thd); bool check_write_error(THD *thd); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 8604f876f37..567c7ff2b30 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3972,6 +3972,17 @@ void select_create::abort() if (table) { + if (thd->lex->sql_command == SQLCOM_CREATE_TABLE && + thd->current_stmt_binlog_row_based && + !(thd->lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && + mysql_bin_log.is_open()) + { + /* + This should be removed after BUG#47899. + */ + mysql_bin_log.reset_gathered_updates(thd); + } + table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); if (!create_info->table_existed) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f765e5c5cae..d3ac2bf0f95 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7393,6 +7393,11 @@ view_err: mysql_unlock_tables(thd, thd->lock); thd->lock=0; } + /* + If LOCK TABLES list is not empty and contains this table, + unlock the table and remove the table from this list. + */ + mysql_lock_remove(thd, thd->locked_tables, table, FALSE); /* Remove link to old table and rename the new one */ close_temporary_table(thd, table, 1, 1); /* Should pass the 'new_name' as we store table name in the cache */ diff --git a/sql/table.h b/sql/table.h index 8ea7175eec4..bbb39aae6f7 100644 --- a/sql/table.h +++ b/sql/table.h @@ -55,7 +55,6 @@ typedef struct st_order { struct st_order *next; Item **item; /* Point at item in select fields */ Item *item_ptr; /* Storage for initial item */ - Item **item_copy; /* For SPs; the original item ptr */ int counter; /* position in SELECT list, correct only if counter_used is true*/ bool asc; /* true if ascending */