From 7e764ae188efe3f866222eb393513bf30e2b75ab Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Wed, 13 Sep 2017 10:57:23 +0300 Subject: [PATCH] SQL: 1-row partition rotation fix [fixes #260] --- include/my_base.h | 4 ++++ .../suite/versioning/r/partition.result | 6 +++++ mysql-test/suite/versioning/t/partition.test | 8 +++++++ sql/ha_partition.cc | 15 +++++++------ sql/ha_partition.h | 2 +- sql/sql_partition.cc | 22 ++++++++++++++----- storage/innobase/handler/ha_innodb.cc | 4 ++-- 7 files changed, 46 insertions(+), 15 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index ea8fd623b28..a9591fccf40 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -407,6 +407,10 @@ enum ha_base_keytype { when only HA_STATUS_VARIABLE but it won't be used. */ #define HA_STATUS_VARIABLE_EXTRA 128U +/* + Treat empty table as empty (ignore HA_STATUS_TIME hack). +*/ +#define HA_STATUS_OPEN 256U /* Errorcodes given by handler functions diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index 2a42545755b..ad9ecdfccbf 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -159,6 +159,12 @@ x 2 create or replace table t1 (x int) with system versioning +partition by system_time limit 1 ( +partition p0 versioning, +partition pn as of now); +alter table t1 change x big int; +create or replace table t1 (x int) +with system versioning partition by system_time ( partition p0 versioning, partition pn as of now); diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index cbc02d44e31..479b63399bf 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -89,6 +89,14 @@ alter table t1 drop partition p0; select x from t1; +# Bug #260: incorrect IB partitioning warning +create or replace table t1 (x int) +with system versioning +partition by system_time limit 1 ( + partition p0 versioning, + partition pn as of now); +alter table t1 change x big int; + # insert, delete, update create or replace table t1 (x int) with system versioning diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 68fffa24a02..efdbf6f7e18 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3550,7 +3550,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) m_part_info->part_expr->get_monotonicity_info(); else if (m_part_info->list_of_part_fields) m_part_func_monotonicity_info= MONOTONIC_STRICT_INCREASING; - info(HA_STATUS_VARIABLE | HA_STATUS_CONST); + info(HA_STATUS_OPEN | HA_STATUS_VARIABLE | HA_STATUS_CONST); DBUG_RETURN(0); err_handler: @@ -6550,6 +6550,7 @@ int ha_partition::info(uint flag) { uint no_lock_flag= flag & HA_STATUS_NO_LOCK; uint extra_var_flag= flag & HA_STATUS_VARIABLE_EXTRA; + uint open_flag= flag & HA_STATUS_OPEN; DBUG_ENTER("ha_partition::info"); #ifndef DBUG_OFF @@ -6590,7 +6591,7 @@ int ha_partition::info(uint flag) do { file= *file_array; - file->info(HA_STATUS_AUTO | no_lock_flag); + file->info(HA_STATUS_AUTO | no_lock_flag | open_flag); set_if_bigger(auto_increment_value, file->stats.auto_increment_value); } while (*(++file_array)); @@ -6644,7 +6645,7 @@ int ha_partition::info(uint flag) i= bitmap_get_next_set(&m_part_info->read_partitions, i)) { file= m_file[i]; - file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag); + file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag | open_flag); stats.records+= file->stats.records; stats.deleted+= file->stats.deleted; stats.data_file_length+= file->stats.data_file_length; @@ -6725,7 +6726,7 @@ int ha_partition::info(uint flag) if (!(flag & HA_STATUS_VARIABLE) || !bitmap_is_set(&(m_part_info->read_partitions), (file_array - m_file))) - file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag); + file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag | open_flag); if (file->stats.records > max_records) { max_records= file->stats.records; @@ -6744,7 +6745,7 @@ int ha_partition::info(uint flag) this); file= m_file[handler_instance]; - file->info(HA_STATUS_CONST | no_lock_flag); + file->info(HA_STATUS_CONST | no_lock_flag | open_flag); stats.block_size= file->stats.block_size; stats.create_time= file->stats.create_time; ref_length= m_ref_length; @@ -6760,7 +6761,7 @@ int ha_partition::info(uint flag) Note: all engines does not support HA_STATUS_ERRKEY, so set errkey. */ file->errkey= errkey; - file->info(HA_STATUS_ERRKEY | no_lock_flag); + file->info(HA_STATUS_ERRKEY | no_lock_flag | open_flag); errkey= file->errkey; } if (flag & HA_STATUS_TIME) @@ -6777,7 +6778,7 @@ int ha_partition::info(uint flag) do { file= *file_array; - file->info(HA_STATUS_TIME | no_lock_flag); + file->info(HA_STATUS_TIME | no_lock_flag | open_flag); if (file->stats.update_time > stats.update_time) stats.update_time= file->stats.update_time; } while (*(++file_array)); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 0eb96aa2d00..df5a3544a30 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1368,7 +1368,7 @@ public: { handler *file= m_file[part_id]; DBUG_ASSERT(bitmap_is_set(&(m_part_info->read_partitions), part_id)); - file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); + file->info(HA_STATUS_OPEN | HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); part_recs+= file->stats.records; } return part_recs; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 08ba4d84d9b..051249db997 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -3426,11 +3426,21 @@ int vers_get_partition_id(partition_info *part_info, DBUG_ASSERT(part_info); Field *sys_trx_end= part_info->part_field_array[STAT_TRX_END]; DBUG_ASSERT(sys_trx_end); - DBUG_ASSERT(part_info->table); + TABLE *table= part_info->table; + DBUG_ASSERT(table); Vers_part_info *vers_info= part_info->vers_info; - DBUG_ASSERT(vers_info && vers_info->initialized()); - DBUG_ASSERT(sys_trx_end->table == part_info->table && part_info->table->versioned()); - DBUG_ASSERT(part_info->table->vers_end_field() == sys_trx_end); + DBUG_ASSERT(vers_info); + DBUG_ASSERT(vers_info->initialized()); + DBUG_ASSERT(sys_trx_end->table == table); + bool tmp_off= false; + if (!table->versioned() && table->file->native_versioned()) + { + // in copy_data_between_tables() versioning may be temporarily turned off + tmp_off= true; + table->s->versioned= true; + } + DBUG_ASSERT(table->versioned()); + DBUG_ASSERT(table->vers_end_field() == sys_trx_end); // new rows have NULL in sys_trx_end if (sys_trx_end->is_max() || sys_trx_end->is_null()) @@ -3440,7 +3450,6 @@ int vers_get_partition_id(partition_info *part_info, else // row is historical { THD *thd= current_thd; - TABLE *table= part_info->table; switch (thd->lex->sql_command) { @@ -3478,6 +3487,9 @@ int vers_get_partition_id(partition_info *part_info, *part_id= vers_info->hist_part->id; } + if (tmp_off) + table->s->versioned= false; + DBUG_PRINT("exit",("partition: %d", *part_id)); DBUG_RETURN(0); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index d4b5b89ac30..2a34ee85922 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6862,7 +6862,7 @@ ha_innobase::open( } } - info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); + info(HA_STATUS_OPEN | HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); DBUG_RETURN(0); } @@ -14958,7 +14958,7 @@ ha_innobase::info_low( set. That way SHOW TABLE STATUS will show the best estimate, while the optimizer never sees the table empty. */ - if (n_rows == 0 && !(flag & HA_STATUS_TIME)) { + if (n_rows == 0 && !(flag & (HA_STATUS_TIME | HA_STATUS_OPEN))) { n_rows++; }