mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-17 08:34:19 +01:00
make query_start method to return bool - if result will have some rows or not
This commit is contained in:
@@ -87,7 +87,9 @@ pub trait IndexMethodCursor {
|
|||||||
/// For example, for 2 patterns ["SELECT * FROM {table} LIMIT ?", "SELECT * FROM {table} WHERE x = ?"], query_start(...) call can have following arguments:
|
/// For example, for 2 patterns ["SELECT * FROM {table} LIMIT ?", "SELECT * FROM {table} WHERE x = ?"], query_start(...) call can have following arguments:
|
||||||
/// - [Integer(0), Integer(10)] - pattern "SELECT * FROM {table} LIMIT ?" was chosen with LIMIT parameter equals to 10
|
/// - [Integer(0), Integer(10)] - pattern "SELECT * FROM {table} LIMIT ?" was chosen with LIMIT parameter equals to 10
|
||||||
/// - [Integer(1), Text("turso")] - pattern "SELECT * FROM {table} WHERE x = ?" was chosen with equality comparison equals to "turso"
|
/// - [Integer(1), Text("turso")] - pattern "SELECT * FROM {table} WHERE x = ?" was chosen with equality comparison equals to "turso"
|
||||||
fn query_start(&mut self, values: &[Register]) -> Result<IOResult<()>>;
|
///
|
||||||
|
/// Returns false if query will produce no rows (similar to VFilter/Rewind op codes)
|
||||||
|
fn query_start(&mut self, values: &[Register]) -> Result<IOResult<bool>>;
|
||||||
|
|
||||||
/// Moves cursor to the next response row
|
/// Moves cursor to the next response row
|
||||||
/// Returns false if query exhausted all rows
|
/// Returns false if query exhausted all rows
|
||||||
|
|||||||
@@ -151,7 +151,6 @@ pub struct VectorSparseInvertedIndexMethodCursor {
|
|||||||
delete_state: VectorSparseInvertedIndexDeleteState,
|
delete_state: VectorSparseInvertedIndexDeleteState,
|
||||||
search_state: VectorSparseInvertedIndexSearchState,
|
search_state: VectorSparseInvertedIndexSearchState,
|
||||||
search_result: VecDeque<(i64, f64)>,
|
search_result: VecDeque<(i64, f64)>,
|
||||||
search_row: Option<(i64, f64)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexMethod for VectorSparseInvertedIndexMethod {
|
impl IndexMethod for VectorSparseInvertedIndexMethod {
|
||||||
@@ -199,7 +198,6 @@ impl VectorSparseInvertedIndexMethodCursor {
|
|||||||
scratch_cursor: None,
|
scratch_cursor: None,
|
||||||
main_btree: None,
|
main_btree: None,
|
||||||
search_result: VecDeque::new(),
|
search_result: VecDeque::new(),
|
||||||
search_row: None,
|
|
||||||
create_state: VectorSparseInvertedIndexCreateState::Init,
|
create_state: VectorSparseInvertedIndexCreateState::Init,
|
||||||
insert_state: VectorSparseInvertedIndexInsertState::Init,
|
insert_state: VectorSparseInvertedIndexInsertState::Init,
|
||||||
delete_state: VectorSparseInvertedIndexDeleteState::Init,
|
delete_state: VectorSparseInvertedIndexDeleteState::Init,
|
||||||
@@ -459,7 +457,7 @@ impl IndexMethodCursor for VectorSparseInvertedIndexMethodCursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query_start(&mut self, values: &[Register]) -> Result<IOResult<()>> {
|
fn query_start(&mut self, values: &[Register]) -> Result<IOResult<bool>> {
|
||||||
let Some(scratch) = &mut self.scratch_cursor else {
|
let Some(scratch) = &mut self.scratch_cursor else {
|
||||||
return Err(LimboError::InternalError(
|
return Err(LimboError::InternalError(
|
||||||
"cursor must be opened".to_string(),
|
"cursor must be opened".to_string(),
|
||||||
@@ -521,7 +519,7 @@ impl IndexMethodCursor for VectorSparseInvertedIndexMethodCursor {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let position = p[*idx];
|
let position = p[*idx];
|
||||||
let key = ImmutableRecord::from_values(&[Value::Integer(position as i64)], 2);
|
let key = ImmutableRecord::from_values(&[Value::Integer(position as i64)], 1);
|
||||||
self.search_state = VectorSparseInvertedIndexSearchState::Seek {
|
self.search_state = VectorSparseInvertedIndexSearchState::Seek {
|
||||||
collected: collected.take(),
|
collected: collected.take(),
|
||||||
positions: positions.take(),
|
positions: positions.take(),
|
||||||
@@ -551,7 +549,7 @@ impl IndexMethodCursor for VectorSparseInvertedIndexMethodCursor {
|
|||||||
limit: *limit,
|
limit: *limit,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
SeekResult::TryAdvance => {
|
SeekResult::TryAdvance | SeekResult::NotFound => {
|
||||||
self.search_state = VectorSparseInvertedIndexSearchState::Next {
|
self.search_state = VectorSparseInvertedIndexSearchState::Next {
|
||||||
collected: collected.take(),
|
collected: collected.take(),
|
||||||
positions: positions.take(),
|
positions: positions.take(),
|
||||||
@@ -560,9 +558,6 @@ impl IndexMethodCursor for VectorSparseInvertedIndexMethodCursor {
|
|||||||
limit: *limit,
|
limit: *limit,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
SeekResult::NotFound => {
|
|
||||||
return Err(LimboError::Corrupt("inverted index corrupted".to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VectorSparseInvertedIndexSearchState::Read {
|
VectorSparseInvertedIndexSearchState::Read {
|
||||||
@@ -637,7 +632,7 @@ impl IndexMethodCursor for VectorSparseInvertedIndexMethodCursor {
|
|||||||
let Some(rowid) = rowids.as_ref().unwrap().last() else {
|
let Some(rowid) = rowids.as_ref().unwrap().last() else {
|
||||||
let distances = distances.take().unwrap();
|
let distances = distances.take().unwrap();
|
||||||
self.search_result = distances.iter().map(|(d, i)| (*i, d.0)).collect();
|
self.search_result = distances.iter().map(|(d, i)| (*i, d.0)).collect();
|
||||||
return Ok(IOResult::Done(()));
|
return Ok(IOResult::Done(!self.search_result.is_empty()));
|
||||||
};
|
};
|
||||||
let result = return_if_io!(
|
let result = return_if_io!(
|
||||||
main.seek(SeekKey::TableRowId(*rowid), SeekOp::GE { eq_only: true })
|
main.seek(SeekKey::TableRowId(*rowid), SeekOp::GE { eq_only: true })
|
||||||
@@ -709,17 +704,17 @@ impl IndexMethodCursor for VectorSparseInvertedIndexMethodCursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn query_rowid(&mut self) -> Result<IOResult<Option<i64>>> {
|
fn query_rowid(&mut self) -> Result<IOResult<Option<i64>>> {
|
||||||
let result = self.search_row.as_ref().unwrap();
|
let result = self.search_result.front().unwrap();
|
||||||
Ok(IOResult::Done(Some(result.0)))
|
Ok(IOResult::Done(Some(result.0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query_column(&mut self, _: usize) -> Result<IOResult<Value>> {
|
fn query_column(&mut self, _: usize) -> Result<IOResult<Value>> {
|
||||||
let result = self.search_row.as_ref().unwrap();
|
let result = self.search_result.front().unwrap();
|
||||||
Ok(IOResult::Done(Value::Float(result.1)))
|
Ok(IOResult::Done(Value::Float(result.1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query_next(&mut self) -> Result<IOResult<bool>> {
|
fn query_next(&mut self) -> Result<IOResult<bool>> {
|
||||||
self.search_row = self.search_result.pop_front();
|
let _ = self.search_result.pop_front();
|
||||||
Ok(IOResult::Done(self.search_row.is_some()))
|
Ok(IOResult::Done(!self.search_result.is_empty()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -720,10 +720,7 @@ pub fn open_loop(
|
|||||||
cursor_id: index_cursor_id.expect("IndexMethod requires a index cursor"),
|
cursor_id: index_cursor_id.expect("IndexMethod requires a index cursor"),
|
||||||
start_reg,
|
start_reg,
|
||||||
count_reg: query.arguments.len() + 1,
|
count_reg: query.arguments.len() + 1,
|
||||||
});
|
pc_if_empty: loop_end,
|
||||||
program.emit_insn(Insn::Next {
|
|
||||||
cursor_id: index_cursor_id.expect("IndexMethod requires a index cursor"),
|
|
||||||
pc_if_next: loop_end,
|
|
||||||
});
|
});
|
||||||
program.preassign_label_to_next_insn(loop_start);
|
program.preassign_label_to_next_insn(loop_start);
|
||||||
if let Some(table_cursor_id) = table_cursor_id {
|
if let Some(table_cursor_id) = table_cursor_id {
|
||||||
|
|||||||
@@ -819,6 +819,9 @@ impl ProgramBuilder {
|
|||||||
Insn::IdxLT { target_pc, .. } => {
|
Insn::IdxLT { target_pc, .. } => {
|
||||||
resolve(target_pc, "IdxLT");
|
resolve(target_pc, "IdxLT");
|
||||||
}
|
}
|
||||||
|
Insn::IndexMethodQuery { pc_if_empty, .. } => {
|
||||||
|
resolve(pc_if_empty, "IndexMethodQuery");
|
||||||
|
}
|
||||||
Insn::IsNull { reg: _, target_pc } => {
|
Insn::IsNull { reg: _, target_pc } => {
|
||||||
resolve(target_pc, "IsNull");
|
resolve(target_pc, "IsNull");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7248,6 +7248,7 @@ pub fn op_index_method_query(
|
|||||||
cursor_id,
|
cursor_id,
|
||||||
start_reg,
|
start_reg,
|
||||||
count_reg,
|
count_reg,
|
||||||
|
pc_if_empty,
|
||||||
},
|
},
|
||||||
insn
|
insn
|
||||||
);
|
);
|
||||||
@@ -7260,8 +7261,12 @@ pub fn op_index_method_query(
|
|||||||
}
|
}
|
||||||
let cursor = state.cursors[*cursor_id].as_mut().unwrap();
|
let cursor = state.cursors[*cursor_id].as_mut().unwrap();
|
||||||
let cursor = cursor.as_index_method_mut();
|
let cursor = cursor.as_index_method_mut();
|
||||||
return_if_io!(cursor.query_start(&state.registers[*start_reg..*start_reg + *count_reg]));
|
let has_rows = return_if_io!(cursor.query_start(&state.registers[*start_reg..*start_reg + *count_reg]));
|
||||||
state.pc += 1;
|
if !has_rows {
|
||||||
|
state.pc = pc_if_empty.as_offset_int();
|
||||||
|
} else {
|
||||||
|
state.pc += 1;
|
||||||
|
}
|
||||||
Ok(InsnFunctionStepResult::Step)
|
Ok(InsnFunctionStepResult::Step)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -895,6 +895,7 @@ pub enum Insn {
|
|||||||
cursor_id: CursorID,
|
cursor_id: CursorID,
|
||||||
start_reg: usize,
|
start_reg: usize,
|
||||||
count_reg: usize,
|
count_reg: usize,
|
||||||
|
pc_if_empty: BranchOffset,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Deletes an entire database table or index whose root page in the database file is given by P1.
|
/// Deletes an entire database table or index whose root page in the database file is given by P1.
|
||||||
|
|||||||
Reference in New Issue
Block a user