List:Internals« Previous MessageNext Message »
From:dlenev Date:August 9 2005 10:24pm
Subject:bk commit into 5.0 tree (dlenev:1.1955) BUG#11973
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of dlenev. When dlenev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1955 05/08/10 00:23:56 dlenev@stripped +10 -0
  Clumsy but working fix for bug #11973 "SELECT .. INTO var_name; in trigger
  cause crash on update".
  
  Let us update "thd" pointer in LEX, all its units and in LEX::result before
  executing statement in trigger body, since triggers are associated with TABLE
  object and because of this can be used in different threads.

  sql/sql_update.cc
    1.163 05/08/10 00:23:47 dlenev@stripped +3 -3
    multi_update:
      Got rid of redundant "thd" member (we already have it in select_result).

  sql/sql_prepare.cc
    1.145 05/08/10 00:23:47 dlenev@stripped +11 -0
    reinit_stmt_before_use():
      We have to update "thd" pointer in LEX, all its units and in LEX::result,
      since statements which belong to trigger body are associated with TABLE
      object and because of this can be used in different threads.

  sql/sql_parse.cc
    1.458 05/08/10 00:23:46 dlenev@stripped +1 -1
    multi_delete:
      Got rid of redundant "thd" member (we already have it in select_result).

  sql/sql_lex.h
    1.191 05/08/10 00:23:46 dlenev@stripped +1 -0
    st_select_lex_unit:
      Added set_thd() method for updating st_select_lex_unit::thd value
      (we need this in cases when statement to which this unit belongs will
       be used in different threads, as it happens for statements in trigger body).
      We don't update thd of select_result pointed by st_select_lex_unit::result
      in this method, since it is either have too short lifetime (i.e. created for
      each execution) or is accessible via Item_subquery or LEX::result and thus
      already taken care of.

  sql/sql_delete.cc
    1.154 05/08/10 00:23:46 dlenev@stripped +2 -3
    multi_delete:
      Got rid of redundant "thd" member (we already have it in select_result).

  sql/sql_class.h
    1.254 05/08/10 00:23:46 dlenev@stripped +3 -4
    select_result:
      Added set_thd() method for updating select_result::thd value (we need this
      in cases when statement to which this select_result belongs will be used
      in different threads, as it happens for statements in trigger body).
    multi_delete/multi_update:
      Got rid of redundant "thd" member (we already have it in select_result).

  sql/item_subselect.h
    1.73 05/08/10 00:23:46 dlenev@stripped +5 -2
    subselect_engine:
      Moved implementation of set_thd() method to item_subselect.cc,
      since now it also sets "thd" for subselect_engine::result.

  sql/item_subselect.cc
    1.114 05/08/10 00:23:46 dlenev@stripped +8 -0
    subselect_engine:
      Moved implementation of set_thd() method to item_subselect.cc,
      since now it also sets "thd" for subselect_engine::result.

  mysql-test/t/trigger.test
    1.21 05/08/10 00:23:45 dlenev@stripped +23 -0
    Added test case for bug #11973 "SELECT .. INTO var_name; in trigger cause
    crash on update".

  mysql-test/r/trigger.result
    1.16 05/08/10 00:23:45 dlenev@stripped +13 -0
    Added test case for bug #11973 "SELECT .. INTO var_name; in trigger cause
    crash on update".

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	dlenev
# Host:	brandersnatch.localdomain
# Root:	/home/dlenev/src/mysql-5.0-bg11973-2

--- 1.253/sql/sql_class.h	2005-08-03 07:44:30 +04:00
+++ 1.254/sql/sql_class.h	2005-08-10 00:23:46 +04:00
@@ -1560,6 +1560,7 @@
     statement/stored procedure.
   */
   virtual void cleanup();
+  void set_thd(THD *thd_arg) { thd= thd_arg; }
 };
 
 
