This commit is contained in:
Ihor Andrianov 2025-07-07 17:02:52 +03:00 committed by GitHub
commit 5a2257c4b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -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<()>> {