MDEV-5535: Cannot reopen temporary table

mysqld maintains a list of TABLE objects for all temporary
tables created within a session in THD. Here each table is
represented by a TABLE object.

A query referencing a particular temporary table for more
than once, however, failed with ER_CANT_REOPEN_TABLE error
because a TABLE_SHARE was allocate together with the TABLE,
so temporary tables always had only one TABLE per TABLE_SHARE.

This patch lift this restriction by separating TABLE and
TABLE_SHARE objects and storing TABLE_SHAREs for temporary
tables in a list in THD, and TABLEs in a list within their
respective TABLE_SHAREs.
This commit is contained in:
Nirbhay Choubey 2016-06-10 16:19:59 -04:00
parent 547511153f
commit 7305be2f7e
50 changed files with 2315 additions and 1260 deletions

View File

@ -111,6 +111,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/wsrep_dummy.cc ../sql/encryption.cc
../sql/item_windowfunc.cc ../sql/sql_window.cc
../sql/sql_cte.cc
../sql/temporary_tables.cc
${GEN_SOURCES}
${MYSYS_LIBWRAP_SOURCE}
)

View File

@ -1736,7 +1736,8 @@ drop view t1;
create table t1 (a int) select 1 as a;
create temporary table if not exists t1 (a int) select * from t1;
create temporary table if not exists t1 (a int) select * from t1;
ERROR HY000: Can't reopen table: 't1'
Warnings:
Note 1050 Table 't1' already exists
select * from t1;
a
1

View File

@ -380,12 +380,7 @@ alter table t1 add column j int;
unlock tables;
drop table t1;
create temporary table t1 (i int);
#
# This is just for test coverage purposes,
# when this is allowed, remove the --error.
#
lock tables t1 write, t1 as a read, t1 as b read;
ERROR HY000: Can't reopen table: 't1'
alter table t1 add column j int;
unlock tables;
drop table t1;

View File

@ -0,0 +1,133 @@
#
# MDEV-5535: Cannot reopen temporary table
#
DROP DATABASE IF EXISTS temp_db;
CREATE DATABASE temp_db;
USE temp_db;
#
# Reopen temporary table
#
CREATE TEMPORARY TABLE t1(i int)ENGINE=INNODB;
INSERT INTO t1 VALUES(1), (2);
SELECT * FROM t1 a, t1 b;
i i
1 1
2 1
1 2
2 2
DROP TABLE t1;
#
# CREATE & Stored routines
#
CREATE TEMPORARY TABLE t3 AS SELECT 1 AS a;
CREATE PROCEDURE p1()
BEGIN
DROP TEMPORARY TABLE t3;
end|
CREATE FUNCTION f3() RETURNS INT
BEGIN
CALL p1();
RETURN 1;
END|
PREPARE STMT FROM "SELECT f3() AS my_Column, a FROM t3";
EXECUTE STMT;
ERROR HY000: Can't reopen table: 't3'
DROP TABLE t3;
DROP FUNCTION f3;
DROP PROCEDURE p1;
CREATE TEMPORARY TABLE t4 (i INT);
INSERT INTO t4 VALUES(1), (2);
CREATE FUNCTION f4() RETURNS INT
BEGIN
DROP TEMPORARY TABLE t4;
RETURN 1;
END|
SELECT f4() FROM t4;
ERROR HY000: Can't reopen table: 't4'
SELECT * FROM t4;
i
1
2
DROP TABLE t4;
DROP FUNCTION f4;
CREATE TEMPORARY TABLE t5 AS SELECT 1 AS a;
CREATE PROCEDURE p2()
BEGIN
DROP TEMPORARY TABLE t5;
END|
CREATE FUNCTION f5() RETURNS INT
BEGIN
CALL p2();
RETURN 1;
END|
SELECT f5() AS my_column, a FROM t5;
ERROR HY000: Can't reopen table: 't5'
DROP TABLE t5;
DROP FUNCTION f5;
DROP PROCEDURE p2;
#
# CTAS
#
CREATE TABLE t1(i INT);
INSERT INTO t1 VALUES(1), (2);
CREATE TEMPORARY TABLE t1
SELECT temp_1.i a, temp_2.i b FROM t1 AS temp_1, t1 AS temp_2;
SELECT * FROM t1;
a b
1 1
2 1
1 2
2 2
DROP TABLE t1;
SELECT * FROM t1;
i
1
2
DROP TABLE t1;
#
# HANDLER
#
CREATE TABLE t1 (a INT, KEY a(a));
INSERT INTO t1 (a) VALUES (1), (2), (3), (4), (5);
CREATE TABLE t2 (a INT, KEY a (a)) SELECT * FROM t1;
CREATE TEMPORARY TABLE t3 (a INT, KEY a (a)) SELECT * FROM t2;
HANDLER t3 OPEN;
SELECT * FROM t1;
a
1
2
3
4
5
LOCK TABLE t1 READ;
HANDLER t3 OPEN;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
UNLOCK TABLES;
HANDLER t3 OPEN;
ERROR 42000: Not unique table/alias: 't3'
HANDLER t3 READ NEXT;
a
1
HANDLER t3 OPEN AS t3_1;
HANDLER t3_1 READ NEXT;
a
1
HANDLER t3_1 READ NEXT;
a
2
HANDLER t3 CLOSE;
HANDLER t3_1 CLOSE;
DROP TEMPORARY TABLE t3;
DROP TABLE t1, t2;
#
# INSERT-SELECT
#
CREATE TEMPORARY TABLE t4 (a INT) ENGINE=MYISAM;
INSERT INTO t4 VALUES(1), (2);
INSERT INTO t4 SELECT * FROM t4;
SELECT COUNT(*) FROM t4;
COUNT(*)
4
DROP TABLE t4;
# Cleanup
DROP DATABASE temp_db;

View File

@ -1140,9 +1140,12 @@ insert into t3 values (1), (2), (3);
return (select count(*) from t3 as a, t3 as b);
end|
select f11()|
ERROR HY000: Can't reopen table: 'a'
f11()
9
select f11() from t1|
ERROR HY000: Can't reopen table: 'a'
f11()
9
9
create function f12_1() returns int
begin
drop temporary table if exists t3;
@ -1156,6 +1159,7 @@ drop temporary table t3|
select f12_1()|
f12_1()
3
drop temporary table t3|
select f12_1() from t1 limit 1|
f12_1()
3
@ -6933,7 +6937,7 @@ CREATE TEMPORARY TABLE t3 LIKE t1;
CREATE PROCEDURE p1 () BEGIN SELECT f1 FROM t3 AS A WHERE A.f1 IN ( SELECT f1 FROM t3 ) ;
END|
CALL p1;
ERROR HY000: Can't reopen table: 'A'
f1
CREATE VIEW t3 AS SELECT f1 FROM t2 A WHERE A.f1 IN ( SELECT f1 FROM t2 );
DROP TABLE t3;
CALL p1;

View File

@ -632,7 +632,18 @@ handler a1 read a next;
a b
3 d
select a,b from t1;
ERROR HY000: Can't reopen table: 'a1'
a b
0 a
1 b
2 c
3 d
4 e
5 f
6 g
7 h
8 i
9 j
9 k
handler a1 read a prev;
a b
2 c
@ -745,7 +756,7 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
handler t2 close;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
handler t3 open;
ERROR HY000: Can't reopen table: 't3'
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
# After UNLOCK TABLES handlers should be around and
# we should be able to continue reading through them.
unlock tables;
@ -1396,7 +1407,12 @@ handler t2 read a next;
a b
3 NULL
select * from t2;
ERROR HY000: Can't reopen table: 't2'
a b
1 NULL
2 NULL
3 NULL
4 NULL
5 NULL
handler t2 read a next;
a b
4 NULL

View File

@ -460,9 +460,6 @@ drop table t1;
#
# Bug#30882 Dropping a temporary table inside a stored function may cause a server crash
#
# Test HANDLER statements in conjunction with temporary tables. While the temporary table
# is open by a HANDLER, no other statement can access it.
#
create temporary table t1 (a int, b char(1), key a using btree (a), key b using btree (a,b));
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
@ -472,7 +469,6 @@ handler t1 open as a1;
handler a1 read a=(1);
handler a1 read a next;
handler a1 read a next;
--error ER_CANT_REOPEN_TABLE
select a,b from t1;
handler a1 read a prev;
handler a1 read a prev;
@ -564,7 +560,7 @@ handler t1 open;
handler t1 read next;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
handler t2 close;
--error ER_CANT_REOPEN_TABLE
--error ER_LOCK_OR_ACTIVE_TRANSACTION
handler t3 open;
--echo # After UNLOCK TABLES handlers should be around and
--echo # we should be able to continue reading through them.
@ -1182,7 +1178,6 @@ handler t1 read a next;
select * from t1;
--echo # Sic: the position is not lost
handler t2 read a next;
--error ER_CANT_REOPEN_TABLE
select * from t2;
handler t2 read a next;
drop table t1;

