List:Commits« Previous MessageNext Message »
From:Martin Hansson Date:March 24 2011 10:23am
Subject:bzr commit into mysql-trunk branch (martin.hansson:3318)
View as plain text  
#At file:///data0/martin/bzrroot/bug11746628/t-enginestuff/ based on revid:tor.didriksen@stripped

 3318 Martin Hansson	2011-03-24
      Preliminary refactoring in order to fix Bug 11746628 -
      27645: DATETIME FIELD DOES NOT ACCEPT DEFAULT NOW()
      
      This patch removes all references to the members
      TABLE::timestamp_field and TABLE::timestamp_field_type from
      the handler API, as these are subject to removal in the fix
      for the bug. Instead a new interface
      TABLE::[begin|end][insert|update]() has been introduced. The
      new member functions are called from the handler class as
      opposed to copy-pasting the code in all handler subclasses,
      as was the case previously.

    added:
      unittest/gunit/table-t.cc
    modified:
      sql/field.h
      sql/ha_ndbcluster.cc
      sql/ha_partition.cc
      sql/handler.cc
      sql/table.cc
      sql/table.h
      storage/archive/ha_archive.cc
      storage/csv/ha_tina.cc
      storage/example/ha_example.cc
      storage/federated/ha_federated.cc
      storage/heap/ha_heap.cc
      storage/innobase/handler/ha_innodb.cc
      storage/myisam/ha_myisam.cc
      storage/myisammrg/ha_myisammrg.cc
      unittest/gunit/CMakeLists.txt
=== modified file 'sql/field.h'
--- a/sql/field.h	2011-03-22 11:44:40 +0000
+++ b/sql/field.h	2011-03-24 10:23:22 +0000
@@ -21,6 +21,7 @@
 #include "sql_string.h"                         /* String */
 #include "my_decimal.h"                         /* my_decimal */
 #include "sql_error.h"                          /* MYSQL_ERROR */
+#include "mysql_version.h"                      /* FRM_VER */
 
 #define DATETIME_DEC                     6
 
@@ -1398,7 +1399,7 @@ public:
   void sql_type(String &str) const;
   bool can_be_compared_as_longlong() const { return TRUE; }
   bool zero_pack() const { return 0; }
