handle case when target seek page has no matching entries

This commit is contained in:
Nikita Sivukhin
2025-07-12 21:06:42 +04:00
parent 03b2725cc7
commit fc400906d5
2 changed files with 39 additions and 2 deletions

View File

@@ -1764,6 +1764,17 @@ impl BTreeCursor {
return Ok(CursorResult::Ok(if eq_only {
SeekResult::NotFound
} else {
let contents = page.get().contents.as_ref().unwrap();
turso_assert!(
contents.is_leaf(),
"tablebtree_seek() called on non-leaf page"
);
let cell_count = contents.cell_count();
// set cursor to the position where which would hold the op-boundary if it were present
self.stack.set_cell_index(match &seek_op {
SeekOp::GT | SeekOp::GE { .. } => cell_count as i32,
SeekOp::LT | SeekOp::LE { .. } => 0,
});
SeekResult::TryAdvance
}));
};

View File

@@ -2395,6 +2395,7 @@ pub fn op_deferred_seek(
pub enum OpSeekState {
Start,
Seek { rowid: i64, op: SeekOp },
Advance { op: SeekOp },
MoveLast,
}
@@ -2572,7 +2573,32 @@ pub fn op_seek_internal(
let cursor = cursor.as_btree_mut();
return_if_io!(cursor.seek(SeekKey::TableRowId(*rowid), *op))
};
if !matches!(seek_result, SeekResult::Found) {
let found = match seek_result {
SeekResult::Found => true,
SeekResult::NotFound => false,
SeekResult::TryAdvance => {
state.op_seek_state = OpSeekState::Advance { op: *op };
continue;
}
};
if !found {
state.pc = target_pc.as_offset_int()
} else {
state.pc += 1
}
return Ok(InsnFunctionStepResult::Step);
}
OpSeekState::Advance { op } => {
let found = {
let mut cursor = state.get_cursor(*cursor_id);
let cursor = cursor.as_btree_mut();
match op {
SeekOp::GT | SeekOp::GE { eq_only: false } => return_if_io!(cursor.next()),
SeekOp::LT | SeekOp::LE { eq_only: false } => return_if_io!(cursor.prev()),
_ => unreachable!("eq_only: true state must be unreachable"),
}
};
if !found {
state.pc = target_pc.as_offset_int()
} else {
state.pc += 1
@@ -4833,7 +4859,7 @@ pub fn op_idx_delete(
cursor.root_page(),
record
);
found
matches!(seek_result, SeekResult::Found)
};
if !found {