View File

@ -632,7 +632,18 @@ handler a1 read a next;
a b
3 d
select a,b from t1;
ERROR HY000: Can't reopen table: 'a1'
a b
0 a
1 b
2 c
3 d
4 e
5 f
6 g
7 h
8 i
9 j
9 k
handler a1 read a prev;
a b
2 c
@ -745,7 +756,7 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
handler t2 close;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
handler t3 open;
ERROR HY000: Can't reopen table: 't3'
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
# After UNLOCK TABLES handlers should be around and
# we should be able to continue reading through them.
unlock tables;
@ -1396,7 +1407,12 @@ handler t2 read a next;
a b
3 NULL
select * from t2;
ERROR HY000: Can't reopen table: 't2'
a b
1 NULL
2 NULL
3 NULL
4 NULL
5 NULL
handler t2 read a next;
a b
4 NULL

View File

@ -633,7 +633,18 @@ handler a1 read a next;
a b
3 d
select a,b from t1;
ERROR HY000: Can't reopen table: 'a1'
a b
0 a
1 b
2 c
3 d
4 e
5 f
6 g
7 h
8 i
9 j
9 k
handler a1 read a prev;
a b
2 c
@ -747,7 +758,7 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
handler t2 close;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
handler t3 open;
ERROR HY000: Can't reopen table: 't3'
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
# After UNLOCK TABLES handlers should be around and
# we should be able to continue reading through them.
unlock tables;
@ -1400,7 +1411,12 @@ handler t2 read a next;
a b
3 NULL
select * from t2;
ERROR HY000: Can't reopen table: 't2'
a b
1 NULL
2 NULL
3 NULL
4 NULL
5 NULL
handler t2 read a next;
a b
4 NULL

View File

@ -632,7 +632,18 @@ handler a1 read a next;
a b
3 d
select a,b from t1;
ERROR HY000: Can't reopen table: 'a1'
a b
0 a
1 b
2 c
3 d
4 e
5 f
6 g
7 h
8 i
9 j
9 k
handler a1 read a prev;
a b
2 c
@ -745,7 +756,7 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
handler t2 close;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
handler t3 open;
ERROR HY000: Can't reopen table: 't3'
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
# After UNLOCK TABLES handlers should be around and
# we should be able to continue reading through them.
unlock tables;
@ -1396,7 +1407,12 @@ handler t2 read a next;
a b
3 NULL
select * from t2;
ERROR HY000: Can't reopen table: 't2'
a b
1 NULL
2 NULL
3 NULL
4 NULL
5 NULL
handler t2 read a next;
a b
4 NULL

View File

