MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:April 6 2010 12:22pm
Subject:bzr commit into mysql-next-mr-bugfixing branch (alik:3140) Bug#27480
View as plain text  
#At file:///mnt/raid/alik/MySQL/bzr/00/bug27480/mysql-next-mr-bf-bug27480/ based on revid:zhenxing.he@stripped

 3140 Alexander Nozdrin	2010-04-06
      Another preliminary patch for Bug#27480.

    added:
      mysql-test/r/create_notembedded.result
      mysql-test/t/create_notembedded.test
    modified:
      scripts/mysql_system_tables_data.sql
      sql/mysql_priv.h
      sql/sql_acl.cc
      sql/sql_base.cc
      sql/sql_parse.cc
=== 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-04-06 12:22:52 +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-04-06 12:22:52 +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 'scripts/mysql_system_tables_data.sql'
--- a/scripts/mysql_system_tables_data.sql	2009-11-25 10:53:23 +0000
+++ b/scripts/mysql_system_tables_data.sql	2010-04-06 12:22:52 +0000
@@ -10,7 +10,7 @@ set @current_hostname= @@hostname;
 
 -- Fill "db" table with default grants for anyone to
 -- access database 'test' and 'test_%' if "db" table didn't exist
-CREATE TEMPORARY TABLE tmp_db LIKE db;
+CREATE TABLE tmp_db LIKE db;
 INSERT INTO tmp_db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y');
 INSERT INTO tmp_db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y');
 INSERT INTO db SELECT * FROM tmp_db WHERE @had_db_table=0;
@@ -19,7 +19,7 @@ DROP TABLE tmp_db;
 
 -- Fill "users" table with default users allowing root access
 -- from local machine if "users" table didn't exist before
-CREATE TEMPORARY TABLE tmp_user LIKE user;
+CREATE TABLE tmp_user LIKE user;
 set @current_hostname= @@hostname;
 INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
 REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0 FROM dual WHERE LOWER( @current_hostname) != 'localhost';

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2010-03-22 10:36:23 +0000
+++ b/sql/mysql_priv.h	2010-04-06 12:22:52 +0000
@@ -1608,6 +1608,9 @@ TABLE_LIST *unique_table(THD *thd, TABLE
                          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);
@@ -2239,6 +2242,13 @@ 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,
+                    uint flags);
+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-03-20 09:35:40 +0000
+++ b/sql/sql_acl.cc	2010-04-06 12:22:52 +0000
@@ -3969,6 +3969,18 @@ end:
   DBUG_RETURN(return_val);
 }
 
