1use std::collections::{BTreeMap, BTreeSet};
11use std::ops::BitOrAssign;
12use std::sync::Arc;
13use std::{fmt, mem};
14
15use itertools::Itertools;
16use mz_lowertest::MzReflect;
17use mz_ore::cast::CastFrom;
18use mz_ore::collections::CollectionExt;
19use mz_ore::iter::IteratorExt;
20use mz_ore::stack::RecursionLimitError;
21use mz_ore::str::StrExt;
22use mz_ore::treat_as_equal::TreatAsEqual;
23use mz_ore::vec::swap_remove_multiple;
24use mz_pgrepr::TypeFromOidError;
25use mz_pgtz::timezone::TimezoneSpec;
26use mz_proto::{IntoRustIfSome, ProtoType, RustType, TryFromProtoError};
27use mz_repr::adt::array::InvalidArrayError;
28use mz_repr::adt::date::DateError;
29use mz_repr::adt::datetime::DateTimeUnits;
30use mz_repr::adt::range::InvalidRangeError;
31use mz_repr::adt::regex::Regex;
32use mz_repr::adt::timestamp::TimestampError;
33use mz_repr::strconv::{ParseError, ParseHexError};
34use mz_repr::{Datum, Row, RowArena, SqlColumnType, SqlScalarType};
35use proptest::prelude::*;
36use proptest_derive::Arbitrary;
37use serde::{Deserialize, Serialize};
38
39use crate::scalar::func::format::DateTimeFormat;
40use crate::scalar::func::{
41 BinaryFunc, UnaryFunc, UnmaterializableFunc, VariadicFunc, parse_timezone,
42 regexp_replace_parse_flags,
43};
44use crate::scalar::proto_eval_error::proto_incompatible_array_dimensions::ProtoDims;
45use crate::visit::{Visit, VisitChildren};
46
47pub mod func;
48pub mod like_pattern;
49
50include!(concat!(env!("OUT_DIR"), "/mz_expr.scalar.rs"));
51
52#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, MzReflect)]
53pub enum MirScalarExpr {
54 Column(usize, TreatAsEqual<Option<Arc<str>>>),
56 Literal(Result<Row, EvalError>, SqlColumnType),
59 CallUnmaterializable(UnmaterializableFunc),
64 CallUnary {
66 func: UnaryFunc,
67 expr: Box<MirScalarExpr>,
68 },
69 CallBinary {
71 func: BinaryFunc,
72 expr1: Box<MirScalarExpr>,
73 expr2: Box<MirScalarExpr>,
74 },
75 CallVariadic {
77 func: VariadicFunc,
78 exprs: Vec<MirScalarExpr>,
79 },
80 If {
87 cond: Box<MirScalarExpr>,
88 then: Box<MirScalarExpr>,
89 els: Box<MirScalarExpr>,
90 },
91}
92
93impl std::fmt::Debug for MirScalarExpr {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 match self {
98 MirScalarExpr::Column(i, TreatAsEqual(Some(name))) => {
99 write!(f, "Column({i}, {name:?})")
100 }
101 MirScalarExpr::Column(i, TreatAsEqual(None)) => write!(f, "Column({i})"),
102 MirScalarExpr::Literal(lit, typ) => write!(f, "Literal({lit:?}, {typ:?})"),
103 MirScalarExpr::CallUnmaterializable(func) => {
104 write!(f, "CallUnmaterializable({func:?})")
105 }
106 MirScalarExpr::CallUnary { func, expr } => {
107 write!(f, "CallUnary({func:?}, {expr:?})")
108 }
109 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
110 write!(f, "CallBinary({func:?}, {expr1:?}, {expr2:?})")
111 }
112 MirScalarExpr::CallVariadic { func, exprs } => {
113 write!(f, "CallVariadic({func:?}, {exprs:?})")
114 }
115 MirScalarExpr::If { cond, then, els } => {
116 write!(f, "If({cond:?}, {then:?}, {els:?})")
117 }
118 }
119 }
120}
121
122impl MirScalarExpr {
123 pub fn columns(is: &[usize]) -> Vec<MirScalarExpr> {
124 is.iter().map(|i| MirScalarExpr::column(*i)).collect()
125 }
126
127 pub fn column(column: usize) -> Self {
128 MirScalarExpr::Column(column, TreatAsEqual(None))
129 }
130
131 pub fn named_column(column: usize, name: Arc<str>) -> Self {
132 MirScalarExpr::Column(column, TreatAsEqual(Some(name)))
133 }
134
135 pub fn literal(res: Result<Datum, EvalError>, typ: SqlScalarType) -> Self {
136 let typ = typ.nullable(matches!(res, Ok(Datum::Null)));
137 let row = res.map(|datum| Row::pack_slice(&[datum]));
138 MirScalarExpr::Literal(row, typ)
139 }
140
141 pub fn literal_ok(datum: Datum, typ: SqlScalarType) -> Self {
142 MirScalarExpr::literal(Ok(datum), typ)
143 }
144
145 pub fn literal_null(typ: SqlScalarType) -> Self {
146 MirScalarExpr::literal_ok(Datum::Null, typ)
147 }
148
149 pub fn literal_false() -> Self {
150 MirScalarExpr::literal_ok(Datum::False, SqlScalarType::Bool)
151 }
152
153 pub fn literal_true() -> Self {
154 MirScalarExpr::literal_ok(Datum::True, SqlScalarType::Bool)
155 }
156
157 pub fn call_unary<U: Into<UnaryFunc>>(self, func: U) -> Self {
158 MirScalarExpr::CallUnary {
159 func: func.into(),
160 expr: Box::new(self),
161 }
162 }
163
164 pub fn call_binary<B: Into<BinaryFunc>>(self, other: Self, func: B) -> Self {
165 MirScalarExpr::CallBinary {
166 func: func.into(),
167 expr1: Box::new(self),
168 expr2: Box::new(other),
169 }
170 }
171
172 pub fn if_then_else(self, t: Self, f: Self) -> Self {
173 MirScalarExpr::If {
174 cond: Box::new(self),
175 then: Box::new(t),
176 els: Box::new(f),
177 }
178 }
179
180 pub fn or(self, other: Self) -> Self {
181 MirScalarExpr::CallVariadic {
182 func: VariadicFunc::Or,
183 exprs: vec![self, other],
184 }
185 }
186
187 pub fn and(self, other: Self) -> Self {
188 MirScalarExpr::CallVariadic {
189 func: VariadicFunc::And,
190 exprs: vec![self, other],
191 }
192 }
193
194 pub fn not(self) -> Self {
195 self.call_unary(UnaryFunc::Not(func::Not))
196 }
197
198 pub fn call_is_null(self) -> Self {
199 self.call_unary(UnaryFunc::IsNull(func::IsNull))
200 }
201
202 pub fn and_or_args(&self, func_to_match: VariadicFunc) -> Vec<MirScalarExpr> {
205 assert!(func_to_match == VariadicFunc::Or || func_to_match == VariadicFunc::And);
206 match self {
207 MirScalarExpr::CallVariadic { func, exprs } if *func == func_to_match => exprs.clone(),
208 _ => vec![self.clone()],
209 }
210 }
211
212 pub fn expr_eq_literal(&self, expr: &MirScalarExpr) -> Option<(Row, bool)> {
223 if let MirScalarExpr::CallBinary {
224 func: BinaryFunc::Eq(_),
225 expr1,
226 expr2,
227 } = self
228 {
229 if expr1.is_literal_null() || expr2.is_literal_null() {
230 return None;
231 }
232 if let Some(Ok(lit)) = expr1.as_literal_owned() {
233 return Self::expr_eq_literal_inner(expr, lit, expr1, expr2);
234 }
235 if let Some(Ok(lit)) = expr2.as_literal_owned() {
236 return Self::expr_eq_literal_inner(expr, lit, expr2, expr1);
237 }
238 }
239 None
240 }
241
242 fn expr_eq_literal_inner(
243 expr_to_match: &MirScalarExpr,
244 literal: Row,
245 literal_expr: &MirScalarExpr,
246 other_side: &MirScalarExpr,
247 ) -> Option<(Row, bool)> {
248 if other_side == expr_to_match {
249 return Some((literal, false));
250 } else {
251 let (cast_removed, inv_cast_lit) =
253 Self::invert_casts_on_expr_eq_literal_inner(other_side, literal_expr);
254 if &cast_removed == expr_to_match {
255 if let Some(Ok(inv_cast_lit_row)) = inv_cast_lit.as_literal_owned() {
256 return Some((inv_cast_lit_row, true));
257 }
258 }
259 }
260 None
261 }
262
263 pub fn any_expr_eq_literal(&self) -> Option<MirScalarExpr> {
267 if let MirScalarExpr::CallBinary {
268 func: BinaryFunc::Eq(_),
269 expr1,
270 expr2,
271 } = self
272 {
273 if expr1.is_literal() {
274 let (expr, _literal) = Self::invert_casts_on_expr_eq_literal_inner(expr2, expr1);
275 return Some(expr);
276 }
277 if expr2.is_literal() {
278 let (expr, _literal) = Self::invert_casts_on_expr_eq_literal_inner(expr1, expr2);
279 return Some(expr);
280 }
281 }
282 None
283 }
284
285 pub fn invert_casts_on_expr_eq_literal(&self) -> MirScalarExpr {
290 if let MirScalarExpr::CallBinary {
291 func: BinaryFunc::Eq(_),
292 expr1,
293 expr2,
294 } = self
295 {
296 if expr1.is_literal() {
297 let (expr, literal) = Self::invert_casts_on_expr_eq_literal_inner(expr2, expr1);
298 return literal.call_binary(expr, func::Eq);
299 }
300 if expr2.is_literal() {
301 let (expr, literal) = Self::invert_casts_on_expr_eq_literal_inner(expr1, expr2);
302 return literal.call_binary(expr, func::Eq);
303 }
304 }
307 self.clone()
308 }
309
310 fn invert_casts_on_expr_eq_literal_inner(
322 expr: &MirScalarExpr,
323 literal: &MirScalarExpr,
324 ) -> (MirScalarExpr, MirScalarExpr) {
325 assert!(matches!(literal, MirScalarExpr::Literal(..)));
326
327 let temp_storage = &RowArena::new();
328 let eval = |e: &MirScalarExpr| {
329 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(&[]).scalar_type)
330 };
331
332 if let MirScalarExpr::CallUnary {
333 func,
334 expr: inner_expr,
335 } = expr
336 {
337 if let Some(inverse_func) = func.inverse() {
338 if func.preserves_uniqueness() && inverse_func.preserves_uniqueness() {
345 let lit_inv = eval(&MirScalarExpr::CallUnary {
346 func: inverse_func,
347 expr: Box::new(literal.clone()),
348 });
349 if !lit_inv.is_literal_err() {
352 return (*inner_expr.clone(), lit_inv);
353 }
354 }
355 }
356 }
357 (expr.clone(), literal.clone())
358 }
359
360 pub fn impossible_literal_equality_because_types(&self) -> bool {
366 if let MirScalarExpr::CallBinary {
367 func: BinaryFunc::Eq(_),
368 expr1,
369 expr2,
370 } = self
371 {
372 if expr1.is_literal() {
373 return Self::impossible_literal_equality_because_types_inner(expr1, expr2);
374 }
375 if expr2.is_literal() {
376 return Self::impossible_literal_equality_because_types_inner(expr2, expr1);
377 }
378 }
379 false
380 }
381
382 fn impossible_literal_equality_because_types_inner(
383 literal: &MirScalarExpr,
384 other_side: &MirScalarExpr,
385 ) -> bool {
386 assert!(matches!(literal, MirScalarExpr::Literal(..)));
387
388 let temp_storage = &RowArena::new();
389 let eval = |e: &MirScalarExpr| {
390 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(&[]).scalar_type)
391 };
392
393 if let MirScalarExpr::CallUnary { func, .. } = other_side {
394 if let Some(inverse_func) = func.inverse() {
395 if inverse_func.preserves_uniqueness()
396 && eval(&MirScalarExpr::CallUnary {
397 func: inverse_func,
398 expr: Box::new(literal.clone()),
399 })
400 .is_literal_err()
401 {
402 return true;
403 }
404 }
405 }
406
407 false
408 }
409
410 pub fn any_expr_ineq_literal(&self) -> bool {
420 match self {
421 MirScalarExpr::CallBinary {
422 func:
423 BinaryFunc::Lt(_) | BinaryFunc::Lte(_) | BinaryFunc::Gt(_) | BinaryFunc::Gte(_),
424 expr1,
425 expr2,
426 } => expr1.is_literal() || expr2.is_literal(),
427 _ => false,
428 }
429 }
430
431 pub fn permute(&mut self, permutation: &[usize]) {
437 self.visit_columns(|c| *c = permutation[*c]);
438 }
439
440 pub fn permute_map(&mut self, permutation: &BTreeMap<usize, usize>) {
446 self.visit_columns(|c| *c = permutation[c]);
447 }
448
449 pub fn visit_columns<F>(&mut self, mut action: F)
453 where
454 F: FnMut(&mut usize),
455 {
456 self.visit_pre_mut(|e| {
457 if let MirScalarExpr::Column(col, _) = e {
458 action(col);
459 }
460 });
461 }
462
463 pub fn support(&self) -> BTreeSet<usize> {
464 let mut support = BTreeSet::new();
465 self.support_into(&mut support);
466 support
467 }
468
469 pub fn support_into(&self, support: &mut BTreeSet<usize>) {
470 self.visit_pre(|e| {
471 if let MirScalarExpr::Column(i, _) = e {
472 support.insert(*i);
473 }
474 });
475 }
476
477 pub fn take(&mut self) -> Self {
478 mem::replace(self, MirScalarExpr::literal_null(SqlScalarType::String))
479 }
480
481 pub fn as_literal(&self) -> Option<Result<Datum<'_>, &EvalError>> {
484 if let MirScalarExpr::Literal(lit, _column_type) = self {
485 Some(lit.as_ref().map(|row| row.unpack_first()))
486 } else {
487 None
488 }
489 }
490
491 pub fn as_literal_non_error(&self) -> Option<Datum<'_>> {
494 self.as_literal().map(|eval_err| eval_err.ok()).flatten()
495 }
496
497 pub fn as_literal_owned(&self) -> Option<Result<Row, EvalError>> {
498 if let MirScalarExpr::Literal(lit, _column_type) = self {
499 Some(lit.clone())
500 } else {
501 None
502 }
503 }
504
505 pub fn as_literal_str(&self) -> Option<&str> {
506 match self.as_literal() {
507 Some(Ok(Datum::String(s))) => Some(s),
508 _ => None,
509 }
510 }
511
512 pub fn as_literal_int64(&self) -> Option<i64> {
513 match self.as_literal() {
514 Some(Ok(Datum::Int64(i))) => Some(i),
515 _ => None,
516 }
517 }
518
519 pub fn as_literal_err(&self) -> Option<&EvalError> {
520 self.as_literal().and_then(|lit| lit.err())
521 }
522
523 pub fn is_literal(&self) -> bool {
524 matches!(self, MirScalarExpr::Literal(_, _))
525 }
526
527 pub fn is_literal_true(&self) -> bool {
528 Some(Ok(Datum::True)) == self.as_literal()
529 }
530
531 pub fn is_literal_false(&self) -> bool {
532 Some(Ok(Datum::False)) == self.as_literal()
533 }
534
535 pub fn is_literal_null(&self) -> bool {
536 Some(Ok(Datum::Null)) == self.as_literal()
537 }
538
539 pub fn is_literal_ok(&self) -> bool {
540 matches!(self, MirScalarExpr::Literal(Ok(_), _typ))
541 }
542
543 pub fn is_literal_err(&self) -> bool {
544 matches!(self, MirScalarExpr::Literal(Err(_), _typ))
545 }
546
547 pub fn is_column(&self) -> bool {
548 matches!(self, MirScalarExpr::Column(_col, _name))
549 }
550
551 pub fn is_error_if_null(&self) -> bool {
552 matches!(
553 self,
554 Self::CallVariadic {
555 func: VariadicFunc::ErrorIfNull,
556 ..
557 }
558 )
559 }
560
561 pub fn as_mut_temporal_filter(&mut self) -> Result<(&BinaryFunc, &mut MirScalarExpr), String> {
571 if !self.contains_temporal() {
572 return Err("Does not involve mz_now()".to_string());
573 }
574 if let MirScalarExpr::CallBinary { func, expr1, expr2 } = self {
576 if !expr1.contains_temporal()
578 && **expr2 == MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow)
579 {
580 std::mem::swap(expr1, expr2);
581 *func = match func {
582 BinaryFunc::Eq(_) => func::Eq.into(),
583 BinaryFunc::Lt(_) => func::Gt.into(),
584 BinaryFunc::Lte(_) => func::Gte.into(),
585 BinaryFunc::Gt(_) => func::Lt.into(),
586 BinaryFunc::Gte(_) => func::Lte.into(),
587 x => {
588 return Err(format!("Unsupported binary temporal operation: {:?}", x));
589 }
590 };
591 }
592
593 if expr2.contains_temporal()
595 || **expr1 != MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow)
596 {
597 return Err(format!(
598 "Unsupported temporal predicate. Note: `mz_now()` must be directly compared to a mz_timestamp-castable expression. Expression found: {}",
599 MirScalarExpr::CallBinary {
600 func: func.clone(),
601 expr1: expr1.clone(),
602 expr2: expr2.clone()
603 },
604 ));
605 }
606
607 Ok((&*func, expr2))
608 } else {
609 Err(format!(
610 "Unsupported temporal predicate. Note: `mz_now()` must be directly compared to a non-temporal expression of mz_timestamp-castable type. Expression found: {}",
611 self,
612 ))
613 }
614 }
615
616 #[deprecated = "Use `might_error` instead"]
617 pub fn contains_error_if_null(&self) -> bool {
618 let mut worklist = vec![self];
619 while let Some(expr) = worklist.pop() {
620 if expr.is_error_if_null() {
621 return true;
622 }
623 worklist.extend(expr.children());
624 }
625 false
626 }
627
628 pub fn contains_err(&self) -> bool {
629 let mut worklist = vec![self];
630 while let Some(expr) = worklist.pop() {
631 if expr.is_literal_err() {
632 return true;
633 }
634 worklist.extend(expr.children());
635 }
636 false
637 }
638
639 pub fn might_error(&self) -> bool {
645 let mut worklist = vec![self];
646 while let Some(expr) = worklist.pop() {
647 if expr.is_literal_err() || expr.is_error_if_null() {
648 return true;
649 }
650 worklist.extend(expr.children());
651 }
652 false
653 }
654
655 pub fn as_column(&self) -> Option<usize> {
657 if let MirScalarExpr::Column(c, _) = self {
658 Some(*c)
659 } else {
660 None
661 }
662 }
663
664 pub fn reduce(&mut self, column_types: &[SqlColumnType]) {
696 let temp_storage = &RowArena::new();
697 let eval = |e: &MirScalarExpr| {
698 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(column_types).scalar_type)
699 };
700
701 let mut old_self = MirScalarExpr::column(0);
703 while old_self != *self {
704 old_self = self.clone();
705 #[allow(deprecated)]
706 self.visit_mut_pre_post_nolimit(
707 &mut |e| {
708 match e {
709 MirScalarExpr::CallUnary { func, expr } => {
710 if *func == UnaryFunc::IsNull(func::IsNull) {
711 if !expr.typ(column_types).nullable {
712 *e = MirScalarExpr::literal_false();
713 } else {
714 if let Some(expr) = expr.decompose_is_null() {
717 *e = expr
718 }
719 }
720 } else if *func == UnaryFunc::Not(func::Not) {
721 match &mut **expr {
723 MirScalarExpr::CallUnary {
725 expr: inner_expr,
726 func: UnaryFunc::Not(func::Not),
727 } => *e = inner_expr.take(),
728 MirScalarExpr::CallBinary { expr1, expr2, func } => {
731 if let Some(negated_func) = func.negate() {
732 *e = MirScalarExpr::CallBinary {
733 expr1: Box::new(expr1.take()),
734 expr2: Box::new(expr2.take()),
735 func: negated_func,
736 }
737 }
738 }
739 MirScalarExpr::CallVariadic { .. } => {
740 e.demorgans();
741 }
742 _ => {}
743 }
744 }
745 }
746 _ => {}
747 };
748 None
749 },
750 &mut |e| match e {
751 MirScalarExpr::Column(_, _)
753 | MirScalarExpr::Literal(_, _)
754 | MirScalarExpr::CallUnmaterializable(_) => (),
755 MirScalarExpr::CallUnary { func, expr } => {
756 if expr.is_literal() && *func != UnaryFunc::Panic(func::Panic) {
757 *e = eval(e);
758 } else if let UnaryFunc::RecordGet(func::RecordGet(i)) = *func {
759 if let MirScalarExpr::CallVariadic {
760 func: VariadicFunc::RecordCreate { .. },
761 exprs,
762 } = &mut **expr
763 {
764 *e = exprs.swap_remove(i);
765 }
766 }
767 }
768 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
769 if expr1.is_literal() && expr2.is_literal() {
770 *e = eval(e);
771 } else if (expr1.is_literal_null() || expr2.is_literal_null())
772 && func.propagates_nulls()
773 {
774 *e = MirScalarExpr::literal_null(e.typ(column_types).scalar_type);
775 } else if let Some(err) = expr1.as_literal_err() {
776 *e = MirScalarExpr::literal(
777 Err(err.clone()),
778 e.typ(column_types).scalar_type,
779 );
780 } else if let Some(err) = expr2.as_literal_err() {
781 *e = MirScalarExpr::literal(
782 Err(err.clone()),
783 e.typ(column_types).scalar_type,
784 );
785 } else if let BinaryFunc::IsLikeMatch { case_insensitive } = func {
786 if expr2.is_literal() {
787 let pattern = expr2.as_literal_str().unwrap();
789 *e = match like_pattern::compile(pattern, *case_insensitive) {
790 Ok(matcher) => expr1.take().call_unary(UnaryFunc::IsLikeMatch(
791 func::IsLikeMatch(matcher),
792 )),
793 Err(err) => MirScalarExpr::literal(
794 Err(err),
795 e.typ(column_types).scalar_type,
796 ),
797 };
798 }
799 } else if let BinaryFunc::IsRegexpMatch { case_insensitive } = func {
800 if let MirScalarExpr::Literal(Ok(row), _) = &**expr2 {
801 *e = match Regex::new(
802 row.unpack_first().unwrap_str(),
803 *case_insensitive,
804 ) {
805 Ok(regex) => expr1.take().call_unary(UnaryFunc::IsRegexpMatch(
806 func::IsRegexpMatch(regex),
807 )),
808 Err(err) => MirScalarExpr::literal(
809 Err(err.into()),
810 e.typ(column_types).scalar_type,
811 ),
812 };
813 }
814 } else if let BinaryFunc::ExtractInterval(_) = *func
815 && expr1.is_literal()
816 {
817 let units = expr1.as_literal_str().unwrap();
818 *e = match units.parse::<DateTimeUnits>() {
819 Ok(units) => MirScalarExpr::CallUnary {
820 func: UnaryFunc::ExtractInterval(func::ExtractInterval(units)),
821 expr: Box::new(expr2.take()),
822 },
823 Err(_) => MirScalarExpr::literal(
824 Err(EvalError::UnknownUnits(units.into())),
825 e.typ(column_types).scalar_type,
826 ),
827 }
828 } else if let BinaryFunc::ExtractTime(_) = *func
829 && expr1.is_literal()
830 {
831 let units = expr1.as_literal_str().unwrap();
832 *e = match units.parse::<DateTimeUnits>() {
833 Ok(units) => MirScalarExpr::CallUnary {
834 func: UnaryFunc::ExtractTime(func::ExtractTime(units)),
835 expr: Box::new(expr2.take()),
836 },
837 Err(_) => MirScalarExpr::literal(
838 Err(EvalError::UnknownUnits(units.into())),
839 e.typ(column_types).scalar_type,
840 ),
841 }
842 } else if let BinaryFunc::ExtractTimestamp(_) = *func
843 && expr1.is_literal()
844 {
845 let units = expr1.as_literal_str().unwrap();
846 *e = match units.parse::<DateTimeUnits>() {
847 Ok(units) => MirScalarExpr::CallUnary {
848 func: UnaryFunc::ExtractTimestamp(func::ExtractTimestamp(
849 units,
850 )),
851 expr: Box::new(expr2.take()),
852 },
853 Err(_) => MirScalarExpr::literal(
854 Err(EvalError::UnknownUnits(units.into())),
855 e.typ(column_types).scalar_type,
856 ),
857 }
858 } else if let BinaryFunc::ExtractTimestampTz(_) = *func
859 && expr1.is_literal()
860 {
861 let units = expr1.as_literal_str().unwrap();
862 *e = match units.parse::<DateTimeUnits>() {
863 Ok(units) => MirScalarExpr::CallUnary {
864 func: UnaryFunc::ExtractTimestampTz(func::ExtractTimestampTz(
865 units,
866 )),
867 expr: Box::new(expr2.take()),
868 },
869 Err(_) => MirScalarExpr::literal(
870 Err(EvalError::UnknownUnits(units.into())),
871 e.typ(column_types).scalar_type,
872 ),
873 }
874 } else if let BinaryFunc::ExtractDate(_) = *func
875 && expr1.is_literal()
876 {
877 let units = expr1.as_literal_str().unwrap();
878 *e = match units.parse::<DateTimeUnits>() {
879 Ok(units) => MirScalarExpr::CallUnary {
880 func: UnaryFunc::ExtractDate(func::ExtractDate(units)),
881 expr: Box::new(expr2.take()),
882 },
883 Err(_) => MirScalarExpr::literal(
884 Err(EvalError::UnknownUnits(units.into())),
885 e.typ(column_types).scalar_type,
886 ),
887 }
888 } else if let BinaryFunc::DatePartInterval(_) = *func
889 && expr1.is_literal()
890 {
891 let units = expr1.as_literal_str().unwrap();
892 *e = match units.parse::<DateTimeUnits>() {
893 Ok(units) => MirScalarExpr::CallUnary {
894 func: UnaryFunc::DatePartInterval(func::DatePartInterval(
895 units,
896 )),
897 expr: Box::new(expr2.take()),
898 },
899 Err(_) => MirScalarExpr::literal(
900 Err(EvalError::UnknownUnits(units.into())),
901 e.typ(column_types).scalar_type,
902 ),
903 }
904 } else if let BinaryFunc::DatePartTime(_) = *func
905 && expr1.is_literal()
906 {
907 let units = expr1.as_literal_str().unwrap();
908 *e = match units.parse::<DateTimeUnits>() {
909 Ok(units) => MirScalarExpr::CallUnary {
910 func: UnaryFunc::DatePartTime(func::DatePartTime(units)),
911 expr: Box::new(expr2.take()),
912 },
913 Err(_) => MirScalarExpr::literal(
914 Err(EvalError::UnknownUnits(units.into())),
915 e.typ(column_types).scalar_type,
916 ),
917 }
918 } else if let BinaryFunc::DatePartTimestamp(_) = *func
919 && expr1.is_literal()
920 {
921 let units = expr1.as_literal_str().unwrap();
922 *e = match units.parse::<DateTimeUnits>() {
923 Ok(units) => MirScalarExpr::CallUnary {
924 func: UnaryFunc::DatePartTimestamp(func::DatePartTimestamp(
925 units,
926 )),
927 expr: Box::new(expr2.take()),
928 },
929 Err(_) => MirScalarExpr::literal(
930 Err(EvalError::UnknownUnits(units.into())),
931 e.typ(column_types).scalar_type,
932 ),
933 }
934 } else if let BinaryFunc::DatePartTimestampTz(_) = *func
935 && expr1.is_literal()
936 {
937 let units = expr1.as_literal_str().unwrap();
938 *e = match units.parse::<DateTimeUnits>() {
939 Ok(units) => MirScalarExpr::CallUnary {
940 func: UnaryFunc::DatePartTimestampTz(
941 func::DatePartTimestampTz(units),
942 ),
943 expr: Box::new(expr2.take()),
944 },
945 Err(_) => MirScalarExpr::literal(
946 Err(EvalError::UnknownUnits(units.into())),
947 e.typ(column_types).scalar_type,
948 ),
949 }
950 } else if let BinaryFunc::DateTruncTimestamp(_) = *func
951 && expr1.is_literal()
952 {
953 let units = expr1.as_literal_str().unwrap();
954 *e = match units.parse::<DateTimeUnits>() {
955 Ok(units) => MirScalarExpr::CallUnary {
956 func: UnaryFunc::DateTruncTimestamp(func::DateTruncTimestamp(
957 units,
958 )),
959 expr: Box::new(expr2.take()),
960 },
961 Err(_) => MirScalarExpr::literal(
962 Err(EvalError::UnknownUnits(units.into())),
963 e.typ(column_types).scalar_type,
964 ),
965 }
966 } else if let BinaryFunc::DateTruncTimestampTz(_) = *func
967 && expr1.is_literal()
968 {
969 let units = expr1.as_literal_str().unwrap();
970 *e = match units.parse::<DateTimeUnits>() {
971 Ok(units) => MirScalarExpr::CallUnary {
972 func: UnaryFunc::DateTruncTimestampTz(
973 func::DateTruncTimestampTz(units),
974 ),
975 expr: Box::new(expr2.take()),
976 },
977 Err(_) => MirScalarExpr::literal(
978 Err(EvalError::UnknownUnits(units.into())),
979 e.typ(column_types).scalar_type,
980 ),
981 }
982 } else if *func == BinaryFunc::TimezoneTimestamp && expr1.is_literal() {
983 let tz = expr1.as_literal_str().unwrap();
987 *e = match parse_timezone(tz, TimezoneSpec::Posix) {
988 Ok(tz) => MirScalarExpr::CallUnary {
989 func: UnaryFunc::TimezoneTimestamp(func::TimezoneTimestamp(tz)),
990 expr: Box::new(expr2.take()),
991 },
992 Err(err) => MirScalarExpr::literal(
993 Err(err),
994 e.typ(column_types).scalar_type,
995 ),
996 }
997 } else if *func == BinaryFunc::TimezoneTimestampTz && expr1.is_literal() {
998 let tz = expr1.as_literal_str().unwrap();
999 *e = match parse_timezone(tz, TimezoneSpec::Posix) {
1000 Ok(tz) => MirScalarExpr::CallUnary {
1001 func: UnaryFunc::TimezoneTimestampTz(
1002 func::TimezoneTimestampTz(tz),
1003 ),
1004 expr: Box::new(expr2.take()),
1005 },
1006 Err(err) => MirScalarExpr::literal(
1007 Err(err),
1008 e.typ(column_types).scalar_type,
1009 ),
1010 }
1011 } else if let BinaryFunc::ToCharTimestamp(_) = *func
1012 && expr2.is_literal()
1013 {
1014 let format_str = expr2.as_literal_str().unwrap();
1015 *e = MirScalarExpr::CallUnary {
1016 func: UnaryFunc::ToCharTimestamp(func::ToCharTimestamp {
1017 format_string: format_str.to_string(),
1018 format: DateTimeFormat::compile(format_str),
1019 }),
1020 expr: Box::new(expr1.take()),
1021 };
1022 } else if let BinaryFunc::ToCharTimestampTz(_) = *func
1023 && expr2.is_literal()
1024 {
1025 let format_str = expr2.as_literal_str().unwrap();
1026 *e = MirScalarExpr::CallUnary {
1027 func: UnaryFunc::ToCharTimestampTz(func::ToCharTimestampTz {
1028 format_string: format_str.to_string(),
1029 format: DateTimeFormat::compile(format_str),
1030 }),
1031 expr: Box::new(expr1.take()),
1032 };
1033 } else if matches!(*func, BinaryFunc::Eq(_) | BinaryFunc::NotEq(_))
1034 && expr2 < expr1
1035 {
1036 mem::swap(expr1, expr2);
1040 } else if let (
1041 BinaryFunc::Eq(_),
1042 MirScalarExpr::Literal(
1043 Ok(lit_row),
1044 SqlColumnType {
1045 scalar_type:
1046 SqlScalarType::Record {
1047 fields: field_types,
1048 ..
1049 },
1050 ..
1051 },
1052 ),
1053 MirScalarExpr::CallVariadic {
1054 func: VariadicFunc::RecordCreate { .. },
1055 exprs: rec_create_args,
1056 },
1057 ) = (&*func, &**expr1, &**expr2)
1058 {
1059 match lit_row.unpack_first() {
1068 Datum::List(datum_list) => {
1069 *e = MirScalarExpr::CallVariadic {
1070 func: VariadicFunc::And,
1071 exprs: datum_list
1072 .iter()
1073 .zip_eq(field_types)
1074 .zip_eq(rec_create_args)
1075 .map(|((d, (_, typ)), a)| {
1076 MirScalarExpr::literal_ok(
1077 d,
1078 typ.scalar_type.clone(),
1079 )
1080 .call_binary(a.clone(), func::Eq)
1081 })
1082 .collect(),
1083 };
1084 }
1085 _ => {}
1086 }
1087 } else if let (
1088 BinaryFunc::Eq(_),
1089 MirScalarExpr::CallVariadic {
1090 func: VariadicFunc::RecordCreate { .. },
1091 exprs: rec_create_args1,
1092 },
1093 MirScalarExpr::CallVariadic {
1094 func: VariadicFunc::RecordCreate { .. },
1095 exprs: rec_create_args2,
1096 },
1097 ) = (&*func, &**expr1, &**expr2)
1098 {
1099 *e = MirScalarExpr::CallVariadic {
1111 func: VariadicFunc::And,
1112 exprs: rec_create_args1
1113 .into_iter()
1114 .zip_eq(rec_create_args2)
1115 .map(|(a, b)| a.clone().call_binary(b.clone(), func::Eq))
1116 .collect(),
1117 }
1118 }
1119 }
1120 MirScalarExpr::CallVariadic { .. } => {
1121 e.flatten_associative();
1122 let (func, exprs) = match e {
1123 MirScalarExpr::CallVariadic { func, exprs } => (func, exprs),
1124 _ => unreachable!("`flatten_associative` shouldn't change node type"),
1125 };
1126 if *func == VariadicFunc::Coalesce {
1127 if exprs.iter().all(|expr| expr.is_literal_null()) {
1131 *e = MirScalarExpr::literal_null(e.typ(column_types).scalar_type);
1132 return;
1133 }
1134
1135 exprs.retain(|e| !e.is_literal_null());
1137
1138 if let Some(i) = exprs
1143 .iter()
1144 .position(|e| e.is_literal() || !e.typ(column_types).nullable)
1145 {
1146 exprs.truncate(i + 1);
1147 }
1148
1149 let mut prior_exprs = BTreeSet::new();
1151 exprs.retain(|e| prior_exprs.insert(e.clone()));
1152
1153 if exprs.len() == 1 {
1154 *e = exprs[0].take();
1156 }
1157 } else if exprs.iter().all(|e| e.is_literal()) {
1158 *e = eval(e);
1159 } else if func.propagates_nulls()
1160 && exprs.iter().any(|e| e.is_literal_null())
1161 {
1162 *e = MirScalarExpr::literal_null(e.typ(column_types).scalar_type);
1163 } else if let Some(err) = exprs.iter().find_map(|e| e.as_literal_err()) {
1164 *e = MirScalarExpr::literal(
1165 Err(err.clone()),
1166 e.typ(column_types).scalar_type,
1167 );
1168 } else if *func == VariadicFunc::RegexpMatch
1169 && exprs[1].is_literal()
1170 && exprs.get(2).map_or(true, |e| e.is_literal())
1171 {
1172 let needle = exprs[1].as_literal_str().unwrap();
1173 let flags = match exprs.len() {
1174 3 => exprs[2].as_literal_str().unwrap(),
1175 _ => "",
1176 };
1177 *e = match func::build_regex(needle, flags) {
1178 Ok(regex) => mem::take(exprs)
1179 .into_first()
1180 .call_unary(UnaryFunc::RegexpMatch(func::RegexpMatch(regex))),
1181 Err(err) => MirScalarExpr::literal(
1182 Err(err),
1183 e.typ(column_types).scalar_type,
1184 ),
1185 };
1186 } else if *func == VariadicFunc::RegexpReplace
1187 && exprs[1].is_literal()
1188 && exprs.get(3).map_or(true, |e| e.is_literal())
1189 {
1190 let pattern = exprs[1].as_literal_str().unwrap();
1191 let flags = exprs
1192 .get(3)
1193 .map_or("", |expr| expr.as_literal_str().unwrap());
1194 let (limit, flags) = regexp_replace_parse_flags(flags);
1195
1196 *e = match func::build_regex(pattern, &flags) {
1202 Ok(regex) => {
1203 let mut exprs = mem::take(exprs);
1204 let replacement = exprs.swap_remove(2);
1205 let source = exprs.swap_remove(0);
1206 source.call_binary(
1207 replacement,
1208 BinaryFunc::RegexpReplace { regex, limit },
1209 )
1210 }
1211 Err(err) => {
1212 let mut exprs = mem::take(exprs);
1213 let source = exprs.swap_remove(0);
1214 let scalar_type = e.typ(column_types).scalar_type;
1215 source.call_is_null().if_then_else(
1217 MirScalarExpr::literal_null(scalar_type.clone()),
1218 MirScalarExpr::literal(Err(err), scalar_type),
1219 )
1220 }
1221 };
1222 } else if *func == VariadicFunc::RegexpSplitToArray
1223 && exprs[1].is_literal()
1224 && exprs.get(2).map_or(true, |e| e.is_literal())
1225 {
1226 let needle = exprs[1].as_literal_str().unwrap();
1227 let flags = match exprs.len() {
1228 3 => exprs[2].as_literal_str().unwrap(),
1229 _ => "",
1230 };
1231 *e = match func::build_regex(needle, flags) {
1232 Ok(regex) => mem::take(exprs).into_first().call_unary(
1233 UnaryFunc::RegexpSplitToArray(func::RegexpSplitToArray(regex)),
1234 ),
1235 Err(err) => MirScalarExpr::literal(
1236 Err(err),
1237 e.typ(column_types).scalar_type,
1238 ),
1239 };
1240 } else if *func == VariadicFunc::ListIndex && is_list_create_call(&exprs[0])
1241 {
1242 let ind_exprs = exprs.split_off(1);
1245 let top_list_create = exprs.swap_remove(0);
1246 *e = reduce_list_create_list_index_literal(top_list_create, ind_exprs);
1247 } else if *func == VariadicFunc::Or || *func == VariadicFunc::And {
1248 e.undistribute_and_or();
1250 e.reduce_and_canonicalize_and_or();
1251 } else if let VariadicFunc::TimezoneTime = func {
1252 if exprs[0].is_literal() && exprs[2].is_literal_ok() {
1253 let tz = exprs[0].as_literal_str().unwrap();
1254 *e = match parse_timezone(tz, TimezoneSpec::Posix) {
1255 Ok(tz) => MirScalarExpr::CallUnary {
1256 func: UnaryFunc::TimezoneTime(func::TimezoneTime {
1257 tz,
1258 wall_time: exprs[2]
1259 .as_literal()
1260 .unwrap()
1261 .unwrap()
1262 .unwrap_timestamptz()
1263 .naive_utc(),
1264 }),
1265 expr: Box::new(exprs[1].take()),
1266 },
1267 Err(err) => MirScalarExpr::literal(
1268 Err(err),
1269 e.typ(column_types).scalar_type,
1270 ),
1271 }
1272 }
1273 }
1274 }
1275 MirScalarExpr::If { cond, then, els } => {
1276 if let Some(literal) = cond.as_literal() {
1277 match literal {
1278 Ok(Datum::True) => *e = then.take(),
1279 Ok(Datum::False) | Ok(Datum::Null) => *e = els.take(),
1280 Err(err) => {
1281 *e = MirScalarExpr::Literal(
1282 Err(err.clone()),
1283 then.typ(column_types)
1284 .union(&els.typ(column_types))
1285 .unwrap(),
1286 )
1287 }
1288 _ => unreachable!(),
1289 }
1290 } else if then == els {
1291 *e = then.take();
1292 } else if then.is_literal_ok()
1293 && els.is_literal_ok()
1294 && then.typ(column_types).scalar_type == SqlScalarType::Bool
1295 && els.typ(column_types).scalar_type == SqlScalarType::Bool
1296 {
1297 match (then.as_literal(), els.as_literal()) {
1298 (Some(Ok(Datum::True)), _) => {
1301 *e = cond
1304 .clone()
1305 .call_is_null()
1306 .not()
1307 .and(cond.take())
1308 .or(els.take());
1309 }
1310 (Some(Ok(Datum::False)), _) => {
1311 *e = cond
1314 .clone()
1315 .not()
1316 .or(cond.take().call_is_null())
1317 .and(els.take());
1318 }
1319 (_, Some(Ok(Datum::True))) => {
1320 *e = cond
1323 .clone()
1324 .not()
1325 .or(cond.take().call_is_null())
1326 .or(then.take());
1327 }
1328 (_, Some(Ok(Datum::False))) => {
1329 *e = cond
1332 .clone()
1333 .call_is_null()
1334 .not()
1335 .and(cond.take())
1336 .and(then.take());
1337 }
1338 _ => {}
1339 }
1340 } else {
1341 match (&mut **then, &mut **els) {
1353 (
1354 MirScalarExpr::CallUnary { func: f1, expr: e1 },
1355 MirScalarExpr::CallUnary { func: f2, expr: e2 },
1356 ) if f1 == f2
1357 && e1
1358 .typ(column_types)
1359 .union(&e2.typ(column_types))
1360 .is_ok() =>
1361 {
1362 *e = cond
1363 .take()
1364 .if_then_else(e1.take(), e2.take())
1365 .call_unary(f1.clone());
1366 }
1367 (
1368 MirScalarExpr::CallBinary {
1369 func: f1,
1370 expr1: e1a,
1371 expr2: e2a,
1372 },
1373 MirScalarExpr::CallBinary {
1374 func: f2,
1375 expr1: e1b,
1376 expr2: e2b,
1377 },
1378 ) if f1 == f2
1379 && e1a == e1b
1380 && e2a
1381 .typ(column_types)
1382 .union(&e2b.typ(column_types))
1383 .is_ok() =>
1384 {
1385 *e = e1a.take().call_binary(
1386 cond.take().if_then_else(e2a.take(), e2b.take()),
1387 f1.clone(),
1388 );
1389 }
1390 (
1391 MirScalarExpr::CallBinary {
1392 func: f1,
1393 expr1: e1a,
1394 expr2: e2a,
1395 },
1396 MirScalarExpr::CallBinary {
1397 func: f2,
1398 expr1: e1b,
1399 expr2: e2b,
1400 },
1401 ) if f1 == f2
1402 && e2a == e2b
1403 && e1a
1404 .typ(column_types)
1405 .union(&e1b.typ(column_types))
1406 .is_ok() =>
1407 {
1408 *e = cond
1409 .take()
1410 .if_then_else(e1a.take(), e1b.take())
1411 .call_binary(e2a.take(), f1.clone());
1412 }
1413 _ => {}
1414 }
1415 }
1416 }
1417 },
1418 );
1419 }
1420
1421 fn list_create_type(list_create: &MirScalarExpr) -> SqlScalarType {
1424 if let MirScalarExpr::CallVariadic {
1425 func: VariadicFunc::ListCreate { elem_type: typ },
1426 ..
1427 } = list_create
1428 {
1429 (*typ).clone()
1430 } else {
1431 unreachable!()
1432 }
1433 }
1434
1435 fn is_list_create_call(expr: &MirScalarExpr) -> bool {
1436 matches!(
1437 expr,
1438 MirScalarExpr::CallVariadic {
1439 func: VariadicFunc::ListCreate { .. },
1440 ..
1441 }
1442 )
1443 }
1444
1445 fn reduce_list_create_list_index_literal(
1460 mut list_create_to_reduce: MirScalarExpr,
1461 mut index_exprs: Vec<MirScalarExpr>,
1462 ) -> MirScalarExpr {
1463 let mut list_create_mut_refs = vec![&mut list_create_to_reduce];
1475 let mut earlier_list_create_types: Vec<&mut SqlScalarType> = vec![];
1476 let mut i = 0;
1477 while i < index_exprs.len()
1478 && list_create_mut_refs
1479 .iter()
1480 .all(|lc| is_list_create_call(lc))
1481 {
1482 if index_exprs[i].is_literal_ok() {
1483 let removed_index = index_exprs.remove(i);
1485 let index_i64 = match removed_index.as_literal().unwrap().unwrap() {
1486 Datum::Int64(sql_index_i64) => sql_index_i64 - 1,
1487 _ => unreachable!(), };
1489 for list_create in &mut list_create_mut_refs {
1492 let list_create_args = match list_create {
1493 MirScalarExpr::CallVariadic {
1494 func: VariadicFunc::ListCreate { elem_type: _ },
1495 exprs,
1496 } => exprs,
1497 _ => unreachable!(), };
1499 if index_i64 >= 0 && index_i64 < list_create_args.len().try_into().unwrap()
1501 {
1502 let index: usize = index_i64.try_into().unwrap();
1503 **list_create = list_create_args.swap_remove(index);
1504 } else {
1505 let typ = list_create_type(list_create);
1506 **list_create = MirScalarExpr::literal_null(typ);
1507 }
1508 }
1509 for t in earlier_list_create_types.iter_mut() {
1511 if let SqlScalarType::List {
1512 element_type,
1513 custom_id: _,
1514 } = t
1515 {
1516 **t = *element_type.clone();
1517 let mut u = &mut **t;
1520 while let SqlScalarType::List {
1521 element_type,
1522 custom_id,
1523 } = u
1524 {
1525 *custom_id = None;
1526 u = &mut **element_type;
1527 }
1528 } else {
1529 unreachable!("already matched below");
1530 }
1531 }
1532 } else {
1533 list_create_mut_refs = list_create_mut_refs
1537 .into_iter()
1538 .flat_map(|list_create| match list_create {
1539 MirScalarExpr::CallVariadic {
1540 func: VariadicFunc::ListCreate { elem_type },
1541 exprs: list_create_args,
1542 } => {
1543 earlier_list_create_types.push(elem_type);
1544 list_create_args
1545 }
1546 _ => unreachable!(),
1548 })
1549 .collect();
1550 i += 1; }
1552 }
1553 if index_exprs.is_empty() {
1556 assert_eq!(list_create_mut_refs.len(), 1);
1557 list_create_to_reduce
1558 } else {
1559 let mut exprs: Vec<MirScalarExpr> = vec![list_create_to_reduce];
1560 exprs.append(&mut index_exprs);
1561 MirScalarExpr::CallVariadic {
1562 func: VariadicFunc::ListIndex,
1563 exprs,
1564 }
1565 }
1566 }
1567
1568 }
1570
1571 fn decompose_is_null(&mut self) -> Option<MirScalarExpr> {
1579 match self {
1582 MirScalarExpr::CallUnary {
1583 func,
1584 expr: inner_expr,
1585 } => {
1586 if !func.introduces_nulls() {
1587 if func.propagates_nulls() {
1588 *self = inner_expr.take();
1589 return self.decompose_is_null();
1590 } else {
1591 return Some(MirScalarExpr::literal_false());
1594 }
1595 }
1596 }
1597 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1598 if func.propagates_nulls() && !func.introduces_nulls() {
1601 let expr1 = expr1.take().call_is_null();
1602 let expr2 = expr2.take().call_is_null();
1603 return Some(expr1.or(expr2));
1604 }
1605 }
1606 MirScalarExpr::CallVariadic { func, exprs } => {
1607 if func.propagates_nulls() && !func.introduces_nulls() {
1608 let exprs = exprs.into_iter().map(|e| e.take().call_is_null()).collect();
1609 return Some(MirScalarExpr::CallVariadic {
1610 func: VariadicFunc::Or,
1611 exprs,
1612 });
1613 }
1614 }
1615 _ => {}
1616 }
1617
1618 None
1619 }
1620
1621 pub fn flatten_associative(&mut self) {
1624 match self {
1625 MirScalarExpr::CallVariadic {
1626 exprs: outer_operands,
1627 func: outer_func,
1628 } if outer_func.is_associative() => {
1629 *outer_operands = outer_operands
1630 .into_iter()
1631 .flat_map(|o| {
1632 if let MirScalarExpr::CallVariadic {
1633 exprs: inner_operands,
1634 func: inner_func,
1635 } = o
1636 {
1637 if *inner_func == *outer_func {
1638 mem::take(inner_operands)
1639 } else {
1640 vec![o.take()]
1641 }
1642 } else {
1643 vec![o.take()]
1644 }
1645 })
1646 .collect();
1647 }
1648 _ => {}
1649 }
1650 }
1651
1652 fn reduce_and_canonicalize_and_or(&mut self) {
1656 let mut old_self = MirScalarExpr::column(0);
1660 while old_self != *self {
1661 old_self = self.clone();
1662 match self {
1663 MirScalarExpr::CallVariadic {
1664 func: func @ (VariadicFunc::And | VariadicFunc::Or),
1665 exprs,
1666 } => {
1667 exprs.sort();
1671
1672 exprs.dedup(); if exprs.len() == 1 {
1676 *self = exprs.swap_remove(0);
1678 } else if exprs.len() == 0 {
1679 *self = func.unit_of_and_or();
1681 } else if exprs.iter().any(|e| *e == func.zero_of_and_or()) {
1682 *self = func.zero_of_and_or();
1684 } else {
1685 exprs.retain(|e| *e != func.unit_of_and_or());
1688 }
1689 }
1690 _ => {}
1691 }
1692 }
1693 }
1694
1695 fn demorgans(&mut self) {
1697 if let MirScalarExpr::CallUnary {
1698 expr: inner,
1699 func: UnaryFunc::Not(func::Not),
1700 } = self
1701 {
1702 inner.flatten_associative();
1703 match &mut **inner {
1704 MirScalarExpr::CallVariadic {
1705 func: inner_func @ (VariadicFunc::And | VariadicFunc::Or),
1706 exprs,
1707 } => {
1708 *inner_func = inner_func.switch_and_or();
1709 *exprs = exprs.into_iter().map(|e| e.take().not()).collect();
1710 *self = (*inner).take(); }
1712 _ => {}
1713 }
1714 }
1715 }
1716
1717 fn undistribute_and_or(&mut self) {
1782 let mut old_self = MirScalarExpr::column(0);
1787 while old_self != *self {
1788 old_self = self.clone();
1789 self.reduce_and_canonicalize_and_or(); if let MirScalarExpr::CallVariadic {
1791 exprs: outer_operands,
1792 func: outer_func @ (VariadicFunc::Or | VariadicFunc::And),
1793 } = self
1794 {
1795 let inner_func = outer_func.switch_and_or();
1796
1797 outer_operands.iter_mut().for_each(|o| {
1800 if !matches!(o, MirScalarExpr::CallVariadic {func: f, ..} if *f == inner_func) {
1801 *o = MirScalarExpr::CallVariadic {
1802 func: inner_func.clone(),
1803 exprs: vec![o.take()],
1804 };
1805 }
1806 });
1807
1808 let mut inner_operands_refs: Vec<&mut Vec<MirScalarExpr>> = outer_operands
1809 .iter_mut()
1810 .map(|o| match o {
1811 MirScalarExpr::CallVariadic { func: f, exprs } if *f == inner_func => exprs,
1812 _ => unreachable!(), })
1814 .collect();
1815
1816 let mut intersection = inner_operands_refs
1818 .iter()
1819 .map(|v| (*v).clone())
1820 .reduce(|ops1, ops2| ops1.into_iter().filter(|e| ops2.contains(e)).collect())
1821 .unwrap();
1822 intersection.sort();
1823 intersection.dedup();
1824
1825 if !intersection.is_empty() {
1826 inner_operands_refs
1830 .iter_mut()
1831 .for_each(|ops| (**ops).retain(|o| !intersection.contains(o)));
1832
1833 outer_operands
1835 .iter_mut()
1836 .for_each(|o| o.reduce_and_canonicalize_and_or());
1837
1838 *self = MirScalarExpr::CallVariadic {
1840 func: inner_func,
1841 exprs: intersection.into_iter().chain_one(self.clone()).collect(),
1842 };
1843 } else {
1844 let all_inner_operands = inner_operands_refs
1855 .iter()
1856 .enumerate()
1857 .flat_map(|(i, inner_vec)| inner_vec.iter().map(move |a| ((*a).clone(), i)))
1858 .sorted()
1859 .collect_vec();
1860
1861 let undistribution_opportunities = all_inner_operands
1866 .iter()
1867 .chunk_by(|(a, _i)| a)
1868 .into_iter()
1869 .map(|(_a, g)| g.map(|(_a, i)| *i).sorted().dedup().collect_vec())
1870 .filter(|g| g.len() > 1)
1871 .collect_vec();
1872
1873 let indexes_to_undistribute = undistribution_opportunities
1875 .iter()
1876 .find(|index_set| {
1878 index_set
1879 .iter()
1880 .any(|i| inner_operands_refs.get(*i).unwrap().len() == 1)
1881 })
1882 .or_else(|| undistribution_opportunities.first())
1884 .cloned();
1885
1886 outer_operands
1888 .iter_mut()
1889 .for_each(|o| o.reduce_and_canonicalize_and_or());
1890
1891 if let Some(indexes_to_undistribute) = indexes_to_undistribute {
1892 let mut undistribute_from = MirScalarExpr::CallVariadic {
1896 func: outer_func.clone(),
1897 exprs: swap_remove_multiple(outer_operands, indexes_to_undistribute),
1898 };
1899 undistribute_from.undistribute_and_or();
1902 outer_operands.push(undistribute_from);
1905 }
1906 }
1907 }
1908 }
1909 }
1910
1911 pub fn non_null_requirements(&self, columns: &mut BTreeSet<usize>) {
1915 match self {
1916 MirScalarExpr::Column(col, _name) => {
1917 columns.insert(*col);
1918 }
1919 MirScalarExpr::Literal(..) => {}
1920 MirScalarExpr::CallUnmaterializable(_) => (),
1921 MirScalarExpr::CallUnary { func, expr } => {
1922 if func.propagates_nulls() {
1923 expr.non_null_requirements(columns);
1924 }
1925 }
1926 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1927 if func.propagates_nulls() {
1928 expr1.non_null_requirements(columns);
1929 expr2.non_null_requirements(columns);
1930 }
1931 }
1932 MirScalarExpr::CallVariadic { func, exprs } => {
1933 if func.propagates_nulls() {
1934 for expr in exprs {
1935 expr.non_null_requirements(columns);
1936 }
1937 }
1938 }
1939 MirScalarExpr::If { .. } => (),
1940 }
1941 }
1942
1943 pub fn typ(&self, column_types: &[SqlColumnType]) -> SqlColumnType {
1944 match self {
1945 MirScalarExpr::Column(i, _name) => column_types[*i].clone(),
1946 MirScalarExpr::Literal(_, typ) => typ.clone(),
1947 MirScalarExpr::CallUnmaterializable(func) => func.output_type(),
1948 MirScalarExpr::CallUnary { expr, func } => func.output_type(expr.typ(column_types)),
1949 MirScalarExpr::CallBinary { expr1, expr2, func } => {
1950 func.output_type(expr1.typ(column_types), expr2.typ(column_types))
1951 }
1952 MirScalarExpr::CallVariadic { exprs, func } => {
1953 func.output_type(exprs.iter().map(|e| e.typ(column_types)).collect())
1954 }
1955 MirScalarExpr::If { cond: _, then, els } => {
1956 let then_type = then.typ(column_types);
1957 let else_type = els.typ(column_types);
1958 then_type.union(&else_type).unwrap()
1959 }
1960 }
1961 }
1962
1963 pub fn eval<'a>(
1964 &'a self,
1965 datums: &[Datum<'a>],
1966 temp_storage: &'a RowArena,
1967 ) -> Result<Datum<'a>, EvalError> {
1968 match self {
1969 MirScalarExpr::Column(index, _name) => Ok(datums[*index].clone()),
1970 MirScalarExpr::Literal(res, _column_type) => match res {
1971 Ok(row) => Ok(row.unpack_first()),
1972 Err(e) => Err(e.clone()),
1973 },
1974 MirScalarExpr::CallUnmaterializable(x) => Err(EvalError::Internal(
1978 format!("cannot evaluate unmaterializable function: {:?}", x).into(),
1979 )),
1980 MirScalarExpr::CallUnary { func, expr } => func.eval(datums, temp_storage, expr),
1981 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1982 func.eval(datums, temp_storage, expr1, expr2)
1983 }
1984 MirScalarExpr::CallVariadic { func, exprs } => func.eval(datums, temp_storage, exprs),
1985 MirScalarExpr::If { cond, then, els } => match cond.eval(datums, temp_storage)? {
1986 Datum::True => then.eval(datums, temp_storage),
1987 Datum::False | Datum::Null => els.eval(datums, temp_storage),
1988 d => Err(EvalError::Internal(
1989 format!("if condition evaluated to non-boolean datum: {:?}", d).into(),
1990 )),
1991 },
1992 }
1993 }
1994
1995 pub fn contains_temporal(&self) -> bool {
1998 let mut contains = false;
1999 self.visit_pre(|e| {
2000 if let MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow) = e {
2001 contains = true;
2002 }
2003 });
2004 contains
2005 }
2006
2007 pub fn contains_unmaterializable(&self) -> bool {
2009 let mut contains = false;
2010 self.visit_pre(|e| {
2011 if let MirScalarExpr::CallUnmaterializable(_) = e {
2012 contains = true;
2013 }
2014 });
2015 contains
2016 }
2017
2018 pub fn contains_unmaterializable_except(&self, exceptions: &[UnmaterializableFunc]) -> bool {
2021 let mut contains = false;
2022 self.visit_pre(|e| match e {
2023 MirScalarExpr::CallUnmaterializable(f) if !exceptions.contains(f) => contains = true,
2024 _ => (),
2025 });
2026 contains
2027 }
2028
2029 pub fn contains_column(&self) -> bool {
2031 let mut contains = false;
2032 self.visit_pre(|e| {
2033 if let MirScalarExpr::Column(_col, _name) = e {
2034 contains = true;
2035 }
2036 });
2037 contains
2038 }
2039
2040 pub fn contains_dummy(&self) -> bool {
2042 let mut contains = false;
2043 self.visit_pre(|e| {
2044 if let MirScalarExpr::Literal(row, _) = e {
2045 if let Ok(row) = row {
2046 contains |= row.iter().any(|d| d == Datum::Dummy);
2047 }
2048 }
2049 });
2050 contains
2051 }
2052
2053 pub fn size(&self) -> usize {
2055 let mut size = 0;
2056 self.visit_pre(&mut |_: &MirScalarExpr| {
2057 size += 1;
2058 });
2059 size
2060 }
2061}
2062
2063impl MirScalarExpr {
2064 pub fn could_error(&self) -> bool {
2066 match self {
2067 MirScalarExpr::Column(_col, _name) => false,
2068 MirScalarExpr::Literal(row, ..) => row.is_err(),
2069 MirScalarExpr::CallUnmaterializable(_) => true,
2070 MirScalarExpr::CallUnary { func, expr } => func.could_error() || expr.could_error(),
2071 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
2072 func.could_error() || expr1.could_error() || expr2.could_error()
2073 }
2074 MirScalarExpr::CallVariadic { func, exprs } => {
2075 func.could_error() || exprs.iter().any(|e| e.could_error())
2076 }
2077 MirScalarExpr::If { cond, then, els } => {
2078 cond.could_error() || then.could_error() || els.could_error()
2079 }
2080 }
2081 }
2082}
2083
2084impl VisitChildren<Self> for MirScalarExpr {
2085 fn visit_children<F>(&self, mut f: F)
2086 where
2087 F: FnMut(&Self),
2088 {
2089 use MirScalarExpr::*;
2090 match self {
2091 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2092 CallUnary { expr, .. } => {
2093 f(expr);
2094 }
2095 CallBinary { expr1, expr2, .. } => {
2096 f(expr1);
2097 f(expr2);
2098 }
2099 CallVariadic { exprs, .. } => {
2100 for expr in exprs {
2101 f(expr);
2102 }
2103 }
2104 If { cond, then, els } => {
2105 f(cond);
2106 f(then);
2107 f(els);
2108 }
2109 }
2110 }
2111
2112 fn visit_mut_children<F>(&mut self, mut f: F)
2113 where
2114 F: FnMut(&mut Self),
2115 {
2116 use MirScalarExpr::*;
2117 match self {
2118 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2119 CallUnary { expr, .. } => {
2120 f(expr);
2121 }
2122 CallBinary { expr1, expr2, .. } => {
2123 f(expr1);
2124 f(expr2);
2125 }
2126 CallVariadic { exprs, .. } => {
2127 for expr in exprs {
2128 f(expr);
2129 }
2130 }
2131 If { cond, then, els } => {
2132 f(cond);
2133 f(then);
2134 f(els);
2135 }
2136 }
2137 }
2138
2139 fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
2140 where
2141 F: FnMut(&Self) -> Result<(), E>,
2142 E: From<RecursionLimitError>,
2143 {
2144 use MirScalarExpr::*;
2145 match self {
2146 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2147 CallUnary { expr, .. } => {
2148 f(expr)?;
2149 }
2150 CallBinary { expr1, expr2, .. } => {
2151 f(expr1)?;
2152 f(expr2)?;
2153 }
2154 CallVariadic { exprs, .. } => {
2155 for expr in exprs {
2156 f(expr)?;
2157 }
2158 }
2159 If { cond, then, els } => {
2160 f(cond)?;
2161 f(then)?;
2162 f(els)?;
2163 }
2164 }
2165 Ok(())
2166 }
2167
2168 fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
2169 where
2170 F: FnMut(&mut Self) -> Result<(), E>,
2171 E: From<RecursionLimitError>,
2172 {
2173 use MirScalarExpr::*;
2174 match self {
2175 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2176 CallUnary { expr, .. } => {
2177 f(expr)?;
2178 }
2179 CallBinary { expr1, expr2, .. } => {
2180 f(expr1)?;
2181 f(expr2)?;
2182 }
2183 CallVariadic { exprs, .. } => {
2184 for expr in exprs {
2185 f(expr)?;
2186 }
2187 }
2188 If { cond, then, els } => {
2189 f(cond)?;
2190 f(then)?;
2191 f(els)?;
2192 }
2193 }
2194 Ok(())
2195 }
2196}
2197
2198impl MirScalarExpr {
2199 pub fn children(&self) -> impl DoubleEndedIterator<Item = &Self> {
2201 let mut first = None;
2202 let mut second = None;
2203 let mut third = None;
2204 let mut variadic = None;
2205
2206 use MirScalarExpr::*;
2207 match self {
2208 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2209 CallUnary { expr, .. } => {
2210 first = Some(&**expr);
2211 }
2212 CallBinary { expr1, expr2, .. } => {
2213 first = Some(&**expr1);
2214 second = Some(&**expr2);
2215 }
2216 CallVariadic { exprs, .. } => {
2217 variadic = Some(exprs);
2218 }
2219 If { cond, then, els } => {
2220 first = Some(&**cond);
2221 second = Some(&**then);
2222 third = Some(&**els);
2223 }
2224 }
2225
2226 first
2227 .into_iter()
2228 .chain(second)
2229 .chain(third)
2230 .chain(variadic.into_iter().flatten())
2231 }
2232
2233 pub fn children_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Self> {
2235 let mut first = None;
2236 let mut second = None;
2237 let mut third = None;
2238 let mut variadic = None;
2239
2240 use MirScalarExpr::*;
2241 match self {
2242 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2243 CallUnary { expr, .. } => {
2244 first = Some(&mut **expr);
2245 }
2246 CallBinary { expr1, expr2, .. } => {
2247 first = Some(&mut **expr1);
2248 second = Some(&mut **expr2);
2249 }
2250 CallVariadic { exprs, .. } => {
2251 variadic = Some(exprs);
2252 }
2253 If { cond, then, els } => {
2254 first = Some(&mut **cond);
2255 second = Some(&mut **then);
2256 third = Some(&mut **els);
2257 }
2258 }
2259
2260 first
2261 .into_iter()
2262 .chain(second)
2263 .chain(third)
2264 .chain(variadic.into_iter().flatten())
2265 }
2266
2267 pub fn visit_pre<F>(&self, mut f: F)
2269 where
2270 F: FnMut(&Self),
2271 {
2272 let mut worklist = vec![self];
2273 while let Some(e) = worklist.pop() {
2274 f(e);
2275 worklist.extend(e.children().rev());
2276 }
2277 }
2278
2279 pub fn visit_pre_mut<F: FnMut(&mut Self)>(&mut self, mut f: F) {
2281 let mut worklist = vec![self];
2282 while let Some(expr) = worklist.pop() {
2283 f(expr);
2284 worklist.extend(expr.children_mut().rev());
2285 }
2286 }
2287}
2288
2289#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Serialize, Deserialize, Hash, MzReflect)]
2296pub struct FilterCharacteristics {
2297 literal_equality: bool,
2300 like: bool,
2302 is_null: bool,
2303 literal_inequality: usize,
2309 any_filter: bool,
2315}
2316
2317impl BitOrAssign for FilterCharacteristics {
2318 fn bitor_assign(&mut self, rhs: Self) {
2319 self.literal_equality |= rhs.literal_equality;
2320 self.like |= rhs.like;
2321 self.is_null |= rhs.is_null;
2322 self.literal_inequality += rhs.literal_inequality;
2323 self.any_filter |= rhs.any_filter;
2324 }
2325}
2326
2327impl FilterCharacteristics {
2328 pub fn none() -> FilterCharacteristics {
2329 FilterCharacteristics {
2330 literal_equality: false,
2331 like: false,
2332 is_null: false,
2333 literal_inequality: 0,
2334 any_filter: false,
2335 }
2336 }
2337
2338 pub fn explain(&self) -> String {
2339 let mut e = "".to_owned();
2340 if self.literal_equality {
2341 e.push_str("e");
2342 }
2343 if self.like {
2344 e.push_str("l");
2345 }
2346 if self.is_null {
2347 e.push_str("n");
2348 }
2349 for _ in 0..self.literal_inequality {
2350 e.push_str("i");
2351 }
2352 if self.any_filter {
2353 e.push_str("f");
2354 }
2355 e
2356 }
2357
2358 pub fn filter_characteristics(
2359 filters: &Vec<MirScalarExpr>,
2360 ) -> Result<FilterCharacteristics, RecursionLimitError> {
2361 let mut literal_equality = false;
2362 let mut like = false;
2363 let mut is_null = false;
2364 let mut literal_inequality = 0;
2365 let mut any_filter = false;
2366 filters.iter().try_for_each(|f| {
2367 let mut literal_inequality_in_current_filter = false;
2368 let mut is_not_null_in_current_filter = false;
2369 f.visit_pre_with_context(
2370 false,
2371 &mut |not_in_parent_chain, expr| {
2372 not_in_parent_chain
2373 || matches!(
2374 expr,
2375 MirScalarExpr::CallUnary {
2376 func: UnaryFunc::Not(func::Not),
2377 ..
2378 }
2379 )
2380 },
2381 &mut |not_in_parent_chain, expr| {
2382 if !not_in_parent_chain {
2383 if expr.any_expr_eq_literal().is_some() {
2384 literal_equality = true;
2385 }
2386 if expr.any_expr_ineq_literal() {
2387 literal_inequality_in_current_filter = true;
2388 }
2389 if matches!(
2390 expr,
2391 MirScalarExpr::CallUnary {
2392 func: UnaryFunc::IsLikeMatch(_),
2393 ..
2394 }
2395 ) {
2396 like = true;
2397 }
2398 };
2399 if matches!(
2400 expr,
2401 MirScalarExpr::CallUnary {
2402 func: UnaryFunc::IsNull(crate::func::IsNull),
2403 ..
2404 }
2405 ) {
2406 if *not_in_parent_chain {
2407 is_not_null_in_current_filter = true;
2408 } else {
2409 is_null = true;
2410 }
2411 }
2412 },
2413 )?;
2414 if literal_inequality_in_current_filter {
2415 literal_inequality += 1;
2416 }
2417 if !is_not_null_in_current_filter {
2418 any_filter = true;
2420 }
2421 Ok(())
2422 })?;
2423 Ok(FilterCharacteristics {
2424 literal_equality,
2425 like,
2426 is_null,
2427 literal_inequality,
2428 any_filter,
2429 })
2430 }
2431
2432 pub fn add_literal_equality(&mut self) {
2433 self.literal_equality = true;
2434 }
2435
2436 pub fn worst_case_scaling_factor(&self) -> f64 {
2437 let mut factor = 1.0;
2438
2439 if self.literal_equality {
2440 factor *= 0.1;
2441 }
2442
2443 if self.is_null {
2444 factor *= 0.1;
2445 }
2446
2447 if self.literal_inequality >= 2 {
2448 factor *= 0.25;
2449 } else if self.literal_inequality == 1 {
2450 factor *= 0.33;
2451 }
2452
2453 if !(self.literal_equality || self.is_null || self.literal_inequality > 0)
2455 && self.any_filter
2456 {
2457 factor *= 0.9;
2458 }
2459
2460 factor
2461 }
2462}
2463
2464#[derive(
2465 Arbitrary,
2466 Ord,
2467 PartialOrd,
2468 Copy,
2469 Clone,
2470 Debug,
2471 Eq,
2472 PartialEq,
2473 Serialize,
2474 Deserialize,
2475 Hash,
2476 MzReflect,
2477)]
2478pub enum DomainLimit {
2479 None,
2480 Inclusive(i64),
2481 Exclusive(i64),
2482}
2483
2484impl RustType<ProtoDomainLimit> for DomainLimit {
2485 fn into_proto(&self) -> ProtoDomainLimit {
2486 use proto_domain_limit::Kind::*;
2487 let kind = match self {
2488 DomainLimit::None => None(()),
2489 DomainLimit::Inclusive(v) => Inclusive(*v),
2490 DomainLimit::Exclusive(v) => Exclusive(*v),
2491 };
2492 ProtoDomainLimit { kind: Some(kind) }
2493 }
2494
2495 fn from_proto(proto: ProtoDomainLimit) -> Result<Self, TryFromProtoError> {
2496 use proto_domain_limit::Kind::*;
2497 if let Some(kind) = proto.kind {
2498 match kind {
2499 None(()) => Ok(DomainLimit::None),
2500 Inclusive(v) => Ok(DomainLimit::Inclusive(v)),
2501 Exclusive(v) => Ok(DomainLimit::Exclusive(v)),
2502 }
2503 } else {
2504 Err(TryFromProtoError::missing_field("ProtoDomainLimit::kind"))
2505 }
2506 }
2507}
2508
2509#[derive(
2510 Arbitrary, Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect,
2511)]
2512pub enum EvalError {
2513 CharacterNotValidForEncoding(i32),
2514 CharacterTooLargeForEncoding(i32),
2515 DateBinOutOfRange(Box<str>),
2516 DivisionByZero,
2517 Unsupported {
2518 feature: Box<str>,
2519 discussion_no: Option<usize>,
2520 },
2521 FloatOverflow,
2522 FloatUnderflow,
2523 NumericFieldOverflow,
2524 Float32OutOfRange(Box<str>),
2525 Float64OutOfRange(Box<str>),
2526 Int16OutOfRange(Box<str>),
2527 Int32OutOfRange(Box<str>),
2528 Int64OutOfRange(Box<str>),
2529 UInt16OutOfRange(Box<str>),
2530 UInt32OutOfRange(Box<str>),
2531 UInt64OutOfRange(Box<str>),
2532 MzTimestampOutOfRange(Box<str>),
2533 MzTimestampStepOverflow,
2534 OidOutOfRange(Box<str>),
2535 IntervalOutOfRange(Box<str>),
2536 TimestampCannotBeNan,
2537 TimestampOutOfRange,
2538 DateOutOfRange,
2539 CharOutOfRange,
2540 IndexOutOfRange {
2541 provided: i32,
2542 valid_end: i32,
2544 },
2545 InvalidBase64Equals,
2546 InvalidBase64Symbol(char),
2547 InvalidBase64EndSequence,
2548 InvalidTimezone(Box<str>),
2549 InvalidTimezoneInterval,
2550 InvalidTimezoneConversion,
2551 InvalidIanaTimezoneId(Box<str>),
2552 InvalidLayer {
2553 max_layer: usize,
2554 val: i64,
2555 },
2556 InvalidArray(InvalidArrayError),
2557 InvalidEncodingName(Box<str>),
2558 InvalidHashAlgorithm(Box<str>),
2559 InvalidByteSequence {
2560 byte_sequence: Box<str>,
2561 encoding_name: Box<str>,
2562 },
2563 InvalidJsonbCast {
2564 from: Box<str>,
2565 to: Box<str>,
2566 },
2567 InvalidRegex(Box<str>),
2568 InvalidRegexFlag(char),
2569 InvalidParameterValue(Box<str>),
2570 InvalidDatePart(Box<str>),
2571 KeyCannotBeNull,
2572 NegSqrt,
2573 NegLimit,
2574 NullCharacterNotPermitted,
2575 UnknownUnits(Box<str>),
2576 UnsupportedUnits(Box<str>, Box<str>),
2577 UnterminatedLikeEscapeSequence,
2578 Parse(ParseError),
2579 ParseHex(ParseHexError),
2580 Internal(Box<str>),
2581 InfinityOutOfDomain(Box<str>),
2582 NegativeOutOfDomain(Box<str>),
2583 ZeroOutOfDomain(Box<str>),
2584 OutOfDomain(DomainLimit, DomainLimit, Box<str>),
2585 ComplexOutOfRange(Box<str>),
2586 MultipleRowsFromSubquery,
2587 Undefined(Box<str>),
2588 LikePatternTooLong,
2589 LikeEscapeTooLong,
2590 StringValueTooLong {
2591 target_type: Box<str>,
2592 length: usize,
2593 },
2594 MultidimensionalArrayRemovalNotSupported,
2595 IncompatibleArrayDimensions {
2596 dims: Option<(usize, usize)>,
2597 },
2598 TypeFromOid(Box<str>),
2599 InvalidRange(InvalidRangeError),
2600 InvalidRoleId(Box<str>),
2601 InvalidPrivileges(Box<str>),
2602 LetRecLimitExceeded(Box<str>),
2603 MultiDimensionalArraySearch,
2604 MustNotBeNull(Box<str>),
2605 InvalidIdentifier {
2606 ident: Box<str>,
2607 detail: Option<Box<str>>,
2608 },
2609 ArrayFillWrongArraySubscripts,
2610 MaxArraySizeExceeded(usize),
2612 DateDiffOverflow {
2613 unit: Box<str>,
2614 a: Box<str>,
2615 b: Box<str>,
2616 },
2617 IfNullError(Box<str>),
2620 LengthTooLarge,
2621 AclArrayNullElement,
2622 MzAclArrayNullElement,
2623 PrettyError(Box<str>),
2624}
2625
2626impl fmt::Display for EvalError {
2627 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2628 match self {
2629 EvalError::CharacterNotValidForEncoding(v) => {
2630 write!(f, "requested character not valid for encoding: {v}")
2631 }
2632 EvalError::CharacterTooLargeForEncoding(v) => {
2633 write!(f, "requested character too large for encoding: {v}")
2634 }
2635 EvalError::DateBinOutOfRange(message) => f.write_str(message),
2636 EvalError::DivisionByZero => f.write_str("division by zero"),
2637 EvalError::Unsupported {
2638 feature,
2639 discussion_no,
2640 } => {
2641 write!(f, "{} not yet supported", feature)?;
2642 if let Some(discussion_no) = discussion_no {
2643 write!(
2644 f,
2645 ", see https://github.com/MaterializeInc/materialize/discussions/{} for more details",
2646 discussion_no
2647 )?;
2648 }
2649 Ok(())
2650 }
2651 EvalError::FloatOverflow => f.write_str("value out of range: overflow"),
2652 EvalError::FloatUnderflow => f.write_str("value out of range: underflow"),
2653 EvalError::NumericFieldOverflow => f.write_str("numeric field overflow"),
2654 EvalError::Float32OutOfRange(val) => write!(f, "{} real out of range", val.quoted()),
2655 EvalError::Float64OutOfRange(val) => {
2656 write!(f, "{} double precision out of range", val.quoted())
2657 }
2658 EvalError::Int16OutOfRange(val) => write!(f, "{} smallint out of range", val.quoted()),
2659 EvalError::Int32OutOfRange(val) => write!(f, "{} integer out of range", val.quoted()),
2660 EvalError::Int64OutOfRange(val) => write!(f, "{} bigint out of range", val.quoted()),
2661 EvalError::UInt16OutOfRange(val) => write!(f, "{} uint2 out of range", val.quoted()),
2662 EvalError::UInt32OutOfRange(val) => write!(f, "{} uint4 out of range", val.quoted()),
2663 EvalError::UInt64OutOfRange(val) => write!(f, "{} uint8 out of range", val.quoted()),
2664 EvalError::MzTimestampOutOfRange(val) => {
2665 write!(f, "{} mz_timestamp out of range", val.quoted())
2666 }
2667 EvalError::MzTimestampStepOverflow => f.write_str("step mz_timestamp overflow"),
2668 EvalError::OidOutOfRange(val) => write!(f, "{} OID out of range", val.quoted()),
2669 EvalError::IntervalOutOfRange(val) => {
2670 write!(f, "{} interval out of range", val.quoted())
2671 }
2672 EvalError::TimestampCannotBeNan => f.write_str("timestamp cannot be NaN"),
2673 EvalError::TimestampOutOfRange => f.write_str("timestamp out of range"),
2674 EvalError::DateOutOfRange => f.write_str("date out of range"),
2675 EvalError::CharOutOfRange => f.write_str("\"char\" out of range"),
2676 EvalError::IndexOutOfRange {
2677 provided,
2678 valid_end,
2679 } => write!(f, "index {provided} out of valid range, 0..{valid_end}",),
2680 EvalError::InvalidBase64Equals => {
2681 f.write_str("unexpected \"=\" while decoding base64 sequence")
2682 }
2683 EvalError::InvalidBase64Symbol(c) => write!(
2684 f,
2685 "invalid symbol \"{}\" found while decoding base64 sequence",
2686 c.escape_default()
2687 ),
2688 EvalError::InvalidBase64EndSequence => f.write_str("invalid base64 end sequence"),
2689 EvalError::InvalidJsonbCast { from, to } => {
2690 write!(f, "cannot cast jsonb {} to type {}", from, to)
2691 }
2692 EvalError::InvalidTimezone(tz) => write!(f, "invalid time zone '{}'", tz),
2693 EvalError::InvalidTimezoneInterval => {
2694 f.write_str("timezone interval must not contain months or years")
2695 }
2696 EvalError::InvalidTimezoneConversion => f.write_str("invalid timezone conversion"),
2697 EvalError::InvalidIanaTimezoneId(tz) => {
2698 write!(f, "invalid IANA Time Zone Database identifier: '{}'", tz)
2699 }
2700 EvalError::InvalidLayer { max_layer, val } => write!(
2701 f,
2702 "invalid layer: {}; must use value within [1, {}]",
2703 val, max_layer
2704 ),
2705 EvalError::InvalidArray(e) => e.fmt(f),
2706 EvalError::InvalidEncodingName(name) => write!(f, "invalid encoding name '{}'", name),
2707 EvalError::InvalidHashAlgorithm(alg) => write!(f, "invalid hash algorithm '{}'", alg),
2708 EvalError::InvalidByteSequence {
2709 byte_sequence,
2710 encoding_name,
2711 } => write!(
2712 f,
2713 "invalid byte sequence '{}' for encoding '{}'",
2714 byte_sequence, encoding_name
2715 ),
2716 EvalError::InvalidDatePart(part) => write!(f, "invalid datepart {}", part.quoted()),
2717 EvalError::KeyCannotBeNull => f.write_str("key cannot be null"),
2718 EvalError::NegSqrt => f.write_str("cannot take square root of a negative number"),
2719 EvalError::NegLimit => f.write_str("LIMIT must not be negative"),
2720 EvalError::NullCharacterNotPermitted => f.write_str("null character not permitted"),
2721 EvalError::InvalidRegex(e) => write!(f, "invalid regular expression: {}", e),
2722 EvalError::InvalidRegexFlag(c) => write!(f, "invalid regular expression flag: {}", c),
2723 EvalError::InvalidParameterValue(s) => f.write_str(s),
2724 EvalError::UnknownUnits(units) => write!(f, "unit '{}' not recognized", units),
2725 EvalError::UnsupportedUnits(units, typ) => {
2726 write!(f, "unit '{}' not supported for type {}", units, typ)
2727 }
2728 EvalError::UnterminatedLikeEscapeSequence => {
2729 f.write_str("unterminated escape sequence in LIKE")
2730 }
2731 EvalError::Parse(e) => e.fmt(f),
2732 EvalError::PrettyError(e) => e.fmt(f),
2733 EvalError::ParseHex(e) => e.fmt(f),
2734 EvalError::Internal(s) => write!(f, "internal error: {}", s),
2735 EvalError::InfinityOutOfDomain(s) => {
2736 write!(f, "function {} is only defined for finite arguments", s)
2737 }
2738 EvalError::NegativeOutOfDomain(s) => {
2739 write!(f, "function {} is not defined for negative numbers", s)
2740 }
2741 EvalError::ZeroOutOfDomain(s) => {
2742 write!(f, "function {} is not defined for zero", s)
2743 }
2744 EvalError::OutOfDomain(lower, upper, s) => {
2745 use DomainLimit::*;
2746 write!(f, "function {s} is defined for numbers ")?;
2747 match (lower, upper) {
2748 (Inclusive(n), None) => write!(f, "greater than or equal to {n}"),
2749 (Exclusive(n), None) => write!(f, "greater than {n}"),
2750 (None, Inclusive(n)) => write!(f, "less than or equal to {n}"),
2751 (None, Exclusive(n)) => write!(f, "less than {n}"),
2752 (Inclusive(lo), Inclusive(hi)) => write!(f, "between {lo} and {hi} inclusive"),
2753 (Exclusive(lo), Exclusive(hi)) => write!(f, "between {lo} and {hi} exclusive"),
2754 (Inclusive(lo), Exclusive(hi)) => {
2755 write!(f, "between {lo} inclusive and {hi} exclusive")
2756 }
2757 (Exclusive(lo), Inclusive(hi)) => {
2758 write!(f, "between {lo} exclusive and {hi} inclusive")
2759 }
2760 (None, None) => panic!("invalid domain error"),
2761 }
2762 }
2763 EvalError::ComplexOutOfRange(s) => {
2764 write!(f, "function {} cannot return complex numbers", s)
2765 }
2766 EvalError::MultipleRowsFromSubquery => {
2767 write!(f, "more than one record produced in subquery")
2768 }
2769 EvalError::Undefined(s) => {
2770 write!(f, "{} is undefined", s)
2771 }
2772 EvalError::LikePatternTooLong => {
2773 write!(f, "LIKE pattern exceeds maximum length")
2774 }
2775 EvalError::LikeEscapeTooLong => {
2776 write!(f, "invalid escape string")
2777 }
2778 EvalError::StringValueTooLong {
2779 target_type,
2780 length,
2781 } => {
2782 write!(f, "value too long for type {}({})", target_type, length)
2783 }
2784 EvalError::MultidimensionalArrayRemovalNotSupported => {
2785 write!(
2786 f,
2787 "removing elements from multidimensional arrays is not supported"
2788 )
2789 }
2790 EvalError::IncompatibleArrayDimensions { dims: _ } => {
2791 write!(f, "cannot concatenate incompatible arrays")
2792 }
2793 EvalError::TypeFromOid(msg) => write!(f, "{msg}"),
2794 EvalError::InvalidRange(e) => e.fmt(f),
2795 EvalError::InvalidRoleId(msg) => write!(f, "{msg}"),
2796 EvalError::InvalidPrivileges(privilege) => {
2797 write!(f, "unrecognized privilege type: {privilege}")
2798 }
2799 EvalError::LetRecLimitExceeded(max_iters) => {
2800 write!(
2801 f,
2802 "Recursive query exceeded the recursion limit {}. (Use RETURN AT RECURSION LIMIT to not error, but return the current state as the final result when reaching the limit.)",
2803 max_iters
2804 )
2805 }
2806 EvalError::MultiDimensionalArraySearch => write!(
2807 f,
2808 "searching for elements in multidimensional arrays is not supported"
2809 ),
2810 EvalError::MustNotBeNull(v) => write!(f, "{v} must not be null"),
2811 EvalError::InvalidIdentifier { ident, .. } => {
2812 write!(f, "string is not a valid identifier: {}", ident.quoted())
2813 }
2814 EvalError::ArrayFillWrongArraySubscripts => {
2815 f.write_str("wrong number of array subscripts")
2816 }
2817 EvalError::MaxArraySizeExceeded(max_size) => {
2818 write!(
2819 f,
2820 "array size exceeds the maximum allowed ({max_size} bytes)"
2821 )
2822 }
2823 EvalError::DateDiffOverflow { unit, a, b } => {
2824 write!(f, "datediff overflow, {unit} of {a}, {b}")
2825 }
2826 EvalError::IfNullError(s) => f.write_str(s),
2827 EvalError::LengthTooLarge => write!(f, "requested length too large"),
2828 EvalError::AclArrayNullElement => write!(f, "ACL arrays must not contain null values"),
2829 EvalError::MzAclArrayNullElement => {
2830 write!(f, "MZ_ACL arrays must not contain null values")
2831 }
2832 }
2833 }
2834}
2835
2836impl EvalError {
2837 pub fn detail(&self) -> Option<String> {
2838 match self {
2839 EvalError::IncompatibleArrayDimensions { dims: None } => Some(
2840 "Arrays with differing dimensions are not compatible for concatenation.".into(),
2841 ),
2842 EvalError::IncompatibleArrayDimensions {
2843 dims: Some((a_dims, b_dims)),
2844 } => Some(format!(
2845 "Arrays of {} and {} dimensions are not compatible for concatenation.",
2846 a_dims, b_dims
2847 )),
2848 EvalError::InvalidIdentifier { detail, .. } => detail.as_deref().map(Into::into),
2849 EvalError::ArrayFillWrongArraySubscripts => {
2850 Some("Low bound array has different size than dimensions array.".into())
2851 }
2852 _ => None,
2853 }
2854 }
2855
2856 pub fn hint(&self) -> Option<String> {
2857 match self {
2858 EvalError::InvalidBase64EndSequence => Some(
2859 "Input data is missing padding, is truncated, or is otherwise corrupted.".into(),
2860 ),
2861 EvalError::LikeEscapeTooLong => {
2862 Some("Escape string must be empty or one character.".into())
2863 }
2864 EvalError::MzTimestampOutOfRange(_) => Some(
2865 "Integer, numeric, and text casts to mz_timestamp must be in the form of whole \
2866 milliseconds since the Unix epoch. Values with fractional parts cannot be \
2867 converted to mz_timestamp."
2868 .into(),
2869 ),
2870 _ => None,
2871 }
2872 }
2873}
2874
2875impl std::error::Error for EvalError {}
2876
2877impl From<ParseError> for EvalError {
2878 fn from(e: ParseError) -> EvalError {
2879 EvalError::Parse(e)
2880 }
2881}
2882
2883impl From<ParseHexError> for EvalError {
2884 fn from(e: ParseHexError) -> EvalError {
2885 EvalError::ParseHex(e)
2886 }
2887}
2888
2889impl From<InvalidArrayError> for EvalError {
2890 fn from(e: InvalidArrayError) -> EvalError {
2891 EvalError::InvalidArray(e)
2892 }
2893}
2894
2895impl From<regex::Error> for EvalError {
2896 fn from(e: regex::Error) -> EvalError {
2897 EvalError::InvalidRegex(e.to_string().into())
2898 }
2899}
2900
2901impl From<TypeFromOidError> for EvalError {
2902 fn from(e: TypeFromOidError) -> EvalError {
2903 EvalError::TypeFromOid(e.to_string().into())
2904 }
2905}
2906
2907impl From<DateError> for EvalError {
2908 fn from(e: DateError) -> EvalError {
2909 match e {
2910 DateError::OutOfRange => EvalError::DateOutOfRange,
2911 }
2912 }
2913}
2914
2915impl From<TimestampError> for EvalError {
2916 fn from(e: TimestampError) -> EvalError {
2917 match e {
2918 TimestampError::OutOfRange => EvalError::TimestampOutOfRange,
2919 }
2920 }
2921}
2922
2923impl From<InvalidRangeError> for EvalError {
2924 fn from(e: InvalidRangeError) -> EvalError {
2925 EvalError::InvalidRange(e)
2926 }
2927}
2928
2929impl RustType<ProtoEvalError> for EvalError {
2930 fn into_proto(&self) -> ProtoEvalError {
2931 use proto_eval_error::Kind::*;
2932 use proto_eval_error::*;
2933 let kind = match self {
2934 EvalError::CharacterNotValidForEncoding(v) => CharacterNotValidForEncoding(*v),
2935 EvalError::CharacterTooLargeForEncoding(v) => CharacterTooLargeForEncoding(*v),
2936 EvalError::DateBinOutOfRange(v) => DateBinOutOfRange(v.into_proto()),
2937 EvalError::DivisionByZero => DivisionByZero(()),
2938 EvalError::Unsupported {
2939 feature,
2940 discussion_no,
2941 } => Unsupported(ProtoUnsupported {
2942 feature: feature.into_proto(),
2943 discussion_no: discussion_no.into_proto(),
2944 }),
2945 EvalError::FloatOverflow => FloatOverflow(()),
2946 EvalError::FloatUnderflow => FloatUnderflow(()),
2947 EvalError::NumericFieldOverflow => NumericFieldOverflow(()),
2948 EvalError::Float32OutOfRange(val) => Float32OutOfRange(ProtoValueOutOfRange {
2949 value: val.to_string(),
2950 }),
2951 EvalError::Float64OutOfRange(val) => Float64OutOfRange(ProtoValueOutOfRange {
2952 value: val.to_string(),
2953 }),
2954 EvalError::Int16OutOfRange(val) => Int16OutOfRange(ProtoValueOutOfRange {
2955 value: val.to_string(),
2956 }),
2957 EvalError::Int32OutOfRange(val) => Int32OutOfRange(ProtoValueOutOfRange {
2958 value: val.to_string(),
2959 }),
2960 EvalError::Int64OutOfRange(val) => Int64OutOfRange(ProtoValueOutOfRange {
2961 value: val.to_string(),
2962 }),
2963 EvalError::UInt16OutOfRange(val) => Uint16OutOfRange(ProtoValueOutOfRange {
2964 value: val.to_string(),
2965 }),
2966 EvalError::UInt32OutOfRange(val) => Uint32OutOfRange(ProtoValueOutOfRange {
2967 value: val.to_string(),
2968 }),
2969 EvalError::UInt64OutOfRange(val) => Uint64OutOfRange(ProtoValueOutOfRange {
2970 value: val.to_string(),
2971 }),
2972 EvalError::MzTimestampOutOfRange(val) => MzTimestampOutOfRange(ProtoValueOutOfRange {
2973 value: val.to_string(),
2974 }),
2975 EvalError::MzTimestampStepOverflow => MzTimestampStepOverflow(()),
2976 EvalError::OidOutOfRange(val) => OidOutOfRange(ProtoValueOutOfRange {
2977 value: val.to_string(),
2978 }),
2979 EvalError::IntervalOutOfRange(val) => IntervalOutOfRange(ProtoValueOutOfRange {
2980 value: val.to_string(),
2981 }),
2982 EvalError::TimestampCannotBeNan => TimestampCannotBeNan(()),
2983 EvalError::TimestampOutOfRange => TimestampOutOfRange(()),
2984 EvalError::DateOutOfRange => DateOutOfRange(()),
2985 EvalError::CharOutOfRange => CharOutOfRange(()),
2986 EvalError::IndexOutOfRange {
2987 provided,
2988 valid_end,
2989 } => IndexOutOfRange(ProtoIndexOutOfRange {
2990 provided: *provided,
2991 valid_end: *valid_end,
2992 }),
2993 EvalError::InvalidBase64Equals => InvalidBase64Equals(()),
2994 EvalError::InvalidBase64Symbol(sym) => InvalidBase64Symbol(sym.into_proto()),
2995 EvalError::InvalidBase64EndSequence => InvalidBase64EndSequence(()),
2996 EvalError::InvalidTimezone(tz) => InvalidTimezone(tz.into_proto()),
2997 EvalError::InvalidTimezoneInterval => InvalidTimezoneInterval(()),
2998 EvalError::InvalidTimezoneConversion => InvalidTimezoneConversion(()),
2999 EvalError::InvalidLayer { max_layer, val } => InvalidLayer(ProtoInvalidLayer {
3000 max_layer: max_layer.into_proto(),
3001 val: *val,
3002 }),
3003 EvalError::InvalidArray(error) => InvalidArray(error.into_proto()),
3004 EvalError::InvalidEncodingName(v) => InvalidEncodingName(v.into_proto()),
3005 EvalError::InvalidHashAlgorithm(v) => InvalidHashAlgorithm(v.into_proto()),
3006 EvalError::InvalidByteSequence {
3007 byte_sequence,
3008 encoding_name,
3009 } => InvalidByteSequence(ProtoInvalidByteSequence {
3010 byte_sequence: byte_sequence.into_proto(),
3011 encoding_name: encoding_name.into_proto(),
3012 }),
3013 EvalError::InvalidJsonbCast { from, to } => InvalidJsonbCast(ProtoInvalidJsonbCast {
3014 from: from.into_proto(),
3015 to: to.into_proto(),
3016 }),
3017 EvalError::InvalidRegex(v) => InvalidRegex(v.into_proto()),
3018 EvalError::InvalidRegexFlag(v) => InvalidRegexFlag(v.into_proto()),
3019 EvalError::InvalidParameterValue(v) => InvalidParameterValue(v.into_proto()),
3020 EvalError::InvalidDatePart(part) => InvalidDatePart(part.into_proto()),
3021 EvalError::KeyCannotBeNull => KeyCannotBeNull(()),
3022 EvalError::NegSqrt => NegSqrt(()),
3023 EvalError::NegLimit => NegLimit(()),
3024 EvalError::NullCharacterNotPermitted => NullCharacterNotPermitted(()),
3025 EvalError::UnknownUnits(v) => UnknownUnits(v.into_proto()),
3026 EvalError::UnsupportedUnits(units, typ) => UnsupportedUnits(ProtoUnsupportedUnits {
3027 units: units.into_proto(),
3028 typ: typ.into_proto(),
3029 }),
3030 EvalError::UnterminatedLikeEscapeSequence => UnterminatedLikeEscapeSequence(()),
3031 EvalError::Parse(error) => Parse(error.into_proto()),
3032 EvalError::PrettyError(error) => PrettyError(error.into_proto()),
3033 EvalError::ParseHex(error) => ParseHex(error.into_proto()),
3034 EvalError::Internal(v) => Internal(v.into_proto()),
3035 EvalError::InfinityOutOfDomain(v) => InfinityOutOfDomain(v.into_proto()),
3036 EvalError::NegativeOutOfDomain(v) => NegativeOutOfDomain(v.into_proto()),
3037 EvalError::ZeroOutOfDomain(v) => ZeroOutOfDomain(v.into_proto()),
3038 EvalError::OutOfDomain(lower, upper, id) => OutOfDomain(ProtoOutOfDomain {
3039 lower: Some(lower.into_proto()),
3040 upper: Some(upper.into_proto()),
3041 id: id.into_proto(),
3042 }),
3043 EvalError::ComplexOutOfRange(v) => ComplexOutOfRange(v.into_proto()),
3044 EvalError::MultipleRowsFromSubquery => MultipleRowsFromSubquery(()),
3045 EvalError::Undefined(v) => Undefined(v.into_proto()),
3046 EvalError::LikePatternTooLong => LikePatternTooLong(()),
3047 EvalError::LikeEscapeTooLong => LikeEscapeTooLong(()),
3048 EvalError::StringValueTooLong {
3049 target_type,
3050 length,
3051 } => StringValueTooLong(ProtoStringValueTooLong {
3052 target_type: target_type.into_proto(),
3053 length: length.into_proto(),
3054 }),
3055 EvalError::MultidimensionalArrayRemovalNotSupported => {
3056 MultidimensionalArrayRemovalNotSupported(())
3057 }
3058 EvalError::IncompatibleArrayDimensions { dims } => {
3059 IncompatibleArrayDimensions(ProtoIncompatibleArrayDimensions {
3060 dims: dims.into_proto(),
3061 })
3062 }
3063 EvalError::TypeFromOid(v) => TypeFromOid(v.into_proto()),
3064 EvalError::InvalidRange(error) => InvalidRange(error.into_proto()),
3065 EvalError::InvalidRoleId(v) => InvalidRoleId(v.into_proto()),
3066 EvalError::InvalidPrivileges(v) => InvalidPrivileges(v.into_proto()),
3067 EvalError::LetRecLimitExceeded(v) => WmrRecursionLimitExceeded(v.into_proto()),
3068 EvalError::MultiDimensionalArraySearch => MultiDimensionalArraySearch(()),
3069 EvalError::MustNotBeNull(v) => MustNotBeNull(v.into_proto()),
3070 EvalError::InvalidIdentifier { ident, detail } => {
3071 InvalidIdentifier(ProtoInvalidIdentifier {
3072 ident: ident.into_proto(),
3073 detail: detail.into_proto(),
3074 })
3075 }
3076 EvalError::ArrayFillWrongArraySubscripts => ArrayFillWrongArraySubscripts(()),
3077 EvalError::MaxArraySizeExceeded(max_size) => {
3078 MaxArraySizeExceeded(u64::cast_from(*max_size))
3079 }
3080 EvalError::DateDiffOverflow { unit, a, b } => DateDiffOverflow(ProtoDateDiffOverflow {
3081 unit: unit.into_proto(),
3082 a: a.into_proto(),
3083 b: b.into_proto(),
3084 }),
3085 EvalError::IfNullError(s) => IfNullError(s.into_proto()),
3086 EvalError::LengthTooLarge => LengthTooLarge(()),
3087 EvalError::AclArrayNullElement => AclArrayNullElement(()),
3088 EvalError::MzAclArrayNullElement => MzAclArrayNullElement(()),
3089 EvalError::InvalidIanaTimezoneId(s) => InvalidIanaTimezoneId(s.into_proto()),
3090 };
3091 ProtoEvalError { kind: Some(kind) }
3092 }
3093
3094 fn from_proto(proto: ProtoEvalError) -> Result<Self, TryFromProtoError> {
3095 use proto_eval_error::Kind::*;
3096 match proto.kind {
3097 Some(kind) => match kind {
3098 CharacterNotValidForEncoding(v) => Ok(EvalError::CharacterNotValidForEncoding(v)),
3099 CharacterTooLargeForEncoding(v) => Ok(EvalError::CharacterTooLargeForEncoding(v)),
3100 DateBinOutOfRange(v) => Ok(EvalError::DateBinOutOfRange(v.into())),
3101 DivisionByZero(()) => Ok(EvalError::DivisionByZero),
3102 Unsupported(v) => Ok(EvalError::Unsupported {
3103 feature: v.feature.into(),
3104 discussion_no: v.discussion_no.into_rust()?,
3105 }),
3106 FloatOverflow(()) => Ok(EvalError::FloatOverflow),
3107 FloatUnderflow(()) => Ok(EvalError::FloatUnderflow),
3108 NumericFieldOverflow(()) => Ok(EvalError::NumericFieldOverflow),
3109 Float32OutOfRange(val) => Ok(EvalError::Float32OutOfRange(val.value.into())),
3110 Float64OutOfRange(val) => Ok(EvalError::Float64OutOfRange(val.value.into())),
3111 Int16OutOfRange(val) => Ok(EvalError::Int16OutOfRange(val.value.into())),
3112 Int32OutOfRange(val) => Ok(EvalError::Int32OutOfRange(val.value.into())),
3113 Int64OutOfRange(val) => Ok(EvalError::Int64OutOfRange(val.value.into())),
3114 Uint16OutOfRange(val) => Ok(EvalError::UInt16OutOfRange(val.value.into())),
3115 Uint32OutOfRange(val) => Ok(EvalError::UInt32OutOfRange(val.value.into())),
3116 Uint64OutOfRange(val) => Ok(EvalError::UInt64OutOfRange(val.value.into())),
3117 MzTimestampOutOfRange(val) => {
3118 Ok(EvalError::MzTimestampOutOfRange(val.value.into()))
3119 }
3120 MzTimestampStepOverflow(()) => Ok(EvalError::MzTimestampStepOverflow),
3121 OidOutOfRange(val) => Ok(EvalError::OidOutOfRange(val.value.into())),
3122 IntervalOutOfRange(val) => Ok(EvalError::IntervalOutOfRange(val.value.into())),
3123 TimestampCannotBeNan(()) => Ok(EvalError::TimestampCannotBeNan),
3124 TimestampOutOfRange(()) => Ok(EvalError::TimestampOutOfRange),
3125 DateOutOfRange(()) => Ok(EvalError::DateOutOfRange),
3126 CharOutOfRange(()) => Ok(EvalError::CharOutOfRange),
3127 IndexOutOfRange(v) => Ok(EvalError::IndexOutOfRange {
3128 provided: v.provided,
3129 valid_end: v.valid_end,
3130 }),
3131 InvalidBase64Equals(()) => Ok(EvalError::InvalidBase64Equals),
3132 InvalidBase64Symbol(v) => char::from_proto(v).map(EvalError::InvalidBase64Symbol),
3133 InvalidBase64EndSequence(()) => Ok(EvalError::InvalidBase64EndSequence),
3134 InvalidTimezone(v) => Ok(EvalError::InvalidTimezone(v.into())),
3135 InvalidTimezoneInterval(()) => Ok(EvalError::InvalidTimezoneInterval),
3136 InvalidTimezoneConversion(()) => Ok(EvalError::InvalidTimezoneConversion),
3137 InvalidLayer(v) => Ok(EvalError::InvalidLayer {
3138 max_layer: usize::from_proto(v.max_layer)?,
3139 val: v.val,
3140 }),
3141 InvalidArray(error) => Ok(EvalError::InvalidArray(error.into_rust()?)),
3142 InvalidEncodingName(v) => Ok(EvalError::InvalidEncodingName(v.into())),
3143 InvalidHashAlgorithm(v) => Ok(EvalError::InvalidHashAlgorithm(v.into())),
3144 InvalidByteSequence(v) => Ok(EvalError::InvalidByteSequence {
3145 byte_sequence: v.byte_sequence.into(),
3146 encoding_name: v.encoding_name.into(),
3147 }),
3148 InvalidJsonbCast(v) => Ok(EvalError::InvalidJsonbCast {
3149 from: v.from.into(),
3150 to: v.to.into(),
3151 }),
3152 InvalidRegex(v) => Ok(EvalError::InvalidRegex(v.into())),
3153 InvalidRegexFlag(v) => Ok(EvalError::InvalidRegexFlag(char::from_proto(v)?)),
3154 InvalidParameterValue(v) => Ok(EvalError::InvalidParameterValue(v.into())),
3155 InvalidDatePart(part) => Ok(EvalError::InvalidDatePart(part.into())),
3156 KeyCannotBeNull(()) => Ok(EvalError::KeyCannotBeNull),
3157 NegSqrt(()) => Ok(EvalError::NegSqrt),
3158 NegLimit(()) => Ok(EvalError::NegLimit),
3159 NullCharacterNotPermitted(()) => Ok(EvalError::NullCharacterNotPermitted),
3160 UnknownUnits(v) => Ok(EvalError::UnknownUnits(v.into())),
3161 UnsupportedUnits(v) => {
3162 Ok(EvalError::UnsupportedUnits(v.units.into(), v.typ.into()))
3163 }
3164 UnterminatedLikeEscapeSequence(()) => Ok(EvalError::UnterminatedLikeEscapeSequence),
3165 Parse(error) => Ok(EvalError::Parse(error.into_rust()?)),
3166 ParseHex(error) => Ok(EvalError::ParseHex(error.into_rust()?)),
3167 Internal(v) => Ok(EvalError::Internal(v.into())),
3168 InfinityOutOfDomain(v) => Ok(EvalError::InfinityOutOfDomain(v.into())),
3169 NegativeOutOfDomain(v) => Ok(EvalError::NegativeOutOfDomain(v.into())),
3170 ZeroOutOfDomain(v) => Ok(EvalError::ZeroOutOfDomain(v.into())),
3171 OutOfDomain(v) => Ok(EvalError::OutOfDomain(
3172 v.lower.into_rust_if_some("ProtoDomainLimit::lower")?,
3173 v.upper.into_rust_if_some("ProtoDomainLimit::upper")?,
3174 v.id.into(),
3175 )),
3176 ComplexOutOfRange(v) => Ok(EvalError::ComplexOutOfRange(v.into())),
3177 MultipleRowsFromSubquery(()) => Ok(EvalError::MultipleRowsFromSubquery),
3178 Undefined(v) => Ok(EvalError::Undefined(v.into())),
3179 LikePatternTooLong(()) => Ok(EvalError::LikePatternTooLong),
3180 LikeEscapeTooLong(()) => Ok(EvalError::LikeEscapeTooLong),
3181 StringValueTooLong(v) => Ok(EvalError::StringValueTooLong {
3182 target_type: v.target_type.into(),
3183 length: usize::from_proto(v.length)?,
3184 }),
3185 MultidimensionalArrayRemovalNotSupported(()) => {
3186 Ok(EvalError::MultidimensionalArrayRemovalNotSupported)
3187 }
3188 IncompatibleArrayDimensions(v) => Ok(EvalError::IncompatibleArrayDimensions {
3189 dims: v.dims.into_rust()?,
3190 }),
3191 TypeFromOid(v) => Ok(EvalError::TypeFromOid(v.into())),
3192 InvalidRange(e) => Ok(EvalError::InvalidRange(e.into_rust()?)),
3193 InvalidRoleId(v) => Ok(EvalError::InvalidRoleId(v.into())),
3194 InvalidPrivileges(v) => Ok(EvalError::InvalidPrivileges(v.into())),
3195 WmrRecursionLimitExceeded(v) => Ok(EvalError::LetRecLimitExceeded(v.into())),
3196 MultiDimensionalArraySearch(()) => Ok(EvalError::MultiDimensionalArraySearch),
3197 MustNotBeNull(v) => Ok(EvalError::MustNotBeNull(v.into())),
3198 InvalidIdentifier(v) => Ok(EvalError::InvalidIdentifier {
3199 ident: v.ident.into(),
3200 detail: v.detail.into_rust()?,
3201 }),
3202 ArrayFillWrongArraySubscripts(()) => Ok(EvalError::ArrayFillWrongArraySubscripts),
3203 MaxArraySizeExceeded(max_size) => {
3204 Ok(EvalError::MaxArraySizeExceeded(usize::cast_from(max_size)))
3205 }
3206 DateDiffOverflow(v) => Ok(EvalError::DateDiffOverflow {
3207 unit: v.unit.into(),
3208 a: v.a.into(),
3209 b: v.b.into(),
3210 }),
3211 IfNullError(v) => Ok(EvalError::IfNullError(v.into())),
3212 LengthTooLarge(()) => Ok(EvalError::LengthTooLarge),
3213 AclArrayNullElement(()) => Ok(EvalError::AclArrayNullElement),
3214 MzAclArrayNullElement(()) => Ok(EvalError::MzAclArrayNullElement),
3215 InvalidIanaTimezoneId(s) => Ok(EvalError::InvalidIanaTimezoneId(s.into())),
3216 PrettyError(s) => Ok(EvalError::PrettyError(s.into())),
3217 },
3218 None => Err(TryFromProtoError::missing_field("ProtoEvalError::kind")),
3219 }
3220 }
3221}
3222
3223impl RustType<ProtoDims> for (usize, usize) {
3224 fn into_proto(&self) -> ProtoDims {
3225 ProtoDims {
3226 f0: self.0.into_proto(),
3227 f1: self.1.into_proto(),
3228 }
3229 }
3230
3231 fn from_proto(proto: ProtoDims) -> Result<Self, TryFromProtoError> {
3232 Ok((proto.f0.into_rust()?, proto.f1.into_rust()?))
3233 }
3234}
3235
3236#[cfg(test)]
3237mod tests {
3238 use super::*;
3239
3240 #[mz_ore::test]
3241 #[cfg_attr(miri, ignore)] fn test_reduce() {
3243 let relation_type = vec![
3244 SqlScalarType::Int64.nullable(true),
3245 SqlScalarType::Int64.nullable(true),
3246 SqlScalarType::Int64.nullable(false),
3247 ];
3248 let col = MirScalarExpr::column;
3249 let err = |e| MirScalarExpr::literal(Err(e), SqlScalarType::Int64);
3250 let lit = |i| MirScalarExpr::literal_ok(Datum::Int64(i), SqlScalarType::Int64);
3251 let null = || MirScalarExpr::literal_null(SqlScalarType::Int64);
3252
3253 struct TestCase {
3254 input: MirScalarExpr,
3255 output: MirScalarExpr,
3256 }
3257
3258 let test_cases = vec![
3259 TestCase {
3260 input: MirScalarExpr::CallVariadic {
3261 func: VariadicFunc::Coalesce,
3262 exprs: vec![lit(1)],
3263 },
3264 output: lit(1),
3265 },
3266 TestCase {
3267 input: MirScalarExpr::CallVariadic {
3268 func: VariadicFunc::Coalesce,
3269 exprs: vec![lit(1), lit(2)],
3270 },
3271 output: lit(1),
3272 },
3273 TestCase {
3274 input: MirScalarExpr::CallVariadic {
3275 func: VariadicFunc::Coalesce,
3276 exprs: vec![null(), lit(2), null()],
3277 },
3278 output: lit(2),
3279 },
3280 TestCase {
3281 input: MirScalarExpr::CallVariadic {
3282 func: VariadicFunc::Coalesce,
3283 exprs: vec![null(), col(0), null(), col(1), lit(2), lit(3)],
3284 },
3285 output: MirScalarExpr::CallVariadic {
3286 func: VariadicFunc::Coalesce,
3287 exprs: vec![col(0), col(1), lit(2)],
3288 },
3289 },
3290 TestCase {
3291 input: MirScalarExpr::CallVariadic {
3292 func: VariadicFunc::Coalesce,
3293 exprs: vec![col(0), col(2), col(1)],
3294 },
3295 output: MirScalarExpr::CallVariadic {
3296 func: VariadicFunc::Coalesce,
3297 exprs: vec![col(0), col(2)],
3298 },
3299 },
3300 TestCase {
3301 input: MirScalarExpr::CallVariadic {
3302 func: VariadicFunc::Coalesce,
3303 exprs: vec![lit(1), err(EvalError::DivisionByZero)],
3304 },
3305 output: lit(1),
3306 },
3307 TestCase {
3308 input: MirScalarExpr::CallVariadic {
3309 func: VariadicFunc::Coalesce,
3310 exprs: vec![
3311 null(),
3312 err(EvalError::DivisionByZero),
3313 err(EvalError::NumericFieldOverflow),
3314 ],
3315 },
3316 output: err(EvalError::DivisionByZero),
3317 },
3318 ];
3319
3320 for tc in test_cases {
3321 let mut actual = tc.input.clone();
3322 actual.reduce(&relation_type);
3323 assert!(
3324 actual == tc.output,
3325 "input: {}\nactual: {}\nexpected: {}",
3326 tc.input,
3327 actual,
3328 tc.output
3329 );
3330 }
3331 }
3332}