MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Martin Hansson Date:September 28 2009 12:44pm
Subject:bzr commit into mysql-pe branch (martin.hansson:3624) Bug#46958
View as plain text  
#At file:///data0/martin/bzr/bug46958/6.0bt/ based on revid:dao-gang.qu@stripped

 3624 Martin Hansson	2009-09-28 [merge]
      Merge of Bug#46958

    modified:
      mysql-test/r/delete.result
      mysql-test/t/delete.test
      sql/sql_class.h
      sql/sql_delete.cc
=== modified file 'mysql-test/r/delete.result'
--- a/mysql-test/r/delete.result	2008-02-27 22:59:48 +0000
+++ b/mysql-test/r/delete.result	2009-09-28 12:43:54 +0000
@@ -420,3 +420,48 @@ DROP DATABASE db1;
 DROP DATABASE db2;
 DROP PROCEDURE count_rows;
 DROP TABLE t1, t2;
+#
+# Bug#46958: Assertion in Diagnostics_area::set_ok_status, trigger, 
+# merge table
+#
+CREATE TABLE t1 ( a INT );
+CREATE TABLE t2 ( a INT );
+CREATE TABLE t3 ( a INT );
+INSERT INTO t1 VALUES (1), (2);
+INSERT INTO t2 VALUES (1), (2);
+INSERT INTO t3 VALUES (1), (2);
+CREATE TRIGGER tr1 BEFORE DELETE ON t2
+FOR EACH ROW INSERT INTO no_such_table VALUES (1);
+DELETE t1, t2, t3 FROM t1, t2, t3;
+ERROR 42S02: Table 'test.no_such_table' doesn't exist
+SELECT * FROM t1;
+a
+SELECT * FROM t2;
+a
+1
+2
+SELECT * FROM t3;
+a
+1
+2
+DROP TABLE t1, t2, t3;
+CREATE TABLE t1 ( a INT );
+CREATE TABLE t2 ( a INT );
+CREATE TABLE t3 ( a INT );
+INSERT INTO t1 VALUES (1), (2);
+INSERT INTO t2 VALUES (1), (2);
+INSERT INTO t3 VALUES (1), (2);
+CREATE TRIGGER tr1 AFTER DELETE ON t2
+FOR EACH ROW INSERT INTO no_such_table VALUES (1);
+DELETE t1, t2, t3 FROM t1, t2, t3;
+ERROR 42S02: Table 'test.no_such_table' doesn't exist
+SELECT * FROM t1;
+a
+SELECT * FROM t2;
+a
+2
+SELECT * FROM t3;
+a
+1
+2
+DROP TABLE t1, t2, t3;

=== modified file 'mysql-test/t/delete.test'
--- a/mysql-test/t/delete.test	2008-02-27 22:59:48 +0000
+++ b/mysql-test/t/delete.test	2009-09-28 12:43:54 +0000
@@ -445,3 +445,47 @@ DROP DATABASE db1;
 DROP DATABASE db2;
 DROP PROCEDURE count_rows;
 DROP TABLE t1, t2;
+
+--echo #
+--echo # Bug#46958: Assertion in Diagnostics_area::set_ok_status, trigger, 
+--echo # merge table
+--echo #
+CREATE TABLE t1 ( a INT );
+CREATE TABLE t2 ( a INT );
+CREATE TABLE t3 ( a INT );
+
+INSERT INTO t1 VALUES (1), (2);
+INSERT INTO t2 VALUES (1), (2);
+INSERT INTO t3 VALUES (1), (2);
+
+CREATE TRIGGER tr1 BEFORE DELETE ON t2
+FOR EACH ROW INSERT INTO no_such_table VALUES (1);
+
+--error ER_NO_SUCH_TABLE
+DELETE t1, t2, t3 FROM t1, t2, t3;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+SELECT * FROM t3;
+
+DROP TABLE t1, t2, t3;
+
+CREATE TABLE t1 ( a INT );
+CREATE TABLE t2 ( a INT );
+CREATE TABLE t3 ( a INT );
+
+INSERT INTO t1 VALUES (1), (2);
+INSERT INTO t2 VALUES (1), (2);
+INSERT INTO t3 VALUES (1), (2);
+
+CREATE TRIGGER tr1 AFTER DELETE ON t2
+FOR EACH ROW INSERT INTO no_such_table VALUES (1);
+
+--error ER_NO_SUCH_TABLE
+DELETE t1, t2, t3 FROM t1, t2, t3;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+SELECT * FROM t3;
+
+DROP TABLE t1, t2, t3;

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2009-09-16 08:23:16 +0000
+++ b/sql/sql_class.h	2009-09-28 12:43:54 +0000
@@ -3259,7 +3259,8 @@ public:
   bool send_data(List<Item> &items);
   bool initialize_tables (JOIN *join);
   void send_error(uint errcode,const char *err);
