• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gluesql / gluesql / 22275856923

22 Feb 2026 11:01AM UTC coverage: 98.17% (+0.09%) from 98.085%
22275856923

Pull #1883

github

web-flow
Merge 6026cc70f into 80a446e87
Pull Request #1883: Add patch coverage diff summary to PR coverage bot comment

21 of 29 new or added lines in 11 files covered. (72.41%)

67 existing lines in 24 files now uncovered.

42750 of 43547 relevant lines covered (98.17%)

66356.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.8
/core/src/executor/evaluate.rs
1
mod error;
2
mod evaluated;
3
mod expr;
4
mod function;
5

6
use {
7
    self::function::BreakCase,
8
    super::{context::RowContext, select::select},
9
    crate::{
10
        ast::{Aggregate, Expr, Function, Projection, SetExpr},
11
        data::{CustomFunction, Interval, Row, Value},
12
        mock::MockStorage,
13
        result::{Error, Result},
14
        store::GStore,
15
    },
16
    async_recursion::async_recursion,
17
    chrono::prelude::Utc,
18
    futures::{
19
        future::{ready, try_join_all},
20
        stream::{self, StreamExt, TryStreamExt},
21
    },
22
    im::HashMap,
23
    std::{borrow::Cow, ops::ControlFlow, sync::Arc},
24
};
25

26
pub use {error::EvaluateError, evaluated::Evaluated};
27

28
pub async fn evaluate<'a, 'b, 'c, T>(
120,598✔
29
    storage: &'a T,
120,598✔
30
    context: Option<Arc<RowContext<'b>>>,
120,598✔
31
    aggregated: Option<Arc<HashMap<&'c Aggregate, Value>>>,
120,598✔
32
    expr: &'a Expr,
120,598✔
33
) -> Result<Evaluated<'a>>
120,598✔
34
where
120,598✔
35
    'b: 'a,
120,598✔
36
    'c: 'a,
120,598✔
37
    T: GStore,
120,598✔
38
{
120,598✔
39
    evaluate_inner(Some(storage), context, aggregated, expr).await
120,598✔
40
}
120,598✔
41

42
pub async fn evaluate_stateless<'a, 'b: 'a>(
3,141,037✔
43
    context: Option<RowContext<'b>>,
3,141,037✔
44
    expr: &'a Expr,
3,141,037✔
45
) -> Result<Evaluated<'a>> {
3,141,037✔
46
    let context = context.map(Arc::new);
336,492✔
47
    let storage: Option<&MockStorage> = None;
336,492✔
48

49
    evaluate_inner(storage, context, None, expr).await
336,492✔
50
}
336,492✔
51

52
#[async_recursion]
53
async fn evaluate_inner<'a, 'b, 'c, T>(
54
    storage: Option<&'a T>,
55
    context: Option<Arc<RowContext<'b>>>,
56
    aggregated: Option<Arc<HashMap<&'c Aggregate, Value>>>,
57
    expr: &'a Expr,
58
) -> Result<Evaluated<'a>>
59
where
60
    'b: 'a,
61
    'c: 'a,
62
    T: GStore,
63
{
1,353,580✔
64
    let eval = |expr| {
676,790✔
65
        let context = context.as_ref().map(Arc::clone);
167,227✔
66
        let aggregated = aggregated.as_ref().map(Arc::clone);
167,227✔
67

68
        evaluate_inner(storage, context, aggregated, expr)
167,227✔
69
    };
167,227✔
70

71
    match expr {
1,353,580✔
72
        Expr::Literal(literal) => Ok(expr::literal(literal)),
376,245✔
73
        Expr::Value(value) => Ok(Evaluated::Value(Cow::Borrowed(value))),
25,507✔
74
        Expr::TypedString { data_type, value } => expr::typed_string(data_type, value),
2,875✔
75
        Expr::Identifier(ident) => {
78,202✔
76
            let context = context.ok_or_else(|| {
78,202✔
77
                EvaluateError::ContextRequiredForIdentEvaluation(Box::new(expr.clone()))
136✔
78
            })?;
136✔
79

80
            match context.get_value(ident) {
78,066✔
81
                Some(value) => Ok(Evaluated::Value(Cow::Owned(value.clone()))),
78,010✔
82
                None => Err(EvaluateError::IdentifierNotFound(ident.to_owned()).into()),
56✔
83
            }
84
        }
85
        Expr::Nested(expr) => eval(expr).await,
2,092✔
86
        Expr::CompoundIdentifier { alias, ident } => {
65,516✔
87
            let context = context.ok_or_else(|| {
65,516✔
88
                EvaluateError::ContextRequiredForIdentEvaluation(Box::new(expr.clone()))
136✔
89
            })?;
136✔
90

91
            match context.get_alias_value(alias, ident) {
65,380✔
92
                Some(value) => Ok(Evaluated::Value(Cow::Owned(value.clone()))),
65,366✔
93
                None => Err(EvaluateError::CompoundIdentifierNotFound {
14✔
94
                    table_alias: alias.to_owned(),
14✔
95
                    column_name: ident.to_owned(),
14✔
96
                }
14✔
97
                .into()),
14✔
98
            }
99
        }
100
        Expr::Subquery(query) => {
2,078✔
101
            let storage = storage
2,078✔
102
                .ok_or_else(|| EvaluateError::UnsupportedStatelessExpr(Box::new(expr.clone())))?;
2,078✔
103
            if let SetExpr::Select(select) = &query.body
1,671✔
104
                && matches!(select.projection, Projection::SchemalessMap)
1,671✔
105
            {
106
                return Err(EvaluateError::SchemalessProjectionForSubQuery.into());
28✔
107
            }
1,643✔
108

109
            let evaluations = select(storage, query, context.as_ref().map(Arc::clone))
1,643✔
110
                .await?
1,643✔
111
                .map(|row| {
1,643✔
112
                    let values = row?.into_values();
1,573✔
113
                    if values.len() > 1 {
1,573✔
114
                        return Err(EvaluateError::MoreThanOneColumnReturned.into());
14✔
115
                    }
1,559✔
116
                    let value = values.into_iter().next();
1,559✔
117

118
                    Ok::<_, Error>(value)
1,559✔
119
                })
1,573✔
120
                .take(2)
1,643✔
121
                .try_collect::<Vec<_>>()
1,643✔
122
                .await?;
1,643✔
123

124
            if evaluations.len() > 1 {
1,629✔
125
                return Err(EvaluateError::MoreThanOneRowReturned.into());
14✔
126
            }
1,615✔
127

128
            let value = evaluations
1,615✔
129
                .into_iter()
1,615✔
130
                .next()
1,615✔
131
                .flatten()
1,615✔
132
                .unwrap_or(Value::Null);
1,615✔
133

134
            Ok(Evaluated::Value(Cow::Owned(value)))
1,615✔
135
        }
136
        Expr::BinaryOp { op, left, right } => {
58,045✔
137
            let left = eval(left).await?;
58,045✔
138
            let right = eval(right).await?;
57,877✔
139

140
            expr::binary_op(op, left, right)
57,695✔
141
        }
142
        Expr::UnaryOp { op, expr } => {
11,196✔
143
            let v = eval(expr).await?;
11,196✔
144

145
            expr::unary_op(op, v)
11,196✔
146
        }
147
        Expr::Aggregate(aggr) => match aggregated
1,795✔
148
            .as_ref()
1,795✔
149
            .and_then(|aggregated| aggregated.get(aggr.as_ref()))
1,795✔
150
        {
151
            Some(value) => Ok(Evaluated::Value(Cow::Owned(value.clone()))),
1,795✔
UNCOV
152
            None => Err(EvaluateError::UnreachableEmptyAggregateValue(aggr.clone()).into()),
×
153
        },
154
        Expr::Function(func) => {
35,325✔
155
            let context = context.as_ref().map(Arc::clone);
35,325✔
156
            let aggregated = aggregated.as_ref().map(Arc::clone);
35,325✔
157

158
            evaluate_function(storage, context, aggregated, func).await
35,325✔
159
        }
160
        Expr::InList {
161
            expr,
5,942✔
162
            list,
5,942✔
163
            negated,
5,942✔
164
        } => {
165
            let negated = *negated;
5,942✔
166
            let target = eval(expr).await?;
5,942✔
167

168
            if target.is_null() {
5,942✔
169
                return Ok(target);
28✔
170
            }
5,914✔
171

172
            let matched = try_join_all(list.iter().map(eval))
5,914✔
173
                .await?
5,914✔
174
                .into_iter()
5,914✔
175
                .any(|v| v.evaluate_eq(&target).is_true());
12,256✔
176

177
            Ok(Evaluated::Value(Cow::Owned(Value::Bool(matched ^ negated))))
5,914✔
178
        }
179
        Expr::InSubquery {
180
            expr: target_expr,
1,167✔
181
            subquery,
1,167✔
182
            negated,
1,167✔
183
        } => {
184
            let storage = storage
1,167✔
185
                .ok_or_else(|| EvaluateError::UnsupportedStatelessExpr(Box::new(expr.clone())))?;
1,167✔
186
            if let SetExpr::Select(select) = &subquery.body
1,167✔
187
                && matches!(select.projection, Projection::SchemalessMap)
1,167✔
188
            {
189
                return Err(EvaluateError::SchemalessProjectionForInSubQuery.into());
28✔
190
            }
1,139✔
191
            let target = eval(target_expr).await?;
1,139✔
192

193
            select(storage, subquery, context)
1,139✔
194
                .await?
1,139✔
195
                .map(|row| {
1,825✔
196
                    let value = row?.into_values().into_iter().next().unwrap_or(Value::Null);
1,825✔
197

198
                    Ok(Evaluated::Value(Cow::Owned(value)))
1,825✔
199
                })
1,825✔
200
                .try_filter(|evaluated| ready(evaluated.evaluate_eq(&target).is_true()))
1,825✔
201
                .try_next()
1,139✔
202
                .await
203
                .map(|v| v.is_some() ^ negated)
1,139✔
204
                .map(Value::Bool)
1,139✔
205
                .map(|v| Evaluated::Value(Cow::Owned(v)))
1,139✔
206
        }
207
        Expr::Between {
208
            expr,
888✔
209
            negated,
888✔
210
            low,
888✔
211
            high,
888✔
212
        } => {
213
            let target = eval(expr).await?;
888✔
214
            let low = eval(low).await?;
888✔
215
            let high = eval(high).await?;
888✔
216

217
            Ok(expr::between(&target, *negated, &low, &high))
888✔
218
        }
219
        Expr::Like {
220
            expr,
1,500✔
221
            negated,
1,500✔
222
            pattern,
1,500✔
223
        } => {
224
            let target = eval(expr).await?;
1,500✔
225
            let pattern = eval(pattern).await?;
1,500✔
226
            let evaluated = target.like(pattern, true)?;
1,500✔
227

228
            Ok(match negated {
1,472✔
229
                true => {
230
                    let t =
318✔
231
                        evaluated.evaluate_eq(&Evaluated::Value(Cow::Owned(Value::Bool(false))));
318✔
232
                    Evaluated::Value(Cow::Owned(Value::from(t)))
318✔
233
                }
234
                false => evaluated,
1,154✔
235
            })
236
        }
237
        Expr::ILike {
238
            expr,
944✔
239
            negated,
944✔
240
            pattern,
944✔
241
        } => {
242
            let target = eval(expr).await?;
944✔
243
            let pattern = eval(pattern).await?;
944✔
244
            let evaluated = target.like(pattern, false)?;
944✔
245

246
            Ok(match negated {
916✔
247
                true => {
248
                    let t =
318✔
249
                        evaluated.evaluate_eq(&Evaluated::Value(Cow::Owned(Value::Bool(false))));
318✔
250
                    Evaluated::Value(Cow::Owned(Value::from(t)))
318✔
251
                }
252
                false => evaluated,
598✔
253
            })
254
        }
255
        Expr::Exists { subquery, negated } => {
145✔
256
            let storage = storage
145✔
257
                .ok_or_else(|| EvaluateError::UnsupportedStatelessExpr(Box::new(expr.clone())))?;
145✔
258

259
            select(storage, subquery, context)
145✔
260
                .await?
145✔
261
                .try_next()
145✔
262
                .await
263
                .map(|v| v.is_some() ^ negated)
145✔
264
                .map(Value::Bool)
145✔
265
                .map(|v| Evaluated::Value(Cow::Owned(v)))
145✔
266
        }
267
        Expr::IsNull(expr) => {
1,244✔
268
            let v = eval(expr).await?.is_null();
1,244✔
269

270
            Ok(Evaluated::Value(Cow::Owned(Value::Bool(v))))
1,244✔
271
        }
272
        Expr::IsNotNull(expr) => {
735✔
273
            let v = eval(expr).await?.is_null();
735✔
274

275
            Ok(Evaluated::Value(Cow::Owned(Value::Bool(!v))))
735✔
276
        }
277
        Expr::Case {
278
            operand,
383✔
279
            when_then,
383✔
280
            else_result,
383✔
281
        } => {
282
            let operand = match operand {
383✔
283
                Some(op) => eval(op).await?,
103✔
284
                None => Evaluated::Value(Cow::Owned(Value::Bool(true))),
280✔
285
            };
286

287
            for (when, then) in when_then {
694✔
288
                let when = eval(when).await?;
565✔
289

290
                if when.evaluate_eq(&operand).is_true() {
565✔
291
                    return eval(then).await;
254✔
292
                }
311✔
293
            }
294

295
            match else_result {
129✔
296
                Some(er) => eval(er).await,
73✔
297
                None => Ok(Evaluated::Value(Cow::Owned(Value::Null))),
56✔
298
            }
299
        }
300
        Expr::ArrayIndex { obj, indexes } => {
1,386✔
301
            let obj = eval(obj).await?;
1,386✔
302
            let indexes = try_join_all(indexes.iter().map(eval)).await?;
1,386✔
303
            expr::array_index(obj, indexes)
1,386✔
304
        }
305
        Expr::Array { elem } => try_join_all(elem.iter().map(eval))
844✔
306
            .await?
844✔
307
            .into_iter()
844✔
308
            .map(Value::try_from)
844✔
309
            .collect::<Result<Vec<_>>>()
844✔
310
            .map(Value::List)
844✔
311
            .map(|v| Evaluated::Value(Cow::Owned(v))),
844✔
312
        Expr::Interval {
313
            expr,
2,736✔
314
            leading_field,
2,736✔
315
            last_field,
2,736✔
316
        } => {
317
            let value = eval(expr)
2,736✔
318
                .await
319
                .and_then(Value::try_from)
2,736✔
320
                .map(String::from)?;
2,736✔
321

322
            Interval::try_from_str(&value, *leading_field, *last_field)
2,736✔
323
                .map(Value::Interval)
2,736✔
324
                .map(|v| Evaluated::Value(Cow::Owned(v)))
2,736✔
325
        }
326
    }
327
}
676,790✔
328

