summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/innodb/r/sp_temp_table.result253
-rw-r--r--mysql-test/suite/innodb/t/sp_temp_table.test103
-rw-r--r--storage/innobase/handler/ha_innodb.cc25
-rw-r--r--storage/innobase/include/dict0dict.h8
-rw-r--r--storage/innobase/include/dict0dict.ic12
-rw-r--r--storage/innobase/row/row0mysql.c9
6 files changed, 406 insertions, 4 deletions
diff --git a/mysql-test/suite/innodb/r/sp_temp_table.result b/mysql-test/suite/innodb/r/sp_temp_table.result
new file mode 100644
index 00000000000..49a2a4aa831
--- /dev/null
+++ b/mysql-test/suite/innodb/r/sp_temp_table.result
@@ -0,0 +1,253 @@
+#
+# Bug #19306524 FAILING ASSERTION WITH TEMP TABLE FOR A PROCEDURE
+# CALLED FROM A FUNCTION
+#
+call mtr.add_suppression("MySQL is trying to drop table");
+CREATE PROCEDURE cachedata(
+IN obj_id BIGINT UNSIGNED,
+IN start DATETIME,
+IN end DATETIME
+)
+cachedata:BEGIN
+DECLARE cache_count BIGINT;
+SET @timestamp := NOW();
+CREATE TEMPORARY TABLE IF NOT EXISTS cachedata (
+timestamp DATETIME,
+object_id BIGINT UNSIGNED NOT NULL,
+start DATETIME,
+end DATETIME,
+seqno BIGINT AUTO_INCREMENT,
+value FLOAT,
+PRIMARY KEY (seqno),
+INDEX (timestamp),
+INDEX (object_id, start, end)
+) ENGINE=INNODB;
+DELETE FROM cachedata WHERE
+timestamp < DATE_SUB(@timestamp, INTERVAL 15 SECOND);
+SELECT count(*) INTO cache_count FROM cachedata WHERE
+object_id = obj_id
+AND start = start
+AND end = end;
+IF cache_count > 0 THEN LEAVE cachedata;
+END IF;
+INSERT INTO cachedata (timestamp, object_id, start, end, value) VALUES
+(@timestamp, obj_id, start, end, 1234),
+(@timestamp, obj_id, start, end, 4567),
+(@timestamp, obj_id, start, end, 8901),
+(@timestamp, obj_id, start, end, 1234),
+(@timestamp, obj_id, start, end, 4567),
+(@timestamp, obj_id, start, end, 8901),
+(@timestamp, obj_id, start, end, 1234),
+(@timestamp, obj_id, start, end, 4567),
+(@timestamp, obj_id, start, end, 8901),
+(@timestamp, obj_id, start, end, 1234),
+(@timestamp, obj_id, start, end, 4567),
+(@timestamp, obj_id, start, end, 8901),
+(@timestamp, obj_id, start, end, 2345),
+(@timestamp, obj_id, start, end, 1234),
+(@timestamp, obj_id, start, end, 4567),
+(@timestamp, obj_id, start, end, 8901),
+(@timestamp, obj_id, start, end, 2345),
+(@timestamp, obj_id, start, end, 1234),
+(@timestamp, obj_id, start, end, 4567),
+(@timestamp, obj_id, start, end, 8901),
+(@timestamp, obj_id, start, end, 2345);
+END$$
+CREATE FUNCTION get_cache(
+obj_id BIGINT UNSIGNED,
+start DATETIME,
+end DATETIME
+)
+RETURNS FLOAT
+READS SQL DATA
+BEGIN
+DECLARE result FLOAT;
+CALL cachedata(obj_id, start, end);
+SELECT SUM(value) INTO result FROM cachedata WHERE
+object_id = obj_id
+AND start = start
+AND end = end;
+RETURN result;
+END$$
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+SELECT get_cache(1, '2014-01-01', '2014-02-01');
+get_cache(1, '2014-01-01', '2014-02-01')
+95247
+select sleep(1);
+sleep(1)
+0
+DROP FUNCTION get_cache;
+DROP PROCEDURE cachedata;
diff --git a/mysql-test/suite/innodb/t/sp_temp_table.test b/mysql-test/suite/innodb/t/sp_temp_table.test
new file mode 100644
index 00000000000..b2883f551b9
--- /dev/null
+++ b/mysql-test/suite/innodb/t/sp_temp_table.test
@@ -0,0 +1,103 @@
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+--echo #
+--echo # Bug #19306524 FAILING ASSERTION WITH TEMP TABLE FOR A PROCEDURE
+--echo # CALLED FROM A FUNCTION
+--echo #
+
+call mtr.add_suppression("MySQL is trying to drop table");
+
+DELIMITER $$;
+CREATE PROCEDURE cachedata(
+ IN obj_id BIGINT UNSIGNED,
+ IN start DATETIME,
+ IN end DATETIME
+)
+
+cachedata:BEGIN
+ DECLARE cache_count BIGINT;
+
+ SET @timestamp := NOW();
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS cachedata (
+ timestamp DATETIME,
+ object_id BIGINT UNSIGNED NOT NULL,
+ start DATETIME,
+ end DATETIME,
+ seqno BIGINT AUTO_INCREMENT,
+ value FLOAT,
+ PRIMARY KEY (seqno),
+ INDEX (timestamp),
+ INDEX (object_id, start, end)
+ ) ENGINE=INNODB;
+
+ DELETE FROM cachedata WHERE
+ timestamp < DATE_SUB(@timestamp, INTERVAL 15 SECOND);
+
+ SELECT count(*) INTO cache_count FROM cachedata WHERE
+ object_id = obj_id
+ AND start = start
+ AND end = end;
+
+ IF cache_count > 0 THEN LEAVE cachedata;
+ END IF;
+
+ INSERT INTO cachedata (timestamp, object_id, start, end, value) VALUES
+ (@timestamp, obj_id, start, end, 1234),
+ (@timestamp, obj_id, start, end, 4567),
+ (@timestamp, obj_id, start, end, 8901),
+ (@timestamp, obj_id, start, end, 1234),
+ (@timestamp, obj_id, start, end, 4567),
+ (@timestamp, obj_id, start, end, 8901),
+ (@timestamp, obj_id, start, end, 1234),
+ (@timestamp, obj_id, start, end, 4567),
+ (@timestamp, obj_id, start, end, 8901),
+ (@timestamp, obj_id, start, end, 1234),
+ (@timestamp, obj_id, start, end, 4567),
+ (@timestamp, obj_id, start, end, 8901),
+ (@timestamp, obj_id, start, end, 2345),
+ (@timestamp, obj_id, start, end, 1234),
+ (@timestamp, obj_id, start, end, 4567),
+ (@timestamp, obj_id, start, end, 8901),
+ (@timestamp, obj_id, start, end, 2345),
+ (@timestamp, obj_id, start, end, 1234),
+ (@timestamp, obj_id, start, end, 4567),
+ (@timestamp, obj_id, start, end, 8901),
+ (@timestamp, obj_id, start, end, 2345);
+
+END$$
+
+
+CREATE FUNCTION get_cache(
+ obj_id BIGINT UNSIGNED,
+ start DATETIME,
+ end DATETIME
+)
+ RETURNS FLOAT
+ READS SQL DATA
+BEGIN
+ DECLARE result FLOAT;
+
+ CALL cachedata(obj_id, start, end);
+
+ SELECT SUM(value) INTO result FROM cachedata WHERE
+ object_id = obj_id
+ AND start = start
+ AND end = end;
+
+ RETURN result;
+END$$
+
+DELIMITER ;$$
+
+let $i = 30;
+while ($i)
+{
+ SELECT get_cache(1, '2014-01-01', '2014-02-01');
+ select sleep(1);
+ dec $i;
+}
+
+DROP FUNCTION get_cache;
+DROP PROCEDURE cachedata;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 28f7c95d243..137a89dc9de 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -9173,6 +9173,7 @@ ha_innobase::start_stmt(
thr_lock_type lock_type)
{
trx_t* trx;
+ DBUG_ENTER("ha_innobase::start_stmt");
update_thd(thd);
@@ -9195,6 +9196,28 @@ ha_innobase::start_stmt(
prebuilt->hint_need_to_fetch_extra_cols = 0;
reset_template(prebuilt);
+ if (dict_table_is_temporary(prebuilt->table)
+ && prebuilt->mysql_has_locked
+ && prebuilt->select_lock_type == LOCK_NONE) {
+ ulint error;
+
+ switch (thd_sql_command(thd)) {
+ case SQLCOM_INSERT:
+ case SQLCOM_UPDATE:
+ case SQLCOM_DELETE:
+ init_table_handle_for_HANDLER();
+ prebuilt->select_lock_type = LOCK_X;
+ error = row_lock_table_for_mysql(prebuilt, NULL, 1);
+
+ if (error != DB_SUCCESS) {
+ error = convert_error_code_to_mysql(
+ (int) error, 0, thd);
+ DBUG_RETURN((int) error);
+ }
+ break;
+ }
+ }
+
if (!prebuilt->mysql_has_locked) {
/* This handle is for a temporary table created inside
this same LOCK TABLES; since MySQL does NOT call external_lock
@@ -9227,7 +9250,7 @@ ha_innobase::start_stmt(
innobase_register_trx(ht, thd, trx);
- return(0);
+ DBUG_RETURN(0);
}
/******************************************************************//**
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 254d4e149ca..003639d55b5 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -1367,6 +1367,14 @@ dict_table_init_referenced_rbt(
/*===========================*/
dict_table_t* table); /*!< in: the table object whose
table->referenced_rbt will be initialized */
+/********************************************************************//**
+Check if it is a temporary table.
+@return true if temporary table flag is set. */
+UNIV_INLINE
+ibool
+dict_table_is_temporary(
+/*====================*/
+ const dict_table_t* table); /*!< in: table to check */
#ifndef UNIV_NONINL
#include "dict0dict.ic"
diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic
index a63e1d16427..b65cae2a1d8 100644
--- a/storage/innobase/include/dict0dict.ic
+++ b/storage/innobase/include/dict0dict.ic
@@ -1004,3 +1004,15 @@ dict_table_init_referenced_rbt(
ut_a(table->referenced_rbt != NULL);
return(table->referenced_rbt);
}
+
+/********************************************************************//**
+Check if it is a temporary table.
+@return true if temporary table flag is set. */
+UNIV_INLINE
+ibool
+dict_table_is_temporary(
+/*====================*/
+ const dict_table_t* table) /*!< in: table to check */
+{
+ return(table->flags & (DICT_TF2_TEMPORARY << DICT_TF2_SHIFT));
+}
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 8555054b86f..181ca966451 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -3089,6 +3089,9 @@ row_drop_table_for_mysql(
ulint namelen;
ibool locked_dictionary = FALSE;
pars_info_t* info = NULL;
+ DBUG_ENTER("row_drop_table_for_mysql");
+
+ DBUG_PRINT("row_drop_table_for_mysql", ("table: %s", name));
ut_a(name != NULL);
@@ -3099,7 +3102,7 @@ row_drop_table_for_mysql(
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
" is replaced with raw.\n", stderr);
- return(DB_ERROR);
+ DBUG_RETURN(DB_ERROR);
}
trx->op_info = "dropping table";
@@ -3504,7 +3507,7 @@ funct_exit:
srv_wake_master_thread();
- return((int) err);
+ DBUG_RETURN((int) err);
}
/*********************************************************************//**