diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index da851791640..b029efa7479 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -569,6 +569,13 @@ delete from t1; Warnings: Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions unlock tables; +# +# MDEV-20336 Assertion bitmap_is_set(read_partitions) upon SELECT FOR UPDATE from versioned table +# +create or replace table t1 (pk int primary key) with system versioning partition by system_time limit 100 (partition p1 history, partition pn current); +execute immediate 'select * from t1 for update'; +pk +drop table t1; # Test cleanup drop database test; create database test; diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index f602c49d7c1..a3feadee1b5 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -529,6 +529,13 @@ delete from t1 where x < 3; delete from t1; unlock tables; +--echo # +--echo # MDEV-20336 Assertion bitmap_is_set(read_partitions) upon SELECT FOR UPDATE from versioned table +--echo # +create or replace table t1 (pk int primary key) with system versioning partition by system_time limit 100 (partition p1 history, partition pn current); +execute immediate 'select * from t1 for update'; +drop table t1; + --echo # Test cleanup drop database test; create database test; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 125669a403d..aa630e83ba0 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3951,7 +3951,12 @@ int ha_partition::external_lock(THD *thd, int lock_type) { if (m_part_info->part_expr) m_part_info->part_expr->walk(&Item::register_field_in_read_map, 1, 0); - if (m_part_info->part_type == VERSIONING_PARTITION) + if (m_part_info->part_type == VERSIONING_PARTITION && + /* TODO: MDEV-20345 exclude more inapproriate commands like INSERT + These commands may be excluded because working history partition is needed + only for versioned DML. */ + thd->lex->sql_command != SQLCOM_SELECT && + thd->lex->sql_command != SQLCOM_INSERT_SELECT) m_part_info->vers_set_hist_part(thd); } DBUG_RETURN(0); @@ -4104,7 +4109,10 @@ int ha_partition::start_stmt(THD *thd, thr_lock_type lock_type) case TL_WRITE_ONLY: if (m_part_info->part_expr) m_part_info->part_expr->walk(&Item::register_field_in_read_map, 1, 0); - if (m_part_info->part_type == VERSIONING_PARTITION) + if (m_part_info->part_type == VERSIONING_PARTITION && + // TODO: MDEV-20345 (see above) + thd->lex->sql_command != SQLCOM_SELECT && + thd->lex->sql_command != SQLCOM_INSERT_SELECT) m_part_info->vers_set_hist_part(thd); default:; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 33ff0bc70cc..2d6a843f7ad 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -816,7 +816,10 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) else vers_conditions.init(SYSTEM_TIME_ALL); } - else if (!vers_conditions.is_set()) + else if (!vers_conditions.is_set() && + /* We cannot optimize REPLACE .. SELECT because it may need + to call vers_set_hist_part() to update history. */ + thd->lex->sql_command != SQLCOM_REPLACE_SELECT) { table->partition_names= newx List; String *s= newx String(vers_info->now_part->partition_name,