diff --git a/core/storage/btree.rs b/core/storage/btree.rs index a58893de4..6cc0addf8 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -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 })); }; diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index f6cd37498..08a0095be 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -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 {