@ -0,0 +1,30 @@
include/master-slave.inc
[connection master]
connection slave;
reset master;
#
# MDEV-5535: Cannot reopen temporary table
#
connection master;
DROP TABLE IF EXISTS t1, t2, t3;
CREATE TEMPORARY TABLE t1(c1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
CREATE TEMPORARY TABLE t2 SELECT A.c1 a, B.c1 b FROM t1 AS A, t1 AS B;
CREATE TABLE t3 SELECT * FROM t2;
SELECT COUNT(*) = 5 FROM t1;
COUNT(*) = 5
1
SELECT COUNT(*) = 25 FROM t2;
COUNT(*) = 25
1
SELECT COUNT(*) = 25 FROM t3;
COUNT(*) = 25
1
connection slave;
SELECT COUNT(*) = 25 FROM t3;
COUNT(*) = 25
1
connection master;
DROP TABLE t1, t2, t3;
connection slave;
include/rpl_end.inc

View File

@ -0,0 +1,43 @@
--source include/have_innodb.inc
--source include/master-slave.inc
# Clean up old slave's binlogs (see rpl_temporary.test for explanation).
save_master_pos;
connection slave;
sync_with_master;
reset master;
--echo #
--echo # MDEV-5535: Cannot reopen temporary table
--echo #
connection master;
--disable_query_log
CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
--enable_query_log
disable_warnings;
DROP TABLE IF EXISTS t1, t2, t3;
enable_warnings;
CREATE TEMPORARY TABLE t1(c1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
CREATE TEMPORARY TABLE t2 SELECT A.c1 a, B.c1 b FROM t1 AS A, t1 AS B;
CREATE TABLE t3 SELECT * FROM t2;
SELECT COUNT(*) = 5 FROM t1;
SELECT COUNT(*) = 25 FROM t2;
SELECT COUNT(*) = 25 FROM t3;
sync_slave_with_master;
SELECT COUNT(*) = 25 FROM t3;
connection master;
DROP TABLE t1, t2, t3;
sync_slave_with_master;
--source include/rpl_end.inc

View File

@ -1618,7 +1618,6 @@ drop view t1;
create table t1 (a int) select 1 as a;
create temporary table if not exists t1 (a int) select * from t1;
--error ER_CANT_REOPEN_TABLE
create temporary table if not exists t1 (a int) select * from t1;
select * from t1;
drop temporary table t1;

View File

@ -442,11 +442,6 @@ alter table t1 add column j int;
unlock tables;
drop table t1;
create temporary table t1 (i int);
--echo #
--echo # This is just for test coverage purposes,
--echo # when this is allowed, remove the --error.
--echo #
--error ER_CANT_REOPEN_TABLE
lock tables t1 write, t1 as a read, t1 as b read;
alter table t1 add column j int;
unlock tables;

View File

@ -0,0 +1,128 @@
--source include/have_innodb.inc
--echo #
--echo # MDEV-5535: Cannot reopen temporary table
--echo #
--disable_warnings
DROP DATABASE IF EXISTS temp_db;
--enable_warnings
CREATE DATABASE temp_db;
USE temp_db;
--echo #
--echo # Reopen temporary table
--echo #
CREATE TEMPORARY TABLE t1(i int)ENGINE=INNODB;
INSERT INTO t1 VALUES(1), (2);
SELECT * FROM t1 a, t1 b;
DROP TABLE t1;
--echo #
--echo # CREATE & Stored routines
--echo #
CREATE TEMPORARY TABLE t3 AS SELECT 1 AS a;
DELIMITER |;
CREATE PROCEDURE p1()
BEGIN
DROP TEMPORARY TABLE t3;
end|
CREATE FUNCTION f3() RETURNS INT
BEGIN
CALL p1();
RETURN 1;
END|
DELIMITER ;|
PREPARE STMT FROM "SELECT f3() AS my_Column, a FROM t3";
--error ER_CANT_REOPEN_TABLE
EXECUTE STMT;
DROP TABLE t3;
DROP FUNCTION f3;
DROP PROCEDURE p1;
CREATE TEMPORARY TABLE t4 (i INT);
INSERT INTO t4 VALUES(1), (2);
DELIMITER |;
CREATE FUNCTION f4() RETURNS INT
BEGIN
DROP TEMPORARY TABLE t4;
RETURN 1;
END|
DELIMITER ;|
--error ER_CANT_REOPEN_TABLE
SELECT f4() FROM t4;
SELECT * FROM t4;
DROP TABLE t4;
DROP FUNCTION f4;
CREATE TEMPORARY TABLE t5 AS SELECT 1 AS a;
DELIMITER |;
CREATE PROCEDURE p2()
BEGIN
DROP TEMPORARY TABLE t5;
END|
CREATE FUNCTION f5() RETURNS INT
BEGIN
CALL p2();
RETURN 1;
END|
DELIMITER ;|
--error ER_CANT_REOPEN_TABLE
SELECT f5() AS my_column, a FROM t5;
DROP TABLE t5;
DROP FUNCTION f5;
DROP PROCEDURE p2;
--echo #
--echo # CTAS
--echo #
CREATE TABLE t1(i INT);
INSERT INTO t1 VALUES(1), (2);
CREATE TEMPORARY TABLE t1
SELECT temp_1.i a, temp_2.i b FROM t1 AS temp_1, t1 AS temp_2;
SELECT * FROM t1;
DROP TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # HANDLER
--echo #
CREATE TABLE t1 (a INT, KEY a(a));
INSERT INTO t1 (a) VALUES (1), (2), (3), (4), (5);
CREATE TABLE t2 (a INT, KEY a (a)) SELECT * FROM t1;
CREATE TEMPORARY TABLE t3 (a INT, KEY a (a)) SELECT * FROM t2;
HANDLER t3 OPEN;
SELECT * FROM t1;
LOCK TABLE t1 READ;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
HANDLER t3 OPEN;
UNLOCK TABLES;
--error ER_NONUNIQ_TABLE
HANDLER t3 OPEN;
HANDLER t3 READ NEXT;
HANDLER t3 OPEN AS t3_1;
HANDLER t3_1 READ NEXT;
HANDLER t3_1 READ NEXT;
HANDLER t3 CLOSE;
HANDLER t3_1 CLOSE;
DROP TEMPORARY TABLE t3;
DROP TABLE t1, t2;
--echo #
--echo # INSERT-SELECT
--echo #
CREATE TEMPORARY TABLE t4 (a INT) ENGINE=MYISAM;
INSERT INTO t4 VALUES(1), (2);
INSERT INTO t4 SELECT * FROM t4;
SELECT COUNT(*) FROM t4;
DROP TABLE t4;
--echo # Cleanup
DROP DATABASE temp_db;

View File

@ -1368,11 +1368,6 @@ select f10()|
create table t4 as select 1 as id|
select f10()|
# Practical cases which we don't handle well (yet)
#
# Function which does not work because of well-known and documented
# limitation of MySQL. We can't use the several instances of the
# same temporary table in statement.
create function f11() returns int
begin
drop temporary table if exists t3;
@ -1380,9 +1375,7 @@ begin
insert into t3 values (1), (2), (3);
return (select count(*) from t3 as a, t3 as b);
end|
--error ER_CANT_REOPEN_TABLE
select f11()|
--error ER_CANT_REOPEN_TABLE
select f11() from t1|
# Test that using a single table instance at a time works
create function f12_1() returns int
@ -1397,6 +1390,7 @@ create function f12_2() returns int
drop temporary table t3|
select f12_1()|
drop temporary table t3|
select f12_1() from t1 limit 1|
# Cleanup
@ -8278,7 +8272,6 @@ delimiter |;
CREATE PROCEDURE p1 () BEGIN SELECT f1 FROM t3 AS A WHERE A.f1 IN ( SELECT f1 FROM t3 ) ;
END|
delimiter ;|
--error ER_CANT_REOPEN_TABLE
CALL p1;
CREATE VIEW t3 AS SELECT f1 FROM t2 A WHERE A.f1 IN ( SELECT f1 FROM t2 );
DROP TABLE t3;

View File

@ -1,5 +1,5 @@
# Copyright (c) 2006, 2014, Oracle and/or its affiliates.
# Copyright (c) 2010, 2015, MariaDB
# Copyright (c) 2010, 2016, MariaDB Corporation
#
# 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
@ -141,7 +141,7 @@ SET (SQL_SOURCE
item_windowfunc.cc sql_window.cc
sql_cte.cc sql_cte.h
${WSREP_SOURCES}
table_cache.cc encryption.cc
table_cache.cc encryption.cc temporary_tables.cc
${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc
${GEN_SOURCES}
${GEN_DIGEST_SOURCES}

View File

@ -6159,7 +6159,7 @@ int Load_log_event::do_apply_event(NET* net, rpl_group_info *rgi,
update it inside mysql_load().
*/
List<Item> tmp_list;
if (open_temporary_tables(thd, &tables) ||
if (thd->open_temporary_tables(&tables) ||
mysql_load(thd, &ex, &tables, field_list, tmp_list, tmp_list,
handle_dup, ignore, net != 0))
thd->is_slave_error= 1;

View File

@ -1,5 +1,6 @@
/* Copyright (c) 2006, 2013, Oracle and/or its affiliates.
Copyright (c) 2010, 2013, Monty Program Ab
Copyright (c) 2016, MariaDB Corporation
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
@ -52,8 +53,8 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery)
no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id),
info_fd(-1), cur_log_fd(-1), relay_log(&sync_relaylog_period),
sync_counter(0), is_relay_log_recovery(is_slave_recovery),
save_temporary_tables(0), mi(0),
inuse_relaylog_list(0), last_inuse_relaylog(0),
save_temporary_tables(0),
mi(0), inuse_relaylog_list(0), last_inuse_relaylog(0),
cur_log_old_open_count(0), group_relay_log_pos(0),
event_relay_log_pos(0),
#if HAVE_valgrind
@ -1062,24 +1063,53 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
void Relay_log_info::close_temporary_tables()
{
TABLE *table,*next;
DBUG_ENTER("Relay_log_info::close_temporary_tables");
for (table=save_temporary_tables ; table ; table=next)
{
next=table->next;
TMP_TABLE_SHARE *share;
TABLE *table;
if (!save_temporary_tables)
{
/* There are no temporary tables. */
DBUG_VOID_RETURN;
}
while ((share= save_temporary_tables->pop_front()))
{
/*
Iterate over the list of tables for this TABLE_SHARE and close them.
*/
while ((table= share->all_tmp_tables.pop_front()))
{
DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'",
table->s->db.str, table->s->table_name.str));
/* Reset in_use as the table may have been created by another thd */
table->in_use= 0;
/*
Lets not free TABLE_SHARE here as there could be multiple TABLEs opened
for the same table (TABLE_SHARE).
*/
closefrm(table);
my_free(table);
}
/* Reset in_use as the table may have been created by another thd */
table->in_use=0;
/*
Don't ask for disk deletion. For now, anyway they will be deleted when
slave restarts, but it is a better intention to not delete them.
*/
DBUG_PRINT("info", ("table: 0x%lx", (long) table));
close_temporary(table, 1, 0);
free_table_share(share);
my_free(share);
}
save_temporary_tables= 0;
/* By now, there mustn't be any elements left in the list. */
DBUG_ASSERT(save_temporary_tables->is_empty());
my_free(save_temporary_tables);
save_temporary_tables= NULL;
slave_open_temp_tables= 0;
DBUG_VOID_RETURN;
}
@ -1756,6 +1786,7 @@ void rpl_group_info::cleanup_context(THD *thd, bool error)
}
m_table_map.clear_tables();
slave_close_thread_tables(thd);
if (error)
{
thd->mdl_context.release_transactional_locks();

View File

@ -148,7 +148,7 @@ public:
Protected by data_lock.
*/
TABLE *save_temporary_tables;
All_tmp_tables_list *save_temporary_tables;
/*
standard lock acquisition order to avoid deadlocks:

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
Copyright (c) 2008, 2015, MariaDB
Copyright (c) 2008, 2016, MariaDB Corporation
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
@ -4895,8 +4895,11 @@ err_during_init:
/*
TODO: see if we can do this conditionally in next_event() instead
to avoid unneeded position re-init
We only reset THD::temporary_tables to 0 here and not free it, as this
could be used by slave through Relay_log_info::save_temporary_tables.
*/
thd->temporary_tables = 0; // remove tempation from destructor to close them
thd->temporary_tables= 0;
rli->sql_driver_thd= 0;
thd->rgi_fake= thd->rgi_slave= NULL;

View File

@ -3077,7 +3077,7 @@ int sp_instr::exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables)
Check whenever we have access to tables for this statement
and open and lock them before executing instructions core function.
*/
if (open_temporary_tables(thd, tables) ||
if (thd->open_temporary_tables(tables) ||
check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE)
|| open_and_lock_tables(thd, tables, TRUE, 0))
result= -1;

View File

@ -54,7 +54,7 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
DEBUG_SYNC(thd, "ha_admin_try_alter");
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
result_code= (open_temporary_tables(thd, table_list) ||
result_code= (thd->open_temporary_tables(table_list) ||
mysql_recreate_table(thd, table_list, false));
reenable_binlog(thd);
/*
@ -445,7 +445,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
da->push_warning_info(&tmp_wi);
open_error= (open_temporary_tables(thd, table) ||
open_error= (thd->open_temporary_tables(table) ||
open_and_lock_tables(thd, table, TRUE, 0));
da->pop_warning_info();
@ -460,7 +460,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
mode. It does make sense for the user to see such errors.
*/
open_error= (open_temporary_tables(thd, table) ||
open_error= (thd->open_temporary_tables(table) ||
open_and_lock_tables(thd, table, TRUE, 0));
}
thd->prepare_derived_at_open= FALSE;
@ -952,7 +952,7 @@ send_result_message:
table->mdl_request.ticket= NULL;
DEBUG_SYNC(thd, "ha_admin_open_ltable");
table->mdl_request.set_type(MDL_SHARED_WRITE);
if (!open_temporary_tables(thd, table) &&
if (!thd->open_temporary_tables(table) &&
(table->table= open_ltable(thd, table, lock_type, 0)))
{
uint save_flags;

View File

@ -1,4 +1,5 @@
/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2016, MariaDB Corporation
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
@ -16,7 +17,6 @@
#include "sql_parse.h" // check_access
#include "sql_table.h" // mysql_alter_table,
// mysql_exchange_partition
#include "sql_base.h" // open_temporary_tables
#include "sql_alter.h"
#include "wsrep_mysqld.h"
@ -305,10 +305,8 @@ bool Sql_cmd_alter_table::execute(THD *thd)
thd->enable_slow_log= opt_log_slow_admin_statements;
#ifdef WITH_WSREP
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
if ((!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, first_table)))
!thd->find_temporary_table(first_table)))
{
WSREP_TO_ISOLATION_BEGIN(((lex->name.str) ? select_lex->db : NULL),
((lex->name.str) ? lex->name.str : NULL),

File diff suppressed because it is too large Load Diff

View File

@ -59,8 +59,6 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE,
IGNORE_EXCEPT_NON_UNIQUE};
uint create_tmp_table_def_key(THD *thd, char *key, const char *db,
const char *table_name);
uint get_table_def_key(const TABLE_LIST *table_list, const char **key);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
uint lock_flags);
@ -124,11 +122,6 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx);
bool get_key_map_from_key_list(key_map *map, TABLE *table,
List<String> *index_list);
TABLE *open_table_uncached(THD *thd, handlerton *hton,
LEX_CUSTRING *frm, const char *path,
const char *db, const char *table_name,
bool add_to_temporary_tables_list,
bool open_in_engine);
TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
TABLE *find_write_locked_table(TABLE *list, const char *db,
const char *table_name);
@ -138,21 +131,12 @@ thr_lock_type read_lock_type_for_table(THD *thd,
bool routine_modifies_data);
my_bool mysql_rm_tmp_tables(void);
bool rm_temporary_table(handlerton *base, const char *path);
void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
const MDL_savepoint &start_of_statement_svp);
TABLE_LIST *find_table_in_list(TABLE_LIST *table,
TABLE_LIST *TABLE_LIST::*link,
const char *db_name,
const char *table_name);
TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name);
bool find_and_use_temporary_table(THD *thd, const char *db,
const char *table_name, TABLE **out_table);
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
bool find_and_use_temporary_table(THD *thd, const TABLE_LIST *tl,
TABLE **out_table);
TABLE *find_temporary_table(THD *thd, const char *table_key,
uint table_key_length);
void close_thread_tables(THD *thd);
void switch_to_nullable_trigger_fields(List<Item> &items, TABLE *);
bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
@ -272,17 +256,8 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
int decide_logging_format(THD *thd, TABLE_LIST *tables);
void close_thread_table(THD *thd, TABLE **table_ptr);
bool close_temporary_tables(THD *thd);
TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
bool check_alias);
int drop_temporary_table(THD *thd, TABLE *table, bool *is_trans);
void close_temporary_table(THD *thd, TABLE *table, bool free_share,
bool delete_table);
void close_temporary(TABLE *table, bool free_share, bool delete_table);
bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
const char *table_name);
bool open_temporary_tables(THD *thd, TABLE_LIST *tl_list);
bool open_temporary_table(THD *thd, TABLE_LIST *tl);
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
class Open_tables_backup;
@ -311,7 +286,6 @@ bool tdc_open_view(THD *thd, TABLE_LIST *table_list, uint flags);
TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
const char *table_name,
bool no_error);
void mark_tmp_table_for_reuse(TABLE *table);
int update_virtual_fields(THD *thd, TABLE *table,
enum enum_vcol_update_mode vcol_update_mode= VCOL_UPDATE_FOR_READ);

