MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Mikael Ronstrom Date:July 29 2009 2:06pm
Subject:bzr commit into mysql-5.4 branch (mikael:3477) Bug#32115
View as plain text  
#At file:///home/mikael/mysql_clones/mysql-6.0-bugteam-bug32115/

 3477 Mikael Ronstrom	2009-07-29
      Bug#32115, made use of local lex object to avoid side effects of opening partitioned tables
      modified:
        sql/sql_partition.cc

=== modified file 'sql/sql_partition.cc'
--- a/sql/sql_partition.cc	2009-07-08 12:17:27 +0000
+++ b/sql/sql_partition.cc	2009-07-29 14:06:35 +0000
@@ -859,6 +859,84 @@ int check_signed_flag(partition_info *pa
   return error;
 }
 
+/*
+  Initialize lex object for use in fix_fields and parsing.
+
+  SYNOPSIS
+    init_lex_with_single_table()
+    thd                 The thread object
+    table               The table object
+  RETURN VALUE
+    TRUE                An error occurred, memory allocation error
+    FALSE               Ok
+
+  DESCRIPTION
+    This function is used to initialize a lex object on the
+    stack for use by fix_fields and for parsing. In order to
+    work properly it also needs to initialize the
+    Name_resolution_context object of the lexer.
+    Finally it needs to set a couple of variables to ensure
+    proper functioning of fix_fields.
+*/
+
+static int
+init_lex_with_single_table(THD *thd, TABLE *table)
+{
+  TABLE_LIST *table_list;
+  Table_ident *table_ident;
+  LEX *lex= thd->lex;
+  /*
+    We will call the parser to create a part_info struct based on the
+    partition string stored in the frm file.
+    We will use a local lex object for this purpose. However we also
+    need to set the Name_resolution_object for this lex object. We
+    do this by using add_table_to_list where we add the table that
+    we're working with to the Name_resolution_context.
+  */
+  lex_start(thd);
+  lex->select_lex.context.init();
+  if ((!(table_ident= new Table_ident(thd,
+                                      table->s->table_name,
+                                      table->s->db, TRUE))) ||
+      (!(table_list= lex->select_lex.add_table_to_list(thd,
+                                                       table_ident,
+                                                       NULL,
+                                                       0))))
+    return TRUE;
+  lex->select_lex.context.table_list=
+    lex->select_lex.context.first_name_resolution_table= table_list;
+  lex->use_only_table_context= TRUE;
+  lex->select_lex.cur_pos_in_select_list= UNDEF_POS;
+  table->map= 1; //To ensure correct calculation of const item
+  table->get_fields_in_item_tree= TRUE;
+  table_list->table= table;
+  return FALSE;
+}
+
+/*
+  End use of local lex with single table
+
+  SYNOPSIS
+    end_lex_with_single_table()
+    thd               The thread object
+    table             The table object
+    old_lex           The real lex object connected to THD
+
+  DESCRIPTION
+    This function restores the real lex object after calling
+    init_lex_with_single_table and also restores some table
+    variables temporarily set.
+*/
+
+static int
+end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex)
+{
+  LEX *lex= thd->lex;
+  table->map= 0;
+  table->get_fields_in_item_tree= FALSE;
+  lex_end(lex);
+  thd->lex= old_lex;
+}
 
 /*
   The function uses a new feature in fix_fields where the flag 
@@ -900,18 +978,20 @@ bool fix_fields_part_func(THD *thd, Item
                           bool is_sub_part, bool is_field_to_be_setup)
 {
   partition_info *part_info= table->part_info;
-  uint dir_length, home_dir_length;
   bool result= TRUE;
-  TABLE_LIST tables;
-  TABLE_LIST *save_table_list, *save_first_table, *save_last_table;
   int error;
-  Name_resolution_context *context;
   const char *save_where;
-  char* db_name;
-  char db_name_string[FN_REFLEN];
-  bool save_use_only_table_context;
+  LEX *old_lex= thd->lex;
+  LEX lex;
   DBUG_ENTER("fix_fields_part_func");
 
+  thd->lex= &lex;
+  if (init_lex_with_single_table(thd, table))
+  {
+    mem_alloc_error(sizeof(Table_ident));
+    goto end;
+  }
+
   if (part_info->fixed)
   {
     if (!(is_sub_part || (error= check_signed_flag(part_info))))
@@ -919,43 +999,8 @@ bool fix_fields_part_func(THD *thd, Item
     goto end;
   }
 
-  /*
-    Set-up the TABLE_LIST object to be a list with a single table
-    Set the object to zero to create NULL pointers and set alias
-    and real name to table name and get database name from file name.
-    TODO: Consider generalizing or refactoring Lex::add_table_to_list() so
-    it can be used in all places where we create TABLE_LIST objects.
-    Also consider creating appropriate constructors for TABLE_LIST.
-  */
-
-  bzero((void*)&tables, sizeof(TABLE_LIST));
-  tables.alias= tables.table_name= (char*) table->s->table_name.str;
-  tables.table= table;
-  tables.next_local= 0;
-  tables.next_name_resolution_table= 0;
-  /*
-    Cache the table in Item_fields. All the tables can be cached except
-    the trigger pseudo table.
-  */
-  tables.cacheable_table= TRUE;
-  context= thd->lex->current_context();
-  tables.select_lex= context->select_lex;
-  strmov(db_name_string, table->s->normalized_path.str);
-  dir_length= dirname_length(db_name_string);
-  db_name_string[dir_length - 1]= 0;
-  home_dir_length= dirname_length(db_name_string);
-  db_name= &db_name_string[home_dir_length];
-  tables.db= db_name;
-
-  table->map= 1; //To ensure correct calculation of const item
-  table->get_fields_in_item_tree= TRUE;
-  save_table_list= context->table_list;
-  save_first_table= context->first_name_resolution_table;
-  save_last_table= context->last_name_resolution_table;
-  context->table_list= &tables;
-  context->first_name_resolution_table= &tables;
-  context->last_name_resolution_table= NULL;
-  func_expr->walk(&Item::change_context_processor, 0, (uchar*) context);
+  func_expr->walk(&Item::change_context_processor, 0,
+                  (uchar*) &lex.select_lex.context);
   save_where= thd->where;
   thd->where= "partition function";
   /*
@@ -970,23 +1015,12 @@ bool fix_fields_part_func(THD *thd, Item
     that does this during val_int must be disallowed as partition
     function.
     SEE Bug #21658
-  */
-  /*
+
     This is a tricky call to prepare for since it can have a large number
     of interesting side effects, both desirable and undesirable.
   */
-
-  save_use_only_table_context= thd->lex->use_only_table_context;
-  thd->lex->use_only_table_context= TRUE;
-  thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
-  
   error= func_expr->fix_fields(thd, (Item**)&func_expr);
 
-  thd->lex->use_only_table_context= save_use_only_table_context;
-
-  context->table_list= save_table_list;
-  context->first_name_resolution_table= save_first_table;
-  context->last_name_resolution_table= save_last_table;
   if (unlikely(error))
   {
     DBUG_PRINT("info", ("Field in partition function not part of table"));
@@ -994,7 +1028,6 @@ bool fix_fields_part_func(THD *thd, Item
       clear_field_flag(table);
     goto end;
   }
-  thd->where= save_where;
   if (unlikely(func_expr->const_item()))
   {
     my_error(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0));
@@ -1009,8 +1042,7 @@ bool fix_fields_part_func(THD *thd, Item
   if (!is_sub_part)
     part_info->fixed= TRUE;
 end:
-  table->get_fields_in_item_tree= FALSE;
-  table->map= 0; //Restore old value
+  end_lex_with_single_table(thd, table, old_lex);
   DBUG_RETURN(result);
 }
 
@@ -3809,16 +3841,11 @@ bool mysql_unpack_partition(THD *thd,
 
   Parser_state parser_state(thd, part_buf, part_info_len);
 
-  lex_start(thd);
-  *work_part_info_used= false;
-  /*
-    We need to use the current SELECT_LEX since I need to keep the
-    Name_resolution_context object which is referenced from the
-    Item_field objects.
-    This is not a nice solution since if the parser uses current_select
-    for anything else it will corrupt the current LEX object.
-  */
-  thd->lex->current_select= old_lex->current_select; 
+  if (init_lex_with_single_table(thd, table))
+  {
+    mem_alloc_error(sizeof(Table_ident));
+    goto end;
+  }
   /*
     All Items created is put into a free list on the THD object. This list
     is used to free all Item objects after completing a query. We don't
@@ -3828,6 +3855,7 @@ bool mysql_unpack_partition(THD *thd,
     Thus we move away the current list temporarily and start a new list that
     we then save in the partition info structure.
   */
+  *work_part_info_used= false;
   lex.part_info= new partition_info();/* Indicates MYSQLparse from this place */
   if (!lex.part_info)
   {
@@ -3941,8 +3969,7 @@ bool mysql_unpack_partition(THD *thd,
 
   result= FALSE;
 end:
-  lex_end(thd->lex);
-  thd->lex= old_lex;
+  end_lex_with_single_table(thd, table, old_lex);
   thd->variables.character_set_client= old_character_set_client;
   DBUG_RETURN(result);
 }

Thread
bzr commit into mysql-5.4 branch (mikael:3477) Bug#32115Mikael Ronstrom29 Jul
  • Re: bzr commit into mysql-5.4 branch (mikael:3477) Bug#32115Ingo Strüwing29 Jul
    • Re: bzr commit into mysql-5.4 branch (mikael:3477) Bug#32115Mattias Jonsson5 Aug