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::soft_assert_or_log;
21use mz_ore::stack::RecursionLimitError;
22use mz_ore::str::StrExt;
23use mz_ore::treat_as_equal::TreatAsEqual;
24use mz_ore::vec::swap_remove_multiple;
25use mz_pgrepr::TypeFromOidError;
26use mz_pgtz::timezone::TimezoneSpec;
27use mz_proto::{IntoRustIfSome, ProtoType, RustType, TryFromProtoError};
28use mz_repr::adt::array::InvalidArrayError;
29use mz_repr::adt::date::DateError;
30use mz_repr::adt::datetime::DateTimeUnits;
31use mz_repr::adt::range::InvalidRangeError;
32use mz_repr::adt::regex::{Regex, RegexCompilationError};
33use mz_repr::adt::timestamp::TimestampError;
34use mz_repr::strconv::{ParseError, ParseHexError};
35use mz_repr::{Datum, ReprColumnType, ReprScalarType, Row, RowArena, SqlColumnType, SqlScalarType};
36
37use proptest::prelude::*;
38use proptest_derive::Arbitrary;
39use serde::{Deserialize, Serialize};
40
41use crate::explain::{HumanizedExplain, HumanizerMode};
42use crate::scalar::func::format::DateTimeFormat;
43use crate::scalar::func::variadic::{
44 And, Coalesce, ListCreate, ListIndex, Or, RegexpMatch, RegexpReplace, RegexpSplitToArray,
45};
46use crate::scalar::func::{
47 BinaryFunc, UnaryFunc, UnmaterializableFunc, VariadicFunc, parse_timezone,
48 regexp_replace_parse_flags,
49};
50use crate::scalar::proto_eval_error::proto_incompatible_array_dimensions::ProtoDims;
51use crate::visit::{Visit, VisitChildren};
52
53pub mod func;
54pub mod like_pattern;
55
56include!(concat!(env!("OUT_DIR"), "/mz_expr.scalar.rs"));
57
58#[derive(
59 Clone,
60 PartialEq,
61 Eq,
62 PartialOrd,
63 Ord,
64 Hash,
65 Serialize,
66 Deserialize,
67 MzReflect
68)]
69pub enum MirScalarExpr {
70 Column(usize, TreatAsEqual<Option<Arc<str>>>),
72 Literal(Result<Row, EvalError>, ReprColumnType),
75 CallUnmaterializable(UnmaterializableFunc),
80 CallUnary {
82 func: UnaryFunc,
83 expr: Box<MirScalarExpr>,
84 },
85 CallBinary {
87 func: BinaryFunc,
88 expr1: Box<MirScalarExpr>,
89 expr2: Box<MirScalarExpr>,
90 },
91 CallVariadic {
93 func: VariadicFunc,
94 exprs: Vec<MirScalarExpr>,
95 },
96 If {
103 cond: Box<MirScalarExpr>,
104 then: Box<MirScalarExpr>,
105 els: Box<MirScalarExpr>,
106 },
107}
108
109impl std::fmt::Debug for MirScalarExpr {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 match self {
114 MirScalarExpr::Column(i, TreatAsEqual(Some(name))) => {
115 write!(f, "Column({i}, {name:?})")
116 }
117 MirScalarExpr::Column(i, TreatAsEqual(None)) => write!(f, "Column({i})"),
118 MirScalarExpr::Literal(lit, typ) => write!(f, "Literal({lit:?}, {typ:?})"),
119 MirScalarExpr::CallUnmaterializable(func) => {
120 write!(f, "CallUnmaterializable({func:?})")
121 }
122 MirScalarExpr::CallUnary { func, expr } => {
123 write!(f, "CallUnary({func:?}, {expr:?})")
124 }
125 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
126 write!(f, "CallBinary({func:?}, {expr1:?}, {expr2:?})")
127 }
128 MirScalarExpr::CallVariadic { func, exprs } => {
129 write!(f, "CallVariadic({func:?}, {exprs:?})")
130 }
131 MirScalarExpr::If { cond, then, els } => {
132 write!(f, "If({cond:?}, {then:?}, {els:?})")
133 }
134 }
135 }
136}
137
138impl MirScalarExpr {
139 pub fn columns(is: &[usize]) -> Vec<MirScalarExpr> {
140 is.iter().map(|i| MirScalarExpr::column(*i)).collect()
141 }
142
143 pub fn column(column: usize) -> Self {
144 MirScalarExpr::Column(column, TreatAsEqual(None))
145 }
146
147 pub fn named_column(column: usize, name: Arc<str>) -> Self {
148 MirScalarExpr::Column(column, TreatAsEqual(Some(name)))
149 }
150
151 pub fn literal(res: Result<Datum, EvalError>, typ: ReprScalarType) -> Self {
152 let typ = ReprColumnType {
153 scalar_type: typ,
154 nullable: matches!(res, Ok(Datum::Null)),
155 };
156 let row = res.map(|datum| Row::pack_slice(&[datum]));
157 MirScalarExpr::Literal(row, typ)
158 }
159
160 pub fn literal_ok(datum: Datum, typ: ReprScalarType) -> Self {
161 MirScalarExpr::literal(Ok(datum), typ)
162 }
163
164 pub fn literal_from_single_element_row(row: Row, typ: ReprScalarType) -> Self {
168 soft_assert_or_log!(
169 row.iter().count() == 1,
170 "literal_from_row called with a Row containing {} datums",
171 row.iter().count()
172 );
173 let nullable = row.unpack_first() == Datum::Null;
174 let typ = ReprColumnType {
175 scalar_type: typ,
176 nullable,
177 };
178 MirScalarExpr::Literal(Ok(row), typ)
179 }
180
181 pub fn literal_null(typ: ReprScalarType) -> Self {
182 MirScalarExpr::literal_ok(Datum::Null, typ)
183 }
184
185 pub fn literal_false() -> Self {
186 MirScalarExpr::literal_ok(Datum::False, ReprScalarType::Bool)
187 }
188
189 pub fn literal_true() -> Self {
190 MirScalarExpr::literal_ok(Datum::True, ReprScalarType::Bool)
191 }
192
193 pub fn call_unary<U: Into<UnaryFunc>>(self, func: U) -> Self {
194 MirScalarExpr::CallUnary {
195 func: func.into(),
196 expr: Box::new(self),
197 }
198 }
199
200 pub fn call_binary<B: Into<BinaryFunc>>(self, other: Self, func: B) -> Self {
201 MirScalarExpr::CallBinary {
202 func: func.into(),
203 expr1: Box::new(self),
204 expr2: Box::new(other),
205 }
206 }
207
208 pub fn call_variadic<V: Into<VariadicFunc>>(func: V, exprs: Vec<Self>) -> Self {
210 MirScalarExpr::CallVariadic {
211 func: func.into(),
212 exprs,
213 }
214 }
215
216 pub fn if_then_else(self, t: Self, f: Self) -> Self {
217 MirScalarExpr::If {
218 cond: Box::new(self),
219 then: Box::new(t),
220 els: Box::new(f),
221 }
222 }
223
224 pub fn or(self, other: Self) -> Self {
225 MirScalarExpr::call_variadic(Or, vec![self, other])
226 }
227
228 pub fn and(self, other: Self) -> Self {
229 MirScalarExpr::call_variadic(And, vec![self, other])
230 }
231
232 pub fn not(self) -> Self {
233 self.call_unary(UnaryFunc::Not(func::Not))
234 }
235
236 pub fn call_is_null(self) -> Self {
237 self.call_unary(UnaryFunc::IsNull(func::IsNull))
238 }
239
240 pub fn and_or_args(&self, func_to_match: VariadicFunc) -> Vec<MirScalarExpr> {
243 assert!(func_to_match == Or.into() || func_to_match == And.into());
244 match self {
245 MirScalarExpr::CallVariadic { func, exprs } if *func == func_to_match => exprs.clone(),
246 _ => vec![self.clone()],
247 }
248 }
249
250 pub fn expr_eq_literal(&self, expr: &MirScalarExpr) -> Option<(Row, bool)> {
261 if let MirScalarExpr::CallBinary {
262 func: BinaryFunc::Eq(_),
263 expr1,
264 expr2,
265 } = self
266 {
267 if expr1.is_literal_null() || expr2.is_literal_null() {
268 return None;
269 }
270 if let Some(Ok(lit)) = expr1.as_literal_owned() {
271 return Self::expr_eq_literal_inner(expr, lit, expr1, expr2);
272 }
273 if let Some(Ok(lit)) = expr2.as_literal_owned() {
274 return Self::expr_eq_literal_inner(expr, lit, expr2, expr1);
275 }
276 }
277 None
278 }
279
280 fn expr_eq_literal_inner(
281 expr_to_match: &MirScalarExpr,
282 literal: Row,
283 literal_expr: &MirScalarExpr,
284 other_side: &MirScalarExpr,
285 ) -> Option<(Row, bool)> {
286 if other_side == expr_to_match {
287 return Some((literal, false));
288 } else {
289 let (cast_removed, inv_cast_lit) =
291 Self::invert_casts_on_expr_eq_literal_inner(other_side, literal_expr);
292 if &cast_removed == expr_to_match {
293 if let Some(Ok(inv_cast_lit_row)) = inv_cast_lit.as_literal_owned() {
294 return Some((inv_cast_lit_row, true));
295 }
296 }
297 }
298 None
299 }
300
301 pub fn any_expr_eq_literal(&self) -> Option<MirScalarExpr> {
305 if let MirScalarExpr::CallBinary {
306 func: BinaryFunc::Eq(_),
307 expr1,
308 expr2,
309 } = self
310 {
311 if expr1.is_literal() {
312 let (expr, _literal) = Self::invert_casts_on_expr_eq_literal_inner(expr2, expr1);
313 return Some(expr);
314 }
315 if expr2.is_literal() {
316 let (expr, _literal) = Self::invert_casts_on_expr_eq_literal_inner(expr1, expr2);
317 return Some(expr);
318 }
319 }
320 None
321 }
322
323 pub fn invert_casts_on_expr_eq_literal(&self) -> MirScalarExpr {
328 if let MirScalarExpr::CallBinary {
329 func: BinaryFunc::Eq(_),
330 expr1,
331 expr2,
332 } = self
333 {
334 if expr1.is_literal() {
335 let (expr, literal) = Self::invert_casts_on_expr_eq_literal_inner(expr2, expr1);
336 return literal.call_binary(expr, func::Eq);
337 }
338 if expr2.is_literal() {
339 let (expr, literal) = Self::invert_casts_on_expr_eq_literal_inner(expr1, expr2);
340 return literal.call_binary(expr, func::Eq);
341 }
342 }
345 self.clone()
346 }
347
348 fn invert_casts_on_expr_eq_literal_inner(
360 expr: &MirScalarExpr,
361 literal: &MirScalarExpr,
362 ) -> (MirScalarExpr, MirScalarExpr) {
363 assert!(matches!(literal, MirScalarExpr::Literal(..)));
364
365 let temp_storage = &RowArena::new();
366 let eval = |e: &MirScalarExpr| {
367 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(&[]).scalar_type)
368 };
369
370 if let MirScalarExpr::CallUnary {
371 func,
372 expr: inner_expr,
373 } = expr
374 {
375 if let Some(inverse_func) = func.inverse() {
376 if func.preserves_uniqueness() && inverse_func.preserves_uniqueness() {
383 let lit_inv = eval(&MirScalarExpr::CallUnary {
384 func: inverse_func,
385 expr: Box::new(literal.clone()),
386 });
387 if !lit_inv.is_literal_err() {
390 return (*inner_expr.clone(), lit_inv);
391 }
392 }
393 }
394 }
395 (expr.clone(), literal.clone())
396 }
397
398 pub fn impossible_literal_equality_because_types(&self) -> bool {
404 if let MirScalarExpr::CallBinary {
405 func: BinaryFunc::Eq(_),
406 expr1,
407 expr2,
408 } = self
409 {
410 if expr1.is_literal() {
411 return Self::impossible_literal_equality_because_types_inner(expr1, expr2);
412 }
413 if expr2.is_literal() {
414 return Self::impossible_literal_equality_because_types_inner(expr2, expr1);
415 }
416 }
417 false
418 }
419
420 fn impossible_literal_equality_because_types_inner(
421 literal: &MirScalarExpr,
422 other_side: &MirScalarExpr,
423 ) -> bool {
424 assert!(matches!(literal, MirScalarExpr::Literal(..)));
425
426 let temp_storage = &RowArena::new();
427 let eval = |e: &MirScalarExpr| {
428 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(&[]).scalar_type)
429 };
430
431 if let MirScalarExpr::CallUnary { func, .. } = other_side {
432 if let Some(inverse_func) = func.inverse() {
433 if inverse_func.preserves_uniqueness()
434 && eval(&MirScalarExpr::CallUnary {
435 func: inverse_func,
436 expr: Box::new(literal.clone()),
437 })
438 .is_literal_err()
439 {
440 return true;
441 }
442 }
443 }
444
445 false
446 }
447
448 pub fn any_expr_ineq_literal(&self) -> bool {
458 match self {
459 MirScalarExpr::CallBinary {
460 func:
461 BinaryFunc::Lt(_) | BinaryFunc::Lte(_) | BinaryFunc::Gt(_) | BinaryFunc::Gte(_),
462 expr1,
463 expr2,
464 } => expr1.is_literal() || expr2.is_literal(),
465 _ => false,
466 }
467 }
468
469 pub fn permute(&mut self, permutation: &[usize]) {
475 self.visit_columns(|c| *c = permutation[*c]);
476 }
477
478 pub fn permute_map(&mut self, permutation: &BTreeMap<usize, usize>) {
484 self.visit_columns(|c| *c = permutation[c]);
485 }
486
487 pub fn visit_columns<F>(&mut self, mut action: F)
491 where
492 F: FnMut(&mut usize),
493 {
494 self.visit_pre_mut(|e| {
495 if let MirScalarExpr::Column(col, _) = e {
496 action(col);
497 }
498 });
499 }
500
501 pub fn support(&self) -> BTreeSet<usize> {
502 let mut support = BTreeSet::new();
503 self.support_into(&mut support);
504 support
505 }
506
507 pub fn support_into(&self, support: &mut BTreeSet<usize>) {
508 self.visit_pre(|e| {
509 if let MirScalarExpr::Column(i, _) = e {
510 support.insert(*i);
511 }
512 });
513 }
514
515 pub fn take(&mut self) -> Self {
516 mem::replace(self, MirScalarExpr::literal_null(ReprScalarType::String))
517 }
518
519 pub fn as_literal(&self) -> Option<Result<Datum<'_>, &EvalError>> {
522 if let MirScalarExpr::Literal(lit, _column_type) = self {
523 Some(lit.as_ref().map(|row| row.unpack_first()))
524 } else {
525 None
526 }
527 }
528
529 pub fn as_literal_non_error(&self) -> Option<Datum<'_>> {
532 self.as_literal().map(|eval_err| eval_err.ok()).flatten()
533 }
534
535 pub fn as_literal_owned(&self) -> Option<Result<Row, EvalError>> {
536 if let MirScalarExpr::Literal(lit, _column_type) = self {
537 Some(lit.clone())
538 } else {
539 None
540 }
541 }
542
543 pub fn as_literal_non_null_row(&self) -> Option<&Row> {
545 if let MirScalarExpr::Literal(Ok(row), _) = self {
546 if !row.unpack_first().is_null() {
547 return Some(row);
548 }
549 }
550 None
551 }
552
553 pub fn as_literal_str(&self) -> Option<&str> {
554 match self.as_literal() {
555 Some(Ok(Datum::String(s))) => Some(s),
556 _ => None,
557 }
558 }
559
560 pub fn as_literal_int64(&self) -> Option<i64> {
561 match self.as_literal() {
562 Some(Ok(Datum::Int64(i))) => Some(i),
563 _ => None,
564 }
565 }
566
567 pub fn as_literal_err(&self) -> Option<&EvalError> {
568 self.as_literal().and_then(|lit| lit.err())
569 }
570
571 pub fn is_literal(&self) -> bool {
572 matches!(self, MirScalarExpr::Literal(_, _))
573 }
574
575 pub fn is_literal_true(&self) -> bool {
576 Some(Ok(Datum::True)) == self.as_literal()
577 }
578
579 pub fn is_literal_false(&self) -> bool {
580 Some(Ok(Datum::False)) == self.as_literal()
581 }
582
583 pub fn is_literal_null(&self) -> bool {
584 Some(Ok(Datum::Null)) == self.as_literal()
585 }
586
587 pub fn is_literal_ok(&self) -> bool {
588 matches!(self, MirScalarExpr::Literal(Ok(_), _typ))
589 }
590
591 pub fn is_literal_err(&self) -> bool {
592 matches!(self, MirScalarExpr::Literal(Err(_), _typ))
593 }
594
595 pub fn is_column(&self) -> bool {
596 matches!(self, MirScalarExpr::Column(_col, _name))
597 }
598
599 pub fn is_error_if_null(&self) -> bool {
600 matches!(
601 self,
602 Self::CallVariadic {
603 func: VariadicFunc::ErrorIfNull(_),
604 ..
605 }
606 )
607 }
608
609 pub fn as_mut_temporal_filter(&mut self) -> Result<(&BinaryFunc, &mut MirScalarExpr), String> {
619 if !self.contains_temporal() {
620 return Err("Does not involve mz_now()".to_string());
621 }
622 if let MirScalarExpr::CallBinary { func, expr1, expr2 } = self {
624 if !expr1.contains_temporal()
626 && **expr2 == MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow)
627 {
628 std::mem::swap(expr1, expr2);
629 *func = match func {
630 BinaryFunc::Eq(_) => func::Eq.into(),
631 BinaryFunc::Lt(_) => func::Gt.into(),
632 BinaryFunc::Lte(_) => func::Gte.into(),
633 BinaryFunc::Gt(_) => func::Lt.into(),
634 BinaryFunc::Gte(_) => func::Lte.into(),
635 x => {
636 return Err(format!("Unsupported binary temporal operation: {:?}", x));
637 }
638 };
639 }
640
641 if expr2.contains_temporal()
643 || **expr1 != MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow)
644 {
645 let mode = HumanizedExplain::new(false); let bad_expr = MirScalarExpr::CallBinary {
647 func: func.clone(),
648 expr1: expr1.clone(),
649 expr2: expr2.clone(),
650 };
651 return Err(format!(
652 "Unsupported temporal predicate. Note: `mz_now()` must be directly compared to a mz_timestamp-castable expression. Expression found: {}",
653 mode.expr(&bad_expr, None),
654 ));
655 }
656
657 Ok((&*func, expr2))
658 } else {
659 let mode = HumanizedExplain::new(false); Err(format!(
661 "Unsupported temporal predicate. Note: `mz_now()` must be directly compared to a non-temporal expression of mz_timestamp-castable type. Expression found: {}",
662 mode.expr(self, None),
663 ))
664 }
665 }
666
667 #[deprecated = "Use `might_error` instead"]
668 pub fn contains_error_if_null(&self) -> bool {
669 let mut worklist = vec![self];
670 while let Some(expr) = worklist.pop() {
671 if expr.is_error_if_null() {
672 return true;
673 }
674 worklist.extend(expr.children());
675 }
676 false
677 }
678
679 pub fn contains_err(&self) -> bool {
680 let mut worklist = vec![self];
681 while let Some(expr) = worklist.pop() {
682 if expr.is_literal_err() {
683 return true;
684 }
685 worklist.extend(expr.children());
686 }
687 false
688 }
689
690 pub fn might_error(&self) -> bool {
696 let mut worklist = vec![self];
697 while let Some(expr) = worklist.pop() {
698 if expr.is_literal_err() || expr.is_error_if_null() {
699 return true;
700 }
701 worklist.extend(expr.children());
702 }
703 false
704 }
705
706 pub fn as_column(&self) -> Option<usize> {
708 if let MirScalarExpr::Column(c, _) = self {
709 Some(*c)
710 } else {
711 None
712 }
713 }
714
715 pub fn reduce(&mut self, column_types: &[ReprColumnType]) {
748 let temp_storage = &RowArena::new();
749 let eval = |e: &MirScalarExpr| {
750 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(column_types).scalar_type)
751 };
752
753 let mut old_self = MirScalarExpr::column(0);
755 while old_self != *self {
756 old_self = self.clone();
757 #[allow(deprecated)]
758 self.visit_mut_pre_post_nolimit(
759 &mut |e| {
760 match e {
761 MirScalarExpr::CallUnary { func, expr } => {
762 if *func == UnaryFunc::IsNull(func::IsNull) {
763 if !expr.typ(column_types).nullable {
764 *e = MirScalarExpr::literal_false();
765 } else {
766 if let Some(expr) = expr.decompose_is_null() {
769 *e = expr
770 }
771 }
772 } else if *func == UnaryFunc::Not(func::Not) {
773 match &mut **expr {
775 MirScalarExpr::CallUnary {
777 expr: inner_expr,
778 func: UnaryFunc::Not(func::Not),
779 } => *e = inner_expr.take(),
780 MirScalarExpr::CallBinary { expr1, expr2, func } => {
783 if let Some(negated_func) = func.negate() {
784 *e = MirScalarExpr::CallBinary {
785 expr1: Box::new(expr1.take()),
786 expr2: Box::new(expr2.take()),
787 func: negated_func,
788 }
789 }
790 }
791 MirScalarExpr::CallVariadic { .. } => {
792 e.demorgans();
793 }
794 _ => {}
795 }
796 }
797 }
798 _ => {}
799 };
800 None
801 },
802 &mut |e| match e {
803 MirScalarExpr::Column(_, _)
805 | MirScalarExpr::Literal(_, _)
806 | MirScalarExpr::CallUnmaterializable(_) => (),
807 MirScalarExpr::CallUnary { func, expr } => {
808 if expr.is_literal() && *func != UnaryFunc::Panic(func::Panic) {
809 *e = eval(e);
810 } else if let UnaryFunc::RecordGet(func::RecordGet(i)) = *func {
811 if let MirScalarExpr::CallVariadic {
812 func: VariadicFunc::RecordCreate(..),
813 exprs,
814 } = &mut **expr
815 {
816 *e = exprs.swap_remove(i);
817 }
818 }
819 }
820 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
821 if expr1.is_literal() && expr2.is_literal() {
822 *e = eval(e);
823 } else if (expr1.is_literal_null() || expr2.is_literal_null())
824 && func.propagates_nulls()
825 {
826 *e = MirScalarExpr::literal_null(e.typ(column_types).scalar_type);
827 } else if let Some(err) = expr1.as_literal_err() {
828 *e = MirScalarExpr::literal(
829 Err(err.clone()),
830 e.typ(column_types).scalar_type,
831 );
832 } else if let Some(err) = expr2.as_literal_err() {
833 *e = MirScalarExpr::literal(
834 Err(err.clone()),
835 e.typ(column_types).scalar_type,
836 );
837 } else if let BinaryFunc::IsLikeMatchCaseInsensitive(_) = func {
838 if expr2.is_literal() {
839 let pattern = expr2.as_literal_str().unwrap();
841 *e = match like_pattern::compile(pattern, true) {
842 Ok(matcher) => expr1.take().call_unary(UnaryFunc::IsLikeMatch(
843 func::IsLikeMatch(matcher),
844 )),
845 Err(err) => MirScalarExpr::literal(
846 Err(err),
847 e.typ(column_types).scalar_type,
848 ),
849 };
850 }
851 } else if let BinaryFunc::IsLikeMatchCaseSensitive(_) = func {
852 if expr2.is_literal() {
853 let pattern = expr2.as_literal_str().unwrap();
855 *e = match like_pattern::compile(pattern, false) {
856 Ok(matcher) => expr1.take().call_unary(UnaryFunc::IsLikeMatch(
857 func::IsLikeMatch(matcher),
858 )),
859 Err(err) => MirScalarExpr::literal(
860 Err(err),
861 e.typ(column_types).scalar_type,
862 ),
863 };
864 }
865 } else if matches!(
866 func,
867 BinaryFunc::IsRegexpMatchCaseSensitive(_)
868 | BinaryFunc::IsRegexpMatchCaseInsensitive(_)
869 ) {
870 let case_insensitive =
871 matches!(func, BinaryFunc::IsRegexpMatchCaseInsensitive(_));
872 if let MirScalarExpr::Literal(Ok(row), _) = &**expr2 {
873 *e = match Regex::new(
874 row.unpack_first().unwrap_str(),
875 case_insensitive,
876 ) {
877 Ok(regex) => expr1.take().call_unary(UnaryFunc::IsRegexpMatch(
878 func::IsRegexpMatch(regex),
879 )),
880 Err(err) => MirScalarExpr::literal(
881 Err(err.into()),
882 e.typ(column_types).scalar_type,
883 ),
884 };
885 }
886 } else if let BinaryFunc::ExtractInterval(_) = *func
887 && expr1.is_literal()
888 {
889 let units = expr1.as_literal_str().unwrap();
890 *e = match units.parse::<DateTimeUnits>() {
891 Ok(units) => MirScalarExpr::CallUnary {
892 func: UnaryFunc::ExtractInterval(func::ExtractInterval(units)),
893 expr: Box::new(expr2.take()),
894 },
895 Err(_) => MirScalarExpr::literal(
896 Err(EvalError::UnknownUnits(units.into())),
897 e.typ(column_types).scalar_type,
898 ),
899 }
900 } else if let BinaryFunc::ExtractTime(_) = *func
901 && expr1.is_literal()
902 {
903 let units = expr1.as_literal_str().unwrap();
904 *e = match units.parse::<DateTimeUnits>() {
905 Ok(units) => MirScalarExpr::CallUnary {
906 func: UnaryFunc::ExtractTime(func::ExtractTime(units)),
907 expr: Box::new(expr2.take()),
908 },
909 Err(_) => MirScalarExpr::literal(
910 Err(EvalError::UnknownUnits(units.into())),
911 e.typ(column_types).scalar_type,
912 ),
913 }
914 } else if let BinaryFunc::ExtractTimestamp(_) = *func
915 && expr1.is_literal()
916 {
917 let units = expr1.as_literal_str().unwrap();
918 *e = match units.parse::<DateTimeUnits>() {
919 Ok(units) => MirScalarExpr::CallUnary {
920 func: UnaryFunc::ExtractTimestamp(func::ExtractTimestamp(
921 units,
922 )),
923 expr: Box::new(expr2.take()),
924 },
925 Err(_) => MirScalarExpr::literal(
926 Err(EvalError::UnknownUnits(units.into())),
927 e.typ(column_types).scalar_type,
928 ),
929 }
930 } else if let BinaryFunc::ExtractTimestampTz(_) = *func
931 && expr1.is_literal()
932 {
933 let units = expr1.as_literal_str().unwrap();
934 *e = match units.parse::<DateTimeUnits>() {
935 Ok(units) => MirScalarExpr::CallUnary {
936 func: UnaryFunc::ExtractTimestampTz(func::ExtractTimestampTz(
937 units,
938 )),
939 expr: Box::new(expr2.take()),
940 },
941 Err(_) => MirScalarExpr::literal(
942 Err(EvalError::UnknownUnits(units.into())),
943 e.typ(column_types).scalar_type,
944 ),
945 }
946 } else if let BinaryFunc::ExtractDate(_) = *func
947 && expr1.is_literal()
948 {
949 let units = expr1.as_literal_str().unwrap();
950 *e = match units.parse::<DateTimeUnits>() {
951 Ok(units) => MirScalarExpr::CallUnary {
952 func: UnaryFunc::ExtractDate(func::ExtractDate(units)),
953 expr: Box::new(expr2.take()),
954 },
955 Err(_) => MirScalarExpr::literal(
956 Err(EvalError::UnknownUnits(units.into())),
957 e.typ(column_types).scalar_type,
958 ),
959 }
960 } else if let BinaryFunc::DatePartInterval(_) = *func
961 && expr1.is_literal()
962 {
963 let units = expr1.as_literal_str().unwrap();
964 *e = match units.parse::<DateTimeUnits>() {
965 Ok(units) => MirScalarExpr::CallUnary {
966 func: UnaryFunc::DatePartInterval(func::DatePartInterval(
967 units,
968 )),
969 expr: Box::new(expr2.take()),
970 },
971 Err(_) => MirScalarExpr::literal(
972 Err(EvalError::UnknownUnits(units.into())),
973 e.typ(column_types).scalar_type,
974 ),
975 }
976 } else if let BinaryFunc::DatePartTime(_) = *func
977 && expr1.is_literal()
978 {
979 let units = expr1.as_literal_str().unwrap();
980 *e = match units.parse::<DateTimeUnits>() {
981 Ok(units) => MirScalarExpr::CallUnary {
982 func: UnaryFunc::DatePartTime(func::DatePartTime(units)),
983 expr: Box::new(expr2.take()),
984 },
985 Err(_) => MirScalarExpr::literal(
986 Err(EvalError::UnknownUnits(units.into())),
987 e.typ(column_types).scalar_type,
988 ),
989 }
990 } else if let BinaryFunc::DatePartTimestamp(_) = *func
991 && expr1.is_literal()
992 {
993 let units = expr1.as_literal_str().unwrap();
994 *e = match units.parse::<DateTimeUnits>() {
995 Ok(units) => MirScalarExpr::CallUnary {
996 func: UnaryFunc::DatePartTimestamp(func::DatePartTimestamp(
997 units,
998 )),
999 expr: Box::new(expr2.take()),
1000 },
1001 Err(_) => MirScalarExpr::literal(
1002 Err(EvalError::UnknownUnits(units.into())),
1003 e.typ(column_types).scalar_type,
1004 ),
1005 }
1006 } else if let BinaryFunc::DatePartTimestampTz(_) = *func
1007 && expr1.is_literal()
1008 {
1009 let units = expr1.as_literal_str().unwrap();
1010 *e = match units.parse::<DateTimeUnits>() {
1011 Ok(units) => MirScalarExpr::CallUnary {
1012 func: UnaryFunc::DatePartTimestampTz(
1013 func::DatePartTimestampTz(units),
1014 ),
1015 expr: Box::new(expr2.take()),
1016 },
1017 Err(_) => MirScalarExpr::literal(
1018 Err(EvalError::UnknownUnits(units.into())),
1019 e.typ(column_types).scalar_type,
1020 ),
1021 }
1022 } else if let BinaryFunc::DateTruncTimestamp(_) = *func
1023 && expr1.is_literal()
1024 {
1025 let units = expr1.as_literal_str().unwrap();
1026 *e = match units.parse::<DateTimeUnits>() {
1027 Ok(units) => MirScalarExpr::CallUnary {
1028 func: UnaryFunc::DateTruncTimestamp(func::DateTruncTimestamp(
1029 units,
1030 )),
1031 expr: Box::new(expr2.take()),
1032 },
1033 Err(_) => MirScalarExpr::literal(
1034 Err(EvalError::UnknownUnits(units.into())),
1035 e.typ(column_types).scalar_type,
1036 ),
1037 }
1038 } else if let BinaryFunc::DateTruncTimestampTz(_) = *func
1039 && expr1.is_literal()
1040 {
1041 let units = expr1.as_literal_str().unwrap();
1042 *e = match units.parse::<DateTimeUnits>() {
1043 Ok(units) => MirScalarExpr::CallUnary {
1044 func: UnaryFunc::DateTruncTimestampTz(
1045 func::DateTruncTimestampTz(units),
1046 ),
1047 expr: Box::new(expr2.take()),
1048 },
1049 Err(_) => MirScalarExpr::literal(
1050 Err(EvalError::UnknownUnits(units.into())),
1051 e.typ(column_types).scalar_type,
1052 ),
1053 }
1054 } else if matches!(func, BinaryFunc::TimezoneTimestampBinary(_))
1055 && expr1.is_literal()
1056 {
1057 let tz = expr1.as_literal_str().unwrap();
1061 *e = match parse_timezone(tz, TimezoneSpec::Posix) {
1062 Ok(tz) => MirScalarExpr::CallUnary {
1063 func: UnaryFunc::TimezoneTimestamp(func::TimezoneTimestamp(tz)),
1064 expr: Box::new(expr2.take()),
1065 },
1066 Err(err) => MirScalarExpr::literal(
1067 Err(err),
1068 e.typ(column_types).scalar_type,
1069 ),
1070 }
1071 } else if matches!(func, BinaryFunc::TimezoneTimestampTzBinary(_))
1072 && expr1.is_literal()
1073 {
1074 let tz = expr1.as_literal_str().unwrap();
1075 *e = match parse_timezone(tz, TimezoneSpec::Posix) {
1076 Ok(tz) => MirScalarExpr::CallUnary {
1077 func: UnaryFunc::TimezoneTimestampTz(
1078 func::TimezoneTimestampTz(tz),
1079 ),
1080 expr: Box::new(expr2.take()),
1081 },
1082 Err(err) => MirScalarExpr::literal(
1083 Err(err),
1084 e.typ(column_types).scalar_type,
1085 ),
1086 }
1087 } else if let BinaryFunc::ToCharTimestamp(_) = *func
1088 && expr2.is_literal()
1089 {
1090 let format_str = expr2.as_literal_str().unwrap();
1091 *e = MirScalarExpr::CallUnary {
1092 func: UnaryFunc::ToCharTimestamp(func::ToCharTimestamp {
1093 format_string: format_str.to_string(),
1094 format: DateTimeFormat::compile(format_str),
1095 }),
1096 expr: Box::new(expr1.take()),
1097 };
1098 } else if let BinaryFunc::ToCharTimestampTz(_) = *func
1099 && expr2.is_literal()
1100 {
1101 let format_str = expr2.as_literal_str().unwrap();
1102 *e = MirScalarExpr::CallUnary {
1103 func: UnaryFunc::ToCharTimestampTz(func::ToCharTimestampTz {
1104 format_string: format_str.to_string(),
1105 format: DateTimeFormat::compile(format_str),
1106 }),
1107 expr: Box::new(expr1.take()),
1108 };
1109 } else if matches!(*func, BinaryFunc::Eq(_) | BinaryFunc::NotEq(_))
1110 && expr2 < expr1
1111 {
1112 mem::swap(expr1, expr2);
1116 } else if let (
1117 BinaryFunc::Eq(_),
1118 MirScalarExpr::Literal(
1119 Ok(lit_row),
1120 ReprColumnType {
1121 scalar_type:
1122 ReprScalarType::Record {
1123 fields: field_types,
1124 ..
1125 },
1126 ..
1127 },
1128 ),
1129 MirScalarExpr::CallVariadic {
1130 func: VariadicFunc::RecordCreate(..),
1131 exprs: rec_create_args,
1132 },
1133 ) = (&*func, &**expr1, &**expr2)
1134 {
1135 match lit_row.unpack_first() {
1144 Datum::List(datum_list) => {
1145 *e = MirScalarExpr::call_variadic(
1146 And,
1147 datum_list
1148 .iter()
1149 .zip_eq(field_types)
1150 .zip_eq(rec_create_args)
1151 .map(|((d, typ), a)| {
1152 MirScalarExpr::literal_ok(
1153 d,
1154 typ.scalar_type.clone(),
1155 )
1156 .call_binary(a.clone(), func::Eq)
1157 })
1158 .collect(),
1159 );
1160 }
1161 _ => {}
1162 }
1163 } else if let (
1164 BinaryFunc::Eq(_),
1165 MirScalarExpr::CallVariadic {
1166 func: VariadicFunc::RecordCreate(..),
1167 exprs: rec_create_args1,
1168 },
1169 MirScalarExpr::CallVariadic {
1170 func: VariadicFunc::RecordCreate(..),
1171 exprs: rec_create_args2,
1172 },
1173 ) = (&*func, &**expr1, &**expr2)
1174 {
1175 *e = MirScalarExpr::call_variadic(
1187 And,
1188 rec_create_args1
1189 .into_iter()
1190 .zip_eq(rec_create_args2)
1191 .map(|(a, b)| a.clone().call_binary(b.clone(), func::Eq))
1192 .collect(),
1193 )
1194 }
1195 }
1196 MirScalarExpr::CallVariadic { .. } => {
1197 e.flatten_associative();
1198 let (func, exprs) = match e {
1199 MirScalarExpr::CallVariadic { func, exprs } => (func, exprs),
1200 _ => unreachable!("`flatten_associative` shouldn't change node type"),
1201 };
1202 if *func == Coalesce.into() {
1203 if exprs.iter().all(|expr| expr.is_literal_null()) {
1207 *e = MirScalarExpr::literal_null(e.typ(column_types).scalar_type);
1208 return;
1209 }
1210
1211 exprs.retain(|e| !e.is_literal_null());
1213
1214 if let Some(i) = exprs
1219 .iter()
1220 .position(|e| e.is_literal() || !e.typ(column_types).nullable)
1221 {
1222 exprs.truncate(i + 1);
1223 }
1224
1225 let mut prior_exprs = BTreeSet::new();
1227 exprs.retain(|e| prior_exprs.insert(e.clone()));
1228
1229 if exprs.len() == 1 {
1230 *e = exprs[0].take();
1232 }
1233 } else if exprs.iter().all(|e| e.is_literal()) {
1234 *e = eval(e);
1235 } else if func.propagates_nulls()
1236 && exprs.iter().any(|e| e.is_literal_null())
1237 {
1238 *e = MirScalarExpr::literal_null(e.typ(column_types).scalar_type);
1239 } else if let Some(err) = exprs.iter().find_map(|e| e.as_literal_err()) {
1240 *e = MirScalarExpr::literal(
1241 Err(err.clone()),
1242 e.typ(column_types).scalar_type,
1243 );
1244 } else if *func == RegexpMatch.into()
1245 && exprs[1].is_literal()
1246 && exprs.get(2).map_or(true, |e| e.is_literal())
1247 {
1248 let needle = exprs[1].as_literal_str().unwrap();
1249 let flags = match exprs.len() {
1250 3 => exprs[2].as_literal_str().unwrap(),
1251 _ => "",
1252 };
1253 *e = match func::build_regex(needle, flags) {
1254 Ok(regex) => mem::take(exprs)
1255 .into_first()
1256 .call_unary(UnaryFunc::RegexpMatch(func::RegexpMatch(regex))),
1257 Err(err) => MirScalarExpr::literal(
1258 Err(err),
1259 e.typ(column_types).scalar_type,
1260 ),
1261 };
1262 } else if *func == RegexpReplace.into()
1263 && exprs[1].is_literal()
1264 && exprs.get(3).map_or(true, |e| e.is_literal())
1265 {
1266 let pattern = exprs[1].as_literal_str().unwrap();
1267 let flags = exprs
1268 .get(3)
1269 .map_or("", |expr| expr.as_literal_str().unwrap());
1270 let (limit, flags) = regexp_replace_parse_flags(flags);
1271
1272 *e = match func::build_regex(pattern, &flags) {
1278 Ok(regex) => {
1279 let mut exprs = mem::take(exprs);
1280 let replacement = exprs.swap_remove(2);
1281 let source = exprs.swap_remove(0);
1282 source.call_binary(
1283 replacement,
1284 BinaryFunc::from(func::RegexpReplace { regex, limit }),
1285 )
1286 }
1287 Err(err) => {
1288 let mut exprs = mem::take(exprs);
1289 let source = exprs.swap_remove(0);
1290 let scalar_type = e.typ(column_types).scalar_type;
1291 source.call_is_null().if_then_else(
1293 MirScalarExpr::literal_null(scalar_type.clone()),
1294 MirScalarExpr::literal(Err(err), scalar_type),
1295 )
1296 }
1297 };
1298 } else if *func == RegexpSplitToArray.into()
1299 && exprs[1].is_literal()
1300 && exprs.get(2).map_or(true, |e| e.is_literal())
1301 {
1302 let needle = exprs[1].as_literal_str().unwrap();
1303 let flags = match exprs.len() {
1304 3 => exprs[2].as_literal_str().unwrap(),
1305 _ => "",
1306 };
1307 *e = match func::build_regex(needle, flags) {
1308 Ok(regex) => mem::take(exprs).into_first().call_unary(
1309 UnaryFunc::RegexpSplitToArray(func::RegexpSplitToArray(regex)),
1310 ),
1311 Err(err) => MirScalarExpr::literal(
1312 Err(err),
1313 e.typ(column_types).scalar_type,
1314 ),
1315 };
1316 } else if *func == ListIndex.into() && is_list_create_call(&exprs[0]) {
1317 let ind_exprs = exprs.split_off(1);
1320 let top_list_create = exprs.swap_remove(0);
1321 *e = reduce_list_create_list_index_literal(top_list_create, ind_exprs);
1322 } else if *func == Or.into() || *func == And.into() {
1323 e.undistribute_and_or();
1325 e.reduce_and_canonicalize_and_or();
1326 } else if let VariadicFunc::TimezoneTimeVariadic(_) = func {
1327 if exprs[0].is_literal() && exprs[2].is_literal_ok() {
1328 let tz = exprs[0].as_literal_str().unwrap();
1329 *e = match parse_timezone(tz, TimezoneSpec::Posix) {
1330 Ok(tz) => MirScalarExpr::CallUnary {
1331 func: UnaryFunc::TimezoneTime(func::TimezoneTime {
1332 tz,
1333 wall_time: exprs[2]
1334 .as_literal()
1335 .unwrap()
1336 .unwrap()
1337 .unwrap_timestamptz()
1338 .naive_utc(),
1339 }),
1340 expr: Box::new(exprs[1].take()),
1341 },
1342 Err(err) => MirScalarExpr::literal(
1343 Err(err),
1344 e.typ(column_types).scalar_type,
1345 ),
1346 }
1347 }
1348 }
1349 }
1350 MirScalarExpr::If { cond, then, els } => {
1351 if let Some(literal) = cond.as_literal() {
1352 match literal {
1353 Ok(Datum::True) => *e = then.take(),
1354 Ok(Datum::False) | Ok(Datum::Null) => *e = els.take(),
1355 Err(err) => {
1356 *e = MirScalarExpr::Literal(
1357 Err(err.clone()),
1358 then.typ(column_types)
1359 .union(&els.typ(column_types))
1360 .unwrap(),
1361 )
1362 }
1363 _ => unreachable!(),
1364 }
1365 } else if then == els {
1366 *e = then.take();
1367 } else if then.is_literal_ok()
1368 && els.is_literal_ok()
1369 && then.typ(column_types).scalar_type == ReprScalarType::Bool
1370 && els.typ(column_types).scalar_type == ReprScalarType::Bool
1371 {
1372 match (then.as_literal(), els.as_literal()) {
1373 (Some(Ok(Datum::True)), _) => {
1376 *e = cond
1379 .clone()
1380 .call_is_null()
1381 .not()
1382 .and(cond.take())
1383 .or(els.take());
1384 }
1385 (Some(Ok(Datum::False)), _) => {
1386 *e = cond
1389 .clone()
1390 .not()
1391 .or(cond.take().call_is_null())
1392 .and(els.take());
1393 }
1394 (_, Some(Ok(Datum::True))) => {
1395 *e = cond
1398 .clone()
1399 .not()
1400 .or(cond.take().call_is_null())
1401 .or(then.take());
1402 }
1403 (_, Some(Ok(Datum::False))) => {
1404 *e = cond
1407 .clone()
1408 .call_is_null()
1409 .not()
1410 .and(cond.take())
1411 .and(then.take());
1412 }
1413 _ => {}
1414 }
1415 } else {
1416 match (&mut **then, &mut **els) {
1428 (
1429 MirScalarExpr::CallUnary { func: f1, expr: e1 },
1430 MirScalarExpr::CallUnary { func: f2, expr: e2 },
1431 ) if f1 == f2 && e1.typ(column_types) == e2.typ(column_types) => {
1432 *e = cond
1433 .take()
1434 .if_then_else(e1.take(), e2.take())
1435 .call_unary(f1.clone());
1436 }
1437 (
1438 MirScalarExpr::CallBinary {
1439 func: f1,
1440 expr1: e1a,
1441 expr2: e2a,
1442 },
1443 MirScalarExpr::CallBinary {
1444 func: f2,
1445 expr1: e1b,
1446 expr2: e2b,
1447 },
1448 ) if f1 == f2
1449 && e1a == e1b
1450 && e2a.typ(column_types) == e2b.typ(column_types) =>
1451 {
1452 *e = e1a.take().call_binary(
1453 cond.take().if_then_else(e2a.take(), e2b.take()),
1454 f1.clone(),
1455 );
1456 }
1457 (
1458 MirScalarExpr::CallBinary {
1459 func: f1,
1460 expr1: e1a,
1461 expr2: e2a,
1462 },
1463 MirScalarExpr::CallBinary {
1464 func: f2,
1465 expr1: e1b,
1466 expr2: e2b,
1467 },
1468 ) if f1 == f2
1469 && e2a == e2b
1470 && e1a.typ(column_types) == e1b.typ(column_types) =>
1471 {
1472 *e = cond
1473 .take()
1474 .if_then_else(e1a.take(), e1b.take())
1475 .call_binary(e2a.take(), f1.clone());
1476 }
1477 _ => {}
1478 }
1479 }
1480 }
1481 },
1482 );
1483 }
1484
1485 fn list_create_type(list_create: &MirScalarExpr) -> ReprScalarType {
1488 if let MirScalarExpr::CallVariadic {
1489 func: VariadicFunc::ListCreate(ListCreate { elem_type: typ }),
1490 ..
1491 } = list_create
1492 {
1493 ReprScalarType::from(typ)
1494 } else {
1495 unreachable!()
1496 }
1497 }
1498
1499 fn is_list_create_call(expr: &MirScalarExpr) -> bool {
1500 matches!(
1501 expr,
1502 MirScalarExpr::CallVariadic {
1503 func: VariadicFunc::ListCreate(..),
1504 ..
1505 }
1506 )
1507 }
1508
1509 fn reduce_list_create_list_index_literal(
1524 mut list_create_to_reduce: MirScalarExpr,
1525 mut index_exprs: Vec<MirScalarExpr>,
1526 ) -> MirScalarExpr {
1527 let mut list_create_mut_refs = vec![&mut list_create_to_reduce];
1539 let mut earlier_list_create_types: Vec<&mut SqlScalarType> = vec![];
1540 let mut i = 0;
1541 while i < index_exprs.len()
1542 && list_create_mut_refs
1543 .iter()
1544 .all(|lc| is_list_create_call(lc))
1545 {
1546 if index_exprs[i].is_literal_ok() {
1547 let removed_index = index_exprs.remove(i);
1549 let index_i64 = match removed_index.as_literal().unwrap().unwrap() {
1550 Datum::Int64(sql_index_i64) => sql_index_i64 - 1,
1551 _ => unreachable!(), };
1553 for list_create in &mut list_create_mut_refs {
1556 let list_create_args = match list_create {
1557 MirScalarExpr::CallVariadic {
1558 func: VariadicFunc::ListCreate(ListCreate { elem_type: _ }),
1559 exprs,
1560 } => exprs,
1561 _ => unreachable!(), };
1563 if index_i64 >= 0 && index_i64 < list_create_args.len().try_into().unwrap()
1565 {
1566 let index: usize = index_i64.try_into().unwrap();
1567 **list_create = list_create_args.swap_remove(index);
1568 } else {
1569 let typ = list_create_type(list_create);
1570 **list_create = MirScalarExpr::literal_null(typ);
1571 }
1572 }
1573 for t in earlier_list_create_types.iter_mut() {
1575 if let SqlScalarType::List {
1576 element_type,
1577 custom_id: _,
1578 } = t
1579 {
1580 **t = *element_type.clone();
1581 let mut u = &mut **t;
1584 while let SqlScalarType::List {
1585 element_type,
1586 custom_id,
1587 } = u
1588 {
1589 *custom_id = None;
1590 u = &mut **element_type;
1591 }
1592 } else {
1593 unreachable!("already matched below");
1594 }
1595 }
1596 } else {
1597 list_create_mut_refs = list_create_mut_refs
1601 .into_iter()
1602 .flat_map(|list_create| match list_create {
1603 MirScalarExpr::CallVariadic {
1604 func: VariadicFunc::ListCreate(ListCreate { elem_type }),
1605 exprs: list_create_args,
1606 } => {
1607 earlier_list_create_types.push(elem_type);
1608 list_create_args
1609 }
1610 _ => unreachable!(),
1612 })
1613 .collect();
1614 i += 1; }
1616 }
1617 if index_exprs.is_empty() {
1620 assert_eq!(list_create_mut_refs.len(), 1);
1621 list_create_to_reduce
1622 } else {
1623 MirScalarExpr::call_variadic(
1624 ListIndex,
1625 std::iter::once(list_create_to_reduce)
1626 .chain(index_exprs)
1627 .collect(),
1628 )
1629 }
1630 }
1631
1632 }
1634
1635 fn decompose_is_null(&mut self) -> Option<MirScalarExpr> {
1643 match self {
1646 MirScalarExpr::CallUnary {
1647 func,
1648 expr: inner_expr,
1649 } => {
1650 if !func.introduces_nulls() {
1651 if func.propagates_nulls() {
1652 *self = inner_expr.take();
1653 return self.decompose_is_null();
1654 } else {
1655 return Some(MirScalarExpr::literal_false());
1674 }
1675 }
1676 }
1677 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1678 if func.propagates_nulls() && !func.introduces_nulls() {
1681 let expr1 = expr1.take().call_is_null();
1682 let expr2 = expr2.take().call_is_null();
1683 return Some(expr1.or(expr2));
1684 }
1685 }
1686 MirScalarExpr::CallVariadic { func, exprs } => {
1687 if func.propagates_nulls() && !func.introduces_nulls() {
1688 let exprs = exprs.into_iter().map(|e| e.take().call_is_null()).collect();
1689 return Some(MirScalarExpr::call_variadic(Or, exprs));
1690 }
1691 }
1692 _ => {}
1693 }
1694
1695 None
1696 }
1697
1698 pub fn flatten_associative(&mut self) {
1701 match self {
1702 MirScalarExpr::CallVariadic {
1703 exprs: outer_operands,
1704 func: outer_func,
1705 } if outer_func.is_associative() => {
1706 *outer_operands = outer_operands
1707 .into_iter()
1708 .flat_map(|o| {
1709 if let MirScalarExpr::CallVariadic {
1710 exprs: inner_operands,
1711 func: inner_func,
1712 } = o
1713 {
1714 if *inner_func == *outer_func {
1715 mem::take(inner_operands)
1716 } else {
1717 vec![o.take()]
1718 }
1719 } else {
1720 vec![o.take()]
1721 }
1722 })
1723 .collect();
1724 }
1725 _ => {}
1726 }
1727 }
1728
1729 fn reduce_and_canonicalize_and_or(&mut self) {
1733 let mut old_self = MirScalarExpr::column(0);
1737 while old_self != *self {
1738 old_self = self.clone();
1739 match self {
1740 MirScalarExpr::CallVariadic {
1741 func: func @ (VariadicFunc::And(_) | VariadicFunc::Or(_)),
1742 exprs,
1743 } => {
1744 exprs.sort();
1748
1749 exprs.dedup(); if exprs.len() == 1 {
1753 *self = exprs.swap_remove(0);
1755 } else if exprs.len() == 0 {
1756 *self = func.unit_of_and_or();
1758 } else if exprs.iter().any(|e| *e == func.zero_of_and_or()) {
1759 *self = func.zero_of_and_or();
1761 } else {
1762 exprs.retain(|e| *e != func.unit_of_and_or());
1765 }
1766 }
1767 _ => {}
1768 }
1769 }
1770 }
1771
1772 fn demorgans(&mut self) {
1774 if let MirScalarExpr::CallUnary {
1775 expr: inner,
1776 func: UnaryFunc::Not(func::Not),
1777 } = self
1778 {
1779 inner.flatten_associative();
1780 match &mut **inner {
1781 MirScalarExpr::CallVariadic {
1782 func: inner_func @ (VariadicFunc::And(_) | VariadicFunc::Or(_)),
1783 exprs,
1784 } => {
1785 *inner_func = inner_func.switch_and_or();
1786 *exprs = exprs.into_iter().map(|e| e.take().not()).collect();
1787 *self = (*inner).take(); }
1789 _ => {}
1790 }
1791 }
1792 }
1793
1794 fn undistribute_and_or(&mut self) {
1859 let mut old_self = MirScalarExpr::column(0);
1864 while old_self != *self {
1865 old_self = self.clone();
1866 self.reduce_and_canonicalize_and_or(); if let MirScalarExpr::CallVariadic {
1868 exprs: outer_operands,
1869 func: outer_func @ (VariadicFunc::Or(_) | VariadicFunc::And(_)),
1870 } = self
1871 {
1872 let inner_func = outer_func.switch_and_or();
1873
1874 outer_operands.iter_mut().for_each(|o| {
1877 if !matches!(o, MirScalarExpr::CallVariadic {func: f, ..} if *f == inner_func) {
1878 *o = MirScalarExpr::CallVariadic {
1879 func: inner_func.clone(),
1880 exprs: vec![o.take()],
1881 };
1882 }
1883 });
1884
1885 let mut inner_operands_refs: Vec<&mut Vec<MirScalarExpr>> = outer_operands
1886 .iter_mut()
1887 .map(|o| match o {
1888 MirScalarExpr::CallVariadic { func: f, exprs } if *f == inner_func => exprs,
1889 _ => unreachable!(), })
1891 .collect();
1892
1893 let mut intersection = inner_operands_refs
1895 .iter()
1896 .map(|v| (*v).clone())
1897 .reduce(|ops1, ops2| ops1.into_iter().filter(|e| ops2.contains(e)).collect())
1898 .unwrap();
1899 intersection.sort();
1900 intersection.dedup();
1901
1902 if !intersection.is_empty() {
1903 inner_operands_refs
1907 .iter_mut()
1908 .for_each(|ops| (**ops).retain(|o| !intersection.contains(o)));
1909
1910 outer_operands
1912 .iter_mut()
1913 .for_each(|o| o.reduce_and_canonicalize_and_or());
1914
1915 *self = MirScalarExpr::CallVariadic {
1917 func: inner_func,
1918 exprs: intersection.into_iter().chain_one(self.clone()).collect(),
1919 };
1920 } else {
1921 let all_inner_operands = inner_operands_refs
1932 .iter()
1933 .enumerate()
1934 .flat_map(|(i, inner_vec)| inner_vec.iter().map(move |a| ((*a).clone(), i)))
1935 .sorted()
1936 .collect_vec();
1937
1938 let undistribution_opportunities = all_inner_operands
1943 .iter()
1944 .chunk_by(|(a, _i)| a)
1945 .into_iter()
1946 .map(|(_a, g)| g.map(|(_a, i)| *i).sorted().dedup().collect_vec())
1947 .filter(|g| g.len() > 1)
1948 .collect_vec();
1949
1950 let indexes_to_undistribute = undistribution_opportunities
1952 .iter()
1953 .find(|index_set| {
1955 index_set
1956 .iter()
1957 .any(|i| inner_operands_refs.get(*i).unwrap().len() == 1)
1958 })
1959 .or_else(|| undistribution_opportunities.first())
1961 .cloned();
1962
1963 outer_operands
1965 .iter_mut()
1966 .for_each(|o| o.reduce_and_canonicalize_and_or());
1967
1968 if let Some(indexes_to_undistribute) = indexes_to_undistribute {
1969 let mut undistribute_from = MirScalarExpr::CallVariadic {
1973 func: outer_func.clone(),
1974 exprs: swap_remove_multiple(outer_operands, indexes_to_undistribute),
1975 };
1976 undistribute_from.undistribute_and_or();
1979 outer_operands.push(undistribute_from);
1982 }
1983 }
1984 }
1985 }
1986 }
1987
1988 pub fn non_null_requirements(&self, columns: &mut BTreeSet<usize>) {
1992 match self {
1993 MirScalarExpr::Column(col, _name) => {
1994 columns.insert(*col);
1995 }
1996 MirScalarExpr::Literal(..) => {}
1997 MirScalarExpr::CallUnmaterializable(_) => (),
1998 MirScalarExpr::CallUnary { func, expr } => {
1999 if func.propagates_nulls() {
2000 expr.non_null_requirements(columns);
2001 }
2002 }
2003 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
2004 if func.propagates_nulls() {
2005 expr1.non_null_requirements(columns);
2006 expr2.non_null_requirements(columns);
2007 }
2008 }
2009 MirScalarExpr::CallVariadic { func, exprs } => {
2010 if func.propagates_nulls() {
2011 for expr in exprs {
2012 expr.non_null_requirements(columns);
2013 }
2014 }
2015 }
2016 MirScalarExpr::If { .. } => (),
2017 }
2018 }
2019
2020 pub fn sql_typ(&self, column_types: &[SqlColumnType]) -> SqlColumnType {
2021 let repr_column_types = column_types.iter().map(ReprColumnType::from).collect_vec();
2022 SqlColumnType::from_repr(&self.typ(&repr_column_types))
2023 }
2024
2025 pub fn typ(&self, column_types: &[ReprColumnType]) -> ReprColumnType {
2026 match self {
2027 MirScalarExpr::Column(i, _name) => column_types[*i].clone(),
2028 MirScalarExpr::Literal(_, typ) => typ.clone(),
2029 MirScalarExpr::CallUnmaterializable(func) => func.output_type(),
2030 MirScalarExpr::CallUnary { expr, func } => func.output_type(expr.typ(column_types)),
2031 MirScalarExpr::CallBinary { expr1, expr2, func } => {
2032 func.output_type(&[expr1.typ(column_types), expr2.typ(column_types)])
2033 }
2034 MirScalarExpr::CallVariadic { exprs, func } => {
2035 func.output_type(exprs.iter().map(|e| e.typ(column_types)).collect())
2036 }
2037 MirScalarExpr::If { cond: _, then, els } => {
2038 let then_type = then.typ(column_types);
2039 let else_type = els.typ(column_types);
2040 then_type.union(&else_type).unwrap()
2041 }
2042 }
2043 }
2044
2045 pub fn eval<'a>(
2046 &'a self,
2047 datums: &[Datum<'a>],
2048 temp_storage: &'a RowArena,
2049 ) -> Result<Datum<'a>, EvalError> {
2050 match self {
2051 MirScalarExpr::Column(index, _name) => Ok(datums[*index]),
2052 MirScalarExpr::Literal(res, _column_type) => match res {
2053 Ok(row) => Ok(row.unpack_first()),
2054 Err(e) => Err(e.clone()),
2055 },
2056 MirScalarExpr::CallUnmaterializable(x) => Err(EvalError::Internal(
2060 format!("cannot evaluate unmaterializable function: {:?}", x).into(),
2061 )),
2062 MirScalarExpr::CallUnary { func, expr } => func.eval(datums, temp_storage, expr),
2063 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
2064 func.eval(datums, temp_storage, &[expr1, expr2])
2065 }
2066 MirScalarExpr::CallVariadic { func, exprs } => func.eval(datums, temp_storage, exprs),
2067 MirScalarExpr::If { cond, then, els } => match cond.eval(datums, temp_storage)? {
2068 Datum::True => then.eval(datums, temp_storage),
2069 Datum::False | Datum::Null => els.eval(datums, temp_storage),
2070 d => Err(EvalError::Internal(
2071 format!("if condition evaluated to non-boolean datum: {:?}", d).into(),
2072 )),
2073 },
2074 }
2075 }
2076
2077 pub fn contains_temporal(&self) -> bool {
2080 let mut contains = false;
2081 self.visit_pre(|e| {
2082 if let MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow) = e {
2083 contains = true;
2084 }
2085 });
2086 contains
2087 }
2088
2089 pub fn contains_unmaterializable(&self) -> bool {
2091 let mut contains = false;
2092 self.visit_pre(|e| {
2093 if let MirScalarExpr::CallUnmaterializable(_) = e {
2094 contains = true;
2095 }
2096 });
2097 contains
2098 }
2099
2100 pub fn contains_unmaterializable_except(&self, exceptions: &[UnmaterializableFunc]) -> bool {
2103 let mut contains = false;
2104 self.visit_pre(|e| match e {
2105 MirScalarExpr::CallUnmaterializable(f) if !exceptions.contains(f) => contains = true,
2106 _ => (),
2107 });
2108 contains
2109 }
2110
2111 pub fn contains_column(&self) -> bool {
2113 let mut contains = false;
2114 self.visit_pre(|e| {
2115 if let MirScalarExpr::Column(_col, _name) = e {
2116 contains = true;
2117 }
2118 });
2119 contains
2120 }
2121
2122 pub fn contains_dummy(&self) -> bool {
2124 let mut contains = false;
2125 self.visit_pre(|e| {
2126 if let MirScalarExpr::Literal(row, _) = e {
2127 if let Ok(row) = row {
2128 contains |= row.iter().any(|d| d.contains_dummy());
2129 }
2130 }
2131 });
2132 contains
2133 }
2134
2135 pub fn size(&self) -> usize {
2137 let mut size = 0;
2138 self.visit_pre(&mut |_: &MirScalarExpr| {
2139 size += 1;
2140 });
2141 size
2142 }
2143}
2144
2145impl MirScalarExpr {
2146 pub fn could_error(&self) -> bool {
2148 match self {
2149 MirScalarExpr::Column(_col, _name) => false,
2150 MirScalarExpr::Literal(row, ..) => row.is_err(),
2151 MirScalarExpr::CallUnmaterializable(_) => true,
2152 MirScalarExpr::CallUnary { func, expr } => func.could_error() || expr.could_error(),
2153 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
2154 func.could_error() || expr1.could_error() || expr2.could_error()
2155 }
2156 MirScalarExpr::CallVariadic { func, exprs } => {
2157 func.could_error() || exprs.iter().any(|e| e.could_error())
2158 }
2159 MirScalarExpr::If { cond, then, els } => {
2160 cond.could_error() || then.could_error() || els.could_error()
2161 }
2162 }
2163 }
2164}
2165
2166impl VisitChildren<Self> for MirScalarExpr {
2167 fn visit_children<F>(&self, mut f: F)
2168 where
2169 F: FnMut(&Self),
2170 {
2171 use MirScalarExpr::*;
2172 match self {
2173 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2174 CallUnary { expr, .. } => {
2175 f(expr);
2176 }
2177 CallBinary { expr1, expr2, .. } => {
2178 f(expr1);
2179 f(expr2);
2180 }
2181 CallVariadic { exprs, .. } => {
2182 for expr in exprs {
2183 f(expr);
2184 }
2185 }
2186 If { cond, then, els } => {
2187 f(cond);
2188 f(then);
2189 f(els);
2190 }
2191 }
2192 }
2193
2194 fn visit_mut_children<F>(&mut self, mut f: F)
2195 where
2196 F: FnMut(&mut Self),
2197 {
2198 use MirScalarExpr::*;
2199 match self {
2200 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2201 CallUnary { expr, .. } => {
2202 f(expr);
2203 }
2204 CallBinary { expr1, expr2, .. } => {
2205 f(expr1);
2206 f(expr2);
2207 }
2208 CallVariadic { exprs, .. } => {
2209 for expr in exprs {
2210 f(expr);
2211 }
2212 }
2213 If { cond, then, els } => {
2214 f(cond);
2215 f(then);
2216 f(els);
2217 }
2218 }
2219 }
2220
2221 fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
2222 where
2223 F: FnMut(&Self) -> Result<(), E>,
2224 E: From<RecursionLimitError>,
2225 {
2226 use MirScalarExpr::*;
2227 match self {
2228 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2229 CallUnary { expr, .. } => {
2230 f(expr)?;
2231 }
2232 CallBinary { expr1, expr2, .. } => {
2233 f(expr1)?;
2234 f(expr2)?;
2235 }
2236 CallVariadic { exprs, .. } => {
2237 for expr in exprs {
2238 f(expr)?;
2239 }
2240 }
2241 If { cond, then, els } => {
2242 f(cond)?;
2243 f(then)?;
2244 f(els)?;
2245 }
2246 }
2247 Ok(())
2248 }
2249
2250 fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
2251 where
2252 F: FnMut(&mut Self) -> Result<(), E>,
2253 E: From<RecursionLimitError>,
2254 {
2255 use MirScalarExpr::*;
2256 match self {
2257 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2258 CallUnary { expr, .. } => {
2259 f(expr)?;
2260 }
2261 CallBinary { expr1, expr2, .. } => {
2262 f(expr1)?;
2263 f(expr2)?;
2264 }
2265 CallVariadic { exprs, .. } => {
2266 for expr in exprs {
2267 f(expr)?;
2268 }
2269 }
2270 If { cond, then, els } => {
2271 f(cond)?;
2272 f(then)?;
2273 f(els)?;
2274 }
2275 }
2276 Ok(())
2277 }
2278}
2279
2280impl MirScalarExpr {
2281 pub fn children(&self) -> impl DoubleEndedIterator<Item = &Self> {
2283 let mut first = None;
2284 let mut second = None;
2285 let mut third = None;
2286 let mut variadic = None;
2287
2288 use MirScalarExpr::*;
2289 match self {
2290 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2291 CallUnary { expr, .. } => {
2292 first = Some(&**expr);
2293 }
2294 CallBinary { expr1, expr2, .. } => {
2295 first = Some(&**expr1);
2296 second = Some(&**expr2);
2297 }
2298 CallVariadic { exprs, .. } => {
2299 variadic = Some(exprs);
2300 }
2301 If { cond, then, els } => {
2302 first = Some(&**cond);
2303 second = Some(&**then);
2304 third = Some(&**els);
2305 }
2306 }
2307
2308 first
2309 .into_iter()
2310 .chain(second)
2311 .chain(third)
2312 .chain(variadic.into_iter().flatten())
2313 }
2314
2315 pub fn children_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Self> {
2317 let mut first = None;
2318 let mut second = None;
2319 let mut third = None;
2320 let mut variadic = None;
2321
2322 use MirScalarExpr::*;
2323 match self {
2324 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2325 CallUnary { expr, .. } => {
2326 first = Some(&mut **expr);
2327 }
2328 CallBinary { expr1, expr2, .. } => {
2329 first = Some(&mut **expr1);
2330 second = Some(&mut **expr2);
2331 }
2332 CallVariadic { exprs, .. } => {
2333 variadic = Some(exprs);
2334 }
2335 If { cond, then, els } => {
2336 first = Some(&mut **cond);
2337 second = Some(&mut **then);
2338 third = Some(&mut **els);
2339 }
2340 }
2341
2342 first
2343 .into_iter()
2344 .chain(second)
2345 .chain(third)
2346 .chain(variadic.into_iter().flatten())
2347 }
2348
2349 pub fn visit_pre<F>(&self, mut f: F)
2351 where
2352 F: FnMut(&Self),
2353 {
2354 let mut worklist = vec![self];
2355 while let Some(e) = worklist.pop() {
2356 f(e);
2357 worklist.extend(e.children().rev());
2358 }
2359 }
2360
2361 pub fn visit_pre_mut<F: FnMut(&mut Self)>(&mut self, mut f: F) {
2363 let mut worklist = vec![self];
2364 while let Some(expr) = worklist.pop() {
2365 f(expr);
2366 worklist.extend(expr.children_mut().rev());
2367 }
2368 }
2369}
2370
2371#[derive(
2378 Eq,
2379 PartialEq,
2380 Ord,
2381 PartialOrd,
2382 Debug,
2383 Clone,
2384 Serialize,
2385 Deserialize,
2386 Hash,
2387 MzReflect
2388)]
2389pub struct FilterCharacteristics {
2390 literal_equality: bool,
2393 like: bool,
2395 is_null: bool,
2396 literal_inequality: usize,
2402 any_filter: bool,
2408}
2409
2410impl BitOrAssign for FilterCharacteristics {
2411 fn bitor_assign(&mut self, rhs: Self) {
2412 self.literal_equality |= rhs.literal_equality;
2413 self.like |= rhs.like;
2414 self.is_null |= rhs.is_null;
2415 self.literal_inequality += rhs.literal_inequality;
2416 self.any_filter |= rhs.any_filter;
2417 }
2418}
2419
2420impl FilterCharacteristics {
2421 pub fn none() -> FilterCharacteristics {
2422 FilterCharacteristics {
2423 literal_equality: false,
2424 like: false,
2425 is_null: false,
2426 literal_inequality: 0,
2427 any_filter: false,
2428 }
2429 }
2430
2431 pub fn explain(&self) -> String {
2432 let mut e = "".to_owned();
2433 if self.literal_equality {
2434 e.push_str("e");
2435 }
2436 if self.like {
2437 e.push_str("l");
2438 }
2439 if self.is_null {
2440 e.push_str("n");
2441 }
2442 for _ in 0..self.literal_inequality {
2443 e.push_str("i");
2444 }
2445 if self.any_filter {
2446 e.push_str("f");
2447 }
2448 e
2449 }
2450
2451 pub fn filter_characteristics(
2452 filters: &Vec<MirScalarExpr>,
2453 ) -> Result<FilterCharacteristics, RecursionLimitError> {
2454 let mut literal_equality = false;
2455 let mut like = false;
2456 let mut is_null = false;
2457 let mut literal_inequality = 0;
2458 let mut any_filter = false;
2459 filters.iter().try_for_each(|f| {
2460 let mut literal_inequality_in_current_filter = false;
2461 let mut is_not_null_in_current_filter = false;
2462 f.visit_pre_with_context(
2463 false,
2464 &mut |not_in_parent_chain, expr| {
2465 not_in_parent_chain
2466 || matches!(
2467 expr,
2468 MirScalarExpr::CallUnary {
2469 func: UnaryFunc::Not(func::Not),
2470 ..
2471 }
2472 )
2473 },
2474 &mut |not_in_parent_chain, expr| {
2475 if !not_in_parent_chain {
2476 if expr.any_expr_eq_literal().is_some() {
2477 literal_equality = true;
2478 }
2479 if expr.any_expr_ineq_literal() {
2480 literal_inequality_in_current_filter = true;
2481 }
2482 if matches!(
2483 expr,
2484 MirScalarExpr::CallUnary {
2485 func: UnaryFunc::IsLikeMatch(_),
2486 ..
2487 }
2488 ) {
2489 like = true;
2490 }
2491 };
2492 if matches!(
2493 expr,
2494 MirScalarExpr::CallUnary {
2495 func: UnaryFunc::IsNull(crate::func::IsNull),
2496 ..
2497 }
2498 ) {
2499 if *not_in_parent_chain {
2500 is_not_null_in_current_filter = true;
2501 } else {
2502 is_null = true;
2503 }
2504 }
2505 },
2506 )?;
2507 if literal_inequality_in_current_filter {
2508 literal_inequality += 1;
2509 }
2510 if !is_not_null_in_current_filter {
2511 any_filter = true;
2513 }
2514 Ok(())
2515 })?;
2516 Ok(FilterCharacteristics {
2517 literal_equality,
2518 like,
2519 is_null,
2520 literal_inequality,
2521 any_filter,
2522 })
2523 }
2524
2525 pub fn add_literal_equality(&mut self) {
2526 self.literal_equality = true;
2527 }
2528
2529 pub fn worst_case_scaling_factor(&self) -> f64 {
2530 let mut factor = 1.0;
2531
2532 if self.literal_equality {
2533 factor *= 0.1;
2534 }
2535
2536 if self.is_null {
2537 factor *= 0.1;
2538 }
2539
2540 if self.literal_inequality >= 2 {
2541 factor *= 0.25;
2542 } else if self.literal_inequality == 1 {
2543 factor *= 0.33;
2544 }
2545
2546 if !(self.literal_equality || self.is_null || self.literal_inequality > 0)
2548 && self.any_filter
2549 {
2550 factor *= 0.9;
2551 }
2552
2553 factor
2554 }
2555}
2556
2557#[derive(
2558 Arbitrary,
2559 Ord,
2560 PartialOrd,
2561 Copy,
2562 Clone,
2563 Debug,
2564 Eq,
2565 PartialEq,
2566 Serialize,
2567 Deserialize,
2568 Hash,
2569 MzReflect
2570)]
2571pub enum DomainLimit {
2572 None,
2573 Inclusive(i64),
2574 Exclusive(i64),
2575}
2576
2577impl RustType<ProtoDomainLimit> for DomainLimit {
2578 fn into_proto(&self) -> ProtoDomainLimit {
2579 use proto_domain_limit::Kind::*;
2580 let kind = match self {
2581 DomainLimit::None => None(()),
2582 DomainLimit::Inclusive(v) => Inclusive(*v),
2583 DomainLimit::Exclusive(v) => Exclusive(*v),
2584 };
2585 ProtoDomainLimit { kind: Some(kind) }
2586 }
2587
2588 fn from_proto(proto: ProtoDomainLimit) -> Result<Self, TryFromProtoError> {
2589 use proto_domain_limit::Kind::*;
2590 if let Some(kind) = proto.kind {
2591 match kind {
2592 None(()) => Ok(DomainLimit::None),
2593 Inclusive(v) => Ok(DomainLimit::Inclusive(v)),
2594 Exclusive(v) => Ok(DomainLimit::Exclusive(v)),
2595 }
2596 } else {
2597 Err(TryFromProtoError::missing_field("ProtoDomainLimit::kind"))
2598 }
2599 }
2600}
2601
2602#[derive(
2603 Arbitrary,
2604 Ord,
2605 PartialOrd,
2606 Clone,
2607 Debug,
2608 Eq,
2609 PartialEq,
2610 Serialize,
2611 Deserialize,
2612 Hash,
2613 MzReflect
2614)]
2615pub enum EvalError {
2616 CharacterNotValidForEncoding(i32),
2617 CharacterTooLargeForEncoding(i32),
2618 DateBinOutOfRange(Box<str>),
2619 DivisionByZero,
2620 Unsupported {
2621 feature: Box<str>,
2622 discussion_no: Option<usize>,
2623 },
2624 FloatOverflow,
2625 FloatUnderflow,
2626 NumericFieldOverflow,
2627 Float32OutOfRange(Box<str>),
2628 Float64OutOfRange(Box<str>),
2629 Int16OutOfRange(Box<str>),
2630 Int32OutOfRange(Box<str>),
2631 Int64OutOfRange(Box<str>),
2632 UInt16OutOfRange(Box<str>),
2633 UInt32OutOfRange(Box<str>),
2634 UInt64OutOfRange(Box<str>),
2635 MzTimestampOutOfRange(Box<str>),
2636 MzTimestampStepOverflow,
2637 OidOutOfRange(Box<str>),
2638 IntervalOutOfRange(Box<str>),
2639 TimestampCannotBeNan,
2640 TimestampOutOfRange,
2641 DateOutOfRange,
2642 CharOutOfRange,
2643 IndexOutOfRange {
2644 provided: i32,
2645 valid_end: i32,
2647 },
2648 InvalidBase64Equals,
2649 InvalidBase64Symbol(char),
2650 InvalidBase64EndSequence,
2651 InvalidTimezone(Box<str>),
2652 InvalidTimezoneInterval,
2653 InvalidTimezoneConversion,
2654 InvalidIanaTimezoneId(Box<str>),
2655 InvalidLayer {
2656 max_layer: usize,
2657 val: i64,
2658 },
2659 InvalidArray(InvalidArrayError),
2660 InvalidEncodingName(Box<str>),
2661 InvalidHashAlgorithm(Box<str>),
2662 InvalidByteSequence {
2663 byte_sequence: Box<str>,
2664 encoding_name: Box<str>,
2665 },
2666 InvalidJsonbCast {
2667 from: Box<str>,
2668 to: Box<str>,
2669 },
2670 InvalidRegex(Box<str>),
2671 InvalidRegexFlag(char),
2672 InvalidParameterValue(Box<str>),
2673 InvalidDatePart(Box<str>),
2674 KeyCannotBeNull,
2675 NegSqrt,
2676 NegLimit,
2677 NullCharacterNotPermitted,
2678 UnknownUnits(Box<str>),
2679 UnsupportedUnits(Box<str>, Box<str>),
2680 UnterminatedLikeEscapeSequence,
2681 Parse(ParseError),
2682 ParseHex(ParseHexError),
2683 Internal(Box<str>),
2684 InfinityOutOfDomain(Box<str>),
2685 NegativeOutOfDomain(Box<str>),
2686 ZeroOutOfDomain(Box<str>),
2687 OutOfDomain(DomainLimit, DomainLimit, Box<str>),
2688 ComplexOutOfRange(Box<str>),
2689 MultipleRowsFromSubquery,
2690 NegativeRowsFromSubquery,
2691 Undefined(Box<str>),
2692 LikePatternTooLong,
2693 LikeEscapeTooLong,
2694 StringValueTooLong {
2695 target_type: Box<str>,
2696 length: usize,
2697 },
2698 MultidimensionalArrayRemovalNotSupported,
2699 IncompatibleArrayDimensions {
2700 dims: Option<(usize, usize)>,
2701 },
2702 TypeFromOid(Box<str>),
2703 InvalidRange(InvalidRangeError),
2704 InvalidRoleId(Box<str>),
2705 InvalidPrivileges(Box<str>),
2706 InvalidCatalogJson(Box<str>),
2707 LetRecLimitExceeded(Box<str>),
2708 MultiDimensionalArraySearch,
2709 MustNotBeNull(Box<str>),
2710 InvalidIdentifier {
2711 ident: Box<str>,
2712 detail: Option<Box<str>>,
2713 },
2714 ArrayFillWrongArraySubscripts,
2715 MaxArraySizeExceeded(usize),
2717 DateDiffOverflow {
2718 unit: Box<str>,
2719 a: Box<str>,
2720 b: Box<str>,
2721 },
2722 IfNullError(Box<str>),
2725 LengthTooLarge,
2726 AclArrayNullElement,
2727 MzAclArrayNullElement,
2728 PrettyError(Box<str>),
2729 RedactError(Box<str>),
2730}
2731
2732impl fmt::Display for EvalError {
2733 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2734 match self {
2735 EvalError::CharacterNotValidForEncoding(v) => {
2736 write!(f, "requested character not valid for encoding: {v}")
2737 }
2738 EvalError::CharacterTooLargeForEncoding(v) => {
2739 write!(f, "requested character too large for encoding: {v}")
2740 }
2741 EvalError::DateBinOutOfRange(message) => f.write_str(message),
2742 EvalError::DivisionByZero => f.write_str("division by zero"),
2743 EvalError::Unsupported {
2744 feature,
2745 discussion_no,
2746 } => {
2747 write!(f, "{} not yet supported", feature)?;
2748 if let Some(discussion_no) = discussion_no {
2749 write!(
2750 f,
2751 ", see https://github.com/MaterializeInc/materialize/discussions/{} for more details",
2752 discussion_no
2753 )?;
2754 }
2755 Ok(())
2756 }
2757 EvalError::FloatOverflow => f.write_str("value out of range: overflow"),
2758 EvalError::FloatUnderflow => f.write_str("value out of range: underflow"),
2759 EvalError::NumericFieldOverflow => f.write_str("numeric field overflow"),
2760 EvalError::Float32OutOfRange(val) => write!(f, "{} real out of range", val.quoted()),
2761 EvalError::Float64OutOfRange(val) => {
2762 write!(f, "{} double precision out of range", val.quoted())
2763 }
2764 EvalError::Int16OutOfRange(val) => write!(f, "{} smallint out of range", val.quoted()),
2765 EvalError::Int32OutOfRange(val) => write!(f, "{} integer out of range", val.quoted()),
2766 EvalError::Int64OutOfRange(val) => write!(f, "{} bigint out of range", val.quoted()),
2767 EvalError::UInt16OutOfRange(val) => write!(f, "{} uint2 out of range", val.quoted()),
2768 EvalError::UInt32OutOfRange(val) => write!(f, "{} uint4 out of range", val.quoted()),
2769 EvalError::UInt64OutOfRange(val) => write!(f, "{} uint8 out of range", val.quoted()),
2770 EvalError::MzTimestampOutOfRange(val) => {
2771 write!(f, "{} mz_timestamp out of range", val.quoted())
2772 }
2773 EvalError::MzTimestampStepOverflow => f.write_str("step mz_timestamp overflow"),
2774 EvalError::OidOutOfRange(val) => write!(f, "{} OID out of range", val.quoted()),
2775 EvalError::IntervalOutOfRange(val) => {
2776 write!(f, "{} interval out of range", val.quoted())
2777 }
2778 EvalError::TimestampCannotBeNan => f.write_str("timestamp cannot be NaN"),
2779 EvalError::TimestampOutOfRange => f.write_str("timestamp out of range"),
2780 EvalError::DateOutOfRange => f.write_str("date out of range"),
2781 EvalError::CharOutOfRange => f.write_str("\"char\" out of range"),
2782 EvalError::IndexOutOfRange {
2783 provided,
2784 valid_end,
2785 } => write!(f, "index {provided} out of valid range, 0..{valid_end}",),
2786 EvalError::InvalidBase64Equals => {
2787 f.write_str("unexpected \"=\" while decoding base64 sequence")
2788 }
2789 EvalError::InvalidBase64Symbol(c) => write!(
2790 f,
2791 "invalid symbol \"{}\" found while decoding base64 sequence",
2792 c.escape_default()
2793 ),
2794 EvalError::InvalidBase64EndSequence => f.write_str("invalid base64 end sequence"),
2795 EvalError::InvalidJsonbCast { from, to } => {
2796 write!(f, "cannot cast jsonb {} to type {}", from, to)
2797 }
2798 EvalError::InvalidTimezone(tz) => write!(f, "invalid time zone '{}'", tz),
2799 EvalError::InvalidTimezoneInterval => {
2800 f.write_str("timezone interval must not contain months or years")
2801 }
2802 EvalError::InvalidTimezoneConversion => f.write_str("invalid timezone conversion"),
2803 EvalError::InvalidIanaTimezoneId(tz) => {
2804 write!(f, "invalid IANA Time Zone Database identifier: '{}'", tz)
2805 }
2806 EvalError::InvalidLayer { max_layer, val } => write!(
2807 f,
2808 "invalid layer: {}; must use value within [1, {}]",
2809 val, max_layer
2810 ),
2811 EvalError::InvalidArray(e) => e.fmt(f),
2812 EvalError::InvalidEncodingName(name) => write!(f, "invalid encoding name '{}'", name),
2813 EvalError::InvalidHashAlgorithm(alg) => write!(f, "invalid hash algorithm '{}'", alg),
2814 EvalError::InvalidByteSequence {
2815 byte_sequence,
2816 encoding_name,
2817 } => write!(
2818 f,
2819 "invalid byte sequence '{}' for encoding '{}'",
2820 byte_sequence, encoding_name
2821 ),
2822 EvalError::InvalidDatePart(part) => write!(f, "invalid datepart {}", part.quoted()),
2823 EvalError::KeyCannotBeNull => f.write_str("key cannot be null"),
2824 EvalError::NegSqrt => f.write_str("cannot take square root of a negative number"),
2825 EvalError::NegLimit => f.write_str("LIMIT must not be negative"),
2826 EvalError::NullCharacterNotPermitted => f.write_str("null character not permitted"),
2827 EvalError::InvalidRegex(e) => write!(f, "invalid regular expression: {}", e),
2828 EvalError::InvalidRegexFlag(c) => write!(f, "invalid regular expression flag: {}", c),
2829 EvalError::InvalidParameterValue(s) => f.write_str(s),
2830 EvalError::UnknownUnits(units) => write!(f, "unit '{}' not recognized", units),
2831 EvalError::UnsupportedUnits(units, typ) => {
2832 write!(f, "unit '{}' not supported for type {}", units, typ)
2833 }
2834 EvalError::UnterminatedLikeEscapeSequence => {
2835 f.write_str("unterminated escape sequence in LIKE")
2836 }
2837 EvalError::Parse(e) => e.fmt(f),
2838 EvalError::PrettyError(e) => e.fmt(f),
2839 EvalError::RedactError(e) => e.fmt(f),
2840 EvalError::ParseHex(e) => e.fmt(f),
2841 EvalError::Internal(s) => write!(f, "internal error: {}", s),
2842 EvalError::InfinityOutOfDomain(s) => {
2843 write!(f, "function {} is only defined for finite arguments", s)
2844 }
2845 EvalError::NegativeOutOfDomain(s) => {
2846 write!(f, "function {} is not defined for negative numbers", s)
2847 }
2848 EvalError::ZeroOutOfDomain(s) => {
2849 write!(f, "function {} is not defined for zero", s)
2850 }
2851 EvalError::OutOfDomain(lower, upper, s) => {
2852 use DomainLimit::*;
2853 write!(f, "function {s} is defined for numbers ")?;
2854 match (lower, upper) {
2855 (Inclusive(n), None) => write!(f, "greater than or equal to {n}"),
2856 (Exclusive(n), None) => write!(f, "greater than {n}"),
2857 (None, Inclusive(n)) => write!(f, "less than or equal to {n}"),
2858 (None, Exclusive(n)) => write!(f, "less than {n}"),
2859 (Inclusive(lo), Inclusive(hi)) => write!(f, "between {lo} and {hi} inclusive"),
2860 (Exclusive(lo), Exclusive(hi)) => write!(f, "between {lo} and {hi} exclusive"),
2861 (Inclusive(lo), Exclusive(hi)) => {
2862 write!(f, "between {lo} inclusive and {hi} exclusive")
2863 }
2864 (Exclusive(lo), Inclusive(hi)) => {
2865 write!(f, "between {lo} exclusive and {hi} inclusive")
2866 }
2867 (None, None) => panic!("invalid domain error"),
2868 }
2869 }
2870 EvalError::ComplexOutOfRange(s) => {
2871 write!(f, "function {} cannot return complex numbers", s)
2872 }
2873 EvalError::MultipleRowsFromSubquery => {
2874 write!(f, "more than one record produced in subquery")
2875 }
2876 EvalError::NegativeRowsFromSubquery => {
2877 write!(f, "negative number of rows produced in subquery")
2878 }
2879 EvalError::Undefined(s) => {
2880 write!(f, "{} is undefined", s)
2881 }
2882 EvalError::LikePatternTooLong => {
2883 write!(f, "LIKE pattern exceeds maximum length")
2884 }
2885 EvalError::LikeEscapeTooLong => {
2886 write!(f, "invalid escape string")
2887 }
2888 EvalError::StringValueTooLong {
2889 target_type,
2890 length,
2891 } => {
2892 write!(f, "value too long for type {}({})", target_type, length)
2893 }
2894 EvalError::MultidimensionalArrayRemovalNotSupported => {
2895 write!(
2896 f,
2897 "removing elements from multidimensional arrays is not supported"
2898 )
2899 }
2900 EvalError::IncompatibleArrayDimensions { dims: _ } => {
2901 write!(f, "cannot concatenate incompatible arrays")
2902 }
2903 EvalError::TypeFromOid(msg) => write!(f, "{msg}"),
2904 EvalError::InvalidRange(e) => e.fmt(f),
2905 EvalError::InvalidRoleId(msg) => write!(f, "{msg}"),
2906 EvalError::InvalidPrivileges(privilege) => {
2907 write!(f, "unrecognized privilege type: {privilege}")
2908 }
2909 EvalError::InvalidCatalogJson(msg) => {
2910 write!(f, "invalid catalog JSON: {msg}")
2911 }
2912 EvalError::LetRecLimitExceeded(max_iters) => {
2913 write!(
2914 f,
2915 "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.)",
2916 max_iters
2917 )
2918 }
2919 EvalError::MultiDimensionalArraySearch => write!(
2920 f,
2921 "searching for elements in multidimensional arrays is not supported"
2922 ),
2923 EvalError::MustNotBeNull(v) => write!(f, "{v} must not be null"),
2924 EvalError::InvalidIdentifier { ident, .. } => {
2925 write!(f, "string is not a valid identifier: {}", ident.quoted())
2926 }
2927 EvalError::ArrayFillWrongArraySubscripts => {
2928 f.write_str("wrong number of array subscripts")
2929 }
2930 EvalError::MaxArraySizeExceeded(max_size) => {
2931 write!(
2932 f,
2933 "array size exceeds the maximum allowed ({max_size} bytes)"
2934 )
2935 }
2936 EvalError::DateDiffOverflow { unit, a, b } => {
2937 write!(f, "datediff overflow, {unit} of {a}, {b}")
2938 }
2939 EvalError::IfNullError(s) => f.write_str(s),
2940 EvalError::LengthTooLarge => write!(f, "requested length too large"),
2941 EvalError::AclArrayNullElement => write!(f, "ACL arrays must not contain null values"),
2942 EvalError::MzAclArrayNullElement => {
2943 write!(f, "MZ_ACL arrays must not contain null values")
2944 }
2945 }
2946 }
2947}
2948
2949impl EvalError {
2950 pub fn detail(&self) -> Option<String> {
2951 match self {
2952 EvalError::IncompatibleArrayDimensions { dims: None } => Some(
2953 "Arrays with differing dimensions are not compatible for concatenation.".into(),
2954 ),
2955 EvalError::IncompatibleArrayDimensions {
2956 dims: Some((a_dims, b_dims)),
2957 } => Some(format!(
2958 "Arrays of {} and {} dimensions are not compatible for concatenation.",
2959 a_dims, b_dims
2960 )),
2961 EvalError::InvalidIdentifier { detail, .. } => detail.as_deref().map(Into::into),
2962 EvalError::ArrayFillWrongArraySubscripts => {
2963 Some("Low bound array has different size than dimensions array.".into())
2964 }
2965 _ => None,
2966 }
2967 }
2968
2969 pub fn hint(&self) -> Option<String> {
2970 match self {
2971 EvalError::InvalidBase64EndSequence => Some(
2972 "Input data is missing padding, is truncated, or is otherwise corrupted.".into(),
2973 ),
2974 EvalError::LikeEscapeTooLong => {
2975 Some("Escape string must be empty or one character.".into())
2976 }
2977 EvalError::MzTimestampOutOfRange(_) => Some(
2978 "Integer, numeric, and text casts to mz_timestamp must be in the form of whole \
2979 milliseconds since the Unix epoch. Values with fractional parts cannot be \
2980 converted to mz_timestamp."
2981 .into(),
2982 ),
2983 _ => None,
2984 }
2985 }
2986}
2987
2988impl std::error::Error for EvalError {}
2989
2990impl From<ParseError> for EvalError {
2991 fn from(e: ParseError) -> EvalError {
2992 EvalError::Parse(e)
2993 }
2994}
2995
2996impl From<ParseHexError> for EvalError {
2997 fn from(e: ParseHexError) -> EvalError {
2998 EvalError::ParseHex(e)
2999 }
3000}
3001
3002impl From<InvalidArrayError> for EvalError {
3003 fn from(e: InvalidArrayError) -> EvalError {
3004 EvalError::InvalidArray(e)
3005 }
3006}
3007
3008impl From<RegexCompilationError> for EvalError {
3009 fn from(e: RegexCompilationError) -> EvalError {
3010 EvalError::InvalidRegex(e.to_string().into())
3011 }
3012}
3013
3014impl From<TypeFromOidError> for EvalError {
3015 fn from(e: TypeFromOidError) -> EvalError {
3016 EvalError::TypeFromOid(e.to_string().into())
3017 }
3018}
3019
3020impl From<DateError> for EvalError {
3021 fn from(e: DateError) -> EvalError {
3022 match e {
3023 DateError::OutOfRange => EvalError::DateOutOfRange,
3024 }
3025 }
3026}
3027
3028impl From<TimestampError> for EvalError {
3029 fn from(e: TimestampError) -> EvalError {
3030 match e {
3031 TimestampError::OutOfRange => EvalError::TimestampOutOfRange,
3032 }
3033 }
3034}
3035
3036impl From<InvalidRangeError> for EvalError {
3037 fn from(e: InvalidRangeError) -> EvalError {
3038 EvalError::InvalidRange(e)
3039 }
3040}
3041
3042impl RustType<ProtoEvalError> for EvalError {
3043 fn into_proto(&self) -> ProtoEvalError {
3044 use proto_eval_error::Kind::*;
3045 use proto_eval_error::*;
3046 let kind = match self {
3047 EvalError::CharacterNotValidForEncoding(v) => CharacterNotValidForEncoding(*v),
3048 EvalError::CharacterTooLargeForEncoding(v) => CharacterTooLargeForEncoding(*v),
3049 EvalError::DateBinOutOfRange(v) => DateBinOutOfRange(v.into_proto()),
3050 EvalError::DivisionByZero => DivisionByZero(()),
3051 EvalError::Unsupported {
3052 feature,
3053 discussion_no,
3054 } => Unsupported(ProtoUnsupported {
3055 feature: feature.into_proto(),
3056 discussion_no: discussion_no.into_proto(),
3057 }),
3058 EvalError::FloatOverflow => FloatOverflow(()),
3059 EvalError::FloatUnderflow => FloatUnderflow(()),
3060 EvalError::NumericFieldOverflow => NumericFieldOverflow(()),
3061 EvalError::Float32OutOfRange(val) => Float32OutOfRange(ProtoValueOutOfRange {
3062 value: val.to_string(),
3063 }),
3064 EvalError::Float64OutOfRange(val) => Float64OutOfRange(ProtoValueOutOfRange {
3065 value: val.to_string(),
3066 }),
3067 EvalError::Int16OutOfRange(val) => Int16OutOfRange(ProtoValueOutOfRange {
3068 value: val.to_string(),
3069 }),
3070 EvalError::Int32OutOfRange(val) => Int32OutOfRange(ProtoValueOutOfRange {
3071 value: val.to_string(),
3072 }),
3073 EvalError::Int64OutOfRange(val) => Int64OutOfRange(ProtoValueOutOfRange {
3074 value: val.to_string(),
3075 }),
3076 EvalError::UInt16OutOfRange(val) => Uint16OutOfRange(ProtoValueOutOfRange {
3077 value: val.to_string(),
3078 }),
3079 EvalError::UInt32OutOfRange(val) => Uint32OutOfRange(ProtoValueOutOfRange {
3080 value: val.to_string(),
3081 }),
3082 EvalError::UInt64OutOfRange(val) => Uint64OutOfRange(ProtoValueOutOfRange {
3083 value: val.to_string(),
3084 }),
3085 EvalError::MzTimestampOutOfRange(val) => MzTimestampOutOfRange(ProtoValueOutOfRange {
3086 value: val.to_string(),
3087 }),
3088 EvalError::MzTimestampStepOverflow => MzTimestampStepOverflow(()),
3089 EvalError::OidOutOfRange(val) => OidOutOfRange(ProtoValueOutOfRange {
3090 value: val.to_string(),
3091 }),
3092 EvalError::IntervalOutOfRange(val) => IntervalOutOfRange(ProtoValueOutOfRange {
3093 value: val.to_string(),
3094 }),
3095 EvalError::TimestampCannotBeNan => TimestampCannotBeNan(()),
3096 EvalError::TimestampOutOfRange => TimestampOutOfRange(()),
3097 EvalError::DateOutOfRange => DateOutOfRange(()),
3098 EvalError::CharOutOfRange => CharOutOfRange(()),
3099 EvalError::IndexOutOfRange {
3100 provided,
3101 valid_end,
3102 } => IndexOutOfRange(ProtoIndexOutOfRange {
3103 provided: *provided,
3104 valid_end: *valid_end,
3105 }),
3106 EvalError::InvalidBase64Equals => InvalidBase64Equals(()),
3107 EvalError::InvalidBase64Symbol(sym) => InvalidBase64Symbol(sym.into_proto()),
3108 EvalError::InvalidBase64EndSequence => InvalidBase64EndSequence(()),
3109 EvalError::InvalidTimezone(tz) => InvalidTimezone(tz.into_proto()),
3110 EvalError::InvalidTimezoneInterval => InvalidTimezoneInterval(()),
3111 EvalError::InvalidTimezoneConversion => InvalidTimezoneConversion(()),
3112 EvalError::InvalidLayer { max_layer, val } => InvalidLayer(ProtoInvalidLayer {
3113 max_layer: max_layer.into_proto(),
3114 val: *val,
3115 }),
3116 EvalError::InvalidArray(error) => InvalidArray(error.into_proto()),
3117 EvalError::InvalidEncodingName(v) => InvalidEncodingName(v.into_proto()),
3118 EvalError::InvalidHashAlgorithm(v) => InvalidHashAlgorithm(v.into_proto()),
3119 EvalError::InvalidByteSequence {
3120 byte_sequence,
3121 encoding_name,
3122 } => InvalidByteSequence(ProtoInvalidByteSequence {
3123 byte_sequence: byte_sequence.into_proto(),
3124 encoding_name: encoding_name.into_proto(),
3125 }),
3126 EvalError::InvalidJsonbCast { from, to } => InvalidJsonbCast(ProtoInvalidJsonbCast {
3127 from: from.into_proto(),
3128 to: to.into_proto(),
3129 }),
3130 EvalError::InvalidRegex(v) => InvalidRegex(v.into_proto()),
3131 EvalError::InvalidRegexFlag(v) => InvalidRegexFlag(v.into_proto()),
3132 EvalError::InvalidParameterValue(v) => InvalidParameterValue(v.into_proto()),
3133 EvalError::InvalidDatePart(part) => InvalidDatePart(part.into_proto()),
3134 EvalError::KeyCannotBeNull => KeyCannotBeNull(()),
3135 EvalError::NegSqrt => NegSqrt(()),
3136 EvalError::NegLimit => NegLimit(()),
3137 EvalError::NullCharacterNotPermitted => NullCharacterNotPermitted(()),
3138 EvalError::UnknownUnits(v) => UnknownUnits(v.into_proto()),
3139 EvalError::UnsupportedUnits(units, typ) => UnsupportedUnits(ProtoUnsupportedUnits {
3140 units: units.into_proto(),
3141 typ: typ.into_proto(),
3142 }),
3143 EvalError::UnterminatedLikeEscapeSequence => UnterminatedLikeEscapeSequence(()),
3144 EvalError::Parse(error) => Parse(error.into_proto()),
3145 EvalError::PrettyError(error) => PrettyError(error.into_proto()),
3146 EvalError::RedactError(error) => RedactError(error.into_proto()),
3147 EvalError::ParseHex(error) => ParseHex(error.into_proto()),
3148 EvalError::Internal(v) => Internal(v.into_proto()),
3149 EvalError::InfinityOutOfDomain(v) => InfinityOutOfDomain(v.into_proto()),
3150 EvalError::NegativeOutOfDomain(v) => NegativeOutOfDomain(v.into_proto()),
3151 EvalError::ZeroOutOfDomain(v) => ZeroOutOfDomain(v.into_proto()),
3152 EvalError::OutOfDomain(lower, upper, id) => OutOfDomain(ProtoOutOfDomain {
3153 lower: Some(lower.into_proto()),
3154 upper: Some(upper.into_proto()),
3155 id: id.into_proto(),
3156 }),
3157 EvalError::ComplexOutOfRange(v) => ComplexOutOfRange(v.into_proto()),
3158 EvalError::MultipleRowsFromSubquery => MultipleRowsFromSubquery(()),
3159 EvalError::NegativeRowsFromSubquery => NegativeRowsFromSubquery(()),
3160 EvalError::Undefined(v) => Undefined(v.into_proto()),
3161 EvalError::LikePatternTooLong => LikePatternTooLong(()),
3162 EvalError::LikeEscapeTooLong => LikeEscapeTooLong(()),
3163 EvalError::StringValueTooLong {
3164 target_type,
3165 length,
3166 } => StringValueTooLong(ProtoStringValueTooLong {
3167 target_type: target_type.into_proto(),
3168 length: length.into_proto(),
3169 }),
3170 EvalError::MultidimensionalArrayRemovalNotSupported => {
3171 MultidimensionalArrayRemovalNotSupported(())
3172 }
3173 EvalError::IncompatibleArrayDimensions { dims } => {
3174 IncompatibleArrayDimensions(ProtoIncompatibleArrayDimensions {
3175 dims: dims.into_proto(),
3176 })
3177 }
3178 EvalError::TypeFromOid(v) => TypeFromOid(v.into_proto()),
3179 EvalError::InvalidRange(error) => InvalidRange(error.into_proto()),
3180 EvalError::InvalidRoleId(v) => InvalidRoleId(v.into_proto()),
3181 EvalError::InvalidPrivileges(v) => InvalidPrivileges(v.into_proto()),
3182 EvalError::InvalidCatalogJson(v) => InvalidCatalogJson(v.into_proto()),
3183 EvalError::LetRecLimitExceeded(v) => WmrRecursionLimitExceeded(v.into_proto()),
3184 EvalError::MultiDimensionalArraySearch => MultiDimensionalArraySearch(()),
3185 EvalError::MustNotBeNull(v) => MustNotBeNull(v.into_proto()),
3186 EvalError::InvalidIdentifier { ident, detail } => {
3187 InvalidIdentifier(ProtoInvalidIdentifier {
3188 ident: ident.into_proto(),
3189 detail: detail.into_proto(),
3190 })
3191 }
3192 EvalError::ArrayFillWrongArraySubscripts => ArrayFillWrongArraySubscripts(()),
3193 EvalError::MaxArraySizeExceeded(max_size) => {
3194 MaxArraySizeExceeded(u64::cast_from(*max_size))
3195 }
3196 EvalError::DateDiffOverflow { unit, a, b } => DateDiffOverflow(ProtoDateDiffOverflow {
3197 unit: unit.into_proto(),
3198 a: a.into_proto(),
3199 b: b.into_proto(),
3200 }),
3201 EvalError::IfNullError(s) => IfNullError(s.into_proto()),
3202 EvalError::LengthTooLarge => LengthTooLarge(()),
3203 EvalError::AclArrayNullElement => AclArrayNullElement(()),
3204 EvalError::MzAclArrayNullElement => MzAclArrayNullElement(()),
3205 EvalError::InvalidIanaTimezoneId(s) => InvalidIanaTimezoneId(s.into_proto()),
3206 };
3207 ProtoEvalError { kind: Some(kind) }
3208 }
3209
3210 fn from_proto(proto: ProtoEvalError) -> Result<Self, TryFromProtoError> {
3211 use proto_eval_error::Kind::*;
3212 match proto.kind {
3213 Some(kind) => match kind {
3214 CharacterNotValidForEncoding(v) => Ok(EvalError::CharacterNotValidForEncoding(v)),
3215 CharacterTooLargeForEncoding(v) => Ok(EvalError::CharacterTooLargeForEncoding(v)),
3216 DateBinOutOfRange(v) => Ok(EvalError::DateBinOutOfRange(v.into())),
3217 DivisionByZero(()) => Ok(EvalError::DivisionByZero),
3218 Unsupported(v) => Ok(EvalError::Unsupported {
3219 feature: v.feature.into(),
3220 discussion_no: v.discussion_no.into_rust()?,
3221 }),
3222 FloatOverflow(()) => Ok(EvalError::FloatOverflow),
3223 FloatUnderflow(()) => Ok(EvalError::FloatUnderflow),
3224 NumericFieldOverflow(()) => Ok(EvalError::NumericFieldOverflow),
3225 Float32OutOfRange(val) => Ok(EvalError::Float32OutOfRange(val.value.into())),
3226 Float64OutOfRange(val) => Ok(EvalError::Float64OutOfRange(val.value.into())),
3227 Int16OutOfRange(val) => Ok(EvalError::Int16OutOfRange(val.value.into())),
3228 Int32OutOfRange(val) => Ok(EvalError::Int32OutOfRange(val.value.into())),
3229 Int64OutOfRange(val) => Ok(EvalError::Int64OutOfRange(val.value.into())),
3230 Uint16OutOfRange(val) => Ok(EvalError::UInt16OutOfRange(val.value.into())),
3231 Uint32OutOfRange(val) => Ok(EvalError::UInt32OutOfRange(val.value.into())),
3232 Uint64OutOfRange(val) => Ok(EvalError::UInt64OutOfRange(val.value.into())),
3233 MzTimestampOutOfRange(val) => {
3234 Ok(EvalError::MzTimestampOutOfRange(val.value.into()))
3235 }
3236 MzTimestampStepOverflow(()) => Ok(EvalError::MzTimestampStepOverflow),
3237 OidOutOfRange(val) => Ok(EvalError::OidOutOfRange(val.value.into())),
3238 IntervalOutOfRange(val) => Ok(EvalError::IntervalOutOfRange(val.value.into())),
3239 TimestampCannotBeNan(()) => Ok(EvalError::TimestampCannotBeNan),
3240 TimestampOutOfRange(()) => Ok(EvalError::TimestampOutOfRange),
3241 DateOutOfRange(()) => Ok(EvalError::DateOutOfRange),
3242 CharOutOfRange(()) => Ok(EvalError::CharOutOfRange),
3243 IndexOutOfRange(v) => Ok(EvalError::IndexOutOfRange {
3244 provided: v.provided,
3245 valid_end: v.valid_end,
3246 }),
3247 InvalidBase64Equals(()) => Ok(EvalError::InvalidBase64Equals),
3248 InvalidBase64Symbol(v) => char::from_proto(v).map(EvalError::InvalidBase64Symbol),
3249 InvalidBase64EndSequence(()) => Ok(EvalError::InvalidBase64EndSequence),
3250 InvalidTimezone(v) => Ok(EvalError::InvalidTimezone(v.into())),
3251 InvalidTimezoneInterval(()) => Ok(EvalError::InvalidTimezoneInterval),
3252 InvalidTimezoneConversion(()) => Ok(EvalError::InvalidTimezoneConversion),
3253 InvalidLayer(v) => Ok(EvalError::InvalidLayer {
3254 max_layer: usize::from_proto(v.max_layer)?,
3255 val: v.val,
3256 }),
3257 InvalidArray(error) => Ok(EvalError::InvalidArray(error.into_rust()?)),
3258 InvalidEncodingName(v) => Ok(EvalError::InvalidEncodingName(v.into())),
3259 InvalidHashAlgorithm(v) => Ok(EvalError::InvalidHashAlgorithm(v.into())),
3260 InvalidByteSequence(v) => Ok(EvalError::InvalidByteSequence {
3261 byte_sequence: v.byte_sequence.into(),
3262 encoding_name: v.encoding_name.into(),
3263 }),
3264 InvalidJsonbCast(v) => Ok(EvalError::InvalidJsonbCast {
3265 from: v.from.into(),
3266 to: v.to.into(),
3267 }),
3268 InvalidRegex(v) => Ok(EvalError::InvalidRegex(v.into())),
3269 InvalidRegexFlag(v) => Ok(EvalError::InvalidRegexFlag(char::from_proto(v)?)),
3270 InvalidParameterValue(v) => Ok(EvalError::InvalidParameterValue(v.into())),
3271 InvalidDatePart(part) => Ok(EvalError::InvalidDatePart(part.into())),
3272 KeyCannotBeNull(()) => Ok(EvalError::KeyCannotBeNull),
3273 NegSqrt(()) => Ok(EvalError::NegSqrt),
3274 NegLimit(()) => Ok(EvalError::NegLimit),
3275 NullCharacterNotPermitted(()) => Ok(EvalError::NullCharacterNotPermitted),
3276 UnknownUnits(v) => Ok(EvalError::UnknownUnits(v.into())),
3277 UnsupportedUnits(v) => {
3278 Ok(EvalError::UnsupportedUnits(v.units.into(), v.typ.into()))
3279 }
3280 UnterminatedLikeEscapeSequence(()) => Ok(EvalError::UnterminatedLikeEscapeSequence),
3281 Parse(error) => Ok(EvalError::Parse(error.into_rust()?)),
3282 ParseHex(error) => Ok(EvalError::ParseHex(error.into_rust()?)),
3283 Internal(v) => Ok(EvalError::Internal(v.into())),
3284 InfinityOutOfDomain(v) => Ok(EvalError::InfinityOutOfDomain(v.into())),
3285 NegativeOutOfDomain(v) => Ok(EvalError::NegativeOutOfDomain(v.into())),
3286 ZeroOutOfDomain(v) => Ok(EvalError::ZeroOutOfDomain(v.into())),
3287 OutOfDomain(v) => Ok(EvalError::OutOfDomain(
3288 v.lower.into_rust_if_some("ProtoDomainLimit::lower")?,
3289 v.upper.into_rust_if_some("ProtoDomainLimit::upper")?,
3290 v.id.into(),
3291 )),
3292 ComplexOutOfRange(v) => Ok(EvalError::ComplexOutOfRange(v.into())),
3293 MultipleRowsFromSubquery(()) => Ok(EvalError::MultipleRowsFromSubquery),
3294 NegativeRowsFromSubquery(()) => Ok(EvalError::NegativeRowsFromSubquery),
3295 Undefined(v) => Ok(EvalError::Undefined(v.into())),
3296 LikePatternTooLong(()) => Ok(EvalError::LikePatternTooLong),
3297 LikeEscapeTooLong(()) => Ok(EvalError::LikeEscapeTooLong),
3298 StringValueTooLong(v) => Ok(EvalError::StringValueTooLong {
3299 target_type: v.target_type.into(),
3300 length: usize::from_proto(v.length)?,
3301 }),
3302 MultidimensionalArrayRemovalNotSupported(()) => {
3303 Ok(EvalError::MultidimensionalArrayRemovalNotSupported)
3304 }
3305 IncompatibleArrayDimensions(v) => Ok(EvalError::IncompatibleArrayDimensions {
3306 dims: v.dims.into_rust()?,
3307 }),
3308 TypeFromOid(v) => Ok(EvalError::TypeFromOid(v.into())),
3309 InvalidRange(e) => Ok(EvalError::InvalidRange(e.into_rust()?)),
3310 InvalidRoleId(v) => Ok(EvalError::InvalidRoleId(v.into())),
3311 InvalidPrivileges(v) => Ok(EvalError::InvalidPrivileges(v.into())),
3312 InvalidCatalogJson(v) => Ok(EvalError::InvalidCatalogJson(v.into())),
3313 WmrRecursionLimitExceeded(v) => Ok(EvalError::LetRecLimitExceeded(v.into())),
3314 MultiDimensionalArraySearch(()) => Ok(EvalError::MultiDimensionalArraySearch),
3315 MustNotBeNull(v) => Ok(EvalError::MustNotBeNull(v.into())),
3316 InvalidIdentifier(v) => Ok(EvalError::InvalidIdentifier {
3317 ident: v.ident.into(),
3318 detail: v.detail.into_rust()?,
3319 }),
3320 ArrayFillWrongArraySubscripts(()) => Ok(EvalError::ArrayFillWrongArraySubscripts),
3321 MaxArraySizeExceeded(max_size) => {
3322 Ok(EvalError::MaxArraySizeExceeded(usize::cast_from(max_size)))
3323 }
3324 DateDiffOverflow(v) => Ok(EvalError::DateDiffOverflow {
3325 unit: v.unit.into(),
3326 a: v.a.into(),
3327 b: v.b.into(),
3328 }),
3329 IfNullError(v) => Ok(EvalError::IfNullError(v.into())),
3330 LengthTooLarge(()) => Ok(EvalError::LengthTooLarge),
3331 AclArrayNullElement(()) => Ok(EvalError::AclArrayNullElement),
3332 MzAclArrayNullElement(()) => Ok(EvalError::MzAclArrayNullElement),
3333 InvalidIanaTimezoneId(s) => Ok(EvalError::InvalidIanaTimezoneId(s.into())),
3334 PrettyError(s) => Ok(EvalError::PrettyError(s.into())),
3335 RedactError(s) => Ok(EvalError::RedactError(s.into())),
3336 },
3337 None => Err(TryFromProtoError::missing_field("ProtoEvalError::kind")),
3338 }
3339 }
3340}
3341
3342impl RustType<ProtoDims> for (usize, usize) {
3343 fn into_proto(&self) -> ProtoDims {
3344 ProtoDims {
3345 f0: self.0.into_proto(),
3346 f1: self.1.into_proto(),
3347 }
3348 }
3349
3350 fn from_proto(proto: ProtoDims) -> Result<Self, TryFromProtoError> {
3351 Ok((proto.f0.into_rust()?, proto.f1.into_rust()?))
3352 }
3353}
3354
3355#[cfg(test)]
3356mod tests {
3357 use super::*;
3358
3359 #[mz_ore::test]
3360 #[cfg_attr(miri, ignore)] fn test_reduce() {
3362 let relation_type: Vec<ReprColumnType> = vec![
3363 ReprScalarType::Int64.nullable(true),
3364 ReprScalarType::Int64.nullable(true),
3365 ReprScalarType::Int64.nullable(false),
3366 ]
3367 .into_iter()
3368 .collect();
3369 let col = MirScalarExpr::column;
3370 let int64_typ = ReprScalarType::Int64;
3371 let err = |e| MirScalarExpr::literal(Err(e), int64_typ.clone());
3372 let lit = |i| MirScalarExpr::literal_ok(Datum::Int64(i), int64_typ.clone());
3373 let null = || MirScalarExpr::literal_null(int64_typ.clone());
3374
3375 struct TestCase {
3376 input: MirScalarExpr,
3377 output: MirScalarExpr,
3378 }
3379
3380 let test_cases = vec![
3381 TestCase {
3382 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1)]),
3383 output: lit(1),
3384 },
3385 TestCase {
3386 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1), lit(2)]),
3387 output: lit(1),
3388 },
3389 TestCase {
3390 input: MirScalarExpr::call_variadic(Coalesce, vec![null(), lit(2), null()]),
3391 output: lit(2),
3392 },
3393 TestCase {
3394 input: MirScalarExpr::call_variadic(
3395 Coalesce,
3396 vec![null(), col(0), null(), col(1), lit(2), lit(3)],
3397 ),
3398 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(1), lit(2)]),
3399 },
3400 TestCase {
3401 input: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2), col(1)]),
3402 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2)]),
3403 },
3404 TestCase {
3405 input: MirScalarExpr::call_variadic(
3406 Coalesce,
3407 vec![lit(1), err(EvalError::DivisionByZero)],
3408 ),
3409 output: lit(1),
3410 },
3411 TestCase {
3412 input: MirScalarExpr::call_variadic(
3413 Coalesce,
3414 vec![
3415 null(),
3416 err(EvalError::DivisionByZero),
3417 err(EvalError::NumericFieldOverflow),
3418 ],
3419 ),
3420 output: err(EvalError::DivisionByZero),
3421 },
3422 ];
3423
3424 for tc in test_cases {
3425 let mut actual = tc.input.clone();
3426 actual.reduce(&relation_type);
3427 assert!(
3428 actual == tc.output,
3429 "input: {}\nactual: {}\nexpected: {}",
3430 tc.input,
3431 actual,
3432 tc.output
3433 );
3434 }
3435 }
3436}