drasi_core/evaluation/expressions/
mod.rs

1// Copyright 2024 The Drasi Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#[cfg(test)]
16mod tests;
17
18use std::collections::BTreeMap;
19use std::sync::Arc;
20
21use async_recursion::async_recursion;
22use chrono::{
23    Datelike, Duration, LocalResult, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Weekday,
24};
25use drasi_query_ast::ast;
26
27use crate::evaluation::temporal_constants::{
28    self, EPOCH_MIDNIGHT_NAIVE_DATETIME, MIDNIGHT_NAIVE_TIME, UTC_FIXED_OFFSET,
29};
30use crate::evaluation::variable_value::duration::Duration as DurationStruct;
31use crate::evaluation::variable_value::float::Float;
32use crate::evaluation::variable_value::integer::Integer;
33use crate::evaluation::variable_value::zoned_datetime::ZonedDateTime;
34use crate::evaluation::variable_value::zoned_time::ZonedTime;
35use crate::evaluation::variable_value::{ListRange, RangeBound};
36use crate::interface::{ResultKey, ResultOwner};
37use crate::{evaluation::variable_value::VariableValue, interface::ResultIndex};
38
39use super::{
40    context::{ExpressionEvaluationContext, SideEffects},
41    functions::{aggregation::Accumulator, Function, FunctionRegistry},
42    EvaluationError, FunctionEvaluationError,
43};
44
45pub struct ExpressionEvaluator {
46    functions: Arc<FunctionRegistry>,
47    result_index: Arc<dyn ResultIndex>,
48}
49
50impl ExpressionEvaluator {
51    pub fn new(
52        functions: Arc<FunctionRegistry>,
53        result_index: Arc<dyn ResultIndex>,
54    ) -> ExpressionEvaluator {
55        ExpressionEvaluator {
56            functions,
57            result_index,
58        }
59    }
60
61    #[async_recursion]
62    pub async fn evaluate_expression(
63        &self,
64        context: &ExpressionEvaluationContext<'_>,
65        expression: &ast::Expression,
66    ) -> Result<VariableValue, EvaluationError> {
67        match expression {
68            ast::Expression::UnaryExpression(expression) => {
69                self.evaluate_unary_expression(context, expression).await
70            }
71            ast::Expression::BinaryExpression(expression) => {
72                self.evaluate_binary_expression(context, expression).await
73            }
74            ast::Expression::FunctionExpression(expression) => {
75                self.evaluate_function_expression(context, expression).await
76            }
77            ast::Expression::CaseExpression(expression) => {
78                self.evaluate_case_expression(context, expression).await
79            }
80            ast::Expression::ListExpression(expression) => {
81                self.evaluate_list_expression(context, expression).await
82            }
83            ast::Expression::ObjectExpression(expression) => {
84                self.evaluate_object_expression(context, expression).await
85            }
86            ast::Expression::IteratorExpression(expression) => {
87                self.evaluate_iterator_expression(context, expression).await
88            }
89        }
90    }
91
92    pub async fn evaluate_predicate(
93        &self,
94        context: &ExpressionEvaluationContext<'_>,
95        expression: &ast::Expression,
96    ) -> Result<bool, EvaluationError> {
97        let value = self.evaluate_expression(context, expression).await?;
98        match value {
99            // Value::Bool(b) => Ok(VariableValue::Bool(b)),
100            VariableValue::Bool(b) => Ok(b),
101            _ => Ok(false),
102        }
103    }
104
105    pub async fn evaluate_projection_field(
106        &self,
107        context: &ExpressionEvaluationContext<'_>,
108        expression: &ast::Expression,
109    ) -> Result<(String, VariableValue), EvaluationError> {
110        let value = self.evaluate_expression(context, expression).await?;
111        let alias = match expression {
112            ast::Expression::UnaryExpression(expression) => match expression {
113                ast::UnaryExpression::Property { name: _, key } => key,
114                ast::UnaryExpression::Parameter(p) => p,
115                ast::UnaryExpression::Alias { source: _, alias } => alias,
116                ast::UnaryExpression::Identifier(id) => id,
117                _ => "expression",
118            },
119            ast::Expression::BinaryExpression(_) => "expression",
120            ast::Expression::FunctionExpression(f) => &f.name,
121            ast::Expression::CaseExpression(_) => "case",
122            ast::Expression::ListExpression(_) => "list",
123            ast::Expression::ObjectExpression(_) => "object",
124            ast::Expression::IteratorExpression(_) => "iterator",
125        };
126
127        Ok((alias.to_string(), value))
128    }
129
130    #[async_recursion]
131    async fn evaluate_unary_expression(
132        &self,
133        context: &ExpressionEvaluationContext<'_>,
134        expression: &ast::UnaryExpression,
135    ) -> Result<VariableValue, EvaluationError> {
136        let result = match expression {
137            ast::UnaryExpression::Not(expression) => {
138                VariableValue::Bool(!self.evaluate_predicate(context, expression).await?)
139            }
140            ast::UnaryExpression::Exists(_) => todo!(),
141            ast::UnaryExpression::IsNull(e) => {
142                VariableValue::Bool(self.evaluate_expression(context, e).await?.is_null())
143            }
144            ast::UnaryExpression::IsNotNull(e) => {
145                VariableValue::Bool(!self.evaluate_expression(context, e).await?.is_null())
146            }
147            ast::UnaryExpression::Literal(l) => match l {
148                ast::Literal::Boolean(b) => VariableValue::Bool(*b),
149                ast::Literal::Text(t) => VariableValue::String(t.to_string()),
150                ast::Literal::Null => VariableValue::Null,
151                ast::Literal::Date(_) => VariableValue::Date(*temporal_constants::EPOCH_NAIVE_DATE),
152                ast::Literal::Integer(i) => VariableValue::Integer(Integer::from(
153                    match serde_json::Number::from(*i).as_i64() {
154                        Some(n) => n,
155                        None => return Err(EvaluationError::ParseError),
156                    },
157                )),
158                ast::Literal::Real(r) => match serde_json::Number::from_f64(*r) {
159                    Some(n) => VariableValue::Float(Float::from(match n.as_f64() {
160                        Some(n) => n,
161                        None => return Err(EvaluationError::ParseError),
162                    })),
163                    None => VariableValue::Null,
164                },
165                ast::Literal::LocalTime(_t) => VariableValue::LocalTime(*MIDNIGHT_NAIVE_TIME),
166                ast::Literal::ZonedTime(_t) => VariableValue::ZonedTime(ZonedTime::new(
167                    *MIDNIGHT_NAIVE_TIME,
168                    *UTC_FIXED_OFFSET,
169                )),
170                ast::Literal::LocalDateTime(_dt) => {
171                    VariableValue::LocalDateTime(*EPOCH_MIDNIGHT_NAIVE_DATETIME)
172                }
173                ast::Literal::ZonedDateTime(_dt) => {
174                    let local_datetime = *EPOCH_MIDNIGHT_NAIVE_DATETIME;
175                    VariableValue::ZonedDateTime(ZonedDateTime::new(
176                        match local_datetime.and_local_timezone(*UTC_FIXED_OFFSET) {
177                            LocalResult::Single(dt) => dt,
178                            _ => {
179                                return Err(EvaluationError::InvalidType {
180                                    expected: "DateTime".to_string(),
181                                })
182                            }
183                        },
184                        None,
185                    ))
186                }
187                ast::Literal::Duration(_d) => {
188                    VariableValue::Duration(DurationStruct::new(chrono::Duration::zero(), 0, 0))
189                }
190                ast::Literal::Object(o) => {
191                    let mut map = BTreeMap::new();
192                    for (key, value) in o {
193                        let val = match value {
194                            ast::Literal::Integer(i) => VariableValue::Integer(Integer::from(
195                                match serde_json::Number::from(*i).as_i64() {
196                                    Some(n) => n,
197                                    None => return Err(EvaluationError::ParseError),
198                                },
199                            )),
200                            ast::Literal::Text(s) => VariableValue::String(s.to_string()),
201                            ast::Literal::Real(r) => match serde_json::Number::from_f64(*r) {
202                                Some(n) => VariableValue::Float(Float::from(match n.as_f64() {
203                                    Some(n) => n,
204                                    None => return Err(EvaluationError::OverflowError),
205                                })),
206                                None => return Err(EvaluationError::ParseError),
207                            },
208                            _ => VariableValue::Null,
209                        };
210                        map.insert(key.to_string(), val);
211                    }
212                    VariableValue::Object(map)
213                }
214                ast::Literal::Expression(expr) => {
215                    let expression = *expr.clone();
216                    VariableValue::Expression(expression)
217                }
218            },
219            ast::UnaryExpression::Property { name, key } => {
220                match context.get_variable(name.clone()) {
221                    Some(v) => match v {
222                        VariableValue::Element(e) => e.get_property(key).into(),
223
224                        //type of object
225                        VariableValue::Object(o) => match o.get(&key.to_string()) {
226                            Some(v) => v.clone(),
227                            None => VariableValue::Null,
228                        },
229                        VariableValue::Date(d) => {
230                            match get_date_property(*d, (*key).to_string()).await {
231                                Some(v) => VariableValue::Integer(v.into()),
232                                None => {
233                                    return Err(EvaluationError::UnknownProperty {
234                                        property_name: (*key).to_string(),
235                                    })
236                                }
237                            }
238                        }
239                        VariableValue::LocalTime(t) => {
240                            match get_local_time_property(*t, (*key).to_string()).await {
241                                Some(v) => VariableValue::Integer(v.into()),
242                                None => {
243                                    return Err(EvaluationError::UnknownProperty {
244                                        property_name: (*key).to_string(),
245                                    })
246                                }
247                            }
248                        }
249                        VariableValue::ZonedTime(t) => {
250                            match get_time_property(*t, (*key).to_string()).await {
251                                Some(v) => {
252                                    if (*key).to_string() == "timezone"
253                                        || (*key).to_string() == "offset"
254                                    {
255                                        VariableValue::String(v.to_string())
256                                    } else {
257                                        match v.parse::<i64>() {
258                                            Ok(parsed_num) => {
259                                                VariableValue::Integer(parsed_num.into())
260                                            }
261                                            Err(_) => {
262                                                return Err(EvaluationError::ParseError);
263                                            }
264                                        }
265                                    }
266                                }
267                                None => {
268                                    return Err(EvaluationError::UnknownProperty {
269                                        property_name: (*key).to_string(),
270                                    })
271                                }
272                            }
273                        }
274                        VariableValue::LocalDateTime(t) => {
275                            match get_local_datetime_property(*t, (*key).to_string()).await {
276                                Some(v) => VariableValue::Integer(v.into()),
277                                None => {
278                                    return Err(EvaluationError::UnknownProperty {
279                                        property_name: (*key).to_string(),
280                                    })
281                                }
282                            }
283                        }
284                        VariableValue::ZonedDateTime(t) => {
285                            match get_datetime_property(t.clone(), (*key).to_string()).await {
286                                Some(v) => {
287                                    if (*key).to_string() == "timezone"
288                                        || (*key).to_string() == "offset"
289                                    {
290                                        VariableValue::String(v.to_string())
291                                    } else {
292                                        match v.parse::<i64>() {
293                                            Ok(parsed_num) => {
294                                                VariableValue::Integer(parsed_num.into())
295                                            }
296                                            Err(_) => {
297                                                return Err(EvaluationError::ParseError);
298                                            }
299                                        }
300                                    }
301                                }
302                                None => {
303                                    return Err(EvaluationError::UnknownProperty {
304                                        property_name: (*key).to_string(),
305                                    })
306                                }
307                            }
308                        }
309                        VariableValue::Duration(d) => {
310                            match get_duration_property(d.clone(), (*key).to_string()).await {
311                                Some(v) => VariableValue::Integer(v.into()),
312                                None => {
313                                    return Err(EvaluationError::UnknownProperty {
314                                        property_name: (*key).to_string(),
315                                    })
316                                }
317                            }
318                        }
319                        _ => VariableValue::Null,
320                    },
321                    None => VariableValue::Null,
322                }
323            }
324            ast::UnaryExpression::ExpressionProperty { exp, key } => {
325                let v = self.evaluate_expression(context, exp).await?;
326                match v {
327                    //type of object
328                    VariableValue::Object(o) => match o.get(&key.to_string()) {
329                        Some(v) => v.clone(),
330                        None => VariableValue::Null,
331                    },
332                    VariableValue::Date(d) => {
333                        match get_date_property(d, (*key).to_string()).await {
334                            Some(v) => VariableValue::Integer(v.into()),
335                            None => {
336                                return Err(EvaluationError::UnknownFunction((*key).to_string()))
337                            }
338                        }
339                    }
340                    VariableValue::LocalTime(t) => {
341                        match get_local_time_property(t, (*key).to_string()).await {
342                            Some(v) => VariableValue::Integer(v.into()),
343                            None => {
344                                return Err(EvaluationError::UnknownFunction((*key).to_string()))
345                            }
346                        }
347                    }
348                    VariableValue::ZonedTime(t) => match get_time_property(t, (*key).to_string())
349                        .await
350                    {
351                        Some(v) => {
352                            if (*key).to_string() == "timezone" || (*key).to_string() == "offset" {
353                                VariableValue::String(v.to_string())
354                            } else {
355                                match v.parse::<i64>() {
356                                    Ok(parsed_num) => VariableValue::Integer(parsed_num.into()),
357                                    Err(_) => {
358                                        return Err(EvaluationError::ParseError);
359                                    }
360                                }
361                            }
362                        }
363                        None => return Err(EvaluationError::UnknownFunction((*key).to_string())),
364                    },
365                    VariableValue::LocalDateTime(t) => {
366                        match get_local_datetime_property(t, (*key).to_string()).await {
367                            Some(v) => VariableValue::Integer(v.into()),
368                            None => {
369                                return Err(EvaluationError::UnknownFunction((*key).to_string()))
370                            }
371                        }
372                    }
373                    VariableValue::ZonedDateTime(t) => {
374                        match get_datetime_property(t.clone(), (*key).to_string()).await {
375                            Some(v) => {
376                                if (*key).to_string() == "timezone"
377                                    || (*key).to_string() == "offset"
378                                {
379                                    VariableValue::String(v.to_string())
380                                } else {
381                                    match v.parse::<i64>() {
382                                        Ok(parsed_num) => VariableValue::Integer(parsed_num.into()),
383                                        Err(_) => {
384                                            return Err(EvaluationError::ParseError);
385                                        }
386                                    }
387                                }
388                            }
389                            None => {
390                                return Err(EvaluationError::UnknownFunction((*key).to_string()))
391                            }
392                        }
393                    }
394                    VariableValue::Duration(d) => {
395                        match get_duration_property(d.clone(), (*key).to_string()).await {
396                            Some(v) => VariableValue::Integer(v.into()),
397                            None => {
398                                return Err(EvaluationError::UnknownFunction((*key).to_string()))
399                            }
400                        }
401                    }
402                    _ => VariableValue::Null,
403                }
404            }
405            ast::UnaryExpression::Parameter(p) => match context.get_variable(p.clone()) {
406                Some(v) => v.clone(),
407                None => VariableValue::Null,
408            },
409            ast::UnaryExpression::Variable { name, value } => {
410                //review
411                // create an object with name being the key and val being the value
412                let variable_value = self.evaluate_expression(context, value).await?;
413                let mut map = BTreeMap::new();
414                map.insert(name.to_string(), variable_value.clone());
415                VariableValue::Object(map)
416            }
417            ast::UnaryExpression::Alias { source, alias: _ } => {
418                self.evaluate_expression(context, source).await?
419            }
420            ast::UnaryExpression::Identifier(ident) => match context.get_variable(ident.clone()) {
421                Some(value) => value.clone(),
422                None => return Err(EvaluationError::UnknownIdentifier(ident.to_string())),
423            },
424            ast::UnaryExpression::ListRange {
425                start_bound,
426                end_bound,
427            } => match (start_bound, end_bound) {
428                (Some(start), Some(end)) => {
429                    let start = self.evaluate_expression(context, start).await?;
430                    if !start.is_i64() {
431                        return Err(EvaluationError::OverflowError);
432                    }
433                    let end = self.evaluate_expression(context, end).await?;
434                    if !end.is_i64() {
435                        return Err(EvaluationError::OverflowError);
436                    }
437                    VariableValue::ListRange(ListRange {
438                        start: RangeBound::Index(match start.as_i64() {
439                            Some(n) => n,
440                            None => return Err(EvaluationError::OverflowError),
441                        }),
442                        end: RangeBound::Index(match end.as_i64() {
443                            Some(n) => n,
444                            None => return Err(EvaluationError::OverflowError),
445                        }),
446                    })
447                }
448                (Some(start), None) => {
449                    let start = self.evaluate_expression(context, start).await?;
450                    VariableValue::ListRange(ListRange {
451                        start: RangeBound::Index(match start.as_i64() {
452                            Some(n) => n,
453                            None => return Err(EvaluationError::OverflowError),
454                        }),
455                        end: RangeBound::Unbounded,
456                    })
457                }
458                (None, Some(end)) => {
459                    let end = self.evaluate_expression(context, end).await?;
460                    VariableValue::ListRange(ListRange {
461                        start: RangeBound::Unbounded,
462                        end: RangeBound::Index(match end.as_i64() {
463                            Some(n) => n,
464                            None => return Err(EvaluationError::OverflowError),
465                        }),
466                    })
467                }
468                (None, None) => VariableValue::ListRange(ListRange {
469                    start: RangeBound::Unbounded,
470                    end: RangeBound::Unbounded,
471                }),
472            },
473        };
474        Ok(result)
475    }
476
477    #[async_recursion]
478    async fn evaluate_binary_expression(
479        &self,
480        context: &ExpressionEvaluationContext<'_>,
481        expression: &ast::BinaryExpression,
482    ) -> Result<VariableValue, EvaluationError> {
483        let result = match expression {
484            ast::BinaryExpression::And(c1, c2) => VariableValue::Bool(
485                self.evaluate_predicate(context, c1).await?
486                    && self.evaluate_predicate(context, c2).await?,
487            ),
488            ast::BinaryExpression::Or(c1, c2) => VariableValue::Bool(
489                self.evaluate_predicate(context, c1).await?
490                    || self.evaluate_predicate(context, c2).await?,
491            ),
492            ast::BinaryExpression::Eq(e1, e2) => match (
493                self.evaluate_expression(context, e1).await?,
494                self.evaluate_expression(context, e2).await?,
495            ) {
496                (VariableValue::Integer(n1), VariableValue::Integer(n2)) => {
497                    VariableValue::Bool(n1 == n2)
498                }
499                (VariableValue::Float(n1), VariableValue::Float(n2)) => {
500                    VariableValue::Bool(n1 == n2)
501                }
502                (VariableValue::String(s1), VariableValue::String(s2)) => {
503                    VariableValue::Bool(s1 == s2)
504                }
505                (VariableValue::Bool(b1), VariableValue::Bool(b2)) => VariableValue::Bool(b1 == b2),
506                (VariableValue::Null, VariableValue::Null) => VariableValue::Bool(true),
507                (VariableValue::List(a1), VariableValue::List(a2)) => VariableValue::Bool(a1 == a2),
508                (VariableValue::ElementReference(e1), VariableValue::ElementReference(e2)) => {
509                    VariableValue::Bool(e1 == e2)
510                }
511                (VariableValue::Date(date1), VariableValue::Date(date2)) => {
512                    VariableValue::Bool(date1 == date2)
513                }
514                (VariableValue::LocalTime(time1), VariableValue::LocalTime(time2)) => {
515                    VariableValue::Bool(time1 == time2)
516                }
517                (VariableValue::LocalDateTime(dt1), VariableValue::LocalDateTime(dt2)) => {
518                    VariableValue::Bool(dt1 == dt2)
519                }
520                (VariableValue::ZonedTime(time1), VariableValue::ZonedTime(time2)) => {
521                    VariableValue::Bool(time1 == time2)
522                }
523                (VariableValue::ZonedDateTime(zdt1), VariableValue::ZonedDateTime(zdt2)) => {
524                    VariableValue::Bool(zdt1 == zdt2)
525                }
526                (VariableValue::Duration(d1), VariableValue::Duration(d2)) => {
527                    VariableValue::Bool(d1 == d2)
528                }
529                (VariableValue::Awaiting, VariableValue::Awaiting) => VariableValue::Bool(true),
530                _ => VariableValue::Bool(false),
531            },
532            ast::BinaryExpression::Ne(e1, e2) => match (
533                self.evaluate_expression(context, e1).await?,
534                self.evaluate_expression(context, e2).await?,
535            ) {
536                (VariableValue::Integer(n1), VariableValue::Integer(n2)) => {
537                    VariableValue::Bool(n1 != n2)
538                }
539                (VariableValue::Float(n1), VariableValue::Float(n2)) => {
540                    VariableValue::Bool(n1 != n2)
541                }
542                (VariableValue::Float(n1), VariableValue::Integer(n2)) => VariableValue::Bool(
543                    n1 != match n2.as_i64() {
544                        Some(n) => n as f64,
545                        None => {
546                            return Err(EvaluationError::InvalidType {
547                                expected: "Integer".to_string(),
548                            })
549                        }
550                    },
551                ),
552                (VariableValue::Integer(n1), VariableValue::Float(n2)) => VariableValue::Bool(
553                    n2 != match n1.as_i64() {
554                        Some(n) => n as f64,
555                        None => {
556                            return Err(EvaluationError::InvalidType {
557                                expected: "Integer".to_string(),
558                            })
559                        }
560                    },
561                ),
562                (VariableValue::String(s1), VariableValue::String(s2)) => {
563                    VariableValue::Bool(s1 != s2)
564                }
565                (VariableValue::Bool(b1), VariableValue::Bool(b2)) => VariableValue::Bool(b1 != b2),
566                (VariableValue::Null, VariableValue::Null) => VariableValue::Bool(false),
567                (VariableValue::List(a1), VariableValue::List(a2)) => VariableValue::Bool(a1 != a2),
568                (VariableValue::Date(date1), VariableValue::Date(date2)) => {
569                    VariableValue::Bool(date1 != date2)
570                }
571                (VariableValue::LocalTime(time1), VariableValue::LocalTime(time2)) => {
572                    VariableValue::Bool(time1 != time2)
573                }
574                (VariableValue::LocalDateTime(dt1), VariableValue::LocalDateTime(dt2)) => {
575                    VariableValue::Bool(dt1 != dt2)
576                }
577                (VariableValue::ZonedTime(time1), VariableValue::ZonedTime(time2)) => {
578                    VariableValue::Bool(time1 != time2)
579                }
580                (VariableValue::ZonedDateTime(zdt1), VariableValue::ZonedDateTime(zdt2)) => {
581                    VariableValue::Bool(zdt1 != zdt2)
582                }
583                (VariableValue::Duration(d1), VariableValue::Duration(d2)) => {
584                    VariableValue::Bool(d1 != d2)
585                }
586                (VariableValue::ElementReference(e1), VariableValue::ElementReference(e2)) => {
587                    VariableValue::Bool(e1 != e2)
588                }
589                _ => VariableValue::Bool(false),
590            },
591            ast::BinaryExpression::Lt(e1, e2) => match (
592                self.evaluate_expression(context, e1).await?,
593                self.evaluate_expression(context, e2).await?,
594            ) {
595                (VariableValue::Integer(n1), VariableValue::Integer(n2)) => VariableValue::Bool(
596                    n1.as_i64().unwrap_or_default() < n2.as_i64().unwrap_or_default(),
597                ),
598                (VariableValue::Float(n1), VariableValue::Float(n2)) => VariableValue::Bool(
599                    n1.as_f64().unwrap_or_default() < n2.as_f64().unwrap_or_default(),
600                ),
601                (VariableValue::Float(n1), VariableValue::Integer(n2)) => VariableValue::Bool(
602                    n1.as_f64().unwrap_or_default() < n2.as_i64().unwrap_or_default() as f64,
603                ),
604                (VariableValue::Integer(n1), VariableValue::Float(n2)) => VariableValue::Bool(
605                    (n1.as_i64().unwrap_or_default() as f64) < n2.as_f64().unwrap_or_default(),
606                ),
607                (VariableValue::Date(date1), VariableValue::Date(date2)) => {
608                    VariableValue::Bool(date1 < date2)
609                }
610                (VariableValue::LocalTime(time1), VariableValue::LocalTime(time2)) => {
611                    VariableValue::Bool(time1 < time2)
612                }
613                (VariableValue::LocalDateTime(dt1), VariableValue::LocalDateTime(dt2)) => {
614                    VariableValue::Bool(dt1 < dt2)
615                }
616                (VariableValue::LocalDateTime(dt1), VariableValue::Date(date2)) => {
617                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
618                    VariableValue::Bool(dt1 < dt2)
619                }
620                (VariableValue::LocalDateTime(dt1), VariableValue::LocalTime(time2)) => {
621                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
622                    VariableValue::Bool(dt1 < dt2)
623                }
624                (VariableValue::LocalTime(time1), VariableValue::LocalDateTime(dt2)) => {
625                    let dt1 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time1);
626                    VariableValue::Bool(dt1 < dt2)
627                }
628                (VariableValue::Date(date1), VariableValue::LocalDateTime(dt2)) => {
629                    let dt1 = NaiveDateTime::new(date1, *MIDNIGHT_NAIVE_TIME);
630                    VariableValue::Bool(dt1 < dt2)
631                }
632                (VariableValue::ZonedTime(time1), VariableValue::ZonedTime(time2)) => {
633                    let dt1 = match NaiveDateTime::new(
634                        *temporal_constants::EPOCH_NAIVE_DATE,
635                        *time1.time(),
636                    )
637                    .and_local_timezone(*time1.offset())
638                    {
639                        LocalResult::Single(dt) => dt,
640                        _ => {
641                            return Err(EvaluationError::InvalidType {
642                                expected: "Time".to_string(),
643                            })
644                        }
645                    };
646                    let dt2 = match NaiveDateTime::new(
647                        *temporal_constants::EPOCH_NAIVE_DATE,
648                        *time2.time(),
649                    )
650                    .and_local_timezone(*time2.offset())
651                    {
652                        LocalResult::Single(dt) => dt,
653                        _ => {
654                            return Err(EvaluationError::InvalidType {
655                                expected: "Time".to_string(),
656                            })
657                        }
658                    };
659                    VariableValue::Bool(dt1 < dt2)
660                }
661                (VariableValue::ZonedDateTime(zdt1), VariableValue::ZonedDateTime(zdt2)) => {
662                    VariableValue::Bool(zdt1.datetime() < zdt2.datetime())
663                }
664                (VariableValue::ZonedDateTime(zdt1), VariableValue::Date(date2)) => {
665                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
666                    VariableValue::Bool(zdt1.datetime() < &dt2.and_utc())
667                }
668                (VariableValue::ZonedDateTime(zdt1), VariableValue::LocalDateTime(dt2)) => {
669                    VariableValue::Bool(zdt1.datetime().naive_utc() < dt2)
670                }
671                (VariableValue::ZonedDateTime(zdt1), VariableValue::LocalTime(time2)) => {
672                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
673                    VariableValue::Bool(zdt1.datetime() < &dt2.and_utc())
674                }
675                (VariableValue::ZonedDateTime(zdt1), VariableValue::ZonedTime(time2)) => {
676                    let dt2 =
677                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time2.time());
678                    let zdt2 = match dt2.and_local_timezone(*time2.offset()) {
679                        LocalResult::Single(dt) => dt,
680                        _ => {
681                            return Err(EvaluationError::InvalidType {
682                                expected: "Time".to_string(),
683                            })
684                        }
685                    };
686                    VariableValue::Bool(zdt1.datetime() < &zdt2)
687                }
688                (VariableValue::ZonedTime(time1), VariableValue::ZonedDateTime(zdt2)) => {
689                    let dt1 =
690                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
691                    let zdt1 = match dt1.and_local_timezone(*time1.offset()) {
692                        LocalResult::Single(dt) => dt,
693                        _ => {
694                            return Err(EvaluationError::InvalidType {
695                                expected: "DateTiie".to_string(),
696                            })
697                        }
698                    };
699                    VariableValue::Bool(zdt1 < *zdt2.datetime())
700                }
701                (VariableValue::ZonedTime(time1), VariableValue::Date(date2)) => {
702                    let dt1 =
703                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
704                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
705                    VariableValue::Bool(dt1 < dt2)
706                }
707                (VariableValue::ZonedTime(time1), VariableValue::LocalDateTime(dt2)) => {
708                    let dt1 =
709                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
710                    VariableValue::Bool(dt1 < dt2)
711                }
712                (VariableValue::ZonedTime(time1), VariableValue::LocalTime(time2)) => {
713                    let dt1 =
714                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
715                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
716                    VariableValue::Bool(dt1 < dt2)
717                }
718                (VariableValue::Duration(d1), VariableValue::Duration(d2)) => {
719                    let year1 = d1.year();
720                    let year2 = d2.year();
721                    let month1 = d1.month() + year1 * 12;
722                    let month2 = d2.month() + year2 * 12;
723                    // assume 30 days per month?
724                    VariableValue::Bool(
725                        *d1.duration() + Duration::days(30 * month1)
726                            < *d2.duration() + Duration::days(30 * month2),
727                    )
728                }
729                _ => VariableValue::Bool(false),
730            },
731            ast::BinaryExpression::Le(e1, e2) => match (
732                self.evaluate_expression(context, e1).await?,
733                self.evaluate_expression(context, e2).await?,
734            ) {
735                (VariableValue::Integer(n1), VariableValue::Integer(n2)) => VariableValue::Bool(
736                    n1.as_i64().unwrap_or_default() <= n2.as_i64().unwrap_or_default(),
737                ),
738                (VariableValue::Float(n1), VariableValue::Float(n2)) => VariableValue::Bool(
739                    n1.as_f64().unwrap_or_default() <= n2.as_f64().unwrap_or_default(),
740                ),
741                (VariableValue::Float(n1), VariableValue::Integer(n2)) => VariableValue::Bool(
742                    n1.as_f64().unwrap_or_default() <= n2.as_i64().unwrap_or_default() as f64,
743                ),
744                (VariableValue::Integer(n1), VariableValue::Float(n2)) => VariableValue::Bool(
745                    n1.as_i64().unwrap_or_default() as f64 <= n2.as_f64().unwrap_or_default(),
746                ),
747                (VariableValue::ZonedDateTime(zdt1), VariableValue::ZonedDateTime(zdt2)) => {
748                    VariableValue::Bool(zdt1.datetime() <= zdt2.datetime())
749                }
750                (VariableValue::Date(date1), VariableValue::Date(date2)) => {
751                    VariableValue::Bool(date1 <= date2)
752                }
753                (VariableValue::LocalTime(time1), VariableValue::LocalTime(time2)) => {
754                    VariableValue::Bool(time1 <= time2)
755                }
756                (VariableValue::LocalDateTime(dt1), VariableValue::LocalDateTime(dt2)) => {
757                    VariableValue::Bool(dt1 <= dt2)
758                }
759                (VariableValue::LocalDateTime(dt1), VariableValue::Date(date2)) => {
760                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
761                    VariableValue::Bool(dt1 <= dt2)
762                }
763                (VariableValue::LocalDateTime(dt1), VariableValue::LocalTime(time2)) => {
764                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
765                    VariableValue::Bool(dt1 <= dt2)
766                }
767                (VariableValue::LocalTime(time1), VariableValue::LocalDateTime(dt2)) => {
768                    let dt1 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time1);
769                    VariableValue::Bool(dt1 <= dt2)
770                }
771                (VariableValue::Date(date1), VariableValue::LocalDateTime(dt2)) => {
772                    let dt1 = NaiveDateTime::new(date1, *MIDNIGHT_NAIVE_TIME);
773                    VariableValue::Bool(dt1 <= dt2)
774                }
775                (VariableValue::ZonedTime(time1), VariableValue::ZonedTime(time2)) => {
776                    let dt1 = match NaiveDateTime::new(
777                        *temporal_constants::EPOCH_NAIVE_DATE,
778                        *time1.time(),
779                    )
780                    .and_local_timezone(*time1.offset())
781                    {
782                        LocalResult::Single(dt) => dt,
783                        _ => {
784                            return Err(EvaluationError::InvalidType {
785                                expected: "Time".to_string(),
786                            })
787                        }
788                    };
789                    let dt2 = match NaiveDateTime::new(
790                        *temporal_constants::EPOCH_NAIVE_DATE,
791                        *time2.time(),
792                    )
793                    .and_local_timezone(*time2.offset())
794                    {
795                        LocalResult::Single(dt) => dt,
796                        _ => {
797                            return Err(EvaluationError::InvalidType {
798                                expected: "Time".to_string(),
799                            })
800                        }
801                    };
802                    VariableValue::Bool(dt1 <= dt2)
803                }
804                (VariableValue::ZonedDateTime(zdt1), VariableValue::Date(date2)) => {
805                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
806                    VariableValue::Bool(zdt1.datetime() <= &dt2.and_utc())
807                }
808                (VariableValue::ZonedDateTime(zdt1), VariableValue::LocalDateTime(dt2)) => {
809                    VariableValue::Bool(zdt1.datetime().naive_utc() <= dt2)
810                }
811                (VariableValue::ZonedDateTime(zdt1), VariableValue::LocalTime(time2)) => {
812                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
813                    VariableValue::Bool(zdt1.datetime() <= &dt2.and_utc())
814                }
815                (VariableValue::ZonedDateTime(zdt1), VariableValue::ZonedTime(time2)) => {
816                    let dt2 =
817                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time2.time());
818                    let zdt2 = match dt2.and_local_timezone(*time2.offset()) {
819                        LocalResult::Single(dt) => dt,
820                        _ => {
821                            return Err(EvaluationError::InvalidType {
822                                expected: "Time".to_string(),
823                            })
824                        }
825                    };
826                    VariableValue::Bool(zdt1.datetime() <= &zdt2)
827                }
828                (VariableValue::ZonedTime(time1), VariableValue::ZonedDateTime(zdt2)) => {
829                    let dt1 =
830                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
831                    let zdt1 = match dt1.and_local_timezone(*time1.offset()) {
832                        LocalResult::Single(dt) => dt,
833                        _ => {
834                            return Err(EvaluationError::InvalidType {
835                                expected: "DateTime".to_string(),
836                            })
837                        }
838                    };
839                    VariableValue::Bool(zdt1 <= *zdt2.datetime())
840                }
841                (VariableValue::ZonedTime(time1), VariableValue::Date(date2)) => {
842                    let dt1 =
843                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
844                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
845                    VariableValue::Bool(dt1 <= dt2)
846                }
847                (VariableValue::ZonedTime(time1), VariableValue::LocalDateTime(dt2)) => {
848                    let dt1 =
849                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
850                    VariableValue::Bool(dt1 <= dt2)
851                }
852                (VariableValue::ZonedTime(time1), VariableValue::LocalTime(time2)) => {
853                    let dt1 =
854                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
855                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
856                    VariableValue::Bool(dt1 <= dt2)
857                }
858                (VariableValue::Duration(d1), VariableValue::Duration(d2)) => {
859                    let year1 = d1.year();
860                    let year2 = d2.year();
861                    let month1 = d1.month() + year1 * 12;
862                    let month2 = d2.month() + year2 * 12;
863                    // assume 30 days per month?
864                    VariableValue::Bool(
865                        *d1.duration() + Duration::days(30 * month1)
866                            <= *d2.duration() + Duration::days(30 * month2),
867                    )
868                }
869                _ => VariableValue::Bool(false),
870            },
871            ast::BinaryExpression::Gt(e1, e2) => match (
872                self.evaluate_expression(context, e1).await?,
873                self.evaluate_expression(context, e2).await?,
874            ) {
875                (VariableValue::Integer(n1), VariableValue::Integer(n2)) => VariableValue::Bool(
876                    n1.as_i64().unwrap_or_default() > n2.as_i64().unwrap_or_default(),
877                ),
878                (VariableValue::Float(n1), VariableValue::Float(n2)) => VariableValue::Bool(
879                    n1.as_f64().unwrap_or_default() > n2.as_f64().unwrap_or_default(),
880                ),
881                (VariableValue::Float(n1), VariableValue::Integer(n2)) => VariableValue::Bool(
882                    n1.as_f64().unwrap_or_default() > n2.as_i64().unwrap_or_default() as f64,
883                ),
884                (VariableValue::Integer(n1), VariableValue::Float(n2)) => VariableValue::Bool(
885                    n1.as_i64().unwrap_or_default() as f64 > n2.as_f64().unwrap_or_default(),
886                ),
887                (VariableValue::Date(date1), VariableValue::Date(date2)) => {
888                    VariableValue::Bool(date1 > date2)
889                }
890                (VariableValue::LocalTime(time1), VariableValue::LocalTime(time2)) => {
891                    VariableValue::Bool(time1 > time2)
892                }
893                (VariableValue::LocalDateTime(dt1), VariableValue::LocalDateTime(dt2)) => {
894                    VariableValue::Bool(dt1 > dt2)
895                }
896                (VariableValue::LocalDateTime(dt1), VariableValue::Date(date2)) => {
897                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
898                    VariableValue::Bool(dt1 > dt2)
899                }
900                (VariableValue::LocalDateTime(dt1), VariableValue::LocalTime(time2)) => {
901                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
902                    VariableValue::Bool(dt1 > dt2)
903                }
904                (VariableValue::LocalTime(time1), VariableValue::LocalDateTime(dt2)) => {
905                    let dt1 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time1);
906                    VariableValue::Bool(dt1 > dt2)
907                }
908                (VariableValue::Date(date1), VariableValue::LocalDateTime(dt2)) => {
909                    let dt1 = NaiveDateTime::new(date1, *MIDNIGHT_NAIVE_TIME);
910                    VariableValue::Bool(dt1 > dt2)
911                }
912                (VariableValue::ZonedTime(time1), VariableValue::ZonedTime(time2)) => {
913                    let dt1 = match NaiveDateTime::new(
914                        *temporal_constants::EPOCH_NAIVE_DATE,
915                        *time1.time(),
916                    )
917                    .and_local_timezone(*time1.offset())
918                    {
919                        LocalResult::Single(dt) => dt,
920                        _ => {
921                            return Err(EvaluationError::InvalidType {
922                                expected: "Time".to_string(),
923                            })
924                        }
925                    };
926                    let dt2 = match NaiveDateTime::new(
927                        *temporal_constants::EPOCH_NAIVE_DATE,
928                        *time2.time(),
929                    )
930                    .and_local_timezone(*time2.offset())
931                    {
932                        LocalResult::Single(dt) => dt,
933                        _ => {
934                            return Err(EvaluationError::InvalidType {
935                                expected: "Time".to_string(),
936                            })
937                        }
938                    };
939
940                    VariableValue::Bool(dt1 > dt2)
941                }
942                (VariableValue::ZonedDateTime(zdt1), VariableValue::ZonedDateTime(zdt2)) => {
943                    VariableValue::Bool(zdt1.datetime() > zdt2.datetime())
944                }
945                (VariableValue::ZonedDateTime(zdt1), VariableValue::Date(date2)) => {
946                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
947                    VariableValue::Bool(zdt1.datetime() > &dt2.and_utc())
948                }
949                (VariableValue::ZonedDateTime(zdt1), VariableValue::LocalDateTime(dt2)) => {
950                    VariableValue::Bool(zdt1.datetime().naive_utc() > dt2)
951                }
952                (VariableValue::ZonedDateTime(zdt1), VariableValue::LocalTime(time2)) => {
953                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
954                    VariableValue::Bool(zdt1.datetime() > &dt2.and_utc())
955                }
956                (VariableValue::ZonedDateTime(zdt1), VariableValue::ZonedTime(time2)) => {
957                    let dt2 =
958                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time2.time());
959                    let zdt2 = match dt2.and_local_timezone(*time2.offset()) {
960                        LocalResult::Single(dt) => dt,
961                        _ => {
962                            return Err(EvaluationError::InvalidType {
963                                expected: "Time".to_string(),
964                            })
965                        }
966                    };
967                    VariableValue::Bool(zdt1.datetime() > &zdt2)
968                }
969                (VariableValue::ZonedTime(time1), VariableValue::ZonedDateTime(zdt2)) => {
970                    let dt1 =
971                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
972                    let zdt1 = match dt1.and_local_timezone(*time1.offset()) {
973                        LocalResult::Single(dt) => dt,
974                        _ => {
975                            return Err(EvaluationError::InvalidType {
976                                expected: "Time".to_string(),
977                            })
978                        }
979                    };
980                    VariableValue::Bool(zdt1 > *zdt2.datetime())
981                }
982                (VariableValue::ZonedTime(time1), VariableValue::Date(date2)) => {
983                    let dt1 =
984                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
985                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
986                    VariableValue::Bool(dt1 > dt2)
987                }
988                (VariableValue::ZonedTime(time1), VariableValue::LocalDateTime(dt2)) => {
989                    let dt1 =
990                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
991                    VariableValue::Bool(dt1 > dt2)
992                }
993                (VariableValue::Date(date1), VariableValue::ZonedDateTime(zdt2)) => {
994                    let dt1 = NaiveDateTime::new(date1, *MIDNIGHT_NAIVE_TIME);
995                    VariableValue::Bool(&dt1.and_utc() > zdt2.datetime())
996                }
997                (VariableValue::Date(date1), VariableValue::LocalTime(time2)) => {
998                    let dt1 = NaiveDateTime::new(date1, *MIDNIGHT_NAIVE_TIME);
999                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
1000                    VariableValue::Bool(dt1 > dt2)
1001                }
1002                (VariableValue::Date(date1), VariableValue::ZonedTime(time2)) => {
1003                    let dt1 = NaiveDateTime::new(date1, *MIDNIGHT_NAIVE_TIME);
1004                    let dt2 =
1005                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time2.time());
1006                    let zdt2 = match dt2.and_local_timezone(*time2.offset()) {
1007                        LocalResult::Single(dt) => dt,
1008                        _ => {
1009                            return Err(EvaluationError::InvalidType {
1010                                expected: "Time".to_string(),
1011                            })
1012                        }
1013                    };
1014                    VariableValue::Bool(dt1.and_utc() > zdt2)
1015                }
1016                (VariableValue::ZonedTime(time1), VariableValue::LocalTime(time2)) => {
1017                    let dt1 =
1018                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
1019                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
1020                    VariableValue::Bool(dt1 > dt2)
1021                }
1022                (VariableValue::Duration(d1), VariableValue::Duration(d2)) => {
1023                    let year1 = d1.year();
1024                    let year2 = d2.year();
1025                    let month1 = d1.month() + year1 * 12;
1026                    let month2 = d2.month() + year2 * 12;
1027                    // assume 30 days per month?
1028                    VariableValue::Bool(
1029                        *d1.duration() + Duration::days(30 * month1)
1030                            > *d2.duration() + Duration::days(30 * month2),
1031                    )
1032                }
1033                _ => VariableValue::Bool(false),
1034            },
1035            ast::BinaryExpression::Ge(e1, e2) => match (
1036                self.evaluate_expression(context, e1).await?,
1037                self.evaluate_expression(context, e2).await?,
1038            ) {
1039                (VariableValue::Integer(n1), VariableValue::Integer(n2)) => VariableValue::Bool(
1040                    n1.as_i64().unwrap_or_default() >= n2.as_i64().unwrap_or_default(),
1041                ),
1042                (VariableValue::Float(n1), VariableValue::Float(n2)) => VariableValue::Bool(
1043                    n1.as_f64().unwrap_or_default() >= n2.as_f64().unwrap_or_default(),
1044                ),
1045                (VariableValue::Float(n1), VariableValue::Integer(n2)) => VariableValue::Bool(
1046                    n1.as_f64().unwrap_or_default() >= n2.as_i64().unwrap_or_default() as f64,
1047                ),
1048                (VariableValue::Integer(n1), VariableValue::Float(n2)) => VariableValue::Bool(
1049                    n1.as_i64().unwrap_or_default() as f64 >= n2.as_f64().unwrap_or_default(),
1050                ),
1051                (VariableValue::Date(date1), VariableValue::Date(date2)) => {
1052                    VariableValue::Bool(date1 >= date2)
1053                }
1054                (VariableValue::LocalTime(time1), VariableValue::LocalTime(time2)) => {
1055                    VariableValue::Bool(time1 >= time2)
1056                }
1057                (VariableValue::LocalDateTime(dt1), VariableValue::LocalDateTime(dt2)) => {
1058                    VariableValue::Bool(dt1 >= dt2)
1059                }
1060                (VariableValue::LocalDateTime(dt1), VariableValue::Date(date2)) => {
1061                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
1062                    VariableValue::Bool(dt1 >= dt2)
1063                }
1064                (VariableValue::LocalDateTime(dt1), VariableValue::LocalTime(time2)) => {
1065                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
1066                    VariableValue::Bool(dt1 >= dt2)
1067                }
1068                (VariableValue::LocalTime(time1), VariableValue::LocalDateTime(dt2)) => {
1069                    let dt1 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time1);
1070                    VariableValue::Bool(dt1 >= dt2)
1071                }
1072                (VariableValue::Date(date1), VariableValue::LocalDateTime(dt2)) => {
1073                    let dt1 = NaiveDateTime::new(date1, *MIDNIGHT_NAIVE_TIME);
1074                    VariableValue::Bool(dt1 >= dt2)
1075                }
1076                (VariableValue::LocalDateTime(dt1), VariableValue::ZonedDateTime(zdt2)) => {
1077                    VariableValue::Bool(dt1 >= zdt2.datetime().naive_utc())
1078                }
1079                (VariableValue::ZonedDateTime(zdt1), VariableValue::Date(date2)) => {
1080                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
1081                    VariableValue::Bool(zdt1.datetime() >= &dt2.and_utc())
1082                }
1083                (VariableValue::ZonedDateTime(zdt1), VariableValue::LocalDateTime(dt2)) => {
1084                    VariableValue::Bool(zdt1.datetime().naive_utc() >= dt2)
1085                }
1086                (VariableValue::ZonedDateTime(zdt1), VariableValue::LocalTime(time2)) => {
1087                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
1088                    VariableValue::Bool(zdt1.datetime() >= &dt2.and_utc())
1089                }
1090                (VariableValue::ZonedDateTime(zdt1), VariableValue::ZonedTime(time2)) => {
1091                    let dt2 =
1092                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time2.time());
1093                    let zdt2 = match dt2.and_local_timezone(*time2.offset()) {
1094                        LocalResult::Single(dt) => dt,
1095                        _ => {
1096                            return Err(EvaluationError::InvalidType {
1097                                expected: "Time".to_string(),
1098                            })
1099                        }
1100                    };
1101                    VariableValue::Bool(zdt1.datetime() >= &zdt2)
1102                }
1103                (VariableValue::ZonedTime(time1), VariableValue::ZonedDateTime(zdt2)) => {
1104                    let dt1 =
1105                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
1106                    let zdt1 = match dt1.and_local_timezone(zdt2.datetime().timezone()) {
1107                        LocalResult::Single(dt) => dt,
1108                        _ => {
1109                            return Err(EvaluationError::InvalidType {
1110                                expected: "Time".to_string(),
1111                            })
1112                        }
1113                    };
1114                    VariableValue::Bool(zdt1 >= *zdt2.datetime())
1115                }
1116                (VariableValue::ZonedTime(time1), VariableValue::Date(date2)) => {
1117                    let dt1 =
1118                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
1119                    let dt2 = NaiveDateTime::new(date2, *MIDNIGHT_NAIVE_TIME);
1120                    VariableValue::Bool(dt1 >= dt2)
1121                }
1122                (VariableValue::ZonedTime(time1), VariableValue::LocalDateTime(dt2)) => {
1123                    let dt1 =
1124                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
1125                    VariableValue::Bool(dt1 >= dt2)
1126                }
1127                (VariableValue::ZonedTime(time1), VariableValue::LocalTime(time2)) => {
1128                    let dt1 =
1129                        NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, *time1.time());
1130                    let dt2 = NaiveDateTime::new(*temporal_constants::EPOCH_NAIVE_DATE, time2);
1131                    VariableValue::Bool(dt1 >= dt2)
1132                }
1133                (VariableValue::ZonedTime(time1), VariableValue::ZonedTime(time2)) => {
1134                    let dt1 = match NaiveDateTime::new(
1135                        *temporal_constants::EPOCH_NAIVE_DATE,
1136                        *time1.time(),
1137                    )
1138                    .and_local_timezone(*time1.offset())
1139                    {
1140                        LocalResult::Single(dt) => dt,
1141                        _ => {
1142                            return Err(EvaluationError::InvalidType {
1143                                expected: "Time".to_string(),
1144                            })
1145                        }
1146                    };
1147                    let dt2 = match NaiveDateTime::new(
1148                        *temporal_constants::EPOCH_NAIVE_DATE,
1149                        *time2.time(),
1150                    )
1151                    .and_local_timezone(*time2.offset())
1152                    {
1153                        LocalResult::Single(dt) => dt,
1154                        _ => {
1155                            return Err(EvaluationError::InvalidType {
1156                                expected: "Time".to_string(),
1157                            })
1158                        }
1159                    };
1160                    VariableValue::Bool(dt1 >= dt2)
1161                }
1162                (VariableValue::Duration(d1), VariableValue::Duration(d2)) => {
1163                    let year1 = d1.year();
1164                    let year2 = d2.year();
1165                    let month1 = d1.month() + year1 * 12;
1166                    let month2 = d2.month() + year2 * 12;
1167                    // assume 30 days per month?
1168                    VariableValue::Bool(
1169                        *d1.duration() + Duration::days(30 * month1)
1170                            >= *d2.duration() + Duration::days(30 * month2),
1171                    )
1172                }
1173                (VariableValue::ZonedDateTime(zdt1), VariableValue::ZonedDateTime(zdt2)) => {
1174                    VariableValue::Bool(zdt1.datetime() >= zdt2.datetime())
1175                }
1176                _ => VariableValue::Bool(false),
1177            },
1178            ast::BinaryExpression::Add(e1, e2) => {
1179                let n1 = self.evaluate_expression(context, e1).await?;
1180                let n2 = self.evaluate_expression(context, e2).await?;
1181                match (n1, n2) {
1182                    (VariableValue::Integer(n1), VariableValue::Integer(n2)) => {
1183                        VariableValue::Integer(Integer::from(
1184                            n1.as_i64().unwrap_or_default() + n2.as_i64().unwrap_or_default(),
1185                        ))
1186                    }
1187                    (VariableValue::Float(n1), VariableValue::Float(n2)) => {
1188                        VariableValue::Float(Float::from(
1189                            n1.as_f64().unwrap_or_default() + n2.as_f64().unwrap_or_default(),
1190                        ))
1191                    }
1192                    (VariableValue::Float(n1), VariableValue::Integer(n2)) => {
1193                        VariableValue::Float(Float::from(
1194                            n1.as_f64().unwrap_or_default()
1195                                + n2.as_i64().unwrap_or_default() as f64,
1196                        ))
1197                    }
1198                    (VariableValue::Integer(n1), VariableValue::Float(n2)) => {
1199                        VariableValue::Float(Float::from(
1200                            n1.as_i64().unwrap_or_default() as f64
1201                                + n2.as_f64().unwrap_or_default(),
1202                        ))
1203                    }
1204                    (VariableValue::Integer(n1), VariableValue::String(s2)) => {
1205                        VariableValue::String(n1.to_string() + &s2)
1206                    }
1207                    (VariableValue::Float(n1), VariableValue::String(s2)) => {
1208                        VariableValue::String(n1.to_string() + &s2)
1209                    }
1210                    (VariableValue::String(s1), VariableValue::Bool(b2)) => {
1211                        VariableValue::String(s1 + &b2.to_string())
1212                    }
1213                    (VariableValue::String(s1), VariableValue::Integer(n2)) => {
1214                        VariableValue::String(s1 + &n2.to_string())
1215                    }
1216                    (VariableValue::String(s1), VariableValue::Float(n2)) => {
1217                        VariableValue::String(s1 + &n2.to_string())
1218                    }
1219                    (VariableValue::String(s1), VariableValue::String(s2)) => {
1220                        VariableValue::String(s1 + &s2)
1221                    }
1222                    (VariableValue::Date(date), VariableValue::Duration(duration)) => date
1223                        .checked_add_signed(*duration.duration())
1224                        .map_or(VariableValue::Null, |new_date| {
1225                            VariableValue::Date(new_date)
1226                        }),
1227                    (VariableValue::LocalTime(time), VariableValue::Duration(duration)) => {
1228                        let new_time = time + *duration.duration();
1229                        VariableValue::LocalTime(new_time)
1230                    }
1231                    (VariableValue::LocalDateTime(dt), VariableValue::Duration(duration)) => dt
1232                        .checked_add_signed(*duration.duration())
1233                        .map_or(VariableValue::Null, |new_dt| {
1234                            VariableValue::LocalDateTime(new_dt)
1235                        }),
1236                    (VariableValue::ZonedTime(time), VariableValue::Duration(duration)) => {
1237                        let new_time = *time.time() + *duration.duration();
1238                        VariableValue::ZonedTime(ZonedTime::new(new_time, *time.offset()))
1239                    }
1240                    (VariableValue::ZonedDateTime(zdt), VariableValue::Duration(d)) => zdt
1241                        .datetime()
1242                        .checked_add_signed(*d.duration())
1243                        .map_or(VariableValue::Null, |new_zdt| {
1244                            VariableValue::ZonedDateTime(ZonedDateTime::new(
1245                                new_zdt,
1246                                zdt.timezone().clone(),
1247                            ))
1248                        }),
1249                    (VariableValue::Duration(duration1), VariableValue::Duration(duration2)) => {
1250                        VariableValue::Duration(duration1 + duration2)
1251                    }
1252                    _ => VariableValue::Null,
1253                }
1254            }
1255            ast::BinaryExpression::Subtract(e1, e2) => {
1256                let n1 = self.evaluate_expression(context, e1).await?;
1257                let n2 = self.evaluate_expression(context, e2).await?;
1258                match (n1, n2) {
1259                    (VariableValue::Integer(n1), VariableValue::Integer(n2)) => {
1260                        VariableValue::Integer(Integer::from(
1261                            n1.as_i64().unwrap_or_default() - n2.as_i64().unwrap_or_default(),
1262                        ))
1263                    }
1264                    (VariableValue::Float(n1), VariableValue::Float(n2)) => {
1265                        VariableValue::Float(Float::from(
1266                            n1.as_f64().unwrap_or_default() - n2.as_f64().unwrap_or_default(),
1267                        ))
1268                    }
1269                    (VariableValue::Float(n1), VariableValue::Integer(n2)) => {
1270                        VariableValue::Float(Float::from(
1271                            n1.as_f64().unwrap_or_default()
1272                                - n2.as_i64().unwrap_or_default() as f64,
1273                        ))
1274                    }
1275                    (VariableValue::Integer(n1), VariableValue::Float(n2)) => {
1276                        VariableValue::Float(Float::from(
1277                            n1.as_i64().unwrap_or_default() as f64
1278                                - n2.as_f64().unwrap_or_default(),
1279                        ))
1280                    }
1281                    (VariableValue::Date(date), VariableValue::Duration(duration)) => date
1282                        .checked_sub_signed(*duration.duration())
1283                        .map_or(VariableValue::Null, |new_date| {
1284                            VariableValue::Date(new_date)
1285                        }),
1286                    (VariableValue::LocalTime(time), VariableValue::Duration(duration)) => {
1287                        let new_time = time - *duration.duration();
1288                        VariableValue::LocalTime(new_time)
1289                    }
1290                    (VariableValue::LocalDateTime(dt), VariableValue::Duration(duration)) => dt
1291                        .checked_sub_signed(*duration.duration())
1292                        .map_or(VariableValue::Null, |new_dt| {
1293                            VariableValue::LocalDateTime(new_dt)
1294                        }),
1295                    (VariableValue::ZonedTime(time), VariableValue::Duration(duration)) => {
1296                        let new_time = *time.time() - *duration.duration();
1297                        VariableValue::ZonedTime(ZonedTime::new(new_time, *time.offset()))
1298                    }
1299                    (VariableValue::ZonedDateTime(zdt), VariableValue::Duration(d)) => zdt
1300                        .datetime()
1301                        .checked_sub_signed(*d.duration())
1302                        .map_or(VariableValue::Null, |new_zdt| {
1303                            VariableValue::ZonedDateTime(ZonedDateTime::new(
1304                                new_zdt,
1305                                zdt.timezone().clone(),
1306                            ))
1307                        }),
1308                    (VariableValue::Duration(duration1), VariableValue::Duration(duration2)) => {
1309                        VariableValue::Duration(duration1 - duration2)
1310                    }
1311                    _ => VariableValue::Null,
1312                }
1313            }
1314            ast::BinaryExpression::Multiply(e1, e2) => {
1315                let n1 = self.evaluate_expression(context, e1).await?;
1316                let n2 = self.evaluate_expression(context, e2).await?;
1317                match (n1, n2) {
1318                    (VariableValue::Integer(n1), VariableValue::Integer(n2)) => {
1319                        VariableValue::Integer(Integer::from(
1320                            n1.as_i64().unwrap_or_default() * n2.as_i64().unwrap_or_default(),
1321                        ))
1322                    }
1323                    (VariableValue::Float(n1), VariableValue::Float(n2)) => {
1324                        VariableValue::Float(Float::from(
1325                            n1.as_f64().unwrap_or_default() * n2.as_f64().unwrap_or_default(),
1326                        ))
1327                    }
1328                    (VariableValue::Float(n1), VariableValue::Integer(n2)) => {
1329                        VariableValue::Float(Float::from(
1330                            n1.as_f64().unwrap_or_default()
1331                                * n2.as_i64().unwrap_or_default() as f64,
1332                        ))
1333                    }
1334                    (VariableValue::Integer(n1), VariableValue::Float(n2)) => {
1335                        VariableValue::Float(Float::from(
1336                            n1.as_i64().unwrap_or_default() as f64
1337                                * n2.as_f64().unwrap_or_default(),
1338                        ))
1339                    }
1340                    _ => VariableValue::Null,
1341                }
1342            }
1343            ast::BinaryExpression::Divide(e1, e2) => {
1344                let n1 = self.evaluate_expression(context, e1).await?;
1345                let n2 = self.evaluate_expression(context, e2).await?;
1346                match (n1, n2) {
1347                    (VariableValue::Integer(n1), VariableValue::Integer(n2)) => {
1348                        let m1 = n1.as_i64().ok_or(EvaluationError::OverflowError)?;
1349                        let m2 = n2.as_i64().ok_or(EvaluationError::OverflowError)?;
1350                        if m2 == 0 {
1351                            return Err(EvaluationError::DivideByZero);
1352                        } else {
1353                            VariableValue::Float(Float::from(m1 as f64 / m2 as f64))
1354                        }
1355                    }
1356                    (VariableValue::Float(n1), VariableValue::Float(n2)) => {
1357                        let m1 = n1.as_f64().ok_or(EvaluationError::OverflowError)?;
1358                        let m2 = n2.as_f64().ok_or(EvaluationError::OverflowError)?;
1359                        if m2 == 0.0 {
1360                            return Err(EvaluationError::DivideByZero);
1361                        } else {
1362                            VariableValue::Float(Float::from(m1 / m2))
1363                        }
1364                    }
1365                    (VariableValue::Float(n1), VariableValue::Integer(n2)) => {
1366                        let m1 = n1.as_f64().ok_or(EvaluationError::OverflowError)?;
1367                        let m2 = n2.as_i64().ok_or(EvaluationError::OverflowError)?;
1368                        if m2 == 0 {
1369                            return Err(EvaluationError::DivideByZero);
1370                        } else {
1371                            VariableValue::Float(Float::from(m1 / m2 as f64))
1372                        }
1373                    }
1374                    (VariableValue::Integer(n1), VariableValue::Float(n2)) => {
1375                        let m1 = n1.as_i64().ok_or(EvaluationError::OverflowError)?;
1376                        let m2 = n2.as_f64().ok_or(EvaluationError::OverflowError)?;
1377                        if m2 == 0.0 {
1378                            return Err(EvaluationError::DivideByZero);
1379                        } else {
1380                            VariableValue::Float(Float::from(m1 as f64 / m2))
1381                        }
1382                    }
1383                    _ => VariableValue::Null,
1384                }
1385            }
1386            ast::BinaryExpression::In(e1, e2) => {
1387                let e1 = self.evaluate_expression(context, e1).await?;
1388                match self.evaluate_expression(context, e2).await? {
1389                    VariableValue::List(a) => VariableValue::Bool(a.contains(&e1)),
1390                    _ => {
1391                        return Err(EvaluationError::InvalidType {
1392                            expected: "List".to_string(),
1393                        })
1394                    }
1395                }
1396            }
1397            ast::BinaryExpression::Modulo(e1, e2) => {
1398                let n1 = self.evaluate_expression(context, e1).await?;
1399                let n2 = self.evaluate_expression(context, e2).await?;
1400                match (n1, n2) {
1401                    (VariableValue::Integer(n1), VariableValue::Integer(n2)) => {
1402                        VariableValue::Integer(Integer::from(
1403                            n1.as_i64().unwrap_or_default() % n2.as_i64().unwrap_or_default(),
1404                        ))
1405                    }
1406                    (VariableValue::Float(n1), VariableValue::Float(n2)) => {
1407                        VariableValue::Float(Float::from(
1408                            n1.as_f64().unwrap_or_default() % n2.as_f64().unwrap_or_default(),
1409                        ))
1410                    }
1411                    (VariableValue::Float(n1), VariableValue::Integer(n2)) => {
1412                        VariableValue::Float(Float::from(
1413                            n1.as_f64().unwrap_or_default()
1414                                % n2.as_i64().unwrap_or_default() as f64,
1415                        ))
1416                    }
1417                    (VariableValue::Integer(n1), VariableValue::Float(n2)) => {
1418                        VariableValue::Float(Float::from(
1419                            n1.as_i64().unwrap_or_default() as f64
1420                                % n2.as_f64().unwrap_or_default(),
1421                        ))
1422                    }
1423                    _ => VariableValue::Null,
1424                }
1425            }
1426            ast::BinaryExpression::Exponent(e1, e2) => {
1427                let n1 = self.evaluate_expression(context, e1).await?;
1428                let n2 = self.evaluate_expression(context, e2).await?;
1429                match (n1, n2) {
1430                    (VariableValue::Integer(n1), VariableValue::Integer(n2)) => {
1431                        VariableValue::Integer(Integer::from(
1432                            n1.as_i64().unwrap_or_default().pow(
1433                                n2.as_i64()
1434                                    .unwrap_or_default()
1435                                    .try_into()
1436                                    .map_err(|_| EvaluationError::OverflowError)?,
1437                            ),
1438                        ))
1439                    }
1440                    (VariableValue::Float(n1), VariableValue::Float(n2)) => {
1441                        VariableValue::Float(Float::from(
1442                            n1.as_f64()
1443                                .unwrap_or_default()
1444                                .powf(n2.as_f64().unwrap_or_default()),
1445                        ))
1446                    }
1447                    (VariableValue::Float(n1), VariableValue::Integer(n2)) => {
1448                        VariableValue::Float(Float::from(
1449                            n1.as_f64()
1450                                .unwrap_or_default()
1451                                .powf(n2.as_i64().unwrap_or_default() as f64),
1452                        ))
1453                    }
1454                    (VariableValue::Integer(n1), VariableValue::Float(n2)) => {
1455                        VariableValue::Float(Float::from(
1456                            (n1.as_i64().unwrap_or_default() as f64)
1457                                .powf(n2.as_f64().unwrap_or_default()),
1458                        ))
1459                    }
1460                    _ => VariableValue::Null,
1461                }
1462            }
1463            ast::BinaryExpression::HasLabel(e1, e2) => {
1464                let subject = self.evaluate_expression(context, e1).await?;
1465                let label = match self.evaluate_expression(context, e2).await? {
1466                    VariableValue::String(s) => Arc::from(s),
1467                    _ => {
1468                        return Err(EvaluationError::InvalidType {
1469                            expected: "String".to_string(),
1470                        })
1471                    }
1472                };
1473
1474                match subject {
1475                    VariableValue::Element(n) => {
1476                        VariableValue::Bool(n.get_metadata().labels.contains(&label))
1477                    }
1478                    _ => VariableValue::Bool(false),
1479                }
1480            }
1481            ast::BinaryExpression::Index(e1, e2) => {
1482                let index_exp = self.evaluate_expression(context, e2).await?;
1483                let variable_value_list = self.evaluate_expression(context, e1).await?;
1484                let list = match variable_value_list.as_array() {
1485                    Some(list) => list,
1486                    None => {
1487                        return Err(EvaluationError::InvalidType {
1488                            expected: "List".to_string(),
1489                        })
1490                    }
1491                };
1492                match index_exp {
1493                    VariableValue::ListRange(list_range) => {
1494                        let start_bound = match list_range.start {
1495                            RangeBound::Index(index) => {
1496                                if index < 0 {
1497                                    index.abs() + 1
1498                                } else if index > list.len() as i64 {
1499                                    list.len() as i64
1500                                } else {
1501                                    index
1502                                }
1503                            }
1504                            RangeBound::Unbounded => 0,
1505                        };
1506                        let end_bound = match list_range.end {
1507                            RangeBound::Index(index) => {
1508                                if index > list.len() as i64 {
1509                                    list.len() as i64
1510                                } else if index < 0 {
1511                                    list.len() as i64 + index
1512                                } else {
1513                                    index
1514                                }
1515                            }
1516                            RangeBound::Unbounded => list.len() as i64,
1517                        };
1518                        let result = list[start_bound as usize..end_bound as usize].to_vec();
1519                        return Ok(VariableValue::List(result));
1520                    }
1521                    VariableValue::Integer(index) => {
1522                        let index_i64 = match index.as_i64() {
1523                            Some(index) => index,
1524                            None => {
1525                                return Err(EvaluationError::InvalidType {
1526                                    expected: "Integer".to_string(),
1527                                })
1528                            }
1529                        };
1530                        if index_i64 >= list.len() as i64 {
1531                            return Ok(VariableValue::Null);
1532                        }
1533                        if index_i64 < 0 {
1534                            let index_i64 = list.len() as i64 + index_i64;
1535                            let element = list[index_i64 as usize].clone();
1536                            return Ok(element);
1537                        }
1538                        let index = match index.as_i64() {
1539                            Some(index) => index as usize,
1540                            None => {
1541                                return Err(EvaluationError::InvalidType {
1542                                    expected: "Integer".to_string(),
1543                                })
1544                            }
1545                        };
1546                        let element = list[index].clone();
1547
1548                        return Ok(element);
1549                    }
1550                    _ => {
1551                        return Err(EvaluationError::InvalidType {
1552                            expected: "Integer or ListRange".to_string(),
1553                        })
1554                    }
1555                }
1556            }
1557        };
1558        Ok(result)
1559    }
1560
1561    async fn evaluate_function_expression(
1562        &self,
1563        context: &ExpressionEvaluationContext<'_>,
1564        expression: &ast::FunctionExpression,
1565    ) -> Result<VariableValue, EvaluationError> {
1566        let result = match self.functions.get_function(&expression.name) {
1567            Some(function) => match function.as_ref() {
1568                Function::Scalar(scalar) => {
1569                    let mut values = Vec::new();
1570                    for arg in &expression.args {
1571                        values.push(self.evaluate_expression(context, arg).await?);
1572                    }
1573                    scalar
1574                        .call(context, expression, values)
1575                        .await
1576                        .map_err(EvaluationError::FunctionError)?
1577                }
1578                Function::LazyScalar(scalar) => scalar
1579                    .call(context, expression, &expression.args)
1580                    .await
1581                    .map_err(EvaluationError::FunctionError)?,
1582                Function::Aggregating(aggregate) => {
1583                    let mut values = Vec::new();
1584                    for arg in &expression.args {
1585                        values.push(self.evaluate_expression(context, arg).await?);
1586                    }
1587                    let grouping_keys = Arc::new(match context.get_output_grouping_key() {
1588                        Some(group_expressions) => {
1589                            let mut grouping_keys = Vec::new();
1590                            for group_expression in group_expressions {
1591                                grouping_keys.push(
1592                                    self.evaluate_expression(context, group_expression).await?,
1593                                );
1594                            }
1595                            grouping_keys
1596                        }
1597                        None => Vec::new(),
1598                    });
1599
1600                    let result_key = ResultKey::GroupBy(grouping_keys.clone());
1601                    let result_owner = ResultOwner::Function(expression.position_in_query);
1602
1603                    let mut accumulator = {
1604                        if aggregate.accumulator_is_lazy() {
1605                            aggregate.initialize_accumulator(
1606                                context,
1607                                expression,
1608                                &grouping_keys,
1609                                self.result_index.clone(),
1610                            )
1611                        } else {
1612                            match self.result_index.get(&result_key, &result_owner).await? {
1613                                Some(acc) => Accumulator::Value(acc),
1614                                None => aggregate.initialize_accumulator(
1615                                    context,
1616                                    expression,
1617                                    &grouping_keys,
1618                                    self.result_index.clone(),
1619                                ),
1620                            }
1621                        }
1622                    };
1623
1624                    let result = match context.get_side_effects() {
1625                        SideEffects::Apply => aggregate
1626                            .apply(context, values, &mut accumulator)
1627                            .await
1628                            .map_err(EvaluationError::FunctionError)?,
1629                        SideEffects::RevertForUpdate | SideEffects::RevertForDelete => aggregate
1630                            .revert(context, values, &mut accumulator)
1631                            .await
1632                            .map_err(EvaluationError::FunctionError)?,
1633                        SideEffects::Snapshot => aggregate
1634                            .snapshot(context, values, &accumulator)
1635                            .await
1636                            .map_err(EvaluationError::FunctionError)?,
1637                    };
1638
1639                    //println!("{:?} {}{} : {:?}", context.get_side_effects(), expression.name, expression.position_in_query, result);
1640
1641                    match accumulator {
1642                        super::functions::aggregation::Accumulator::Value(va) => {
1643                            self.result_index
1644                                .set(result_key, result_owner, Some(va))
1645                                .await?
1646                        }
1647                        super::functions::aggregation::Accumulator::LazySortedSet(
1648                            mut accumulator,
1649                        ) => accumulator.commit().await?,
1650                    };
1651
1652                    result
1653                }
1654                Function::ContextMutator(context_mutator) => {
1655                    if expression.args.is_empty() {
1656                        VariableValue::Null
1657                    } else {
1658                        let new_context = match context_mutator.call(context, expression).await {
1659                            Ok(new_context) => new_context,
1660                            Err(e) => {
1661                                return Err(EvaluationError::FunctionError(e));
1662                            }
1663                        };
1664
1665                        self.evaluate_expression(&new_context, &expression.args[0])
1666                            .await?
1667                    }
1668                }
1669            },
1670            None => {
1671                return Err(EvaluationError::UnknownFunction(
1672                    expression.name.to_string(),
1673                ))
1674            }
1675        };
1676
1677        Ok(result)
1678    }
1679
1680    async fn evaluate_case_expression(
1681        &self,
1682        context: &ExpressionEvaluationContext<'_>,
1683        expression: &ast::CaseExpression,
1684    ) -> Result<VariableValue, EvaluationError> {
1685        let match_ = match expression.match_ {
1686            Some(ref match_) => Some(self.evaluate_expression(context, match_).await?),
1687            None => None,
1688        };
1689
1690        for when in &expression.when {
1691            match match_ {
1692                Some(ref match_) => {
1693                    let condition = self.evaluate_expression(context, &when.0).await?;
1694                    if condition == *match_ {
1695                        return self.evaluate_expression(context, &when.1).await;
1696                    }
1697                }
1698                None => {
1699                    let condition = self.evaluate_predicate(context, &when.0).await?;
1700                    if condition {
1701                        return self.evaluate_expression(context, &when.1).await;
1702                    }
1703                }
1704            }
1705        }
1706
1707        match expression.else_ {
1708            Some(ref else_) => Ok(self.evaluate_expression(context, else_).await?),
1709            None => Ok(VariableValue::Null),
1710        }
1711    }
1712
1713    async fn evaluate_list_expression(
1714        &self,
1715        context: &ExpressionEvaluationContext<'_>,
1716        expression: &ast::ListExpression,
1717    ) -> Result<VariableValue, EvaluationError> {
1718        let mut result = Vec::new();
1719        for e in &expression.elements {
1720            result.push(self.evaluate_expression(context, e).await?);
1721        }
1722
1723        Ok(VariableValue::List(result))
1724    }
1725
1726    async fn evaluate_object_expression(
1727        &self,
1728        context: &ExpressionEvaluationContext<'_>,
1729        expression: &ast::ObjectExpression,
1730    ) -> Result<VariableValue, EvaluationError> {
1731        let mut result = BTreeMap::new();
1732        for (key, value) in &expression.elements {
1733            result.insert(
1734                key.to_string(),
1735                self.evaluate_expression(context, value).await?,
1736            );
1737        }
1738
1739        Ok(VariableValue::Object(result))
1740    }
1741
1742    pub async fn evaluate_assignment(
1743        &self,
1744        context: &ExpressionEvaluationContext<'_>,
1745        expression: &ast::Expression,
1746    ) -> Result<(Arc<str>, VariableValue), FunctionEvaluationError> {
1747        match expression {
1748            ast::Expression::BinaryExpression(exp) => match exp {
1749                ast::BinaryExpression::Eq(var, val) => {
1750                    let variable = match *var.clone() {
1751                        ast::Expression::UnaryExpression(exp) => match exp {
1752                            ast::UnaryExpression::Identifier(ident) => ident,
1753                            _ => {
1754                                return Err(FunctionEvaluationError::InvalidType {
1755                                    expected: "Identifier expression".to_string(),
1756                                })
1757                            }
1758                        },
1759                        _ => {
1760                            return Err(FunctionEvaluationError::InvalidType {
1761                                expected: "Unary expression".to_string(),
1762                            })
1763                        }
1764                    };
1765                    let value = match self.evaluate_expression(context, val).await {
1766                        Ok(value) => value,
1767                        Err(_) => {
1768                            return Err(FunctionEvaluationError::InvalidType {
1769                                expected: "valid identifier expresssion".to_string(),
1770                            })
1771                        }
1772                    };
1773                    Ok((variable, value))
1774                }
1775                _ => Err(FunctionEvaluationError::InvalidType {
1776                    expected: "Eq expression".to_string(),
1777                }),
1778            },
1779            _ => Err(FunctionEvaluationError::InvalidType {
1780                expected: "Binary expression".to_string(),
1781            }),
1782        }
1783    }
1784
1785    async fn evaluate_iterator_expression(
1786        &self,
1787        context: &ExpressionEvaluationContext<'_>,
1788        expression: &ast::IteratorExpression,
1789    ) -> Result<VariableValue, EvaluationError> {
1790        let items = self
1791            .evaluate_expression(context, &expression.list_expression)
1792            .await?;
1793        match items {
1794            VariableValue::List(items) => {
1795                let mut result = Vec::new();
1796                let mut variables = context.clone_variables();
1797                for item in items {
1798                    if let Some(filter) = &expression.filter {
1799                        variables
1800                            .insert(expression.item_identifier.to_string().into(), item.clone());
1801                        let local_context =
1802                            ExpressionEvaluationContext::new(&variables, context.get_clock());
1803                        if !self.evaluate_predicate(&local_context, filter).await? {
1804                            continue;
1805                        }
1806                    }
1807
1808                    if let Some(map_expression) = &expression.map_expression {
1809                        variables
1810                            .insert(expression.item_identifier.to_string().into(), item.clone());
1811                        let local_context =
1812                            ExpressionEvaluationContext::new(&variables, context.get_clock());
1813                        let item_result = self
1814                            .evaluate_expression(&local_context, map_expression)
1815                            .await?;
1816                        result.push(item_result);
1817                    } else {
1818                        result.push(item);
1819                    }
1820                }
1821                Ok(VariableValue::List(result))
1822            }
1823            _ => Err(EvaluationError::InvalidType {
1824                expected: "List".to_string(),
1825            }),
1826        }
1827    }
1828
1829    pub async fn reduce_iterator_expression(
1830        &self,
1831        context: &ExpressionEvaluationContext<'_>,
1832        expression: &ast::IteratorExpression,
1833        accumulator_variable: Arc<str>,
1834    ) -> Result<VariableValue, EvaluationError> {
1835        let items = self
1836            .evaluate_expression(context, &expression.list_expression)
1837            .await?;
1838        match items {
1839            VariableValue::List(items) => {
1840                let mut result = match context.get_variable(accumulator_variable.clone()) {
1841                    Some(value) => value.clone(),
1842                    None => VariableValue::Null,
1843                };
1844                let mut variables = context.clone_variables();
1845                for item in items {
1846                    if let Some(filter) = &expression.filter {
1847                        variables
1848                            .insert(expression.item_identifier.to_string().into(), item.clone());
1849                        let local_context =
1850                            ExpressionEvaluationContext::new(&variables, context.get_clock());
1851
1852                        if !self.evaluate_predicate(&local_context, filter).await? {
1853                            continue;
1854                        }
1855                    }
1856
1857                    if let Some(map_expression) = &expression.map_expression {
1858                        variables
1859                            .insert(expression.item_identifier.to_string().into(), item.clone());
1860                        let local_context =
1861                            ExpressionEvaluationContext::new(&variables, context.get_clock());
1862                        result = self
1863                            .evaluate_expression(&local_context, map_expression)
1864                            .await?;
1865                        variables.insert(accumulator_variable.to_string().into(), result.clone());
1866                    }
1867                }
1868                Ok(result)
1869            }
1870            _ => Err(EvaluationError::InvalidType {
1871                expected: "List".to_string(),
1872            }),
1873        }
1874    }
1875}
1876
1877async fn get_date_property(date: NaiveDate, property: String) -> Option<u32> {
1878    match property.as_str() {
1879        "year" => Some(date.year() as u32),
1880        "month" => Some(date.month()),
1881        "day" => Some(date.day()),
1882        "quarter" => Some((date.month() - 1) / 3 + 1),
1883        "week" => Some(date.iso_week().week()),
1884        "dayOfWeek" => {
1885            let day_of_week = date.weekday();
1886            let day_of_week_num = match day_of_week {
1887                Weekday::Mon => 1,
1888                Weekday::Tue => 2,
1889                Weekday::Wed => 3,
1890                Weekday::Thu => 4,
1891                Weekday::Fri => 5,
1892                Weekday::Sat => 6,
1893                Weekday::Sun => 7,
1894            };
1895            Some(day_of_week_num)
1896        }
1897        "weekDay" => {
1898            let day_of_week = date.weekday();
1899            let day_of_week_num = match day_of_week {
1900                Weekday::Mon => 1,
1901                Weekday::Tue => 2,
1902                Weekday::Wed => 3,
1903                Weekday::Thu => 4,
1904                Weekday::Fri => 5,
1905                Weekday::Sat => 6,
1906                Weekday::Sun => 7,
1907            };
1908            Some(day_of_week_num)
1909        }
1910        "ordinalDay" => Some(date.ordinal()),
1911        "weekYear" => Some(date.iso_week().year() as u32),
1912        "dayOfQuarter" => {
1913            let quarter = (date.month() - 1) / 3 + 1;
1914            let start_date = match NaiveDate::from_ymd_opt(date.year(), (quarter - 1) * 3 + 1, 1) {
1915                Some(date) => date,
1916                None => return None,
1917            };
1918
1919            let duration = date - start_date;
1920            let num_days = duration.num_days();
1921            Some((num_days + 1) as u32)
1922        }
1923        "quarterDay" => {
1924            let quarter = (date.month() - 1) / 3 + 1;
1925            let start_date = match NaiveDate::from_ymd_opt(date.year(), (quarter - 1) * 3 + 1, 1) {
1926                Some(date) => date,
1927                None => return None,
1928            };
1929            let duration = date - start_date;
1930            let num_days = duration.num_days();
1931            Some((num_days + 1) as u32)
1932        }
1933        _ => None,
1934    }
1935}
1936
1937async fn get_local_time_property(time: NaiveTime, property: String) -> Option<u32> {
1938    match property.as_str() {
1939        "hour" => Some(time.hour()),
1940        "minute" => Some(time.minute()),
1941        "second" => Some(time.second()),
1942        "millisecond" => Some(time.nanosecond() / 1000000),
1943        "microsecond" => Some(time.nanosecond() / 1000),
1944        "nanosecond" => Some(time.nanosecond()),
1945        _ => None,
1946    }
1947}
1948
1949async fn get_time_property(zoned_time: ZonedTime, property: String) -> Option<String> {
1950    let time = zoned_time.time();
1951    let offset = zoned_time.offset();
1952    match property.as_str() {
1953        "hour" => Some(time.hour().to_string()),
1954        "minute" => Some(time.minute().to_string()),
1955        "second" => Some(time.second().to_string()),
1956        "millisecond" => Some((time.nanosecond() / 1000000).to_string()),
1957        "microsecond" => Some((time.nanosecond() / 1000).to_string()),
1958        "nanosecond" => Some(time.nanosecond().to_string()),
1959        "offset" => Some(offset.to_string()),
1960        "timezone" => Some(offset.to_string()),
1961        "offsetSeconds" => {
1962            let seconds = offset.local_minus_utc();
1963            Some(seconds.to_string())
1964        }
1965        "offsetMinutes" => {
1966            let minutes = offset.local_minus_utc() / 60;
1967            Some(minutes.to_string())
1968        }
1969        _ => None,
1970    }
1971}
1972
1973async fn get_local_datetime_property(datetime: NaiveDateTime, property: String) -> Option<u32> {
1974    let date = datetime.date();
1975    let time = datetime.time();
1976    match property.as_str() {
1977        "year" => Some(date.year() as u32),
1978        "month" => Some(date.month()),
1979        "day" => Some(date.day()),
1980        "quarter" => Some((date.month() - 1) / 3 + 1),
1981        "week" => Some(date.iso_week().week()),
1982        "dayOfWeek" => {
1983            let day_of_week = date.weekday();
1984            let day_of_week_num = match day_of_week {
1985                Weekday::Mon => 1,
1986                Weekday::Tue => 2,
1987                Weekday::Wed => 3,
1988                Weekday::Thu => 4,
1989                Weekday::Fri => 5,
1990                Weekday::Sat => 6,
1991                Weekday::Sun => 7,
1992            };
1993            Some(day_of_week_num)
1994        }
1995        "weekDay" => {
1996            let day_of_week = date.weekday();
1997            let day_of_week_num = match day_of_week {
1998                Weekday::Mon => 1,
1999                Weekday::Tue => 2,
2000                Weekday::Wed => 3,
2001                Weekday::Thu => 4,
2002                Weekday::Fri => 5,
2003                Weekday::Sat => 6,
2004                Weekday::Sun => 7,
2005            };
2006            Some(day_of_week_num)
2007        }
2008        "ordinalDay" => Some(date.ordinal()),
2009        "weekYear" => Some(date.iso_week().year() as u32),
2010        "dayOfQuarter" => {
2011            let quarter = (date.month() - 1) / 3 + 1;
2012            let start_date = match NaiveDate::from_ymd_opt(date.year(), (quarter - 1) * 3 + 1, 1) {
2013                Some(date) => date,
2014                None => return None,
2015            };
2016            let duration = date - start_date;
2017            let num_days = duration.num_days();
2018            Some((num_days + 1) as u32)
2019        }
2020        "quarterDay" => {
2021            let quarter = (date.month() - 1) / 3 + 1;
2022            let start_date = match NaiveDate::from_ymd_opt(date.year(), (quarter - 1) * 3 + 1, 1) {
2023                Some(date) => date,
2024                None => return None,
2025            };
2026            let duration = date - start_date;
2027            let num_days = duration.num_days();
2028            Some((num_days + 1) as u32)
2029        }
2030        "hour" => Some(time.hour()),
2031        "minute" => Some(time.minute()),
2032        "second" => Some(time.second()),
2033        "millisecond" => Some(time.nanosecond() / 1000000),
2034        "microsecond" => Some(time.nanosecond() / 1000),
2035        "nanosecond" => Some(time.nanosecond()),
2036        _ => None,
2037    }
2038}
2039
2040async fn get_datetime_property(zoned_datetime: ZonedDateTime, property: String) -> Option<String> {
2041    let datetime = zoned_datetime.datetime();
2042
2043    let date = datetime.date_naive();
2044    let time = datetime.time();
2045    let offset = datetime.offset();
2046    let timezone = zoned_datetime.timezone();
2047
2048    match property.as_str() {
2049        "year" => Some(date.year().to_string()),
2050        "month" => Some(date.month().to_string()),
2051        "day" => Some(date.day().to_string()),
2052        "quarter" => Some(((date.month() - 1) / 3 + 1).to_string()),
2053        "week" => Some(date.iso_week().week().to_string()),
2054        "dayOfWeek" => {
2055            let day_of_week = date.weekday();
2056            let day_of_week_num = match day_of_week {
2057                Weekday::Mon => "1",
2058                Weekday::Tue => "2",
2059                Weekday::Wed => "3",
2060                Weekday::Thu => "4",
2061                Weekday::Fri => "5",
2062                Weekday::Sat => "6",
2063                Weekday::Sun => "7",
2064            };
2065            Some(day_of_week_num.to_string())
2066        }
2067        "weekDay" => {
2068            let day_of_week = date.weekday();
2069            let day_of_week_num = match day_of_week {
2070                Weekday::Mon => "1",
2071                Weekday::Tue => "2",
2072                Weekday::Wed => "3",
2073                Weekday::Thu => "4",
2074                Weekday::Fri => "5",
2075                Weekday::Sat => "6",
2076                Weekday::Sun => "7",
2077            };
2078            Some(day_of_week_num.to_string())
2079        }
2080        "ordinalDay" => Some(date.ordinal().to_string()),
2081        "weekYear" => Some(date.iso_week().year().to_string()),
2082        "dayOfQuarter" => {
2083            let quarter = (date.month() - 1) / 3 + 1;
2084            let start_date = match NaiveDate::from_ymd_opt(date.year(), (quarter - 1) * 3 + 1, 1) {
2085                Some(date) => date,
2086                None => return None,
2087            };
2088            let duration = date - start_date;
2089            let num_days = duration.num_days();
2090            Some((num_days + 1).to_string())
2091        }
2092        "quarterDay" => {
2093            let quarter = (date.month() - 1) / 3 + 1;
2094            let start_date = match NaiveDate::from_ymd_opt(date.year(), (quarter - 1) * 3 + 1, 1) {
2095                Some(date) => date,
2096                None => return None,
2097            };
2098            let duration = date - start_date;
2099            let num_days = duration.num_days();
2100            Some((num_days + 1).to_string())
2101        }
2102        "hour" => Some(time.hour().to_string()),
2103        "minute" => Some(time.minute().to_string()),
2104        "second" => Some(time.second().to_string()),
2105        "millisecond" => Some((time.nanosecond() / 1000000).to_string()),
2106        "microsecond" => Some((time.nanosecond() / 1000).to_string()),
2107        "nanosecond" => Some(time.nanosecond().to_string()),
2108        "timezone" => match timezone {
2109            Some(tz) => Some(tz.to_string()),
2110            None => Some(offset.to_string()),
2111        },
2112        "offset" => Some(offset.to_string()),
2113        "offsetSeconds" => {
2114            let seconds = offset.local_minus_utc();
2115            Some(seconds.to_string())
2116        }
2117        "offsetMinutes" => {
2118            let minutes = offset.local_minus_utc() / 60;
2119            Some(minutes.to_string())
2120        }
2121        "epochMillis" => {
2122            let epoch = *EPOCH_MIDNIGHT_NAIVE_DATETIME;
2123            let duration = datetime.naive_utc() - epoch;
2124            let millis = duration.num_milliseconds();
2125            Some(millis.to_string())
2126        }
2127        "epochSeconds" => {
2128            let epoch = *EPOCH_MIDNIGHT_NAIVE_DATETIME;
2129            let duration = datetime.naive_utc() - epoch;
2130            let seconds = duration.num_seconds();
2131            Some(seconds.to_string())
2132        }
2133        _ => None,
2134    }
2135}
2136
2137async fn get_duration_property(duration_struct: DurationStruct, property: String) -> Option<i64> {
2138    let year = duration_struct.year();
2139    let month = duration_struct.month();
2140    let duration = duration_struct.duration();
2141
2142    match property.as_str() {
2143        "years" => Some(year + month / 12 + duration.num_days() / 365),
2144        "months" => Some(month + year * 12 + duration.num_days() / 30),
2145        "quarters" => Some(month / 3 + year * 4),
2146        "weeks" => Some(duration.num_weeks()),
2147        "days" => Some(duration.num_days()),
2148        "hours" => Some(duration.num_hours()),
2149        "minutes" => Some(duration.num_minutes()),
2150        "seconds" => Some(duration.num_seconds()),
2151        "milliseconds" => Some(duration.num_milliseconds()),
2152        "microseconds" => Some(duration.num_microseconds().unwrap_or_default()),
2153        "nanoseconds" => Some(duration.num_nanoseconds().unwrap_or_default()),
2154        "quartersOfYear" => {
2155            let quarters = month / 3 + 1;
2156            Some(quarters)
2157        }
2158        "monthsOfYear" => {
2159            if month % 12 == 0 {
2160                return Some(12);
2161            }
2162            let months = month % 12;
2163            Some(months)
2164        }
2165        "monthsOfQuarter" => {
2166            if month % 3 == 0 {
2167                return Some(3);
2168            }
2169            let months = month % 3;
2170            Some(months)
2171        }
2172        "daysOfWeek" => {
2173            if duration.num_days() % 7 == 0 {
2174                return Some(7);
2175            }
2176            let days = duration.num_days() % 7;
2177            Some(days)
2178        }
2179        "minutesOfHour" => {
2180            let mins = duration.num_minutes() % 60;
2181            Some(mins)
2182        }
2183        "secondsOfMinute" => {
2184            let secs = duration.num_seconds() % 60;
2185            Some(secs)
2186        }
2187        "millisecondsOfSecond" => {
2188            let millis = duration.num_milliseconds() % 1000;
2189            Some(millis)
2190        }
2191        "microsecondsOfSecond" => {
2192            let micros = duration.num_microseconds().unwrap_or_default() % 1000000;
2193            Some(micros)
2194        }
2195        "nanosecondsOfSecond" => {
2196            let nanos = duration.num_nanoseconds().unwrap_or_default() % 1000000000;
2197            Some(nanos)
2198        }
2199        _ => None,
2200    }
2201}