List:Commits« Previous MessageNext Message »
From:Martin Skold Date:April 4 2007 11:22am
Subject:bk commit into 5.1 tree (mskold:1.2432)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of marty. When marty 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@stripped, 2007-04-04 13:21:49+02:00, mskold@stripped +11 -0
  Merge mysql.com:/windows/Linux_space/MySQL/mysql-5.0
  into  mysql.com:/windows/Linux_space/MySQL/mysql-5.1
  MERGE: 1.1810.2399.18

  include/my_base.h@stripped, 2007-04-04 13:21:44+02:00, mskold@stripped +9 -10
    Merge
    MERGE: 1.70.5.1

  mysql-test/r/ndb_trigger.result@stripped, 2007-04-04 12:59:12+02:00, mskold@stripped +0 -171
    Using local, will re-generate.
    MERGE: 1.1.1.1

  mysql-test/t/ndb_trigger.test@stripped, 2007-04-04 13:21:44+02:00, mskold@stripped +0 -1
    Merge
    MERGE: 1.1.1.1

  sql/ha_ndbcluster.cc@stripped, 2007-04-04 13:21:44+02:00, mskold@stripped +2 -5
    Merge
    MERGE: 1.175.61.12

  sql/ha_ndbcluster.h@stripped, 2007-04-04 12:55:31+02:00, mskold@stripped +0 -0
    Auto merged
    MERGE: 1.82.6.3

  sql/mysql_priv.h@stripped, 2007-04-04 13:21:44+02:00, mskold@stripped +0 -0
    Merge
    MERGE: 1.290.87.1

  sql/sql_delete.cc@stripped, 2007-04-04 13:21:44+02:00, mskold@stripped +21 -21
    Merge
    MERGE: 1.144.21.1

  sql/sql_insert.cc@stripped, 2007-04-04 13:21:45+02:00, mskold@stripped +0 -3
    Merge
    MERGE: 1.146.46.1

  sql/sql_load.cc@stripped, 2007-04-04 13:21:45+02:00, mskold@stripped +0 -1
    Merge
    MERGE: 1.78.7.1

  sql/sql_trigger.h@stripped, 2007-04-04 12:55:31+02:00, mskold@stripped +0 -0
    Auto merged
    MERGE: 1.19.4.1

  sql/sql_update.cc@stripped, 2007-04-04 13:21:45+02:00, mskold@stripped +12 -11
    Merge
    MERGE: 1.154.25.2

# 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:	mskold
# Host:	linux.site
# Root:	/windows/Linux_space/MySQL/mysql-5.1/RESYNC

--- 1.95/include/my_base.h	2007-04-04 13:22:01 +02:00
+++ 1.96/include/my_base.h	2007-04-04 13:22:01 +02:00
@@ -171,7 +171,15 @@ enum ha_extra_function {
     Off by default.
   */
   HA_EXTRA_WRITE_CAN_REPLACE,
-  HA_EXTRA_WRITE_CANNOT_REPLACE
+  HA_EXTRA_WRITE_CANNOT_REPLACE,
+  /*
+    Inform handler that delete_row()/update_row() cannot batch deletes/updates
+    and should perform them immediately. This may be needed when table has 
+    AFTER DELETE/UPDATE triggers which access to subject table.
+    These flags are reset by the handler::extra(HA_EXTRA_RESET) call.
+  */
+  HA_EXTRA_DELETE_CANNOT_BATCH,
+  HA_EXTRA_UPDATE_CANNOT_BATCH
 };
 
 	/* The following is parameter to ha_panic() */

--- 1.475/sql/mysql_priv.h	2007-04-04 13:22:01 +02:00
+++ 1.476/sql/mysql_priv.h	2007-04-04 13:22:01 +02:00
@@ -974,6 +974,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
                   bool ignore);
 int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
                                            TABLE_LIST *table_list);
+void prepare_triggers_for_insert_stmt(THD *thd, TABLE *table,
+                                      enum_duplicates duplic);
 bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
 bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
                   SQL_LIST *order, ha_rows rows, ulonglong options,

