remove optimization

- even if index search will return only 1 row - it will call next in the loop - and we incorrecty can process same row values multiple times
- the following query failed with this optimization:

turso> CREATE TABLE t (id INTEGER PRIMARY KEY AUTOINCREMENT, k TEXT, c0 INT);
turso> CREATE UNIQUE INDEX idx_p1_0 ON t(c0);
turso> insert into t values (null, 'uu', -1);
turso> insert into t values (null, 'uu', -2);
turso> UPDATE t SET c0 = NULL WHERE c0 = -1;
turso> SELECT * FROM t
┌────┬────┬────┐
│ id │ k  │ c0 │
├────┼────┼────┤
│  1 │ uu │    │
├────┼────┼────┤
│  2 │ uu │    │
└────┴────┴────┘
This commit is contained in:
Nikita Sivukhin
2025-09-30 16:37:41 +04:00
parent e9b8b0265d
commit a32ed53bd8
2 changed files with 0 additions and 17 deletions

View File

@@ -142,10 +142,6 @@ fn optimize_update_plan(plan: &mut UpdatePlan, schema: &Schema) -> Result<()> {
if !plan.indexes_to_update.iter().any(|i| Arc::ptr_eq(index, i)) {
return Ok(());
}
// Fine to use index if we aren't going to be iterating over it, since it returns at most 1 row.
if table_ref.op.returns_max_1_row() {
return Ok(());
}
// Otherwise, fall back to a table scan.
table_ref.op = Operation::Scan(Scan::BTreeTable {
iter_dir: IterationDirection::Forwards,

View File

@@ -795,19 +795,6 @@ impl Operation {
Operation::Search(Search::Seek { index, .. }) => index.as_ref(),
}
}
pub fn returns_max_1_row(&self) -> bool {
match self {
Operation::Scan(_) => false,
Operation::Search(Search::RowidEq { .. }) => true,
Operation::Search(Search::Seek { index, seek_def }) => {
let Some(index) = index else {
return false;
};
index.unique && seek_def.seek.as_ref().is_some_and(|seek| seek.op.eq_only())
}
}
}
}
impl JoinedTable {