List:Commits« Previous MessageNext Message »
From:Staale Smedseng Date:February 24 2009 3:43pm
Subject:bzr commit into mysql-5.1-bugteam branch (staale.smedseng:2804) Bug#39953
View as plain text  
#At file:///Users/staale/z/b39953/ based on revid:aelkin@stripped

 2804 Staale Smedseng	2009-02-24
      Bug#39953 Triggers are not working properly with multi table updates
                  
      open_table() is modified to take a flag instructing it not to check
      whether a table for update is used by the calling statement in a
      SF/trigger context.
                        
      mysql_multi_update_prepare() is modified to do this check after the
      tables are opened and locks are (possibly) downgraded.

    modified:
      .cvsignore
      mysql-test/r/trigger.result
      mysql-test/t/trigger.test
      sql/mysql_priv.h
      sql/sql_base.cc
      sql/sql_update.cc
=== modified file '.cvsignore'
--- a/.cvsignore	2000-07-31 19:29:14 +0000
+++ b/.cvsignore	2009-02-24 15:43:33 +0000
@@ -1,37 +1,40 @@
-.snprj
-COPYING
-COPYING.LIB
-INSTALL-SOURCE
-INSTALL-SOURCE-GENERIC
-Logs
-MIRRORS
-Makefile
-Makefile.in
-NEW-RPMS
+skr
 PUBLIC
-Projects
-TODO
+MIRRORS
+internal-docs
 WIN-LICENSE
-aclocal.m4
-binary
+TODO
+Makefile
+.bzr
+conftest.s2
 compile
-confdefs.h
-config.cache
+COPYING
+Logs
+.bzrignore
+INSTALL-SOURCE
 config.h
-config.log
+mysql-copyright-120700-194832
 config.status
-configure
-configure.in-removed
-conftest.c
+mysql-copyright-120700-221248
+NEW-RPMS
+config.log
+Projects
+libtool
 conftest.s1
-conftest.s2
 conftest.subs
-internal-docs
-libtool
+config.cache
+stamp-h
+Makefile.in
 linked_client_sources
 linked_server_sources
-mysql-copyright-120700-194832
-mysql-copyright-120700-221248
-skr
-stamp-h
+INSTALL-SOURCE-GENERIC
 tmp
+COPYING.LIB
+configure.in-removed
+configure
+.snprj
+confdefs.h
+binary
+aclocal.m4
+.bzr-mysql
+conftest.c

=== modified file 'mysql-test/r/trigger.result'
--- a/mysql-test/r/trigger.result	2008-05-30 09:12:07 +0000
+++ b/mysql-test/r/trigger.result	2009-02-24 15:43:33 +0000
@@ -2053,4 +2053,15 @@ select @a, @b;
 drop trigger trg1;
 drop trigger trg2;
 drop table t1, t2;
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TRIGGER IF EXISTS t_insert;
+CREATE TABLE t1 (a int, date_insert timestamp, PRIMARY KEY (a));
+INSERT INTO t1 (a) VALUES (2);
+CREATE TABLE t2 (a int, b int, PRIMARY KEY (a));
+CREATE TRIGGER t_insert AFTER INSERT ON t2 FOR EACH ROW BEGIN UPDATE t1,t2 SET
+date_insert=NOW() WHERE t1.a=t2.b AND t2.a=NEW.a; END |
+INSERT INTO t2 (a,b) VALUES (1,2);
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
 End of 5.1 tests.

=== modified file 'mysql-test/t/trigger.test'
--- a/mysql-test/t/trigger.test	2008-05-30 09:12:07 +0000
+++ b/mysql-test/t/trigger.test	2009-02-24 15:43:33 +0000
@@ -2337,4 +2337,26 @@ drop trigger trg1;
 drop trigger trg2;
 drop table t1, t2;
 
