diff --git a/core/types.rs b/core/types.rs index 940175ae7..99874e765 100644 --- a/core/types.rs +++ b/core/types.rs @@ -1638,10 +1638,10 @@ where V2: AsValueRef, E1: ExactSizeIterator, E2: ExactSizeIterator, - I1: IntoIterator, - I2: IntoIterator, + I1: IntoIterator, + I2: IntoIterator, { - let (l, r) = (l.into_iter(), r.into_iter()); + let (l, r): (E1, E2) = (l.into_iter(), r.into_iter()); assert!( l.len() >= column_info.len(), "{} < {}", @@ -1656,17 +1656,9 @@ where ); let (l, r) = (l.take(column_info.len()), r.take(column_info.len())); for (i, (l, r)) in l.zip(r).enumerate() { - let l = l.as_value_ref(); - let r = r.as_value_ref(); let column_order = column_info[i].sort_order; let collation = column_info[i].collation; - let cmp = match (l, r) { - (ValueRef::Text(left, _), ValueRef::Text(right, _)) => collation.compare_strings( - &String::from_utf8_lossy(left), - &String::from_utf8_lossy(right), - ), - _ => l.partial_cmp(&r).unwrap(), - }; + let cmp = compare_immutable_single(l, r, collation); if !cmp.is_eq() { return match column_order { SortOrder::Asc => cmp, @@ -1677,6 +1669,22 @@ where std::cmp::Ordering::Equal } +pub fn compare_immutable_single(l: V1, r: V2, collation: CollationSeq) -> std::cmp::Ordering +where + V1: AsValueRef, + V2: AsValueRef, +{ + let l = l.as_value_ref(); + let r = r.as_value_ref(); + match (l, r) { + (ValueRef::Text(left, _), ValueRef::Text(right, _)) => collation.compare_strings( + &String::from_utf8_lossy(left), + &String::from_utf8_lossy(right), + ), + _ => l.partial_cmp(&r).unwrap(), + } +} + #[derive(Debug, Clone, Copy)] pub enum RecordCompare { Int, diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index bb3cc2512..02c9ec8ce 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -75,7 +75,7 @@ use super::{ CommitState, }; use parking_lot::RwLock; -use turso_parser::ast::{self, ForeignKeyClause, Name, SortOrder}; +use turso_parser::ast::{self, ForeignKeyClause, Name}; use turso_parser::parser::Parser; use super::{ @@ -537,29 +537,12 @@ pub fn op_compare( )); } - let mut cmp = std::cmp::Ordering::Equal; - for (i, key_col) in key_info.iter().enumerate().take(count) { - // TODO (https://github.com/tursodatabase/turso/issues/2304): this logic is almost the same as compare_immutable() - // but that one works on RefValue and this works on Value. There are tons of cases like this where we could reuse - // functionality if we had a trait that both RefValue and Value implement. - let a = state.registers[start_reg_a + i].get_value(); - let b = state.registers[start_reg_b + i].get_value(); - let column_order = key_col.sort_order; - let collation = key_col.collation; - cmp = match (a, b) { - (Value::Text(left), Value::Text(right)) => { - collation.compare_strings(left.as_str(), right.as_str()) - } - _ => a.partial_cmp(b).unwrap(), - }; - if !cmp.is_eq() { - cmp = match column_order { - SortOrder::Asc => cmp, - SortOrder::Desc => cmp.reverse(), - }; - break; - } - } + // (https://github.com/tursodatabase/turso/issues/2304): reusing logic from compare_immutable(). + // TODO: There are tons of cases like this where we could reuse this in a similar vein + let a_range = (start_reg_a..start_reg_a + count + 1).map(|idx| state.registers[idx].get_value()); + let b_range = (start_reg_b..start_reg_b + count + 1).map(|idx| state.registers[idx].get_value()); + let cmp = compare_immutable(a_range, b_range, key_info); + state.last_compare = Some(cmp); state.pc += 1; Ok(InsnFunctionStepResult::Step)