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