summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2017-01-17 13:09:04 +0100
committerOleksandr Byelkin <sanja@mariadb.com>2017-09-04 16:45:02 +0200
commit17589989eec9cf4e9f7084505710a42929efe115 (patch)
tree8b4d2564d65bdc7656ec741aa7b6b5237d2b5387
parentbe45f083e6e7d8da6dbf2349d9c59673d7e61139 (diff)
downloadmariadb-git-17589989eec9cf4e9f7084505710a42929efe115.tar.gz
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))
-rw-r--r--mysql-test/r/sp.result28
-rw-r--r--mysql-test/t/sp.test31
-rw-r--r--sql/sp.cc1
-rw-r--r--sql/sp_head.cc20
-rw-r--r--sql/sp_head.h3
5 files changed, 82 insertions, 1 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index d9b5dfd5a1f..c6867d46489 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -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
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 6eba2522089..99020eb951f 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -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
diff --git a/sql/sp.cc b/sql/sp.cc
index 2e268e483e7..5a64c28865e 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -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();
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index bf25d45ffaf..ae274ee8714 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -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)
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 604190079cb..5d3697daa16 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -232,6 +232,7 @@ private:
*/
uint32 unsafe_flags;
+ uint m_select_number;
public:
inline Stored_program_creation_ctx *get_creation_ctx()
{
@@ -521,6 +522,8 @@ public:
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