MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Martin Hansson Date:September 28 2009 12:45pm
Subject:bzr push into mysql-pe branch (martin.hansson:3623 to 3624) Bug#46958
View as plain text  
 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
 3623 Dao-Gang.Qu@stripped	2009-09-28
      Bug #45827  Stmt using two autoinc values does not produce unsafe warning
      
      One statement that have more than one different tables to update with 
      autoinc columns just was marked as unsafe in mixed mode, so the unsafe 
      warning can't be produced in statement mode.
      
      To fix the problem, mark the statement as unsafe in statement mode too.
     @ mysql-test/extra/rpl_tests/rpl_insert_id.test
        The test case is updated due to a patch of bug#45827.
     @ mysql-test/r/merge_recover.result
        The test result is updated due to a patch of bug#45827.
     @ mysql-test/suite/backup_ptr/t/backup_ptr_objects.test
        The test case is updated due to a patch of bug#45827.
     @ mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result
        The test result is updated due to a patch of bug#45827.
     @ mysql-test/suite/binlog/r/binlog_unsafe.result
        Test result for bug#45827
     @ mysql-test/suite/binlog/t/binlog_unsafe.test
        Added test to verify if stmt that have more than one
        different tables to update with autoinc columns will 
        produce unsafe warning
     @ mysql-test/suite/rpl/t/rpl_trigger.test
        The test case is updated due to a patch of bug#45827.
     @ sql/sql_base.cc
        Reomved the 'set_current_stmt_binlog_row_based_if_mixed' function 
        for producing unsafe warnings by executing 'decide_logging_format' 
        function later in statement mode.

    modified:
      mysql-test/extra/rpl_tests/rpl_insert_id.test
      mysql-test/r/merge_recover.result
      mysql-test/suite/backup_ptr/t/backup_ptr_objects.test
      mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result
      mysql-test/suite/binlog/r/binlog_unsafe.result
      mysql-test/suite/binlog/t/binlog_unsafe.test
      mysql-test/suite/rpl/t/rpl_trigger.test
      sql/sql_base.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 push into mysql-pe branch (martin.hansson:3623 to 3624) Bug#46958Martin Hansson28 Sep