1use crate::turso_debug_assert;
2use branches::{mark_unlikely, unlikely};
3use either::Either;
4use turso_ext::{AggCtx, ContextDestructor, FinalizeFunction, StepFunction, ValueDestructor};
5use turso_parser::ast::SortOrder;
6
7use crate::alloc::*;
8use crate::error::LimboError;
9use crate::ext::{ExtValue, ExtValueType};
10use crate::index_method::IndexMethodCursor;
11use crate::numeric::format_float;
12use crate::numeric::nonnan::NonNan;
13use crate::numeric::Numeric;
14use crate::pseudo::PseudoCursor;
15use crate::schema::Index;
16use crate::storage::btree::CursorTrait;
17use crate::storage::sqlite3_ondisk::{read_integer, read_value, read_varint, write_varint};
18use crate::translate::collate::CollationSeq;
19use crate::translate::plan::IterationDirection;
20use crate::vdbe::sorter::Sorter;
21use crate::vdbe::Register;
22use crate::vtab::VirtualTableCursor;
23use crate::{Completion, CompletionError, Result, IO};
24use std::borrow::{Borrow, Cow};
25use std::cell::Cell;
26use std::fmt::{Debug, Display};
27use std::future::Future;
28use std::iter::{FusedIterator, Peekable};
29use std::ops::Deref;
30use std::task::{Poll, Waker};
31
32#[derive(Debug, Clone, Copy, PartialEq)]
38pub enum ValueType {
39 Null,
40 Integer,
41 Float,
42 Text,
43 Blob,
44 Error,
45}
46
47impl Display for ValueType {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 let value = match self {
50 Self::Null => "NULL",
51 Self::Integer => "INT",
52 Self::Float => "REAL",
53 Self::Blob => "BLOB",
54 Self::Text => "TEXT",
55 Self::Error => "ERROR",
56 };
57 write!(f, "{value}")
58 }
59}
60
61#[derive(Debug, Clone, Copy, PartialEq)]
62#[cfg_attr(clt_turso_feature = "serde", derive(serde::Serialize, serde::Deserialize))]
63pub enum TextSubtype {
64 Text,
65 #[cfg(clt_turso_feature = "json")]
66 Json,
67}
68
69#[derive(Debug, Clone)]
70#[cfg_attr(clt_turso_feature = "serde", derive(serde::Serialize, serde::Deserialize))]
71pub struct Text {
72 pub value: Cow<'static, str>,
73 pub subtype: TextSubtype,
74}
75
76impl Display for Text {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 write!(f, "{}", self.as_str())
79 }
80}
81
82impl Text {
83 pub fn new(value: impl Into<Cow<'static, str>>) -> Self {
84 Self {
85 value: value.into(),
86 subtype: TextSubtype::Text,
87 }
88 }
89 #[cfg(clt_turso_feature = "json")]
90 pub fn json(value: String) -> Self {
91 Self {
92 value: value.into(),
93 subtype: TextSubtype::Json,
94 }
95 }
96
97 pub fn as_str(&self) -> &str {
98 &self.value
99 }
100}
101
102#[derive(Debug, Clone, Copy)]
103pub struct TextRef<'a> {
104 pub value: &'a str,
105 pub subtype: TextSubtype,
106}
107
108impl<'a> TextRef<'a> {
109 pub fn new(value: &'a str, subtype: TextSubtype) -> Self {
110 Self { value, subtype }
111 }
112
113 #[inline]
114 pub fn as_str(&self) -> &'a str {
115 self.value
116 }
117}
118
119impl<'a> Borrow<str> for TextRef<'a> {
120 #[inline]
121 fn borrow(&self) -> &str {
122 self.as_str()
123 }
124}
125
126impl<'a> Deref for TextRef<'a> {
127 type Target = str;
128
129 #[inline]
130 fn deref(&self) -> &Self::Target {
131 self.as_str()
132 }
133}
134
135pub trait Extendable<T> {
136 fn do_extend(&mut self, other: &T) -> Result<()>;
137}
138
139impl<T: AnyText> Extendable<T> for Text {
140 #[inline(always)]
141 fn do_extend(&mut self, other: &T) -> Result<()> {
142 let other_str = other.as_ref();
143 match &mut self.value {
144 Cow::Owned(s) => {
145 let needed = other_str.len();
146 if s.capacity() >= needed {
147 turso_debug_assert!(
149 s.as_ptr().wrapping_add(s.len()) <= other_str.as_ptr()
150 || other_str.as_ptr().wrapping_add(other_str.len()) <= s.as_ptr(),
151 "source and destination ranges must not overlap"
152 );
153 unsafe {
154 std::ptr::copy_nonoverlapping(other_str.as_ptr(), s.as_mut_ptr(), needed);
155 s.as_mut_vec().set_len(needed);
156 }
157 } else {
158 other_str.clone_into(s);
159 }
160 }
161 Cow::Borrowed(_) => {
162 self.value = Cow::Owned(other_str.to_owned());
163 }
164 }
165 self.subtype = other.subtype();
166 Ok(())
167 }
168}
169
170impl<T: AnyBlob> Extendable<T> for std::vec::Vec<u8> {
171 #[inline(always)]
172 fn do_extend(&mut self, other: &T) -> Result<()> {
173 let other_slice = other.as_slice();
174 let needed = other_slice.len();
175 if self.capacity() >= needed {
176 turso_debug_assert!(
178 self.as_ptr().wrapping_add(self.len()) <= other_slice.as_ptr()
179 || other_slice.as_ptr().wrapping_add(other_slice.len()) <= self.as_ptr(),
180 "source and destination ranges must not overlap"
181 );
182 unsafe {
183 std::ptr::copy_nonoverlapping(other_slice.as_ptr(), self.as_mut_ptr(), needed);
184 self.set_len(needed);
185 }
186 } else {
187 self.clear();
188 self.try_reserve(self.len().abs_diff(needed))?;
190 self.extend_from_slice(other_slice);
191 }
192 Ok(())
193 }
194}
195
196pub trait AnyText: AsRef<str> {
197 fn subtype(&self) -> TextSubtype;
198}
199
200impl AnyText for Text {
201 fn subtype(&self) -> TextSubtype {
202 self.subtype
203 }
204}
205
206impl AnyText for &str {
207 fn subtype(&self) -> TextSubtype {
208 TextSubtype::Text
209 }
210}
211
212pub trait AnyBlob {
213 fn as_slice(&self) -> &[u8];
214}
215
216impl AnyBlob for std::vec::Vec<u8> {
217 fn as_slice(&self) -> &[u8] {
218 self.as_slice()
219 }
220}
221
222impl AnyBlob for &[u8] {
223 fn as_slice(&self) -> &[u8] {
224 self
225 }
226}
227
228impl AsRef<str> for Text {
229 fn as_ref(&self) -> &str {
230 self.as_str()
231 }
232}
233
234impl From<&str> for Text {
235 fn from(value: &str) -> Self {
236 Text {
237 value: value.to_owned().into(),
238 subtype: TextSubtype::Text,
239 }
240 }
241}
242
243impl From<String> for Text {
244 fn from(value: String) -> Self {
245 Text {
246 value: Cow::from(value),
247 subtype: TextSubtype::Text,
248 }
249 }
250}
251
252impl From<Text> for String {
253 fn from(value: Text) -> Self {
254 value.value.into_owned()
255 }
256}
257
258#[derive(Debug, Clone)]
265#[cfg_attr(clt_turso_feature = "serde", derive(serde::Serialize, serde::Deserialize))]
266pub enum Value {
267 Null,
268 Numeric(Numeric),
269 Text(Text),
270 Blob(std::vec::Vec<u8>),
271}
272
273#[derive(Clone, Copy)]
274pub enum ValueRef<'a> {
275 Null,
276 Numeric(Numeric),
277 Text(TextRef<'a>),
278 Blob(&'a [u8]),
279}
280
281impl Debug for ValueRef<'_> {
282 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
283 match self {
284 ValueRef::Null => write!(f, "Null"),
285 ValueRef::Numeric(Numeric::Integer(i)) => f.debug_tuple("Integer").field(i).finish(),
286 ValueRef::Numeric(Numeric::Float(float)) => {
287 let fval: f64 = (*float).into();
288 f.debug_tuple("Float").field(&fval).finish()
289 }
290 ValueRef::Text(text_ref) => {
291 let text = text_ref.as_str();
293 let max_len = text.len().min(256);
294 f.debug_struct("Text")
295 .field("data", &&text[0..max_len])
296 .field("truncated", &(text.len() > max_len))
298 .finish()
299 }
300 ValueRef::Blob(blob) => {
301 let max_len = blob.len().min(32);
303 f.debug_struct("Blob")
304 .field("data", &&blob[0..max_len])
305 .field("truncated", &(blob.len() > max_len))
307 .finish()
308 }
309 }
310 }
311}
312
313pub trait AsValueRef {
314 fn as_value_ref<'a>(&'a self) -> ValueRef<'a>;
315}
316
317impl<'b> AsValueRef for ValueRef<'b> {
318 #[inline]
319 fn as_value_ref<'a>(&'a self) -> ValueRef<'a> {
320 *self
321 }
322}
323
324impl AsValueRef for Value {
325 #[inline]
326 fn as_value_ref<'a>(&'a self) -> ValueRef<'a> {
327 self.as_ref()
328 }
329}
330
331impl AsValueRef for &mut Value {
332 #[inline]
333 fn as_value_ref<'a>(&'a self) -> ValueRef<'a> {
334 self.as_ref()
335 }
336}
337
338impl<V1, V2> AsValueRef for Either<V1, V2>
339where
340 V1: AsValueRef,
341 V2: AsValueRef,
342{
343 #[inline]
344 fn as_value_ref<'a>(&'a self) -> ValueRef<'a> {
345 match self {
346 Either::Left(left) => left.as_value_ref(),
347 Either::Right(right) => right.as_value_ref(),
348 }
349 }
350}
351
352impl<V: AsValueRef> AsValueRef for &V {
353 fn as_value_ref<'a>(&'a self) -> ValueRef<'a> {
354 (*self).as_value_ref()
355 }
356}
357
358impl Value {
359 pub const fn from_f64(f: f64) -> Self {
360 match NonNan::new(f) {
361 Some(nn) => Self::Numeric(Numeric::Float(nn)),
362 None => Self::Null,
363 }
364 }
365
366 pub const fn from_i64(i: i64) -> Self {
367 Self::Numeric(Numeric::Integer(i))
368 }
369
370 pub fn as_ref<'a>(&'a self) -> ValueRef<'a> {
371 match self {
372 Value::Null => ValueRef::Null,
373 Value::Numeric(n) => ValueRef::Numeric(*n),
374 Value::Text(v) => ValueRef::Text(TextRef {
375 value: &v.value,
376 subtype: v.subtype,
377 }),
378 Value::Blob(v) => ValueRef::Blob(v.as_slice()),
379 }
380 }
381
382 pub fn build_text(text: impl Into<Cow<'static, str>>) -> Self {
384 Self::Text(Text::new(text))
385 }
386
387 pub fn to_blob(&self) -> Option<&[u8]> {
388 match self {
389 Self::Blob(blob) => Some(blob),
390 _ => None,
391 }
392 }
393
394 pub fn from_blob(data: std::vec::Vec<u8>) -> Self {
395 Value::Blob(data)
396 }
397
398 pub fn to_text(&self) -> Option<&str> {
399 match self {
400 Value::Text(t) => Some(t.as_str()),
401 _ => None,
402 }
403 }
404
405 pub const fn as_blob(&self) -> &std::vec::Vec<u8> {
406 match self {
407 Value::Blob(b) => b,
408 _ => panic!("as_blob must be called only for Value::Blob"),
409 }
410 }
411
412 pub const fn as_blob_mut(&mut self) -> &mut std::vec::Vec<u8> {
413 match self {
414 Value::Blob(b) => b,
415 _ => panic!("as_blob must be called only for Value::Blob"),
416 }
417 }
418 pub fn as_float(&self) -> f64 {
419 match self {
420 Value::Numeric(Numeric::Float(f)) => f64::from(*f),
421 Value::Numeric(Numeric::Integer(i)) => *i as f64,
422 _ => panic!("as_float must be called only for Value::Numeric"),
423 }
424 }
425
426 pub fn to_float_or_zero(&self) -> f64 {
427 match self {
428 Value::Numeric(Numeric::Float(f)) => f64::from(*f),
429 Value::Numeric(Numeric::Integer(i)) => *i as f64,
430 _ => 0.0,
431 }
432 }
433
434 pub const fn as_int(&self) -> Option<i64> {
435 match self {
436 Value::Numeric(Numeric::Integer(i)) => Some(*i),
437 _ => None,
438 }
439 }
440
441 pub const fn as_uint(&self) -> u64 {
442 match self {
443 Value::Numeric(Numeric::Integer(i)) => (*i).cast_unsigned(),
444 _ => 0,
445 }
446 }
447
448 pub fn from_text(text: impl Into<Cow<'static, str>>) -> Self {
449 Value::Text(Text::new(text))
450 }
451
452 pub const fn value_type(&self) -> ValueType {
453 match self {
454 Value::Null => ValueType::Null,
455 Value::Numeric(Numeric::Integer(_)) => ValueType::Integer,
456 Value::Numeric(Numeric::Float(_)) => ValueType::Float,
457 Value::Text(_) => ValueType::Text,
458 Value::Blob(_) => ValueType::Blob,
459 }
460 }
461 pub fn serialize_serial(&self, out: &mut std::vec::Vec<u8>) {
462 match self {
463 Value::Null => {}
464 Value::Numeric(Numeric::Integer(i)) => {
465 let serial_type = SerialType::from(self);
466 match serial_type.kind() {
467 SerialTypeKind::I8 => out.extend_from_slice(&(*i as i8).to_be_bytes()),
468 SerialTypeKind::I16 => out.extend_from_slice(&(*i as i16).to_be_bytes()),
469 SerialTypeKind::I24 => out.extend_from_slice(&(*i as i32).to_be_bytes()[1..]), SerialTypeKind::I32 => out.extend_from_slice(&(*i as i32).to_be_bytes()),
471 SerialTypeKind::I48 => out.extend_from_slice(&i.to_be_bytes()[2..]), SerialTypeKind::I64 => out.extend_from_slice(&i.to_be_bytes()),
473 _ => unreachable!(),
474 }
475 }
476 Value::Numeric(Numeric::Float(f)) => {
477 let fval: f64 = (*f).into();
478 out.extend_from_slice(&fval.to_be_bytes());
479 }
480 Value::Text(t) => out.extend_from_slice(t.value.as_bytes()),
481 Value::Blob(b) => out.extend_from_slice(b),
482 };
483 }
484
485 pub fn cast_text(&self) -> Option<String> {
487 Some(match self {
488 Value::Null => return None,
489 v => v.to_string(),
490 })
491 }
492}
493
494#[derive(Debug, Clone, PartialEq)]
495pub struct ExternalAggState {
496 pub context: usize,
497 pub state: *mut AggCtx,
498 pub argc: usize,
499 pub step_fn: StepFunction,
500 pub finalize_fn: FinalizeFunction,
501 pub aggregate_destructor: Option<ContextDestructor>,
502 pub value_destructor: Option<ValueDestructor>,
503}
504
505impl Display for Value {
516 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
517 match self {
518 Self::Null => write!(f, ""),
519 Self::Numeric(Numeric::Integer(i)) => write!(f, "{i}"),
520 Self::Numeric(Numeric::Float(fl)) => f.write_str(&format_float(f64::from(*fl))),
521 Self::Text(s) => write!(f, "{}", s.as_str()),
522 Self::Blob(b) => write!(f, "{}", String::from_utf8_lossy(b)),
523 }
524 }
525}
526
527impl Value {
528 pub fn to_ffi(&self) -> ExtValue {
529 match self {
530 Self::Null => ExtValue::null(),
531 Self::Numeric(Numeric::Integer(i)) => ExtValue::from_integer(*i),
532 Self::Numeric(Numeric::Float(fl)) => ExtValue::from_float(f64::from(*fl)),
533 Self::Text(text) => ExtValue::from_text(text.as_str().to_string()),
534 Self::Blob(blob) => ExtValue::from_blob(blob.to_vec()),
535 }
536 }
537
538 pub(crate) fn from_ffi_ref(v: &ExtValue) -> Result<Self> {
539 match v.value_type() {
540 ExtValueType::Null => Ok(Value::Null),
541 ExtValueType::Integer => {
542 let Some(int) = v.to_integer() else {
543 return Ok(Value::Null);
544 };
545 Ok(Value::from_i64(int))
546 }
547 ExtValueType::Float => {
548 let Some(float) = v.to_float() else {
549 return Ok(Value::Null);
550 };
551 Ok(Value::from_f64(float))
552 }
553 ExtValueType::Text => {
554 let Some(text) = v.to_text() else {
555 return Ok(Value::Null);
556 };
557 #[cfg(clt_turso_feature = "json")]
558 if v.is_json() {
559 return Ok(Value::Text(Text::json(text.to_string())));
560 }
561 Ok(Value::build_text(text.to_string()))
562 }
563 ExtValueType::Blob => {
564 let Some(blob) = v.to_blob() else {
565 return Ok(Value::Null);
566 };
567 Ok(Value::Blob(blob))
568 }
569 ExtValueType::Error => {
570 let Some(err) = v.to_error_details() else {
571 return Ok(Value::Null);
572 };
573 match err {
574 (_, Some(msg)) => Err(LimboError::ExtensionError(msg)),
575 (code, None) => Err(LimboError::ExtensionError(code.to_string())),
576 }
577 }
578 }
579 }
580
581 pub fn from_ffi(v: ExtValue) -> Result<Self> {
582 let res = Self::from_ffi_ref(&v);
583 unsafe { v.__free_internal_type() };
584 res
585 }
586}
587
588pub trait FromValue: Sealed {
590 fn from_sql(val: Value) -> Result<Self>
591 where
592 Self: Sized;
593}
594
595impl FromValue for Value {
596 fn from_sql(val: Value) -> Result<Self> {
597 Ok(val)
598 }
599}
600impl Sealed for crate::Value {}
601
602macro_rules! impl_int_from_value {
603 ($ty:ty, $cast:expr) => {
604 impl FromValue for $ty {
605 fn from_sql(val: Value) -> Result<Self> {
606 match val {
607 Value::Null => Err(LimboError::NullValue),
608 Value::Numeric(Numeric::Integer(i)) => Ok($cast(i)),
609 _ => Err(LimboError::InvalidColumnType),
610 }
611 }
612 }
613
614 impl Sealed for $ty {}
615 };
616}
617
618impl_int_from_value!(i32, |i| i as i32);
619impl_int_from_value!(u32, |i| i as u32);
620impl_int_from_value!(i64, |i| i);
621impl_int_from_value!(u64, |i| i as u64);
622
623impl FromValue for f64 {
624 fn from_sql(val: Value) -> Result<Self> {
625 match val {
626 Value::Null => Err(LimboError::NullValue),
627 Value::Numeric(Numeric::Float(f)) => Ok(f64::from(f)),
628 _ => Err(LimboError::InvalidColumnType),
629 }
630 }
631}
632impl Sealed for f64 {}
633
634impl FromValue for std::vec::Vec<u8> {
635 fn from_sql(val: Value) -> Result<Self> {
636 match val {
637 Value::Null => Err(LimboError::NullValue),
638 Value::Blob(blob) => Ok(blob),
639 _ => Err(LimboError::InvalidColumnType),
640 }
641 }
642}
643impl Sealed for std::vec::Vec<u8> {}
644
645impl<const N: usize> FromValue for [u8; N] {
646 fn from_sql(val: Value) -> Result<Self> {
647 match val {
648 Value::Null => Err(LimboError::NullValue),
649 Value::Blob(blob) => blob.try_into().map_err(|_| LimboError::InvalidBlobSize(N)),
650 _ => Err(LimboError::InvalidColumnType),
651 }
652 }
653}
654impl<const N: usize> Sealed for [u8; N] {}
655
656impl FromValue for String {
657 fn from_sql(val: Value) -> Result<Self> {
658 match val {
659 Value::Null => Err(LimboError::NullValue),
660 Value::Text(s) => Ok(s.to_string()),
661 _ => Err(LimboError::InvalidColumnType),
662 }
663 }
664}
665impl Sealed for String {}
666
667impl FromValue for bool {
668 fn from_sql(val: Value) -> Result<Self> {
669 match val {
670 Value::Null => Err(LimboError::NullValue),
671 Value::Numeric(Numeric::Integer(i)) => match i {
672 0 => Ok(false),
673 1 => Ok(true),
674 _ => Err(LimboError::InvalidColumnType),
675 },
676 _ => Err(LimboError::InvalidColumnType),
677 }
678 }
679}
680impl Sealed for bool {}
681
682impl<T> FromValue for Option<T>
683where
684 T: FromValue,
685{
686 fn from_sql(val: Value) -> Result<Self> {
687 match val {
688 Value::Null => Ok(None),
689 _ => T::from_sql(val).map(Some),
690 }
691 }
692}
693impl<T> Sealed for Option<T> {}
694
695mod sealed {
696 pub trait Sealed {}
697}
698#[allow(unused_imports)] use crate::vdbe::insn::Insn;
700use sealed::Sealed;
701
702#[derive(Debug, Clone, PartialEq)]
703pub struct SumAggState {
704 pub r_err: f64, pub approx: bool, pub ovrfl: bool, }
708impl Default for SumAggState {
709 fn default() -> Self {
710 Self {
711 r_err: 0.0,
712 approx: false,
713 ovrfl: false,
714 }
715 }
716}
717
718#[derive(Debug, Clone, PartialEq)]
722pub enum AggContext {
723 Builtin(Vec<Value>),
726 External(ExternalAggState),
728}
729
730impl AggContext {
731 pub fn compute_external(&self) -> Result<Value> {
732 if let Self::External(ext_state) = self {
733 let mut final_value =
734 unsafe { (ext_state.finalize_fn)(ext_state.context, ext_state.state) };
735 let value = Value::from_ffi_ref(&final_value);
736 if let Some(value_destructor) = ext_state.value_destructor {
737 unsafe { value_destructor(&mut final_value) };
738 } else {
739 unsafe { final_value.__free_internal_type() };
740 }
741 if let Some(aggregate_destructor) = ext_state.aggregate_destructor {
742 unsafe { aggregate_destructor(ext_state.state as usize) };
743 }
744 value
745 } else {
746 panic!("AggContext::compute_external() expected External, found {self:?}");
747 }
748 }
749
750 pub fn payload_mut(&mut self) -> &mut [Value] {
752 match self {
753 Self::Builtin(payload) => payload,
754 Self::External(_) => panic!("payload_mut() called on External aggregate"),
755 }
756 }
757
758 pub fn payload_vec_mut(&mut self) -> &mut Vec<Value> {
761 match self {
762 Self::Builtin(payload) => payload,
763 Self::External(_) => panic!("payload_vec_mut() called on External aggregate"),
764 }
765 }
766
767 pub fn payload(&self) -> &[Value] {
769 match self {
770 Self::Builtin(payload) => payload,
771 Self::External(_) => panic!("payload() called on External aggregate"),
772 }
773 }
774}
775
776impl PartialEq<Value> for Value {
777 fn eq(&self, other: &Value) -> bool {
778 let (left, right) = (self.as_value_ref(), other.as_value_ref());
779 left.eq(&right)
780 }
781}
782
783impl PartialOrd<Value> for Value {
784 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
785 Some(self.cmp(other))
786 }
787}
788
789impl PartialOrd<AggContext> for AggContext {
790 fn partial_cmp(&self, other: &AggContext) -> Option<std::cmp::Ordering> {
791 match (self, other) {
792 (Self::Builtin(a), Self::Builtin(b)) => {
793 match (a.first(), b.first()) {
795 (Some(a), Some(b)) => a.partial_cmp(b),
796 _ => None,
797 }
798 }
799 _ => None,
800 }
801 }
802}
803
804impl Eq for Value {}
805
806impl Ord for Value {
807 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
808 let (left, right) = (self.as_value_ref(), other.as_value_ref());
809 left.cmp(&right)
810 }
811}
812
813impl std::ops::Add<Value> for Value {
814 type Output = Value;
815
816 fn add(mut self, rhs: Self) -> Self::Output {
817 self += rhs;
818 self
819 }
820}
821
822impl std::ops::Add<f64> for Value {
823 type Output = Value;
824
825 fn add(mut self, rhs: f64) -> Self::Output {
826 self += rhs;
827 self
828 }
829}
830
831impl std::ops::Add<i64> for Value {
832 type Output = Value;
833
834 fn add(mut self, rhs: i64) -> Self::Output {
835 self += rhs;
836 self
837 }
838}
839
840impl std::ops::AddAssign for Value {
841 fn add_assign(mut self: &mut Self, rhs: Self) {
842 match (&mut self, &rhs) {
843 (Self::Numeric(_), Self::Numeric(_)) => {
844 let sum = (|| {
845 let lhs_num = Numeric::from_value(&self)?;
846 let rhs_num = Numeric::from_value(&rhs)?;
847 lhs_num.checked_add(rhs_num)
848 })();
849 *self = sum.into();
850 }
851 (Self::Text(string_left), Self::Text(string_right)) => {
852 string_left.value.to_mut().push_str(&string_right.value);
853 string_left.subtype = TextSubtype::Text;
854 }
855 (Self::Text(string_left), Self::Numeric(Numeric::Integer(int_right))) => {
856 let string_right = int_right.to_string();
857 string_left.value.to_mut().push_str(&string_right);
858 string_left.subtype = TextSubtype::Text;
859 }
860 (Self::Numeric(Numeric::Integer(int_left)), Self::Text(string_right)) => {
861 let string_left = int_left.to_string();
862 *self = Self::build_text(string_left + string_right.as_str());
863 }
864 (Self::Text(string_left), Self::Numeric(Numeric::Float(_))) => {
865 let string_right = rhs.to_string();
866 string_left.value.to_mut().push_str(&string_right);
867 string_left.subtype = TextSubtype::Text;
868 }
869 (Self::Numeric(Numeric::Float(_)), Self::Text(string_right)) => {
870 let string_left = self.to_string();
871 *self = Self::build_text(string_left + string_right.as_str());
872 }
873 (_, Self::Null) => {}
874 (Self::Null, _) => *self = rhs,
875 _ => *self = Self::from_f64(0.0),
876 }
877 }
878}
879
880impl std::ops::AddAssign<i64> for Value {
881 fn add_assign(&mut self, rhs: i64) {
882 let sum = (|| {
883 let lhs_num = Numeric::from_value(&self)?;
884 let rhs_num = Numeric::Integer(rhs);
885 lhs_num.checked_add(rhs_num)
886 })();
887 *self = sum.into();
888 }
889}
890
891impl std::ops::AddAssign<f64> for Value {
892 fn add_assign(&mut self, rhs: f64) {
893 let sum = (|| {
894 let lhs_num = Numeric::from_value(&self)?;
895 let rhs_num = NonNan::new(rhs).map(Numeric::Float)?;
896 lhs_num.checked_add(rhs_num)
897 })();
898
899 *self = sum.into();
900 }
901}
902
903impl std::ops::Div<Value> for Value {
904 type Output = Value;
905
906 fn div(self, rhs: Value) -> Self::Output {
907 let div = (|| {
908 let lhs_num = Numeric::from_value(self)?;
909 let rhs_num = Numeric::from_value(rhs)?;
910 lhs_num.checked_div(rhs_num)
911 })();
912 div.into()
913 }
914}
915
916impl std::ops::DivAssign<Value> for Value {
917 fn div_assign(&mut self, rhs: Value) {
918 *self = self.clone() / rhs;
919 }
920}
921
922impl From<ValueRef<'_>> for Value {
923 fn from(value: ValueRef<'_>) -> Self {
924 value.to_owned()
925 }
926}
927
928impl TryFrom<ValueRef<'_>> for i64 {
929 type Error = LimboError;
930
931 fn try_from(value: ValueRef<'_>) -> Result<Self, Self::Error> {
932 match value {
933 ValueRef::Numeric(Numeric::Integer(i)) => Ok(i),
934 _ => Err(LimboError::ConversionError("Expected integer value".into())),
935 }
936 }
937}
938
939impl TryFrom<ValueRef<'_>> for String {
940 type Error = LimboError;
941
942 #[inline]
943 fn try_from(value: ValueRef<'_>) -> Result<Self, Self::Error> {
944 Ok(<&str>::try_from(value)?.to_string())
945 }
946}
947
948impl<'a> TryFrom<ValueRef<'a>> for &'a str {
949 type Error = LimboError;
950
951 #[inline]
952 fn try_from(value: ValueRef<'a>) -> Result<Self, Self::Error> {
953 match value {
954 ValueRef::Text(s) => Ok(s.as_str()),
955 _ => Err(LimboError::ConversionError("Expected text value".into())),
956 }
957 }
958}
959
960mod immutable_record {
961 use super::*;
962
963 pub struct ImmutableRecord {
968 payload: Value,
974 }
975
976 unsafe impl Send for ImmutableRecord {}
979 unsafe impl Sync for ImmutableRecord {}
980
981 impl Clone for ImmutableRecord {
982 fn clone(&self) -> Self {
983 Self {
984 payload: self.payload.clone(),
985 }
986 }
987 }
988
989 impl PartialEq for ImmutableRecord {
990 fn eq(&self, other: &Self) -> bool {
991 self.payload == other.payload }
993 }
994
995 impl Eq for ImmutableRecord {}
996
997 impl PartialOrd for ImmutableRecord {
998 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
999 Some(self.cmp(other))
1000 }
1001 }
1002
1003 impl Ord for ImmutableRecord {
1004 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1005 self.payload.cmp(&other.payload) }
1007 }
1008
1009 impl std::fmt::Debug for ImmutableRecord {
1010 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1011 match &self.payload {
1012 Value::Blob(bytes) => {
1013 let preview = if bytes.len() > 20 {
1014 format!("{:?} ... ({} bytes total)", &bytes[..20], bytes.len())
1015 } else {
1016 format!("{bytes:?}")
1017 };
1018 write!(f, "ImmutableRecord {{ payload: {preview} }}")
1019 }
1020 Value::Text(s) => {
1021 let string = s.as_str();
1022 let preview = if string.len() > 20 {
1023 format!("{:?} ... ({} chars total)", &string[..20], string.len())
1024 } else {
1025 format!("{string:?}")
1026 };
1027 write!(f, "ImmutableRecord {{ payload: {preview} }}")
1028 }
1029 other => write!(f, "ImmutableRecord {{ payload: {other:?} }}"),
1030 }
1031 }
1032 }
1033
1034 #[derive(Clone, Copy)]
1035 pub struct ImmutableRecordRef<'a> {
1036 payload: &'a [u8],
1037 }
1038
1039 impl std::fmt::Debug for ImmutableRecordRef<'_> {
1040 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1041 let bytes = self.payload;
1042 let preview = if bytes.len() > 20 {
1043 format!("{:?} ... ({} bytes total)", &bytes[..20], bytes.len())
1044 } else {
1045 format!("{bytes:?}")
1046 };
1047 write!(f, "ImmutableRecordRef {{ payload: {preview} }}")
1048 }
1049 }
1050
1051 struct AppendWriter<'a> {
1052 buf: &'a mut std::vec::Vec<u8>,
1053 pos: usize,
1054 buf_capacity_start: usize,
1055 buf_ptr_start: *const u8,
1056 }
1057
1058 impl<'a> AppendWriter<'a> {
1059 fn new(buf: &'a mut std::vec::Vec<u8>, pos: usize) -> Self {
1060 let buf_ptr_start = buf.as_ptr();
1061 let buf_capacity_start = buf.capacity();
1062 Self {
1063 buf,
1064 pos,
1065 buf_capacity_start,
1066 buf_ptr_start,
1067 }
1068 }
1069
1070 #[inline]
1071 fn extend_from_slice(&mut self, slice: &[u8]) {
1072 self.buf[self.pos..self.pos + slice.len()].copy_from_slice(slice);
1073 self.pos += slice.len();
1074 }
1075
1076 fn assert_finish_capacity(&self) {
1077 assert_eq!(self.buf_capacity_start, self.buf.capacity());
1079 assert_eq!(self.buf_ptr_start, self.buf.as_ptr());
1080 }
1081 }
1082
1083 #[inline(always)]
1084 fn iter(payload: &[u8]) -> Result<ValueIterator<'_>, LimboError> {
1085 ValueIterator::new(payload)
1086 }
1087
1088 fn values(payload: &[u8]) -> Result<Vec<ValueRef<'_>>> {
1089 let iter = iter(payload)?;
1090 let values = iter.try_collect::<Result<_>>()??;
1091 Ok(values)
1092 }
1093
1094 fn values_range(payload: &[u8], range: std::ops::Range<usize>) -> Result<Vec<ValueRef<'_>>> {
1095 let mut iter = iter(payload)?;
1096 let mut values = Vec::try_with_capacity_ext(range.end - range.start)?;
1097 if let Some(value) = iter.nth(range.start) {
1098 values.push(value?);
1099 } else {
1100 return Ok(values);
1101 }
1102 for _ in range.start + 1..range.end {
1103 if let Some(value) = iter.next() {
1104 values.push(value?);
1105 } else {
1106 break;
1107 }
1108 }
1109 Ok(values)
1110 }
1111
1112 fn two_values(
1113 payload: &[u8],
1114 idx1: usize,
1115 idx2: usize,
1116 ) -> Result<(ValueRef<'_>, ValueRef<'_>)> {
1117 let mut iter = iter(payload)?;
1118 let val1 = iter.nth(idx1);
1119 let val2 = iter.nth(idx2 - idx1 - 1);
1120 match (val1, val2) {
1121 (Some(v1), Some(v2)) => Ok((v1?, v2?)),
1122 _ => Err(LimboError::InternalError("index out of bound".to_string())),
1123 }
1124 }
1125
1126 fn three_values(
1127 payload: &[u8],
1128 idx1: usize,
1129 idx2: usize,
1130 idx3: usize,
1131 ) -> Result<(ValueRef<'_>, ValueRef<'_>, ValueRef<'_>)> {
1132 let mut iter = iter(payload)?;
1133 let val1 = iter.nth(idx1);
1134 let val2 = iter.nth(idx2 - idx1 - 1);
1135 let val3 = iter.nth(idx3 - idx2 - 1);
1136 match (val1, val2, val3) {
1137 (Some(v1), Some(v2), Some(v3)) => Ok((v1?, v2?, v3?)),
1138 _ => Err(LimboError::InternalError("index out of bound".to_string())),
1139 }
1140 }
1141
1142 fn four_values(
1143 payload: &[u8],
1144 idx1: usize,
1145 idx2: usize,
1146 idx3: usize,
1147 idx4: usize,
1148 ) -> Result<(ValueRef<'_>, ValueRef<'_>, ValueRef<'_>, ValueRef<'_>)> {
1149 let mut iter = iter(payload)?;
1150 let val1 = iter.nth(idx1);
1151 let val2 = iter.nth(idx2 - idx1 - 1);
1152 let val3 = iter.nth(idx3 - idx2 - 1);
1153 let val4 = iter.nth(idx4 - idx3 - 1);
1154 match (val1, val2, val3, val4) {
1155 (Some(v1), Some(v2), Some(v3), Some(v4)) => Ok((v1?, v2?, v3?, v4?)),
1156 _ => Err(LimboError::InternalError("index out of bound".to_string())),
1157 }
1158 }
1159
1160 fn values_owned(payload: &[u8]) -> Result<Vec<Value>> {
1161 let iter = iter(payload).expect("Failed to create payload iterator");
1162 let values = iter
1163 .map(|v| Ok::<_, LimboError>(v?.to_owned()))
1164 .try_collect::<Result<_>>()??;
1165 Ok(values)
1166 }
1167
1168 fn values_owned_range(payload: &[u8], range: std::ops::Range<usize>) -> Result<Vec<Value>> {
1169 let mut iter = iter(payload).expect("Failed to create payload iterator");
1170 let mut values = Vec::try_with_capacity_ext(range.end - range.start)?;
1171 if let Some(value) = iter.nth(range.start) {
1172 values.push(value?.to_owned());
1173 } else {
1174 return Ok(values);
1175 }
1176 for _ in range.start + 1..range.end {
1177 if let Some(value) = iter.next() {
1178 values.push(value?.to_owned());
1179 } else {
1180 break;
1181 }
1182 }
1183 Ok(values)
1184 }
1185
1186 fn contains_null(payload: &[u8]) -> Result<bool> {
1187 let (header_size, header_varint_len) = read_varint(payload)?;
1188 let header_size = header_size as usize;
1189
1190 if header_size > payload.len() || header_varint_len > payload.len() {
1191 return Err(LimboError::Corrupt(
1192 "Payload too small for indicated header size".into(),
1193 ));
1194 }
1195
1196 let mut header = &payload[header_varint_len..header_size];
1197
1198 while !header.is_empty() {
1199 let (serial_type, bytes_read) = read_varint(header)?;
1200 if serial_type == 0 {
1201 return Ok(true);
1202 }
1203 header = &header[bytes_read..];
1204 }
1205
1206 Ok(false)
1207 }
1208
1209 fn last_value(payload: &[u8]) -> Option<Result<ValueRef<'_>>> {
1210 if unlikely(payload.is_empty()) {
1211 return Some(Err(LimboError::InternalError(
1212 "Record is invalidated".into(),
1213 )));
1214 }
1215 let iter = match iter(payload) {
1216 Ok(it) => it,
1217 Err(e) => return Some(Err(e)),
1218 };
1219 iter.last()
1220 }
1221
1222 fn first_value(payload: &[u8]) -> Result<ValueRef<'_>> {
1223 if unlikely(payload.is_empty()) {
1224 return Err(LimboError::InternalError("Record is invalidated".into()));
1225 }
1226 match iter(payload)?.next() {
1227 Some(v) => v,
1228 None => Err(LimboError::InternalError("Record has no columns".into())),
1229 }
1230 }
1231
1232 fn value(payload: &[u8], idx: usize) -> Result<ValueRef<'_>> {
1233 if unlikely(payload.is_empty()) {
1234 return Err(LimboError::InternalError("Record is invalidated".into()));
1235 }
1236 let mut iter = iter(payload)?;
1237 iter.nth(idx)
1238 .transpose()?
1239 .ok_or_else(|| LimboError::InternalError("Index out of bounds".into()))
1240 }
1241
1242 fn value_opt(payload: &[u8], idx: usize) -> Option<ValueRef<'_>> {
1243 let mut iter = match iter(payload) {
1244 Ok(it) => it,
1245 Err(_) => {
1246 mark_unlikely();
1247 return None;
1248 }
1249 };
1250 match iter.nth(idx) {
1251 Some(Ok(v)) => Some(v),
1252 _ => {
1253 mark_unlikely();
1254 None
1255 }
1256 }
1257 }
1258
1259 fn column_count(payload: &[u8]) -> usize {
1260 iter(payload).map(|it| it.count()).unwrap_or_default()
1261 }
1262
1263 impl ImmutableRecord {
1264 pub fn get_values(&self) -> Result<Vec<ValueRef<'_>>> {
1266 values(self.get_payload())
1267 }
1268
1269 pub fn get_values_range(&self, range: std::ops::Range<usize>) -> Result<Vec<ValueRef<'_>>> {
1271 values_range(self.get_payload(), range)
1272 }
1273
1274 pub fn get_two_values(
1276 &self,
1277 idx1: usize,
1278 idx2: usize,
1279 ) -> Result<(ValueRef<'_>, ValueRef<'_>)> {
1280 two_values(self.get_payload(), idx1, idx2)
1281 }
1282
1283 pub fn get_three_values(
1285 &self,
1286 idx1: usize,
1287 idx2: usize,
1288 idx3: usize,
1289 ) -> Result<(ValueRef<'_>, ValueRef<'_>, ValueRef<'_>)> {
1290 three_values(self.get_payload(), idx1, idx2, idx3)
1291 }
1292
1293 pub fn get_four_values(
1295 &self,
1296 idx1: usize,
1297 idx2: usize,
1298 idx3: usize,
1299 idx4: usize,
1300 ) -> Result<(ValueRef<'_>, ValueRef<'_>, ValueRef<'_>, ValueRef<'_>)> {
1301 four_values(self.get_payload(), idx1, idx2, idx3, idx4)
1302 }
1303
1304 pub fn get_values_owned(&self) -> Result<Vec<Value>> {
1306 values_owned(self.get_payload())
1307 }
1308
1309 pub fn get_values_owned_range(&self, range: std::ops::Range<usize>) -> Result<Vec<Value>> {
1311 values_owned_range(self.get_payload(), range)
1312 }
1313
1314 #[inline(always)]
1315 pub fn iter(&self) -> Result<ValueIterator<'_>, LimboError> {
1316 iter(self.get_payload())
1317 }
1318
1319 #[inline]
1320 pub fn contains_null(&self) -> Result<bool> {
1324 contains_null(self.get_payload())
1325 }
1326
1327 #[inline]
1328 pub fn last_value(&self) -> Option<Result<ValueRef<'_>>> {
1329 last_value(self.get_payload())
1330 }
1331
1332 #[inline]
1333 pub fn first_value(&self) -> Result<ValueRef<'_>> {
1334 first_value(self.get_payload())
1335 }
1336
1337 #[inline]
1338 pub fn get_value(&self, idx: usize) -> Result<ValueRef<'_>> {
1339 value(self.get_payload(), idx)
1340 }
1341
1342 #[inline]
1343 pub fn get_value_opt(&self, idx: usize) -> Option<ValueRef<'_>> {
1344 value_opt(self.get_payload(), idx)
1345 }
1346
1347 pub fn column_count(&self) -> usize {
1348 column_count(self.get_payload())
1349 }
1350 }
1351
1352 impl<'a> ImmutableRecordRef<'a> {
1353 #[inline(always)]
1354 pub fn iter(&self) -> Result<ValueIterator<'a>, LimboError> {
1355 iter(self.payload)
1356 }
1357
1358 pub fn get_values(&self) -> Result<Vec<ValueRef<'a>>> {
1359 values(self.payload)
1360 }
1361
1362 pub fn get_two_values(
1363 &self,
1364 idx1: usize,
1365 idx2: usize,
1366 ) -> Result<(ValueRef<'a>, ValueRef<'a>)> {
1367 two_values(self.payload, idx1, idx2)
1368 }
1369
1370 pub fn get_three_values(
1371 &self,
1372 idx1: usize,
1373 idx2: usize,
1374 idx3: usize,
1375 ) -> Result<(ValueRef<'_>, ValueRef<'_>, ValueRef<'_>)> {
1376 three_values(self.get_payload(), idx1, idx2, idx3)
1377 }
1378
1379 pub fn get_values_owned(&self) -> Result<Vec<Value>> {
1380 values_owned(self.payload)
1381 }
1382
1383 #[inline]
1384 pub fn get_value_opt(&self, idx: usize) -> Option<ValueRef<'a>> {
1385 value_opt(self.payload, idx)
1386 }
1387
1388 pub fn column_count(&self) -> usize {
1389 column_count(self.payload)
1390 }
1391 }
1392
1393 impl ImmutableRecord {
1394 pub fn new(payload_capacity: usize) -> Result<Self> {
1395 let mut payload = std::vec::Vec::new();
1396 payload.try_reserve_exact(payload_capacity)?;
1397 Ok(Self {
1398 payload: Value::Blob(payload),
1399 })
1400 }
1401
1402 pub const fn from_bin_record(payload: std::vec::Vec<u8>) -> Self {
1403 Self {
1404 payload: Value::Blob(payload),
1405 }
1406 }
1407
1408 pub fn as_record_ref(&self) -> ImmutableRecordRef<'_> {
1409 ImmutableRecordRef::from_bin_record(self.get_payload())
1410 }
1411
1412 pub fn from_registers<'a, I: Iterator<Item = &'a Register> + Clone>(
1413 registers: impl IntoIterator<Item = &'a Register, IntoIter = I>,
1418 len: usize,
1419 ) -> Result<Self> {
1420 Self::from_values(registers.into_iter().map(|x| x.get_value()), len)
1421 }
1422
1423 pub fn from_values<'a>(
1424 values: impl IntoIterator<Item = impl AsValueRef + 'a> + Clone,
1425 len: usize,
1426 ) -> Result<Self> {
1427 let mut serials = Vec::try_with_capacity_ext(len)?;
1428 let mut size_header = 0;
1429 let mut size_values = 0;
1430
1431 let mut serial_type_buf = [0; 9];
1432 for value in values.clone() {
1434 let serial_type = SerialType::from(value.as_value_ref());
1435 let n = write_varint(&mut serial_type_buf[0..], serial_type.into());
1436 serials.push((serial_type_buf, n));
1437
1438 let value_size = serial_type.size();
1439
1440 size_header += n;
1441 size_values += value_size;
1442 }
1443
1444 let header_size = Record::calc_header_size(size_header);
1445
1446 let mut buf = std::vec::Vec::new();
1448 buf.try_reserve_exact(header_size + size_values)?;
1449 assert_eq!(buf.capacity(), header_size + size_values);
1450 let n = write_varint(&mut serial_type_buf, header_size as u64);
1451
1452 buf.resize(buf.capacity(), 0);
1453 let mut writer = AppendWriter::new(&mut buf, 0);
1454 writer.extend_from_slice(&serial_type_buf[..n]);
1455
1456 for (value, n) in serials {
1458 writer.extend_from_slice(&value[..n]);
1459 }
1460
1461 for value in values {
1463 let value = value.as_value_ref();
1464 match value {
1465 ValueRef::Null => {}
1466 ValueRef::Numeric(Numeric::Integer(i)) => {
1467 let serial_type = SerialType::from(value);
1468 match serial_type.kind() {
1469 SerialTypeKind::ConstInt0 | SerialTypeKind::ConstInt1 => {}
1470 SerialTypeKind::I8 => {
1471 writer.extend_from_slice(&(i as i8).to_be_bytes())
1472 }
1473 SerialTypeKind::I16 => {
1474 writer.extend_from_slice(&(i as i16).to_be_bytes())
1475 }
1476 SerialTypeKind::I24 => {
1477 writer.extend_from_slice(&(i as i32).to_be_bytes()[1..])
1478 } SerialTypeKind::I32 => {
1480 writer.extend_from_slice(&(i as i32).to_be_bytes())
1481 }
1482 SerialTypeKind::I48 => writer.extend_from_slice(&i.to_be_bytes()[2..]), SerialTypeKind::I64 => writer.extend_from_slice(&i.to_be_bytes()),
1484 other => panic!("Serial type is not an integer: {other:?}"),
1485 }
1486 }
1487 ValueRef::Numeric(Numeric::Float(f)) => {
1488 let fval: f64 = f.into();
1489 writer.extend_from_slice(&fval.to_be_bytes());
1490 }
1491 ValueRef::Text(t) => {
1492 writer.extend_from_slice(t.value.as_bytes());
1493 }
1494 ValueRef::Blob(b) => {
1495 writer.extend_from_slice(b);
1496 }
1497 };
1498 }
1499
1500 writer.assert_finish_capacity();
1501 Ok(Self {
1502 payload: Value::Blob(buf),
1503 })
1504 }
1505
1506 #[inline]
1507 pub fn into_payload(self) -> std::vec::Vec<u8> {
1508 match self.payload {
1509 Value::Blob(b) => b,
1510 _ => panic!("payload must be a blob"),
1511 }
1512 }
1513
1514 #[inline]
1515 pub const fn as_blob(&self) -> &std::vec::Vec<u8> {
1516 match &self.payload {
1517 Value::Blob(b) => b,
1518 _ => panic!("payload must be a blob"),
1519 }
1520 }
1521
1522 #[inline]
1523 pub const fn as_blob_mut(&mut self) -> &mut std::vec::Vec<u8> {
1524 match &mut self.payload {
1525 Value::Blob(b) => b,
1526 _ => panic!("payload must be a blob"),
1527 }
1528 }
1529
1530 #[inline]
1531 pub const fn as_blob_value(&self) -> &Value {
1532 &self.payload
1533 }
1534
1535 #[inline]
1536 pub fn start_serialization(&mut self, payload: &[u8]) -> Result<()> {
1537 let blob = self.as_blob_mut();
1538 blob.try_reserve(payload.len())?;
1539 blob.extend_from_slice(payload);
1540 Ok(())
1541 }
1542
1543 #[inline]
1544 pub fn invalidate(&mut self) {
1545 self.as_blob_mut().clear();
1546 }
1547
1548 #[inline]
1549 pub const fn is_invalidated(&self) -> bool {
1550 self.as_blob().is_empty()
1551 }
1552
1553 #[inline]
1554 pub fn get_payload(&self) -> &[u8] {
1555 self.as_blob()
1556 }
1557 }
1558
1559 impl<'a> ImmutableRecordRef<'a> {
1560 pub const fn from_bin_record(payload: &'a [u8]) -> Self {
1561 Self { payload }
1562 }
1563
1564 #[inline]
1565 pub const fn get_payload(&self) -> &'a [u8] {
1566 self.payload
1567 }
1568
1569 #[inline]
1570 pub const fn is_invalidated(&self) -> bool {
1571 self.payload.is_empty()
1572 }
1573 }
1574}
1575
1576pub use immutable_record::{ImmutableRecord, ImmutableRecordRef};
1577
1578#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1579pub struct Record {
1580 values: Vec<Value>,
1581}
1582
1583impl Record {
1584 pub fn count(&self) -> usize {
1590 self.values.len()
1591 }
1592
1593 pub fn last_value(&self) -> Option<&Value> {
1594 self.values.last()
1595 }
1596
1597 pub fn get_values(&self) -> &Vec<Value> {
1598 &self.values
1599 }
1600
1601 pub fn get_value(&self, idx: usize) -> &Value {
1602 &self.values[idx]
1603 }
1604
1605 pub fn len(&self) -> usize {
1606 self.values.len()
1607 }
1608
1609 pub fn is_empty(&self) -> bool {
1610 self.values.is_empty()
1611 }
1612}
1613
1614pub struct ValueIterator<'a> {
1632 header_section: Cell<&'a [u8]>,
1634 data_section: Cell<&'a [u8]>,
1636}
1637
1638impl<'a> ValueIterator<'a> {
1639 #[inline(always)]
1650 pub fn new(payload: &'a [u8]) -> Result<Self> {
1651 let (header_size, header_varint_len) = read_varint(payload)?;
1652 let header_size = header_size as usize;
1653
1654 if header_size > payload.len()
1655 || header_varint_len > payload.len()
1656 || header_varint_len > header_size
1657 {
1658 return Err(LimboError::Corrupt(
1659 "Payload too small for indicated header size".into(),
1660 ));
1661 }
1662
1663 Ok(Self {
1664 header_section: Cell::new(&payload[header_varint_len..header_size]),
1665 data_section: Cell::new(&payload[header_size..]),
1666 })
1667 }
1668
1669 pub const fn is_empty(&self) -> bool {
1671 self.header_section.get().is_empty()
1672 }
1673
1674 #[inline(always)]
1676 pub const fn header_section_ref(&self) -> &'a [u8] {
1677 self.header_section.get()
1678 }
1679
1680 #[inline(always)]
1682 pub const fn data_section_ref(&self) -> &'a [u8] {
1683 self.data_section.get()
1684 }
1685
1686 #[inline(always)]
1688 pub fn set_header_section(&self, header: &'a [u8]) {
1689 self.header_section.set(header);
1690 }
1691
1692 #[inline(always)]
1694 pub fn set_data_section(&self, data: &'a [u8]) {
1695 self.data_section.set(data);
1696 }
1697}
1698
1699impl<'a> Iterator for ValueIterator<'a> {
1700 type Item = Result<ValueRef<'a>, LimboError>;
1701
1702 #[inline(always)]
1703 fn count(self) -> usize
1704 where
1705 Self: Sized,
1706 {
1707 let mut count = 0;
1708 let mut header = self.header_section.get();
1709 while !header.is_empty() {
1710 match read_varint(header) {
1711 Ok((_, bytes_read)) => {
1712 count += 1;
1713 header = &header[bytes_read..];
1714 }
1715 Err(_) => break,
1716 }
1717 }
1718 count
1719 }
1720
1721 #[inline(always)]
1722 fn size_hint(&self) -> (usize, Option<usize>) {
1723 let mut count = 0;
1724 let mut header = self.header_section.get();
1725 while !header.is_empty() {
1726 match read_varint(header) {
1727 Ok((_, bytes_read)) => {
1728 count += 1;
1729 header = &header[bytes_read..];
1730 }
1731 Err(_) => break,
1732 }
1733 }
1734 (count, Some(count))
1735 }
1736
1737 fn fold<B, F>(self, init: B, mut f: F) -> B
1738 where
1739 F: FnMut(B, Self::Item) -> B,
1740 {
1741 let mut acc = init;
1742 for item in self {
1743 acc = f(acc, item);
1744 }
1745 acc
1746 }
1747
1748 #[inline(always)]
1750 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1751 let mut header = self.header_section.get();
1752 let mut data = self.data_section.get();
1753
1754 let mut data_sum = 0;
1755 for _ in 0..n {
1756 if unlikely(header.is_empty()) {
1757 return None;
1758 }
1759
1760 let (serial_type, bytes_read) = match read_varint(header) {
1761 Ok(v) => v,
1762 Err(e) => {
1763 mark_unlikely();
1764 return Some(Err(e));
1765 }
1766 };
1767 header = &header[bytes_read..];
1768
1769 data_sum += match get_serial_type_size(serial_type) {
1770 Ok(size) => size,
1771 Err(e) => {
1772 mark_unlikely();
1773 return Some(Err(e));
1774 }
1775 };
1776 }
1777
1778 if unlikely(data_sum > data.len()) {
1779 return Some(Err(LimboError::Corrupt(
1780 "Data section too small for indicated serial type size".into(),
1781 )));
1782 }
1783 data = &data[data_sum..];
1784
1785 self.header_section.set(header);
1787 self.data_section.set(data);
1788
1789 self.next()
1791 }
1792
1793 #[inline(always)]
1794 fn next(&mut self) -> Option<Self::Item> {
1795 let header = self.header_section.get();
1796 if unlikely(header.is_empty()) {
1797 return None;
1798 }
1799
1800 let (serial_type, bytes_read) = match read_varint(header) {
1802 Ok(v) => v,
1803 Err(e) => {
1804 mark_unlikely();
1805 return Some(Err(e));
1806 }
1807 };
1808
1809 self.header_section.set(&header[bytes_read..]);
1811
1812 let data_section = self.data_section.get();
1813
1814 match crate::storage::sqlite3_ondisk::read_value_serial_type(data_section, serial_type) {
1815 Ok((value, n)) => {
1816 self.data_section.set(&data_section[n..]);
1817 Some(Ok(value))
1818 }
1819 Err(e) => {
1820 mark_unlikely();
1821 Some(Err(e))
1822 }
1823 }
1824 }
1825}
1826
1827impl<'a> FusedIterator for ValueIterator<'a> {}
1829
1830impl<'a> Clone for ValueIterator<'a> {
1831 fn clone(&self) -> Self {
1832 Self {
1833 header_section: Cell::new(self.header_section.get()),
1834 data_section: Cell::new(self.data_section.get()),
1835 }
1836 }
1837}
1838
1839impl<'a> ValueRef<'a> {
1840 pub fn from_f64(f: f64) -> Self {
1841 match NonNan::new(f) {
1842 Some(nn) => Self::Numeric(Numeric::Float(nn)),
1843 None => Self::Null,
1844 }
1845 }
1846
1847 pub fn from_i64(i: i64) -> Self {
1848 Self::Numeric(Numeric::Integer(i))
1849 }
1850
1851 pub fn to_ffi(&self) -> ExtValue {
1852 match self {
1853 Self::Null => ExtValue::null(),
1854 Self::Numeric(Numeric::Integer(i)) => ExtValue::from_integer(*i),
1855 Self::Numeric(Numeric::Float(fl)) => ExtValue::from_float(f64::from(*fl)),
1856 Self::Text(text) => ExtValue::from_text(text.as_str().to_string()),
1857 Self::Blob(blob) => ExtValue::from_blob(blob.to_vec()),
1858 }
1859 }
1860
1861 pub fn to_blob(&self) -> Option<&'a [u8]> {
1862 match self {
1863 Self::Blob(blob) => Some(*blob),
1864 _ => None,
1865 }
1866 }
1867
1868 pub fn to_text(&self) -> Option<&'a str> {
1869 match self {
1870 Self::Text(t) => Some(t.as_str()),
1871 _ => None,
1872 }
1873 }
1874
1875 pub fn as_blob(&self) -> &'a [u8] {
1876 match self {
1877 Self::Blob(b) => b,
1878 _ => panic!("as_blob must be called only for Value::Blob"),
1879 }
1880 }
1881
1882 pub fn as_float(&self) -> f64 {
1883 match self {
1884 Self::Numeric(Numeric::Float(f)) => f64::from(*f),
1885 Self::Numeric(Numeric::Integer(i)) => *i as f64,
1886 _ => panic!("as_float must be called only for ValueRef::Numeric"),
1887 }
1888 }
1889
1890 pub const fn as_int(&self) -> Option<i64> {
1891 match self {
1892 Self::Numeric(Numeric::Integer(i)) => Some(*i),
1893 _ => None,
1894 }
1895 }
1896
1897 pub const fn as_uint(&self) -> u64 {
1898 match self {
1899 Self::Numeric(Numeric::Integer(i)) => (*i).cast_unsigned(),
1900 _ => 0,
1901 }
1902 }
1903
1904 #[inline]
1905 pub fn to_owned(&self) -> Value {
1906 match self {
1907 ValueRef::Null => Value::Null,
1908 ValueRef::Numeric(n) => Value::from(*n),
1909 ValueRef::Text(text) => Value::Text(Text {
1910 value: text.value.to_string().into(),
1911 subtype: text.subtype,
1912 }),
1913 ValueRef::Blob(b) => Value::Blob(b.to_vec()),
1914 }
1915 }
1916
1917 pub fn value_type(&self) -> ValueType {
1918 match self {
1919 Self::Null => ValueType::Null,
1920 Self::Numeric(Numeric::Integer(_)) => ValueType::Integer,
1921 Self::Numeric(Numeric::Float(_)) => ValueType::Float,
1922 Self::Text(_) => ValueType::Text,
1923 Self::Blob(_) => ValueType::Blob,
1924 }
1925 }
1926}
1927
1928impl Display for ValueRef<'_> {
1929 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1930 match self {
1931 Self::Null => write!(f, "NULL"),
1932 Self::Numeric(Numeric::Integer(i)) => write!(f, "{i}"),
1933 Self::Numeric(Numeric::Float(fl)) => {
1934 let fval: f64 = (*fl).into();
1935 write!(f, "{fval:?}")
1936 }
1937 Self::Text(s) => write!(f, "{}", s.as_str()),
1938 Self::Blob(b) => write!(f, "{}", String::from_utf8_lossy(b)),
1939 }
1940 }
1941}
1942
1943impl<'a> PartialEq<ValueRef<'a>> for ValueRef<'a> {
1944 fn eq(&self, other: &ValueRef<'a>) -> bool {
1945 match (self, other) {
1946 (Self::Null, Self::Null) => true,
1947 (Self::Numeric(a), Self::Numeric(b)) => a == b,
1948 (Self::Text(text_left), Self::Text(text_right)) => {
1949 text_left.value.as_bytes() == text_right.value.as_bytes()
1950 }
1951 (Self::Blob(blob_left), Self::Blob(blob_right)) => blob_left.eq(blob_right),
1952 _ => false,
1953 }
1954 }
1955}
1956
1957impl<'a> PartialEq<Value> for ValueRef<'a> {
1958 fn eq(&self, other: &Value) -> bool {
1959 let other = other.as_value_ref();
1960 self.eq(&other)
1961 }
1962}
1963
1964impl<'a> Eq for ValueRef<'a> {}
1965
1966impl<'a> PartialOrd<ValueRef<'a>> for ValueRef<'a> {
1967 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1968 Some(self.cmp(other))
1969 }
1970}
1971
1972impl<'a> Ord for ValueRef<'a> {
1973 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1974 match (self, other) {
1975 (Self::Null, Self::Null) => std::cmp::Ordering::Equal,
1976 (Self::Null, _) => std::cmp::Ordering::Less,
1977 (_, Self::Null) => std::cmp::Ordering::Greater,
1978
1979 (Self::Numeric(a), Self::Numeric(b)) => a.cmp(b),
1980
1981 (Self::Numeric(_), _) => std::cmp::Ordering::Less,
1983 (_, Self::Numeric(_)) => std::cmp::Ordering::Greater,
1984
1985 (Self::Text(text_left), Self::Text(text_right)) => {
1986 text_left.value.as_bytes().cmp(text_right.value.as_bytes())
1987 }
1988 (Self::Text(_), Self::Blob(_)) => std::cmp::Ordering::Less,
1989 (Self::Blob(_), Self::Text(_)) => std::cmp::Ordering::Greater,
1990
1991 (Self::Blob(blob_left), Self::Blob(blob_right)) => blob_left.cmp(blob_right),
1992 }
1993 }
1994}
1995
1996#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1997pub struct KeyInfo {
1998 pub sort_order: SortOrder,
1999 pub collation: CollationSeq,
2000 pub nulls_order: Option<turso_parser::ast::NullsOrder>,
2001}
2002
2003#[cfg(not(nightly))]
2004pub type IndexKeyInfo = Vec<KeyInfo>;
2005#[cfg(nightly)]
2006pub type IndexKeyInfo = Vec<KeyInfo, DynAllocator>;
2007
2008#[derive(Debug, Clone, PartialEq, Eq)]
2009pub struct IndexInfo {
2015 pub key_info: IndexKeyInfo,
2017 pub has_rowid: bool,
2019 pub num_cols: usize,
2021 pub is_unique: bool,
2023}
2024
2025impl Default for IndexInfo {
2026 fn default() -> Self {
2027 Self {
2028 key_info: Self::key_info_in(TursoAllocator),
2029 has_rowid: true,
2030 num_cols: 1,
2031 is_unique: false,
2032 }
2033 }
2034}
2035
2036impl IndexInfo {
2037 pub fn key_info_in<A: ConcurrentAllocator>(alloc: A) -> IndexKeyInfo {
2038 <IndexKeyInfo as TursoVecInExt<KeyInfo, DynAllocator>>::new_in(DynAllocator::new(alloc))
2039 }
2040
2041 #[cfg(not(nightly))]
2042 pub fn key_info_from_iter_in<A, I>(
2043 key_info: I,
2044 _alloc: A,
2045 ) -> Result<IndexKeyInfo, TryReserveError>
2046 where
2047 A: ConcurrentAllocator,
2048 I: IntoIterator<Item = KeyInfo>,
2049 {
2050 key_info.into_iter().try_collect()
2051 }
2052
2053 #[cfg(nightly)]
2054 pub fn key_info_from_iter_in<A, I>(
2055 key_info: I,
2056 alloc: A,
2057 ) -> Result<IndexKeyInfo, TryReserveError>
2058 where
2059 A: ConcurrentAllocator,
2060 I: IntoIterator<Item = KeyInfo>,
2061 {
2062 key_info
2063 .into_iter()
2064 .try_collect_in(DynAllocator::new(alloc))
2065 }
2066
2067 pub fn new<I>(
2068 key_info: I,
2069 has_rowid: bool,
2070 num_cols: usize,
2071 is_unique: bool,
2072 ) -> Result<Self, TryReserveError>
2073 where
2074 I: IntoIterator<Item = KeyInfo>,
2075 {
2076 Self::new_in(key_info, has_rowid, num_cols, is_unique, TursoAllocator)
2077 }
2078
2079 pub fn new_in<A, I>(
2080 key_info: I,
2081 has_rowid: bool,
2082 num_cols: usize,
2083 is_unique: bool,
2084 alloc: A,
2085 ) -> Result<Self, TryReserveError>
2086 where
2087 A: ConcurrentAllocator,
2088 I: IntoIterator<Item = KeyInfo>,
2089 {
2090 Ok(Self {
2091 key_info: Self::key_info_from_iter_in(key_info, alloc)?,
2092 has_rowid,
2093 num_cols,
2094 is_unique,
2095 })
2096 }
2097
2098 pub fn new_from_index(index: &Index) -> Result<Self, TryReserveError> {
2099 Self::new_from_index_in(index, TursoAllocator)
2100 }
2101
2102 pub fn new_from_index_in<A: ConcurrentAllocator>(
2103 index: &Index,
2104 alloc: A,
2105 ) -> Result<Self, TryReserveError> {
2106 let key_info = index
2107 .columns
2108 .iter()
2109 .map(|c| KeyInfo {
2110 sort_order: c.order,
2111 collation: c.collation.unwrap_or_default(),
2112 nulls_order: None,
2113 })
2114 .chain(index.has_rowid.then_some(KeyInfo {
2115 sort_order: SortOrder::Asc,
2116 collation: CollationSeq::Binary,
2117 nulls_order: None,
2118 }));
2119 Self::new_in(
2120 key_info,
2121 index.has_rowid,
2122 index.columns.len() + (index.has_rowid as usize),
2123 index.unique,
2124 alloc,
2125 )
2126 }
2127}
2128
2129pub fn compare_immutable<V1, V2, E1, E2, I1, I2>(
2130 l: I1,
2131 r: I2,
2132 column_info: &[KeyInfo],
2133) -> std::cmp::Ordering
2134where
2135 V1: AsValueRef,
2136 V2: AsValueRef,
2137 E1: ExactSizeIterator<Item = V1>,
2138 E2: ExactSizeIterator<Item = V2>,
2139 I1: IntoIterator<IntoIter = E1, Item = E1::Item>,
2140 I2: IntoIterator<IntoIter = E2, Item = E2::Item>,
2141{
2142 let (l, r): (E1, E2) = (l.into_iter(), r.into_iter());
2143 assert!(
2144 l.len() >= column_info.len(),
2145 "{} < {}",
2146 l.len(),
2147 column_info.len()
2148 );
2149 assert!(
2150 r.len() >= column_info.len(),
2151 "{} < {}",
2152 r.len(),
2153 column_info.len()
2154 );
2155 let (l, r) = (l.take(column_info.len()), r.take(column_info.len()));
2156 for (i, (l, r)) in l.zip(r).enumerate() {
2157 let column_order = column_info[i].sort_order;
2158 let collation = column_info[i].collation;
2159 let cmp = compare_immutable_single(l, r, collation);
2160 if !cmp.is_eq() {
2161 return match column_order {
2162 SortOrder::Asc => cmp,
2163 SortOrder::Desc => cmp.reverse(),
2164 };
2165 }
2166 }
2167 std::cmp::Ordering::Equal
2168}
2169
2170pub fn compare_immutable_iter<V, E1, E2>(
2171 mut l: E1,
2172 mut r: E2,
2173 column_info: &[KeyInfo],
2174) -> Result<std::cmp::Ordering>
2175where
2176 V: AsValueRef,
2177 E1: Iterator<Item = Result<V>>,
2178 E2: Iterator<Item = Result<V>>,
2179{
2180 for col_info in column_info.iter() {
2181 let l = match l.next() {
2182 Some(v) => v,
2183 None => break,
2184 };
2185 let r = match r.next() {
2186 Some(v) => v,
2187 None => break,
2188 };
2189 let column_order = col_info.sort_order;
2190 let collation = col_info.collation;
2191 let cmp = compare_immutable_single(l?, r?, collation);
2192 if !cmp.is_eq() {
2193 return match column_order {
2194 SortOrder::Asc => Ok(cmp),
2195 SortOrder::Desc => Ok(cmp.reverse()),
2196 };
2197 }
2198 }
2199 Ok(std::cmp::Ordering::Equal)
2200}
2201
2202pub fn compare_immutable_single<V1, V2>(l: V1, r: V2, collation: CollationSeq) -> std::cmp::Ordering
2203where
2204 V1: AsValueRef,
2205 V2: AsValueRef,
2206{
2207 let l = l.as_value_ref();
2208 let r = r.as_value_ref();
2209 match (l, r) {
2210 (ValueRef::Text(left), ValueRef::Text(right)) => collation.compare_strings(&left, &right),
2211 _ => l.cmp(&r),
2212 }
2213}
2214
2215#[derive(Debug, Clone, Copy)]
2216pub enum RecordCompare {
2217 Int,
2218 String,
2219 Generic,
2220}
2221
2222impl RecordCompare {
2223 pub fn compare<V, E, I>(
2224 &self,
2225 serialized: &ImmutableRecord,
2226 unpacked: I,
2227 index_info: &IndexInfo,
2228 skip: usize,
2229 tie_breaker: std::cmp::Ordering,
2230 ) -> Result<std::cmp::Ordering>
2231 where
2232 V: AsValueRef,
2233 E: ExactSizeIterator<Item = V>,
2234 I: IntoIterator<IntoIter = E, Item = E::Item>,
2235 {
2236 let unpacked = unpacked.into_iter();
2237 match self {
2238 RecordCompare::Int => {
2239 compare_records_int(serialized, unpacked, index_info, tie_breaker)
2240 }
2241 RecordCompare::String => {
2242 compare_records_string(serialized, unpacked, index_info, tie_breaker)
2243 }
2244 RecordCompare::Generic => {
2245 compare_records_generic(serialized, unpacked, index_info, skip, tie_breaker)
2246 }
2247 }
2248 }
2249}
2250
2251pub fn find_compare<I, E, V>(unpacked: I, index_info: &IndexInfo) -> RecordCompare
2252where
2253 V: AsValueRef,
2254 E: ExactSizeIterator<Item = V>,
2255 I: IntoIterator<IntoIter = Peekable<E>, Item = V>,
2256{
2257 let mut unpacked = unpacked.into_iter();
2258 if unpacked.len() != 0 && index_info.num_cols <= 13 {
2259 let val = unpacked.peek().unwrap();
2260 match val.as_value_ref() {
2261 ValueRef::Numeric(Numeric::Integer(_)) => RecordCompare::Int,
2262 ValueRef::Text(_) if index_info.key_info[0].collation == CollationSeq::Binary => {
2263 RecordCompare::String
2264 }
2265 _ => RecordCompare::Generic,
2266 }
2267 } else {
2268 RecordCompare::Generic
2269 }
2270}
2271
2272pub fn get_tie_breaker_from_seek_op(seek_op: SeekOp) -> std::cmp::Ordering {
2273 match seek_op {
2274 SeekOp::GE { eq_only: true } | SeekOp::LE { eq_only: true } => std::cmp::Ordering::Equal,
2276
2277 SeekOp::GE { eq_only: false } => std::cmp::Ordering::Greater,
2279 SeekOp::GT => std::cmp::Ordering::Less,
2280
2281 SeekOp::LE { eq_only: false } => std::cmp::Ordering::Less,
2283 SeekOp::LT => std::cmp::Ordering::Greater,
2284 }
2285}
2286
2287fn compare_records_int<V, I>(
2327 serialized: &ImmutableRecord,
2328 unpacked: I,
2329 index_info: &IndexInfo,
2330 tie_breaker: std::cmp::Ordering,
2331) -> Result<std::cmp::Ordering>
2332where
2333 V: AsValueRef,
2334 I: ExactSizeIterator<Item = V>,
2335{
2336 let payload = serialized.get_payload();
2337 if payload.len() < 2 {
2338 return compare_records_generic(serialized, unpacked, index_info, 0, tie_breaker);
2339 }
2340
2341 let (header_size, offset_1st_serialtype) = read_varint(payload)?;
2342 let header_size = header_size as usize;
2343
2344 if payload.len() < header_size {
2345 return Err(LimboError::Corrupt(format!(
2346 "Record payload too short: claimed header size {} but payload only {} bytes",
2347 header_size,
2348 payload.len()
2349 )));
2350 }
2351
2352 let (first_serial_type, _) = read_varint(&payload[offset_1st_serialtype..])?;
2353
2354 let serialtype_is_integer = matches!(first_serial_type, 1..=6 | 8 | 9);
2355 if !serialtype_is_integer {
2356 return compare_records_generic(serialized, unpacked, index_info, 0, tie_breaker);
2357 }
2358
2359 let data_start = header_size;
2360
2361 let lhs_int = read_integer(&payload[data_start..], first_serial_type as u8)?;
2362 let mut unpacked = unpacked.peekable();
2363 let ValueRef::Numeric(Numeric::Integer(rhs_int)) = unpacked.peek().unwrap().as_value_ref()
2365 else {
2366 return compare_records_generic(serialized, unpacked, index_info, 0, tie_breaker);
2367 };
2368 let comparison = match index_info.key_info[0].sort_order {
2369 SortOrder::Asc => lhs_int.cmp(&rhs_int),
2370 SortOrder::Desc => lhs_int.cmp(&rhs_int).reverse(),
2371 };
2372 match comparison {
2373 std::cmp::Ordering::Equal => {
2374 if unpacked.len() > 1 {
2376 return compare_records_generic(serialized, unpacked, index_info, 1, tie_breaker);
2377 }
2378 Ok(tie_breaker)
2379 }
2380 other => Ok(other),
2381 }
2382}
2383
2384fn compare_records_string<V, I>(
2423 serialized: &ImmutableRecord,
2424 unpacked: I,
2425 index_info: &IndexInfo,
2426 tie_breaker: std::cmp::Ordering,
2427) -> Result<std::cmp::Ordering>
2428where
2429 V: AsValueRef,
2430 I: ExactSizeIterator<Item = V>,
2431{
2432 let payload = serialized.get_payload();
2433 if payload.len() < 2 {
2434 return compare_records_generic(serialized, unpacked, index_info, 0, tie_breaker);
2435 }
2436
2437 let (header_size, offset_1st_serialtype) = read_varint(payload)?;
2438 let header_size = header_size as usize;
2439
2440 if payload.len() < header_size {
2441 return Err(LimboError::Corrupt(format!(
2442 "Record payload too short: claimed header size {} but payload only {} bytes",
2443 header_size,
2444 payload.len()
2445 )));
2446 }
2447
2448 let (first_serial_type, _) = read_varint(&payload[offset_1st_serialtype..])?;
2449
2450 let serialtype_is_string = first_serial_type >= 13 && (first_serial_type & 1) == 1;
2451 if !serialtype_is_string {
2452 return compare_records_generic(serialized, unpacked, index_info, 0, tie_breaker);
2453 }
2454
2455 let mut unpacked = unpacked.peekable();
2456
2457 let ValueRef::Text(rhs_text) = unpacked.peek().unwrap().as_value_ref() else {
2458 return compare_records_generic(serialized, unpacked, index_info, 0, tie_breaker);
2459 };
2460
2461 let string_len = (first_serial_type as usize - 13) / 2;
2462 let data_start = header_size;
2463
2464 turso_debug_assert!(data_start + string_len <= payload.len());
2465
2466 let serial_type = SerialType::try_from(first_serial_type)?;
2467 let (lhs_value, _) = read_value(&payload[data_start..], serial_type)?;
2468
2469 let ValueRef::Text(lhs_text) = lhs_value else {
2470 return compare_records_generic(serialized, unpacked, index_info, 0, tie_breaker);
2471 };
2472
2473 let collation = index_info.key_info[0].collation;
2474 let comparison = collation.compare_strings(&lhs_text, &rhs_text);
2475
2476 let final_comparison = match index_info.key_info[0].sort_order {
2477 SortOrder::Asc => comparison,
2478 SortOrder::Desc => comparison.reverse(),
2479 };
2480
2481 match final_comparison {
2482 std::cmp::Ordering::Equal => {
2483 let len_cmp = lhs_text.len().cmp(&rhs_text.len());
2484 if len_cmp != std::cmp::Ordering::Equal {
2485 let adjusted = match index_info.key_info[0].sort_order {
2486 SortOrder::Asc => len_cmp,
2487 SortOrder::Desc => len_cmp.reverse(),
2488 };
2489 return Ok(adjusted);
2490 }
2491
2492 if unpacked.len() > 1 {
2493 return compare_records_generic(serialized, unpacked, index_info, 1, tie_breaker);
2494 }
2495 Ok(tie_breaker)
2496 }
2497 other => Ok(other),
2498 }
2499}
2500
2501pub fn compare_records_generic<V, I>(
2534 serialized: &ImmutableRecord,
2535 unpacked: I,
2536 index_info: &IndexInfo,
2537 skip: usize,
2538 tie_breaker: std::cmp::Ordering,
2539) -> Result<std::cmp::Ordering>
2540where
2541 V: AsValueRef,
2542 I: ExactSizeIterator<Item = V>,
2543{
2544 let payload = serialized.get_payload();
2545 if payload.is_empty() {
2546 return Ok(std::cmp::Ordering::Less);
2547 }
2548
2549 let (header_size, mut header_pos) = read_varint(payload)?;
2550 let header_end = header_size as usize;
2551 turso_debug_assert!(header_end <= payload.len());
2552
2553 let mut data_pos = header_size as usize;
2554
2555 for _ in 0..skip {
2557 if header_pos >= header_end {
2558 break;
2559 }
2560
2561 let (serial_type_raw, bytes_read) = read_varint(&payload[header_pos..])?;
2562 header_pos += bytes_read;
2563
2564 let serial_type = SerialType::try_from(serial_type_raw)?;
2565 if !matches!(
2566 serial_type.kind(),
2567 SerialTypeKind::ConstInt0 | SerialTypeKind::ConstInt1 | SerialTypeKind::Null
2568 ) {
2569 data_pos += serial_type.size();
2570 }
2571 }
2572
2573 let mut field_idx = skip;
2574 let field_limit = unpacked.len().min(index_info.key_info.len());
2575
2576 for rhs_value in unpacked.skip(skip) {
2578 let rhs_value = &rhs_value.as_value_ref();
2579 if field_idx >= field_limit || header_pos >= header_end {
2580 break;
2581 }
2582 let (serial_type_raw, bytes_read) = read_varint(&payload[header_pos..])?;
2583 header_pos += bytes_read;
2584
2585 let serial_type = SerialType::try_from(serial_type_raw)?;
2586
2587 let lhs_value = match serial_type.kind() {
2588 SerialTypeKind::ConstInt0 => ValueRef::Numeric(Numeric::Integer(0)),
2589 SerialTypeKind::ConstInt1 => ValueRef::Numeric(Numeric::Integer(1)),
2590 SerialTypeKind::Null => ValueRef::Null,
2591 _ => {
2592 let (value, field_size) = read_value(&payload[data_pos..], serial_type)?;
2593 data_pos += field_size;
2594 value
2595 }
2596 };
2597
2598 let comparison = match (&lhs_value, rhs_value) {
2599 (ValueRef::Text(lhs_text), ValueRef::Text(rhs_text)) => index_info.key_info[field_idx]
2600 .collation
2601 .compare_strings(lhs_text, rhs_text),
2602
2603 _ => lhs_value.cmp(rhs_value),
2604 };
2605
2606 let final_comparison = match index_info.key_info[field_idx].sort_order {
2607 SortOrder::Asc => comparison,
2608 SortOrder::Desc => comparison.reverse(),
2609 };
2610
2611 if final_comparison != std::cmp::Ordering::Equal {
2612 return Ok(final_comparison);
2613 }
2614
2615 field_idx += 1;
2616 }
2617
2618 Ok(tie_breaker)
2619}
2620
2621const I8_LOW: i64 = -128;
2622const I8_HIGH: i64 = 127;
2623const I16_LOW: i64 = -32768;
2624const I16_HIGH: i64 = 32767;
2625const I24_LOW: i64 = -8388608;
2626const I24_HIGH: i64 = 8388607;
2627const I32_LOW: i64 = -2147483648;
2628const I32_HIGH: i64 = 2147483647;
2629const I48_LOW: i64 = -140737488355328;
2630const I48_HIGH: i64 = 140737488355327;
2631
2632#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
2635#[repr(transparent)]
2636pub struct SerialType(u64);
2637
2638#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
2639pub enum SerialTypeKind {
2640 Null,
2641 I8,
2642 I16,
2643 I24,
2644 I32,
2645 I48,
2646 I64,
2647 F64,
2648 ConstInt0,
2649 ConstInt1,
2650 Text,
2651 Blob,
2652}
2653
2654impl SerialType {
2655 #[inline(always)]
2656 pub fn u64_is_valid_serial_type(n: u64) -> bool {
2657 n != 10 && n != 11
2658 }
2659
2660 const NULL: Self = Self(0);
2661 const I8: Self = Self(1);
2662 const I16: Self = Self(2);
2663 const I24: Self = Self(3);
2664 const I32: Self = Self(4);
2665 const I48: Self = Self(5);
2666 const I64: Self = Self(6);
2667 const F64: Self = Self(7);
2668 const CONST_INT0: Self = Self(8);
2669 const CONST_INT1: Self = Self(9);
2670
2671 pub const fn null() -> Self {
2672 Self::NULL
2673 }
2674
2675 pub const fn i8() -> Self {
2676 Self::I8
2677 }
2678
2679 pub const fn i16() -> Self {
2680 Self::I16
2681 }
2682
2683 pub const fn i24() -> Self {
2684 Self::I24
2685 }
2686
2687 pub const fn i32() -> Self {
2688 Self::I32
2689 }
2690
2691 pub const fn i48() -> Self {
2692 Self::I48
2693 }
2694
2695 pub const fn i64() -> Self {
2696 Self::I64
2697 }
2698
2699 pub const fn f64() -> Self {
2700 Self::F64
2701 }
2702
2703 pub const fn const_int0() -> Self {
2704 Self::CONST_INT0
2705 }
2706
2707 pub const fn const_int1() -> Self {
2708 Self::CONST_INT1
2709 }
2710
2711 pub const fn blob(size: u64) -> Self {
2712 Self(12 + size * 2)
2713 }
2714
2715 pub const fn text(size: u64) -> Self {
2716 Self(13 + size * 2)
2717 }
2718
2719 #[inline(always)]
2720 pub const fn kind(&self) -> SerialTypeKind {
2721 match self.0 {
2722 0 => SerialTypeKind::Null,
2723 1 => SerialTypeKind::I8,
2724 2 => SerialTypeKind::I16,
2725 3 => SerialTypeKind::I24,
2726 4 => SerialTypeKind::I32,
2727 5 => SerialTypeKind::I48,
2728 6 => SerialTypeKind::I64,
2729 7 => SerialTypeKind::F64,
2730 8 => SerialTypeKind::ConstInt0,
2731 9 => SerialTypeKind::ConstInt1,
2732 n if n >= 12 => match n % 2 {
2733 0 => SerialTypeKind::Blob,
2734 1 => SerialTypeKind::Text,
2735 _ => {
2736 mark_unlikely();
2737 unreachable!();
2738 }
2739 },
2740 _ => {
2741 mark_unlikely();
2742 unreachable!();
2743 }
2744 }
2745 }
2746
2747 pub const fn size(&self) -> usize {
2748 match self.kind() {
2749 SerialTypeKind::Null => 0,
2750 SerialTypeKind::I8 => 1,
2751 SerialTypeKind::I16 => 2,
2752 SerialTypeKind::I24 => 3,
2753 SerialTypeKind::I32 => 4,
2754 SerialTypeKind::I48 => 6,
2755 SerialTypeKind::I64 => 8,
2756 SerialTypeKind::F64 => 8,
2757 SerialTypeKind::ConstInt0 => 0,
2758 SerialTypeKind::ConstInt1 => 0,
2759 SerialTypeKind::Text => (self.0 as usize - 13) / 2,
2760 SerialTypeKind::Blob => (self.0 as usize - 12) / 2,
2761 }
2762 }
2763}
2764
2765#[inline(always)]
2766pub fn get_serial_type_size(serial: u64) -> Result<usize> {
2767 match serial {
2768 0 | 8 | 9 => Ok(0),
2769 1 => Ok(1),
2770 2 => Ok(2),
2771 3 => Ok(3),
2772 4 => Ok(4),
2773 5 => Ok(6),
2774 6 | 7 => Ok(8),
2775 n if n >= 12 => match n % 2 {
2776 0 => Ok(((n - 12) / 2) as usize), 1 => Ok(((n - 13) / 2) as usize), _ => {
2779 mark_unlikely();
2780 unreachable!();
2781 }
2782 },
2783 _ => {
2784 mark_unlikely();
2785 Err(LimboError::Corrupt(format!(
2786 "Invalid serial type: {serial}"
2787 )))
2788 }
2789 }
2790}
2791
2792impl<T: AsValueRef> From<T> for SerialType {
2793 fn from(value: T) -> Self {
2794 let value = value.as_value_ref();
2795 match value {
2796 ValueRef::Null => SerialType::null(),
2797 ValueRef::Numeric(Numeric::Integer(i)) => match i {
2798 0 => SerialType::const_int0(),
2799 1 => SerialType::const_int1(),
2800 i if (I8_LOW..=I8_HIGH).contains(&i) => SerialType::i8(),
2801 i if (I16_LOW..=I16_HIGH).contains(&i) => SerialType::i16(),
2802 i if (I24_LOW..=I24_HIGH).contains(&i) => SerialType::i24(),
2803 i if (I32_LOW..=I32_HIGH).contains(&i) => SerialType::i32(),
2804 i if (I48_LOW..=I48_HIGH).contains(&i) => SerialType::i48(),
2805 _ => SerialType::i64(),
2806 },
2807 ValueRef::Numeric(Numeric::Float(_)) => SerialType::f64(),
2808 ValueRef::Text(t) => SerialType::text(t.value.len() as u64),
2809 ValueRef::Blob(b) => SerialType::blob(b.len() as u64),
2810 }
2811 }
2812}
2813
2814impl From<SerialType> for u64 {
2815 fn from(serial_type: SerialType) -> Self {
2816 serial_type.0
2817 }
2818}
2819
2820impl TryFrom<u64> for SerialType {
2821 type Error = LimboError;
2822
2823 #[inline(always)]
2824 fn try_from(uint: u64) -> Result<Self> {
2825 if unlikely(uint == 10 || uint == 11) {
2826 return Err(LimboError::Corrupt(format!("Invalid serial type: {uint}")));
2827 }
2828 Ok(SerialType(uint))
2829 }
2830}
2831
2832impl Record {
2833 pub fn new(values: Vec<Value>) -> Self {
2834 Self { values }
2835 }
2836
2837 pub fn calc_header_size(sizeof_serial_types: usize) -> usize {
2846 if sizeof_serial_types < i8::MAX as usize {
2847 return sizeof_serial_types + 1;
2848 }
2849
2850 let mut header_size = sizeof_serial_types;
2851 let mut temp_buf = [0u8; 9];
2853 let mut prev_header_size;
2854
2855 loop {
2856 prev_header_size = header_size;
2857 let varint_len = write_varint(&mut temp_buf, header_size as u64);
2858 header_size = sizeof_serial_types + varint_len;
2859
2860 if header_size == prev_header_size {
2861 break;
2862 }
2863 }
2864
2865 header_size
2866 }
2867
2868 pub fn serialize(&self, buf: &mut std::vec::Vec<u8>) {
2869 let initial_i = buf.len();
2870
2871 for value in &self.values {
2873 let serial_type = SerialType::from(value);
2874 buf.resize(buf.len() + 9, 0); let len = buf.len();
2876 let n = write_varint(&mut buf[len - 9..], serial_type.into());
2877 buf.truncate(buf.len() - 9 + n); }
2879
2880 let mut header_size = buf.len() - initial_i;
2881 for value in &self.values {
2883 match value {
2884 Value::Null => {}
2885 Value::Numeric(Numeric::Integer(i)) => {
2886 let serial_type = SerialType::from(value);
2887 match serial_type.kind() {
2888 SerialTypeKind::ConstInt0 | SerialTypeKind::ConstInt1 => {}
2889 SerialTypeKind::I8 => buf.extend_from_slice(&(*i as i8).to_be_bytes()),
2890 SerialTypeKind::I16 => buf.extend_from_slice(&(*i as i16).to_be_bytes()),
2891 SerialTypeKind::I24 => {
2892 buf.extend_from_slice(&(*i as i32).to_be_bytes()[1..])
2893 } SerialTypeKind::I32 => buf.extend_from_slice(&(*i as i32).to_be_bytes()),
2895 SerialTypeKind::I48 => buf.extend_from_slice(&i.to_be_bytes()[2..]), SerialTypeKind::I64 => buf.extend_from_slice(&i.to_be_bytes()),
2897 _ => {
2898 mark_unlikely();
2899 unreachable!();
2900 }
2901 }
2902 }
2903 Value::Numeric(Numeric::Float(f)) => {
2904 buf.extend_from_slice(&f64::from(*f).to_be_bytes())
2905 }
2906 Value::Text(t) => buf.extend_from_slice(t.value.as_bytes()),
2907 Value::Blob(b) => buf.extend_from_slice(b),
2908 };
2909 }
2910
2911 let mut header_bytes_buf = std::vec::Vec::new();
2912 header_size = Record::calc_header_size(header_size);
2913 header_bytes_buf.extend(std::iter::repeat_n(0, 9));
2914 let n = write_varint(header_bytes_buf.as_mut_slice(), header_size as u64);
2915 header_bytes_buf.truncate(n);
2916 buf.splice(initial_i..initial_i, header_bytes_buf.iter().cloned());
2917 }
2918}
2919
2920pub enum Cursor {
2921 BTree(Box<dyn CursorTrait>),
2922 IndexMethod(Box<dyn IndexMethodCursor>),
2923 Pseudo(Box<PseudoCursor>),
2924 Sorter(Box<Sorter>),
2925 Virtual(VirtualTableCursor),
2926 MaterializedView(Box<crate::incremental::cursor::MaterializedViewCursor>),
2927}
2928
2929impl Debug for Cursor {
2930 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2931 match self {
2932 Self::BTree(..) => f.debug_tuple("BTree").finish(),
2933 Self::IndexMethod(..) => f.debug_tuple("IndexMethod").finish(),
2934 Self::Pseudo(..) => f.debug_tuple("Pseudo").finish(),
2935 Self::Sorter(..) => f.debug_tuple("Sorter").finish(),
2936 Self::Virtual(..) => f.debug_tuple("Virtual").finish(),
2937 Self::MaterializedView(..) => f.debug_tuple("MaterializedView").finish(),
2938 }
2939 }
2940}
2941
2942impl Cursor {
2943 pub fn new_btree(cursor: Box<dyn CursorTrait>) -> Self {
2944 cursor.register_with_pager();
2946 Self::BTree(cursor)
2947 }
2948
2949 pub fn new_pseudo(cursor: PseudoCursor) -> Self {
2950 Self::Pseudo(Box::new(cursor))
2951 }
2952
2953 pub fn new_sorter(cursor: Sorter) -> Self {
2954 Self::Sorter(Box::new(cursor))
2955 }
2956
2957 pub fn new_materialized_view(
2958 cursor: crate::incremental::cursor::MaterializedViewCursor,
2959 ) -> Self {
2960 Self::MaterializedView(Box::new(cursor))
2961 }
2962
2963 pub fn as_btree_mut(&mut self) -> &mut dyn CursorTrait {
2964 match self {
2965 Self::BTree(cursor) => cursor.as_mut(),
2966 _ => {
2967 mark_unlikely();
2968 panic!("Cursor is not a btree cursor");
2969 }
2970 }
2971 }
2972
2973 pub fn as_pseudo_mut(&mut self) -> &mut PseudoCursor {
2974 match self {
2975 Self::Pseudo(cursor) => cursor,
2976 _ => {
2977 mark_unlikely();
2978 panic!("Cursor is not a pseudo cursor");
2979 }
2980 }
2981 }
2982
2983 pub fn as_sorter_mut(&mut self) -> &mut Sorter {
2984 match self {
2985 Self::Sorter(cursor) => cursor,
2986 _ => {
2987 mark_unlikely();
2988 panic!("Cursor is not a sorter cursor")
2989 }
2990 }
2991 }
2992
2993 pub fn as_virtual_mut(&mut self) -> &mut VirtualTableCursor {
2994 match self {
2995 Self::Virtual(cursor) => cursor,
2996 _ => {
2997 mark_unlikely();
2998 panic!("Cursor is not a virtual cursor")
2999 }
3000 }
3001 }
3002
3003 pub fn as_materialized_view_mut(
3004 &mut self,
3005 ) -> &mut crate::incremental::cursor::MaterializedViewCursor {
3006 match self {
3007 Self::MaterializedView(cursor) => cursor,
3008 _ => {
3009 mark_unlikely();
3010 panic!("Cursor is not a materialized view cursor");
3011 }
3012 }
3013 }
3014
3015 pub fn as_index_method_mut(&mut self) -> &mut dyn IndexMethodCursor {
3016 match self {
3017 Self::IndexMethod(cursor) => cursor.as_mut(),
3018 _ => {
3019 mark_unlikely();
3020 panic!("Cursor is not an IndexMethod cursor");
3021 }
3022 }
3023 }
3024
3025 pub fn set_null_flag(&mut self, flag: bool) {
3027 match self {
3028 Self::BTree(cursor) => cursor.set_null_flag(flag),
3029 Self::Virtual(cursor) => cursor.set_null_flag(flag),
3030 _ => {
3031 mark_unlikely();
3032 panic!("set_null_flag on unexpected cursor type");
3033 }
3034 }
3035 }
3036}
3037
3038#[derive(Debug)]
3039#[must_use]
3040pub enum IOCompletions {
3041 Single(Completion),
3042}
3043
3044pub struct IOCompletionAsync<'a, I: ?Sized + IO> {
3045 io: &'a I,
3046 completion: Completion,
3047}
3048
3049impl<'a, I: ?Sized + IO> Future for IOCompletionAsync<'a, I> {
3050 type Output = Result<()>;
3051
3052 fn poll(
3053 mut self: std::pin::Pin<&mut Self>,
3054 cx: &mut std::task::Context<'_>,
3055 ) -> std::task::Poll<Self::Output> {
3056 let completion = std::pin::pin!(&mut self.as_mut().completion);
3057 match completion.poll(cx) {
3058 Poll::Pending => {
3059 self.io.step()?;
3060 Poll::Pending
3061 }
3062 res => res,
3063 }
3064 }
3065}
3066
3067impl IOCompletions {
3068 pub fn wait<I: ?Sized + IO>(self, io: &I) -> Result<()> {
3070 match self {
3071 IOCompletions::Single(c) => io.wait_for_completion(c),
3072 }
3073 }
3074
3075 pub async fn wait_async<I: ?Sized + IO>(self, io: &I) -> Result<()> {
3078 match self {
3079 IOCompletions::Single(c) => IOCompletionAsync { io, completion: c }.await,
3080 }
3081 }
3082
3083 pub fn finished(&self) -> bool {
3084 match self {
3085 IOCompletions::Single(c) => c.finished(),
3086 }
3087 }
3088
3089 pub fn is_explicit_yield(&self) -> bool {
3092 match self {
3093 IOCompletions::Single(c) => c.is_explicit_yield(),
3094 }
3095 }
3096
3097 pub fn abort(&self) {
3099 match self {
3100 IOCompletions::Single(c) => c.abort(),
3101 }
3102 }
3103
3104 pub fn get_error(&self) -> Option<CompletionError> {
3105 match self {
3106 IOCompletions::Single(c) => c.get_error(),
3107 }
3108 }
3109
3110 pub fn set_waker(&self, waker: Option<&Waker>) {
3111 if let Some(waker) = waker {
3112 match self {
3113 IOCompletions::Single(c) => c.set_waker(waker),
3114 }
3115 }
3116 }
3117}
3118
3119#[derive(Debug)]
3120#[must_use]
3121pub enum IOResult<T> {
3122 Done(T),
3123 IO(IOCompletions),
3124}
3125
3126impl<T> IOResult<T> {
3127 #[inline]
3128 pub fn is_io(&self) -> bool {
3129 matches!(self, IOResult::IO(..))
3130 }
3131
3132 #[inline]
3133 pub fn io(self) -> Option<IOCompletions> {
3134 match self {
3135 IOResult::Done(_) => None,
3136 IOResult::IO(io) => Some(io),
3137 }
3138 }
3139
3140 #[inline]
3141 pub fn map<U>(self, func: impl FnOnce(T) -> U) -> IOResult<U> {
3142 match self {
3143 IOResult::Done(t) => IOResult::Done(func(t)),
3144 IOResult::IO(io) => IOResult::IO(io),
3145 }
3146 }
3147}
3148
3149#[macro_export]
3151macro_rules! return_if_io {
3152 ($expr:expr) => {
3153 match $expr {
3154 Ok(IOResult::Done(v)) => v,
3155 Ok(IOResult::IO(io)) => return Ok(IOResult::IO(io)),
3156 Err(err) => {
3157 branches::mark_unlikely();
3158 return Err(err);
3159 }
3160 }
3161 };
3162}
3163
3164#[macro_export]
3165macro_rules! return_and_restore_if_io {
3166 ($field:expr, $saved_state:expr, $e:expr) => {
3167 match $e {
3168 Ok(IOResult::Done(v)) => v,
3169 Ok(IOResult::IO(io)) => {
3170 let _ = std::mem::replace($field, $saved_state);
3171 return Ok(IOResult::IO(io));
3172 }
3173 Err(e) => {
3174 let _ = std::mem::replace($field, $saved_state);
3175 return Err(e);
3176 }
3177 }
3178 };
3179}
3180
3181#[derive(Debug, PartialEq, Clone, Copy)]
3182pub enum SeekResult {
3183 Found,
3185 NotFound,
3187 TryAdvance,
3196}
3197
3198#[derive(Clone, Copy, PartialEq, Eq, Debug)]
3199pub enum SeekOp {
3201 GE {
3204 eq_only: bool,
3205 },
3206 GT,
3207 LE {
3210 eq_only: bool,
3211 },
3212 LT,
3213}
3214
3215impl SeekOp {
3216 #[inline(always)]
3226 pub fn iteration_direction(&self) -> IterationDirection {
3227 match self {
3228 SeekOp::GE { .. } | SeekOp::GT => IterationDirection::Forwards,
3229 SeekOp::LE { .. } | SeekOp::LT => IterationDirection::Backwards,
3230 }
3231 }
3232
3233 pub fn eq_only(&self) -> bool {
3234 match self {
3235 SeekOp::GE { eq_only } | SeekOp::LE { eq_only } => *eq_only,
3236 _ => false,
3237 }
3238 }
3239
3240 pub fn reverse(&self) -> Self {
3241 match self {
3242 SeekOp::GE { eq_only } => SeekOp::LE { eq_only: *eq_only },
3243 SeekOp::GT => SeekOp::LT,
3244 SeekOp::LE { eq_only } => SeekOp::GE { eq_only: *eq_only },
3245 SeekOp::LT => SeekOp::GT,
3246 }
3247 }
3248}
3249
3250#[derive(Clone, PartialEq, Debug)]
3251pub enum SeekKey<'a> {
3252 TableRowId(i64),
3253 IndexKey(&'a ImmutableRecord),
3254}
3255
3256#[derive(Debug)]
3257pub enum DatabaseChangeType {
3258 Delete,
3259 Update { bin_record: std::vec::Vec<u8> },
3260 Insert { bin_record: std::vec::Vec<u8> },
3261}
3262
3263#[derive(Debug)]
3264pub struct DatabaseChange {
3265 pub change_id: i64,
3266 pub change_time: u64,
3267 pub change: DatabaseChangeType,
3268 pub table_name: String,
3269 pub id: i64,
3270}
3271
3272#[derive(Debug)]
3273pub struct WalFrameInfo {
3274 pub page_no: u32,
3275 pub db_size: u32,
3276}
3277
3278#[derive(Debug, PartialEq)]
3279pub struct WalState {
3280 pub checkpoint_seq_no: u32,
3281 pub max_frame: u64,
3282}
3283
3284impl WalFrameInfo {
3285 pub fn is_commit_frame(&self) -> bool {
3286 self.db_size > 0
3287 }
3288 pub fn from_frame_header(frame: &[u8]) -> Self {
3289 let page_no = u32::from_be_bytes(frame[0..4].try_into().unwrap());
3290 let db_size = u32::from_be_bytes(frame[4..8].try_into().unwrap());
3291 Self { page_no, db_size }
3292 }
3293 pub fn put_to_frame_header(&self, frame: &mut [u8]) {
3294 frame[0..4].copy_from_slice(&self.page_no.to_be_bytes());
3295 frame[4..8].copy_from_slice(&self.db_size.to_be_bytes());
3296 }
3297}
3298
3299#[cfg(clt_turso_tests)]
3300mod tests {
3301 use super::*;
3302 use crate::alloc::vec;
3303 use crate::translate::collate::CollationSeq;
3304
3305 #[test]
3306 fn test_value_iterator_simple() {
3307 let mut buf = std::vec::Vec::new();
3308 let record = Record::new(vec![Value::from_i64(42), Value::Text(Text::new("hello"))]);
3309 record.serialize(&mut buf);
3310
3311 let iter = ValueIterator::new(&buf).unwrap();
3312 assert!(!iter.is_empty());
3313 assert_eq!(iter.clone().count(), 2);
3314
3315 let mut iter = ValueIterator::new(&buf).unwrap();
3316
3317 let val = iter.next().unwrap().unwrap();
3318 assert_eq!(val, ValueRef::from_i64(42));
3319
3320 let val = iter.next().unwrap().unwrap();
3321 assert_eq!(
3322 val,
3323 ValueRef::Text(TextRef::new("hello", TextSubtype::Text))
3324 );
3325
3326 assert!(iter.next().is_none());
3327 }
3328
3329 #[test]
3330 fn test_value_iterator_nulls() {
3331 let mut buf = std::vec::Vec::new();
3332 let record = Record::new(vec![Value::Null, Value::Null, Value::Null]);
3333 record.serialize(&mut buf);
3334
3335 let iter = ValueIterator::new(&buf).unwrap();
3336
3337 for val in iter {
3338 assert_eq!(val.unwrap(), ValueRef::Null);
3339 }
3340 }
3341
3342 #[test]
3343 fn test_value_iterator_mixed_types() {
3344 let mut buf = std::vec::Vec::new();
3345 let record = Record::new(vec![
3346 Value::Null,
3347 Value::from_i64(100),
3348 Value::from_f64(std::f64::consts::PI),
3349 Value::Text(Text::new("test")),
3350 Value::Blob(std::vec![1, 2, 3]),
3351 Value::from_i64(0),
3352 Value::from_i64(1),
3353 ]);
3354 record.serialize(&mut buf);
3355
3356 let iter = ValueIterator::new(&buf).unwrap();
3357 let values: Vec<_> = iter.try_collect::<Result<Vec<_>>>().unwrap().unwrap();
3358
3359 assert_eq!(values[0], ValueRef::Null);
3360 assert_eq!(values[1], ValueRef::from_i64(100));
3361 assert_eq!(values[2], ValueRef::from_f64(std::f64::consts::PI));
3362 assert_eq!(
3363 values[3],
3364 ValueRef::Text(TextRef::new("test", TextSubtype::Text))
3365 );
3366 assert_eq!(values[4], ValueRef::Blob(&[1, 2, 3]));
3367 assert_eq!(values[5], ValueRef::from_i64(0));
3368 assert_eq!(values[6], ValueRef::from_i64(1));
3369 }
3370
3371 #[test]
3372 fn test_value_iterator_large_record() {
3373 let mut buf = std::vec::Vec::new();
3374 let values: Vec<Value> = (0..20)
3375 .map(|i| Value::from_i64(i as i64))
3376 .try_collect()
3377 .unwrap();
3378 let record = Record::new(values);
3379 record.serialize(&mut buf);
3380
3381 let iter = ValueIterator::new(&buf).unwrap();
3382 assert_eq!(iter.count(), 20);
3383
3384 let iter = ValueIterator::new(&buf).unwrap();
3385 for (i, val) in iter.enumerate() {
3386 assert_eq!(val.unwrap(), ValueRef::from_i64(i as i64));
3387 }
3388 }
3389
3390 #[test]
3391 fn test_value_iterator_zero_allocation() {
3392 let mut buf = std::vec::Vec::new();
3393 let values: Vec<Value> = (0..5)
3394 .map(|i| Value::from_i64(i as i64))
3395 .try_collect()
3396 .unwrap();
3397 let record = Record::new(values);
3398 record.serialize(&mut buf);
3399
3400 let mut iter = ValueIterator::new(&buf).unwrap();
3401 let _ = iter.next();
3402 let _ = iter.next();
3403 }
3404
3405 pub fn compare_immutable_for_testing(
3406 l: &[ValueRef],
3407 r: &[ValueRef],
3408 index_key_info: &[KeyInfo],
3409 tie_breaker: std::cmp::Ordering,
3410 ) -> std::cmp::Ordering {
3411 let min_len = l.len().min(r.len());
3412
3413 for i in 0..min_len {
3414 let column_order = index_key_info[i].sort_order;
3415 let collation = index_key_info[i].collation;
3416
3417 let cmp = match (&l[i], &r[i]) {
3418 (ValueRef::Text(left), ValueRef::Text(right)) => {
3419 collation.compare_strings(left, right)
3420 }
3421 _ => l[i].partial_cmp(&r[i]).unwrap_or(std::cmp::Ordering::Equal),
3422 };
3423
3424 if cmp != std::cmp::Ordering::Equal {
3425 return match column_order {
3426 SortOrder::Asc => cmp,
3427 SortOrder::Desc => cmp.reverse(),
3428 };
3429 }
3430 }
3431
3432 tie_breaker
3433 }
3434
3435 fn create_record(values: Vec<Value>) -> ImmutableRecord {
3436 let registers: Vec<Register> = values
3437 .into_iter()
3438 .map(Register::Value)
3439 .try_collect()
3440 .unwrap();
3441 ImmutableRecord::from_registers(®isters, registers.len()).unwrap()
3442 }
3443
3444 #[test]
3445 fn immutable_record_ref_borrows_bin_record_payload() {
3446 let expected_values = vec![Value::from_i64(42), Value::build_text("borrowed")];
3447 let record = create_record(expected_values.clone());
3448 let payload = record.get_payload();
3449
3450 let borrowed = ImmutableRecordRef::from_bin_record(payload);
3451
3452 assert_eq!(borrowed.get_payload().as_ptr(), payload.as_ptr());
3453 assert_eq!(borrowed.column_count(), 2);
3454 assert_eq!(borrowed.get_values_owned().unwrap(), expected_values);
3455 }
3456
3457 fn create_index_info(
3458 num_cols: usize,
3459 sort_orders: Vec<SortOrder>,
3460 collations: Vec<CollationSeq>,
3461 ) -> IndexInfo {
3462 IndexInfo::new(
3463 sort_orders
3464 .into_iter()
3465 .zip(collations)
3466 .map(|(sort_order, collation)| KeyInfo {
3467 sort_order,
3468 collation,
3469 nulls_order: None,
3470 }),
3471 false,
3472 num_cols,
3473 false,
3474 )
3475 .unwrap()
3476 }
3477
3478 fn assert_compare_matches_full_comparison(
3479 serialized_values: Vec<Value>,
3480 unpacked_values: Vec<ValueRef>,
3481 index_info: &IndexInfo,
3482 test_name: &str,
3483 ) {
3484 let serialized = create_record(serialized_values.clone());
3485
3486 let serialized_ref_values: Vec<ValueRef> = serialized_values
3487 .iter()
3488 .map(Value::as_ref)
3489 .try_collect()
3490 .unwrap();
3491
3492 let tie_breaker = std::cmp::Ordering::Equal;
3493
3494 let gold_result = compare_immutable_for_testing(
3495 &serialized_ref_values,
3496 &unpacked_values,
3497 &index_info.key_info,
3498 tie_breaker,
3499 );
3500
3501 let comparer = find_compare(unpacked_values.iter().peekable(), index_info);
3502 let optimized_result = comparer
3503 .compare(&serialized, &unpacked_values, index_info, 0, tie_breaker)
3504 .unwrap();
3505
3506 assert_eq!(
3507 gold_result, optimized_result,
3508 "Test '{test_name}' failed: Full Comparison: {gold_result:?}, Optimized: {optimized_result:?}, Strategy: {comparer:?}"
3509 );
3510
3511 let generic_result = compare_records_generic(
3512 &serialized,
3513 unpacked_values.iter(),
3514 index_info,
3515 0,
3516 tie_breaker,
3517 )
3518 .unwrap();
3519 assert_eq!(
3520 gold_result, generic_result,
3521 "Test '{test_name}' failed with generic: Full Comparison: {gold_result:?}, Generic: {generic_result:?}\n LHS: {serialized_values:?}\n RHS: {unpacked_values:?}"
3522 );
3523 }
3524
3525 #[test]
3526 fn test_calc_header_size() {
3527 const MIN_SERIALTYPES_SIZE_FOR_1_BYTE_HEADER: usize = 0;
3529 assert_eq!(
3530 Record::calc_header_size(MIN_SERIALTYPES_SIZE_FOR_1_BYTE_HEADER),
3531 MIN_SERIALTYPES_SIZE_FOR_1_BYTE_HEADER + 1
3532 );
3533 const BITS_7_MAX: usize = (1 << 7) - 1; const MAX_SERIALTYPES_SIZE_FOR_1_BYTE_HEADER: usize = BITS_7_MAX - 1;
3535 assert_eq!(
3536 Record::calc_header_size(MAX_SERIALTYPES_SIZE_FOR_1_BYTE_HEADER),
3537 MAX_SERIALTYPES_SIZE_FOR_1_BYTE_HEADER + 1
3538 );
3539
3540 const MIN_SERIALTYPES_SIZE_FOR_2_BYTE_HEADER: usize =
3542 MAX_SERIALTYPES_SIZE_FOR_1_BYTE_HEADER + 1;
3543 assert_eq!(
3544 Record::calc_header_size(MIN_SERIALTYPES_SIZE_FOR_2_BYTE_HEADER),
3545 MIN_SERIALTYPES_SIZE_FOR_2_BYTE_HEADER + 2
3546 );
3547 const BITS_14_MAX: usize = (1 << 14) - 1;
3548 const MAX_SERIALTYPES_SIZE_FOR_2_BYTE_HEADER: usize = BITS_14_MAX - 2;
3549 assert_eq!(
3550 Record::calc_header_size(MAX_SERIALTYPES_SIZE_FOR_2_BYTE_HEADER),
3551 MAX_SERIALTYPES_SIZE_FOR_2_BYTE_HEADER + 2
3552 );
3553
3554 const MIN_SERIALTYPES_SIZE_FOR_3_BYTE_HEADER: usize =
3556 MAX_SERIALTYPES_SIZE_FOR_2_BYTE_HEADER + 1;
3557 assert_eq!(
3558 Record::calc_header_size(MIN_SERIALTYPES_SIZE_FOR_3_BYTE_HEADER),
3559 MIN_SERIALTYPES_SIZE_FOR_3_BYTE_HEADER + 3
3560 );
3561 const BITS_21_MAX: usize = (1 << 21) - 1;
3562 const MAX_SERIALTYPES_SIZE_FOR_3_BYTE_HEADER: usize = BITS_21_MAX - 3;
3563 assert_eq!(
3564 Record::calc_header_size(MAX_SERIALTYPES_SIZE_FOR_3_BYTE_HEADER),
3565 MAX_SERIALTYPES_SIZE_FOR_3_BYTE_HEADER + 3
3566 );
3567
3568 const MIN_SERIALTYPES_SIZE_FOR_4_BYTE_HEADER: usize =
3570 MAX_SERIALTYPES_SIZE_FOR_3_BYTE_HEADER + 1;
3571 assert_eq!(
3572 Record::calc_header_size(MIN_SERIALTYPES_SIZE_FOR_4_BYTE_HEADER),
3573 MIN_SERIALTYPES_SIZE_FOR_4_BYTE_HEADER + 4
3574 );
3575 const BITS_28_MAX: usize = (1 << 28) - 1;
3576 const MAX_SERIALTYPES_SIZE_FOR_4_BYTE_HEADER: usize = BITS_28_MAX - 4;
3577 assert_eq!(
3578 Record::calc_header_size(MAX_SERIALTYPES_SIZE_FOR_4_BYTE_HEADER),
3579 MAX_SERIALTYPES_SIZE_FOR_4_BYTE_HEADER + 4
3580 );
3581 }
3582
3583 #[test]
3584 fn test_integer_fast_path() {
3585 let index_info = create_index_info(
3586 2,
3587 vec![SortOrder::Asc, SortOrder::Asc],
3588 vec![CollationSeq::Binary; 2],
3589 );
3590
3591 let test_cases = vec![
3592 (
3593 vec![Value::from_i64(42)],
3594 vec![ValueRef::from_i64(42)],
3595 "equal_integers",
3596 ),
3597 (
3598 vec![Value::from_i64(10)],
3599 vec![ValueRef::from_i64(20)],
3600 "less_than_integers",
3601 ),
3602 (
3603 vec![Value::from_i64(30)],
3604 vec![ValueRef::from_i64(20)],
3605 "greater_than_integers",
3606 ),
3607 (
3608 vec![Value::from_i64(0)],
3609 vec![ValueRef::from_i64(0)],
3610 "zero_integers",
3611 ),
3612 (
3613 vec![Value::from_i64(-5)],
3614 vec![ValueRef::from_i64(-5)],
3615 "negative_integers",
3616 ),
3617 (
3618 vec![Value::from_i64(i64::MAX)],
3619 vec![ValueRef::from_i64(i64::MAX)],
3620 "max_integers",
3621 ),
3622 (
3623 vec![Value::from_i64(i64::MIN)],
3624 vec![ValueRef::from_i64(i64::MIN)],
3625 "min_integers",
3626 ),
3627 (
3628 vec![Value::from_i64(42), Value::Text(Text::new("hello"))],
3629 vec![
3630 ValueRef::from_i64(42),
3631 ValueRef::Text(TextRef::new("hello", TextSubtype::Text)),
3632 ],
3633 "integer_text_equal",
3634 ),
3635 (
3636 vec![Value::from_i64(42), Value::Text(Text::new("hello"))],
3637 vec![
3638 ValueRef::from_i64(42),
3639 ValueRef::Text(TextRef::new("world", TextSubtype::Text)),
3640 ],
3641 "integer_equal_text_different",
3642 ),
3643 ];
3644
3645 for (serialized_values, unpacked_values, test_name) in test_cases {
3646 println!(
3647 "Testing integer fast path `{test_name}`\nLHS: {serialized_values:?}\nRHS: {unpacked_values:?}"
3648 );
3649 assert_compare_matches_full_comparison(
3650 serialized_values,
3651 unpacked_values,
3652 &index_info,
3653 test_name,
3654 );
3655 }
3656 }
3657
3658 #[test]
3659 fn test_string_fast_path() {
3660 let index_info = create_index_info(
3661 2,
3662 vec![SortOrder::Asc, SortOrder::Asc],
3663 vec![CollationSeq::Binary; 2],
3664 );
3665
3666 let test_cases = vec![
3667 (
3668 vec![Value::Text(Text::new("hello"))],
3669 vec![ValueRef::Text(TextRef::new("hello", TextSubtype::Text))],
3670 "equal_strings",
3671 ),
3672 (
3673 vec![Value::Text(Text::new("abc"))],
3674 vec![ValueRef::Text(TextRef::new("def", TextSubtype::Text))],
3675 "less_than_strings",
3676 ),
3677 (
3678 vec![Value::Text(Text::new("xyz"))],
3679 vec![ValueRef::Text(TextRef::new("abc", TextSubtype::Text))],
3680 "greater_than_strings",
3681 ),
3682 (
3683 vec![Value::Text(Text::new(""))],
3684 vec![ValueRef::Text(TextRef::new("", TextSubtype::Text))],
3685 "empty_strings",
3686 ),
3687 (
3688 vec![Value::Text(Text::new("a"))],
3689 vec![ValueRef::Text(TextRef::new("aa", TextSubtype::Text))],
3690 "prefix_strings",
3691 ),
3692 (
3694 vec![Value::Text(Text::new("hello")), Value::from_i64(42)],
3695 vec![
3696 ValueRef::Text(TextRef::new("hello", TextSubtype::Text)),
3697 ValueRef::from_i64(42),
3698 ],
3699 "string_integer_equal",
3700 ),
3701 (
3702 vec![Value::Text(Text::new("hello")), Value::from_i64(42)],
3703 vec![
3704 ValueRef::Text(TextRef::new("hello", TextSubtype::Text)),
3705 ValueRef::from_i64(99),
3706 ],
3707 "string_equal_integer_different",
3708 ),
3709 ];
3710
3711 for (serialized_values, unpacked_values, test_name) in test_cases {
3712 assert_compare_matches_full_comparison(
3713 serialized_values,
3714 unpacked_values,
3715 &index_info,
3716 test_name,
3717 );
3718 }
3719 }
3720
3721 #[test]
3722 fn test_type_precedence() {
3723 let index_info = create_index_info(1, vec![SortOrder::Asc], vec![CollationSeq::Binary]);
3724
3725 let test_cases = vec![
3727 (
3729 vec![Value::Null],
3730 vec![ValueRef::from_i64(42)],
3731 "null_vs_integer",
3732 ),
3733 (
3734 vec![Value::Null],
3735 vec![ValueRef::from_f64(64.4)],
3736 "null_vs_float",
3737 ),
3738 (
3739 vec![Value::Null],
3740 vec![ValueRef::Text(TextRef::new("hello", TextSubtype::Text))],
3741 "null_vs_text",
3742 ),
3743 (
3744 vec![Value::Null],
3745 vec![ValueRef::Blob(b"blob")],
3746 "null_vs_blob",
3747 ),
3748 (
3750 vec![Value::from_i64(42)],
3751 vec![ValueRef::Text(TextRef::new("hello", TextSubtype::Text))],
3752 "integer_vs_text",
3753 ),
3754 (
3755 vec![Value::from_f64(64.4)],
3756 vec![ValueRef::Text(TextRef::new("hello", TextSubtype::Text))],
3757 "float_vs_text",
3758 ),
3759 (
3760 vec![Value::from_i64(42)],
3761 vec![ValueRef::Blob(b"blob")],
3762 "integer_vs_blob",
3763 ),
3764 (
3765 vec![Value::from_f64(64.4)],
3766 vec![ValueRef::Blob(b"blob")],
3767 "float_vs_blob",
3768 ),
3769 (
3771 vec![Value::Text(Text::new("hello"))],
3772 vec![ValueRef::Blob(b"blob")],
3773 "text_vs_blob",
3774 ),
3775 (
3777 vec![Value::from_i64(42)],
3778 vec![ValueRef::from_f64(42.0)],
3779 "integer_vs_equal_float",
3780 ),
3781 (
3782 vec![Value::from_i64(42)],
3783 vec![ValueRef::from_f64(42.5)],
3784 "integer_vs_different_float",
3785 ),
3786 (
3787 vec![Value::from_f64(42.5)],
3788 vec![ValueRef::from_i64(42)],
3789 "float_vs_integer",
3790 ),
3791 ];
3792
3793 for (serialized_values, unpacked_values, test_name) in test_cases {
3794 assert_compare_matches_full_comparison(
3795 serialized_values,
3796 unpacked_values,
3797 &index_info,
3798 test_name,
3799 );
3800 }
3801 }
3802
3803 #[test]
3804 fn test_sort_order_desc() {
3805 let index_info = create_index_info(
3806 2,
3807 vec![SortOrder::Desc, SortOrder::Asc],
3808 vec![CollationSeq::Binary; 2],
3809 );
3810
3811 let test_cases = vec![
3812 (
3814 vec![Value::from_i64(10)],
3815 vec![ValueRef::from_i64(20)],
3816 "desc_integer_reversed",
3817 ),
3818 (
3819 vec![Value::Text(Text::new("abc"))],
3820 vec![ValueRef::Text(TextRef::new("def", TextSubtype::Text))],
3821 "desc_string_reversed",
3822 ),
3823 (
3825 vec![Value::from_i64(10), Value::Text(Text::new("hello"))],
3826 vec![
3827 ValueRef::from_i64(20),
3828 ValueRef::Text(TextRef::new("hello", TextSubtype::Text)),
3829 ],
3830 "desc_first_asc_second",
3831 ),
3832 ];
3833
3834 for (serialized_values, unpacked_values, test_name) in test_cases {
3835 assert_compare_matches_full_comparison(
3836 serialized_values,
3837 unpacked_values,
3838 &index_info,
3839 test_name,
3840 );
3841 }
3842 }
3843
3844 #[test]
3845 fn test_edge_cases() {
3846 let index_info =
3847 create_index_info(15, vec![SortOrder::Asc; 15], vec![CollationSeq::Binary; 15]);
3848
3849 let test_cases = vec![
3850 (
3851 vec![Value::from_i64(42)],
3852 vec![
3853 ValueRef::from_i64(42),
3854 ValueRef::Text(TextRef::new("extra", TextSubtype::Text)),
3855 ],
3856 "fewer_serialized_fields",
3857 ),
3858 (
3859 vec![Value::from_i64(42), Value::Text(Text::new("extra"))],
3860 vec![ValueRef::from_i64(42)],
3861 "fewer_unpacked_fields",
3862 ),
3863 (vec![], vec![], "both_empty"),
3864 (vec![], vec![ValueRef::from_i64(42)], "empty_serialized"),
3865 (
3866 (0..15).map(Value::from_i64).try_collect().unwrap(),
3867 (0..15).map(ValueRef::from_i64).try_collect().unwrap(),
3868 "large_field_count",
3869 ),
3870 (
3871 vec![Value::Blob(std::vec![1, 2, 3])],
3872 vec![ValueRef::Blob(&[1, 2, 3])],
3873 "blob_first_field",
3874 ),
3875 (
3876 vec![Value::Text(Text::new("hello")), Value::from_i64(5)],
3877 vec![ValueRef::Text(TextRef::new("hello", TextSubtype::Text))],
3878 "equal_text_prefix_but_more_serialized_fields",
3879 ),
3880 (
3881 vec![Value::Text(Text::new("same")), Value::from_i64(5)],
3882 vec![
3883 ValueRef::Text(TextRef::new("same", TextSubtype::Text)),
3884 ValueRef::from_i64(5),
3885 ],
3886 "equal_text_then_equal_int",
3887 ),
3888 ];
3889
3890 for (serialized_values, unpacked_values, test_name) in test_cases {
3891 assert_compare_matches_full_comparison(
3892 serialized_values,
3893 unpacked_values,
3894 &index_info,
3895 test_name,
3896 );
3897 }
3898 }
3899
3900 #[test]
3901 fn test_skip_parameter() {
3902 let index_info = create_index_info(
3903 3,
3904 vec![SortOrder::Asc, SortOrder::Asc, SortOrder::Asc],
3905 vec![CollationSeq::Binary; 3],
3906 );
3907
3908 let serialized = create_record(vec![
3909 Value::from_i64(1),
3910 Value::from_i64(2),
3911 Value::from_i64(3),
3912 ]);
3913 let unpacked = [
3914 ValueRef::from_i64(1),
3915 ValueRef::from_i64(99),
3916 ValueRef::from_i64(3),
3917 ];
3918
3919 let tie_breaker = std::cmp::Ordering::Equal;
3920 let result_skip_0 =
3921 compare_records_generic(&serialized, unpacked.iter(), &index_info, 0, tie_breaker)
3922 .unwrap();
3923 let result_skip_1 =
3924 compare_records_generic(&serialized, unpacked.iter(), &index_info, 1, tie_breaker)
3925 .unwrap();
3926
3927 assert_eq!(result_skip_0, std::cmp::Ordering::Less);
3928
3929 assert_eq!(result_skip_1, std::cmp::Ordering::Less);
3930 }
3931
3932 #[test]
3933 fn test_strategy_selection() {
3934 let collations_small = vec![CollationSeq::Binary; 3];
3935 let collations_large = vec![CollationSeq::Binary; 15];
3936 let index_info_small = create_index_info(
3937 3,
3938 vec![SortOrder::Asc, SortOrder::Asc, SortOrder::Asc],
3939 collations_small,
3940 );
3941 let index_info_large = create_index_info(15, vec![SortOrder::Asc; 15], collations_large);
3942
3943 let int_values = [
3944 ValueRef::from_i64(42),
3945 ValueRef::Text(TextRef::new("hello", TextSubtype::Text)),
3946 ];
3947 assert!(matches!(
3948 find_compare(int_values.iter().peekable(), &index_info_small),
3949 RecordCompare::Int
3950 ));
3951
3952 let string_values = [
3953 ValueRef::Text(TextRef::new("hello", TextSubtype::Text)),
3954 ValueRef::from_i64(42),
3955 ];
3956 assert!(matches!(
3957 find_compare(string_values.iter().peekable(), &index_info_small),
3958 RecordCompare::String
3959 ));
3960
3961 let large_values: Vec<ValueRef> = (0..15).map(ValueRef::from_i64).try_collect().unwrap();
3962 assert!(matches!(
3963 find_compare(large_values.iter().peekable(), &index_info_large),
3964 RecordCompare::Generic
3965 ));
3966
3967 let blob_values = [ValueRef::Blob(&[1, 2, 3])];
3968 assert!(matches!(
3969 find_compare(blob_values.iter().peekable(), &index_info_small),
3970 RecordCompare::Generic
3971 ));
3972 }
3973
3974 #[test]
3975 fn test_serialize_null() {
3976 let record = Record::new(vec![Value::Null]);
3977 let mut buf = std::vec::Vec::new();
3978 record.serialize(&mut buf);
3979
3980 let header_length = record.values.len() + 1;
3981 let header = &buf[0..header_length];
3982 assert_eq!(header[0], header_length as u8);
3984 assert_eq!(header[1] as u64, u64::from(SerialType::null()));
3986 assert_eq!(buf.len(), header_length);
3988 }
3989
3990 #[test]
3991 fn test_serialize_integers() {
3992 let record = Record::new(vec![
3993 Value::from_i64(0), Value::from_i64(1), Value::from_i64(42), Value::from_i64(1000), Value::from_i64(1_000_000), Value::from_i64(1_000_000_000), Value::from_i64(1_000_000_000_000), Value::from_i64(i64::MAX), ]);
4002 let mut buf = std::vec::Vec::new();
4003 record.serialize(&mut buf);
4004
4005 let header_length = record.values.len() + 1;
4006 let header = &buf[0..header_length];
4007 assert_eq!(header[0], header_length as u8); assert_eq!(header[1] as u64, u64::from(SerialType::const_int0())); assert_eq!(header[2] as u64, u64::from(SerialType::const_int1())); assert_eq!(header[3] as u64, u64::from(SerialType::i8())); assert_eq!(header[4] as u64, u64::from(SerialType::i16())); assert_eq!(header[5] as u64, u64::from(SerialType::i24())); assert_eq!(header[6] as u64, u64::from(SerialType::i32())); assert_eq!(header[7] as u64, u64::from(SerialType::i48())); assert_eq!(header[8] as u64, u64::from(SerialType::i64())); let mut cur_offset = header_length;
4022
4023 let i8_bytes = &buf[cur_offset..cur_offset + size_of::<i8>()];
4028 cur_offset += size_of::<i8>();
4029
4030 let i16_bytes = &buf[cur_offset..cur_offset + size_of::<i16>()];
4032 cur_offset += size_of::<i16>();
4033
4034 let i24_bytes = &buf[cur_offset..cur_offset + 3];
4036 cur_offset += 3;
4037
4038 let i32_bytes = &buf[cur_offset..cur_offset + size_of::<i32>()];
4040 cur_offset += size_of::<i32>();
4041
4042 let i48_bytes = &buf[cur_offset..cur_offset + 6];
4044 cur_offset += 6;
4045
4046 let i64_bytes = &buf[cur_offset..cur_offset + size_of::<i64>()];
4048
4049 let val_int8 = i8::from_be_bytes(i8_bytes.try_into().unwrap());
4051 let val_int16 = i16::from_be_bytes(i16_bytes.try_into().unwrap());
4052
4053 let mut i24_with_padding = vec![0];
4054 i24_with_padding.extend(i24_bytes);
4055 let val_int24 = i32::from_be_bytes(i24_with_padding.try_into().unwrap());
4056
4057 let val_int32 = i32::from_be_bytes(i32_bytes.try_into().unwrap());
4058
4059 let mut i48_with_padding = vec![0, 0];
4060 i48_with_padding.extend(i48_bytes);
4061 let val_int48 = i64::from_be_bytes(i48_with_padding.try_into().unwrap());
4062
4063 let val_int64 = i64::from_be_bytes(i64_bytes.try_into().unwrap());
4064
4065 assert_eq!(val_int8, 42);
4066 assert_eq!(val_int16, 1000);
4067 assert_eq!(val_int24, 1_000_000);
4068 assert_eq!(val_int32, 1_000_000_000);
4069 assert_eq!(val_int48, 1_000_000_000_000);
4070 assert_eq!(val_int64, i64::MAX);
4071
4072 assert_eq!(
4075 buf.len(),
4076 header_length + size_of::<i8>() + size_of::<i16>() + (size_of::<i32>() - 1) + size_of::<i32>() + (size_of::<i64>() - 2) + size_of::<i64>() );
4084 }
4085
4086 #[test]
4087 fn test_serialize_const_integers() {
4088 let record = Record::new(vec![Value::from_i64(0), Value::from_i64(1)]);
4089 let mut buf = std::vec::Vec::new();
4090 record.serialize(&mut buf);
4091
4092 let expected_header_size = 3; assert_eq!(buf.len(), expected_header_size);
4096
4097 assert_eq!(buf[0], expected_header_size as u8);
4099
4100 assert_eq!(buf[1] as u64, u64::from(SerialType::const_int0())); assert_eq!(buf[2] as u64, u64::from(SerialType::const_int1())); assert_eq!(buf[1], 8); assert_eq!(buf[2], 9); }
4106
4107 #[test]
4108 fn test_serialize_single_const_int0() {
4109 let record = Record::new(vec![Value::from_i64(0)]);
4110 let mut buf = std::vec::Vec::new();
4111 record.serialize(&mut buf);
4112
4113 assert_eq!(buf.len(), 2);
4115 assert_eq!(buf[0], 2); assert_eq!(buf[1], 8); }
4118
4119 #[test]
4120 fn test_serialize_float() {
4121 #[warn(clippy::approx_constant)]
4122 let record = Record::new(vec![Value::from_f64(3.15555)]);
4123 let mut buf = std::vec::Vec::new();
4124 record.serialize(&mut buf);
4125
4126 let header_length = record.values.len() + 1;
4127 let header = &buf[0..header_length];
4128 assert_eq!(header[0], header_length as u8);
4129 assert_eq!(header[1] as u64, u64::from(SerialType::f64()));
4131 let float_bytes = &buf[header_length..header_length + size_of::<f64>()];
4133 let float = f64::from_be_bytes(float_bytes.try_into().unwrap());
4134 assert_eq!(float, 3.15555);
4135 assert_eq!(buf.len(), header_length + size_of::<f64>());
4137 }
4138
4139 #[test]
4140 fn test_serialize_text() {
4141 let text = "hello";
4142 let record = Record::new(vec![Value::Text(Text::new(text))]);
4143 let mut buf = std::vec::Vec::new();
4144 record.serialize(&mut buf);
4145
4146 let header_length = record.values.len() + 1;
4147 let header = &buf[0..header_length];
4148 assert_eq!(header[0], header_length as u8);
4150 assert_eq!(header[1], (5 * 2 + 13) as u8);
4152 assert_eq!(&buf[2..7], b"hello");
4154 assert_eq!(buf.len(), header_length + text.len());
4156 }
4157
4158 #[test]
4159 fn test_serialize_blob() {
4160 let blob = std::vec![1, 2, 3, 4, 5];
4161 let record = Record::new(vec![Value::Blob(blob.clone())]);
4162 let mut buf = std::vec::Vec::new();
4163 record.serialize(&mut buf);
4164
4165 let header_length = record.values.len() + 1;
4166 let header = &buf[0..header_length];
4167 assert_eq!(header[0], header_length as u8);
4169 assert_eq!(header[1], (5 * 2 + 12) as u8);
4171 assert_eq!(&buf[2..7], &[1, 2, 3, 4, 5]);
4173 assert_eq!(buf.len(), header_length + blob.len());
4175 }
4176
4177 #[test]
4178 fn test_serialize_mixed_types() {
4179 let text = "test";
4180 let record = Record::new(vec![
4181 Value::Null,
4182 Value::from_i64(42),
4183 Value::from_f64(3.15),
4184 Value::Text(Text::new(text)),
4185 ]);
4186 let mut buf = std::vec::Vec::new();
4187 record.serialize(&mut buf);
4188
4189 let header_length = record.values.len() + 1;
4190 let header = &buf[0..header_length];
4191 assert_eq!(header[0], header_length as u8);
4193 assert_eq!(header[1] as u64, u64::from(SerialType::null()));
4195 assert_eq!(header[2] as u64, u64::from(SerialType::i8()));
4197 assert_eq!(header[3] as u64, u64::from(SerialType::f64()));
4199 assert_eq!(header[4] as u64, (4 * 2 + 13) as u64);
4201
4202 let mut cur_offset = header_length;
4204 let i8_bytes = &buf[cur_offset..cur_offset + size_of::<i8>()];
4205 cur_offset += size_of::<i8>();
4206 let f64_bytes = &buf[cur_offset..cur_offset + size_of::<f64>()];
4207 cur_offset += size_of::<f64>();
4208 let text_bytes = &buf[cur_offset..cur_offset + text.len()];
4209
4210 let val_int8 = i8::from_be_bytes(i8_bytes.try_into().unwrap());
4211 let val_float = f64::from_be_bytes(f64_bytes.try_into().unwrap());
4212 let val_text = String::from_utf8(text_bytes.to_vec()).unwrap();
4213
4214 assert_eq!(val_int8, 42);
4215 assert_eq!(val_float, 3.15);
4216 assert_eq!(val_text, "test");
4217
4218 assert_eq!(
4220 buf.len(),
4221 header_length + size_of::<i8>() + size_of::<f64>() + text.len()
4222 );
4223 }
4224
4225 #[test]
4234 fn test_valueref_partial_cmp_no_panic_on_nan() {
4235 use crate::numeric::nonnan::NonNan;
4236
4237 assert!(NonNan::new(f64::NAN).is_none());
4240
4241 assert_eq!(ValueRef::from_f64(f64::NAN), ValueRef::Null);
4243
4244 let values: Vec<ValueRef> = vec![
4247 ValueRef::Null,
4248 ValueRef::from_i64(0),
4249 ValueRef::from_i64(-1),
4250 ValueRef::from_i64(i64::MAX),
4251 ValueRef::from_i64(i64::MIN),
4252 ValueRef::from_f64(0.0),
4253 ValueRef::from_f64(-0.0),
4254 ValueRef::from_f64(1.5),
4255 ValueRef::from_f64(-1.5),
4256 ValueRef::from_f64(f64::MAX),
4257 ValueRef::from_f64(f64::MIN),
4258 ValueRef::from_f64(f64::MIN_POSITIVE),
4259 ValueRef::from_f64(f64::INFINITY),
4260 ValueRef::from_f64(f64::NEG_INFINITY),
4261 ValueRef::from_f64(f64::NAN), ValueRef::Text(TextRef::new("hello", TextSubtype::Text)),
4263 ValueRef::Text(TextRef::new("", TextSubtype::Text)),
4264 ValueRef::Blob(&[1, 2, 3]),
4265 ValueRef::Blob(&[]),
4266 ];
4267
4268 for (i, a) in values.iter().enumerate() {
4271 for (j, b) in values.iter().enumerate() {
4272 let result = a.partial_cmp(b);
4273 assert!(
4274 result.is_some(),
4275 "partial_cmp returned None for values[{i}]={a:?} vs values[{j}]={b:?}"
4276 );
4277 assert_eq!(result.unwrap(), a.cmp(b));
4279 }
4280 }
4281
4282 for a in &values {
4284 for b in &values {
4285 let _ = compare_immutable_single(*a, *b, CollationSeq::Binary);
4286 }
4287 }
4288
4289 for a in &values {
4291 for b in &values {
4292 let ab = a.cmp(b);
4293 let ba = b.cmp(a);
4294 assert_eq!(ab, ba.reverse(), "antisymmetry failed for {a:?} vs {b:?}");
4295 }
4296 }
4297 }
4298
4299 #[test]
4300 fn test_column_count_matches_values_written() {
4301 for num_values in 1..=10 {
4303 let values: Vec<Value> = (0..num_values)
4304 .map(|i| Value::from_i64(i as i64))
4305 .try_collect()
4306 .unwrap();
4307
4308 let record = ImmutableRecord::from_values(&values, values.len()).unwrap();
4309 let cnt = record.column_count();
4310 assert_eq!(
4311 cnt, num_values,
4312 "column_count should be {num_values}, not {cnt}"
4313 );
4314 }
4315 }
4316}