From c89ddfdf15a98da3ce95bd8ca69e70fbfcba1c43 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Feb 2006 12:19:00 -0800 Subject: [PATCH] Bug #14526: Partitions: indexed searches fail. When inserting a row into a partitioned table, the value of auto_increment fields was not calculated until after deciding what partition to add the row into, which led to rows being written to the wrong partitions (or spurious errors). mysql-test/r/partition.result: Add new results mysql-test/t/partition.test: Add new regression test sql/ha_partition.cc: Fix notes about, and handling of, auto_increment in ha_partition::write_row(). We have to decide on an auto_increment value before we can figure out which partition the rows should be inserted into. --- mysql-test/r/partition.result | 18 ++++++++++++++++++ mysql-test/t/partition.test | 12 ++++++++++++ sql/ha_partition.cc | 24 +++++++++++++----------- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index e2601937da6..6fa5590d989 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -312,4 +312,22 @@ partition by hash(f_int1) partitions 2; insert into t1 values (1,1),(2,2); replace into t1 values (1,1),(2,2); drop table t1; +create table t2 (s1 int not null auto_increment, primary key (s1)) partition by list (s1) (partition p1 values in (1),partition p2 values in (2),partition p3 values in (3),partition p4 values in (4)); +insert into t2 values (null),(null),(null); +select * from t2; +s1 +1 +2 +3 +select * from t2 where s1 < 2; +s1 +1 +update t2 set s1 = s1 + 1 order by s1 desc; +select * from t2 where s1 < 3; +s1 +2 +select * from t2 where s1 = 2; +s1 +2 +drop table t2; End of 5.1 tests diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index ded54ad28b4..ebd3cc9a249 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -401,4 +401,16 @@ insert into t1 values (1,1),(2,2); replace into t1 values (1,1),(2,2); drop table t1; +# +# Bug #14526: Partitions: indexed searches fail +# +create table t2 (s1 int not null auto_increment, primary key (s1)) partition by list (s1) (partition p1 values in (1),partition p2 values in (2),partition p3 values in (3),partition p4 values in (4)); +insert into t2 values (null),(null),(null); +select * from t2; +select * from t2 where s1 < 2; +update t2 set s1 = s1 + 1 order by s1 desc; +select * from t2 where s1 < 3; +select * from t2 where s1 = 2; +drop table t2; + --echo End of 5.1 tests diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 1897886ce45..143747dc150 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2600,22 +2600,13 @@ void ha_partition::unlock_row() ha_berkeley.cc has a variant 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 applied 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. ADDITIONAL INFO: - Most handlers set timestamp when calling write row if any such fields - exists. Since we are calling an underlying handler we assume theŽ - underlying handler will assume this responsibility. - - Underlying handlers will also call update_auto_increment to calculate - the new auto increment value. We will catch the call to - get_auto_increment and ensure this increment value is maintained by - only one of the underlying handlers. + 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(byte * buf) @@ -2629,6 +2620,17 @@ int ha_partition::write_row(byte * buf) 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(); + + /* + 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. + */ + if (table->next_number_field && buf == table->record[0]) + update_auto_increment(); + #ifdef NOT_NEEDED if (likely(buf == rec0)) #endif