summaryrefslogtreecommitdiff
path: root/mysql-test/r/sp-prelocking.result
diff options
context:
space:
mode:
authorDmitry Lenev <dmitry.lenev@oracle.com>2016-07-25 16:06:52 +0300
committerSergei Golubchik <serg@mariadb.org>2017-01-06 10:46:21 +0100
commite4978d26b79120c58706e57fc66e4de1ec4b230c (patch)
tree322b970ed1962e8444240d9bca1aac646e93c3e8 /mysql-test/r/sp-prelocking.result
parent43378f367c5c01ebc214919006e2072fb2356724 (diff)
downloadmariadb-git-e4978d26b79120c58706e57fc66e4de1ec4b230c.tar.gz
MDEV-9084 Calling a stored function from a nested select from temporary table causes unpredictable behavior
Cherry-pick: f4a0af070ce49abae60040f6f32e1074309c27fb Author: Dmitry Lenev <dmitry.lenev@oracle.com> Date: Mon Jul 25 16:06:52 2016 +0300 Fix for bug #16672723 "CAN'T FIND TEMPORARY TABLE". Attempt to execute prepared CREATE TABLE SELECT statement which used temporary table in the subquery in FROM clause and stored function failed with unwarranted ER_NO_SUCH_TABLE error. The same happened when such statement was used in stored procedure and this procedure was re-executed. The problem occurred because execution of such prepared statement/its re-execution as part of stored procedure incorrectly set Query_table_list::query_tables_own_last marker, indicating the last table which is directly used by statement. As result temporary table used in the subquery was treated as indirectly used/belonging to prelocking list and was not pre-opened by open_temporary_tables() call before statement execution. Thus causing ER_NO_SUCH_TABLE errors since our code assumes that temporary tables need to be correctly pre-opened before statement execution. This problem became visible only in version 5.6 after patches related to bug 11746602/27480 "EXTEND CREATE TEMPORARY TABLES PRIVILEGE TO ALLOW TEMP TABLE OPERATIONS" since they have introduced pre-opening of temporary tables for statements. Incorrect setting of Query_table_list::query_tables_own_last happened in LEX::first_lists_tables_same() method which is called by CREATE TABLE SELECT implementation as part of LEX::unlink_first_table(), which temporary excludes table list element for table being created from the query table list before handling SELECT part. LEX::first_lists_tables_same() tries to ensure that global table list of the statement starts with the first table list element from the first statement select. To do this it moves such table list element to the head of the global table list. If this table happens to be last directly-used table for the statement, query_tables_own_last marker is pointing to it. Since this marker was not updated when table list element was moved we ended up with all tables except the first table separated by it as if they were not directly used by statement (i.e. belonged to prelocked tables list). This fix changes code of LEX::first_lists_tables_same() to update query_tables_own_last marker in cases when it points to the table being moved. It is set to the table which precedes table being moved in this case.
Diffstat (limited to 'mysql-test/r/sp-prelocking.result')
-rw-r--r--mysql-test/r/sp-prelocking.result23
1 files changed, 23 insertions, 0 deletions
diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result
index 5b594e9ea55..eb47cc21f41 100644
--- a/mysql-test/r/sp-prelocking.result
+++ b/mysql-test/r/sp-prelocking.result
@@ -340,3 +340,26 @@ f1()
DROP FUNCTION f1;
DROP VIEW v1;
DROP TABLE t1,t2;
+#
+# Bug #16672723 "CAN'T FIND TEMPORARY TABLE".
+#
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+CREATE TEMPORARY TABLE tmp1(a INT);
+PREPARE stmt1 FROM "CREATE TEMPORARY TABLE tmp2 AS SELECT b FROM (SELECT f1() AS b FROM tmp1) AS t";
+# The below statement failed before the fix.
+EXECUTE stmt1;
+DROP TEMPORARY TABLES tmp1, tmp2;
+DEALLOCATE PREPARE stmt1;
+DROP FUNCTION f1;
+create procedure sp1()
+begin
+drop table if exists t1, t2;
+create temporary table t1 select 1 v;
+create table t2 (col varchar(45)) select distinct col from (select sf1() as col from t1) t;
+end$$
+create function sf1() returns text return 'blah';
+call test.sp1();
+call test.sp1();
+drop procedure sp1;
+drop function sf1;
+drop table t2;