From: Date: July 27 2008 3:10pm Subject: bzr commit into mysql-5.1 branch (holyfoot:2680) Bug#38272 List-Archive: http://lists.mysql.com/commits/50573 X-Bug: 38272 Message-Id: <20080727131034.492212C380B7@hfmain.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///home/hf/work/mysql_common/38272/ 2680 Alexey Botchkov 2008-07-27 Bug#38272 timestamps fields incorrectly defaulted on update accross partitions. It's not Innodb-specific bug. ha_partition::update_row() didn't set table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET when orig_timestamp_type == TIMESTAMP_AUTO_SET_ON_INSERT. So that a partition sets the timestamp field when a record is moved to a different partition. Fixed by doing '= TIMESTAMP_NO_AUTO_SET' unconditionally. Also ha_partition::write_row() is fixed in same way as now Field_timestamp::set() is called twice in SET_ON_INSERT case. per-file messages: mysql-test/r/partition.result Bug#38272 timestamps fields incorrectly defaulted on update accross partitions. test result mysql-test/t/partition.test Bug#38272 timestamps fields incorrectly defaulted on update accross partitions. test case sql/ha_partition.cc Bug#38272 timestamps fields incorrectly defaulted on update accross partitions. Do table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET unconditionally in ha_partition::update_row and ::write_row() modified: mysql-test/r/partition.result mysql-test/t/partition.test sql/ha_partition.cc === modified file 'mysql-test/r/partition.result' --- a/mysql-test/r/partition.result 2008-07-07 20:42:19 +0000 +++ b/mysql-test/r/partition.result 2008-07-27 13:01:35 +0000 @@ -1604,4 +1604,29 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=16 DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (id) SUBPARTITION BY HASH (id) SUBPARTITIONS 2 (PARTITION pa1 VALUES LESS THAN (10) ENGINE = MyISAM, PARTITION pa2 VALUES LESS THAN (20) ENGINE = MyISAM, PARTITION pa11 VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */ drop table t1; +CREATE TABLE t1 ( +`ID` bigint(20) NOT NULL AUTO_INCREMENT, +`createdDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +`number` int, +PRIMARY KEY (`ID`, number) +) +PARTITION BY RANGE (number) ( +PARTITION p0 VALUES LESS THAN (6), +PARTITION p1 VALUES LESS THAN (11) +); +create table t2 ( +`ID` bigint(20), +`createdDate` TIMESTAMP, +`number` int +); +INSERT INTO t1 SET number=1; +insert into t2 select * from t1; +SELECT SLEEP(1); +SLEEP(1) +0 +UPDATE t1 SET number=6; +select count(*) from t1, t2 where t1.createdDate = t2.createdDate; +count(*) +1 +drop table t1, t2; End of 5.1 tests === modified file 'mysql-test/t/partition.test' --- a/mysql-test/t/partition.test 2008-06-17 10:41:06 +0000 +++ b/mysql-test/t/partition.test 2008-07-27 13:01:35 +0000 @@ -1767,4 +1767,34 @@ while ($n) --enable_query_log show create table t1; drop table t1; + +# +# Bug #38272 timestamps fields incorrectly defaulted on update accross partitions. +# + +CREATE TABLE t1 ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `createdDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `number` int, + PRIMARY KEY (`ID`, number) +) +PARTITION BY RANGE (number) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11) +); + +create table t2 ( + `ID` bigint(20), + `createdDate` TIMESTAMP, + `number` int +); + +INSERT INTO t1 SET number=1; +insert into t2 select * from t1; +SELECT SLEEP(1); +UPDATE t1 SET number=6; +select count(*) from t1, t2 where t1.createdDate = t2.createdDate; + +drop table t1, t2; + --echo End of 5.1 tests === modified file 'sql/ha_partition.cc' --- a/sql/ha_partition.cc 2008-07-07 20:42:19 +0000 +++ b/sql/ha_partition.cc 2008-07-27 13:01:35 +0000 @@ -2724,6 +2724,7 @@ int ha_partition::write_row(uchar * buf) bool autoincrement_lock= FALSE; my_bitmap_map *old_map; THD *thd= ha_thd(); + timestamp_auto_set_type orig_timestamp_type= table->timestamp_field_type; #ifdef NOT_NEEDED uchar *rec0= m_rec0; #endif @@ -2733,6 +2734,7 @@ int ha_partition::write_row(uchar * buf) /* 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 @@ -2799,6 +2801,7 @@ int ha_partition::write_row(uchar * buf) error= m_file[part_id]->ha_write_row(buf); reenable_binlog(thd); exit: + table->timestamp_field_type= orig_timestamp_type; if (autoincrement_lock) pthread_mutex_unlock(&table_share->mutex); DBUG_RETURN(error); @@ -2851,10 +2854,8 @@ int ha_partition::update_row(const uchar 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; - } + 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,