1use crate::error::{DdbError, Result};
3use crate::functions::Value;
4use crate::parser::{BinaryOperator, Expression, Literal, UnaryOperator};
5use super::row::Row;
6use super::system_vars::SystemVariables;
7
8pub struct Evaluator {
10 system_vars: SystemVariables,
11}
12
13impl Evaluator {
14 pub fn new() -> Self {
15 Evaluator {
16 system_vars: SystemVariables::new(),
17 }
18 }
19
20 pub fn evaluate(&self, expr: &Expression, row: &Row) -> Result<Value> {
22 match expr {
23 Expression::Literal(lit) => Ok(self.evaluate_literal(lit)),
24 Expression::Column(name) => self.evaluate_column(name, row),
25 Expression::SystemVariable(name) => self.evaluate_system_variable(name),
26 Expression::Function { name, args } => self.evaluate_function(name, args, row),
27 Expression::BinaryOp { left, op, right } => {
28 self.evaluate_binary_op(left, op, right, row)
29 }
30 Expression::UnaryOp { op, operand } => self.evaluate_unary_op(op, operand, row),
31 }
32 }
33
34 fn evaluate_literal(&self, lit: &Literal) -> Value {
36 match lit {
37 Literal::String(s) => Value::String(s.clone()),
38 Literal::Number(n) => Value::Float(*n),
39 Literal::Integer(i) => Value::Integer(*i),
40 Literal::Boolean(b) => Value::Boolean(*b),
41 Literal::Null => Value::Null,
42 }
43 }
44
45 fn evaluate_column(&self, name: &str, row: &Row) -> Result<Value> {
47 row.get(name)
48 .cloned()
49 .ok_or_else(|| DdbError::ExecutionError(format!("Column not found: {}", name)))
50 }
51
52 fn evaluate_system_variable(&self, name: &str) -> Result<Value> {
54 self.system_vars
55 .get(name)
56 .cloned()
57 .ok_or_else(|| DdbError::ExecutionError(format!("Unknown system variable: @@{}", name)))
58 }
59
60 fn evaluate_function(&self, name: &str, args: &[Expression], row: &Row) -> Result<Value> {
62 let is_count_star = name.to_uppercase() == "COUNT"
64 && args.len() == 1
65 && matches!(&args[0], Expression::Column(col) if col == "*");
66
67 if is_count_star {
70 return Ok(Value::Integer(1));
72 }
73
74 let arg_values: Result<Vec<Value>> = args.iter().map(|arg| self.evaluate(arg, row)).collect();
76 let arg_values = arg_values?;
77
78 match name.to_uppercase().as_str() {
80 "ABS" => {
82 if arg_values.len() != 1 {
83 return Err(DdbError::FunctionError("ABS requires 1 argument".to_string()));
84 }
85 crate::functions::math::abs(&arg_values[0])
86 }
87 "CEIL" | "CEILING" => {
88 if arg_values.len() != 1 {
89 return Err(DdbError::FunctionError("CEIL requires 1 argument".to_string()));
90 }
91 crate::functions::math::ceil(&arg_values[0])
92 }
93 "FLOOR" => {
94 if arg_values.len() != 1 {
95 return Err(DdbError::FunctionError("FLOOR requires 1 argument".to_string()));
96 }
97 crate::functions::math::floor(&arg_values[0])
98 }
99 "ROUND" => {
100 if arg_values.is_empty() || arg_values.len() > 2 {
101 return Err(DdbError::FunctionError("ROUND requires 1-2 arguments".to_string()));
102 }
103 let decimals = if arg_values.len() == 2 {
104 Some(&arg_values[1])
105 } else {
106 None
107 };
108 crate::functions::math::round(&arg_values[0], decimals)
109 }
110 "SQRT" => {
111 if arg_values.len() != 1 {
112 return Err(DdbError::FunctionError("SQRT requires 1 argument".to_string()));
113 }
114 crate::functions::math::sqrt(&arg_values[0])
115 }
116 "POW" | "POWER" => {
117 if arg_values.len() != 2 {
118 return Err(DdbError::FunctionError("POW requires 2 arguments".to_string()));
119 }
120 crate::functions::math::pow(&arg_values[0], &arg_values[1])
121 }
122
123 "UPPER" | "UCASE" => {
125 if arg_values.len() != 1 {
126 return Err(DdbError::FunctionError("UPPER requires 1 argument".to_string()));
127 }
128 crate::functions::string::upper(&arg_values[0])
129 }
130 "LOWER" | "LCASE" => {
131 if arg_values.len() != 1 {
132 return Err(DdbError::FunctionError("LOWER requires 1 argument".to_string()));
133 }
134 crate::functions::string::lower(&arg_values[0])
135 }
136 "LENGTH" | "CHAR_LENGTH" => {
137 if arg_values.len() != 1 {
138 return Err(DdbError::FunctionError("LENGTH requires 1 argument".to_string()));
139 }
140 crate::functions::string::length(&arg_values[0])
141 }
142 "TRIM" => {
143 if arg_values.len() != 1 {
144 return Err(DdbError::FunctionError("TRIM requires 1 argument".to_string()));
145 }
146 crate::functions::string::trim(&arg_values[0])
147 }
148 "CONCAT" => crate::functions::string::concat(&arg_values),
149 "SUBSTR" | "SUBSTRING" => {
150 if arg_values.len() < 2 || arg_values.len() > 3 {
151 return Err(DdbError::FunctionError("SUBSTR requires 2-3 arguments".to_string()));
152 }
153 let len = if arg_values.len() == 3 {
154 Some(&arg_values[2])
155 } else {
156 None
157 };
158 crate::functions::string::substr(&arg_values[0], &arg_values[1], len)
159 }
160
161 "CAST" => {
163 if arg_values.len() != 2 {
164 return Err(DdbError::FunctionError("CAST requires 2 arguments (value, type)".to_string()));
165 }
166 let type_name = arg_values[1].to_string();
167 crate::functions::conversion::cast(&arg_values[0], &type_name)
168 }
169 "ATOF" => {
170 if arg_values.len() != 1 {
171 return Err(DdbError::FunctionError("ATOF requires 1 argument".to_string()));
172 }
173 crate::functions::conversion::atof(&arg_values[0])
174 }
175 "ATOI" => {
176 if arg_values.len() != 1 {
177 return Err(DdbError::FunctionError("ATOI requires 1 argument".to_string()));
178 }
179 crate::functions::conversion::atoi(&arg_values[0])
180 }
181
182 "NOW" | "CURRENT_TIMESTAMP" => Ok(crate::functions::datetime::now()),
184 "CURDATE" | "CURRENT_DATE" => Ok(crate::functions::datetime::curdate()),
185 "CURTIME" | "CURRENT_TIME" => Ok(crate::functions::datetime::curtime()),
186 "YEAR" => {
187 if arg_values.len() != 1 {
188 return Err(DdbError::FunctionError("YEAR requires 1 argument".to_string()));
189 }
190 crate::functions::datetime::year(&arg_values[0])
191 }
192 "MONTH" => {
193 if arg_values.len() != 1 {
194 return Err(DdbError::FunctionError("MONTH requires 1 argument".to_string()));
195 }
196 crate::functions::datetime::month(&arg_values[0])
197 }
198 "DAY" => {
199 if arg_values.len() != 1 {
200 return Err(DdbError::FunctionError("DAY requires 1 argument".to_string()));
201 }
202 crate::functions::datetime::day(&arg_values[0])
203 }
204 "DATEDIFF" => {
205 if arg_values.len() != 2 {
206 return Err(DdbError::FunctionError("DATEDIFF requires 2 arguments".to_string()));
207 }
208 crate::functions::datetime::datediff(&arg_values[0], &arg_values[1])
209 }
210 "DATEADD" => {
211 if arg_values.len() != 3 {
212 return Err(DdbError::FunctionError("DATEADD requires 3 arguments (date, interval, unit)".to_string()));
213 }
214 let unit = arg_values[2].to_string();
215 crate::functions::datetime::dateadd(&arg_values[0], &arg_values[1], &unit)
216 }
217
218 "IF" => {
220 if arg_values.len() != 3 {
221 return Err(DdbError::FunctionError("IF requires 3 arguments".to_string()));
222 }
223 crate::functions::conditional::if_fn(&arg_values[0], &arg_values[1], &arg_values[2])
224 }
225 "IFNULL" => {
226 if arg_values.len() != 2 {
227 return Err(DdbError::FunctionError("IFNULL requires 2 arguments".to_string()));
228 }
229 crate::functions::conditional::ifnull(&arg_values[0], &arg_values[1])
230 }
231 "COALESCE" => crate::functions::conditional::coalesce(&arg_values),
232
233 "VERSION" => Ok(crate::functions::system::version()),
235 "DATABASE" => Ok(crate::functions::system::database(None)),
236 "UUID" => Ok(crate::functions::system::uuid()),
237
238 "HASH" => {
240 if arg_values.len() != 1 {
241 return Err(DdbError::FunctionError("HASH requires 1 argument".to_string()));
242 }
243 crate::functions::utility::hash(&arg_values[0])
244 }
245 "BASE64_ENCODE" => {
246 if arg_values.len() != 1 {
247 return Err(DdbError::FunctionError("BASE64_ENCODE requires 1 argument".to_string()));
248 }
249 crate::functions::utility::base64_encode(&arg_values[0])
250 }
251 "BASE64_DECODE" => {
252 if arg_values.len() != 1 {
253 return Err(DdbError::FunctionError("BASE64_DECODE requires 1 argument".to_string()));
254 }
255 crate::functions::utility::base64_decode(&arg_values[0])
256 }
257
258 _ => Err(DdbError::FunctionError(format!("Unknown function: {}", name))),
259 }
260 }
261
262 fn evaluate_binary_op(
264 &self,
265 left: &Expression,
266 op: &BinaryOperator,
267 right: &Expression,
268 row: &Row,
269 ) -> Result<Value> {
270 let left_val = self.evaluate(left, row)?;
271 let right_val = self.evaluate(right, row)?;
272
273 match op {
274 BinaryOperator::Equal => Ok(Value::Boolean(self.compare_values(&left_val, &right_val) == std::cmp::Ordering::Equal)),
275 BinaryOperator::NotEqual => Ok(Value::Boolean(self.compare_values(&left_val, &right_val) != std::cmp::Ordering::Equal)),
276 BinaryOperator::GreaterThan => Ok(Value::Boolean(self.compare_values(&left_val, &right_val) == std::cmp::Ordering::Greater)),
277 BinaryOperator::GreaterEqual => {
278 let cmp = self.compare_values(&left_val, &right_val);
279 Ok(Value::Boolean(cmp == std::cmp::Ordering::Greater || cmp == std::cmp::Ordering::Equal))
280 }
281 BinaryOperator::LessThan => Ok(Value::Boolean(self.compare_values(&left_val, &right_val) == std::cmp::Ordering::Less)),
282 BinaryOperator::LessEqual => {
283 let cmp = self.compare_values(&left_val, &right_val);
284 Ok(Value::Boolean(cmp == std::cmp::Ordering::Less || cmp == std::cmp::Ordering::Equal))
285 }
286 BinaryOperator::Like => self.evaluate_like(&left_val, &right_val),
287 BinaryOperator::And => {
288 let left_bool = self.to_boolean(&left_val)?;
289 let right_bool = self.to_boolean(&right_val)?;
290 Ok(Value::Boolean(left_bool && right_bool))
291 }
292 BinaryOperator::Or => {
293 let left_bool = self.to_boolean(&left_val)?;
294 let right_bool = self.to_boolean(&right_val)?;
295 Ok(Value::Boolean(left_bool || right_bool))
296 }
297 }
298 }
299
300 fn evaluate_unary_op(
302 &self,
303 op: &UnaryOperator,
304 operand: &Expression,
305 row: &Row,
306 ) -> Result<Value> {
307 let val = self.evaluate(operand, row)?;
308
309 match op {
310 UnaryOperator::Not => {
311 let bool_val = self.to_boolean(&val)?;
312 Ok(Value::Boolean(!bool_val))
313 }
314 UnaryOperator::IsNull => Ok(Value::Boolean(val.is_null())),
315 }
316 }
317
318 fn compare_values(&self, left: &Value, right: &Value) -> std::cmp::Ordering {
320 use std::cmp::Ordering;
321
322 match (left, right) {
323 (Value::Null, Value::Null) => Ordering::Equal,
324 (Value::Null, _) => Ordering::Less,
325 (_, Value::Null) => Ordering::Greater,
326 (Value::Integer(a), Value::Integer(b)) => a.cmp(b),
327 (Value::Float(a), Value::Float(b)) => {
328 a.partial_cmp(b).unwrap_or(Ordering::Equal)
329 }
330 (Value::Integer(a), Value::Float(b)) => {
331 (*a as f64).partial_cmp(b).unwrap_or(Ordering::Equal)
332 }
333 (Value::Float(a), Value::Integer(b)) => {
334 a.partial_cmp(&(*b as f64)).unwrap_or(Ordering::Equal)
335 }
336 (Value::String(a), Value::String(b)) => a.cmp(b),
337 (Value::Boolean(a), Value::Boolean(b)) => a.cmp(b),
338 _ => Ordering::Equal,
339 }
340 }
341
342 fn evaluate_like(&self, value: &Value, pattern: &Value) -> Result<Value> {
345 let val_str = value.to_string();
346 let pattern_str = pattern.to_string();
347
348 let matched = if !pattern_str.contains('_') {
350 if pattern_str.starts_with('%') && pattern_str.ends_with('%') {
352 let search = &pattern_str[1..pattern_str.len()-1];
354 if !search.contains('%') {
355 return Ok(Value::Boolean(val_str.contains(search)));
356 }
357 } else if pattern_str.starts_with('%') {
358 let suffix = &pattern_str[1..];
360 if !suffix.contains('%') {
361 return Ok(Value::Boolean(val_str.ends_with(suffix)));
362 }
363 } else if pattern_str.ends_with('%') {
364 let prefix = &pattern_str[..pattern_str.len()-1];
366 if !prefix.contains('%') {
367 return Ok(Value::Boolean(val_str.starts_with(prefix)));
368 }
369 } else if !pattern_str.contains('%') {
370 return Ok(Value::Boolean(val_str == pattern_str));
372 }
373
374 self.evaluate_like_regex(&val_str, &pattern_str)?
376 } else {
377 self.evaluate_like_regex(&val_str, &pattern_str)?
379 };
380
381 Ok(Value::Boolean(matched))
382 }
383
384 #[inline]
386 fn evaluate_like_regex(&self, val_str: &str, pattern_str: &str) -> Result<bool> {
387 let mut regex_pattern = String::with_capacity(pattern_str.len() * 2);
389
390 for ch in pattern_str.chars() {
391 match ch {
392 '%' => regex_pattern.push_str(".*"),
393 '_' => regex_pattern.push('.'),
394 '.' | '^' | '$' | '*' | '+' | '?' | '(' | ')' | '[' | ']' |
396 '{' | '}' | '\\' | '|' => {
397 regex_pattern.push('\\');
398 regex_pattern.push(ch);
399 }
400 _ => regex_pattern.push(ch),
401 }
402 }
403
404 let regex = regex::Regex::new(&format!("^{}$", regex_pattern))
405 .map_err(|e| DdbError::ExecutionError(format!("Invalid LIKE pattern: {}", e)))?;
406
407 Ok(regex.is_match(val_str))
408 }
409
410 fn to_boolean(&self, value: &Value) -> Result<bool> {
412 match value {
413 Value::Boolean(b) => Ok(*b),
414 Value::Integer(i) => Ok(*i != 0),
415 Value::Float(f) => Ok(*f != 0.0),
416 Value::String(s) => Ok(!s.is_empty()),
417 Value::Null => Ok(false),
418 _ => Ok(true),
419 }
420 }
421}
422
423impl Default for Evaluator {
424 fn default() -> Self {
425 Self::new()
426 }
427}
428
429#[cfg(test)]
430mod tests {
431 use super::*;
432 use crate::parser::Literal;
433
434 #[test]
435 fn test_evaluate_literal() {
436 let evaluator = Evaluator::new();
437 let row = Row::new();
438
439 let expr = Expression::Literal(Literal::Integer(42));
440 let result = evaluator.evaluate(&expr, &row).unwrap();
441 assert_eq!(result, Value::Integer(42));
442
443 let expr = Expression::Literal(Literal::String("hello".to_string()));
444 let result = evaluator.evaluate(&expr, &row).unwrap();
445 assert_eq!(result, Value::String("hello".to_string()));
446 }
447
448 #[test]
449 fn test_evaluate_column() {
450 let evaluator = Evaluator::new();
451 let mut row = Row::new();
452 row.set("age", Value::Integer(25));
453
454 let expr = Expression::Column("age".to_string());
455 let result = evaluator.evaluate(&expr, &row).unwrap();
456 assert_eq!(result, Value::Integer(25));
457 }
458
459 #[test]
460 fn test_evaluate_binary_op() {
461 let evaluator = Evaluator::new();
462 let mut row = Row::new();
463 row.set("age", Value::Integer(25));
464
465 let expr = Expression::BinaryOp {
467 left: Box::new(Expression::Column("age".to_string())),
468 op: BinaryOperator::GreaterThan,
469 right: Box::new(Expression::Literal(Literal::Integer(18))),
470 };
471
472 let result = evaluator.evaluate(&expr, &row).unwrap();
473 assert_eq!(result, Value::Boolean(true));
474 }
475
476 #[test]
477 fn test_evaluate_function() {
478 let evaluator = Evaluator::new();
479 let mut row = Row::new();
480 row.set("name", Value::String("john".to_string()));
481
482 let expr = Expression::Function {
484 name: "UPPER".to_string(),
485 args: vec![Expression::Column("name".to_string())],
486 };
487
488 let result = evaluator.evaluate(&expr, &row).unwrap();
489 assert_eq!(result, Value::String("JOHN".to_string()));
490 }
491
492 #[test]
493 fn test_evaluate_like() {
494 let evaluator = Evaluator::new();
495 let _row = Row::new();
496
497 let value = Value::String("hello world".to_string());
498 let pattern = Value::String("hello%".to_string());
499
500 let result = evaluator.evaluate_like(&value, &pattern).unwrap();
501 assert_eq!(result, Value::Boolean(true));
502
503 let pattern = Value::String("%world".to_string());
504 let result = evaluator.evaluate_like(&value, &pattern).unwrap();
505 assert_eq!(result, Value::Boolean(true));
506
507 let pattern = Value::String("hello_world".to_string());
509 let result = evaluator.evaluate_like(&value, &pattern).unwrap();
510 assert_eq!(result, Value::Boolean(true)); }
512}