MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:konstantin Date:July 6 2006 7:59pm
Subject:bk commit into 4.1 tree (konstantin:1.2522) BUG#19399
View as plain text  
Below is the list of changes that have just been committed into a local
4.1 repository of kostja. When kostja 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.2522 06/07/06 23:59:04 konstantin@stripped +6 -0
  A fix and a test case for Bug#19399 "res 'Lost Connection' when 
  dropping/creating tables".
  
  The bug could lead to a crash when multi-delete statements were
  prepared and used with temporary tables.
  
  The bug was caused by lack of clean-up of multi-delete tables before
  re-execution of a prepared statement. In a statement like
  DELETE t1 FROM t1, t2 WHERE ... the first table list (t1) is
  moved to lex->auxilliary_table_list and excluded from lex->query_tables
  or select_lex->tables. Thus it was unaccessible to reinit_stmt_before_use
  and not cleaned up before re-execution of a prepared statement. 

  sql/table.h
    1.76 06/07/06 23:59:01 konstantin@stripped +5 -0
    Declare st_table_list::reinit_before_use().

  sql/table.cc
    1.135 06/07/06 23:59:01 konstantin@stripped +17 -0
    Implement st_table_list::reinit_before_use().

  sql/sql_prepare.cc
    1.158 06/07/06 23:59:01 konstantin@stripped +13 -7
    Move the one table clean-up functionality to a method of st_table_list.
    Clean up auxiliary_table_list if it's not empty.

  sql/sql_lex.cc
    1.154 06/07/06 23:59:01 konstantin@stripped +1 -0
    Always initialize auxilliary_table_list when we initialize the lex:
    this way we don't have to check that lex->sql_command equals to
    SQLCOM_DELETE_MULTI whenever we need to access auxilliary_table_list.
    In particular, in reinit_stmt_before_use we can simply check that
    auxilliary_table_list is not NULL and clean it up if the check returns
    a true value.

  mysql-test/t/ps.test
    1.51 06/07/06 23:59:01 konstantin@stripped +25 -0
    A test case for Bug#19399 "Stored Procedures 'Lost Connection' when 
    dropping/creating tables": test that multi-delete
    tables are cleaned up properly before re-execution.

  mysql-test/r/ps.result
    1.50 06/07/06 23:59:01 konstantin@stripped +14 -0
    Updated test results (Bug#19399)

# 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:	konstantin
# Host:	bodhi.netgear
# Root:	/opt/local/work/mysql-4.1-19399

--- 1.153/sql/sql_lex.cc	2006-05-26 20:30:14 +04:00
+++ 1.154/sql/sql_lex.cc	2006-07-06 23:59:01 +04:00
@@ -125,6 +125,7 @@
   lex->value_list.empty();
   lex->update_list.empty();
   lex->param_list.empty();
+  lex->auxilliary_table_list.empty();
   lex->unit.next= lex->unit.master=
     lex->unit.link_next= lex->unit.return_to= 0;
   lex->unit.prev= lex->unit.link_prev= 0;

--- 1.134/sql/table.cc	2006-06-23 12:19:24 +04:00
+++ 1.135/sql/table.cc	2006-07-06 23:59:01 +04:00
@@ -1523,6 +1523,23 @@
   DBUG_RETURN(ha_checktype((enum db_type) (uint) *(head+3)));
 }
 
+/*
+  Cleanup this table for re-execution.
+
+  SYNOPSIS
+    st_table_list::reinit_before_use()
+*/
+
+void st_table_list::reinit_before_use(THD * /* thd */)
+{
+  /*
+    Reset old pointers to TABLEs: they are not valid since the tables
+    were closed in the end of previous prepare or execute call.
+  */
+  table= 0;
+  table_list= 0;
+}
+
 
 /*****************************************************************************
 ** Instansiate templates

--- 1.75/sql/table.h	2006-01-23 21:13:13 +03:00
+++ 1.76/sql/table.h	2006-07-06 23:59:01 +04:00
@@ -238,6 +238,11 @@
   bool		cacheable_table;	/* stop PS caching */
   /* used in multi-upd privelege check */
   bool		table_in_update_from_clause;
