diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 9643478b96b..c6d2db89ccd 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1997,5 +1997,39 @@ CREATE TABLE t1(id INT,KEY(id)) ENGINE=MYISAM PARTITION BY HASH(id) PARTITIONS 2; DROP TABLE t1; SET SESSION SQL_MODE=DEFAULT; + +Bug#40281: partitioning the general log table crashes the server + +--- set up partitioned log, and switch to it +USE mysql; +SET GLOBAL general_log =0; +CREATE TABLE gl_partitioned LIKE general_log; +ALTER TABLE gl_partitioned ENGINE=myisam; +ALTER TABLE gl_partitioned PARTITION BY HASH (thread_id) PARTITIONS 10; +ALTER TABLE general_log RENAME TO gl_nonpartitioned; +ALTER TABLE gl_partitioned RENAME TO general_log; +SELECT @@global.log_output INTO @old_glo; +SET GLOBAL log_output='table'; +SET GLOBAL general_log =1; +--- do some things to be logged to partitioned log, should fail +USE /* 1 */ test; +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1); +SELECT * FROM t1; +i +1 +USE mysql; +SET GLOBAL general_log =0; +ALTER TABLE general_log RENAME TO gl_partitioned; +ALTER TABLE gl_nonpartitioned RENAME TO general_log; +--- show whether we actually logged anything (no) to general_log +SELECT COUNT(argument) FROM gl_partitioned; +COUNT(argument) +0 +DROP TABLE gl_partitioned; +SET GLOBAL log_output=@old_glo; +SET GLOBAL general_log =1; +USE /* 2 */ test; +DROP TABLE t1; End of 5.1 tests SET @@global.general_log= @old_general_log; diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 18bcf84407b..54687c94466 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1998,6 +1998,53 @@ CREATE TABLE t1(id INT,KEY(id)) ENGINE=MYISAM DROP TABLE t1; SET SESSION SQL_MODE=DEFAULT; +--echo +--echo Bug#40281: partitioning the general log table crashes the server +--echo + +--echo --- set up partitioned log, and switch to it + +USE mysql; +SET GLOBAL general_log =0; +CREATE TABLE gl_partitioned LIKE general_log; +ALTER TABLE gl_partitioned ENGINE=myisam; +ALTER TABLE gl_partitioned PARTITION BY HASH (thread_id) PARTITIONS 10; +ALTER TABLE general_log RENAME TO gl_nonpartitioned; +ALTER TABLE gl_partitioned RENAME TO general_log; + +SELECT @@global.log_output INTO @old_glo; +SET GLOBAL log_output='table'; +SET GLOBAL general_log =1; + +--echo --- do some things to be logged to partitioned log, should fail +USE /* 1 */ test; + +CREATE TABLE t1 (i INT); + +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,); +connection master; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1; +disconnect master; + +connection default; + +USE mysql; +SET GLOBAL general_log =0; +ALTER TABLE general_log RENAME TO gl_partitioned; +ALTER TABLE gl_nonpartitioned RENAME TO general_log; + +--echo --- show whether we actually logged anything (no) to general_log +SELECT COUNT(argument) FROM gl_partitioned; + +DROP TABLE gl_partitioned; + +SET GLOBAL log_output=@old_glo; +SET GLOBAL general_log =1; + +USE /* 2 */ test; +DROP TABLE t1; + --echo End of 5.1 tests SET @@global.general_log= @old_general_log; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 06fb9e32e35..562716a7db7 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5414,6 +5414,13 @@ int ha_partition::extra(enum ha_extra_function operation) /* Currently only NDB use the *_CANNOT_BATCH */ break; } + /* + http://dev.mysql.com/doc/refman/5.1/en/partitioning-limitations.html + says we no longer support logging to partitioned tables, so we fail + here. + */ + case HA_EXTRA_MARK_AS_LOG_TABLE: + DBUG_RETURN(ER_UNSUPORTED_LOG_ENGINE); default: { /* Temporary crash to discover what is wrong */ diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 284eaebbe87..a181a6b3f13 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -3824,8 +3824,13 @@ bool mysql_unpack_partition(THD *thd, Item_field objects. This is not a nice solution since if the parser uses current_select for anything else it will corrupt the current LEX object. + Also, we need to make sure there even is a select -- if the statement + was a "USE ...", current_select will be NULL, but we may still end up + here if we try to log to a partitioned table. This is currently + unsupported, but should still fail rather than crash! */ - thd->lex->current_select= old_lex->current_select; + if (!(thd->lex->current_select= old_lex->current_select)) + goto end; /* All Items created is put into a free list on the THD object. This list is used to free all Item objects after completing a query. We don't