diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index e0d2e07bef2..0b96f71d585 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -432,3 +432,4 @@ explain select * from t1 where a=binary 'aaa';
 explain select * from t1 where a='aaa' collate latin1_bin;
 # this one cannot:
 explain select * from t1 where a='aaa' collate latin1_german1_ci;
+drop table t1;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 82912f8a0fa..185d4f115ad 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3514,7 +3514,7 @@ Item_func_sp::func_name() const
              1 +                         // .
              1 +                         // end of string
              ALIGN_SIZE(1));             // to avoid String reallocation
-  String qname((char *)alloc_root(&thd->mem_root, len), len,
+  String qname((char *)alloc_root(thd->mem_root, len), len,
                system_charset_info);
 
   qname.length(0);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 28d77cdf8b5..72c85e2dd40 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -313,7 +313,7 @@ Item_sum_sum_distinct::~Item_sum_sum_distinct()
 Item *
 Item_sum_sum_distinct::copy_or_same(THD *thd)
 {
-  return new (&thd->mem_root) Item_sum_sum_distinct(thd, this);
+  return new (thd->mem_root) Item_sum_sum_distinct(thd, this);
 }
 
 C_MODE_START
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 997edbdf155..f036cbc799b 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1041,7 +1041,7 @@ QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
   rowid_length= table->file->ref_length;
   record= head->record[0];
   init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
-  thd_param->malloc= &alloc;
+  thd_param->mem_root= &alloc;
 }
 
 
@@ -7497,7 +7497,7 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
   if (!parent_alloc)
   {
     init_sql_alloc(&alloc, join->thd->variables.range_alloc_block_size, 0);
-    thd->mem_root= &alloc;
+    join->thd->mem_root= &alloc;
   }
   else
     bzero(&alloc, sizeof(MEM_ROOT));            // ensure that it's not used
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index f548c16d808..c3043ed2c73 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -608,15 +608,13 @@ parse_quoted_escaped_string(char *ptr, char *end,
 
 my_bool
 File_parser::parse(gptr base, MEM_ROOT *mem_root,
-		  struct File_option *parameters, uint required)
+                   struct File_option *parameters, uint required)
 {
   uint first_param= 0, found= 0;
   register char *ptr= start;
   char *eol;
   LEX_STRING *str;
-  MEM_ROOT *sql_mem;
   List<LEX_STRING> *list;
-  bool change_mem;
   DBUG_ENTER("File_parser::parse");
 
   while (ptr < end && found < required)
@@ -720,18 +718,7 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
 	}
 	case FILE_OPTIONS_STRLIST:
 	{
-	  /*
-	    TODO: remove play with mem_root, when List will be able
-	    to store MEM_ROOT* pointer for list elements allocation
-            FIXME: we can't handle empty lists
-	  */
-	  sql_mem= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC);
-	  list= (List<LEX_STRING>*)(base + parameter->offset);
-	  if ((change_mem= (sql_mem != mem_root)))
-	  {
-	    change_mem= 1;
-	    my_pthread_setspecific_ptr(THR_MALLOC, mem_root);
-	  }
+          list= (List<LEX_STRING>*)(base + parameter->offset);
 	    
 	  list->empty();
 	  // list parsing
@@ -739,7 +726,7 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
 	  {
 	    if (!(str= (LEX_STRING*)alloc_root(mem_root,
 					       sizeof(LEX_STRING))) ||
-		list->push_back(str))
+		list->push_back(str, mem_root))
 	      goto list_err;
 	    if(!(ptr= parse_quoted_escaped_string(ptr, end, mem_root, str)))
 	      goto list_err_w_message;
@@ -754,20 +741,15 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
 	      goto list_err_w_message;
 	    }
 	  }
-	end_of_list:
+      end_of_list:
 	  if (*(ptr++) != '\n')
 	    goto list_err;
-
-	  if (change_mem)
-	    my_pthread_setspecific_ptr(THR_MALLOC, sql_mem);
 	  break;
 
       list_err_w_message:
 	  my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
 		     parameter->name.str, line);
       list_err:
