Skip to content
Permalink
Browse files
MDEV-13936: Server crashes in Time_and_counter_tracker::incr_loops
Repeat reworked solution of procedures for all posible Sp (functions &
triggers).
  • Loading branch information
sanja-byelkin committed Nov 14, 2017
1 parent 05103c8 commit 0f43279
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 19 deletions.
@@ -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
@@ -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.
@@ -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
@@ -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.
@@ -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)
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)

0 comments on commit 0f43279

Please sign in to comment.