1mod binary_op;
2mod case;
3mod exists;
4mod is_null;
5mod like;
6mod nested;
7mod order_by;
8mod regex;
9mod unary_op;
10
11pub mod aggregate;
12pub mod alias_as;
13pub mod between;
14pub mod function;
15pub mod in_list;
16pub mod numeric;
17
18use {
19 crate::{
20 ast::{BinaryOperator, Expr, Literal, UnaryOperator},
21 data::Value,
22 parse_sql::{parse_comma_separated_exprs, parse_expr, parse_query},
23 plan::{ExprPlan, QueryPlan},
24 prelude::DataType,
25 query_builder::QueryNode,
26 result::Result,
27 translate::{NO_PARAMS, translate_expr, translate_query},
28 },
29 aggregate::AggregateNode,
30 bigdecimal::BigDecimal,
31 function::FunctionNode,
32 in_list::InListNode,
33 numeric::NumericNode,
34 std::borrow::Cow,
35};
36pub use {
37 case::case,
38 exists::{exists, not_exists},
39 nested::nested,
40 unary_op::{bitwise_not, factorial, minus, not, plus},
41};
42
43#[derive(Clone, Debug)]
44pub enum ExprNode<'a> {
45 Expr(Cow<'a, Expr>),
46 SqlExpr(Cow<'a, str>),
47 Identifier(Cow<'a, str>),
48 Numeric(NumericNode<'a>),
49 QuotedString(Cow<'a, str>),
50 TypedString {
51 data_type: DataType,
52 value: Cow<'a, str>,
53 },
54 Between {
55 expr: Box<ExprNode<'a>>,
56 negated: bool,
57 low: Box<ExprNode<'a>>,
58 high: Box<ExprNode<'a>>,
59 },
60 Like {
61 expr: Box<ExprNode<'a>>,
62 negated: bool,
63 pattern: Box<ExprNode<'a>>,
64 },
65 ILike {
66 expr: Box<ExprNode<'a>>,
67 negated: bool,
68 pattern: Box<ExprNode<'a>>,
69 },
70 Regex {
71 expr: Box<ExprNode<'a>>,
72 negated: bool,
73 pattern: Box<ExprNode<'a>>,
74 case_sensitive: bool,
75 },
76 BinaryOp {
77 left: Box<ExprNode<'a>>,
78 op: BinaryOperator,
79 right: Box<ExprNode<'a>>,
80 },
81 UnaryOp {
82 op: UnaryOperator,
83 expr: Box<ExprNode<'a>>,
84 },
85 IsNull(Box<ExprNode<'a>>),
86 IsNotNull(Box<ExprNode<'a>>),
87 InList {
88 expr: Box<ExprNode<'a>>,
89 list: Box<InListNode<'a>>,
90 negated: bool,
91 },
92 Nested(Box<ExprNode<'a>>),
93 Function(Box<FunctionNode<'a>>),
94 Aggregate(Box<AggregateNode<'a>>),
95 Exists {
96 subquery: Box<QueryNode<'a>>,
97 negated: bool,
98 },
99 Subquery(Box<QueryNode<'a>>),
100 Case {
101 operand: Option<Box<ExprNode<'a>>>,
102 when_then: Vec<(ExprNode<'a>, ExprNode<'a>)>,
103 else_result: Option<Box<ExprNode<'a>>>,
104 },
105}
106
107impl ExprNode<'_> {
108 pub(super) fn build_expr_plan(self) -> Result<ExprPlan> {
109 match self {
110 ExprNode::Expr(expr) => Ok(expr.into_owned().into()),
111 ExprNode::SqlExpr(expr) => {
112 let expr = parse_expr(expr)?;
113
114 translate_expr(&expr, NO_PARAMS).map(Into::into)
115 }
116 ExprNode::Identifier(value) => {
117 let idents = value.as_ref().split('.').collect::<Vec<_>>();
118
119 Ok(match idents.as_slice() {
120 [alias, ident] => ExprPlan::CompoundIdentifier {
121 alias: (*alias).to_owned(),
122 ident: (*ident).to_owned(),
123 },
124 _ => ExprPlan::Identifier(value.into_owned()),
125 })
126 }
127 ExprNode::Numeric(node) => node.try_into().map(ExprPlan::Literal),
128 ExprNode::QuotedString(value) => {
129 let value = value.into_owned();
130
131 Ok(ExprPlan::Literal(Literal::QuotedString(value)))
132 }
133 ExprNode::TypedString { data_type, value } => Ok(ExprPlan::TypedString {
134 data_type,
135 value: value.into_owned(),
136 }),
137 ExprNode::Between {
138 expr,
139 negated,
140 low,
141 high,
142 } => {
143 let expr = (*expr).build_expr_plan().map(Box::new)?;
144 let low = (*low).build_expr_plan().map(Box::new)?;
145 let high = (*high).build_expr_plan().map(Box::new)?;
146
147 Ok(ExprPlan::Between {
148 expr,
149 negated,
150 low,
151 high,
152 })
153 }
154 ExprNode::Like {
155 expr,
156 negated,
157 pattern,
158 } => {
159 let expr = (*expr).build_expr_plan().map(Box::new)?;
160 let pattern = (*pattern).build_expr_plan().map(Box::new)?;
161
162 Ok(ExprPlan::Like {
163 expr,
164 negated,
165 pattern,
166 })
167 }
168 ExprNode::ILike {
169 expr,
170 negated,
171 pattern,
172 } => {
173 let expr = (*expr).build_expr_plan().map(Box::new)?;
174 let pattern = (*pattern).build_expr_plan().map(Box::new)?;
175
176 Ok(ExprPlan::ILike {
177 expr,
178 negated,
179 pattern,
180 })
181 }
182 ExprNode::Regex {
183 expr,
184 negated,
185 pattern,
186 case_sensitive,
187 } => {
188 let expr = (*expr).build_expr_plan().map(Box::new)?;
189 let pattern = (*pattern).build_expr_plan().map(Box::new)?;
190
191 Ok(ExprPlan::Regex {
192 expr,
193 negated,
194 pattern,
195 case_sensitive,
196 })
197 }
198 ExprNode::BinaryOp { left, op, right } => {
199 let left = (*left).build_expr_plan().map(Box::new)?;
200 let right = (*right).build_expr_plan().map(Box::new)?;
201
202 Ok(ExprPlan::BinaryOp { left, op, right })
203 }
204 ExprNode::UnaryOp { op, expr } => {
205 let expr = (*expr).build_expr_plan().map(Box::new)?;
206 Ok(ExprPlan::UnaryOp { op, expr })
207 }
208 ExprNode::IsNull(expr) => (*expr)
209 .build_expr_plan()
210 .map(Box::new)
211 .map(ExprPlan::IsNull),
212 ExprNode::IsNotNull(expr) => (*expr)
213 .build_expr_plan()
214 .map(Box::new)
215 .map(ExprPlan::IsNotNull),
216 ExprNode::InList {
217 expr,
218 list,
219 negated,
220 } => {
221 let expr = (*expr).build_expr_plan().map(Box::new)?;
222
223 match *list {
224 InListNode::InList(list) => {
225 let list = list
226 .into_iter()
227 .map(ExprNode::build_expr_plan)
228 .collect::<Result<Vec<_>>>()?;
229 Ok(ExprPlan::InList {
230 expr,
231 list,
232 negated,
233 })
234 }
235 InListNode::Query(subquery) => {
236 let subquery = subquery.build_query_plan().map(Box::new)?;
237 Ok(ExprPlan::InSubquery {
238 expr,
239 subquery,
240 negated,
241 })
242 }
243 InListNode::Text(value) => {
244 let subquery = parse_query(value.clone())
245 .and_then(|item| translate_query(&item, NO_PARAMS))
246 .map(QueryPlan::from)
247 .map(Box::new);
248
249 if let Ok(subquery) = subquery {
250 return Ok(ExprPlan::InSubquery {
251 expr,
252 subquery,
253 negated,
254 });
255 }
256
257 parse_comma_separated_exprs(&*value)?
258 .iter()
259 .map(|expr| translate_expr(expr, NO_PARAMS).map(Into::into))
260 .collect::<Result<Vec<_>>>()
261 .map(|list| ExprPlan::InList {
262 expr,
263 list,
264 negated,
265 })
266 }
267 }
268 }
269 ExprNode::Nested(expr) => (*expr)
270 .build_expr_plan()
271 .map(Box::new)
272 .map(ExprPlan::Nested),
273 ExprNode::Function(func_expr) => (*func_expr)
274 .build_function_expr_plan()
275 .map(Box::new)
276 .map(ExprPlan::Function),
277 ExprNode::Aggregate(aggr_expr) => (*aggr_expr)
278 .build_aggregate_expr_plan()
279 .map(Box::new)
280 .map(ExprPlan::Aggregate),
281 ExprNode::Exists { subquery, negated } => (*subquery)
282 .build_query_plan()
283 .map(Box::new)
284 .map(|subquery| ExprPlan::Exists { subquery, negated }),
285 ExprNode::Subquery(subquery) => (*subquery)
286 .build_query_plan()
287 .map(Box::new)
288 .map(ExprPlan::Subquery),
289 ExprNode::Case {
290 operand,
291 when_then,
292 else_result,
293 } => {
294 let operand = operand
295 .map(|expr| (*expr).build_expr_plan())
296 .transpose()?
297 .map(Box::new);
298 let when_then = when_then
299 .into_iter()
300 .map(|(when, then)| {
301 let when = when.build_expr_plan()?;
302 let then = then.build_expr_plan()?;
303 Ok((when, then))
304 })
305 .collect::<Result<Vec<_>>>()?;
306
307 let else_result = else_result
308 .map(|expr| (*expr).build_expr_plan())
309 .transpose()?
310 .map(Box::new);
311 Ok(ExprPlan::Case {
312 operand,
313 when_then,
314 else_result,
315 })
316 }
317 }
318 }
319}
320
321impl ExprNode<'_> {
322 pub(super) fn build_expr(self) -> Result<Expr> {
323 match self {
324 ExprNode::Expr(expr) => Ok(expr.into_owned()),
325 ExprNode::SqlExpr(expr) => {
326 let expr = parse_expr(expr)?;
327
328 translate_expr(&expr, NO_PARAMS)
329 }
330 ExprNode::Identifier(value) => {
331 let idents = value.as_ref().split('.').collect::<Vec<_>>();
332
333 Ok(match idents.as_slice() {
334 [alias, ident] => Expr::CompoundIdentifier {
335 alias: (*alias).to_owned(),
336 ident: (*ident).to_owned(),
337 },
338 _ => Expr::Identifier(value.into_owned()),
339 })
340 }
341 ExprNode::Numeric(node) => node.try_into().map(Expr::Literal),
342 ExprNode::QuotedString(value) => {
343 let value = value.into_owned();
344
345 Ok(Expr::Literal(Literal::QuotedString(value)))
346 }
347 ExprNode::TypedString { data_type, value } => Ok(Expr::TypedString {
348 data_type,
349 value: value.into_owned(),
350 }),
351 ExprNode::Between {
352 expr,
353 negated,
354 low,
355 high,
356 } => {
357 let expr = expr.build_expr().map(Box::new)?;
358 let low = low.build_expr().map(Box::new)?;
359 let high = high.build_expr().map(Box::new)?;
360
361 Ok(Expr::Between {
362 expr,
363 negated,
364 low,
365 high,
366 })
367 }
368 ExprNode::Like {
369 expr,
370 negated,
371 pattern,
372 } => {
373 let expr = expr.build_expr().map(Box::new)?;
374 let pattern = pattern.build_expr().map(Box::new)?;
375
376 Ok(Expr::Like {
377 expr,
378 negated,
379 pattern,
380 })
381 }
382 ExprNode::ILike {
383 expr,
384 negated,
385 pattern,
386 } => {
387 let expr = expr.build_expr().map(Box::new)?;
388 let pattern = pattern.build_expr().map(Box::new)?;
389
390 Ok(Expr::ILike {
391 expr,
392 negated,
393 pattern,
394 })
395 }
396 ExprNode::Regex {
397 expr,
398 negated,
399 pattern,
400 case_sensitive,
401 } => {
402 let expr = expr.build_expr().map(Box::new)?;
403 let pattern = pattern.build_expr().map(Box::new)?;
404
405 Ok(Expr::Regex {
406 expr,
407 negated,
408 pattern,
409 case_sensitive,
410 })
411 }
412 ExprNode::BinaryOp { left, op, right } => {
413 let left = left.build_expr().map(Box::new)?;
414 let right = right.build_expr().map(Box::new)?;
415
416 Ok(Expr::BinaryOp { left, op, right })
417 }
418 ExprNode::UnaryOp { op, expr } => {
419 let expr = expr.build_expr().map(Box::new)?;
420 Ok(Expr::UnaryOp { op, expr })
421 }
422 ExprNode::IsNull(expr) => expr.build_expr().map(Box::new).map(Expr::IsNull),
423 ExprNode::IsNotNull(expr) => expr.build_expr().map(Box::new).map(Expr::IsNotNull),
424 ExprNode::InList {
425 expr,
426 list,
427 negated,
428 } => {
429 let expr = expr.build_expr().map(Box::new)?;
430
431 match *list {
432 InListNode::InList(list) => {
433 let list = list
434 .into_iter()
435 .map(ExprNode::build_expr)
436 .collect::<Result<Vec<_>>>()?;
437 Ok(Expr::InList {
438 expr,
439 list,
440 negated,
441 })
442 }
443 InListNode::Text(value) => {
444 let subquery = parse_query(value.clone())
445 .and_then(|item| translate_query(&item, NO_PARAMS))
446 .map(Box::new);
447
448 if let Ok(subquery) = subquery {
449 return Ok(Expr::InSubquery {
450 expr,
451 subquery,
452 negated,
453 });
454 }
455
456 parse_comma_separated_exprs(&value)?
457 .iter()
458 .map(|expr| translate_expr(expr, NO_PARAMS))
459 .collect::<Result<Vec<_>>>()
460 .map(|list| Expr::InList {
461 expr,
462 list,
463 negated,
464 })
465 }
466 InListNode::Query(subquery) => {
467 let subquery = (*subquery).build_query().map(Box::new)?;
468 Ok(Expr::InSubquery {
469 expr,
470 subquery,
471 negated,
472 })
473 }
474 }
475 }
476 ExprNode::Nested(expr) => expr.build_expr().map(Box::new).map(Expr::Nested),
477 ExprNode::Function(func_expr) => {
478 func_expr.build_function().map(Box::new).map(Expr::Function)
479 }
480 ExprNode::Aggregate(aggr_expr) => aggr_expr
481 .build_aggregate()
482 .map(Box::new)
483 .map(Expr::Aggregate),
484 ExprNode::Exists { subquery, negated } => (*subquery)
485 .build_query()
486 .map(Box::new)
487 .map(|subquery| Expr::Exists { subquery, negated }),
488 ExprNode::Subquery(subquery) => {
489 (*subquery).build_query().map(Box::new).map(Expr::Subquery)
490 }
491 ExprNode::Case {
492 operand,
493 when_then,
494 else_result,
495 } => {
496 let operand = operand
497 .map(|expr| expr.build_expr())
498 .transpose()?
499 .map(Box::new);
500 let when_then = when_then
501 .into_iter()
502 .map(|(when, then)| {
503 let when = when.build_expr()?;
504 let then = then.build_expr()?;
505 Ok((when, then))
506 })
507 .collect::<Result<Vec<_>>>()?;
508
509 let else_result = else_result
510 .map(|expr| expr.build_expr())
511 .transpose()?
512 .map(Box::new);
513 Ok(Expr::Case {
514 operand,
515 when_then,
516 else_result,
517 })
518 }
519 }
520 }
521}
522
523impl<'a> From<&'a str> for ExprNode<'a> {
524 fn from(expr: &'a str) -> Self {
525 ExprNode::SqlExpr(Cow::Borrowed(expr))
526 }
527}
528
529impl From<String> for ExprNode<'_> {
530 fn from(expr: String) -> Self {
531 ExprNode::SqlExpr(Cow::Owned(expr))
532 }
533}
534
535impl From<i64> for ExprNode<'_> {
536 fn from(n: i64) -> Self {
537 ExprNode::Expr(Cow::Owned(Expr::Literal(Literal::Number(
538 BigDecimal::from(n),
539 ))))
540 }
541}
542
543impl From<bool> for ExprNode<'_> {
544 fn from(b: bool) -> Self {
545 ExprNode::Expr(Cow::Owned(Expr::Value(Value::Bool(b))))
546 }
547}
548
549impl<'a> From<QueryNode<'a>> for ExprNode<'a> {
550 fn from(node: QueryNode<'a>) -> Self {
551 ExprNode::Subquery(Box::new(node))
552 }
553}
554
555impl From<Expr> for ExprNode<'_> {
556 fn from(expr: Expr) -> Self {
557 ExprNode::Expr(Cow::Owned(expr))
558 }
559}
560
561impl<'a> From<&'a Expr> for ExprNode<'a> {
562 fn from(expr: &'a Expr) -> Self {
563 ExprNode::Expr(Cow::Borrowed(expr))
564 }
565}
566
567impl From<Value> for ExprNode<'_> {
568 fn from(v: Value) -> Self {
569 ExprNode::Expr(Cow::Owned(Expr::Value(v)))
570 }
571}
572
573pub fn expr<'a, T: Into<Cow<'a, str>>>(value: T) -> ExprNode<'a> {
574 ExprNode::SqlExpr(value.into())
575}
576
577pub fn col<'a, T: Into<Cow<'a, str>>>(value: T) -> ExprNode<'a> {
578 ExprNode::Identifier(value.into())
579}
580
581pub fn num<'a, T: Into<NumericNode<'a>>>(value: T) -> ExprNode<'a> {
582 ExprNode::Numeric(value.into())
583}
584
585pub fn text<'a, T: Into<Cow<'a, str>>>(value: T) -> ExprNode<'a> {
586 ExprNode::QuotedString(value.into())
587}
588
589pub fn date<'a, T: Into<Cow<'a, str>>>(date: T) -> ExprNode<'a> {
590 ExprNode::TypedString {
591 data_type: DataType::Date,
592 value: date.into(),
593 }
594}
595
596pub fn timestamp<'a, T: Into<Cow<'a, str>>>(timestamp: T) -> ExprNode<'a> {
597 ExprNode::TypedString {
598 data_type: DataType::Timestamp,
599 value: timestamp.into(),
600 }
601}
602
603pub fn time<'a, T: Into<Cow<'a, str>>>(time: T) -> ExprNode<'a> {
604 ExprNode::TypedString {
605 data_type: DataType::Time,
606 value: time.into(),
607 }
608}
609
610pub fn uuid<'a, T: Into<Cow<'a, str>>>(uuid: T) -> ExprNode<'a> {
611 ExprNode::TypedString {
612 data_type: DataType::Uuid,
613 value: uuid.into(),
614 }
615}
616
617pub fn bytea<'a, T: AsRef<[u8]>>(bytea: T) -> ExprNode<'a> {
623 ExprNode::Expr(Cow::Owned(Expr::Value(Value::Bytea(
624 bytea.as_ref().to_vec(),
625 ))))
626}
627
628pub fn subquery<'a, T: Into<QueryNode<'a>>>(query_node: T) -> ExprNode<'a> {
629 ExprNode::Subquery(Box::new(query_node.into()))
630}
631
632pub fn null() -> ExprNode<'static> {
633 ExprNode::Expr(Cow::Owned(Expr::Value(Value::Null)))
634}
635
636pub fn value(v: Value) -> ExprNode<'static> {
637 ExprNode::Expr(Cow::Owned(Expr::Value(v)))
638}
639
640#[cfg(test)]
641mod tests {
642 use {
643 super::ExprNode,
644 crate::{
645 ast::Expr,
646 data::Value,
647 plan::ExprPlan,
648 query_builder::{
649 QueryNode, bytea, col, date, expr, null, num, subquery, table, test_expr, text,
650 time, timestamp, uuid, value,
651 },
652 },
653 };
654
655 #[test]
656 fn into_expr_node() {
657 let actual: ExprNode = "id IS NOT NULL".into();
658 let expected = "id IS NOT NULL";
659 test_expr(actual, expected);
660
661 let actual: ExprNode = String::from("1 + 10)").into();
662 let expected = "1 + 10";
663 test_expr(actual, expected);
664
665 let actual: ExprNode = 1024.into();
666 let expected = "1024";
667 test_expr(actual, expected);
668
669 let actual: ExprNode = true.into();
670 let expected = "True";
671 test_expr(actual, expected);
672
673 let actual: ExprNode = QueryNode::from(table("Foo").select().project("id")).into();
674 let expected = "(SELECT id FROM Foo)";
675 test_expr(actual, expected);
676
677 let expr = Expr::Identifier("id".to_owned());
678 let actual: ExprNode = (&expr).into();
679 let expected = "id";
680 test_expr(actual, expected);
681
682 let actual: ExprNode = expr.into();
683 test_expr(actual, expected);
684 }
685
686 #[test]
687 fn syntactic_sugar() {
688 let actual = expr("col1 > 10");
689 let expected = "col1 > 10";
690 test_expr(actual, expected);
691
692 let actual = col("id");
693 let expected = "id";
694 test_expr(actual, expected);
695
696 let actual = col("Foo.id");
697 let expected = "Foo.id";
698 test_expr(actual, expected);
699
700 let actual = num(2048);
701 let expected = "2048";
702 test_expr(actual, expected);
703
704 let actual = num(6.5);
705 let expected = "6.5";
706 test_expr(actual, expected);
707
708 let actual = num("123.456");
709 let expected = "123.456";
710 test_expr(actual, expected);
711
712 let actual = text("hello world");
713 let expected = "'hello world'";
714 test_expr(actual, expected);
715
716 let actual = date("2022-10-11");
717 let expected = "DATE '2022-10-11'";
718 test_expr(actual, expected);
719
720 let actual = timestamp("2022-10-11 13:34:49");
721 let expected = "TIMESTAMP '2022-10-11 13:34:49'";
722 test_expr(actual, expected);
723
724 let actual = time("15:00:07");
725 let expected = "TIME '15:00:07'";
726 test_expr(actual, expected);
727
728 let actual = uuid("936DA01F9ABD4d9d80C702AF85C822A8");
729 let expected = "UUID '936DA01F9ABD4d9d80C702AF85C822A8'";
730 test_expr(actual, expected);
731
732 let actual = bytea(b"hello world");
733 let expected = "X'68656c6c6f20776f726c64'";
734 test_expr(actual, expected);
735
736 let actual = subquery(table("Foo").select().filter("id IS NOT NULL"));
737 let expected = "(SELECT * FROM Foo WHERE id IS NOT NULL)";
738 test_expr(actual, expected);
739
740 let actual = subquery(
741 table("Foo")
742 .select()
743 .project("id")
744 .order_by("id")
745 .distinct(),
746 );
747 let expected = "(SELECT DISTINCT id FROM Foo ORDER BY id)";
748 test_expr(actual, expected);
749
750 let actual = null();
751 let expected = "NULL";
752 test_expr(actual, expected);
753 }
754
755 #[test]
756 fn value_injection() {
757 let test = |actual: ExprNode, expected: ExprPlan| {
758 pretty_assertions::assert_eq!(actual.build_expr_plan(), Ok(expected));
759 };
760
761 test(Value::I64(42).into(), ExprPlan::Value(Value::I64(42)));
762 test(
763 Value::Str("hello".to_owned()).into(),
764 ExprPlan::Value(Value::Str("hello".to_owned())),
765 );
766 test(value(Value::I64(100)), ExprPlan::Value(Value::I64(100)));
767 test(value(Value::Bool(true)), ExprPlan::Value(Value::Bool(true)));
768 }
769}