summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2017-11-06 14:35:58 +0100
committerOleksandr Byelkin <sanja@mariadb.com>2017-11-13 14:31:49 +0100
commitefc18ad7d290a2b767f4f9e3d35905f3d236ecd0 (patch)
tree97f8b369bddada5618f449afd7c78951a2b75c5b
parent1fdf11669c1295bb49f50d1aaefec2d93bb24191 (diff)
downloadmariadb-git-efc18ad7d290a2b767f4f9e3d35905f3d236ecd0.tar.gz
MDEV-13936: Server crashes in Time_and_counter_tracker::incr_loopsbb-10.1-MDEV-13936
Repeat reworked solution of procedures for all posible Sp (functions & triggers).
-rw-r--r--mysql-test/r/sp.result12
-rw-r--r--mysql-test/r/trigger.result17
-rw-r--r--mysql-test/t/sp.test17
-rw-r--r--mysql-test/t/trigger.test24
-rw-r--r--sql/sp_head.cc42
5 files changed, 93 insertions, 19 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index c6867d46489..9b0ace5c002 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -8107,4 +8107,16 @@ CALL p();
drop procedure p;
drop view v;
drop table t, tmp_t;
+#
+# MDEV-13936: Server crashes in Time_and_counter_tracker::incr_loops
+#
+CREATE TABLE t1 (i INT);
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE RAND() > 0.5;
+CREATE FUNCTION f1() RETURNS INT RETURN ( SELECT MAX(i) FROM v1 );
+REPLACE INTO v1 VALUES (f1());
+ERROR HY000: The target table v1 of the INSERT is not insertable-into
+SET @aux = f1();
+DROP FUNCTION f1;
+DROP VIEW v1;
+DROP TABLE t1;
#End of 10.1 tests
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 86219875bed..8455450e294 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -2290,3 +2290,20 @@ INSERT INTO t1 VALUES ('a');
ERROR 22001: Data too long for column 'c' at row 1
DROP TRIGGER t1_bi;
DROP TABLE t1;
+#
+# MDEV-13936: Server crashes in Time_and_counter_tracker::incr_loops
+#
+CREATE TABLE t1 (i INT);
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE RAND() > 0.5;
+CREATE TABLE t2 (a int);
+CREATE TABLE t3 (a int);
+create trigger trg after insert on t2 for each row
+INSERT INTO t3 SELECT MAX(i) FROM v1 UNION SELECT MAX(i) FROM v1;
+drop table t1;
+insert into t2 value (2);
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE TABLE t1 (i INT);
+insert into t2 value (2);
+DROP VIEW v1;
+DROP TABLE t1,t2,t3;
+End of 10.1 tests.
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 99020eb951f..7453cec8f21 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -9588,4 +9588,21 @@ drop procedure p;
drop view v;
drop table t, tmp_t;
+
+--echo #
+--echo # MDEV-13936: Server crashes in Time_and_counter_tracker::incr_loops
+--echo #
+CREATE TABLE t1 (i INT);
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE RAND() > 0.5;
+CREATE FUNCTION f1() RETURNS INT RETURN ( SELECT MAX(i) FROM v1 );
+
+--error ER_NON_INSERTABLE_TABLE
+REPLACE INTO v1 VALUES (f1());
+SET @aux = f1();
+
+# Cleanup
+DROP FUNCTION f1;
+DROP VIEW v1;
+DROP TABLE t1;
+
--echo #End of 10.1 tests
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index a02dce34837..ff6f38b719d 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -2634,3 +2634,27 @@ INSERT INTO t1 VALUES ('a');
DROP TRIGGER t1_bi;
DROP TABLE t1;
+--echo #
+--echo # MDEV-13936: Server crashes in Time_and_counter_tracker::incr_loops
+--echo #
+
+CREATE TABLE t1 (i INT);
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE RAND() > 0.5;
+CREATE TABLE t2 (a int);
+CREATE TABLE t3 (a int);
+
+create trigger trg after insert on t2 for each row
+ INSERT INTO t3 SELECT MAX(i) FROM v1 UNION SELECT MAX(i) FROM v1;
+
+drop table t1;
+
+--error ER_NO_SUCH_TABLE
+insert into t2 value (2);
+CREATE TABLE t1 (i INT);
+insert into t2 value (2);
+
+DROP VIEW v1;
+DROP TABLE t1,t2,t3;
+
+
+--echo End of 10.1 tests.
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 257a1d36a2a..31e4678a5e4 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1136,6 +1136,19 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
if (check_stack_overrun(thd, 7 * STACK_MIN_SIZE, (uchar*)&old_packet))
DBUG_RETURN(TRUE);
+ /*
+ 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.
+
+ Other problem is that it can be more SELECTs parsed in case of fixing
+ error causes previous interruption of the SP. So it is save not just
+ assign old value but add it.
+ */
+ thd->select_number+= m_select_number;
+
/* init per-instruction memroot */
init_sql_alloc(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
@@ -1469,6 +1482,16 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
m_recursion_level + 1));
m_first_instance->m_first_free_instance= this;
+ /*
+ 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 || thd->is_error())
+ set_select_number(thd->select_number);
+
DBUG_RETURN(err_status);
}
@@ -2099,26 +2122,7 @@ 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)