diff --git a/CMakeLists.txt b/CMakeLists.txt index e4dc16040a7..8aacfe8e382 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR) +CMAKE_MINIMUM_REQUIRED(VERSION 2.6 FATAL_ERROR) PROJECT(MySql) diff --git a/include/config-win.h b/include/config-win.h index 3a21551ebbb..ce8c0fd17ee 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -17,15 +17,6 @@ #define BIG_TABLES -#ifdef __WIN2000__ -/* We have to do this define before including windows.h to get the AWE API -functions */ -#define _WIN32_WINNT 0x0500 -#else -/* Get NT 4.0 functions */ -#define _WIN32_WINNT 0x0400 -#endif - #if defined(_MSC_VER) && _MSC_VER >= 1400 /* Avoid endless warnings about sprintf() etc. being unsafe. */ #define _CRT_SECURE_NO_DEPRECATE 1 diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index bf9108459d7..934085ab796 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -2141,4 +2141,24 @@ SELECT * FROM m1; c1 DROP TABLE m1; DROP TABLE t1; +# +# Bug45781 infinite hang/crash in "opening tables" after handler tries to +# open merge table +# +DROP TABLE IF EXISTS m1,t1; +CREATE TABLE t1(a int)engine=myisam; +CREATE TABLE t2(a int)engine=myisam; +CREATE TABLE t3(a int)engine=myisam; +CREATE TABLE t4(a int)engine=myisam; +CREATE TABLE t5(a int)engine=myisam; +CREATE TABLE t6(a int)engine=myisam; +CREATE TABLE t7(a int)engine=myisam; +CREATE TABLE m1(a int)engine=merge union=(t1,t2,t3,t4,t5,t6,t7); +SELECT 1 FROM m1; +1 +HANDLER m1 OPEN; +ERROR HY000: Table storage engine for 'm1' doesn't have this option +DROP TABLE m1,t1,t2,t3,t4,t5,t6,t7; +SELECT 1 FROM m1; +ERROR 42S02: Table 'test.m1' doesn't exist End of 5.1 tests diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 8760876b7ee..0d90468fc8d 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -1555,4 +1555,28 @@ SELECT * FROM m1; DROP TABLE m1; DROP TABLE t1; +--echo # +--echo # Bug45781 infinite hang/crash in "opening tables" after handler tries to +--echo # open merge table +--echo # + +--disable_warnings +DROP TABLE IF EXISTS m1,t1; +--enable_warnings + +CREATE TABLE t1(a int)engine=myisam; +CREATE TABLE t2(a int)engine=myisam; +CREATE TABLE t3(a int)engine=myisam; +CREATE TABLE t4(a int)engine=myisam; +CREATE TABLE t5(a int)engine=myisam; +CREATE TABLE t6(a int)engine=myisam; +CREATE TABLE t7(a int)engine=myisam; +CREATE TABLE m1(a int)engine=merge union=(t1,t2,t3,t4,t5,t6,t7); +SELECT 1 FROM m1; +--error ER_ILLEGAL_HA +HANDLER m1 OPEN; +DROP TABLE m1,t1,t2,t3,t4,t5,t6,t7; +--error ER_NO_SUCH_TABLE +SELECT 1 FROM m1; # Should not hang! + --echo End of 5.1 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 88e1620b152..b81070000b3 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7375,7 +7375,13 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, /* make * substituting permanent */ SELECT_LEX *select_lex= thd->lex->current_select; select_lex->with_wild= 0; - select_lex->item_list= fields; + /* + The assignment below is translated to memcpy() call (at least on some + platforms). memcpy() expects that source and destination areas do not + overlap. That problem was detected by valgrind. + */ + if (&select_lex->item_list != &fields) + select_lex->item_list= fields; thd->restore_active_arena(arena, &backup); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 16810e29343..1e92d95573a 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -252,14 +252,37 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) /* for now HANDLER can be used only for real TABLES */ tables->required_type= FRMTYPE_TABLE; + /* + We use open_tables() here, rather than, say, + open_ltable() or open_table() because we would like to be able + to open a temporary table. + */ error= open_tables(thd, &tables, &counter, 0); - /* restore the state and merge the opened table into handler_tables list */ if (thd->open_tables) { - thd->open_tables->next= thd->handler_tables; - thd->handler_tables= thd->open_tables; + if (thd->open_tables->next) + { + /* + We opened something that is more than a single table. + This happens with MERGE engine. Don't try to link + this mess into thd->handler_tables list, close it + and report an error. We must do it right away + because mysql_ha_close_table(), called down the road, + can close a single table only. + */ + close_thread_tables(thd); + my_error(ER_ILLEGAL_HA, MYF(0), tables->alias); + error= 1; + } + else + { + /* Merge the opened table into handler_tables list. */ + thd->open_tables->next= thd->handler_tables; + thd->handler_tables= thd->open_tables; + } } + /* Restore the state. */ thd->open_tables= backup_open_tables; if (error) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 401745bd9b8..28909bbb911 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1807,7 +1807,8 @@ JOIN::exec() curr_join->having= curr_join->tmp_having= 0; // Allready done /* Change sum_fields reference to calculated fields in tmp_table */ - curr_join->all_fields= *curr_all_fields; + if (curr_join != this) + curr_join->all_fields= *curr_all_fields; if (!items1) { items1= items0 + all_fields.elements; @@ -1826,8 +1827,11 @@ JOIN::exec() fields_list.elements, all_fields)) DBUG_VOID_RETURN; } - curr_join->tmp_all_fields1= tmp_all_fields1; - curr_join->tmp_fields_list1= tmp_fields_list1; + if (curr_join != this) + { + curr_join->tmp_all_fields1= tmp_all_fields1; + curr_join->tmp_fields_list1= tmp_fields_list1; + } curr_join->items1= items1; } curr_all_fields= &tmp_all_fields1; @@ -1975,8 +1979,11 @@ JOIN::exec() tmp_fields_list2, tmp_all_fields2, fields_list.elements, tmp_all_fields1)) DBUG_VOID_RETURN; - curr_join->tmp_fields_list2= tmp_fields_list2; - curr_join->tmp_all_fields2= tmp_all_fields2; + if (curr_join != this) + { + curr_join->tmp_fields_list2= tmp_fields_list2; + curr_join->tmp_all_fields2= tmp_all_fields2; + } } curr_fields_list= &curr_join->tmp_fields_list2; curr_all_fields= &curr_join->tmp_all_fields2; @@ -2031,8 +2038,11 @@ JOIN::exec() tmp_table_param.save_copy_field= curr_join->tmp_table_param.copy_field; tmp_table_param.save_copy_field_end= curr_join->tmp_table_param.copy_field_end; - curr_join->tmp_all_fields3= tmp_all_fields3; - curr_join->tmp_fields_list3= tmp_fields_list3; + if (curr_join != this) + { + curr_join->tmp_all_fields3= tmp_all_fields3; + curr_join->tmp_fields_list3= tmp_fields_list3; + } } else { diff --git a/sql/sql_select.h b/sql/sql_select.h index 353c2b1d610..a0366d47149 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -466,7 +466,8 @@ public: group_optimized_away= 0; all_fields= fields_arg; - fields_list= fields_arg; + if (&fields_list != &fields_arg) /* Avoid valgrind-warning */ + fields_list= fields_arg; bzero((char*) &keyuse,sizeof(keyuse)); tmp_table_param.init(); tmp_table_param.end_write_records= HA_POS_ERROR; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 7d6a7ade540..ffb9b6d001a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -47,6 +47,12 @@ #include #include +/* this is to get the bison compilation windows warnings out */ +#ifdef _MSC_VER +/* warning C4065: switch statement contains 'default' but no 'case' labels */ +#pragma warning (disable : 4065) +#endif + int yylex(void *yylval, void *yythd); const LEX_STRING null_lex_str= {0,0};