--- 1.208/sql/sql_delete.cc	2007-04-04 13:22:01 +02:00
+++ 1.209/sql/sql_delete.cc	2007-04-04 13:22:01 +02:00
@@ -216,7 +216,20 @@ bool mysql_delete(THD *thd, TABLE_LIST *
 
   init_ftfuncs(thd, select_lex, 1);
   thd->proc_info="updating";
-  will_batch= !table->file->start_bulk_delete();
+  if (table->triggers && 
+      table->triggers->has_triggers(TRG_EVENT_DELETE,
+                                    TRG_ACTION_AFTER))
+  {
+    /*
+      The table has AFTER DELETE triggers that might access to subject table
+      and therefore might need delete to be done immediately. So we turn-off
+      the batching.
+    */
+    (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+    will_batch= FALSE;
+  }
+  else
+    will_batch= !table->file->start_bulk_delete();
 
 
   table->mark_columns_needed_for_delete();
@@ -552,6 +565,17 @@ multi_delete::initialize_tables(JOIN *jo
 	transactional_tables= 1;
       else
 	normal_tables= 1;
+      if (tbl->triggers &&
+          tbl->triggers->has_triggers(TRG_EVENT_DELETE,
+                                      TRG_ACTION_AFTER))
+      {
+	/*
+          The table has AFTER DELETE triggers that might access to subject 
+          table and therefore might need delete to be done immediately. 
+          So we turn-off the batching.
+        */
+	(void) tbl->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+      }
       tbl->prepare_for_position();
       tbl->mark_columns_needed_for_delete();
     }

--- 1.244/sql/sql_insert.cc	2007-04-04 13:22:01 +02:00
+++ 1.245/sql/sql_insert.cc	2007-04-04 13:22:01 +02:00
@@ -341,6 +341,51 @@ static int check_update_fields(THD *thd,
 }
 
 
+  Prepare triggers  for INSERT-like statement.
+
+  SYNOPSIS
+    prepare_triggers_for_insert_stmt()
+      thd     The current thread
+      table   Table to which insert will happen
+      duplic  Type of duplicate handling for insert which will happen
+
+  NOTE
+    Prepare triggers for INSERT-like statement by marking fields
+    used by triggers and inform handlers that batching of UPDATE/DELETE 
+    cannot be done if there are BEFORE UPDATE/DELETE triggers.
+*/
+
+void prepare_triggers_for_insert_stmt(THD *thd, TABLE *table,
+                                      enum_duplicates duplic)
+{
+  if (table->triggers)
+  {
+    if (table->triggers->has_triggers(TRG_EVENT_DELETE,
+                                      TRG_ACTION_AFTER))
+    {
+      /*
+        The table has AFTER DELETE triggers that might access to 
+        subject table and therefore might need delete to be done 
+        immediately. So we turn-off the batching.
+      */ 
+      (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+    }
+    if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+                                      TRG_ACTION_AFTER))
+    {
+      /*
+        The table has AFTER UPDATE triggers that might access to subject 
+        table and therefore might need update to be done immediately. 
+        So we turn-off the batching.
+      */ 
+      (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+    }
+    mark_fields_used_by_triggers_for_insert_stmt(thd, table, duplic);
+  }
+}
+
+
+/*
 bool mysql_insert(THD *thd,TABLE_LIST *table_list,
                   List<Item> &fields,
                   List<List_item> &values_list,

--- 1.222/sql/sql_update.cc	2007-04-04 13:22:01 +02:00
+++ 1.223/sql/sql_update.cc	2007-04-04 13:22:01 +02:00
@@ -447,7 +447,20 @@ int mysql_update(THD *thd,
                               (thd->variables.sql_mode &
                                (MODE_STRICT_TRANS_TABLES |
                                 MODE_STRICT_ALL_TABLES)));
-  will_batch= !table->file->start_bulk_update();
+  if (table->triggers &&
+      table->triggers->has_triggers(TRG_EVENT_UPDATE,
+                                    TRG_ACTION_AFTER))
+  {
+    /*
+      The table has AFTER UPDATE triggers that might access to subject 
+      table and therefore might need update to be done immediately. 
+      So we turn-off the batching.
+    */ 
+    (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+    will_batch= FALSE;
+  }
+  else
+    will_batch= !table->file->start_bulk_update();
 
   /*
     We can use compare_record() to optimize away updates if
@@ -1116,6 +1129,20 @@ int multi_update::prepare(List<Item> &no
       table->no_keyread=1;
       table->used_keys.clear_all();
       table->pos_in_table_list= tl;
+      if (table->triggers)
+      {
+	table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE);
+	if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+					  TRG_ACTION_AFTER))
+	{
+	  /*
+	    The table has AFTER UPDATE triggers that might access to subject 
+	    table and therefore might need update to be done immediately. 
+	    So we turn-off the batching.
+	  */ 
+	  (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+	}
+      }
     }
   }
 

--- 1.2/mysql-test/t/ndb_trigger.test	2007-04-04 13:22:01 +02:00
+++ 1.3/mysql-test/t/ndb_trigger.test	2007-04-04 13:22:01 +02:00
@@ -110,5 +110,112 @@ drop trigger t4_au;
 drop trigger t4_ad;
 
 drop table t1, t2, t3, t4, t5;
