mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-10 10:44:22 +01:00
make find_cell use binary search
This commit is contained in:
@@ -3846,30 +3846,42 @@ 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()
|
||||
{
|
||||
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 = self.find_cell_state.get_cell_idx() as usize;
|
||||
}
|
||||
|
||||
while low <= high && cell_count > 0 {
|
||||
let mid = low + (high - low) / 2;
|
||||
self.find_cell_state.set(mid as isize);
|
||||
|
||||
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) => {
|
||||
if key.to_rowid() <= cell._rowid {
|
||||
break;
|
||||
Ordering::Less
|
||||
} else {
|
||||
Ordering::Greater
|
||||
}
|
||||
}
|
||||
BTreeCell::TableInteriorCell(cell) => {
|
||||
if key.to_rowid() <= cell._rowid {
|
||||
break;
|
||||
Ordering::Less
|
||||
} else {
|
||||
Ordering::Greater
|
||||
}
|
||||
}
|
||||
BTreeCell::IndexInteriorCell(IndexInteriorCell {
|
||||
@@ -3882,41 +3894,44 @@ 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 => {}
|
||||
}
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
if comparison_result == Ordering::Greater {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
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<()>> {
|
||||
|
||||
Reference in New Issue
Block a user