-  void set_time();
+  virtual void set_time();
   virtual void set_default()
   {
     if (table->timestamp_field == this &&

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2011-03-22 11:44:40 +0000
+++ b/sql/ha_ndbcluster.cc	2011-03-24 10:23:22 +0000
@@ -2902,9 +2902,6 @@ int ha_ndbcluster::write_row(uchar *reco
   }
 
   ha_statistic_increment(&SSV::ha_write_count);
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
-    table->timestamp_field->set_time();
-
   if (!(op= trans->getNdbOperation(m_table)))
     ERR_RETURN(trans->getNdbError());
 
@@ -3142,11 +3139,6 @@ int ha_ndbcluster::update_row(const ucha
   }
 
   ha_statistic_increment(&SSV::ha_update_count);
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
-  {
-    table->timestamp_field->set_time();
-    bitmap_set_bit(table->write_set, table->timestamp_field->field_index);
-  }
 
   if (m_use_partition_function &&
       (error= get_parts_for_update(old_data, new_data, table->record[0],

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2011-03-18 10:31:17 +0000
+++ b/sql/ha_partition.cc	2011-03-24 10:23:22 +0000
@@ -3233,10 +3233,6 @@ void ha_partition::try_semi_consistent_r
     Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
     sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
 
-    ADDITIONAL INFO:
-
-    We have to set timestamp fields and auto_increment fields, because those
-    may be used in determining which partition the row should be written to.
 */
 
 int ha_partition::write_row(uchar * buf)
@@ -3247,17 +3243,11 @@ int ha_partition::write_row(uchar * buf)
   bool have_auto_increment= table->next_number_field && buf == table->record[0];
   my_bitmap_map *old_map;
   THD *thd= ha_thd();
-  timestamp_auto_set_type saved_timestamp_type= table->timestamp_field_type;
   sql_mode_t saved_sql_mode= thd->variables.sql_mode;
   bool saved_auto_inc_field_not_null= table->auto_increment_field_not_null;
   DBUG_ENTER("ha_partition::write_row");
   DBUG_ASSERT(buf == m_rec0);
 
-  /* If we have a timestamp column, update it to the current time */
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
-    table->timestamp_field->set_time();
-  table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
   /*
     If we have an auto_increment column and we are writing a changed row
     or a new row, then update the auto_increment value in the record.
@@ -3327,7 +3317,6 @@ int ha_partition::write_row(uchar * buf)
 exit:
   thd->variables.sql_mode= saved_sql_mode;
   table->auto_increment_field_not_null= saved_auto_inc_field_not_null;
-  table->timestamp_field_type= saved_timestamp_type;
   DBUG_RETURN(error);
 }
 
@@ -3362,18 +3351,8 @@ int ha_partition::update_row(const uchar
   uint32 new_part_id, old_part_id;
   int error= 0;
   longlong func_value;
-  timestamp_auto_set_type orig_timestamp_type= table->timestamp_field_type;
   DBUG_ENTER("ha_partition::update_row");
 
-  /*
-    We need to set timestamp field once before we calculate
-    the partition. Then we disable timestamp calculations
-    inside m_file[*]->update_row() methods
-  */
-  if (orig_timestamp_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
-    table->timestamp_field->set_time();
-  table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
   if ((error= get_parts_for_update(old_data, new_data, table->record[0],
                                    m_part_info, &old_part_id, &new_part_id,
                                    &func_value)))
@@ -3448,7 +3427,6 @@ exit:
       info(HA_STATUS_AUTO);
     set_auto_increment_if_higher(table->found_next_number_field);
   }
-  table->timestamp_field_type= orig_timestamp_type;
   DBUG_RETURN(error);
 }
 

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2011-03-22 11:44:40 +0000
+++ b/sql/handler.cc	2011-03-24 10:23:22 +0000
@@ -5951,7 +5951,9 @@ int handler::ha_write_row(uchar *buf)
   MYSQL_START_TABLE_IO_WAIT(locker, &state, m_psi,
                             PSI_TABLE_WRITE_ROW, MAX_KEY, 0);
 
+  table->start_insert();
   error= write_row(buf);
+  table->end_insert();
 
   MYSQL_END_TABLE_IO_WAIT(locker);
   MYSQL_INSERT_ROW_DONE(error);
@@ -5984,7 +5986,9 @@ int handler::ha_update_row(const uchar *
   MYSQL_START_TABLE_IO_WAIT(locker, &state, m_psi,
                             PSI_TABLE_UPDATE_ROW, MAX_KEY, 0);
 
+  table->start_update();
   error= update_row(old_data, new_data);
+  table->end_update();
 
   MYSQL_END_TABLE_IO_WAIT(locker);
   MYSQL_UPDATE_ROW_DONE(error);

=== modified file 'sql/table.cc'
--- a/sql/table.cc	2011-03-17 09:47:50 +0000
+++ b/sql/table.cc	2011-03-24 10:23:22 +0000
@@ -5411,6 +5411,45 @@ bool TABLE::update_const_key_parts(Item 
 }
 
 /**
+   This member function is called by the handler right before a new row is
+   inserted in the table.
+*/
+void TABLE::start_insert() {
+  saved_timestamp_field_type= timestamp_field_type;
+  if ((timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) != 0)
+    timestamp_field->set_time();
+  timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+}
+
+/**
+   This member function is called by the handler right after a new row is
+   inserted in the table.
+*/
+void TABLE::end_insert() {
+  timestamp_field_type= saved_timestamp_field_type;  
+}
+
+/**
+   This member function is called by the handler right before a row in the
+   table is updated.
+*/
+void TABLE::start_update() {
+  saved_timestamp_field_type= timestamp_field_type;
+  if ((timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) != 0)
+    timestamp_field->set_time();
+  timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+}
+
+/**
+   This member function is called by the handler right after a row in the
+   table is updated.
+*/
+void TABLE::end_update() {
+  timestamp_field_type= saved_timestamp_field_type;
+}
+
+
+/**
   Test if the order list consists of simple field expressions
 
   @param order                Linked list of ORDER BY arguments

=== modified file 'sql/table.h'
--- a/sql/table.h	2011-03-09 20:54:55 +0000
+++ b/sql/table.h	2011-03-24 10:23:22 +0000
@@ -931,6 +931,7 @@ private:
   TABLE *share_next, **share_prev;
 
   friend struct TABLE_share;
+  timestamp_auto_set_type saved_timestamp_field_type;
 
 public:
 
@@ -1174,6 +1175,12 @@ public:
   }
 
   bool update_const_key_parts(Item *conds);
+
+  void start_insert();
+  void end_insert();
+  void start_update();
+  void end_update();
+
 };
 
 

=== modified file 'storage/archive/ha_archive.cc'
--- a/storage/archive/ha_archive.cc	2011-03-22 11:44:40 +0000
+++ b/storage/archive/ha_archive.cc	2011-03-24 10:23:22 +0000
@@ -871,8 +871,6 @@ int ha_archive::write_row(uchar *buf)
     DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
   ha_statistic_increment(&SSV::ha_write_count);
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
-    table->timestamp_field->set_time();
   mysql_mutex_lock(&share->mutex);
 
   if (!share->archive_write_open)

=== modified file 'storage/csv/ha_tina.cc'
--- a/storage/csv/ha_tina.cc	2011-03-22 11:44:40 +0000
+++ b/storage/csv/ha_tina.cc	2011-03-24 10:23:22 +0000
@@ -986,9 +986,6 @@ int ha_tina::write_row(uchar * buf)
 
   ha_statistic_increment(&SSV::ha_write_count);
 
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
-    table->timestamp_field->set_time();
-
   size= encode_quote(buf);
 
   if (!share->tina_write_opened)
@@ -1037,8 +1034,8 @@ int ha_tina::open_update_temp_file_if_ne
 
 /*
   This is called for an update.
-  Make sure you put in code to increment the auto increment, also
-  update any timestamp data. Currently auto increment is not being
+  Make sure you put in code to increment the auto increment.
+  Currently auto increment is not being
   fixed since autoincrements have yet to be added to this table handler.
   This will be called in a table scan right before the previous ::rnd_next()
   call.
@@ -1051,9 +1048,6 @@ int ha_tina::update_row(const uchar * ol
 
   ha_statistic_increment(&SSV::ha_update_count);
 
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
-    table->timestamp_field->set_time();
-
   size= encode_quote(new_data);
 
   /*

=== modified file 'storage/example/ha_example.cc'
--- a/storage/example/ha_example.cc	2011-03-22 11:44:40 +0000
+++ b/storage/example/ha_example.cc	2011-03-24 10:23:22 +0000
@@ -365,9 +365,6 @@ int ha_example::close(void)
   ha_berekly.cc has an example of how to store it intact by "packing" it
   for ha_berkeley's own native storage type.
 
-  See the note for update_row() on auto_increments and timestamps. This
-  case also applies to write_row().
-
   Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
   sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
 
@@ -396,16 +393,6 @@ int ha_example::write_row(uchar *buf)
   Keep in mind that the server can do updates based on ordering if an ORDER BY
   clause was used. Consecutive ordering is not guaranteed.
 
-  @details
-  Currently new_data will not have an updated auto_increament record, or
-  and updated timestamp field. You can do these for example by doing:
-  @code
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
-    table->timestamp_field->set_time();
-  if (table->next_number_field && record == table->record[0])
-    update_auto_increment();
-  @endcode
-
   Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
 
   @see

=== modified file 'storage/federated/ha_federated.cc'
--- a/storage/federated/ha_federated.cc	2011-03-22 11:44:40 +0000
+++ b/storage/federated/ha_federated.cc	2011-03-24 10:23:22 +0000
@@ -1834,8 +1834,6 @@ int ha_federated::write_row(uchar *buf)
   values_string.length(0);
   insert_field_value_string.length(0);
   ha_statistic_increment(&SSV::ha_write_count);
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
-    table->timestamp_field->set_time();
 
   /*
     start both our field and field values strings
@@ -2108,12 +2106,12 @@ int ha_federated::repair(THD* thd, HA_CH
 
   Keep in mind that the server can do updates based on ordering if an ORDER BY
   clause was used. Consecutive ordering is not guaranteed.
-  Currently new_data will not have an updated auto_increament record, or
-  and updated timestamp field. You can do these for federated by doing these:
-  if (table->timestamp_on_update_now)
-    update_timestamp(new_row+table->timestamp_on_update_now-1);
-  if (table->next_number_field && record == table->record[0])
-    update_auto_increment();
+
+  Currently new_data will not have an updated AUTO_INCREMENT record. You can
+  do this for federated by doing the following:
+
+    if (table->next_number_field && record == table->record[0])
+      update_auto_increment();
 
   Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
 */

=== modified file 'storage/heap/ha_heap.cc'
--- a/storage/heap/ha_heap.cc	2011-03-22 11:44:40 +0000
+++ b/storage/heap/ha_heap.cc	2011-03-24 10:23:22 +0000
@@ -225,8 +225,7 @@ int ha_heap::write_row(uchar * buf)
 {
   int res;
   ha_statistic_increment(&SSV::ha_write_count);
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
-    table->timestamp_field->set_time();
+
   if (table->next_number_field && buf == table->record[0])
   {
     if ((res= update_auto_increment()))
@@ -249,8 +248,7 @@ int ha_heap::update_row(const uchar * ol
 {
   int res;
   ha_statistic_increment(&SSV::ha_update_count);
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
-    table->timestamp_field->set_time();
+
   res= heap_update(file,old_data,new_data);
   if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
               file->s->records)

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2011-03-22 11:44:40 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2011-03-24 10:23:22 +0000
@@ -5338,9 +5338,6 @@ ha_innobase::write_row(
 
 	ha_statistic_increment(&SSV::ha_write_count);
 
-	if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
-		table->timestamp_field->set_time();
-
 	sql_command = thd_sql_command(user_thd);
 
 	if ((sql_command == SQLCOM_ALTER_TABLE
@@ -5727,9 +5724,6 @@ ha_innobase::update_row(
 
 	ha_statistic_increment(&SSV::ha_update_count);
 
-	if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
-		table->timestamp_field->set_time();
-
 	if (prebuilt->upd_node) {
 		uvect = prebuilt->upd_node->update;
 	} else {

=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc	2011-03-22 11:44:40 +0000
+++ b/storage/myisam/ha_myisam.cc	2011-03-24 10:23:22 +0000
@@ -766,10 +766,6 @@ int ha_myisam::write_row(uchar *buf)
 {
   ha_statistic_increment(&SSV::ha_write_count);
 
-  /* If we have a timestamp column, update it to the current time */
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
-    table->timestamp_field->set_time();
-
   /*
     If we have an auto_increment column and we are writing a changed row
     or a new row, then update the auto_increment value in the record.
@@ -1532,8 +1528,6 @@ bool ha_myisam::is_crashed() const
 int ha_myisam::update_row(const uchar *old_data, uchar *new_data)
 {
   ha_statistic_increment(&SSV::ha_update_count);
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
-    table->timestamp_field->set_time();
   return mi_update(file,old_data,new_data);
 }
 

=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc	2011-03-22 11:44:40 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc	2011-03-24 10:23:22 +0000
@@ -1046,8 +1046,6 @@ int ha_myisammrg::write_row(uchar * buf)
   if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables)
     DBUG_RETURN(HA_ERR_TABLE_READONLY);
 
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
-    table->timestamp_field->set_time();
   if (table->next_number_field && buf == table->record[0])
   {
     int error;
@@ -1061,8 +1059,6 @@ int ha_myisammrg::update_row(const uchar
 {
   DBUG_ASSERT(this->file->children_attached);
   ha_statistic_increment(&SSV::ha_update_count);
-  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
-    table->timestamp_field->set_time();
   return myrg_update(file,old_data,new_data);
 }
 

=== modified file 'unittest/gunit/CMakeLists.txt'
--- a/unittest/gunit/CMakeLists.txt	2011-02-17 14:39:47 +0000
+++ b/unittest/gunit/CMakeLists.txt	2011-03-24 10:23:22 +0000
@@ -222,6 +222,7 @@ SET(TESTS
 # Add tests (link them with gunit library and the server libraries) 
 SET(SERVER_TESTS
   item
+  table
 )
 
 FOREACH(test ${TESTS})

=== added file 'unittest/gunit/table-t.cc'
--- a/unittest/gunit/table-t.cc	1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/table-t.cc	2011-03-24 10:23:22 +0000
@@ -0,0 +1,109 @@
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+// First include (the generated) my_config.h, to get correct platform defines,
+// then gtest.h (before any other MySQL headers), to avoid min() macros etc ...
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include "table.h"
+#include "field.h"
+
+namespace {
+
+class Mock_field_timestamp : public Field_timestamp
+{
+public:
+  bool set_time_called;
+  Mock_field_timestamp() : Field_timestamp(false, "mock", &my_charset_latin1),
+                           set_time_called(false) {}
+  void set_time() { set_time_called= true; }
+  void reset_mock() { set_time_called= false; }
+};
+
+
+TEST(TableTest, start_insert)
+{
+  TABLE table;
+  Mock_field_timestamp field;
+  table.timestamp_field= &field;
+
+  table.timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+  table.start_insert();
+  ASSERT_EQ(TIMESTAMP_NO_AUTO_SET, table.timestamp_field_type);
+  ASSERT_FALSE(field.set_time_called);
+
+  field.reset_mock();
+  table.timestamp_field_type= TIMESTAMP_AUTO_SET_ON_INSERT;
+  table.start_insert();
+  ASSERT_EQ(TIMESTAMP_NO_AUTO_SET, table.timestamp_field_type);
+  ASSERT_TRUE(field.set_time_called);
+  table.end_insert();
+  ASSERT_EQ(TIMESTAMP_AUTO_SET_ON_INSERT, table.timestamp_field_type);
+
+  field.reset_mock();
+  table.timestamp_field_type= TIMESTAMP_AUTO_SET_ON_UPDATE;
+  table.start_insert();
+  ASSERT_EQ(TIMESTAMP_NO_AUTO_SET, table.timestamp_field_type);
+  ASSERT_FALSE(field.set_time_called);
+  table.end_insert();
+  ASSERT_EQ(TIMESTAMP_AUTO_SET_ON_UPDATE, table.timestamp_field_type);
+
+  field.reset_mock();
+  table.timestamp_field_type= TIMESTAMP_AUTO_SET_ON_BOTH;
+  table.start_insert();
+  ASSERT_EQ(TIMESTAMP_NO_AUTO_SET, table.timestamp_field_type);
+  ASSERT_TRUE(field.set_time_called);
+  table.end_insert();
+  ASSERT_EQ(TIMESTAMP_AUTO_SET_ON_BOTH, table.timestamp_field_type);
+}
+
+TEST(TableTest, start_update)
+{
+  TABLE table;
+  Mock_field_timestamp field;
+  table.timestamp_field= &field;
+
+  table.timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+  table.start_update();
+  ASSERT_EQ(TIMESTAMP_NO_AUTO_SET, table.timestamp_field_type);
+  ASSERT_FALSE(field.set_time_called);
+
+  field.reset_mock();
+  table.timestamp_field_type= TIMESTAMP_AUTO_SET_ON_INSERT;
+  table.start_update();
+  ASSERT_EQ(TIMESTAMP_NO_AUTO_SET, table.timestamp_field_type);
+  ASSERT_FALSE(field.set_time_called);
+  table.end_update();
+  ASSERT_EQ(TIMESTAMP_AUTO_SET_ON_INSERT, table.timestamp_field_type);
+
+  field.reset_mock();
+  table.timestamp_field_type= TIMESTAMP_AUTO_SET_ON_UPDATE;
+  table.start_update();
+  ASSERT_EQ(TIMESTAMP_NO_AUTO_SET, table.timestamp_field_type);
+  ASSERT_TRUE(field.set_time_called);
+  table.end_update();
+  ASSERT_EQ(TIMESTAMP_AUTO_SET_ON_UPDATE, table.timestamp_field_type);
+
+  field.reset_mock();
+  table.timestamp_field_type= TIMESTAMP_AUTO_SET_ON_BOTH;
+  table.start_update();
+  ASSERT_EQ(TIMESTAMP_NO_AUTO_SET, table.timestamp_field_type);
+  ASSERT_TRUE(field.set_time_called);
+  table.end_update();
+  ASSERT_EQ(TIMESTAMP_AUTO_SET_ON_BOTH, table.timestamp_field_type);
+}
+
+}


Attachment: [text/bzr-bundle] bzr/martin.hansson@oracle.com-20110324102322-zads1x9usovg2rla.bundle
Thread
bzr commit into mysql-trunk branch (martin.hansson:3318) Martin Hansson24 Mar