1use std::collections::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::iter::IteratorExt;
19use mz_ore::soft_assert_or_log;
20use mz_ore::stack::RecursionLimitError;
21use mz_ore::str::StrExt;
22use mz_ore::treat_as_equal::TreatAsEqual;
23use mz_ore::vec::swap_remove_multiple;
24use mz_pgrepr::TypeFromOidError;
25use mz_proto::{IntoRustIfSome, ProtoType, RustType, TryFromProtoError};
26use mz_repr::adt::array::InvalidArrayError;
27use mz_repr::adt::date::DateError;
28use mz_repr::adt::range::InvalidRangeError;
29use mz_repr::adt::regex::RegexCompilationError;
30use mz_repr::adt::timestamp::TimestampError;
31use mz_repr::strconv::{ParseError, ParseHexError};
32use mz_repr::{Datum, ReprColumnType, ReprScalarType, Row, RowArena, SqlColumnType};
33
34#[cfg(any(test, feature = "proptest"))]
35use proptest::prelude::*;
36#[cfg(any(test, feature = "proptest"))]
37use proptest_derive::Arbitrary;
38use serde::{Deserialize, Serialize};
39
40use crate::explain::{HumanizedExplain, HumanizerMode};
41pub use crate::scalar::columns::Columns;
42pub use crate::scalar::eval::Eval;
43use crate::scalar::func::variadic::{And, Or};
44use crate::scalar::func::{BinaryFunc, UnaryFunc, UnmaterializableFunc, VariadicFunc};
45pub use crate::scalar::optimizable::OptimizableExpr;
46use crate::scalar::proto_eval_error::proto_incompatible_array_dimensions::ProtoDims;
47use crate::visit::{Visit, VisitChildren};
48
49pub mod columns;
50pub mod eval;
51pub mod func;
52pub mod like_pattern;
53pub mod optimizable;
54mod reduce;
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 take(&mut self) -> Self {
470 mem::replace(self, MirScalarExpr::literal_null(ReprScalarType::String))
471 }
472
473 pub fn as_literal(&self) -> Option<Result<Datum<'_>, &EvalError>> {
476 if let MirScalarExpr::Literal(lit, _column_type) = self {
477 Some(lit.as_ref().map(|row| row.unpack_first()))
478 } else {
479 None
480 }
481 }
482
483 pub fn as_literal_non_error(&self) -> Option<Datum<'_>> {
486 self.as_literal().map(|eval_err| eval_err.ok()).flatten()
487 }
488
489 pub fn as_literal_owned(&self) -> Option<Result<Row, EvalError>> {
490 if let MirScalarExpr::Literal(lit, _column_type) = self {
491 Some(lit.clone())
492 } else {
493 None
494 }
495 }
496
497 pub fn as_literal_non_null_row(&self) -> Option<&Row> {
499 if let MirScalarExpr::Literal(Ok(row), _) = self {
500 if !row.unpack_first().is_null() {
501 return Some(row);
502 }
503 }
504 None
505 }
506
507 pub fn as_literal_str(&self) -> Option<&str> {
508 match self.as_literal() {
509 Some(Ok(Datum::String(s))) => Some(s),
510 _ => None,
511 }
512 }
513
514 pub fn as_literal_int64(&self) -> Option<i64> {
515 match self.as_literal() {
516 Some(Ok(Datum::Int64(i))) => Some(i),
517 _ => None,
518 }
519 }
520
521 pub fn as_literal_err(&self) -> Option<&EvalError> {
522 self.as_literal().and_then(|lit| lit.err())
523 }
524
525 pub fn is_literal(&self) -> bool {
526 matches!(self, MirScalarExpr::Literal(_, _))
527 }
528
529 pub fn is_literal_true(&self) -> bool {
530 Some(Ok(Datum::True)) == self.as_literal()
531 }
532
533 pub fn is_literal_false(&self) -> bool {
534 Some(Ok(Datum::False)) == self.as_literal()
535 }
536
537 pub fn is_literal_null(&self) -> bool {
538 Some(Ok(Datum::Null)) == self.as_literal()
539 }
540
541 pub fn is_literal_ok(&self) -> bool {
542 matches!(self, MirScalarExpr::Literal(Ok(_), _typ))
543 }
544
545 pub fn is_literal_err(&self) -> bool {
546 matches!(self, MirScalarExpr::Literal(Err(_), _typ))
547 }
548
549 pub fn is_error_if_null(&self) -> bool {
550 matches!(
551 self,
552 Self::CallVariadic {
553 func: VariadicFunc::ErrorIfNull(_),
554 ..
555 }
556 )
557 }
558
559 pub fn as_mut_temporal_filter(&mut self) -> Result<(&BinaryFunc, &mut MirScalarExpr), String> {
569 if !self.contains_temporal() {
570 return Err("Does not involve mz_now()".to_string());
571 }
572 if let MirScalarExpr::CallBinary { func, expr1, expr2 } = self {
574 if !expr1.contains_temporal()
576 && **expr2 == MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow)
577 {
578 let new_func = match func {
579 BinaryFunc::Eq(_) => func::Eq.into(),
580 BinaryFunc::Lt(_) => func::Gt.into(),
581 BinaryFunc::Lte(_) => func::Gte.into(),
582 BinaryFunc::Gt(_) => func::Lt.into(),
583 BinaryFunc::Gte(_) => func::Lte.into(),
584 x => {
585 return Err(format!("Unsupported binary temporal operation: {:?}", x));
586 }
587 };
588 std::mem::swap(expr1, expr2);
589 *func = new_func;
590 }
591
592 if expr2.contains_temporal()
594 || **expr1 != MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow)
595 {
596 let mode = HumanizedExplain::new(false); let bad_expr = MirScalarExpr::CallBinary {
598 func: func.clone(),
599 expr1: expr1.clone(),
600 expr2: expr2.clone(),
601 };
602 return Err(format!(
603 "Unsupported temporal predicate. Note: `mz_now()` must be directly compared to a mz_timestamp-castable expression. Expression found: {}",
604 mode.expr(&bad_expr, None),
605 ));
606 }
607
608 Ok((&*func, expr2))
609 } else {
610 let mode = HumanizedExplain::new(false); Err(format!(
612 "Unsupported temporal predicate. Note: `mz_now()` must be directly compared to a non-temporal expression of mz_timestamp-castable type. Expression found: {}",
613 mode.expr(self, None),
614 ))
615 }
616 }
617
618 #[deprecated = "Use `might_error` instead"]
619 pub fn contains_error_if_null(&self) -> bool {
620 let mut worklist = vec![self];
621 while let Some(expr) = worklist.pop() {
622 if expr.is_error_if_null() {
623 return true;
624 }
625 worklist.extend(expr.children());
626 }
627 false
628 }
629
630 pub fn contains_err(&self) -> bool {
631 let mut worklist = vec![self];
632 while let Some(expr) = worklist.pop() {
633 if expr.is_literal_err() {
634 return true;
635 }
636 worklist.extend(expr.children());
637 }
638 false
639 }
640
641 pub fn might_error(&self) -> bool {
647 let mut worklist = vec![self];
648 while let Some(expr) = worklist.pop() {
649 if expr.is_literal_err() || expr.is_error_if_null() {
650 return true;
651 }
652 worklist.extend(expr.children());
653 }
654 false
655 }
656
657 pub fn reduce(&mut self, column_types: &[ReprColumnType]) {
690 reduce::reduce(self, column_types);
691 }
692
693 fn decompose_is_null(&mut self) -> Option<MirScalarExpr> {
701 match self {
704 MirScalarExpr::CallUnary {
705 func,
706 expr: inner_expr,
707 } => {
708 if !func.introduces_nulls() {
709 if func.propagates_nulls() {
710 *self = inner_expr.take();
711 return self.decompose_is_null();
712 } else {
713 return Some(MirScalarExpr::literal_false());
732 }
733 }
734 }
735 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
736 if func.propagates_nulls() && !func.introduces_nulls() {
739 let expr1 = expr1.take().call_is_null();
740 let expr2 = expr2.take().call_is_null();
741 return Some(expr1.or(expr2));
742 }
743 }
744 MirScalarExpr::CallVariadic { func, exprs } => {
745 if func.propagates_nulls() && !func.introduces_nulls() {
746 let exprs = exprs.into_iter().map(|e| e.take().call_is_null()).collect();
747 return Some(MirScalarExpr::call_variadic(Or, exprs));
748 }
749 }
750 _ => {}
751 }
752
753 None
754 }
755
756 pub fn flatten_associative(&mut self) {
759 match self {
760 MirScalarExpr::CallVariadic {
761 exprs: outer_operands,
762 func: outer_func,
763 } if outer_func.is_associative() => {
764 *outer_operands = outer_operands
765 .into_iter()
766 .flat_map(|o| {
767 if let MirScalarExpr::CallVariadic {
768 exprs: inner_operands,
769 func: inner_func,
770 } = o
771 {
772 if *inner_func == *outer_func {
773 mem::take(inner_operands)
774 } else {
775 vec![o.take()]
776 }
777 } else {
778 vec![o.take()]
779 }
780 })
781 .collect();
782 }
783 _ => {}
784 }
785 }
786
787 fn reduce_and_canonicalize_and_or(&mut self) {
791 let mut old_self = MirScalarExpr::column(0);
795 while old_self != *self {
796 old_self = self.clone();
797 match self {
798 MirScalarExpr::CallVariadic {
799 func: func @ (VariadicFunc::And(_) | VariadicFunc::Or(_)),
800 exprs,
801 } => {
802 exprs.sort();
806
807 exprs.dedup(); if exprs.len() == 1 {
811 *self = exprs.swap_remove(0);
813 } else if exprs.len() == 0 {
814 *self = func.unit_of_and_or();
816 } else if exprs.iter().any(|e| *e == func.zero_of_and_or()) {
817 *self = func.zero_of_and_or();
819 } else {
820 exprs.retain(|e| *e != func.unit_of_and_or());
823 }
824 }
825 _ => {}
826 }
827 }
828 }
829
830 fn demorgans(&mut self) {
832 if let MirScalarExpr::CallUnary {
833 expr: inner,
834 func: UnaryFunc::Not(func::Not),
835 } = self
836 {
837 inner.flatten_associative();
838 match &mut **inner {
839 MirScalarExpr::CallVariadic {
840 func: inner_func @ (VariadicFunc::And(_) | VariadicFunc::Or(_)),
841 exprs,
842 } => {
843 *inner_func = inner_func.switch_and_or();
844 *exprs = exprs.into_iter().map(|e| e.take().not()).collect();
845 *self = (*inner).take(); }
847 _ => {}
848 }
849 }
850 }
851
852 fn undistribute_and_or(&mut self) {
917 let mut old_self = MirScalarExpr::column(0);
922 while old_self != *self {
923 old_self = self.clone();
924 self.reduce_and_canonicalize_and_or(); if let MirScalarExpr::CallVariadic {
926 exprs: outer_operands,
927 func: outer_func @ (VariadicFunc::Or(_) | VariadicFunc::And(_)),
928 } = self
929 {
930 let inner_func = outer_func.switch_and_or();
931
932 outer_operands.iter_mut().for_each(|o| {
935 if !matches!(o, MirScalarExpr::CallVariadic {func: f, ..} if *f == inner_func) {
936 *o = MirScalarExpr::CallVariadic {
937 func: inner_func.clone(),
938 exprs: vec![o.take()],
939 };
940 }
941 });
942
943 let mut inner_operands_refs: Vec<&mut Vec<MirScalarExpr>> = outer_operands
944 .iter_mut()
945 .map(|o| match o {
946 MirScalarExpr::CallVariadic { func: f, exprs } if *f == inner_func => exprs,
947 _ => unreachable!(), })
949 .collect();
950
951 let mut intersection = inner_operands_refs
953 .iter()
954 .map(|v| (*v).clone())
955 .reduce(|ops1, ops2| ops1.into_iter().filter(|e| ops2.contains(e)).collect())
956 .unwrap();
957 intersection.sort();
958 intersection.dedup();
959
960 if !intersection.is_empty() {
961 inner_operands_refs
965 .iter_mut()
966 .for_each(|ops| (**ops).retain(|o| !intersection.contains(o)));
967
968 outer_operands
970 .iter_mut()
971 .for_each(|o| o.reduce_and_canonicalize_and_or());
972
973 *self = MirScalarExpr::CallVariadic {
975 func: inner_func,
976 exprs: intersection.into_iter().chain_one(self.clone()).collect(),
977 };
978 } else {
979 let all_inner_operands = inner_operands_refs
990 .iter()
991 .enumerate()
992 .flat_map(|(i, inner_vec)| inner_vec.iter().map(move |a| ((*a).clone(), i)))
993 .sorted()
994 .collect_vec();
995
996 let undistribution_opportunities = all_inner_operands
1001 .iter()
1002 .chunk_by(|(a, _i)| a)
1003 .into_iter()
1004 .map(|(_a, g)| g.map(|(_a, i)| *i).sorted().dedup().collect_vec())
1005 .filter(|g| g.len() > 1)
1006 .collect_vec();
1007
1008 let indexes_to_undistribute = undistribution_opportunities
1010 .iter()
1011 .find(|index_set| {
1013 index_set
1014 .iter()
1015 .any(|i| inner_operands_refs.get(*i).unwrap().len() == 1)
1016 })
1017 .or_else(|| undistribution_opportunities.first())
1019 .cloned();
1020
1021 outer_operands
1023 .iter_mut()
1024 .for_each(|o| o.reduce_and_canonicalize_and_or());
1025
1026 if let Some(indexes_to_undistribute) = indexes_to_undistribute {
1027 let mut undistribute_from = MirScalarExpr::CallVariadic {
1031 func: outer_func.clone(),
1032 exprs: swap_remove_multiple(outer_operands, indexes_to_undistribute),
1033 };
1034 undistribute_from.undistribute_and_or();
1037 outer_operands.push(undistribute_from);
1040 }
1041 }
1042 }
1043 }
1044 }
1045
1046 pub fn non_null_requirements(&self, columns: &mut BTreeSet<usize>) {
1050 match self {
1051 MirScalarExpr::Column(col, _name) => {
1052 columns.insert(*col);
1053 }
1054 MirScalarExpr::Literal(..) => {}
1055 MirScalarExpr::CallUnmaterializable(_) => (),
1056 MirScalarExpr::CallUnary { func, expr } => {
1057 if func.propagates_nulls() {
1058 expr.non_null_requirements(columns);
1059 }
1060 }
1061 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1062 if func.propagates_nulls() {
1063 expr1.non_null_requirements(columns);
1064 expr2.non_null_requirements(columns);
1065 }
1066 }
1067 MirScalarExpr::CallVariadic { func, exprs } => {
1068 if func.propagates_nulls() {
1069 for expr in exprs {
1070 expr.non_null_requirements(columns);
1071 }
1072 }
1073 }
1074 MirScalarExpr::If { .. } => (),
1075 }
1076 }
1077
1078 pub fn sql_typ(&self, column_types: &[SqlColumnType]) -> SqlColumnType {
1079 let repr_column_types = column_types.iter().map(ReprColumnType::from).collect_vec();
1080 SqlColumnType::from_repr(&self.typ(&repr_column_types))
1081 }
1082
1083 pub fn typ(&self, column_types: &[ReprColumnType]) -> ReprColumnType {
1084 match self {
1085 MirScalarExpr::Column(i, _name) => column_types[*i].clone(),
1086 MirScalarExpr::Literal(_, typ) => typ.clone(),
1087 MirScalarExpr::CallUnmaterializable(func) => func.output_type(),
1088 MirScalarExpr::CallUnary { expr, func } => func.output_type(expr.typ(column_types)),
1089 MirScalarExpr::CallBinary { expr1, expr2, func } => {
1090 func.output_type(&[expr1.typ(column_types), expr2.typ(column_types)])
1091 }
1092 MirScalarExpr::CallVariadic { exprs, func } => {
1093 func.output_type(exprs.iter().map(|e| e.typ(column_types)).collect())
1094 }
1095 MirScalarExpr::If { cond: _, then, els } => {
1096 let then_type = then.typ(column_types);
1097 let else_type = els.typ(column_types);
1098 then_type.union(&else_type).unwrap()
1099 }
1100 }
1101 }
1102
1103 pub fn contains_temporal(&self) -> bool {
1106 let mut contains = false;
1107 self.visit_pre(|e| {
1108 if let MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow) = e {
1109 contains = true;
1110 }
1111 });
1112 contains
1113 }
1114
1115 pub fn contains_unmaterializable(&self) -> bool {
1117 let mut contains = false;
1118 self.visit_pre(|e| {
1119 if let MirScalarExpr::CallUnmaterializable(_) = e {
1120 contains = true;
1121 }
1122 });
1123 contains
1124 }
1125
1126 pub fn contains_unmaterializable_except(&self, exceptions: &[UnmaterializableFunc]) -> bool {
1129 let mut contains = false;
1130 self.visit_pre(|e| match e {
1131 MirScalarExpr::CallUnmaterializable(f) if !exceptions.contains(f) => contains = true,
1132 _ => (),
1133 });
1134 contains
1135 }
1136
1137 pub fn contains_column(&self) -> bool {
1139 let mut contains = false;
1140 self.visit_pre(|e| {
1141 if let MirScalarExpr::Column(_col, _name) = e {
1142 contains = true;
1143 }
1144 });
1145 contains
1146 }
1147
1148 pub fn contains_dummy(&self) -> bool {
1150 let mut contains = false;
1151 self.visit_pre(|e| {
1152 if let MirScalarExpr::Literal(row, _) = e {
1153 if let Ok(row) = row {
1154 contains |= row.iter().any(|d| d.contains_dummy());
1155 }
1156 }
1157 });
1158 contains
1159 }
1160
1161 pub fn size(&self) -> usize {
1163 let mut size = 0;
1164 self.visit_pre(&mut |_: &MirScalarExpr| {
1165 size += 1;
1166 });
1167 size
1168 }
1169}
1170
1171impl Eval for MirScalarExpr {
1172 fn eval<'a>(
1173 &'a self,
1174 datums: &[Datum<'a>],
1175 temp_storage: &'a RowArena,
1176 ) -> Result<Datum<'a>, EvalError> {
1177 match self {
1178 MirScalarExpr::Column(index, _name) => Ok(datums[*index]),
1179 MirScalarExpr::Literal(res, _column_type) => match res {
1180 Ok(row) => Ok(row.unpack_first()),
1181 Err(e) => Err(e.clone()),
1182 },
1183 MirScalarExpr::CallUnmaterializable(x) => Err(EvalError::Internal(
1187 format!("cannot evaluate unmaterializable function: {:?}", x).into(),
1188 )),
1189 MirScalarExpr::CallUnary { func, expr } => {
1190 func.eval(datums, temp_storage, expr.as_ref())
1191 }
1192 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1193 func.eval(datums, temp_storage, &[expr1.as_ref(), expr2.as_ref()])
1194 }
1195 MirScalarExpr::CallVariadic { func, exprs } => {
1196 func.eval(datums, temp_storage, exprs.as_slice())
1197 }
1198 MirScalarExpr::If { cond, then, els } => match cond.eval(datums, temp_storage)? {
1199 Datum::True => then.eval(datums, temp_storage),
1200 Datum::False | Datum::Null => els.eval(datums, temp_storage),
1201 d => Err(EvalError::Internal(
1202 format!("if condition evaluated to non-boolean datum: {:?}", d).into(),
1203 )),
1204 },
1205 }
1206 }
1207
1208 fn could_error(&self) -> bool {
1209 match self {
1210 MirScalarExpr::Column(_col, _name) => false,
1211 MirScalarExpr::Literal(row, ..) => row.is_err(),
1212 MirScalarExpr::CallUnmaterializable(_) => true,
1213 MirScalarExpr::CallUnary { func, expr } => func.could_error() || expr.could_error(),
1214 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1215 func.could_error() || expr1.could_error() || expr2.could_error()
1216 }
1217 MirScalarExpr::CallVariadic { func, exprs } => {
1218 func.could_error() || exprs.iter().any(|e| e.could_error())
1219 }
1220 MirScalarExpr::If { cond, then, els } => {
1221 cond.could_error() || then.could_error() || els.could_error()
1222 }
1223 }
1224 }
1225}
1226
1227impl Columns for MirScalarExpr {
1228 fn column(c: usize) -> Self {
1229 MirScalarExpr::column(c)
1230 }
1231
1232 fn is_column(&self) -> bool {
1233 matches!(self, MirScalarExpr::Column(_col, _name))
1234 }
1235
1236 fn as_column(&self) -> Option<usize> {
1237 if let MirScalarExpr::Column(c, _) = self {
1238 Some(*c)
1239 } else {
1240 None
1241 }
1242 }
1243
1244 fn as_column_mut(&mut self) -> Option<&mut usize> {
1245 if let MirScalarExpr::Column(c, _) = self {
1246 Some(c)
1247 } else {
1248 None
1249 }
1250 }
1251
1252 fn support_into(&self, support: &mut BTreeSet<usize>) {
1253 self.visit_pre(|e| {
1254 if let MirScalarExpr::Column(i, _) = e {
1255 support.insert(*i);
1256 }
1257 });
1258 }
1259
1260 fn visit_columns<F>(&mut self, mut action: F)
1261 where
1262 F: FnMut(&mut usize),
1263 {
1264 self.visit_pre_mut(|e| {
1265 if let MirScalarExpr::Column(col, _) = e {
1266 action(col);
1267 }
1268 });
1269 }
1270}
1271
1272impl VisitChildren<Self> for MirScalarExpr {
1273 fn visit_children<F>(&self, mut f: F)
1274 where
1275 F: FnMut(&Self),
1276 {
1277 use MirScalarExpr::*;
1278 match self {
1279 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1280 CallUnary { expr, .. } => {
1281 f(expr);
1282 }
1283 CallBinary { expr1, expr2, .. } => {
1284 f(expr1);
1285 f(expr2);
1286 }
1287 CallVariadic { exprs, .. } => {
1288 for expr in exprs {
1289 f(expr);
1290 }
1291 }
1292 If { cond, then, els } => {
1293 f(cond);
1294 f(then);
1295 f(els);
1296 }
1297 }
1298 }
1299
1300 fn visit_mut_children<F>(&mut self, mut f: F)
1301 where
1302 F: FnMut(&mut Self),
1303 {
1304 use MirScalarExpr::*;
1305 match self {
1306 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1307 CallUnary { expr, .. } => {
1308 f(expr);
1309 }
1310 CallBinary { expr1, expr2, .. } => {
1311 f(expr1);
1312 f(expr2);
1313 }
1314 CallVariadic { exprs, .. } => {
1315 for expr in exprs {
1316 f(expr);
1317 }
1318 }
1319 If { cond, then, els } => {
1320 f(cond);
1321 f(then);
1322 f(els);
1323 }
1324 }
1325 }
1326
1327 fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
1328 where
1329 F: FnMut(&Self) -> Result<(), E>,
1330 {
1331 use MirScalarExpr::*;
1332 match self {
1333 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1334 CallUnary { expr, .. } => {
1335 f(expr)?;
1336 }
1337 CallBinary { expr1, expr2, .. } => {
1338 f(expr1)?;
1339 f(expr2)?;
1340 }
1341 CallVariadic { exprs, .. } => {
1342 for expr in exprs {
1343 f(expr)?;
1344 }
1345 }
1346 If { cond, then, els } => {
1347 f(cond)?;
1348 f(then)?;
1349 f(els)?;
1350 }
1351 }
1352 Ok(())
1353 }
1354
1355 fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
1356 where
1357 F: FnMut(&mut Self) -> Result<(), E>,
1358 {
1359 use MirScalarExpr::*;
1360 match self {
1361 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1362 CallUnary { expr, .. } => {
1363 f(expr)?;
1364 }
1365 CallBinary { expr1, expr2, .. } => {
1366 f(expr1)?;
1367 f(expr2)?;
1368 }
1369 CallVariadic { exprs, .. } => {
1370 for expr in exprs {
1371 f(expr)?;
1372 }
1373 }
1374 If { cond, then, els } => {
1375 f(cond)?;
1376 f(then)?;
1377 f(els)?;
1378 }
1379 }
1380 Ok(())
1381 }
1382
1383 fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Self>
1384 where
1385 Self: 'a,
1386 {
1387 self.children()
1388 }
1389
1390 fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut Self>
1391 where
1392 Self: 'a,
1393 {
1394 self.children_mut()
1395 }
1396}
1397
1398impl MirScalarExpr {
1399 pub fn children(&self) -> impl DoubleEndedIterator<Item = &Self> {
1401 let mut first = None;
1402 let mut second = None;
1403 let mut third = None;
1404 let mut variadic = None;
1405
1406 use MirScalarExpr::*;
1407 match self {
1408 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1409 CallUnary { expr, .. } => {
1410 first = Some(&**expr);
1411 }
1412 CallBinary { expr1, expr2, .. } => {
1413 first = Some(&**expr1);
1414 second = Some(&**expr2);
1415 }
1416 CallVariadic { exprs, .. } => {
1417 variadic = Some(exprs);
1418 }
1419 If { cond, then, els } => {
1420 first = Some(&**cond);
1421 second = Some(&**then);
1422 third = Some(&**els);
1423 }
1424 }
1425
1426 first
1427 .into_iter()
1428 .chain(second)
1429 .chain(third)
1430 .chain(variadic.into_iter().flatten())
1431 }
1432
1433 pub fn children_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Self> {
1435 let mut first = None;
1436 let mut second = None;
1437 let mut third = None;
1438 let mut variadic = None;
1439
1440 use MirScalarExpr::*;
1441 match self {
1442 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1443 CallUnary { expr, .. } => {
1444 first = Some(&mut **expr);
1445 }
1446 CallBinary { expr1, expr2, .. } => {
1447 first = Some(&mut **expr1);
1448 second = Some(&mut **expr2);
1449 }
1450 CallVariadic { exprs, .. } => {
1451 variadic = Some(exprs);
1452 }
1453 If { cond, then, els } => {
1454 first = Some(&mut **cond);
1455 second = Some(&mut **then);
1456 third = Some(&mut **els);
1457 }
1458 }
1459
1460 first
1461 .into_iter()
1462 .chain(second)
1463 .chain(third)
1464 .chain(variadic.into_iter().flatten())
1465 }
1466
1467 pub fn visit_pre<F>(&self, mut f: F)
1469 where
1470 F: FnMut(&Self),
1471 {
1472 let mut worklist = vec![self];
1473 while let Some(e) = worklist.pop() {
1474 f(e);
1475 worklist.extend(e.children().rev());
1476 }
1477 }
1478
1479 pub fn visit_pre_mut<F: FnMut(&mut Self)>(&mut self, mut f: F) {
1481 let mut worklist = vec![self];
1482 while let Some(expr) = worklist.pop() {
1483 f(expr);
1484 worklist.extend(expr.children_mut().rev());
1485 }
1486 }
1487}
1488
1489#[derive(
1496 Eq,
1497 PartialEq,
1498 Ord,
1499 PartialOrd,
1500 Debug,
1501 Clone,
1502 Serialize,
1503 Deserialize,
1504 Hash,
1505 MzReflect
1506)]
1507pub struct FilterCharacteristics {
1508 literal_equality: bool,
1511 like: bool,
1513 is_null: bool,
1514 literal_inequality: usize,
1520 any_filter: bool,
1526}
1527
1528impl BitOrAssign for FilterCharacteristics {
1529 fn bitor_assign(&mut self, rhs: Self) {
1530 self.literal_equality |= rhs.literal_equality;
1531 self.like |= rhs.like;
1532 self.is_null |= rhs.is_null;
1533 self.literal_inequality += rhs.literal_inequality;
1534 self.any_filter |= rhs.any_filter;
1535 }
1536}
1537
1538impl FilterCharacteristics {
1539 pub fn none() -> FilterCharacteristics {
1540 FilterCharacteristics {
1541 literal_equality: false,
1542 like: false,
1543 is_null: false,
1544 literal_inequality: 0,
1545 any_filter: false,
1546 }
1547 }
1548
1549 pub fn explain(&self) -> String {
1550 let mut e = "".to_owned();
1551 if self.literal_equality {
1552 e.push_str("e");
1553 }
1554 if self.like {
1555 e.push_str("l");
1556 }
1557 if self.is_null {
1558 e.push_str("n");
1559 }
1560 for _ in 0..self.literal_inequality {
1561 e.push_str("i");
1562 }
1563 if self.any_filter {
1564 e.push_str("f");
1565 }
1566 e
1567 }
1568
1569 pub fn filter_characteristics(
1570 filters: &Vec<MirScalarExpr>,
1571 ) -> Result<FilterCharacteristics, RecursionLimitError> {
1572 let mut literal_equality = false;
1573 let mut like = false;
1574 let mut is_null = false;
1575 let mut literal_inequality = 0;
1576 let mut any_filter = false;
1577 filters.iter().try_for_each(|f| {
1578 let mut literal_inequality_in_current_filter = false;
1579 let mut is_not_null_in_current_filter = false;
1580 f.visit_pre_with_context(
1581 false,
1582 &mut |not_in_parent_chain, expr| {
1583 not_in_parent_chain
1584 || matches!(
1585 expr,
1586 MirScalarExpr::CallUnary {
1587 func: UnaryFunc::Not(func::Not),
1588 ..
1589 }
1590 )
1591 },
1592 &mut |not_in_parent_chain, expr| {
1593 if !not_in_parent_chain {
1594 if expr.any_expr_eq_literal().is_some() {
1595 literal_equality = true;
1596 }
1597 if expr.any_expr_ineq_literal() {
1598 literal_inequality_in_current_filter = true;
1599 }
1600 if matches!(
1601 expr,
1602 MirScalarExpr::CallUnary {
1603 func: UnaryFunc::IsLikeMatch(_),
1604 ..
1605 }
1606 ) {
1607 like = true;
1608 }
1609 };
1610 if matches!(
1611 expr,
1612 MirScalarExpr::CallUnary {
1613 func: UnaryFunc::IsNull(crate::func::IsNull),
1614 ..
1615 }
1616 ) {
1617 if *not_in_parent_chain {
1618 is_not_null_in_current_filter = true;
1619 } else {
1620 is_null = true;
1621 }
1622 }
1623 },
1624 );
1625 if literal_inequality_in_current_filter {
1626 literal_inequality += 1;
1627 }
1628 if !is_not_null_in_current_filter {
1629 any_filter = true;
1631 }
1632 Ok(())
1633 })?;
1634 Ok(FilterCharacteristics {
1635 literal_equality,
1636 like,
1637 is_null,
1638 literal_inequality,
1639 any_filter,
1640 })
1641 }
1642
1643 pub fn add_literal_equality(&mut self) {
1644 self.literal_equality = true;
1645 }
1646
1647 pub fn worst_case_scaling_factor(&self) -> f64 {
1648 let mut factor = 1.0;
1649
1650 if self.literal_equality {
1651 factor *= 0.1;
1652 }
1653
1654 if self.is_null {
1655 factor *= 0.1;
1656 }
1657
1658 if self.literal_inequality >= 2 {
1659 factor *= 0.25;
1660 } else if self.literal_inequality == 1 {
1661 factor *= 0.33;
1662 }
1663
1664 if !(self.literal_equality || self.is_null || self.literal_inequality > 0)
1666 && self.any_filter
1667 {
1668 factor *= 0.9;
1669 }
1670
1671 factor
1672 }
1673}
1674
1675#[derive(
1676 Ord,
1677 PartialOrd,
1678 Copy,
1679 Clone,
1680 Debug,
1681 Eq,
1682 PartialEq,
1683 Serialize,
1684 Deserialize,
1685 Hash,
1686 MzReflect
1687)]
1688#[cfg_attr(any(test, feature = "proptest"), derive(Arbitrary))]
1689pub enum DomainLimit {
1690 None,
1691 Inclusive(i64),
1692 Exclusive(i64),
1693}
1694
1695impl RustType<ProtoDomainLimit> for DomainLimit {
1696 fn into_proto(&self) -> ProtoDomainLimit {
1697 use proto_domain_limit::Kind::*;
1698 let kind = match self {
1699 DomainLimit::None => None(()),
1700 DomainLimit::Inclusive(v) => Inclusive(*v),
1701 DomainLimit::Exclusive(v) => Exclusive(*v),
1702 };
1703 ProtoDomainLimit { kind: Some(kind) }
1704 }
1705
1706 fn from_proto(proto: ProtoDomainLimit) -> Result<Self, TryFromProtoError> {
1707 use proto_domain_limit::Kind::*;
1708 if let Some(kind) = proto.kind {
1709 match kind {
1710 None(()) => Ok(DomainLimit::None),
1711 Inclusive(v) => Ok(DomainLimit::Inclusive(v)),
1712 Exclusive(v) => Ok(DomainLimit::Exclusive(v)),
1713 }
1714 } else {
1715 Err(TryFromProtoError::missing_field("ProtoDomainLimit::kind"))
1716 }
1717 }
1718}
1719
1720#[derive(
1721 Ord,
1722 PartialOrd,
1723 Clone,
1724 Debug,
1725 Eq,
1726 PartialEq,
1727 Serialize,
1728 Deserialize,
1729 Hash,
1730 MzReflect
1731)]
1732#[cfg_attr(any(test, feature = "proptest"), derive(Arbitrary))]
1733pub enum EvalError {
1734 CharacterNotValidForEncoding(i32),
1735 CharacterTooLargeForEncoding(i32),
1736 DateBinOutOfRange(Box<str>),
1737 DivisionByZero,
1738 Unsupported {
1739 feature: Box<str>,
1740 discussion_no: Option<usize>,
1741 },
1742 FloatOverflow,
1743 FloatUnderflow,
1744 NumericFieldOverflow,
1745 Float32OutOfRange(Box<str>),
1746 Float64OutOfRange(Box<str>),
1747 Int16OutOfRange(Box<str>),
1748 Int32OutOfRange(Box<str>),
1749 Int64OutOfRange(Box<str>),
1750 UInt16OutOfRange(Box<str>),
1751 UInt32OutOfRange(Box<str>),
1752 UInt64OutOfRange(Box<str>),
1753 MzTimestampOutOfRange(Box<str>),
1754 MzTimestampStepOverflow,
1755 OidOutOfRange(Box<str>),
1756 IntervalOutOfRange(Box<str>),
1757 TimestampCannotBeNan,
1758 TimestampOutOfRange,
1759 DateOutOfRange,
1760 CharOutOfRange,
1761 IndexOutOfRange {
1762 provided: i32,
1763 valid_end: i32,
1765 },
1766 InvalidBase64Equals,
1767 InvalidBase64Symbol(char),
1768 InvalidBase64EndSequence,
1769 InvalidTimezone(Box<str>),
1770 InvalidTimezoneInterval,
1771 InvalidTimezoneConversion,
1772 InvalidIanaTimezoneId(Box<str>),
1773 InvalidLayer {
1774 max_layer: usize,
1775 val: i64,
1776 },
1777 InvalidArray(InvalidArrayError),
1778 InvalidEncodingName(Box<str>),
1779 InvalidHashAlgorithm(Box<str>),
1780 InvalidByteSequence {
1781 byte_sequence: Box<str>,
1782 encoding_name: Box<str>,
1783 },
1784 InvalidJsonbCast {
1785 from: Box<str>,
1786 to: Box<str>,
1787 },
1788 InvalidRegex(Box<str>),
1789 InvalidRegexFlag(char),
1790 InvalidParameterValue(Box<str>),
1791 InvalidDatePart(Box<str>),
1792 KeyCannotBeNull,
1793 NegSqrt,
1794 NegLimit,
1795 NullCharacterNotPermitted,
1796 UnknownUnits(Box<str>),
1797 UnsupportedUnits(Box<str>, Box<str>),
1798 UnterminatedLikeEscapeSequence,
1799 Parse(ParseError),
1800 ParseHex(ParseHexError),
1801 Internal(Box<str>),
1802 InfinityOutOfDomain(Box<str>),
1803 NegativeOutOfDomain(Box<str>),
1804 ZeroOutOfDomain(Box<str>),
1805 OutOfDomain(DomainLimit, DomainLimit, Box<str>),
1806 ComplexOutOfRange(Box<str>),
1807 MultipleRowsFromSubquery,
1808 NegativeRowsFromSubquery,
1809 Undefined(Box<str>),
1810 LikePatternTooLong,
1811 LikeEscapeTooLong,
1812 StringValueTooLong {
1813 target_type: Box<str>,
1814 length: usize,
1815 },
1816 MultidimensionalArrayRemovalNotSupported,
1817 IncompatibleArrayDimensions {
1818 dims: Option<(usize, usize)>,
1819 },
1820 TypeFromOid(Box<str>),
1821 InvalidRange(InvalidRangeError),
1822 InvalidRoleId(Box<str>),
1823 InvalidPrivileges(Box<str>),
1824 InvalidCatalogJson(Box<str>),
1825 LetRecLimitExceeded(Box<str>),
1826 MultiDimensionalArraySearch,
1827 MustNotBeNull(Box<str>),
1828 InvalidIdentifier {
1829 ident: Box<str>,
1830 detail: Option<Box<str>>,
1831 },
1832 ArrayFillWrongArraySubscripts,
1833 MaxArraySizeExceeded(usize),
1835 DateDiffOverflow {
1836 unit: Box<str>,
1837 a: Box<str>,
1838 b: Box<str>,
1839 },
1840 IfNullError(Box<str>),
1843 LengthTooLarge,
1844 AclArrayNullElement,
1845 MzAclArrayNullElement,
1846 PrettyError(Box<str>),
1847 RedactError(Box<str>),
1848}
1849
1850impl fmt::Display for EvalError {
1851 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1852 match self {
1853 EvalError::CharacterNotValidForEncoding(v) => {
1854 write!(f, "requested character not valid for encoding: {v}")
1855 }
1856 EvalError::CharacterTooLargeForEncoding(v) => {
1857 write!(f, "requested character too large for encoding: {v}")
1858 }
1859 EvalError::DateBinOutOfRange(message) => f.write_str(message),
1860 EvalError::DivisionByZero => f.write_str("division by zero"),
1861 EvalError::Unsupported {
1862 feature,
1863 discussion_no,
1864 } => {
1865 write!(f, "{} not yet supported", feature)?;
1866 if let Some(discussion_no) = discussion_no {
1867 write!(
1868 f,
1869 ", see https://github.com/MaterializeInc/materialize/discussions/{} for more details",
1870 discussion_no
1871 )?;
1872 }
1873 Ok(())
1874 }
1875 EvalError::FloatOverflow => f.write_str("value out of range: overflow"),
1876 EvalError::FloatUnderflow => f.write_str("value out of range: underflow"),
1877 EvalError::NumericFieldOverflow => f.write_str("numeric field overflow"),
1878 EvalError::Float32OutOfRange(val) => write!(f, "{} real out of range", val.quoted()),
1879 EvalError::Float64OutOfRange(val) => {
1880 write!(f, "{} double precision out of range", val.quoted())
1881 }
1882 EvalError::Int16OutOfRange(val) => write!(f, "{} smallint out of range", val.quoted()),
1883 EvalError::Int32OutOfRange(val) => write!(f, "{} integer out of range", val.quoted()),
1884 EvalError::Int64OutOfRange(val) => write!(f, "{} bigint out of range", val.quoted()),
1885 EvalError::UInt16OutOfRange(val) => write!(f, "{} uint2 out of range", val.quoted()),
1886 EvalError::UInt32OutOfRange(val) => write!(f, "{} uint4 out of range", val.quoted()),
1887 EvalError::UInt64OutOfRange(val) => write!(f, "{} uint8 out of range", val.quoted()),
1888 EvalError::MzTimestampOutOfRange(val) => {
1889 write!(f, "{} mz_timestamp out of range", val.quoted())
1890 }
1891 EvalError::MzTimestampStepOverflow => f.write_str("step mz_timestamp overflow"),
1892 EvalError::OidOutOfRange(val) => write!(f, "{} OID out of range", val.quoted()),
1893 EvalError::IntervalOutOfRange(val) => {
1894 write!(f, "{} interval out of range", val.quoted())
1895 }
1896 EvalError::TimestampCannotBeNan => f.write_str("timestamp cannot be NaN"),
1897 EvalError::TimestampOutOfRange => f.write_str("timestamp out of range"),
1898 EvalError::DateOutOfRange => f.write_str("date out of range"),
1899 EvalError::CharOutOfRange => f.write_str("\"char\" out of range"),
1900 EvalError::IndexOutOfRange {
1901 provided,
1902 valid_end,
1903 } => write!(f, "index {provided} out of valid range, 0..{valid_end}",),
1904 EvalError::InvalidBase64Equals => {
1905 f.write_str("unexpected \"=\" while decoding base64 sequence")
1906 }
1907 EvalError::InvalidBase64Symbol(c) => write!(
1908 f,
1909 "invalid symbol \"{}\" found while decoding base64 sequence",
1910 c.escape_default()
1911 ),
1912 EvalError::InvalidBase64EndSequence => f.write_str("invalid base64 end sequence"),
1913 EvalError::InvalidJsonbCast { from, to } => {
1914 write!(f, "cannot cast jsonb {} to type {}", from, to)
1915 }
1916 EvalError::InvalidTimezone(tz) => write!(f, "invalid time zone '{}'", tz),
1917 EvalError::InvalidTimezoneInterval => {
1918 f.write_str("timezone interval must not contain months or years")
1919 }
1920 EvalError::InvalidTimezoneConversion => f.write_str("invalid timezone conversion"),
1921 EvalError::InvalidIanaTimezoneId(tz) => {
1922 write!(f, "invalid IANA Time Zone Database identifier: '{}'", tz)
1923 }
1924 EvalError::InvalidLayer { max_layer, val } => write!(
1925 f,
1926 "invalid layer: {}; must use value within [1, {}]",
1927 val, max_layer
1928 ),
1929 EvalError::InvalidArray(e) => e.fmt(f),
1930 EvalError::InvalidEncodingName(name) => write!(f, "invalid encoding name '{}'", name),
1931 EvalError::InvalidHashAlgorithm(alg) => write!(f, "invalid hash algorithm '{}'", alg),
1932 EvalError::InvalidByteSequence {
1933 byte_sequence,
1934 encoding_name,
1935 } => write!(
1936 f,
1937 "invalid byte sequence '{}' for encoding '{}'",
1938 byte_sequence, encoding_name
1939 ),
1940 EvalError::InvalidDatePart(part) => write!(f, "invalid datepart {}", part.quoted()),
1941 EvalError::KeyCannotBeNull => f.write_str("key cannot be null"),
1942 EvalError::NegSqrt => f.write_str("cannot take square root of a negative number"),
1943 EvalError::NegLimit => f.write_str("LIMIT must not be negative"),
1944 EvalError::NullCharacterNotPermitted => f.write_str("null character not permitted"),
1945 EvalError::InvalidRegex(e) => write!(f, "invalid regular expression: {}", e),
1946 EvalError::InvalidRegexFlag(c) => write!(f, "invalid regular expression flag: {}", c),
1947 EvalError::InvalidParameterValue(s) => f.write_str(s),
1948 EvalError::UnknownUnits(units) => write!(f, "unit '{}' not recognized", units),
1949 EvalError::UnsupportedUnits(units, typ) => {
1950 write!(f, "unit '{}' not supported for type {}", units, typ)
1951 }
1952 EvalError::UnterminatedLikeEscapeSequence => {
1953 f.write_str("unterminated escape sequence in LIKE")
1954 }
1955 EvalError::Parse(e) => e.fmt(f),
1956 EvalError::PrettyError(e) => e.fmt(f),
1957 EvalError::RedactError(e) => e.fmt(f),
1958 EvalError::ParseHex(e) => e.fmt(f),
1959 EvalError::Internal(s) => write!(f, "internal error: {}", s),
1960 EvalError::InfinityOutOfDomain(s) => {
1961 write!(f, "function {} is only defined for finite arguments", s)
1962 }
1963 EvalError::NegativeOutOfDomain(s) => {
1964 write!(f, "function {} is not defined for negative numbers", s)
1965 }
1966 EvalError::ZeroOutOfDomain(s) => {
1967 write!(f, "function {} is not defined for zero", s)
1968 }
1969 EvalError::OutOfDomain(lower, upper, s) => {
1970 use DomainLimit::*;
1971 write!(f, "function {s} is defined for numbers ")?;
1972 match (lower, upper) {
1973 (Inclusive(n), None) => write!(f, "greater than or equal to {n}"),
1974 (Exclusive(n), None) => write!(f, "greater than {n}"),
1975 (None, Inclusive(n)) => write!(f, "less than or equal to {n}"),
1976 (None, Exclusive(n)) => write!(f, "less than {n}"),
1977 (Inclusive(lo), Inclusive(hi)) => write!(f, "between {lo} and {hi} inclusive"),
1978 (Exclusive(lo), Exclusive(hi)) => write!(f, "between {lo} and {hi} exclusive"),
1979 (Inclusive(lo), Exclusive(hi)) => {
1980 write!(f, "between {lo} inclusive and {hi} exclusive")
1981 }
1982 (Exclusive(lo), Inclusive(hi)) => {
1983 write!(f, "between {lo} exclusive and {hi} inclusive")
1984 }
1985 (None, None) => panic!("invalid domain error"),
1986 }
1987 }
1988 EvalError::ComplexOutOfRange(s) => {
1989 write!(f, "function {} cannot return complex numbers", s)
1990 }
1991 EvalError::MultipleRowsFromSubquery => {
1992 write!(f, "more than one record produced in subquery")
1993 }
1994 EvalError::NegativeRowsFromSubquery => {
1995 write!(f, "negative number of rows produced in subquery")
1996 }
1997 EvalError::Undefined(s) => {
1998 write!(f, "{} is undefined", s)
1999 }
2000 EvalError::LikePatternTooLong => {
2001 write!(f, "LIKE pattern exceeds maximum length")
2002 }
2003 EvalError::LikeEscapeTooLong => {
2004 write!(f, "invalid escape string")
2005 }
2006 EvalError::StringValueTooLong {
2007 target_type,
2008 length,
2009 } => {
2010 write!(f, "value too long for type {}({})", target_type, length)
2011 }
2012 EvalError::MultidimensionalArrayRemovalNotSupported => {
2013 write!(
2014 f,
2015 "removing elements from multidimensional arrays is not supported"
2016 )
2017 }
2018 EvalError::IncompatibleArrayDimensions { dims: _ } => {
2019 write!(f, "cannot concatenate incompatible arrays")
2020 }
2021 EvalError::TypeFromOid(msg) => write!(f, "{msg}"),
2022 EvalError::InvalidRange(e) => e.fmt(f),
2023 EvalError::InvalidRoleId(msg) => write!(f, "{msg}"),
2024 EvalError::InvalidPrivileges(privilege) => {
2025 write!(f, "unrecognized privilege type: {privilege}")
2026 }
2027 EvalError::InvalidCatalogJson(msg) => {
2028 write!(f, "invalid catalog JSON: {msg}")
2029 }
2030 EvalError::LetRecLimitExceeded(max_iters) => {
2031 write!(
2032 f,
2033 "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.)",
2034 max_iters
2035 )
2036 }
2037 EvalError::MultiDimensionalArraySearch => write!(
2038 f,
2039 "searching for elements in multidimensional arrays is not supported"
2040 ),
2041 EvalError::MustNotBeNull(v) => write!(f, "{v} must not be null"),
2042 EvalError::InvalidIdentifier { ident, .. } => {
2043 write!(f, "string is not a valid identifier: {}", ident.quoted())
2044 }
2045 EvalError::ArrayFillWrongArraySubscripts => {
2046 f.write_str("wrong number of array subscripts")
2047 }
2048 EvalError::MaxArraySizeExceeded(max_size) => {
2049 write!(
2050 f,
2051 "array size exceeds the maximum allowed ({max_size} bytes)"
2052 )
2053 }
2054 EvalError::DateDiffOverflow { unit, a, b } => {
2055 write!(f, "datediff overflow, {unit} of {a}, {b}")
2056 }
2057 EvalError::IfNullError(s) => f.write_str(s),
2058 EvalError::LengthTooLarge => write!(f, "requested length too large"),
2059 EvalError::AclArrayNullElement => write!(f, "ACL arrays must not contain null values"),
2060 EvalError::MzAclArrayNullElement => {
2061 write!(f, "MZ_ACL arrays must not contain null values")
2062 }
2063 }
2064 }
2065}
2066
2067impl EvalError {
2068 pub fn detail(&self) -> Option<String> {
2069 match self {
2070 EvalError::IncompatibleArrayDimensions { dims: None } => Some(
2071 "Arrays with differing dimensions are not compatible for concatenation.".into(),
2072 ),
2073 EvalError::IncompatibleArrayDimensions {
2074 dims: Some((a_dims, b_dims)),
2075 } => Some(format!(
2076 "Arrays of {} and {} dimensions are not compatible for concatenation.",
2077 a_dims, b_dims
2078 )),
2079 EvalError::InvalidIdentifier { detail, .. } => detail.as_deref().map(Into::into),
2080 EvalError::ArrayFillWrongArraySubscripts => {
2081 Some("Low bound array has different size than dimensions array.".into())
2082 }
2083 _ => None,
2084 }
2085 }
2086
2087 pub fn hint(&self) -> Option<String> {
2088 match self {
2089 EvalError::InvalidBase64EndSequence => Some(
2090 "Input data is missing padding, is truncated, or is otherwise corrupted.".into(),
2091 ),
2092 EvalError::LikeEscapeTooLong => {
2093 Some("Escape string must be empty or one character.".into())
2094 }
2095 EvalError::MzTimestampOutOfRange(_) => Some(
2096 "Integer, numeric, and text casts to mz_timestamp must be in the form of whole \
2097 milliseconds since the Unix epoch. Values with fractional parts cannot be \
2098 converted to mz_timestamp."
2099 .into(),
2100 ),
2101 _ => None,
2102 }
2103 }
2104}
2105
2106impl std::error::Error for EvalError {}
2107
2108impl From<ParseError> for EvalError {
2109 fn from(e: ParseError) -> EvalError {
2110 EvalError::Parse(e)
2111 }
2112}
2113
2114impl From<ParseHexError> for EvalError {
2115 fn from(e: ParseHexError) -> EvalError {
2116 EvalError::ParseHex(e)
2117 }
2118}
2119
2120impl From<InvalidArrayError> for EvalError {
2121 fn from(e: InvalidArrayError) -> EvalError {
2122 EvalError::InvalidArray(e)
2123 }
2124}
2125
2126impl From<RegexCompilationError> for EvalError {
2127 fn from(e: RegexCompilationError) -> EvalError {
2128 EvalError::InvalidRegex(e.to_string().into())
2129 }
2130}
2131
2132impl From<TypeFromOidError> for EvalError {
2133 fn from(e: TypeFromOidError) -> EvalError {
2134 EvalError::TypeFromOid(e.to_string().into())
2135 }
2136}
2137
2138impl From<DateError> for EvalError {
2139 fn from(e: DateError) -> EvalError {
2140 match e {
2141 DateError::OutOfRange => EvalError::DateOutOfRange,
2142 }
2143 }
2144}
2145
2146impl From<TimestampError> for EvalError {
2147 fn from(e: TimestampError) -> EvalError {
2148 match e {
2149 TimestampError::OutOfRange => EvalError::TimestampOutOfRange,
2150 }
2151 }
2152}
2153
2154impl From<InvalidRangeError> for EvalError {
2155 fn from(e: InvalidRangeError) -> EvalError {
2156 EvalError::InvalidRange(e)
2157 }
2158}
2159
2160impl RustType<ProtoEvalError> for EvalError {
2161 fn into_proto(&self) -> ProtoEvalError {
2162 use proto_eval_error::Kind::*;
2163 use proto_eval_error::*;
2164 let kind = match self {
2165 EvalError::CharacterNotValidForEncoding(v) => CharacterNotValidForEncoding(*v),
2166 EvalError::CharacterTooLargeForEncoding(v) => CharacterTooLargeForEncoding(*v),
2167 EvalError::DateBinOutOfRange(v) => DateBinOutOfRange(v.into_proto()),
2168 EvalError::DivisionByZero => DivisionByZero(()),
2169 EvalError::Unsupported {
2170 feature,
2171 discussion_no,
2172 } => Unsupported(ProtoUnsupported {
2173 feature: feature.into_proto(),
2174 discussion_no: discussion_no.into_proto(),
2175 }),
2176 EvalError::FloatOverflow => FloatOverflow(()),
2177 EvalError::FloatUnderflow => FloatUnderflow(()),
2178 EvalError::NumericFieldOverflow => NumericFieldOverflow(()),
2179 EvalError::Float32OutOfRange(val) => Float32OutOfRange(ProtoValueOutOfRange {
2180 value: val.to_string(),
2181 }),
2182 EvalError::Float64OutOfRange(val) => Float64OutOfRange(ProtoValueOutOfRange {
2183 value: val.to_string(),
2184 }),
2185 EvalError::Int16OutOfRange(val) => Int16OutOfRange(ProtoValueOutOfRange {
2186 value: val.to_string(),
2187 }),
2188 EvalError::Int32OutOfRange(val) => Int32OutOfRange(ProtoValueOutOfRange {
2189 value: val.to_string(),
2190 }),
2191 EvalError::Int64OutOfRange(val) => Int64OutOfRange(ProtoValueOutOfRange {
2192 value: val.to_string(),
2193 }),
2194 EvalError::UInt16OutOfRange(val) => Uint16OutOfRange(ProtoValueOutOfRange {
2195 value: val.to_string(),
2196 }),
2197 EvalError::UInt32OutOfRange(val) => Uint32OutOfRange(ProtoValueOutOfRange {
2198 value: val.to_string(),
2199 }),
2200 EvalError::UInt64OutOfRange(val) => Uint64OutOfRange(ProtoValueOutOfRange {
2201 value: val.to_string(),
2202 }),
2203 EvalError::MzTimestampOutOfRange(val) => MzTimestampOutOfRange(ProtoValueOutOfRange {
2204 value: val.to_string(),
2205 }),
2206 EvalError::MzTimestampStepOverflow => MzTimestampStepOverflow(()),
2207 EvalError::OidOutOfRange(val) => OidOutOfRange(ProtoValueOutOfRange {
2208 value: val.to_string(),
2209 }),
2210 EvalError::IntervalOutOfRange(val) => IntervalOutOfRange(ProtoValueOutOfRange {
2211 value: val.to_string(),
2212 }),
2213 EvalError::TimestampCannotBeNan => TimestampCannotBeNan(()),
2214 EvalError::TimestampOutOfRange => TimestampOutOfRange(()),
2215 EvalError::DateOutOfRange => DateOutOfRange(()),
2216 EvalError::CharOutOfRange => CharOutOfRange(()),
2217 EvalError::IndexOutOfRange {
2218 provided,
2219 valid_end,
2220 } => IndexOutOfRange(ProtoIndexOutOfRange {
2221 provided: *provided,
2222 valid_end: *valid_end,
2223 }),
2224 EvalError::InvalidBase64Equals => InvalidBase64Equals(()),
2225 EvalError::InvalidBase64Symbol(sym) => InvalidBase64Symbol(sym.into_proto()),
2226 EvalError::InvalidBase64EndSequence => InvalidBase64EndSequence(()),
2227 EvalError::InvalidTimezone(tz) => InvalidTimezone(tz.into_proto()),
2228 EvalError::InvalidTimezoneInterval => InvalidTimezoneInterval(()),
2229 EvalError::InvalidTimezoneConversion => InvalidTimezoneConversion(()),
2230 EvalError::InvalidLayer { max_layer, val } => InvalidLayer(ProtoInvalidLayer {
2231 max_layer: max_layer.into_proto(),
2232 val: *val,
2233 }),
2234 EvalError::InvalidArray(error) => InvalidArray(error.into_proto()),
2235 EvalError::InvalidEncodingName(v) => InvalidEncodingName(v.into_proto()),
2236 EvalError::InvalidHashAlgorithm(v) => InvalidHashAlgorithm(v.into_proto()),
2237 EvalError::InvalidByteSequence {
2238 byte_sequence,
2239 encoding_name,
2240 } => InvalidByteSequence(ProtoInvalidByteSequence {
2241 byte_sequence: byte_sequence.into_proto(),
2242 encoding_name: encoding_name.into_proto(),
2243 }),
2244 EvalError::InvalidJsonbCast { from, to } => InvalidJsonbCast(ProtoInvalidJsonbCast {
2245 from: from.into_proto(),
2246 to: to.into_proto(),
2247 }),
2248 EvalError::InvalidRegex(v) => InvalidRegex(v.into_proto()),
2249 EvalError::InvalidRegexFlag(v) => InvalidRegexFlag(v.into_proto()),
2250 EvalError::InvalidParameterValue(v) => InvalidParameterValue(v.into_proto()),
2251 EvalError::InvalidDatePart(part) => InvalidDatePart(part.into_proto()),
2252 EvalError::KeyCannotBeNull => KeyCannotBeNull(()),
2253 EvalError::NegSqrt => NegSqrt(()),
2254 EvalError::NegLimit => NegLimit(()),
2255 EvalError::NullCharacterNotPermitted => NullCharacterNotPermitted(()),
2256 EvalError::UnknownUnits(v) => UnknownUnits(v.into_proto()),
2257 EvalError::UnsupportedUnits(units, typ) => UnsupportedUnits(ProtoUnsupportedUnits {
2258 units: units.into_proto(),
2259 typ: typ.into_proto(),
2260 }),
2261 EvalError::UnterminatedLikeEscapeSequence => UnterminatedLikeEscapeSequence(()),
2262 EvalError::Parse(error) => Parse(error.into_proto()),
2263 EvalError::PrettyError(error) => PrettyError(error.into_proto()),
2264 EvalError::RedactError(error) => RedactError(error.into_proto()),
2265 EvalError::ParseHex(error) => ParseHex(error.into_proto()),
2266 EvalError::Internal(v) => Internal(v.into_proto()),
2267 EvalError::InfinityOutOfDomain(v) => InfinityOutOfDomain(v.into_proto()),
2268 EvalError::NegativeOutOfDomain(v) => NegativeOutOfDomain(v.into_proto()),
2269 EvalError::ZeroOutOfDomain(v) => ZeroOutOfDomain(v.into_proto()),
2270 EvalError::OutOfDomain(lower, upper, id) => OutOfDomain(ProtoOutOfDomain {
2271 lower: Some(lower.into_proto()),
2272 upper: Some(upper.into_proto()),
2273 id: id.into_proto(),
2274 }),
2275 EvalError::ComplexOutOfRange(v) => ComplexOutOfRange(v.into_proto()),
2276 EvalError::MultipleRowsFromSubquery => MultipleRowsFromSubquery(()),
2277 EvalError::NegativeRowsFromSubquery => NegativeRowsFromSubquery(()),
2278 EvalError::Undefined(v) => Undefined(v.into_proto()),
2279 EvalError::LikePatternTooLong => LikePatternTooLong(()),
2280 EvalError::LikeEscapeTooLong => LikeEscapeTooLong(()),
2281 EvalError::StringValueTooLong {
2282 target_type,
2283 length,
2284 } => StringValueTooLong(ProtoStringValueTooLong {
2285 target_type: target_type.into_proto(),
2286 length: length.into_proto(),
2287 }),
2288 EvalError::MultidimensionalArrayRemovalNotSupported => {
2289 MultidimensionalArrayRemovalNotSupported(())
2290 }
2291 EvalError::IncompatibleArrayDimensions { dims } => {
2292 IncompatibleArrayDimensions(ProtoIncompatibleArrayDimensions {
2293 dims: dims.into_proto(),
2294 })
2295 }
2296 EvalError::TypeFromOid(v) => TypeFromOid(v.into_proto()),
2297 EvalError::InvalidRange(error) => InvalidRange(error.into_proto()),
2298 EvalError::InvalidRoleId(v) => InvalidRoleId(v.into_proto()),
2299 EvalError::InvalidPrivileges(v) => InvalidPrivileges(v.into_proto()),
2300 EvalError::InvalidCatalogJson(v) => InvalidCatalogJson(v.into_proto()),
2301 EvalError::LetRecLimitExceeded(v) => WmrRecursionLimitExceeded(v.into_proto()),
2302 EvalError::MultiDimensionalArraySearch => MultiDimensionalArraySearch(()),
2303 EvalError::MustNotBeNull(v) => MustNotBeNull(v.into_proto()),
2304 EvalError::InvalidIdentifier { ident, detail } => {
2305 InvalidIdentifier(ProtoInvalidIdentifier {
2306 ident: ident.into_proto(),
2307 detail: detail.into_proto(),
2308 })
2309 }
2310 EvalError::ArrayFillWrongArraySubscripts => ArrayFillWrongArraySubscripts(()),
2311 EvalError::MaxArraySizeExceeded(max_size) => {
2312 MaxArraySizeExceeded(u64::cast_from(*max_size))
2313 }
2314 EvalError::DateDiffOverflow { unit, a, b } => DateDiffOverflow(ProtoDateDiffOverflow {
2315 unit: unit.into_proto(),
2316 a: a.into_proto(),
2317 b: b.into_proto(),
2318 }),
2319 EvalError::IfNullError(s) => IfNullError(s.into_proto()),
2320 EvalError::LengthTooLarge => LengthTooLarge(()),
2321 EvalError::AclArrayNullElement => AclArrayNullElement(()),
2322 EvalError::MzAclArrayNullElement => MzAclArrayNullElement(()),
2323 EvalError::InvalidIanaTimezoneId(s) => InvalidIanaTimezoneId(s.into_proto()),
2324 };
2325 ProtoEvalError { kind: Some(kind) }
2326 }
2327
2328 fn from_proto(proto: ProtoEvalError) -> Result<Self, TryFromProtoError> {
2329 use proto_eval_error::Kind::*;
2330 match proto.kind {
2331 Some(kind) => match kind {
2332 CharacterNotValidForEncoding(v) => Ok(EvalError::CharacterNotValidForEncoding(v)),
2333 CharacterTooLargeForEncoding(v) => Ok(EvalError::CharacterTooLargeForEncoding(v)),
2334 DateBinOutOfRange(v) => Ok(EvalError::DateBinOutOfRange(v.into())),
2335 DivisionByZero(()) => Ok(EvalError::DivisionByZero),
2336 Unsupported(v) => Ok(EvalError::Unsupported {
2337 feature: v.feature.into(),
2338 discussion_no: v.discussion_no.into_rust()?,
2339 }),
2340 FloatOverflow(()) => Ok(EvalError::FloatOverflow),
2341 FloatUnderflow(()) => Ok(EvalError::FloatUnderflow),
2342 NumericFieldOverflow(()) => Ok(EvalError::NumericFieldOverflow),
2343 Float32OutOfRange(val) => Ok(EvalError::Float32OutOfRange(val.value.into())),
2344 Float64OutOfRange(val) => Ok(EvalError::Float64OutOfRange(val.value.into())),
2345 Int16OutOfRange(val) => Ok(EvalError::Int16OutOfRange(val.value.into())),
2346 Int32OutOfRange(val) => Ok(EvalError::Int32OutOfRange(val.value.into())),
2347 Int64OutOfRange(val) => Ok(EvalError::Int64OutOfRange(val.value.into())),
2348 Uint16OutOfRange(val) => Ok(EvalError::UInt16OutOfRange(val.value.into())),
2349 Uint32OutOfRange(val) => Ok(EvalError::UInt32OutOfRange(val.value.into())),
2350 Uint64OutOfRange(val) => Ok(EvalError::UInt64OutOfRange(val.value.into())),
2351 MzTimestampOutOfRange(val) => {
2352 Ok(EvalError::MzTimestampOutOfRange(val.value.into()))
2353 }
2354 MzTimestampStepOverflow(()) => Ok(EvalError::MzTimestampStepOverflow),
2355 OidOutOfRange(val) => Ok(EvalError::OidOutOfRange(val.value.into())),
2356 IntervalOutOfRange(val) => Ok(EvalError::IntervalOutOfRange(val.value.into())),
2357 TimestampCannotBeNan(()) => Ok(EvalError::TimestampCannotBeNan),
2358 TimestampOutOfRange(()) => Ok(EvalError::TimestampOutOfRange),
2359 DateOutOfRange(()) => Ok(EvalError::DateOutOfRange),
2360 CharOutOfRange(()) => Ok(EvalError::CharOutOfRange),
2361 IndexOutOfRange(v) => Ok(EvalError::IndexOutOfRange {
2362 provided: v.provided,
2363 valid_end: v.valid_end,
2364 }),
2365 InvalidBase64Equals(()) => Ok(EvalError::InvalidBase64Equals),
2366 InvalidBase64Symbol(v) => char::from_proto(v).map(EvalError::InvalidBase64Symbol),
2367 InvalidBase64EndSequence(()) => Ok(EvalError::InvalidBase64EndSequence),
2368 InvalidTimezone(v) => Ok(EvalError::InvalidTimezone(v.into())),
2369 InvalidTimezoneInterval(()) => Ok(EvalError::InvalidTimezoneInterval),
2370 InvalidTimezoneConversion(()) => Ok(EvalError::InvalidTimezoneConversion),
2371 InvalidLayer(v) => Ok(EvalError::InvalidLayer {
2372 max_layer: usize::from_proto(v.max_layer)?,
2373 val: v.val,
2374 }),
2375 InvalidArray(error) => Ok(EvalError::InvalidArray(error.into_rust()?)),
2376 InvalidEncodingName(v) => Ok(EvalError::InvalidEncodingName(v.into())),
2377 InvalidHashAlgorithm(v) => Ok(EvalError::InvalidHashAlgorithm(v.into())),
2378 InvalidByteSequence(v) => Ok(EvalError::InvalidByteSequence {
2379 byte_sequence: v.byte_sequence.into(),
2380 encoding_name: v.encoding_name.into(),
2381 }),
2382 InvalidJsonbCast(v) => Ok(EvalError::InvalidJsonbCast {
2383 from: v.from.into(),
2384 to: v.to.into(),
2385 }),
2386 InvalidRegex(v) => Ok(EvalError::InvalidRegex(v.into())),
2387 InvalidRegexFlag(v) => Ok(EvalError::InvalidRegexFlag(char::from_proto(v)?)),
2388 InvalidParameterValue(v) => Ok(EvalError::InvalidParameterValue(v.into())),
2389 InvalidDatePart(part) => Ok(EvalError::InvalidDatePart(part.into())),
2390 KeyCannotBeNull(()) => Ok(EvalError::KeyCannotBeNull),
2391 NegSqrt(()) => Ok(EvalError::NegSqrt),
2392 NegLimit(()) => Ok(EvalError::NegLimit),
2393 NullCharacterNotPermitted(()) => Ok(EvalError::NullCharacterNotPermitted),
2394 UnknownUnits(v) => Ok(EvalError::UnknownUnits(v.into())),
2395 UnsupportedUnits(v) => {
2396 Ok(EvalError::UnsupportedUnits(v.units.into(), v.typ.into()))
2397 }
2398 UnterminatedLikeEscapeSequence(()) => Ok(EvalError::UnterminatedLikeEscapeSequence),
2399 Parse(error) => Ok(EvalError::Parse(error.into_rust()?)),
2400 ParseHex(error) => Ok(EvalError::ParseHex(error.into_rust()?)),
2401 Internal(v) => Ok(EvalError::Internal(v.into())),
2402 InfinityOutOfDomain(v) => Ok(EvalError::InfinityOutOfDomain(v.into())),
2403 NegativeOutOfDomain(v) => Ok(EvalError::NegativeOutOfDomain(v.into())),
2404 ZeroOutOfDomain(v) => Ok(EvalError::ZeroOutOfDomain(v.into())),
2405 OutOfDomain(v) => Ok(EvalError::OutOfDomain(
2406 v.lower.into_rust_if_some("ProtoDomainLimit::lower")?,
2407 v.upper.into_rust_if_some("ProtoDomainLimit::upper")?,
2408 v.id.into(),
2409 )),
2410 ComplexOutOfRange(v) => Ok(EvalError::ComplexOutOfRange(v.into())),
2411 MultipleRowsFromSubquery(()) => Ok(EvalError::MultipleRowsFromSubquery),
2412 NegativeRowsFromSubquery(()) => Ok(EvalError::NegativeRowsFromSubquery),
2413 Undefined(v) => Ok(EvalError::Undefined(v.into())),
2414 LikePatternTooLong(()) => Ok(EvalError::LikePatternTooLong),
2415 LikeEscapeTooLong(()) => Ok(EvalError::LikeEscapeTooLong),
2416 StringValueTooLong(v) => Ok(EvalError::StringValueTooLong {
2417 target_type: v.target_type.into(),
2418 length: usize::from_proto(v.length)?,
2419 }),
2420 MultidimensionalArrayRemovalNotSupported(()) => {
2421 Ok(EvalError::MultidimensionalArrayRemovalNotSupported)
2422 }
2423 IncompatibleArrayDimensions(v) => Ok(EvalError::IncompatibleArrayDimensions {
2424 dims: v.dims.into_rust()?,
2425 }),
2426 TypeFromOid(v) => Ok(EvalError::TypeFromOid(v.into())),
2427 InvalidRange(e) => Ok(EvalError::InvalidRange(e.into_rust()?)),
2428 InvalidRoleId(v) => Ok(EvalError::InvalidRoleId(v.into())),
2429 InvalidPrivileges(v) => Ok(EvalError::InvalidPrivileges(v.into())),
2430 InvalidCatalogJson(v) => Ok(EvalError::InvalidCatalogJson(v.into())),
2431 WmrRecursionLimitExceeded(v) => Ok(EvalError::LetRecLimitExceeded(v.into())),
2432 MultiDimensionalArraySearch(()) => Ok(EvalError::MultiDimensionalArraySearch),
2433 MustNotBeNull(v) => Ok(EvalError::MustNotBeNull(v.into())),
2434 InvalidIdentifier(v) => Ok(EvalError::InvalidIdentifier {
2435 ident: v.ident.into(),
2436 detail: v.detail.into_rust()?,
2437 }),
2438 ArrayFillWrongArraySubscripts(()) => Ok(EvalError::ArrayFillWrongArraySubscripts),
2439 MaxArraySizeExceeded(max_size) => {
2440 Ok(EvalError::MaxArraySizeExceeded(usize::cast_from(max_size)))
2441 }
2442 DateDiffOverflow(v) => Ok(EvalError::DateDiffOverflow {
2443 unit: v.unit.into(),
2444 a: v.a.into(),
2445 b: v.b.into(),
2446 }),
2447 IfNullError(v) => Ok(EvalError::IfNullError(v.into())),
2448 LengthTooLarge(()) => Ok(EvalError::LengthTooLarge),
2449 AclArrayNullElement(()) => Ok(EvalError::AclArrayNullElement),
2450 MzAclArrayNullElement(()) => Ok(EvalError::MzAclArrayNullElement),
2451 InvalidIanaTimezoneId(s) => Ok(EvalError::InvalidIanaTimezoneId(s.into())),
2452 PrettyError(s) => Ok(EvalError::PrettyError(s.into())),
2453 RedactError(s) => Ok(EvalError::RedactError(s.into())),
2454 },
2455 None => Err(TryFromProtoError::missing_field("ProtoEvalError::kind")),
2456 }
2457 }
2458}
2459
2460impl RustType<ProtoDims> for (usize, usize) {
2461 fn into_proto(&self) -> ProtoDims {
2462 ProtoDims {
2463 f0: self.0.into_proto(),
2464 f1: self.1.into_proto(),
2465 }
2466 }
2467
2468 fn from_proto(proto: ProtoDims) -> Result<Self, TryFromProtoError> {
2469 Ok((proto.f0.into_rust()?, proto.f1.into_rust()?))
2470 }
2471}
2472
2473#[cfg(test)]
2474mod tests {
2475 use super::*;
2476 use crate::scalar::func::variadic::Coalesce;
2477
2478 #[mz_ore::test]
2479 #[cfg_attr(miri, ignore)] fn test_reduce() {
2481 let relation_type: Vec<ReprColumnType> = vec![
2482 ReprScalarType::Int64.nullable(true),
2483 ReprScalarType::Int64.nullable(true),
2484 ReprScalarType::Int64.nullable(false),
2485 ]
2486 .into_iter()
2487 .collect();
2488 let col = MirScalarExpr::column;
2489 let int64_typ = ReprScalarType::Int64;
2490 let err = |e| MirScalarExpr::literal(Err(e), int64_typ.clone());
2491 let lit = |i| MirScalarExpr::literal_ok(Datum::Int64(i), int64_typ.clone());
2492 let null = || MirScalarExpr::literal_null(int64_typ.clone());
2493
2494 struct TestCase {
2495 input: MirScalarExpr,
2496 output: MirScalarExpr,
2497 }
2498
2499 let test_cases = vec![
2500 TestCase {
2501 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1)]),
2502 output: lit(1),
2503 },
2504 TestCase {
2505 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1), lit(2)]),
2506 output: lit(1),
2507 },
2508 TestCase {
2509 input: MirScalarExpr::call_variadic(Coalesce, vec![null(), lit(2), null()]),
2510 output: lit(2),
2511 },
2512 TestCase {
2513 input: MirScalarExpr::call_variadic(
2514 Coalesce,
2515 vec![null(), col(0), null(), col(1), lit(2), lit(3)],
2516 ),
2517 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(1), lit(2)]),
2518 },
2519 TestCase {
2520 input: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2), col(1)]),
2521 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2)]),
2522 },
2523 TestCase {
2524 input: MirScalarExpr::call_variadic(
2525 Coalesce,
2526 vec![lit(1), err(EvalError::DivisionByZero)],
2527 ),
2528 output: lit(1),
2529 },
2530 TestCase {
2531 input: MirScalarExpr::call_variadic(
2532 Coalesce,
2533 vec![
2534 null(),
2535 err(EvalError::DivisionByZero),
2536 err(EvalError::NumericFieldOverflow),
2537 ],
2538 ),
2539 output: err(EvalError::DivisionByZero),
2540 },
2541 ];
2542
2543 for tc in test_cases {
2544 let mut actual = tc.input.clone();
2545 actual.reduce(&relation_type);
2546 assert!(
2547 actual == tc.output,
2548 "input: {}\nactual: {}\nexpected: {}",
2549 tc.input,
2550 actual,
2551 tc.output
2552 );
2553 }
2554 }
2555
2556 #[mz_ore::test]
2560 fn test_visit_mut_post_replace_subtrees() {
2561 let col = MirScalarExpr::column;
2562 let mut expr = col(0).if_then_else(col(1).if_then_else(col(2), col(3)), col(4));
2563
2564 expr.visit_mut_post(&mut |expr: &mut MirScalarExpr| match expr {
2565 MirScalarExpr::Column(n, _) => *n += 1,
2566 MirScalarExpr::If { then, .. } => {
2567 let then = then.take();
2568 *expr = then;
2569 }
2570 _ => {}
2571 });
2572
2573 assert_eq!(expr, col(3));
2575 }
2576
2577 #[mz_ore::test]
2583 fn test_visit_mut_pre_post_explicit_children() {
2584 let col = MirScalarExpr::column;
2585 let mut expr = col(5)
2586 .if_then_else(col(6), col(7))
2587 .if_then_else(col(1).if_then_else(col(2), col(3)), col(4));
2588
2589 expr.visit_mut_pre_post(
2593 &mut |expr: &mut MirScalarExpr| -> Option<Vec<&mut MirScalarExpr>> {
2594 if let MirScalarExpr::If { .. } = expr {
2595 let MirScalarExpr::If { then, els, .. } = expr else {
2596 unreachable!()
2597 };
2598 let then = then.take();
2599 let els = els.take();
2600 *expr = MirScalarExpr::column(0).if_then_else(then, els);
2601
2602 let MirScalarExpr::If { then, els, .. } = expr else {
2603 unreachable!()
2604 };
2605 Some(vec![then.as_mut(), els.as_mut()])
2606 } else {
2607 None
2609 }
2610 },
2611 &mut |expr: &mut MirScalarExpr| {
2612 if let MirScalarExpr::Column(n, _) = expr {
2613 *n += 10;
2614 }
2615 },
2616 );
2617
2618 let expected = col(0).if_then_else(col(0).if_then_else(col(12), col(13)), col(14));
2620 assert_eq!(expr, expected);
2621 }
2622}