+# Test for bug#26242
+# Verify that AFTER UPDATE/DELETE triggers are executed
+# after the change has actually taken place
+
+CREATE TABLE t1 (
+  id INT NOT NULL PRIMARY KEY,
+  xy INT
+) ENGINE=ndbcluster;
+
+INSERT INTO t1 VALUES (1, 0);
+
+DELIMITER //;
+CREATE TRIGGER t1_update AFTER UPDATE ON t1 FOR EACH ROW BEGIN REPLACE INTO t2 SELECT * FROM t1 WHERE t1.id = NEW.id; END //
+DELIMITER ;//
+
+CREATE TABLE t2 (
+  id INT NOT NULL PRIMARY KEY,
+  xy INT
+) ENGINE=ndbcluster;
+
+INSERT INTO t2 VALUES (2, 0);
+
+CREATE TABLE t3 (id INT NOT NULL PRIMARY KEY) ENGINE=ndbcluster;
+
+INSERT INTO t3 VALUES (1);
+
+CREATE TABLE t4 LIKE t1;
+
+DELIMITER //;
+CREATE TRIGGER t4_update AFTER UPDATE ON t4 FOR EACH ROW BEGIN REPLACE INTO t5 SELECT * FROM t4 WHERE t4.id = NEW.id; END //
+DELIMITER ;//
+
+CREATE TABLE t5 LIKE t2;
+
+UPDATE t1 SET xy = 3 WHERE id = 1;
+SELECT xy FROM t1 where id = 1;
+SELECT xy FROM t2 where id = 1;
+
+UPDATE t1 SET xy  = 4 WHERE id IN (SELECT id FROM t3 WHERE id = 1);
+SELECT xy FROM t1 where id = 1;
+SELECT xy FROM t2 where id = 1;
+
+INSERT INTO t4 SELECT * FROM t1;
+INSERT INTO t5 SELECT * FROM t2;
+UPDATE t1,t4 SET t1.xy = 3, t4.xy = 3 WHERE t1.id = 1 AND t4.id = 1;
+SELECT xy FROM t1 where id = 1;
+SELECT xy FROM t2 where id = 1;
+SELECT xy FROM t4 where id = 1;
+SELECT xy FROM t5 where id = 1;
+
+UPDATE t1,t4 SET t1.xy = 4, t4.xy = 4 WHERE t1.id IN (SELECT id FROM t3 WHERE id = 1) AND t4.id IN (SELECT id FROM t3 WHERE id = 1);
+SELECT xy FROM t1 where id = 1;
+SELECT xy FROM t2 where id = 1;
+SELECT xy FROM t4 where id = 1;
+SELECT xy FROM t5 where id = 1;
+
+INSERT INTO t1 VALUES (1,0) ON DUPLICATE KEY UPDATE xy = 5;
+SELECT xy FROM t1 where id = 1;
+SELECT xy FROM t2 where id = 1;
+
+DROP TRIGGER t1_update;
+DROP TRIGGER t4_update;
+
+DELIMITER //;
+CREATE TRIGGER t1_delete AFTER DELETE ON t1 FOR EACH ROW BEGIN REPLACE INTO t2 SELECT * FROM t1 WHERE t1.id > 4; END //
+DELIMITER ;//
+
+DELIMITER //;
+CREATE TRIGGER t4_delete AFTER DELETE ON t4 FOR EACH ROW BEGIN REPLACE INTO t5 SELECT * FROM t4 WHERE t4.id > 4; END //
+DELIMITER ;//
+
+INSERT INTO t1 VALUES (5, 0),(6,0);
+INSERT INTO t2 VALUES (5, 1),(6,1);
+INSERT INTO t3 VALUES (5);
+SELECT * FROM t1 order by id;
+SELECT * FROM t2 order by id;
+DELETE FROM t1 WHERE id IN (SELECT id FROM t3 WHERE id = 5);
+SELECT * FROM t1 order by id;
+SELECT * FROM t2 order by id;
+
+INSERT INTO t1 VALUES (5,0);
+UPDATE t2 SET xy = 1 WHERE id = 6;
+TRUNCATE t4;
+INSERT INTO t4 SELECT * FROM t1;
+TRUNCATE t5;
+INSERT INTO t5 SELECT * FROM t2;
+SELECT * FROM t1 order by id;
+SELECT * FROM t2 order by id;
+SELECT * FROM t4 order by id;
+SELECT * FROM t5 order by id;
+DELETE FROM t1,t4 USING t1,t3,t4 WHERE t1.id IN (SELECT id FROM t3 WHERE id = 5) AND t4.id IN (SELECT id FROM t3 WHERE id = 5);
+SELECT * FROM t1 order by id;
+SELECT * FROM t2 order by id;
+SELECT * FROM t4 order by id;
+SELECT * FROM t5 order by id;
+
+INSERT INTO t1 VALUES (5, 0);
+REPLACE INTO t2 VALUES (6,1);
+SELECT * FROM t1 order by id;
+SELECT * FROM t2 order by id;
+REPLACE INTO t1 VALUES (5, 1);
+SELECT * FROM t1 order by id;
+SELECT * FROM t2 order by id;
+
+DROP TRIGGER t1_delete;
+DROP TRIGGER t4_delete;
+DROP TABLE t1, t2, t3, t4, t5;
 
 --echo End of 5.1 tests

