MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:March 11 2010 9:41am
Subject:bzr commit into mysql-5.5-next-mr-bugfixing branch (alik:2969)
Bug#27480
View as plain text  
#At file:///mnt/raid/alik/MySQL/bzr/00/bug27480/mysql-next-mr-bf-bug27480/ based on revid:holyfoot@stripped

 2969 Alexander Nozdrin	2010-03-11
      Patch for Bug#27480 (Extend CREATE TEMPORARY TABLES privilege
      to allow temp table operations).
      
      The problem was that CREATE TEMPORARY TABLES did not allow
      SELECT, INSERT INTO, UPDATE, DELETE FROM statements
      for temporary tables.

    added:
      mysql-test/r/create_notembedded.result
      mysql-test/t/create_notembedded.test
    modified:
      sql/mysql_priv.h
      sql/sql_acl.cc
      sql/sql_base.cc
      sql/sql_parse.cc
      sql/table.h
=== added file 'mysql-test/r/create_notembedded.result'
--- a/mysql-test/r/create_notembedded.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/create_notembedded.result	2010-03-11 09:41:41 +0000
@@ -0,0 +1,102 @@
+DROP DATABASE IF EXISTS mysqltest2;
+CREATE DATABASE mysqltest2;
+GRANT CREATE, SELECT ON test.* TO mysqltest_u1@localhost;
+GRANT CREATE TEMPORARY TABLES ON mysqltest2.* TO mysqltest_u1@localhost;
+CREATE TEMPORARY TABLE tmp1(a INT);
+CREATE TEMPORARY TABLE tmp2(a INT);
+CREATE TABLE t1(a INT);
+ERROR 42000: CREATE command denied to user 'mysqltest_u1'@'localhost' for table 't1'
+CREATE TABLE test.t1(a INT);
+INSERT INTO tmp1 VALUES (11), (12), (13);
+INSERT INTO tmp2 VALUES (21), (22), (23);
+CREATE TEMPORARY TABLE tmp3(b INT);
+INSERT INTO tmp3 SELECT a FROM tmp1 UNION SELECT a FROM tmp2;
+SELECT * FROM tmp3;
+b
+11
+12
+13
+21
+22
+23
+SELECT * FROM tmp1;
+a
+11
+12
+13
+SELECT * FROM tmp1, tmp2;
+a	a
+11	21
+12	21
+13	21
+11	22
+12	22
+13	22
+11	23
+12	23
+13	23
+SELECT * FROM tmp1, t1, tmp2;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
+SELECT * FROM tmp1, test.t1, tmp2;
+a	a	a
+UPDATE tmp1 SET a = a * 10;
+SELECT * FROM tmp1;
+a
+110
+120
+130
+UPDATE tmp2 SET a = a - 20 WHERE a >= 10;
+SELECT * FROM tmp2;
+a
+1
+2
+3
+UPDATE tmp1, tmp3
+SET a = a * 1, b = b * 1
+WHERE b < 100;
+SELECT * FROM tmp1;
+a
+110
+120
+130
+SELECT * FROM tmp3;
+b
+11
+12
+13
+21
+22
+23
+DELETE FROM tmp1;
+SELECT * FROM tmp1;
+a
+DELETE FROM tmp2 WHERE a > 2;
+SELECT * FROM tmp2;
+a
+1
+2
+DELETE FROM tmp2;
+INSERT INTO tmp1 VALUES (1), (2), (3);
+INSERT INTO tmp2 VALUES (2), (3), (4);
+SELECT * FROM tmp1;
+a
+1
+2
+3
+SELECT * FROM tmp2;
+a
+2
+3
+4
+DELETE a1, a2
+FROM tmp1 AS a1 INNER JOIN tmp2 AS a2
+WHERE a1.a = a2.a;
+SELECT * FROM tmp1;
+a
+1
+SELECT * FROM tmp2;
+a
+4
+DROP DATABASE mysqltest2;
+DROP TABLE t1;
+DROP USER mysqltest_u1@localhost;