@@ -1915,14 +1916,13 @@
 {
   TABLE_LIST *delete_tables, *table_being_deleted;
   Unique **tempfiles;
-  THD *thd;
   ha_rows deleted, found;
   uint num_of_tables;
   int error;
   bool do_delete, transactional_tables, normal_tables, delete_while_scanning;
 
 public:
-  multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
+  multi_delete(TABLE_LIST *dt, uint num_of_tables);
   ~multi_delete();
   int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
   bool send_data(List<Item> &items);
@@ -1938,7 +1938,6 @@
   TABLE_LIST *all_tables; /* query/update command tables */
   TABLE_LIST *leaves;     /* list of leves of join table tree */
   TABLE_LIST *update_tables, *table_being_updated;
-  THD *thd;
   TABLE **tmp_tables, *main_table, *table_to_update;
   TMP_TABLE_PARAM *tmp_table_param;
   ha_rows updated, found;
@@ -1950,7 +1949,7 @@
   bool do_update, trans_safe, transactional_tables, ignore;
 
 public:
-  multi_update(THD *thd_arg, TABLE_LIST *ut, TABLE_LIST *leaves_list,
+  multi_update(TABLE_LIST *ut, TABLE_LIST *leaves_list,
 	       List<Item> *fields, List<Item> *values,
 	       enum_duplicates handle_duplicates, bool ignore);
   ~multi_update();

--- 1.153/sql/sql_delete.cc	2005-07-01 08:05:35 +04:00
+++ 1.154/sql/sql_delete.cc	2005-08-10 00:23:46 +04:00
@@ -407,9 +407,8 @@
 }
 
 
-multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
-			   uint num_of_tables_arg)
-  : delete_tables(dt), thd(thd_arg), deleted(0), found(0),
+multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
+  : delete_tables(dt), deleted(0), found(0),
     num_of_tables(num_of_tables_arg), error(0),
     do_delete(0), transactional_tables(0), normal_tables(0)
 {

--- 1.190/sql/sql_lex.h	2005-07-19 20:06:43 +04:00
+++ 1.191/sql/sql_lex.h	2005-08-10 00:23:46 +04:00
@@ -458,6 +458,7 @@
   inline bool is_prepared() { return prepared; }
   bool change_result(select_subselect *result, select_subselect *old_result);
   void set_limit(st_select_lex *values);
+  void set_thd(THD *thd_arg) { thd= thd_arg; }
 
   friend void lex_start(THD *thd, uchar *buf, uint length);
   friend int subselect_union_engine::exec();

--- 1.457/sql/sql_parse.cc	2005-08-03 14:13:59 +04:00
+++ 1.458/sql/sql_parse.cc	2005-08-10 00:23:46 +04:00
@@ -3318,7 +3318,7 @@
     if ((res= mysql_multi_delete_prepare(thd)))
       goto error;
 
-    if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
+    if (!thd->is_fatal_error && (result= new multi_delete(aux_tables,
 							  lex->table_count)))
     {
       res= mysql_select(thd, &select_lex->ref_pointer_array,

--- 1.162/sql/sql_update.cc	2005-07-13 17:12:18 +04:00
+++ 1.163/sql/sql_update.cc	2005-08-10 00:23:47 +04:00
@@ -820,7 +820,7 @@
   if (mysql_multi_update_prepare(thd))
     DBUG_RETURN(TRUE);
 
-  if (!(result= new multi_update(thd, table_list,
+  if (!(result= new multi_update(table_list,
 				 thd->lex->select_lex.leaf_tables,
 				 fields, values,
 				 handle_duplicates, ignore)))
@@ -846,13 +846,13 @@
 }
 
 
-multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
+multi_update::multi_update(TABLE_LIST *table_list,
 			   TABLE_LIST *leaves_list,
 			   List<Item> *field_list, List<Item> *value_list,
 			   enum enum_duplicates handle_duplicates_arg,
                            bool ignore_arg)
   :all_tables(table_list), leaves(leaves_list), update_tables(0),
-   thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list),
+   tmp_tables(0), updated(0), found(0), fields(field_list),
    values(value_list), table_count(0), copy_field(0),
    handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(0),
    transactional_tables(1), ignore(ignore_arg)

--- 1.113/sql/item_subselect.cc	2005-07-01 08:05:35 +04:00
+++ 1.114/sql/item_subselect.cc	2005-08-10 00:23:46 +04:00
@@ -1271,6 +1271,14 @@
 }
 
 
+void subselect_engine::set_thd(THD *thd_arg)
+{
+  thd= thd_arg;
+  if (result)
+    result->set_thd(thd_arg);
+}
+
+
 subselect_single_select_engine::
 subselect_single_select_engine(st_select_lex *select,
 			       select_subselect *result,

--- 1.72/sql/item_subselect.h	2005-07-13 18:05:50 +04:00
+++ 1.73/sql/item_subselect.h	2005-08-10 00:23:46 +04:00
@@ -299,8 +299,11 @@
   virtual ~subselect_engine() {}; // to satisfy compiler
   virtual void cleanup()= 0;
 
-  // set_thd should be called before prepare()
-  void set_thd(THD *thd_arg) { thd= thd_arg; }
+  /*
+    Also sets "thd" for subselect_engine::result.
+    Should be called before prepare().
+  */
+  void set_thd(THD *thd_arg);
   THD * get_thd() { return thd; }
   virtual int prepare()= 0;
   virtual void fix_length_and_dec(Item_cache** row)= 0;

--- 1.15/mysql-test/r/trigger.result	2005-07-30 10:24:47 +04:00
+++ 1.16/mysql-test/r/trigger.result	2005-08-10 00:23:45 +04:00
@@ -635,3 +635,16 @@
 Trigger	Event	Table	Statement	Timing	Created	sql_mode
 t1_bi	INSERT	t1	 set new.a = '2004-01-00'	BEFORE	#	
 drop table t1;
+create table t1 (id int, data int, username varchar(16));
+insert into t1 (id, data) values (1, 0);
+create trigger t1_whoupdated before update on t1 for each row
+begin
+declare user varchar(32);
+declare i int;
+select user() into user;
+set NEW.username = user;
+select count(*) from ((select 1) union (select 2)) as d1 into i;
+end|
+update t1 set data = 1;
+update t1 set data = 2;
+drop table t1;

--- 1.20/mysql-test/t/trigger.test	2005-07-30 10:24:47 +04:00
+++ 1.21/mysql-test/t/trigger.test	2005-08-10 00:23:45 +04:00
@@ -642,3 +642,26 @@
 --replace_column 6 #
 show triggers;
 drop table t1;
+
+# Test for bug #11973 "SELECT .. INTO var_name; in trigger cause
+#                      crash on update"
+create table t1 (id int, data int, username varchar(16));
+insert into t1 (id, data) values (1, 0);
+delimiter |;
+create trigger t1_whoupdated before update on t1 for each row
+begin
+  declare user varchar(32);
+  declare i int;
+  select user() into user;
+  set NEW.username = user;
+  select count(*) from ((select 1) union (select 2)) as d1 into i;
+end|
+delimiter ;|
+update t1 set data = 1;
+
+connect (addconroot, localhost, root,,);
+connection addconroot;
+update t1 set data = 2;
+
+connection default;
+drop table t1;

--- 1.144/sql/sql_prepare.cc	2005-07-29 18:11:44 +04:00
+++ 1.145/sql/sql_prepare.cc	2005-08-10 00:23:47 +04:00
@@ -1850,6 +1850,13 @@
   SELECT_LEX *sl= lex->all_selects_list;
   DBUG_ENTER("reinit_stmt_before_use");
 
+  /*
+    We have to update "thd" pointer in LEX, all its units and in LEX::result,
+    since statements which belong to trigger body are associated with TABLE
+    object and because of this can be used in different threads.
+  */
+  lex->thd= thd;
+
   if (lex->empty_field_list_on_rset)
   {
     lex->empty_field_list_on_rset= 0;
@@ -1888,6 +1895,7 @@
       unit->types.empty();
       /* for derived tables & PS (which can't be reset by Item_subquery) */
       unit->reinit_exec_mechanism();
+      unit->set_thd(thd);
     }
   }
 
@@ -1926,7 +1934,10 @@
     lex->select_lex.leaf_tables= lex->leaf_tables_insert;
 
   if (lex->result)
+  {
     lex->result->cleanup();
+    lex->result->set_thd(thd);
+  }
 
   DBUG_VOID_RETURN;
 }
Thread
bk commit into 5.0 tree (dlenev:1.1955) BUG#11973dlenev9 Aug