List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:March 24 2011 9:02am
Subject:bzr commit into mysql-trunk branch (alexander.nozdrin:3532) Bug#11746602
View as plain text  
#At file:///home/alik/MySQL/bzr/00/bug27480/mysql-trunk-bug27480/ based on revid:alexander.nozdrin@stripped

 3532 Alexander Nozdrin	2011-03-24
      Patch for Bug#11746602 (27480: Extend CREATE TEMPORARY TABLES privilege
      to allow temp table operations).
      
      The idea of this patch is to check CREATE TEMPORARY TABLES privilege
      for CREATE TEMPORARY TABLE statement only. Privileges are not checked
      for temporary tables for other statements.

    modified:
      mysql-test/include/handler.inc
      mysql-test/r/flush_read_lock.result
      mysql-test/r/grant2.result
      mysql-test/r/handler_innodb.result
      mysql-test/r/handler_myisam.result
      mysql-test/r/merge.result
      mysql-test/t/flush_read_lock.test
      mysql-test/t/grant2.test
      mysql-test/t/merge.test
      sql/sql_acl.cc
      sql/sql_alter.cc
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_handler.cc
      sql/sql_insert.cc
      sql/sql_parse.cc
      sql/sql_prepare.cc
      sql/sql_table.cc
=== modified file 'mysql-test/include/handler.inc'
--- a/mysql-test/include/handler.inc	2010-11-18 16:34:56 +0000
+++ b/mysql-test/include/handler.inc	2011-03-24 09:02:22 +0000
@@ -804,6 +804,7 @@ 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;
+create temporary table t4 like t3;
 handler t1 open;
 handler t2 open;
 handler t3 open;
@@ -818,8 +819,10 @@ handler t1 open;
 handler t1 read next;
 --error ER_LOCK_OR_ACTIVE_TRANSACTION
 handler t2 close;
---error ER_LOCK_OR_ACTIVE_TRANSACTION
+--error ER_CANT_REOPEN_TABLE
 handler t3 open;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+handler t4 open;
 --echo # After UNLOCK TABLES handlers should be around and
 --echo # we should be able to continue reading through them.
 unlock tables;
@@ -829,7 +832,7 @@ handler t2 read next;
 handler t2 close;
 handler t3 read next;
 handler t3 close;
-drop temporary table t3;
+drop temporary tables t3, t4;
 --echo #
 --echo # Other operations that implicitly close handler:
 --echo #

=== modified file 'mysql-test/r/flush_read_lock.result'
--- a/mysql-test/r/flush_read_lock.result	2010-11-11 17:11:05 +0000
+++ b/mysql-test/r/flush_read_lock.result	2011-03-24 09:02:22 +0000
@@ -543,11 +543,10 @@ Success: Was not able to run 'drop table
 Success: 'drop table t2_base' is blocked by FTWRL active in another connection.
 Success: FTWRL is blocked when 'drop table t2_base' is active in another connection.
 # 13.1.b) DROP TABLES which affects only temporary tables
-#         in theory can be compatible with FTWRL.
-#         In practice it is not yet.
-Success: Was not able to run 'drop table t2_temp' under FTWRL.
-Success: 'drop table t2_temp' is blocked by FTWRL active in another connection.
-Success: FTWRL is blocked when 'drop table t2_temp' is active in another connection.
+#         is compatible with FTWRL.
+Success: Was able to run 'drop table t2_temp' under FTWRL.
+Success: Was able to run 'drop table t2_temp' with FTWRL active in another connection.
+Success: Was able to run FTWRL while 'drop table t2_temp' was active in another connection.
 #
 # 13.1.c) DROP TEMPORARY TABLES should be compatible with FTWRL.
 Success: Was able to run 'drop temporary table t2_temp' under FTWRL.

=== modified file 'mysql-test/r/grant2.result'
--- a/mysql-test/r/grant2.result	2010-08-09 08:32:50 +0000
+++ b/mysql-test/r/grant2.result	2011-03-24 09:02:22 +0000
@@ -472,3 +472,330 @@ root	localhost		Y
 FLUSH PRIVILEGES;
 USE test;
 End of 5.1 tests