+#
+# Bug#39953 Triggers are not working properly with multi table updates
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TRIGGER IF EXISTS t_insert;
+--enable_warnings
+
+CREATE TABLE t1 (a int, date_insert timestamp, PRIMARY KEY (a));
+INSERT INTO t1 (a) VALUES (2);
+CREATE TABLE t2 (a int, b int, PRIMARY KEY (a));
+DELIMITER |;
+CREATE TRIGGER t_insert AFTER INSERT ON t2 FOR EACH ROW BEGIN UPDATE t1,t2 SET
+date_insert=NOW() WHERE t1.a=t2.b AND t2.a=NEW.a; END |
+DELIMITER ;|
+INSERT INTO t2 (a,b) VALUES (1,2);
+
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+
 --echo End of 5.1 tests.

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2009-02-14 10:40:22 +0000
+++ b/sql/mysql_priv.h	2009-02-24 15:43:33 +0000
@@ -2065,6 +2065,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, 
 #define MYSQL_OPEN_TEMPORARY_ONLY               0x0008
 #define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY      0x0010
 #define MYSQL_LOCK_PERF_SCHEMA                  0x0020
+#define MYSQL_SKIP_UPDATE_USED_TABLE_CHECK      0x0040
 
 void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
 void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2009-02-06 16:06:41 +0000
+++ b/sql/sql_base.cc	2009-02-24 15:43:33 +0000
@@ -2500,6 +2500,9 @@ bool check_if_table_exists(THD *thd, TAB
                           No version number checking is done.
                           MYSQL_OPEN_TEMPORARY_ONLY - Open only temporary
                           table not the base table or view.
+                          MYSQL_SKIP_CANT_UPDATE_CHECK - Don't check for
+                          table already in use in calling statement (when
+                          in a SF/trigger context).
 
   IMPLEMENTATION
     Uses a cache of open tables to find a table not in use.
@@ -2600,6 +2603,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *
     TABLE *best_table= 0;
     int best_distance= INT_MIN;
     bool check_if_used= thd->prelocked_mode &&
+                        !(flags & MYSQL_SKIP_UPDATE_USED_TABLE_CHECK) &&
                         ((int) table_list->lock_type >=
                          (int) TL_WRITE_ALLOW_WRITE);
     for (table=thd->open_tables; table ; table=table->next)

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2009-02-05 09:49:32 +0000
+++ b/sql/sql_update.cc	2009-02-24 15:43:33 +0000
@@ -972,9 +972,12 @@ int mysql_multi_update_prepare(THD *thd)
 
 reopen_tables:
 
-  /* open tables and create derived ones, but do not lock and fill them */
+  /* open tables and create derived ones, do not lock and fill them and skip
+     the check for update table in use by calling statement (in SF/trigger
+     context), it will be checked below */
   if (((original_multiupdate || need_reopen) &&
-       open_tables(thd, &table_list, &table_count, 0)) ||
+       open_tables(thd, &table_list, &table_count, 
+         MYSQL_SKIP_UPDATE_USED_TABLE_CHECK)) ||
       mysql_handle_derived(lex, &mysql_derived_prepare))
     DBUG_RETURN(TRUE);
   /*
@@ -1031,6 +1034,19 @@ reopen_tables:
         DBUG_RETURN(TRUE);
       }
 
+      if (table->query_id && table->query_id != thd->query_id)
+      {
+        /*
+          If we are in stored function or trigger we should ensure that
+          we won't change table that is already used by calling statement.
+          So if we are opening table for writing, we should check that it
+          is not already open by some calling stamement.
+        */
+        my_error(ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG, MYF(0),
+                 table->s->table_name.str);
+        DBUG_RETURN(0);
+      }
+      
       table->mark_columns_needed_for_update();
       DBUG_PRINT("info",("setting table `%s` for update", tl->alias));
       /*


Attachment: [text/bzr-bundle] bzr/staale.smedseng@sun.com-20090224154333-kf0kecc0hj8nr3l3.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (staale.smedseng:2804) Bug#39953Staale Smedseng24 Feb
  • Re: bzr commit into mysql-5.1-bugteam branch (staale.smedseng:2804)Bug#39953Davi Arnaut25 Feb