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!(
985 function,
986 MathFunc::Ceil | MathFunc::Ceiling | MathFunc::Floor | MathFunc::Trunc
987 ) {
988 return Value::from_i64(i);
989 }
990 }
991
992 let Some(f) = v.map(|v| v.to_f64()) else {
993 return Value::Null;
994 };
995
996 if matches!(function, MathFunc::Ln | MathFunc::Log10 | MathFunc::Log2) && f <= 0.0 {
997 return Value::Null;
998 }
999
1000 #[allow(unused_unsafe)]
1001 let result = match function {
1002 MathFunc::Acos => unsafe { cmath::acos(f) },
1003 MathFunc::Acosh => unsafe { cmath::acosh(f) },
1004 MathFunc::Asin => unsafe { cmath::asin(f) },
1005 MathFunc::Asinh => unsafe { cmath::asinh(f) },
1006 MathFunc::Atan => unsafe { cmath::atan(f) },
1007 MathFunc::Atanh => unsafe { cmath::atanh(f) },
1008 MathFunc::Ceil | MathFunc::Ceiling => libm::ceil(f),
1009 MathFunc::Cos => unsafe { cmath::cos(f) },
1010 MathFunc::Cosh => unsafe { cmath::cosh(f) },
1011 MathFunc::Degrees => cmath::degrees(f),
1012 MathFunc::Exp => unsafe { cmath::exp(f) },
1013 MathFunc::Floor => libm::floor(f),
1014 MathFunc::Ln => unsafe { cmath::log(f) },
1015 MathFunc::Log10 => unsafe { cmath::log10(f) },
1016 MathFunc::Log2 => unsafe { cmath::log2(f) },
1017 MathFunc::Radians => cmath::radians(f),
1018 MathFunc::Sin => unsafe { cmath::sin(f) },
1019 MathFunc::Sinh => unsafe { cmath::sinh(f) },
1020 MathFunc::Sqrt => libm::sqrt(f),
1021 MathFunc::Tan => unsafe { cmath::tan(f) },
1022 MathFunc::Tanh => unsafe { cmath::tanh(f) },
1023 MathFunc::Trunc => libm::trunc(f),
1024 _ => unreachable!("Unexpected mathematical unary function {:?}", function),
1025 };
1026
1027 if result.is_nan() {
1028 Value::Null
1029 } else {
1030 Value::from_f64(result)
1031 }
1032 }
1033
1034 pub fn exec_math_binary(&self, rhs: &Value, function: &MathFunc) -> Value {
1035 let Some(lhs) = Numeric::from_value_strict(self).map(|v| v.to_f64()) else {
1036 return Value::Null;
1037 };
1038
1039 let Some(rhs) = Numeric::from_value_strict(rhs).map(|v| v.to_f64()) else {
1040 return Value::Null;
1041 };
1042
1043 #[allow(unused_unsafe)]
1044 let result = match function {
1045 MathFunc::Atan2 => unsafe { cmath::atan2(lhs, rhs) },
1046 MathFunc::Mod => libm::fmod(lhs, rhs),
1047 MathFunc::Pow | MathFunc::Power => unsafe { cmath::pow(lhs, rhs) },
1048 _ => unreachable!("Unexpected mathematical binary function {:?}", function),
1049 };
1050
1051 if result.is_nan() {
1052 Value::Null
1053 } else {
1054 Value::from_f64(result)
1055 }
1056 }
1057
1058 pub fn exec_math_log(&self, base: Option<&Value>) -> Value {
1059 let Some(f) = Numeric::from_value_strict(self).map(|v| v.to_f64()) else {
1060 return Value::Null;
1061 };
1062
1063 let base = match base.map(|value| Numeric::from_value_strict(value).map(|v| v.to_f64())) {
1064 Some(Some(f)) => f,
1065 Some(None) => return Value::Null,
1066 None => 10.0,
1067 };
1068
1069 if f <= 0.0 || base <= 0.0 || base == 1.0 {
1070 return Value::Null;
1071 }
1072
1073 if base == 2.0 {
1074 return Value::from_f64(libm::log2(f));
1075 } else if base == 10.0 {
1076 return Value::from_f64(libm::log10(f));
1077 };
1078
1079 let log_x = libm::log(f);
1080 let log_base = libm::log(base);
1081
1082 if log_base <= 0.0 {
1083 return Value::Null;
1084 }
1085
1086 let result = log_x / log_base;
1087 Value::from_f64(result)
1088 }
1089
1090 pub fn exec_add(&self, rhs: &Value) -> Value {
1091 (|| Numeric::from_value(self)?.checked_add(Numeric::from_value(rhs)?))().into()
1092 }
1093
1094 pub fn exec_subtract(&self, rhs: &Value) -> Value {
1095 (|| Numeric::from_value(self)?.checked_sub(Numeric::from_value(rhs)?))().into()
1096 }
1097
1098 pub fn exec_multiply(&self, rhs: &Value) -> Value {
1099 (|| Numeric::from_value(self)?.checked_mul(Numeric::from_value(rhs)?))().into()
1100 }
1101
1102 pub fn exec_divide(&self, rhs: &Value) -> Value {
1103 (|| Numeric::from_value(self)?.checked_div(Numeric::from_value(rhs)?))().into()
1104 }
1105
1106 pub fn exec_bit_and(&self, rhs: &Value) -> Value {
1107 (NullableInteger::from(self) & NullableInteger::from(rhs)).into()
1108 }
1109
1110 pub fn exec_bit_or(&self, rhs: &Value) -> Value {
1111 (NullableInteger::from(self) | NullableInteger::from(rhs)).into()
1112 }
1113
1114 pub fn exec_remainder(&self, rhs: &Value) -> Value {
1115 let convert_to_float = matches!(Numeric::from_value(self), Some(Numeric::Float(_)))
1116 || matches!(Numeric::from_value(rhs), Some(Numeric::Float(_)));
1117
1118 match NullableInteger::from(self) % NullableInteger::from(rhs) {
1119 NullableInteger::Null => Value::Null,
1120 NullableInteger::Integer(v) => {
1121 if convert_to_float {
1122 Value::from_f64(v as f64)
1123 } else {
1124 Value::from_i64(v)
1125 }
1126 }
1127 }
1128 }
1129
1130 pub fn exec_bit_not(&self) -> Value {
1131 (!NullableInteger::from(self)).into()
1132 }
1133
1134 pub fn exec_shift_left(&self, rhs: &Value) -> Value {
1135 (NullableInteger::from(self) << NullableInteger::from(rhs)).into()
1136 }
1137
1138 pub fn exec_shift_right(&self, rhs: &Value) -> Value {
1139 (NullableInteger::from(self) >> NullableInteger::from(rhs)).into()
1140 }
1141
1142 pub fn exec_boolean_not(&self) -> Value {
1143 match Numeric::from_value(self).map(|v| v.to_bool()) {
1144 None => Value::Null,
1145 Some(v) => Value::from_i64(!v as i64),
1146 }
1147 }
1148
1149 pub fn exec_concat(&self, rhs: &Value) -> Value {
1150 if let (Value::Blob(lhs), Value::Blob(rhs)) = (self, rhs) {
1151 return Value::Blob([lhs.as_slice(), rhs.as_slice()].concat());
1152 }
1153
1154 let Some(lhs) = self.cast_text() else {
1155 return Value::Null;
1156 };
1157
1158 let Some(rhs) = rhs.cast_text() else {
1159 return Value::Null;
1160 };
1161
1162 Value::build_text(lhs + &rhs)
1163 }
1164
1165 pub fn exec_and(&self, rhs: &Value) -> Value {
1166 match (
1167 Numeric::from_value(self).map(|v| v.to_bool()),
1168 Numeric::from_value(rhs).map(|v| v.to_bool()),
1169 ) {
1170 (Some(false), _) | (_, Some(false)) => Value::from_i64(0),
1171 (None, _) | (_, None) => Value::Null,
1172 _ => Value::from_i64(1),
1173 }
1174 }
1175
1176 pub fn exec_or(&self, rhs: &Value) -> Value {
1177 match (
1178 Numeric::from_value(self).map(|v| v.to_bool()),
1179 Numeric::from_value(rhs).map(|v| v.to_bool()),
1180 ) {
1181 (Some(true), _) | (_, Some(true)) => Value::from_i64(1),
1182 (None, _) | (_, None) => Value::Null,
1183 _ => Value::from_i64(0),
1184 }
1185 }
1186
1187 pub fn exec_like(pattern: &str, text: &str, escape: Option<char>) -> Result<bool, LimboError> {
1188 const MAX_LIKE_PATTERN_LENGTH: usize = 50000;
1189 if pattern.len() > MAX_LIKE_PATTERN_LENGTH {
1190 return Err(LimboError::Constraint(
1191 "LIKE or GLOB pattern too complex".to_string(),
1192 ));
1193 }
1194 let pattern = sqlite_text_prefix(pattern);
1195 let text = sqlite_text_prefix(text);
1196
1197 let has_escape = escape.is_some_and(|e| pattern.contains(e));
1198
1199 if !has_escape && !pattern.contains(['%', '_']) {
1201 return Ok(pattern.eq_ignore_ascii_case(text));
1202 }
1203
1204 if !has_escape
1206 && pattern.ends_with('%')
1207 && !pattern[..pattern.len() - 1].contains(['%', '_'])
1208 {
1209 let prefix = &pattern[..pattern.len() - 1];
1210 if text.len() >= prefix.len() && text.is_char_boundary(prefix.len()) {
1211 return Ok(text[..prefix.len()].eq_ignore_ascii_case(prefix));
1212 }
1213 }
1215
1216 if !has_escape && pattern.starts_with('%') && !pattern[1..].contains(['%', '_']) {
1218 let suffix = &pattern[1..];
1219 let start = text.len().wrapping_sub(suffix.len());
1220 if text.len() >= suffix.len() && text.is_char_boundary(start) {
1221 return Ok(text[start..].eq_ignore_ascii_case(suffix));
1222 }
1223 }
1225
1226 Ok(pattern_compare(pattern, text, &LIKE_INFO, escape) == CompareResult::Match)
1227 }
1228
1229 pub fn exec_glob(pattern: &str, text: &str) -> Result<bool, LimboError> {
1230 const MAX_GLOB_PATTERN_LENGTH: usize = 50000;
1231 const GLOB_CHARS: [char; 3] = ['*', '?', '['];
1232
1233 if pattern.len() > MAX_GLOB_PATTERN_LENGTH {
1234 return Err(LimboError::Constraint(
1235 "GLOB pattern too complex".to_string(),
1236 ));
1237 }
1238 let pattern = sqlite_text_prefix(pattern);
1239 let text = sqlite_text_prefix(text);
1240
1241 if !pattern.contains(GLOB_CHARS) {
1243 return Ok(pattern == text);
1244 }
1245
1246 if pattern.ends_with('*') && !pattern[..pattern.len() - 1].contains(GLOB_CHARS) {
1248 let prefix = &pattern[..pattern.len() - 1];
1249 if text.len() >= prefix.len() && text.is_char_boundary(prefix.len()) {
1250 return Ok(&text[..prefix.len()] == prefix);
1251 }
1252 }
1254
1255 if pattern.starts_with('*') && !pattern[1..].contains(GLOB_CHARS) {
1257 let suffix = &pattern[1..];
1258 let start = text.len().wrapping_sub(suffix.len());
1259 if text.len() >= suffix.len() && text.is_char_boundary(start) {
1260 return Ok(&text[start..] == suffix);
1261 }
1262 }
1264
1265 Ok(pattern_compare(pattern, text, &GLOB_INFO, None) == CompareResult::Match)
1266 }
1267
1268 pub fn exec_min<'a, T: Iterator<Item = &'a Value>>(regs: T) -> Value {
1269 let mut result: Option<&Value> = None;
1271 for v in regs {
1272 if matches!(v, Value::Null) {
1273 return Value::Null;
1274 }
1275 result = Some(match result {
1276 None => v,
1277 Some(cur) if v < cur => v,
1278 Some(cur) => cur,
1279 });
1280 }
1281 result.map(|v| v.to_owned()).unwrap_or(Value::Null)
1282 }
1283
1284 pub fn exec_max<'a, T: Iterator<Item = &'a Value>>(regs: T) -> Value {
1285 let mut result: Option<&Value> = None;
1287 for v in regs {
1288 if matches!(v, Value::Null) {
1289 return Value::Null;
1290 }
1291 result = Some(match result {
1292 None => v,
1293 Some(cur) if v > cur => v,
1294 Some(cur) => cur,
1295 });
1296 }
1297 result.map(|v| v.to_owned()).unwrap_or(Value::Null)
1298 }
1299
1300 pub fn exec_group_concat(&mut self, other: &Value) {
1304 let Value::Text(text) = self else {
1305 panic!("concat_to_text must be called only on Value::Text");
1306 };
1307 text.value.to_mut().push_str(&other.to_string());
1308 }
1309
1310 pub fn exec_concat_strings<'a, T: Iterator<Item = &'a Self>>(registers: T) -> Self {
1311 let mut result = String::new();
1312 for val in registers {
1313 match val {
1314 Value::Null => continue,
1315 Value::Text(s) => result.push_str(s.as_str()),
1316 Value::Blob(b) => result.push_str(&String::from_utf8_lossy(b)),
1317 Value::Numeric(Numeric::Integer(i)) => result.push_str(&i.to_string()),
1318 Value::Numeric(Numeric::Float(f)) => result.push_str(&format_float(f64::from(*f))),
1319 }
1320 }
1321 Value::build_text(result)
1322 }
1323
1324 pub fn exec_concat_ws<'a, T: ExactSizeIterator<Item = &'a Self>>(mut registers: T) -> Self {
1325 if registers.len() == 0 {
1326 return Value::Null;
1327 }
1328
1329 let separator = match registers
1330 .next()
1331 .expect("registers should have at least one element after length check")
1332 {
1333 Value::Null | Value::Blob(_) => return Value::Null,
1334 v => format!("{v}"),
1335 };
1336
1337 let parts = registers.filter_map(|val| match val {
1338 Value::Text(_) | Value::Numeric(_) => Some(format!("{val}")),
1339 _ => None,
1340 });
1341
1342 let result = parts.collect::<Vec<_>>().join(&separator);
1343 Value::build_text(result)
1344 }
1345
1346 pub fn exec_char<'a, T: Iterator<Item = &'a Self>>(values: T) -> Self {
1347 let result: String = values
1348 .filter_map(|x| match x {
1349 Value::Numeric(Numeric::Integer(i)) => {
1350 if *i >= 0 {
1354 Some(char::from_u32(*i as u32).unwrap_or('\u{FFFD}'))
1355 } else {
1356 Some('\u{FFFD}')
1357 }
1358 }
1359 Value::Null => Some('\0'),
1361 _ => None,
1362 })
1363 .collect();
1364 Value::build_text(result)
1365 }
1366}
1367
1368fn parse_n_hex(bytes: &[u8], n: usize) -> Result<u32> {
1370 if bytes.len() < n {
1371 return Err(LimboError::ParseError("invalid Unicode escape".to_string()));
1372 }
1373 let mut v: u32 = 0;
1374 for &b in &bytes[..n] {
1375 let digit = match b {
1376 b'0'..=b'9' => b - b'0',
1377 b'a'..=b'f' => b - b'a' + 10,
1378 b'A'..=b'F' => b - b'A' + 10,
1379 _ => return Err(LimboError::ParseError("invalid Unicode escape".to_string())),
1380 };
1381 v = (v << 4) | digit as u32;
1382 }
1383 Ok(v)
1384}
1385
1386#[derive(PartialEq)]
1390enum CompareResult {
1391 Match,
1392 NoMatch,
1393 NoWildcardMatch,
1394}
1395
1396struct PatternInfo {
1397 match_all: char,
1398 match_one: char,
1399 match_set: Option<char>,
1400 no_case: bool,
1401}
1402
1403const LIKE_INFO: PatternInfo = PatternInfo {
1404 match_all: '%',
1405 match_one: '_',
1406 match_set: None,
1407 no_case: true,
1408};
1409
1410const GLOB_INFO: PatternInfo = PatternInfo {
1411 match_all: '*',
1412 match_one: '?',
1413 match_set: Some('['),
1414 no_case: false,
1415};
1416
1417fn pattern_compare(
1422 pattern: &str,
1423 text: &str,
1424 info: &PatternInfo,
1425 escape: Option<char>,
1426) -> CompareResult {
1427 let mut p_indices = pattern.char_indices();
1428 let mut t_indices = text.char_indices();
1429
1430 let mut p_curr = p_indices.next();
1431 let mut t_curr = t_indices.next();
1432
1433 let mut wildcard_p_iter: Option<std::str::CharIndices> = None;
1435 let mut wildcard_t_iter: Option<std::str::CharIndices> = None;
1436
1437 loop {
1438 match (p_curr, t_curr) {
1439 (Some((_, p_char)), Some((_, t_char))) => {
1440 if p_char == info.match_all && Some(p_char) != escape {
1441 let mut next_p = p_indices.clone();
1443 while let Some((_, c)) = next_p.clone().next() {
1444 if c == info.match_all && Some(c) != escape {
1445 next_p.next();
1446 } else {
1447 break;
1448 }
1449 }
1450
1451 let mut lookahead_p = next_p.clone();
1452 if let Some((_, next_char)) = lookahead_p.next() {
1453 let is_wildcard = (next_char == info.match_all
1454 && Some(next_char) != escape)
1455 || (next_char == info.match_one && Some(next_char) != escape)
1456 || (info.match_set == Some(next_char));
1457
1458 let is_escaped_next = Some(next_char) == escape;
1459
1460 if !is_wildcard && !is_escaped_next {
1461 let mut found = false;
1462
1463 if compare_chars(next_char, t_char, info.no_case) {
1465 found = true;
1466 } else {
1467 let lookahead_t = t_indices.clone();
1469 for (_, t_c) in lookahead_t {
1470 if compare_chars(next_char, t_c, info.no_case) {
1471 found = true;
1472 break;
1473 }
1474 }
1475 }
1476
1477 if !found {
1478 return CompareResult::NoWildcardMatch;
1479 }
1480 }
1481 }
1482
1483 p_indices = next_p;
1484 wildcard_p_iter = Some(p_indices.clone());
1485 p_curr = p_indices.next();
1486
1487 if p_curr.is_none() {
1488 return CompareResult::Match;
1489 }
1490
1491 wildcard_t_iter = Some(t_indices.clone());
1492 continue;
1493 }
1494
1495 if p_char == info.match_one && Some(p_char) != escape {
1496 p_curr = p_indices.next();
1497 t_curr = t_indices.next();
1498 continue;
1499 }
1500
1501 if info.match_set == Some(p_char) {
1503 let mut seen = false;
1504 let mut invert = false;
1505 let c = t_char;
1506
1507 let mut next_c_opt = p_indices.next();
1508
1509 if let Some((_, c2)) = next_c_opt {
1510 if c2 == '^' {
1511 invert = true;
1512 next_c_opt = p_indices.next();
1513 }
1514 }
1515
1516 let mut c2_opt = next_c_opt;
1517 if let Some((_, c2)) = c2_opt {
1518 if c2 == ']' {
1519 if c == ']' {
1520 seen = true;
1521 }
1522 c2_opt = p_indices.next();
1523 }
1524 }
1525
1526 let mut prior_c: Option<char> = None;
1527
1528 while let Some((_, c2)) = c2_opt {
1529 if c2 == ']' {
1530 break;
1531 }
1532
1533 let mut is_range = false;
1534 if c2 == '-' && prior_c.is_some() {
1535 let lookahead = p_indices.clone().next();
1536 if let Some((_, c3)) = lookahead {
1537 if c3 != ']' {
1538 is_range = true;
1539 let start = prior_c.unwrap();
1540 let end = c3;
1541 if c >= start && c <= end {
1542 seen = true;
1543 }
1544 p_indices.next();
1545 prior_c = None;
1546 }
1547 }
1548 }
1549
1550 if !is_range {
1551 if c == c2 {
1552 seen = true;
1553 }
1554 prior_c = Some(c2);
1555 }
1556
1557 c2_opt = p_indices.next();
1558 }
1559
1560 if c2_opt.is_none() || !(seen ^ invert) {
1561 } else {
1563 p_curr = p_indices.next();
1564 t_curr = t_indices.next();
1565 continue;
1566 }
1567 } else {
1568 let (expected_char, next_p_iter) = if Some(p_char) == escape {
1569 if let Some((_, literal)) = p_indices.next() {
1570 (literal, p_indices.clone())
1571 } else {
1572 return CompareResult::NoMatch;
1573 }
1574 } else {
1575 (p_char, p_indices.clone())
1576 };
1577
1578 if compare_chars(expected_char, t_char, info.no_case) {
1579 p_indices = next_p_iter;
1580 p_curr = p_indices.next();
1581 t_curr = t_indices.next();
1582 continue;
1583 }
1584 }
1585 }
1586 (None, None) => return CompareResult::Match,
1587 (Some((_, p_char)), None) if p_char == info.match_all && Some(p_char) != escape => {
1588 let mut temp = p_indices.clone();
1589 loop {
1590 match temp.next() {
1591 Some((_, c)) if c == info.match_all && Some(c) != escape => continue,
1592 None => return CompareResult::Match,
1593 _ => break,
1594 }
1595 }
1596 }
1597 _ => {}
1598 }
1599
1600 if let (Some(wp), Some(wt)) = (wildcard_p_iter.clone(), wildcard_t_iter.clone()) {
1602 p_indices = wp;
1603 p_curr = p_indices.next();
1604 t_indices = wt.clone();
1605 t_curr = t_indices.next();
1606
1607 if t_curr.is_some() {
1608 wildcard_t_iter = Some(t_indices.clone());
1609 continue;
1610 }
1611 }
1612
1613 return CompareResult::NoMatch;
1614 }
1615}
1616
1617fn compare_chars(p: char, t: char, no_case: bool) -> bool {
1618 if no_case {
1619 p.eq_ignore_ascii_case(&t)
1620 } else {
1621 p == t
1622 }
1623}
1624
1625#[cfg(clt_turso_tests)]
1626mod tests {
1627 use crate::numeric::Numeric;
1628 use crate::types::Value;
1629 use crate::vdbe::Register;
1630
1631 use rand::{Rng, RngCore};
1632
1633 #[test]
1634 fn test_exec_add() {
1635 let inputs = vec![
1636 (Value::from_i64(3), Value::from_i64(1)),
1637 (Value::from_f64(3.0), Value::from_f64(1.0)),
1638 (Value::from_f64(3.0), Value::from_i64(1)),
1639 (Value::from_i64(3), Value::from_f64(1.0)),
1640 (Value::Null, Value::Null),
1641 (Value::Null, Value::from_i64(1)),
1642 (Value::Null, Value::from_f64(1.0)),
1643 (Value::Null, Value::Text("2".into())),
1644 (Value::from_i64(1), Value::Null),
1645 (Value::from_f64(1.0), Value::Null),
1646 (Value::Text("1".into()), Value::Null),
1647 (Value::Text("1".into()), Value::Text("3".into())),
1648 (Value::Text("1.0".into()), Value::Text("3.0".into())),
1649 (Value::Text("1.0".into()), Value::from_f64(3.0)),
1650 (Value::Text("1.0".into()), Value::from_i64(3)),
1651 (Value::from_f64(1.0), Value::Text("3.0".into())),
1652 (Value::from_i64(1), Value::Text("3".into())),
1653 ];
1654
1655 let outputs = [
1656 Value::from_i64(4),
1657 Value::from_f64(4.0),
1658 Value::from_f64(4.0),
1659 Value::from_f64(4.0),
1660 Value::Null,
1661 Value::Null,
1662 Value::Null,
1663 Value::Null,
1664 Value::Null,
1665 Value::Null,
1666 Value::Null,
1667 Value::from_i64(4),
1668 Value::from_f64(4.0),
1669 Value::from_f64(4.0),
1670 Value::from_f64(4.0),
1671 Value::from_f64(4.0),
1672 Value::from_f64(4.0),
1673 ];
1674
1675 assert_eq!(
1676 inputs.len(),
1677 outputs.len(),
1678 "Inputs and Outputs should have same size"
1679 );
1680 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1681 assert_eq!(
1682 lhs.exec_add(rhs),
1683 outputs[i],
1684 "Wrong ADD for lhs: {lhs}, rhs: {rhs}"
1685 );
1686 }
1687 }
1688
1689 #[test]
1690 fn test_exec_subtract() {
1691 let inputs = vec![
1692 (Value::from_i64(3), Value::from_i64(1)),
1693 (Value::from_f64(3.0), Value::from_f64(1.0)),
1694 (Value::from_f64(3.0), Value::from_i64(1)),
1695 (Value::from_i64(3), Value::from_f64(1.0)),
1696 (Value::Null, Value::Null),
1697 (Value::Null, Value::from_i64(1)),
1698 (Value::Null, Value::from_f64(1.0)),
1699 (Value::Null, Value::Text("1".into())),
1700 (Value::from_i64(1), Value::Null),
1701 (Value::from_f64(1.0), Value::Null),
1702 (Value::Text("4".into()), Value::Null),
1703 (Value::Text("1".into()), Value::Text("3".into())),
1704 (Value::Text("1.0".into()), Value::Text("3.0".into())),
1705 (Value::Text("1.0".into()), Value::from_f64(3.0)),
1706 (Value::Text("1.0".into()), Value::from_i64(3)),
1707 (Value::from_f64(1.0), Value::Text("3.0".into())),
1708 (Value::from_i64(1), Value::Text("3".into())),
1709 ];
1710
1711 let outputs = [
1712 Value::from_i64(2),
1713 Value::from_f64(2.0),
1714 Value::from_f64(2.0),
1715 Value::from_f64(2.0),
1716 Value::Null,
1717 Value::Null,
1718 Value::Null,
1719 Value::Null,
1720 Value::Null,
1721 Value::Null,
1722 Value::Null,
1723 Value::from_i64(-2),
1724 Value::from_f64(-2.0),
1725 Value::from_f64(-2.0),
1726 Value::from_f64(-2.0),
1727 Value::from_f64(-2.0),
1728 Value::from_f64(-2.0),
1729 ];
1730
1731 assert_eq!(
1732 inputs.len(),
1733 outputs.len(),
1734 "Inputs and Outputs should have same size"
1735 );
1736 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1737 assert_eq!(
1738 lhs.exec_subtract(rhs),
1739 outputs[i],
1740 "Wrong subtract for lhs: {lhs}, rhs: {rhs}"
1741 );
1742 }
1743 }
1744
1745 #[test]
1746 fn test_exec_multiply() {
1747 let inputs = vec![
1748 (Value::from_i64(3), Value::from_i64(2)),
1749 (Value::from_f64(3.0), Value::from_f64(2.0)),
1750 (Value::from_f64(3.0), Value::from_i64(2)),
1751 (Value::from_i64(3), Value::from_f64(2.0)),
1752 (Value::Null, Value::Null),
1753 (Value::Null, Value::from_i64(1)),
1754 (Value::Null, Value::from_f64(1.0)),
1755 (Value::Null, Value::Text("1".into())),
1756 (Value::from_i64(1), Value::Null),
1757 (Value::from_f64(1.0), Value::Null),
1758 (Value::Text("4".into()), Value::Null),
1759 (Value::Text("2".into()), Value::Text("3".into())),
1760 (Value::Text("2.0".into()), Value::Text("3.0".into())),
1761 (Value::Text("2.0".into()), Value::from_f64(3.0)),
1762 (Value::Text("2.0".into()), Value::from_i64(3)),
1763 (Value::from_f64(2.0), Value::Text("3.0".into())),
1764 (Value::from_i64(2), Value::Text("3.0".into())),
1765 ];
1766
1767 let outputs = [
1768 Value::from_i64(6),
1769 Value::from_f64(6.0),
1770 Value::from_f64(6.0),
1771 Value::from_f64(6.0),
1772 Value::Null,
1773 Value::Null,
1774 Value::Null,
1775 Value::Null,
1776 Value::Null,
1777 Value::Null,
1778 Value::Null,
1779 Value::from_i64(6),
1780 Value::from_f64(6.0),
1781 Value::from_f64(6.0),
1782 Value::from_f64(6.0),
1783 Value::from_f64(6.0),
1784 Value::from_f64(6.0),
1785 ];
1786
1787 assert_eq!(
1788 inputs.len(),
1789 outputs.len(),
1790 "Inputs and Outputs should have same size"
1791 );
1792 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1793 assert_eq!(
1794 lhs.exec_multiply(rhs),
1795 outputs[i],
1796 "Wrong multiply for lhs: {lhs}, rhs: {rhs}"
1797 );
1798 }
1799 }
1800
1801 #[test]
1802 fn test_exec_divide() {
1803 let inputs = vec![
1804 (Value::from_i64(1), Value::from_i64(0)),
1805 (Value::from_f64(1.0), Value::from_f64(0.0)),
1806 (Value::from_i64(i64::MIN), Value::from_i64(-1)),
1807 (Value::from_f64(6.0), Value::from_f64(2.0)),
1808 (Value::from_f64(6.0), Value::from_i64(2)),
1809 (Value::from_i64(6), Value::from_i64(2)),
1810 (Value::Null, Value::from_i64(2)),
1811 (Value::from_i64(2), Value::Null),
1812 (Value::Null, Value::Null),
1813 (Value::Text("6".into()), Value::Text("2".into())),
1814 (Value::Text("6".into()), Value::from_i64(2)),
1815 ];
1816
1817 let outputs = [
1818 Value::Null,
1819 Value::Null,
1820 Value::from_f64(9.223372036854776e18),
1821 Value::from_f64(3.0),
1822 Value::from_f64(3.0),
1823 Value::from_f64(3.0),
1824 Value::Null,
1825 Value::Null,
1826 Value::Null,
1827 Value::from_f64(3.0),
1828 Value::from_f64(3.0),
1829 ];
1830
1831 assert_eq!(
1832 inputs.len(),
1833 outputs.len(),
1834 "Inputs and Outputs should have same size"
1835 );
1836 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1837 assert_eq!(
1838 lhs.exec_divide(rhs),
1839 outputs[i],
1840 "Wrong divide for lhs: {lhs}, rhs: {rhs}"
1841 );
1842 }
1843 }
1844
1845 #[test]
1846 fn test_exec_remainder() {
1847 let inputs = vec![
1848 (Value::Null, Value::Null),
1849 (Value::Null, Value::from_f64(1.0)),
1850 (Value::Null, Value::from_i64(1)),
1851 (Value::Null, Value::Text("1".into())),
1852 (Value::from_f64(1.0), Value::Null),
1853 (Value::from_i64(1), Value::Null),
1854 (Value::from_i64(12), Value::from_i64(0)),
1855 (Value::from_f64(12.0), Value::from_f64(0.0)),
1856 (Value::from_f64(12.0), Value::from_i64(0)),
1857 (Value::from_i64(12), Value::from_f64(0.0)),
1858 (Value::from_i64(i64::MIN), Value::from_i64(-1)),
1859 (Value::from_i64(12), Value::from_i64(3)),
1860 (Value::from_f64(12.0), Value::from_f64(3.0)),
1861 (Value::from_f64(12.0), Value::from_i64(3)),
1862 (Value::from_i64(12), Value::from_f64(3.0)),
1863 (Value::from_i64(12), Value::from_i64(-3)),
1864 (Value::from_f64(12.0), Value::from_f64(-3.0)),
1865 (Value::from_f64(12.0), Value::from_i64(-3)),
1866 (Value::from_i64(12), Value::from_f64(-3.0)),
1867 (Value::Text("12.0".into()), Value::Text("3.0".into())),
1868 (Value::Text("12.0".into()), Value::from_f64(3.0)),
1869 (Value::from_f64(12.0), Value::Text("3.0".into())),
1870 ];
1871 let outputs = vec![
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::Null,
1881 Value::Null,
1882 Value::from_f64(0.0),
1883 Value::from_i64(0),
1884 Value::from_f64(0.0),
1885 Value::from_f64(0.0),
1886 Value::from_f64(0.0),
1887 Value::from_i64(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 Value::from_f64(0.0),
1893 Value::from_f64(0.0),
1894 ];
1895
1896 assert_eq!(
1897 inputs.len(),
1898 outputs.len(),
1899 "Inputs and Outputs should have same size"
1900 );
1901
1902 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1903 assert_eq!(
1904 lhs.exec_remainder(rhs),
1905 outputs[i],
1906 "Wrong remainder for lhs: {lhs}, rhs: {rhs}"
1907 );
1908 }
1909 }
1910
1911 #[test]
1912 fn test_exec_and() {
1913 let inputs = vec![
1914 (Value::from_i64(0), Value::Null),
1915 (Value::Null, Value::from_i64(1)),
1916 (Value::Null, Value::Null),
1917 (Value::from_f64(0.0), Value::Null),
1918 (Value::from_i64(1), Value::from_f64(2.2)),
1919 (Value::from_i64(0), Value::Text("string".into())),
1920 (Value::from_i64(0), Value::Text("1".into())),
1921 (Value::from_i64(1), Value::Text("1".into())),
1922 ];
1923 let outputs = [
1924 Value::from_i64(0),
1925 Value::Null,
1926 Value::Null,
1927 Value::from_i64(0),
1928 Value::from_i64(1),
1929 Value::from_i64(0),
1930 Value::from_i64(0),
1931 Value::from_i64(1),
1932 ];
1933
1934 assert_eq!(
1935 inputs.len(),
1936 outputs.len(),
1937 "Inputs and Outputs should have same size"
1938 );
1939 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1940 assert_eq!(
1941 lhs.exec_and(rhs),
1942 outputs[i],
1943 "Wrong AND for lhs: {lhs}, rhs: {rhs}"
1944 );
1945 }
1946 }
1947
1948 #[test]
1949 fn test_exec_or() {
1950 let inputs = vec![
1951 (Value::from_i64(0), Value::Null),
1952 (Value::Null, Value::from_i64(1)),
1953 (Value::Null, Value::Null),
1954 (Value::from_f64(0.0), Value::Null),
1955 (Value::from_i64(1), Value::from_f64(2.2)),
1956 (Value::from_f64(0.0), Value::from_i64(0)),
1957 (Value::from_i64(0), Value::Text("string".into())),
1958 (Value::from_i64(0), Value::Text("1".into())),
1959 (Value::from_i64(0), Value::Text("".into())),
1960 ];
1961 let outputs = [
1962 Value::Null,
1963 Value::from_i64(1),
1964 Value::Null,
1965 Value::Null,
1966 Value::from_i64(1),
1967 Value::from_i64(0),
1968 Value::from_i64(0),
1969 Value::from_i64(1),
1970 Value::from_i64(0),
1971 ];
1972
1973 assert_eq!(
1974 inputs.len(),
1975 outputs.len(),
1976 "Inputs and Outputs should have same size"
1977 );
1978 for (i, (lhs, rhs)) in inputs.iter().enumerate() {
1979 assert_eq!(
1980 lhs.exec_or(rhs),
1981 outputs[i],
1982 "Wrong OR for lhs: {lhs}, rhs: {rhs}"
1983 );
1984 }
1985 }
1986
1987 #[test]
1988 fn test_length() {
1989 let input_str = Value::build_text("bob");
1990 let expected_len = Value::from_i64(3);
1991 assert_eq!(input_str.exec_length(), expected_len);
1992
1993 let input_integer = Value::from_i64(123);
1994 let expected_len = Value::from_i64(3);
1995 assert_eq!(input_integer.exec_length(), expected_len);
1996
1997 let input_float = Value::from_f64(123.456);
1998 let expected_len = Value::from_i64(7);
1999 assert_eq!(input_float.exec_length(), expected_len);
2000
2001 let expected_blob = Value::Blob("example".as_bytes().to_vec());
2002 let expected_len = Value::from_i64(7);
2003 assert_eq!(expected_blob.exec_length(), expected_len);
2004 }
2005
2006 #[test]
2007 fn test_quote() {
2008 let input = Value::build_text("abc\0edf");
2009 let expected = Value::build_text("'abc'");
2010 assert_eq!(input.exec_quote(), expected);
2011
2012 let input = Value::from_i64(123);
2013 let expected = Value::build_text("123");
2014 assert_eq!(input.exec_quote(), expected);
2015
2016 let input = Value::from_f64(12.34);
2017 let expected = Value::build_text("12.34");
2018 assert_eq!(input.exec_quote(), expected);
2019
2020 let input = Value::build_text("hello''world");
2021 let expected = Value::build_text("'hello''''world'");
2022 assert_eq!(input.exec_quote(), expected);
2023
2024 let input = Value::from_f64(
2025 crate::numeric::str_to_f64("2.042747795102219097e+05")
2026 .map(f64::from)
2027 .unwrap(),
2028 );
2029 let expected = Value::build_text("2.042747795102219097e+05");
2030 assert_eq!(input.exec_quote(), expected);
2031 }
2032
2033 #[test]
2034 fn test_typeof() {
2035 let input = Value::Null;
2036 let expected: Value = Value::build_text("null");
2037 assert_eq!(input.exec_typeof(), expected);
2038
2039 let input = Value::from_i64(123);
2040 let expected: Value = Value::build_text("integer");
2041 assert_eq!(input.exec_typeof(), expected);
2042
2043 let input = Value::from_f64(123.456);
2044 let expected: Value = Value::build_text("real");
2045 assert_eq!(input.exec_typeof(), expected);
2046
2047 let input = Value::build_text("hello");
2048 let expected: Value = Value::build_text("text");
2049 assert_eq!(input.exec_typeof(), expected);
2050
2051 let input = Value::Blob("limbo".as_bytes().to_vec());
2052 let expected: Value = Value::build_text("blob");
2053 assert_eq!(input.exec_typeof(), expected);
2054 }
2055
2056 #[test]
2057 fn test_unicode() {
2058 assert_eq!(Value::build_text("a").exec_unicode(), Value::from_i64(97));
2059 assert_eq!(
2060 Value::build_text("😊").exec_unicode(),
2061 Value::from_i64(128522)
2062 );
2063 assert_eq!(Value::build_text("").exec_unicode(), Value::Null);
2064 assert_eq!(Value::build_text("\0").exec_unicode(), Value::Null);
2065 assert_eq!(Value::from_i64(23).exec_unicode(), Value::from_i64(50));
2066 assert_eq!(Value::from_i64(0).exec_unicode(), Value::from_i64(48));
2067 assert_eq!(Value::from_f64(0.0).exec_unicode(), Value::from_i64(48));
2068 assert_eq!(Value::from_f64(23.45).exec_unicode(), Value::from_i64(50));
2069 assert_eq!(Value::Null.exec_unicode(), Value::Null);
2070 assert_eq!(
2071 Value::Blob("example".as_bytes().to_vec()).exec_unicode(),
2072 Value::from_i64(101)
2073 );
2074 }
2075
2076 #[test]
2077 fn test_unistr() {
2078 assert_eq!(
2080 Value::build_text(r"\u0041").exec_unistr().unwrap(),
2081 Value::build_text("A")
2082 );
2083 assert_eq!(
2084 Value::build_text(r"\0041").exec_unistr().unwrap(),
2085 Value::build_text("A")
2086 );
2087 assert_eq!(
2088 Value::build_text(r"\+01F600").exec_unistr().unwrap(),
2089 Value::build_text("😀")
2090 );
2091 assert_eq!(
2092 Value::build_text(r"\U0001F600").exec_unistr().unwrap(),
2093 Value::build_text("😀")
2094 );
2095 assert_eq!(
2097 Value::build_text(r"a\\b").exec_unistr().unwrap(),
2098 Value::build_text(r"a\b")
2099 );
2100 assert_eq!(
2102 Value::build_text(r"\u00E4").exec_unistr().unwrap(),
2103 Value::build_text("ä")
2104 );
2105 assert_eq!(
2106 Value::build_text(r"\u00e4").exec_unistr().unwrap(),
2107 Value::build_text("ä")
2108 );
2109 assert_eq!(
2111 Value::build_text(r"\u0048\u0065\u006C\u006C\u006F")
2112 .exec_unistr()
2113 .unwrap(),
2114 Value::build_text("Hello")
2115 );
2116 assert_eq!(
2118 Value::build_text(r"hi \u0041 \U0001F600")
2119 .exec_unistr()
2120 .unwrap(),
2121 Value::build_text("hi A 😀")
2122 );
2123 assert_eq!(
2125 Value::build_text("hello").exec_unistr().unwrap(),
2126 Value::build_text("hello")
2127 );
2128 assert_eq!(
2130 Value::build_text("").exec_unistr().unwrap(),
2131 Value::build_text("")
2132 );
2133 assert_eq!(Value::Null.exec_unistr().unwrap(), Value::Null);
2135 assert_eq!(
2137 Value::build_text(r"\u0000").exec_unistr().unwrap(),
2138 Value::build_text("\0")
2139 );
2140 assert!(Value::build_text(r"\uD83D").exec_unistr().is_err());
2142 assert!(Value::build_text(r"\U00110000").exec_unistr().is_err());
2144 assert!(Value::build_text(r"\q").exec_unistr().is_err());
2146 assert!(Value::build_text(r"\u00").exec_unistr().is_err());
2147 assert!(Value::build_text("abc\\").exec_unistr().is_err());
2148 assert!(Value::build_text(r"\u00GG").exec_unistr().is_err());
2150 assert!(Value::build_text(r"\+01FG00").exec_unistr().is_err());
2151 assert!(Value::build_text(r"\U0001F6GG").exec_unistr().is_err());
2152 }
2153
2154 #[test]
2155 fn test_unistr_quote() {
2156 assert_eq!(Value::Null.exec_unistr_quote(), Value::build_text("NULL"));
2157 assert_eq!(
2158 Value::from_i64(42).exec_unistr_quote(),
2159 Value::build_text("42")
2160 );
2161 assert_eq!(
2162 Value::from_f64(1.5).exec_unistr_quote(),
2163 Value::build_text("1.5")
2164 );
2165 assert_eq!(
2166 Value::Blob(vec![0xDE, 0xAD]).exec_unistr_quote(),
2167 Value::build_text("X'DEAD'")
2168 );
2169 assert_eq!(
2170 Value::build_text("hello").exec_unistr_quote(),
2171 Value::build_text("'hello'")
2172 );
2173 assert_eq!(
2175 Value::build_text("a\\b").exec_unistr_quote(),
2176 Value::build_text("'a\\b'")
2177 );
2178 assert_eq!(
2179 Value::build_text("it's").exec_unistr_quote(),
2180 Value::build_text("'it''s'")
2181 );
2182 assert_eq!(
2183 Value::build_text("a\tb").exec_unistr_quote(),
2184 Value::build_text("unistr('a\\u0009b')")
2185 );
2186 assert_eq!(
2187 Value::build_text("a\t\\b").exec_unistr_quote(),
2188 Value::build_text("unistr('a\\u0009\\\\b')")
2189 );
2190 assert_eq!(
2191 Value::build_text("a\tb'c").exec_unistr_quote(),
2192 Value::build_text("unistr('a\\u0009b''c')")
2193 );
2194 assert_eq!(
2195 Value::build_text("\x01abc'\\\t\n\r\x1fXYZ\0\x01tail").exec_unistr_quote(),
2196 Value::build_text(r"unistr('\u0001abc''\\\u0009\u000a\u000d\u001fXYZ')")
2197 );
2198 assert_eq!(
2199 Value::build_text("a\x01b\0c").exec_unistr_quote(),
2200 Value::build_text("unistr('a\\u0001b')")
2201 );
2202 assert_eq!(
2203 Value::build_text("\x01").exec_unistr_quote(),
2204 Value::build_text("unistr('\\u0001')")
2205 );
2206 assert_eq!(
2207 Value::build_text("\x01\x1f").exec_unistr_quote(),
2208 Value::build_text("unistr('\\u0001\\u001f')")
2209 );
2210 assert_eq!(
2211 Value::build_text("\x10").exec_unistr_quote(),
2212 Value::build_text("unistr('\\u0010')")
2213 );
2214 assert_eq!(
2215 Value::build_text("\x1f").exec_unistr_quote(),
2216 Value::build_text("unistr('\\u001f')")
2217 );
2218 assert_eq!(
2220 Value::build_text(" ").exec_unistr_quote(),
2221 Value::build_text("' '")
2222 );
2223 assert_eq!(
2224 Value::build_text("\0abc").exec_unistr_quote(),
2225 Value::build_text("''")
2226 );
2227 assert_eq!(
2228 Value::build_text("").exec_unistr_quote(),
2229 Value::build_text("''")
2230 );
2231 assert_eq!(
2232 Value::build_text("a\nb").exec_unistr_quote(),
2233 Value::build_text("unistr('a\\u000ab')")
2234 );
2235 assert_eq!(
2236 Value::build_text("a\rb").exec_unistr_quote(),
2237 Value::build_text("unistr('a\\u000db')")
2238 );
2239 assert_eq!(
2240 Value::build_text("a\0\t").exec_unistr_quote(),
2241 Value::build_text("'a'")
2242 );
2243 }
2244
2245 #[test]
2246 fn test_min_max() {
2247 let input_int_vec = [
2248 Register::Value(Value::from_i64(-1)),
2249 Register::Value(Value::from_i64(10)),
2250 ];
2251 assert_eq!(
2252 Value::exec_min(input_int_vec.iter().map(|v| v.get_value())),
2253 Value::from_i64(-1)
2254 );
2255 assert_eq!(
2256 Value::exec_max(input_int_vec.iter().map(|v| v.get_value())),
2257 Value::from_i64(10)
2258 );
2259
2260 let str1 = Register::Value(Value::build_text("A"));
2261 let str2 = Register::Value(Value::build_text("z"));
2262 let input_str_vec = [str2, str1.clone()];
2263 assert_eq!(
2264 Value::exec_min(input_str_vec.iter().map(|v| v.get_value())),
2265 Value::build_text("A")
2266 );
2267 assert_eq!(
2268 Value::exec_max(input_str_vec.iter().map(|v| v.get_value())),
2269 Value::build_text("z")
2270 );
2271
2272 let input_null_vec = [Register::Value(Value::Null), Register::Value(Value::Null)];
2273 assert_eq!(
2274 Value::exec_min(input_null_vec.iter().map(|v| v.get_value())),
2275 Value::Null
2276 );
2277 assert_eq!(
2278 Value::exec_max(input_null_vec.iter().map(|v| v.get_value())),
2279 Value::Null
2280 );
2281
2282 let input_mixed_vec = [Register::Value(Value::from_i64(10)), str1];
2283 assert_eq!(
2284 Value::exec_min(input_mixed_vec.iter().map(|v| v.get_value())),
2285 Value::from_i64(10)
2286 );
2287 assert_eq!(
2288 Value::exec_max(input_mixed_vec.iter().map(|v| v.get_value())),
2289 Value::build_text("A")
2290 );
2291
2292 let input_with_null = [
2294 Register::Value(Value::from_i64(1)),
2295 Register::Value(Value::Null),
2296 ];
2297 assert_eq!(
2298 Value::exec_min(input_with_null.iter().map(|v| v.get_value())),
2299 Value::Null
2300 );
2301 assert_eq!(
2302 Value::exec_max(input_with_null.iter().map(|v| v.get_value())),
2303 Value::Null
2304 );
2305 }
2306
2307 #[test]
2308 fn test_trim() {
2309 let input_str = Value::build_text(" Bob and Alice ");
2310 let expected_str = Value::build_text("Bob and Alice");
2311 assert_eq!(input_str.exec_trim(None), expected_str);
2312
2313 let input_str = Value::build_text(" Bob and Alice ");
2314 let pattern_str = Value::build_text("Bob and");
2315 let expected_str = Value::build_text("Alice");
2316 assert_eq!(input_str.exec_trim(Some(&pattern_str)), expected_str);
2317
2318 let input_str = Value::build_text("\ta");
2319 let expected_str = Value::build_text("\ta");
2320 assert_eq!(input_str.exec_trim(None), expected_str);
2321
2322 let input_str = Value::build_text("\na");
2323 let expected_str = Value::build_text("\na");
2324 assert_eq!(input_str.exec_trim(None), expected_str);
2325
2326 let input_int = Value::from_i64(12345);
2328 let expected_text = Value::build_text("12345");
2329 assert_eq!(input_int.exec_trim(None), expected_text);
2330
2331 let input_float = Value::from_f64(123.5);
2333 let expected_text = Value::build_text("123.5");
2334 assert_eq!(input_float.exec_trim(None), expected_text);
2335 }
2336
2337 #[test]
2338 fn test_ltrim() {
2339 let input_str = Value::build_text(" Bob and Alice ");
2340 let expected_str = Value::build_text("Bob and Alice ");
2341 assert_eq!(input_str.exec_ltrim(None), expected_str);
2342
2343 let input_str = Value::build_text(" Bob and Alice ");
2344 let pattern_str = Value::build_text("Bob and");
2345 let expected_str = Value::build_text("Alice ");
2346 assert_eq!(input_str.exec_ltrim(Some(&pattern_str)), expected_str);
2347 }
2348
2349 #[test]
2350 fn test_rtrim() {
2351 let input_str = Value::build_text(" Bob and Alice ");
2352 let expected_str = Value::build_text(" Bob and Alice");
2353 assert_eq!(input_str.exec_rtrim(None), expected_str);
2354
2355 let input_str = Value::build_text(" Bob and Alice ");
2356 let pattern_str = Value::build_text("Bob and");
2357 let expected_str = Value::build_text(" Bob and Alice");
2358 assert_eq!(input_str.exec_rtrim(Some(&pattern_str)), expected_str);
2359
2360 let input_str = Value::build_text(" Bob and Alice ");
2361 let pattern_str = Value::build_text("and Alice");
2362 let expected_str = Value::build_text(" Bob");
2363 assert_eq!(input_str.exec_rtrim(Some(&pattern_str)), expected_str);
2364 }
2365
2366 #[test]
2367 fn test_soundex() {
2368 let input_str = Value::build_text("Pfister");
2369 let expected_str = Value::build_text("P236");
2370 assert_eq!(input_str.exec_soundex(), expected_str);
2371
2372 let input_str = Value::build_text("husobee");
2373 let expected_str = Value::build_text("H210");
2374 assert_eq!(input_str.exec_soundex(), expected_str);
2375
2376 let input_str = Value::build_text("Tymczak");
2377 let expected_str = Value::build_text("T522");
2378 assert_eq!(input_str.exec_soundex(), expected_str);
2379
2380 let input_str = Value::build_text("Ashcraft");
2381 let expected_str = Value::build_text("A261");
2382 assert_eq!(input_str.exec_soundex(), expected_str);
2383
2384 let input_str = Value::build_text("Robert");
2385 let expected_str = Value::build_text("R163");
2386 assert_eq!(input_str.exec_soundex(), expected_str);
2387
2388 let input_str = Value::build_text("Rupert");
2389 let expected_str = Value::build_text("R163");
2390 assert_eq!(input_str.exec_soundex(), expected_str);
2391
2392 let input_str = Value::build_text("Rubin");
2393 let expected_str = Value::build_text("R150");
2394 assert_eq!(input_str.exec_soundex(), expected_str);
2395
2396 let input_str = Value::build_text("Kant");
2397 let expected_str = Value::build_text("K530");
2398 assert_eq!(input_str.exec_soundex(), expected_str);
2399
2400 let input_str = Value::build_text("Knuth");
2401 let expected_str = Value::build_text("K530");
2402 assert_eq!(input_str.exec_soundex(), expected_str);
2403
2404 let input_str = Value::build_text("x");
2405 let expected_str = Value::build_text("X000");
2406 assert_eq!(input_str.exec_soundex(), expected_str);
2407
2408 let input_str = Value::build_text("闪电五连éž");
2409 let expected_str = Value::build_text("?000");
2410 assert_eq!(input_str.exec_soundex(), expected_str);
2411 }
2412
2413 #[test]
2414 fn test_upper_case() {
2415 let input_str = Value::build_text("Limbo");
2416 let expected_str = Value::build_text("LIMBO");
2417 assert_eq!(input_str.exec_upper().unwrap(), expected_str);
2418
2419 let input_int = Value::from_i64(10);
2420 assert_eq!(input_int.exec_upper().unwrap(), Value::build_text("10"));
2421 assert_eq!(Value::Null.exec_upper(), None)
2422 }
2423
2424 #[test]
2425 fn test_lower_case() {
2426 let input_str = Value::build_text("Limbo");
2427 let expected_str = Value::build_text("limbo");
2428 assert_eq!(input_str.exec_lower().unwrap(), expected_str);
2429
2430 let input_int = Value::from_i64(10);
2431 assert_eq!(input_int.exec_lower().unwrap(), Value::build_text("10"));
2432 assert_eq!(Value::Null.exec_lower(), None)
2433 }
2434
2435 #[test]
2436 fn test_hex() {
2437 let input_str = Value::build_text("limbo");
2438 let expected_val = Value::build_text("6C696D626F");
2439 assert_eq!(input_str.exec_hex(), expected_val);
2440
2441 let input_int = Value::from_i64(100);
2442 let expected_val = Value::build_text("313030");
2443 assert_eq!(input_int.exec_hex(), expected_val);
2444
2445 let input_float = Value::from_f64(12.34);
2446 let expected_val = Value::build_text("31322E3334");
2447 assert_eq!(input_float.exec_hex(), expected_val);
2448
2449 let input_blob = Value::Blob(vec![0xff]);
2450 let expected_val = Value::build_text("FF");
2451 assert_eq!(input_blob.exec_hex(), expected_val);
2452 }
2453
2454 #[test]
2455 fn test_cast_blob_preserves_blob_bytes() {
2456 let input_blob = Value::Blob(vec![0xd2, 0x64, 0xc0, 0x07, 0xf6, 0x44, 0xe4, 0x59]);
2457 let expected = input_blob.clone();
2458
2459 assert_eq!(input_blob.exec_cast("BLOB"), expected);
2460 }
2461
2462 #[test]
2463 fn test_unhex() {
2464 let input = Value::build_text("6f");
2465 let expected = Value::Blob(vec![0x6f]);
2466 assert_eq!(input.exec_unhex(None), expected);
2467
2468 let input = Value::build_text("6f");
2469 let expected = Value::Blob(vec![0x6f]);
2470 assert_eq!(input.exec_unhex(None), expected);
2471
2472 let input = Value::build_text("611");
2473 let expected = Value::Null;
2474 assert_eq!(input.exec_unhex(None), expected);
2475
2476 let input = Value::build_text("");
2477 let expected = Value::Blob(vec![]);
2478 assert_eq!(input.exec_unhex(None), expected);
2479
2480 let input = Value::build_text("61x");
2481 let expected = Value::Null;
2482 assert_eq!(input.exec_unhex(None), expected);
2483
2484 let input = Value::Null;
2485 let expected = Value::Null;
2486 assert_eq!(input.exec_unhex(None), expected);
2487
2488 let input = Value::build_text("aa-bb");
2489 let expected = Value::Blob(vec![0xaa, 0xbb]);
2490 assert_eq!(input.exec_unhex(Some(&Value::build_text("-"))), expected);
2491
2492 let input = Value::build_text("aa--bb");
2493 let expected = Value::Blob(vec![0xaa, 0xbb]);
2494 assert_eq!(input.exec_unhex(Some(&Value::build_text("-"))), expected);
2495
2496 let input = Value::build_text("aa-bb-cc");
2497 let expected = Value::Blob(vec![0xaa, 0xbb, 0xcc]);
2498 assert_eq!(input.exec_unhex(Some(&Value::build_text("-"))), expected);
2499
2500 let input = Value::build_text("aa bb");
2501 let expected = Value::Blob(vec![0xaa, 0xbb]);
2502 assert_eq!(input.exec_unhex(Some(&Value::build_text(" "))), expected);
2503
2504 let input = Value::build_text("A BCD");
2505 let expected = Value::Null;
2506 assert_eq!(input.exec_unhex(Some(&Value::build_text(" "))), expected);
2507
2508 let input = Value::build_text("yx2xEzyx");
2509 let expected = Value::Null;
2510 assert_eq!(input.exec_unhex(Some(&Value::build_text("xyz"))), expected);
2511
2512 let input = Value::build_text("aa?bb");
2513 let expected = Value::Null;
2514 assert_eq!(input.exec_unhex(Some(&Value::build_text("-"))), expected);
2515
2516 let input = Value::build_text("aabb");
2517 let expected = Value::Null;
2518 assert_eq!(input.exec_unhex(Some(&Value::Null)), expected);
2519 }
2520
2521 #[test]
2522 fn test_abs() {
2523 let int_positive_reg = Value::from_i64(10);
2524 let int_negative_reg = Value::from_i64(-10);
2525 assert_eq!(int_positive_reg.exec_abs().unwrap(), int_positive_reg);
2526 assert_eq!(int_negative_reg.exec_abs().unwrap(), int_positive_reg);
2527
2528 let float_positive_reg = Value::from_i64(10);
2529 let float_negative_reg = Value::from_i64(-10);
2530 assert_eq!(float_positive_reg.exec_abs().unwrap(), float_positive_reg);
2531 assert_eq!(float_negative_reg.exec_abs().unwrap(), float_positive_reg);
2532
2533 assert_eq!(
2534 Value::build_text("a").exec_abs().unwrap(),
2535 Value::from_f64(0.0)
2536 );
2537 assert_eq!(Value::Null.exec_abs().unwrap(), Value::Null);
2538
2539 assert!(Value::from_i64(i64::MIN).exec_abs().is_err());
2541 }
2542
2543 #[test]
2544 fn test_char() {
2545 assert_eq!(
2546 Value::exec_char(
2547 [
2548 Register::Value(Value::from_i64(108)),
2549 Register::Value(Value::from_i64(105))
2550 ]
2551 .iter()
2552 .map(|reg| reg.get_value())
2553 ),
2554 Value::build_text("li")
2555 );
2556 assert_eq!(Value::exec_char(std::iter::empty()), Value::build_text(""));
2557 assert_eq!(
2558 Value::exec_char(
2559 [Register::Value(Value::Null)]
2560 .iter()
2561 .map(|reg| reg.get_value())
2562 ),
2563 Value::build_text("\0")
2564 );
2565 assert_eq!(
2566 Value::exec_char(
2567 [Register::Value(Value::build_text("a"))]
2568 .iter()
2569 .map(|reg| reg.get_value())
2570 ),
2571 Value::build_text("")
2572 );
2573 }
2574
2575 #[test]
2576 fn test_like_with_escape_or_regexmeta_chars() {
2577 assert!(Value::exec_like(r#"\%A"#, r#"\A"#, None).unwrap());
2578 assert!(Value::exec_like("%a%a", "aaaa", None).unwrap());
2579 }
2580
2581 #[test]
2582 fn test_like_without_escape() {
2583 assert!(Value::exec_like("a%", "aaaa", None).unwrap());
2584 assert!(Value::exec_like("%a%a", "aaaa", None).unwrap());
2585 assert!(!Value::exec_like("%a.a", "aaaa", None).unwrap());
2586 assert!(!Value::exec_like("a.a%", "aaaa", None).unwrap());
2587 assert!(!Value::exec_like("%a.ab", "aaaa", None).unwrap());
2588 }
2589
2590 #[test]
2591 fn test_exec_like_with_escape() {
2592 assert!(Value::exec_like("abcX%", "abc%", Some('X')).unwrap());
2593 assert!(!Value::exec_like("abcX%", "abc5", Some('X')).unwrap());
2594 assert!(!Value::exec_like("abcX%", "abc", Some('X')).unwrap());
2595 assert!(!Value::exec_like("abcX%", "abcX%", Some('X')).unwrap());
2596 assert!(!Value::exec_like("abcX%", "abc%%", Some('X')).unwrap());
2597
2598 assert!(Value::exec_like("abcX_", "abc_", Some('X')).unwrap());
2599 assert!(!Value::exec_like("abcX_", "abc5", Some('X')).unwrap());
2600 assert!(!Value::exec_like("abcX_", "abc", Some('X')).unwrap());
2601 assert!(!Value::exec_like("abcX_", "abcX_", Some('X')).unwrap());
2602 assert!(!Value::exec_like("abcX_", "abc__", Some('X')).unwrap());
2603
2604 assert!(Value::exec_like("abcXX", "abcX", Some('X')).unwrap());
2605 assert!(!Value::exec_like("abcXX", "abc5", Some('X')).unwrap());
2606 assert!(!Value::exec_like("abcXX", "abc", Some('X')).unwrap());
2607 assert!(!Value::exec_like("abcXX", "abcXX", Some('X')).unwrap());
2608 }
2609
2610 #[test]
2611 fn test_glob() {
2612 assert!(Value::exec_glob(r#"?*/abc/?*"#, r#"x//a/ab/abc/y"#).unwrap());
2613 assert!(Value::exec_glob(r#"a[1^]"#, r#"a1"#).unwrap());
2614 assert!(Value::exec_glob(r#"a[1^]*"#, r#"a^"#).unwrap());
2615 assert!(!Value::exec_glob(r#"a[a*"#, r#"a["#).unwrap());
2616 assert!(!Value::exec_glob(r#"a[a"#, r#"a[a"#).unwrap());
2617 assert!(Value::exec_glob(r#"a[[]"#, r#"a["#).unwrap());
2618 assert!(Value::exec_glob(r#"abc[^][*?]efg"#, r#"abcdefg"#).unwrap());
2619 assert!(!Value::exec_glob(r#"abc[^][*?]efg"#, r#"abc]efg"#).unwrap());
2620 }
2621
2622 #[test]
2623 fn test_random() {
2624 match Value::exec_random(|| rand::rng().random()) {
2625 Value::Numeric(Numeric::Integer(value)) => {
2626 assert!(
2628 (i64::MIN..=i64::MAX).contains(&value),
2629 "Random number out of range"
2630 );
2631 }
2632 _ => panic!("exec_random did not return an Integer variant"),
2633 }
2634 }
2635
2636 #[test]
2637 fn test_exec_randomblob() {
2638 struct TestCase {
2639 input: Value,
2640 expected_len: usize,
2641 }
2642
2643 let test_cases = vec![
2644 TestCase {
2645 input: Value::from_i64(5),
2646 expected_len: 5,
2647 },
2648 TestCase {
2649 input: Value::from_i64(0),
2650 expected_len: 1,
2651 },
2652 TestCase {
2653 input: Value::from_i64(-1),
2654 expected_len: 1,
2655 },
2656 TestCase {
2657 input: Value::build_text(""),
2658 expected_len: 1,
2659 },
2660 TestCase {
2661 input: Value::build_text("5"),
2662 expected_len: 5,
2663 },
2664 TestCase {
2665 input: Value::build_text("0"),
2666 expected_len: 1,
2667 },
2668 TestCase {
2669 input: Value::build_text("-1"),
2670 expected_len: 1,
2671 },
2672 TestCase {
2673 input: Value::from_f64(2.9),
2674 expected_len: 2,
2675 },
2676 TestCase {
2677 input: Value::from_f64(-3.15),
2678 expected_len: 1,
2679 },
2680 TestCase {
2681 input: Value::Null,
2682 expected_len: 1,
2683 },
2684 ];
2685
2686 for test_case in &test_cases {
2687 let result = test_case
2688 .input
2689 .exec_randomblob(|dest| {
2690 rand::rng().fill_bytes(dest);
2691 })
2692 .unwrap();
2693 match result {
2694 Value::Blob(blob) => {
2695 assert_eq!(blob.len(), test_case.expected_len);
2696 }
2697 _ => panic!("exec_randomblob did not return a Blob variant"),
2698 }
2699 }
2700
2701 let input = Value::from_i64(Value::MAX_BLOB_LENGTH + 1);
2703 assert!(input.exec_randomblob(|_| {}).is_err());
2704 }
2705
2706 #[test]
2707 fn test_exec_round() {
2708 let input_val = Value::from_f64(123.456);
2709 let expected_val = Value::from_f64(123.0);
2710 assert_eq!(input_val.exec_round(None), expected_val);
2711
2712 let input_val = Value::from_f64(123.456);
2713 let precision_val = Value::from_i64(2);
2714 let expected_val = Value::from_f64(123.46);
2715 assert_eq!(input_val.exec_round(Some(&precision_val)), expected_val);
2716
2717 let input_val = Value::from_f64(123.456);
2718 let precision_val = Value::build_text("1");
2719 let expected_val = Value::from_f64(123.5);
2720 assert_eq!(input_val.exec_round(Some(&precision_val)), expected_val);
2721
2722 let input_val = Value::build_text("123.456");
2723 let precision_val = Value::from_i64(2);
2724 let expected_val = Value::from_f64(123.46);
2725 assert_eq!(input_val.exec_round(Some(&precision_val)), expected_val);
2726
2727 let input_val = Value::from_i64(123);
2728 let precision_val = Value::from_i64(1);
2729 let expected_val = Value::from_f64(123.0);
2730 assert_eq!(input_val.exec_round(Some(&precision_val)), expected_val);
2731
2732 let input_val = Value::from_f64(100.123);
2733 let expected_val = Value::from_f64(100.0);
2734 assert_eq!(input_val.exec_round(None), expected_val);
2735
2736 let input_val = Value::from_f64(100.123);
2737 let expected_val = Value::Null;
2738 assert_eq!(input_val.exec_round(Some(&Value::Null)), expected_val);
2739 }
2740
2741 #[test]
2742 fn test_exec_if() {
2743 let reg = Value::from_i64(0);
2744 assert!(!reg.exec_if(false, false));
2745 assert!(reg.exec_if(false, true));
2746
2747 let reg = Value::from_i64(1);
2748 assert!(reg.exec_if(false, false));
2749 assert!(!reg.exec_if(false, true));
2750
2751 let reg = Value::Null;
2752 assert!(!reg.exec_if(false, false));
2753 assert!(!reg.exec_if(false, true));
2754
2755 let reg = Value::Null;
2756 assert!(reg.exec_if(true, false));
2757 assert!(reg.exec_if(true, true));
2758
2759 let reg = Value::Null;
2760 assert!(!reg.exec_if(false, false));
2761 assert!(!reg.exec_if(false, true));
2762 }
2763
2764 #[test]
2765 fn test_nullif() {
2766 assert_eq!(
2767 Value::from_i64(1).exec_nullif(&Value::from_i64(1)),
2768 Value::Null
2769 );
2770 assert_eq!(
2771 Value::from_f64(1.1).exec_nullif(&Value::from_f64(1.1)),
2772 Value::Null
2773 );
2774 assert_eq!(
2775 Value::build_text("limbo").exec_nullif(&Value::build_text("limbo")),
2776 Value::Null
2777 );
2778
2779 assert_eq!(
2780 Value::from_i64(1).exec_nullif(&Value::from_i64(2)),
2781 Value::from_i64(1)
2782 );
2783 assert_eq!(
2784 Value::from_f64(1.1).exec_nullif(&Value::from_f64(1.2)),
2785 Value::from_f64(1.1)
2786 );
2787 assert_eq!(
2788 Value::build_text("limbo").exec_nullif(&Value::build_text("limb")),
2789 Value::build_text("limbo")
2790 );
2791 }
2792
2793 #[test]
2794 fn test_substring() {
2795 let str_value = Value::build_text("limbo");
2796 let start_value = Value::from_i64(1);
2797 let length_value = Value::from_i64(3);
2798 let expected_val = Value::build_text("lim");
2799 assert_eq!(
2800 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2801 expected_val
2802 );
2803
2804 let str_value = Value::build_text("limbo");
2805 let start_value = Value::from_i64(1);
2806 let length_value = Value::from_i64(10);
2807 let expected_val = Value::build_text("limbo");
2808 assert_eq!(
2809 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2810 expected_val
2811 );
2812
2813 let str_value = Value::build_text("limbo");
2814 let start_value = Value::from_i64(10);
2815 let length_value = Value::from_i64(3);
2816 let expected_val = Value::build_text("");
2817 assert_eq!(
2818 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2819 expected_val
2820 );
2821
2822 let str_value = Value::build_text("limbo");
2823 let start_value = Value::from_i64(3);
2824 let length_value = Value::Null;
2825 let expected_val = Value::Null;
2826 assert_eq!(
2827 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2828 expected_val
2829 );
2830
2831 let str_value = Value::build_text("limbo");
2832 let start_value = Value::from_i64(10);
2833 let length_value = Value::Null;
2834 let expected_val = Value::Null;
2835 assert_eq!(
2836 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2837 expected_val
2838 );
2839
2840 let str_value = Value::build_text("limbo");
2841 let start_value = Value::from_i64(-7_096_519_388_852_014_892);
2842 let length_value = Value::from_i64(-4_829_175_794_346_763_833);
2843 let expected_val = Value::build_text("");
2844 assert_eq!(
2845 Value::exec_substring(&str_value, &start_value, Some(&length_value)),
2846 expected_val
2847 );
2848 }
2849
2850 #[test]
2851 fn test_exec_instr() {
2852 let input = Value::build_text("limbo");
2853 let pattern = Value::build_text("im");
2854 let expected = Value::from_i64(2);
2855 assert_eq!(input.exec_instr(&pattern), expected);
2856
2857 let input = Value::build_text("limbo");
2858 let pattern = Value::build_text("limbo");
2859 let expected = Value::from_i64(1);
2860 assert_eq!(input.exec_instr(&pattern), expected);
2861
2862 let input = Value::build_text("limbo");
2863 let pattern = Value::build_text("o");
2864 let expected = Value::from_i64(5);
2865 assert_eq!(input.exec_instr(&pattern), expected);
2866
2867 let input = Value::build_text("liiiiimbo");
2868 let pattern = Value::build_text("ii");
2869 let expected = Value::from_i64(2);
2870 assert_eq!(input.exec_instr(&pattern), expected);
2871
2872 let input = Value::build_text("limbo");
2873 let pattern = Value::build_text("limboX");
2874 let expected = Value::from_i64(0);
2875 assert_eq!(input.exec_instr(&pattern), expected);
2876
2877 let input = Value::build_text("limbo");
2878 let pattern = Value::build_text("");
2879 let expected = Value::from_i64(1);
2880 assert_eq!(input.exec_instr(&pattern), expected);
2881
2882 let input = Value::build_text("");
2883 let pattern = Value::build_text("limbo");
2884 let expected = Value::from_i64(0);
2885 assert_eq!(input.exec_instr(&pattern), expected);
2886
2887 let input = Value::build_text("");
2888 let pattern = Value::build_text("");
2889 let expected = Value::from_i64(1);
2890 assert_eq!(input.exec_instr(&pattern), expected);
2891
2892 let input = Value::Null;
2893 let pattern = Value::Null;
2894 let expected = Value::Null;
2895 assert_eq!(input.exec_instr(&pattern), expected);
2896
2897 let input = Value::build_text("limbo");
2898 let pattern = Value::Null;
2899 let expected = Value::Null;
2900 assert_eq!(input.exec_instr(&pattern), expected);
2901
2902 let input = Value::Null;
2903 let pattern = Value::build_text("limbo");
2904 let expected = Value::Null;
2905 assert_eq!(input.exec_instr(&pattern), expected);
2906
2907 let input = Value::from_i64(123);
2908 let pattern = Value::from_i64(2);
2909 let expected = Value::from_i64(2);
2910 assert_eq!(input.exec_instr(&pattern), expected);
2911
2912 let input = Value::from_i64(123);
2913 let pattern = Value::from_i64(5);
2914 let expected = Value::from_i64(0);
2915 assert_eq!(input.exec_instr(&pattern), expected);
2916
2917 let input = Value::from_f64(12.34);
2918 let pattern = Value::from_f64(2.3);
2919 let expected = Value::from_i64(2);
2920 assert_eq!(input.exec_instr(&pattern), expected);
2921
2922 let input = Value::from_f64(12.34);
2923 let pattern = Value::from_f64(5.6);
2924 let expected = Value::from_i64(0);
2925 assert_eq!(input.exec_instr(&pattern), expected);
2926
2927 let input = Value::from_f64(12.34);
2928 let pattern = Value::build_text(".");
2929 let expected = Value::from_i64(3);
2930 assert_eq!(input.exec_instr(&pattern), expected);
2931
2932 let input = Value::Blob(vec![1, 2, 3, 4, 5]);
2933 let pattern = Value::Blob(vec![3, 4]);
2934 let expected = Value::from_i64(3);
2935 assert_eq!(input.exec_instr(&pattern), expected);
2936
2937 let input = Value::Blob(vec![1, 2, 3, 4, 5]);
2938 let pattern = Value::Blob(vec![3, 2]);
2939 let expected = Value::from_i64(0);
2940 assert_eq!(input.exec_instr(&pattern), expected);
2941
2942 let input = Value::Blob(vec![0x61, 0x62, 0x63, 0x64, 0x65]);
2943 let pattern = Value::build_text("cd");
2944 let expected = Value::from_i64(3);
2945 assert_eq!(input.exec_instr(&pattern), expected);
2946
2947 let input = Value::build_text("abcde");
2948 let pattern = Value::Blob(vec![0x63, 0x64]);
2949 let expected = Value::from_i64(3);
2950 assert_eq!(input.exec_instr(&pattern), expected);
2951
2952 let input = Value::build_text("abcde");
2953 let pattern = Value::build_text("");
2954 let expected = Value::from_i64(1);
2955 assert_eq!(input.exec_instr(&pattern), expected);
2956 }
2957
2958 #[test]
2959 fn test_exec_sign() {
2960 let input = Value::from_i64(42);
2961 let expected = Some(Value::from_i64(1));
2962 assert_eq!(input.exec_sign(), expected);
2963
2964 let input = Value::from_i64(-42);
2965 let expected = Some(Value::from_i64(-1));
2966 assert_eq!(input.exec_sign(), expected);
2967
2968 let input = Value::from_i64(0);
2969 let expected = Some(Value::from_i64(0));
2970 assert_eq!(input.exec_sign(), expected);
2971
2972 let input = Value::from_f64(0.0);
2973 let expected = Some(Value::from_i64(0));
2974 assert_eq!(input.exec_sign(), expected);
2975
2976 let input = Value::from_f64(0.1);
2977 let expected = Some(Value::from_i64(1));
2978 assert_eq!(input.exec_sign(), expected);
2979
2980 let input = Value::from_f64(42.0);
2981 let expected = Some(Value::from_i64(1));
2982 assert_eq!(input.exec_sign(), expected);
2983
2984 let input = Value::from_f64(-42.0);
2985 let expected = Some(Value::from_i64(-1));
2986 assert_eq!(input.exec_sign(), expected);
2987
2988 let input = Value::build_text("abc");
2989 let expected = None;
2990 assert_eq!(input.exec_sign(), expected);
2991
2992 let input = Value::build_text("42");
2993 let expected = Some(Value::from_i64(1));
2994 assert_eq!(input.exec_sign(), expected);
2995
2996 let input = Value::build_text("-42");
2997 let expected = Some(Value::from_i64(-1));
2998 assert_eq!(input.exec_sign(), expected);
2999
3000 let input = Value::build_text("0");
3001 let expected = Some(Value::from_i64(0));
3002 assert_eq!(input.exec_sign(), expected);
3003
3004 let input = Value::Blob(b"abc".to_vec());
3005 let expected = None;
3006 assert_eq!(input.exec_sign(), expected);
3007
3008 let input = Value::Blob(b"42".to_vec());
3009 let expected = None;
3010 assert_eq!(input.exec_sign(), expected);
3011
3012 let input = Value::Blob(b"-42".to_vec());
3013 let expected = None;
3014 assert_eq!(input.exec_sign(), expected);
3015
3016 let input = Value::Blob(b"0".to_vec());
3017 let expected = None;
3018 assert_eq!(input.exec_sign(), expected);
3019
3020 let input = Value::Null;
3021 let expected = None;
3022 assert_eq!(input.exec_sign(), expected);
3023 }
3024
3025 #[test]
3026 fn test_exec_zeroblob() {
3027 let input = Value::from_i64(0);
3028 let expected = Value::Blob(vec![]);
3029 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3030
3031 let input = Value::Null;
3032 let expected = Value::Blob(vec![]);
3033 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3034
3035 let input = Value::from_i64(4);
3036 let expected = Value::Blob(vec![0; 4]);
3037 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3038
3039 let input = Value::from_i64(-1);
3040 let expected = Value::Blob(vec![]);
3041 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3042
3043 let input = Value::build_text("5");
3044 let expected = Value::Blob(vec![0; 5]);
3045 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3046
3047 let input = Value::build_text("-5");
3048 let expected = Value::Blob(vec![]);
3049 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3050
3051 let input = Value::build_text("text");
3052 let expected = Value::Blob(vec![]);
3053 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3054
3055 let input = Value::from_f64(2.6);
3056 let expected = Value::Blob(vec![0; 2]);
3057 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3058
3059 let input = Value::Blob(vec![1]);
3060 let expected = Value::Blob(vec![]);
3061 assert_eq!(input.exec_zeroblob().unwrap(), expected);
3062
3063 let input = Value::from_i64(Value::MAX_BLOB_LENGTH + 1);
3065 assert!(input.exec_zeroblob().is_err());
3066 }
3067
3068 #[test]
3069 fn test_replace() {
3070 let input_str = Value::build_text("bob");
3071 let pattern_str = Value::build_text("b");
3072 let replace_str = Value::build_text("a");
3073 let expected_str = Value::build_text("aoa");
3074 assert_eq!(
3075 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3076 expected_str
3077 );
3078
3079 let input_str = Value::build_text("bob");
3080 let pattern_str = Value::build_text("b");
3081 let replace_str = Value::build_text("");
3082 let expected_str = Value::build_text("o");
3083 assert_eq!(
3084 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3085 expected_str
3086 );
3087
3088 let input_str = Value::build_text("bob");
3089 let pattern_str = Value::build_text("b");
3090 let replace_str = Value::build_text("abc");
3091 let expected_str = Value::build_text("abcoabc");
3092 assert_eq!(
3093 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3094 expected_str
3095 );
3096
3097 let input_str = Value::build_text("bob");
3098 let pattern_str = Value::build_text("a");
3099 let replace_str = Value::build_text("b");
3100 let expected_str = Value::build_text("bob");
3101 assert_eq!(
3102 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3103 expected_str
3104 );
3105
3106 let input_str = Value::build_text("bob");
3107 let pattern_str = Value::build_text("");
3108 let replace_str = Value::build_text("a");
3109 let expected_str = Value::build_text("bob");
3110 assert_eq!(
3111 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3112 expected_str
3113 );
3114
3115 let input_str = Value::build_text("bob");
3116 let pattern_str = Value::Null;
3117 let replace_str = Value::build_text("a");
3118 let expected_str = Value::Null;
3119 assert_eq!(
3120 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3121 expected_str
3122 );
3123
3124 let input_str = Value::build_text("bo5");
3125 let pattern_str = Value::from_i64(5);
3126 let replace_str = Value::build_text("a");
3127 let expected_str = Value::build_text("boa");
3128 assert_eq!(
3129 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3130 expected_str
3131 );
3132
3133 let input_str = Value::build_text("bo5.0");
3134 let pattern_str = Value::from_f64(5.0);
3135 let replace_str = Value::build_text("a");
3136 let expected_str = Value::build_text("boa");
3137 assert_eq!(
3138 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3139 expected_str
3140 );
3141
3142 let input_str = Value::build_text("bo5");
3143 let pattern_str = Value::from_f64(5.0);
3144 let replace_str = Value::build_text("a");
3145 let expected_str = Value::build_text("bo5");
3146 assert_eq!(
3147 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3148 expected_str
3149 );
3150
3151 let input_str = Value::build_text("bo5.0");
3152 let pattern_str = Value::from_f64(5.0);
3153 let replace_str = Value::from_f64(6.0);
3154 let expected_str = Value::build_text("bo6.0");
3155 assert_eq!(
3156 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3157 expected_str
3158 );
3159
3160 let input_str = Value::build_text("tes3");
3162 let pattern_str = Value::from_i64(3);
3163 let replace_str = Value::from_f64(0.3);
3164 let expected_str = Value::build_text("tes0.3");
3165 assert_eq!(
3166 Value::exec_replace(&input_str, &pattern_str, &replace_str),
3167 expected_str
3168 );
3169 }
3170}