Commit 17589989 authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

MDEV-10972: Insert from select / view / union -- repeatable crash in 10.1, 10.2 Linux/Mac/Windows

save thd->select_number between parsing and executions (in case it was not complete executed due to errors (for example epsent table))
parent be45f083
......@@ -8079,4 +8079,32 @@ CALL sp1();
CALL sp1();
drop user 'foo'@'%';
drop procedure sp1;
#
# MDEV-10972: Insert from select / view / union --
# repeatable crash in 10.1, 10.2 Linux/Mac/Windows
#
create table t (id int auto_increment primary key);
insert into t values (9494),(9495),(9496),(9497),(9498),(9499),(9500),(9501),(9502),(9503);
create VIEW v AS
select id from t
union
select id from t
;
drop procedure if exists p;
Warnings:
Note 1305 PROCEDURE test.p does not exist
create procedure p()
insert into tmp_t select t.id from (
select id from v
union
select id from v
) sq
inner join t on (sq.id = t.id);
CALL p();
ERROR 42S02: Table 'test.tmp_t' doesn't exist
create table tmp_t (id int null);
CALL p();
drop procedure p;
drop view v;
drop table t, tmp_t;
#End of 10.1 tests
......@@ -9556,5 +9556,36 @@ CALL sp1();
drop user 'foo'@'%';
drop procedure sp1;
--echo #
--echo # MDEV-10972: Insert from select / view / union --
--echo # repeatable crash in 10.1, 10.2 Linux/Mac/Windows
--echo #
create table t (id int auto_increment primary key);
insert into t values (9494),(9495),(9496),(9497),(9498),(9499),(9500),(9501),(9502),(9503);
create VIEW v AS
select id from t
union
select id from t
;
drop procedure if exists p;
create procedure p()
insert into tmp_t select t.id from (
select id from v
union
select id from v
) sq
inner join t on (sq.id = t.id);
--error ER_NO_SUCH_TABLE
CALL p();
create table tmp_t (id int null);
CALL p();
drop procedure p;
drop view v;
drop table t, tmp_t;
--echo #End of 10.1 tests
......@@ -760,6 +760,7 @@ static sp_head *sp_compile(THD *thd, String *defstr, ulonglong sql_mode,
else
{
sp= thd->lex->sphead;
sp->set_select_number(thd->select_number);
}
thd->pop_internal_handler();
......
......@@ -598,7 +598,7 @@ sp_head::sp_head()
m_flags(0),
m_sp_cache_version(0),
m_creation_ctx(0),
unsafe_flags(0),
unsafe_flags(0), m_select_number(1),
m_recursion_level(0),
m_next_cached_sp(0),
m_cont_level(0)
......@@ -2100,8 +2100,26 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (!err_status)
{
/*
Normally the counter is not reset between parsing and first execution,
but it is possible in case of error to have parsing on one CALL and
first execution (where VIEW will be parsed and added). So we store the
counter after parsing and restore it before execution just to avoid
repeating SELECT numbers.
*/
thd->select_number= m_select_number;
err_status= execute(thd, TRUE);
DBUG_PRINT("info", ("execute returned %d", (int) err_status));
/*
This execution of the SP was aborted with an error (e.g. "Table not
found"). However it might still have consumed some numbers from the
thd->select_number counter. The next sp->exec() call must not use the
consumed numbers, so we remember the first free number (We know that
nobody will use it as this execution has stopped with an error).
*/
if (err_status)
set_select_number(thd->select_number);
}
if (save_log_general)
......
......@@ -232,6 +232,7 @@ class sp_head :private Query_arena
*/
uint32 unsafe_flags;
uint m_select_number;
public:
inline Stored_program_creation_ctx *get_creation_ctx()
{
......@@ -521,6 +522,8 @@ class sp_head :private Query_arena
sp_pcontext *get_parse_context() { return m_pcont; }
void set_select_number(uint num) { m_select_number= num; }
private:
MEM_ROOT *m_thd_root; ///< Temp. store for thd's mem_root
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment