1use crate::turso_assert;
2use crate::{
3 function::MathFunc,
4 numeric::{format_float, format_float_for_quote, NullableInteger, Numeric},
5 translate::collate::CollationSeq,
6 types::{compare_immutable_single, AsValueRef, SeekOp},
7 vdbe::affinity::{real_to_i64, Affinity},
8 LimboError, Result, Value, ValueRef,
9};
10
11#[cfg(not(clt_turso_tests))]
13mod cmath {
14 pub fn exp(x: f64) -> f64 {
15 x.exp()
16 }
17 pub fn log(x: f64) -> f64 {
18 x.ln()
19 }
20 pub fn log10(x: f64) -> f64 {
21 x.log(10.)
22 }
23 pub fn log2(x: f64) -> f64 {
24 x.log(2.)
25 }
26 pub fn pow(x: f64, y: f64) -> f64 {
27 x.powf(y)
28 }
29 pub fn sin(x: f64) -> f64 {
30 x.sin()
31 }
32 pub fn sinh(x: f64) -> f64 {
33 x.sinh()
34 }
35 pub fn asin(x: f64) -> f64 {
36 x.asin()
37 }
38 pub fn asinh(x: f64) -> f64 {
39 x.asinh()
40 }
41 pub fn cos(x: f64) -> f64 {
42 x.cos()
43 }
44 pub fn cosh(x: f64) -> f64 {
45 x.cosh()
46 }
47 pub fn acos(x: f64) -> f64 {
48 x.acos()
49 }
50 pub fn acosh(x: f64) -> f64 {
51 x.acosh()
52 }
53 pub fn tan(x: f64) -> f64 {
54 x.tan()
55 }
56 pub fn tanh(x: f64) -> f64 {
57 x.tanh()
58 }
59 pub fn atan(x: f64) -> f64 {
60 x.atan()
61 }
62 pub fn atanh(x: f64) -> f64 {
63 x.atanh()
64 }
65 pub fn atan2(x: f64, y: f64) -> f64 {
66 x.atan2(y)
67 }
68 pub fn degrees(x: f64) -> f64 {
69 x.to_degrees()
70 }
71 pub fn radians(x: f64) -> f64 {
72 x.to_radians()
73 }
74}
75
76#[cfg(clt_turso_tests)]
78mod cmath {
79 extern "C" {
80 pub fn exp(x: f64) -> f64;
81 pub fn log(x: f64) -> f64;
82 pub fn log10(x: f64) -> f64;
83 pub fn log2(x: f64) -> f64;
84 pub fn pow(x: f64, y: f64) -> f64;
85
86 pub fn sin(x: f64) -> f64;
87 pub fn sinh(x: f64) -> f64;
88 pub fn asin(x: f64) -> f64;
89 pub fn asinh(x: f64) -> f64;
90
91 pub fn cos(x: f64) -> f64;
92 pub fn cosh(x: f64) -> f64;
93 pub fn acos(x: f64) -> f64;
94 pub fn acosh(x: f64) -> f64;
95
96 pub fn tan(x: f64) -> f64;
97 pub fn tanh(x: f64) -> f64;
98 pub fn atan(x: f64) -> f64;
99 pub fn atanh(x: f64) -> f64;
100 pub fn atan2(x: f64, y: f64) -> f64;
101 }
102
103 #[allow(clippy::excessive_precision)]
105 const M_PI: f64 = 3.141592653589793238462643383279502884;
106
107 pub fn degrees(x: f64) -> f64 {
108 x * 180.0 / M_PI
109 }
110 pub fn radians(x: f64) -> f64 {
111 x * M_PI / 180.0
112 }
113}
114
115#[derive(Debug, Clone, Copy, PartialEq)]
116pub(super) enum ComparisonOp {
117 Eq,
118 Ne,
119 Lt,
120 Le,
121 Gt,
122 Ge,
123}
124
125impl ComparisonOp {
126 pub(super) fn compare<V1: AsValueRef, V2: AsValueRef>(
127 &self,
128 lhs: V1,
129 rhs: V2,
130 collation: CollationSeq,
131 ) -> bool {
132 let order = compare_immutable_single(lhs, rhs, collation);
133 match self {
134 ComparisonOp::Eq => order.is_eq(),
135 ComparisonOp::Ne => order.is_ne(),
136 ComparisonOp::Lt => order.is_lt(),
137 ComparisonOp::Le => order.is_le(),
138 ComparisonOp::Gt => order.is_gt(),
139 ComparisonOp::Ge => order.is_ge(),
140 }
141 }
142
143 pub(super) fn compare_nulls<V1: AsValueRef, V2: AsValueRef>(
144 &self,
145 lhs: V1,
146 rhs: V2,
147 null_eq: bool,
148 ) -> bool {
149 let (lhs, rhs) = (lhs.as_value_ref(), rhs.as_value_ref());
150 turso_assert!(matches!(lhs, ValueRef::Null) || matches!(rhs, ValueRef::Null));
151
152 match self {
153 ComparisonOp::Eq => {
154 let both_null = lhs == rhs;
155 null_eq && both_null
156 }
157 ComparisonOp::Ne => {
158 let at_least_one_null = lhs != rhs;
159 null_eq && at_least_one_null
160 }
161 ComparisonOp::Lt | ComparisonOp::Le | ComparisonOp::Gt | ComparisonOp::Ge => false,
162 }
163 }
164}
165
166impl From<SeekOp> for ComparisonOp {
167 fn from(value: SeekOp) -> Self {
168 match value {
169 SeekOp::GE { eq_only: true } | SeekOp::LE { eq_only: true } => ComparisonOp::Eq,
170 SeekOp::GE { eq_only: false } => ComparisonOp::Ge,
171 SeekOp::GT => ComparisonOp::Gt,
172 SeekOp::LE { eq_only: false } => ComparisonOp::Le,
173 SeekOp::LT => ComparisonOp::Lt,
174 }
175 }
176}
177
178#[inline]
179fn sqlite_text_prefix(s: &str) -> &str {
180 match s.find('\0') {
181 Some(idx) => &s[..idx],
182 None => s,
183 }
184}
185
186enum TrimType {
187 All,
188 Left,
189 Right,
190}
191
192impl Value {
193 pub fn exec_lower(&self) -> Option<Self> {
194 self.cast_text()
195 .map(|s| Value::build_text(s.to_ascii_lowercase()))
196 }
197
198 pub fn exec_length(&self) -> Self {
199 match self {
200 Value::Text(t) => {
201 Value::from_i64(sqlite_text_prefix(t.as_str()).chars().count() as i64)
202 }
203 Value::Numeric(_) => {
204 Value::from_i64(self.to_string().chars().count() as i64)
206 }
207 Value::Blob(blob) => Value::from_i64(blob.len() as i64),
208 _ => self.to_owned(),
209 }
210 }
211
212 pub fn exec_octet_length(&self) -> Self {
213 match self {
214 Value::Text(s) => Value::from_i64(s.as_str().len() as i64),
215 Value::Blob(blob) => Value::from_i64(blob.len() as i64),
216 Value::Numeric(_) => Value::from_i64(self.to_string().len() as i64),
217 _ => self.to_owned(),
218 }
219 }
220
221 pub fn exec_upper(&self) -> Option<Self> {
222 self.cast_text()
223 .map(|s| Value::build_text(s.to_ascii_uppercase()))
224 }
225
226 pub fn exec_sign(&self) -> Option<Value> {
227 let v = Numeric::from_value_strict(self).map(|value| value.to_f64())?;
228
229 Some(Value::from_i64(if v > 0.0 {
230 1
231 } else if v < 0.0 {
232 -1
233 } else {
234 0
235 }))
236 }
237
238 pub fn exec_soundex(&self) -> Value {
240 let s = match self {
241 Value::Text(s) => s.as_str(),
242 Value::Null => return Value::build_text("?000"),
243 _ => return Value::build_text("?000"),
244 };
245
246 if s.bytes().any(|b| !b.is_ascii_alphabetic()) {
247 return Value::build_text("?000");
248 }
249
250 let mut bytes = s.bytes();
251 let Some(first_char) = bytes.next() else {
252 return Value::build_text("?000");
253 };
254
255 let first_upper = first_char.to_ascii_uppercase();
256 let mut result = String::with_capacity(4);
257 result.push(first_upper as char);
258 let get_code = |b: u8| -> Option<char> {
259 match b.to_ascii_lowercase() {
260 b'b' | b'f' | b'p' | b'v' => Some('1'),
261 b'c' | b'g' | b'j' | b'k' | b'q' | b's' | b'x' | b'z' => Some('2'),
262 b'd' | b't' => Some('3'),
263 b'l' => Some('4'),
264 b'm' | b'n' => Some('5'),
265 b'r' => Some('6'),
266 _ => None, }
268 };
269
270 let mut prev_code = get_code(first_char);
271
272 for b in bytes {
273 if result.len() >= 4 {
274 break;
275 }
276
277 let lower = b.to_ascii_lowercase();
279 if lower == b'h' || lower == b'w' {
280 continue;
281 }
282
283 let code = get_code(b);
284 if code.is_some() && code != prev_code {
285 result.push(code.unwrap());
286 prev_code = code;
287 } else if code.is_none() {
288 prev_code = None;
290 }
291 }
292
293 while result.len() < 4 {
294 result.push('0');
295 }
296
297 Value::build_text(result)
298 }
299
300 pub fn exec_abs(&self) -> Result<Self> {
301 Ok(match self {
302 Value::Null => Value::Null,
303 Value::Numeric(Numeric::Integer(v)) => {
304 Value::from_i64(v.checked_abs().ok_or(LimboError::IntegerOverflow)?)
305 }
306 Value::Numeric(Numeric::Float(non_nan)) => Value::from_f64(f64::from(*non_nan).abs()),
307 _ => {
308 let s = match self {
309 Value::Text(text) => std::borrow::Cow::Borrowed(text.as_str()),
310 Value::Blob(blob) => String::from_utf8_lossy(blob),
311 _ => unreachable!(),
312 };
313
314 crate::numeric::str_to_f64(s)
315 .map(|v| Value::from_f64(f64::from(v).abs()))
316 .unwrap_or_else(|| Value::from_f64(0.0))
317 }
318 })
319 }
320
321 pub fn exec_random<F>(generate_random_number: F) -> Self
322 where
323 F: Fn() -> i64,
324 {
325 Value::from_i64(generate_random_number())
326 }
327
328 pub const MAX_BLOB_LENGTH: i64 = 1_000_000_000;
330
331 pub fn exec_randomblob<F>(&self, fill_bytes: F) -> Result<Value>
332 where
333 F: Fn(&mut [u8]),
334 {
335 let length = match self {
336 Value::Numeric(Numeric::Integer(i)) => *i,
337 Value::Numeric(Numeric::Float(f)) => f64::from(*f) as i64,
338 Value::Text(t) => t.as_str().parse().unwrap_or(1),
339 _ => 1,
340 }
341 .max(1);
342
343 if length > Self::MAX_BLOB_LENGTH {
344 return Err(LimboError::TooBig);
345 }
346
347 let mut blob: Vec<u8> = vec![0; length as usize];
348 fill_bytes(&mut blob);
349 Ok(Value::Blob(blob))
350 }
351
352 pub fn exec_quote(&self) -> Self {
353 use std::fmt::Write;
354 match self {
355 Value::Null => Value::build_text("NULL"),
356 Value::Numeric(Numeric::Integer(i)) => Value::build_text(i.to_string()),
357 Value::Numeric(Numeric::Float(f)) => {
358 Value::build_text(format_float_for_quote(f64::from(*f)))
359 }
360 Value::Blob(b) => {
361 let mut quoted = String::with_capacity(3 + b.len() * 2);
363 quoted.push_str("X'");
364 for byte in b.iter() {
365 write!(&mut quoted, "{byte:02X}").expect("unable to write hex bytes");
366 }
367 quoted.push('\'');
368 Value::build_text(quoted)
369 }
370 Value::Text(s) => {
371 let mut quoted = String::with_capacity(s.as_str().len() + 2);
372 quoted.push('\'');
373 for c in s.as_str().chars() {
374 if c == '\0' {
375 break;
376 } else if c == '\'' {
377 quoted.push('\'');
378 quoted.push(c);
379 } else {
380 quoted.push(c);
381 }
382 }
383 quoted.push('\'');
384 Value::build_text(quoted)
385 }
386 }
387 }
388
389 pub fn exec_unistr_quote(&self) -> Self {
390 const HEX: &[u8; 16] = b"0123456789abcdef";
391
392 match self {
393 Value::Text(s) => {
394 let s = s.as_str();
395 let mut end = s.len();
396 let mut has_ctrl = false;
397
398 for (i, &b) in s.as_bytes().iter().enumerate() {
399 match b {
400 0 => {
401 end = i;
402 break;
403 }
404 1..=0x1f => has_ctrl = true,
405 _ => {}
406 }
407 }
408
409 if !has_ctrl {
410 return self.exec_quote();
411 }
412
413 let prefix = &s[..end];
414 let mut extra = 0;
415 for &b in prefix.as_bytes() {
416 extra += match b {
417 1..=0x1f => 5, b'\\' | b'\'' => 1,
419 _ => 0,
420 };
421 }
422
423 let mut out = String::with_capacity(prefix.len() + extra + "unistr('')".len());
424 out.push_str("unistr('");
425 for c in prefix.chars() {
426 match c {
427 '\x01'..='\x1f' => {
428 let b = c as u8;
429 out.push('\\');
430 out.push('u');
431 out.push('0');
432 out.push('0');
433 out.push(HEX[(b >> 4) as usize] as char);
434 out.push(HEX[(b & 0x0f) as usize] as char);
435 }
436 '\\' => out.push_str("\\\\"),
437 '\'' => out.push_str("''"),
438 _ => out.push(c),
439 }
440 }
441 out.push_str("')");
442 Value::build_text(out)
443 }
444 _ => self.exec_quote(),
445 }
446 }
447
448 pub fn exec_nullif(&self, second_value: &Self) -> Self {
449 if self != second_value {
450 self.clone()
451 } else {
452 Value::Null
453 }
454 }
455
456 pub fn exec_substring(
457 value: &Value,
458 start_value: &Value,
459 length_value: Option<&Value>,
460 ) -> Value {
461 const fn ceil_char_boundary(s: &str, index: usize) -> usize {
464 const fn is_utf8_char_boundary(c: u8) -> bool {
465 (c as i8) >= -0x40
467 }
468
469 if index >= s.len() {
470 s.len()
471 } else {
472 let mut i = index;
473 while i < s.len() {
474 if is_utf8_char_boundary(s.as_bytes()[i]) {
475 break;
476 }
477 i += 1;
478 }
479
480 debug_assert!(i <= index + 3);
482
483 i
484 }
485 }
486
487 fn calculate_postions(
490 mut p1: i64,
491 len: usize,
492 length_value: Option<&Value>,
493 ) -> (usize, usize) {
494 let len = len as i64;
495 let mut p2 = match length_value {
496 Some(Value::Numeric(Numeric::Integer(length))) => *length,
497 _ => Value::MAX_BLOB_LENGTH,
500 };
501
502 let explicit_length = length_value.is_some();
504
505 if p1 < 0 {
507 p1 = p1.wrapping_add(len);
508 if p1 < 0 {
509 if p2 < 0 {
510 p2 = 0;
511 } else {
512 p2 += p1;
513 }
514 p1 = 0;
515 }
516 } else if p1 > 0 {
517 p1 -= 1; } else if p2 > 0 && explicit_length {
519 p2 -= 1;
523 }
524
525 if p2 < 0 {
527 if p2 < -p1 {
528 p2 = p1;
529 } else {
530 p2 = -p2;
531 }
532 p1 -= p2;
533 }
534
535 let start = p1.max(0).min(len) as usize;
537 let end = p1.saturating_add(p2).max(0).min(len) as usize;
538 (start, end)
539 }
540
541 let start_value = start_value.exec_cast("INT");
542 let length_value = length_value.map(|value| value.exec_cast("INT"));
543
544 if matches!(length_value, Some(Value::Null)) {
546 return Value::Null;
547 }
548
549 match (value, start_value) {
550 (Value::Blob(b), Value::Numeric(Numeric::Integer(start))) => {
551 let (start, end) = calculate_postions(start, b.len(), length_value.as_ref());
552 Value::from_blob(b[start..end].to_vec())
553 }
554 (value, Value::Numeric(Numeric::Integer(start))) => {
555 if let Some(text) = value.cast_text() {
556 let s = sqlite_text_prefix(text.as_str());
557 let char_count = s.chars().count();
559 let (mut start, mut end) =
560 calculate_postions(start, char_count, length_value.as_ref());
561
562 let mut start_byte_idx = 0;
564 end -= start;
565 while start > 0 {
566 start_byte_idx = ceil_char_boundary(s, start_byte_idx + 1);
567 start -= 1;
568 }
569 let mut end_byte_idx = start_byte_idx;
570 while end > 0 {
571 end_byte_idx = ceil_char_boundary(s, end_byte_idx + 1);
572 end -= 1;
573 }
574 Value::build_text(s[start_byte_idx..end_byte_idx].to_string())
575 } else {
576 Value::Null
577 }
578 }
579 _ => Value::Null,
580 }
581 }
582
583 pub fn exec_instr(&self, pattern: &Value) -> Value {
584 if self == &Value::Null || pattern == &Value::Null {
585 return Value::Null;
586 }
587
588 if let (Value::Blob(reg), Value::Blob(pattern)) = (self, pattern) {
589 if pattern.is_empty() {
591 return Value::from_i64(1);
592 }
593 let result = reg
594 .windows(pattern.len())
595 .position(|window| window == *pattern)
596 .map_or(0, |i| i + 1);
597 return Value::from_i64(result as i64);
598 }
599
600 let reg_str;
601 let reg = match self {
602 Value::Text(s) => s.as_str(),
603 _ => {
604 reg_str = self.to_string();
605 reg_str.as_str()
606 }
607 };
608
609 let pattern_str;
610 let pattern = match pattern {
611 Value::Text(s) => s.as_str(),
612 _ => {
613 pattern_str = pattern.to_string();
614 pattern_str.as_str()
615 }
616 };
617
618 match reg.find(pattern) {
619 Some(byte_pos) => {
620 let char_pos = reg[..byte_pos].chars().count() + 1;
622 Value::from_i64(char_pos as i64)
623 }
624 None => Value::from_i64(0),
625 }
626 }
627
628 pub fn exec_typeof(&self) -> Value {
629 match self {
630 Value::Null => Value::build_text("null"),
631 Value::Numeric(Numeric::Integer(_)) => Value::build_text("integer"),
632 Value::Numeric(Numeric::Float(_)) => Value::build_text("real"),
633 Value::Text(_) => Value::build_text("text"),
634 Value::Blob(_) => Value::build_text("blob"),
635 }
636 }
637
638 pub fn exec_hex(&self) -> Value {
639 match self {
640 Value::Text(_) | Value::Numeric(_) => {
641 let text = self.to_string();
642 Value::build_text(hex::encode_upper(text))
643 }
644 Value::Blob(blob_bytes) => Value::build_text(hex::encode_upper(blob_bytes)),
645 Value::Null => Value::build_text(""),
646 }
647 }
648
649 pub fn exec_unhex(&self, ignored_chars: Option<&Value>) -> Value {
650 match self {
651 Value::Null => Value::Null,
652 _ => match ignored_chars {
653 None => match self
654 .cast_text()
655 .map(|s| hex::decode(&s[0..s.find('\0').unwrap_or(s.len())]))
656 {
657 Some(Ok(bytes)) => Value::Blob(bytes),
658 _ => Value::Null,
659 },
660 Some(ignore) => match ignore {
661 Value::Text(_) => {
662 let input = self.to_string();
663 let ignore = ignore.to_string();
664 let mut chars = input.chars().peekable();
665 let mut out = Vec::with_capacity(input.len() / 2);
666
667 let is_sep = |c: char| ignore.contains(c) && !c.is_ascii_hexdigit();
668
669 loop {
670 while let Some(&c) = chars.peek() {
671 if is_sep(c) {
672 chars.next();
673 } else {
674 break;
675 }
676 }
677
678 let Some(c1) = chars.next() else {
679 return Value::Blob(out);
680 };
681 let Some(hi) = c1.to_digit(16) else {
682 return Value::Null;
683 };
684
685 let Some(c2) = chars.next() else {
686 return Value::Null;
687 };
688 let Some(lo) = c2.to_digit(16) else {
689 return Value::Null;
690 };
691
692 out.push(((hi << 4) | lo) as u8);
693 }
694 }
695 _ => Value::Null,
696 },
697 },
698 }
699 }
700
701 pub fn exec_unicode(&self) -> Value {
702 match self {
703 Value::Text(_) | Value::Numeric(_) | Value::Blob(_) => {
704 let text = self.to_string();
705 if let Some(first_char) = text.chars().next() {
706 if first_char == '\0' {
707 return Value::Null;
708 }
709 Value::from_i64(first_char as u32 as i64)
710 } else {
711 Value::Null
712 }
713 }
714 _ => Value::Null,
715 }
716 }
717
718 pub fn exec_unistr(&self) -> Result<Value> {
719 let text = match self {
720 Value::Text(t) => std::borrow::Cow::Borrowed(t.as_str()),
721 Value::Numeric(_) | Value::Blob(_) => std::borrow::Cow::Owned(self.to_string()),
722 _ => return Ok(Value::Null),
723 };
724 let bytes = text.as_bytes();
725 let len = bytes.len();
726 let mut out = String::with_capacity(len);
727 let mut i = 0;
728
729 while i < len {
730 if bytes[i] != b'\\' {
731 let start = i;
732 while i < len && bytes[i] != b'\\' {
733 i += 1;
734 }
735 out.push_str(&text[start..i]);
736 continue;
737 }
738
739 let v = match bytes.get(i + 1) {
740 Some(b'\\') => {
741 out.push('\\');
742 i += 2;
743 continue;
744 }
745 Some(b) if b.is_ascii_hexdigit() => {
746 let v = parse_n_hex(&bytes[i + 1..], 4)?;
747 i += 5;
748 v
749 }
750 Some(b'+') => {
751 let v = parse_n_hex(&bytes[i + 2..], 6)?;
752 i += 8;
753 v
754 }
755 Some(b'u') => {
756 let v = parse_n_hex(&bytes[i + 2..], 4)?;
757 i += 6;
758 v
759 }
760 Some(b'U') => {
761 let v = parse_n_hex(&bytes[i + 2..], 8)?;
762 i += 10;
763 v
764 }
765 _ => return Err(LimboError::ParseError("invalid Unicode escape".to_string())),
766 };
767
768 let ch = char::from_u32(v)
771 .ok_or_else(|| LimboError::ParseError("invalid Unicode escape".to_string()))?;
772 out.push(ch);
773 }
774
775 Ok(Value::build_text(out))
776 }
777
778 pub fn exec_round(&self, precision: Option<&Value>) -> Value {
779 let Some(f) = Numeric::from_value(self).map(|v| v.to_f64()) else {
780 return Value::Null;
781 };
782
783 let precision = match precision.map(|v| Numeric::from_value(v).map(|v| v.to_f64())) {
784 None => 0.0,
785 Some(Some(v)) => v,
786 Some(None) => return Value::Null,
787 };
788
789 if !(-4503599627370496.0..=4503599627370496.0).contains(&f) {
790 return Value::from_f64(f);
791 }
792
793 let precision = if precision < 1.0 { 0.0 } else { precision };
794 let precision = precision.clamp(0.0, 30.0) as usize;
795
796 if precision == 0 {
797 return Value::from_f64(((f + if f < 0.0 { -0.5 } else { 0.5 }) as i64) as f64);
798 }
799
800 let f: f64 = crate::numeric::str_to_f64(format!("{f:.precision$}"))
801 .expect("formatted float should always parse successfully")
802 .into();
803
804 Value::from_f64(f)
805 }
806
807 fn _exec_trim(&self, pattern: Option<&Value>, trim_type: TrimType) -> Value {
808 let text_cow = match self {
809 Value::Text(s) => std::borrow::Cow::Borrowed(s.as_str()),
810 Value::Null => return Value::Null,
811 _ => std::borrow::Cow::Owned(self.to_string()),
812 };
813 let trimmed = match pattern {
814 Some(p) => {
815 if matches!(p, Value::Null) {
816 return Value::Null;
817 }
818 let pat_cow = match p {
819 Value::Text(s) => std::borrow::Cow::Borrowed(s.as_str()),
820 _ => std::borrow::Cow::Owned(p.to_string()),
821 };
822 let p_str = pat_cow.as_ref();
823 match trim_type {
824 TrimType::All => text_cow.trim_matches(|c| p_str.contains(c)),
825 TrimType::Left => text_cow.trim_start_matches(|c| p_str.contains(c)),
826 TrimType::Right => text_cow.trim_end_matches(|c| p_str.contains(c)),
827 }
828 }
829 None => match trim_type {
830 TrimType::All => text_cow.trim_matches(' '),
831 TrimType::Left => text_cow.trim_start_matches(' '),
832 TrimType::Right => text_cow.trim_end_matches(' '),
833 },
834 };
835 Value::build_text(trimmed.to_string())
836 }
837
838 pub fn exec_trim(&self, pattern: Option<&Value>) -> Value {
840 self._exec_trim(pattern, TrimType::All)
841 }
842 pub fn exec_rtrim(&self, pattern: Option<&Value>) -> Value {
844 self._exec_trim(pattern, TrimType::Right)
845 }
846
847 pub fn exec_ltrim(&self, pattern: Option<&Value>) -> Value {
849 self._exec_trim(pattern, TrimType::Left)
850 }
851
852 pub fn exec_zeroblob(&self) -> Result<Value> {
853 let length: i64 = match self {
854 Value::Numeric(Numeric::Integer(i)) => *i,
855 Value::Numeric(Numeric::Float(f)) => f64::from(*f) as i64,
856 Value::Text(s) => s.as_str().parse().unwrap_or(0),
857 _ => 0,
858 }
859 .max(0);
860
861 if length > Self::MAX_BLOB_LENGTH {
862 return Err(LimboError::TooBig);
863 }
864
865 Ok(Value::Blob(vec![0; length as usize]))
866 }
867
868 pub fn exec_if(&self, jump_if_null: bool, not: bool) -> bool {
870 Numeric::from_value(self)
871 .map(|v| v.to_bool())
872 .map(|jump| if not { !jump } else { jump })
873 .unwrap_or(jump_if_null)
874 }
875
876 pub fn exec_cast(&self, datatype: &str) -> Value {
877 if matches!(self, Value::Null) {
878 return Value::Null;
879 }
880 match Affinity::affinity(datatype) {
881 Affinity::Blob => {
884 if let Value::Blob(blob) = self {
885 return Value::Blob(blob.clone());
886 }
887 let text = self.to_string();
890 Value::Blob(text.into_bytes())
891 }
892 Affinity::Text => {
895 Value::build_text(self.to_string())
898 }
899 Affinity::Real => match self {
900 Value::Blob(b) => {
901 let text = String::from_utf8_lossy(b);
902 Value::from_f64(
903 crate::numeric::str_to_f64(&text)
904 .map(f64::from)
905 .unwrap_or(0.0),
906 )
907 }
908 Value::Text(t) => {
909 Value::from_f64(crate::numeric::str_to_f64(t).map(f64::from).unwrap_or(0.0))
910 }
911 Value::Numeric(Numeric::Integer(i)) => Value::from_f64(*i as f64),
912 Value::Numeric(Numeric::Float(f)) => Value::Numeric(Numeric::Float(*f)),
913 _ => Value::from_f64(0.0),
914 },
915 Affinity::Integer => match self {
916 Value::Blob(b) => {
917 let text = String::from_utf8_lossy(b);
919 Value::from_i64(crate::numeric::str_to_i64(&text).unwrap_or(0))
920 }
921 Value::Text(t) => Value::from_i64(crate::numeric::str_to_i64(t).unwrap_or(0)),
922 Value::Numeric(Numeric::Integer(i)) => Value::from_i64(*i),
923 Value::Numeric(Numeric::Float(f)) => Value::from_i64(real_to_i64(f64::from(*f))),
926 _ => Value::from_i64(0),
927 },
928 Affinity::Numeric => match self {
929 Value::Null => Value::Null,
930 Value::Numeric(Numeric::Integer(v)) => Value::from_i64(*v),
931 Value::Numeric(Numeric::Float(v)) => Value::Numeric(Numeric::Float(*v)),
932 _ => {
933 let s = match self {
934 Value::Text(text) => text.as_str().into(),
935 Value::Blob(blob) => String::from_utf8_lossy(blob.as_slice()),
936 _ => unreachable!(),
937 };
938 crate::util::checked_cast_text_to_numeric(&s, false)
939 .ok()
940 .unwrap_or_else(|| Value::from_i64(0))
941 }
942 },
943 }
944 }
945
946 pub fn exec_replace(source: &Value, pattern: &Value, replacement: &Value) -> Value {
947 if matches!(source, Value::Null)
953 || matches!(pattern, Value::Null)
954 || matches!(replacement, Value::Null)
955 {
956 return Value::Null;
957 }
958
959 let source = source.exec_cast("TEXT");
960 let pattern = pattern.exec_cast("TEXT");
961 let replacement = replacement.exec_cast("TEXT");
962
963 match (&source, &pattern, &replacement) {
965 (Value::Text(source), Value::Text(pattern), Value::Text(replacement)) => {
966 if pattern.as_str().is_empty() || pattern.as_str().starts_with('\0') {
967 return Value::Text(source.clone());
968 }
969
970 let result = source
971 .as_str()
972 .replace(pattern.as_str(), replacement.as_str());
973 Value::build_text(result)
974 }
975 _ => unreachable!("text cast should never fail"),
976 }
977 }
978
979 pub fn exec_math_unary(&self, function: &MathFunc) -> Value {
980 let v = Numeric::from_value_strict(self);
981
982 if let Some(Numeric::Integer(i)) = v {
984 if matches! { function, MathFunc::Ceil | MathFunc::Ceiling | MathFunc::Floor | MathFunc::Trunc }
985 {
986 return Value::from_i64(i);
987 }
988 }
989
990 let Some(f) = v.map(|v| v.to_f64()) else {
991 return Value::Null;
992 };
993
994 if matches! { function, MathFunc::Ln | MathFunc::Log10 | MathFunc::Log2 } && f <= 0.0 {
995 return Value::Null;
996 }
997
998 #[allow(unused_unsafe)]
999 let result = match function {
1000 MathFunc::Acos => unsafe { cmath::acos(f) },
1001 MathFunc::Acosh => unsafe { cmath::acosh(f) },
1002 MathFunc::Asin => unsafe { cmath::asin(f) },
1003 MathFunc::Asinh => unsafe { cmath::asinh(f) },
1004 MathFunc::Atan => unsafe { cmath::atan(f) },
1005 MathFunc::Atanh => unsafe { cmath::atanh(f) },
1006 MathFunc::Ceil | MathFunc::Ceiling => libm::ceil(f),
1007 MathFunc::Cos => unsafe { cmath::cos(f) },
1008 MathFunc::Cosh => unsafe { cmath::cosh(f) },
1009 MathFunc::Degrees => cmath::degrees(f),
1010 MathFunc::Exp => unsafe { cmath::exp(f) },
1011 MathFunc::Floor => libm::floor(f),
1012 MathFunc::Ln => unsafe { cmath::log(f) },
1013 MathFunc::Log10 => unsafe { cmath::log10(f) },
1014 MathFunc::Log2 => unsafe { cmath::log2(f) },
1015 MathFunc::Radians => cmath::radians(f),
1016 MathFunc::Sin => unsafe { cmath::sin(f) },
1017 MathFunc::Sinh => unsafe { cmath::sinh(f) },
1018 MathFunc::Sqrt => libm::sqrt(f),
1019 MathFunc::Tan => unsafe { cmath::tan(f) },
1020 MathFunc::Tanh => unsafe { cmath::tanh(f) },
1021 MathFunc::Trunc => libm::trunc(f),
1022 _ => unreachable!("Unexpected mathematical unary function {:?}", function),
1023 };
1024
1025 if result.is_nan() {
1026 Value::Null
1027 } else {
1028 Value::from_f64(result)
1029 }
1030 }
1031
1032 pub fn exec_math_binary(&self, rhs: &Value, function: &MathFunc) -> Value {
1033 let Some(lhs) = Numeric::from_value_strict(self).map(|v| v.to_f64()) else {
1034 return Value::Null;
1035 };
1036
1037 let Some(rhs) = Numeric::from_value_strict(rhs).map(|v| v.to_f64()) else {
1038 return Value::Null;
1039 };
1040
1041 #[allow(unused_unsafe)]
1042 let result = match function {
1043 MathFunc::Atan2 => unsafe { cmath::atan2(lhs, rhs) },
1044 MathFunc::Mod => libm::fmod(lhs, rhs),
1045 MathFunc::Pow | MathFunc::Power => unsafe { cmath::pow(lhs, rhs) },
1046 _ => unreachable!("Unexpected mathematical binary function {:?}", function),
1047 };
1048
1049 if result.is_nan() {
1050 Value::Null
1051 } else {
1052 Value::from_f64(result)
1053 }
1054 }
1055
1056 pub fn exec_math_log(&self, base: Option<&Value>) -> Value {
1057 let Some(f) = Numeric::from_value_strict(self).map(|v| v.to_f64()) else {
1058 return Value::Null;
1059 };
1060
1061 let base = match base.map(|value| Numeric::from_value_strict(value).map(|v| v.to_f64())) {
1062 Some(Some(f)) => f,
1063 Some(None) => return Value::Null,
1064 None => 10.0,
1065 };
1066
1067 if f <= 0.0 || base <= 0.0 || base == 1.0 {
1068 return Value::Null;
1069 }
1070
1071 if base == 2.0 {
1072 return Value::from_f64(libm::log2(f));
1073 } else if base == 10.0 {
1074 return Value::from_f64(libm::log10(f));
1075 };
1076
1077 let log_x = libm::log(f);
1078 let log_base = libm::log(base);
1079
1080 if log_base <= 0.0 {
1081 return Value::Null;
1082 }
1083
1084 let result = log_x / log_base;
1085 Value::from_f64(result)
1086 }
1087
1088 pub fn exec_add(&self, rhs: &Value) -> Value {
1089 (|| Numeric::from_value(self)?.checked_add(Numeric::from_value(rhs)?))().into()
1090 }
1091
1092 pub fn exec_subtract(&self, rhs: &Value) -> Value {
1093 (|| Numeric::from_value(self)?.checked_sub(Numeric::from_value(rhs)?))().into()
1094 }
1095
1096 pub fn exec_multiply(&self, rhs: &Value) -> Value {
1097 (|| Numeric::from_value(self)?.checked_mul(Numeric::from_value(rhs)?))().into()
1098 }
1099
1100 pub fn exec_divide(&self, rhs: &Value) -> Value {
1101 (|| Numeric::from_value(self)?.checked_div(Numeric::from_value(rhs)?))().into()
1102 }
1103
1104 pub fn exec_bit_and(&self, rhs: &Value) -> Value {
1105 (NullableInteger::from(self) & NullableInteger::from(rhs)).into()
1106 }
1107
1108 pub fn exec_bit_or(&self, rhs: &Value) -> Value {
1109 (NullableInteger::from(self) | NullableInteger::from(rhs)).into()
1110 }
1111
1112 pub fn exec_remainder(&self, rhs: &Value) -> Value {
1113 let convert_to_float = matches!(Numeric::from_value(self), Some(Numeric::Float(_)))
1114 || matches!(Numeric::from_value(rhs), Some(Numeric::Float(_)));
1115
1116 match NullableInteger::from(self) % NullableInteger::from(rhs) {
1117 NullableInteger::Null => Value::Null,
1118 NullableInteger::Integer(v) => {
1119 if convert_to_float {
1120 Value::from_f64(v as f64)
1121 } else {
1122 Value::from_i64(v)
1123 }
1124 }
1125 }
1126 }
1127
1128 pub fn exec_bit_not(&self) -> Value {
1129 (!NullableInteger::from(self)).into()
1130 }
1131
1132 pub fn exec_shift_left(&self, rhs: &Value) -> Value {
1133 (NullableInteger::from(self) << NullableInteger::from(rhs)).into()
1134 }
1135
1136 pub fn exec_shift_right(&self, rhs: &Value) -> Value {
1137 (NullableInteger::from(self) >> NullableInteger::from(rhs)).into()
1138 }
1139
1140 pub fn exec_boolean_not(&self) -> Value {
1141 match Numeric::from_value(self).map(|v| v.to_bool()) {
1142 None => Value::Null,
1143 Some(v) => Value::from_i64(!v as i64),
1144 }
1145 }
1146
1147 pub fn exec_concat(&self, rhs: &Value) -> Value {
1148 if let (Value::Blob(lhs), Value::Blob(rhs)) = (self, rhs) {
1149 return Value::Blob([lhs.as_slice(), rhs.as_slice()].concat());
1150 }
1151
1152 let Some(lhs) = self.cast_text() else {
1153 return Value::Null;
1154 };
1155
1156 let Some(rhs) = rhs.cast_text() else {
1157 return Value::Null;
1158 };
1159
1160 Value::build_text(lhs + &rhs)
1161 }
1162
1163 pub fn exec_and(&self, rhs: &Value) -> Value {
1164 match (
1165 Numeric::from_value(self).map(|v| v.to_bool()),
1166 Numeric::from_value(rhs).map(|v| v.to_bool()),
1167 ) {
1168 (Some(false), _) | (_, Some(false)) => Value::from_i64(0),
1169 (None, _) | (_, None) => Value::Null,
1170 _ => Value::from_i64(1),
1171 }
1172 }
1173
1174 pub fn exec_or(&self, rhs: &Value) -> Value {
1175 match (
1176 Numeric::from_value(self).map(|v| v.to_bool()),
1177 Numeric::from_value(rhs).map(|v| v.to_bool()),
1178 ) {
1179 (Some(true), _) | (_, Some(true)) => Value::from_i64(1),
1180 (None, _) | (_, None) => Value::Null,
1181 _ => Value::from_i64(0),
1182 }
1183 }
1184
1185 pub fn exec_like(pattern: &str, text: &str, escape: Option<char>) -> Result<bool, LimboError> {
1186 const MAX_LIKE_PATTERN_LENGTH: usize = 50000;
1187 if pattern.len() > MAX_LIKE_PATTERN_LENGTH {
1188 return Err(LimboError::Constraint(
1189 "LIKE or GLOB pattern too complex".to_string(),
1190 ));
1191 }
1192 let pattern = sqlite_text_prefix(pattern);
1193 let text = sqlite_text_prefix(text);
1194
1195 let has_escape = escape.is_some_and(|e| pattern.contains(e));
1196
1197 if !has_escape && !pattern.contains(['%', '_']) {
1199 return Ok(pattern.eq_ignore_ascii_case(text));
1200 }
1201
1202 if !has_escape
1204 && pattern.ends_with('%')
1205 && !pattern[..pattern.len() - 1].contains(['%', '_'])
1206 {
1207 let prefix = &pattern[..pattern.len() - 1];
1208 if text.len() >= prefix.len() && text.is_char_boundary(prefix.len()) {
1209 return Ok(text[..prefix.len()].eq_ignore_ascii_case(prefix));
1210 }
1211 }
1213
1214 if !has_escape && pattern.starts_with('%') && !pattern[1..].contains(['%', '_']) {
1216 let suffix = &pattern[1..];
1217 let start = text.len().wrapping_sub(suffix.len());
1218 if text.len() >= suffix.len() && text.is_char_boundary(start) {
1219 return Ok(text[start..].eq_ignore_ascii_case(suffix));
1220 }
1221 }
1223
1224 Ok(pattern_compare(pattern, text, &LIKE_INFO, escape) == CompareResult::Match)
1225 }
1226
1227 pub fn exec_glob(pattern: &str, text: &str) -> Result<bool, LimboError> {
1228 const MAX_GLOB_PATTERN_LENGTH: usize = 50000;
1229 const GLOB_CHARS: [char; 3] = ['*', '?', '['];
1230
1231 if pattern.len() > MAX_GLOB_PATTERN_LENGTH {
1232 return Err(LimboError::Constraint(
1233 "GLOB pattern too complex".to_string(),
1234 ));
1235 }
1236 let pattern = sqlite_text_prefix(pattern);
1237 let text = sqlite_text_prefix(text);
1238
1239 if !pattern.contains(GLOB_CHARS) {
1241 return Ok(pattern == text);
1242 }
1243
1244 if pattern.ends_with('*') && !pattern[..pattern.len() - 1].contains(GLOB_CHARS) {
1246 let prefix = &pattern[..pattern.len() - 1];
1247 if text.len() >= prefix.len() && text.is_char_boundary(prefix.len()) {
1248 return Ok(&text[..prefix.len()] == prefix);
1249 }
1250 }
1252
1253 if pattern.starts_with('*') && !pattern[1..].contains(GLOB_CHARS) {
1255 let suffix = &pattern[1..];
1256 let start = text.len().wrapping_sub(suffix.len());
1257 if text.len() >= suffix.len() && text.is_char_boundary(start) {
1258 return Ok(&text[start..] == suffix);
1259 }
1260 }
1262
1263 Ok(pattern_compare(pattern, text, &GLOB_INFO, None) == CompareResult::Match)
1264 }
1265
1266 pub fn exec_min<'a, T: Iterator<Item = &'a Value>>(regs: T) -> Value {
1267 let mut result: Option<&Value> = None;
1269 for v in regs {
1270 if matches!(v, Value::Null) {
1271 return Value::Null;
1272 }
1273 result = Some(match result {
1274 None => v,
1275 Some(cur) if v < cur => v,
1276 Some(cur) => cur,
1277 });
1278 }
1279 result.map(|v| v.to_owned()).unwrap_or(Value::Null)
1280 }
1281
1282 pub fn exec_max<'a, T: Iterator<Item = &'a Value>>(regs: T) -> Value {
1283 let mut result: Option<&Value> = None;
1285 for v in regs {
1286 if matches!(v, Value::Null) {
1287 return Value::Null;
1288 }
1289 result = Some(match result {
1290 None => v,
1291 Some(cur) if v > cur => v,
1292 Some(cur) => cur,
1293 });
1294 }
1295 result.map(|v| v.to_owned()).unwrap_or(Value::Null)
1296 }
1297
1298 pub fn exec_group_concat(&mut self, other: &Value) {
1302 let Value::Text(text) = self else {
1303 panic!("concat_to_text must be called only on Value::Text");
1304 };
1305 text.value.to_mut().push_str(&other.to_string());
1306 }
1307
1308 pub fn exec_concat_strings<'a, T: Iterator<Item = &'a Self>>(registers: T) -> Self {
1309 let mut result = String::new();
1310 for val in registers {
1311 match val {
1312 Value::Null => continue,
1313 Value::Text(s) => result.push_str(s.as_str()),
1314 Value::Blob(b) => result.push_str(&String::from_utf8_lossy(b)),
1315 Value::Numeric(Numeric::Integer(i)) => result.push_str(&i.to_string()),
1316 Value::Numeric(Numeric::Float(f)) => result.push_str(&format_float(f64::from(*f))),
1317 }
1318 }
1319 Value::build_text(result)
1320 }
1321
1322 pub fn exec_concat_ws<'a, T: ExactSizeIterator<Item = &'a Self>>(mut registers: T) -> Self {
1323 if registers.len() == 0 {
1324 return Value::Null;
1325 }
1326
1327 let separator = match registers
1328 .next()
1329 .expect("registers should have at least one element after length check")
1330 {
1331 Value::Null | Value::Blob(_) => return Value::Null,
1332 v => format!("{v}"),
1333 };
1334
1335 let parts = registers.filter_map(|val| match val {
1336 Value::Text(_) | Value::Numeric(_) => Some(format!("{val}")),
1337 _ => None,
1338 });
1339
1340 let result = parts.collect::<Vec<_>>().join(&separator);
1341 Value::build_text(result)
1342 }
1343
1344 pub fn exec_char<'a, T: Iterator<Item = &'a Self>>(values: T) -> Self {
1345 let result: String = values
1346 .filter_map(|x| match x {
1347 Value::Numeric(Numeric::Integer(i)) => {
1348 if *i >= 0 {
1352 Some(char::from_u32(*i as u32).unwrap_or('\u{FFFD}'))
1353 } else {
1354 Some('\u{FFFD}')
1355 }
1356 }
1357 Value::Null => Some('\0'),
1359 _ => None,
1360 })
1361 .collect();
1362 Value::build_text(result)
1363 }
1364}
1365
1366fn parse_n_hex(bytes: &[u8], n: usize) -> Result<u32> {
1368 if bytes.len() < n {
1369 return Err(LimboError::ParseError("invalid Unicode escape".to_string()));
1370 }
1371 let mut v: u32 = 0;
1372 for &b in &bytes[..n] {
1373 let digit = match b {
1374 b'0'..=b'9' => b - b'0',
1375 b'a'..=b'f' => b - b'a' + 10,
1376 b'A'..=b'F' => b - b'A' + 10,
1377 _ => return Err(LimboError::ParseError("invalid Unicode escape".to_string())),
1378 };
1379 v = (v << 4) | digit as u32;
1380 }
1381 Ok(v)
1382}
1383
1384#[derive(PartialEq)]
1388enum CompareResult {
1389 Match,
1390 NoMatch,
1391 NoWildcardMatch,
1392}
1393
1394struct PatternInfo {
1395 match_all: char,
1396 match_one: char,
1397 match_set: Option<char>,
1398 no_case: bool,
1399}
1400
1401const LIKE_INFO: PatternInfo = PatternInfo {
1402 match_all: '%',
1403 match_one: '_',
1404 match_set: None,
1405 no_case: true,
1406};
1407
1408const GLOB_INFO: PatternInfo = PatternInfo {
1409 match_all: '*',
1410 match_one: '?',
1411 match_set: Some('['),
1412 no_case: false,
1413};
1414
1415fn pattern_compare(
1420 pattern: &str,
1421 text: &str,
1422 info: &PatternInfo,
1423 escape: Option<char>,
1424) -> CompareResult {
1425 let mut p_indices = pattern.char_indices();
1426 let mut t_indices = text.char_indices();
1427
1428 let mut p_curr = p_indices.next();
1429 let mut t_curr = t_indices.next();
1430
1431 let mut wildcard_p_iter: Option<std::str::CharIndices> = None;
1433 let mut wildcard_t_iter: Option<std::str::CharIndices> = None;
1434
1435 loop {
1436 match (p_curr, t_curr) {
1437 (Some((_, p_char)), Some((_, t_char))) => {
1438 if p_char == info.match_all && Some(p_char) != escape {
1439 let mut next_p = p_indices.clone();
1441 while let Some((_, c)) = next_p.clone().next() {
1442 if c == info.match_all && Some(c) != escape {
1443 next_p.next();
1444 } else {
1445 break;
1446 }
1447 }
1448
1449 let mut lookahead_p = next_p.clone();
1450 if let Some((_, next_char)) = lookahead_p.next() {
1451 let is_wildcard = (next_char == info.match_all
1452 && Some(next_char) != escape)
1453 || (next_char == info.match_one && Some(next_char) != escape)
1454 || (info.match_set == Some(next_char));
1455
1456 let is_escaped_next = Some(next_char) == escape;
1457
1458 if !is_wildcard && !is_escaped_next {
1459 let mut found = false;
1460
1461 if compare_chars(next_char, t_char, info.no_case) {
1463 found = true;
1464 } else {
1465 let lookahead_t = t_indices.clone();
1467 for (_, t_c) in lookahead_t {
1468 if compare_chars(next_char, t_c, info.no_case) {
1469 found = true;
1470 break;
1471 }
1472 }
1473 }
1474
1475 if !found {
1476 return CompareResult::NoWildcardMatch;
1477 }
1478 }
1479 }
1480
1481 p_indices = next_p;
1482 wildcard_p_iter = Some(p_indices.clone());
1483 p_curr = p_indices.next();
1484
1485 if p_curr.is_none() {
1486 return CompareResult::Match;
1487 }
1488
1489 wildcard_t_iter = Some(t_indices.clone());
1490 continue;
1491 }
1492
1493 if p_char == info.match_one && Some(p_char) != escape {
1494 p_curr = p_indices.next();
1495 t_curr = t_indices.next();
1496 continue;
1497 }
1498
1499 if info.match_set == Some(p_char) {
1501 let mut seen = false;
1502 let mut invert = false;
1503 let c = t_char;
1504
1505 let mut next_c_opt = p_indices.next();
1506
1507 if let Some((_, c2)) = next_c_opt {
1508 if c2 == '^' {
1509 invert = true;
1510 next_c_opt = p_indices.next();
1511 }
1512 }
1513
1514 let mut c2_opt = next_c_opt;
1515 if let Some((_, c2)) = c2_opt {
1516 if c2 == ']' {
1517 if c == ']' {
1518 seen = true;
1519 }
1520 c2_opt = p_indices.next();
1521 }
1522 }
1523
1524 let mut prior_c: Option<char> = None;
1525
1526 while let Some((_, c2)) = c2_opt {
1527 if c2 == ']' {
1528 break;
1529 }
1530
1531 let mut is_range = false;
1532 if c2 == '-' && prior_c.is_some() {
1533 let lookahead = p_indices.clone().next();
1534 if let Some((_, c3)) = lookahead {
1535 if c3 != ']' {
1536 is_range = true;
1537 let start = prior_c.unwrap();
1538 let end = c3;
1539 if c >= start && c <= end {
1540 seen = true;
1541 }
1542 p_indices.next();
1543 prior_c = None;
1544 }
1545 }
1546 }
1547
1548 if !is_range {
1549 if c == c2 {
1550 seen = true;
1551 }
1552 prior_c = Some(c2);
1553 }
1554
1555 c2_opt = p_indices.next();
1556 }
1557
1558 if c2_opt.is_none() || !(seen ^ invert) {
1559 } else {
1561 p_curr = p_indices.next();
1562 t_curr = t_indices.next();
1563 continue;
1564 }
1565 } else {
1566 let (expected_char, next_p_iter) = if Some(p_char) == escape {
1567 if let Some((_, literal)) = p_indices.next() {
1568 (literal, p_indices.clone())
1569 } else {
1570 return CompareResult::NoMatch;
1571 }
1572 } else {
1573 (p_char, p_indices.clone())
1574 };
1575
1576 if compare_chars(expected_char, t_char, info.no_case) {
1577 p_indices = next_p_iter;
1578 p_curr = p_indices.next();
1579 t_curr = t_indices.next();
1580 continue;
1581 }
1582 }
1583 }
1584 (None, None) => return CompareResult::Match,
1585 (Some((_, p_char)), None) if p_char == info.match_all && Some(p_char) != escape => {
1586 let mut temp = p_indices.clone();
1587 loop {
1588 match temp.next() {
1589 Some((_, c)) if c == info.match_all && Some(c) != escape => continue,
1590 None => return CompareResult::Match,
1591 _ => break,
1592 }
1593 }
1594 }
1595 _ => {}
1596 }
1597
1598 if let (Some(wp), Some(wt)) = (wildcard_p_iter.clone(), wildcard_t_iter.clone()) {
1600 p_indices = wp;
1601 p_curr = p_indices.next();
1602 t_indices = wt.clone();
1603 t_curr = t_indices.next();
1604
1605 if t_curr.is_some() {
1606 wildcard_t_iter = Some(t_indices.clone());
1607 continue;
1608 }
1609 }
1610
1611 return CompareResult::NoMatch;
1612 }
1613}
1614
1615fn compare_chars(p: char, t: char, no_case: bool) -> bool {
1616 if no_case {
1617 p.eq_ignore_ascii_case(&t)
1618 } else {
1619 p == t
1620 }
1621}
1622
1623#[cfg(clt_turso_tests)]
1624mod tests {
1625 use crate::numeric::Numeric;
1626 use crate::types::Value;
1627 use crate::vdbe::Register;
1628
1629 use rand::{Rng, RngCore};
1630
1631 #[test]
1632 fn test_exec_add() {
1633 let inputs = vec![
1634 (Value::from_i64(3), Value::from_i64(1)),
1635 (Value::from_f64(3.0), Value::from_f64(1.0)),
1636 (Value::from_f64(3.0), Value::from_i64(1)),
1637 (Value::from_i64(3), Value::from_f64(1.0)),
1638 (Value::Null, Value::Null),
1639 (Value::Null, Value::from_i64(1)),
1640 (Value::Null, Value::from_f64(1.0)),
1641 (Value::Null, Value::Text("2".into())),
1642 (Value::from_i64(1), Value::Null),
1643 (Value::from_f64(1.0), Value::Null),
1644 (Value::Text("1".into()), Value::Null),
1645 (Value::Text("1".into()), Value::Text("3".into())),
1646 (Value::Text("1.0".into()), Value::Text("3.0".into())),
1647 (Value::Text("1.0".into()), Value::from_f64(3.0)),
1648 (Value::Text("1.0".into()), Value::from_i64(3)),
1649 (Value::from_f64(1.0), Value::Text("3.0".into())),
1650 (Value::from_i64(1), Value::Text("3".into())),
1651 ];
1652
1653 let outputs = [
1654 Value::from_i64(4),
1655 Value::from_f64(4.0),
1656 Value::from_f64(4.0),
1657 Value::from_f64(4.0),
1658 Value::Null,
1659 Value::Null,
1660 Value::Null,
1661 Value::Null,
1662 Value::Null,
1663 Value::Null,
1664 Value::Null,
1665 Value::from_i64(4),
1666 Value::from_f64(4.0),
1667 Value::from_f64(4.0),
1668 Value::from_f64(4.0),
1669 Value::from_f64(4.0),
1670 Value::from_f64(4.0),
1671 ];
1672
1673 assert_eq!(
1674 inputs.len(),
1675 outputs.len(),
1676 "Inputs and Outputs should have same size"
1677 );
1678 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1679 assert_eq!(
1680 lhs.exec_add(rhs),
1681 outputs[i],
1682 "Wrong ADD for lhs: {lhs}, rhs: {rhs}"
1683 );
1684 }
1685 }
1686
1687 #[test]
1688 fn test_exec_subtract() {
1689 let inputs = vec![
1690 (Value::from_i64(3), Value::from_i64(1)),
1691 (Value::from_f64(3.0), Value::from_f64(1.0)),
1692 (Value::from_f64(3.0), Value::from_i64(1)),
1693 (Value::from_i64(3), Value::from_f64(1.0)),
1694 (Value::Null, Value::Null),
1695 (Value::Null, Value::from_i64(1)),
1696 (Value::Null, Value::from_f64(1.0)),
1697 (Value::Null, Value::Text("1".into())),
1698 (Value::from_i64(1), Value::Null),
1699 (Value::from_f64(1.0), Value::Null),
1700 (Value::Text("4".into()), Value::Null),
1701 (Value::Text("1".into()), Value::Text("3".into())),
1702 (Value::Text("1.0".into()), Value::Text("3.0".into())),
1703 (Value::Text("1.0".into()), Value::from_f64(3.0)),
1704 (Value::Text("1.0".into()), Value::from_i64(3)),
1705 (Value::from_f64(1.0), Value::Text("3.0".into())),
1706 (Value::from_i64(1), Value::Text("3".into())),
1707 ];
1708
1709 let outputs = [
1710 Value::from_i64(2),
1711 Value::from_f64(2.0),
1712 Value::from_f64(2.0),
1713 Value::from_f64(2.0),
1714 Value::Null,
1715 Value::Null,
1716 Value::Null,
1717 Value::Null,
1718 Value::Null,
1719 Value::Null,
1720 Value::Null,
1721 Value::from_i64(-2),
1722 Value::from_f64(-2.0),
1723 Value::from_f64(-2.0),
1724 Value::from_f64(-2.0),
1725 Value::from_f64(-2.0),
1726 Value::from_f64(-2.0),
1727 ];
1728
1729 assert_eq!(
1730 inputs.len(),
1731 outputs.len(),
1732 "Inputs and Outputs should have same size"
1733 );
1734 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1735 assert_eq!(
1736 lhs.exec_subtract(rhs),
1737 outputs[i],
1738 "Wrong subtract for lhs: {lhs}, rhs: {rhs}"
1739 );
1740 }
1741 }
1742
1743 #[test]
1744 fn test_exec_multiply() {
1745 let inputs = vec![
1746 (Value::from_i64(3), Value::from_i64(2)),
1747 (Value::from_f64(3.0), Value::from_f64(2.0)),
1748 (Value::from_f64(3.0), Value::from_i64(2)),
1749 (Value::from_i64(3), Value::from_f64(2.0)),
1750 (Value::Null, Value::Null),
1751 (Value::Null, Value::from_i64(1)),
1752 (Value::Null, Value::from_f64(1.0)),
1753 (Value::Null, Value::Text("1".into())),
1754 (Value::from_i64(1), Value::Null),
1755 (Value::from_f64(1.0), Value::Null),
1756 (Value::Text("4".into()), Value::Null),
1757 (Value::Text("2".into()), Value::Text("3".into())),
1758 (Value::Text("2.0".into()), Value::Text("3.0".into())),
1759 (Value::Text("2.0".into()), Value::from_f64(3.0)),
1760 (Value::Text("2.0".into()), Value::from_i64(3)),
1761 (Value::from_f64(2.0), Value::Text("3.0".into())),
1762 (Value::from_i64(2), Value::Text("3.0".into())),
1763 ];
1764
1765 let outputs = [
1766 Value::from_i64(6),
1767 Value::from_f64(6.0),
1768 Value::from_f64(6.0),
1769 Value::from_f64(6.0),
1770 Value::Null,
1771 Value::Null,
1772 Value::Null,
1773 Value::Null,
1774 Value::Null,
1775 Value::Null,
1776 Value::Null,
1777 Value::from_i64(6),
1778 Value::from_f64(6.0),
1779 Value::from_f64(6.0),
1780 Value::from_f64(6.0),
1781 Value::from_f64(6.0),
1782 Value::from_f64(6.0),
1783 ];
1784
1785 assert_eq!(
1786 inputs.len(),
1787 outputs.len(),
1788 "Inputs and Outputs should have same size"
1789 );
1790 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1791 assert_eq!(
1792 lhs.exec_multiply(rhs),
1793 outputs[i],
1794 "Wrong multiply for lhs: {lhs}, rhs: {rhs}"
1795 );
1796 }
1797 }
1798
1799 #[test]
1800 fn test_exec_divide() {
1801 let inputs = vec![
1802 (Value::from_i64(1), Value::from_i64(0)),
1803 (Value::from_f64(1.0), Value::from_f64(0.0)),
1804 (Value::from_i64(i64::MIN), Value::from_i64(-1)),
1805 (Value::from_f64(6.0), Value::from_f64(2.0)),
1806 (Value::from_f64(6.0), Value::from_i64(2)),
1807 (Value::from_i64(6), Value::from_i64(2)),
1808 (Value::Null, Value::from_i64(2)),
1809 (Value::from_i64(2), Value::Null),
1810 (Value::Null, Value::Null),
1811 (Value::Text("6".into()), Value::Text("2".into())),
1812 (Value::Text("6".into()), Value::from_i64(2)),
1813 ];
1814
1815 let outputs = [
1816 Value::Null,
1817 Value::Null,
1818 Value::from_f64(9.223372036854776e18),
1819 Value::from_f64(3.0),
1820 Value::from_f64(3.0),
1821 Value::from_f64(3.0),
1822 Value::Null,
1823 Value::Null,
1824 Value::Null,
1825 Value::from_f64(3.0),
1826 Value::from_f64(3.0),
1827 ];
1828
1829 assert_eq!(
1830 inputs.len(),
1831 outputs.len(),
1832 "Inputs and Outputs should have same size"
1833 );
1834 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1835 assert_eq!(
1836 lhs.exec_divide(rhs),
1837 outputs[i],
1838 "Wrong divide for lhs: {lhs}, rhs: {rhs}"
1839 );
1840 }
1841 }
1842
1843 #[test]
1844 fn test_exec_remainder() {
1845 let inputs = vec![
1846 (Value::Null, Value::Null),
1847 (Value::Null, Value::from_f64(1.0)),
1848 (Value::Null, Value::from_i64(1)),
1849 (Value::Null, Value::Text("1".into())),
1850 (Value::from_f64(1.0), Value::Null),
1851 (Value::from_i64(1), Value::Null),
1852 (Value::from_i64(12), Value::from_i64(0)),
1853 (Value::from_f64(12.0), Value::from_f64(0.0)),
1854 (Value::from_f64(12.0), Value::from_i64(0)),
1855 (Value::from_i64(12), Value::from_f64(0.0)),
1856 (Value::from_i64(i64::MIN), Value::from_i64(-1)),
1857 (Value::from_i64(12), Value::from_i64(3)),
1858 (Value::from_f64(12.0), Value::from_f64(3.0)),
1859 (Value::from_f64(12.0), Value::from_i64(3)),
1860 (Value::from_i64(12), Value::from_f64(3.0)),
1861 (Value::from_i64(12), Value::from_i64(-3)),
1862 (Value::from_f64(12.0), Value::from_f64(-3.0)),
1863 (Value::from_f64(12.0), Value::from_i64(-3)),
1864 (Value::from_i64(12), Value::from_f64(-3.0)),
1865 (Value::Text("12.0".into()), Value::Text("3.0".into())),
1866 (Value::Text("12.0".into()), Value::from_f64(3.0)),
1867 (Value::from_f64(12.0), Value::Text("3.0".into())),
1868 ];
1869 let outputs = vec![
1870 Value::Null,
1871 Value::Null,
1872 Value::Null,
1873 Value::Null,
1874 Value::Null,
1875 Value::Null,
1876 Value::Null,
1877 Value::Null,
1878 Value::Null,
1879 Value::Null,
1880 Value::from_f64(0.0),
1881 Value::from_i64(0),
1882 Value::from_f64(0.0),
1883 Value::from_f64(0.0),
1884 Value::from_f64(0.0),
1885 Value::from_i64(0),
1886 Value::from_f64(0.0),
1887 Value::from_f64(0.0),
1888 Value::from_f64(0.0),
1889 Value::from_f64(0.0),
1890 Value::from_f64(0.0),
1891 Value::from_f64(0.0),
1892 ];
1893
1894 assert_eq!(
1895 inputs.len(),
1896 outputs.len(),
1897 "Inputs and Outputs should have same size"
1898 );
1899
1900 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1901 assert_eq!(
1902 lhs.exec_remainder(rhs),
1903 outputs[i],
1904 "Wrong remainder for lhs: {lhs}, rhs: {rhs}"
1905 );
1906 }
1907 }
1908
1909 #[test]
1910 fn test_exec_and() {
1911 let inputs = vec![
1912 (Value::from_i64(0), Value::Null),
1913 (Value::Null, Value::from_i64(1)),
1914 (Value::Null, Value::Null),
1915 (Value::from_f64(0.0), Value::Null),
1916 (Value::from_i64(1), Value::from_f64(2.2)),
1917 (Value::from_i64(0), Value::Text("string".into())),
1918 (Value::from_i64(0), Value::Text("1".into())),
1919 (Value::from_i64(1), Value::Text("1".into())),
1920 ];
1921 let outputs = [
1922 Value::from_i64(0),
1923 Value::Null,
1924 Value::Null,
1925 Value::from_i64(0),
1926 Value::from_i64(1),
1927 Value::from_i64(0),
1928 Value::from_i64(0),
1929 Value::from_i64(1),
1930 ];
1931
1932 assert_eq!(
1933 inputs.len(),
1934 outputs.len(),
1935 "Inputs and Outputs should have same size"
1936 );
1937 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1938 assert_eq!(
1939 lhs.exec_and(rhs),
1940 outputs[i],
1941 "Wrong AND for lhs: {lhs}, rhs: {rhs}"
1942 );
1943 }
1944 }
1945
1946 #[test]
1947 fn test_exec_or() {
1948 let inputs = vec![
1949 (Value::from_i64(0), Value::Null),
1950 (Value::Null, Value::from_i64(1)),
1951 (Value::Null, Value::Null),
1952 (Value::from_f64(0.0), Value::Null),
1953 (Value::from_i64(1), Value::from_f64(2.2)),
1954 (Value::from_f64(0.0), Value::from_i64(0)),
1955 (Value::from_i64(0), Value::Text("string".into())),
1956 (Value::from_i64(0), Value::Text("1".into())),
1957 (Value::from_i64(0), Value::Text("".into())),
1958 ];
1959 let outputs = [
1960 Value::Null,
1961 Value::from_i64(1),
1962 Value::Null,
1963 Value::Null,
1964 Value::from_i64(1),
1965 Value::from_i64(0),
1966 Value::from_i64(0),
1967 Value::from_i64(1),
1968 Value::from_i64(0),
1969 ];
1970
1971 assert_eq!(
1972 inputs.len(),
1973 outputs.len(),
1974 "Inputs and Outputs should have same size"
1975 );
1976 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1977 assert_eq!(
1978 lhs.exec_or(rhs),
1979 outputs[i],
1980 "Wrong OR for lhs: {lhs}, rhs: {rhs}"
1981 );
1982 }
1983 }
1984
1985 #[test]
1986 fn test_length() {
1987 let input_str = Value::build_text("bob");
1988 let expected_len = Value::from_i64(3);
1989 assert_eq!(input_str.exec_length(), expected_len);
1990
1991 let input_integer = Value::from_i64(123);
1992 let expected_len = Value::from_i64(3);
1993 assert_eq!(input_integer.exec_length(), expected_len);
1994
1995 let input_float = Value::from_f64(123.456);
1996 let expected_len = Value::from_i64(7);
1997 assert_eq!(input_float.exec_length(), expected_len);
1998
1999 let expected_blob = Value::Blob("example".as_bytes().to_vec());
2000 let expected_len = Value::from_i64(7);
2001 assert_eq!(expected_blob.exec_length(), expected_len);
2002 }
2003
2004 #[test]
2005 fn test_quote() {
2006 let input = Value::build_text("abc\0edf");
2007 let expected = Value::build_text("'abc'");
2008 assert_eq!(input.exec_quote(), expected);
2009
2010 let input = Value::from_i64(123);
2011 let expected = Value::build_text("123");
2012 assert_eq!(input.exec_quote(), expected);
2013
2014 let input = Value::from_f64(12.34);
2015 let expected = Value::build_text("12.34");
2016 assert_eq!(input.exec_quote(), expected);
2017
2018 let input = Value::build_text("hello''world");
2019 let expected = Value::build_text("'hello''''world'");
2020 assert_eq!(input.exec_quote(), expected);
2021
2022 let input = Value::from_f64(
2023 crate::numeric::str_to_f64("2.042747795102219097e+05")
2024 .map(f64::from)
2025 .unwrap(),
2026 );
2027 let expected = Value::build_text("2.042747795102219097e+05");
2028 assert_eq!(input.exec_quote(), expected);
2029 }
2030
2031 #[test]
2032 fn test_typeof() {
2033 let input = Value::Null;
2034 let expected: Value = Value::build_text("null");
2035 assert_eq!(input.exec_typeof(), expected);
2036
2037 let input = Value::from_i64(123);
2038 let expected: Value = Value::build_text("integer");
2039 assert_eq!(input.exec_typeof(), expected);
2040
2041 let input = Value::from_f64(123.456);
2042 let expected: Value = Value::build_text("real");
2043 assert_eq!(input.exec_typeof(), expected);
2044
2045 let input = Value::build_text("hello");
2046 let expected: Value = Value::build_text("text");
2047 assert_eq!(input.exec_typeof(), expected);
2048
2049 let input = Value::Blob("limbo".as_bytes().to_vec());
2050 let expected: Value = Value::build_text("blob");
2051 assert_eq!(input.exec_typeof(), expected);
2052 }
2053
2054 #[test]
2055 fn test_unicode() {
2056 assert_eq!(Value::build_text("a").exec_unicode(), Value::from_i64(97));
2057 assert_eq!(
2058 Value::build_text("😊").exec_unicode(),
2059 Value::from_i64(128522)
2060 );
2061 assert_eq!(Value::build_text("").exec_unicode(), Value::Null);
2062 assert_eq!(Value::build_text("\0").exec_unicode(), Value::Null);
2063 assert_eq!(Value::from_i64(23).exec_unicode(), Value::from_i64(50));
2064 assert_eq!(Value::from_i64(0).exec_unicode(), Value::from_i64(48));
2065 assert_eq!(Value::from_f64(0.0).exec_unicode(), Value::from_i64(48));
2066 assert_eq!(Value::from_f64(23.45).exec_unicode(), Value::from_i64(50));
2067 assert_eq!(Value::Null.exec_unicode(), Value::Null);
2068 assert_eq!(
2069 Value::Blob("example".as_bytes().to_vec()).exec_unicode(),
2070 Value::from_i64(101)
2071 );
2072 }
2073
2074 #[test]
2075 fn test_unistr() {
2076 assert_eq!(
2078 Value::build_text(r"\u0041").exec_unistr().unwrap(),
2079 Value::build_text("A")
2080 );
2081 assert_eq!(
2082 Value::build_text(r"\0041").exec_unistr().unwrap(),
2083 Value::build_text("A")
2084 );
2085 assert_eq!(
2086 Value::build_text(r"\+01F600").exec_unistr().unwrap(),
2087 Value::build_text("😀")
2088 );
2089 assert_eq!(
2090 Value::build_text(r"\U0001F600").exec_unistr().unwrap(),
2091 Value::build_text("😀")
2092 );
2093 assert_eq!(
2095 Value::build_text(r"a\\b").exec_unistr().unwrap(),
2096 Value::build_text(r"a\b")
2097 );
2098 assert_eq!(
2100 Value::build_text(r"\u00E4").exec_unistr().unwrap(),
2101 Value::build_text("ä")
2102 );
2103 assert_eq!(
2104 Value::build_text(r"\u00e4").exec_unistr().unwrap(),
2105 Value::build_text("ä")
2106 );
2107 assert_eq!(
2109 Value::build_text(r"\u0048\u0065\u006C\u006C\u006F")
2110 .exec_unistr()
2111 .unwrap(),
2112 Value::build_text("Hello")
2113 );
2114 assert_eq!(
2116 Value::build_text(r"hi \u0041 \U0001F600")
2117 .exec_unistr()
2118 .unwrap(),
2119 Value::build_text("hi A 😀")
2120 );
2121 assert_eq!(
2123 Value::build_text("hello").exec_unistr().unwrap(),
2124 Value::build_text("hello")
2125 );
2126 assert_eq!(
2128 Value::build_text("").exec_unistr().unwrap(),
2129 Value::build_text("")
2130 );
2131 assert_eq!(Value::Null.exec_unistr().unwrap(), Value::Null);
2133 assert_eq!(
2135 Value::build_text(r"\u0000").exec_unistr().unwrap(),
2136 Value::build_text("\0")
2137 );
2138 assert!(Value::build_text(r"\uD83D").exec_unistr().is_err());
2140 assert!(Value::build_text(r"\U00110000").exec_unistr().is_err());
2142 assert!(Value::build_text(r"\q").exec_unistr().is_err());
2144 assert!(Value::build_text(r"\u00").exec_unistr().is_err());
2145 assert!(Value::build_text("abc\\").exec_unistr().is_err());
2146 assert!(Value::build_text(r"\u00GG").exec_unistr().is_err());
2148 assert!(Value::build_text(r"\+01FG00").exec_unistr().is_err());
2149 assert!(Value::build_text(r"\U0001F6GG").exec_unistr().is_err());
2150 }
2151
2152 #[test]
2153 fn test_unistr_quote() {
2154 assert_eq!(Value::Null.exec_unistr_quote(), Value::build_text("NULL"));
2155 assert_eq!(
2156 Value::from_i64(42).exec_unistr_quote(),
2157 Value::build_text("42")
2158 );
2159 assert_eq!(
2160 Value::from_f64(1.5).exec_unistr_quote(),
2161 Value::build_text("1.5")
2162 );
2163 assert_eq!(
2164 Value::Blob(vec![0xDE, 0xAD]).exec_unistr_quote(),
2165 Value::build_text("X'DEAD'")
2166 );
2167 assert_eq!(
2168 Value::build_text("hello").exec_unistr_quote(),
2169 Value::build_text("'hello'")
2170 );
2171 assert_eq!(
2173 Value::build_text("a\\b").exec_unistr_quote(),
2174 Value::build_text("'a\\b'")
2175 );
2176 assert_eq!(
2177 Value::build_text("it's").exec_unistr_quote(),
2178 Value::build_text("'it''s'")
2179 );
2180 assert_eq!(
2181 Value::build_text("a\tb").exec_unistr_quote(),
2182 Value::build_text("unistr('a\\u0009b')")
2183 );
2184 assert_eq!(
2185 Value::build_text("a\t\\b").exec_unistr_quote(),
2186 Value::build_text("unistr('a\\u0009\\\\b')")
2187 );
2188 assert_eq!(
2189 Value::build_text("a\tb'c").exec_unistr_quote(),
2190 Value::build_text("unistr('a\\u0009b''c')")
2191 );
2192 assert_eq!(
2193 Value::build_text("\x01abc'\\\t\n\r\x1fXYZ\0\x01tail").exec_unistr_quote(),
2194 Value::build_text(r"unistr('\u0001abc''\\\u0009\u000a\u000d\u001fXYZ')")
2195 );
2196 assert_eq!(
2197 Value::build_text("a\x01b\0c").exec_unistr_quote(),
2198 Value::build_text("unistr('a\\u0001b')")
2199 );
2200 assert_eq!(
2201 Value::build_text("\x01").exec_unistr_quote(),
2202 Value::build_text("unistr('\\u0001')")
2203 );
2204 assert_eq!(
2205 Value::build_text("\x01\x1f").exec_unistr_quote(),
2206 Value::build_text("unistr('\\u0001\\u001f')")
2207 );
2208 assert_eq!(
2209 Value::build_text("\x10").exec_unistr_quote(),
2210 Value::build_text("unistr('\\u0010')")
2211 );
2212 assert_eq!(
2213 Value::build_text("\x1f").exec_unistr_quote(),
2214 Value::build_text("unistr('\\u001f')")
2215 );
2216 assert_eq!(
2218 Value::build_text(" ").exec_unistr_quote(),
2219 Value::build_text("' '")
2220 );
2221 assert_eq!(
2222 Value::build_text("\0abc").exec_unistr_quote(),
2223 Value::build_text("''")
2224 );
2225 assert_eq!(
2226 Value::build_text("").exec_unistr_quote(),
2227 Value::build_text("''")
2228 );
2229 assert_eq!(
2230 Value::build_text("a\nb").exec_unistr_quote(),
2231 Value::build_text("unistr('a\\u000ab')")
2232 );
2233 assert_eq!(
2234 Value::build_text("a\rb").exec_unistr_quote(),
2235 Value::build_text("unistr('a\\u000db')")
2236 );
2237 assert_eq!(
2238 Value::build_text("a\0\t").exec_unistr_quote(),
2239 Value::build_text("'a'")
2240 );
2241 }
2242
2243 #[test]
2244 fn test_min_max() {
2245 let input_int_vec = [
2246 Register::Value(Value::from_i64(-1)),
2247 Register::Value(Value::from_i64(10)),
2248 ];
2249 assert_eq!(
2250 Value::exec_min(input_int_vec.iter().map(|v| v.get_value())),
2251 Value::from_i64(-1)
2252 );
2253 assert_eq!(
2254 Value::exec_max(input_int_vec.iter().map(|v| v.get_value())),
2255 Value::from_i64(10)
2256 );
2257
2258 let str1 = Register::Value(Value::build_text("A"));
2259 let str2 = Register::Value(Value::build_text("z"));
2260 let input_str_vec = [str2, str1.clone()];
2261 assert_eq!(
2262 Value::exec_min(input_str_vec.iter().map(|v| v.get_value())),
2263 Value::build_text("A")
2264 );
2265 assert_eq!(
2266 Value::exec_max(input_str_vec.iter().map(|v| v.get_value())),
2267 Value::build_text("z")
2268 );
2269
2270 let input_null_vec = [Register::Value(Value::Null), Register::Value(Value::Null)];
2271 assert_eq!(
2272 Value::exec_min(input_null_vec.iter().map(|v| v.get_value())),
2273 Value::Null
2274 );
2275 assert_eq!(
2276 Value::exec_max(input_null_vec.iter().map(|v| v.get_value())),
2277 Value::Null
2278 );
2279
2280 let input_mixed_vec = [Register::Value(Value::from_i64(10)), str1];
2281 assert_eq!(
2282 Value::exec_min(input_mixed_vec.iter().map(|v| v.get_value())),
2283 Value::from_i64(10)
2284 );
2285 assert_eq!(
2286 Value::exec_max(input_mixed_vec.iter().map(|v| v.get_value())),
2287 Value::build_text("A")
2288 );
2289
2290 let input_with_null = [
2292 Register::Value(Value::from_i64(1)),
2293 Register::Value(Value::Null),
2294 ];
2295 assert_eq!(
2296 Value::exec_min(input_with_null.iter().map(|v| v.get_value())),
2297 Value::Null
2298 );
2299 assert_eq!(
2300 Value::exec_max(input_with_null.iter().map(|v| v.get_value())),
2301 Value::Null
2302 );
2303 }
2304
2305 #[test]
2306 fn test_trim() {
2307 let input_str = Value::build_text(" Bob and Alice ");
2308 let expected_str = Value::build_text("Bob and Alice");
2309 assert_eq!(input_str.exec_trim(None), expected_str);
2310
2311 let input_str = Value::build_text(" Bob and Alice ");
2312 let pattern_str = Value::build_text("Bob and");
2313 let expected_str = Value::build_text("Alice");
2314 assert_eq!(input_str.exec_trim(Some(&pattern_str)), expected_str);
2315
2316 let input_str = Value::build_text("\ta");
2317 let expected_str = Value::build_text("\ta");
2318 assert_eq!(input_str.exec_trim(None), expected_str);
2319
2320 let input_str = Value::build_text("\na");
2321 let expected_str = Value::build_text("\na");
2322 assert_eq!(input_str.exec_trim(None), expected_str);
2323
2324 let input_int = Value::from_i64(12345);
2326 let expected_text = Value::build_text("12345");
2327 assert_eq!(input_int.exec_trim(None), expected_text);
2328
2329 let input_float = Value::from_f64(123.5);
2331 let expected_text = Value::build_text("123.5");
2332 assert_eq!(input_float.exec_trim(None), expected_text);
2333 }
2334
2335 #[test]
2336 fn test_ltrim() {
2337 let input_str = Value::build_text(" Bob and Alice ");
2338 let expected_str = Value::build_text("Bob and Alice ");
2339 assert_eq!(input_str.exec_ltrim(None), expected_str);
2340
2341 let input_str = Value::build_text(" Bob and Alice ");
2342 let pattern_str = Value::build_text("Bob and");
2343 let expected_str = Value::build_text("Alice ");
2344 assert_eq!(input_str.exec_ltrim(Some(&pattern_str)), expected_str);
2345 }
2346
2347 #[test]
2348 fn test_rtrim() {
2349 let input_str = Value::build_text(" Bob and Alice ");
2350 let expected_str = Value::build_text(" Bob and Alice");
2351 assert_eq!(input_str.exec_rtrim(None), expected_str);
2352
2353 let input_str = Value::build_text(" Bob and Alice ");
2354 let pattern_str = Value::build_text("Bob and");
2355 let expected_str = Value::build_text(" Bob and Alice");
2356 assert_eq!(input_str.exec_rtrim(Some(&pattern_str)), expected_str);
2357
2358 let input_str = Value::build_text(" Bob and Alice ");
2359 let pattern_str = Value::build_text("and Alice");
2360 let expected_str = Value::build_text(" Bob");
2361 assert_eq!(input_str.exec_rtrim(Some(&pattern_str)), expected_str);
2362 }
2363
2364 #[test]
2365 fn test_soundex() {
2366 let input_str = Value::build_text("Pfister");
2367 let expected_str = Value::build_text("P236");
2368 assert_eq!(input_str.exec_soundex(), expected_str);
2369
2370 let input_str = Value::build_text("husobee");
2371 let expected_str = Value::build_text("H210");
2372 assert_eq!(input_str.exec_soundex(), expected_str);
2373
2374 let input_str = Value::build_text("Tymczak");
2375 let expected_str = Value::build_text("T522");
2376 assert_eq!(input_str.exec_soundex(), expected_str);
2377
2378 let input_str = Value::build_text("Ashcraft");
2379 let expected_str = Value::build_text("A261");
2380 assert_eq!(input_str.exec_soundex(), expected_str);
2381
2382 let input_str = Value::build_text("Robert");
2383 let expected_str = Value::build_text("R163");
2384 assert_eq!(input_str.exec_soundex(), expected_str);
2385
2386 let input_str = Value::build_text("Rupert");
2387 let expected_str = Value::build_text("R163");
2388 assert_eq!(input_str.exec_soundex(), expected_str);
2389
2390 let input_str = Value::build_text("Rubin");
2391 let expected_str = Value::build_text("R150");
2392 assert_eq!(input_str.exec_soundex(), expected_str);
2393
2394 let input_str = Value::build_text("Kant");
2395 let expected_str = Value::build_text("K530");
2396 assert_eq!(input_str.exec_soundex(), expected_str);
2397
2398 let input_str = Value::build_text("Knuth");
2399 let expected_str = Value::build_text("K530");
2400 assert_eq!(input_str.exec_soundex(), expected_str);
2401
2402 let input_str = Value::build_text("x");
2403 let expected_str = Value::build_text("X000");
2404 assert_eq!(input_str.exec_soundex(), expected_str);
2405
2406 let input_str = Value::build_text("闪电五连éž");
2407 let expected_str = Value::build_text("?000");
2408 assert_eq!(input_str.exec_soundex(), expected_str);
2409 }
2410
2411 #[test]
2412 fn test_upper_case() {
2413 let input_str = Value::build_text("Limbo");
2414 let expected_str = Value::build_text("LIMBO");
2415 assert_eq!(input_str.exec_upper().unwrap(), expected_str);
2416
2417 let input_int = Value::from_i64(10);
2418 assert_eq!(input_int.exec_upper().unwrap(), Value::build_text("10"));
2419 assert_eq!(Value::Null.exec_upper(), None)
2420 }
2421
2422 #[test]
2423 fn test_lower_case() {
2424 let input_str = Value::build_text("Limbo");
2425 let expected_str = Value::build_text("limbo");
2426 assert_eq!(input_str.exec_lower().unwrap(), expected_str);
2427
2428 let input_int = Value::from_i64(10);
2429 assert_eq!(input_int.exec_lower().unwrap(), Value::build_text("10"));
2430 assert_eq!(Value::Null.exec_lower(), None)
2431 }
2432
2433 #[test]
2434 fn test_hex() {
2435 let input_str = Value::build_text("limbo");
2436 let expected_val = Value::build_text("6C696D626F");
2437 assert_eq!(input_str.exec_hex(), expected_val);
2438
2439 let input_int = Value::from_i64(100);
2440 let expected_val = Value::build_text("313030");
2441 assert_eq!(input_int.exec_hex(), expected_val);
2442
2443 let input_float = Value::from_f64(12.34);
2444 let expected_val = Value::build_text("31322E3334");
2445 assert_eq!(input_float.exec_hex(), expected_val);
2446
2447 let input_blob = Value::Blob(vec![0xff]);
2448 let expected_val = Value::build_text("FF");
2449 assert_eq!(input_blob.exec_hex(), expected_val);
2450 }
2451
2452 #[test]
2453 fn test_cast_blob_preserves_blob_bytes() {
2454 let input_blob = Value::Blob(vec![0xd2, 0x64, 0xc0, 0x07, 0xf6, 0x44, 0xe4, 0x59]);
2455 let expected = input_blob.clone();
2456
2457 assert_eq!(input_blob.exec_cast("BLOB"), expected);
2458 }
2459
2460 #[test]
2461 fn test_unhex() {
2462 let input = Value::build_text("6f");
2463 let expected = Value::Blob(vec![0x6f]);
2464 assert_eq!(input.exec_unhex(None), expected);
2465
2466 let input = Value::build_text("6f");
2467 let expected = Value::Blob(vec![0x6f]);
2468 assert_eq!(input.exec_unhex(None), expected);
2469
2470 let input = Value::build_text("611");
2471 let expected = Value::Null;
2472 assert_eq!(input.exec_unhex(None), expected);
2473
2474 let input = Value::build_text("");
2475 let expected = Value::Blob(vec![]);
2476 assert_eq!(input.exec_unhex(None), expected);
2477
2478 let input = Value::build_text("61x");
2479 let expected = Value::Null;
2480 assert_eq!(input.exec_unhex(None), expected);
2481
2482 let input = Value::Null;
2483 let expected = Value::Null;
2484 assert_eq!(input.exec_unhex(None), expected);
2485
2486 let input = Value::build_text("aa-bb");
2487 let expected = Value::Blob(vec![0xaa, 0xbb]);
2488 assert_eq!(input.exec_unhex(Some(&Value::build_text("-"))), expected);
2489
2490 let input = Value::build_text("aa--bb");
2491 let expected = Value::Blob(vec![0xaa, 0xbb]);
2492 assert_eq!(input.exec_unhex(Some(&Value::build_text("-"))), expected);
2493
2494 let input = Value::build_text("aa-bb-cc");
2495 let expected = Value::Blob(vec![0xaa, 0xbb, 0xcc]);
2496 assert_eq!(input.exec_unhex(Some(&Value::build_text("-"))), expected);
2497
2498 let input = Value::build_text("aa bb");
2499 let expected = Value::Blob(vec![0xaa, 0xbb]);
2500 assert_eq!(input.exec_unhex(Some(&Value::build_text(" "))), expected);
2501
2502 let input = Value::build_text("A BCD");
2503 let expected = Value::Null;
2504 assert_eq!(input.exec_unhex(Some(&Value::build_text(" "))), expected);
2505
2506 let input = Value::build_text("yx2xEzyx");
2507 let expected = Value::Null;
2508 assert_eq!(input.exec_unhex(Some(&Value::build_text("xyz"))), expected);
2509
2510 let input = Value::build_text("aa?bb");
2511 let expected = Value::Null;
2512 assert_eq!(input.exec_unhex(Some(&Value::build_text("-"))), expected);
2513
2514 let input = Value::build_text("aabb");
2515 let expected = Value::Null;
2516 assert_eq!(input.exec_unhex(Some(&Value::Null)), expected);
2517 }
2518
2519 #[test]
2520 fn test_abs() {
2521 let int_positive_reg = Value::from_i64(10);
2522 let int_negative_reg = Value::from_i64(-10);
2523 assert_eq!(int_positive_reg.exec_abs().unwrap(), int_positive_reg);
2524 assert_eq!(int_negative_reg.exec_abs().unwrap(), int_positive_reg);
2525
2526 let float_positive_reg = Value::from_i64(10);
2527 let float_negative_reg = Value::from_i64(-10);
2528 assert_eq!(float_positive_reg.exec_abs().unwrap(), float_positive_reg);
2529 assert_eq!(float_negative_reg.exec_abs().unwrap(), float_positive_reg);
2530
2531 assert_eq!(
2532 Value::build_text("a").exec_abs().unwrap(),
2533 Value::from_f64(0.0)
2534 );
2535 assert_eq!(Value::Null.exec_abs().unwrap(), Value::Null);
2536
2537 assert!(Value::from_i64(i64::MIN).exec_abs().is_err());
2539 }
2540
2541 #[test]
2542 fn test_char() {
2543 assert_eq!(
2544 Value::exec_char(
2545 [
2546 Register::Value(Value::from_i64(108)),
2547 Register::Value(Value::from_i64(105))
2548 ]
2549 .iter()
2550 .map(|reg| reg.get_value())
2551 ),
2552 Value::build_text("li")
2553 );
2554 assert_eq!(Value::exec_char(std::iter::empty()), Value::build_text(""));
2555 assert_eq!(
2556 Value::exec_char(
2557 [Register::Value(Value::Null)]
2558 .iter()
2559 .map(|reg| reg.get_value())
2560 ),
2561 Value::build_text("\0")
2562 );
2563 assert_eq!(
2564 Value::exec_char(
2565 [Register::Value(Value::build_text("a"))]
2566 .iter()
2567 .map(|reg| reg.get_value())
2568 ),
2569 Value::build_text("")
2570 );
2571 }
2572
2573 #[test]
2574 fn test_like_with_escape_or_regexmeta_chars() {
2575 assert!(Value::exec_like(r#"\%A"#, r#"\A"#, None).unwrap());
2576 assert!(Value::exec_like("%a%a", "aaaa", None).unwrap());
2577 }
2578
2579 #[test]
2580 fn test_like_without_escape() {
2581 assert!(Value::exec_like("a%", "aaaa", None).unwrap());
2582 assert!(Value::exec_like("%a%a", "aaaa", None).unwrap());
2583 assert!(!Value::exec_like("%a.a", "aaaa", None).unwrap());
2584 assert!(!Value::exec_like("a.a%", "aaaa", None).unwrap());
2585 assert!(!Value::exec_like("%a.ab", "aaaa", None).unwrap());
2586 }
2587
2588 #[test]
2589 fn test_exec_like_with_escape() {
2590 assert!(Value::exec_like("abcX%", "abc%", Some('X')).unwrap());
2591 assert!(!Value::exec_like("abcX%", "abc5", Some('X')).unwrap());
2592 assert!(!Value::exec_like("abcX%", "abc", Some('X')).unwrap());
2593 assert!(!Value::exec_like("abcX%", "abcX%", Some('X')).unwrap());
2594 assert!(!Value::exec_like("abcX%", "abc%%", Some('X')).unwrap());
2595
2596 assert!(Value::exec_like("abcX_", "abc_", Some('X')).unwrap());
2597 assert!(!Value::exec_like("abcX_", "abc5", Some('X')).unwrap());
2598 assert!(!Value::exec_like("abcX_", "abc", Some('X')).unwrap());
2599 assert!(!Value::exec_like("abcX_", "abcX_", Some('X')).unwrap());
2600 assert!(!Value::exec_like("abcX_", "abc__", Some('X')).unwrap());
2601
2602 assert!(Value::exec_like("abcXX", "abcX", Some('X')).unwrap());
2603 assert!(!Value::exec_like("abcXX", "abc5", Some('X')).unwrap());
2604 assert!(!Value::exec_like("abcXX", "abc", Some('X')).unwrap());
2605 assert!(!Value::exec_like("abcXX", "abcXX", Some('X')).unwrap());
2606 }
2607
2608 #[test]
2609 fn test_glob() {
2610 assert!(Value::exec_glob(r#"?*/abc/?*"#, r#"x//a/ab/abc/y"#).unwrap());
2611 assert!(Value::exec_glob(r#"a[1^]"#, r#"a1"#).unwrap());
2612 assert!(Value::exec_glob(r#"a[1^]*"#, r#"a^"#).unwrap());
2613 assert!(!Value::exec_glob(r#"a[a*"#, r#"a["#).unwrap());
2614 assert!(!Value::exec_glob(r#"a[a"#, r#"a[a"#).unwrap());
2615 assert!(Value::exec_glob(r#"a[[]"#, r#"a["#).unwrap());
2616 assert!(Value::exec_glob(r#"abc[^][*?]efg"#, r#"abcdefg"#).unwrap());
2617 assert!(!Value::exec_glob(r#"abc[^][*?]efg"#, r#"abc]efg"#).unwrap());
2618 }
2619
2620 #[test]
2621 fn test_random() {
2622 match Value::exec_random(|| rand::rng().random()) {
2623 Value::Numeric(Numeric::Integer(value)) => {
2624 assert!(
2626 (i64::MIN..=i64::MAX).contains(&value),
2627 "Random number out of range"
2628 );
2629 }
2630 _ => panic!("exec_random did not return an Integer variant"),
2631 }
2632 }
2633
2634 #[test]
2635 fn test_exec_randomblob() {
2636 struct TestCase {
2637 input: Value,
2638 expected_len: usize,
2639 }
2640
2641 let test_cases = vec![
2642 TestCase {
2643 input: Value::from_i64(5),
2644 expected_len: 5,
2645 },
2646 TestCase {
2647 input: Value::from_i64(0),
2648 expected_len: 1,
2649 },
2650 TestCase {
2651 input: Value::from_i64(-1),
2652 expected_len: 1,
2653 },
2654 TestCase {
2655 input: Value::build_text(""),
2656 expected_len: 1,
2657 },
2658 TestCase {
2659 input: Value::build_text("5"),
2660 expected_len: 5,
2661 },
2662 TestCase {
2663 input: Value::build_text("0"),
2664 expected_len: 1,
2665 },
2666 TestCase {
2667 input: Value::build_text("-1"),
2668 expected_len: 1,
2669 },
2670 TestCase {
2671 input: Value::from_f64(2.9),
2672 expected_len: 2,
2673 },
2674 TestCase {
2675 input: Value::from_f64(-3.15),
2676 expected_len: 1,
2677 },
2678 TestCase {
2679 input: Value::Null,
2680 expected_len: 1,
2681 },
2682 ];
2683
2684 for test_case in &test_cases {
2685 let result = test_case
2686 .input
2687 .exec_randomblob(|dest| {
2688 rand::rng().fill_bytes(dest);
2689 })
2690 .unwrap();
2691 match result {
2692 Value::Blob(blob) => {
2693 assert_eq!(blob.len(), test_case.expected_len);
2694 }
2695 _ => panic!("exec_randomblob did not return a Blob variant"),
2696 }
2697 }
2698
2699 let input = Value::from_i64(Value::MAX_BLOB_LENGTH + 1);
2701 assert!(input.exec_randomblob(|_| {}).is_err());
2702 }
2703
2704 #[test]
2705 fn test_exec_round() {
2706 let input_val = Value::from_f64(123.456);
2707 let expected_val = Value::from_f64(123.0);
2708 assert_eq!(input_val.exec_round(None), expected_val);
2709
2710 let input_val = Value::from_f64(123.456);
2711 let precision_val = Value::from_i64(2);
2712 let expected_val = Value::from_f64(123.46);
2713 assert_eq!(input_val.exec_round(Some(&precision_val)), expected_val);
2714
2715 let input_val = Value::from_f64(123.456);
2716 let precision_val = Value::build_text("1");
2717 let expected_val = Value::from_f64(123.5);
2718 assert_eq!(input_val.exec_round(Some(&precision_val)), expected_val);
2719
2720 let input_val = Value::build_text("123.456");
2721 let precision_val = Value::from_i64(2);
2722 let expected_val = Value::from_f64(123.46);
2723 assert_eq!(input_val.exec_round(Some(&precision_val)), expected_val);
2724
2725 let input_val = Value::from_i64(123);
2726 let precision_val = Value::from_i64(1);
2727 let expected_val = Value::from_f64(123.0);
2728 assert_eq!(input_val.exec_round(Some(&precision_val)), expected_val);
2729
2730 let input_val = Value::from_f64(100.123);
2731 let expected_val = Value::from_f64(100.0);
2732 assert_eq!(input_val.exec_round(None), expected_val);
2733
2734 let input_val = Value::from_f64(100.123);
2735 let expected_val = Value::Null;
2736 assert_eq!(input_val.exec_round(Some(&Value::Null)), expected_val);
2737 }
2738
2739 #[test]
2740 fn test_exec_if() {
2741 let reg = Value::from_i64(0);
2742 assert!(!reg.exec_if(false, false));
2743 assert!(reg.exec_if(false, true));
2744
2745 let reg = Value::from_i64(1);
2746 assert!(reg.exec_if(false, false));
2747 assert!(!reg.exec_if(false, true));
2748
2749 let reg = Value::Null;
2750 assert!(!reg.exec_if(false, false));
2751 assert!(!reg.exec_if(false, true));
2752
2753 let reg = Value::Null;
2754 assert!(reg.exec_if(true, false));
2755 assert!(reg.exec_if(true, true));
2756
2757 let reg = Value::Null;
2758 assert!(!reg.exec_if(false, false));
2759 assert!(!reg.exec_if(false, true));
2760 }
2761
2762 #[test]
2763 fn test_nullif() {
2764 assert_eq!(
2765 Value::from_i64(1).exec_nullif(&Value::from_i64(1)),
2766 Value::Null
2767 );
2768 assert_eq!(
2769 Value::from_f64(1.1).exec_nullif(&Value::from_f64(1.1)),
2770 Value::Null
2771 );
2772 assert_eq!(
2773 Value::build_text("limbo").exec_nullif(&Value::build_text("limbo")),
2774 Value::Null
2775 );
2776
2777 assert_eq!(
2778 Value::from_i64(1).exec_nullif(&Value::from_i64(2)),
2779 Value::from_i64(1)
2780 );
2781 assert_eq!(
2782 Value::from_f64(1.1).exec_nullif(&Value::from_f64(1.2)),
2783 Value::from_f64(1.1)
2784 );
2785 assert_eq!(
2786 Value::build_text("limbo").exec_nullif(&Value::build_text("limb")),
2787 Value::build_text("limbo")
2788 );
2789 }
2790
2791 #[test]
2792 fn test_substring() {
2793 let str_value = Value::build_text("limbo");
2794 let start_value = Value::from_i64(1);
2795 let length_value = Value::from_i64(3);
2796 let expected_val = Value::build_text("lim");
2797 assert_eq!(
2798 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2799 expected_val
2800 );
2801
2802 let str_value = Value::build_text("limbo");
2803 let start_value = Value::from_i64(1);
2804 let length_value = Value::from_i64(10);
2805 let expected_val = Value::build_text("limbo");
2806 assert_eq!(
2807 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2808 expected_val
2809 );
2810
2811 let str_value = Value::build_text("limbo");
2812 let start_value = Value::from_i64(10);
2813 let length_value = Value::from_i64(3);
2814 let expected_val = Value::build_text("");
2815 assert_eq!(
2816 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2817 expected_val
2818 );
2819
2820 let str_value = Value::build_text("limbo");
2821 let start_value = Value::from_i64(3);
2822 let length_value = Value::Null;
2823 let expected_val = Value::Null;
2824 assert_eq!(
2825 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2826 expected_val
2827 );
2828
2829 let str_value = Value::build_text("limbo");
2830 let start_value = Value::from_i64(10);
2831 let length_value = Value::Null;
2832 let expected_val = Value::Null;
2833 assert_eq!(
2834 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2835 expected_val
2836 );
2837
2838 let str_value = Value::build_text("limbo");
2839 let start_value = Value::from_i64(-7_096_519_388_852_014_892);
2840 let length_value = Value::from_i64(-4_829_175_794_346_763_833);
2841 let expected_val = Value::build_text("");
2842 assert_eq!(
2843 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2844 expected_val
2845 );
2846 }
2847
2848 #[test]
2849 fn test_exec_instr() {
2850 let input = Value::build_text("limbo");
2851 let pattern = Value::build_text("im");
2852 let expected = Value::from_i64(2);
2853 assert_eq!(input.exec_instr(&pattern), expected);
2854
2855 let input = Value::build_text("limbo");
2856 let pattern = Value::build_text("limbo");
2857 let expected = Value::from_i64(1);
2858 assert_eq!(input.exec_instr(&pattern), expected);
2859
2860 let input = Value::build_text("limbo");
2861 let pattern = Value::build_text("o");
2862 let expected = Value::from_i64(5);
2863 assert_eq!(input.exec_instr(&pattern), expected);
2864
2865 let input = Value::build_text("liiiiimbo");
2866 let pattern = Value::build_text("ii");
2867 let expected = Value::from_i64(2);
2868 assert_eq!(input.exec_instr(&pattern), expected);
2869
2870 let input = Value::build_text("limbo");
2871 let pattern = Value::build_text("limboX");
2872 let expected = Value::from_i64(0);
2873 assert_eq!(input.exec_instr(&pattern), expected);
2874
2875 let input = Value::build_text("limbo");
2876 let pattern = Value::build_text("");
2877 let expected = Value::from_i64(1);
2878 assert_eq!(input.exec_instr(&pattern), expected);
2879
2880 let input = Value::build_text("");
2881 let pattern = Value::build_text("limbo");
2882 let expected = Value::from_i64(0);
2883 assert_eq!(input.exec_instr(&pattern), expected);
2884
2885 let input = Value::build_text("");
2886 let pattern = Value::build_text("");
2887 let expected = Value::from_i64(1);
2888 assert_eq!(input.exec_instr(&pattern), expected);
2889
2890 let input = Value::Null;
2891 let pattern = Value::Null;
2892 let expected = Value::Null;
2893 assert_eq!(input.exec_instr(&pattern), expected);
2894
2895 let input = Value::build_text("limbo");
2896 let pattern = Value::Null;
2897 let expected = Value::Null;
2898 assert_eq!(input.exec_instr(&pattern), expected);
2899
2900 let input = Value::Null;
2901 let pattern = Value::build_text("limbo");
2902 let expected = Value::Null;
2903 assert_eq!(input.exec_instr(&pattern), expected);
2904
2905 let input = Value::from_i64(123);
2906 let pattern = Value::from_i64(2);
2907 let expected = Value::from_i64(2);
2908 assert_eq!(input.exec_instr(&pattern), expected);
2909
2910 let input = Value::from_i64(123);
2911 let pattern = Value::from_i64(5);
2912 let expected = Value::from_i64(0);
2913 assert_eq!(input.exec_instr(&pattern), expected);
2914
2915 let input = Value::from_f64(12.34);
2916 let pattern = Value::from_f64(2.3);
2917 let expected = Value::from_i64(2);
2918 assert_eq!(input.exec_instr(&pattern), expected);
2919
2920 let input = Value::from_f64(12.34);
2921 let pattern = Value::from_f64(5.6);
2922 let expected = Value::from_i64(0);
2923 assert_eq!(input.exec_instr(&pattern), expected);
2924
2925 let input = Value::from_f64(12.34);
2926 let pattern = Value::build_text(".");
2927 let expected = Value::from_i64(3);
2928 assert_eq!(input.exec_instr(&pattern), expected);
2929
2930 let input = Value::Blob(vec![1, 2, 3, 4, 5]);
2931 let pattern = Value::Blob(vec![3, 4]);
2932 let expected = Value::from_i64(3);
2933 assert_eq!(input.exec_instr(&pattern), expected);
2934
2935 let input = Value::Blob(vec![1, 2, 3, 4, 5]);
2936 let pattern = Value::Blob(vec![3, 2]);
2937 let expected = Value::from_i64(0);
2938 assert_eq!(input.exec_instr(&pattern), expected);
2939
2940 let input = Value::Blob(vec![0x61, 0x62, 0x63, 0x64, 0x65]);
2941 let pattern = Value::build_text("cd");
2942 let expected = Value::from_i64(3);
2943 assert_eq!(input.exec_instr(&pattern), expected);
2944
2945 let input = Value::build_text("abcde");
2946 let pattern = Value::Blob(vec![0x63, 0x64]);
2947 let expected = Value::from_i64(3);
2948 assert_eq!(input.exec_instr(&pattern), expected);
2949
2950 let input = Value::build_text("abcde");
2951 let pattern = Value::build_text("");
2952 let expected = Value::from_i64(1);
2953 assert_eq!(input.exec_instr(&pattern), expected);
2954 }
2955
2956 #[test]
2957 fn test_exec_sign() {
2958 let input = Value::from_i64(42);
2959 let expected = Some(Value::from_i64(1));
2960 assert_eq!(input.exec_sign(), expected);
2961
2962 let input = Value::from_i64(-42);
2963 let expected = Some(Value::from_i64(-1));
2964 assert_eq!(input.exec_sign(), expected);
2965
2966 let input = Value::from_i64(0);
2967 let expected = Some(Value::from_i64(0));
2968 assert_eq!(input.exec_sign(), expected);
2969
2970 let input = Value::from_f64(0.0);
2971 let expected = Some(Value::from_i64(0));
2972 assert_eq!(input.exec_sign(), expected);
2973
2974 let input = Value::from_f64(0.1);
2975 let expected = Some(Value::from_i64(1));
2976 assert_eq!(input.exec_sign(), expected);
2977
2978 let input = Value::from_f64(42.0);
2979 let expected = Some(Value::from_i64(1));
2980 assert_eq!(input.exec_sign(), expected);
2981
2982 let input = Value::from_f64(-42.0);
2983 let expected = Some(Value::from_i64(-1));
2984 assert_eq!(input.exec_sign(), expected);
2985
2986 let input = Value::build_text("abc");
2987 let expected = None;
2988 assert_eq!(input.exec_sign(), expected);
2989
2990 let input = Value::build_text("42");
2991 let expected = Some(Value::from_i64(1));
2992 assert_eq!(input.exec_sign(), expected);
2993
2994 let input = Value::build_text("-42");
2995 let expected = Some(Value::from_i64(-1));
2996 assert_eq!(input.exec_sign(), expected);
2997
2998 let input = Value::build_text("0");
2999 let expected = Some(Value::from_i64(0));
3000 assert_eq!(input.exec_sign(), expected);
3001
3002 let input = Value::Blob(b"abc".to_vec());
3003 let expected = None;
3004 assert_eq!(input.exec_sign(), expected);
3005
3006 let input = Value::Blob(b"42".to_vec());
3007 let expected = None;
3008 assert_eq!(input.exec_sign(), expected);
3009
3010 let input = Value::Blob(b"-42".to_vec());
3011 let expected = None;
3012 assert_eq!(input.exec_sign(), expected);
3013
3014 let input = Value::Blob(b"0".to_vec());
3015 let expected = None;
3016 assert_eq!(input.exec_sign(), expected);
3017
3018 let input = Value::Null;
3019 let expected = None;
3020 assert_eq!(input.exec_sign(), expected);
3021 }
3022
3023 #[test]
3024 fn test_exec_zeroblob() {
3025 let input = Value::from_i64(0);
3026 let expected = Value::Blob(vec![]);
3027 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3028
3029 let input = Value::Null;
3030 let expected = Value::Blob(vec![]);
3031 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3032
3033 let input = Value::from_i64(4);
3034 let expected = Value::Blob(vec![0; 4]);
3035 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3036
3037 let input = Value::from_i64(-1);
3038 let expected = Value::Blob(vec![]);
3039 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3040
3041 let input = Value::build_text("5");
3042 let expected = Value::Blob(vec![0; 5]);
3043 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3044
3045 let input = Value::build_text("-5");
3046 let expected = Value::Blob(vec![]);
3047 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3048
3049 let input = Value::build_text("text");
3050 let expected = Value::Blob(vec![]);
3051 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3052
3053 let input = Value::from_f64(2.6);
3054 let expected = Value::Blob(vec![0; 2]);
3055 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3056
3057 let input = Value::Blob(vec![1]);
3058 let expected = Value::Blob(vec![]);
3059 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3060
3061 let input = Value::from_i64(Value::MAX_BLOB_LENGTH + 1);
3063 assert!(input.exec_zeroblob().is_err());
3064 }
3065
3066 #[test]
3067 fn test_replace() {
3068 let input_str = Value::build_text("bob");
3069 let pattern_str = Value::build_text("b");
3070 let replace_str = Value::build_text("a");
3071 let expected_str = Value::build_text("aoa");
3072 assert_eq!(
3073 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3074 expected_str
3075 );
3076
3077 let input_str = Value::build_text("bob");
3078 let pattern_str = Value::build_text("b");
3079 let replace_str = Value::build_text("");
3080 let expected_str = Value::build_text("o");
3081 assert_eq!(
3082 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3083 expected_str
3084 );
3085
3086 let input_str = Value::build_text("bob");
3087 let pattern_str = Value::build_text("b");
3088 let replace_str = Value::build_text("abc");
3089 let expected_str = Value::build_text("abcoabc");
3090 assert_eq!(
3091 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3092 expected_str
3093 );
3094
3095 let input_str = Value::build_text("bob");
3096 let pattern_str = Value::build_text("a");
3097 let replace_str = Value::build_text("b");
3098 let expected_str = Value::build_text("bob");
3099 assert_eq!(
3100 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3101 expected_str
3102 );
3103
3104 let input_str = Value::build_text("bob");
3105 let pattern_str = Value::build_text("");
3106 let replace_str = Value::build_text("a");
3107 let expected_str = Value::build_text("bob");
3108 assert_eq!(
3109 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3110 expected_str
3111 );
3112
3113 let input_str = Value::build_text("bob");
3114 let pattern_str = Value::Null;
3115 let replace_str = Value::build_text("a");
3116 let expected_str = Value::Null;
3117 assert_eq!(
3118 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3119 expected_str
3120 );
3121
3122 let input_str = Value::build_text("bo5");
3123 let pattern_str = Value::from_i64(5);
3124 let replace_str = Value::build_text("a");
3125 let expected_str = Value::build_text("boa");
3126 assert_eq!(
3127 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3128 expected_str
3129 );
3130
3131 let input_str = Value::build_text("bo5.0");
3132 let pattern_str = Value::from_f64(5.0);
3133 let replace_str = Value::build_text("a");
3134 let expected_str = Value::build_text("boa");
3135 assert_eq!(
3136 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3137 expected_str
3138 );
3139
3140 let input_str = Value::build_text("bo5");
3141 let pattern_str = Value::from_f64(5.0);
3142 let replace_str = Value::build_text("a");
3143 let expected_str = Value::build_text("bo5");
3144 assert_eq!(
3145 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3146 expected_str
3147 );
3148
3149 let input_str = Value::build_text("bo5.0");
3150 let pattern_str = Value::from_f64(5.0);
3151 let replace_str = Value::from_f64(6.0);
3152 let expected_str = Value::build_text("bo6.0");
3153 assert_eq!(
3154 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3155 expected_str
3156 );
3157
3158 let input_str = Value::build_text("tes3");
3160 let pattern_str = Value::from_i64(3);
3161 let replace_str = Value::from_f64(0.3);
3162 let expected_str = Value::build_text("tes0.3");
3163 assert_eq!(
3164 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3165 expected_str
3166 );
3167 }
3168}