summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2015-09-22 21:59:18 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2015-10-12 11:53:07 +0200
commit92271c78b6c78b1a0248ce5d1c96326b930de610 (patch)
tree61e0a1806c33eb1b638a71822f55c440d61e9e85
parente19a6f3dca7509eb8e042796a9311dba937ad9d7 (diff)
downloadmariadb-git-92271c78b6c78b1a0248ce5d1c96326b930de610.tar.gz
MDEV-8087: Server crashed in Time_and_counter_tracker::incr_loops
Problem: Procedure which uses stack of views first executed without most deep view. It fails but one view cached (as well as whole procedure). Then simultaniusely create the second view we lack and execute the procedure. In the beginning of procedure execution the view is not yet created so procedure used as it was cached (cache was not invalidated). But by the time we are trying to use most deep view it is already created. The problem with the view is that thd->select_number (first view was not parsed) so second view will get the same number. The fix is in keeping the thd->select_number correct even if we use cached views. In the proposed solution (to keep it simple) counter can be bigger then should but it should not create problem because numbers are still unique and situation is very rare.
-rw-r--r--mysql-test/r/view_debug.result21
-rw-r--r--mysql-test/t/view_debug.test37
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_view.cc6
4 files changed, 66 insertions, 0 deletions
diff --git a/mysql-test/r/view_debug.result b/mysql-test/r/view_debug.result
new file mode 100644
index 00000000000..ccec91c9e03
--- /dev/null
+++ b/mysql-test/r/view_debug.result
@@ -0,0 +1,21 @@
+#
+#MDEV-8087:Server crashed in Time_and_counter_tracker::incr_loops
+#
+CREATE PROCEDURE proc() SELECT * FROM v2;
+CREATE ALGORITHM = UNDEFINED VIEW v1 AS SELECT 1;
+CREATE ALGORITHM = TEMPTABLE VIEW v2 AS SELECT 3 FROM v1;
+DROP VIEW v1;
+CALL proc();
+ERROR HY000: View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+SET DEBUG_SYNC= 'after_cached_view_opened SIGNAL oppp WAIT_FOR created';
+CALL proc();
+SET DEBUG_SYNC= 'now WAIT_FOR oppp';
+SET DEBUG_SYNC= 'RESET';
+CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT 2;
+SET DEBUG_SYNC= 'now SIGNAL created';
+SET DEBUG_SYNC= 'RESET';
+3
+3
+SET DEBUG_SYNC= 'RESET';
+drop procedure proc;
+drop view v1,v2;
diff --git a/mysql-test/t/view_debug.test b/mysql-test/t/view_debug.test
new file mode 100644
index 00000000000..7f33e4d9735
--- /dev/null
+++ b/mysql-test/t/view_debug.test
@@ -0,0 +1,37 @@
+
+--source include/have_debug.inc
+
+--echo #
+--echo #MDEV-8087:Server crashed in Time_and_counter_tracker::incr_loops
+--echo #
+
+CREATE PROCEDURE proc() SELECT * FROM v2;
+
+CREATE ALGORITHM = UNDEFINED VIEW v1 AS SELECT 1;
+CREATE ALGORITHM = TEMPTABLE VIEW v2 AS SELECT 3 FROM v1;
+DROP VIEW v1;
+
+--connect (con1,localhost,root,,test)
+
+--connect (con2,localhost,root,,test)
+
+--connection con1
+--error ER_VIEW_INVALID
+CALL proc();
+SET DEBUG_SYNC= 'after_cached_view_opened SIGNAL oppp WAIT_FOR created';
+send CALL proc();
+
+--connection con2
+SET DEBUG_SYNC= 'now WAIT_FOR oppp';
+SET DEBUG_SYNC= 'RESET';
+CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT 2;
+SET DEBUG_SYNC= 'now SIGNAL created';
+SET DEBUG_SYNC= 'RESET';
+
+--connection con1
+--reap
+SET DEBUG_SYNC= 'RESET';
+
+
+drop procedure proc;
+drop view v1,v2;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 473fd18a2ee..d39da819513 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -2421,6 +2421,8 @@ struct LEX: public Query_tables_list
/** SELECT of CREATE VIEW statement */
LEX_STRING create_view_select;
+ uint number_of_selects; // valid only for view
+
/** Start of 'ON table', in trigger statements. */
const char* raw_trg_on_table_name_begin;
/** End of 'ON table', in trigger statements. */
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index c439bb7a696..b240958898c 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1170,6 +1170,9 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
*/
mysql_derived_reinit(thd, NULL, table);
+ thd->select_number+= table->view->number_of_selects;
+
+ DEBUG_SYNC(thd, "after_cached_view_opened");
DBUG_RETURN(0);
}
@@ -1357,6 +1360,9 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
parse_status= parse_sql(thd, & parser_state, table->view_creation_ctx);
+ lex->number_of_selects=
+ (thd->select_number - view_select->select_number) + 1;
+
/* Restore environment. */
if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) ||