Skip to content

Commit

Permalink
MDEV-10972: Insert from select / view / union -- repeatable crash in …
Browse files Browse the repository at this point in the history
…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))
  • Loading branch information
sanja-byelkin committed Sep 4, 2017
1 parent be45f08 commit 1758998
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 1 deletion.
28 changes: 28 additions & 0 deletions mysql-test/r/sp.result
Original file line number Diff line number Diff line change
Expand Up @@ -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
31 changes: 31 additions & 0 deletions mysql-test/t/sp.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions sql/sp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
20 changes: 19 additions & 1 deletion sql/sp_head.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions sql/sp_head.h
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 1758998

Please sign in to comment.