+static bool check_grant_for_temp_table(THD *thd, TABLE_LIST *tl)
+{
+  TABLE *table= tl->table;
+
+  if (!table && tl->correspondent_table)
+    table= tl->correspondent_table->table;
+
+  return !(table &&
+      table->s->tmp_table != NO_TMP_TABLE &&
+      !check_access(thd, CREATE_TMP_ACL, table->s->db.str, NULL, NULL, 0, TRUE));
+}
+
 
 /**
   @brief Check table level grants
@@ -4098,9 +4110,24 @@ 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 (!check_grant_for_temp_table(thd, table))
+      continue;
+
+    if (!grant_table)
     {
       want_access &= ~table->grant.privilege;
       goto err;					// No grants
@@ -4113,12 +4140,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 +4296,9 @@ bool check_column_grant_in_table_ref(THD
     table_name= table->s->table_name.str;
   }
 
+  if (!check_grant_for_temp_table(thd, table_ref))
+    return FALSE;
+
   if (grant->want_privilege)
     return check_grant_column(thd, grant, db_name, table_name, name,
                               length, sctx);
@@ -4320,7 +4344,9 @@ 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();
+    bool is_tmp_table= field->table->s->tmp_table != NO_TMP_TABLE;
 
     if (table_name != fields->get_table_name())
     {
@@ -4342,11 +4368,20 @@ bool check_grant_all_columns(THD *thd, u
         }
 
         grant_table= grant->grant_table;
-        DBUG_ASSERT (grant_table);
+
+        DBUG_ASSERT(grant_table || !grant_table && is_tmp_table);
       }
     }
 
-    if (want_access)
+    if (is_tmp_table)
+    {
+      if (check_access(thd, CREATE_TMP_ACL, fields->get_db_name(),
+                       NULL, NULL, 0, TRUE))
+      {
+        goto err;
+      }
+    }
+    else if (want_access)
     {
       GRANT_COLUMN *grant_column= 
         column_hash_search(grant_table, field_name,

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2010-03-22 10:36:23 +0000
+++ b/sql/sql_base.cc	2010-04-06 12:22:52 +0000
@@ -1951,16 +1951,26 @@ 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");
+
+  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",
@@ -1969,7 +1979,7 @@ TABLE *find_temporary_table(THD *thd, TA
       DBUG_RETURN(table);
     }
   }
-  DBUG_RETURN(0);                               // Not a temporary table
+  DBUG_RETURN(NULL);  // Not a temporary table
 }
 
 
@@ -2124,6 +2134,147 @@ bool rename_temporary_table(THD* thd, TA
 }
 
 
+void update_table_flags(THD *thd, TABLE_LIST *table_list, TABLE *table)
+{
+  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,
+                                          table_list->alias);
+  /* Fix alias if table name changes */
+  if (strcmp(table->alias, table_list->alias))
+  {
+    uint length=(uint) strlen(table_list->alias)+1;
+    table->alias= (char*) my_realloc((char*) table->alias, length,
+                                     MYF(MY_WME));
+    memcpy((char*) table->alias, table_list->alias, length);
+  }
+  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();
+  table_list->table= table;
+  DBUG_ASSERT(table->key_read == 0);
+  /* Tables may be reused in a sub statement. */
+  if (table->file->extra(HA_EXTRA_IS_ATTACHED_CHILDREN))
+    table->file->extra(HA_EXTRA_DETACH_CHILDREN);
+}
+
+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, 0))
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
+
+/*
+  Unless requested otherwise, try to resolve this table in the 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.
+*/
+bool open_tmp_table(THD *thd,
+                    const char *table_key,
+                    uint table_key_length,
+                    TABLE_LIST *table_list,
+                    TABLE **tmp_table,
+                    uint flags)
+{
+  DBUG_ENTER("open_tmp_table");
+  DBUG_PRINT("enter", ("table: '%s'.'%s'",
+                       table_list->db, table_list->table_name));
+
+  *tmp_table= NULL;
+
+  if (table_list->open_type == OT_BASE_ONLY ||
+      (flags & MYSQL_OPEN_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;
+
+  if (table_list->open_type == OT_TEMPORARY_ONLY ||
+      (flags & MYSQL_OPEN_TEMPORARY_ONLY))
+  {
+    if (table_list->open_strategy == TABLE_LIST::OPEN_NORMAL)
+    {
+      my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->table_name);
+      DBUG_RETURN(TRUE);
+    }
+    else
+      DBUG_RETURN(FALSE);
+  }
+
+  DBUG_RETURN(FALSE);
+}
+
+
 /**
    Force all other threads to stop using the table by upgrading
    metadata lock on it and remove unused TABLE instances from cache.
@@ -2504,57 +2655,6 @@ bool open_table(THD *thd, TABLE_LIST *ta
       DBUG_RETURN(TRUE);
     }
   }
-  /*
-    Unless requested otherwise, try to resolve this table in the 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->open_type != OT_BASE_ONLY &&
-      ! (flags & MYSQL_OPEN_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(TRUE);
-	}
-	table->query_id= thd->query_id;
-	thd->thread_specific_used= TRUE;
-        DBUG_PRINT("info",("Using temporary table"));
-        goto reset;
-      }
-    }
-  }
-
-  if (table_list->open_type == OT_TEMPORARY_ONLY ||
-      (flags & MYSQL_OPEN_TEMPORARY_ONLY))
-  {
-    if (table_list->open_strategy == TABLE_LIST::OPEN_NORMAL)
-    {
-      my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->table_name);
-      DBUG_RETURN(TRUE);
-    }
-    else
-      DBUG_RETURN(FALSE);
-  }
 
   /*
     The table is not temporary - if we're in pre-locked or LOCK TABLES
@@ -2931,42 +3031,7 @@ bool open_table(THD *thd, TABLE_LIST *ta
   table->reginfo.lock_type=TL_READ;		/* Assume read */
 
  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);
-  }
-  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();
-  table_list->table= table;
-  DBUG_ASSERT(table->key_read == 0);
-  /* Tables may be reused in a sub statement. */
-  if (table->file->extra(HA_EXTRA_IS_ATTACHED_CHILDREN))
-    table->file->extra(HA_EXTRA_DETACH_CHILDREN);
+  update_table_flags(thd, table_list, table);
   DBUG_RETURN(FALSE);
 
 err_unlock:
@@ -4140,6 +4205,15 @@ open_and_process_table(THD *thd, LEX *le
   DBUG_ENTER("open_and_process_table");
 
   /*
+    If this is a temporary table. it is already open.
+  */
+  if (tables->table &&
+      tables->table->s->tmp_table != NO_TMP_TABLE)
+  {
+    goto end;
+  }
+
+  /*
     Ignore placeholders for derived tables. After derived tables
     processing, link to created temporary table will be put here.
     If this is derived table for view then we still want to process

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-03-20 09:35:40 +0000
+++ b/sql/sql_parse.cc	2010-04-06 12:22:52 +0000
@@ -2115,6 +2115,9 @@ mysql_execute_command(THD *thd)
     if (thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, TRUE))
       goto error;
 
+  if (open_tmp_tables(thd, all_tables))
+    goto error;
+
   switch (lex->sql_command) {
 
   case SQLCOM_SHOW_EVENTS:


Attachment: [text/bzr-bundle] bzr/alik@sun.com-20100406122252-zkyh0ixyixkjh4s5.bundle
Thread
bzr commit into mysql-next-mr-bugfixing branch (alik:3140) Bug#27480Alexander Nozdrin6 Apr