1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use {
super::{expr, EvaluateError, Evaluated},
crate::{
ast::{Expr, Function},
data::{Row, Value},
result::Result,
},
std::borrow::Cow,
uuid::Uuid,
};
type Columns<'a> = &'a [String];
pub fn evaluate_stateless<'a>(
context: Option<(Columns, &'a Row)>,
expr: &'a Expr,
) -> Result<Evaluated<'a>> {
let eval = |expr| evaluate_stateless(context, expr);
match expr {
Expr::Literal(ast_literal) => expr::literal(ast_literal),
Expr::TypedString { data_type, value } => {
expr::typed_string(data_type, Cow::Borrowed(value))
}
Expr::Identifier(ident) => {
let (columns, row) = match context {
Some(context) => context,
None => {
return Err(EvaluateError::ValueNotFound(ident.to_owned()).into());
}
};
let value = columns
.iter()
.position(|column| column == ident)
.map(|index| row.get_value(index))
.flatten();
match value {
Some(value) => Ok(value.clone()),
None => Err(EvaluateError::ValueNotFound(ident.to_owned()).into()),
}
.map(Evaluated::from)
}
Expr::Nested(expr) => eval(expr),
Expr::BinaryOp { op, left, right } => {
let left = eval(left)?;
let right = eval(right)?;
expr::binary_op(op, left, right)
}
Expr::UnaryOp { op, expr } => {
let v = eval(expr)?;
expr::unary_op(op, v)
}
Expr::Cast { expr, data_type } => eval(expr)?.cast(data_type),
Expr::InList {
expr,
list,
negated,
} => {
let negated = *negated;
let target = eval(expr)?;
list.iter()
.filter_map(|expr| {
let target = ⌖
eval(expr).map_or_else(
|error| Some(Err(error)),
|evaluated| (target == &evaluated).then(|| Ok(!negated)),
)
})
.take(1)
.collect::<Vec<_>>()
.into_iter()
.next()
.unwrap_or(Ok(negated))
.map(Value::Bool)
.map(Evaluated::from)
}
Expr::Between {
expr,
negated,
low,
high,
} => {
let target = eval(expr)?;
let low = eval(low)?;
let high = eval(high)?;
expr::between(target, *negated, low, high)
}
Expr::IsNull(expr) => {
let v = eval(expr)?.is_null();
Ok(Evaluated::from(Value::Bool(v)))
}
Expr::IsNotNull(expr) => {
let v = eval(expr)?.is_null();
Ok(Evaluated::from(Value::Bool(!v)))
}
Expr::Wildcard | Expr::QualifiedWildcard(_) => {
Err(EvaluateError::UnreachableWildcardExpr.into())
}
Expr::Function(func) => match func.as_ref() {
Function::GenerateUuid() => Ok(Evaluated::from(Value::Uuid(Uuid::new_v4().as_u128()))),
_ => Err(EvaluateError::UnsupportedStatelessExpr(expr.clone()).into()),
},
_ => Err(EvaluateError::UnsupportedStatelessExpr(expr.clone()).into()),
}
}