1use crate::{Item, Value, Error, Result};
37use std::collections::HashMap;
38
39#[derive(Debug, Clone, PartialEq)]
41pub enum Expr {
42 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 And(Box<Expr>, Box<Expr>),
52 Or(Box<Expr>, Box<Expr>),
53 Not(Box<Expr>),
54
55 AttributeExists(String),
57 AttributeNotExists(String),
58 BeginsWith(Box<Expr>, Box<Expr>),
59
60 AttributePath(String),
62 ValuePlaceholder(String),
63 Literal(Value),
64}
65
66#[derive(Debug, Clone, Default)]
68pub struct ExpressionContext {
69 pub values: HashMap<String, Value>,
71 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
91pub 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 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 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 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 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#[derive(Debug, Clone, PartialEq)]
219pub enum UpdateAction {
220 Set(String, UpdateValue),
222 Remove(String),
224 Add(String, UpdateValue),
226 Delete(String, UpdateValue),
228}
229
230#[derive(Debug, Clone, PartialEq)]
232pub enum UpdateValue {
233 Value(Value),
235 Placeholder(String),
237 Path(String),
239 Add(String, Box<UpdateValue>),
241 Sub(String, Box<UpdateValue>),
242}
243
244pub 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 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 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 result.insert(attr_name, add_value);
286 }
287 }
288 UpdateAction::Delete(_path, _value) => {
289 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#[derive(Debug, Clone, PartialEq)]
360enum Token {
361 Equal,
363 NotEqual,
364 LessThan,
365 LessThanOrEqual,
366 GreaterThan,
367 GreaterThanOrEqual,
368
369 And,
371 Or,
372 Not,
373
374 Set,
376 Remove,
377 Add,
378 Delete,
379
380 Plus,
382 Minus,
383
384 AttributeExists,
386 AttributeNotExists,
387 BeginsWith,
388
389 Identifier(String),
391 NamePlaceholder(String), ValuePlaceholder(String), LeftParen,
396 RightParen,
397 Comma,
398
399 Eof,
400}
401
402struct 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
527pub struct ExpressionParser {
529 tokens: Vec<Token>,
530 pos: usize,
531}
532
533impl ExpressionParser {
534 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) }
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
704pub struct UpdateExpressionParser {
706 tokens: Vec<Token>,
707 pos: usize,
708}
709
710impl UpdateExpressionParser {
711 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 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 if self.current() != &Token::Equal {
780 return Err(Error::InvalidExpression("Expected = in SET action".into()));
781 }
782 self.advance();
783
784 let value = self.parse_update_value()?;
786
787 actions.push(UpdateAction::Set(path, value));
788
789 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 let base = match self.current() {
876 Token::Identifier(p) => {
877 let path = p.clone();
878 self.advance();
879
880 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 #[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 #[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}