From 9d44e97a7a5ab907cf4e5ad60e4b9bba3dbbdd28 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Thu, 21 Aug 2025 15:42:36 +0300 Subject: [PATCH 1/3] Fix: all indexes need to be updated if the rowid changes --- core/translate/update.rs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/core/translate/update.rs b/core/translate/update.rs index 296166c8e..0eceb8ecd 100644 --- a/core/translate/update.rs +++ b/core/translate/update.rs @@ -349,17 +349,26 @@ pub fn prepare_update_plan( // Check what indexes will need to be updated by checking set_clauses and see // if a column is contained in an index. let indexes = schema.get_indices(table_name.as_str()); - let indexes_to_update = indexes + let rowid_alias_used = set_clauses .iter() - .filter(|index| { - index.columns.iter().any(|index_column| { - set_clauses - .iter() - .any(|(set_index_column, _)| index_column.pos_in_table == *set_index_column) + .any(|(idx, _)| columns[*idx].is_rowid_alias); + let indexes_to_update = if rowid_alias_used { + // If the rowid alias is used in the SET clause, we need to update all indexes + indexes.to_vec() + } else { + // otherwise we need to update the indexes whose columns are set in the SET clause + indexes + .iter() + .filter(|index| { + index.columns.iter().any(|index_column| { + set_clauses + .iter() + .any(|(set_index_column, _)| index_column.pos_in_table == *set_index_column) + }) }) - }) - .cloned() - .collect(); + .cloned() + .collect() + }; Ok(Plan::Update(UpdatePlan { table_references, From e224bb15a832503b7f9d41e63b5dc8b4330adbe4 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Thu, 21 Aug 2025 16:25:35 +0300 Subject: [PATCH 2/3] Fix incorrect UNIQUE constraint failure behavior in UPDATE UPDATE should skip over the UNIQUE constraint failure if the existing row it found during the check has the same rowid as the row we are currently updating --- core/translate/emitter.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/translate/emitter.rs b/core/translate/emitter.rs index e2498f121..670c334bd 100644 --- a/core/translate/emitter.rs +++ b/core/translate/emitter.rs @@ -1056,8 +1056,10 @@ fn emit_update_insns( dest: idx_rowid_reg, }); + // Skip over the UNIQUE constraint failure if the existing row is the one that we are currently changing + let original_rowid_reg = beg; program.emit_insn(Insn::Eq { - lhs: rowid_reg, + lhs: original_rowid_reg, rhs: idx_rowid_reg, target_pc: constraint_check, flags: CmpInsFlags::default(), // TODO: not sure what type of comparison flag is needed From 22be35e790a2f4273431d2c6769379059ff00edd Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Thu, 21 Aug 2025 16:26:40 +0300 Subject: [PATCH 3/3] Add regression test --- testing/update.test | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/testing/update.test b/testing/update.test index 091b5c1f0..e471a2d8c 100755 --- a/testing/update.test +++ b/testing/update.test @@ -366,3 +366,15 @@ do_execsql_test_on_specific_db {:memory:} row-values-repeated-values-should-take INSERT INTO test (id, name) VALUES (1, 'test'); UPDATE test SET (name, name) = ('mordor', 'shire') RETURNING id, name; } {1|shire} + +do_execsql_test_on_specific_db {:memory:} rowid-update-updates-all-indexes { + CREATE TABLE t (a integer primary key, b unique, c unique); + INSERT INTO t VALUES (1,1,1); + UPDATE t SET a = 2, b = 3; + SELECT * from t; + -- massage optimizer into using b and c indexes respectively + SELECT * from t WHERE b > 0; + SELECT * from t WHERE c > 0; +} {2|3|1 +2|3|1 +2|3|1}