-  int  do_deletes();
+  int do_deletes();
+  int do_table_deletes(TABLE *table, bool ignore);
   bool send_eof();
   inline ha_rows num_deleted()
   {

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2009-08-31 20:25:11 +0000
+++ b/sql/sql_delete.cc	2009-09-28 12:43:54 +0000
@@ -879,22 +879,19 @@ void multi_delete::abort()
 
 
 
-/*
+/**
   Do delete from other tables.
-  Returns values:
-	0 ok
-	1 error
+
+  @retval 0 ok
+  @retval 1 error
+
+  @todo Is there any reason not use the normal nested-loops join? If not, and
+  there is no documentation supporting it, this method and callee should be
+  removed and there should be hooks within normal execution.
 */
 
 int multi_delete::do_deletes()
 {
-  int local_error= 0, counter= 0, tmp_error;
-  bool will_batch;
-  /*
-    If the IGNORE option is used all non fatal errors will be translated
-    to warnings and we should not break the row-by-row iteration
-  */
-  bool ignore= thd->lex->current_select->no_error;
   DBUG_ENTER("do_deletes");
   DBUG_ASSERT(do_delete);
 
@@ -905,79 +902,108 @@ int multi_delete::do_deletes()
   table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
                         delete_tables);
  
-  for (; table_being_deleted;
+  for (uint counter= 0; table_being_deleted;
        table_being_deleted= table_being_deleted->next_local, counter++)
   { 
-    ha_rows last_deleted= deleted;
     TABLE *table = table_being_deleted->table;
     if (tempfiles[counter]->get(table))
+      DBUG_RETURN(1);
+
+    int local_error= 
+      do_table_deletes(table, thd->lex->current_select->no_error);
+
+    if (thd->killed && !local_error)
+      DBUG_RETURN(1);
+
+    if (local_error == -1)				// End of file
+      local_error = 0;
+
+    if (local_error)
+      DBUG_RETURN(local_error);
+  }
+  DBUG_RETURN(0);
+}
+
+
+/**
+   Implements the inner loop of nested-loops join within multi-DELETE
+   execution.
+
+   @param table The table from which to delete.
+
+   @param ignore If used, all non fatal errors will be translated
+   to warnings and we should not break the row-by-row iteration.
+
+   @return Status code
+
+   @retval  0 All ok.
+   @retval  1 Triggers or handler reported error.
+   @retval -1 End of file from handler.
+*/
+int multi_delete::do_table_deletes(TABLE *table, bool ignore)
+{
+  int local_error= 0;
+  READ_RECORD info;
+  ha_rows last_deleted= deleted;
+  DBUG_ENTER("do_deletes_for_table");
+  init_read_record(&info, thd, table, NULL, 0, 1, FALSE);
+  /*
+    Ignore any rows not found in reference tables as they may already have
+    been deleted by foreign key handling
+  */
+  info.ignore_not_found_rows= 1;
+  bool will_batch= !table->file->start_bulk_delete();
+  while (!(local_error= info.read_record(&info)) && !thd->killed)
+  {
+    if (table->triggers &&
+        table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
+                                          TRG_ACTION_BEFORE, FALSE))
     {
-      local_error=1;
+      local_error= 1;
       break;
     }
-
-    READ_RECORD	info;
-    init_read_record(&info, thd, table, NULL, 0, 1, FALSE);
+      
+    local_error= table->file->ha_delete_row(table->record[0]);
+    if (local_error && !ignore)
+    {
+      table->file->print_error(local_error, MYF(0));
+      break;
+    }
+      
     /*
-      Ignore any rows not found in reference tables as they may already have
-      been deleted by foreign key handling
+      Increase the reported number of deleted rows only if no error occurred
+      during ha_delete_row.
+      Also, don't execute the AFTER trigger if the row operation failed.
     */
-    info.ignore_not_found_rows= 1;
-    will_batch= !table->file->start_bulk_delete();
-    while (!(local_error=info.read_record(&info)) && !thd->killed)
+    if (!local_error)
     {
+      deleted++;
       if (table->triggers &&
           table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
-                                            TRG_ACTION_BEFORE, FALSE))
+                                            TRG_ACTION_AFTER, FALSE))
       {
         local_error= 1;
         break;
       }
-
-      local_error= table->file->ha_delete_row(table->record[0]);
-      if (local_error && !ignore)
-      {
-        table->file->print_error(local_error,MYF(0));
-        break;
-      }
-
-      /*
-        Increase the reported number of deleted rows only if no error occurred
-        during ha_delete_row.
-        Also, don't execute the AFTER trigger if the row operation failed.
-      */
-      if (!local_error)
-      {
-        deleted++;
-        if (table->triggers &&
-            table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
-                                              TRG_ACTION_AFTER, FALSE))
-        {
-          local_error= 1;
-          break;
-        }
-      }
     }
-    if (will_batch && (tmp_error= table->file->end_bulk_delete()))
+  }
+  if (will_batch)
+  {
+    int tmp_error= table->file->end_bulk_delete();
+    if (tmp_error && !local_error)
     {
-      if (!local_error)
-      {
-        local_error= tmp_error;
-        table->file->print_error(local_error,MYF(0));
-      }
+      local_error= tmp_error;
+      table->file->print_error(local_error, MYF(0));
     }
-    if (last_deleted != deleted && !table->file->has_transactions())
-      thd->transaction.stmt.modified_non_trans_table= TRUE;
-    end_read_record(&info);
-    if (thd->killed && !local_error)
-      local_error= 1;
-    if (local_error == -1)				// End of file
-      local_error = 0;
   }
+  if (last_deleted != deleted && !table->file->has_transactions())
+    thd->transaction.stmt.modified_non_trans_table= TRUE;
+
+  end_read_record(&info);
+
   DBUG_RETURN(local_error);
 }
 
-
 /*
   Send ok to the client
 


Attachment: [text/bzr-bundle] bzr/martin.hansson@sun.com-20090928124354-2gdp89kpotsf4sfe.bundle
Thread
bzr commit into mysql-pe branch (martin.hansson:3624) Bug#46958Martin Hansson28 Sep