summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <holyfoot/hf@mysql.com/hfmain.(none)>2007-11-12 21:11:31 +0400
committerunknown <holyfoot/hf@mysql.com/hfmain.(none)>2007-11-12 21:11:31 +0400
commit81d83c1c73df68648b55014d35f68746531084d4 (patch)
treeed73a583276c2f1abaf128909d01e69d8bf761ef
parentb61146e1f6cb24ecf6b56a199abb13be5e4e7a8e (diff)
downloadmariadb-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.result5
-rw-r--r--mysql-test/t/partition.test21
-rw-r--r--sql/ha_partition.cc28
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);
}