329
async fn evaluate_function<'a, 'b: 'a, 'c: 'a, T: GStore>(
35,325✔
330
    storage: Option<&'a T>,
35,325✔
331
    context: Option<Arc<RowContext<'b>>>,
35,325✔
332
    aggregated: Option<Arc<HashMap<&'c Aggregate, Value>>>,
35,325✔
333
    func: &'b Function,
35,325✔
334
) -> Result<Evaluated<'a>> {
35,325✔
335
    use function as f;
336

337
    let eval = |expr| {
52,468✔
338
        let context = context.as_ref().map(Arc::clone);
52,468✔
339
        let aggregated = aggregated.as_ref().map(Arc::clone);
52,468✔
340

341
        evaluate_inner(storage, context, aggregated, expr)
52,468✔
342
    };
52,468✔
343

344
    let name = func.to_string();
35,325✔
345

346
    let result = match func {
35,325✔
347
        // --- text ---
348
        Function::Concat(exprs) => {
98✔
349
            let exprs = stream::iter(exprs).then(eval).try_collect().await?;
98✔
350
            f::concat(exprs)
84✔
351
        }
352
        Function::Custom { name, exprs } => {
40✔
353
            let CustomFunction {
354
                func_name,
7✔
355
                args,
7✔
356
                body,
7✔
357
            } = storage
40✔
358
                .ok_or(EvaluateError::UnsupportedCustomFunction)?
40✔
359
                .fetch_function(name)
9✔
360
                .await?
9✔
361
                .ok_or_else(|| EvaluateError::UnsupportedFunction(name.to_string()))?;
7✔
362

363
            let min = args.iter().filter(|arg| arg.default.is_none()).count();
14✔
364
            let max = args.len();
7✔
365

366
            if !(min..=max).contains(&exprs.len()) {
7✔
367
                return Err((EvaluateError::FunctionArgsLengthNotWithinRange {
2✔
368
                    name: func_name.to_owned(),
2✔
369
                    expected_minimum: min,
2✔
370
                    expected_maximum: max,
2✔
371
                    found: exprs.len(),
2✔
372
                })
2✔
373
                .into());
2✔
374
            }
5✔
375

376
            let exprs = exprs.iter().chain(
5✔
377
                args.iter()
5✔
378
                    .skip(exprs.len())
5✔
379
                    .filter_map(|arg| arg.default.as_ref()),
5✔
380
            );
381

382
            let context = stream::iter(args.iter().zip(exprs))
5✔
383
                .then(|(arg, expr)| async {
10✔
384
                    eval(expr)
10✔
385
                        .await?
10✔
386
                        .try_into_value(&arg.data_type, true)
10✔
387
                        .map(|value| (arg.name.clone(), value))
10✔
388
                })
20✔
389
                .try_collect::<Vec<(String, Value)>>()
5✔
390
                .await
391
                .map(|pairs| {
5✔
392
                    let (columns, values): (Vec<_>, Vec<_>) = pairs.into_iter().unzip();
5✔
393
                    let row = Cow::Owned(Row {
5✔
394
                        columns: columns.into(),
5✔
395
                        values,
5✔
396
                    });
5✔
397
                    let context = RowContext::new(name, row, None);
5✔
398
                    Some(Arc::new(context))
5✔
399
                })?;
5✔
400

401
            return evaluate_inner(storage, context, None, body).await;
5✔
402
        }
403
        Function::ConcatWs { separator, exprs } => {
234✔
404
            let separator = eval(separator).await?;
234✔
405
            let exprs = stream::iter(exprs).then(eval).try_collect().await?;
234✔
406
            f::concat_ws(&name, separator, exprs)
234✔
407
        }
408
        Function::IfNull { expr, then } => f::ifnull(eval(expr).await?, eval(then).await?),
650✔
409
        Function::NullIf { expr1, expr2 } => f::nullif(eval(expr1).await?, &eval(expr2).await?),
84✔
410
        Function::Lower(expr) => f::lower(&name, eval(expr).await?),
776✔
411
        Function::Initcap(expr) => f::initcap(&name, eval(expr).await?),
140✔
412
        Function::Upper(expr) => f::upper(&name, eval(expr).await?),
580✔
413
        Function::Left { expr, size } | Function::Right { expr, size } => {
440✔
414
            let expr = eval(expr).await?;
660✔
415
            let size = eval(size).await?;
660✔
416

417
            f::left_or_right(&name, expr, size)
660✔
418
        }
419
        Function::Replace { expr, old, new } => {
192✔
420
            let expr = eval(expr).await?;
192✔
421
            let old = eval(old).await?;
192✔
422
            let new = eval(new).await?;
192✔
423

424
            f::replace(&name, expr, old, new)
192✔
425
        }
426
        Function::Lpad { expr, size, fill } | Function::Rpad { expr, size, fill } => {
1,092✔
427
            let expr = eval(expr).await?;
1,912✔
428
            let size = eval(size).await?;
1,912✔
429
            let fill = match fill {
1,912✔
430
                Some(v) => Some(eval(v).await?),
768✔
431
                None => None,
1,144✔
432
            };
433

434
            f::lpad_or_rpad(&name, expr, size, fill)
1,912✔
435
        }
436
        Function::LastDay(expr) => {
436✔
437
            let expr = eval(expr).await?;
436✔
438
            f::last_day(&name, expr)
436✔
439
        }
440
        Function::Trim {
441
            expr,
804✔
442
            filter_chars,
804✔
443
            trim_where_field,
804✔
444
        } => {
445
            let expr = eval(expr).await?;
804✔
446
            let filter_chars = match filter_chars {
804✔
447
                Some(v) => Some(eval(v).await?),
514✔
448
                None => None,
290✔
449
            };
450

451
            return expr.trim(name, filter_chars, trim_where_field.as_ref());
804✔
452
        }
453
        Function::Ltrim { expr, chars } => {
768✔
454
            let expr = eval(expr).await?;
768✔
455
            let chars = match chars {
768✔
456
                Some(v) => Some(eval(v).await?),
412✔
457
                None => None,
356✔
458
            };
459

460
            return expr.ltrim(name, chars);
768✔
461
        }
462
        Function::Rtrim { expr, chars } => {
824✔
463
            let expr = eval(expr).await?;
824✔
464
            let chars = match chars {
824✔
465
                Some(v) => Some(eval(v).await?),
496✔
466
                None => None,
328✔
467
            };
468

469
            return expr.rtrim(name, chars);
824✔
470
        }
471
        Function::Reverse(expr) => {
178✔
472
            let expr = eval(expr).await?;
178✔
473

474
            f::reverse(&name, expr)
178✔
475
        }
476
        Function::Repeat { expr, num } => {
192✔
477
            let expr = eval(expr).await?;
192✔
478
            let num = eval(num).await?;
192✔
479

480
            f::repeat(&name, expr, num)
192✔
481
        }
482
        Function::Substr { expr, start, count } => {
2,469✔
483
            let expr = eval(expr).await?;
2,469✔
484
            let start = eval(start).await?;
2,469✔
485
            let count = match count {
2,469✔
486
                Some(v) => Some(eval(v).await?),
809✔
487
                None => None,
1,660✔
488
            };
489

490
            return expr.substr(name, start, count);
2,469✔
491
        }
492
        Function::Ascii(expr) => f::ascii(&name, eval(expr).await?),
2,058✔
493
        Function::Chr(expr) => f::chr(&name, eval(expr).await?),
1,988✔
494
        Function::Md5(expr) => f::md5(&name, eval(expr).await?),
408✔
495
        Function::Hex(expr) => f::hex(&name, eval(expr).await?),
1,224✔
496

497
        // --- float ---
498
        Function::Abs(expr) => f::abs(&name, eval(expr).await?),
336✔
499
        Function::Sign(expr) => f::sign(&name, eval(expr).await?),
224✔
500
        Function::Sqrt(expr) => f::sqrt(eval(expr).await?),
84✔
501
        Function::Power { expr, power } => {
154✔
502
            let expr = eval(expr).await?;
154✔
503
            let power = eval(power).await?;
154✔
504

505
            f::power(&name, expr, power)
154✔
506
        }
507
        Function::Ceil(expr) => f::ceil(&name, eval(expr).await?),
224✔
508
        Function::Rand(expr) => {
356✔
509
            let expr = match expr {
356✔
510
                Some(v) => Some(eval(v).await?),
220✔
511
                None => None,
136✔
512
            };
513

514
            f::rand(&name, expr)
356✔
515
        }
516
        Function::Round(expr) => f::round(&name, eval(expr).await?),
496✔
517
        Function::Trunc(expr) => f::trunc(&name, eval(expr).await?),
224✔
518
        Function::Floor(expr) => f::floor(&name, eval(expr).await?),
224✔
519
        Function::Radians(expr) => f::radians(&name, eval(expr).await?),
252✔
520
        Function::Degrees(expr) => f::degrees(&name, eval(expr).await?),
224✔
521
        Function::Pi() => {
522
            return Ok(Evaluated::Value(Cow::Owned(Value::F64(
56✔
523
                std::f64::consts::PI,
56✔
524
            ))));
56✔
525
        }
526
        Function::Exp(expr) => f::exp(&name, eval(expr).await?),
70✔
527
        Function::Log { antilog, base } => {
98✔
528
            let antilog = eval(antilog).await?;
98✔
529
            let base = eval(base).await?;
98✔
530

531
            f::log(&name, antilog, base)
98✔
532
        }
533
        Function::Ln(expr) => f::ln(&name, eval(expr).await?),
70✔
534
        Function::Log2(expr) => f::log2(&name, eval(expr).await?),
70✔
535
        Function::Log10(expr) => f::log10(&name, eval(expr).await?),
70✔
536
        Function::Sin(expr) => f::sin(&name, eval(expr).await?),
84✔
537
        Function::Cos(expr) => f::cos(&name, eval(expr).await?),
84✔
538
        Function::Tan(expr) => f::tan(&name, eval(expr).await?),
84✔
539
        Function::Asin(expr) => f::asin(&name, eval(expr).await?),
56✔
540
        Function::Acos(expr) => f::acos(&name, eval(expr).await?),
70✔
541
        Function::Atan(expr) => f::atan(&name, eval(expr).await?),
206✔
542

543
        // --- integer ---
544
        Function::Div { dividend, divisor } => {
472✔
545
            let dividend = eval(dividend).await?;
472✔
546
            let divisor = eval(divisor).await?;
472✔
547

548
            f::div(&name, dividend, divisor)
472✔
549
        }
550
        Function::Mod { dividend, divisor } => {
430✔
551
            let dividend = eval(dividend).await?;
430✔
552
            let divisor = eval(divisor).await?;
430✔
553

554
            return dividend.modulo(&divisor);
430✔
555
        }
556
        Function::Gcd { left, right } => {
810✔
557
            let left = eval(left).await?;
810✔
558
            let right = eval(right).await?;
810✔
559

560
            f::gcd(&name, left, right)
810✔
561
        }
562
        Function::Lcm { left, right } => {
810✔
563
            let left = eval(left).await?;
810✔
564
            let right = eval(right).await?;
810✔
565

566
            f::lcm(&name, left, right)
810✔
567
        }
568

569
        // --- spatial ---
570
        Function::Point { x, y } => {
750✔
571
            let x = eval(x).await?;
750✔
572
            let y = eval(y).await?;
750✔
573

574
            f::point(&name, x, y)
750✔
575
        }
576
        Function::GetX(expr) => f::get_x(&name, eval(expr).await?),
56✔
577
        Function::GetY(expr) => f::get_y(&name, eval(expr).await?),
56✔
578
        Function::CalcDistance {
579
            geometry1,
42✔
580
            geometry2,
42✔
581
        } => {
582
            let geometry1 = eval(geometry1).await?;
42✔
583
            let geometry2 = eval(geometry2).await?;
42✔
584

585
            f::calc_distance(&name, geometry1, geometry2)
42✔
586
        }
587

588
        // --- etc ---
589
        Function::Unwrap { expr, selector } => {
612✔
590
            let expr = eval(expr).await?;
612✔
591
            let selector = eval(selector).await?;
612✔
592

593
            f::unwrap(&name, expr, selector)
612✔
594
        }
595
        Function::GenerateUuid() => return Ok(f::generate_uuid()),
981✔
596
        Function::Greatest(exprs) => {
112✔
597
            let exprs = stream::iter(exprs).then(eval).try_collect().await?;
112✔
598
            return f::greatest(&name, exprs);
112✔
599
        }
600
        Function::Now() | Function::CurrentTimestamp() => {
601
            return Ok(Evaluated::Value(Cow::Owned(Value::Timestamp(
686✔
602
                Utc::now().naive_utc(),
686✔
603
            ))));
686✔
604
        }
605
        Function::CurrentDate() => {
606
            return Ok(Evaluated::Value(Cow::Owned(Value::Date(
342✔
607
                Utc::now().date_naive(),
342✔
608
            ))));
342✔
609
        }
610
        Function::CurrentTime() => {
611
            return Ok(Evaluated::Value(Cow::Owned(Value::Time(Utc::now().time()))));
450✔
612
        }
613
        Function::Format { expr, format } => {
402✔
614
            let expr = eval(expr).await?;
402✔
615
            let format = eval(format).await?;
402✔
616

617
            f::format(&name, expr, format)
402✔
618
        }
619
        Function::ToDate { expr, format } => {
304✔
620
            let expr = eval(expr).await?;
304✔
621
            let format = eval(format).await?;
304✔
622
            f::to_date(&name, expr, format)
304✔
623
        }
624
        Function::ToTimestamp { expr, format } => {
304✔
625
            let expr = eval(expr).await?;
304✔
626
            let format = eval(format).await?;
304✔
627
            f::to_timestamp(&name, expr, format)
304✔
628
        }
629
        Function::ToTime { expr, format } => {
234✔
630
            let expr = eval(expr).await?;
234✔
631
            let format = eval(format).await?;
234✔
632
            f::to_time(&name, expr, format)
234✔
633
        }
634
        Function::Position {
635
            from_expr,
207✔
636
            sub_expr,
207✔
637
        } => {
638
            let from_expr = eval(from_expr).await?;
207✔
639
            let sub_expr = eval(sub_expr).await?;
207✔
640
            f::position(from_expr, sub_expr)
207✔
641
        }
642
        Function::FindIdx {
643
            from_expr,
563✔
644
            sub_expr,
563✔
645
            start,
563✔
646
        } => {
647
            let from_expr = eval(from_expr).await?;
563✔
648
            let sub_expr = eval(sub_expr).await?;
563✔
649
            let start = match start {
563✔
650
                Some(idx) => Some(eval(idx).await?),
342✔
651
                None => None,
221✔
652
            };
653
            f::find_idx(&name, from_expr, sub_expr, start)
563✔
654
        }
655
        Function::Cast { expr, data_type } => return eval(expr).await?.cast(data_type),
3,179✔
656
        Function::Extract { field, expr } => {
239✔
657
            let expr = eval(expr).await?;
239✔
658
            f::extract(*field, expr)
239✔
659
        }
660
        Function::Coalesce(exprs) => {
1,010✔
661
            let exprs = stream::iter(exprs).then(eval).try_collect().await?;
1,010✔
662
            return f::coalesce(exprs);
996✔
663
        }
664

665
        // --- list ---
666
        Function::Append { expr, value } => {
178✔
667
            let expr = eval(expr).await?;
178✔
668
            let value = eval(value).await?;
178✔
669
            f::append(expr, value)
178✔
670
        }
671
        Function::Prepend { expr, value } => {
178✔
672
            let expr = eval(expr).await?;
178✔
673
            let value = eval(value).await?;
178✔
674
            f::prepend(expr, value)
178✔
675
        }
676
        Function::Skip { expr, size } => {
98✔
677
            let expr = eval(expr).await?;
98✔
678
            let size = eval(size).await?;
98✔
679
            f::skip(&name, expr, size)
98✔
680
        }
681
        Function::Sort { expr, order } => {
140✔
682
            let expr = eval(expr).await?;
140✔
683
            let order = match order {
140✔
684
                Some(o) => eval(o).await?,
98✔
685
                None => Evaluated::Value(Cow::Owned(Value::Str("ASC".to_owned()))),
42✔
686
            };
687
            f::sort(expr, order)
140✔
688
        }
689
        Function::Take { expr, size } => {
262✔
690
            let expr = eval(expr).await?;
262✔
691
            let size = eval(size).await?;
262✔
692
            f::take(&name, expr, size)
262✔
693
        }
694
        Function::Slice {
695
            expr,
168✔
696
            start,
168✔
697
            length,
168✔
698
        } => {
699
            let expr = eval(expr).await?;
168✔
700
            let start = eval(start).await?;
168✔
701
            let length = eval(length).await?;
168✔
702
            f::slice(&name, expr, start, length)
168✔
703
        }
704
        Function::IsEmpty(expr) => {
154✔
705
            let expr = eval(expr).await?;
154✔
706
            f::is_empty(expr)
154✔
707
        }
708
        Function::AddMonth { expr, size } => {
154✔
709
            let expr = eval(expr).await?;
154✔
710
            let size = eval(size).await?;
154✔
711
            f::add_month(&name, expr, size)
154✔
712
        }
713
        Function::Length(expr) => f::length(&name, eval(expr).await?),
131✔
714
        Function::Entries(expr) => f::entries(&name, eval(expr).await?),
28✔
715
        Function::Keys(expr) => f::keys(eval(expr).await?),
56✔
716
        Function::Values(expr) => {
70✔
717
            let expr = eval(expr).await?;
70✔
718
            f::values(expr)
70✔
719
        }
720
        Function::Splice {
721
            list_data,
84✔
722
            begin_index,
84✔
723
            end_index,
84✔
724
            values,
84✔
725
        } => {
726
            let list_data = eval(list_data).await?;
84✔
727
            let begin_index = eval(begin_index).await?;
84✔
728
            let end_index = eval(end_index).await?;
84✔
729
            let values = match values {
84✔
730
                Some(v) => Some(eval(v).await?),
56✔
731
                None => None,
28✔
732
            };
733
            f::splice(&name, list_data, begin_index, end_index, values)
84✔
734
        }
735
        Function::Dedup(list) => f::dedup(eval(list).await?),
42✔
736
    };
737

738
    match result {
3,818✔
739
        ControlFlow::Continue(v) => Ok(v),
19,342✔
740
        ControlFlow::Break(BreakCase::Null) => Ok(Evaluated::Value(Cow::Owned(Value::Null))),
1,412✔
741
        ControlFlow::Break(BreakCase::Err(err)) => Err(err),
2,406✔
742
    }
743
}
35,325✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc