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:
parent
547511153f
commit
7305be2f7e
@ -111,6 +111,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
|||||||
../sql/wsrep_dummy.cc ../sql/encryption.cc
|
../sql/wsrep_dummy.cc ../sql/encryption.cc
|
||||||
../sql/item_windowfunc.cc ../sql/sql_window.cc
|
../sql/item_windowfunc.cc ../sql/sql_window.cc
|
||||||
../sql/sql_cte.cc
|
../sql/sql_cte.cc
|
||||||
|
../sql/temporary_tables.cc
|
||||||
${GEN_SOURCES}
|
${GEN_SOURCES}
|
||||||
${MYSYS_LIBWRAP_SOURCE}
|
${MYSYS_LIBWRAP_SOURCE}
|
||||||
)
|
)
|
||||||
|
@ -1736,7 +1736,8 @@ drop view t1;
|
|||||||
create table t1 (a int) select 1 as a;
|
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;
|
||||||
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;
|
select * from t1;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
|
@ -380,12 +380,7 @@ alter table t1 add column j int;
|
|||||||
unlock tables;
|
unlock tables;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create temporary table t1 (i int);
|
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;
|
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;
|
alter table t1 add column j int;
|
||||||
unlock tables;
|
unlock tables;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
133
mysql-test/r/reopen_temp_table.result
Normal file
133
mysql-test/r/reopen_temp_table.result
Normal 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;
|
@ -1140,9 +1140,12 @@ insert into t3 values (1), (2), (3);
|
|||||||
return (select count(*) from t3 as a, t3 as b);
|
return (select count(*) from t3 as a, t3 as b);
|
||||||
end|
|
end|
|
||||||
select f11()|
|
select f11()|
|
||||||
ERROR HY000: Can't reopen table: 'a'
|
f11()
|
||||||
|
9
|
||||||
select f11() from t1|
|
select f11() from t1|
|
||||||
ERROR HY000: Can't reopen table: 'a'
|
f11()
|
||||||
|
9
|
||||||
|
9
|
||||||
create function f12_1() returns int
|
create function f12_1() returns int
|
||||||
begin
|
begin
|
||||||
drop temporary table if exists t3;
|
drop temporary table if exists t3;
|
||||||
@ -1156,6 +1159,7 @@ drop temporary table t3|
|
|||||||
select f12_1()|
|
select f12_1()|
|
||||||
f12_1()
|
f12_1()
|
||||||
3
|
3
|
||||||
|
drop temporary table t3|
|
||||||
select f12_1() from t1 limit 1|
|
select f12_1() from t1 limit 1|
|
||||||
f12_1()
|
f12_1()
|
||||||
3
|
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 ) ;
|
CREATE PROCEDURE p1 () BEGIN SELECT f1 FROM t3 AS A WHERE A.f1 IN ( SELECT f1 FROM t3 ) ;
|
||||||
END|
|
END|
|
||||||
CALL p1;
|
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 );
|
CREATE VIEW t3 AS SELECT f1 FROM t2 A WHERE A.f1 IN ( SELECT f1 FROM t2 );
|
||||||
DROP TABLE t3;
|
DROP TABLE t3;
|
||||||
CALL p1;
|
CALL p1;
|
||||||
|
@ -632,7 +632,18 @@ handler a1 read a next;
|
|||||||
a b
|
a b
|
||||||
3 d
|
3 d
|
||||||
select a,b from t1;
|
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;
|
handler a1 read a prev;
|
||||||
a b
|
a b
|
||||||
2 c
|
2 c
|
||||||
@ -745,7 +756,7 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
|
|||||||
handler t2 close;
|
handler t2 close;
|
||||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||||
handler t3 open;
|
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
|
# After UNLOCK TABLES handlers should be around and
|
||||||
# we should be able to continue reading through them.
|
# we should be able to continue reading through them.
|
||||||
unlock tables;
|
unlock tables;
|
||||||
@ -1396,7 +1407,12 @@ handler t2 read a next;
|
|||||||
a b
|
a b
|
||||||
3 NULL
|
3 NULL
|
||||||
select * from t2;
|
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;
|
handler t2 read a next;
|
||||||
a b
|
a b
|
||||||
4 NULL
|
4 NULL
|
||||||
|
@ -460,9 +460,6 @@ drop table t1;
|
|||||||
#
|
#
|
||||||
# Bug#30882 Dropping a temporary table inside a stored function may cause a server crash
|
# 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));
|
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"),
|
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=(1);
|
||||||
handler a1 read a next;
|
handler a1 read a next;
|
||||||
handler a1 read a next;
|
handler a1 read a next;
|
||||||
--error ER_CANT_REOPEN_TABLE
|
|
||||||
select a,b from t1;
|
select a,b from t1;
|
||||||
handler a1 read a prev;
|
handler a1 read a prev;
|
||||||
handler a1 read a prev;
|
handler a1 read a prev;
|
||||||
@ -564,7 +560,7 @@ handler t1 open;
|
|||||||
handler t1 read next;
|
handler t1 read next;
|
||||||
--error ER_LOCK_OR_ACTIVE_TRANSACTION
|
--error ER_LOCK_OR_ACTIVE_TRANSACTION
|
||||||
handler t2 close;
|
handler t2 close;
|
||||||
--error ER_CANT_REOPEN_TABLE
|
--error ER_LOCK_OR_ACTIVE_TRANSACTION
|
||||||
handler t3 open;
|
handler t3 open;
|
||||||
--echo # After UNLOCK TABLES handlers should be around and
|
--echo # After UNLOCK TABLES handlers should be around and
|
||||||
--echo # we should be able to continue reading through them.
|
--echo # we should be able to continue reading through them.
|
||||||
@ -1182,7 +1178,6 @@ handler t1 read a next;
|
|||||||
select * from t1;
|
select * from t1;
|
||||||
--echo # Sic: the position is not lost
|
--echo # Sic: the position is not lost
|
||||||
handler t2 read a next;
|
handler t2 read a next;
|
||||||
--error ER_CANT_REOPEN_TABLE
|
|
||||||
select * from t2;
|
select * from t2;
|
||||||
handler t2 read a next;
|
handler t2 read a next;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -632,7 +632,18 @@ handler a1 read a next;
|
|||||||
a b
|
a b
|
||||||
3 d
|
3 d
|
||||||
select a,b from t1;
|
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;
|
handler a1 read a prev;
|
||||||
a b
|
a b
|
||||||
2 c
|
2 c
|
||||||
@ -745,7 +756,7 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
|
|||||||
handler t2 close;
|
handler t2 close;
|
||||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||||
handler t3 open;
|
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
|
# After UNLOCK TABLES handlers should be around and
|
||||||
# we should be able to continue reading through them.
|
# we should be able to continue reading through them.
|
||||||
unlock tables;
|
unlock tables;
|
||||||
@ -1396,7 +1407,12 @@ handler t2 read a next;
|
|||||||
a b
|
a b
|
||||||
3 NULL
|
3 NULL
|
||||||
select * from t2;
|
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;
|
handler t2 read a next;
|
||||||
a b
|
a b
|
||||||
4 NULL
|
4 NULL
|
||||||
|
@ -633,7 +633,18 @@ handler a1 read a next;
|
|||||||
a b
|
a b
|
||||||
3 d
|
3 d
|
||||||
select a,b from t1;
|
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;
|
handler a1 read a prev;
|
||||||
a b
|
a b
|
||||||
2 c
|
2 c
|
||||||
@ -747,7 +758,7 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
|
|||||||
handler t2 close;
|
handler t2 close;
|
||||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||||
handler t3 open;
|
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
|
# After UNLOCK TABLES handlers should be around and
|
||||||
# we should be able to continue reading through them.
|
# we should be able to continue reading through them.
|
||||||
unlock tables;
|
unlock tables;
|
||||||
@ -1400,7 +1411,12 @@ handler t2 read a next;
|
|||||||
a b
|
a b
|
||||||
3 NULL
|
3 NULL
|
||||||
select * from t2;
|
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;
|
handler t2 read a next;
|
||||||
a b
|
a b
|
||||||
4 NULL
|
4 NULL
|
||||||
|
@ -632,7 +632,18 @@ handler a1 read a next;
|
|||||||
a b
|
a b
|
||||||
3 d
|
3 d
|
||||||
select a,b from t1;
|
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;
|
handler a1 read a prev;
|
||||||
a b
|
a b
|
||||||
2 c
|
2 c
|
||||||
@ -745,7 +756,7 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
|
|||||||
handler t2 close;
|
handler t2 close;
|
||||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||||
handler t3 open;
|
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
|
# After UNLOCK TABLES handlers should be around and
|
||||||
# we should be able to continue reading through them.
|
# we should be able to continue reading through them.
|
||||||
unlock tables;
|
unlock tables;
|
||||||
@ -1396,7 +1407,12 @@ handler t2 read a next;
|
|||||||
a b
|
a b
|
||||||
3 NULL
|
3 NULL
|
||||||
select * from t2;
|
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;
|
handler t2 read a next;
|
||||||
a b
|
a b
|
||||||
4 NULL
|
4 NULL
|
||||||
|
30
mysql-test/suite/rpl/r/rpl_reopen_temp_table.result
Normal file
30
mysql-test/suite/rpl/r/rpl_reopen_temp_table.result
Normal 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
|
43
mysql-test/suite/rpl/t/rpl_reopen_temp_table.test
Normal file
43
mysql-test/suite/rpl/t/rpl_reopen_temp_table.test
Normal 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
|
@ -1618,7 +1618,6 @@ drop view t1;
|
|||||||
|
|
||||||
create table t1 (a int) select 1 as a;
|
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 ER_CANT_REOPEN_TABLE
|
|
||||||
create temporary table if not exists t1 (a int) select * from t1;
|
create temporary table if not exists t1 (a int) select * from t1;
|
||||||
select * from t1;
|
select * from t1;
|
||||||
drop temporary table t1;
|
drop temporary table t1;
|
||||||
|
@ -442,11 +442,6 @@ alter table t1 add column j int;
|
|||||||
unlock tables;
|
unlock tables;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create temporary table t1 (i int);
|
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;
|
lock tables t1 write, t1 as a read, t1 as b read;
|
||||||
alter table t1 add column j int;
|
alter table t1 add column j int;
|
||||||
unlock tables;
|
unlock tables;
|
||||||
|
128
mysql-test/t/reopen_temp_table.test
Normal file
128
mysql-test/t/reopen_temp_table.test
Normal 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;
|
@ -1368,11 +1368,6 @@ select f10()|
|
|||||||
create table t4 as select 1 as id|
|
create table t4 as select 1 as id|
|
||||||
select f10()|
|
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
|
create function f11() returns int
|
||||||
begin
|
begin
|
||||||
drop temporary table if exists t3;
|
drop temporary table if exists t3;
|
||||||
@ -1380,9 +1375,7 @@ begin
|
|||||||
insert into t3 values (1), (2), (3);
|
insert into t3 values (1), (2), (3);
|
||||||
return (select count(*) from t3 as a, t3 as b);
|
return (select count(*) from t3 as a, t3 as b);
|
||||||
end|
|
end|
|
||||||
--error ER_CANT_REOPEN_TABLE
|
|
||||||
select f11()|
|
select f11()|
|
||||||
--error ER_CANT_REOPEN_TABLE
|
|
||||||
select f11() from t1|
|
select f11() from t1|
|
||||||
# Test that using a single table instance at a time works
|
# Test that using a single table instance at a time works
|
||||||
create function f12_1() returns int
|
create function f12_1() returns int
|
||||||
@ -1397,6 +1390,7 @@ create function f12_2() returns int
|
|||||||
|
|
||||||
drop temporary table t3|
|
drop temporary table t3|
|
||||||
select f12_1()|
|
select f12_1()|
|
||||||
|
drop temporary table t3|
|
||||||
select f12_1() from t1 limit 1|
|
select f12_1() from t1 limit 1|
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
@ -8278,7 +8272,6 @@ delimiter |;
|
|||||||
CREATE PROCEDURE p1 () BEGIN SELECT f1 FROM t3 AS A WHERE A.f1 IN ( SELECT f1 FROM t3 ) ;
|
CREATE PROCEDURE p1 () BEGIN SELECT f1 FROM t3 AS A WHERE A.f1 IN ( SELECT f1 FROM t3 ) ;
|
||||||
END|
|
END|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
--error ER_CANT_REOPEN_TABLE
|
|
||||||
CALL p1;
|
CALL p1;
|
||||||
CREATE VIEW t3 AS SELECT f1 FROM t2 A WHERE A.f1 IN ( SELECT f1 FROM t2 );
|
CREATE VIEW t3 AS SELECT f1 FROM t2 A WHERE A.f1 IN ( SELECT f1 FROM t2 );
|
||||||
DROP TABLE t3;
|
DROP TABLE t3;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Copyright (c) 2006, 2014, Oracle and/or its affiliates.
|
# 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
|
# 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
|
# 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
|
item_windowfunc.cc sql_window.cc
|
||||||
sql_cte.cc sql_cte.h
|
sql_cte.cc sql_cte.h
|
||||||
${WSREP_SOURCES}
|
${WSREP_SOURCES}
|
||||||
table_cache.cc encryption.cc
|
table_cache.cc encryption.cc temporary_tables.cc
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc
|
${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc
|
||||||
${GEN_SOURCES}
|
${GEN_SOURCES}
|
||||||
${GEN_DIGEST_SOURCES}
|
${GEN_DIGEST_SOURCES}
|
||||||
|
@ -6159,7 +6159,7 @@ int Load_log_event::do_apply_event(NET* net, rpl_group_info *rgi,
|
|||||||
update it inside mysql_load().
|
update it inside mysql_load().
|
||||||
*/
|
*/
|
||||||
List<Item> tmp_list;
|
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,
|
mysql_load(thd, &ex, &tables, field_list, tmp_list, tmp_list,
|
||||||
handle_dup, ignore, net != 0))
|
handle_dup, ignore, net != 0))
|
||||||
thd->is_slave_error= 1;
|
thd->is_slave_error= 1;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* Copyright (c) 2006, 2013, Oracle and/or its affiliates.
|
/* Copyright (c) 2006, 2013, Oracle and/or its affiliates.
|
||||||
Copyright (c) 2010, 2013, Monty Program Ab
|
Copyright (c) 2010, 2013, Monty Program Ab
|
||||||
|
Copyright (c) 2016, MariaDB Corporation
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
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),
|
no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id),
|
||||||
info_fd(-1), cur_log_fd(-1), relay_log(&sync_relaylog_period),
|
info_fd(-1), cur_log_fd(-1), relay_log(&sync_relaylog_period),
|
||||||
sync_counter(0), is_relay_log_recovery(is_slave_recovery),
|
sync_counter(0), is_relay_log_recovery(is_slave_recovery),
|
||||||
save_temporary_tables(0), mi(0),
|
save_temporary_tables(0),
|
||||||
inuse_relaylog_list(0), last_inuse_relaylog(0),
|
mi(0), inuse_relaylog_list(0), last_inuse_relaylog(0),
|
||||||
cur_log_old_open_count(0), group_relay_log_pos(0),
|
cur_log_old_open_count(0), group_relay_log_pos(0),
|
||||||
event_relay_log_pos(0),
|
event_relay_log_pos(0),
|
||||||
#if HAVE_valgrind
|
#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()
|
void Relay_log_info::close_temporary_tables()
|
||||||
{
|
{
|
||||||
TABLE *table,*next;
|
|
||||||
DBUG_ENTER("Relay_log_info::close_temporary_tables");
|
DBUG_ENTER("Relay_log_info::close_temporary_tables");
|
||||||
|
|
||||||
for (table=save_temporary_tables ; table ; table=next)
|
TMP_TABLE_SHARE *share;
|
||||||
{
|
TABLE *table;
|
||||||
next=table->next;
|
|
||||||
|
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
|
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.
|
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;
|
slave_open_temp_tables= 0;
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1756,6 +1786,7 @@ void rpl_group_info::cleanup_context(THD *thd, bool error)
|
|||||||
}
|
}
|
||||||
m_table_map.clear_tables();
|
m_table_map.clear_tables();
|
||||||
slave_close_thread_tables(thd);
|
slave_close_thread_tables(thd);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
thd->mdl_context.release_transactional_locks();
|
thd->mdl_context.release_transactional_locks();
|
||||||
|
@ -148,7 +148,7 @@ public:
|
|||||||
|
|
||||||
Protected by data_lock.
|
Protected by data_lock.
|
||||||
*/
|
*/
|
||||||
TABLE *save_temporary_tables;
|
All_tmp_tables_list *save_temporary_tables;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
standard lock acquisition order to avoid deadlocks:
|
standard lock acquisition order to avoid deadlocks:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
|
/* 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
|
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
|
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
|
TODO: see if we can do this conditionally in next_event() instead
|
||||||
to avoid unneeded position re-init
|
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;
|
rli->sql_driver_thd= 0;
|
||||||
thd->rgi_fake= thd->rgi_slave= NULL;
|
thd->rgi_fake= thd->rgi_slave= NULL;
|
||||||
|
|
||||||
|
@ -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
|
Check whenever we have access to tables for this statement
|
||||||
and open and lock them before executing instructions core function.
|
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)
|
check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE)
|
||||||
|| open_and_lock_tables(thd, tables, TRUE, 0))
|
|| open_and_lock_tables(thd, tables, TRUE, 0))
|
||||||
result= -1;
|
result= -1;
|
||||||
|
@ -54,7 +54,7 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
|
|||||||
|
|
||||||
DEBUG_SYNC(thd, "ha_admin_try_alter");
|
DEBUG_SYNC(thd, "ha_admin_try_alter");
|
||||||
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
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));
|
mysql_recreate_table(thd, table_list, false));
|
||||||
reenable_binlog(thd);
|
reenable_binlog(thd);
|
||||||
/*
|
/*
|
||||||
@ -445,7 +445,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
|||||||
|
|
||||||
da->push_warning_info(&tmp_wi);
|
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));
|
open_and_lock_tables(thd, table, TRUE, 0));
|
||||||
|
|
||||||
da->pop_warning_info();
|
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.
|
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));
|
open_and_lock_tables(thd, table, TRUE, 0));
|
||||||
}
|
}
|
||||||
thd->prepare_derived_at_open= FALSE;
|
thd->prepare_derived_at_open= FALSE;
|
||||||
@ -952,7 +952,7 @@ send_result_message:
|
|||||||
table->mdl_request.ticket= NULL;
|
table->mdl_request.ticket= NULL;
|
||||||
DEBUG_SYNC(thd, "ha_admin_open_ltable");
|
DEBUG_SYNC(thd, "ha_admin_open_ltable");
|
||||||
table->mdl_request.set_type(MDL_SHARED_WRITE);
|
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)))
|
(table->table= open_ltable(thd, table, lock_type, 0)))
|
||||||
{
|
{
|
||||||
uint save_flags;
|
uint save_flags;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
/* 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
|
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
|
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_parse.h" // check_access
|
||||||
#include "sql_table.h" // mysql_alter_table,
|
#include "sql_table.h" // mysql_alter_table,
|
||||||
// mysql_exchange_partition
|
// mysql_exchange_partition
|
||||||
#include "sql_base.h" // open_temporary_tables
|
|
||||||
#include "sql_alter.h"
|
#include "sql_alter.h"
|
||||||
#include "wsrep_mysqld.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;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
|
|
||||||
|
|
||||||
if ((!thd->is_current_stmt_binlog_format_row() ||
|
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),
|
WSREP_TO_ISOLATION_BEGIN(((lex->name.str) ? select_lex->db : NULL),
|
||||||
((lex->name.str) ? lex->name.str : NULL),
|
((lex->name.str) ? lex->name.str : NULL),
|
||||||
|
955
sql/sql_base.cc
955
sql/sql_base.cc
File diff suppressed because it is too large
Load Diff
@ -59,8 +59,6 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
|
|||||||
IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE,
|
IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE,
|
||||||
IGNORE_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);
|
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,
|
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
||||||
uint lock_flags);
|
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,
|
bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
||||||
List<String> *index_list);
|
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_locked_table(TABLE *list, const char *db, const char *table_name);
|
||||||
TABLE *find_write_locked_table(TABLE *list, const char *db,
|
TABLE *find_write_locked_table(TABLE *list, const char *db,
|
||||||
const char *table_name);
|
const char *table_name);
|
||||||
@ -138,21 +131,12 @@ thr_lock_type read_lock_type_for_table(THD *thd,
|
|||||||
bool routine_modifies_data);
|
bool routine_modifies_data);
|
||||||
|
|
||||||
my_bool mysql_rm_tmp_tables(void);
|
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,
|
void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
|
||||||
const MDL_savepoint &start_of_statement_svp);
|
const MDL_savepoint &start_of_statement_svp);
|
||||||
TABLE_LIST *find_table_in_list(TABLE_LIST *table,
|
TABLE_LIST *find_table_in_list(TABLE_LIST *table,
|
||||||
TABLE_LIST *TABLE_LIST::*link,
|
TABLE_LIST *TABLE_LIST::*link,
|
||||||
const char *db_name,
|
const char *db_name,
|
||||||
const char *table_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 close_thread_tables(THD *thd);
|
||||||
void switch_to_nullable_trigger_fields(List<Item> &items, TABLE *);
|
void switch_to_nullable_trigger_fields(List<Item> &items, TABLE *);
|
||||||
bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *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);
|
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
|
||||||
int decide_logging_format(THD *thd, TABLE_LIST *tables);
|
int decide_logging_format(THD *thd, TABLE_LIST *tables);
|
||||||
void close_thread_table(THD *thd, TABLE **table_ptr);
|
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,
|
TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
|
||||||
bool check_alias);
|
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);
|
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
|
||||||
|
|
||||||
class Open_tables_backup;
|
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,
|
TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
|
||||||
const char *table_name,
|
const char *table_name,
|
||||||
bool no_error);
|
bool no_error);
|
||||||
void mark_tmp_table_for_reuse(TABLE *table);
|
|
||||||
|
|
||||||
int update_virtual_fields(THD *thd, TABLE *table,
|
int update_virtual_fields(THD *thd, TABLE *table,
|
||||||
enum enum_vcol_update_mode vcol_update_mode= VCOL_UPDATE_FOR_READ);
|
enum enum_vcol_update_mode vcol_update_mode= VCOL_UPDATE_FOR_READ);
|
||||||
|
@ -1999,36 +1999,32 @@ lookup:
|
|||||||
for (; block_table != block_table_end; block_table++)
|
for (; block_table != block_table_end; block_table++)
|
||||||
{
|
{
|
||||||
TABLE_LIST table_list;
|
TABLE_LIST table_list;
|
||||||
TABLE *tmptable;
|
TMP_TABLE_SHARE *tmptable;
|
||||||
Query_cache_table *table = block_table->parent;
|
Query_cache_table *table = block_table->parent;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check that we have not temporary tables with same names of tables
|
Check that we do not have temporary tables with same names as that of
|
||||||
of this query. If we have such tables, we will not send data from
|
base tables from this query. If we have such tables, we will not send
|
||||||
query cache, because temporary tables hide real tables by which
|
data from query cache, because temporary tables hide real tables by which
|
||||||
query in query cache was made.
|
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 ==
|
DBUG_PRINT("qcache",
|
||||||
table->key_length() &&
|
("Temporary table detected: '%s.%s'",
|
||||||
!memcmp(tmptable->s->table_cache_key.str, table->data(),
|
tmptable->db.str, tmptable->table_name.str));
|
||||||
table->key_length()))
|
unlock();
|
||||||
{
|
/*
|
||||||
DBUG_PRINT("qcache",
|
We should not store result of this query because it contain
|
||||||
("Temporary table detected: '%s.%s'",
|
temporary tables => assign following variable to make check
|
||||||
tmptable->s->db.str, tmptable->alias.c_ptr()));
|
faster.
|
||||||
unlock();
|
*/
|
||||||
/*
|
thd->query_cache_is_applicable= 0; // Query can't be cached
|
||||||
We should not store result of this query because it contain
|
thd->lex->safe_to_cache_query= 0; // For prepared statements
|
||||||
temporary tables => assign following variable to make check
|
BLOCK_UNLOCK_RD(query_block);
|
||||||
faster.
|
DBUG_RETURN(-1);
|
||||||
*/
|
|
||||||
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));
|
bzero((char*) &table_list,sizeof(table_list));
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
#include "tztime.h" // MYSQL_TIME <-> my_time_t
|
#include "tztime.h" // MYSQL_TIME <-> my_time_t
|
||||||
#include "sql_acl.h" // NO_ACCESS,
|
#include "sql_acl.h" // NO_ACCESS,
|
||||||
// acl_getroot_no_password
|
// acl_getroot_no_password
|
||||||
#include "sql_base.h" // close_temporary_tables
|
#include "sql_base.h"
|
||||||
#include "sql_handler.h" // mysql_ha_cleanup
|
#include "sql_handler.h" // mysql_ha_cleanup
|
||||||
#include "rpl_rli.h"
|
#include "rpl_rli.h"
|
||||||
#include "rpl_filter.h"
|
#include "rpl_filter.h"
|
||||||
@ -883,7 +883,8 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
|
|||||||
main_da(0, false, false),
|
main_da(0, false, false),
|
||||||
m_stmt_da(&main_da),
|
m_stmt_da(&main_da),
|
||||||
tdc_hash_pins(0),
|
tdc_hash_pins(0),
|
||||||
xid_hash_pins(0)
|
xid_hash_pins(0),
|
||||||
|
m_tmp_tables_locked(false)
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
,
|
,
|
||||||
wsrep_applier(is_wsrep_applier),
|
wsrep_applier(is_wsrep_applier),
|
||||||
@ -1586,7 +1587,7 @@ void THD::cleanup(void)
|
|||||||
locked_tables_list.unlock_locked_tables(this);
|
locked_tables_list.unlock_locked_tables(this);
|
||||||
|
|
||||||
delete_dynamic(&user_var_events);
|
delete_dynamic(&user_var_events);
|
||||||
close_temporary_tables(this);
|
close_temporary_tables();
|
||||||
|
|
||||||
transaction.xid_state.xa_state= XA_NOTR;
|
transaction.xid_state.xa_state= XA_NOTR;
|
||||||
trans_rollback(this);
|
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
|
Before we will throw away current open tables state we want
|
||||||
to be sure that it was properly cleaned up.
|
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 &&
|
derived_tables == 0 &&
|
||||||
lock == 0 &&
|
lock == 0 &&
|
||||||
locked_tables_mode == LTM_NONE &&
|
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
|
void
|
||||||
wait_for_commit::reinit()
|
wait_for_commit::reinit()
|
||||||
{
|
{
|
||||||
|
176
sql/sql_class.h
176
sql/sql_class.h
@ -1264,6 +1264,61 @@ enum enum_locked_tables_mode
|
|||||||
LTM_PRELOCKED_UNDER_LOCK_TABLES
|
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
|
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().
|
base tables that were opened with @see open_tables().
|
||||||
*/
|
*/
|
||||||
TABLE *open_tables;
|
TABLE *open_tables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
List of temporary tables used by this thread. Contains user-level
|
A list of temporary tables used by this thread. This includes
|
||||||
temporary tables, created with CREATE TEMPORARY TABLE, and
|
user-level temporary tables, created with CREATE TEMPORARY TABLE,
|
||||||
internal temporary tables, created, e.g., to resolve a SELECT,
|
and internal temporary tables, created, e.g., to resolve a SELECT,
|
||||||
or for an intermediate table used in ALTER.
|
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;
|
TABLE *derived_tables;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
During a MySQL session, one can lock tables in two modes: automatic
|
During a MySQL session, one can lock tables in two modes: automatic
|
||||||
or manual. In automatic mode all necessary tables are locked just before
|
or manual. In automatic mode all necessary tables are locked just before
|
||||||
@ -1379,8 +1439,11 @@ public:
|
|||||||
|
|
||||||
void reset_open_tables_state(THD *thd)
|
void reset_open_tables_state(THD *thd)
|
||||||
{
|
{
|
||||||
open_tables= temporary_tables= derived_tables= 0;
|
open_tables= 0;
|
||||||
extra_lock= lock= 0;
|
temporary_tables= 0;
|
||||||
|
derived_tables= 0;
|
||||||
|
extra_lock= 0;
|
||||||
|
lock= 0;
|
||||||
locked_tables_mode= LTM_NONE;
|
locked_tables_mode= LTM_NONE;
|
||||||
state_flags= 0U;
|
state_flags= 0U;
|
||||||
m_reprepare_observer= NULL;
|
m_reprepare_observer= NULL;
|
||||||
@ -3544,13 +3607,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
DBUG_PRINT("debug",
|
DBUG_PRINT("debug",
|
||||||
("temporary_tables: %s, in_sub_stmt: %s, system_thread: %s",
|
("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)));
|
show_system_thread(system_thread)));
|
||||||
if (in_sub_stmt == 0)
|
if (in_sub_stmt == 0)
|
||||||
{
|
{
|
||||||
if (wsrep_binlog_format() == BINLOG_FORMAT_ROW)
|
if (wsrep_binlog_format() == BINLOG_FORMAT_ROW)
|
||||||
set_current_stmt_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();
|
set_current_stmt_binlog_format_stmt();
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -3950,10 +4013,6 @@ private:
|
|||||||
LEX_STRING invoker_user;
|
LEX_STRING invoker_user;
|
||||||
LEX_STRING invoker_host;
|
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:
|
public:
|
||||||
/*
|
/*
|
||||||
Flag, mutex and condition for a thread to wait for a signal from another
|
Flag, mutex and condition for a thread to wait for a signal from another
|
||||||
@ -3971,26 +4030,85 @@ public:
|
|||||||
*/
|
*/
|
||||||
rpl_gtid last_commit_gtid;
|
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 *tdc_hash_pins;
|
||||||
LF_PINS *xid_hash_pins;
|
LF_PINS *xid_hash_pins;
|
||||||
bool fix_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
|
inline ulong wsrep_binlog_format() const
|
||||||
{
|
{
|
||||||
return WSREP_FORMAT(variables.binlog_format);
|
return WSREP_FORMAT(variables.binlog_format);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2000, 2014, Oracle and/or its affiliates.
|
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
|
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
|
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 db_name= { table->db, table->db_length };
|
||||||
LEX_STRING table_name= { table->table_name, table->table_name_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);
|
(void) delete_statistics_for_table(thd, &db_name, &table_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2001, 2015, Oracle and/or its affiliates.
|
/* 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
|
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
|
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 */
|
/* Must be a temporary table */
|
||||||
table->file->ha_index_or_rnd_end();
|
table->file->ha_index_or_rnd_end();
|
||||||
table->query_id= thd->query_id;
|
|
||||||
table->open_by_handler= 0;
|
table->open_by_handler= 0;
|
||||||
mark_tmp_table_for_reuse(table);
|
thd->mark_tmp_table_as_free_for_reuse(table);
|
||||||
}
|
}
|
||||||
my_free(handler->lock);
|
my_free(handler->lock);
|
||||||
handler->init();
|
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
|
open_ltable() or open_table() because we would like to be able
|
||||||
to open a temporary table.
|
to open a temporary table.
|
||||||
*/
|
*/
|
||||||
error= (open_temporary_tables(thd, tables) ||
|
error= (thd->open_temporary_tables(tables) ||
|
||||||
open_tables(thd, &tables, &counter, 0));
|
open_tables(thd, &tables, &counter, 0));
|
||||||
|
|
||||||
if (error)
|
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.
|
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
|
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
|
was opened for HANDLER as it is used to link them together.
|
||||||
(see thd->temporary_tables).
|
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(sql_handler->table->next == NULL ||
|
DBUG_ASSERT(sql_handler->table->next == NULL ||
|
||||||
sql_handler->table->s->tmp_table);
|
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
|
Remove temporary tables from the HANDLER's hash table. The reason
|
||||||
for having a separate function, rather than calling
|
for having a separate function, rather than calling
|
||||||
mysql_ha_rm_tables() is that it is not always feasible (e.g. in
|
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.
|
temporary tables.
|
||||||
|
|
||||||
@See close_temporary_tables
|
@See THD::close_temporary_tables()
|
||||||
@param thd Thread identifier.
|
@param thd Thread identifier.
|
||||||
*/
|
*/
|
||||||
void mysql_ha_rm_temporary_tables(THD *thd)
|
void mysql_ha_rm_temporary_tables(THD *thd)
|
||||||
|
@ -4078,7 +4078,12 @@ static TABLE *create_table_from_items(THD *thd,
|
|||||||
}
|
}
|
||||||
else
|
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
|
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(0);
|
||||||
}
|
}
|
||||||
DBUG_ASSERT(create_table->table == create_info->table);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -4461,6 +4465,7 @@ void select_create::abort_result_set()
|
|||||||
if (table)
|
if (table)
|
||||||
{
|
{
|
||||||
bool tmp_table= table->s->tmp_table;
|
bool tmp_table= table->s->tmp_table;
|
||||||
|
|
||||||
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||||
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
|
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
|
||||||
table->auto_increment_field_not_null= FALSE;
|
table->auto_increment_field_not_null= FALSE;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
|
/* 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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -23,7 +23,10 @@
|
|||||||
// set_handler_table_locks,
|
// set_handler_table_locks,
|
||||||
// lock_global_read_lock,
|
// lock_global_read_lock,
|
||||||
// make_global_read_lock_block_commit
|
// 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_cache.h" // QUERY_CACHE_FLAGS_SIZE, query_cache_*
|
||||||
#include "sql_show.h" // mysqld_list_*, mysqld_show_*,
|
#include "sql_show.h" // mysqld_list_*, mysqld_show_*,
|
||||||
// calc_sum_of_all_status
|
// 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)
|
for (TABLE_LIST *table= tables; table; table= table->next_global)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(table->db && table->table_name);
|
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 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1967,7 +1970,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
thd->set_query(fields, query_length);
|
thd->set_query(fields, query_length);
|
||||||
general_log_print(thd, command, "%s %s", table_list.table_name, fields);
|
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;
|
break;
|
||||||
|
|
||||||
if (check_table_access(thd, SELECT_ACL, &table_list,
|
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 (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;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4066,7 +4069,7 @@ end_with_restore_list:
|
|||||||
Temporary tables should be opened for SHOW CREATE TABLE, but not
|
Temporary tables should be opened for SHOW CREATE TABLE, but not
|
||||||
for SHOW CREATE VIEW.
|
for SHOW CREATE VIEW.
|
||||||
*/
|
*/
|
||||||
if (open_temporary_tables(thd, all_tables))
|
if (thd->open_temporary_tables(all_tables))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4274,7 +4277,8 @@ end_with_restore_list:
|
|||||||
*/
|
*/
|
||||||
if (first_table->lock_type != TL_WRITE_DELAYED)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4586,7 +4590,7 @@ end_with_restore_list:
|
|||||||
{
|
{
|
||||||
if (!lex->tmp_table() &&
|
if (!lex->tmp_table() &&
|
||||||
(!thd->is_current_stmt_binlog_format_row() ||
|
(!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);
|
WSREP_TO_ISOLATION_BEGIN(NULL, NULL, all_tables);
|
||||||
break;
|
break;
|
||||||
@ -4739,7 +4743,7 @@ end_with_restore_list:
|
|||||||
CF_PREOPEN_TMP_TABLES was set and the tables would be pre-opened
|
CF_PREOPEN_TMP_TABLES was set and the tables would be pre-opened
|
||||||
in a usual way, they would have been closed.
|
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;
|
goto error;
|
||||||
|
|
||||||
if (lock_tables_precheck(thd, all_tables))
|
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.
|
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;
|
return TRUE;
|
||||||
|
|
||||||
if (check_access(thd, SELECT_ACL, dst_table->db,
|
if (check_access(thd, SELECT_ACL, dst_table->db,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
Copyright (c) 2014, SkySQL Ab.
|
Copyright (c) 2014, SkySQL Ab.
|
||||||
|
Copyright (c) 2016, MariaDB Corporation
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
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
|
#ifdef WITH_WSREP
|
||||||
if (WSREP_ON)
|
if (WSREP_ON)
|
||||||
{
|
{
|
||||||
/* Forward declaration */
|
|
||||||
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
|
|
||||||
|
|
||||||
if ((!thd->is_current_stmt_binlog_format_row() ||
|
if ((!thd->is_current_stmt_binlog_format_row() ||
|
||||||
/* TODO: Do we really need to check for temp tables in this case? */
|
/* 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,
|
wsrep_to_isolation_begin(thd, table_list->db, table_list->table_name,
|
||||||
NULL))
|
NULL))
|
||||||
{
|
{
|
||||||
@ -783,11 +781,9 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
|
|||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
/* Forward declaration */
|
if (WSREP(thd) &&
|
||||||
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
|
(!thd->is_current_stmt_binlog_format_row() ||
|
||||||
|
!thd->find_temporary_table(first_table)) &&
|
||||||
if (WSREP(thd) && (!thd->is_current_stmt_binlog_format_row() ||
|
|
||||||
!find_temporary_table(thd, first_table)) &&
|
|
||||||
wsrep_to_isolation_begin(
|
wsrep_to_isolation_begin(
|
||||||
thd, first_table->db, first_table->table_name, NULL)
|
thd, first_table->db, first_table->table_name, NULL)
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates.
|
/* 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
|
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
|
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 (table_list->lock_type != TL_WRITE_DELAYED)
|
||||||
{
|
{
|
||||||
if (open_temporary_tables(thd, table_list))
|
if (thd->open_temporary_tables(table_list))
|
||||||
goto error;
|
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,
|
Since we can't pre-open temporary tables for SQLCOM_CREATE_VIEW,
|
||||||
(see mysql_create_view) we have to do it here instead.
|
(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;
|
goto err;
|
||||||
|
|
||||||
if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL,
|
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 (sql_command_flags[sql_command] & CF_PREOPEN_TMP_TABLES)
|
||||||
{
|
{
|
||||||
if (open_temporary_tables(thd, tables))
|
if (thd->open_temporary_tables(tables))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4155,7 +4155,7 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
|
|||||||
'only_view_structure()'.
|
'only_view_structure()'.
|
||||||
*/
|
*/
|
||||||
lex->sql_command= SQLCOM_SHOW_FIELDS;
|
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,
|
open_normal_and_derived_tables(thd, table_list,
|
||||||
(MYSQL_OPEN_IGNORE_FLUSH |
|
(MYSQL_OPEN_IGNORE_FLUSH |
|
||||||
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
|
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
|
||||||
@ -4218,6 +4218,7 @@ end:
|
|||||||
all tables open within this Open_tables_state.
|
all tables open within this Open_tables_state.
|
||||||
*/
|
*/
|
||||||
thd->temporary_tables= NULL;
|
thd->temporary_tables= NULL;
|
||||||
|
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
/*
|
/*
|
||||||
Release metadata lock we might have acquired.
|
Release metadata lock we might have acquired.
|
||||||
|
128
sql/sql_table.cc
128
sql/sql_table.cc
@ -25,7 +25,7 @@
|
|||||||
#include "sql_table.h"
|
#include "sql_table.h"
|
||||||
#include "sql_parse.h" // test_if_data_home_dir
|
#include "sql_parse.h" // test_if_data_home_dir
|
||||||
#include "sql_cache.h" // query_cache_*
|
#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 "lock.h" // mysql_unlock_tables
|
||||||
#include "strfunc.h" // find_type2, find_set
|
#include "strfunc.h" // find_type2, find_set
|
||||||
#include "sql_truncate.h" // regenerate_locked_table
|
#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 db_name= { table->db, table->db_length };
|
||||||
LEX_STRING table_name= { table->table_name, table->table_name_length };
|
LEX_STRING table_name= { table->table_name, table->table_name_length };
|
||||||
if (table->open_type == OT_BASE_ONLY ||
|
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);
|
(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 &&
|
DBUG_ASSERT(!(thd->locked_tables_mode &&
|
||||||
table->open_type != OT_BASE_ONLY &&
|
table->open_type != OT_BASE_ONLY &&
|
||||||
find_temporary_table(thd, table) &&
|
thd->find_temporary_table(table) &&
|
||||||
table->mdl_request.ticket != NULL));
|
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))
|
if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table))
|
||||||
error= 1;
|
error= 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
table_creation_was_logged= table->table->s->table_creation_was_logged;
|
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;
|
goto err;
|
||||||
}
|
}
|
||||||
table->table= 0;
|
table->table= 0;
|
||||||
@ -4635,7 +4629,8 @@ err:
|
|||||||
which was created.
|
which was created.
|
||||||
@param[out] key_count Number of keys in table 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
|
Note that this function assumes that caller already have taken
|
||||||
exclusive metadata lock on table being created or used some other
|
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 */
|
/* Check if table exists */
|
||||||
if (create_info->tmp_table())
|
if (create_info->tmp_table())
|
||||||
{
|
{
|
||||||
TABLE *tmp_table;
|
/*
|
||||||
if (find_and_use_temporary_table(thd, db, table_name, &tmp_table))
|
If a table exists, it must have been pre-opened. Try looking for one
|
||||||
goto err;
|
in-use in THD::all_temp_tables list of TABLE_SHAREs.
|
||||||
|
*/
|
||||||
|
TABLE *tmp_table= thd->find_temporary_table(db, table_name);
|
||||||
|
|
||||||
if (tmp_table)
|
if (tmp_table)
|
||||||
{
|
{
|
||||||
bool table_creation_was_logged= tmp_table->s->table_creation_was_logged;
|
bool table_creation_was_logged= tmp_table->s->table_creation_was_logged;
|
||||||
if (options.or_replace())
|
if (options.or_replace())
|
||||||
{
|
{
|
||||||
bool tmp;
|
|
||||||
/*
|
/*
|
||||||
We are using CREATE OR REPLACE on an existing temporary table
|
We are using CREATE OR REPLACE on an existing temporary table
|
||||||
Remove the old table so that we can re-create it.
|
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;
|
goto err;
|
||||||
}
|
}
|
||||||
else if (options.if_not_exists())
|
else if (options.if_not_exists())
|
||||||
@ -4847,17 +4844,12 @@ int create_table_impl(THD *thd,
|
|||||||
create_info->table= 0;
|
create_info->table= 0;
|
||||||
if (!frm_only && create_info->tmp_table())
|
if (!frm_only && create_info->tmp_table())
|
||||||
{
|
{
|
||||||
/*
|
TABLE *table= thd->create_and_open_tmp_table(create_info->db_type, frm,
|
||||||
Open a table (skipping table cache) and add it into
|
path, db, table_name, true);
|
||||||
THD::temporary_tables list.
|
|
||||||
*/
|
|
||||||
|
|
||||||
TABLE *table= open_table_uncached(thd, create_info->db_type, frm, path,
|
|
||||||
db, table_name, true, true);
|
|
||||||
|
|
||||||
if (!table)
|
if (!table)
|
||||||
{
|
{
|
||||||
(void) rm_temporary_table(create_info->db_type, path);
|
(void) thd->rm_temporary_table(create_info->db_type, path);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7143,7 +7135,8 @@ static bool mysql_inplace_alter_table(THD *thd,
|
|||||||
HA_EXTRA_NOT_USED,
|
HA_EXTRA_NOT_USED,
|
||||||
NULL);
|
NULL);
|
||||||
table_list->table= table= 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.
|
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);
|
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
|
||||||
/* QQ; do something about metadata locks ? */
|
/* 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
|
// Delete temporary .frm/.par
|
||||||
(void) quick_rm_table(thd, create_info->db_type, alter_ctx->new_db,
|
(void) quick_rm_table(thd, create_info->db_type, alter_ctx->new_db,
|
||||||
alter_ctx->tmp_name, FN_IS_TMP | NO_HA_TABLE);
|
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 (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);
|
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alter_ctx.new_alias);
|
||||||
DBUG_RETURN(true);
|
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.
|
// We assume that the table is non-temporary.
|
||||||
DBUG_ASSERT(!table->s->tmp_table);
|
DBUG_ASSERT(!table->s->tmp_table);
|
||||||
|
|
||||||
if (!(altered_table= open_table_uncached(thd, new_db_type, &frm,
|
if (!(altered_table=
|
||||||
alter_ctx.get_tmp_path(),
|
thd->create_and_open_tmp_table(new_db_type, &frm,
|
||||||
alter_ctx.new_db,
|
alter_ctx.get_tmp_path(),
|
||||||
alter_ctx.tmp_name,
|
alter_ctx.new_db, alter_ctx.tmp_name,
|
||||||
true, false)))
|
false)))
|
||||||
goto err_new_table_cleanup;
|
goto err_new_table_cleanup;
|
||||||
|
|
||||||
/* Set markers for fields in TABLE object for altered table. */
|
/* 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",
|
ha_alter_info.report_unsupported_error("LOCK=NONE/SHARED",
|
||||||
"LOCK=EXCLUSIVE");
|
"LOCK=EXCLUSIVE");
|
||||||
close_temporary_table(thd, altered_table, true, false);
|
thd->drop_temporary_table(altered_table, NULL, false);
|
||||||
goto err_new_table_cleanup;
|
goto err_new_table_cleanup;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -8876,7 +8874,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
Alter_info::ALTER_TABLE_LOCK_NONE)
|
Alter_info::ALTER_TABLE_LOCK_NONE)
|
||||||
{
|
{
|
||||||
ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
|
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;
|
goto err_new_table_cleanup;
|
||||||
}
|
}
|
||||||
break;
|
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",
|
ha_alter_info.report_unsupported_error("ALGORITHM=INPLACE",
|
||||||
"ALGORITHM=COPY");
|
"ALGORITHM=COPY");
|
||||||
close_temporary_table(thd, altered_table, true, false);
|
thd->drop_temporary_table(altered_table, NULL, false);
|
||||||
goto err_new_table_cleanup;
|
goto err_new_table_cleanup;
|
||||||
}
|
}
|
||||||
// COPY with LOCK=NONE is not supported, no point in trying.
|
// 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)
|
Alter_info::ALTER_TABLE_LOCK_NONE)
|
||||||
{
|
{
|
||||||
ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
|
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;
|
goto err_new_table_cleanup;
|
||||||
}
|
}
|
||||||
// Otherwise use COPY
|
// Otherwise use COPY
|
||||||
@ -8906,7 +8904,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
break;
|
break;
|
||||||
case HA_ALTER_ERROR:
|
case HA_ALTER_ERROR:
|
||||||
default:
|
default:
|
||||||
close_temporary_table(thd, altered_table, true, false);
|
thd->drop_temporary_table(altered_table, NULL, false);
|
||||||
goto err_new_table_cleanup;
|
goto err_new_table_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8925,7 +8923,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
}
|
}
|
||||||
else
|
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 (create_info->tmp_table())
|
||||||
{
|
{
|
||||||
if (!open_table_uncached(thd, new_db_type, &frm,
|
TABLE *tmp_table=
|
||||||
alter_ctx.get_tmp_path(),
|
thd->create_and_open_tmp_table(new_db_type, &frm,
|
||||||
alter_ctx.new_db, alter_ctx.tmp_name,
|
alter_ctx.get_tmp_path(),
|
||||||
true, true))
|
alter_ctx.new_db, alter_ctx.tmp_name,
|
||||||
|
true);
|
||||||
|
if (!tmp_table)
|
||||||
|
{
|
||||||
goto err_new_table_cleanup;
|
goto err_new_table_cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Open the table since we need to copy the data. */
|
/* Open the table since we need to copy the data. */
|
||||||
if (table->s->tmp_table != NO_TMP_TABLE)
|
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),
|
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, strlen(alter_ctx.tmp_name),
|
||||||
alter_ctx.tmp_name, TL_READ_NO_INSERT);
|
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;
|
new_table= tbl.table;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* table is a normal table: Create temporary table in same directory */
|
/*
|
||||||
/* Open our intermediate table. */
|
table is a normal table: Create temporary table in same directory.
|
||||||
new_table= open_table_uncached(thd, new_db_type, &frm,
|
Open our intermediate table.
|
||||||
alter_ctx.get_tmp_path(),
|
*/
|
||||||
alter_ctx.new_db, alter_ctx.tmp_name,
|
new_table=
|
||||||
true, true);
|
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)
|
if (!new_table)
|
||||||
goto err_new_table_cleanup;
|
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=
|
new_table->s->table_creation_was_logged=
|
||||||
table->s->table_creation_was_logged;
|
table->s->table_creation_was_logged;
|
||||||
/* Remove link to old table and rename the new one */
|
/* 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 */
|
/* Should pass the 'new_name' as we store table name in the cache */
|
||||||
if (rename_temporary_table(thd, new_table,
|
if (thd->rename_temporary_table(new_table, alter_ctx.new_db,
|
||||||
alter_ctx.new_db, alter_ctx.new_name))
|
alter_ctx.new_name))
|
||||||
goto err_new_table_cleanup;
|
goto err_new_table_cleanup;
|
||||||
/* We don't replicate alter table statement on temporary tables */
|
/* We don't replicate alter table statement on temporary tables */
|
||||||
if (!thd->is_current_stmt_binlog_format_row() &&
|
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
|
Close the intermediate table that will be the new table, but do
|
||||||
not delete it! Even altough MERGE tables do not have their children
|
not delete it! Even though MERGE tables do not have their children
|
||||||
attached here it is safe to call close_temporary_table().
|
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;
|
new_table= NULL;
|
||||||
|
|
||||||
DEBUG_SYNC(thd, "alter_table_before_rename_result_table");
|
DEBUG_SYNC(thd, "alter_table_before_rename_result_table");
|
||||||
@ -9231,8 +9240,7 @@ err_new_table_cleanup:
|
|||||||
my_free(const_cast<uchar*>(frm.str));
|
my_free(const_cast<uchar*>(frm.str));
|
||||||
if (new_table)
|
if (new_table)
|
||||||
{
|
{
|
||||||
/* close_temporary_table() frees the new_table pointer. */
|
thd->drop_temporary_table(new_table, NULL, true);
|
||||||
close_temporary_table(thd, new_table, true, true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
(void) quick_rm_table(thd, new_db_type,
|
(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. */
|
/* Allow to open real tables only. */
|
||||||
table->required_type= FRMTYPE_TABLE;
|
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))
|
open_and_lock_tables(thd, table, FALSE, 0))
|
||||||
{
|
{
|
||||||
t= NULL;
|
t= NULL;
|
||||||
|
@ -82,7 +82,7 @@ static my_bool print_cached_tables_callback(TDC_element *element,
|
|||||||
TABLE *entry;
|
TABLE *entry;
|
||||||
|
|
||||||
mysql_mutex_lock(&element->LOCK_table_share);
|
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++))
|
while ((entry= it++))
|
||||||
{
|
{
|
||||||
THD *in_use= entry->in_use;
|
THD *in_use= entry->in_use;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "sql_parse.h" // parse_sql
|
#include "sql_parse.h" // parse_sql
|
||||||
#include "parse_file.h"
|
#include "parse_file.h"
|
||||||
#include "sp.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_show.h" // append_definer, append_identifier
|
||||||
#include "sql_table.h" // build_table_filename,
|
#include "sql_table.h" // build_table_filename,
|
||||||
// check_n_cut_mysql50_prefix
|
// 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);
|
DBUG_ASSERT(tables->next_global == 0);
|
||||||
|
|
||||||
/* We do not allow creation of triggers on temporary tables. */
|
/* 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);
|
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2004, 2013, Oracle and/or its affiliates.
|
/* 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
|
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
|
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);
|
lex->link_first_table_back(view, link_to_local);
|
||||||
view->open_type= OT_BASE_ONLY;
|
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))
|
open_and_lock_tables(thd, lex->query_tables, TRUE, 0))
|
||||||
{
|
{
|
||||||
view= lex->unlink_first_table(&link_to_local);
|
view= lex->unlink_first_table(&link_to_local);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates.
|
/* 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
|
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
|
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
|
switching @@SESSION.binlog_format from MIXED to STATEMENT when there are
|
||||||
open temp tables and we are logging in row format.
|
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 &&
|
var->save_result.ulonglong_value == BINLOG_FORMAT_STMT &&
|
||||||
((thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
|
((thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
|
||||||
thd->is_current_stmt_binlog_format_row()) ||
|
thd->is_current_stmt_binlog_format_row()) ||
|
||||||
|
@ -3922,7 +3922,7 @@ bool TABLE_SHARE::visit_subgraph(Wait_for_flush *wait_for_flush,
|
|||||||
tdc->all_tables_refs++;
|
tdc->all_tables_refs++;
|
||||||
mysql_mutex_unlock(&tdc->LOCK_table_share);
|
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
|
In case of multiple searches running in parallel, avoid going
|
||||||
|
25
sql/table.h
25
sql/table.h
@ -2,6 +2,7 @@
|
|||||||
#define TABLE_INCLUDED
|
#define TABLE_INCLUDED
|
||||||
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
|
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
|
||||||
Copyright (c) 2009, 2014, SkySQL Ab.
|
Copyright (c) 2009, 2014, SkySQL Ab.
|
||||||
|
Copyright (c) 2016, MariaDB Corporation
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
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.
|
One should use methods of I_P_List template instead.
|
||||||
*/
|
*/
|
||||||
TABLE *share_all_next, **share_all_prev;
|
TABLE *share_all_next, **share_all_prev;
|
||||||
friend struct TDC_element;
|
friend struct All_share_tables;
|
||||||
|
|
||||||
public:
|
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
|
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);
|
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)
|
inline void mark_as_null_row(TABLE *table)
|
||||||
{
|
{
|
||||||
table->null_row=1;
|
table->null_row=1;
|
||||||
|
@ -965,7 +965,7 @@ void tdc_release_share(TABLE_SHARE *share)
|
|||||||
|
|
||||||
static void kill_delayed_threads_for_table(TDC_element *element)
|
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;
|
TABLE *tab;
|
||||||
|
|
||||||
mysql_mutex_assert_owner(&element->LOCK_table_share);
|
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 ||
|
if (remove_type == TDC_RT_REMOVE_NOT_OWN ||
|
||||||
remove_type == TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE)
|
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++))
|
while ((table= it++))
|
||||||
{
|
{
|
||||||
my_refs++;
|
my_refs++;
|
||||||
|
@ -27,9 +27,6 @@ struct TDC_element
|
|||||||
TABLE_SHARE *share;
|
TABLE_SHARE *share;
|
||||||
|
|
||||||
typedef I_P_List <TABLE, TABLE_share> TABLE_list;
|
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,
|
Protects ref_count, m_flush_tickets, all_tables, free_tables, flushed,
|
||||||
all_tables_refs.
|
all_tables_refs.
|
||||||
|
1499
sql/temporary_tables.cc
Normal file
1499
sql/temporary_tables.cc
Normal file
File diff suppressed because it is too large
Load Diff
@ -62,7 +62,6 @@ err:
|
|||||||
|
|
||||||
#include "transaction.h" // trans_commit(), trans_rollback()
|
#include "transaction.h" // trans_commit(), trans_rollback()
|
||||||
#include "rpl_rli.h" // class Relay_log_info;
|
#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)
|
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);
|
wsrep_dump_rbr_buf_with_header(thd, buf, buf_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
TABLE *tmp;
|
if (thd->has_thd_temporary_tables())
|
||||||
while ((tmp = thd->temporary_tables))
|
|
||||||
{
|
{
|
||||||
WSREP_DEBUG("Applier %lld, has temporary tables: %s.%s",
|
WSREP_DEBUG("Applier %lld has temporary tables. Closing them now..",
|
||||||
(longlong) thd->thread_id,
|
thd->thread_id);
|
||||||
(tmp->s) ? tmp->s->db.str : "void",
|
thd->close_temporary_tables();
|
||||||
(tmp->s) ? tmp->s->table_name.str : "void");
|
|
||||||
close_temporary_table(thd, tmp, 1, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rcode;
|
return rcode;
|
||||||
|
@ -1085,8 +1085,6 @@ static bool wsrep_prepare_keys_for_isolation(THD* thd,
|
|||||||
ka->keys= 0;
|
ka->keys= 0;
|
||||||
ka->keys_len= 0;
|
ka->keys_len= 0;
|
||||||
|
|
||||||
extern TABLE* find_temporary_table(THD*, const TABLE_LIST*);
|
|
||||||
|
|
||||||
if (db || table)
|
if (db || table)
|
||||||
{
|
{
|
||||||
TABLE_LIST tmp_table;
|
TABLE_LIST tmp_table;
|
||||||
@ -1098,7 +1096,7 @@ static bool wsrep_prepare_keys_for_isolation(THD* thd,
|
|||||||
(table) ? table : "",
|
(table) ? table : "",
|
||||||
MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT);
|
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))))
|
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)
|
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;
|
wsrep_key_t* tmp;
|
||||||
tmp= (wsrep_key_t*)my_realloc(
|
tmp= (wsrep_key_t*)my_realloc(
|
||||||
@ -2443,26 +2441,13 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
|
|||||||
TABLE_LIST* src_table,
|
TABLE_LIST* src_table,
|
||||||
HA_CREATE_INFO *create_info)
|
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())
|
if (create_info->tmp_table())
|
||||||
{
|
{
|
||||||
|
|
||||||
/* CREATE TEMPORARY TABLE LIKE must be skipped from replication */
|
/* CREATE TEMPORARY TABLE LIKE must be skipped from replication */
|
||||||
WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s",
|
WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s",
|
||||||
thd->query());
|
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 */
|
/* this is straight CREATE TABLE LIKE... eith no tmp tables */
|
||||||
WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL);
|
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));
|
bzero((void*) &tbl, sizeof(tbl));
|
||||||
tbl.db= src_table->db;
|
tbl.db= src_table->db;
|
||||||
tbl.table_name= tbl.alias= src_table->table_name;
|
tbl.table_name= tbl.alias= src_table->table_name;
|
||||||
tbl.table= tmp_table;
|
tbl.table= src_table->table;
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
String query(buf, sizeof(buf), system_charset_info);
|
String query(buf, sizeof(buf), system_charset_info);
|
||||||
query.length(0); // Have to zero it since constructor doesn't
|
query.length(0); // Have to zero it since constructor doesn't
|
||||||
|
@ -360,13 +360,10 @@ static void wsrep_replication_process(THD *thd)
|
|||||||
mysql_cond_broadcast(&COND_thread_count);
|
mysql_cond_broadcast(&COND_thread_count);
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
|
||||||
TABLE *tmp;
|
if(thd->has_thd_temporary_tables())
|
||||||
while ((tmp = thd->temporary_tables))
|
|
||||||
{
|
{
|
||||||
WSREP_WARN("Applier %lld, has temporary tables at exit: %s.%s",
|
WSREP_WARN("Applier %lld has temporary tables at exit.",
|
||||||
(longlong) thd->thread_id,
|
thd->thread_id);
|
||||||
(tmp->s) ? tmp->s->db.str : "void",
|
|
||||||
(tmp->s) ? tmp->s->table_name.str : "void");
|
|
||||||
}
|
}
|
||||||
wsrep_return_from_bf_mode(thd, &shadow);
|
wsrep_return_from_bf_mode(thd, &shadow);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
@ -1640,7 +1640,7 @@ long long spider_direct_sql_body(
|
|||||||
table_list.table_name = direct_sql->table_names[roop_count];
|
table_list.table_name = direct_sql->table_names[roop_count];
|
||||||
#endif
|
#endif
|
||||||
if (!(direct_sql->tables[roop_count] =
|
if (!(direct_sql->tables[roop_count] =
|
||||||
find_temporary_table(thd, &table_list)))
|
thd->find_temporary_table(&table_list)))
|
||||||
{
|
{
|
||||||
#if MYSQL_VERSION_ID < 50500
|
#if MYSQL_VERSION_ID < 50500
|
||||||
#else
|
#else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user