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 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 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 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 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 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 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}