+
+# --
+# -- Bug#11746602: 27480 - Extend CREATE TEMPORARY TABLES privilege to
+# -- allow temp table operations
+# --
+
+############################################################################
+# Setup environment.
+###########################################################################
+DROP DATABASE IF EXISTS mysqltest_db1;
+CREATE DATABASE mysqltest_db1;
+# mysqltest_u1@localhost has CREATE_TMP_ACL, FILE_ACL and EXECUTE_ACL only
+# (EXECUTE_ACL is needed to call p0, and FILE_ACL is needed for SELECT
+# OUTFILE/LOAD DATA INFILE).
+GRANT FILE ON *.* TO mysqltest_u1@localhost;
+GRANT CREATE TEMPORARY TABLES, EXECUTE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+# mysqltest_u2@localhost has all privileges but CREATE_TMP_ACL.
+GRANT ALL PRIVILEGES ON mysqltest_db1.* TO mysqltest_u2@localhost;
+REVOKE CREATE TEMPORARY TABLES ON mysqltest_db1.* FROM mysqltest_u2@localhost;
+# mysqltest_u3@localhost has CREATE_TMP_ACL & EXECUTE_ACL.
+# This user is required to check SUID-stored-routines.
+GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u3@localhost;
+GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u3@localhost;
+# mysqltest_u4@localhost has only EXECUTE_ACL.
+# We need this user to check that once created temporary tables
+# are accessible by anyone.
+GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u4@localhost;
+# Create stored routine to test how privilege checking is done for its
+# arguments.
+CREATE PROCEDURE mysqltest_db1.p0(i INT) SELECT i;
+# Create SUID-stored-routines.
+CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p1()
+CREATE TEMPORARY TABLE t4(x INT);
+CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p2()
+INSERT INTO t4 VALUES (1), (2), (3);
+CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p3()
+SELECT * FROM t4 ORDER BY x;
+# We need separate key cache to test CACHE INDEX and LOAD INDEX.
+SET GLOBAL keycache1.key_buffer_size = 128 * 1024;
+###########################################################################
+# Check that CREATE_TMP_ACL is enough to issue any supported SQL-statement
+# against temporary tables (loosely follow order in sql_command enum).
+###########################################################################
+
+# -- connect con1, mysqltest_u1@localhost, mysqltest_db1
+#
+# Variants of CREATE TABLE.
+#
+CREATE TEMPORARY TABLE t1(a INT);
+CREATE TEMPORARY TABLE t2 LIKE t1;
+CREATE TEMPORARY TABLE t3(a INT, b INT, PRIMARY KEY (a));
+CREATE TEMPORARY TABLE t4 SELECT * FROM t1;
+# Also check that we allow creation of MERGE table with underlying
+# temporary table without additional privileges.
+CREATE TEMPORARY TABLE t5(a INT) ENGINE = MyISAM;
+CREATE TEMPORARY TABLE t6(a INT) ENGINE = MERGE UNION = (t5);
+#
+# SELECT.
+#
+INSERT INTO t1 VALUES (1), (2), (3);
+SELECT * FROM t1 ORDER BY a;
+a
+1
+2
+3
+#
+# CREATE/DROP INDEX.
+#
+CREATE INDEX idx1 ON t3(b);
+DROP INDEX idx1 ON t3;
+#
+# ALTER TABLE.
+# 
+ALTER TABLE t4 ADD COLUMN b INT;
+# Check that we allow altering of MERGE table with underlying
+# temporary table without additional privileges.
+ALTER TABLE t6 UNION = ();
+ALTER TABLE t6 UNION = (t5);
+#
+# Simple INSERT and INSERT ... SELECT.
+#
+INSERT INTO t1 VALUES (4);
+INSERT INTO t2 SELECT a FROM t1;
+SELECT * FROM t1 ORDER BY a;
+a
+1
+2
+3
+4
+SELECT * FROM t2 ORDER BY a;
+a
+1
+2
+3
+4
+#
+# UPDATE and multi-UPDATE.
+#
+UPDATE t1 SET a = a * 10;
+UPDATE t1 SET a = 100 WHERE a = 10;
+UPDATE t1, t2 SET t1.a = 200 WHERE t1.a = t2.a * 10 AND t1.a = 20;
+SELECT * FROM t1 ORDER BY a;
+a
+30
+40
+100
+200
+#
+# DELETE and multi-DELETE.
+#
+DELETE FROM t1 WHERE a = 100;
+DELETE t1 FROM t1, t2 WHERE t1.a = t2.a * 100 AND t1.a = 200;
+SELECT * FROM t1 ORDER BY a;
+a
+30
+40
+#
+# TRUNCATE TABLE.
+#
+TRUNCATE TABLE t1;
+SELECT * FROM t1 ORDER BY a;
+a
+#
+# SHOW COLUMNS/DESCRIBE and SHOW KEYS.
+#
+SHOW COLUMNS FROM t1;
+Field	Type	Null	Key	Default	Extra
+SHOW KEYS FROM t3;
+Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment	Index_comment
+t3	0	PRIMARY	1	a	A	0	NULL	NULL		BTREE		
+#
+# SHOW CREATE TABLE.
+#
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TEMPORARY TABLE `t1` (
+  `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+#
+# LOAD DATA INFILE (also SELECT INTO OUTFILE).
+#
+INSERT INTO t1 VALUES (1), (2), (3);
+SELECT a INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug27480.txt' FROM t1 ;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug27480.txt' INTO TABLE t1;
+SELECT * FROM t1 ORDER BY a;
+a
+1
+1
+2
+2
+3
+3
+#
+# SET.
+#
+SET @a := (SELECT COUNT(*) FROM t1);
+SELECT @a;
+@a
+6
+#
+# LOCK TABLES.
+#
+LOCK TABLES t1 READ;
+UNLOCK TABLES;
+#
+# CHECK/REPAIR/ANALYZE/OPTIMIZE and CHECKSUM.
+#
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+mysqltest_db1.t1	analyze	status	OK
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+mysqltest_db1.t1	check	status	OK
+OPTIMIZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+mysqltest_db1.t1	optimize	status	Table is already up to date
+REPAIR TABLE t1;
+Table	Op	Msg_type	Msg_text
+mysqltest_db1.t1	repair	status	OK
+#
+# REPLACE and REPLACE ... SELECT.
+#
+INSERT INTO t3 VALUES (1, 111), (2, 222), (3, 333);
+REPLACE INTO t3 VALUES (1, 1111), (4, 444), (0, 001);
+REPLACE INTO t2 SELECT b FROM t3;
+SELECT * FROM t2 ORDER BY a;
+a
+1
+1
+2
+3
+4
+222
+333
+444
+1111
+SELECT * FROM t3 ORDER BY a;
+a	b
+0	1
+1	1111
+2	222
+3	333
+4	444
+#
+# CACHE and LOAD INDEX.
+#
+CACHE INDEX t3 IN keycache1;
+Table	Op	Msg_type	Msg_text
+mysqltest_db1.t3	assign_to_keycache	status	OK
+LOAD INDEX INTO CACHE t3;
+Table	Op	Msg_type	Msg_text
+mysqltest_db1.t3	preload_keys	status	OK
+#
+# RENAME (doesn't work for temporary tables, thus should fail).
+#
+RENAME TABLE t3 TO t3_1;
+ERROR 42000: DROP, ALTER command denied to user 'mysqltest_u1'@'localhost' for table 't3'
+#
+# HANDLER OPEN/READ/CLOSE.
+#
+HANDLER t1 OPEN;
+HANDLER t1 READ NEXT;
+a
+1
+HANDLER t1 CLOSE;
+#
+# DO.
+#
+DO (SELECT COUNT(*) FROM t1);
+#
+# CHECKSUM TABLE.
+#
+DELETE FROM t1;
+CHECKSUM TABLE t1;
+Table	Checksum
+mysqltest_db1.t1	0
+#
+# CALL.
+#
+CALL p0((SELECT COUNT(*) FROM t1));
+i
+0
+#
+# PREPARE, EXECUTE and DEALLOCATE.
+#
+PREPARE stmt1 FROM 'SELECT * FROM t1 ORDER BY a';
+PREPARE stmt2 FROM 'SELECT * FROM t2 ORDER BY a';
+EXECUTE stmt1;
+a
+EXECUTE stmt2;
+a
+1
+1
+2
+3
+4
+222
+333
+444
+1111
+DEALLOCATE PREPARE stmt1;
+DEALLOCATE PREPARE stmt2;
+#
+# DROP TABLE and DROP TEMPORARY TABLE.
+#
+DROP TABLE t1;
+CREATE TEMPORARY TABLE t1(a INT);
+DROP TEMPORARY TABLE t1;
+###########################################################################
+# - Check that even having all privileges but CREATE_TMP_ACL is not enough
+#   to create temporary tables.
+# - Check that creation/working with temporary tables is possible via
+#   SUID-stored-routines.
+# - Check that even outside of SUID context we can access temporary
+#   table once it is created.
+###########################################################################
+
+# -- connect con2, mysqltest_u2@localhost, mysqltest_db1
+CREATE TEMPORARY TABLE t2(a INT);
+ERROR 42000: Access denied for user 'mysqltest_u2'@'localhost' to database 'mysqltest_db1'
+CALL p1();
+CALL p2();
+CALL p3();
+x
+1
+2
+3
+# Check that once table is created it can be accessed even
+# outside of such a SUID context.
+INSERT INTO t4 VALUES (4);
+UPDATE t4 SET x = 10 WHERE x = 1;
+DELETE FROM t4 WHERE x < 3;
+SELECT * FROM t4 ORDER BY x;
+x
+3
+4
+10
+DROP TEMPORARY TABLE t4;
+###########################################################################
+# - Check that once table is created it can be accessed from within any
+#   context.
+###########################################################################
+
+# -- connect con3, mysqltest_u4@localhost, mysqltest_db1
+CALL p1();
+INSERT INTO t4 VALUES (4);
+UPDATE t4 SET x = 10 WHERE x = 1;
+DELETE FROM t4 WHERE x < 3;
+SELECT * FROM t4 ORDER BY x;
+x
+4
+DROP TEMPORARY TABLE t4;
+###########################################################################
+# That's all. Cleanup.
+###########################################################################
+
+# -- connection: default
+# -- disconnect con1
+# All remaining temporary tables are automatically dropped.
+# -- disconnect con2
+# -- disconnect con3
+SET GLOBAL keycache1.key_buffer_size = 0;
+DROP DATABASE mysqltest_db1;
+DROP USER mysqltest_u1@localhost;
+DROP USER mysqltest_u2@localhost;
+DROP USER mysqltest_u3@localhost;
+DROP USER mysqltest_u4@localhost;

=== modified file 'mysql-test/r/handler_innodb.result'
--- a/mysql-test/r/handler_innodb.result	2010-11-18 16:34:56 +0000
+++ b/mysql-test/r/handler_innodb.result	2011-03-24 09:02:22 +0000
@@ -784,6 +784,7 @@ 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;
+create temporary table t4 like t3;
 handler t1 open;
 handler t2 open;
 handler t3 open;
@@ -799,6 +800,8 @@ ERROR HY000: Can't execute the given com
 handler t2 close;
 ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
 handler t3 open;
+ERROR HY000: Can't reopen table: 't3'
+handler t4 open;
 ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
 # After UNLOCK TABLES handlers should be around and
 # we should be able to continue reading through them.
@@ -815,7 +818,7 @@ handler t3 read next;
 a
 1
 handler t3 close;
-drop temporary table t3;
+drop temporary tables t3, t4;
 #
 # Other operations that implicitly close handler:
 #

=== modified file 'mysql-test/r/handler_myisam.result'
--- a/mysql-test/r/handler_myisam.result	2011-01-17 16:27:07 +0000
+++ b/mysql-test/r/handler_myisam.result	2011-03-24 09:02:22 +0000
@@ -782,6 +782,7 @@ 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;
+create temporary table t4 like t3;
 handler t1 open;
 handler t2 open;
 handler t3 open;
@@ -797,6 +798,8 @@ ERROR HY000: Can't execute the given com
 handler t2 close;
 ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
 handler t3 open;
+ERROR HY000: Can't reopen table: 't3'
+handler t4 open;
 ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
 # After UNLOCK TABLES handlers should be around and
 # we should be able to continue reading through them.
@@ -813,7 +816,7 @@ handler t3 read next;
 a
 1
 handler t3 close;
-drop temporary table t3;
+drop temporary tables t3, t4;
 #
 # Other operations that implicitly close handler:
 #

=== modified file 'mysql-test/r/merge.result'
--- a/mysql-test/r/merge.result	2011-02-15 18:21:37 +0000
+++ b/mysql-test/r/merge.result	2011-03-24 09:02:22 +0000
@@ -2716,13 +2716,14 @@ DROP TABLE tm1, t1, t2, t3, t4, t5;
 # Bug#47633 - assert in ha_myisammrg::info during OPTIMIZE
 #
 CREATE TEMPORARY TABLE t1 (c1 INT);
-ALTER TABLE t1 ENGINE=MERGE UNION(t_not_exists,t1);
+CREATE TEMPORARY TABLE t2 (c1 INT);
+ALTER TABLE t1 ENGINE=MERGE UNION(t_not_exists, t2);
 OPTIMIZE TABLE t1;
 Table	Op	Msg_type	Msg_text
 test.t1	optimize	Error	Table 'test.t_not_exists' doesn't exist
 test.t1	optimize	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
 test.t1	optimize	error	Corrupt
-DROP TABLE t1;
+DROP TABLE t1, t2;
 #
 # Bug#36171 - CREATE TEMPORARY TABLE and MERGE engine
 # More tests with TEMPORARY MERGE table and permanent children.

=== modified file 'mysql-test/t/flush_read_lock.test'
--- a/mysql-test/t/flush_read_lock.test	2010-11-12 13:57:08 +0000
+++ b/mysql-test/t/flush_read_lock.test	2011-03-24 09:02:22 +0000
@@ -706,11 +706,10 @@ let $cleanup_stmt1= create table t2_base
 --source include/check_ftwrl_incompatible.inc
 
 --echo # 13.1.b) DROP TABLES which affects only temporary tables
---echo #         in theory can be compatible with FTWRL.
---echo #         In practice it is not yet.
+--echo #         is compatible with FTWRL.
 let $statement= drop table t2_temp;
-let $cleanup_stmt1= create temporary table t2_temp(j int);
---source include/check_ftwrl_incompatible.inc
+let $cleanup_stmt= create temporary table t2_temp(j int);
+--source include/check_ftwrl_compatible.inc
 
 --echo #
 --echo # 13.1.c) DROP TEMPORARY TABLES should be compatible with FTWRL.

=== modified file 'mysql-test/t/grant2.test'
--- a/mysql-test/t/grant2.test	2010-08-09 08:32:50 +0000
+++ b/mysql-test/t/grant2.test	2011-03-24 09:02:22 +0000
@@ -667,5 +667,308 @@ USE test;
 
 --echo End of 5.1 tests
 
+
+--echo 
+--echo # --
+--echo # -- Bug#11746602: 27480 - Extend CREATE TEMPORARY TABLES privilege to
+--echo # -- allow temp table operations
+--echo # --
+--echo
+
+--echo ############################################################################
+--echo # Setup environment.
+--echo ###########################################################################
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest_db1;
+--enable_warnings
+
+CREATE DATABASE mysqltest_db1;
+
+--echo # mysqltest_u1@localhost has CREATE_TMP_ACL, FILE_ACL and EXECUTE_ACL only
+--echo # (EXECUTE_ACL is needed to call p0, and FILE_ACL is needed for SELECT
+--echo # OUTFILE/LOAD DATA INFILE).
+GRANT FILE ON *.* TO mysqltest_u1@localhost;
+GRANT CREATE TEMPORARY TABLES, EXECUTE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--echo # mysqltest_u2@localhost has all privileges but CREATE_TMP_ACL.
+GRANT ALL PRIVILEGES ON mysqltest_db1.* TO mysqltest_u2@localhost;
+REVOKE CREATE TEMPORARY TABLES ON mysqltest_db1.* FROM mysqltest_u2@localhost;
+
+--echo # mysqltest_u3@localhost has CREATE_TMP_ACL & EXECUTE_ACL.
+--echo # This user is required to check SUID-stored-routines.
+GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u3@localhost;
+GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u3@localhost;
+
+--echo # mysqltest_u4@localhost has only EXECUTE_ACL.
+--echo # We need this user to check that once created temporary tables
+--echo # are accessible by anyone.
+GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u4@localhost;
+
+--echo # Create stored routine to test how privilege checking is done for its
+--echo # arguments.
+CREATE PROCEDURE mysqltest_db1.p0(i INT) SELECT i;
+
+--echo # Create SUID-stored-routines.
+CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p1()
+  CREATE TEMPORARY TABLE t4(x INT);
+
+CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p2()
+  INSERT INTO t4 VALUES (1), (2), (3);
+
+CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p3()
+  SELECT * FROM t4 ORDER BY x;
+
+--echo # We need separate key cache to test CACHE INDEX and LOAD INDEX.
+SET GLOBAL keycache1.key_buffer_size = 128 * 1024;
+
+--echo ###########################################################################
+--echo # Check that CREATE_TMP_ACL is enough to issue any supported SQL-statement
+--echo # against temporary tables (loosely follow order in sql_command enum).
+--echo ###########################################################################
+
+--echo
+--echo # -- connect con1, mysqltest_u1@localhost, mysqltest_db1
+--connect (con1,localhost,mysqltest_u1,,mysqltest_db1)
+
+--echo #
+--echo # Variants of CREATE TABLE.
+--echo #
+CREATE TEMPORARY TABLE t1(a INT);
+CREATE TEMPORARY TABLE t2 LIKE t1;
+CREATE TEMPORARY TABLE t3(a INT, b INT, PRIMARY KEY (a));
+CREATE TEMPORARY TABLE t4 SELECT * FROM t1;
+--echo # Also check that we allow creation of MERGE table with underlying
+--echo # temporary table without additional privileges.
+CREATE TEMPORARY TABLE t5(a INT) ENGINE = MyISAM;
+CREATE TEMPORARY TABLE t6(a INT) ENGINE = MERGE UNION = (t5);
+
+--echo #
+--echo # SELECT.
+--echo #
+INSERT INTO t1 VALUES (1), (2), (3);
+SELECT * FROM t1 ORDER BY a;
+
+--echo #
+--echo # CREATE/DROP INDEX.
+--echo #
+CREATE INDEX idx1 ON t3(b);
+DROP INDEX idx1 ON t3;
+
+--echo #
+--echo # ALTER TABLE.
+--echo # 
+ALTER TABLE t4 ADD COLUMN b INT;
+--echo # Check that we allow altering of MERGE table with underlying
+--echo # temporary table without additional privileges.
+ALTER TABLE t6 UNION = ();
+ALTER TABLE t6 UNION = (t5);
+
+--echo #
+--echo # Simple INSERT and INSERT ... SELECT.
+--echo #
+INSERT INTO t1 VALUES (4);
+INSERT INTO t2 SELECT a FROM t1;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+--echo #
+--echo # UPDATE and multi-UPDATE.
+--echo #
+UPDATE t1 SET a = a * 10;
+UPDATE t1 SET a = 100 WHERE a = 10;
+UPDATE t1, t2 SET t1.a = 200 WHERE t1.a = t2.a * 10 AND t1.a = 20;
+SELECT * FROM t1 ORDER BY a;
+
+--echo #
+--echo # DELETE and multi-DELETE.
+--echo #
+DELETE FROM t1 WHERE a = 100;
+DELETE t1 FROM t1, t2 WHERE t1.a = t2.a * 100 AND t1.a = 200;
+SELECT * FROM t1 ORDER BY a;
+
+--echo #
+--echo # TRUNCATE TABLE.
+--echo #
+TRUNCATE TABLE t1;
+SELECT * FROM t1 ORDER BY a;
+
+--echo #
+--echo # SHOW COLUMNS/DESCRIBE and SHOW KEYS.
+--echo #
+SHOW COLUMNS FROM t1;
+SHOW KEYS FROM t3;
+
+--echo #
+--echo # SHOW CREATE TABLE.
+--echo #
+SHOW CREATE TABLE t1;
+
+--echo #
+--echo # LOAD DATA INFILE (also SELECT INTO OUTFILE).
+--echo #
+INSERT INTO t1 VALUES (1), (2), (3);
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--eval SELECT a INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/bug27480.txt' FROM t1 
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/bug27480.txt' INTO TABLE t1
+--remove_file $MYSQLTEST_VARDIR/tmp/bug27480.txt
+SELECT * FROM t1 ORDER BY a;
+
+--echo #
+--echo # SET.
+--echo #
+SET @a := (SELECT COUNT(*) FROM t1);
+SELECT @a;
+
+--echo #
+--echo # LOCK TABLES.
+--echo #
+LOCK TABLES t1 READ;
+UNLOCK TABLES;
+
+--echo #
+--echo # CHECK/REPAIR/ANALYZE/OPTIMIZE and CHECKSUM.
+--echo #
+ANALYZE TABLE t1;
+CHECK TABLE t1;
+OPTIMIZE TABLE t1;
+REPAIR TABLE t1;
+
+--echo #
+--echo # REPLACE and REPLACE ... SELECT.
+--echo #
+INSERT INTO t3 VALUES (1, 111), (2, 222), (3, 333);
+REPLACE INTO t3 VALUES (1, 1111), (4, 444), (0, 001);
+REPLACE INTO t2 SELECT b FROM t3;
+SELECT * FROM t2 ORDER BY a;
+SELECT * FROM t3 ORDER BY a;
+
+--echo #
+--echo # CACHE and LOAD INDEX.
+--echo #
+CACHE INDEX t3 IN keycache1;
+LOAD INDEX INTO CACHE t3;
+
+--echo #
+--echo # RENAME (doesn't work for temporary tables, thus should fail).
+--echo #
+--error ER_TABLEACCESS_DENIED_ERROR
+RENAME TABLE t3 TO t3_1;
+
+--echo #
+--echo # HANDLER OPEN/READ/CLOSE.
+--echo #
+HANDLER t1 OPEN;
+HANDLER t1 READ NEXT;
+HANDLER t1 CLOSE;
+
+--echo #
+--echo # DO.
+--echo #
+DO (SELECT COUNT(*) FROM t1);
+
+--echo #
+--echo # CHECKSUM TABLE.
+--echo #
+DELETE FROM t1;
+CHECKSUM TABLE t1;
+
+--echo #
+--echo # CALL.
+--echo #
+CALL p0((SELECT COUNT(*) FROM t1));
+
+--echo #
+--echo # PREPARE, EXECUTE and DEALLOCATE.
+--echo #
+PREPARE stmt1 FROM 'SELECT * FROM t1 ORDER BY a';
+PREPARE stmt2 FROM 'SELECT * FROM t2 ORDER BY a';
+EXECUTE stmt1;
+EXECUTE stmt2;
+DEALLOCATE PREPARE stmt1;
+DEALLOCATE PREPARE stmt2;
+
+--echo #
+--echo # DROP TABLE and DROP TEMPORARY TABLE.
+--echo #
+DROP TABLE t1;
+
+CREATE TEMPORARY TABLE t1(a INT);
+DROP TEMPORARY TABLE t1;
+
+
+--echo ###########################################################################
+--echo # - Check that even having all privileges but CREATE_TMP_ACL is not enough
+--echo #   to create temporary tables.
+--echo # - Check that creation/working with temporary tables is possible via
+--echo #   SUID-stored-routines.
+--echo # - Check that even outside of SUID context we can access temporary
+--echo #   table once it is created.
+--echo ###########################################################################
+
+--echo
+--echo # -- connect con2, mysqltest_u2@localhost, mysqltest_db1
+--connect (con2,localhost,mysqltest_u2,,mysqltest_db1)
+
+--error ER_DBACCESS_DENIED_ERROR
+CREATE TEMPORARY TABLE t2(a INT);
+
+CALL p1();
+
+CALL p2();
+
+CALL p3();
+  
+--echo # Check that once table is created it can be accessed even
+--echo # outside of such a SUID context.
+INSERT INTO t4 VALUES (4);
+UPDATE t4 SET x = 10 WHERE x = 1;
+DELETE FROM t4 WHERE x < 3;
+SELECT * FROM t4 ORDER BY x;
+DROP TEMPORARY TABLE t4;
+
+--echo ###########################################################################
+--echo # - Check that once table is created it can be accessed from within any
+--echo #   context.
+--echo ###########################################################################
+
+--echo
+--echo # -- connect con3, mysqltest_u4@localhost, mysqltest_db1
+--connect (con3,localhost,mysqltest_u4,,mysqltest_db1)
+
+CALL p1();
+INSERT INTO t4 VALUES (4);
+UPDATE t4 SET x = 10 WHERE x = 1;
+DELETE FROM t4 WHERE x < 3;
+SELECT * FROM t4 ORDER BY x;
+DROP TEMPORARY TABLE t4;
+
+--echo ###########################################################################
+--echo # That's all. Cleanup.
+--echo ###########################################################################
+
+--echo
+--echo # -- connection: default
+--connection default
+
+--echo # -- disconnect con1
+--echo # All remaining temporary tables are automatically dropped.
+--disconnect con1
+
+--echo # -- disconnect con2
+--disconnect con2
+
+--echo # -- disconnect con3
+--disconnect con3
+
+SET GLOBAL keycache1.key_buffer_size = 0;
+DROP DATABASE mysqltest_db1;
+DROP USER mysqltest_u1@localhost;
+DROP USER mysqltest_u2@localhost;
+DROP USER mysqltest_u3@localhost;
+DROP USER mysqltest_u4@localhost;
+
+
 # Wait till we reached the initial number of concurrent sessions
 --source include/wait_until_count_sessions.inc

=== modified file 'mysql-test/t/merge.test'
--- a/mysql-test/t/merge.test	2011-02-15 18:21:37 +0000
+++ b/mysql-test/t/merge.test	2011-03-24 09:02:22 +0000
@@ -2194,9 +2194,10 @@ DROP TABLE tm1, t1, t2, t3, t4, t5;
 --echo # Bug#47633 - assert in ha_myisammrg::info during OPTIMIZE
 --echo #
 CREATE TEMPORARY TABLE t1 (c1 INT);
-ALTER TABLE t1 ENGINE=MERGE UNION(t_not_exists,t1);
+CREATE TEMPORARY TABLE t2 (c1 INT);
+ALTER TABLE t1 ENGINE=MERGE UNION(t_not_exists, t2);
 OPTIMIZE TABLE t1;
-DROP TABLE t1;
+DROP TABLE t1, t2;
 
 --echo #
 --echo # Bug#36171 - CREATE TEMPORARY TABLE and MERGE engine

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2011-02-18 09:56:51 +0000
+++ b/sql/sql_acl.cc	2011-03-24 09:02:22 +0000
@@ -4617,6 +4617,20 @@ bool check_grant(THD *thd, ulong want_ac
       }
       continue;
     }
+
+    if (is_temporary_table(tl))
+    {
+      /*
+        If this table list element corresponds to a pre-opened temporary
+        table skip checking of all table-level privileges for it.
+        Note that during creation of temporary table we still need to check
+        if user has CREATE_TMP_ACL, but this is not a table-level privilege.
+      */
+      tl->grant.privilege|= TABLE_ACLS;
+      tl->grant.want_privilege= 0;
+      continue;
+    }
+
     GRANT_TABLE *grant_table= table_hash_search(sctx->host, sctx->ip,
                                                 tl->get_db_name(),
                                                 sctx->priv_user,

=== modified file 'sql/sql_alter.cc'
--- a/sql/sql_alter.cc	2010-10-05 09:15:51 +0000
+++ b/sql/sql_alter.cc	2011-03-24 09:02:22 +0000
@@ -16,6 +16,7 @@
 #include "sql_parse.h"                       // check_access
 #include "sql_table.h"                       // mysql_alter_table,
                                              // mysql_exchange_partition
+#include "sql_base.h"                        // open_temporary_tables
 #include "sql_alter.h"
 
 bool Sql_cmd_alter_table::execute(THD *thd)
@@ -64,10 +65,31 @@ bool Sql_cmd_alter_table::execute(THD *t
     DBUG_RETURN(TRUE);                  /* purecov: inspected */
 
   /* If it is a merge table, check privileges for merge children. */
-  if (create_info.merge_list.first &&
-      check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
-                         create_info.merge_list.first, FALSE, UINT_MAX, FALSE))
-    DBUG_RETURN(TRUE);
+  if (create_info.merge_list.first)
+  {
+    /* Pre-open underlying temporary tables to simplify privilege checking. */
+    if (open_temporary_tables(thd, create_info.merge_list.first))
+      DBUG_RETURN(TRUE);
+
+    if (check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
+                           create_info.merge_list.first, FALSE, UINT_MAX, FALSE))
+      DBUG_RETURN(TRUE);
+
+    /*
+      Since one of tables in UNION clause might be already used by table being
+      altered we need to close all tables opened for UNION checking to allow
+      normal open of table being altered.
+      To do this we simply close all tables and then open only tables from the
+      main statement's table list.
+    */
+    close_thread_tables(thd);
+
+    for (TABLE_LIST *tl= lex->query_tables; tl; tl= tl->next_global)
+      tl->table= NULL;
+
+    if (open_temporary_tables(thd, lex->query_tables))
+      DBUG_RETURN(TRUE);
+  }
 
   if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
     DBUG_RETURN(TRUE);                  /* purecov: inspected */

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2011-03-09 12:24:36 +0000
+++ b/sql/sql_base.cc	2011-03-24 09:02:22 +0000
@@ -2059,10 +2059,13 @@ TABLE *find_temporary_table(THD *thd,
   thd->temporary_tables list, it's impossible to tell here whether
   we're dealing with an internal or a user temporary table.
 
-  If is_trans is not null, we return the type of the table:
+  In is_trans out-parameter, we return the type of the table:
   either transactional (e.g. innodb) as TRUE or non-transactional
   (e.g. myisam) as FALSE.
 
+  This function assumes that table to be dropped was pre-opened
+  using table list provided.
+
   @retval  0  the table was found and dropped successfully.
   @retval  1  the table was not found in the list of temporary tables
               of this thread
@@ -2071,14 +2074,15 @@ TABLE *find_temporary_table(THD *thd,
 
 int drop_temporary_table(THD *thd, TABLE_LIST *table_list, bool *is_trans)
 {
-  TABLE *table;
   DBUG_ENTER("drop_temporary_table");
   DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'",
                           table_list->db, table_list->table_name));
 
-  if (!(table= find_temporary_table(thd, table_list)))
+  if (!is_temporary_table(table_list))
     DBUG_RETURN(1);
 
+  TABLE *table= table_list->table;
+
   /* Table might be in use by some outer statement. */
   if (table->query_id && table->query_id != thd->query_id)
   {
@@ -2086,8 +2090,7 @@ int drop_temporary_table(THD *thd, TABLE
     DBUG_RETURN(-1);
   }
 
-  if (is_trans != NULL)
-    *is_trans= table->file->has_transactions();
+  *is_trans= table->file->has_transactions();
 
   /*
     If LOCK TABLES list is not empty and contains this table,
@@ -2095,6 +2098,7 @@ int drop_temporary_table(THD *thd, TABLE
   */
   mysql_lock_remove(thd, thd->lock, table);
   close_temporary_table(thd, table, 1, 1);
+  table_list->table= NULL;
   DBUG_RETURN(0);
 }
 

=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h	2011-03-09 12:24:36 +0000
+++ b/sql/sql_base.h	2011-03-24 09:02:22 +0000
@@ -577,7 +577,21 @@ private:
 
 inline bool is_temporary_table(TABLE_LIST *tl)
 {
-  return tl->table ? (tl->table->s->tmp_table != NO_TMP_TABLE) : FALSE;
+  if (tl->view || tl->schema_table)
+    return FALSE;
+
+  if (!tl->table)
+    return FALSE;
+
+  /*
+    NOTE: 'table->s' might be NULL for specially constructed TABLE
+    instances. See SHOW TRIGGERS for example.
+  */
+
+  if (!tl->table->s)
+    return FALSE;
+
+  return tl->table->s->tmp_table != NO_TMP_TABLE;
 }
 
 

=== modified file 'sql/sql_handler.cc'
--- a/sql/sql_handler.cc	2011-01-17 16:27:07 +0000
+++ b/sql/sql_handler.cc	2011-03-24 09:02:22 +0000
@@ -287,10 +287,6 @@ bool mysql_ha_open(THD *thd, TABLE_LIST
   */
   DBUG_ASSERT(! hash_tables->table);
 
-  /*
-    TODO/FIXME: In the upcoming patch we somehow should handle
-                situation with privilege check for temporary table.
-  */
   error= open_temporary_tables(thd, hash_tables);
 
   if (!error)

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2011-02-15 17:36:23 +0000
+++ b/sql/sql_insert.cc	2011-03-24 09:02:22 +0000
@@ -3799,10 +3799,10 @@ static TABLE *create_table_from_items(TH
         {
           /*
             This shouldn't happen as creation of temporary table should make
-            it preparable for open. But let us do close_temporary_table() here
-            just in case.
+            it preparable for open. Anyway we can't drop temporary table if
+            we are unable to fint it.
           */
-          drop_temporary_table(thd, create_table, NULL);
+          DBUG_ASSERT(0);
         }
         else
         {

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2011-03-09 12:24:36 +0000
+++ b/sql/sql_parse.cc	2011-03-24 09:02:22 +0000
@@ -114,6 +114,7 @@
 
 static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
 static void sql_kill(THD *thd, ulong id, bool only_kill_query);
+static bool lock_tables_precheck(THD *thd, TABLE_LIST *tables);
 
 const char *any_db="*any*";	// Special symbol for check_access
 
@@ -455,6 +456,7 @@ void init_update_queries(void)
     pre-opening temporary tables for those statements is somewhat custom.
   */
   sql_command_flags[SQLCOM_CREATE_TABLE]|=    CF_PREOPEN_TMP_TABLES;
+  sql_command_flags[SQLCOM_DROP_TABLE]|=      CF_PREOPEN_TMP_TABLES;
   sql_command_flags[SQLCOM_CREATE_INDEX]|=    CF_PREOPEN_TMP_TABLES;
   sql_command_flags[SQLCOM_ALTER_TABLE]|=     CF_PREOPEN_TMP_TABLES;
   sql_command_flags[SQLCOM_TRUNCATE]|=        CF_PREOPEN_TMP_TABLES;
@@ -472,6 +474,7 @@ void init_update_queries(void)
   sql_command_flags[SQLCOM_SELECT]|=          CF_PREOPEN_TMP_TABLES;
   sql_command_flags[SQLCOM_SET_OPTION]|=      CF_PREOPEN_TMP_TABLES;
   sql_command_flags[SQLCOM_DO]|=              CF_PREOPEN_TMP_TABLES;
+  sql_command_flags[SQLCOM_HA_OPEN]|=         CF_PREOPEN_TMP_TABLES;
   sql_command_flags[SQLCOM_CALL]|=            CF_PREOPEN_TMP_TABLES;
   sql_command_flags[SQLCOM_CHECKSUM]|=        CF_PREOPEN_TMP_TABLES;
   sql_command_flags[SQLCOM_ANALYZE]|=         CF_PREOPEN_TMP_TABLES;
@@ -488,6 +491,7 @@ void init_update_queries(void)
     have to be closed before emporary tables are pre-opened.
   */
   sql_command_flags[SQLCOM_CREATE_TABLE]|=    CF_HA_CLOSE;
+  sql_command_flags[SQLCOM_DROP_TABLE]|=      CF_HA_CLOSE;
   sql_command_flags[SQLCOM_ALTER_TABLE]|=     CF_HA_CLOSE;
   sql_command_flags[SQLCOM_TRUNCATE]|=        CF_HA_CLOSE;
   sql_command_flags[SQLCOM_REPAIR]|=          CF_HA_CLOSE;
@@ -2396,19 +2400,6 @@ case SQLCOM_PREPARE:
       goto end_with_restore_list;
     }
 
-    /*
-      Pre-open temporary tables from UNION clause to simplify privilege
-      checking for them.
-    */
-    if (lex->create_info.merge_list.elements)
-    {
-      if (open_temporary_tables(thd, lex->create_info.merge_list.first))
-      {
-        res= 1;
-        goto end_with_restore_list;
-      }
-    }
-
     if ((res= create_table_precheck(thd, select_tables, create_table)))
       goto end_with_restore_list;
 
@@ -3259,8 +3250,7 @@ end_with_restore_list:
     if (open_temporary_tables(thd, all_tables))
       goto error;
 
-    if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
-                           FALSE, UINT_MAX, FALSE))
+    if (lock_tables_precheck(thd, all_tables))
       goto error;
 
     thd->variables.option_bits|= OPTION_TABLE_LOCK;
@@ -3757,6 +3747,9 @@ end_with_restore_list:
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
     if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE))
       goto error;
+    /* Close temporary tables which were pre-opened for privilege checking. */
+    close_thread_tables(thd);
+    all_tables->table= NULL;
     res= mysql_ha_open(thd, first_table, 0);
     break;
   case SQLCOM_HA_CLOSE:
@@ -4998,10 +4991,10 @@ static bool check_show_access(THD *thd,
     DBUG_ASSERT(dst_table);
 
     /*
-      TODO/FIXME: In the upcoming patch we somehow should handle
-                  situation when table in question is a temporary
-                  table.
+      Open temporary tables to be able to detect them during privilege check.
     */
+    if (open_temporary_tables(thd, dst_table))
+      return TRUE;
 
     if (check_access(thd, SELECT_ACL, dst_table->db,
                      &dst_table->grant.privilege,
@@ -5016,6 +5009,9 @@ static bool check_show_access(THD *thd,
     if (check_grant(thd, SELECT_ACL, dst_table, TRUE, UINT_MAX, FALSE))
       return TRUE; /* Access denied */
 
+    close_thread_tables(thd);
+    dst_table->table= NULL;
+
     /* Access granted */
     return FALSE;
   }
@@ -6773,6 +6769,19 @@ bool multi_delete_precheck(THD *thd, TAB
   TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
   DBUG_ENTER("multi_delete_precheck");
 
+  /*
+    Temporary tables are pre-opened in 'tables' list only. Here we need to
+    initialize TABLE instances in 'aux_tables' list.
+  */
+  for (TABLE_LIST *tl= aux_tables; tl; tl= tl->next_global)
+  {
+    if (tl->table)
+      continue;
+
+    if (tl->correspondent_table)
+      tl->table= tl->correspondent_table->table;
+  }
+
   /* sql_yacc guarantees that tables and aux_tables are not zero */
   DBUG_ASSERT(aux_tables != 0);
   if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE))
@@ -7041,9 +7050,9 @@ bool create_table_precheck(THD *thd, TAB
     CREATE TABLE ... SELECT, also require INSERT.
   */
 
-  want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
-              CREATE_TMP_ACL : CREATE_ACL) |
-             (select_lex->item_list.elements ? INSERT_ACL : 0);
+  want_priv= (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
+             CREATE_TMP_ACL :
+             (CREATE_ACL | (select_lex->item_list.elements ? INSERT_ACL : 0));
 
   if (check_access(thd, want_priv, create_table->db,
                    &create_table->grant.privilege,
@@ -7052,11 +7061,35 @@ bool create_table_precheck(THD *thd, TAB
     goto err;
 
   /* If it is a merge table, check privileges for merge children. */
-  if (lex->create_info.merge_list.first &&
-      check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
-                         lex->create_info.merge_list.first,
-                         FALSE, UINT_MAX, FALSE))
-    goto err;
+  if (lex->create_info.merge_list.first)
+  {
+    /*
+      Pre-open temporary tables from UNION clause to simplify privilege
+      checking for them.
+    */
+    if (open_temporary_tables(thd, lex->create_info.merge_list.first))
+      goto err;
+
+    if (check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
+                           lex->create_info.merge_list.first,
+                           FALSE, UINT_MAX, FALSE))
+      goto err;
+
+    /*
+      Since the MERGE table in question might already exist with exactly
+      the same definition we need to close all tables opened for underlying
+      checking to allow normal open of table being created.
+      To do this we simply close all tables and then open only tables from
+      the main statement's table list.
+    */
+    close_thread_tables(thd);
+
+    for (TABLE_LIST *tl= lex->query_tables; tl; tl= tl->next_global)
+      tl->table= NULL;
+
+    if (open_temporary_tables(thd, lex->query_tables))
+      DBUG_RETURN(TRUE);
+  }
 
   if (want_priv != CREATE_TMP_ACL &&
       check_grant(thd, want_priv, create_table, FALSE, 1, FALSE))
@@ -7081,6 +7114,35 @@ err:
 }
 
 
+/**
+  Check privileges for LOCK TABLES statement.
+
+  @param thd     Thread context.
+  @param tables  List of tables to be locked.
+
+  @retval FALSE - Success.
+  @retval TRUE  - Failure.
+*/
+
+static bool lock_tables_precheck(THD *thd, TABLE_LIST *tables)
+{
+  TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
+
+  for (TABLE_LIST *table= tables; table != first_not_own_table && table;
+       table= table->next_global)
+  {
+    if (is_temporary_table(table))
+      continue;
+
+    if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, table,
+                           FALSE, 1, FALSE))
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
+
 /**
   negate given expression.
 

=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc	2011-03-09 12:24:36 +0000
+++ b/sql/sql_prepare.cc	2011-03-24 09:02:22 +0000
@@ -1716,14 +1716,6 @@ static bool mysql_test_create_table(Prep
   TABLE_LIST *create_table= lex->query_tables;
   TABLE_LIST *tables= lex->create_last_non_select_table->next_global;
 
-  if (lex->create_info.merge_list.elements)
-  {
-    if (open_temporary_tables(thd, lex->create_info.merge_list.first))
-    {
-      DBUG_RETURN(TRUE);
-    }
-  }
-
   if (create_table_precheck(thd, tables, create_table))
     DBUG_RETURN(TRUE);
 

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2011-03-09 12:24:36 +0000
+++ b/sql/sql_table.cc	2011-03-24 09:02:22 +0000
@@ -2062,14 +2062,18 @@ bool mysql_rm_table(THD *thd,TABLE_LIST
                            thd->variables.lock_wait_timeout, 0))
         DBUG_RETURN(true);
       for (table= tables; table; table= table->next_local)
+      {
+        if (is_temporary_table(table))
+          continue;
+
         tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
                          false);
+      }
     }
     else
     {
       for (table= tables; table; table= table->next_local)
-        if (table->open_type != OT_BASE_ONLY &&
-	    find_temporary_table(thd, table))
+        if (is_temporary_table(table))
         {
           /*
             A temporary table.
@@ -2136,6 +2140,9 @@ bool mysql_rm_table(THD *thd,TABLE_LIST
   @note This function assumes that metadata locks have already been taken.
         It is also assumed that the tables have been removed from TDC.
 
+  @note This function assumes that temporary tables to be dropped have
+        been pre-opened using corresponding table list elements.
+
   @todo When logging to the binary log, we should log
         tmp_tables and transactional tables as separate statements if we
         are in a transaction;  This is needed to get these tables into the


Attachment: [text/bzr-bundle] bzr/alexander.nozdrin@oracle.com-20110324090222-k29hmbp4mc45cqlx.bundle
Thread
bzr commit into mysql-trunk branch (alexander.nozdrin:3532) Bug#11746602Alexander Nozdrin24 Mar