kstone_core/
expression.rs

1/// Expression system for DynamoDB-style condition and update expressions
2///
3/// Supports:
4/// - **Condition expressions**: =, <>, <, <=, >, >=, AND, OR, NOT, functions
5/// - **Update expressions**: SET, REMOVE, ADD, DELETE actions
6/// - Attribute paths and value placeholders
7///
8/// # Condition Expression Examples
9///
10/// ```ignore
11/// // Parse: age > :min_age AND active = :is_active
12/// let expr = ConditionExpressionParser::parse("age > :min_age AND active = :is_active")?;
13///
14/// // Evaluate with context
15/// let context = ExpressionContext::new()
16///     .with_value(":min_age", Value::number(18))
17///     .with_value(":is_active", Value::Bool(true));
18///
19/// let evaluator = ExpressionEvaluator::new(&item, &context);
20/// let result = evaluator.evaluate(&expr)?;
21/// ```
22///
23/// # Update Expression Examples
24///
25/// ```ignore
26/// // Parse: SET age = age + :inc, active = :val REMOVE temp
27/// let actions = UpdateExpressionParser::parse("SET age = age + :inc REMOVE temp")?;
28///
29/// let context = ExpressionContext::new()
30///     .with_value(":inc", Value::number(1));
31///
32/// let executor = UpdateExecutor::new(&context);
33/// let updated_item = executor.execute(&item, &actions)?;
34/// ```
35
36use crate::{Item, Value, Error, Result};
37use std::collections::HashMap;
38
39/// Expression AST node
40#[derive(Debug, Clone, PartialEq)]
41pub enum Expr {
42    // Comparison operators
43    Equal(Box<Expr>, Box<Expr>),
44    NotEqual(Box<Expr>, Box<Expr>),
45    LessThan(Box<Expr>, Box<Expr>),
46    LessThanOrEqual(Box<Expr>, Box<Expr>),
47    GreaterThan(Box<Expr>, Box<Expr>),
48    GreaterThanOrEqual(Box<Expr>, Box<Expr>),
49
50    // Logical operators
51    And(Box<Expr>, Box<Expr>),
52    Or(Box<Expr>, Box<Expr>),
53    Not(Box<Expr>),
54
55    // Functions
56    AttributeExists(String),
57    AttributeNotExists(String),
58    BeginsWith(Box<Expr>, Box<Expr>),
59
60    // Operands
61    AttributePath(String),
62    ValuePlaceholder(String),
63    Literal(Value),
64}
65
66/// Expression context with attribute values and names
67#[derive(Debug, Clone, Default)]
68pub struct ExpressionContext {
69    /// Expression attribute values (:value1 -> Value)
70    pub values: HashMap<String, Value>,
71    /// Expression attribute names (#name -> actual_name)
72    pub names: HashMap<String, String>,
73}
74
75impl ExpressionContext {
76    pub fn new() -> Self {
77        Self::default()
78    }
79
80    pub fn with_value(mut self, placeholder: impl Into<String>, value: Value) -> Self {
81        self.values.insert(placeholder.into(), value);
82        self
83    }
84
85    pub fn with_name(mut self, placeholder: impl Into<String>, name: impl Into<String>) -> Self {
86        self.names.insert(placeholder.into(), name.into());
87        self
88    }
89}
90
91/// Expression evaluator
92pub struct ExpressionEvaluator<'a> {
93    item: &'a Item,
94    context: &'a ExpressionContext,
95}
96
97impl<'a> ExpressionEvaluator<'a> {
98    pub fn new(item: &'a Item, context: &'a ExpressionContext) -> Self {
99        Self { item, context }
100    }
101
102    /// Evaluate expression against item
103    pub fn evaluate(&self, expr: &Expr) -> Result<bool> {
104        match expr {
105            Expr::Equal(left, right) => {
106                let l = self.resolve_value(left)?;
107                let r = self.resolve_value(right)?;
108                Ok(l == r)
109            }
110            Expr::NotEqual(left, right) => {
111                let l = self.resolve_value(left)?;
112                let r = self.resolve_value(right)?;
113                Ok(l != r)
114            }
115            Expr::LessThan(left, right) => {
116                let l = self.resolve_value(left)?;
117                let r = self.resolve_value(right)?;
118                Ok(self.compare_values(&l, &r)? < 0)
119            }
120            Expr::LessThanOrEqual(left, right) => {
121                let l = self.resolve_value(left)?;
122                let r = self.resolve_value(right)?;
123                Ok(self.compare_values(&l, &r)? <= 0)
124            }
125            Expr::GreaterThan(left, right) => {
126                let l = self.resolve_value(left)?;
127                let r = self.resolve_value(right)?;
128                Ok(self.compare_values(&l, &r)? > 0)
129            }
130            Expr::GreaterThanOrEqual(left, right) => {
131                let l = self.resolve_value(left)?;
132                let r = self.resolve_value(right)?;
133                Ok(self.compare_values(&l, &r)? >= 0)
134            }
135            Expr::And(left, right) => {
136                Ok(self.evaluate(left)? && self.evaluate(right)?)
137            }
138            Expr::Or(left, right) => {
139                Ok(self.evaluate(left)? || self.evaluate(right)?)
140            }
141            Expr::Not(expr) => {
142                Ok(!self.evaluate(expr)?)
143            }
144            Expr::AttributeExists(path) => {
145                let attr_name = self.resolve_attribute_name(path);
146                Ok(self.item.contains_key(&attr_name))
147            }
148            Expr::AttributeNotExists(path) => {
149                let attr_name = self.resolve_attribute_name(path);
150                Ok(!self.item.contains_key(&attr_name))
151            }
152            Expr::BeginsWith(path_expr, value_expr) => {
153                let path_value = self.resolve_value(path_expr)?;
154                let prefix_value = self.resolve_value(value_expr)?;
155
156                match (&path_value, &prefix_value) {
157                    (Value::S(s), Value::S(prefix)) => Ok(s.starts_with(prefix)),
158                    (Value::B(b), Value::B(prefix)) => Ok(b.starts_with(prefix.as_ref())),
159                    _ => Err(Error::InvalidExpression("begins_with requires string or binary operands".into()))
160                }
161            }
162            Expr::AttributePath(_) | Expr::ValuePlaceholder(_) | Expr::Literal(_) => {
163                Err(Error::InvalidExpression("Cannot evaluate operand as boolean expression".into()))
164            }
165        }
166    }
167
168    /// Resolve an expression to a value
169    fn resolve_value(&self, expr: &Expr) -> Result<Value> {
170        match expr {
171            Expr::AttributePath(path) => {
172                let attr_name = self.resolve_attribute_name(path);
173                self.item.get(&attr_name)
174                    .cloned()
175                    .ok_or_else(|| Error::InvalidExpression(format!("Attribute '{}' not found", attr_name)))
176            }
177            Expr::ValuePlaceholder(placeholder) => {
178                self.context.values.get(placeholder)
179                    .cloned()
180                    .ok_or_else(|| Error::InvalidExpression(format!("Value placeholder '{}' not found", placeholder)))
181            }
182            Expr::Literal(value) => Ok(value.clone()),
183            _ => Err(Error::InvalidExpression("Cannot resolve non-value expression to value".into()))
184        }
185    }
186
187    /// Resolve attribute name (handle #placeholder)
188    fn resolve_attribute_name(&self, path: &str) -> String {
189        if path.starts_with('#') {
190            self.context.names.get(path)
191                .cloned()
192                .unwrap_or_else(|| path.to_string())
193        } else {
194            path.to_string()
195        }
196    }
197
198    /// Compare two values (returns -1, 0, or 1)
199    fn compare_values(&self, left: &Value, right: &Value) -> Result<i32> {
200        match (left, right) {
201            (Value::N(l), Value::N(r)) => {
202                let l_num: f64 = l.parse().map_err(|_| Error::InvalidExpression("Invalid number".into()))?;
203                let r_num: f64 = r.parse().map_err(|_| Error::InvalidExpression("Invalid number".into()))?;
204                Ok(if l_num < r_num { -1 } else if l_num > r_num { 1 } else { 0 })
205            }
206            (Value::S(l), Value::S(r)) => {
207                Ok(if l < r { -1 } else if l > r { 1 } else { 0 })
208            }
209            (Value::B(l), Value::B(r)) => {
210                Ok(if l < r { -1 } else if l > r { 1 } else { 0 })
211            }
212            _ => Err(Error::InvalidExpression("Cannot compare different types".into()))
213        }
214    }
215}
216
217/// Update expression actions
218#[derive(Debug, Clone, PartialEq)]
219pub enum UpdateAction {
220    /// SET path = value (or SET path = path + value for increment)
221    Set(String, UpdateValue),
222    /// REMOVE path
223    Remove(String),
224    /// ADD path value (for numbers or sets)
225    Add(String, UpdateValue),
226    /// DELETE path value (for sets)
227    Delete(String, UpdateValue),
228}
229
230/// Value in update expression (can be literal, placeholder, or arithmetic)
231#[derive(Debug, Clone, PartialEq)]
232pub enum UpdateValue {
233    /// Direct value (from placeholder or literal)
234    Value(Value),
235    /// Placeholder to be resolved
236    Placeholder(String),
237    /// Attribute path reference
238    Path(String),
239    /// Arithmetic: path + value or path - value
240    Add(String, Box<UpdateValue>),
241    Sub(String, Box<UpdateValue>),
242}
243
244/// Update executor
245pub struct UpdateExecutor<'a> {
246    context: &'a ExpressionContext,
247}
248
249impl<'a> UpdateExecutor<'a> {
250    pub fn new(context: &'a ExpressionContext) -> Self {
251        Self { context }
252    }
253
254    /// Execute update actions on an item
255    pub fn execute(&self, item: &Item, actions: &[UpdateAction]) -> Result<Item> {
256        let mut result = item.clone();
257
258        for action in actions {
259            match action {
260                UpdateAction::Set(path, value) => {
261                    let attr_name = self.resolve_attribute_name(path);
262                    let resolved_value = self.resolve_update_value(value, &result)?;
263                    result.insert(attr_name, resolved_value);
264                }
265                UpdateAction::Remove(path) => {
266                    let attr_name = self.resolve_attribute_name(path);
267                    result.remove(&attr_name);
268                }
269                UpdateAction::Add(path, value) => {
270                    let attr_name = self.resolve_attribute_name(path);
271                    let add_value = self.resolve_update_value(value, &result)?;
272
273                    if let Some(existing) = result.get(&attr_name) {
274                        // Add to existing number
275                        match (existing, &add_value) {
276                            (Value::N(n1), Value::N(n2)) => {
277                                let num1: f64 = n1.parse().map_err(|_| Error::InvalidExpression("Invalid number".into()))?;
278                                let num2: f64 = n2.parse().map_err(|_| Error::InvalidExpression("Invalid number".into()))?;
279                                result.insert(attr_name, Value::number(num1 + num2));
280                            }
281                            _ => return Err(Error::InvalidExpression("ADD requires numbers".into()))
282                        }
283                    } else {
284                        // Initialize with value
285                        result.insert(attr_name, add_value);
286                    }
287                }
288                UpdateAction::Delete(_path, _value) => {
289                    // DELETE is for sets - not implementing full set support in this phase
290                    return Err(Error::InvalidExpression("DELETE action not yet supported".into()));
291                }
292            }
293        }
294
295        Ok(result)
296    }
297
298    fn resolve_update_value(&self, value: &UpdateValue, item: &Item) -> Result<Value> {
299        match value {
300            UpdateValue::Value(v) => Ok(v.clone()),
301            UpdateValue::Placeholder(placeholder) => {
302                self.context.values.get(placeholder)
303                    .cloned()
304                    .ok_or_else(|| Error::InvalidExpression(format!("Placeholder {} not found", placeholder)))
305            }
306            UpdateValue::Path(path) => {
307                let attr_name = self.resolve_attribute_name(path);
308                item.get(&attr_name)
309                    .cloned()
310                    .ok_or_else(|| Error::InvalidExpression(format!("Attribute {} not found", attr_name)))
311            }
312            UpdateValue::Add(path, val) => {
313                let attr_name = self.resolve_attribute_name(path);
314                let base = item.get(&attr_name)
315                    .cloned()
316                    .ok_or_else(|| Error::InvalidExpression(format!("Attribute {} not found", attr_name)))?;
317                let increment = self.resolve_update_value(val, item)?;
318
319                match (&base, &increment) {
320                    (Value::N(n1), Value::N(n2)) => {
321                        let num1: f64 = n1.parse().map_err(|_| Error::InvalidExpression("Invalid number".into()))?;
322                        let num2: f64 = n2.parse().map_err(|_| Error::InvalidExpression("Invalid number".into()))?;
323                        Ok(Value::number(num1 + num2))
324                    }
325                    _ => Err(Error::InvalidExpression("Addition requires numbers".into()))
326                }
327            }
328            UpdateValue::Sub(path, val) => {
329                let attr_name = self.resolve_attribute_name(path);
330                let base = item.get(&attr_name)
331                    .cloned()
332                    .ok_or_else(|| Error::InvalidExpression(format!("Attribute {} not found", attr_name)))?;
333                let decrement = self.resolve_update_value(val, item)?;
334
335                match (&base, &decrement) {
336                    (Value::N(n1), Value::N(n2)) => {
337                        let num1: f64 = n1.parse().map_err(|_| Error::InvalidExpression("Invalid number".into()))?;
338                        let num2: f64 = n2.parse().map_err(|_| Error::InvalidExpression("Invalid number".into()))?;
339                        Ok(Value::number(num1 - num2))
340                    }
341                    _ => Err(Error::InvalidExpression("Subtraction requires numbers".into()))
342                }
343            }
344        }
345    }
346
347    fn resolve_attribute_name(&self, path: &str) -> String {
348        if path.starts_with('#') {
349            self.context.names.get(path)
350                .cloned()
351                .unwrap_or_else(|| path.to_string())
352        } else {
353            path.to_string()
354        }
355    }
356}
357
358/// Token for lexer
359#[derive(Debug, Clone, PartialEq)]
360enum Token {
361    // Operators
362    Equal,
363    NotEqual,
364    LessThan,
365    LessThanOrEqual,
366    GreaterThan,
367    GreaterThanOrEqual,
368
369    // Keywords
370    And,
371    Or,
372    Not,
373
374    // Update keywords
375    Set,
376    Remove,
377    Add,
378    Delete,
379
380    // Arithmetic
381    Plus,
382    Minus,
383
384    // Functions
385    AttributeExists,
386    AttributeNotExists,
387    BeginsWith,
388
389    // Identifiers and literals
390    Identifier(String),
391    NamePlaceholder(String),    // #name
392    ValuePlaceholder(String),   // :value
393
394    // Delimiters
395    LeftParen,
396    RightParen,
397    Comma,
398
399    Eof,
400}
401
402/// Simple lexer
403struct Lexer {
404    input: Vec<char>,
405    pos: usize,
406}
407
408impl Lexer {
409    fn new(input: &str) -> Self {
410        Self {
411            input: input.chars().collect(),
412            pos: 0,
413        }
414    }
415
416    fn current(&self) -> Option<char> {
417        self.input.get(self.pos).copied()
418    }
419
420    fn advance(&mut self) {
421        self.pos += 1;
422    }
423
424    fn skip_whitespace(&mut self) {
425        while let Some(ch) = self.current() {
426            if ch.is_whitespace() {
427                self.advance();
428            } else {
429                break;
430            }
431        }
432    }
433
434    fn read_identifier(&mut self) -> String {
435        let start = self.pos;
436        while let Some(ch) = self.current() {
437            if ch.is_alphanumeric() || ch == '_' {
438                self.advance();
439            } else {
440                break;
441            }
442        }
443        self.input[start..self.pos].iter().collect()
444    }
445
446    fn next_token(&mut self) -> Result<Token> {
447        self.skip_whitespace();
448
449        match self.current() {
450            None => Ok(Token::Eof),
451            Some('(') => {
452                self.advance();
453                Ok(Token::LeftParen)
454            }
455            Some(')') => {
456                self.advance();
457                Ok(Token::RightParen)
458            }
459            Some(',') => {
460                self.advance();
461                Ok(Token::Comma)
462            }
463            Some('+') => {
464                self.advance();
465                Ok(Token::Plus)
466            }
467            Some('-') => {
468                self.advance();
469                Ok(Token::Minus)
470            }
471            Some('=') => {
472                self.advance();
473                Ok(Token::Equal)
474            }
475            Some('<') => {
476                self.advance();
477                if self.current() == Some('>') {
478                    self.advance();
479                    Ok(Token::NotEqual)
480                } else if self.current() == Some('=') {
481                    self.advance();
482                    Ok(Token::LessThanOrEqual)
483                } else {
484                    Ok(Token::LessThan)
485                }
486            }
487            Some('>') => {
488                self.advance();
489                if self.current() == Some('=') {
490                    self.advance();
491                    Ok(Token::GreaterThanOrEqual)
492                } else {
493                    Ok(Token::GreaterThan)
494                }
495            }
496            Some('#') => {
497                self.advance();
498                let name = self.read_identifier();
499                Ok(Token::NamePlaceholder(format!("#{}", name)))
500            }
501            Some(':') => {
502                self.advance();
503                let name = self.read_identifier();
504                Ok(Token::ValuePlaceholder(format!(":{}", name)))
505            }
506            Some(ch) if ch.is_alphabetic() => {
507                let ident = self.read_identifier();
508                match ident.to_uppercase().as_str() {
509                    "AND" => Ok(Token::And),
510                    "OR" => Ok(Token::Or),
511                    "NOT" => Ok(Token::Not),
512                    "SET" => Ok(Token::Set),
513                    "REMOVE" => Ok(Token::Remove),
514                    "ADD" => Ok(Token::Add),
515                    "DELETE" => Ok(Token::Delete),
516                    "ATTRIBUTE_EXISTS" => Ok(Token::AttributeExists),
517                    "ATTRIBUTE_NOT_EXISTS" => Ok(Token::AttributeNotExists),
518                    "BEGINS_WITH" => Ok(Token::BeginsWith),
519                    _ => Ok(Token::Identifier(ident)),
520                }
521            }
522            Some(ch) => Err(Error::InvalidExpression(format!("Unexpected character: {}", ch)))
523        }
524    }
525}
526
527/// Expression parser
528pub struct ExpressionParser {
529    tokens: Vec<Token>,
530    pos: usize,
531}
532
533impl ExpressionParser {
534    /// Parse a condition expression string into AST
535    pub fn parse(input: &str) -> Result<Expr> {
536        let mut lexer = Lexer::new(input);
537        let mut tokens = Vec::new();
538
539        loop {
540            let token = lexer.next_token()?;
541            let is_eof = token == Token::Eof;
542            tokens.push(token);
543            if is_eof {
544                break;
545            }
546        }
547
548        let mut parser = Self { tokens, pos: 0 };
549        parser.parse_expr()
550    }
551
552    fn current(&self) -> &Token {
553        self.tokens.get(self.pos).unwrap_or(&Token::Eof)
554    }
555
556    fn advance(&mut self) {
557        self.pos += 1;
558    }
559
560    fn expect(&mut self, expected: Token) -> Result<()> {
561        if self.current() == &expected {
562            self.advance();
563            Ok(())
564        } else {
565            Err(Error::InvalidExpression(format!("Expected {:?}, got {:?}", expected, self.current())))
566        }
567    }
568
569    fn parse_expr(&mut self) -> Result<Expr> {
570        self.parse_or()
571    }
572
573    fn parse_or(&mut self) -> Result<Expr> {
574        let mut left = self.parse_and()?;
575
576        while self.current() == &Token::Or {
577            self.advance();
578            let right = self.parse_and()?;
579            left = Expr::Or(Box::new(left), Box::new(right));
580        }
581
582        Ok(left)
583    }
584
585    fn parse_and(&mut self) -> Result<Expr> {
586        let mut left = self.parse_not()?;
587
588        while self.current() == &Token::And {
589            self.advance();
590            let right = self.parse_not()?;
591            left = Expr::And(Box::new(left), Box::new(right));
592        }
593
594        Ok(left)
595    }
596
597    fn parse_not(&mut self) -> Result<Expr> {
598        if self.current() == &Token::Not {
599            self.advance();
600            let expr = self.parse_not()?;
601            Ok(Expr::Not(Box::new(expr)))
602        } else {
603            self.parse_comparison()
604        }
605    }
606
607    fn parse_comparison(&mut self) -> Result<Expr> {
608        let left = self.parse_operand()?;
609
610        let op = self.current().clone();
611        match op {
612            Token::Equal => {
613                self.advance();
614                let right = self.parse_operand()?;
615                Ok(Expr::Equal(Box::new(left), Box::new(right)))
616            }
617            Token::NotEqual => {
618                self.advance();
619                let right = self.parse_operand()?;
620                Ok(Expr::NotEqual(Box::new(left), Box::new(right)))
621            }
622            Token::LessThan => {
623                self.advance();
624                let right = self.parse_operand()?;
625                Ok(Expr::LessThan(Box::new(left), Box::new(right)))
626            }
627            Token::LessThanOrEqual => {
628                self.advance();
629                let right = self.parse_operand()?;
630                Ok(Expr::LessThanOrEqual(Box::new(left), Box::new(right)))
631            }
632            Token::GreaterThan => {
633                self.advance();
634                let right = self.parse_operand()?;
635                Ok(Expr::GreaterThan(Box::new(left), Box::new(right)))
636            }
637            Token::GreaterThanOrEqual => {
638                self.advance();
639                let right = self.parse_operand()?;
640                Ok(Expr::GreaterThanOrEqual(Box::new(left), Box::new(right)))
641            }
642            _ => Ok(left) // Could be a function call that returns bool
643        }
644    }
645
646    fn parse_operand(&mut self) -> Result<Expr> {
647        match self.current().clone() {
648            Token::LeftParen => {
649                self.advance();
650                let expr = self.parse_expr()?;
651                self.expect(Token::RightParen)?;
652                Ok(expr)
653            }
654            Token::Identifier(name) => {
655                self.advance();
656                Ok(Expr::AttributePath(name))
657            }
658            Token::NamePlaceholder(name) => {
659                self.advance();
660                Ok(Expr::AttributePath(name))
661            }
662            Token::ValuePlaceholder(name) => {
663                self.advance();
664                Ok(Expr::ValuePlaceholder(name))
665            }
666            Token::AttributeExists => {
667                self.advance();
668                self.expect(Token::LeftParen)?;
669                let path = match self.current().clone() {
670                    Token::Identifier(p) => p,
671                    Token::NamePlaceholder(p) => p,
672                    _ => return Err(Error::InvalidExpression("Expected attribute path".into()))
673                };
674                self.advance();
675                self.expect(Token::RightParen)?;
676                Ok(Expr::AttributeExists(path))
677            }
678            Token::AttributeNotExists => {
679                self.advance();
680                self.expect(Token::LeftParen)?;
681                let path = match self.current().clone() {
682                    Token::Identifier(p) => p,
683                    Token::NamePlaceholder(p) => p,
684                    _ => return Err(Error::InvalidExpression("Expected attribute path".into()))
685                };
686                self.advance();
687                self.expect(Token::RightParen)?;
688                Ok(Expr::AttributeNotExists(path))
689            }
690            Token::BeginsWith => {
691                self.advance();
692                self.expect(Token::LeftParen)?;
693                let path = self.parse_operand()?;
694                self.expect(Token::Comma)?;
695                let prefix = self.parse_operand()?;
696                self.expect(Token::RightParen)?;
697                Ok(Expr::BeginsWith(Box::new(path), Box::new(prefix)))
698            }
699            _ => Err(Error::InvalidExpression(format!("Unexpected token: {:?}", self.current())))
700        }
701    }
702}
703
704/// Update expression parser
705pub struct UpdateExpressionParser {
706    tokens: Vec<Token>,
707    pos: usize,
708}
709
710impl UpdateExpressionParser {
711    /// Parse an update expression string into actions
712    /// Example: "SET age = age + :inc, active = :val REMOVE temp ADD score :points"
713    pub fn parse(input: &str) -> Result<Vec<UpdateAction>> {
714        let mut lexer = Lexer::new(input);
715        let mut tokens = Vec::new();
716
717        loop {
718            let token = lexer.next_token()?;
719            let is_eof = token == Token::Eof;
720            tokens.push(token);
721            if is_eof {
722                break;
723            }
724        }
725
726        let mut parser = Self { tokens, pos: 0 };
727        parser.parse_update_expr()
728    }
729
730    fn current(&self) -> &Token {
731        self.tokens.get(self.pos).unwrap_or(&Token::Eof)
732    }
733
734    fn advance(&mut self) {
735        self.pos += 1;
736    }
737
738    fn parse_update_expr(&mut self) -> Result<Vec<UpdateAction>> {
739        let mut actions = Vec::new();
740
741        while self.current() != &Token::Eof {
742            match self.current() {
743                Token::Set => {
744                    self.advance();
745                    actions.extend(self.parse_set_actions()?);
746                }
747                Token::Remove => {
748                    self.advance();
749                    actions.extend(self.parse_remove_actions()?);
750                }
751                Token::Add => {
752                    self.advance();
753                    actions.extend(self.parse_add_actions()?);
754                }
755                Token::Delete => {
756                    self.advance();
757                    actions.extend(self.parse_delete_actions()?);
758                }
759                _ => return Err(Error::InvalidExpression(format!("Unexpected token in update expression: {:?}", self.current())))
760            }
761        }
762
763        Ok(actions)
764    }
765
766    fn parse_set_actions(&mut self) -> Result<Vec<UpdateAction>> {
767        let mut actions = Vec::new();
768
769        loop {
770            // Get attribute path
771            let path = match self.current() {
772                Token::Identifier(p) => p.clone(),
773                Token::NamePlaceholder(p) => p.clone(),
774                _ => return Err(Error::InvalidExpression("Expected attribute path in SET".into()))
775            };
776            self.advance();
777
778            // Expect =
779            if self.current() != &Token::Equal {
780                return Err(Error::InvalidExpression("Expected = in SET action".into()));
781            }
782            self.advance();
783
784            // Parse value (could be path, placeholder, or arithmetic)
785            let value = self.parse_update_value()?;
786
787            actions.push(UpdateAction::Set(path, value));
788
789            // Check for comma (more SET actions) or end
790            if self.current() == &Token::Comma {
791                self.advance();
792            } else {
793                break;
794            }
795        }
796
797        Ok(actions)
798    }
799
800    fn parse_remove_actions(&mut self) -> Result<Vec<UpdateAction>> {
801        let mut actions = Vec::new();
802
803        loop {
804            let path = match self.current() {
805                Token::Identifier(p) => p.clone(),
806                Token::NamePlaceholder(p) => p.clone(),
807                _ => return Err(Error::InvalidExpression("Expected attribute path in REMOVE".into()))
808            };
809            self.advance();
810
811            actions.push(UpdateAction::Remove(path));
812
813            if self.current() == &Token::Comma {
814                self.advance();
815            } else {
816                break;
817            }
818        }
819
820        Ok(actions)
821    }
822
823    fn parse_add_actions(&mut self) -> Result<Vec<UpdateAction>> {
824        let mut actions = Vec::new();
825
826        loop {
827            let path = match self.current() {
828                Token::Identifier(p) => p.clone(),
829                Token::NamePlaceholder(p) => p.clone(),
830                _ => return Err(Error::InvalidExpression("Expected attribute path in ADD".into()))
831            };
832            self.advance();
833
834            let value = self.parse_update_value()?;
835
836            actions.push(UpdateAction::Add(path, value));
837
838            if self.current() == &Token::Comma {
839                self.advance();
840            } else {
841                break;
842            }
843        }
844
845        Ok(actions)
846    }
847
848    fn parse_delete_actions(&mut self) -> Result<Vec<UpdateAction>> {
849        let mut actions = Vec::new();
850
851        loop {
852            let path = match self.current() {
853                Token::Identifier(p) => p.clone(),
854                Token::NamePlaceholder(p) => p.clone(),
855                _ => return Err(Error::InvalidExpression("Expected attribute path in DELETE".into()))
856            };
857            self.advance();
858
859            let value = self.parse_update_value()?;
860
861            actions.push(UpdateAction::Delete(path, value));
862
863            if self.current() == &Token::Comma {
864                self.advance();
865            } else {
866                break;
867            }
868        }
869
870        Ok(actions)
871    }
872
873    fn parse_update_value(&mut self) -> Result<UpdateValue> {
874        // First, get the base value (path or placeholder)
875        let base = match self.current() {
876            Token::Identifier(p) => {
877                let path = p.clone();
878                self.advance();
879
880                // Check for arithmetic
881                match self.current() {
882                    Token::Plus => {
883                        self.advance();
884                        let operand = self.parse_update_value()?;
885                        return Ok(UpdateValue::Add(path, Box::new(operand)));
886                    }
887                    Token::Minus => {
888                        self.advance();
889                        let operand = self.parse_update_value()?;
890                        return Ok(UpdateValue::Sub(path, Box::new(operand)));
891                    }
892                    _ => UpdateValue::Path(path)
893                }
894            }
895            Token::NamePlaceholder(p) => {
896                let path = p.clone();
897                self.advance();
898                UpdateValue::Path(path)
899            }
900            Token::ValuePlaceholder(p) => {
901                let placeholder = p.clone();
902                self.advance();
903                UpdateValue::Placeholder(placeholder)
904            }
905            _ => return Err(Error::InvalidExpression(format!("Unexpected token in update value: {:?}", self.current())))
906        };
907
908        Ok(base)
909    }
910}
911
912#[cfg(test)]
913mod tests {
914    use super::*;
915
916    #[test]
917    fn test_attribute_exists() {
918        let mut item = HashMap::new();
919        item.insert("name".to_string(), Value::string("Alice"));
920
921        let expr = Expr::AttributeExists("name".to_string());
922        let context = ExpressionContext::new();
923        let evaluator = ExpressionEvaluator::new(&item, &context);
924
925        assert!(evaluator.evaluate(&expr).unwrap());
926    }
927
928    #[test]
929    fn test_attribute_not_exists() {
930        let item = HashMap::new();
931
932        let expr = Expr::AttributeNotExists("missing".to_string());
933        let context = ExpressionContext::new();
934        let evaluator = ExpressionEvaluator::new(&item, &context);
935
936        assert!(evaluator.evaluate(&expr).unwrap());
937    }
938
939    #[test]
940    fn test_equal_with_placeholder() {
941        let mut item = HashMap::new();
942        item.insert("age".to_string(), Value::number(30));
943
944        let expr = Expr::Equal(
945            Box::new(Expr::AttributePath("age".to_string())),
946            Box::new(Expr::ValuePlaceholder(":val".to_string())),
947        );
948
949        let context = ExpressionContext::new()
950            .with_value(":val", Value::number(30));
951
952        let evaluator = ExpressionEvaluator::new(&item, &context);
953        assert!(evaluator.evaluate(&expr).unwrap());
954    }
955
956    #[test]
957    fn test_greater_than() {
958        let mut item = HashMap::new();
959        item.insert("score".to_string(), Value::number(85));
960
961        let expr = Expr::GreaterThan(
962            Box::new(Expr::AttributePath("score".to_string())),
963            Box::new(Expr::Literal(Value::number(70))),
964        );
965
966        let context = ExpressionContext::new();
967        let evaluator = ExpressionEvaluator::new(&item, &context);
968
969        assert!(evaluator.evaluate(&expr).unwrap());
970    }
971
972    #[test]
973    fn test_and_operator() {
974        let mut item = HashMap::new();
975        item.insert("age".to_string(), Value::number(25));
976        item.insert("active".to_string(), Value::Bool(true));
977
978        let expr = Expr::And(
979            Box::new(Expr::GreaterThan(
980                Box::new(Expr::AttributePath("age".to_string())),
981                Box::new(Expr::Literal(Value::number(18))),
982            )),
983            Box::new(Expr::Equal(
984                Box::new(Expr::AttributePath("active".to_string())),
985                Box::new(Expr::Literal(Value::Bool(true))),
986            )),
987        );
988
989        let context = ExpressionContext::new();
990        let evaluator = ExpressionEvaluator::new(&item, &context);
991
992        assert!(evaluator.evaluate(&expr).unwrap());
993    }
994
995    #[test]
996    fn test_begins_with() {
997        let mut item = HashMap::new();
998        item.insert("email".to_string(), Value::string("alice@example.com"));
999
1000        let expr = Expr::BeginsWith(
1001            Box::new(Expr::AttributePath("email".to_string())),
1002            Box::new(Expr::Literal(Value::string("alice"))),
1003        );
1004
1005        let context = ExpressionContext::new();
1006        let evaluator = ExpressionEvaluator::new(&item, &context);
1007
1008        assert!(evaluator.evaluate(&expr).unwrap());
1009    }
1010
1011    #[test]
1012    fn test_name_placeholder() {
1013        let mut item = HashMap::new();
1014        item.insert("user-name".to_string(), Value::string("Alice"));
1015
1016        let expr = Expr::AttributeExists("#name".to_string());
1017
1018        let context = ExpressionContext::new()
1019            .with_name("#name", "user-name");
1020
1021        let evaluator = ExpressionEvaluator::new(&item, &context);
1022        assert!(evaluator.evaluate(&expr).unwrap());
1023    }
1024
1025    // Parser tests
1026    #[test]
1027    fn test_parse_simple_comparison() {
1028        let expr = ExpressionParser::parse("age > :min_age").unwrap();
1029        assert!(matches!(expr, Expr::GreaterThan(_, _)));
1030    }
1031
1032    #[test]
1033    fn test_parse_and_expression() {
1034        let expr = ExpressionParser::parse("age > :min AND active = :is_active").unwrap();
1035        assert!(matches!(expr, Expr::And(_, _)));
1036    }
1037
1038    #[test]
1039    fn test_parse_or_expression() {
1040        let expr = ExpressionParser::parse("age < :young OR age > :old").unwrap();
1041        assert!(matches!(expr, Expr::Or(_, _)));
1042    }
1043
1044    #[test]
1045    fn test_parse_not_expression() {
1046        let expr = ExpressionParser::parse("NOT active").unwrap();
1047        assert!(matches!(expr, Expr::Not(_)));
1048    }
1049
1050    #[test]
1051    fn test_parse_attribute_exists() {
1052        let expr = ExpressionParser::parse("attribute_exists(email)").unwrap();
1053        assert!(matches!(expr, Expr::AttributeExists(_)));
1054    }
1055
1056    #[test]
1057    fn test_parse_begins_with() {
1058        let expr = ExpressionParser::parse("begins_with(email, :prefix)").unwrap();
1059        assert!(matches!(expr, Expr::BeginsWith(_, _)));
1060    }
1061
1062    #[test]
1063    fn test_parse_complex_expression() {
1064        let expr = ExpressionParser::parse(
1065            "(age >= :min_age AND age <= :max_age) OR attribute_exists(verified)"
1066        ).unwrap();
1067        assert!(matches!(expr, Expr::Or(_, _)));
1068    }
1069
1070    #[test]
1071    fn test_parse_with_name_placeholder() {
1072        let expr = ExpressionParser::parse("attribute_exists(#name)").unwrap();
1073        match expr {
1074            Expr::AttributeExists(path) => assert_eq!(path, "#name"),
1075            _ => panic!("Expected AttributeExists"),
1076        }
1077    }
1078
1079    #[test]
1080    fn test_parse_and_evaluate() {
1081        let mut item = HashMap::new();
1082        item.insert("age".to_string(), Value::number(25));
1083        item.insert("active".to_string(), Value::Bool(true));
1084
1085        let expr = ExpressionParser::parse("age > :min AND active = :is_active").unwrap();
1086
1087        let context = ExpressionContext::new()
1088            .with_value(":min", Value::number(18))
1089            .with_value(":is_active", Value::Bool(true));
1090
1091        let evaluator = ExpressionEvaluator::new(&item, &context);
1092        assert!(evaluator.evaluate(&expr).unwrap());
1093    }
1094
1095    // Update expression tests
1096    #[test]
1097    fn test_update_set_simple() {
1098        let mut item = HashMap::new();
1099        item.insert("age".to_string(), Value::number(25));
1100
1101        let actions = UpdateExpressionParser::parse("SET age = :new_age").unwrap();
1102        assert_eq!(actions.len(), 1);
1103
1104        let context = ExpressionContext::new()
1105            .with_value(":new_age", Value::number(30));
1106
1107        let executor = UpdateExecutor::new(&context);
1108        let result = executor.execute(&item, &actions).unwrap();
1109
1110        match result.get("age").unwrap() {
1111            Value::N(n) => assert_eq!(n, "30"),
1112            _ => panic!("Expected number"),
1113        }
1114    }
1115
1116    #[test]
1117    fn test_update_set_increment() {
1118        let mut item = HashMap::new();
1119        item.insert("score".to_string(), Value::number(100));
1120
1121        let actions = UpdateExpressionParser::parse("SET score = score + :inc").unwrap();
1122
1123        let context = ExpressionContext::new()
1124            .with_value(":inc", Value::number(50));
1125
1126        let executor = UpdateExecutor::new(&context);
1127        let result = executor.execute(&item, &actions).unwrap();
1128
1129        match result.get("score").unwrap() {
1130            Value::N(n) => assert_eq!(n, "150"),
1131            _ => panic!("Expected number"),
1132        }
1133    }
1134
1135    #[test]
1136    fn test_update_remove() {
1137        let mut item = HashMap::new();
1138        item.insert("temp".to_string(), Value::string("delete_me"));
1139        item.insert("keep".to_string(), Value::string("keep_me"));
1140
1141        let actions = UpdateExpressionParser::parse("REMOVE temp").unwrap();
1142
1143        let context = ExpressionContext::new();
1144        let executor = UpdateExecutor::new(&context);
1145        let result = executor.execute(&item, &actions).unwrap();
1146
1147        assert!(!result.contains_key("temp"));
1148        assert!(result.contains_key("keep"));
1149    }
1150
1151    #[test]
1152    fn test_update_add() {
1153        let mut item = HashMap::new();
1154        item.insert("count".to_string(), Value::number(10));
1155
1156        let actions = UpdateExpressionParser::parse("ADD count :inc").unwrap();
1157
1158        let context = ExpressionContext::new()
1159            .with_value(":inc", Value::number(5));
1160
1161        let executor = UpdateExecutor::new(&context);
1162        let result = executor.execute(&item, &actions).unwrap();
1163
1164        match result.get("count").unwrap() {
1165            Value::N(n) => assert_eq!(n, "15"),
1166            _ => panic!("Expected number"),
1167        }
1168    }
1169
1170    #[test]
1171    fn test_update_multiple_actions() {
1172        let mut item = HashMap::new();
1173        item.insert("age".to_string(), Value::number(25));
1174        item.insert("temp".to_string(), Value::string("delete"));
1175        item.insert("score".to_string(), Value::number(100));
1176
1177        let actions = UpdateExpressionParser::parse(
1178            "SET age = :new_age, active = :is_active REMOVE temp ADD score :bonus"
1179        ).unwrap();
1180
1181        let context = ExpressionContext::new()
1182            .with_value(":new_age", Value::number(26))
1183            .with_value(":is_active", Value::Bool(true))
1184            .with_value(":bonus", Value::number(50));
1185
1186        let executor = UpdateExecutor::new(&context);
1187        let result = executor.execute(&item, &actions).unwrap();
1188
1189        match result.get("age").unwrap() {
1190            Value::N(n) => assert_eq!(n, "26"),
1191            _ => panic!("Expected number"),
1192        }
1193        assert_eq!(result.get("active").unwrap(), &Value::Bool(true));
1194        assert!(!result.contains_key("temp"));
1195        match result.get("score").unwrap() {
1196            Value::N(n) => assert_eq!(n, "150"),
1197            _ => panic!("Expected number"),
1198        }
1199    }
1200}