alopex_sql/executor/evaluator/
mod.rs1pub(crate) mod binary_op;
8mod column_ref;
9pub(crate) mod conditional;
10mod context;
11pub(crate) mod datetime;
12mod function_call;
13pub(crate) mod hash;
14mod is_null;
15mod literal;
16pub(crate) mod numeric;
17pub(crate) mod pattern;
18pub mod registry;
19pub(crate) mod string;
20mod timestamp;
21pub(crate) mod type_fn;
22mod unary_op;
23pub mod vector_ops;
24
25pub use vector_ops::{VectorError, VectorMetric, vector_distance, vector_similarity};
26
27pub use context::EvalContext;
28pub(crate) use context::begin_statement;
29
30use crate::executor::{EvaluationError, ExecutorError, Result};
31use crate::planner::typed_expr::TypedExpr;
32use crate::planner::typed_expr::TypedExprKind;
33use crate::storage::SqlValue;
34
35pub fn evaluate(expr: &TypedExpr, ctx: &EvalContext<'_>) -> Result<SqlValue> {
37 match &expr.kind {
38 TypedExprKind::Literal(lit) => literal::eval_literal(lit, &expr.resolved_type),
39 TypedExprKind::ColumnRef { column_index, .. } => {
40 column_ref::eval_column_ref(*column_index, ctx)
41 }
42 TypedExprKind::BinaryOp { left, op, right } => {
43 binary_op::eval_binary_op(op, left, right, ctx)
44 }
45 TypedExprKind::UnaryOp { op, operand } => unary_op::eval_unary_op(op, operand, ctx),
46 TypedExprKind::IsNull { expr, negated } => is_null::eval_is_null(expr, *negated, ctx),
47 TypedExprKind::VectorLiteral(values) => {
48 Ok(SqlValue::Vector(values.iter().map(|v| *v as f32).collect()))
49 }
50 TypedExprKind::FunctionCall {
51 name,
52 args,
53 distinct,
54 star,
55 } => function_call::evaluate_function_call(name, args, *distinct, *star, ctx),
56 TypedExprKind::Cast { expr, target_type } => {
57 timestamp::evaluate_cast(expr, target_type, ctx)
58 }
59 TypedExprKind::Like {
60 expr,
61 pattern,
62 escape,
63 negated,
64 kind,
65 } => pattern::evaluate_pattern(expr, pattern, escape.as_deref(), *negated, *kind, ctx),
66 TypedExprKind::Between {
67 expr,
68 low,
69 high,
70 negated,
71 } => evaluate_between(expr, low, high, *negated, ctx),
72 TypedExprKind::InList {
73 expr,
74 list,
75 negated,
76 } => evaluate_in_list(expr, list, *negated, ctx),
77 other => Err(ExecutorError::Evaluation(
79 EvaluationError::UnsupportedExpression(format!("{other:?}")),
80 )),
81 }
82}
83
84fn evaluate_between(
85 expr: &TypedExpr,
86 low: &TypedExpr,
87 high: &TypedExpr,
88 negated: bool,
89 ctx: &EvalContext<'_>,
90) -> Result<SqlValue> {
91 let value = evaluate(expr, ctx)?;
92 let lower = binary_op::eval_binary_values(
93 &crate::ast::expr::BinaryOp::GtEq,
94 value.clone(),
95 evaluate(low, ctx)?,
96 )?;
97 let upper = binary_op::eval_binary_values(
98 &crate::ast::expr::BinaryOp::LtEq,
99 value,
100 evaluate(high, ctx)?,
101 )?;
102 let result = binary_op::eval_binary_values(&crate::ast::expr::BinaryOp::And, lower, upper)?;
103 negate_predicate(result, negated)
104}
105
106fn evaluate_in_list(
107 expr: &TypedExpr,
108 list: &[TypedExpr],
109 negated: bool,
110 ctx: &EvalContext<'_>,
111) -> Result<SqlValue> {
112 let value = evaluate(expr, ctx)?;
113 let mut unknown = false;
114
115 for item in list {
116 match binary_op::eval_binary_values(
117 &crate::ast::expr::BinaryOp::Eq,
118 value.clone(),
119 evaluate(item, ctx)?,
120 )? {
121 SqlValue::Boolean(true) => return Ok(SqlValue::Boolean(!negated)),
122 SqlValue::Boolean(false) => {}
123 SqlValue::Null => unknown = true,
124 other => {
125 return Err(ExecutorError::Evaluation(EvaluationError::TypeMismatch {
126 expected: "Boolean".into(),
127 actual: other.type_name().into(),
128 }));
129 }
130 }
131 }
132
133 if unknown {
134 Ok(SqlValue::Null)
135 } else {
136 Ok(SqlValue::Boolean(negated))
137 }
138}
139
140fn negate_predicate(value: SqlValue, negated: bool) -> Result<SqlValue> {
141 if !negated {
142 return Ok(value);
143 }
144 match value {
145 SqlValue::Boolean(value) => Ok(SqlValue::Boolean(!value)),
146 SqlValue::Null => Ok(SqlValue::Null),
147 other => Err(ExecutorError::Evaluation(EvaluationError::TypeMismatch {
148 expected: "Boolean".into(),
149 actual: other.type_name().into(),
150 })),
151 }
152}