diff --git a/mysql-test/main/partition_innodb.result b/mysql-test/main/partition_innodb.result index f3d24347ff9..5c63fcfbbc9 100644 --- a/mysql-test/main/partition_innodb.result +++ b/mysql-test/main/partition_innodb.result @@ -1028,5 +1028,29 @@ COUNT(*) 2 DROP TABLE t1; # +# MDEV-18244 Server crashes in ha_innobase::update_thd / ... / ha_partition::update_next_auto_inc_val +# +CREATE TABLE t1 (a INT) +ENGINE=InnoDB +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (6), +PARTITION pn VALUES LESS THAN MAXVALUE +); +INSERT INTO t1 VALUES (4),(5),(6); +ALTER TABLE t1 MODIFY a INT AUTO_INCREMENT PRIMARY KEY; +UPDATE t1 PARTITION (p0) SET a = 3 WHERE a = 5; +INSERT INTO t1 PARTITION(p0) VALUES (); +ERROR HY000: Found a row not matching the given partition set +INSERT INTO t1 PARTITION(p0) VALUES (-1); +INSERT INTO t1 VALUES (); +SELECT * FROM t1; +a +-1 +1 +3 +4 +6 +DROP TABLE t1; +# # End of 10.3 tests # diff --git a/mysql-test/main/partition_innodb.test b/mysql-test/main/partition_innodb.test index 629bc29e758..f7ce9b03a54 100644 --- a/mysql-test/main/partition_innodb.test +++ b/mysql-test/main/partition_innodb.test @@ -1105,6 +1105,26 @@ INSERT INTO t1 VALUES (1, 7, 8, 9), (2, NULL, NULL, NULL), (3, NULL, NULL, NULL) SELECT COUNT(*) FROM t1 WHERE x IS NULL AND y IS NULL AND z IS NULL; DROP TABLE t1; +--echo # +--echo # MDEV-18244 Server crashes in ha_innobase::update_thd / ... / ha_partition::update_next_auto_inc_val +--echo # + +CREATE TABLE t1 (a INT) + ENGINE=InnoDB + PARTITION BY RANGE (a) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION pn VALUES LESS THAN MAXVALUE + ); +INSERT INTO t1 VALUES (4),(5),(6); +ALTER TABLE t1 MODIFY a INT AUTO_INCREMENT PRIMARY KEY; +UPDATE t1 PARTITION (p0) SET a = 3 WHERE a = 5; +--error ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET +INSERT INTO t1 PARTITION(p0) VALUES (); +INSERT INTO t1 PARTITION(p0) VALUES (-1); +INSERT INTO t1 VALUES (); +SELECT * FROM t1; +DROP TABLE t1; + --echo # --echo # End of 10.3 tests --echo # diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 5a78249644d..ccda01de6b7 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3459,8 +3459,7 @@ bool ha_partition::init_partition_bitmaps() /* Open handler object - - SYNOPSIS +SYNOPSIS open() name Full path of table name mode Open mode flags @@ -3586,6 +3585,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) } else { + check_insert_autoincrement(); if (unlikely((error= open_read_partitions(name_buff, sizeof(name_buff))))) goto err_handler; m_num_locks= m_file_sample->lock_count(); @@ -4472,11 +4472,8 @@ exit: table->found_next_number_field->field_index)) { update_next_auto_inc_val(); - /* - The following call is safe as part_share->auto_inc_initialized - (tested in the call) is guaranteed to be set for update statements. - */ - set_auto_increment_if_higher(table->found_next_number_field); + if (part_share->auto_inc_initialized) + set_auto_increment_if_higher(table->found_next_number_field); } DBUG_RETURN(error); } @@ -8144,6 +8141,7 @@ int ha_partition::info(uint flag) if (flag & HA_STATUS_AUTO) { bool auto_inc_is_first_in_idx= (table_share->next_number_keypart == 0); + bool all_parts_opened= true; DBUG_PRINT("info", ("HA_STATUS_AUTO")); if (!table->found_next_number_field) stats.auto_increment_value= 0; @@ -8174,6 +8172,15 @@ int ha_partition::info(uint flag) ("checking all partitions for auto_increment_value")); do { + if (!bitmap_is_set(&m_opened_partitions, (uint)(file_array - m_file))) + { + /* + Some partitions aren't opened. + So we can't calculate the autoincrement. + */ + all_parts_opened= false; + break; + } file= *file_array; file->info(HA_STATUS_AUTO | no_lock_flag); set_if_bigger(auto_increment_value, @@ -8182,7 +8189,7 @@ int ha_partition::info(uint flag) DBUG_ASSERT(auto_increment_value); stats.auto_increment_value= auto_increment_value; - if (auto_inc_is_first_in_idx) + if (all_parts_opened && auto_inc_is_first_in_idx) { set_if_bigger(part_share->next_auto_inc_val, auto_increment_value); @@ -8485,6 +8492,7 @@ int ha_partition::change_partitions_to_open(List *partition_names) return 0; } + check_insert_autoincrement(); if (bitmap_cmp(&m_opened_partitions, &m_part_info->read_partitions) != 0) return 0; diff --git a/sql/ha_partition.h b/sql/ha_partition.h index d48947822b9..1085eca72cc 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1329,6 +1329,19 @@ private: unlock_auto_increment(); } + void check_insert_autoincrement() + { + /* + If we INSERT into the table having the AUTO_INCREMENT column, + we have to read all partitions for the next autoincrement value + unless we already did it. + */ + if (!part_share->auto_inc_initialized && + ha_thd()->lex->sql_command == SQLCOM_INSERT && + table->found_next_number_field) + bitmap_set_all(&m_part_info->read_partitions); + } + public: /*