=== added file 'mysql-test/t/create_notembedded.test'
--- a/mysql-test/t/create_notembedded.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/create_notembedded.test	2010-03-11 09:41:41 +0000
@@ -0,0 +1,92 @@
+# Grant tests not performed with embedded server
+-- source include/not_embedded.inc
+
+#
+# Bug#27480: Extend CREATE TEMPORARY TABLES privilege to allow temp table
+# operations.
+#
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest2;
+--enable_warnings
+
+CREATE DATABASE mysqltest2;
+
+GRANT CREATE, SELECT ON test.* TO mysqltest_u1@localhost;
+GRANT CREATE TEMPORARY TABLES ON mysqltest2.* TO mysqltest_u1@localhost;
+
+--connect (con1, localhost, mysqltest_u1, , mysqltest2)
+
+CREATE TEMPORARY TABLE tmp1(a INT);
+CREATE TEMPORARY TABLE tmp2(a INT);
+
+--error ER_TABLEACCESS_DENIED_ERROR
+CREATE TABLE t1(a INT);
+
+CREATE TABLE test.t1(a INT);
+
+# Check INSERT INTO.
+
+INSERT INTO tmp1 VALUES (11), (12), (13);
+INSERT INTO tmp2 VALUES (21), (22), (23);
+
+CREATE TEMPORARY TABLE tmp3(b INT);
+INSERT INTO tmp3 SELECT a FROM tmp1 UNION SELECT a FROM tmp2;
+SELECT * FROM tmp3;
+
+# Check SELECT.
+
+SELECT * FROM tmp1;
+
+SELECT * FROM tmp1, tmp2;
+
+--error ER_TABLEACCESS_DENIED_ERROR
+SELECT * FROM tmp1, t1, tmp2;
+
+SELECT * FROM tmp1, test.t1, tmp2;
+
+# Check UPDATE.
+
+UPDATE tmp1 SET a = a * 10;
+SELECT * FROM tmp1;
+
+UPDATE tmp2 SET a = a - 20 WHERE a >= 10;
+SELECT * FROM tmp2;
+
+UPDATE tmp1, tmp3
+SET a = a * 1, b = b * 1
+WHERE b < 100;
+
+SELECT * FROM tmp1;
+SELECT * FROM tmp3;
+
+# Check DELETE.
+
+DELETE FROM tmp1;
+SELECT * FROM tmp1;
+
+DELETE FROM tmp2 WHERE a > 2;
+SELECT * FROM tmp2;
+
+DELETE FROM tmp2;
+
+INSERT INTO tmp1 VALUES (1), (2), (3);
+INSERT INTO tmp2 VALUES (2), (3), (4);
+
+SELECT * FROM tmp1;
+SELECT * FROM tmp2;
+
+DELETE a1, a2
+FROM tmp1 AS a1 INNER JOIN tmp2 AS a2
+WHERE a1.a = a2.a;
+
+SELECT * FROM tmp1;
+SELECT * FROM tmp2;
+
+--connection default
+--disconnect con1
+
+DROP DATABASE mysqltest2;
+DROP TABLE t1;
+
+DROP USER mysqltest_u1@localhost;

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2010-02-17 12:15:07 +0000
+++ b/sql/mysql_priv.h	2010-03-11 09:41:41 +0000
@@ -1604,8 +1604,13 @@ TABLE_LIST *find_table_in_list(TABLE_LIS
                                const char *table_name);
 TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
                          bool check_alias);
+
 TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name);
 TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list);
+TABLE *find_temporary_table(THD *thd,
+                            const char *table_key,
+                            uint table_key_length);
+
 int drop_temporary_table(THD *thd, TABLE_LIST *table_list);
 void close_temporary_table(THD *thd, TABLE *table, bool free_share,
                            bool delete_table);
@@ -2222,6 +2227,12 @@ void open_table_error(TABLE_SHARE *share
 int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
                           uint db_stat, uint prgflag, uint ha_open_flags,
                           TABLE *outparam, bool is_create_table);
