mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 18:18:03 +00:00
Merge 650c85ccd7
into 931a33642e
This commit is contained in:
commit
5a2257c4b7
1 changed files with 52 additions and 44 deletions
|
@ -445,16 +445,16 @@ pub enum CursorSeekState {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FindCellState(Option<isize>);
|
||||
struct FindCellState(Option<(usize, usize)>); // low, high
|
||||
|
||||
impl FindCellState {
|
||||
#[inline]
|
||||
fn set(&mut self, cell_idx: isize) {
|
||||
self.0 = Some(cell_idx)
|
||||
fn set(&mut self, lowhigh: (usize, usize)) {
|
||||
self.0 = Some(lowhigh);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_cell_idx(&mut self) -> isize {
|
||||
fn get_state(&mut self) -> (usize, usize) {
|
||||
self.0.expect("get can only be called after a set")
|
||||
}
|
||||
|
||||
|
@ -3863,32 +3863,30 @@ impl BTreeCursor {
|
|||
|
||||
/// Find the index of the cell in the page that contains the given rowid.
|
||||
fn find_cell(&mut self, page: &PageContent, key: &BTreeKey) -> Result<CursorResult<usize>> {
|
||||
if self.find_cell_state.0.is_none() {
|
||||
self.find_cell_state.set(0);
|
||||
}
|
||||
let cell_count = page.cell_count();
|
||||
while self.find_cell_state.get_cell_idx() < cell_count as isize {
|
||||
assert!(self.find_cell_state.get_cell_idx() >= 0);
|
||||
let cell_idx = self.find_cell_state.get_cell_idx() as usize;
|
||||
match page
|
||||
.cell_get(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(page.page_type(), self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(page.page_type(), self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
)
|
||||
.unwrap()
|
||||
{
|
||||
BTreeCell::TableLeafCell(cell) => {
|
||||
if key.to_rowid() <= cell._rowid {
|
||||
break;
|
||||
}
|
||||
}
|
||||
BTreeCell::TableInteriorCell(cell) => {
|
||||
if key.to_rowid() <= cell._rowid {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let mut low = 0;
|
||||
let mut high = if cell_count > 0 { cell_count - 1 } else { 0 };
|
||||
let mut result_index = cell_count;
|
||||
if self.find_cell_state.0.is_some() {
|
||||
(low, high) = self.find_cell_state.get_state();
|
||||
}
|
||||
|
||||
while low <= high && cell_count > 0 {
|
||||
let mid = low + (high - low) / 2;
|
||||
self.find_cell_state.set((low, high));
|
||||
let cell = match page.cell_get(
|
||||
mid,
|
||||
payload_overflow_threshold_max(page.page_type(), self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(page.page_type(), self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
) {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
let comparison_result = match cell {
|
||||
BTreeCell::TableLeafCell(cell) => key.to_rowid().cmp(&cell._rowid),
|
||||
BTreeCell::TableInteriorCell(cell) => key.to_rowid().cmp(&cell._rowid),
|
||||
BTreeCell::IndexInteriorCell(IndexInteriorCell {
|
||||
payload,
|
||||
first_overflow_page,
|
||||
|
@ -3899,41 +3897,51 @@ impl BTreeCursor {
|
|||
payload,
|
||||
first_overflow_page,
|
||||
payload_size,
|
||||
..
|
||||
}) => {
|
||||
// TODO: implement efficient comparison of records
|
||||
// e.g. https://github.com/sqlite/sqlite/blob/master/src/vdbeaux.c#L4719
|
||||
return_if_io!(self.read_record_w_possible_overflow(
|
||||
payload,
|
||||
first_overflow_page,
|
||||
payload_size,
|
||||
payload_size
|
||||
));
|
||||
|
||||
let key_values = key.to_index_key_values();
|
||||
let record = self.get_immutable_record();
|
||||
let record = record.as_ref().unwrap();
|
||||
let record_same_number_cols = &record.get_values()[..key_values.len()];
|
||||
let order = compare_immutable(
|
||||
compare_immutable(
|
||||
key_values,
|
||||
record_same_number_cols,
|
||||
self.key_sort_order(),
|
||||
&self.collations,
|
||||
);
|
||||
match order {
|
||||
Ordering::Less | Ordering::Equal => {
|
||||
break;
|
||||
}
|
||||
Ordering::Greater => {}
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
match comparison_result {
|
||||
Ordering::Equal => {
|
||||
result_index = mid;
|
||||
break;
|
||||
}
|
||||
Ordering::Greater => {
|
||||
low = mid + 1;
|
||||
}
|
||||
Ordering::Less => {
|
||||
result_index = mid;
|
||||
if mid == 0 {
|
||||
break;
|
||||
}
|
||||
high = mid - 1;
|
||||
}
|
||||
}
|
||||
let cell_idx = self.find_cell_state.get_cell_idx();
|
||||
self.find_cell_state.set(cell_idx + 1);
|
||||
}
|
||||
let cell_idx = self.find_cell_state.get_cell_idx();
|
||||
assert!(cell_idx >= 0);
|
||||
let cell_idx = cell_idx as usize;
|
||||
assert!(cell_idx <= cell_count);
|
||||
|
||||
self.find_cell_state.reset();
|
||||
Ok(CursorResult::Ok(cell_idx))
|
||||
assert!(result_index <= cell_count);
|
||||
|
||||
Ok(CursorResult::Ok(result_index))
|
||||
}
|
||||
|
||||
pub fn seek_end(&mut self) -> Result<CursorResult<()>> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue