gluesql_core/translate/
function.rs

1use {
2    super::{
3        TranslateError,
4        ast_literal::{translate_datetime_field, translate_trim_where_field},
5        expr::translate_expr,
6        translate_data_type, translate_object_name,
7    },
8    crate::{
9        ast::{Aggregate, CountArgExpr, Expr, Function},
10        result::Result,
11    },
12    sqlparser::ast::{
13        CastFormat as SqlCastFormat, CastKind as SqlCastKind, DataType as SqlDataType,
14        DateTimeField as SqlDateTimeField, DuplicateTreatment as SqlDuplicateTreatment,
15        Expr as SqlExpr, Function as SqlFunction, FunctionArg as SqlFunctionArg,
16        FunctionArgExpr as SqlFunctionArgExpr, FunctionArguments as SqlFunctionArguments,
17        TrimWhereField as SqlTrimWhereField,
18    },
19};
20
21pub fn translate_trim(
22    expr: &SqlExpr,
23    trim_where: &Option<SqlTrimWhereField>,
24    trim_what: &Option<Box<SqlExpr>>,
25) -> Result<Expr> {
26    let expr = translate_expr(expr)?;
27    let trim_where_field = trim_where.as_ref().map(translate_trim_where_field);
28    let filter_chars = trim_what
29        .as_ref()
30        .map(|expr| translate_expr(expr.as_ref()))
31        .transpose()?;
32
33    Ok(Expr::Function(Box::new(Function::Trim {
34        expr,
35        filter_chars,
36        trim_where_field,
37    })))
38}
39
40pub fn translate_floor(expr: &SqlExpr) -> Result<Expr> {
41    let expr = translate_expr(expr)?;
42
43    Ok(Expr::Function(Box::new(Function::Floor(expr))))
44}
45
46pub fn translate_ceil(expr: &SqlExpr) -> Result<Expr> {
47    let expr = translate_expr(expr)?;
48
49    Ok(Expr::Function(Box::new(Function::Ceil(expr))))
50}
51
52pub fn translate_position(sub_expr: &SqlExpr, from_expr: &SqlExpr) -> Result<Expr> {
53    let from_expr = translate_expr(from_expr)?;
54    let sub_expr = translate_expr(sub_expr)?;
55    Ok(Expr::Function(Box::new(Function::Position {
56        from_expr,
57        sub_expr,
58    })))
59}
60
61pub fn translate_cast(
62    kind: &SqlCastKind,
63    expr: &SqlExpr,
64    data_type: &SqlDataType,
65    format: Option<&SqlCastFormat>,
66) -> Result<Expr> {
67    if kind == &SqlCastKind::TryCast {
68        return Err(TranslateError::TryCastNotSupported.into());
69    } else if kind == &SqlCastKind::SafeCast {
70        return Err(TranslateError::SafeCastNotSupported.into());
71    } else if let Some(format) = format {
72        return Err(TranslateError::UnsupportedCastFormat(format.to_string()).into());
73    }
74
75    let expr = translate_expr(expr)?;
76    let data_type = translate_data_type(data_type)?;
77    Ok(Expr::Function(Box::new(Function::Cast { expr, data_type })))
78}
79
80pub fn translate_extract(field: &SqlDateTimeField, expr: &SqlExpr) -> Result<Expr> {
81    let field = translate_datetime_field(field)?;
82    let expr = translate_expr(expr)?;
83    Ok(Expr::Function(Box::new(Function::Extract { field, expr })))
84}
85
86fn check_len(name: String, found: usize, expected: usize) -> Result<()> {
87    if found == expected {
88        Ok(())
89    } else {
90        Err(TranslateError::FunctionArgsLengthNotMatching {
91            name,
92            found,
93            expected,
94        }
95        .into())
96    }
97}
98
99fn check_len_range(
100    name: String,
101    found: usize,
102    expected_minimum: usize,
103    expected_maximum: usize,
104) -> Result<()> {
105    if found >= expected_minimum && found <= expected_maximum {
106        Ok(())
107    } else {
108        Err(TranslateError::FunctionArgsLengthNotWithinRange {
109            name,
110            expected_minimum,
111            expected_maximum,
112            found,
113        }
114        .into())
115    }
116}
117
118fn check_len_min(name: String, found: usize, expected_minimum: usize) -> Result<()> {
119    if found >= expected_minimum {
120        Ok(())
121    } else {
122        Err(TranslateError::FunctionArgsLengthNotMatchingMin {
123            name,
124            expected_minimum,
125            found,
126        }
127        .into())
128    }
129}
130
131fn translate_function_zero_arg(func: Function, args: Vec<&SqlExpr>, name: String) -> Result<Expr> {
132    check_len(name, args.len(), 0)?;
133
134    Ok(Expr::Function(Box::new(func)))
135}
136
137fn translate_function_one_arg<T: FnOnce(Expr) -> Function>(
138    func: T,
139    args: Vec<&SqlExpr>,
140    name: String,
141) -> Result<Expr> {
142    check_len(name, args.len(), 1)?;
143
144    translate_expr(args[0])
145        .map(func)
146        .map(Box::new)
147        .map(Expr::Function)
148}
149
150fn translate_aggregate_one_arg<T: FnOnce(Expr, bool) -> Aggregate>(
151    func: T,
152    args: Vec<&SqlExpr>,
153    name: String,
154    distinct: bool,
155) -> Result<Expr> {
156    check_len(name, args.len(), 1)?;
157
158    translate_expr(args[0])
159        .map(|expr| func(expr, distinct))
160        .map(Box::new)
161        .map(Expr::Aggregate)
162}
163
164fn translate_function_trim<T: FnOnce(Expr, Option<Expr>) -> Function>(
165    func: T,
166    args: Vec<&SqlExpr>,
167    name: String,
168) -> Result<Expr> {
169    check_len_range(name, args.len(), 1, 2)?;
170
171    let expr = translate_expr(args[0])?;
172    let chars = if args.len() == 1 {
173        None
174    } else {
175        Some(translate_expr(args[1])?)
176    };
177
178    let result = func(expr, chars);
179
180    Ok(Expr::Function(Box::new(result)))
181}
182
183pub fn translate_function_arg_exprs(
184    function_arg_exprs: Vec<&SqlFunctionArgExpr>,
185) -> Result<Vec<&SqlExpr>> {
186    function_arg_exprs
187        .into_iter()
188        .map(|function_arg| match function_arg {
189            SqlFunctionArgExpr::Expr(expr) => Ok(expr),
190            SqlFunctionArgExpr::Wildcard | SqlFunctionArgExpr::QualifiedWildcard(_) => {
191                Err(TranslateError::WildcardFunctionArgNotAccepted.into())
192            }
193        })
194        .collect::<Result<Vec<_>>>()
195}
196
197pub fn translate_function(sql_function: &SqlFunction) -> Result<Expr> {
198    let SqlFunction { name, args, .. } = sql_function;
199    let name = translate_object_name(name)?.to_uppercase();
200    let (args, distinct) = match args {
201        SqlFunctionArguments::None => (Vec::new(), false),
202        SqlFunctionArguments::Subquery(_) => {
203            return Err(TranslateError::UnreachableSubqueryFunctionArgNotSupported.into());
204        }
205        SqlFunctionArguments::List(list) => {
206            let distinct = list
207                .duplicate_treatment
208                .is_some_and(|dt| matches!(dt, SqlDuplicateTreatment::Distinct));
209            (list.args.iter().collect(), distinct)
210        }
211    };
212
213    let function_arg_exprs = args
214        .iter()
215        .map(|arg| match arg {
216            SqlFunctionArg::Named { .. } => {
217                Err(TranslateError::NamedFunctionArgNotSupported.into())
218            }
219            SqlFunctionArg::Unnamed(arg_expr) => Ok(arg_expr),
220        })
221        .collect::<Result<Vec<_>>>()?;
222
223    if name.as_str() == "COUNT" {
224        check_len(name, args.len(), 1)?;
225
226        let count_arg = match function_arg_exprs[0] {
227            SqlFunctionArgExpr::Expr(expr) => CountArgExpr::Expr(translate_expr(expr)?),
228            SqlFunctionArgExpr::QualifiedWildcard(idents) => {
229                let table_name = translate_object_name(idents)?;
230                let idents = format!("{table_name}.*");
231
232                return Err(TranslateError::QualifiedWildcardInCountNotSupported(idents).into());
233            }
234            SqlFunctionArgExpr::Wildcard => CountArgExpr::Wildcard,
235        };
236
237        return Ok(Expr::Aggregate(Box::new(Aggregate::count(
238            count_arg, distinct,
239        ))));
240    }
241
242    let args = translate_function_arg_exprs(function_arg_exprs)?;
243
244    match name.as_str() {
245        "SUM" => translate_aggregate_one_arg(Aggregate::sum, args, name, distinct),
246        "MIN" => translate_aggregate_one_arg(Aggregate::min, args, name, distinct),
247        "MAX" => translate_aggregate_one_arg(Aggregate::max, args, name, distinct),
248        "AVG" => translate_aggregate_one_arg(Aggregate::avg, args, name, distinct),
249        "VARIANCE" => translate_aggregate_one_arg(Aggregate::variance, args, name, distinct),
250        "STDEV" => translate_aggregate_one_arg(Aggregate::stdev, args, name, distinct),
251        "COALESCE" => {
252            let exprs = args
253                .into_iter()
254                .map(translate_expr)
255                .collect::<Result<Vec<_>>>()?;
256            Ok(Expr::Function(Box::new(Function::Coalesce(exprs))))
257        }
258        "CONCAT" => {
259            let exprs = args
260                .into_iter()
261                .map(translate_expr)
262                .collect::<Result<Vec<_>>>()?;
263            Ok(Expr::Function(Box::new(Function::Concat(exprs))))
264        }
265        "CONCAT_WS" => {
266            check_len_min(name, args.len(), 2)?;
267            let separator = translate_expr(args[0])?;
268            let exprs = args
269                .into_iter()
270                .skip(1)
271                .map(translate_expr)
272                .collect::<Result<Vec<_>>>()?;
273            Ok(Expr::Function(Box::new(Function::ConcatWs {
274                separator,
275                exprs,
276            })))
277        }
278        "FIND_IDX" => {
279            check_len_range(name, args.len(), 2, 3)?;
280
281            let from_expr = translate_expr(args[0])?;
282            let sub_expr = translate_expr(args[1])?;
283            let start = (args.len() > 2)
284                .then(|| translate_expr(args[2]))
285                .transpose()?;
286
287            Ok(Expr::Function(Box::new(Function::FindIdx {
288                from_expr,
289                sub_expr,
290                start,
291            })))
292        }
293        "LOWER" => translate_function_one_arg(Function::Lower, args, name),
294        "INITCAP" => translate_function_one_arg(Function::Initcap, args, name),
295        "UPPER" => translate_function_one_arg(Function::Upper, args, name),
296        "LEFT" => {
297            check_len(name, args.len(), 2)?;
298
299            let expr = translate_expr(args[0])?;
300            let size = translate_expr(args[1])?;
301
302            Ok(Expr::Function(Box::new(Function::Left { expr, size })))
303        }
304        "IFNULL" => {
305            check_len(name, args.len(), 2)?;
306            let expr = translate_expr(args[0])?;
307            let then = translate_expr(args[1])?;
308            Ok(Expr::Function(Box::new(Function::IfNull { expr, then })))
309        }
310        "NULLIF" => {
311            check_len(name, args.len(), 2)?;
312            let expr1 = translate_expr(args[0])?;
313            let expr2 = translate_expr(args[1])?;
314            Ok(Expr::Function(Box::new(Function::NullIf { expr1, expr2 })))
315        }
316        "RIGHT" => {
317            check_len(name, args.len(), 2)?;
318
319            let expr = translate_expr(args[0])?;
320            let size = translate_expr(args[1])?;
321
322            Ok(Expr::Function(Box::new(Function::Right { expr, size })))
323        }
324        "SQRT" => {
325            check_len(name, args.len(), 1)?;
326
327            translate_expr(args[0])
328                .map(Function::Sqrt)
329                .map(Box::new)
330                .map(Expr::Function)
331        }
332        "POWER" => {
333            check_len(name, args.len(), 2)?;
334
335            let expr = translate_expr(args[0])?;
336            let power = translate_expr(args[1])?;
337
338            Ok(Expr::Function(Box::new(Function::Power { expr, power })))
339        }
340        "LPAD" => {
341            check_len_range(name, args.len(), 2, 3)?;
342
343            let expr = translate_expr(args[0])?;
344            let size = translate_expr(args[1])?;
345            let fill = if args.len() == 2 {
346                None
347            } else {
348                Some(translate_expr(args[2])?)
349            };
350
351            Ok(Expr::Function(Box::new(Function::Lpad {
352                expr,
353                size,
354                fill,
355            })))
356        }
357        "RPAD" => {
358            check_len_range(name, args.len(), 2, 3)?;
359
360            let expr = translate_expr(args[0])?;
361            let size = translate_expr(args[1])?;
362            let fill = if args.len() == 2 {
363                None
364            } else {
365                Some(translate_expr(args[2])?)
366            };
367
368            Ok(Expr::Function(Box::new(Function::Rpad {
369                expr,
370                size,
371                fill,
372            })))
373        }
374        "RAND" => {
375            check_len_range(name, args.len(), 0, 1)?;
376            let v = if args.is_empty() {
377                None
378            } else {
379                Some(translate_expr(args[0])?)
380            };
381            Ok(Expr::Function(Box::new(Function::Rand(v))))
382        }
383        "ROUND" => translate_function_one_arg(Function::Round, args, name),
384        "TRUNC" => translate_function_one_arg(Function::Trunc, args, name),
385        "EXP" => translate_function_one_arg(Function::Exp, args, name),
386        "LN" => translate_function_one_arg(Function::Ln, args, name),
387        "LOG" => {
388            check_len(name, args.len(), 2)?;
389
390            let antilog = translate_expr(args[0])?;
391            let base = translate_expr(args[1])?;
392
393            Ok(Expr::Function(Box::new(Function::Log { antilog, base })))
394        }
395        "LOG2" => translate_function_one_arg(Function::Log2, args, name),
396        "LOG10" => translate_function_one_arg(Function::Log10, args, name),
397        "SIN" => translate_function_one_arg(Function::Sin, args, name),
398        "COS" => translate_function_one_arg(Function::Cos, args, name),
399        "TAN" => translate_function_one_arg(Function::Tan, args, name),
400        "ASIN" => translate_function_one_arg(Function::Asin, args, name),
401        "ACOS" => translate_function_one_arg(Function::Acos, args, name),
402        "ATAN" => translate_function_one_arg(Function::Atan, args, name),
403        "RADIANS" => translate_function_one_arg(Function::Radians, args, name),
404        "DEGREES" => translate_function_one_arg(Function::Degrees, args, name),
405        "PI" => translate_function_zero_arg(Function::Pi(), args, name),
406        "NOW" => translate_function_zero_arg(Function::Now(), args, name),
407        "CURRENT_DATE" => translate_function_zero_arg(Function::CurrentDate(), args, name),
408        "CURRENT_TIME" => translate_function_zero_arg(Function::CurrentTime(), args, name),
409        "CURRENT_TIMESTAMP" => {
410            translate_function_zero_arg(Function::CurrentTimestamp(), args, name)
411        }
412        "GCD" => {
413            check_len(name, args.len(), 2)?;
414
415            let left = translate_expr(args[0])?;
416            let right = translate_expr(args[1])?;
417
418            Ok(Expr::Function(Box::new(Function::Gcd { left, right })))
419        }
420        "LAST_DAY" => {
421            check_len(name, args.len(), 1)?;
422
423            let expr = translate_expr(args[0])?;
424
425            Ok(Expr::Function(Box::new(Function::LastDay(expr))))
426        }
427        "LCM" => {
428            check_len(name, args.len(), 2)?;
429
430            let left = translate_expr(args[0])?;
431            let right = translate_expr(args[1])?;
432
433            Ok(Expr::Function(Box::new(Function::Lcm { left, right })))
434        }
435        "LTRIM" => {
436            translate_function_trim(|expr, chars| Function::Ltrim { expr, chars }, args, name)
437        }
438        "RTRIM" => {
439            translate_function_trim(|expr, chars| Function::Rtrim { expr, chars }, args, name)
440        }
441        "DIV" => {
442            check_len(name, args.len(), 2)?;
443
444            let dividend = translate_expr(args[0])?;
445            let divisor = translate_expr(args[1])?;
446
447            Ok(Expr::Function(Box::new(Function::Div {
448                dividend,
449                divisor,
450            })))
451        }
452        "MOD" => {
453            check_len(name, args.len(), 2)?;
454
455            let dividend = translate_expr(args[0])?;
456            let divisor = translate_expr(args[1])?;
457
458            Ok(Expr::Function(Box::new(Function::Mod {
459                dividend,
460                divisor,
461            })))
462        }
463        "REVERSE" => translate_function_one_arg(Function::Reverse, args, name),
464        "REPLACE" => {
465            check_len(name, args.len(), 3)?;
466            let expr = translate_expr(args[0])?;
467            let old = translate_expr(args[1])?;
468            let new = translate_expr(args[2])?;
469
470            Ok(Expr::Function(Box::new(Function::Replace {
471                expr,
472                old,
473                new,
474            })))
475        }
476        "REPEAT" => {
477            check_len(name, args.len(), 2)?;
478
479            let expr = translate_expr(args[0])?;
480            let num = translate_expr(args[1])?;
481
482            Ok(Expr::Function(Box::new(Function::Repeat { expr, num })))
483        }
484        "SUBSTR" => {
485            check_len_range(name, args.len(), 2, 3)?;
486
487            let expr = translate_expr(args[0])?;
488            let start = translate_expr(args[1])?;
489            let count = (args.len() > 2)
490                .then(|| translate_expr(args[2]))
491                .transpose()?;
492
493            Ok(Expr::Function(Box::new(Function::Substr {
494                expr,
495                start,
496                count,
497            })))
498        }
499        "UNWRAP" => {
500            check_len(name, args.len(), 2)?;
501
502            let expr = translate_expr(args[0])?;
503            let selector = translate_expr(args[1])?;
504
505            Ok(Expr::Function(Box::new(Function::Unwrap {
506                expr,
507                selector,
508            })))
509        }
510        "ABS" => translate_function_one_arg(Function::Abs, args, name),
511        "SIGN" => translate_function_one_arg(Function::Sign, args, name),
512        "GENERATE_UUID" => translate_function_zero_arg(Function::GenerateUuid(), args, name),
513        "FORMAT" => {
514            check_len(name, args.len(), 2)?;
515
516            let expr = translate_expr(args[0])?;
517            let format = translate_expr(args[1])?;
518
519            Ok(Expr::Function(Box::new(Function::Format { expr, format })))
520        }
521        "TO_DATE" => {
522            check_len(name, args.len(), 2)?;
523
524            let expr = translate_expr(args[0])?;
525            let format = translate_expr(args[1])?;
526
527            Ok(Expr::Function(Box::new(Function::ToDate { expr, format })))
528        }
529
530        "TO_TIMESTAMP" => {
531            check_len(name, args.len(), 2)?;
532
533            let expr = translate_expr(args[0])?;
534            let format = translate_expr(args[1])?;
535
536            Ok(Expr::Function(Box::new(Function::ToTimestamp {
537                expr,
538                format,
539            })))
540        }
541        "TO_TIME" => {
542            check_len(name, args.len(), 2)?;
543
544            let expr = translate_expr(args[0])?;
545            let format = translate_expr(args[1])?;
546
547            Ok(Expr::Function(Box::new(Function::ToTime { expr, format })))
548        }
549        "ADD_MONTH" => {
550            check_len(name, args.len(), 2)?;
551
552            let expr = translate_expr(args[0])?;
553            let size = translate_expr(args[1])?;
554
555            Ok(Expr::Function(Box::new(Function::AddMonth { expr, size })))
556        }
557        "ASCII" => {
558            check_len(name, args.len(), 1)?;
559
560            let expr = translate_expr(args[0])?;
561            Ok(Expr::Function(Box::new(Function::Ascii(expr))))
562        }
563        "CHR" => {
564            check_len(name, args.len(), 1)?;
565
566            let expr = translate_expr(args[0])?;
567            Ok(Expr::Function(Box::new(Function::Chr(expr))))
568        }
569        "MD5" => {
570            check_len(name, args.len(), 1)?;
571
572            let expr = translate_expr(args[0])?;
573            Ok(Expr::Function(Box::new(Function::Md5(expr))))
574        }
575        "HEX" => {
576            check_len(name, args.len(), 1)?;
577
578            let expr = translate_expr(args[0])?;
579            Ok(Expr::Function(Box::new(Function::Hex(expr))))
580        }
581        "LENGTH" => {
582            check_len(name, args.len(), 1)?;
583
584            let expr = translate_expr(args[0])?;
585            Ok(Expr::Function(Box::new(Function::Length(expr))))
586        }
587        "APPEND" => {
588            check_len(name, args.len(), 2)?;
589            let expr = translate_expr(args[0])?;
590            let value = translate_expr(args[1])?;
591
592            Ok(Expr::Function(Box::new(Function::Append { expr, value })))
593        }
594        "PREPEND" => {
595            check_len(name, args.len(), 2)?;
596            let expr = translate_expr(args[0])?;
597            let value = translate_expr(args[1])?;
598
599            Ok(Expr::Function(Box::new(Function::Prepend { expr, value })))
600        }
601        "SKIP" => {
602            check_len(name, args.len(), 2)?;
603            let expr = translate_expr(args[0])?;
604            let size = translate_expr(args[1])?;
605
606            Ok(Expr::Function(Box::new(Function::Skip { expr, size })))
607        }
608        "SORT" => {
609            check_len_range(name, args.len(), 1, 2)?;
610            let expr = translate_expr(args[0])?;
611            let order = (args.len() > 1)
612                .then(|| translate_expr(args[1]))
613                .transpose()?;
614
615            Ok(Expr::Function(Box::new(Function::Sort { expr, order })))
616        }
617        "TAKE" => {
618            check_len(name, args.len(), 2)?;
619            let expr = translate_expr(args[0])?;
620            let size = translate_expr(args[1])?;
621
622            Ok(Expr::Function(Box::new(Function::Take { expr, size })))
623        }
624        "POINT" => {
625            check_len(name, args.len(), 2)?;
626            let x = translate_expr(args[0])?;
627            let y = translate_expr(args[1])?;
628            Ok(Expr::Function(Box::new(Function::Point { x, y })))
629        }
630        "GET_X" => {
631            check_len(name, args.len(), 1)?;
632
633            let expr = translate_expr(args[0])?;
634            Ok(Expr::Function(Box::new(Function::GetX(expr))))
635        }
636        "GET_Y" => {
637            check_len(name, args.len(), 1)?;
638
639            let expr = translate_expr(args[0])?;
640            Ok(Expr::Function(Box::new(Function::GetY(expr))))
641        }
642        "CALC_DISTANCE" => {
643            check_len(name, args.len(), 2)?;
644
645            let geometry1 = translate_expr(args[0])?;
646            let geometry2 = translate_expr(args[1])?;
647            Ok(Expr::Function(Box::new(Function::CalcDistance {
648                geometry1,
649                geometry2,
650            })))
651        }
652        "IS_EMPTY" => {
653            check_len(name, args.len(), 1)?;
654
655            let expr = translate_expr(args[0])?;
656            Ok(Expr::Function(Box::new(Function::IsEmpty(expr))))
657        }
658        "SLICE" => {
659            check_len(name, args.len(), 3)?;
660            let expr = translate_expr(args[0])?;
661            let start = translate_expr(args[1])?;
662            let length = translate_expr(args[2])?;
663
664            Ok(Expr::Function(Box::new(Function::Slice {
665                expr,
666                start,
667                length,
668            })))
669        }
670        "GREATEST" => {
671            check_len_min(name, args.len(), 2)?;
672            let exprs = args
673                .into_iter()
674                .map(translate_expr)
675                .collect::<Result<Vec<_>>>()?;
676            Ok(Expr::Function(Box::new(Function::Greatest(exprs))))
677        }
678        "ENTRIES" => {
679            check_len(name, args.len(), 1)?;
680
681            let expr = translate_expr(args[0])?;
682            Ok(Expr::Function(Box::new(Function::Entries(expr))))
683        }
684        "KEYS" => {
685            check_len(name, args.len(), 1)?;
686
687            let expr = translate_expr(args[0])?;
688            Ok(Expr::Function(Box::new(Function::Keys(expr))))
689        }
690        "VALUES" => {
691            check_len(name, args.len(), 1)?;
692
693            let expr = translate_expr(args[0])?;
694            Ok(Expr::Function(Box::new(Function::Values(expr))))
695        }
696        "SPLICE" => {
697            check_len_range(name, args.len(), 3, 4)?;
698            let list_data = translate_expr(args[0])?;
699            let begin_index = translate_expr(args[1])?;
700            let end_index = translate_expr(args[2])?;
701            let values = if args.len() == 4 {
702                Some(translate_expr(args[3])?)
703            } else {
704                None
705            };
706            Ok(Expr::Function(Box::new(Function::Splice {
707                list_data,
708                begin_index,
709                end_index,
710                values,
711            })))
712        }
713        "DEDUP" => {
714            check_len(name, args.len(), 1)?;
715            let list = translate_expr(args[0])?;
716            Ok(Expr::Function(Box::new(Function::Dedup(list))))
717        }
718        _ => {
719            let exprs = args
720                .into_iter()
721                .map(translate_expr)
722                .collect::<Result<Vec<_>>>()?;
723            Ok(Expr::Function(Box::new(Function::Custom { name, exprs })))
724        }
725    }
726}
727
728#[cfg(test)]
729mod tests {
730    use {
731        super::*,
732        crate::{ast::DataType, parse_sql::parse_expr},
733    };
734
735    #[test]
736    fn cast() {
737        let expr = |sql| parse_expr(sql).and_then(|parsed| translate_expr(&parsed));
738
739        let actual = expr("CAST(name AS TEXT)");
740        let expected = Ok(Expr::Function(Box::new(Function::Cast {
741            expr: Expr::Identifier("name".to_owned()),
742            data_type: DataType::Text,
743        })));
744        assert_eq!(actual, expected);
745
746        let actual = expr("name::TEXT");
747        let expected = Ok(Expr::Function(Box::new(Function::Cast {
748            expr: Expr::Identifier("name".to_owned()),
749            data_type: DataType::Text,
750        })));
751        assert_eq!(actual, expected);
752
753        let actual = expr("TRY_CAST(id AS BOOLEAN)");
754        let expected = Err(TranslateError::TryCastNotSupported.into());
755        assert_eq!(actual, expected);
756
757        let actual = expr("SAFE_CAST(id AS UINT8)");
758        let expected = Err(TranslateError::SafeCastNotSupported.into());
759        assert_eq!(actual, expected);
760    }
761}