+bool open_tmp_table(THD *thd,
+                    const char *table_key,
+                    uint table_key_length,
+                    TABLE_LIST *table_list,
+                    TABLE **tmp_table);
+bool open_tmp_tables(THD *thd, TABLE_LIST *table_list);
 int readfrm(const char *name, uchar **data, size_t *length);
 int writefrm(const char* name, const uchar* data, size_t len);
 int closefrm(TABLE *table, bool free_share);

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2010-02-10 16:01:31 +0000
+++ b/sql/sql_acl.cc	2010-03-11 09:41:41 +0000
@@ -4098,9 +4098,23 @@ bool check_grant(THD *thd, ulong want_ac
       }
       continue;
     }
-    if (!(grant_table= table_hash_search(sctx->host, sctx->ip,
-                                         table->get_db_name(), sctx->priv_user,
-                                         table->get_table_name(), FALSE)))
+    grant_table= table_hash_search(sctx->host, sctx->ip,
+                                   table->get_db_name(), sctx->priv_user,
+                                   table->get_table_name(), FALSE);
+
+    if (grant_table)
+    {
+      table->grant.grant_table=grant_table;     // Remember for column test
+      table->grant.version=grant_version;
+      table->grant.privilege|= grant_table->privs;
+      table->grant.want_privilege= ((want_access & COL_ACLS)
+                                    & ~table->grant.privilege);
+    }
+
+    if (table->tmp_table_access_granted)
+      continue;
+
+    if (!grant_table)
     {
       want_access &= ~table->grant.privilege;
       goto err;					// No grants
@@ -4113,12 +4127,6 @@ bool check_grant(THD *thd, ulong want_ac
     if (any_combination_will_do)
       continue;
 
-    table->grant.grant_table=grant_table;	// Remember for column test
-    table->grant.version=grant_version;
-    table->grant.privilege|= grant_table->privs;
-    table->grant.want_privilege= ((want_access & COL_ACLS)
-				  & ~table->grant.privilege);
-
     if (!(~table->grant.privilege & want_access))
       continue;
 
@@ -4275,6 +4283,9 @@ bool check_column_grant_in_table_ref(THD
     table_name= table->s->table_name.str;
   }
 
+  if (table_ref->tmp_table_access_granted)
+    return FALSE;
+
   if (grant->want_privilege)
     return check_grant_column(thd, grant, db_name, table_name, name,
                               length, sctx);
@@ -4322,6 +4333,26 @@ bool check_grant_all_columns(THD *thd, u
   {
     const char *field_name= fields->name();
 
+    {
+      Field *fld= fields->field();
+      if (fld)
+      {
+        TABLE *tbl= fld->table;
+
+        if (tbl->pos_in_table_list)
+        {
+          if (tbl->pos_in_table_list->tmp_table_access_granted)
+          {
+            /*
+              This field belongs to a temporary table. The user should have
+              had the CREATE TEMPORARY TABLE privilege to come here.
+            */
+            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	2010-02-10 22:27:23 +0000
+++ b/sql/sql_base.cc	2010-03-11 09:41:41 +0000
@@ -1794,16 +1794,25 @@ TABLE *find_temporary_table(THD *thd, TA
 {
   char	key[MAX_DBKEY_LENGTH];
   uint	key_length;
-  TABLE *table;
-  DBUG_ENTER("find_temporary_table");
+  DBUG_ENTER("find_temporary_table(TABLE_LIST)");
   DBUG_PRINT("enter", ("table: '%s'.'%s'",
                        table_list->db, table_list->table_name));
 
   key_length= create_table_def_key(thd, key, table_list, 1);
-  for (table=thd->temporary_tables ; table ; table= table->next)
+
+  DBUG_RETURN(find_temporary_table(thd, key, key_length));
+}
+
+TABLE *find_temporary_table(THD *thd,
+                            const char *table_key,
+                            uint table_key_length)
+{
+  DBUG_ENTER("find_temporary_table(key)");
+
+  for (TABLE *table= thd->temporary_tables; table; table= table->next)
   {
-    if (table->s->table_cache_key.length == key_length &&
-	!memcmp(table->s->table_cache_key.str, key, key_length))
+    if (table->s->table_cache_key.length == table_key_length &&
+        !memcmp(table->s->table_cache_key.str, table_key, table_key_length))
     {
       DBUG_PRINT("info",
                  ("Found table. server_id: %u  pseudo_thread_id: %lu",
@@ -2509,6 +2518,124 @@ bool check_if_table_exists(THD *thd, TAB
   }
 }
 
+bool open_tmp_tables(THD *thd, TABLE_LIST *table_list)
+{
+  for (TABLE_LIST *tl= table_list; tl; tl= tl->next_global)
+  {
+    /*
+      If TABLE_LIST::schema_table is set, TABLE_LIST::table_name may be
+      corrupted.
+
+      TABLE_LIST::db may be an empty string, and TABLE_LIST::table_name
+      is corrupted in this case.
+    */
+
+    if (tl->schema_table || !tl->db[0])
+      continue;
+
+    char key[MAX_DBKEY_LENGTH];
+    uint key_length;
+
+    key_length= create_table_def_key(thd, key, tl, 1);
+
+    if (open_tmp_table(thd, key, key_length, tl, &tl->table))
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
+void update_table_flags(THD *thd, TABLE_LIST *tl, TABLE *table)
+{
+  if (thd->lex->need_correct_ident())
+    table->alias_name_used= my_strcasecmp(table_alias_charset,
+                                          table->s->table_name.str, tl->alias);
+  /* Fix alias if table name changes */
+  if (strcmp(table->alias, tl->alias))
+  {
+    uint length=(uint) strlen(tl->alias)+1;
+    table->alias= (char*) my_realloc((char*) table->alias, length, MYF(MY_WME));
+    memcpy((char*) table->alias, tl->alias, length);
+  }
+
+  /* These variables are also set in reopen_table() */
+  table->tablenr=thd->current_tablenr++;
+  table->used_fields=0;
+  table->const_table=0;
+  table->null_row= table->maybe_null= 0;
+  table->force_index= table->force_index_order= table->force_index_group= 0;
+  table->status= STATUS_NO_RECORD;
+  table->insert_values= 0;
+  table->fulltext_searched= 0;
+  table->file->ft_handler= 0;
+  table->reginfo.impossible_range= 0;
+
+  /* Catch wrong handling of the auto_increment_field_not_null. */
+  DBUG_ASSERT(!table->auto_increment_field_not_null);
+  table->auto_increment_field_not_null= FALSE;
+
+  if (table->timestamp_field)
+    table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
+
+  table->pos_in_table_list= tl;
+  tl->updatable= 1; // It is not derived table nor non-updatable VIEW
+  table->clear_column_bitmaps();
+
+  DBUG_ASSERT(table->key_read == 0);
+}
+
+
+bool open_tmp_table(THD *thd,
+                    const char *table_key,
+                    uint table_key_length,
+                    TABLE_LIST *table_list,
+                    TABLE **tmp_table)
+{
+  DBUG_ENTER("open_tmp_table");
+  DBUG_PRINT("enter", ("table: '%s'.'%s'",
+                       table_list->db, table_list->table_name));
+
+  *tmp_table= NULL;
+
+  if (table_list->skip_temporary)
+  {
+    DBUG_PRINT("info", ("skip_temporary is set"));
+    DBUG_RETURN(FALSE);
+  }
+
+  TABLE *table= find_temporary_table(thd, table_key, table_key_length);
+
+  if (!table)
+    DBUG_RETURN(FALSE);
+
+  if (table->query_id)
+  {
+    /*
+      We're trying to use the same temporary table twice in a query.
+      Right now we don't support this because a temporary table is always
+      represented by only one TABLE object in THD, and it can not be
+      cloned. Emit an error for an unsupported behaviour.
+    */
+
+    DBUG_PRINT("error",
+               ("query_id: %lu  server_id: %u  pseudo_thread_id: %lu",
+                (ulong) table->query_id, (uint) thd->server_id,
+                (ulong) thd->variables.pseudo_thread_id));
+    my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias);
+    DBUG_RETURN(TRUE);
+  }
+
+  table->query_id= thd->query_id;
+  thd->thread_specific_used= TRUE;
+
+  update_table_flags(thd, table_list, table);
+
+  DBUG_PRINT("info", ("Using temporary table"));
+  *tmp_table= table;
+
+  DBUG_RETURN(FALSE);
+}
+
 
 /*
   Open a table.
@@ -2546,7 +2673,7 @@ bool check_if_table_exists(THD *thd, TAB
 TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
 		  bool *refresh, uint flags)
 {
-  reg1	TABLE *table;
+  TABLE *table;
   char	key[MAX_DBKEY_LENGTH];
   uint	key_length;
   char	*alias= table_list->alias;
@@ -2573,39 +2700,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *
     of temporary tables of this thread. In MySQL temporary tables
     are always thread-local and "shadow" possible base tables with the
     same name. This block implements the behaviour.
-    TODO: move this block into a separate function.
   */
-  if (!table_list->skip_temporary)
-  {
-    for (table= thd->temporary_tables; table ; table=table->next)
-    {
-      if (table->s->table_cache_key.length == key_length +
-          TMP_TABLE_KEY_EXTRA &&
-	  !memcmp(table->s->table_cache_key.str, key,
-		  key_length + TMP_TABLE_KEY_EXTRA))
-      {
-        /*
-          We're trying to use the same temporary table twice in a query.
-          Right now we don't support this because a temporary table
-          is always represented by only one TABLE object in THD, and
-          it can not be cloned. Emit an error for an unsupported behaviour.
-        */
-	if (table->query_id)
-	{
-          DBUG_PRINT("error",
-                     ("query_id: %lu  server_id: %u  pseudo_thread_id: %lu",
-                      (ulong) table->query_id, (uint) thd->server_id,
-                      (ulong) thd->variables.pseudo_thread_id));
-	  my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias);
-	  DBUG_RETURN(0);
-	}
-	table->query_id= thd->query_id;
-	thd->thread_specific_used= TRUE;
-        DBUG_PRINT("info",("Using temporary table"));
-        goto reset;
-      }
-    }
-  }
+
+  if (open_tmp_table(thd, key, key_length + TMP_TABLE_KEY_EXTRA, table_list, &table))
+    DBUG_RETURN(0); // Error occurred.
+
+  if (table)
+    goto reset; // Tmp table has been found.
 
   if (flags & MYSQL_OPEN_TEMPORARY_ONLY)
   {
@@ -2987,37 +3088,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *
  reset:
   DBUG_ASSERT(table->s->ref_count > 0 || table->s->tmp_table != NO_TMP_TABLE);
 
-  if (thd->lex->need_correct_ident())
-    table->alias_name_used= my_strcasecmp(table_alias_charset,
-                                          table->s->table_name.str, alias);
-  /* Fix alias if table name changes */
-  if (strcmp(table->alias, alias))
-  {
-    uint length=(uint) strlen(alias)+1;
-    table->alias= (char*) my_realloc((char*) table->alias, length,
-                                     MYF(MY_WME));
-    memcpy((char*) table->alias, alias, length);
-  }
-  /* These variables are also set in reopen_table() */
-  table->tablenr=thd->current_tablenr++;
-  table->used_fields=0;
-  table->const_table=0;
-  table->null_row= table->maybe_null= 0;
-  table->force_index= table->force_index_order= table->force_index_group= 0;
-  table->status=STATUS_NO_RECORD;
-  table->insert_values= 0;
-  table->fulltext_searched= 0;
-  table->file->ft_handler= 0;
-  table->reginfo.impossible_range= 0;
-  /* Catch wrong handling of the auto_increment_field_not_null. */
-  DBUG_ASSERT(!table->auto_increment_field_not_null);
-  table->auto_increment_field_not_null= FALSE;
-  if (table->timestamp_field)
-    table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
-  table->pos_in_table_list= table_list;
-  table_list->updatable= 1; // It is not derived table nor non-updatable VIEW
-  table->clear_column_bitmaps();
-  DBUG_ASSERT(table->key_read == 0);
+  update_table_flags(thd, table_list, table);
+
   DBUG_RETURN(table);
 }
 

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-02-05 12:05:37 +0000
+++ b/sql/sql_parse.cc	2010-03-11 09:41:41 +0000
@@ -1844,6 +1844,25 @@ bool sp_process_definer(THD *thd)
   DBUG_RETURN(FALSE);
 }
 
+static bool resolve_temporary_tables(THD *thd, TABLE_LIST *table_list)
+{
+  if (open_tmp_tables(thd, table_list))
+    return TRUE;
+
+  for (TABLE_LIST *tl= table_list;
+       tl && tl!= thd->lex->first_not_own_table();
+       tl= tl->next_global)
+  {
+    if (!tl->table)
+      continue;
+
+    tl->tmp_table_access_granted= !check_access(thd, CREATE_TMP_ACL, tl->db,
+                                                NULL, NULL, 0, TRUE);
+  }
+
+  return FALSE;
+}
+
 
 /**
   Execute command saved in thd and lex->sql_command.
@@ -2123,6 +2142,16 @@ mysql_execute_command(THD *thd)
     ulong privileges_requested= lex->exchange ? SELECT_ACL | FILE_ACL :
       SELECT_ACL;
 
+    /*
+      Resolve temporary tables and check if access is granted to them
+      (the current user have the CREATE TEMPORARY TABLES privilege).
+    */
+
+    if ((res= resolve_temporary_tables(thd, all_tables)))
+      break;
+
+    /* Check access. */
+
     if (all_tables)
       res= check_table_access(thd,
                               privileges_requested,
@@ -2931,6 +2960,10 @@ end_with_restore_list:
   {
     ha_rows found= 0, updated= 0;
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
+
+    if ((res= resolve_temporary_tables(thd, all_tables)))
+      break;
+
     if (update_precheck(thd, all_tables))
       break;
     if (!thd->locked_tables &&
@@ -2960,6 +2993,8 @@ end_with_restore_list:
     /* if we switched from normal update, rights are checked */
     if (up_result != 2)
     {
+      if ((res= resolve_temporary_tables(thd, all_tables)))
+        break;
       if ((res= multi_update_precheck(thd, all_tables)))
         break;
     }
@@ -3071,6 +3106,10 @@ end_with_restore_list:
   case SQLCOM_INSERT:
   {
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
+
+    if ((res= resolve_temporary_tables(thd, all_tables)))
+      break;
+
     if ((res= insert_precheck(thd, all_tables)))
       break;
 
@@ -3102,6 +3141,10 @@ end_with_restore_list:
   {
     select_result *sel_result;
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
+
+    if ((res= resolve_temporary_tables(thd, all_tables)))
+      break;
+
     if ((res= insert_precheck(thd, all_tables)))
       break;
 
@@ -3197,8 +3240,13 @@ end_with_restore_list:
   case SQLCOM_DELETE:
   {
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
+
+    if ((res= resolve_temporary_tables(thd, all_tables)))
+      break;
+
     if ((res= delete_precheck(thd, all_tables)))
       break;
+
     DBUG_ASSERT(select_lex->offset_limit == 0);
     unit->set_limit(select_lex);
 
@@ -3230,6 +3278,12 @@ end_with_restore_list:
       break;
     }
 
+    if ((res= resolve_temporary_tables(thd, all_tables)))
+      break;
+
+    for (TABLE_LIST *tl= aux_tables; tl; tl= tl->next_global)
+      tl->tmp_table_access_granted= tl->correspondent_table->tmp_table_access_granted;
+
     if ((res= multi_delete_precheck(thd, all_tables)))
       break;
 

=== modified file 'sql/table.h'
--- a/sql/table.h	2010-01-13 12:22:34 +0000
+++ b/sql/table.h	2010-03-11 09:41:41 +0000
@@ -1421,6 +1421,8 @@ struct TABLE_LIST
   /* TRUE <=> this table is a const one and was optimized away. */
   bool optimized_away;
 
+  bool tmp_table_access_granted;
+
   uint i_s_requested_object;
   bool has_db_lookup_value;
   bool has_table_lookup_value;


Attachment: [text/bzr-bundle] bzr/alik@sun.com-20100311094141-pck0qi62l752e35v.bundle
Thread
bzr commit into mysql-5.5-next-mr-bugfixing branch (alik:2969)Bug#27480Alexander Nozdrin11 Mar