-	  if (change_mem)
-	    my_pthread_setspecific_ptr(THR_MALLOC, sql_mem);
 	  DBUG_RETURN(TRUE);
 	}
 	default:
diff --git a/sql/sp.cc b/sql/sp.cc
index a1e52ee1ca7..96bb8a17a49 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -166,7 +166,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
   }
 
   bzero((char *)&chistics, sizeof(chistics));
-  if ((ptr= get_field(&thd->mem_root,
+  if ((ptr= get_field(thd->mem_root,
 		      table->field[MYSQL_PROC_FIELD_ACCESS])) == NULL)
   {
     ret= SP_GET_FIELD_FAILED;
@@ -189,7 +189,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
     chistics.daccess= SP_CONTAINS_SQL;
   }
 
-  if ((ptr= get_field(&thd->mem_root,
+  if ((ptr= get_field(thd->mem_root,
 		      table->field[MYSQL_PROC_FIELD_DETERMINISTIC])) == NULL)
   {
     ret= SP_GET_FIELD_FAILED;
@@ -197,7 +197,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
   }
   chistics.detistic= (ptr[0] == 'N' ? FALSE : TRUE);    
 
-  if ((ptr= get_field(&thd->mem_root,
+  if ((ptr= get_field(thd->mem_root,
 		      table->field[MYSQL_PROC_FIELD_SECURITY_TYPE])) == NULL)
   {
     ret= SP_GET_FIELD_FAILED;
@@ -205,7 +205,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
   }
   chistics.suid= (ptr[0] == 'I' ? SP_IS_NOT_SUID : SP_IS_SUID);
 
-  if ((params= get_field(&thd->mem_root,
+  if ((params= get_field(thd->mem_root,
 			 table->field[MYSQL_PROC_FIELD_PARAM_LIST])) == NULL)
   {
     params= "";
@@ -213,14 +213,14 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
 
   if (type == TYPE_ENUM_PROCEDURE)
     returns= "";
-  else if ((returns= get_field(&thd->mem_root,
+  else if ((returns= get_field(thd->mem_root,
 			       table->field[MYSQL_PROC_FIELD_RETURNS])) == NULL)
   {
     ret= SP_GET_FIELD_FAILED;
     goto done;
   }
 
-  if ((body= get_field(&thd->mem_root,
+  if ((body= get_field(thd->mem_root,
 		       table->field[MYSQL_PROC_FIELD_BODY])) == NULL)
   {
     ret= SP_GET_FIELD_FAILED;
@@ -228,7 +228,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
   }
 
   // Get additional information
-  if ((definer= get_field(&thd->mem_root,
+  if ((definer= get_field(thd->mem_root,
 			  table->field[MYSQL_PROC_FIELD_DEFINER])) == NULL)
   {
     ret= SP_GET_FIELD_FAILED;
@@ -511,10 +511,10 @@ print_field_values(THD *thd, TABLE *table,
     String name_string;
     struct st_used_field *used_field= used_fields;
 
-    if (get_field(&thd->mem_root, used_field->field, &db_string))
+    if (get_field(thd->mem_root, used_field->field, &db_string))
       db_string.set_ascii("", 0);
     used_field+= 1;
-    get_field(&thd->mem_root, used_field->field, &name_string);
+    get_field(thd->mem_root, used_field->field, &name_string);
 
     if (!wild || !wild[0] || !wild_compare(name_string.ptr(), wild, 0))
     {
@@ -539,7 +539,7 @@ print_field_values(THD *thd, TABLE *table,
 	  {
 	    String tmp_string;
 
-	    get_field(&thd->mem_root, used_field->field, &tmp_string);
+	    get_field(thd->mem_root, used_field->field, &tmp_string);
 	    protocol->store(&tmp_string);
 	  }
 	  break;
@@ -982,7 +982,7 @@ sp_cache_functions(THD *thd, LEX *lex)
       newlex->proc_table= oldlex->proc_table; // hint if mysql.oper is opened
       name.m_name.str= strchr(name.m_qname.str, '.');
       name.m_db.length= name.m_name.str - name.m_qname.str;
-      name.m_db.str= strmake_root(&thd->mem_root,
+      name.m_db.str= strmake_root(thd->mem_root,
 				  name.m_qname.str, name.m_db.length);
       name.m_name.str+= 1;
       name.m_name.length= name.m_qname.length - name.m_db.length - 1;
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 8de1b6e906a..47e3952bcdd 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -190,7 +190,7 @@ void
 sp_name::init_qname(THD *thd)
 {
   m_qname.length= m_db.length+m_name.length+1;
-  m_qname.str= alloc_root(&thd->mem_root, m_qname.length+1);
+  m_qname.str= thd->alloc(m_qname.length+1);
   sprintf(m_qname.str, "%*s.%*s",
 	  m_db.length, (m_db.length ? m_db.str : ""),
 	  m_name.length, m_name.str);
@@ -232,10 +232,9 @@ sp_head::operator new(size_t size)
   MEM_ROOT own_root;
   sp_head *sp;
 
-  bzero((char *)&own_root, sizeof(own_root));
   init_alloc_root(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
-  sp= (sp_head *)alloc_root(&own_root, size);
-  sp->mem_root= own_root;
+  sp= (sp_head *) alloc_root(&own_root, size);
+  sp->main_mem_root= own_root;
   DBUG_PRINT("info", ("mem_root 0x%lx", (ulong) &sp->mem_root));
   DBUG_RETURN(sp);
 }
@@ -245,9 +244,10 @@ sp_head::operator delete(void *ptr, size_t size)
 {
   DBUG_ENTER("sp_head::operator delete");
   MEM_ROOT own_root;
-  sp_head *sp= (sp_head *)ptr;
+  sp_head *sp= (sp_head *) ptr;
 
-  memcpy(&own_root, (const void *)&sp->mem_root, sizeof(MEM_ROOT));
+  /* Make a copy of main_mem_root as free_root will free the sp */
+  own_root= sp->main_mem_root;
   DBUG_PRINT("info", ("mem_root 0x%lx moved to 0x%lx",
                       (ulong) &sp->mem_root, (ulong) &own_root));
   free_root(&own_root, MYF(0));
@@ -291,7 +291,7 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
   DBUG_ENTER("sp_head::init_strings");
   uint n;			/* Counter for nul trimming */ 
   /* During parsing, we must use thd->mem_root */
-  MEM_ROOT *root= &thd->mem_root;
+  MEM_ROOT *root= thd->mem_root;
 
   /* We have to copy strings to get them into the right memroot */
   if (name)
@@ -916,19 +916,19 @@ sp_head::set_info(char *definer, uint definerlen,
   if (! p)
     p= definer;		// Weird...
   len= p-definer;
-  m_definer_user.str= strmake_root(&mem_root, definer, len);
+  m_definer_user.str= strmake_root(mem_root, definer, len);
   m_definer_user.length= len;
   len= definerlen-len-1;
-  m_definer_host.str= strmake_root(&mem_root, p+1, len);
+  m_definer_host.str= strmake_root(mem_root, p+1, len);
   m_definer_host.length= len;
   m_created= created;
   m_modified= modified;
-  m_chistics= (st_sp_chistics *)alloc_root(&mem_root, sizeof(st_sp_chistics));
-  memcpy(m_chistics, chistics, sizeof(st_sp_chistics));
+  m_chistics= (st_sp_chistics *) memdup_root(mem_root, (char*) chistics,
+                                             sizeof(*chistics));
   if (m_chistics->comment.length == 0)
     m_chistics->comment.str= 0;
   else
-    m_chistics->comment.str= strmake_root(&mem_root,
+    m_chistics->comment.str= strmake_root(mem_root,
 					  m_chistics->comment.str,
 					  m_chistics->comment.length);
   m_sql_mode= sql_mode;
@@ -939,14 +939,14 @@ sp_head::reset_thd_mem_root(THD *thd)
 {
   DBUG_ENTER("sp_head::reset_thd_mem_root");
   m_thd_root= thd->mem_root;
-  thd->mem_root= mem_root;
+  thd->mem_root= &main_mem_root;
   DBUG_PRINT("info", ("mem_root 0x%lx moved to thd mem root 0x%lx",
                       (ulong) &mem_root, (ulong) &thd->mem_root));
   free_list= thd->free_list; // Keep the old list
   thd->free_list= NULL;	// Start a new one
   /* Copy the db, since substatements will point to it */
   m_thd_db= thd->db;
-  thd->db= strmake_root(&thd->mem_root, thd->db, thd->db_length);
+  thd->db= thd->strmake(thd->db, thd->db_length);
   m_thd= thd;
   DBUG_VOID_RETURN;
 }
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 6aa05838291..4bfe1076f65 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -231,7 +231,7 @@ public:
 
 private:
 
-  MEM_ROOT m_thd_root;		// Temp. store for thd's mem_root
+  MEM_ROOT *m_thd_root;		// Temp. store for thd's mem_root
   THD *m_thd;			// Set if we have reset mem_root
   char *m_thd_db;		// Original thd->db pointer
 
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index a1481bb2522..2cb3c9eb782 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -815,7 +815,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
 
   pthread_mutex_lock(&LOCK_open);
   if (open_unireg_entry(thd, table, db, table_name, table_name, 0,
-                        &thd->mem_root) ||
+                        thd->mem_root) ||
       !(table->table_cache_key =memdup_root(&table->mem_root,(char*) key,
 					    key_length)))
   {
@@ -1135,7 +1135,7 @@ bool reopen_table(TABLE *table,bool locked)
   safe_mutex_assert_owner(&LOCK_open);
 
   if (open_unireg_entry(table->in_use, &tmp, db, table_name,
-			table->table_name, 0, &table->in_use->mem_root))
+			table->table_name, 0, table->in_use->mem_root))
     goto end;
   free_io_cache(table);
 
@@ -1774,7 +1774,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
   thd->current_tablenr= 0;
   /* open_ltable can be used only for BASIC TABLEs */
   table_list->required_type= FRMTYPE_TABLE;
-  while (!(table= open_table(thd, table_list, &thd->mem_root, &refresh)) &&
+  while (!(table= open_table(thd, table_list, thd->mem_root, &refresh)) &&
          refresh)
     ;
 
@@ -2999,7 +2999,8 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
             during cleunup() this item will be put in list to replace
             expression from VIEW
           */
-          thd->nocheck_register_item_tree_change(it->ref(), item, &thd->mem_root);
+          thd->nocheck_register_item_tree_change(it->ref(), item,
+                                                 thd->mem_root);
         }
       }
       /* All fields are used */
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 987e557c37c..515c1c13b58 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1174,7 +1174,7 @@ public:
       use new arena if we are in a prepared statements and we have not
       already changed to use this arena.
     */
-    if (current_arena->is_stmt_prepare() &&
+    if (!current_arena->is_conventional() &&
         mem_root != &current_arena->main_mem_root)
     {
       set_n_backup_item_arena(current_arena, backup);
diff --git a/sql/sql_list.h b/sql/sql_list.h
index d8d3719d39d..141742c3d4a 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -113,6 +113,16 @@ public:
     }
     return 1;
   }
+  inline bool push_back(void *info, MEM_ROOT *mem_root)
+  {
+    if (((*last)=new (mem_root) list_node(info, &end_of_list)))
+    {
+      last= &(*last)->next;
+      elements++;
+      return 0;
+    }
+    return 1;
+  }
   inline bool push_front(void *info)
   {
     list_node *node=new list_node(info,first);
@@ -284,6 +294,8 @@ public:
   inline List() :base_list() {}
   inline List(const List<T> &tmp) :base_list(tmp) {}
   inline bool push_back(T *a) { return base_list::push_back(a); }
+  inline bool push_back(T *a, MEM_ROOT *mem_root)
+  { return base_list::push_back(a, mem_root); }
   inline bool push_front(T *a) { return base_list::push_front(a); }
   inline T* head() {return (T*) base_list::head(); }
   inline T** head_ref() {return (T**) base_list::head_ref(); }
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 4f94bfb6c05..9f25408acf8 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1828,7 +1828,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
     {
       DBUG_PRINT("info",("Using READ_ONLY cursor"));
       if (!stmt->cursor &&
-          !(stmt->cursor= new (&stmt->mem_root) Cursor()))
+          !(stmt->cursor= new (&stmt->main_mem_root) Cursor()))
       {
         send_error(thd, ER_OUT_OF_RESOURCES);
         DBUG_VOID_RETURN;
@@ -2013,7 +2013,12 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
 
 /*
   COM_FETCH handler: fetches requested amount of rows from cursor
+
   SYNOPSIS
+    mysql_stmt_fetch()
+    thd			Thread handler
+    packet		Packet from client (with stmt_id & num_rows)
+    packet_length	Length of packet
 */
 
 void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
@@ -2023,7 +2028,6 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
   ulong num_rows= uint4korr(packet+=4);
   Statement *stmt;
   int error;
-
   DBUG_ENTER("mysql_stmt_fetch");
 
   if (!(stmt= thd->stmt_map.find(stmt_id)) ||
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index d154e3e93c1..f679c45ae3d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1497,7 +1497,6 @@ JOIN::exec()
 	    are fixed or do not need fix_fields, too
 	  */
 	  curr_table->select->cond->quick_fix_field();
-          cur_tabl
 	}
 	curr_table->select_cond= curr_table->select->cond;
 	curr_table->select_cond->top_level_item();
@@ -1653,9 +1652,13 @@ Cursor::init_from_thd(THD *thd)
   /*
     We need to save and reset thd->mem_root, otherwise it'll be freed
     later in mysql_parse.
+
+    We can't just change the thd->mem_root here as we want to keep the things
+    that is already allocated in thd->mem_root for Cursor::fetch()
   */
-  mem_root=       thd->mem_root;
-  init_sql_alloc(&thd->mem_root,
+  main_mem_root=  *thd->mem_root;
+  /* Allocate new memory root for thd */
+  init_sql_alloc(thd->mem_root,
                  thd->variables.query_alloc_block_size,
                  thd->variables.query_prealloc_size);
 
@@ -1669,7 +1672,7 @@ Cursor::init_from_thd(THD *thd)
   open_tables=    thd->open_tables;
   lock=           thd->lock;
   query_id=       thd->query_id;
-  free_list= thd->free_list;
+  free_list=	  thd->free_list;
   reset_thd(thd);
   /*
     XXX: thd->locked_tables is not changed.
@@ -1684,8 +1687,11 @@ Cursor::init_from_thd(THD *thd)
 void
 Cursor::init_thd(THD *thd)
 {
-  thd->mem_root= mem_root;
-
+  /*
+    Use the original mem_root, in which we store all memory allocated
+    during the lifetime of the cursor.
+  */
+  thd->mem_root= &main_mem_root;
   DBUG_ASSERT(thd->derived_tables == 0);
   thd->derived_tables= derived_tables;
 
@@ -1773,11 +1779,10 @@ int
 Cursor::fetch(ulong num_rows)
 {
   THD *thd= join->thd;
-  JOIN_TAB *join_tab= join->join_tab + join->const_tables;;
+  JOIN_TAB *join_tab= join->join_tab + join->const_tables;
   COND *on_expr= *join_tab->on_expr_ref;
   COND *select_cond= join_tab->select_cond;
   READ_RECORD *info= &join_tab->read_record;
-
   int error= 0;
 
   join->fetch_limit+= num_rows;
@@ -1853,7 +1858,6 @@ Cursor::fetch(ulong num_rows)
     ::send_eof(thd);
     thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
     /* save references to memory, allocated during fetch */
-    mem_root= thd->mem_root;
     free_list= thd->free_list;
     break;
     /* Limit clause worked: this is the same as 'no more rows' */
@@ -1875,8 +1879,7 @@ Cursor::fetch(ulong num_rows)
       Must be last, as some memory might be allocated for free purposes,
       like in free_tmp_table() (TODO: fix this issue)
     */
-    mem_root= thd->mem_root;
-    free_root(&mem_root, MYF(0));
+    free_root(&main_mem_root, MYF(0));
     break;
   default:
     close();
@@ -1888,8 +1891,7 @@ Cursor::fetch(ulong num_rows)
       Must be last, as some memory might be allocated for free purposes,
       like in free_tmp_table() (TODO: fix this issue)
     */
-    mem_root= thd->mem_root;
-    free_root(&mem_root, MYF(0));
+    free_root(&main_mem_root, MYF(0));
     break;
   }
   return error;
@@ -1940,7 +1942,7 @@ Cursor::~Cursor()
     Must be last, as some memory might be allocated for free purposes,
     like in free_tmp_table() (TODO: fix this issue)
   */
-  free_root(&mem_root, MYF(0));
+  free_root(&main_mem_root, MYF(0));
 }
 
 /*********************************************************************/
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index f4f9841ead3..e73bf81eb74 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1401,7 +1401,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
                             create_info, *extra_fields, *keys, 0,
                             select_field_count))
     {
-      if (!(table= open_table(thd, create_table, &thd->mem_root, (bool*) 0)))
+      if (!(table= open_table(thd, create_table, thd->mem_root, (bool*) 0)))
         quick_rm_table(create_info->db_type, create_table->db,
                        table_case_name(create_info, create_table->real_name));
     }
@@ -3077,7 +3077,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
       bzero((void*) &tbl, sizeof(tbl));
       tbl.db= new_db;
       tbl.real_name= tbl.alias= tmp_name;
-      new_table= open_table(thd, &tbl, &thd->mem_root, 0);
+      new_table= open_table(thd, &tbl, thd->mem_root, 0);
     }
     else
     {
@@ -3516,6 +3516,8 @@ int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
   create_info.db_type=DB_TYPE_DEFAULT;
   create_info.row_type=ROW_TYPE_DEFAULT;
   create_info.default_table_charset=default_charset_info;
+  /* Force alter table to recreate table */
+  lex->alter_info.flags= ALTER_CHANGE_COLUMN;
   DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
                                 table_list, lex->create_list,
                                 lex->key_list, 0, (ORDER *) 0,
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 17f3bc48678..5d175be74e1 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -134,7 +134,6 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
   TABLE *table= tables->table;
   char dir_buff[FN_REFLEN], file_buff[FN_REFLEN];
   LEX_STRING dir, file;
-  MEM_ROOT *old_global_root;
   LEX_STRING *trg_def, *name;
   List_iterator_fast<LEX_STRING> it(names_list);
 
@@ -168,9 +167,6 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
                          triggers_file_ext, NullS) - file_buff;
   file.str= file_buff;
 
-  old_global_root= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC);
-  my_pthread_setspecific_ptr(THR_MALLOC, &table->mem_root);
-
   /*
     Soon we will invalidate table object and thus Table_triggers_list object
     so don't care about place to which trg_def->ptr points and other
@@ -181,17 +177,12 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
   */
   if (!(trg_def= (LEX_STRING *)alloc_root(&table->mem_root,
                                           sizeof(LEX_STRING))) ||
-      definitions_list.push_back(trg_def))
-  {
-    my_pthread_setspecific_ptr(THR_MALLOC, old_global_root);
+      definitions_list.push_back(trg_def, &table->mem_root))
     return 1;
-  }
 
   trg_def->str= thd->query;
   trg_def->length= thd->query_length;
 
-  my_pthread_setspecific_ptr(THR_MALLOC, old_global_root);
-
   return sql_create_definition_file(&dir, &file, &triggers_file_type,
                                     (gptr)this, triggers_file_parameters, 3);
 }
@@ -302,7 +293,6 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
   char path_buff[FN_REFLEN];
   LEX_STRING path;
   File_parser *parser;
-  MEM_ROOT *old_global_mem_root;
 
   DBUG_ENTER("Table_triggers_list::check_n_load");
 
@@ -406,14 +396,9 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
         trg_name_str->str= trg_name_buff;
         trg_name_str->length= lex.name_and_length.length;
 
-	old_global_mem_root= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC);
-	my_pthread_setspecific_ptr(THR_MALLOC, &table->mem_root);
-
-        if (triggers->names_list.push_back(trg_name_str))
+        if (triggers->names_list.push_back(trg_name_str, &table->mem_root))
           goto err_with_lex_cleanup;
 
-        my_pthread_setspecific_ptr(THR_MALLOC, old_global_mem_root);
-
         lex_end(&lex);
       }
       thd->lex= old_lex;
@@ -431,7 +416,8 @@ err_with_lex_cleanup:
       We don't care about this error message much because .TRG files will
       be merged into .FRM anyway.
     */
-    my_error(ER_WRONG_OBJECT, MYF(0), table_name, triggers_file_ext, "TRIGGER");
+    my_error(ER_WRONG_OBJECT, MYF(0), table_name, triggers_file_ext,
+             "TRIGGER");
     DBUG_RETURN(1);
   }
 
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 20d762eba55..792e2cdf775 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -314,6 +314,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
     thd_arg->lex->current_select= lex_select_save;
     if (!item_list.elements)
     {
+      Field **field;
       Item_arena *tmp_arena,backup;
       tmp_arena= thd->change_arena_if_needed(&backup);
 
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index f8994148ffc..a03a7acdf72 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -434,7 +434,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
 	DBUG_RETURN(-1);
       }
 
-      if (!(parser= sql_parse_prepare(&path, &thd->mem_root, 0)))
+      if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0)))
 	DBUG_RETURN(1);
 
       if (!parser->ok() ||
@@ -451,7 +451,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
         TODO: read dependence list, too, to process cascade/restrict
         TODO: special cascade/restrict procedure for alter?
       */
-      if (parser->parse((gptr)view, &thd->mem_root,
+      if (parser->parse((gptr)view, thd->mem_root,
                         view_parameters + revision_number_position, 1))
       {
         DBUG_RETURN(thd->net.report_error? -1 : 0);
@@ -565,7 +565,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
     TODO: when VIEWs will be stored in cache, table mem_root should
     be used here
   */
-  if (parser->parse((gptr)table, &thd->mem_root, view_parameters,
+  if (parser->parse((gptr)table, thd->mem_root, view_parameters,
                     required_view_parameters))
     goto err;
 
@@ -586,7 +586,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
 
     now Lex placed in statement memory
   */
-  table->view= lex= thd->lex= (LEX*) new(&thd->mem_root) st_lex_local;
+  table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local;
   lex_start(thd, (uchar*)table->query.str, table->query.length);
   lex->select_lex.select_number= ++thd->select_number;
   old_lex->derived_tables|= DERIVED_VIEW;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 82646e1db36..309a9249d0e 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1848,7 +1848,7 @@ sp_proc_stmt:
 		  i->m_query.length= lex->ptr - sp->m_tmp_query;
 		else
 		  i->m_query.length= lex->tok_end - sp->m_tmp_query;
-		i->m_query.str= strmake_root(&YYTHD->mem_root,
+		i->m_query.str= strmake_root(YYTHD->mem_root,
 					     (char *)sp->m_tmp_query,
 					     i->m_query.length);
 		i->set_lex(lex);
diff --git a/sql/table.cc b/sql/table.cc
index 71999b2c3d4..403d9db342c 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -89,7 +89,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
 
   error=1;
   disk_buff=NULL;
-  old_root= my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
+  root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
+  old_root= *root_ptr;
 
   if ((file=my_open(fn_format(index_file, name, "", reg_ext,
 			      MY_UNPACK_FILENAME),
@@ -123,8 +124,6 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
   outparam->blob_ptr_size=sizeof(char*);
   outparam->db_stat = db_stat;
   init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
-  root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
-  old_root= *root_ptr;
   *root_ptr= &outparam->mem_root;
 
   outparam->real_name=strdup_root(&outparam->mem_root,