View File

@ -1999,36 +1999,32 @@ lookup:
for (; block_table != block_table_end; block_table++)
{
TABLE_LIST table_list;
TABLE *tmptable;
TMP_TABLE_SHARE *tmptable;
Query_cache_table *table = block_table->parent;
/*
Check that we have not temporary tables with same names of tables
of this query. If we have such tables, we will not send data from
query cache, because temporary tables hide real tables by which
Check that we do not have temporary tables with same names as that of
base tables from this query. If we have such tables, we will not send
data from query cache, because temporary tables hide real tables by which
query in query cache was made.
*/
for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next)
if ((tmptable=
thd->find_tmp_table_share_w_base_key((char *) table->data(),
table->key_length())))
{
if (tmptable->s->table_cache_key.length - TMP_TABLE_KEY_EXTRA ==
table->key_length() &&
!memcmp(tmptable->s->table_cache_key.str, table->data(),
table->key_length()))
{
DBUG_PRINT("qcache",
("Temporary table detected: '%s.%s'",
tmptable->s->db.str, tmptable->alias.c_ptr()));
unlock();
/*
We should not store result of this query because it contain
temporary tables => assign following variable to make check
faster.
*/
thd->query_cache_is_applicable= 0; // Query can't be cached
thd->lex->safe_to_cache_query= 0; // For prepared statements
BLOCK_UNLOCK_RD(query_block);
DBUG_RETURN(-1);
}
DBUG_PRINT("qcache",
("Temporary table detected: '%s.%s'",
tmptable->db.str, tmptable->table_name.str));
unlock();
/*
We should not store result of this query because it contain
temporary tables => assign following variable to make check
faster.
*/
thd->query_cache_is_applicable= 0; // Query can't be cached
thd->lex->safe_to_cache_query= 0; // For prepared statements
BLOCK_UNLOCK_RD(query_block);
DBUG_RETURN(-1);
}
bzero((char*) &table_list,sizeof(table_list));

View File

