diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 496d566a5ee..290d264174e 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -675,3 +675,9 @@ a 10 drop table t1; deallocate prepare stmt; +create table t1 (id int); +prepare stmt from "insert into t1 (id) select id from t1 union select id from t1"; +execute stmt; +execute stmt; +deallocate prepare stmt; +drop table t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 60b77576572..415185d825b 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -693,3 +693,15 @@ execute stmt using @offset, @limit, @offset, @limit, @limit; drop table t1; deallocate prepare stmt; + +# +# Bug#11060 "Server crashes on calling stored procedure with INSERT SELECT +# UNION SELECT" aka "Server crashes on re-execution of prepared INSERT ... +# SELECT with UNION". +# +create table t1 (id int); +prepare stmt from "insert into t1 (id) select id from t1 union select id from t1"; +execute stmt; +execute stmt; +deallocate prepare stmt; +drop table t1; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a963af4c6e3..ac0067282dc 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1988,10 +1988,22 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par, int select_insert::prepare(List &values, SELECT_LEX_UNIT *u) { + int res; + LEX *lex= thd->lex; + SELECT_LEX *lex_current_select_save= lex->current_select; DBUG_ENTER("select_insert::prepare"); unit= u; - if (check_insert_fields(thd, table_list, *fields, values, !insert_into_view)) + /* + Since table in which we are going to insert is added to the first + select, LEX::current_select should point to the first select while + we are fixing fields from insert list. + */ + lex->current_select= &lex->select_lex; + res= check_insert_fields(thd, table_list, *fields, values, + !insert_into_view); + lex->current_select= lex_current_select_save; + if (res) DBUG_RETURN(1); /* if it is INSERT into join view then check_insert_fields already found @@ -2003,12 +2015,12 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) Is table which we are changing used somewhere in other parts of query */ - if (!(thd->lex->current_select->options & OPTION_BUFFER_RESULT) && + if (!(lex->current_select->options & OPTION_BUFFER_RESULT) && unique_table(table_list, table_list->next_global)) { /* Using same table for INSERT and SELECT */ - thd->lex->current_select->options|= OPTION_BUFFER_RESULT; - thd->lex->current_select->join->select_options|= OPTION_BUFFER_RESULT; + lex->current_select->options|= OPTION_BUFFER_RESULT; + lex->current_select->join->select_options|= OPTION_BUFFER_RESULT; } else {