--- 1.26/sql/sql_trigger.h	2007-04-04 13:22:01 +02:00
+++ 1.27/sql/sql_trigger.h	2007-04-04 13:22:01 +02:00
@@ -110,6 +110,11 @@ public:
                                 const char *old_table,
                                 const char *new_db,
                                 const char *new_table);
+  bool has_triggers(trg_event_type event_type, 
+                    trg_action_time_type action_time)
+  {
+    return (bodies[event_type][action_time]);
+  }
   bool has_delete_triggers()
   {
     return (bodies[TRG_EVENT_DELETE][TRG_ACTION_BEFORE] ||

--- 1.406/sql/ha_ndbcluster.cc	2007-04-04 13:22:01 +02:00
+++ 1.407/sql/ha_ndbcluster.cc	2007-04-04 13:22:01 +02:00
@@ -2992,8 +2992,13 @@ int ha_ndbcluster::update_row(const byte
       no_fields++;
     op->setValue(no_fields, part_func_value);
   }
-  // Execute update operation
-  if (!cursor && execute_no_commit(this,trans,FALSE) != 0) {
+  /*
+    Execute update operation if we are not doing a scan for update
+    and there exist UPDATE AFTER triggers
+  */
+
+  if ((!cursor || m_update_cannot_batch) && 
+      execute_no_commit(this,trans,false) != 0) {
     no_uncommitted_rows_execute_failure();
     DBUG_RETURN(ndb_err(trans));
   }
@@ -3047,7 +3052,7 @@ int ha_ndbcluster::delete_row(const byte
 
     no_uncommitted_rows_update(-1);
 
-    if (!m_primary_key_update)
+    if (!(m_primary_key_update || m_delete_cannot_batch))
       // If deleting from cursor, NoCommit will be handled in next_result
       DBUG_RETURN(0);
   }
@@ -3886,7 +3891,13 @@ int ha_ndbcluster::extra(enum ha_extra_f
     DBUG_PRINT("info", ("Turning OFF use of write instead of insert"));
     m_use_write= FALSE;
     break;
-  default:
+  case HA_EXTRA_DELETE_CANNOT_BATCH:
+    DBUG_PRINT("info", ("HA_EXTRA_DELETE_CANNOT_BATCH"));
+    m_delete_cannot_batch= TRUE;
+    break;
+  case HA_EXTRA_UPDATE_CANNOT_BATCH:
+    DBUG_PRINT("info", ("HA_EXTRA_UPDATE_CANNOT_BATCH"));
+    m_update_cannot_batch= TRUE;
     break;
   }
   
@@ -3897,6 +3908,8 @@ int ha_ndbcluster::extra(enum ha_extra_f
 int ha_ndbcluster::reset()
 {
   DBUG_ENTER("ha_ndbcluster::reset");
+  m_delete_cannot_batch= FALSE;
+  m_update_cannot_batch= FALSE;
   cond_clear();
   /*
     Regular partition pruning will set the bitmap appropriately.
@@ -5826,6 +5839,8 @@ ha_ndbcluster::ha_ndbcluster(handlerton 
   m_bulk_insert_rows((ha_rows) 1024),
   m_rows_changed((ha_rows) 0),
   m_bulk_insert_not_flushed(FALSE),
+  m_delete_cannot_batch(FALSE),
+  m_update_cannot_batch(FALSE),
   m_ops_pending(0),
   m_skip_auto_increment(TRUE),
   m_blobs_pending(0),

--- 1.168/sql/ha_ndbcluster.h	2007-04-04 13:22:01 +02:00
+++ 1.169/sql/ha_ndbcluster.h	2007-04-04 13:22:01 +02:00
@@ -960,6 +960,8 @@ private:
   ha_rows m_bulk_insert_rows;
   ha_rows m_rows_changed;
   bool m_bulk_insert_not_flushed;
+  bool m_delete_cannot_batch;
+  bool m_update_cannot_batch;
   ha_rows m_ops_pending;
   bool m_skip_auto_increment;
   bool m_blobs_pending;
Thread
bk commit into 5.1 tree (mskold:1.2432)Martin Skold4 Apr