List:Commits« Previous MessageNext Message »
From:Mattias Jonsson Date:May 18 2012 11:12pm
Subject:bzr push into mysql-trunk branch (mattias.jonsson:3834 to 3835) WL#4443
View as plain text  
 3835 Mattias Jonsson	2012-05-19
      WL#4443
      Fix for CREATE SELECT and delayed locking.
      
      To be consistent with the protocol for locking
      and THD::decide_logging_format(), we postpone
      locking of target table to after all locks has been
      taken on the source tables.
      
      i.e. we create the table in create_select::prepare()
      and lock it in create_select::prepare2().
      prepare() is called from JOIN::prepare() and
      prepare2() from JOIN::exec().

    modified:
      mysql-test/r/partition_explicit_prune.result
      mysql-test/r/partition_locking.result
      mysql-test/t/partition_explicit_prune.test
      mysql-test/t/partition_locking.test
      sql/sql_class.h
      sql/sql_insert.cc
      sql/sql_select.cc
 3834 Mattias Jonsson	2012-05-17
      WL#4443
      Fix + test for multi UPDATE with BEFORE UPDATE triggers.

    modified:
      mysql-test/r/partition_locking.result
      mysql-test/t/partition_locking.test
      sql/sql_update.cc
=== modified file 'mysql-test/r/partition_explicit_prune.result'
--- a/mysql-test/r/partition_explicit_prune.result	revid:mattias.jonsson@stripped
+++ b/mysql-test/r/partition_explicit_prune.result	revid:mattias.jonsson@stripped
@@ -1923,4 +1923,11 @@ CREATE TEMPORARY TABLE t1 (a INT);
 SELECT * FROM t1 PARTITION(pNonexisting);
 ERROR HY000: PARTITION () clause on non partitioned table
 DROP TEMPORARY TABLE t1;
+#
+# Test CREATE LIKE does not take PARTITION clause
+#
+CREATE TABLE t1 (a INT) PARTITION BY HASH (a) PARTITIONS 3;
+CREATE TABLE t2 LIKE t1 PARTITION (p0, p2);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARTITION (p0, p2)' at line 1
+DROP TABLE t1;
 SET @@default_storage_engine = @old_default_storage_engine;

=== modified file 'mysql-test/r/partition_locking.result'
--- a/mysql-test/r/partition_locking.result	revid:mattias.jonsson@stripped
+++ b/mysql-test/r/partition_locking.result	revid:mattias.jonsson@stripped
@@ -5131,3 +5131,42 @@ DROP TABLE t2;
 INSERT INTO t1 VALUES (1);
 ERROR 42S02: Table 'test.t2' doesn't exist
 DROP TABLE t1;
+CREATE TABLE t1 (a INT) PARTITION BY HASH (a) PARTITIONS 3;
+INSERT INTO t1 VALUES (1), (3), (9), (2), (8), (7);
+FLUSH STATUS;
+CREATE TABLE t2 SELECT * FROM t1 PARTITION (p1, p2);
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_FIRST	2
+HANDLER_READ_KEY	2
+HANDLER_READ_RND_NEXT	6
+HANDLER_WRITE	21
+# 8 locks (2 tables, 2 partitions, lock/unlock)
+SELECT * FROM t2;
+a
+1
+2
+7
+8
+DROP TABLE t2;
+FLUSH STATUS;
+CREATE TABLE t2 SELECT * FROM t1 WHERE a IN (1, 3, 9);
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_FIRST	2
+HANDLER_READ_KEY	2
+HANDLER_READ_RND_NEXT	6
+HANDLER_WRITE	20
+# 8 locks (2 tables, 2 partitions, lock/unlock)
+SELECT * FROM t2;
+a
+1
+3
+9
+DROP TABLE t1, t2;

=== modified file 'mysql-test/t/partition_explicit_prune.test'
--- a/mysql-test/t/partition_explicit_prune.test	revid:mattias.jonsson@stripped
+++ b/mysql-test/t/partition_explicit_prune.test	revid:mattias.jonsson@stripped
@@ -843,4 +843,12 @@ CREATE TEMPORARY TABLE t1 (a INT);
 SELECT * FROM t1 PARTITION(pNonexisting);
 DROP TEMPORARY TABLE t1;
 
+--echo #
+--echo # Test CREATE LIKE does not take PARTITION clause
+--echo #
+CREATE TABLE t1 (a INT) PARTITION BY HASH (a) PARTITIONS 3;
+--error ER_PARSE_ERROR
+CREATE TABLE t2 LIKE t1 PARTITION (p0, p2);
+DROP TABLE t1;
+
 SET @@default_storage_engine = @old_default_storage_engine;

=== modified file 'mysql-test/t/partition_locking.test'
--- a/mysql-test/t/partition_locking.test	revid:mattias.jonsson@stripped
+++ b/mysql-test/t/partition_locking.test	revid:mattias.jonsson@stripped
@@ -1975,3 +1975,23 @@ DROP TABLE t2;
 --error ER_NO_SUCH_TABLE
 INSERT INTO t1 VALUES (1);
 DROP TABLE t1;
+
+CREATE TABLE t1 (a INT) PARTITION BY HASH (a) PARTITIONS 3;
+INSERT INTO t1 VALUES (1), (3), (9), (2), (8), (7);
+
+FLUSH STATUS;
+CREATE TABLE t2 SELECT * FROM t1 PARTITION (p1, p2);
+eval $get_handler_status_counts;
+--echo # 8 locks (2 tables, 2 partitions, lock/unlock)
+--sorted_result
+SELECT * FROM t2;
+DROP TABLE t2;
+
+FLUSH STATUS;
+CREATE TABLE t2 SELECT * FROM t1 WHERE a IN (1, 3, 9);
+eval $get_handler_status_counts;
+--echo # 8 locks (2 tables, 2 partitions, lock/unlock)
+--sorted_result
+SELECT * FROM t2;
+
+DROP TABLE t1, t2;

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	revid:mattias.jonsson@stripped
+++ b/sql/sql_class.h	revid:mattias.jonsson@stripped
@@ -4367,7 +4367,7 @@ public:
   // Needed for access from local class MY_HOOKS in prepare(), since thd is proteted.
   const THD *get_thd(void) { return thd; }
   const HA_CREATE_INFO *get_create_info() { return create_info; };
-  int prepare2(void) { return 0; }
+  int prepare2(void);
 };
 
 #include <myisam.h>

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	revid:mattias.jonsson@stripped
+++ b/sql/sql_insert.cc	revid:mattias.jonsson@stripped
@@ -3897,9 +3897,7 @@ void select_insert::abort_result_set() {
 static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
                                       TABLE_LIST *create_table,
                                       Alter_info *alter_info,
-                                      List<Item> *items,
-                                      MYSQL_LOCK **lock,
-                                      TABLEOP_HOOKS *hooks)
+                                      List<Item> *items)
 {
   TABLE tmp_table;		// Used during 'Create_field()'
   TABLE_SHARE share;
@@ -4017,38 +4015,63 @@ static TABLE *create_table_from_items(TH
     if (!table)                                   // open failed
       DBUG_RETURN(0);
   }
+  DBUG_RETURN(table);
+}
 
-  DEBUG_SYNC(thd,"create_table_select_before_lock");
 
-  table->reginfo.lock_type=TL_WRITE;
-  hooks->prelock(&table, 1);                    // Call prelock hooks
-  /*
-    mysql_lock_tables() below should never fail with request to reopen table
-    since it won't wait for the table lock (we have exclusive metadata lock on
-    the table) and thus can't get aborted.
-  */
-  if (! ((*lock)= mysql_lock_tables(thd, &table, 1, 0)) ||
-        hooks->postlock(&table, 1))
+/**
+  Create the new table from the selected items.
+
+  @param values  List of items to be used as new columns
+  @param u       Select
+
+  @return Operation status.
+    @retval 0   Success
+    @retval !=0 Failure
+*/
+
+int
+select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
+{
+  DBUG_ENTER("select_create::prepare");
+
+  unit= u;
+  DBUG_ASSERT(create_table->table == NULL);
+
+  DEBUG_SYNC(thd,"create_table_select_before_check_if_exists");
+
+  if (!(table= create_table_from_items(thd, create_info, create_table,
+                                       alter_info, &values)))
+    /* abort() deletes table */
+    DBUG_RETURN(-1);
+
+  if (table->s->fields < values.elements)
   {
-    if (*lock)
-    {
-      mysql_unlock_tables(thd, *lock);
-      *lock= 0;
-    }
-    drop_open_table(thd, table, create_table->db, create_table->table_name);
-    DBUG_RETURN(0);
+    my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
+    DBUG_RETURN(-1);
   }
-  DBUG_RETURN(table);
+  /* First field to copy */
+  field= table->field+table->s->fields - values.elements;
+
+  DBUG_RETURN(0);
 }
 
 
+/**
+  Lock the newly created table.
+
+  @return Operation status.
+    @retval 0   Success
+    @retval !=0 Failure
+*/
+
 int
-select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
+select_create::prepare2()
 {
-  MYSQL_LOCK *extra_lock= NULL;
-  DBUG_ENTER("select_create::prepare");
+  DBUG_ENTER("select_create::prepare2");
+  DEBUG_SYNC(thd,"create_table_select_before_lock");
 
-  TABLEOP_HOOKS *hook_ptr= NULL;
+  MYSQL_LOCK *extra_lock= NULL;
   /*
     For row-based replication, the CREATE-SELECT statement is written
     in two pieces: the first one contain the CREATE TABLE statement
@@ -4108,19 +4131,25 @@ select_create::prepare(List<Item> &value
   };
 
   MY_HOOKS hooks(this, create_table, select_tables);
-  hook_ptr= &hooks;
-
-  unit= u;
-  DBUG_ASSERT(create_table->table == NULL);
-
-  DEBUG_SYNC(thd,"create_table_select_before_check_if_exists");
-
-  if (!(table= create_table_from_items(thd, create_info, create_table,
-                                       alter_info, &values,
-                                       &extra_lock, hook_ptr)))
-    /* abort() deletes table */
-    DBUG_RETURN(-1);
-
+ 
+  table->reginfo.lock_type=TL_WRITE;
+  hooks.prelock(&table, 1);                    // Call prelock hooks
+  /*
+    mysql_lock_tables() below should never fail with request to reopen table
+    since it won't wait for the table lock (we have exclusive metadata lock on
+    the table) and thus can't get aborted.
+  */
+  if (! (extra_lock= mysql_lock_tables(thd, &table, 1, 0)) ||
+        hooks.postlock(&table, 1))
+  {
+    if (extra_lock)
+    {
+      mysql_unlock_tables(thd, extra_lock);
+      extra_lock= 0;
+    }
+    drop_open_table(thd, table, create_table->db, create_table->table_name);
+    DBUG_RETURN(1);
+  }
   if (extra_lock)
   {
     DBUG_ASSERT(m_plock == NULL);
@@ -4132,23 +4161,13 @@ select_create::prepare(List<Item> &value
 
     *m_plock= extra_lock;
   }
-
-  if (table->s->fields < values.elements)
-  {
-    my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
-    DBUG_RETURN(-1);
-  }
-
- /* First field to copy */
-  field= table->field+table->s->fields - values.elements;
-
   /* Mark all fields that are given values */
   for (Field **f= field ; *f ; f++)
     bitmap_set_bit(table->write_set, (*f)->field_index);
 
   // Set up an empty bitmap of function defaults
   if (info.add_function_default_columns(table, table->write_set))
-    DBUG_RETURN(TRUE);
+    DBUG_RETURN(1);
 
   table->next_number_field=table->found_next_number_field;
 

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	revid:mattias.jonsson@stripped
+++ b/sql/sql_select.cc	revid:mattias.jonsson@stripped
@@ -788,7 +788,8 @@ bool JOIN::prepare_result(List<Item> **c
       select_lex->handle_derived(thd->lex, &mysql_derived_create))
     goto err;
 
-  (void) result->prepare2(); // Currently, this cannot fail.
+  if (result->prepare2())
+    goto err;
 
   if ((select_lex->options & OPTION_SCHEMA_TABLE) &&
       get_schema_tables_result(this, PROCESSED_BY_JOIN_EXEC))

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (mattias.jonsson:3834 to 3835) WL#4443Mattias Jonsson20 May