@ -37,7 +37,7 @@
#include "tztime.h" // MYSQL_TIME <-> my_time_t
#include "sql_acl.h" // NO_ACCESS,
// acl_getroot_no_password
#include "sql_base.h" // close_temporary_tables
#include "sql_base.h"
#include "sql_handler.h" // mysql_ha_cleanup
#include "rpl_rli.h"
#include "rpl_filter.h"
@ -883,7 +883,8 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
main_da(0, false, false),
m_stmt_da(&main_da),
tdc_hash_pins(0),
xid_hash_pins(0)
xid_hash_pins(0),
m_tmp_tables_locked(false)
#ifdef WITH_WSREP
,
wsrep_applier(is_wsrep_applier),
@ -1586,7 +1587,7 @@ void THD::cleanup(void)
locked_tables_list.unlock_locked_tables(this);
delete_dynamic(&user_var_events);
close_temporary_tables(this);
close_temporary_tables();
transaction.xid_state.xa_state= XA_NOTR;
trans_rollback(this);
@ -4319,7 +4320,8 @@ void THD::restore_backup_open_tables_state(Open_tables_backup *backup)
Before we will throw away current open tables state we want
to be sure that it was properly cleaned up.
*/
DBUG_ASSERT(open_tables == 0 && temporary_tables == 0 &&
DBUG_ASSERT(open_tables == 0 &&
temporary_tables == 0 &&
derived_tables == 0 &&
lock == 0 &&
locked_tables_mode == LTM_NONE &&
@ -6982,24 +6984,6 @@ THD::signal_wakeup_ready()
}
void THD::rgi_lock_temporary_tables()
{
mysql_mutex_lock(&rgi_slave->rli->data_lock);
temporary_tables= rgi_slave->rli->save_temporary_tables;
}
void THD::rgi_unlock_temporary_tables()
{
rgi_slave->rli->save_temporary_tables= temporary_tables;
mysql_mutex_unlock(&rgi_slave->rli->data_lock);
}
bool THD::rgi_have_temporary_tables()
{
return rgi_slave->rli->save_temporary_tables != 0;
}
void
wait_for_commit::reinit()
{

View File

@ -1264,6 +1264,61 @@ enum enum_locked_tables_mode
LTM_PRELOCKED_UNDER_LOCK_TABLES
};
/**
The following structure is an extension to TABLE_SHARE and is
exclusively for temporary tables.
@note:
Although, TDC_element has data members (like next, prev &
all_tables) to store the list of TABLE_SHARE & TABLE objects
related to a particular TABLE_SHARE, they cannot be moved to
TABLE_SHARE in order to be reused for temporary tables. This
is because, as concurrent threads iterating through hash of
TDC_element's may need access to all_tables, but if all_tables
is made part of TABLE_SHARE, then TDC_element->share->all_tables
is not always guaranteed to be valid, as TDC_element can live
longer than TABLE_SHARE.
*/
struct TMP_TABLE_SHARE : public TABLE_SHARE
{
private:
/*
Link to all temporary table shares. Declared as private to
avoid direct manipulation with those objects. One should
use methods of I_P_List template instead.
*/
TMP_TABLE_SHARE *tmp_next;
TMP_TABLE_SHARE **tmp_prev;
friend struct All_tmp_table_shares;
public:
/*
Doubly-linked (back-linked) lists of used and unused TABLE objects
for this share.
*/
All_share_tables_list all_tmp_tables;
};
/**
Helper class which specifies which members of TMP_TABLE_SHARE are
used for participation in the list of temporary tables.
*/
struct All_tmp_table_shares
{
static inline TMP_TABLE_SHARE **next_ptr(TMP_TABLE_SHARE *l)
{
return &l->tmp_next;
}
static inline TMP_TABLE_SHARE ***prev_ptr(TMP_TABLE_SHARE *l)
{
return &l->tmp_prev;
}
};
/* Also used in rpl_rli.h. */
typedef I_P_List <TMP_TABLE_SHARE, All_tmp_table_shares> All_tmp_tables_list;
/**
Class that holds information about tables which were opened and locked
@ -1293,15 +1348,20 @@ public:
base tables that were opened with @see open_tables().
*/
TABLE *open_tables;
/**
List of temporary tables used by this thread. Contains user-level
temporary tables, created with CREATE TEMPORARY TABLE, and
internal temporary tables, created, e.g., to resolve a SELECT,
A list of temporary tables used by this thread. This includes
user-level temporary tables, created with CREATE TEMPORARY TABLE,
and internal temporary tables, created, e.g., to resolve a SELECT,
or for an intermediate table used in ALTER.
XXX Why are internal temporary tables added to this list?
*/
TABLE *temporary_tables;
All_tmp_tables_list *temporary_tables;
/*
Derived tables.
*/
TABLE *derived_tables;
/*
During a MySQL session, one can lock tables in two modes: automatic
or manual. In automatic mode all necessary tables are locked just before
@ -1379,8 +1439,11 @@ public:
void reset_open_tables_state(THD *thd)
{
open_tables= temporary_tables= derived_tables= 0;
extra_lock= lock= 0;
open_tables= 0;
temporary_tables= 0;
derived_tables= 0;
extra_lock= 0;
lock= 0;
locked_tables_mode= LTM_NONE;
state_flags= 0U;
m_reprepare_observer= NULL;
@ -3544,13 +3607,13 @@ public:
*/
DBUG_PRINT("debug",
("temporary_tables: %s, in_sub_stmt: %s, system_thread: %s",
YESNO(temporary_tables), YESNO(in_sub_stmt),
YESNO(has_thd_temporary_tables()), YESNO(in_sub_stmt),
show_system_thread(system_thread)));
if (in_sub_stmt == 0)
{
if (wsrep_binlog_format() == BINLOG_FORMAT_ROW)
set_current_stmt_binlog_format_row();
else if (temporary_tables == NULL)
else if (!has_thd_temporary_tables())
set_current_stmt_binlog_format_stmt();
}
DBUG_VOID_RETURN;
@ -3950,10 +4013,6 @@ private:
LEX_STRING invoker_user;
LEX_STRING invoker_host;
/* Protect against add/delete of temporary tables in parallel replication */
void rgi_lock_temporary_tables();
void rgi_unlock_temporary_tables();
bool rgi_have_temporary_tables();
public:
/*
Flag, mutex and condition for a thread to wait for a signal from another
@ -3971,26 +4030,85 @@ public:
*/
rpl_gtid last_commit_gtid;
inline void lock_temporary_tables()
{
if (rgi_slave)
rgi_lock_temporary_tables();
}
inline void unlock_temporary_tables()
{
if (rgi_slave)
rgi_unlock_temporary_tables();
}
inline bool have_temporary_tables()
{
return (temporary_tables ||
(rgi_slave && rgi_have_temporary_tables()));
}
LF_PINS *tdc_hash_pins;
LF_PINS *xid_hash_pins;
bool fix_xid_hash_pins();
/* Members related to temporary tables. */
public:
bool has_thd_temporary_tables();
TABLE *create_and_open_tmp_table(handlerton *hton,
LEX_CUSTRING *frm,
const char *path,
const char *db,
const char *table_name,
bool open_in_engine);
TABLE *find_temporary_table(const char *db, const char *table_name);
TABLE *find_temporary_table(const TABLE_LIST *tl);
TMP_TABLE_SHARE *find_tmp_table_share_w_base_key(const char *key,
uint key_length);
TMP_TABLE_SHARE *find_tmp_table_share(const char *db,
const char *table_name);
TMP_TABLE_SHARE *find_tmp_table_share(const TABLE_LIST *tl);
TMP_TABLE_SHARE *find_tmp_table_share(const char *key, uint key_length);
bool open_temporary_table(TABLE_LIST *tl);
bool open_temporary_tables(TABLE_LIST *tl);
bool close_temporary_tables();
bool rename_temporary_table(TABLE *table, const char *db,
const char *table_name);
bool drop_temporary_table(TABLE *table, bool *is_trans, bool delete_table);
bool rm_temporary_table(handlerton *hton, const char *path);
void mark_tmp_tables_as_free_for_reuse();
void mark_tmp_table_as_free_for_reuse(TABLE *table);
private:
/* Whether a lock has been acquired? */
bool m_tmp_tables_locked;
/* Opened table states. */
enum Temporary_table_state {
TMP_TABLE_IN_USE,
TMP_TABLE_NOT_IN_USE,
TMP_TABLE_ANY
};
bool has_temporary_tables();
uint create_tmp_table_def_key(char *key, const char *db,
const char *table_name);
TMP_TABLE_SHARE *create_temporary_table(handlerton *hton, LEX_CUSTRING *frm,
const char *path, const char *db,
const char *table_name);
TABLE *find_temporary_table(const char *key, uint key_length,
Temporary_table_state state);
TABLE *open_temporary_table(TMP_TABLE_SHARE *share, const char *alias,
bool open_in_engine);
bool find_and_use_tmp_table(const TABLE_LIST *tl, TABLE **out_table);
bool use_temporary_table(TABLE *table, TABLE **out_table);
void close_temporary_table(TABLE *table);
bool log_events_and_free_tmp_shares();
void free_tmp_table_share(TMP_TABLE_SHARE *share, bool delete_table);
void free_temporary_table(TABLE *table);
bool lock_temporary_tables();
void unlock_temporary_tables();
inline uint tmpkeyval(TMP_TABLE_SHARE *share)
{
return uint4korr(share->table_cache_key.str +
share->table_cache_key.length - 4);
}
inline TMP_TABLE_SHARE *tmp_table_share(TABLE *table)
{
DBUG_ASSERT(table->s->tmp_table);
return static_cast<TMP_TABLE_SHARE *>(table->s);
}
public:
inline ulong wsrep_binlog_format() const
{
return WSREP_FORMAT(variables.binlog_format);

View File

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2014, Oracle and/or its affiliates.
Copyright (c) 2009, 2015, MariaDB
Copyright (c) 2009, 2016, MariaDB Corporation
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
@ -886,7 +886,8 @@ mysql_rm_db_internal(THD *thd,char *db, bool if_exists, bool silent)
{
LEX_STRING db_name= { table->db, table->db_length };
LEX_STRING table_name= { table->table_name, table->table_name_length };
if (table->open_type == OT_BASE_ONLY || !find_temporary_table(thd, table))
if (table->open_type == OT_BASE_ONLY ||
!thd->find_temporary_table(table))
(void) delete_statistics_for_table(thd, &db_name, &table_name);
}
}

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2001, 2015, Oracle and/or its affiliates.
Copyright (c) 2011, 2015, MariaDB
Copyright (c) 2011, 2016, MariaDB Corporation
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
@ -178,9 +178,8 @@ static void mysql_ha_close_table(SQL_HANDLER *handler)
{
/* Must be a temporary table */
table->file->ha_index_or_rnd_end();
table->query_id= thd->query_id;
table->open_by_handler= 0;
mark_tmp_table_for_reuse(table);
thd->mark_tmp_table_as_free_for_reuse(table);
}
my_free(handler->lock);
handler->init();
@ -294,7 +293,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen)
open_ltable() or open_table() because we would like to be able
to open a temporary table.
*/
error= (open_temporary_tables(thd, tables) ||
error= (thd->open_temporary_tables(tables) ||
open_tables(thd, &tables, &counter, 0));
if (error)
@ -389,8 +388,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen)
/*
Assert that the above check prevents opening of views and merge tables.
For temporary tables, TABLE::next can be set even if only one table
was opened for HANDLER as it is used to link them together
(see thd->temporary_tables).
was opened for HANDLER as it is used to link them together.
*/
DBUG_ASSERT(sql_handler->table->next == NULL ||
sql_handler->table->s->tmp_table);
@ -1195,10 +1193,10 @@ void mysql_ha_set_explicit_lock_duration(THD *thd)
Remove temporary tables from the HANDLER's hash table. The reason
for having a separate function, rather than calling
mysql_ha_rm_tables() is that it is not always feasible (e.g. in
close_temporary_tables) to obtain a TABLE_LIST containing the
THD::close_temporary_tables) to obtain a TABLE_LIST containing the
temporary tables.
@See close_temporary_tables
@See THD::close_temporary_tables()
@param thd Thread identifier.
*/
void mysql_ha_rm_temporary_tables(THD *thd)

View File

