diff options
author | unknown <holyfoot/hf@mysql.com/hfmain.(none)> | 2007-11-12 21:11:31 +0400 |
---|---|---|
committer | unknown <holyfoot/hf@mysql.com/hfmain.(none)> | 2007-11-12 21:11:31 +0400 |
commit | 81d83c1c73df68648b55014d35f68746531084d4 (patch) | |
tree | ed73a583276c2f1abaf128909d01e69d8bf761ef | |
parent | b61146e1f6cb24ecf6b56a199abb13be5e4e7a8e (diff) | |
download | mariadb-git-81d83c1c73df68648b55014d35f68746531084d4.tar.gz |
Bug #32067 Partitions: crash with timestamp column.
Partition handler fails updating tables with partitioning
based on timestamp field, as it calculates the timestamp field
AFTER it calculates the number of partition of a record.
Fixed by adding timestamp_field->set_time() call and disabling
such consequent calls
mysql-test/r/partition.result:
Bug #32067 Partitions: crash with timestamp column.
test result
mysql-test/t/partition.test:
Bug #32067 Partitions: crash with timestamp column.
test case
sql/ha_partition.cc:
Bug #32067 Partitions: crash with timestamp column.
do timestamp_field->set_time() in the ha_partition::update_row()
-rw-r--r-- | mysql-test/r/partition.result | 5 | ||||
-rw-r--r-- | mysql-test/t/partition.test | 21 | ||||
-rw-r--r-- | sql/ha_partition.cc | 28 |
3 files changed, 48 insertions, 6 deletions
diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 4e4bd0bbc0a..b3a498ff0ab 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1291,4 +1291,9 @@ t1 CREATE TABLE `t1` ( `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (b) (PARTITION p1 VALUES LESS THAN (10) ENGINE = MyISAM, PARTITION p2 VALUES LESS THAN (20) ENGINE = MyISAM) */ drop table t1, t2; +create table t1 +(s1 timestamp on update current_timestamp, s2 int) +partition by key(s1) partitions 3; +insert into t1 values (null,null); +drop table t1; End of 5.1 tests diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 2906b4640cd..524862af135 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1528,4 +1528,25 @@ PARTITION BY RANGE (b) ( show create table t1; drop table t1, t2; +# +# Bug #32067 Partitions: crash with timestamp column +# this bug occurs randomly on some UPDATE statement +# with the '1032: Can't find record in 't1'' error + +create table t1 + (s1 timestamp on update current_timestamp, s2 int) + partition by key(s1) partitions 3; + +insert into t1 values (null,null); +--disable_query_log +let $cnt= 1000; +while ($cnt) +{ + update t1 set s2 = 1; + update t1 set s2 = 2; + dec $cnt; +} +--enable_query_log + +drop table t1; --echo End of 5.1 tests diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 8afaab71160..a7638f5a357 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2783,16 +2783,28 @@ exit: int ha_partition::update_row(const uchar *old_data, uchar *new_data) { uint32 new_part_id, old_part_id; - int error; + 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))) { m_part_info->err_value= func_value; - DBUG_RETURN(error); + goto exit; } /* @@ -2804,23 +2816,27 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data) if (new_part_id == old_part_id) { DBUG_PRINT("info", ("Update in partition %d", new_part_id)); - DBUG_RETURN(m_file[new_part_id]->update_row(old_data, new_data)); + error= m_file[new_part_id]->update_row(old_data, new_data); + goto exit; } else { DBUG_PRINT("info", ("Update from partition %d to partition %d", old_part_id, new_part_id)); if ((error= m_file[new_part_id]->write_row(new_data))) - DBUG_RETURN(error); + goto exit; if ((error= m_file[old_part_id]->delete_row(old_data))) { #ifdef IN_THE_FUTURE (void) m_file[new_part_id]->delete_last_inserted_row(new_data); #endif - DBUG_RETURN(error); + goto exit; } } - DBUG_RETURN(0); + +exit: + table->timestamp_field_type= orig_timestamp_type; + DBUG_RETURN(error); } |