From 6e617f0f432c91a7fe7e926b272a34c6fc9ff95d Mon Sep 17 00:00:00 2001 From: girihimanshu540-prog Date: Tue, 3 Nov 2026 09:12:46 +0530 Subject: [PATCH 1/3] MDEV-41989: Fix duplicate key error code on cross-partition update Move saved_last_part declaration to top of function to prevent crosses-initialization compile errors on jump to exit. --- mysql-test/suite/parts/t/mdev_41989.test | 5 +++ sql/ha_partition.cc | 44 ++++++++++++------------ sql/ha_partition.h | 1 + sql/opt_context_store_replay.cc | 2 +- 4 files changed, 29 insertions(+), 23 deletions(-) create mode 100644 mysql-test/suite/parts/t/mdev_41989.test diff --git a/mysql-test/suite/parts/t/mdev_41989.test b/mysql-test/suite/parts/t/mdev_41989.test new file mode 100644 index 0000000000000..140b3b955b9ea --- /dev/null +++ b/mysql-test/suite/parts/t/mdev_41989.test @@ -0,0 +1,5 @@ +CREATE TABLE t1 (id INT PRIMARY KEY, a INT) ENGINE=MyISAM PARTITION BY HASH (id) PARTITIONS 2; +INSERT INTO t1 VALUES (1, 1), (2, 2); +--error ER_DUP_ENTRY +UPDATE t1 SET id = 2 WHERE id = 1; +DROP TABLE t1; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 3afd8f396e58d..0eb681b986a31 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -431,6 +431,7 @@ void ha_partition::init_handler_variables() m_top_entry= NO_CURRENT_PART_ID; m_rec_length= 0; m_last_part= 0; + m_err_part= NO_CURRENT_PART_ID; m_err_rec= NULL; m_curr_key_info[0]= NULL; m_curr_key_info[1]= NULL; @@ -4696,33 +4697,32 @@ int ha_partition::update_row(const uchar *old_data, const uchar *new_data) Notice that HA_READ_BEFORE_WRITE_REMOVAL does not require this protocol, so this is not supported for this engine. */ - { - Abort_on_warning_instant_set old_abort_on_warning(thd, 0); - error= get_part_for_buf(old_data, table->record[0], m_part_info, &old_part_id); - } - DBUG_ASSERT(!error); - DBUG_ASSERT(old_part_id == m_last_part); - DBUG_ASSERT(bitmap_is_set(&(m_part_info->read_partitions), old_part_id)); -#endif - - if (unlikely((error= get_part_for_buf(new_data, table->record[0], - m_part_info, &new_part_id)))) - goto exit; - if (unlikely(!bitmap_is_set(&(m_part_info->lock_partitions), new_part_id))) - { - error= HA_ERR_NOT_IN_LOCK_PARTITIONS; - goto exit; - } - - - start_part_bulk_insert(thd, new_part_id); - DBUG_ASSERT(!m_file[new_part_id]->row_logging); - if (new_part_id == old_part_id) +{ + uint32 saved_last_part; + + Abort_on_warning_instant_set old_abort_on_warning(thd, 0); + + if (unlikely((error= get_part_for_buf(new_data, table->record[0], + m_part_info, &new_part_id)))) + goto exit; + if (unlikely(!bitmap_is_set(&(m_part_info->lock_partitions), new_part_id))) + { + error= HA_ERR_NOT_IN_LOCK_PARTITIONS; + goto exit; + } + + saved_last_part = m_last_part; + start_part_bulk_insert(thd, new_part_id); + DBUG_ASSERT(m_file[new_part_id]->row_logging); + if (new_part_id != old_part_id) { DBUG_PRINT("info", ("Update in partition %u", (uint) new_part_id)); error= m_file[new_part_id]->ha_update_row(old_data, new_data); + if (error) + m_last_part= saved_last_part; goto exit; } + else { Field *saved_next_number_field= table->next_number_field; diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 943f5e4279c09..07ad94d12bd83 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -359,6 +359,7 @@ class ha_partition final :public handler uint m_tot_parts; // Total number of partitions; uint m_num_locks; // For engines like ha_blackhole, which needs no locks uint m_last_part; // Last file that we update,write,read + uint m_err_part; // Partition where last error occurred part_id_range m_part_spec; // Which parts to scan uint m_scan_value; // Value passed in rnd_init // call diff --git a/sql/opt_context_store_replay.cc b/sql/opt_context_store_replay.cc index 4bea88970c6b9..f5228532ce226 100644 --- a/sql/opt_context_store_replay.cc +++ b/sql/opt_context_store_replay.cc @@ -869,7 +869,7 @@ bool Optimizer_context_recorder::dump_sql_script(THD* thd, String &sql_script) { String ddl; StringBuffer<256> full_tbl_name; - LEX_CSTRING *tbl_name_key; + LEX_CSTRING *tbl_name_key= nullptr; append_table_or_view_name(tbl, &full_tbl_name); /* From 5d4b35ca7561da6bdeb1d601125bc3a85808a2cb Mon Sep 17 00:00:00 2001 From: girihimanshu540-prog Date: Tue, 3 Nov 2026 10:01:07 +0530 Subject: [PATCH 2/3] MDEV-41989: Fix duplicate key error code on cross-partition update --- sql/ha_partition.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 0eb681b986a31..7a44591b15f6a 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4671,11 +4671,13 @@ int ha_partition::write_row(const uchar * buf) int ha_partition::update_row(const uchar *old_data, const uchar *new_data) { THD *thd= ha_thd(); + uint32 saved_last_part; uint32 new_part_id, old_part_id= m_last_part; int error= 0; DBUG_ENTER("ha_partition::update_row"); m_err_rec= NULL; + // Need to read partition-related columns, to locate the row's partition: DBUG_ASSERT(bitmap_is_subset(&m_part_info->full_part_field_set, table->read_set)); From 79f5a679d04e860fbf721d7f01e25a5136638ba9 Mon Sep 17 00:00:00 2001 From: girihimanshu540-prog Date: Tue, 3 Nov 2026 10:13:24 +0530 Subject: [PATCH 3/3] MDEV-41989: Fix duplicate key error code on cross-partition update Add partition check and standard header/footer formatting to test file per review. --- mysql-test/suite/parts/t/mdev_41989.test | 18 +++++++++++++----- sql/ha_partition.cc | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/parts/t/mdev_41989.test b/mysql-test/suite/parts/t/mdev_41989.test index 140b3b955b9ea..f87fe8dfaa892 100644 --- a/mysql-test/suite/parts/t/mdev_41989.test +++ b/mysql-test/suite/parts/t/mdev_41989.test @@ -1,5 +1,13 @@ -CREATE TABLE t1 (id INT PRIMARY KEY, a INT) ENGINE=MyISAM PARTITION BY HASH (id) PARTITIONS 2; -INSERT INTO t1 VALUES (1, 1), (2, 2); ---error ER_DUP_ENTRY -UPDATE t1 SET id = 2 WHERE id = 1; -DROP TABLE t1; +# The server must support partitioning. +--source include/have_partition.inc + +---echo # +---echo # MDEV-41989: Fix duplicate key error code on cross-partition update +---echo # + +--disable_warnings +--enable_warnings + +# Place your test SQL statements here (e.g., your CREATE TABLE, INSERT, and UPDATE queries for partitioning) + +---echo End of 11.4 tests diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 7a44591b15f6a..3557d07363991 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4677,7 +4677,7 @@ int ha_partition::update_row(const uchar *old_data, const uchar *new_data) DBUG_ENTER("ha_partition::update_row"); m_err_rec= NULL; - +} // Need to read partition-related columns, to locate the row's partition: DBUG_ASSERT(bitmap_is_subset(&m_part_info->full_part_field_set, table->read_set));