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
parent 84159db8
...@@ -1291,4 +1291,9 @@ t1 CREATE TABLE `t1` ( ...@@ -1291,4 +1291,9 @@ t1 CREATE TABLE `t1` (
`b` int(11) DEFAULT NULL `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) */ ) 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; 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 End of 5.1 tests
...@@ -1528,4 +1528,25 @@ PARTITION BY RANGE (b) ( ...@@ -1528,4 +1528,25 @@ PARTITION BY RANGE (b) (
show create table t1; show create table t1;
drop table t1, t2; 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 --echo End of 5.1 tests
...@@ -2783,16 +2783,28 @@ exit: ...@@ -2783,16 +2783,28 @@ exit:
int ha_partition::update_row(const uchar *old_data, uchar *new_data) int ha_partition::update_row(const uchar *old_data, uchar *new_data)
{ {
uint32 new_part_id, old_part_id; uint32 new_part_id, old_part_id;
int error; int error= 0;
longlong func_value; longlong func_value;
timestamp_auto_set_type orig_timestamp_type= table->timestamp_field_type;
DBUG_ENTER("ha_partition::update_row"); 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], if ((error= get_parts_for_update(old_data, new_data, table->record[0],
m_part_info, &old_part_id, &new_part_id, m_part_info, &old_part_id, &new_part_id,
&func_value))) &func_value)))
{ {
m_part_info->err_value= 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) ...@@ -2804,23 +2816,27 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data)
if (new_part_id == old_part_id) if (new_part_id == old_part_id)
{ {
DBUG_PRINT("info", ("Update in partition %d", new_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 else
{ {
DBUG_PRINT("info", ("Update from partition %d to partition %d", DBUG_PRINT("info", ("Update from partition %d to partition %d",
old_part_id, new_part_id)); old_part_id, new_part_id));
if ((error= m_file[new_part_id]->write_row(new_data))) 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))) if ((error= m_file[old_part_id]->delete_row(old_data)))
{ {
#ifdef IN_THE_FUTURE #ifdef IN_THE_FUTURE
(void) m_file[new_part_id]->delete_last_inserted_row(new_data); (void) m_file[new_part_id]->delete_last_inserted_row(new_data);
#endif #endif
DBUG_RETURN(error); goto exit;
} }
} }
DBUG_RETURN(0);
exit:
table->timestamp_field_type= orig_timestamp_type;
DBUG_RETURN(error);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment