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