@ -4078,7 +4078,12 @@ static TABLE *create_table_from_items(THD *thd,
}
else
{
if (open_temporary_table(thd, create_table))
/*
The pointer to the newly created temporary table has been stored in
table->create_info.
*/
create_table->table= create_info->table;
if (!create_table->table)
{
/*
This shouldn't happen as creation of temporary table should make
@ -4087,7 +4092,6 @@ static TABLE *create_table_from_items(THD *thd,
*/
DBUG_ASSERT(0);
}
DBUG_ASSERT(create_table->table == create_info->table);
}
}
else
@ -4461,6 +4465,7 @@ void select_create::abort_result_set()
if (table)
{
bool tmp_table= table->s->tmp_table;
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
table->auto_increment_field_not_null= FALSE;

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
Copyright (c) 2008, 2015, MariaDB
Copyright (c) 2008, 2016, MariaDB Corporation
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
@ -23,7 +23,10 @@
// set_handler_table_locks,
// lock_global_read_lock,
// make_global_read_lock_block_commit
#include "sql_base.h" // find_temporary_table
#include "sql_base.h" // open_tables, open_and_lock_tables,
// lock_tables, unique_table,
// close_thread_tables, is_temporary_table
// table_cache.h
#include "sql_cache.h" // QUERY_CACHE_FLAGS_SIZE, query_cache_*
#include "sql_show.h" // mysqld_list_*, mysqld_show_*,
// calc_sum_of_all_status
@ -418,7 +421,7 @@ static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables)
for (TABLE_LIST *table= tables; table; table= table->next_global)
{
DBUG_ASSERT(table->db && table->table_name);
if (table->updating && !find_temporary_table(thd, table))
if (table->updating && !thd->find_tmp_table_share(table))
return 1;
}
return 0;
@ -1967,7 +1970,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->set_query(fields, query_length);
general_log_print(thd, command, "%s %s", table_list.table_name, fields);
if (open_temporary_tables(thd, &table_list))
if (thd->open_temporary_tables(&table_list))
break;
if (check_table_access(thd, SELECT_ACL, &table_list,
@ -3264,7 +3267,7 @@ mysql_execute_command(THD *thd)
*/
if (sql_command_flags[lex->sql_command] & CF_PREOPEN_TMP_TABLES)
{
if (open_temporary_tables(thd, all_tables))
if (thd->open_temporary_tables(all_tables))
goto error;
}
@ -4066,7 +4069,7 @@ end_with_restore_list:
Temporary tables should be opened for SHOW CREATE TABLE, but not
for SHOW CREATE VIEW.
*/
if (open_temporary_tables(thd, all_tables))
if (thd->open_temporary_tables(all_tables))
goto error;
/*
@ -4274,7 +4277,8 @@ end_with_restore_list:
*/
if (first_table->lock_type != TL_WRITE_DELAYED)
{
if ((res= open_temporary_tables(thd, all_tables)))
res= (thd->open_temporary_tables(all_tables)) ? TRUE : FALSE;
if (res)
break;
}
@ -4586,7 +4590,7 @@ end_with_restore_list:
{
if (!lex->tmp_table() &&
(!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, table)))
!thd->find_temporary_table(table)))
{
WSREP_TO_ISOLATION_BEGIN(NULL, NULL, all_tables);
break;
@ -4739,7 +4743,7 @@ end_with_restore_list:
CF_PREOPEN_TMP_TABLES was set and the tables would be pre-opened
in a usual way, they would have been closed.
*/
if (open_temporary_tables(thd, all_tables))
if (thd->open_temporary_tables(all_tables))
goto error;
if (lock_tables_precheck(thd, all_tables))
@ -6780,7 +6784,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
/*
Open temporary tables to be able to detect them during privilege check.
*/
if (open_temporary_tables(thd, dst_table))
if (thd->open_temporary_tables(dst_table))
return TRUE;
if (check_access(thd, SELECT_ACL, dst_table->db,

View File

@ -1,5 +1,6 @@
/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2014, SkySQL Ab.
Copyright (c) 2016, MariaDB Corporation
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
@ -534,12 +535,9 @@ bool Sql_cmd_alter_table_exchange_partition::
#ifdef WITH_WSREP
if (WSREP_ON)
{
/* Forward declaration */
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
if ((!thd->is_current_stmt_binlog_format_row() ||
/* TODO: Do we really need to check for temp tables in this case? */
!find_temporary_table(thd, table_list)) &&
!thd->find_temporary_table(table_list)) &&
wsrep_to_isolation_begin(thd, table_list->db, table_list->table_name,
NULL))
{
@ -783,11 +781,9 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
DBUG_RETURN(TRUE);
#ifdef WITH_WSREP
/* Forward declaration */
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
if (WSREP(thd) && (!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, first_table)) &&
if (WSREP(thd) &&
(!thd->is_current_stmt_binlog_format_row() ||
!thd->find_temporary_table(first_table)) &&
wsrep_to_isolation_begin(
thd, first_table->db, first_table->table_name, NULL)
)

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates.
Copyright (c) 2008, 2015, MariaDB
Copyright (c) 2008, 2016, MariaDB
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
@ -1259,7 +1259,7 @@ static bool mysql_test_insert(Prepared_statement *stmt,
*/
if (table_list->lock_type != TL_WRITE_DELAYED)
{
if (open_temporary_tables(thd, table_list))
if (thd->open_temporary_tables(table_list))
goto error;
}
@ -2028,7 +2028,7 @@ static bool mysql_test_create_view(Prepared_statement *stmt)
Since we can't pre-open temporary tables for SQLCOM_CREATE_VIEW,
(see mysql_create_view) we have to do it here instead.
*/
if (open_temporary_tables(thd, tables))
if (thd->open_temporary_tables(tables))
goto err;
if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL,
@ -2280,7 +2280,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
*/
if (sql_command_flags[sql_command] & CF_PREOPEN_TMP_TABLES)
{
if (open_temporary_tables(thd, tables))
if (thd->open_temporary_tables(tables))
goto error;
}

View File

@ -4155,7 +4155,7 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
'only_view_structure()'.
*/
lex->sql_command= SQLCOM_SHOW_FIELDS;
result= (open_temporary_tables(thd, table_list) ||
result= (thd->open_temporary_tables(table_list) ||
open_normal_and_derived_tables(thd, table_list,
(MYSQL_OPEN_IGNORE_FLUSH |
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
@ -4218,6 +4218,7 @@ end:
all tables open within this Open_tables_state.
*/
thd->temporary_tables= NULL;
close_thread_tables(thd);
/*
Release metadata lock we might have acquired.

View File

@ -25,7 +25,7 @@
#include "sql_table.h"
#include "sql_parse.h" // test_if_data_home_dir
#include "sql_cache.h" // query_cache_*
#include "sql_base.h" // open_table_uncached, lock_table_names
#include "sql_base.h" // lock_table_names
#include "lock.h" // mysql_unlock_tables
#include "strfunc.h" // find_type2, find_set
#include "sql_truncate.h" // regenerate_locked_table
@ -2030,7 +2030,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
LEX_STRING db_name= { table->db, table->db_length };
LEX_STRING table_name= { table->table_name, table->table_name_length };
if (table->open_type == OT_BASE_ONLY ||
!find_temporary_table(thd, table))
!thd->find_temporary_table(table))
(void) delete_statistics_for_table(thd, &db_name, &table_name);
}
}
@ -2283,23 +2283,17 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
*/
DBUG_ASSERT(!(thd->locked_tables_mode &&
table->open_type != OT_BASE_ONLY &&
find_temporary_table(thd, table) &&
thd->find_temporary_table(table) &&
table->mdl_request.ticket != NULL));
/*
drop_temporary_table may return one of the following error codes:
. 0 - a temporary table was successfully dropped.
. 1 - a temporary table was not found.
. -1 - a temporary table is used by an outer statement.
*/
if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table))
error= 1;
else
{
table_creation_was_logged= table->table->s->table_creation_was_logged;
if ((error= drop_temporary_table(thd, table->table, &is_trans)) == -1)
if (thd->drop_temporary_table(table->table, &is_trans, true))
{
DBUG_ASSERT(thd->in_sub_stmt);
error= 1;
goto err;
}
table->table= 0;
@ -4635,7 +4629,8 @@ err:
which was created.
@param[out] key_count Number of keys in table which was created.
If one creates a temporary table, this is automatically opened
If one creates a temporary table, its is automatically opened and its
TABLE_SHARE is added to THD::all_temp_tables list.
Note that this function assumes that caller already have taken
exclusive metadata lock on table being created or used some other
@ -4695,20 +4690,22 @@ int create_table_impl(THD *thd,
/* Check if table exists */
if (create_info->tmp_table())
{
TABLE *tmp_table;
if (find_and_use_temporary_table(thd, db, table_name, &tmp_table))
goto err;
/*
If a table exists, it must have been pre-opened. Try looking for one
in-use in THD::all_temp_tables list of TABLE_SHAREs.
*/
TABLE *tmp_table= thd->find_temporary_table(db, table_name);
if (tmp_table)
{
bool table_creation_was_logged= tmp_table->s->table_creation_was_logged;
if (options.or_replace())
{
bool tmp;
/*
We are using CREATE OR REPLACE on an existing temporary table
Remove the old table so that we can re-create it.
*/
if (drop_temporary_table(thd, tmp_table, &tmp))
if (thd->drop_temporary_table(tmp_table, NULL, true))
goto err;
}
else if (options.if_not_exists())
@ -4847,17 +4844,12 @@ int create_table_impl(THD *thd,
create_info->table= 0;
if (!frm_only && create_info->tmp_table())
{
/*
Open a table (skipping table cache) and add it into
THD::temporary_tables list.
*/
TABLE *table= open_table_uncached(thd, create_info->db_type, frm, path,
db, table_name, true, true);
TABLE *table= thd->create_and_open_tmp_table(create_info->db_type, frm,
path, db, table_name, true);
if (!table)
{
(void) rm_temporary_table(create_info->db_type, path);
(void) thd->rm_temporary_table(create_info->db_type, path);
goto err;
}
@ -7143,7 +7135,8 @@ static bool mysql_inplace_alter_table(THD *thd,
HA_EXTRA_NOT_USED,
NULL);
table_list->table= table= NULL;
close_temporary_table(thd, altered_table, true, false);
thd->drop_temporary_table(altered_table, NULL, false);
/*
Replace the old .FRM with the new .FRM, but keep the old name for now.
@ -7233,7 +7226,7 @@ static bool mysql_inplace_alter_table(THD *thd,
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
/* QQ; do something about metadata locks ? */
}
close_temporary_table(thd, altered_table, true, false);
thd->drop_temporary_table(altered_table, NULL, false);
// Delete temporary .frm/.par
(void) quick_rm_table(thd, create_info->db_type, alter_ctx->new_db,
alter_ctx->tmp_name, FN_IS_TMP | NO_HA_TABLE);
@ -8385,7 +8378,12 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (table->s->tmp_table != NO_TMP_TABLE)
{
if (find_temporary_table(thd, alter_ctx.new_db, alter_ctx.new_name))
/*
Check whether a temporary table exists with same requested new name.
If such table exists, there must be a corresponding TABLE_SHARE in
THD::all_temp_tables list.
*/
if (thd->find_tmp_table_share(alter_ctx.new_db, alter_ctx.new_name))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alter_ctx.new_alias);
DBUG_RETURN(true);
@ -8821,11 +8819,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
// We assume that the table is non-temporary.
DBUG_ASSERT(!table->s->tmp_table);
if (!(altered_table= open_table_uncached(thd, new_db_type, &frm,
alter_ctx.get_tmp_path(),
alter_ctx.new_db,
alter_ctx.tmp_name,
true, false)))
if (!(altered_table=
thd->create_and_open_tmp_table(new_db_type, &frm,
alter_ctx.get_tmp_path(),
alter_ctx.new_db, alter_ctx.tmp_name,
false)))
goto err_new_table_cleanup;
/* Set markers for fields in TABLE object for altered table. */
@ -8865,7 +8863,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
ha_alter_info.report_unsupported_error("LOCK=NONE/SHARED",
"LOCK=EXCLUSIVE");
close_temporary_table(thd, altered_table, true, false);
thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup;
}
break;
@ -8876,7 +8874,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
Alter_info::ALTER_TABLE_LOCK_NONE)
{
ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
close_temporary_table(thd, altered_table, true, false);
thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup;
}
break;
@ -8890,7 +8888,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
ha_alter_info.report_unsupported_error("ALGORITHM=INPLACE",
"ALGORITHM=COPY");
close_temporary_table(thd, altered_table, true, false);
thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup;
}
// COPY with LOCK=NONE is not supported, no point in trying.
@ -8898,7 +8896,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
Alter_info::ALTER_TABLE_LOCK_NONE)
{
ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
close_temporary_table(thd, altered_table, true, false);
thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup;
}
// Otherwise use COPY
@ -8906,7 +8904,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
break;
case HA_ALTER_ERROR:
default:
close_temporary_table(thd, altered_table, true, false);
thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup;
}
@ -8925,7 +8923,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
else
{
close_temporary_table(thd, altered_table, true, false);
thd->drop_temporary_table(altered_table, NULL, false);
}
}
@ -8978,13 +8976,18 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (create_info->tmp_table())
{
if (!open_table_uncached(thd, new_db_type, &frm,
alter_ctx.get_tmp_path(),
alter_ctx.new_db, alter_ctx.tmp_name,
true, true))
TABLE *tmp_table=
thd->create_and_open_tmp_table(new_db_type, &frm,
alter_ctx.get_tmp_path(),
alter_ctx.new_db, alter_ctx.tmp_name,
true);
if (!tmp_table)
{
goto err_new_table_cleanup;
}
}
/* Open the table since we need to copy the data. */
if (table->s->tmp_table != NO_TMP_TABLE)
{
@ -8992,18 +8995,24 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
tbl.init_one_table(alter_ctx.new_db, strlen(alter_ctx.new_db),
alter_ctx.tmp_name, strlen(alter_ctx.tmp_name),
alter_ctx.tmp_name, TL_READ_NO_INSERT);
/* Table is in thd->temporary_tables */
(void) open_temporary_table(thd, &tbl);
/*
Table can be found in the list of open tables in THD::all_temp_tables
list.
*/
tbl.table= thd->find_temporary_table(&tbl);
new_table= tbl.table;
}
else
{
/* table is a normal table: Create temporary table in same directory */
/* Open our intermediate table. */
new_table= open_table_uncached(thd, new_db_type, &frm,
alter_ctx.get_tmp_path(),
alter_ctx.new_db, alter_ctx.tmp_name,
true, true);
/*
table is a normal table: Create temporary table in same directory.
Open our intermediate table.
*/
new_table=
thd->create_and_open_tmp_table(new_db_type, &frm,
alter_ctx.get_tmp_path(),
alter_ctx.new_db, alter_ctx.tmp_name,
true);
}
if (!new_table)
goto err_new_table_cleanup;
@ -9071,10 +9080,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
new_table->s->table_creation_was_logged=
table->s->table_creation_was_logged;
/* Remove link to old table and rename the new one */
close_temporary_table(thd, table, true, true);
thd->drop_temporary_table(table, NULL, true);
/* Should pass the 'new_name' as we store table name in the cache */
if (rename_temporary_table(thd, new_table,
alter_ctx.new_db, alter_ctx.new_name))
if (thd->rename_temporary_table(new_table, alter_ctx.new_db,
alter_ctx.new_name))
goto err_new_table_cleanup;
/* We don't replicate alter table statement on temporary tables */
if (!thd->is_current_stmt_binlog_format_row() &&
@ -9086,10 +9095,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
/*
Close the intermediate table that will be the new table, but do
not delete it! Even altough MERGE tables do not have their children
attached here it is safe to call close_temporary_table().
not delete it! Even though MERGE tables do not have their children
attached here it is safe to call THD::drop_temporary_table().
*/
close_temporary_table(thd, new_table, true, false);
thd->drop_temporary_table(new_table, NULL, false);
new_table= NULL;
DEBUG_SYNC(thd, "alter_table_before_rename_result_table");
@ -9231,8 +9240,7 @@ err_new_table_cleanup:
my_free(const_cast<uchar*>(frm.str));
if (new_table)
{
/* close_temporary_table() frees the new_table pointer. */
close_temporary_table(thd, new_table, true, true);
thd->drop_temporary_table(new_table, NULL, true);
}
else
(void) quick_rm_table(thd, new_db_type,
@ -9732,7 +9740,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
/* Allow to open real tables only. */
table->required_type= FRMTYPE_TABLE;
if (open_temporary_tables(thd, table) ||
if (thd->open_temporary_tables(table) ||
open_and_lock_tables(thd, table, FALSE, 0))
{
t= NULL;

View File

@ -82,7 +82,7 @@ static my_bool print_cached_tables_callback(TDC_element *element,
TABLE *entry;
mysql_mutex_lock(&element->LOCK_table_share);
TDC_element::All_share_tables_list::Iterator it(element->all_tables);
All_share_tables_list::Iterator it(element->all_tables);
while ((entry= it++))
{
THD *in_use= entry->in_use;

View File

@ -24,7 +24,7 @@
#include "sql_parse.h" // parse_sql
#include "parse_file.h"
#include "sp.h"
#include "sql_base.h" // find_temporary_table
#include "sql_base.h"
#include "sql_show.h" // append_definer, append_identifier
#include "sql_table.h" // build_table_filename,
// check_n_cut_mysql50_prefix
@ -507,7 +507,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
DBUG_ASSERT(tables->next_global == 0);
/* We do not allow creation of triggers on temporary tables. */
if (create && find_temporary_table(thd, tables))
if (create && thd->find_tmp_table_share(tables))
{
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
goto end;

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2004, 2013, Oracle and/or its affiliates.
Copyright (c) 2011, 2015, MariaDB
Copyright (c) 2011, 2016, MariaDB Corporation
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
@ -429,7 +429,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
lex->link_first_table_back(view, link_to_local);
view->open_type= OT_BASE_ONLY;
if (open_temporary_tables(thd, lex->query_tables) ||
if (thd->open_temporary_tables(lex->query_tables) ||
open_and_lock_tables(thd, lex->query_tables, TRUE, 0))
{
view= lex->unlink_first_table(&link_to_local);

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates.
Copyright (c) 2012, 2015, MariaDB
Copyright (c) 2012, 2016, MariaDB Corporation
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
@ -477,7 +477,8 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var)
switching @@SESSION.binlog_format from MIXED to STATEMENT when there are
open temp tables and we are logging in row format.
*/
if (thd->temporary_tables && var->type == OPT_SESSION &&
if (thd->has_thd_temporary_tables() &&
var->type == OPT_SESSION &&
var->save_result.ulonglong_value == BINLOG_FORMAT_STMT &&
((thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
thd->is_current_stmt_binlog_format_row()) ||

View File

@ -3922,7 +3922,7 @@ bool TABLE_SHARE::visit_subgraph(Wait_for_flush *wait_for_flush,
tdc->all_tables_refs++;
mysql_mutex_unlock(&tdc->LOCK_table_share);
TDC_element::All_share_tables_list::Iterator tables_it(tdc->all_tables);
All_share_tables_list::Iterator tables_it(tdc->all_tables);
/*
In case of multiple searches running in parallel, avoid going

View File

@ -2,6 +2,7 @@
#define TABLE_INCLUDED
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2009, 2014, SkySQL Ab.
Copyright (c) 2016, MariaDB Corporation
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
@ -1012,7 +1013,7 @@ private:
One should use methods of I_P_List template instead.
*/
TABLE *share_all_next, **share_all_prev;
friend struct TDC_element;
friend struct All_share_tables;
public:
@ -1435,6 +1436,19 @@ struct TABLE_share
}
};
struct All_share_tables
{
static inline TABLE **next_ptr(TABLE *l)
{
return &l->share_all_next;
}
static inline TABLE ***prev_ptr(TABLE *l)
{
return &l->share_all_prev;
}
};
typedef I_P_List <TABLE, All_share_tables> All_share_tables_list;
enum enum_schema_table_state
{
@ -2662,15 +2676,6 @@ inline bool is_infoschema_db(const char *name)
TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings);
/**
return true if the table was created explicitly.
*/
inline bool is_user_table(TABLE * table)
{
const char *name= table->s->table_name.str;
return strncmp(name, tmp_file_prefix, tmp_file_prefix_length);
}
inline void mark_as_null_row(TABLE *table)
{
table->null_row=1;

View File

@ -965,7 +965,7 @@ void tdc_release_share(TABLE_SHARE *share)
static void kill_delayed_threads_for_table(TDC_element *element)
{
TDC_element::All_share_tables_list::Iterator it(element->all_tables);
All_share_tables_list::Iterator it(element->all_tables);
TABLE *tab;
mysql_mutex_assert_owner(&element->LOCK_table_share);
@ -1086,7 +1086,7 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
if (remove_type == TDC_RT_REMOVE_NOT_OWN ||
remove_type == TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE)
{
TDC_element::All_share_tables_list::Iterator it(element->all_tables);
All_share_tables_list::Iterator it(element->all_tables);
while ((table= it++))
{
my_refs++;

View File

@ -27,9 +27,6 @@ struct TDC_element
TABLE_SHARE *share;
typedef I_P_List <TABLE, TABLE_share> TABLE_list;
typedef I_P_List <TABLE, I_P_List_adapter<TABLE, &TABLE::share_all_next,
&TABLE::share_all_prev> >
All_share_tables_list;
/**
Protects ref_count, m_flush_tickets, all_tables, free_tables, flushed,
all_tables_refs.

1499
sql/temporary_tables.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,6 @@ err:
#include "transaction.h" // trans_commit(), trans_rollback()
#include "rpl_rli.h" // class Relay_log_info;
#include "sql_base.h" // close_temporary_table()
void wsrep_set_apply_format(THD* thd, Format_description_log_event* ev)
{
@ -277,14 +276,11 @@ wsrep_cb_status_t wsrep_apply_cb(void* const ctx,
wsrep_dump_rbr_buf_with_header(thd, buf, buf_len);
}
TABLE *tmp;
while ((tmp = thd->temporary_tables))
if (thd->has_thd_temporary_tables())
{
WSREP_DEBUG("Applier %lld, has temporary tables: %s.%s",
(longlong) thd->thread_id,
(tmp->s) ? tmp->s->db.str : "void",
(tmp->s) ? tmp->s->table_name.str : "void");
close_temporary_table(thd, tmp, 1, 1);
WSREP_DEBUG("Applier %lld has temporary tables. Closing them now..",
thd->thread_id);
thd->close_temporary_tables();
}
return rcode;

View File

@ -1085,8 +1085,6 @@ static bool wsrep_prepare_keys_for_isolation(THD* thd,
ka->keys= 0;
ka->keys_len= 0;
extern TABLE* find_temporary_table(THD*, const TABLE_LIST*);
if (db || table)
{
TABLE_LIST tmp_table;
@ -1098,7 +1096,7 @@ static bool wsrep_prepare_keys_for_isolation(THD* thd,
(table) ? table : "",
MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT);
if (!table || !find_temporary_table(thd, &tmp_table))
if (!table || !thd->find_temporary_table(&tmp_table))
{
if (!(ka->keys= (wsrep_key_t*)my_malloc(sizeof(wsrep_key_t), MYF(0))))
{
@ -1126,7 +1124,7 @@ static bool wsrep_prepare_keys_for_isolation(THD* thd,
for (const TABLE_LIST* table= table_list; table; table= table->next_global)
{
if (!find_temporary_table(thd, table))
if (!thd->find_temporary_table(table))
{
wsrep_key_t* tmp;
tmp= (wsrep_key_t*)my_realloc(
@ -2443,26 +2441,13 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
TABLE_LIST* src_table,
HA_CREATE_INFO *create_info)
{
TABLE *tmp_table;
bool is_tmp_table= FALSE;
for (tmp_table= thd->temporary_tables; tmp_table; tmp_table=tmp_table->next)
{
if (!strcmp(src_table->db, tmp_table->s->db.str) &&
!strcmp(src_table->table_name, tmp_table->s->table_name.str))
{
is_tmp_table= TRUE;
break;
}
}
if (create_info->tmp_table())
{
/* CREATE TEMPORARY TABLE LIKE must be skipped from replication */
WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s",
thd->query());
}
else if (!is_tmp_table)
else if (!(thd->find_temporary_table(src_table)))
{
/* this is straight CREATE TABLE LIKE... eith no tmp tables */
WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL);
@ -2477,7 +2462,7 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
bzero((void*) &tbl, sizeof(tbl));
tbl.db= src_table->db;
tbl.table_name= tbl.alias= src_table->table_name;
tbl.table= tmp_table;
tbl.table= src_table->table;
char buf[2048];
String query(buf, sizeof(buf), system_charset_info);
query.length(0); // Have to zero it since constructor doesn't

View File

@ -360,13 +360,10 @@ static void wsrep_replication_process(THD *thd)
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
TABLE *tmp;
while ((tmp = thd->temporary_tables))
if(thd->has_thd_temporary_tables())
{
WSREP_WARN("Applier %lld, has temporary tables at exit: %s.%s",
(longlong) thd->thread_id,
(tmp->s) ? tmp->s->db.str : "void",
(tmp->s) ? tmp->s->table_name.str : "void");
WSREP_WARN("Applier %lld has temporary tables at exit.",
thd->thread_id);
}
wsrep_return_from_bf_mode(thd, &shadow);
DBUG_VOID_RETURN;

View File

@ -1640,7 +1640,7 @@ long long spider_direct_sql_body(
table_list.table_name = direct_sql->table_names[roop_count];
#endif
if (!(direct_sql->tables[roop_count] =
find_temporary_table(thd, &table_list)))
thd->find_temporary_table(&table_list)))
{
#if MYSQL_VERSION_ID < 50500
#else