1use std::{ops::Deref, str::FromStr};
2
3use crate::{
4 engine::Engine,
5 error::CvsSqlError,
6 group_by::GroupRow,
7 projections::{Projection, SingleConvert},
8 result_set_metadata::Metadata,
9 util::SmartReference,
10 value::Value,
11};
12use bigdecimal::FromPrimitive;
13use bigdecimal::ToPrimitive;
14use bigdecimal::{BigDecimal, Zero};
15use chrono::{TimeZone, Utc, offset::LocalResult};
16use itertools::Itertools;
17use regex::Regex;
18use sqlparser::ast::{
19 DuplicateTreatment, Function, FunctionArg, FunctionArgExpr, FunctionArguments,
20};
21
22impl SingleConvert for Function {
23 fn convert_single(
24 &self,
25 metadata: &Metadata,
26 engine: &Engine,
27 ) -> Result<Box<dyn Projection>, CvsSqlError> {
28 if !self.within_group.is_empty() {
29 return Err(CvsSqlError::Unsupported("WITHIN GROUP".into()));
30 }
31
32 if self.over.is_some() {
33 return Err(CvsSqlError::Unsupported("OVER".into()));
34 }
35
36 if self.null_treatment.is_some() {
37 return Err(CvsSqlError::Unsupported("IGNORE/RESPECT NULLS".into()));
38 }
39
40 if self.filter.is_some() {
41 return Err(CvsSqlError::Unsupported("FILTER".into()));
42 }
43 if self.parameters != FunctionArguments::None {
44 return Err(CvsSqlError::Unsupported("function parameters".into()));
45 }
46
47 let name = self.name.to_string().to_uppercase();
48 build_function_from_name(&name, metadata, engine, &self.args)
49 }
50}
51fn build_function_from_name(
52 name: &str,
53 metadata: &Metadata,
54 engine: &Engine,
55 args: &FunctionArguments,
56) -> Result<Box<dyn Projection>, CvsSqlError> {
57 match name {
58 "COUNT" => build_aggregator_function(metadata, engine, args, Box::new(Count {})),
59 "AVG" => build_aggregator_function(metadata, engine, args, Box::new(Avg {})),
60 "SUM" => build_aggregator_function(metadata, engine, args, Box::new(Sum {})),
61 "MIN" => build_aggregator_function(metadata, engine, args, Box::new(Min {})),
62 "MAX" => build_aggregator_function(metadata, engine, args, Box::new(Max {})),
63 "ANY_VALUE" => build_aggregator_function(metadata, engine, args, Box::new(AnyValue {})),
64
65 "ABS" => build_function(metadata, engine, args, Box::new(Abs {})),
66 "ASCII" => build_function(metadata, engine, args, Box::new(Ascii {})),
67 "CHR" => build_function(metadata, engine, args, Box::new(Chr {})),
68 "LENGTH" | "CHAR_LENGTH" | "CHARACTER_LENGTH" => {
69 build_function(metadata, engine, args, Box::new(Length {}))
70 }
71 "COALESCE" => build_function(metadata, engine, args, Box::new(Coalece {})),
72 "CONCAT" => build_function(metadata, engine, args, Box::new(Concat {})),
73 "CONCAT_WS" => build_function(metadata, engine, args, Box::new(ConcatWs {})),
74 "CURRENT_DATE" | "CURDATE" => {
75 build_function(metadata, engine, args, Box::new(CurrentDate {}))
76 }
77 "NOW" | "CURRENT_TIME" | "CURRENT_TIMESTAMP" | "CURTIME" | "LOCALTIME"
78 | "LOCALTIMESTAMP" => build_function(metadata, engine, args, Box::new(Now {})),
79 "USER" | "CURRENT_USER" => build_function(metadata, engine, args, Box::new(User {})),
80 "FORMAT" | "DATE_FORMAT" | "TIME_FORMAT" | "TO_CHAR" => {
81 build_function(metadata, engine, args, Box::new(Format {}))
82 }
83 "TO_TIMESTAMP" | "FROM_UNIXTIME" => {
84 build_function(metadata, engine, args, Box::new(ToTimestamp {}))
85 }
86 "GREATEST" => build_function(metadata, engine, args, Box::new(Greatest {})),
87 "IF" => build_function(metadata, engine, args, Box::new(If {})),
88 "NULLIF" => build_function(metadata, engine, args, Box::new(NullIf {})),
89 "LOWER" | "LCASE" => build_function(metadata, engine, args, Box::new(Lower {})),
90 "UPPER" | "UCASE" => build_function(metadata, engine, args, Box::new(Upper {})),
91 "LEAST" => build_function(metadata, engine, args, Box::new(Least {})),
92 "LEFT" => build_function(metadata, engine, args, Box::new(Left {})),
93 "RIGHT" => build_function(metadata, engine, args, Box::new(Right {})),
94 "LPAD" => build_function(metadata, engine, args, Box::new(Lpad {})),
95 "RPAD" => build_function(metadata, engine, args, Box::new(Rpad {})),
96 "LTRIM" => build_function(metadata, engine, args, Box::new(Ltrim {})),
97 "RTRIM" => build_function(metadata, engine, args, Box::new(Rtrim {})),
98 "PI" => build_function(metadata, engine, args, Box::new(Pi {})),
99 "RANDOM" | "RAND" => build_function(metadata, engine, args, Box::new(Random {})),
100 "POSITION" | "LOCATE" => build_function(metadata, engine, args, Box::new(Position {})),
101 "REPEAT" => build_function(metadata, engine, args, Box::new(Repeat {})),
102 "REPLACE" => build_function(metadata, engine, args, Box::new(Replace {})),
103 "REGEX_LIKE" => build_function(metadata, engine, args, Box::new(RegexLike {})),
104 "REGEX_REPLACE" => build_function(metadata, engine, args, Box::new(RegexReplace {})),
105 "REGEXP_SUBSTR" => build_function(metadata, engine, args, Box::new(RegexSubstring {})),
106 "REVERSE" => build_function(metadata, engine, args, Box::new(Reverse {})),
107 "LN" => build_function(metadata, engine, args, Box::new(Ln {})),
108 "EXP" => build_function(metadata, engine, args, Box::new(Exp {})),
109 "LOG" => build_function(metadata, engine, args, Box::new(Log {})),
110 "LOG2" => build_function(metadata, engine, args, Box::new(Log2 {})),
111 "LOG10" => build_function(metadata, engine, args, Box::new(Log10 {})),
112 "POW" | "POWER" => build_function(metadata, engine, args, Box::new(Power {})),
113 "ROUND" => build_function(metadata, engine, args, Box::new(Round {})),
114 "SQRT" => build_function(metadata, engine, args, Box::new(Sqrt {})),
115 _ => Err(CvsSqlError::Unsupported(format!("function {name}"))),
116 }
117}
118
119fn build_aggregator_function(
120 metadata: &Metadata,
121 engine: &Engine,
122 args: &FunctionArguments,
123 operator: Box<dyn AggregateOperator>,
124) -> Result<Box<dyn Projection>, CvsSqlError> {
125 let parent_metadata = match metadata {
126 Metadata::Grouped { parent, this: _ } => parent,
127 _ => return Err(CvsSqlError::NoGroupBy),
128 };
129 let lst = match &args {
130 FunctionArguments::List(lst) => lst,
131 FunctionArguments::Subquery(_) => {
132 return Err(CvsSqlError::Unsupported(
133 "function subquery arguments".into(),
134 ));
135 }
136 FunctionArguments::None => {
137 return Err(CvsSqlError::Unsupported(format!(
138 "Function {} must have an argmeunt",
139 operator.name()
140 )));
141 }
142 };
143 let distinct = matches!(lst.duplicate_treatment, Some(DuplicateTreatment::Distinct));
144
145 if let Some(c) = lst.clauses.first() {
146 return Err(CvsSqlError::Unsupported(format!("{c}")));
147 }
148 let first = match lst.args.first() {
149 Some(arg) => arg,
150 None => {
151 return Err(CvsSqlError::Unsupported(format!(
152 "Function {} must have an argmeunt",
153 operator.name()
154 )));
155 }
156 };
157 if lst.args.len() > 1 {
158 return Err(CvsSqlError::Unsupported(format!(
159 "Function {} must have a single argmeunt",
160 operator.name()
161 )));
162 }
163 let argument = match first {
164 FunctionArg::Unnamed(FunctionArgExpr::Expr(e)) => {
165 e.convert_single(parent_metadata, engine)?
166 }
167 FunctionArg::Unnamed(FunctionArgExpr::Wildcard) => {
168 if operator.support_wildcard_argument() {
169 if distinct {
170 return Err(CvsSqlError::Unsupported("DISTINCT with * argument".into()));
171 }
172 wildcard_operator()
173 } else {
174 return Err(CvsSqlError::Unsupported(format!(
175 "Function {} with * argument",
176 operator.name()
177 )));
178 }
179 }
180 _ => return Err(CvsSqlError::Unsupported(format!("{first}"))),
181 };
182 let name = format!("{}({})", operator.name(), argument.name());
183
184 Ok(Box::new(AggregatedFunction {
185 distinct,
186 argument,
187 operator,
188 name,
189 }))
190}
191
192#[cfg(test)]
193struct AggregationExample<'a> {
194 name: &'a str,
195 data: Vec<&'a str>,
196 is_wildcard: bool,
197 is_distinct: bool,
198 expected_results: &'a str,
199}
200trait AggregateOperator {
201 fn name(&self) -> &str;
202 fn support_wildcard_argument(&self) -> bool {
203 false
204 }
205 fn aggregate(&self, data: &mut dyn Iterator<Item = Value>) -> Value;
206 #[cfg(test)]
207 fn examples<'a>(&'a self) -> Vec<AggregationExample<'a>>;
208}
209
210trait Casters {
211 fn to_number(self) -> Option<BigDecimal>;
212}
213
214impl Casters for Value {
215 fn to_number(self) -> Option<BigDecimal> {
216 match self {
217 Value::Number(num) => Some(num),
218 _ => None,
219 }
220 }
221}
222
223struct Count {}
224
225impl AggregateOperator for Count {
226 fn name(&self) -> &str {
227 "COUNT"
228 }
229 fn support_wildcard_argument(&self) -> bool {
230 true
231 }
232 fn aggregate(&self, data: &mut dyn Iterator<Item = Value>) -> Value {
233 let count = data.count();
234 Value::Number((count as u128).into())
235 }
236 #[cfg(test)]
237 fn examples<'a>(&'a self) -> Vec<AggregationExample<'a>> {
238 vec![
239 AggregationExample {
240 name: "simple",
241 data: vec!["1", "2", "3", "4", "1"],
242 is_distinct: false,
243 is_wildcard: false,
244 expected_results: "5",
245 },
246 AggregationExample {
247 name: "wildcard",
248 data: vec!["1", "2", "3", "4", "1"],
249 is_distinct: false,
250 is_wildcard: true,
251 expected_results: "5",
252 },
253 AggregationExample {
254 name: "distinct",
255 data: vec!["1", "2", "3", "4", "1"],
256 is_distinct: true,
257 is_wildcard: false,
258 expected_results: "4",
259 },
260 ]
261 }
262}
263
264struct Avg {}
265
266impl AggregateOperator for Avg {
267 fn name(&self) -> &str {
268 "AVG"
269 }
270
271 fn aggregate(&self, data: &mut dyn Iterator<Item = Value>) -> Value {
272 let mut total = BigDecimal::zero();
273 let mut count: u128 = 0;
274 for num in data.filter_map(|f| f.to_number()) {
275 count += 1;
276 total += num;
277 }
278 if count == 0 {
279 Value::Empty
280 } else {
281 Value::Number(total / count)
282 }
283 }
284
285 #[cfg(test)]
286 fn examples<'a>(&'a self) -> Vec<AggregationExample<'a>> {
287 vec![
288 AggregationExample {
289 name: "simple",
290 is_distinct: false,
291 is_wildcard: false,
292 data: vec!["5", "11", "11", "1"],
293 expected_results: "7",
294 },
295 AggregationExample {
296 name: "distinct",
297 is_distinct: true,
298 is_wildcard: false,
299 data: vec!["30", "12", "12", "9"],
300 expected_results: "17",
301 },
302 AggregationExample {
303 name: "not_only_numbers",
304 is_distinct: true,
305 is_wildcard: false,
306 data: vec!["10", "", "nop", "12"],
307 expected_results: "11",
308 },
309 AggregationExample {
310 name: "no_numbers",
311 is_distinct: true,
312 is_wildcard: false,
313 data: vec!["a", "", "nop", ""],
314 expected_results: "",
315 },
316 ]
317 }
318}
319
320struct Sum {}
321
322impl AggregateOperator for Sum {
323 fn name(&self) -> &str {
324 "SUM"
325 }
326 fn aggregate(&self, data: &mut dyn Iterator<Item = Value>) -> Value {
327 let total = data
328 .filter_map(|f| f.to_number())
329 .fold(BigDecimal::zero(), |a, b| a + b);
330 Value::Number(total)
331 }
332 #[cfg(test)]
333 fn examples<'a>(&'a self) -> Vec<AggregationExample<'a>> {
334 vec![
335 AggregationExample {
336 name: "simple",
337 is_distinct: false,
338 is_wildcard: false,
339 data: vec!["1", "1", "2", "3"],
340 expected_results: "7",
341 },
342 AggregationExample {
343 name: "distinct",
344 is_distinct: true,
345 is_wildcard: false,
346 data: vec!["1", "1", "2", "3"],
347 expected_results: "6",
348 },
349 AggregationExample {
350 name: "not_only_numbers",
351 is_distinct: true,
352 is_wildcard: false,
353 data: vec!["10", "", "nop", "12"],
354 expected_results: "22",
355 },
356 AggregationExample {
357 name: "no_numbers",
358 is_distinct: true,
359 is_wildcard: false,
360 data: vec!["a", "", "nop", ""],
361 expected_results: "0",
362 },
363 ]
364 }
365}
366struct Min {}
367
368impl AggregateOperator for Min {
369 fn name(&self) -> &str {
370 "MIN"
371 }
372 fn aggregate(&self, data: &mut dyn Iterator<Item = Value>) -> Value {
373 let min = data.min();
374 min.unwrap_or(Value::Empty)
375 }
376
377 #[cfg(test)]
378 fn examples<'a>(&'a self) -> Vec<AggregationExample<'a>> {
379 vec![
380 AggregationExample {
381 name: "numbers",
382 is_distinct: false,
383 is_wildcard: false,
384 data: vec!["1", "1", "2", "3"],
385 expected_results: "1",
386 },
387 AggregationExample {
388 name: "letters",
389 is_distinct: true,
390 is_wildcard: false,
391 data: vec!["e", "b", "d", "q"],
392 expected_results: "b",
393 },
394 ]
395 }
396}
397
398struct Max {}
399impl AggregateOperator for Max {
400 fn name(&self) -> &str {
401 "MAX"
402 }
403 fn aggregate(&self, data: &mut dyn Iterator<Item = Value>) -> Value {
404 let min = data.max();
405 min.unwrap_or(Value::Empty)
406 }
407 #[cfg(test)]
408 fn examples<'a>(&'a self) -> Vec<AggregationExample<'a>> {
409 vec![
410 AggregationExample {
411 name: "numbers",
412 is_distinct: false,
413 is_wildcard: false,
414 data: vec!["1", "1", "2", "3"],
415 expected_results: "3",
416 },
417 AggregationExample {
418 name: "letters",
419 is_distinct: true,
420 is_wildcard: false,
421 data: vec!["e", "b", "d", "q"],
422 expected_results: "q",
423 },
424 ]
425 }
426}
427
428struct AnyValue {}
429impl AggregateOperator for AnyValue {
430 fn name(&self) -> &str {
431 "ANY_VALUE"
432 }
433 fn aggregate(&self, data: &mut dyn Iterator<Item = Value>) -> Value {
434 let val = data.next();
435 val.unwrap_or(Value::Empty)
436 }
437 #[cfg(test)]
438 fn examples<'a>(&'a self) -> Vec<AggregationExample<'a>> {
439 vec![AggregationExample {
440 name: "values",
441 is_distinct: false,
442 is_wildcard: false,
443 data: vec!["a", "b", "2", "3"],
444 expected_results: "a",
445 }]
446 }
447}
448
449struct AggregatedFunction {
450 distinct: bool,
451 argument: Box<dyn Projection>,
452 operator: Box<dyn AggregateOperator>,
453 name: String,
454}
455
456impl Projection for AggregatedFunction {
457 fn get<'a>(&'a self, row: &'a GroupRow) -> SmartReference<'a, Value> {
458 let mut iter = row
459 .group_rows
460 .iter()
461 .map(|r| self.argument.get(r))
462 .map(|v| v.clone());
463 let value = if self.distinct {
464 let mut unique = iter.unique();
465 self.operator.aggregate(&mut unique)
466 } else {
467 self.operator.aggregate(&mut iter)
468 };
469 value.into()
470 }
471 fn name(&self) -> &str {
472 &self.name
473 }
474}
475
476struct Wildcard {}
477impl Projection for Wildcard {
478 fn get<'a>(&'a self, _: &'a GroupRow) -> SmartReference<'a, Value> {
479 Value::Bool(true).into()
480 }
481 fn name(&self) -> &str {
482 "*"
483 }
484}
485fn wildcard_operator() -> Box<dyn Projection> {
486 Box::new(Wildcard {})
487}
488
489#[cfg(test)]
490mod test_aggregations {
491 use std::fs::{self, OpenOptions};
492
493 use crate::{args::Args, engine::Engine, error::CvsSqlError, results::Column};
494 use std::io::Write;
495
496 use super::{AggregateOperator, AggregationExample, AnyValue, Avg, Count, Max, Min, Sum};
497
498 fn test_agg(operator: &impl AggregateOperator) -> Result<(), CvsSqlError> {
499 let dir = format!("./target/function_tests/{}", operator.name().to_lowercase());
500 println!("testing: {}", operator.name());
501 fs::remove_dir_all(&dir).ok();
502 fs::create_dir_all(&dir)?;
503 for example in operator.examples() {
504 test_agg_with_example(operator, &example)?;
505 }
506 fs::remove_dir_all(&dir).ok();
507
508 Ok(())
509 }
510
511 fn test_agg_with_example<'a>(
512 operator: &impl AggregateOperator,
513 example: &AggregationExample<'a>,
514 ) -> Result<(), CvsSqlError> {
515 println!("testing: {} with {}", operator.name(), example.name);
516 let dir = format!("./target/function_tests/{}", operator.name().to_lowercase());
517 let file = format!("{}/{}.csv", dir, example.name);
518 let mut writer = OpenOptions::new()
519 .write(true)
520 .create(true)
521 .truncate(true)
522 .open(&file)?;
523 writeln!(writer, "row")?;
524 for data in &example.data {
525 writeln!(writer, "{data}")?;
526 }
527
528 let table_name = format!(
529 "target.function_tests.{}.{}",
530 operator.name().to_lowercase(),
531 &example.name
532 );
533 let selector = if example.is_distinct {
534 "DISTINCT row"
535 } else if example.is_wildcard {
536 "*"
537 } else {
538 "row"
539 };
540
541 let sql = format!(
542 "SELECT {}({}) FROM {}\n",
543 operator.name(),
544 selector,
545 table_name
546 );
547
548 let args = Args::default();
549 let engine = Engine::try_from(&args)?;
550
551 let results = engine.execute_commands(&sql)?;
552
553 fs::remove_file(file)?;
554
555 let col = Column::from_index(0);
556 let result = results
557 .first()
558 .and_then(|d| d.results.data.iter().next())
559 .map(|d| d.get(&col));
560 let expected_results = example.expected_results.into();
561 assert_eq!(result, Some(&expected_results));
562
563 Ok(())
564 }
565
566 #[test]
567 fn test_count() -> Result<(), CvsSqlError> {
568 test_agg(&Count {})
569 }
570
571 #[test]
572 fn test_sum() -> Result<(), CvsSqlError> {
573 test_agg(&Sum {})
574 }
575
576 #[test]
577 fn test_avg() -> Result<(), CvsSqlError> {
578 test_agg(&Avg {})
579 }
580
581 #[test]
582 fn test_min() -> Result<(), CvsSqlError> {
583 test_agg(&Min {})
584 }
585
586 #[test]
587 fn test_max() -> Result<(), CvsSqlError> {
588 test_agg(&Max {})
589 }
590
591 #[test]
592 fn test_any_value() -> Result<(), CvsSqlError> {
593 test_agg(&AnyValue {})
594 }
595}
596
597#[cfg(test)]
598struct FunctionExample<'a> {
599 name: &'a str,
600 arguments: Vec<&'a str>,
601 expected_results: &'a str,
602}
603
604trait Operator {
605 fn name(&self) -> &str;
606 fn min_args(&self) -> usize;
607 fn max_args(&self) -> Option<usize>;
608 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value>;
609 #[cfg(test)]
610 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
611 vec![]
612 }
613}
614struct SimpleFunction {
615 arguments: Vec<Box<dyn Projection>>,
616 operator: Box<dyn Operator>,
617 name: String,
618}
619impl Projection for SimpleFunction {
620 fn get<'a>(&'a self, row: &'a GroupRow) -> SmartReference<'a, Value> {
621 let mut args = vec![];
622 for a in &self.arguments {
623 args.push(a.get(row));
624 }
625 self.operator.get(&args)
626 }
627 fn name(&self) -> &str {
628 &self.name
629 }
630}
631
632fn build_function(
633 metadata: &Metadata,
634 engine: &Engine,
635 args: &FunctionArguments,
636 operator: Box<dyn Operator>,
637) -> Result<Box<dyn Projection>, CvsSqlError> {
638 let arguments = match &args {
639 FunctionArguments::List(lst) => {
640 if matches!(lst.duplicate_treatment, Some(DuplicateTreatment::Distinct)) {
641 return Err(CvsSqlError::Unsupported(format!(
642 "Function {} with distinct argument",
643 operator.name()
644 )));
645 }
646 if let Some(c) = lst.clauses.first() {
647 return Err(CvsSqlError::Unsupported(format!("{c}")));
648 }
649 let mut args = vec![];
650 for a in &lst.args {
651 let a = match a {
652 FunctionArg::Unnamed(FunctionArgExpr::Expr(e)) => {
653 e.convert_single(metadata, engine)?
654 }
655 _ => {
656 return Err(CvsSqlError::Unsupported(format!(
657 "{} as argument in function {}",
658 a,
659 operator.name()
660 )));
661 }
662 };
663 args.push(a);
664 }
665 args
666 }
667 FunctionArguments::Subquery(_) => {
668 return Err(CvsSqlError::Unsupported(
669 "function subquery arguments".into(),
670 ));
671 }
672 FunctionArguments::None => vec![],
673 };
674 if arguments.len() < operator.min_args() {
675 return Err(CvsSqlError::Unsupported(format!(
676 "Function {} with {} arguments or less",
677 operator.name(),
678 arguments.len()
679 )));
680 }
681 if let Some(max) = operator.max_args()
682 && arguments.len() > max
683 {
684 return Err(CvsSqlError::Unsupported(format!(
685 "Function {} with {} arguments or more",
686 operator.name(),
687 arguments.len()
688 )));
689 }
690 let name = format!(
691 "{}({})",
692 operator.name(),
693 arguments.iter().map(|f| f.name()).join(", ")
694 );
695
696 Ok(Box::new(SimpleFunction {
697 arguments,
698 operator,
699 name,
700 }))
701}
702impl From<Option<BigDecimal>> for SmartReference<'_, Value> {
703 fn from(val: Option<BigDecimal>) -> Self {
704 match val {
705 None => Value::Empty,
706 Some(num) => Value::Number(num),
707 }
708 .into()
709 }
710}
711
712impl From<Option<u32>> for SmartReference<'_, Value> {
713 fn from(val: Option<u32>) -> Self {
714 match val {
715 None => Value::Empty,
716 Some(num) => Value::Number(num.into()),
717 }
718 .into()
719 }
720}
721impl From<f64> for SmartReference<'_, Value> {
722 fn from(val: f64) -> Self {
723 BigDecimal::from_f64(val).into()
724 }
725}
726
727impl From<Option<usize>> for SmartReference<'_, Value> {
728 fn from(val: Option<usize>) -> Self {
729 match val {
730 None => Value::Empty,
731 Some(num) => match BigDecimal::from_usize(num) {
732 Some(num) => Value::Number(num),
733 None => Value::Empty,
734 },
735 }
736 .into()
737 }
738}
739impl From<usize> for SmartReference<'_, Value> {
740 fn from(val: usize) -> Self {
741 match BigDecimal::from_usize(val) {
742 Some(num) => Value::Number(num),
743 None => Value::Empty,
744 }
745 .into()
746 }
747}
748
749impl From<Option<String>> for SmartReference<'_, Value> {
750 fn from(val: Option<String>) -> Self {
751 match val {
752 None => Value::Empty,
753 Some(str) => Value::Str(str),
754 }
755 .into()
756 }
757}
758impl From<Option<&str>> for SmartReference<'_, Value> {
759 fn from(val: Option<&str>) -> Self {
760 match val {
761 None => Value::Empty,
762 Some(str) => Value::Str(str.to_string()),
763 }
764 .into()
765 }
766}
767
768trait Extractor {
769 fn as_num(&self) -> Option<&BigDecimal>;
770 fn as_string(&self) -> Option<&str>;
771 fn as_bool(&self) -> Option<&bool>;
772 fn as_u32(&self) -> Option<u32> {
773 self.as_num().and_then(|s| s.to_u32())
774 }
775 fn as_i64(&self) -> Option<i64> {
776 self.as_num().and_then(|s| s.to_i64())
777 }
778 fn as_usize(&self) -> Option<usize> {
779 self.as_num().and_then(|s| s.to_usize())
780 }
781 fn as_f64(&self) -> Option<f64> {
782 self.as_num().and_then(|s| s.to_f64())
783 }
784}
785impl Extractor for Value {
786 fn as_num(&self) -> Option<&BigDecimal> {
787 match self {
788 Value::Number(num) => Some(num),
789 _ => None,
790 }
791 }
792 fn as_string(&self) -> Option<&str> {
793 match self {
794 Value::Str(str) => Some(str),
795 _ => None,
796 }
797 }
798 fn as_bool(&self) -> Option<&bool> {
799 match self {
800 Value::Bool(b) => Some(b),
801 _ => None,
802 }
803 }
804}
805impl<T: Extractor> Extractor for SmartReference<'_, T> {
806 fn as_num(&self) -> Option<&BigDecimal> {
807 self.deref().as_num()
808 }
809 fn as_string(&self) -> Option<&str> {
810 self.deref().as_string()
811 }
812 fn as_bool(&self) -> Option<&bool> {
813 self.deref().as_bool()
814 }
815}
816impl<T: Extractor> Extractor for Option<&T> {
817 fn as_num(&self) -> Option<&BigDecimal> {
818 self.and_then(|t| t.as_num())
819 }
820 fn as_string(&self) -> Option<&str> {
821 self.and_then(|s| s.as_string())
822 }
823 fn as_bool(&self) -> Option<&bool> {
824 self.and_then(|s| s.as_bool())
825 }
826}
827
828struct Abs {}
829impl Operator for Abs {
830 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
831 args.first().as_num().map(|t| t.abs()).into()
832 }
833 fn max_args(&self) -> Option<usize> {
834 Some(1)
835 }
836 fn min_args(&self) -> usize {
837 1
838 }
839 fn name(&self) -> &str {
840 "ABS"
841 }
842
843 #[cfg(test)]
844 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
845 vec![
846 FunctionExample {
847 name: "positive_number",
848 arguments: vec!["11.44"],
849 expected_results: "11.44",
850 },
851 FunctionExample {
852 name: "negative_number",
853 arguments: vec!["-0.44"],
854 expected_results: "0.44",
855 },
856 FunctionExample {
857 name: "nan",
858 arguments: vec!["test"],
859 expected_results: "",
860 },
861 ]
862 }
863}
864
865struct Ascii {}
866impl Operator for Ascii {
867 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
868 args.first()
869 .as_string()
870 .and_then(|s| s.chars().next())
871 .map(|i| i as u32)
872 .into()
873 }
874 fn max_args(&self) -> Option<usize> {
875 Some(1)
876 }
877 fn min_args(&self) -> usize {
878 1
879 }
880 fn name(&self) -> &str {
881 "ASCII"
882 }
883
884 #[cfg(test)]
885 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
886 vec![
887 FunctionExample {
888 name: "simple",
889 arguments: vec!["a"],
890 expected_results: "97",
891 },
892 FunctionExample {
893 name: "word",
894 arguments: vec!["abc"],
895 expected_results: "97",
896 },
897 FunctionExample {
898 name: "number",
899 arguments: vec!["100"],
900 expected_results: "",
901 },
902 ]
903 }
904}
905
906struct Chr {}
907impl Operator for Chr {
908 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
909 args.first()
910 .as_u32()
911 .and_then(char::from_u32)
912 .map(|c| c.to_string())
913 .into()
914 }
915 fn max_args(&self) -> Option<usize> {
916 Some(1)
917 }
918 fn min_args(&self) -> usize {
919 1
920 }
921 fn name(&self) -> &str {
922 "CHR"
923 }
924
925 #[cfg(test)]
926 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
927 vec![
928 FunctionExample {
929 name: "simple",
930 arguments: vec!["97"],
931 expected_results: "a",
932 },
933 FunctionExample {
934 name: "neg",
935 arguments: vec!["-100"],
936 expected_results: "",
937 },
938 FunctionExample {
939 name: "float",
940 arguments: vec!["97.1"],
941 expected_results: "a",
942 },
943 FunctionExample {
944 name: "str",
945 arguments: vec!["abc"],
946 expected_results: "",
947 },
948 ]
949 }
950}
951
952struct Length {}
953impl Operator for Length {
954 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
955 args.first().as_string().map(|s| s.len()).into()
956 }
957 fn max_args(&self) -> Option<usize> {
958 Some(1)
959 }
960 fn min_args(&self) -> usize {
961 1
962 }
963 fn name(&self) -> &str {
964 "LENGTH"
965 }
966
967 #[cfg(test)]
968 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
969 vec![
970 FunctionExample {
971 name: "simple",
972 arguments: vec!["hello"],
973 expected_results: "5",
974 },
975 FunctionExample {
976 name: "number",
977 arguments: vec!["-100"],
978 expected_results: "",
979 },
980 ]
981 }
982}
983
984struct Coalece {}
985impl Operator for Coalece {
986 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
987 for a in args.iter() {
988 if !a.is_empty() {
989 return a.deref().clone().into();
990 }
991 }
992 Value::Empty.into()
993 }
994 fn max_args(&self) -> Option<usize> {
995 None
996 }
997 fn min_args(&self) -> usize {
998 0
999 }
1000 fn name(&self) -> &str {
1001 "COALESCE"
1002 }
1003
1004 #[cfg(test)]
1005 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1006 vec![
1007 FunctionExample {
1008 name: "simple",
1009 arguments: vec!["", "", "5", "6"],
1010 expected_results: "5",
1011 },
1012 FunctionExample {
1013 name: "nope",
1014 arguments: vec!["", "", "", "", ""],
1015 expected_results: "",
1016 },
1017 FunctionExample {
1018 name: "first",
1019 arguments: vec!["a", "b"],
1020 expected_results: "a",
1021 },
1022 FunctionExample {
1023 name: "empty",
1024 arguments: vec![],
1025 expected_results: "",
1026 },
1027 ]
1028 }
1029}
1030
1031struct Concat {}
1032impl Operator for Concat {
1033 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1034 let str = args.iter().map(|f| f.to_string()).join("");
1035 Value::Str(str).into()
1036 }
1037 fn max_args(&self) -> Option<usize> {
1038 None
1039 }
1040 fn min_args(&self) -> usize {
1041 0
1042 }
1043 fn name(&self) -> &str {
1044 "CONCAT"
1045 }
1046
1047 #[cfg(test)]
1048 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1049 vec![
1050 FunctionExample {
1051 name: "simple",
1052 arguments: vec!["a", "b", "cd", "e"],
1053 expected_results: "abcde",
1054 },
1055 FunctionExample {
1056 name: "with_nums",
1057 arguments: vec!["a", "1", "b"],
1058 expected_results: "a1b",
1059 },
1060 ]
1061 }
1062}
1063
1064struct ConcatWs {}
1065impl Operator for ConcatWs {
1066 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1067 let Some(sep) = args.first() else {
1068 return Value::Empty.into();
1069 };
1070 let sep = sep.to_string();
1071 let str = args
1072 .iter()
1073 .skip(1)
1074 .filter(|f| !f.is_empty())
1075 .map(|f| f.to_string())
1076 .join(sep.as_str());
1077 Value::Str(str).into()
1078 }
1079 fn max_args(&self) -> Option<usize> {
1080 None
1081 }
1082 fn min_args(&self) -> usize {
1083 1
1084 }
1085 fn name(&self) -> &str {
1086 "CONCAT_WS"
1087 }
1088
1089 #[cfg(test)]
1090 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1091 vec![FunctionExample {
1092 name: "simple",
1093 arguments: vec!["|", "a", "b", "cd", "e"],
1094 expected_results: "a|b|cd|e",
1095 }]
1096 }
1097}
1098
1099struct CurrentDate {}
1100impl Operator for CurrentDate {
1101 fn get<'a>(&'a self, _: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1102 Value::Date(Utc::now().naive_utc().date()).into()
1103 }
1104 fn max_args(&self) -> Option<usize> {
1105 Some(0)
1106 }
1107 fn min_args(&self) -> usize {
1108 0
1109 }
1110 fn name(&self) -> &str {
1111 "CURRENT_DATE"
1112 }
1113}
1114struct Now {}
1115impl Operator for Now {
1116 fn get<'a>(&'a self, _: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1117 Value::Timestamp(Utc::now().naive_utc()).into()
1118 }
1119 fn max_args(&self) -> Option<usize> {
1120 Some(0)
1121 }
1122 fn min_args(&self) -> usize {
1123 0
1124 }
1125 fn name(&self) -> &str {
1126 "NOW"
1127 }
1128}
1129struct User {}
1130impl Operator for User {
1131 fn get<'a>(&'a self, _: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1132 Value::Str(whoami::username()).into()
1133 }
1134 fn max_args(&self) -> Option<usize> {
1135 Some(0)
1136 }
1137 fn min_args(&self) -> usize {
1138 0
1139 }
1140 fn name(&self) -> &str {
1141 "CURRENT_USER"
1142 }
1143}
1144
1145struct Format {}
1146impl Operator for Format {
1147 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1148 let Some(value) = args.first() else {
1149 return Value::Empty.into();
1150 };
1151 let format = args.get(1);
1152 let Some(format) = format.as_string() else {
1153 return Value::Empty.into();
1154 };
1155 let formatted = match value.deref() {
1156 Value::Date(date) => date.format(format),
1157 Value::Timestamp(ts) => ts.format(format),
1158 _ => {
1159 return Value::Empty.into();
1160 }
1161 };
1162 let mut text = String::new();
1163 if formatted.write_to(&mut text).is_err() {
1164 return Value::Empty.into();
1165 }
1166
1167 Value::Str(text).into()
1168 }
1169 fn max_args(&self) -> Option<usize> {
1170 Some(2)
1171 }
1172 fn min_args(&self) -> usize {
1173 2
1174 }
1175 fn name(&self) -> &str {
1176 "FORMAT"
1177 }
1178
1179 #[cfg(test)]
1180 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1181 vec![
1182 FunctionExample {
1183 name: "simple_date",
1184 arguments: vec!["2024-11-23", "%d/%m/%Y"],
1185 expected_results: "23/11/2024",
1186 },
1187 FunctionExample {
1188 name: "simple_timestamp",
1189 arguments: vec!["2024-11-23 16:20:21.003", "%v %r"],
1190 expected_results: "23-Nov-2024 04:20:21 PM",
1191 },
1192 FunctionExample {
1193 name: "format_as_number",
1194 arguments: vec!["2024-11-23 16:20:21.003", "123"],
1195 expected_results: "",
1196 },
1197 FunctionExample {
1198 name: "invalid_format",
1199 arguments: vec!["2024-11-23 16:20:21.003", "%Q"],
1200 expected_results: "",
1201 },
1202 FunctionExample {
1203 name: "numeric_value",
1204 arguments: vec!["3", "%v %r"],
1205 expected_results: "",
1206 },
1207 ]
1208 }
1209}
1210
1211struct ToTimestamp {}
1212impl Operator for ToTimestamp {
1213 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1214 let Some(time) = args.first().as_i64() else {
1215 return Value::Empty.into();
1216 };
1217
1218 let LocalResult::Single(time) = Utc.timestamp_opt(time, 0) else {
1219 return Value::Empty.into();
1220 };
1221
1222 Value::Timestamp(time.naive_utc()).into()
1223 }
1224 fn max_args(&self) -> Option<usize> {
1225 Some(1)
1226 }
1227 fn min_args(&self) -> usize {
1228 1
1229 }
1230 fn name(&self) -> &str {
1231 "TO_TIMESTAMP"
1232 }
1233
1234 #[cfg(test)]
1235 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1236 vec![
1237 FunctionExample {
1238 name: "should_work",
1239 arguments: vec!["1400234525"],
1240 expected_results: "2014-05-16 10:02:05",
1241 },
1242 FunctionExample {
1243 name: "nan",
1244 arguments: vec!["test"],
1245 expected_results: "",
1246 },
1247 ]
1248 }
1249}
1250
1251struct Greatest {}
1252impl Operator for Greatest {
1253 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1254 let mut greatest = None;
1255 for a in args.iter() {
1256 match &greatest {
1257 None => greatest = Some(a.deref().clone()),
1258 Some(val) => {
1259 if a.deref() > val {
1260 greatest = Some(a.deref().clone());
1261 }
1262 }
1263 }
1264 }
1265 match greatest {
1266 None => Value::Empty.into(),
1267 Some(greatest) => greatest.into(),
1268 }
1269 }
1270 fn max_args(&self) -> Option<usize> {
1271 None
1272 }
1273 fn min_args(&self) -> usize {
1274 0
1275 }
1276 fn name(&self) -> &str {
1277 "GREATEST"
1278 }
1279
1280 #[cfg(test)]
1281 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1282 vec![
1283 FunctionExample {
1284 name: "greatest",
1285 arguments: vec!["10", "400040", "1044", "-134522352"],
1286 expected_results: "400040",
1287 },
1288 FunctionExample {
1289 name: "empty",
1290 arguments: vec![],
1291 expected_results: "",
1292 },
1293 ]
1294 }
1295}
1296struct If {}
1297impl Operator for If {
1298 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1299 let first = args.first();
1300 let Some(condition) = first.as_bool() else {
1301 return Value::Empty.into();
1302 };
1303 let value = if *condition { args.get(1) } else { args.get(2) };
1304 match value {
1305 Some(v) => v.deref().clone().into(),
1306 None => Value::Empty.into(),
1307 }
1308 }
1309 fn max_args(&self) -> Option<usize> {
1310 Some(3)
1311 }
1312 fn min_args(&self) -> usize {
1313 3
1314 }
1315 fn name(&self) -> &str {
1316 "IF"
1317 }
1318
1319 #[cfg(test)]
1320 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1321 vec![
1322 FunctionExample {
1323 name: "true",
1324 arguments: vec!["TRUE", "100", "-100"],
1325 expected_results: "100",
1326 },
1327 FunctionExample {
1328 name: "false",
1329 arguments: vec!["FALSE", "100", "-100"],
1330 expected_results: "-100",
1331 },
1332 FunctionExample {
1333 name: "not_bool",
1334 arguments: vec!["test", "100", "-100"],
1335 expected_results: "",
1336 },
1337 ]
1338 }
1339}
1340
1341struct NullIf {}
1342impl Operator for NullIf {
1343 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1344 let Some(value_one) = args.first() else {
1345 return Value::Empty.into();
1346 };
1347 let Some(value_two) = args.get(1) else {
1348 return Value::Empty.into();
1349 };
1350 if *value_one != *value_two {
1351 value_one.deref().clone().into()
1352 } else {
1353 Value::Empty.into()
1354 }
1355 }
1356 fn max_args(&self) -> Option<usize> {
1357 Some(2)
1358 }
1359 fn min_args(&self) -> usize {
1360 2
1361 }
1362 fn name(&self) -> &str {
1363 "NULLIF"
1364 }
1365
1366 #[cfg(test)]
1367 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1368 vec![
1369 FunctionExample {
1370 name: "eq",
1371 arguments: vec!["hello", "hello"],
1372 expected_results: "",
1373 },
1374 FunctionExample {
1375 name: "neq",
1376 arguments: vec!["hello", "world"],
1377 expected_results: "hello",
1378 },
1379 ]
1380 }
1381}
1382
1383struct Lower {}
1384impl Operator for Lower {
1385 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1386 args.first()
1387 .and_then(|f| f.as_string())
1388 .map(|f| f.to_lowercase())
1389 .into()
1390 }
1391 fn max_args(&self) -> Option<usize> {
1392 Some(1)
1393 }
1394 fn min_args(&self) -> usize {
1395 1
1396 }
1397 fn name(&self) -> &str {
1398 "LOWER"
1399 }
1400
1401 #[cfg(test)]
1402 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1403 vec![
1404 FunctionExample {
1405 name: "str",
1406 arguments: vec!["HeLLo"],
1407 expected_results: "hello",
1408 },
1409 FunctionExample {
1410 name: "number",
1411 arguments: vec!["123"],
1412 expected_results: "",
1413 },
1414 ]
1415 }
1416}
1417struct Upper {}
1418impl Operator for Upper {
1419 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1420 args.first()
1421 .and_then(|f| f.as_string())
1422 .map(|f| f.to_uppercase())
1423 .into()
1424 }
1425 fn max_args(&self) -> Option<usize> {
1426 Some(1)
1427 }
1428 fn min_args(&self) -> usize {
1429 1
1430 }
1431 fn name(&self) -> &str {
1432 "UPPER"
1433 }
1434
1435 #[cfg(test)]
1436 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1437 vec![
1438 FunctionExample {
1439 name: "str",
1440 arguments: vec!["HeLLo"],
1441 expected_results: "HELLO",
1442 },
1443 FunctionExample {
1444 name: "number",
1445 arguments: vec!["123"],
1446 expected_results: "",
1447 },
1448 ]
1449 }
1450}
1451
1452struct Least {}
1453impl Operator for Least {
1454 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1455 let mut least = None;
1456 for a in args.iter() {
1457 if !a.is_empty() {
1458 match &least {
1459 None => least = Some(a.deref().clone()),
1460 Some(val) => {
1461 if a.deref() < val {
1462 least = Some(a.deref().clone());
1463 }
1464 }
1465 }
1466 }
1467 }
1468 match least {
1469 None => Value::Empty.into(),
1470 Some(least) => least.into(),
1471 }
1472 }
1473 fn max_args(&self) -> Option<usize> {
1474 None
1475 }
1476 fn min_args(&self) -> usize {
1477 0
1478 }
1479 fn name(&self) -> &str {
1480 "LEAST"
1481 }
1482
1483 #[cfg(test)]
1484 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1485 vec![
1486 FunctionExample {
1487 name: "least",
1488 arguments: vec!["10", "400040", "1044", "-4", "-1"],
1489 expected_results: "-4",
1490 },
1491 FunctionExample {
1492 name: "empty",
1493 arguments: vec![],
1494 expected_results: "",
1495 },
1496 ]
1497 }
1498}
1499
1500struct Left {}
1501impl Operator for Left {
1502 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1503 let text = args.first();
1504 let Some(text) = text.as_string() else {
1505 return Value::Empty.into();
1506 };
1507 let length = args.get(1);
1508 let Some(length) = length.as_usize() else {
1509 return Value::Empty.into();
1510 };
1511 if text.len() < length {
1512 Value::Str(text.to_string()).into()
1513 } else {
1514 Value::Str(text[0..length].to_string()).into()
1515 }
1516 }
1517 fn max_args(&self) -> Option<usize> {
1518 Some(2)
1519 }
1520 fn min_args(&self) -> usize {
1521 2
1522 }
1523 fn name(&self) -> &str {
1524 "LEFT"
1525 }
1526
1527 #[cfg(test)]
1528 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1529 vec![
1530 FunctionExample {
1531 name: "simple",
1532 arguments: vec!["test", "2"],
1533 expected_results: "te",
1534 },
1535 FunctionExample {
1536 name: "exact",
1537 arguments: vec!["test", "4"],
1538 expected_results: "test",
1539 },
1540 FunctionExample {
1541 name: "more",
1542 arguments: vec!["test", "12"],
1543 expected_results: "test",
1544 },
1545 FunctionExample {
1546 name: "nan",
1547 arguments: vec!["test", "five"],
1548 expected_results: "",
1549 },
1550 FunctionExample {
1551 name: "not_a_text",
1552 arguments: vec!["10", "10"],
1553 expected_results: "",
1554 },
1555 ]
1556 }
1557}
1558
1559struct Right {}
1560impl Operator for Right {
1561 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1562 let text = args.first();
1563 let Some(text) = text.as_string() else {
1564 return Value::Empty.into();
1565 };
1566 let length = args.get(1);
1567 let Some(length) = length.as_usize() else {
1568 return Value::Empty.into();
1569 };
1570 if text.len() < length {
1571 Value::Str(text.to_string()).into()
1572 } else {
1573 let start = text.len() - length;
1574 Value::Str(text[start..].to_string()).into()
1575 }
1576 }
1577 fn max_args(&self) -> Option<usize> {
1578 Some(2)
1579 }
1580 fn min_args(&self) -> usize {
1581 2
1582 }
1583 fn name(&self) -> &str {
1584 "RIGHT"
1585 }
1586
1587 #[cfg(test)]
1588 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1589 vec![
1590 FunctionExample {
1591 name: "simple",
1592 arguments: vec!["test", "3"],
1593 expected_results: "est",
1594 },
1595 FunctionExample {
1596 name: "exact",
1597 arguments: vec!["test", "4"],
1598 expected_results: "test",
1599 },
1600 FunctionExample {
1601 name: "more",
1602 arguments: vec!["test", "12"],
1603 expected_results: "test",
1604 },
1605 FunctionExample {
1606 name: "nan",
1607 arguments: vec!["test", "five"],
1608 expected_results: "",
1609 },
1610 FunctionExample {
1611 name: "not_a_text",
1612 arguments: vec!["10", "10"],
1613 expected_results: "",
1614 },
1615 ]
1616 }
1617}
1618
1619struct Lpad {}
1620impl Operator for Lpad {
1621 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1622 let text = args.first();
1623 let Some(text) = text.as_string() else {
1624 return Value::Empty.into();
1625 };
1626 let length = args.get(1);
1627 let Some(length) = length.as_usize() else {
1628 return Value::Empty.into();
1629 };
1630 let pad = args.get(2);
1631
1632 let Some(pad) = pad.as_string() else {
1633 return Value::Empty.into();
1634 };
1635
1636 if text.len() > length {
1637 Value::Str(text[0..length].to_string()).into()
1638 } else if pad.is_empty() {
1639 Value::Str(text.to_string()).into()
1640 } else {
1641 let mut str = String::new();
1642 let mut chars = pad.chars().cycle();
1643 for _ in 0..length - text.len() {
1644 let chr = chars.next().unwrap();
1645 str.push(chr);
1646 }
1647 str.push_str(text);
1648 Value::Str(str).into()
1649 }
1650 }
1651
1652 fn max_args(&self) -> Option<usize> {
1653 Some(3)
1654 }
1655 fn min_args(&self) -> usize {
1656 3
1657 }
1658 fn name(&self) -> &str {
1659 "LPAD"
1660 }
1661
1662 #[cfg(test)]
1663 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1664 vec![
1665 FunctionExample {
1666 name: "simple",
1667 arguments: vec!["text", "10", "pad"],
1668 expected_results: "padpadtext",
1669 },
1670 FunctionExample {
1671 name: "more",
1672 arguments: vec!["text", "12", "pad"],
1673 expected_results: "padpadpatext",
1674 },
1675 FunctionExample {
1676 name: "less",
1677 arguments: vec!["text", "3", "pad"],
1678 expected_results: "tex",
1679 },
1680 FunctionExample {
1681 name: "exact",
1682 arguments: vec!["text", "4", "pad"],
1683 expected_results: "text",
1684 },
1685 FunctionExample {
1686 name: "negative",
1687 arguments: vec!["text", "-122", "pad"],
1688 expected_results: "",
1689 },
1690 FunctionExample {
1691 name: "non_text",
1692 arguments: vec!["12", "10", "pad"],
1693 expected_results: "",
1694 },
1695 FunctionExample {
1696 name: "non_number",
1697 arguments: vec!["text", "me", "pad"],
1698 expected_results: "",
1699 },
1700 FunctionExample {
1701 name: "not_pad",
1702 arguments: vec!["text", "10", "2"],
1703 expected_results: "",
1704 },
1705 FunctionExample {
1706 name: "empty_pad",
1707 arguments: vec!["text", "10", "2"],
1708 expected_results: "",
1709 },
1710 ]
1711 }
1712}
1713
1714struct Rpad {}
1715impl Operator for Rpad {
1716 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1717 let text = args.first();
1718 let Some(text) = text.as_string() else {
1719 return Value::Empty.into();
1720 };
1721 let length = args.get(1);
1722 let Some(length) = length.as_usize() else {
1723 return Value::Empty.into();
1724 };
1725 let pad = args.get(2);
1726
1727 let Some(pad) = pad.as_string() else {
1728 return Value::Empty.into();
1729 };
1730
1731 if text.len() > length {
1732 Value::Str(text[0..length].to_string()).into()
1733 } else if pad.is_empty() {
1734 Value::Str(text.to_string()).into()
1735 } else {
1736 let mut str = text.to_string();
1737 let mut chars = pad.chars().cycle();
1738 for _ in 0..length - text.len() {
1739 let chr = chars.next().unwrap();
1740 str.push(chr);
1741 }
1742 Value::Str(str).into()
1743 }
1744 }
1745
1746 fn max_args(&self) -> Option<usize> {
1747 Some(3)
1748 }
1749 fn min_args(&self) -> usize {
1750 3
1751 }
1752 fn name(&self) -> &str {
1753 "RPAD"
1754 }
1755
1756 #[cfg(test)]
1757 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1758 vec![
1759 FunctionExample {
1760 name: "simple",
1761 arguments: vec!["text", "10", "pad"],
1762 expected_results: "textpadpad",
1763 },
1764 FunctionExample {
1765 name: "more",
1766 arguments: vec!["text", "12", "pad"],
1767 expected_results: "textpadpadpa",
1768 },
1769 FunctionExample {
1770 name: "less",
1771 arguments: vec!["text", "3", "pad"],
1772 expected_results: "tex",
1773 },
1774 FunctionExample {
1775 name: "exact",
1776 arguments: vec!["text", "4", "pad"],
1777 expected_results: "text",
1778 },
1779 FunctionExample {
1780 name: "negative",
1781 arguments: vec!["text", "-122", "pad"],
1782 expected_results: "",
1783 },
1784 FunctionExample {
1785 name: "non_text",
1786 arguments: vec!["12", "10", "pad"],
1787 expected_results: "",
1788 },
1789 FunctionExample {
1790 name: "non_number",
1791 arguments: vec!["text", "me", "pad"],
1792 expected_results: "",
1793 },
1794 FunctionExample {
1795 name: "not_pad",
1796 arguments: vec!["text", "10", "2"],
1797 expected_results: "",
1798 },
1799 FunctionExample {
1800 name: "empty_pad",
1801 arguments: vec!["text", "10", "2"],
1802 expected_results: "",
1803 },
1804 ]
1805 }
1806}
1807
1808struct Ltrim {}
1809impl Operator for Ltrim {
1810 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1811 args.first()
1812 .and_then(|f| f.as_string())
1813 .map(|f| f.trim_start())
1814 .into()
1815 }
1816
1817 fn max_args(&self) -> Option<usize> {
1818 Some(1)
1819 }
1820 fn min_args(&self) -> usize {
1821 1
1822 }
1823 fn name(&self) -> &str {
1824 "LTRIM"
1825 }
1826
1827 #[cfg(test)]
1828 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1829 vec![
1830 FunctionExample {
1831 name: "simple",
1832 arguments: vec![" hello"],
1833 expected_results: "hello",
1834 },
1835 FunctionExample {
1836 name: "not_text",
1837 arguments: vec!["12"],
1838 expected_results: "",
1839 },
1840 ]
1841 }
1842}
1843struct Rtrim {}
1844impl Operator for Rtrim {
1845 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1846 args.first()
1847 .and_then(|f| f.as_string())
1848 .map(|f| f.trim_end())
1849 .into()
1850 }
1851
1852 fn max_args(&self) -> Option<usize> {
1853 Some(1)
1854 }
1855 fn min_args(&self) -> usize {
1856 1
1857 }
1858 fn name(&self) -> &str {
1859 "RTRIM"
1860 }
1861
1862 #[cfg(test)]
1863 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1864 vec![
1865 FunctionExample {
1866 name: "simple",
1867 arguments: vec!["hello\t"],
1868 expected_results: "hello",
1869 },
1870 FunctionExample {
1871 name: "not_text",
1872 arguments: vec!["12"],
1873 expected_results: "",
1874 },
1875 ]
1876 }
1877}
1878
1879struct Position {}
1880impl Operator for Position {
1881 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1882 let sub = args.first();
1883 let Some(sub) = sub.as_string() else {
1884 return Value::Empty.into();
1885 };
1886 let str = args.get(1);
1887 let Some(str) = str.as_string() else {
1888 return Value::Empty.into();
1889 };
1890 let start = match args.get(2) {
1891 None => 0,
1892 Some(val) => {
1893 let Some(mut start) = val.as_usize() else {
1894 return Value::Empty.into();
1895 };
1896 if start == 0 {
1897 start = 1;
1898 }
1899 if start > str.len() {
1900 return 0.into();
1901 }
1902 start - 1
1903 }
1904 };
1905 let position = str[start..].find(sub).map(|f| f + 1).unwrap_or_default();
1906 (position + start).into()
1907 }
1908
1909 fn max_args(&self) -> Option<usize> {
1910 Some(3)
1911 }
1912 fn min_args(&self) -> usize {
1913 2
1914 }
1915 fn name(&self) -> &str {
1916 "POSITION"
1917 }
1918
1919 #[cfg(test)]
1920 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1921 vec![
1922 FunctionExample {
1923 name: "simple",
1924 arguments: vec!["bar", "foobarbar"],
1925 expected_results: "4",
1926 },
1927 FunctionExample {
1928 name: "nop",
1929 arguments: vec!["xbar", "foobarbar"],
1930 expected_results: "0",
1931 },
1932 FunctionExample {
1933 name: "with_start",
1934 arguments: vec!["bar", "foobarbar", "5"],
1935 expected_results: "7",
1936 },
1937 FunctionExample {
1938 name: "not_a_sub",
1939 arguments: vec!["5", "foobarbar", "5"],
1940 expected_results: "",
1941 },
1942 FunctionExample {
1943 name: "with_str_as_num",
1944 arguments: vec!["bar", "20", "5"],
1945 expected_results: "",
1946 },
1947 FunctionExample {
1948 name: "with_start_as_str",
1949 arguments: vec!["bar", "foobarbar", "a"],
1950 expected_results: "",
1951 },
1952 FunctionExample {
1953 name: "with_start_larger",
1954 arguments: vec!["bar", "foobarbar", "25"],
1955 expected_results: "0",
1956 },
1957 ]
1958 }
1959}
1960
1961struct Repeat {}
1962impl Operator for Repeat {
1963 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
1964 let str = args.first();
1965 let Some(str) = str.as_string() else {
1966 return Value::Empty.into();
1967 };
1968 let count = args.get(1);
1969 let Some(count) = count.as_usize() else {
1970 return Value::Empty.into();
1971 };
1972 Value::Str(str.repeat(count)).into()
1973 }
1974
1975 fn max_args(&self) -> Option<usize> {
1976 Some(2)
1977 }
1978 fn min_args(&self) -> usize {
1979 2
1980 }
1981 fn name(&self) -> &str {
1982 "REPEAT"
1983 }
1984
1985 #[cfg(test)]
1986 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
1987 vec![
1988 FunctionExample {
1989 name: "simple",
1990 arguments: vec!["bar", "3"],
1991 expected_results: "barbarbar",
1992 },
1993 FunctionExample {
1994 name: "not_a_string",
1995 arguments: vec!["4", "3"],
1996 expected_results: "",
1997 },
1998 FunctionExample {
1999 name: "not_a_number",
2000 arguments: vec!["bar", "test"],
2001 expected_results: "",
2002 },
2003 ]
2004 }
2005}
2006
2007struct Replace {}
2008impl Operator for Replace {
2009 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2010 let str = args.first();
2011 let Some(str) = str.as_string() else {
2012 return Value::Empty.into();
2013 };
2014 let what = args.get(1);
2015 let Some(what) = what.as_string() else {
2016 return Value::Empty.into();
2017 };
2018 let into = args.get(2);
2019 let Some(into) = into.as_string() else {
2020 return Value::Empty.into();
2021 };
2022 Value::Str(str.replace(what, into)).into()
2023 }
2024
2025 fn max_args(&self) -> Option<usize> {
2026 Some(3)
2027 }
2028 fn min_args(&self) -> usize {
2029 3
2030 }
2031 fn name(&self) -> &str {
2032 "REPLACE"
2033 }
2034
2035 #[cfg(test)]
2036 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2037 vec![
2038 FunctionExample {
2039 name: "simple",
2040 arguments: vec!["hello", "l", "L"],
2041 expected_results: "heLLo",
2042 },
2043 FunctionExample {
2044 name: "nope",
2045 arguments: vec!["test", "bar", "foo"],
2046 expected_results: "test",
2047 },
2048 FunctionExample {
2049 name: "not_a_string",
2050 arguments: vec!["1", "test", "one"],
2051 expected_results: "",
2052 },
2053 FunctionExample {
2054 name: "not_a_what",
2055 arguments: vec!["bar", "2", "one"],
2056 expected_results: "",
2057 },
2058 FunctionExample {
2059 name: "not_a_with",
2060 arguments: vec!["bar", "test", "3"],
2061 expected_results: "",
2062 },
2063 ]
2064 }
2065}
2066
2067struct RegexReplace {}
2068impl Operator for RegexReplace {
2069 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2070 let str = args.first();
2071 let Some(str) = str.as_string() else {
2072 return Value::Empty.into();
2073 };
2074 let pattern = args.get(1);
2075 let Some(pattern) = pattern.as_string() else {
2076 return Value::Empty.into();
2077 };
2078 let Ok(pattern) = Regex::new(pattern) else {
2079 return Value::Empty.into();
2080 };
2081 let repl = args.get(2);
2082 let Some(repl) = repl.as_string() else {
2083 return Value::Empty.into();
2084 };
2085 Value::Str(pattern.replace(str, repl).to_string()).into()
2086 }
2087
2088 fn max_args(&self) -> Option<usize> {
2089 Some(3)
2090 }
2091 fn min_args(&self) -> usize {
2092 3
2093 }
2094 fn name(&self) -> &str {
2095 "REGEX_REPLACE"
2096 }
2097
2098 #[cfg(test)]
2099 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2100 vec![
2101 FunctionExample {
2102 name: "simple",
2103 arguments: vec!["a b c", "b", "B"],
2104 expected_results: "a B c",
2105 },
2106 FunctionExample {
2107 name: "few",
2108 arguments: vec!["test", "[a-z]", "T"],
2109 expected_results: "Test",
2110 },
2111 FunctionExample {
2112 name: "not_a_string",
2113 arguments: vec!["1", "b", "B"],
2114 expected_results: "",
2115 },
2116 FunctionExample {
2117 name: "not_a_string_pattern",
2118 arguments: vec!["abc", "1", "B"],
2119 expected_results: "",
2120 },
2121 FunctionExample {
2122 name: "invalid_pattern",
2123 arguments: vec!["abc", "[+", "B"],
2124 expected_results: "",
2125 },
2126 FunctionExample {
2127 name: "no_replacement",
2128 arguments: vec!["abc", "b", "4"],
2129 expected_results: "",
2130 },
2131 ]
2132 }
2133}
2134
2135struct RegexLike {}
2136impl Operator for RegexLike {
2137 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2138 let expr = args.first();
2139 let Some(expr) = expr.as_string() else {
2140 return Value::Empty.into();
2141 };
2142 let pattern = args.get(1);
2143 let Some(pattern) = pattern.as_string() else {
2144 return Value::Empty.into();
2145 };
2146 let flags = args.get(2);
2147 let pattern = if flags.is_some() {
2148 let Some(flags) = flags.as_string() else {
2149 return Value::Empty.into();
2150 };
2151
2152 Regex::new(format!("(?{flags}:{pattern})").as_str())
2153 } else {
2154 Regex::new(pattern)
2155 };
2156
2157 let Ok(pattern) = pattern else {
2158 return Value::Empty.into();
2159 };
2160
2161 Value::Bool(pattern.find(expr).is_some()).into()
2162 }
2163
2164 fn max_args(&self) -> Option<usize> {
2165 Some(3)
2166 }
2167 fn min_args(&self) -> usize {
2168 2
2169 }
2170 fn name(&self) -> &str {
2171 "REGEX_LIKE"
2172 }
2173
2174 #[cfg(test)]
2175 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2176 vec![
2177 FunctionExample {
2178 name: "simple_true",
2179 arguments: vec!["test", "es"],
2180 expected_results: "TRUE",
2181 },
2182 FunctionExample {
2183 name: "simple_false",
2184 arguments: vec!["test", "ES"],
2185 expected_results: "FALSE",
2186 },
2187 FunctionExample {
2188 name: "no_string_one",
2189 arguments: vec!["1", "op"],
2190 expected_results: "",
2191 },
2192 FunctionExample {
2193 name: "no_string_pattern",
2194 arguments: vec!["test", "FALSE"],
2195 expected_results: "",
2196 },
2197 FunctionExample {
2198 name: "invalid_pattern",
2199 arguments: vec!["test", "[+"],
2200 expected_results: "",
2201 },
2202 FunctionExample {
2203 name: "with_flags",
2204 arguments: vec!["test", "TEST", "i"],
2205 expected_results: "TRUE",
2206 },
2207 FunctionExample {
2208 name: "with_flags",
2209 arguments: vec!["test", "TEST", "i"],
2210 expected_results: "TRUE",
2211 },
2212 FunctionExample {
2213 name: "with_invalid_flags",
2214 arguments: vec!["test", "TEST", "q"],
2215 expected_results: "",
2216 },
2217 FunctionExample {
2218 name: "with_no_string_flags",
2219 arguments: vec!["test", "TEST", "TRUE"],
2220 expected_results: "",
2221 },
2222 ]
2223 }
2224}
2225
2226struct RegexSubstring {}
2227impl Operator for RegexSubstring {
2228 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2229 let expr = args.first();
2230 let Some(expr) = expr.as_string() else {
2231 return Value::Empty.into();
2232 };
2233 let pattern = args.get(1);
2234 let Some(pattern) = pattern.as_string() else {
2235 return Value::Empty.into();
2236 };
2237 let pos = args.get(2);
2238 let pos = match pos {
2239 None => Some(1),
2240 Some(pos) => pos.as_usize(),
2241 };
2242 let Some(pos) = pos else {
2243 return Value::Empty.into();
2244 };
2245 if pos == 0 {
2246 return Value::Empty.into();
2247 }
2248 let pos = pos - 1;
2249 let occurrence = args.get(3);
2250 let occurrence = match occurrence {
2251 None => Some(1),
2252 Some(occurrence) => occurrence.as_usize(),
2253 };
2254 let Some(occurrence) = occurrence else {
2255 return Value::Empty.into();
2256 };
2257 if occurrence == 0 {
2258 return Value::Empty.into();
2259 }
2260 let occurrence = occurrence - 1;
2261
2262 let flags = args.get(4);
2263 let pattern = if flags.is_some() {
2264 let Some(flags) = flags.as_string() else {
2265 return Value::Empty.into();
2266 };
2267
2268 Regex::new(format!("(?{flags}:{pattern})").as_str())
2269 } else {
2270 Regex::new(pattern)
2271 };
2272 if pos > expr.len() {
2273 return Value::Str(String::new()).into();
2274 }
2275
2276 let Ok(pattern) = pattern else {
2277 return Value::Empty.into();
2278 };
2279
2280 let matches = pattern
2281 .find_iter(&expr[pos..])
2282 .nth(occurrence)
2283 .map(|f| f.as_str())
2284 .unwrap_or("");
2285
2286 Value::Str(matches.into()).into()
2287 }
2288
2289 fn max_args(&self) -> Option<usize> {
2290 Some(5)
2291 }
2292 fn min_args(&self) -> usize {
2293 2
2294 }
2295 fn name(&self) -> &str {
2296 "REGEXP_SUBSTR"
2297 }
2298
2299 #[cfg(test)]
2300 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2301 vec![
2302 FunctionExample {
2303 name: "simple_true",
2304 arguments: vec!["abc def ghi", "[a-z]+"],
2305 expected_results: "abc",
2306 },
2307 FunctionExample {
2308 name: "can_not_find",
2309 arguments: vec!["test", "ES"],
2310 expected_results: "\"\"",
2311 },
2312 FunctionExample {
2313 name: "with_pos",
2314 arguments: vec!["abc def ghi", "[a-z]+", "2"],
2315 expected_results: "bc",
2316 },
2317 FunctionExample {
2318 name: "with_pos_and_oc",
2319 arguments: vec!["abc def ghi", "[a-z]+", "2", "2"],
2320 expected_results: "def",
2321 },
2322 FunctionExample {
2323 name: "with_pos_and_oc_to_large",
2324 arguments: vec!["abc def ghi", "[a-z]+", "2", "10"],
2325 expected_results: "\"\"",
2326 },
2327 FunctionExample {
2328 name: "with_flags",
2329 arguments: vec!["abc def ghi", "[A-Z]+", "1", "1", "i"],
2330 expected_results: "abc",
2331 },
2332 FunctionExample {
2333 name: "invalid_str",
2334 arguments: vec!["1", "[A-Z]+", "1", "1", "i"],
2335 expected_results: "",
2336 },
2337 FunctionExample {
2338 name: "no_regex",
2339 arguments: vec!["abc def ghi", "2", "1", "1", "i"],
2340 expected_results: "",
2341 },
2342 FunctionExample {
2343 name: "invalid_regex",
2344 arguments: vec!["abc def ghi", "[A-", "1", "1", "i"],
2345 expected_results: "",
2346 },
2347 FunctionExample {
2348 name: "invalid_pos",
2349 arguments: vec!["abc def ghi", "[A-Z]+", "a", "1", "i"],
2350 expected_results: "",
2351 },
2352 FunctionExample {
2353 name: "post_zero",
2354 arguments: vec!["abc def ghi", "[A-Z]+", "0", "1", "i"],
2355 expected_results: "",
2356 },
2357 FunctionExample {
2358 name: "invalid_oc",
2359 arguments: vec!["abc def ghi", "[A-Z]+", "1", "A", "i"],
2360 expected_results: "",
2361 },
2362 FunctionExample {
2363 name: "zero_oc",
2364 arguments: vec!["abc def ghi", "[A-Z]+", "1", "0", "i"],
2365 expected_results: "",
2366 },
2367 FunctionExample {
2368 name: "invalid_flags",
2369 arguments: vec!["abc def ghi", "[A-Z]+", "1", "0", "2"],
2370 expected_results: "",
2371 },
2372 FunctionExample {
2373 name: "unknown_flags",
2374 arguments: vec!["abc def ghi", "[A-Z]+", "1", "0", "1"],
2375 expected_results: "",
2376 },
2377 ]
2378 }
2379}
2380
2381struct Reverse {}
2382impl Operator for Reverse {
2383 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2384 let str = args.first();
2385 let Some(str) = str.as_string() else {
2386 return Value::Empty.into();
2387 };
2388 Value::Str(str.chars().rev().collect()).into()
2389 }
2390
2391 fn max_args(&self) -> Option<usize> {
2392 Some(1)
2393 }
2394 fn min_args(&self) -> usize {
2395 1
2396 }
2397 fn name(&self) -> &str {
2398 "REVERSE"
2399 }
2400
2401 #[cfg(test)]
2402 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2403 vec![
2404 FunctionExample {
2405 name: "simple",
2406 arguments: vec!["simple"],
2407 expected_results: "elpmis",
2408 },
2409 FunctionExample {
2410 name: "nopre",
2411 arguments: vec!["323"],
2412 expected_results: "",
2413 },
2414 ]
2415 }
2416}
2417struct Round {}
2418impl Operator for Round {
2419 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2420 let num = args.first();
2421 let Some(num) = num.as_num() else {
2422 return Value::Empty.into();
2423 };
2424 let digit = args.get(1);
2425 let digit = if digit.is_some() {
2426 digit.as_i64()
2427 } else {
2428 Some(0)
2429 };
2430 let Some(digit) = digit else {
2431 return Value::Empty.into();
2432 };
2433
2434 Value::Number(num.with_scale_round(digit, bigdecimal::RoundingMode::HalfDown)).into()
2435 }
2436
2437 fn max_args(&self) -> Option<usize> {
2438 Some(2)
2439 }
2440 fn min_args(&self) -> usize {
2441 1
2442 }
2443 fn name(&self) -> &str {
2444 "ROUND"
2445 }
2446
2447 #[cfg(test)]
2448 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2449 vec![
2450 FunctionExample {
2451 name: "simple",
2452 arguments: vec!["-1.23"],
2453 expected_results: "-1",
2454 },
2455 FunctionExample {
2456 name: "larger",
2457 arguments: vec!["43.123"],
2458 expected_results: "43",
2459 },
2460 FunctionExample {
2461 name: "go_up",
2462 arguments: vec!["43.6123"],
2463 expected_results: "44",
2464 },
2465 FunctionExample {
2466 name: "with_arg",
2467 arguments: vec![".1234567890123456789012345678901234567890", "35"],
2468 expected_results: "0.12345678901234567890123456789012346",
2469 },
2470 FunctionExample {
2471 name: "with_negative_arg",
2472 arguments: vec!["23.298", "-1"],
2473 expected_results: "20",
2474 },
2475 FunctionExample {
2476 name: "nan1",
2477 arguments: vec!["test"],
2478 expected_results: "",
2479 },
2480 FunctionExample {
2481 name: "nan2",
2482 arguments: vec!["1", "test"],
2483 expected_results: "",
2484 },
2485 ]
2486 }
2487}
2488struct Sqrt {}
2489impl Operator for Sqrt {
2490 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2491 let num = args.first();
2492 let Some(num) = num.as_num() else {
2493 return Value::Empty.into();
2494 };
2495 match num.sqrt() {
2496 Some(num) => Value::Number(num),
2497 None => Value::Empty,
2498 }
2499 .into()
2500 }
2501
2502 fn max_args(&self) -> Option<usize> {
2503 Some(1)
2504 }
2505 fn min_args(&self) -> usize {
2506 1
2507 }
2508 fn name(&self) -> &str {
2509 "SQRT"
2510 }
2511
2512 #[cfg(test)]
2513 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2514 vec![
2515 FunctionExample {
2516 name: "simple",
2517 arguments: vec!["16"],
2518 expected_results: "4",
2519 },
2520 FunctionExample {
2521 name: "larger",
2522 arguments: vec!["121"],
2523 expected_results: "11",
2524 },
2525 FunctionExample {
2526 name: "neg",
2527 arguments: vec!["-4"],
2528 expected_results: "",
2529 },
2530 FunctionExample {
2531 name: "nan",
2532 arguments: vec!["test"],
2533 expected_results: "",
2534 },
2535 ]
2536 }
2537}
2538
2539struct Pi {}
2540impl Operator for Pi {
2541 fn get<'a>(&'a self, _: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2542 let pi = BigDecimal::from_str("3.1415926535897932384626433832795").unwrap();
2543 Value::Number(pi).into()
2544 }
2545
2546 fn max_args(&self) -> Option<usize> {
2547 Some(0)
2548 }
2549 fn min_args(&self) -> usize {
2550 0
2551 }
2552 fn name(&self) -> &str {
2553 "PI"
2554 }
2555}
2556
2557struct Exp {}
2558impl Operator for Exp {
2559 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2560 let num = args.first();
2561 let Some(num) = num.as_num() else {
2562 return Value::Empty.into();
2563 };
2564
2565 Value::Number(num.exp()).into()
2566 }
2567
2568 fn max_args(&self) -> Option<usize> {
2569 Some(1)
2570 }
2571 fn min_args(&self) -> usize {
2572 1
2573 }
2574 fn name(&self) -> &str {
2575 "EXP"
2576 }
2577}
2578
2579struct Ln {}
2580impl Operator for Ln {
2581 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2582 let num = args.first();
2583 let Some(num) = num.as_f64() else {
2584 return Value::Empty.into();
2585 };
2586 if num <= 0.0 {
2587 return Value::Empty.into();
2588 }
2589
2590 num.ln().into()
2591 }
2592
2593 fn max_args(&self) -> Option<usize> {
2594 Some(1)
2595 }
2596 fn min_args(&self) -> usize {
2597 1
2598 }
2599 fn name(&self) -> &str {
2600 "LN"
2601 }
2602}
2603struct Log {}
2604impl Operator for Log {
2605 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2606 let (base, num) = if args.len() == 2 {
2607 let base = args.first();
2608 let Some(base) = base.as_f64() else {
2609 return Value::Empty.into();
2610 };
2611 let num = args.get(1);
2612 let Some(num) = num.as_f64() else {
2613 return Value::Empty.into();
2614 };
2615 if base <= 0.0 {
2616 return Value::Empty.into();
2617 }
2618 (base, num)
2619 } else {
2620 let num = args.first();
2621 let Some(num) = num.as_f64() else {
2622 return Value::Empty.into();
2623 };
2624 (10.0, num)
2625 };
2626 if num <= 0.0 {
2627 return Value::Empty.into();
2628 }
2629
2630 num.log(base).into()
2631 }
2632
2633 fn max_args(&self) -> Option<usize> {
2634 Some(2)
2635 }
2636 fn min_args(&self) -> usize {
2637 1
2638 }
2639 fn name(&self) -> &str {
2640 "LOG"
2641 }
2642 #[cfg(test)]
2643 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2644 vec![
2645 FunctionExample {
2646 name: "simple",
2647 arguments: vec!["100"],
2648 expected_results: "2",
2649 },
2650 FunctionExample {
2651 name: "zero",
2652 arguments: vec!["0"],
2653 expected_results: "",
2654 },
2655 FunctionExample {
2656 name: "not_a_num",
2657 arguments: vec!["test"],
2658 expected_results: "",
2659 },
2660 FunctionExample {
2661 name: "two_args",
2662 arguments: vec!["2", "8"],
2663 expected_results: "3",
2664 },
2665 FunctionExample {
2666 name: "invalid_base",
2667 arguments: vec!["0", "8"],
2668 expected_results: "",
2669 },
2670 FunctionExample {
2671 name: "no_base",
2672 arguments: vec!["", "8"],
2673 expected_results: "",
2674 },
2675 ]
2676 }
2677}
2678
2679struct Log2 {}
2680impl Operator for Log2 {
2681 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2682 let num = args.first();
2683 let Some(num) = num.as_f64() else {
2684 return Value::Empty.into();
2685 };
2686 if num <= 0.0 {
2687 return Value::Empty.into();
2688 }
2689
2690 num.log2().into()
2691 }
2692
2693 fn max_args(&self) -> Option<usize> {
2694 Some(1)
2695 }
2696 fn min_args(&self) -> usize {
2697 1
2698 }
2699 fn name(&self) -> &str {
2700 "LOG2"
2701 }
2702 #[cfg(test)]
2703 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2704 vec![
2705 FunctionExample {
2706 name: "simple",
2707 arguments: vec!["16"],
2708 expected_results: "4",
2709 },
2710 FunctionExample {
2711 name: "zero",
2712 arguments: vec!["0"],
2713 expected_results: "",
2714 },
2715 FunctionExample {
2716 name: "not_a_num",
2717 arguments: vec!["test"],
2718 expected_results: "",
2719 },
2720 ]
2721 }
2722}
2723struct Log10 {}
2724impl Operator for Log10 {
2725 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2726 let num = args.first();
2727 let Some(num) = num.as_f64() else {
2728 return Value::Empty.into();
2729 };
2730 if num <= 0.0 {
2731 return Value::Empty.into();
2732 }
2733
2734 num.log10().into()
2735 }
2736
2737 fn max_args(&self) -> Option<usize> {
2738 Some(1)
2739 }
2740 fn min_args(&self) -> usize {
2741 1
2742 }
2743 fn name(&self) -> &str {
2744 "LOG10"
2745 }
2746 #[cfg(test)]
2747 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2748 vec![
2749 FunctionExample {
2750 name: "simple",
2751 arguments: vec!["100"],
2752 expected_results: "2",
2753 },
2754 FunctionExample {
2755 name: "zero",
2756 arguments: vec!["0"],
2757 expected_results: "",
2758 },
2759 FunctionExample {
2760 name: "not_a_num",
2761 arguments: vec!["test"],
2762 expected_results: "",
2763 },
2764 ]
2765 }
2766}
2767
2768struct Power {}
2769impl Operator for Power {
2770 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2771 let base = args.first();
2772 let Some(base) = base.as_f64() else {
2773 return Value::Empty.into();
2774 };
2775 let num = args.get(1);
2776 let Some(num) = num.as_f64() else {
2777 return Value::Empty.into();
2778 };
2779 if base <= 0.0 {
2780 return Value::Empty.into();
2781 }
2782
2783 base.powf(num).into()
2784 }
2785
2786 fn max_args(&self) -> Option<usize> {
2787 Some(2)
2788 }
2789 fn min_args(&self) -> usize {
2790 2
2791 }
2792 fn name(&self) -> &str {
2793 "POWER"
2794 }
2795 #[cfg(test)]
2796 fn examples<'a>(&'a self) -> Vec<FunctionExample<'a>> {
2797 vec![
2798 FunctionExample {
2799 name: "simple",
2800 arguments: vec!["2", "3"],
2801 expected_results: "8",
2802 },
2803 FunctionExample {
2804 name: "negative",
2805 arguments: vec!["2", "-2"],
2806 expected_results: "0.25",
2807 },
2808 FunctionExample {
2809 name: "not_a_num_base",
2810 arguments: vec!["a", "2"],
2811 expected_results: "",
2812 },
2813 FunctionExample {
2814 name: "not_a_num_exp",
2815 arguments: vec!["2", "a"],
2816 expected_results: "",
2817 },
2818 ]
2819 }
2820}
2821
2822struct Random {}
2823impl Operator for Random {
2824 fn get<'a>(&'a self, args: &[SmartReference<'a, Value>]) -> SmartReference<'a, Value> {
2825 let rnd: f64 = rand::random();
2826 if args.is_empty() {
2827 rnd.into()
2828 } else {
2829 let Some(max) = args.first().as_usize() else {
2830 return Value::Empty.into();
2831 };
2832 if max == 0 {
2833 Value::Number(BigDecimal::zero()).into()
2834 } else {
2835 (rnd * max as f64).floor().into()
2836 }
2837 }
2838 }
2839
2840 fn max_args(&self) -> Option<usize> {
2841 Some(1)
2842 }
2843 fn min_args(&self) -> usize {
2844 0
2845 }
2846 fn name(&self) -> &str {
2847 "RANDOM"
2848 }
2849}
2850
2851#[cfg(test)]
2852mod tests_functions {
2853 use std::fs::{self, OpenOptions};
2854
2855 use bigdecimal::ToPrimitive;
2856 use chrono::{TimeDelta, Utc};
2857 use itertools::Itertools;
2858 use sqlparser::{
2859 ast::{
2860 Expr, Function, FunctionArgumentList, FunctionArguments, Ident, LimitClause,
2861 NullTreatment, Statement,
2862 },
2863 parser::Parser,
2864 };
2865
2866 use crate::{
2867 args::Args,
2868 dialect::FilesDialect,
2869 engine::Engine,
2870 error::CvsSqlError,
2871 projections::SingleConvert,
2872 result_set_metadata::{Metadata, SimpleResultSetMetadata},
2873 results::Column,
2874 value::Value,
2875 };
2876 use std::io::Write;
2877
2878 use super::{
2879 Abs, Ascii, Chr, Coalece, Concat, ConcatWs, CurrentDate, Exp, Format, Greatest, If, Least,
2880 Left, Length, Ln, Log, Log2, Log10, Lower, Lpad, Ltrim, Now, NullIf, Operator, Pi,
2881 Position, Power, Random, RegexLike, RegexReplace, RegexSubstring, Repeat, Replace, Reverse,
2882 Right, Round, Rpad, Rtrim, Sqrt, ToTimestamp, Upper, User,
2883 };
2884
2885 fn test_func(operator: &impl Operator) -> Result<(), CvsSqlError> {
2886 let dir = format!("./target/function_tests/{}", operator.name().to_lowercase());
2887 println!("testing: {}", operator.name());
2888 fs::remove_dir_all(&dir).ok();
2889 for example in operator.examples() {
2890 test_with_details(operator, example.name, &example.arguments, |r| {
2891 let expected_results = if example.expected_results == "\"\"" {
2892 Value::Str(String::new())
2893 } else {
2894 example.expected_results.into()
2895 };
2896 if r == Some(&expected_results) {
2897 true
2898 } else {
2899 println!(
2900 "Function {} example {}, results: {:?}, expecting: [{}]",
2901 operator.name(),
2902 &example.name,
2903 r,
2904 example.expected_results
2905 );
2906 false
2907 }
2908 })?;
2909 }
2910 fs::remove_dir_all(&dir).ok();
2911
2912 Ok(())
2913 }
2914
2915 fn test_with_details<F>(
2916 operator: &impl Operator,
2917 name: &str,
2918 arguments: &[&str],
2919 verify_results: F,
2920 ) -> Result<(), CvsSqlError>
2921 where
2922 F: FnOnce(Option<&Value>) -> bool,
2923 {
2924 println!("testing: {} with {}", operator.name(), name);
2925 let dir = format!("./target/function_tests/{}", operator.name().to_lowercase());
2926 fs::create_dir_all(&dir)?;
2927 let file = format!("{dir}/{name}.csv");
2928 let mut writer = OpenOptions::new()
2929 .write(true)
2930 .create(true)
2931 .truncate(true)
2932 .open(&file)?;
2933 let header = ('a'..='z')
2934 .take(arguments.len())
2935 .map(|c| format!("{c}"))
2936 .join(",");
2937 writeln!(writer, "{header},name")?;
2938 let line = arguments.join(",");
2939 writeln!(writer, "{line},{name}")?;
2940
2941 let table_name = format!(
2942 "target.function_tests.{}.{}",
2943 operator.name().to_lowercase(),
2944 name
2945 );
2946 let sql = format!(
2947 "SELECT {}({}) FROM {}\n",
2948 operator.name(),
2949 header,
2950 table_name
2951 );
2952
2953 let args = Args::default();
2954 let engine = Engine::try_from(&args)?;
2955
2956 let results = engine.execute_commands(&sql)?;
2957
2958 fs::remove_file(file)?;
2959
2960 let col = Column::from_index(0);
2961 let result = results
2962 .first()
2963 .and_then(|d| d.results.data.iter().next())
2964 .map(|d| d.get(&col));
2965
2966 assert!(verify_results(result));
2967
2968 Ok(())
2969 }
2970
2971 #[test]
2972 fn test_abs() -> Result<(), CvsSqlError> {
2973 test_func(&Abs {})
2974 }
2975
2976 #[test]
2977 fn test_ascii() -> Result<(), CvsSqlError> {
2978 test_func(&Ascii {})
2979 }
2980
2981 #[test]
2982 fn test_chr() -> Result<(), CvsSqlError> {
2983 test_func(&Chr {})
2984 }
2985
2986 #[test]
2987 fn test_length() -> Result<(), CvsSqlError> {
2988 test_func(&Length {})
2989 }
2990
2991 #[test]
2992 fn test_coalece() -> Result<(), CvsSqlError> {
2993 test_func(&Coalece {})
2994 }
2995
2996 #[test]
2997 fn test_concat() -> Result<(), CvsSqlError> {
2998 test_func(&Concat {})
2999 }
3000
3001 #[test]
3002 fn test_concat_ws() -> Result<(), CvsSqlError> {
3003 test_func(&ConcatWs {})
3004 }
3005
3006 #[test]
3007 fn test_current_date() -> Result<(), CvsSqlError> {
3008 test_with_details(&CurrentDate {}, "current_date", &[], |r| match r {
3009 Some(Value::Date(dt)) => {
3010 let now = Utc::now().naive_utc().date();
3011 let to = now.succ_opt().unwrap();
3012 let from = now.pred_opt().unwrap();
3013
3014 *dt >= from && *dt <= to
3015 }
3016 _ => false,
3017 })
3018 }
3019
3020 #[test]
3021 fn test_now() -> Result<(), CvsSqlError> {
3022 test_with_details(&Now {}, "now", &[], |r| match r {
3023 Some(Value::Timestamp(dt)) => {
3024 let now = Utc::now().naive_utc();
3025 let to = now.checked_add_signed(TimeDelta::seconds(10)).unwrap();
3026 let from = now.checked_add_signed(TimeDelta::seconds(-10)).unwrap();
3027
3028 *dt >= from && *dt <= to
3029 }
3030 _ => false,
3031 })
3032 }
3033
3034 #[test]
3035 fn test_current_user() -> Result<(), CvsSqlError> {
3036 test_with_details(&User {}, "user", &[], |r| match r {
3037 Some(Value::Str(user)) => *user == whoami::username(),
3038 _ => false,
3039 })
3040 }
3041
3042 #[test]
3043 fn test_format() -> Result<(), CvsSqlError> {
3044 test_func(&Format {})
3045 }
3046
3047 #[test]
3048 fn test_to_timestamp() -> Result<(), CvsSqlError> {
3049 test_func(&ToTimestamp {})
3050 }
3051
3052 #[test]
3053 fn test_greatest() -> Result<(), CvsSqlError> {
3054 test_func(&Greatest {})
3055 }
3056
3057 #[test]
3058 fn test_if() -> Result<(), CvsSqlError> {
3059 test_func(&If {})
3060 }
3061
3062 #[test]
3063 fn test_null_if() -> Result<(), CvsSqlError> {
3064 test_func(&NullIf {})
3065 }
3066
3067 #[test]
3068 fn test_lower() -> Result<(), CvsSqlError> {
3069 test_func(&Lower {})
3070 }
3071
3072 #[test]
3073 fn test_upper() -> Result<(), CvsSqlError> {
3074 test_func(&Upper {})
3075 }
3076
3077 #[test]
3078 fn test_least() -> Result<(), CvsSqlError> {
3079 test_func(&Least {})
3080 }
3081
3082 #[test]
3083 fn test_left() -> Result<(), CvsSqlError> {
3084 test_func(&Left {})
3085 }
3086
3087 #[test]
3088 fn test_right() -> Result<(), CvsSqlError> {
3089 test_func(&Right {})
3090 }
3091
3092 #[test]
3093 fn test_lpad() -> Result<(), CvsSqlError> {
3094 test_func(&Lpad {})
3095 }
3096
3097 #[test]
3098 fn test_rpad() -> Result<(), CvsSqlError> {
3099 test_func(&Rpad {})
3100 }
3101
3102 #[test]
3103 fn test_ltrim() -> Result<(), CvsSqlError> {
3104 test_func(&Ltrim {})
3105 }
3106
3107 #[test]
3108 fn test_rtrim() -> Result<(), CvsSqlError> {
3109 test_func(&Rtrim {})
3110 }
3111
3112 #[test]
3113 fn test_pi() -> Result<(), CvsSqlError> {
3114 test_with_details(&Pi {}, "pi", &[], |r| match r {
3115 Some(Value::Number(num)) => {
3116 num.to_f64().unwrap() > std::f64::consts::PI - 0.001
3117 && num.to_f64().unwrap() < std::f64::consts::PI + 0.001
3118 }
3119 _ => false,
3120 })
3121 }
3122
3123 #[test]
3124 fn test_ln() -> Result<(), CvsSqlError> {
3125 test_with_details(&Ln {}, "ln", &["10"], |r| match r {
3126 Some(Value::Number(num)) => {
3127 num.to_f64().unwrap() > 2.30 && num.to_f64().unwrap() < 2.31
3128 }
3129 _ => false,
3130 })?;
3131 test_with_details(&Ln {}, "neg_ln", &["-10"], |r| r == Some(&Value::Empty))?;
3132 test_with_details(&Ln {}, "nan", &[""], |r| r == Some(&Value::Empty))
3133 }
3134
3135 #[test]
3136 fn test_exp() -> Result<(), CvsSqlError> {
3137 test_with_details(&Exp {}, "exp", &["10"], |r| match r {
3138 Some(Value::Number(num)) => {
3139 num.to_f64().unwrap() > 22026.46 && num.to_f64().unwrap() < 22026.47
3140 }
3141 _ => false,
3142 })?;
3143 test_with_details(&Exp {}, "neg_exp", &["-10"], |r| match r {
3144 Some(Value::Number(num)) => {
3145 num.to_f64().unwrap() > 4.53e-5 && num.to_f64().unwrap() < 4.54e-5
3146 }
3147 _ => false,
3148 })?;
3149 test_with_details(&Exp {}, "nan", &[""], |r| r == Some(&Value::Empty))
3150 }
3151
3152 #[test]
3153 fn test_log() -> Result<(), CvsSqlError> {
3154 test_func(&Log {})
3155 }
3156
3157 #[test]
3158 fn test_log2() -> Result<(), CvsSqlError> {
3159 test_func(&Log2 {})
3160 }
3161
3162 #[test]
3163 fn test_log10() -> Result<(), CvsSqlError> {
3164 test_func(&Log10 {})
3165 }
3166
3167 #[test]
3168 fn test_power() -> Result<(), CvsSqlError> {
3169 test_func(&Power {})
3170 }
3171
3172 #[test]
3173 fn test_position() -> Result<(), CvsSqlError> {
3174 test_func(&Position {})
3175 }
3176
3177 #[test]
3178 fn test_repeat() -> Result<(), CvsSqlError> {
3179 test_func(&Repeat {})
3180 }
3181
3182 #[test]
3183 fn test_replace() -> Result<(), CvsSqlError> {
3184 test_func(&Replace {})
3185 }
3186
3187 #[test]
3188 fn test_regex_replace() -> Result<(), CvsSqlError> {
3189 test_func(&RegexReplace {})
3190 }
3191
3192 #[test]
3193 fn test_regex_like() -> Result<(), CvsSqlError> {
3194 test_func(&RegexLike {})
3195 }
3196
3197 #[test]
3198 fn test_regex_substring() -> Result<(), CvsSqlError> {
3199 test_func(&RegexSubstring {})
3200 }
3201
3202 #[test]
3203 fn test_reverse() -> Result<(), CvsSqlError> {
3204 test_func(&Reverse {})
3205 }
3206 #[test]
3207 fn test_rand() -> Result<(), CvsSqlError> {
3208 test_with_details(&Random {}, "no_args", &[], |r| match r {
3209 Some(Value::Number(num)) => num.to_f64().unwrap() > 0.0 && num.to_f64().unwrap() < 1.0,
3210 _ => false,
3211 })?;
3212 test_with_details(&Random {}, "one_args", &["20"], |r| match r {
3213 Some(Value::Number(num)) => num.to_usize().unwrap() < 20,
3214 _ => false,
3215 })?;
3216 test_with_details(&Random {}, "nan", &["t"], |r| r == Some(&Value::Empty))?;
3217 test_with_details(&Random {}, "neg", &["-10"], |r| r == Some(&Value::Empty))
3218 }
3219
3220 #[test]
3221 fn test_round() -> Result<(), CvsSqlError> {
3222 test_func(&Round {})
3223 }
3224
3225 #[test]
3226 fn test_sqrt() -> Result<(), CvsSqlError> {
3227 test_func(&Sqrt {})
3228 }
3229
3230 fn test_unsupported(change: fn(&mut Function)) -> Result<(), CvsSqlError> {
3231 let args = Args {
3232 write_mode: true,
3233 ..Args::default()
3234 };
3235
3236 let engine = Engine::try_from(&args)?;
3237
3238 let sql = "SELECT * FROM tests.data.dates LIMIT RAND()";
3239 let dialect = FilesDialect {};
3240 let statement = Parser::parse_sql(&dialect, sql)?;
3241 let Some(Statement::Query(query)) = statement.into_iter().next() else {
3242 panic!("Not a select statement");
3243 };
3244 let Some(LimitClause::LimitOffset {
3245 limit,
3246 offset: _,
3247 limit_by: _,
3248 }) = &query.limit_clause
3249 else {
3250 panic!("No limit?")
3251 };
3252 let Some(limit) = limit else {
3253 panic!("No limit?")
3254 };
3255 let Expr::Function(mut func) = limit.clone() else {
3256 panic!("Not a function")
3257 };
3258
3259 change(&mut func);
3260
3261 let metadata = Metadata::Simple(SimpleResultSetMetadata::new(None));
3262 let Err(err) = func.convert_single(&metadata, &engine) else {
3263 panic!("No error");
3264 };
3265
3266 assert!(matches!(err, CvsSqlError::Unsupported(_)));
3267
3268 Ok(())
3269 }
3270
3271 #[test]
3272 fn test_null_treatment_unsupported() -> Result<(), CvsSqlError> {
3273 test_unsupported(|f| f.null_treatment = Some(NullTreatment::IgnoreNulls))
3274 }
3275
3276 #[test]
3277 fn test_filter_unsupported() -> Result<(), CvsSqlError> {
3278 test_unsupported(|f| {
3279 let ext = Box::new(Expr::Identifier(Ident::new("test")));
3280
3281 f.filter = Some(ext);
3282 })
3283 }
3284
3285 #[test]
3286 fn test_parameters_unsupported() -> Result<(), CvsSqlError> {
3287 test_unsupported(|f| {
3288 f.parameters = FunctionArguments::List(FunctionArgumentList {
3289 duplicate_treatment: None,
3290 args: vec![],
3291 clauses: vec![],
3292 });
3293 })
3294 }
3295}