+  /*
+    Cleanup for re-execution in a prepared statement or a stored
+    procedure.
+  */
+  void reinit_before_use(THD *thd);
 } TABLE_LIST;
 
 typedef struct st_changed_table_list

--- 1.49/mysql-test/r/ps.result	2006-04-07 23:50:37 +04:00
+++ 1.50/mysql-test/r/ps.result	2006-07-06 23:59:01 +04:00
@@ -875,3 +875,17 @@
 @@max_prepared_stmt_count	@@prepared_stmt_count
 3	0
 set global max_prepared_stmt_count= @old_max_prepared_stmt_count;
+drop table if exists t1;
+create temporary table if not exists t1 (a1 int);
+prepare stmt from "delete t1 from t1 where (cast(a1/3 as unsigned) * 3) = a1";
+drop temporary table t1;
+create temporary table if not exists t1 (a1 int);
+execute stmt;
+drop temporary table t1;
+create temporary table if not exists t1 (a1 int);
+execute stmt;
+drop temporary table t1;
+create temporary table if not exists t1 (a1 int);
+execute stmt;
+drop temporary table t1;
+deallocate prepare stmt;

--- 1.50/mysql-test/t/ps.test	2006-04-07 23:50:37 +04:00
+++ 1.51/mysql-test/t/ps.test	2006-07-06 23:59:01 +04:00
@@ -926,4 +926,29 @@
 set global max_prepared_stmt_count= @old_max_prepared_stmt_count;
 --enable_ps_protocol
 
+#
+# Bug#19399 "Stored Procedures 'Lost Connection' when dropping/creating
+#            tables"
+# Check that multi-delete tables are also cleaned up before re-execution.
+# 
+--disable_warnings
+drop table if exists t1;
+create temporary table if not exists t1 (a1 int);
+--enable_warnings
+# exact delete syntax is essential
+prepare stmt from "delete t1 from t1 where (cast(a1/3 as unsigned) * 3) = a1";
+drop temporary table t1;
+create temporary table if not exists t1 (a1 int);
+# the server crashed on  the next statement without the fix
+execute stmt;
+drop temporary table t1;
+create temporary table if not exists t1 (a1 int);
+# the problem was in memory corruption: repeat the test just in case
+execute stmt;
+drop temporary table t1;
+create temporary table if not exists t1 (a1 int);
+execute stmt;
+drop temporary table t1;
+deallocate prepare stmt;
+
 # End of 4.1 tests

--- 1.157/sql/sql_prepare.cc	2006-05-07 10:48:09 +04:00
+++ 1.158/sql/sql_prepare.cc	2006-07-06 23:59:01 +04:00
@@ -1727,14 +1727,9 @@
 	 tables;
 	 tables= tables->next)
     {
-      /*
-        Reset old pointers to TABLEs: they are not valid since the tables
-        were closed in the end of previous prepare or execute call.
-      */
-      tables->table= 0;
-      tables->table_list= 0;
+      tables->reinit_before_use(thd);
     }
-    
+
     {
       SELECT_LEX_UNIT *unit= sl->master_unit();
       unit->unclean();
@@ -1742,6 +1737,17 @@
       /* for derived tables & PS (which can't be reset by Item_subquery) */
       unit->reinit_exec_mechanism();
     }
+  }
+  /*
+    Cleanup of the special case of DELETE t1, t2 FROM t1, t2, t3 ...
+    (multi-delete).  We do a full clean up, although at the moment all we
+    need to clean in the tables of MULTI-DELETE list is 'table' member.
+  */
+  for (TABLE_LIST *tables= (TABLE_LIST*) lex->auxilliary_table_list.first;
+       tables;
+       tables= tables->next)
+  {
+    tables->reinit_before_use(thd);
   }
   lex->current_select= &lex->select_lex;
   if (lex->result)
Thread
bk commit into 4.1 tree (konstantin:1.2522) BUG#19399konstantin6 Jul