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

 3531 Alexander Nozdrin	2011-03-09
      Patch for Bug#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/r/flush_read_lock.result
      mysql-test/r/grant.result
      mysql-test/t/flush_read_lock.test
      mysql-test/t/grant.test
      sql/sql_acl.cc
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_parse.cc
      sql/sql_table.cc
=== 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-09 12:34:53 +0000
@@ -543,11 +543,11 @@ 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 semi-compatible with FTWRL: it is if the table exists;
+#         it is not if the table does not exist.
+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/grant.result'
--- a/mysql-test/r/grant.result	2011-02-08 15:54:12 +0000
+++ b/mysql-test/r/grant.result	2011-03-09 12:34:53 +0000
@@ -2348,3 +2348,149 @@ DROP USER mysqltest_u1@localhost;
 
 # End of Bug#38347.
 
+
+# --
+# -- Bug#27480
+# --
+
+DROP DATABASE IF EXISTS mysqltest_db1;
+SET GLOBAL keycache1.key_buffer_size=128*1024;
+CREATE DATABASE mysqltest_db1;
+GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT ALL PRIVILEGES ON mysqltest_db1.* TO mysqltest_u2@localhost;
+REVOKE CREATE TEMPORARY TABLES ON mysqltest_db1.* FROM mysqltest_u2@localhost;
+GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u3@localhost;
+GRANT CREATE ROUTINE ON mysqltest_db1.* TO mysqltest_u3@localhost;
+GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u4@localhost;
+GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u4@localhost;
+CREATE DEFINER=mysqltest_u4@localhost PROCEDURE mysqltest_db1.p1()
+CREATE TEMPORARY TABLE t4(x INT);
+CREATE DEFINER=mysqltest_u4@localhost PROCEDURE mysqltest_db1.p2()
+INSERT INTO t4 VALUES (1), (2), (3);
+CREATE DEFINER=mysqltest_u4@localhost PROCEDURE mysqltest_db1.p3()
+SELECT * FROM t4 ORDER BY x;
+
+# -- connect con1, mysqltest_u1@localhost, mysqltest_db1
+CREATE TEMPORARY TABLE t1(a INT);
+CREATE TEMPORARY TABLE t2(a INT);
+CREATE TEMPORARY TABLE t3(a INT, b INT, PRIMARY KEY (a));
+LOCK TABLES t1 READ;
+UNLOCK TABLES;
+INSERT INTO t1 VALUES(1), (2), (3);
+INSERT INTO t2 SELECT a FROM t1;
+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;
+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
+DELETE FROM t1;
+DELETE FROM t2;
+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
+222
+333
+444
+1111
+SELECT * FROM t3 ORDER BY a;
+a	b
+0	1
+1	1111
+2	222
+3	333
+4	444
+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
+222
+333
+444
+1111
+DEALLOCATE PREPARE stmt1;
+DEALLOCATE PREPARE stmt2;
+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
+DELETE FROM t1;
+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
+CREATE INDEX idx1 ON t3(b);
+DROP INDEX idx1 ON t3;
+RENAME TABLE t3 TO t3_1;
+ERROR 42000: DROP, ALTER command denied to user 'mysqltest_u1'@'localhost' for table 't3'
+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
+CHECKSUM TABLE t1;
+Table	Checksum
+mysqltest_db1.t1	0
+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
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TEMPORARY TABLE `t1` (
+  `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 ADD COLUMN b INT;
+INSERT INTO t1 VALUES(1, 10), (2, 20), (3, 30);
+TRUNCATE TABLE t1;
+SELECT * FROM t1 ORDER BY a;
+a	b
+DROP TABLE t1;
+CREATE TEMPORARY TABLE t1(a INT);
+DROP TEMPORARY TABLE t1;
+
+# -- 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
+
+# -- connect con3, mysqltest_u3@localhost, mysqltest_db1
+CREATE TEMPORARY TABLE t1(a INT);
+INSERT INTO t1 VALUES (1), (2), (3);
+DO (SELECT COUNT(*) FROM t1);
+
+# -- connection: default
+# -- disconnect con1
+# -- disconnect con2
+# -- disconnect con3
+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/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-09 12:34:53 +0000
@@ -706,11 +706,11 @@ 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 semi-compatible with FTWRL: it is if the table exists;
+--echo #         it is not if the table does not exist.
 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/grant.test'
--- a/mysql-test/t/grant.test	2011-02-23 04:53:07 +0000
+++ b/mysql-test/t/grant.test	2011-03-09 12:34:53 +0000
@@ -2010,3 +2010,191 @@ DROP USER mysqltest_u1@localhost;
 --echo
 --echo # End of Bug#38347.
 --echo
+
+--echo 
+--echo # --
+--echo # -- Bug#27480
+--echo # --
+--echo
+
+###########################################################################
+# Setup environment.
+###########################################################################
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest_db1;
+--enable_warnings
+
+SET GLOBAL keycache1.key_buffer_size=128*1024;
+
+CREATE DATABASE mysqltest_db1;
+
+# mysqltest_u1@localhost has CREATE_TMP_ACL only.
+GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+# mysqltest_u2@localhost has all privieleges 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 & CREATE_PROC_ACL.
+# This user is required to check 'DO' statement.
+GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u3@localhost;
+GRANT CREATE ROUTINE ON mysqltest_db1.* TO mysqltest_u3@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_u4@localhost;
+GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u4@localhost;
+
+# Create SUID-stored-routines.
+
+CREATE DEFINER=mysqltest_u4@localhost PROCEDURE mysqltest_db1.p1()
+  CREATE TEMPORARY TABLE t4(x INT);
+
+CREATE DEFINER=mysqltest_u4@localhost PROCEDURE mysqltest_db1.p2()
+  INSERT INTO t4 VALUES (1), (2), (3);
+
+CREATE DEFINER=mysqltest_u4@localhost PROCEDURE mysqltest_db1.p3()
+  SELECT * FROM t4 ORDER BY x;
+
+###########################################################################
+# Check that CREATE_TMP_ACL is enough to issue any supported SQL-statement
+# against temporary tables.
+###########################################################################
+
+--echo
+--echo # -- connect con1, mysqltest_u1@localhost, mysqltest_db1
+--connect (con1,localhost,mysqltest_u1,,mysqltest_db1)
+
+CREATE TEMPORARY TABLE t1(a INT);
+CREATE TEMPORARY TABLE t2(a INT);
+CREATE TEMPORARY TABLE t3(a INT, b INT, PRIMARY KEY (a));
+
+LOCK TABLES t1 READ;
+UNLOCK TABLES;
+
+INSERT INTO t1 VALUES(1), (2), (3);
+INSERT INTO t2 SELECT a FROM t1;
+
+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;
+
+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;
+
+DELETE FROM t1;
+DELETE FROM t2;
+
+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;
+
+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;
+
+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;
+DELETE FROM t1;
+
+CACHE INDEX t3 IN keycache1;
+LOAD INDEX INTO CACHE t3;
+
+CREATE INDEX idx1 ON t3(b);
+DROP INDEX idx1 ON t3;
+
+--error ER_TABLEACCESS_DENIED_ERROR
+RENAME TABLE t3 TO t3_1;
+
+ANALYZE TABLE t1;
+CHECK TABLE t1;
+CHECKSUM TABLE t1;
+OPTIMIZE TABLE t1;
+REPAIR TABLE t1;
+
+SHOW CREATE TABLE t1;
+
+ALTER TABLE t1 ADD COLUMN b INT;
+
+INSERT INTO t1 VALUES(1, 10), (2, 20), (3, 30);
+TRUNCATE TABLE t1;
+
+SELECT * FROM t1 ORDER BY a;
+
+DROP TABLE t1;
+
+CREATE TEMPORARY TABLE t1(a INT);
+DROP TEMPORARY TABLE t1;
+
+###########################################################################
+# - Check that even having all privieleges but CREATE_TMP_ACL is not enough to
+#   create temporary tables.
+# - Check that working with temporary tables is possible via
+#   SUID-stored-routines.
+###########################################################################
+
+--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();
+
+###########################################################################
+# Check that DO works under CREATE_TMP_ACL.
+###########################################################################
+
+--echo
+--echo # -- connect con3, mysqltest_u3@localhost, mysqltest_db1
+--connect (con3,localhost,mysqltest_u3,,mysqltest_db1)
+
+CREATE TEMPORARY TABLE t1(a INT);
+INSERT INTO t1 VALUES (1), (2), (3);
+
+DO (SELECT COUNT(*) FROM t1);
+
+###########################################################################
+# That's all.
+###########################################################################
+
+--echo
+--echo # -- connection: default
+--connection default
+
+--echo # -- disconnect con1
+--disconnect con1
+
+--echo # -- disconnect con2
+--disconnect con2
+
+--echo # -- disconnect con3
+--disconnect con3
+
+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 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2011-02-18 09:56:51 +0000
+++ b/sql/sql_acl.cc	2011-03-09 12:34:53 +0000
@@ -4617,6 +4617,10 @@ bool check_grant(THD *thd, ulong want_ac
       }
       continue;
     }
+
+    if (is_temporary_table(tl))
+      continue;
+
     GRANT_TABLE *grant_table= table_hash_search(sctx->host, sctx->ip,
                                                 tl->get_db_name(),
                                                 sctx->priv_user,
@@ -4798,7 +4802,9 @@ bool check_column_grant_in_table_ref(THD
   }
 
   if (grant->want_privilege)
-    return check_grant_column(thd, grant, db_name, table_name, name,
+    return is_temporary_table(table_ref) ?
+           FALSE :
+           check_grant_column(thd, grant, db_name, table_name, name,
                               length, sctx);
   else
     return FALSE;
@@ -4842,8 +4848,13 @@ bool check_grant_all_columns(THD *thd, u
 
   for (; !fields->end_of_fields(); fields->next())
   {
+    Field *field= fields->field();
     const char *field_name= fields->name();
 
+    if (field && field->table &&
+        is_temporary_table(field->table->pos_in_table_list))
+      continue;
+
     if (table_name != fields->get_table_name())
     {
       table_name= fields->get_table_name();

=== 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-09 12:34:53 +0000
@@ -2071,14 +2071,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)
   {
@@ -2095,6 +2096,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-09 12:34:53 +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_LIST
+    instances, like for SHOW TRIGGERS LIKE ...
+  */
+
+  if (!tl->table->s)
+    return FALSE;
+
+  return tl->table->s->tmp_table != NO_TMP_TABLE;
 }
 
 

=== 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-09 12:34:53 +0000
@@ -455,6 +455,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;
@@ -488,6 +489,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;
@@ -2768,14 +2770,17 @@ end_with_restore_list:
           goto error;
 
         /*
+          SHOW CREATE TABLE is always granted for temporary tables.
+
           The fact that check_some_access() returned FALSE does not mean that
           access is granted. We need to check if first_table->grant.privilege
           contains any table-specific privilege.
         */
         DBUG_PRINT("debug", ("first_table->grant.privilege: %lx",
                              first_table->grant.privilege));
-        if (check_some_access(thd, SHOW_CREATE_TABLE_ACLS, first_table) ||
-            (first_table->grant.privilege & SHOW_CREATE_TABLE_ACLS) == 0)
+        if (!is_temporary_table(first_table) &&
+            (check_some_access(thd, SHOW_CREATE_TABLE_ACLS, first_table) ||
+             (first_table->grant.privilege & SHOW_CREATE_TABLE_ACLS) == 0))
         {
           my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
                   "SHOW", thd->security_ctx->priv_user,
@@ -4657,6 +4662,13 @@ bool check_single_table_access(THD *thd,
 {
   Security_context * backup_ctx= thd->security_ctx;
 
+  /*
+    NOTE: we don't check privileges for temporary tables. This check here
+    is needed for SQLCOM_LOAD.
+  */
+  if (is_temporary_table(all_tables))
+    return 0;
+
   /* we need to switch to the saved context (if any) */
   if (all_tables->security_ctx)
     thd->security_ctx= all_tables->security_ctx;
@@ -5080,6 +5092,13 @@ check_table_access(THD *thd, ulong requi
   for (; i < number && tables != first_not_own_table && tables;
        tables= tables->next_global, i++)
   {
+    /*
+      This check is needed here to make sure LOCK TABLES can be called by
+      users with CREATE_TMP_ACL only.
+    */
+    if (is_temporary_table(tables))
+      continue;
+
     ulong want_access= requirements;
     if (tables->security_ctx)
       sctx= tables->security_ctx;
@@ -6773,6 +6792,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))

=== 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-09 12:34:53 +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 (table->open_type != OT_BASE_ONLY && is_temporary_table(table))
         {
           /*
             A temporary table.


Attachment: [text/bzr-bundle] bzr/alexander.nozdrin@oracle.com-20110309123453-rzkyyew26s0ex1i4.bundle
Thread
bzr commit into mysql-trunk branch (alexander.nozdrin:3531) Bug#27480Alexander Nozdrin9 Mar