Skip to main content

gluesql_core/executor/
evaluate.rs

1mod error;
2mod evaluated;
3mod expr;
4mod function;
5
6use {
7    self::function::BreakCase,
8    super::{
9        context::{AggregateValues, RowContext},
10        query,
11    },
12    crate::{
13        data::{CustomFunction, Interval, Row, Value},
14        mock::MockStorage,
15        plan::{ExprPlan, FunctionExprPlan, ProjectionPlan, plan_scalar_expr},
16        result::{Error, Result},
17        store::GStore,
18    },
19    chrono::prelude::Utc,
20    std::{borrow::Cow, ops::ControlFlow, rc::Rc},
21};
22
23pub use {error::EvaluateError, evaluated::Evaluated};
24
25pub fn evaluate<'a, 'b, T>(
26    storage: &'a T,
27    context: Option<&Rc<RowContext<'b>>>,
28    aggregated: Option<&Rc<AggregateValues>>,
29    expr: &'a ExprPlan,
30) -> Result<Evaluated<'a>>
31where
32    'b: 'a,
33    T: GStore,
34{
35    evaluate_inner(Some(storage), context, aggregated, expr)
36}
37
38pub fn evaluate_stateless<'a, 'b: 'a>(
39    context: Option<RowContext<'b>>,
40    expr: &'a ExprPlan,
41) -> Result<Evaluated<'a>> {
42    let context = context.map(Rc::new);
43    let storage: Option<&MockStorage> = None;
44
45    evaluate_inner(storage, context.as_ref(), None, expr)
46}
47
48fn evaluate_inner<'a, 'b, T>(
49    storage: Option<&'a T>,
50    context: Option<&Rc<RowContext<'b>>>,
51    aggregated: Option<&Rc<AggregateValues>>,
52    expr: &'a ExprPlan,
53) -> Result<Evaluated<'a>>
54where
55    'b: 'a,
56    T: GStore,
57{
58    let eval = |expr| evaluate_inner(storage, context, aggregated, expr);
59
60    match expr {
61        ExprPlan::Literal(literal) => Ok(expr::literal(literal)),
62        ExprPlan::Value(value) => Ok(Evaluated::Value(Cow::Borrowed(value))),
63        ExprPlan::TypedString { data_type, value } => expr::typed_string(data_type, value),
64        ExprPlan::Identifier(ident) => {
65            let context = context
66                .ok_or_else(|| EvaluateError::IdentifierRequiresRowContext(ident.to_owned()))?;
67
68            match context.get_value(ident) {
69                Some(value) => Ok(Evaluated::Value(Cow::Owned(value.clone()))),
70                None => Err(EvaluateError::IdentifierNotFound(ident.to_owned()).into()),
71            }
72        }
73        ExprPlan::Nested(expr) => eval(expr),
74        ExprPlan::CompoundIdentifier { alias, ident } => {
75            let context =
76                context.ok_or_else(|| EvaluateError::CompoundIdentifierRequiresRowContext {
77                    alias: alias.to_owned(),
78                    ident: ident.to_owned(),
79                })?;
80
81            match context.get_alias_value(alias, ident) {
82                Some(value) => Ok(Evaluated::Value(Cow::Owned(value.clone()))),
83                None => Err(EvaluateError::CompoundIdentifierNotFound {
84                    table_alias: alias.to_owned(),
85                    column_name: ident.to_owned(),
86                }
87                .into()),
88            }
89        }
90        ExprPlan::Subquery(query) => {
91            let storage = storage.ok_or(EvaluateError::SubqueryNotAllowedInStatelessExpr)?;
92            if let Some(project) = query.project()
93                && matches!(project.projection, ProjectionPlan::SchemalessMap)
94            {
95                return Err(EvaluateError::SchemalessProjectionForSubQuery.into());
96            }
97
98            let evaluations = query::execute(storage, query, context.cloned())?
99                .map(|row| {
100                    let values = row?.into_values();
101                    if values.len() > 1 {
102                        return Err(EvaluateError::MoreThanOneColumnReturned.into());
103                    }
104                    let value = values.into_iter().next();
105
106                    Ok::<_, Error>(value)
107                })
108                .take(2)
109                .collect::<Result<Vec<_>>>()?;
110
111            if evaluations.len() > 1 {
112                return Err(EvaluateError::MoreThanOneRowReturned.into());
113            }
114
115            let value = evaluations
116                .into_iter()
117                .next()
118                .flatten()
119                .unwrap_or(Value::Null);
120
121            Ok(Evaluated::Value(Cow::Owned(value)))
122        }
123        ExprPlan::BinaryOp { op, left, right } => {
124            let left = eval(left)?;
125            let right = eval(right)?;
126
127            expr::binary_op(op, left, right)
128        }
129        ExprPlan::UnaryOp { op, expr } => {
130            let v = eval(expr)?;
131
132            expr::unary_op(op, v)
133        }
134        ExprPlan::Aggregate(aggr) => match aggregated
135            .as_ref()
136            .and_then(|aggregated| aggr.slot.and_then(|slot| aggregated.get(slot)))
137        {
138            Some(value) => Ok(Evaluated::Value(Cow::Owned(value.clone()))),
139            None if aggr.slot.is_none() => {
140                Err(EvaluateError::UnplannedAggregate(aggr.clone()).into())
141            }
142            None => Err(EvaluateError::AggregateSlotValueMissing(aggr.clone()).into()),
143        },
144        ExprPlan::Function(func) => evaluate_function(storage, context, aggregated, func),
145        ExprPlan::InList {
146            expr,
147            list,
148            negated,
149        } => {
150            let negated = *negated;
151            let target = eval(expr)?;
152
153            if target.is_null() {
154                return Ok(target);
155            }
156
157            let matched = list
158                .iter()
159                .map(eval)
160                .collect::<Result<Vec<_>>>()?
161                .into_iter()
162                .any(|v| v.evaluate_eq(&target).is_true());
163
164            Ok(Evaluated::Value(Cow::Owned(Value::Bool(matched ^ negated))))
165        }
166        ExprPlan::InSubquery {
167            expr: target_expr,
168            subquery,
169            negated,
170        } => {
171            let storage = storage.ok_or(EvaluateError::InSubqueryNotAllowedInStatelessExpr)?;
172            if let Some(project) = subquery.project()
173                && matches!(project.projection, ProjectionPlan::SchemalessMap)
174            {
175                return Err(EvaluateError::SchemalessProjectionForInSubQuery.into());
176            }
177            let target = eval(target_expr)?;
178            let (labels, rows) = query::execute_with_labels(storage, subquery, context.cloned())?;
179
180            if labels.len() > 1 {
181                return Err(EvaluateError::InSubqueryMustReturnOneColumn.into());
182            }
183
184            let mut matched = false;
185            for row in rows {
186                let value = row?.into_values().into_iter().next().unwrap_or(Value::Null);
187                let evaluated = Evaluated::Value(Cow::Owned(value));
188
189                if evaluated.evaluate_eq(&target).is_true() {
190                    matched = true;
191                    break;
192                }
193            }
194
195            Ok(Evaluated::Value(Cow::Owned(Value::Bool(matched ^ negated))))
196        }
197        ExprPlan::Between {
198            expr,
199            negated,
200            low,
201            high,
202        } => {
203            let target = eval(expr)?;
204            let low = eval(low)?;
205            let high = eval(high)?;
206
207            Ok(expr::between(&target, *negated, &low, &high))
208        }
209        ExprPlan::Like {
210            expr,
211            negated,
212            pattern,
213        } => {
214            let target = eval(expr)?;
215            let pattern = eval(pattern)?;
216            let evaluated = target.like(pattern, true)?;
217
218            Ok(match negated {
219                true => {
220                    let t =
221                        evaluated.evaluate_eq(&Evaluated::Value(Cow::Owned(Value::Bool(false))));
222                    Evaluated::Value(Cow::Owned(Value::from(t)))
223                }
224                false => evaluated,
225            })
226        }
227        ExprPlan::ILike {
228            expr,
229            negated,
230            pattern,
231        } => {
232            let target = eval(expr)?;
233            let pattern = eval(pattern)?;
234            let evaluated = target.like(pattern, false)?;
235
236            Ok(match negated {
237                true => {
238                    let t =
239                        evaluated.evaluate_eq(&Evaluated::Value(Cow::Owned(Value::Bool(false))));
240                    Evaluated::Value(Cow::Owned(Value::from(t)))
241                }
242                false => evaluated,
243            })
244        }
245        ExprPlan::Regex {
246            expr,
247            negated,
248            pattern,
249            case_sensitive,
250        } => {
251            let target = eval(expr)?;
252            let pattern = eval(pattern)?;
253
254            target.regex(pattern, *negated, *case_sensitive)
255        }
256        ExprPlan::Exists { subquery, negated } => {
257            let storage = storage.ok_or(EvaluateError::ExistsSubqueryNotAllowedInStatelessExpr)?;
258
259            let exists = query::execute(storage, subquery, context.cloned())?
260                .next()
261                .transpose()?
262                .is_some();
263
264            Ok(Evaluated::Value(Cow::Owned(Value::Bool(exists ^ negated))))
265        }
266        ExprPlan::IsNull(expr) => {
267            let v = eval(expr)?.is_null();
268
269            Ok(Evaluated::Value(Cow::Owned(Value::Bool(v))))
270        }
271        ExprPlan::IsNotNull(expr) => {
272            let v = eval(expr)?.is_null();
273
274            Ok(Evaluated::Value(Cow::Owned(Value::Bool(!v))))
275        }
276        ExprPlan::Case {
277            operand,
278            when_then,
279            else_result,
280        } => {
281            let operand = match operand {
282                Some(op) => eval(op)?,
283                None => Evaluated::Value(Cow::Owned(Value::Bool(true))),
284            };
285
286            for (when, then) in when_then {
287                let when = eval(when)?;
288
289                if when.evaluate_eq(&operand).is_true() {
290                    return eval(then);
291                }
292            }
293
294            match else_result {
295                Some(er) => eval(er),
296                None => Ok(Evaluated::Value(Cow::Owned(Value::Null))),
297            }
298        }
299        ExprPlan::ArrayIndex { obj, indexes } => {
300            let obj = eval(obj)?;
301            let indexes = indexes.iter().map(eval).collect::<Result<Vec<_>>>()?;
302            expr::array_index(obj, indexes)
303        }
304        ExprPlan::Array { elem } => elem
305            .iter()
306            .map(eval)
307            .collect::<Result<Vec<_>>>()?
308            .into_iter()
309            .map(Value::try_from)
310            .collect::<Result<Vec<_>>>()
311            .map(Value::List)
312            .map(|v| Evaluated::Value(Cow::Owned(v))),
313        ExprPlan::Interval {
314            expr,
315            leading_field,
316            last_field,
317        } => {
318            let value = eval(expr).and_then(Value::try_from).map(String::from)?;
319
320            Interval::try_from_str(&value, *leading_field, *last_field)
321                .map(Value::Interval)
322                .map(|v| Evaluated::Value(Cow::Owned(v)))
323        }
324    }
325}
326
327fn evaluate_function<'a, 'b: 'a, T: GStore>(
328    storage: Option<&'a T>,
329    context: Option<&Rc<RowContext<'b>>>,
330    aggregated: Option<&Rc<AggregateValues>>,
331    func: &'a FunctionExprPlan,
332) -> Result<Evaluated<'a>> {
333    use function as f;
334
335    let eval = |expr| evaluate_inner(storage, context, aggregated, expr);
336
337    let name = func.to_string();
338
339    let result = match func {
340        // --- text ---
341        FunctionExprPlan::Concat(exprs) => {
342            let exprs = exprs.iter().map(eval).collect::<Result<Vec<_>>>()?;
343            f::concat(exprs)
344        }
345        FunctionExprPlan::Custom { name, exprs } => {
346            let CustomFunction {
347                func_name,
348                args,
349                body,
350            } = storage
351                .ok_or(EvaluateError::UnsupportedCustomFunction)?
352                .fetch_function(name)?
353                .ok_or_else(|| EvaluateError::UnsupportedFunction(name.clone()))?;
354
355            let min = args.iter().filter(|arg| arg.default.is_none()).count();
356            let max = args.len();
357
358            if !(min..=max).contains(&exprs.len()) {
359                return Err((EvaluateError::FunctionArgsLengthNotWithinRange {
360                    name: func_name.to_owned(),
361                    expected_minimum: min,
362                    expected_maximum: max,
363                    found: exprs.len(),
364                })
365                .into());
366            }
367
368            let mut pairs = Vec::with_capacity(args.len());
369            for (index, arg) in args.iter().enumerate() {
370                let value = if let Some(expr) = exprs.get(index) {
371                    eval(expr)?.try_into_value(&arg.data_type, true)
372                } else {
373                    let default = arg.default.as_ref().ok_or_else(|| {
374                        EvaluateError::FunctionArgsLengthNotWithinRange {
375                            name: func_name.to_owned(),
376                            expected_minimum: min,
377                            expected_maximum: max,
378                            found: exprs.len(),
379                        }
380                    })?;
381                    let default = plan_scalar_expr(default.clone());
382
383                    evaluate_inner(storage, context, aggregated, &default)?
384                        .try_into_value(&arg.data_type, true)
385                }?;
386
387                pairs.push((arg.name.clone(), value));
388            }
389
390            let (columns, values): (Vec<_>, Vec<_>) = pairs.into_iter().unzip();
391            let row = Cow::Owned(Row {
392                columns: columns.into(),
393                values,
394            });
395            let context = RowContext::new(name, row, None);
396            let context = Some(Rc::new(context));
397
398            let body = plan_scalar_expr(body.clone());
399            let evaluated = evaluate_inner(storage, context.as_ref(), None, &body)?;
400            let value = evaluated.try_into()?;
401
402            return Ok(Evaluated::Value(Cow::Owned(value)));
403        }
404        FunctionExprPlan::ConcatWs { separator, exprs } => {
405            let separator = eval(separator)?;
406            let exprs = exprs.iter().map(eval).collect::<Result<Vec<_>>>()?;
407            f::concat_ws(&name, separator, exprs)
408        }
409        FunctionExprPlan::IfNull { expr, then } => f::ifnull(eval(expr)?, eval(then)?),
410        FunctionExprPlan::NullIf { expr1, expr2 } => f::nullif(eval(expr1)?, &eval(expr2)?),
411        FunctionExprPlan::Lower(expr) => f::lower(&name, eval(expr)?),
412        FunctionExprPlan::Initcap(expr) => f::initcap(&name, eval(expr)?),
413        FunctionExprPlan::Upper(expr) => f::upper(&name, eval(expr)?),
414        FunctionExprPlan::Left { expr, size } | FunctionExprPlan::Right { expr, size } => {
415            let expr = eval(expr)?;
416            let size = eval(size)?;
417
418            f::left_or_right(&name, expr, size)
419        }
420        FunctionExprPlan::Replace { expr, old, new } => {
421            let expr = eval(expr)?;
422            let old = eval(old)?;
423            let new = eval(new)?;
424
425            f::replace(&name, expr, old, new)
426        }
427        FunctionExprPlan::Lpad { expr, size, fill }
428        | FunctionExprPlan::Rpad { expr, size, fill } => {
429            let expr = eval(expr)?;
430            let size = eval(size)?;
431            let fill = match fill {
432                Some(v) => Some(eval(v)?),
433                None => None,
434            };
435
436            f::lpad_or_rpad(&name, expr, size, fill)
437        }
438        FunctionExprPlan::LastDay(expr) => {
439            let expr = eval(expr)?;
440            f::last_day(&name, expr)
441        }
442        FunctionExprPlan::Trim {
443            expr,
444            filter_chars,
445            trim_where_field,
446        } => {
447            let expr = eval(expr)?;
448            let filter_chars = match filter_chars {
449                Some(v) => Some(eval(v)?),
450                None => None,
451            };
452
453            return expr.trim(name, filter_chars, trim_where_field.as_ref());
454        }
455        FunctionExprPlan::Ltrim { expr, chars } => {
456            let expr = eval(expr)?;
457            let chars = match chars {
458                Some(v) => Some(eval(v)?),
459                None => None,
460            };
461
462            return expr.ltrim(name, chars);
463        }
464        FunctionExprPlan::Rtrim { expr, chars } => {
465            let expr = eval(expr)?;
466            let chars = match chars {
467                Some(v) => Some(eval(v)?),
468                None => None,
469            };
470
471            return expr.rtrim(name, chars);
472        }
473        FunctionExprPlan::Reverse(expr) => {
474            let expr = eval(expr)?;
475
476            f::reverse(&name, expr)
477        }
478        FunctionExprPlan::Repeat { expr, num } => {
479            let expr = eval(expr)?;
480            let num = eval(num)?;
481
482            f::repeat(&name, expr, num)
483        }
484        FunctionExprPlan::Substr { expr, start, count } => {
485            let expr = eval(expr)?;
486            let start = eval(start)?;
487            let count = match count {
488                Some(v) => Some(eval(v)?),
489                None => None,
490            };
491
492            return expr.substr(name, start, count);
493        }
494        FunctionExprPlan::Ascii(expr) => f::ascii(&name, eval(expr)?),
495        FunctionExprPlan::Chr(expr) => f::chr(&name, eval(expr)?),
496        FunctionExprPlan::Md5(expr) => f::md5(&name, eval(expr)?),
497        FunctionExprPlan::Hex(expr) => f::hex(&name, eval(expr)?),
498
499        // --- float ---
500        FunctionExprPlan::Abs(expr) => f::abs(&name, eval(expr)?),
501        FunctionExprPlan::Sign(expr) => f::sign(&name, eval(expr)?),
502        FunctionExprPlan::Sqrt(expr) => f::sqrt(eval(expr)?),
503        FunctionExprPlan::Power { expr, power } => {
504            let expr = eval(expr)?;
505            let power = eval(power)?;
506
507            f::power(&name, expr, power)
508        }
509        FunctionExprPlan::Ceil(expr) => f::ceil(&name, eval(expr)?),
510        FunctionExprPlan::Rand(expr) => {
511            let expr = match expr {
512                Some(v) => Some(eval(v)?),
513                None => None,
514            };
515
516            f::rand(&name, expr)
517        }
518        FunctionExprPlan::Round(expr) => f::round(&name, eval(expr)?),
519        FunctionExprPlan::Trunc(expr) => f::trunc(&name, eval(expr)?),
520        FunctionExprPlan::Floor(expr) => f::floor(&name, eval(expr)?),
521        FunctionExprPlan::Radians(expr) => f::radians(&name, eval(expr)?),
522        FunctionExprPlan::Degrees(expr) => f::degrees(&name, eval(expr)?),
523        FunctionExprPlan::Pi() => {
524            return Ok(Evaluated::Value(Cow::Owned(Value::F64(
525                std::f64::consts::PI,
526            ))));
527        }
528        FunctionExprPlan::Exp(expr) => f::exp(&name, eval(expr)?),
529        FunctionExprPlan::Log { antilog, base } => {
530            let antilog = eval(antilog)?;
531            let base = eval(base)?;
532
533            f::log(&name, antilog, base)
534        }
535        FunctionExprPlan::Ln(expr) => f::ln(&name, eval(expr)?),
536        FunctionExprPlan::Log2(expr) => f::log2(&name, eval(expr)?),
537        FunctionExprPlan::Log10(expr) => f::log10(&name, eval(expr)?),
538        FunctionExprPlan::Sin(expr) => f::sin(&name, eval(expr)?),
539        FunctionExprPlan::Cos(expr) => f::cos(&name, eval(expr)?),
540        FunctionExprPlan::Tan(expr) => f::tan(&name, eval(expr)?),
541        FunctionExprPlan::Asin(expr) => f::asin(&name, eval(expr)?),
542        FunctionExprPlan::Acos(expr) => f::acos(&name, eval(expr)?),
543        FunctionExprPlan::Atan(expr) => f::atan(&name, eval(expr)?),
544
545        // --- integer ---
546        FunctionExprPlan::Div { dividend, divisor } => {
547            let dividend = eval(dividend)?;
548            let divisor = eval(divisor)?;
549
550            f::div(&name, dividend, divisor)
551        }
552        FunctionExprPlan::Mod { dividend, divisor } => {
553            let dividend = eval(dividend)?;
554            let divisor = eval(divisor)?;
555
556            return dividend.modulo(&divisor);
557        }
558        FunctionExprPlan::Gcd { left, right } => {
559            let left = eval(left)?;
560            let right = eval(right)?;
561
562            f::gcd(&name, left, right)
563        }
564        FunctionExprPlan::Lcm { left, right } => {
565            let left = eval(left)?;
566            let right = eval(right)?;
567
568            f::lcm(&name, left, right)
569        }
570
571        // --- spatial ---
572        FunctionExprPlan::Point { x, y } => {
573            let x = eval(x)?;
574            let y = eval(y)?;
575
576            f::point(&name, x, y)
577        }
578        FunctionExprPlan::GetX(expr) => f::get_x(&name, eval(expr)?),
579        FunctionExprPlan::GetY(expr) => f::get_y(&name, eval(expr)?),
580        FunctionExprPlan::CalcDistance {
581            geometry1,
582            geometry2,
583        } => {
584            let geometry1 = eval(geometry1)?;
585            let geometry2 = eval(geometry2)?;
586
587            f::calc_distance(&name, geometry1, geometry2)
588        }
589
590        // --- etc ---
591        FunctionExprPlan::Unwrap { expr, selector } => {
592            let expr = eval(expr)?;
593            let selector = eval(selector)?;
594
595            f::unwrap(&name, expr, selector)
596        }
597        FunctionExprPlan::GenerateUuid() => return Ok(f::generate_uuid()),
598        FunctionExprPlan::Greatest(exprs) => {
599            let exprs = exprs.iter().map(eval).collect::<Result<Vec<_>>>()?;
600            return f::greatest(&name, exprs);
601        }
602        FunctionExprPlan::Now() | FunctionExprPlan::CurrentTimestamp() => {
603            return Ok(Evaluated::Value(Cow::Owned(Value::Timestamp(
604                Utc::now().naive_utc(),
605            ))));
606        }
607        FunctionExprPlan::CurrentDate() => {
608            return Ok(Evaluated::Value(Cow::Owned(Value::Date(
609                Utc::now().date_naive(),
610            ))));
611        }
612        FunctionExprPlan::CurrentTime() => {
613            return Ok(Evaluated::Value(Cow::Owned(Value::Time(Utc::now().time()))));
614        }
615        FunctionExprPlan::Format { expr, format } => {
616            let expr = eval(expr)?;
617            let format = eval(format)?;
618
619            f::format(&name, expr, format)
620        }
621        FunctionExprPlan::ToDate { expr, format } => {
622            let expr = eval(expr)?;
623            let format = eval(format)?;
624            f::to_date(&name, expr, format)
625        }
626        FunctionExprPlan::ToTimestamp { expr, format } => {
627            let expr = eval(expr)?;
628            let format = eval(format)?;
629            f::to_timestamp(&name, expr, format)
630        }
631        FunctionExprPlan::ToTime { expr, format } => {
632            let expr = eval(expr)?;
633            let format = eval(format)?;
634            f::to_time(&name, expr, format)
635        }
636        FunctionExprPlan::Position {
637            from_expr,
638            sub_expr,
639        } => {
640            let from_expr = eval(from_expr)?;
641            let sub_expr = eval(sub_expr)?;
642            f::position(from_expr, sub_expr)
643        }
644        FunctionExprPlan::FindIdx {
645            from_expr,
646            sub_expr,
647            start,
648        } => {
649            let from_expr = eval(from_expr)?;
650            let sub_expr = eval(sub_expr)?;
651            let start = match start {
652                Some(idx) => Some(eval(idx)?),
653                None => None,
654            };
655            f::find_idx(&name, from_expr, sub_expr, start)
656        }
657        FunctionExprPlan::Cast { expr, data_type } => return eval(expr)?.cast(data_type),
658        FunctionExprPlan::Extract { field, expr } => {
659            let expr = eval(expr)?;
660            f::extract(*field, expr)
661        }
662        FunctionExprPlan::Coalesce(exprs) => {
663            let exprs = exprs.iter().map(eval).collect::<Result<Vec<_>>>()?;
664            return f::coalesce(exprs);
665        }
666
667        // --- list ---
668        FunctionExprPlan::Append { expr, value } => {
669            let expr = eval(expr)?;
670            let value = eval(value)?;
671            f::append(expr, value)
672        }
673        FunctionExprPlan::Prepend { expr, value } => {
674            let expr = eval(expr)?;
675            let value = eval(value)?;
676            f::prepend(expr, value)
677        }
678        FunctionExprPlan::Skip { expr, size } => {
679            let expr = eval(expr)?;
680            let size = eval(size)?;
681            f::skip(&name, expr, size)
682        }
683        FunctionExprPlan::Sort { expr, order } => {
684            let expr = eval(expr)?;
685            let order = match order {
686                Some(o) => eval(o)?,
687                None => Evaluated::Value(Cow::Owned(Value::Str("ASC".to_owned()))),
688            };
689            f::sort(expr, order)
690        }
691        FunctionExprPlan::Take { expr, size } => {
692            let expr = eval(expr)?;
693            let size = eval(size)?;
694            f::take(&name, expr, size)
695        }
696        FunctionExprPlan::Slice {
697            expr,
698            start,
699            length,
700        } => {
701            let expr = eval(expr)?;
702            let start = eval(start)?;
703            let length = eval(length)?;
704            f::slice(&name, expr, start, length)
705        }
706        FunctionExprPlan::IsEmpty(expr) => {
707            let expr = eval(expr)?;
708            f::is_empty(expr)
709        }
710        FunctionExprPlan::AddMonth { expr, size } => {
711            let expr = eval(expr)?;
712            let size = eval(size)?;
713            f::add_month(&name, expr, size)
714        }
715        FunctionExprPlan::Length(expr) => f::length(&name, eval(expr)?),
716        FunctionExprPlan::Entries(expr) => f::entries(&name, eval(expr)?),
717        FunctionExprPlan::Keys(expr) => f::keys(eval(expr)?),
718        FunctionExprPlan::Values(expr) => {
719            let expr = eval(expr)?;
720            f::values(expr)
721        }
722        FunctionExprPlan::Splice {
723            list_data,
724            begin_index,
725            end_index,
726            values,
727        } => {
728            let list_data = eval(list_data)?;
729            let begin_index = eval(begin_index)?;
730            let end_index = eval(end_index)?;
731            let values = match values {
732                Some(v) => Some(eval(v)?),
733                None => None,
734            };
735            f::splice(&name, list_data, begin_index, end_index, values)
736        }
737        FunctionExprPlan::Dedup(list) => f::dedup(eval(list)?),
738    };
739
740    match result {
741        ControlFlow::Continue(v) => Ok(v),
742        ControlFlow::Break(BreakCase::Null) => Ok(Evaluated::Value(Cow::Owned(Value::Null))),
743        ControlFlow::Break(BreakCase::Err(err)) => Err(err),
744    }
745}
746
747#[cfg(test)]
748mod tests {
749    use {
750        super::{EvaluateError, evaluate, evaluate_stateless},
751        crate::{
752            ast::{Expr, Projection, SelectItem, SetExpr, Statement},
753            executor::context::AggregateValues,
754            mock::MockStorage,
755            parse_sql::parse,
756            plan::{AggregateExprPlan, AggregateFunctionPlan, CountArgExprPlan, ExprPlan},
757            result::Error,
758            translate::translate,
759        },
760        std::rc::Rc,
761    };
762
763    #[test]
764    fn aggregate_requires_planner_binding() {
765        let sql = "SELECT COUNT(*) FROM Item";
766        let parsed = parse(sql)
767            .expect(sql)
768            .into_iter()
769            .next()
770            .expect("query statement");
771        let translated = translate(&parsed).expect("translated statement");
772
773        let expr = if let Statement::Query(query) = translated
774            && let SetExpr::Select(select) = query.body
775            && let Projection::SelectItems(items) = select.projection
776            && let Some(SelectItem::Expr { expr, .. }) = items.into_iter().next()
777        {
778            expr
779        } else {
780            panic!("expected SELECT projection expression: {sql}");
781        };
782
783        let Expr::Aggregate(aggregate) = expr else {
784            panic!("expected aggregate expression");
785        };
786
787        let expr = ExprPlan::Aggregate(Box::new(AggregateExprPlan::from((*aggregate).clone())));
788        let result = evaluate_stateless(None, &expr);
789
790        assert_eq!(
791            result,
792            Err(Error::from(EvaluateError::UnplannedAggregate(Box::new(
793                AggregateExprPlan::from(*aggregate)
794            ))))
795        );
796    }
797
798    #[test]
799    fn aggregate_slot_value_must_exist() {
800        let aggregate = AggregateExprPlan {
801            func: AggregateFunctionPlan::Count(CountArgExprPlan::Wildcard),
802            distinct: false,
803            slot: Some(0),
804        };
805
806        let expr = ExprPlan::Aggregate(Box::new(aggregate.clone()));
807        let storage = MockStorage::default();
808        let aggregated = Rc::new(AggregateValues::new(Vec::new()));
809
810        let result = evaluate(&storage, None, Some(&aggregated), &expr);
811
812        assert_eq!(
813            result,
814            Err(Error::from(EvaluateError::AggregateSlotValueMissing(
815                Box::new(aggregate)
816            )))
817        );
818    }
819}