1use std::sync::Arc;
13
14use reifydb_core::{
15 interface::identifier::{ColumnIdentifier, ColumnPrimitive},
16 internal,
17};
18use reifydb_type::{
19 Result,
20 error::{Error, TypeError},
21 fragment::Fragment,
22 value::r#type::Type,
23};
24use serde::{Deserialize, Serialize};
25use serde_json::{from_str, to_string, to_string_pretty};
26
27use super::{
28 AccessPrimitiveExpression, AddExpression, AliasExpression, AndExpression, BetweenExpression, CallExpression,
29 CastExpression, ColumnExpression, ConstantExpression, ContainsExpression, DivExpression, ElseIfExpression,
30 EqExpression, Expression, ExtendExpression, FieldAccessExpression, GreaterThanEqExpression,
31 GreaterThanExpression, IdentExpression, IfExpression, InExpression, LessThanEqExpression, LessThanExpression,
32 ListExpression, MapExpression, MulExpression, NotEqExpression, OrExpression, ParameterExpression,
33 PrefixExpression, PrefixOperator, RemExpression, SubExpression, TupleExpression, TypeExpression,
34 VariableExpression, XorExpression,
35};
36
37#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
42#[serde(tag = "type", rename_all = "snake_case")]
43pub enum JsonExpression {
44 None,
46 Bool {
47 value: String,
48 },
49 Number {
50 value: String,
51 },
52 Text {
53 value: String,
54 },
55 Temporal {
56 value: String,
57 },
58
59 Column {
61 namespace: String,
62 source: String,
63 name: String,
64 },
65 AccessSource {
66 namespace: String,
67 source: String,
68 name: String,
69 },
70 Variable {
71 name: String,
72 },
73 #[serde(rename = "parameter_positional")]
74 ParameterPositional {
75 position: String,
76 },
77 #[serde(rename = "parameter_named")]
78 ParameterNamed {
79 name: String,
80 },
81
82 GreaterThan {
84 left: Box<JsonExpression>,
85 right: Box<JsonExpression>,
86 },
87 GreaterThanEqual {
88 left: Box<JsonExpression>,
89 right: Box<JsonExpression>,
90 },
91 LessThan {
92 left: Box<JsonExpression>,
93 right: Box<JsonExpression>,
94 },
95 LessThanEqual {
96 left: Box<JsonExpression>,
97 right: Box<JsonExpression>,
98 },
99 Equal {
100 left: Box<JsonExpression>,
101 right: Box<JsonExpression>,
102 },
103 NotEqual {
104 left: Box<JsonExpression>,
105 right: Box<JsonExpression>,
106 },
107
108 And {
110 left: Box<JsonExpression>,
111 right: Box<JsonExpression>,
112 },
113 Or {
114 left: Box<JsonExpression>,
115 right: Box<JsonExpression>,
116 },
117 Xor {
118 left: Box<JsonExpression>,
119 right: Box<JsonExpression>,
120 },
121
122 Add {
124 left: Box<JsonExpression>,
125 right: Box<JsonExpression>,
126 },
127 Sub {
128 left: Box<JsonExpression>,
129 right: Box<JsonExpression>,
130 },
131 Mul {
132 left: Box<JsonExpression>,
133 right: Box<JsonExpression>,
134 },
135 Div {
136 left: Box<JsonExpression>,
137 right: Box<JsonExpression>,
138 },
139 Rem {
140 left: Box<JsonExpression>,
141 right: Box<JsonExpression>,
142 },
143
144 Alias {
146 alias: String,
147 expression: Box<JsonExpression>,
148 },
149 Cast {
150 expression: Box<JsonExpression>,
151 to: String,
152 },
153 Call {
154 function: String,
155 args: Vec<JsonExpression>,
156 },
157 Tuple {
158 expressions: Vec<JsonExpression>,
159 },
160 List {
161 expressions: Vec<JsonExpression>,
162 },
163 Prefix {
164 operator: String,
165 expression: Box<JsonExpression>,
166 },
167 Between {
168 value: Box<JsonExpression>,
169 lower: Box<JsonExpression>,
170 upper: Box<JsonExpression>,
171 },
172 In {
173 value: Box<JsonExpression>,
174 list: Box<JsonExpression>,
175 negated: bool,
176 },
177 Contains {
178 value: Box<JsonExpression>,
179 list: Box<JsonExpression>,
180 },
181 If {
182 condition: Box<JsonExpression>,
183 then: Box<JsonExpression>,
184 else_ifs: Vec<JsonElseIf>,
185 #[serde(skip_serializing_if = "Option::is_none")]
186 else_expr: Option<Box<JsonExpression>>,
187 },
188 Map {
189 expressions: Vec<JsonExpression>,
190 },
191 Extend {
192 expressions: Vec<JsonExpression>,
193 },
194 Type {
195 ty: String,
196 },
197 FieldAccess {
198 object: Box<JsonExpression>,
199 field: String,
200 },
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
205pub struct JsonElseIf {
206 pub condition: Box<JsonExpression>,
207 pub then: Box<JsonExpression>,
208}
209
210fn extract_primitive(cp: &ColumnPrimitive) -> (String, String) {
212 match cp {
213 ColumnPrimitive::Primitive {
214 namespace,
215 primitive,
216 } => (namespace.text().to_string(), primitive.text().to_string()),
217 ColumnPrimitive::Alias(alias) => ("_alias".to_string(), alias.text().to_string()),
218 }
219}
220
221fn internal_fragment(text: &str) -> Fragment {
223 Fragment::Internal {
224 text: Arc::from(text),
225 }
226}
227
228impl From<&Expression> for JsonExpression {
229 fn from(expr: &Expression) -> Self {
230 match expr {
231 Expression::Constant(constant) => match constant {
233 ConstantExpression::None {
234 ..
235 } => JsonExpression::None,
236 ConstantExpression::Bool {
237 fragment,
238 } => JsonExpression::Bool {
239 value: fragment.text().to_string(),
240 },
241 ConstantExpression::Number {
242 fragment,
243 } => JsonExpression::Number {
244 value: fragment.text().to_string(),
245 },
246 ConstantExpression::Text {
247 fragment,
248 } => JsonExpression::Text {
249 value: fragment.text().to_string(),
250 },
251 ConstantExpression::Temporal {
252 fragment,
253 } => JsonExpression::Temporal {
254 value: fragment.text().to_string(),
255 },
256 },
257
258 Expression::Column(ColumnExpression(col)) => {
260 let (namespace, source) = extract_primitive(&col.primitive);
261 JsonExpression::Column {
262 namespace,
263 source,
264 name: col.name.text().to_string(),
265 }
266 }
267 Expression::AccessSource(AccessPrimitiveExpression {
268 column,
269 }) => {
270 let (namespace, source) = extract_primitive(&column.primitive);
271 JsonExpression::AccessSource {
272 namespace,
273 source,
274 name: column.name.text().to_string(),
275 }
276 }
277 Expression::Variable(var) => JsonExpression::Variable {
278 name: var.name().to_string(),
279 },
280 Expression::Parameter(param) => match param {
281 ParameterExpression::Positional {
282 fragment,
283 } => JsonExpression::ParameterPositional {
284 position: fragment.text()[1..].to_string(), },
286 ParameterExpression::Named {
287 fragment,
288 } => JsonExpression::ParameterNamed {
289 name: fragment.text()[1..].to_string(), },
291 },
292
293 Expression::GreaterThan(e) => JsonExpression::GreaterThan {
295 left: Box::new((&*e.left).into()),
296 right: Box::new((&*e.right).into()),
297 },
298 Expression::GreaterThanEqual(e) => JsonExpression::GreaterThanEqual {
299 left: Box::new((&*e.left).into()),
300 right: Box::new((&*e.right).into()),
301 },
302 Expression::LessThan(e) => JsonExpression::LessThan {
303 left: Box::new((&*e.left).into()),
304 right: Box::new((&*e.right).into()),
305 },
306 Expression::LessThanEqual(e) => JsonExpression::LessThanEqual {
307 left: Box::new((&*e.left).into()),
308 right: Box::new((&*e.right).into()),
309 },
310 Expression::Equal(e) => JsonExpression::Equal {
311 left: Box::new((&*e.left).into()),
312 right: Box::new((&*e.right).into()),
313 },
314 Expression::NotEqual(e) => JsonExpression::NotEqual {
315 left: Box::new((&*e.left).into()),
316 right: Box::new((&*e.right).into()),
317 },
318
319 Expression::And(e) => JsonExpression::And {
321 left: Box::new((&*e.left).into()),
322 right: Box::new((&*e.right).into()),
323 },
324 Expression::Or(e) => JsonExpression::Or {
325 left: Box::new((&*e.left).into()),
326 right: Box::new((&*e.right).into()),
327 },
328 Expression::Xor(e) => JsonExpression::Xor {
329 left: Box::new((&*e.left).into()),
330 right: Box::new((&*e.right).into()),
331 },
332
333 Expression::Add(e) => JsonExpression::Add {
335 left: Box::new((&*e.left).into()),
336 right: Box::new((&*e.right).into()),
337 },
338 Expression::Sub(e) => JsonExpression::Sub {
339 left: Box::new((&*e.left).into()),
340 right: Box::new((&*e.right).into()),
341 },
342 Expression::Mul(e) => JsonExpression::Mul {
343 left: Box::new((&*e.left).into()),
344 right: Box::new((&*e.right).into()),
345 },
346 Expression::Div(e) => JsonExpression::Div {
347 left: Box::new((&*e.left).into()),
348 right: Box::new((&*e.right).into()),
349 },
350 Expression::Rem(e) => JsonExpression::Rem {
351 left: Box::new((&*e.left).into()),
352 right: Box::new((&*e.right).into()),
353 },
354
355 Expression::Alias(e) => JsonExpression::Alias {
357 alias: e.alias.name().to_string(),
358 expression: Box::new((&*e.expression).into()),
359 },
360 Expression::Cast(e) => JsonExpression::Cast {
361 expression: Box::new((&*e.expression).into()),
362 to: format!("{:?}", e.to.ty),
363 },
364 Expression::Call(e) => JsonExpression::Call {
365 function: e.func.name().to_string(),
366 args: e.args.iter().map(|a| a.into()).collect(),
367 },
368 Expression::Tuple(e) => JsonExpression::Tuple {
369 expressions: e.expressions.iter().map(|a| a.into()).collect(),
370 },
371 Expression::List(e) => JsonExpression::List {
372 expressions: e.expressions.iter().map(|a| a.into()).collect(),
373 },
374 Expression::Prefix(e) => {
375 let operator = match &e.operator {
376 PrefixOperator::Minus(_) => "-",
377 PrefixOperator::Plus(_) => "+",
378 PrefixOperator::Not(_) => "not",
379 };
380 JsonExpression::Prefix {
381 operator: operator.to_string(),
382 expression: Box::new((&*e.expression).into()),
383 }
384 }
385 Expression::Between(e) => JsonExpression::Between {
386 value: Box::new((&*e.value).into()),
387 lower: Box::new((&*e.lower).into()),
388 upper: Box::new((&*e.upper).into()),
389 },
390 Expression::In(e) => JsonExpression::In {
391 value: Box::new((&*e.value).into()),
392 list: Box::new((&*e.list).into()),
393 negated: e.negated,
394 },
395 Expression::Contains(e) => JsonExpression::Contains {
396 value: Box::new((&*e.value).into()),
397 list: Box::new((&*e.list).into()),
398 },
399 Expression::If(e) => JsonExpression::If {
400 condition: Box::new((&*e.condition).into()),
401 then: Box::new((&*e.then_expr).into()),
402 else_ifs: e
403 .else_ifs
404 .iter()
405 .map(|ei| JsonElseIf {
406 condition: Box::new((&*ei.condition).into()),
407 then: Box::new((&*ei.then_expr).into()),
408 })
409 .collect(),
410 else_expr: e.else_expr.as_ref().map(|ee| Box::new((&**ee).into())),
411 },
412 Expression::Map(e) => JsonExpression::Map {
413 expressions: e.expressions.iter().map(|a| a.into()).collect(),
414 },
415 Expression::Extend(e) => JsonExpression::Extend {
416 expressions: e.expressions.iter().map(|a| a.into()).collect(),
417 },
418 Expression::Type(e) => JsonExpression::Type {
419 ty: format!("{:?}", e.ty),
420 },
421 Expression::SumTypeConstructor(_) => JsonExpression::Type {
422 ty: "SumTypeConstructor".to_string(),
423 },
424 Expression::IsVariant(_) => JsonExpression::Type {
425 ty: "IsVariant".to_string(),
426 },
427 Expression::FieldAccess(e) => JsonExpression::FieldAccess {
428 object: Box::new((&*e.object).into()),
429 field: e.field.text().to_string(),
430 },
431 }
432 }
433}
434
435impl TryFrom<JsonExpression> for Expression {
436 type Error = Error;
437
438 fn try_from(json: JsonExpression) -> Result<Self> {
439 Ok(match json {
440 JsonExpression::None => Expression::Constant(ConstantExpression::None {
442 fragment: Fragment::None,
443 }),
444 JsonExpression::Bool {
445 value,
446 } => Expression::Constant(ConstantExpression::Bool {
447 fragment: internal_fragment(&value),
448 }),
449 JsonExpression::Number {
450 value,
451 } => Expression::Constant(ConstantExpression::Number {
452 fragment: internal_fragment(&value),
453 }),
454 JsonExpression::Text {
455 value,
456 } => Expression::Constant(ConstantExpression::Text {
457 fragment: internal_fragment(&value),
458 }),
459 JsonExpression::Temporal {
460 value,
461 } => Expression::Constant(ConstantExpression::Temporal {
462 fragment: internal_fragment(&value),
463 }),
464
465 JsonExpression::Column {
467 namespace,
468 source: primitive,
469 name,
470 } => Expression::Column(ColumnExpression(ColumnIdentifier {
471 primitive: ColumnPrimitive::Primitive {
472 namespace: internal_fragment(&namespace),
473 primitive: internal_fragment(&primitive),
474 },
475 name: internal_fragment(&name),
476 })),
477 JsonExpression::AccessSource {
478 namespace,
479 source: primitive,
480 name,
481 } => Expression::AccessSource(AccessPrimitiveExpression {
482 column: ColumnIdentifier {
483 primitive: ColumnPrimitive::Primitive {
484 namespace: internal_fragment(&namespace),
485 primitive: internal_fragment(&primitive),
486 },
487 name: internal_fragment(&name),
488 },
489 }),
490 JsonExpression::Variable {
491 name,
492 } => Expression::Variable(VariableExpression {
493 fragment: internal_fragment(&format!("${}", name)),
494 }),
495 JsonExpression::ParameterPositional {
496 position,
497 } => Expression::Parameter(ParameterExpression::Positional {
498 fragment: internal_fragment(&format!("${}", position)),
499 }),
500 JsonExpression::ParameterNamed {
501 name,
502 } => Expression::Parameter(ParameterExpression::Named {
503 fragment: internal_fragment(&format!("${}", name)),
504 }),
505
506 JsonExpression::GreaterThan {
508 left,
509 right,
510 } => Expression::GreaterThan(GreaterThanExpression {
511 left: Box::new((*left).try_into()?),
512 right: Box::new((*right).try_into()?),
513 fragment: Fragment::None,
514 }),
515 JsonExpression::GreaterThanEqual {
516 left,
517 right,
518 } => Expression::GreaterThanEqual(GreaterThanEqExpression {
519 left: Box::new((*left).try_into()?),
520 right: Box::new((*right).try_into()?),
521 fragment: Fragment::None,
522 }),
523 JsonExpression::LessThan {
524 left,
525 right,
526 } => Expression::LessThan(LessThanExpression {
527 left: Box::new((*left).try_into()?),
528 right: Box::new((*right).try_into()?),
529 fragment: Fragment::None,
530 }),
531 JsonExpression::LessThanEqual {
532 left,
533 right,
534 } => Expression::LessThanEqual(LessThanEqExpression {
535 left: Box::new((*left).try_into()?),
536 right: Box::new((*right).try_into()?),
537 fragment: Fragment::None,
538 }),
539 JsonExpression::Equal {
540 left,
541 right,
542 } => Expression::Equal(EqExpression {
543 left: Box::new((*left).try_into()?),
544 right: Box::new((*right).try_into()?),
545 fragment: Fragment::None,
546 }),
547 JsonExpression::NotEqual {
548 left,
549 right,
550 } => Expression::NotEqual(NotEqExpression {
551 left: Box::new((*left).try_into()?),
552 right: Box::new((*right).try_into()?),
553 fragment: Fragment::None,
554 }),
555
556 JsonExpression::And {
558 left,
559 right,
560 } => Expression::And(AndExpression {
561 left: Box::new((*left).try_into()?),
562 right: Box::new((*right).try_into()?),
563 fragment: Fragment::None,
564 }),
565 JsonExpression::Or {
566 left,
567 right,
568 } => Expression::Or(OrExpression {
569 left: Box::new((*left).try_into()?),
570 right: Box::new((*right).try_into()?),
571 fragment: Fragment::None,
572 }),
573 JsonExpression::Xor {
574 left,
575 right,
576 } => Expression::Xor(XorExpression {
577 left: Box::new((*left).try_into()?),
578 right: Box::new((*right).try_into()?),
579 fragment: Fragment::None,
580 }),
581
582 JsonExpression::Add {
584 left,
585 right,
586 } => Expression::Add(AddExpression {
587 left: Box::new((*left).try_into()?),
588 right: Box::new((*right).try_into()?),
589 fragment: Fragment::None,
590 }),
591 JsonExpression::Sub {
592 left,
593 right,
594 } => Expression::Sub(SubExpression {
595 left: Box::new((*left).try_into()?),
596 right: Box::new((*right).try_into()?),
597 fragment: Fragment::None,
598 }),
599 JsonExpression::Mul {
600 left,
601 right,
602 } => Expression::Mul(MulExpression {
603 left: Box::new((*left).try_into()?),
604 right: Box::new((*right).try_into()?),
605 fragment: Fragment::None,
606 }),
607 JsonExpression::Div {
608 left,
609 right,
610 } => Expression::Div(DivExpression {
611 left: Box::new((*left).try_into()?),
612 right: Box::new((*right).try_into()?),
613 fragment: Fragment::None,
614 }),
615 JsonExpression::Rem {
616 left,
617 right,
618 } => Expression::Rem(RemExpression {
619 left: Box::new((*left).try_into()?),
620 right: Box::new((*right).try_into()?),
621 fragment: Fragment::None,
622 }),
623
624 JsonExpression::Alias {
626 alias,
627 expression,
628 } => Expression::Alias(AliasExpression {
629 alias: IdentExpression(internal_fragment(&alias)),
630 expression: Box::new((*expression).try_into()?),
631 fragment: Fragment::None,
632 }),
633 JsonExpression::Cast {
634 expression,
635 to,
636 } => {
637 let ty = parse_type(&to)?;
638 Expression::Cast(CastExpression {
639 expression: Box::new((*expression).try_into()?),
640 to: TypeExpression {
641 ty,
642 fragment: internal_fragment(&to),
643 },
644 fragment: Fragment::None,
645 })
646 }
647 JsonExpression::Call {
648 function,
649 args,
650 } => Expression::Call(CallExpression {
651 func: IdentExpression(internal_fragment(&function)),
652 args: args.into_iter().map(|a| a.try_into()).collect::<Result<Vec<_>>>()?,
653 fragment: Fragment::None,
654 }),
655 JsonExpression::Tuple {
656 expressions,
657 } => Expression::Tuple(TupleExpression {
658 expressions: expressions
659 .into_iter()
660 .map(|a| a.try_into())
661 .collect::<Result<Vec<_>>>()?,
662 fragment: Fragment::None,
663 }),
664 JsonExpression::List {
665 expressions,
666 } => Expression::List(ListExpression {
667 expressions: expressions
668 .into_iter()
669 .map(|a| a.try_into())
670 .collect::<Result<Vec<_>>>()?,
671 fragment: Fragment::None,
672 }),
673 JsonExpression::Prefix {
674 operator,
675 expression,
676 } => {
677 let op = match operator.as_str() {
678 "-" => PrefixOperator::Minus(Fragment::None),
679 "+" => PrefixOperator::Plus(Fragment::None),
680 "not" => PrefixOperator::Not(Fragment::None),
681 _ => {
682 return Err(Error(internal!("Unknown prefix operator: {}", operator)));
683 }
684 };
685 Expression::Prefix(PrefixExpression {
686 operator: op,
687 expression: Box::new((*expression).try_into()?),
688 fragment: Fragment::None,
689 })
690 }
691 JsonExpression::Between {
692 value,
693 lower,
694 upper,
695 } => Expression::Between(BetweenExpression {
696 value: Box::new((*value).try_into()?),
697 lower: Box::new((*lower).try_into()?),
698 upper: Box::new((*upper).try_into()?),
699 fragment: Fragment::None,
700 }),
701 JsonExpression::In {
702 value,
703 list,
704 negated,
705 } => Expression::In(InExpression {
706 value: Box::new((*value).try_into()?),
707 list: Box::new((*list).try_into()?),
708 negated,
709 fragment: Fragment::None,
710 }),
711 JsonExpression::Contains {
712 value,
713 list,
714 } => Expression::Contains(ContainsExpression {
715 value: Box::new((*value).try_into()?),
716 list: Box::new((*list).try_into()?),
717 fragment: Fragment::None,
718 }),
719 JsonExpression::If {
720 condition,
721 then,
722 else_ifs,
723 else_expr,
724 } => {
725 let converted_else: Option<Box<Expression>> = match else_expr {
726 Some(ee) => Some(Box::new((*ee).try_into()?)),
727 None => None,
728 };
729 Expression::If(IfExpression {
730 condition: Box::new((*condition).try_into()?),
731 then_expr: Box::new((*then).try_into()?),
732 else_ifs: else_ifs
733 .into_iter()
734 .map(|ei| {
735 Ok(ElseIfExpression {
736 condition: Box::new((*ei.condition).try_into()?),
737 then_expr: Box::new((*ei.then).try_into()?),
738 fragment: Fragment::None,
739 })
740 })
741 .collect::<Result<Vec<_>>>()?,
742 else_expr: converted_else,
743 fragment: Fragment::None,
744 })
745 }
746 JsonExpression::Map {
747 expressions,
748 } => Expression::Map(MapExpression {
749 expressions: expressions
750 .into_iter()
751 .map(|a| a.try_into())
752 .collect::<Result<Vec<_>>>()?,
753 fragment: Fragment::None,
754 }),
755 JsonExpression::Extend {
756 expressions,
757 } => Expression::Extend(ExtendExpression {
758 expressions: expressions
759 .into_iter()
760 .map(|a| a.try_into())
761 .collect::<Result<Vec<_>>>()?,
762 fragment: Fragment::None,
763 }),
764 JsonExpression::Type {
765 ty,
766 } => {
767 let parsed_ty = parse_type(&ty)?;
768 Expression::Type(TypeExpression {
769 ty: parsed_ty,
770 fragment: internal_fragment(&ty),
771 })
772 }
773 JsonExpression::FieldAccess {
774 object,
775 field,
776 } => Expression::FieldAccess(FieldAccessExpression {
777 object: Box::new((*object).try_into()?),
778 field: internal_fragment(&field),
779 fragment: Fragment::None,
780 }),
781 })
782 }
783}
784
785fn parse_type(s: &str) -> Result<Type> {
787 let ty = match s.to_lowercase().as_str() {
789 "boolean" => Type::Boolean,
790 "bool" => Type::Boolean,
791 "int1" => Type::Int1,
792 "int2" => Type::Int2,
793 "int4" => Type::Int4,
794 "int8" => Type::Int8,
795 "int16" => Type::Int16,
796 "int32" => Type::Int4,
797 "int64" => Type::Int8,
798 "uint1" => Type::Uint1,
799 "uint2" => Type::Uint2,
800 "uint4" => Type::Uint4,
801 "uint8" => Type::Uint8,
802 "uint16" => Type::Uint16,
803 "float4" => Type::Float4,
804 "float8" => Type::Float8,
805 "float32" => Type::Float4,
806 "float64" => Type::Float8,
807 "utf8" => Type::Utf8,
808 "string" => Type::Utf8,
809 "text" => Type::Utf8,
810 "blob" => Type::Blob,
811 "uuid4" => Type::Uuid4,
812 "uuid7" => Type::Uuid7,
813 "date" => Type::Date,
814 "time" => Type::Time,
815 "datetime" => Type::DateTime,
816 "duration" => Type::Duration,
817 "identityid" => Type::IdentityId,
818 "int" => Type::Int,
819 "uint" => Type::Uint,
820 "decimal" => Type::Decimal,
821 _ => {
822 return Err(Error(internal!("Unknown type: {}", s)));
823 }
824 };
825
826 Ok(ty)
827}
828
829pub fn to_json(expr: &Expression) -> String {
834 let json_expr: JsonExpression = expr.into();
835 to_string(&json_expr).expect("JsonExpression should always serialize")
836}
837
838pub fn to_json_pretty(expr: &Expression) -> String {
840 let json_expr: JsonExpression = expr.into();
841 to_string_pretty(&json_expr).expect("JsonExpression should always serialize")
842}
843
844pub fn from_json(json: &str) -> Result<Expression> {
846 let json_expr: JsonExpression = from_str(json).map_err(|e| {
847 Error::from(TypeError::SerdeDeserialize {
848 message: e.to_string(),
849 })
850 })?;
851 json_expr.try_into()
852}
853
854#[cfg(test)]
855pub mod tests {
856 use super::*;
857
858 fn column_expr(name: &str) -> Expression {
860 Expression::Column(ColumnExpression(ColumnIdentifier {
861 primitive: ColumnPrimitive::Primitive {
862 namespace: internal_fragment("_context"),
863 primitive: internal_fragment("_context"),
864 },
865 name: internal_fragment(name),
866 }))
867 }
868
869 fn constant_number(val: &str) -> Expression {
870 Expression::Constant(ConstantExpression::Number {
871 fragment: internal_fragment(val),
872 })
873 }
874
875 fn constant_text(val: &str) -> Expression {
876 Expression::Constant(ConstantExpression::Text {
877 fragment: internal_fragment(val),
878 })
879 }
880
881 fn constant_bool(val: &str) -> Expression {
882 Expression::Constant(ConstantExpression::Bool {
883 fragment: internal_fragment(val),
884 })
885 }
886
887 #[test]
892 fn test_undefined() {
893 let expr = Expression::Constant(ConstantExpression::None {
894 fragment: Fragment::None,
895 });
896
897 let json = to_json(&expr);
898 assert_eq!(json, r#"{"type":"none"}"#);
899
900 let recovered = from_json(&json).unwrap();
901 assert_eq!(to_json(&recovered), json);
902 }
903
904 #[test]
905 fn test_bool() {
906 let expr = constant_bool("true");
907
908 let json = to_json(&expr);
909 assert_eq!(json, r#"{"type":"bool","value":"true"}"#);
910
911 let recovered = from_json(&json).unwrap();
912 assert_eq!(to_json(&recovered), json);
913 }
914
915 #[test]
916 fn test_number() {
917 let expr = constant_number("42");
918
919 let json = to_json(&expr);
920 assert_eq!(json, r#"{"type":"number","value":"42"}"#);
921
922 let recovered = from_json(&json).unwrap();
923 assert_eq!(to_json(&recovered), json);
924 }
925
926 #[test]
927 fn test_text() {
928 let expr = constant_text("hello world");
929
930 let json = to_json(&expr);
931 assert_eq!(json, r#"{"type":"text","value":"hello world"}"#);
932
933 let recovered = from_json(&json).unwrap();
934 assert_eq!(to_json(&recovered), json);
935 }
936
937 #[test]
938 fn test_temporal() {
939 let expr = Expression::Constant(ConstantExpression::Temporal {
940 fragment: internal_fragment("2024-01-15T10:30:00"),
941 });
942
943 let json = to_json(&expr);
944 assert_eq!(json, r#"{"type":"temporal","value":"2024-01-15T10:30:00"}"#);
945
946 let recovered = from_json(&json).unwrap();
947 assert_eq!(to_json(&recovered), json);
948 }
949
950 #[test]
955 fn test_column() {
956 let expr = column_expr("age");
957
958 let json = to_json(&expr);
959 assert_eq!(json, r#"{"type":"column","namespace":"_context","source":"_context","name":"age"}"#);
960
961 let recovered = from_json(&json).unwrap();
962 assert_eq!(to_json(&recovered), json);
963 }
964
965 #[test]
966 fn test_variable() {
967 let expr = Expression::Variable(VariableExpression {
968 fragment: internal_fragment("$my_var"),
969 });
970
971 let json = to_json(&expr);
972 assert_eq!(json, r#"{"type":"variable","name":"my_var"}"#);
973
974 let recovered = from_json(&json).unwrap();
975 assert_eq!(to_json(&recovered), json);
976 }
977
978 #[test]
979 fn test_parameter_positional() {
980 let expr = Expression::Parameter(ParameterExpression::Positional {
981 fragment: internal_fragment("$1"),
982 });
983
984 let json = to_json(&expr);
985 assert_eq!(json, r#"{"type":"parameter_positional","position":"1"}"#);
986
987 let recovered = from_json(&json).unwrap();
988 assert_eq!(to_json(&recovered), json);
989 }
990
991 #[test]
992 fn test_parameter_named() {
993 let expr = Expression::Parameter(ParameterExpression::Named {
994 fragment: internal_fragment("$name"),
995 });
996
997 let json = to_json(&expr);
998 assert_eq!(json, r#"{"type":"parameter_named","name":"name"}"#);
999
1000 let recovered = from_json(&json).unwrap();
1001 assert_eq!(to_json(&recovered), json);
1002 }
1003
1004 #[test]
1009 fn test_greater_than() {
1010 let expr = Expression::GreaterThan(GreaterThanExpression {
1011 left: Box::new(column_expr("age")),
1012 right: Box::new(constant_number("18")),
1013 fragment: Fragment::None,
1014 });
1015
1016 let json = to_json(&expr);
1017 assert_eq!(
1018 json,
1019 r#"{"type":"greater_than","left":{"type":"column","namespace":"_context","source":"_context","name":"age"},"right":{"type":"number","value":"18"}}"#
1020 );
1021
1022 let recovered = from_json(&json).unwrap();
1023 assert_eq!(to_json(&recovered), json);
1024 }
1025
1026 #[test]
1027 fn test_greater_than_equal() {
1028 let expr = Expression::GreaterThanEqual(GreaterThanEqExpression {
1029 left: Box::new(column_expr("price")),
1030 right: Box::new(constant_number("100")),
1031 fragment: Fragment::None,
1032 });
1033
1034 let json = to_json(&expr);
1035 assert_eq!(
1036 json,
1037 r#"{"type":"greater_than_equal","left":{"type":"column","namespace":"_context","source":"_context","name":"price"},"right":{"type":"number","value":"100"}}"#
1038 );
1039
1040 let recovered = from_json(&json).unwrap();
1041 assert_eq!(to_json(&recovered), json);
1042 }
1043
1044 #[test]
1045 fn test_less_than() {
1046 let expr = Expression::LessThan(LessThanExpression {
1047 left: Box::new(column_expr("count")),
1048 right: Box::new(constant_number("10")),
1049 fragment: Fragment::None,
1050 });
1051
1052 let json = to_json(&expr);
1053 assert_eq!(
1054 json,
1055 r#"{"type":"less_than","left":{"type":"column","namespace":"_context","source":"_context","name":"count"},"right":{"type":"number","value":"10"}}"#
1056 );
1057
1058 let recovered = from_json(&json).unwrap();
1059 assert_eq!(to_json(&recovered), json);
1060 }
1061
1062 #[test]
1063 fn test_less_than_equal() {
1064 let expr = Expression::LessThanEqual(LessThanEqExpression {
1065 left: Box::new(column_expr("quantity")),
1066 right: Box::new(constant_number("5")),
1067 fragment: Fragment::None,
1068 });
1069
1070 let json = to_json(&expr);
1071 assert_eq!(
1072 json,
1073 r#"{"type":"less_than_equal","left":{"type":"column","namespace":"_context","source":"_context","name":"quantity"},"right":{"type":"number","value":"5"}}"#
1074 );
1075
1076 let recovered = from_json(&json).unwrap();
1077 assert_eq!(to_json(&recovered), json);
1078 }
1079
1080 #[test]
1081 fn test_equal() {
1082 let expr = Expression::Equal(EqExpression {
1083 left: Box::new(column_expr("status")),
1084 right: Box::new(constant_text("active")),
1085 fragment: Fragment::None,
1086 });
1087
1088 let json = to_json(&expr);
1089 assert_eq!(
1090 json,
1091 r#"{"type":"equal","left":{"type":"column","namespace":"_context","source":"_context","name":"status"},"right":{"type":"text","value":"active"}}"#
1092 );
1093
1094 let recovered = from_json(&json).unwrap();
1095 assert_eq!(to_json(&recovered), json);
1096 }
1097
1098 #[test]
1099 fn test_not_equal() {
1100 let expr = Expression::NotEqual(NotEqExpression {
1101 left: Box::new(column_expr("type")),
1102 right: Box::new(constant_text("deleted")),
1103 fragment: Fragment::None,
1104 });
1105
1106 let json = to_json(&expr);
1107 assert_eq!(
1108 json,
1109 r#"{"type":"not_equal","left":{"type":"column","namespace":"_context","source":"_context","name":"type"},"right":{"type":"text","value":"deleted"}}"#
1110 );
1111
1112 let recovered = from_json(&json).unwrap();
1113 assert_eq!(to_json(&recovered), json);
1114 }
1115
1116 #[test]
1121 fn test_and() {
1122 let expr = Expression::And(AndExpression {
1123 left: Box::new(Expression::GreaterThan(GreaterThanExpression {
1124 left: Box::new(column_expr("age")),
1125 right: Box::new(constant_number("18")),
1126 fragment: Fragment::None,
1127 })),
1128 right: Box::new(Expression::Equal(EqExpression {
1129 left: Box::new(column_expr("active")),
1130 right: Box::new(constant_bool("true")),
1131 fragment: Fragment::None,
1132 })),
1133 fragment: Fragment::None,
1134 });
1135
1136 let json = to_json(&expr);
1137 assert_eq!(
1138 json,
1139 r#"{"type":"and","left":{"type":"greater_than","left":{"type":"column","namespace":"_context","source":"_context","name":"age"},"right":{"type":"number","value":"18"}},"right":{"type":"equal","left":{"type":"column","namespace":"_context","source":"_context","name":"active"},"right":{"type":"bool","value":"true"}}}"#
1140 );
1141
1142 let recovered = from_json(&json).unwrap();
1143 assert_eq!(to_json(&recovered), json);
1144 }
1145
1146 #[test]
1147 fn test_or() {
1148 let expr = Expression::Or(OrExpression {
1149 left: Box::new(column_expr("a")),
1150 right: Box::new(column_expr("b")),
1151 fragment: Fragment::None,
1152 });
1153
1154 let json = to_json(&expr);
1155 assert_eq!(
1156 json,
1157 r#"{"type":"or","left":{"type":"column","namespace":"_context","source":"_context","name":"a"},"right":{"type":"column","namespace":"_context","source":"_context","name":"b"}}"#
1158 );
1159
1160 let recovered = from_json(&json).unwrap();
1161 assert_eq!(to_json(&recovered), json);
1162 }
1163
1164 #[test]
1165 fn test_xor() {
1166 let expr = Expression::Xor(XorExpression {
1167 left: Box::new(column_expr("x")),
1168 right: Box::new(column_expr("y")),
1169 fragment: Fragment::None,
1170 });
1171
1172 let json = to_json(&expr);
1173 assert_eq!(
1174 json,
1175 r#"{"type":"xor","left":{"type":"column","namespace":"_context","source":"_context","name":"x"},"right":{"type":"column","namespace":"_context","source":"_context","name":"y"}}"#
1176 );
1177
1178 let recovered = from_json(&json).unwrap();
1179 assert_eq!(to_json(&recovered), json);
1180 }
1181
1182 #[test]
1187 fn test_add() {
1188 let expr = Expression::Add(AddExpression {
1189 left: Box::new(column_expr("price")),
1190 right: Box::new(constant_number("10")),
1191 fragment: Fragment::None,
1192 });
1193
1194 let json = to_json(&expr);
1195 assert_eq!(
1196 json,
1197 r#"{"type":"add","left":{"type":"column","namespace":"_context","source":"_context","name":"price"},"right":{"type":"number","value":"10"}}"#
1198 );
1199
1200 let recovered = from_json(&json).unwrap();
1201 assert_eq!(to_json(&recovered), json);
1202 }
1203
1204 #[test]
1205 fn test_sub() {
1206 let expr = Expression::Sub(SubExpression {
1207 left: Box::new(column_expr("total")),
1208 right: Box::new(constant_number("5")),
1209 fragment: Fragment::None,
1210 });
1211
1212 let json = to_json(&expr);
1213 assert_eq!(
1214 json,
1215 r#"{"type":"sub","left":{"type":"column","namespace":"_context","source":"_context","name":"total"},"right":{"type":"number","value":"5"}}"#
1216 );
1217
1218 let recovered = from_json(&json).unwrap();
1219 assert_eq!(to_json(&recovered), json);
1220 }
1221
1222 #[test]
1223 fn test_mul() {
1224 let expr = Expression::Mul(MulExpression {
1225 left: Box::new(column_expr("qty")),
1226 right: Box::new(constant_number("2")),
1227 fragment: Fragment::None,
1228 });
1229
1230 let json = to_json(&expr);
1231 assert_eq!(
1232 json,
1233 r#"{"type":"mul","left":{"type":"column","namespace":"_context","source":"_context","name":"qty"},"right":{"type":"number","value":"2"}}"#
1234 );
1235
1236 let recovered = from_json(&json).unwrap();
1237 assert_eq!(to_json(&recovered), json);
1238 }
1239
1240 #[test]
1241 fn test_div() {
1242 let expr = Expression::Div(DivExpression {
1243 left: Box::new(column_expr("amount")),
1244 right: Box::new(constant_number("4")),
1245 fragment: Fragment::None,
1246 });
1247
1248 let json = to_json(&expr);
1249 assert_eq!(
1250 json,
1251 r#"{"type":"div","left":{"type":"column","namespace":"_context","source":"_context","name":"amount"},"right":{"type":"number","value":"4"}}"#
1252 );
1253
1254 let recovered = from_json(&json).unwrap();
1255 assert_eq!(to_json(&recovered), json);
1256 }
1257
1258 #[test]
1259 fn test_rem() {
1260 let expr = Expression::Rem(RemExpression {
1261 left: Box::new(column_expr("num")),
1262 right: Box::new(constant_number("3")),
1263 fragment: Fragment::None,
1264 });
1265
1266 let json = to_json(&expr);
1267 assert_eq!(
1268 json,
1269 r#"{"type":"rem","left":{"type":"column","namespace":"_context","source":"_context","name":"num"},"right":{"type":"number","value":"3"}}"#
1270 );
1271
1272 let recovered = from_json(&json).unwrap();
1273 assert_eq!(to_json(&recovered), json);
1274 }
1275
1276 #[test]
1281 fn test_alias() {
1282 let expr = Expression::Alias(AliasExpression {
1283 alias: IdentExpression(internal_fragment("user_name")),
1284 expression: Box::new(column_expr("name")),
1285 fragment: Fragment::None,
1286 });
1287
1288 let json = to_json(&expr);
1289 assert_eq!(
1290 json,
1291 r#"{"type":"alias","alias":"user_name","expression":{"type":"column","namespace":"_context","source":"_context","name":"name"}}"#
1292 );
1293
1294 let recovered = from_json(&json).unwrap();
1295 assert_eq!(to_json(&recovered), json);
1296 }
1297
1298 #[test]
1299 fn test_cast() {
1300 let expr = Expression::Cast(CastExpression {
1301 expression: Box::new(column_expr("value")),
1302 to: TypeExpression {
1303 ty: Type::Int4,
1304 fragment: internal_fragment("Int4"),
1305 },
1306 fragment: Fragment::None,
1307 });
1308
1309 let json = to_json(&expr);
1310 assert_eq!(
1311 json,
1312 r#"{"type":"cast","expression":{"type":"column","namespace":"_context","source":"_context","name":"value"},"to":"Int4"}"#
1313 );
1314
1315 let recovered = from_json(&json).unwrap();
1316 assert_eq!(to_json(&recovered), json);
1317 }
1318
1319 #[test]
1320 fn test_call() {
1321 let expr = Expression::Call(CallExpression {
1322 func: IdentExpression(internal_fragment("math::avg")),
1323 args: vec![column_expr("price")],
1324 fragment: Fragment::None,
1325 });
1326
1327 let json = to_json(&expr);
1328 assert_eq!(
1329 json,
1330 r#"{"type":"call","function":"math::avg","args":[{"type":"column","namespace":"_context","source":"_context","name":"price"}]}"#
1331 );
1332
1333 let recovered = from_json(&json).unwrap();
1334 assert_eq!(to_json(&recovered), json);
1335 }
1336
1337 #[test]
1338 fn test_tuple() {
1339 let expr = Expression::Tuple(TupleExpression {
1340 expressions: vec![constant_number("1"), constant_number("2"), constant_number("3")],
1341 fragment: Fragment::None,
1342 });
1343
1344 let json = to_json(&expr);
1345 assert_eq!(
1346 json,
1347 r#"{"type":"tuple","expressions":[{"type":"number","value":"1"},{"type":"number","value":"2"},{"type":"number","value":"3"}]}"#
1348 );
1349
1350 let recovered = from_json(&json).unwrap();
1351 assert_eq!(to_json(&recovered), json);
1352 }
1353
1354 #[test]
1355 fn test_prefix_minus() {
1356 let expr = Expression::Prefix(PrefixExpression {
1357 operator: PrefixOperator::Minus(Fragment::None),
1358 expression: Box::new(column_expr("value")),
1359 fragment: Fragment::None,
1360 });
1361
1362 let json = to_json(&expr);
1363 assert_eq!(
1364 json,
1365 r#"{"type":"prefix","operator":"-","expression":{"type":"column","namespace":"_context","source":"_context","name":"value"}}"#
1366 );
1367
1368 let recovered = from_json(&json).unwrap();
1369 assert_eq!(to_json(&recovered), json);
1370 }
1371
1372 #[test]
1373 fn test_prefix_not() {
1374 let expr = Expression::Prefix(PrefixExpression {
1375 operator: PrefixOperator::Not(Fragment::None),
1376 expression: Box::new(column_expr("flag")),
1377 fragment: Fragment::None,
1378 });
1379
1380 let json = to_json(&expr);
1381 assert_eq!(
1382 json,
1383 r#"{"type":"prefix","operator":"not","expression":{"type":"column","namespace":"_context","source":"_context","name":"flag"}}"#
1384 );
1385
1386 let recovered = from_json(&json).unwrap();
1387 assert_eq!(to_json(&recovered), json);
1388 }
1389
1390 #[test]
1391 fn test_between() {
1392 let expr = Expression::Between(BetweenExpression {
1393 value: Box::new(column_expr("age")),
1394 lower: Box::new(constant_number("18")),
1395 upper: Box::new(constant_number("65")),
1396 fragment: Fragment::None,
1397 });
1398
1399 let json = to_json(&expr);
1400 assert_eq!(
1401 json,
1402 r#"{"type":"between","value":{"type":"column","namespace":"_context","source":"_context","name":"age"},"lower":{"type":"number","value":"18"},"upper":{"type":"number","value":"65"}}"#
1403 );
1404
1405 let recovered = from_json(&json).unwrap();
1406 assert_eq!(to_json(&recovered), json);
1407 }
1408
1409 #[test]
1410 fn test_in() {
1411 let expr = Expression::In(InExpression {
1412 value: Box::new(column_expr("status")),
1413 list: Box::new(Expression::Tuple(TupleExpression {
1414 expressions: vec![constant_text("active"), constant_text("pending")],
1415 fragment: Fragment::None,
1416 })),
1417 negated: false,
1418 fragment: Fragment::None,
1419 });
1420
1421 let json = to_json(&expr);
1422 assert_eq!(
1423 json,
1424 r#"{"type":"in","value":{"type":"column","namespace":"_context","source":"_context","name":"status"},"list":{"type":"tuple","expressions":[{"type":"text","value":"active"},{"type":"text","value":"pending"}]},"negated":false}"#
1425 );
1426
1427 let recovered = from_json(&json).unwrap();
1428 assert_eq!(to_json(&recovered), json);
1429 }
1430
1431 #[test]
1432 fn test_not_in() {
1433 let expr = Expression::In(InExpression {
1434 value: Box::new(column_expr("type")),
1435 list: Box::new(Expression::Tuple(TupleExpression {
1436 expressions: vec![constant_text("deleted"), constant_text("archived")],
1437 fragment: Fragment::None,
1438 })),
1439 negated: true,
1440 fragment: Fragment::None,
1441 });
1442
1443 let json = to_json(&expr);
1444 assert_eq!(
1445 json,
1446 r#"{"type":"in","value":{"type":"column","namespace":"_context","source":"_context","name":"type"},"list":{"type":"tuple","expressions":[{"type":"text","value":"deleted"},{"type":"text","value":"archived"}]},"negated":true}"#
1447 );
1448
1449 let recovered = from_json(&json).unwrap();
1450 assert_eq!(to_json(&recovered), json);
1451 }
1452
1453 #[test]
1454 fn test_if_simple() {
1455 let expr = Expression::If(IfExpression {
1456 condition: Box::new(Expression::GreaterThan(GreaterThanExpression {
1457 left: Box::new(column_expr("age")),
1458 right: Box::new(constant_number("18")),
1459 fragment: Fragment::None,
1460 })),
1461 then_expr: Box::new(constant_text("adult")),
1462 else_ifs: vec![],
1463 else_expr: Some(Box::new(constant_text("minor"))),
1464 fragment: Fragment::None,
1465 });
1466
1467 let json = to_json(&expr);
1468 assert_eq!(
1469 json,
1470 r#"{"type":"if","condition":{"type":"greater_than","left":{"type":"column","namespace":"_context","source":"_context","name":"age"},"right":{"type":"number","value":"18"}},"then":{"type":"text","value":"adult"},"else_ifs":[],"else_expr":{"type":"text","value":"minor"}}"#
1471 );
1472
1473 let recovered = from_json(&json).unwrap();
1474 assert_eq!(to_json(&recovered), json);
1475 }
1476
1477 #[test]
1478 fn test_if_with_else_if() {
1479 let expr = Expression::If(IfExpression {
1480 condition: Box::new(Expression::GreaterThan(GreaterThanExpression {
1481 left: Box::new(column_expr("score")),
1482 right: Box::new(constant_number("90")),
1483 fragment: Fragment::None,
1484 })),
1485 then_expr: Box::new(constant_text("A")),
1486 else_ifs: vec![ElseIfExpression {
1487 condition: Box::new(Expression::GreaterThan(GreaterThanExpression {
1488 left: Box::new(column_expr("score")),
1489 right: Box::new(constant_number("80")),
1490 fragment: Fragment::None,
1491 })),
1492 then_expr: Box::new(constant_text("B")),
1493 fragment: Fragment::None,
1494 }],
1495 else_expr: Some(Box::new(constant_text("C"))),
1496 fragment: Fragment::None,
1497 });
1498
1499 let json = to_json(&expr);
1500 assert_eq!(
1501 json,
1502 r#"{"type":"if","condition":{"type":"greater_than","left":{"type":"column","namespace":"_context","source":"_context","name":"score"},"right":{"type":"number","value":"90"}},"then":{"type":"text","value":"A"},"else_ifs":[{"condition":{"type":"greater_than","left":{"type":"column","namespace":"_context","source":"_context","name":"score"},"right":{"type":"number","value":"80"}},"then":{"type":"text","value":"B"}}],"else_expr":{"type":"text","value":"C"}}"#
1503 );
1504
1505 let recovered = from_json(&json).unwrap();
1506 assert_eq!(to_json(&recovered), json);
1507 }
1508
1509 #[test]
1510 fn test_map() {
1511 let expr = Expression::Map(MapExpression {
1512 expressions: vec![
1513 Expression::Alias(AliasExpression {
1514 alias: IdentExpression(internal_fragment("user_name")),
1515 expression: Box::new(column_expr("name")),
1516 fragment: Fragment::None,
1517 }),
1518 column_expr("id"),
1519 ],
1520 fragment: Fragment::None,
1521 });
1522
1523 let json = to_json(&expr);
1524 assert_eq!(
1525 json,
1526 r#"{"type":"map","expressions":[{"type":"alias","alias":"user_name","expression":{"type":"column","namespace":"_context","source":"_context","name":"name"}},{"type":"column","namespace":"_context","source":"_context","name":"id"}]}"#
1527 );
1528
1529 let recovered = from_json(&json).unwrap();
1530 assert_eq!(to_json(&recovered), json);
1531 }
1532
1533 #[test]
1534 fn test_extend() {
1535 let expr = Expression::Extend(ExtendExpression {
1536 expressions: vec![Expression::Alias(AliasExpression {
1537 alias: IdentExpression(internal_fragment("full_name")),
1538 expression: Box::new(Expression::Add(AddExpression {
1539 left: Box::new(column_expr("first")),
1540 right: Box::new(column_expr("last")),
1541 fragment: Fragment::None,
1542 })),
1543 fragment: Fragment::None,
1544 })],
1545 fragment: Fragment::None,
1546 });
1547
1548 let json = to_json(&expr);
1549 assert_eq!(
1550 json,
1551 r#"{"type":"extend","expressions":[{"type":"alias","alias":"full_name","expression":{"type":"add","left":{"type":"column","namespace":"_context","source":"_context","name":"first"},"right":{"type":"column","namespace":"_context","source":"_context","name":"last"}}}]}"#
1552 );
1553
1554 let recovered = from_json(&json).unwrap();
1555 assert_eq!(to_json(&recovered), json);
1556 }
1557
1558 #[test]
1559 fn test_type_expression() {
1560 let expr = Expression::Type(TypeExpression {
1561 ty: Type::Utf8,
1562 fragment: internal_fragment("Utf8"),
1563 });
1564
1565 let json = to_json(&expr);
1566 assert_eq!(json, r#"{"type":"type","ty":"Utf8"}"#);
1567
1568 let recovered = from_json(&json).unwrap();
1569 assert_eq!(to_json(&recovered), json);
1570 }
1571
1572 #[test]
1577 fn test_complex_nested_expression() {
1578 let expr = Expression::Or(OrExpression {
1580 left: Box::new(Expression::And(AndExpression {
1581 left: Box::new(Expression::GreaterThan(GreaterThanExpression {
1582 left: Box::new(column_expr("age")),
1583 right: Box::new(constant_number("18")),
1584 fragment: Fragment::None,
1585 })),
1586 right: Box::new(Expression::Equal(EqExpression {
1587 left: Box::new(column_expr("status")),
1588 right: Box::new(constant_text("active")),
1589 fragment: Fragment::None,
1590 })),
1591 fragment: Fragment::None,
1592 })),
1593 right: Box::new(Expression::Equal(EqExpression {
1594 left: Box::new(column_expr("role")),
1595 right: Box::new(constant_text("admin")),
1596 fragment: Fragment::None,
1597 })),
1598 fragment: Fragment::None,
1599 });
1600
1601 let json = to_json(&expr);
1602 let recovered = from_json(&json).unwrap();
1603 assert_eq!(to_json(&recovered), json);
1604
1605 let pretty = to_json_pretty(&expr);
1607 assert!(pretty.contains('\n'));
1608 assert!(pretty.contains("greater_than"));
1609 }
1610
1611 #[test]
1612 fn test_access_source() {
1613 let expr = Expression::AccessSource(AccessPrimitiveExpression {
1614 column: ColumnIdentifier {
1615 primitive: ColumnPrimitive::Primitive {
1616 namespace: internal_fragment("public"),
1617 primitive: internal_fragment("users"),
1618 },
1619 name: internal_fragment("email"),
1620 },
1621 });
1622
1623 let json = to_json(&expr);
1624 assert_eq!(json, r#"{"type":"access_source","namespace":"public","source":"users","name":"email"}"#);
1625
1626 let recovered = from_json(&json).unwrap();
1627 assert_eq!(to_json(&recovered), json);
1628 }
1629}