diff --git a/core/types.rs b/core/types.rs index f61d7f371..bd0f8ff06 100644 --- a/core/types.rs +++ b/core/types.rs @@ -218,6 +218,12 @@ pub enum ValueRef<'a> { Blob(&'a [u8]), } +impl<'a, 'b> From<&'b ValueRef<'a>> for ValueRef<'a> { + fn from(value: &'b ValueRef<'a>) -> Self { + *value + } +} + impl Debug for ValueRef<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -1813,12 +1819,15 @@ fn compare_records_int( /// 4. **Length comparison**: If strings are equal, compares lengths /// 5. **Remaining fields**: If first field is equal and more fields exist, /// delegates to `compare_records_generic()` with `skip=1` -fn compare_records_string( +fn compare_records_string<'a, T>( serialized: &ImmutableRecord, - unpacked: &[ValueRef], + unpacked: &'a [T], index_info: &IndexInfo, tie_breaker: std::cmp::Ordering, -) -> Result { +) -> Result +where + ValueRef<'a>: From<&'a T>, +{ turso_assert!( index_info.key_info.len() >= unpacked.len(), "index_info.key_info.len() < unpacked.len()" @@ -1846,7 +1855,7 @@ fn compare_records_string( return compare_records_generic(serialized, unpacked, index_info, 0, tie_breaker); } - let ValueRef::Text(rhs_text, _) = &unpacked[0] else { + let ValueRef::Text(rhs_text, _) = (&unpacked[0]).into() else { return compare_records_generic(serialized, unpacked, index_info, 0, tie_breaker); }; @@ -1925,13 +1934,16 @@ fn compare_records_string( /// The serialized and unpacked records do not have to contain the same number /// of fields. If all fields that appear in both records are equal, then /// `tie_breaker` is returned. -pub fn compare_records_generic( +pub fn compare_records_generic<'a, T>( serialized: &ImmutableRecord, - unpacked: &[ValueRef], + unpacked: &'a [T], index_info: &IndexInfo, skip: usize, tie_breaker: std::cmp::Ordering, -) -> Result { +) -> Result +where + ValueRef<'a>: From<&'a T>, +{ turso_assert!( index_info.key_info.len() >= unpacked.len(), "index_info.key_info.len() < unpacked.len()" @@ -1971,7 +1983,7 @@ pub fn compare_records_generic( header_pos += bytes_read; let serial_type = SerialType::try_from(serial_type_raw)?; - let rhs_value = &unpacked[field_idx]; + let rhs_value = (&unpacked[field_idx]).into(); let lhs_value = match serial_type.kind() { SerialTypeKind::ConstInt0 => ValueRef::Integer(0), @@ -1993,14 +2005,14 @@ pub fn compare_records_generic( } (ValueRef::Integer(lhs_int), ValueRef::Float(rhs_float)) => { - sqlite_int_float_compare(*lhs_int, *rhs_float) + sqlite_int_float_compare(*lhs_int, rhs_float) } (ValueRef::Float(lhs_float), ValueRef::Integer(rhs_int)) => { - sqlite_int_float_compare(*rhs_int, *lhs_float).reverse() + sqlite_int_float_compare(rhs_int, *lhs_float).reverse() } - _ => lhs_value.partial_cmp(rhs_value).unwrap(), + _ => lhs_value.partial_cmp(&rhs_value).unwrap(), }; let final_comparison = match index_info.key_info[field_idx].sort_order { diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index e56bd4fdb..fa0878c64 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -19,7 +19,7 @@ use crate::types::{ }; use crate::util::normalize_ident; use crate::vdbe::insn::InsertFlags; -use crate::vdbe::{registers_to_ref_values, TxnCleanup}; +use crate::vdbe::TxnCleanup; use crate::vector::{vector32_sparse, vector_concat, vector_distance_jaccard, vector_slice}; use crate::{ error::{ @@ -3405,13 +3405,11 @@ pub fn op_idx_ge( let pc = if let Some(idx_record) = return_if_io!(cursor.record()) { // Create the comparison record from registers - let values = - registers_to_ref_values(&state.registers[*start_reg..*start_reg + *num_regs]); let tie_breaker = get_tie_breaker_from_idx_comp_op(insn); let ord = compare_records_generic( - &idx_record, // The serialized record from the index - &values, // The record built from registers - cursor.get_index_info(), // Sort order flags + &idx_record, // The serialized record from the index + &state.registers[*start_reg..*start_reg + *num_regs], // The record built from registers + cursor.get_index_info(), // Sort order flags 0, tie_breaker, )?; @@ -3473,12 +3471,10 @@ pub fn op_idx_le( let cursor = cursor.as_btree_mut(); let pc = if let Some(idx_record) = return_if_io!(cursor.record()) { - let values = - registers_to_ref_values(&state.registers[*start_reg..*start_reg + *num_regs]); let tie_breaker = get_tie_breaker_from_idx_comp_op(insn); let ord = compare_records_generic( &idx_record, - &values, + &state.registers[*start_reg..*start_reg + *num_regs], cursor.get_index_info(), 0, tie_breaker, @@ -3524,12 +3520,10 @@ pub fn op_idx_gt( let cursor = cursor.as_btree_mut(); let pc = if let Some(idx_record) = return_if_io!(cursor.record()) { - let values = - registers_to_ref_values(&state.registers[*start_reg..*start_reg + *num_regs]); let tie_breaker = get_tie_breaker_from_idx_comp_op(insn); let ord = compare_records_generic( &idx_record, - &values, + &state.registers[*start_reg..*start_reg + *num_regs], cursor.get_index_info(), 0, tie_breaker, @@ -3575,13 +3569,10 @@ pub fn op_idx_lt( let cursor = cursor.as_btree_mut(); let pc = if let Some(idx_record) = return_if_io!(cursor.record()) { - let values = - registers_to_ref_values(&state.registers[*start_reg..*start_reg + *num_regs]); - let tie_breaker = get_tie_breaker_from_idx_comp_op(insn); let ord = compare_records_generic( &idx_record, - &values, + &state.registers[*start_reg..*start_reg + *num_regs], cursor.get_index_info(), 0, tie_breaker, diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs index bcb4372d5..a7b5cbd46 100644 --- a/core/vdbe/mod.rs +++ b/core/vdbe/mod.rs @@ -250,6 +250,12 @@ pub enum Register { Record(ImmutableRecord), } +impl<'a> From<&'a Register> for ValueRef<'a> { + fn from(value: &'a Register) -> Self { + value.get_value().as_ref() + } +} + impl Register { #[inline] pub fn is_null(&self) -> bool { @@ -1002,12 +1008,6 @@ fn make_record(registers: &[Register], start_reg: &usize, count: &usize) -> Immu ImmutableRecord::from_registers(regs, regs.len()) } -pub fn registers_to_ref_values<'a>(registers: &'a [Register]) -> Vec> { - registers - .iter() - .map(|reg| reg.get_value().as_ref()) - .collect() -} #[instrument(skip(program), level = Level::DEBUG)] fn trace_insn(program: &Program, addr: InsnReference, insn: &Insn) {