summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2018-03-21 12:13:37 +0100
committerOleksandr Byelkin <sanja@mariadb.com>2018-03-21 19:47:42 +0100
commitf3994b74327eef37fa6010368f7f8db044cf70f8 (patch)
tree119fadc19e3476a13cc9df65ede9fd0f446861ba
parent2dd4e50d5f74451a5f6bf56d1a36bafffcca878c (diff)
downloadmariadb-git-f3994b74327eef37fa6010368f7f8db044cf70f8.tar.gz
MDEV-15492: Subquery crash similar to MDEV-10050
Detection of first execution of PS fixed. More debug info.
-rw-r--r--mysql-test/r/ps_qc_innodb.result23
-rw-r--r--mysql-test/t/ps_qc_innodb.test35
-rw-r--r--sql/sql_class.cc4
-rw-r--r--sql/sql_prepare.cc4
4 files changed, 65 insertions, 1 deletions
diff --git a/mysql-test/r/ps_qc_innodb.result b/mysql-test/r/ps_qc_innodb.result
new file mode 100644
index 00000000000..775055e858f
--- /dev/null
+++ b/mysql-test/r/ps_qc_innodb.result
@@ -0,0 +1,23 @@
+#
+# MDEV-15492: Subquery crash similar to MDEV-10050
+#
+SET @qcs.save= @@global.query_cache_size, @qct.save= @@global.query_cache_type;
+SET GLOBAL query_cache_size= 512*1024*1024, query_cache_type= ON;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (b INT) ENGINE=InnoDB;
+CREATE VIEW v AS select a from t1 join t2;
+PREPARE stmt1 FROM "SELECT * FROM t1 WHERE a in (SELECT a FROM v)";
+PREPARE stmt2 FROM "SELECT * FROM t1 WHERE a in (SELECT a FROM v)";
+EXECUTE stmt2;
+a
+EXECUTE stmt1;
+a
+INSERT INTO t2 VALUES (0);
+EXECUTE stmt1;
+a
+START TRANSACTION;
+EXECUTE stmt1;
+a
+DROP VIEW v;
+DROP TABLE t1, t2;
+SET GLOBAL query_cache_size= @qcs.save, query_cache_type= @qct.save;
diff --git a/mysql-test/t/ps_qc_innodb.test b/mysql-test/t/ps_qc_innodb.test
new file mode 100644
index 00000000000..e09a2bf4070
--- /dev/null
+++ b/mysql-test/t/ps_qc_innodb.test
@@ -0,0 +1,35 @@
+--source include/have_query_cache.inc
+--source include/have_innodb.inc
+
+--echo #
+--echo # MDEV-15492: Subquery crash similar to MDEV-10050
+--echo #
+
+SET @qcs.save= @@global.query_cache_size, @qct.save= @@global.query_cache_type;
+SET GLOBAL query_cache_size= 512*1024*1024, query_cache_type= ON;
+
+--connect (con1,localhost,root,,test)
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (b INT) ENGINE=InnoDB;
+CREATE VIEW v AS select a from t1 join t2;
+
+PREPARE stmt1 FROM "SELECT * FROM t1 WHERE a in (SELECT a FROM v)";
+
+--connect (con2,localhost,root,,test)
+PREPARE stmt2 FROM "SELECT * FROM t1 WHERE a in (SELECT a FROM v)";
+EXECUTE stmt2;
+
+--connection con1
+EXECUTE stmt1;
+INSERT INTO t2 VALUES (0);
+EXECUTE stmt1;
+START TRANSACTION;
+EXECUTE stmt1;
+
+# Cleanup
+--disconnect con1
+--disconnect con2
+--connection default
+DROP VIEW v;
+DROP TABLE t1, t2;
+SET GLOBAL query_cache_size= @qcs.save, query_cache_type= @qct.save;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index c88c13b9524..ff06b7fb3dc 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2252,15 +2252,19 @@ void THD::check_and_register_item_tree_change(Item **place, Item **new_value,
void THD::rollback_item_tree_changes()
{
+ DBUG_ENTER("THD::rollback_item_tree_changes");
I_List_iterator<Item_change_record> it(change_list);
Item_change_record *change;
while ((change= it++))
{
+ DBUG_PRINT("info", ("Rollback: %p (%p) <- %p",
+ *change->place, change->place, change->old_value));
*change->place= change->old_value;
}
/* We can forget about changes memory: it's allocated in runtime memroot */
change_list.empty();
+ DBUG_VOID_RETURN;
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index a3bf9d6c93c..6aa6aacc504 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -3819,6 +3819,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
Statement stmt_backup;
Query_arena *old_stmt_arena;
bool error= TRUE;
+ bool qc_executed= FALSE;
char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
@@ -3937,6 +3938,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
thd->lex->sql_command= SQLCOM_SELECT;
status_var_increment(thd->status_var.com_stat[SQLCOM_SELECT]);
thd->update_stats();
+ qc_executed= TRUE;
}
}
@@ -3960,7 +3962,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
thd->set_statement(&stmt_backup);
thd->stmt_arena= old_stmt_arena;
- if (state == Query_arena::STMT_PREPARED)
+ if (state == Query_arena::STMT_PREPARED && !qc_executed)
state= Query_arena::STMT_EXECUTED;
if (error == 0 && this->lex->sql_command == SQLCOM_CALL)