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 E: From<RecursionLimitError>,
1331 {
1332 use MirScalarExpr::*;
1333 match self {
1334 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1335 CallUnary { expr, .. } => {
1336 f(expr)?;
1337 }
1338 CallBinary { expr1, expr2, .. } => {
1339 f(expr1)?;
1340 f(expr2)?;
1341 }
1342 CallVariadic { exprs, .. } => {
1343 for expr in exprs {
1344 f(expr)?;
1345 }
1346 }
1347 If { cond, then, els } => {
1348 f(cond)?;
1349 f(then)?;
1350 f(els)?;
1351 }
1352 }
1353 Ok(())
1354 }
1355
1356 fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
1357 where
1358 F: FnMut(&mut Self) -> Result<(), E>,
1359 E: From<RecursionLimitError>,
1360 {
1361 use MirScalarExpr::*;
1362 match self {
1363 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1364 CallUnary { expr, .. } => {
1365 f(expr)?;
1366 }
1367 CallBinary { expr1, expr2, .. } => {
1368 f(expr1)?;
1369 f(expr2)?;
1370 }
1371 CallVariadic { exprs, .. } => {
1372 for expr in exprs {
1373 f(expr)?;
1374 }
1375 }
1376 If { cond, then, els } => {
1377 f(cond)?;
1378 f(then)?;
1379 f(els)?;
1380 }
1381 }
1382 Ok(())
1383 }
1384}
1385
1386impl MirScalarExpr {
1387 pub fn children(&self) -> impl DoubleEndedIterator<Item = &Self> {
1389 let mut first = None;
1390 let mut second = None;
1391 let mut third = None;
1392 let mut variadic = None;
1393
1394 use MirScalarExpr::*;
1395 match self {
1396 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1397 CallUnary { expr, .. } => {
1398 first = Some(&**expr);
1399 }
1400 CallBinary { expr1, expr2, .. } => {
1401 first = Some(&**expr1);
1402 second = Some(&**expr2);
1403 }
1404 CallVariadic { exprs, .. } => {
1405 variadic = Some(exprs);
1406 }
1407 If { cond, then, els } => {
1408 first = Some(&**cond);
1409 second = Some(&**then);
1410 third = Some(&**els);
1411 }
1412 }
1413
1414 first
1415 .into_iter()
1416 .chain(second)
1417 .chain(third)
1418 .chain(variadic.into_iter().flatten())
1419 }
1420
1421 pub fn children_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Self> {
1423 let mut first = None;
1424 let mut second = None;
1425 let mut third = None;
1426 let mut variadic = None;
1427
1428 use MirScalarExpr::*;
1429 match self {
1430 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1431 CallUnary { expr, .. } => {
1432 first = Some(&mut **expr);
1433 }
1434 CallBinary { expr1, expr2, .. } => {
1435 first = Some(&mut **expr1);
1436 second = Some(&mut **expr2);
1437 }
1438 CallVariadic { exprs, .. } => {
1439 variadic = Some(exprs);
1440 }
1441 If { cond, then, els } => {
1442 first = Some(&mut **cond);
1443 second = Some(&mut **then);
1444 third = Some(&mut **els);
1445 }
1446 }
1447
1448 first
1449 .into_iter()
1450 .chain(second)
1451 .chain(third)
1452 .chain(variadic.into_iter().flatten())
1453 }
1454
1455 pub fn visit_pre<F>(&self, mut f: F)
1457 where
1458 F: FnMut(&Self),
1459 {
1460 let mut worklist = vec![self];
1461 while let Some(e) = worklist.pop() {
1462 f(e);
1463 worklist.extend(e.children().rev());
1464 }
1465 }
1466
1467 pub fn visit_pre_mut<F: FnMut(&mut Self)>(&mut self, mut f: F) {
1469 let mut worklist = vec![self];
1470 while let Some(expr) = worklist.pop() {
1471 f(expr);
1472 worklist.extend(expr.children_mut().rev());
1473 }
1474 }
1475}
1476
1477#[derive(
1484 Eq,
1485 PartialEq,
1486 Ord,
1487 PartialOrd,
1488 Debug,
1489 Clone,
1490 Serialize,
1491 Deserialize,
1492 Hash,
1493 MzReflect
1494)]
1495pub struct FilterCharacteristics {
1496 literal_equality: bool,
1499 like: bool,
1501 is_null: bool,
1502 literal_inequality: usize,
1508 any_filter: bool,
1514}
1515
1516impl BitOrAssign for FilterCharacteristics {
1517 fn bitor_assign(&mut self, rhs: Self) {
1518 self.literal_equality |= rhs.literal_equality;
1519 self.like |= rhs.like;
1520 self.is_null |= rhs.is_null;
1521 self.literal_inequality += rhs.literal_inequality;
1522 self.any_filter |= rhs.any_filter;
1523 }
1524}
1525
1526impl FilterCharacteristics {
1527 pub fn none() -> FilterCharacteristics {
1528 FilterCharacteristics {
1529 literal_equality: false,
1530 like: false,
1531 is_null: false,
1532 literal_inequality: 0,
1533 any_filter: false,
1534 }
1535 }
1536
1537 pub fn explain(&self) -> String {
1538 let mut e = "".to_owned();
1539 if self.literal_equality {
1540 e.push_str("e");
1541 }
1542 if self.like {
1543 e.push_str("l");
1544 }
1545 if self.is_null {
1546 e.push_str("n");
1547 }
1548 for _ in 0..self.literal_inequality {
1549 e.push_str("i");
1550 }
1551 if self.any_filter {
1552 e.push_str("f");
1553 }
1554 e
1555 }
1556
1557 pub fn filter_characteristics(
1558 filters: &Vec<MirScalarExpr>,
1559 ) -> Result<FilterCharacteristics, RecursionLimitError> {
1560 let mut literal_equality = false;
1561 let mut like = false;
1562 let mut is_null = false;
1563 let mut literal_inequality = 0;
1564 let mut any_filter = false;
1565 filters.iter().try_for_each(|f| {
1566 let mut literal_inequality_in_current_filter = false;
1567 let mut is_not_null_in_current_filter = false;
1568 f.visit_pre_with_context(
1569 false,
1570 &mut |not_in_parent_chain, expr| {
1571 not_in_parent_chain
1572 || matches!(
1573 expr,
1574 MirScalarExpr::CallUnary {
1575 func: UnaryFunc::Not(func::Not),
1576 ..
1577 }
1578 )
1579 },
1580 &mut |not_in_parent_chain, expr| {
1581 if !not_in_parent_chain {
1582 if expr.any_expr_eq_literal().is_some() {
1583 literal_equality = true;
1584 }
1585 if expr.any_expr_ineq_literal() {
1586 literal_inequality_in_current_filter = true;
1587 }
1588 if matches!(
1589 expr,
1590 MirScalarExpr::CallUnary {
1591 func: UnaryFunc::IsLikeMatch(_),
1592 ..
1593 }
1594 ) {
1595 like = true;
1596 }
1597 };
1598 if matches!(
1599 expr,
1600 MirScalarExpr::CallUnary {
1601 func: UnaryFunc::IsNull(crate::func::IsNull),
1602 ..
1603 }
1604 ) {
1605 if *not_in_parent_chain {
1606 is_not_null_in_current_filter = true;
1607 } else {
1608 is_null = true;
1609 }
1610 }
1611 },
1612 )?;
1613 if literal_inequality_in_current_filter {
1614 literal_inequality += 1;
1615 }
1616 if !is_not_null_in_current_filter {
1617 any_filter = true;
1619 }
1620 Ok(())
1621 })?;
1622 Ok(FilterCharacteristics {
1623 literal_equality,
1624 like,
1625 is_null,
1626 literal_inequality,
1627 any_filter,
1628 })
1629 }
1630
1631 pub fn add_literal_equality(&mut self) {
1632 self.literal_equality = true;
1633 }
1634
1635 pub fn worst_case_scaling_factor(&self) -> f64 {
1636 let mut factor = 1.0;
1637
1638 if self.literal_equality {
1639 factor *= 0.1;
1640 }
1641
1642 if self.is_null {
1643 factor *= 0.1;
1644 }
1645
1646 if self.literal_inequality >= 2 {
1647 factor *= 0.25;
1648 } else if self.literal_inequality == 1 {
1649 factor *= 0.33;
1650 }
1651
1652 if !(self.literal_equality || self.is_null || self.literal_inequality > 0)
1654 && self.any_filter
1655 {
1656 factor *= 0.9;
1657 }
1658
1659 factor
1660 }
1661}
1662
1663#[derive(
1664 Ord,
1665 PartialOrd,
1666 Copy,
1667 Clone,
1668 Debug,
1669 Eq,
1670 PartialEq,
1671 Serialize,
1672 Deserialize,
1673 Hash,
1674 MzReflect
1675)]
1676#[cfg_attr(any(test, feature = "proptest"), derive(Arbitrary))]
1677pub enum DomainLimit {
1678 None,
1679 Inclusive(i64),
1680 Exclusive(i64),
1681}
1682
1683impl RustType<ProtoDomainLimit> for DomainLimit {
1684 fn into_proto(&self) -> ProtoDomainLimit {
1685 use proto_domain_limit::Kind::*;
1686 let kind = match self {
1687 DomainLimit::None => None(()),
1688 DomainLimit::Inclusive(v) => Inclusive(*v),
1689 DomainLimit::Exclusive(v) => Exclusive(*v),
1690 };
1691 ProtoDomainLimit { kind: Some(kind) }
1692 }
1693
1694 fn from_proto(proto: ProtoDomainLimit) -> Result<Self, TryFromProtoError> {
1695 use proto_domain_limit::Kind::*;
1696 if let Some(kind) = proto.kind {
1697 match kind {
1698 None(()) => Ok(DomainLimit::None),
1699 Inclusive(v) => Ok(DomainLimit::Inclusive(v)),
1700 Exclusive(v) => Ok(DomainLimit::Exclusive(v)),
1701 }
1702 } else {
1703 Err(TryFromProtoError::missing_field("ProtoDomainLimit::kind"))
1704 }
1705 }
1706}
1707
1708#[derive(
1709 Ord,
1710 PartialOrd,
1711 Clone,
1712 Debug,
1713 Eq,
1714 PartialEq,
1715 Serialize,
1716 Deserialize,
1717 Hash,
1718 MzReflect
1719)]
1720#[cfg_attr(any(test, feature = "proptest"), derive(Arbitrary))]
1721pub enum EvalError {
1722 CharacterNotValidForEncoding(i32),
1723 CharacterTooLargeForEncoding(i32),
1724 DateBinOutOfRange(Box<str>),
1725 DivisionByZero,
1726 Unsupported {
1727 feature: Box<str>,
1728 discussion_no: Option<usize>,
1729 },
1730 FloatOverflow,
1731 FloatUnderflow,
1732 NumericFieldOverflow,
1733 Float32OutOfRange(Box<str>),
1734 Float64OutOfRange(Box<str>),
1735 Int16OutOfRange(Box<str>),
1736 Int32OutOfRange(Box<str>),
1737 Int64OutOfRange(Box<str>),
1738 UInt16OutOfRange(Box<str>),
1739 UInt32OutOfRange(Box<str>),
1740 UInt64OutOfRange(Box<str>),
1741 MzTimestampOutOfRange(Box<str>),
1742 MzTimestampStepOverflow,
1743 OidOutOfRange(Box<str>),
1744 IntervalOutOfRange(Box<str>),
1745 TimestampCannotBeNan,
1746 TimestampOutOfRange,
1747 DateOutOfRange,
1748 CharOutOfRange,
1749 IndexOutOfRange {
1750 provided: i32,
1751 valid_end: i32,
1753 },
1754 InvalidBase64Equals,
1755 InvalidBase64Symbol(char),
1756 InvalidBase64EndSequence,
1757 InvalidTimezone(Box<str>),
1758 InvalidTimezoneInterval,
1759 InvalidTimezoneConversion,
1760 InvalidIanaTimezoneId(Box<str>),
1761 InvalidLayer {
1762 max_layer: usize,
1763 val: i64,
1764 },
1765 InvalidArray(InvalidArrayError),
1766 InvalidEncodingName(Box<str>),
1767 InvalidHashAlgorithm(Box<str>),
1768 InvalidByteSequence {
1769 byte_sequence: Box<str>,
1770 encoding_name: Box<str>,
1771 },
1772 InvalidJsonbCast {
1773 from: Box<str>,
1774 to: Box<str>,
1775 },
1776 InvalidRegex(Box<str>),
1777 InvalidRegexFlag(char),
1778 InvalidParameterValue(Box<str>),
1779 InvalidDatePart(Box<str>),
1780 KeyCannotBeNull,
1781 NegSqrt,
1782 NegLimit,
1783 NullCharacterNotPermitted,
1784 UnknownUnits(Box<str>),
1785 UnsupportedUnits(Box<str>, Box<str>),
1786 UnterminatedLikeEscapeSequence,
1787 Parse(ParseError),
1788 ParseHex(ParseHexError),
1789 Internal(Box<str>),
1790 InfinityOutOfDomain(Box<str>),
1791 NegativeOutOfDomain(Box<str>),
1792 ZeroOutOfDomain(Box<str>),
1793 OutOfDomain(DomainLimit, DomainLimit, Box<str>),
1794 ComplexOutOfRange(Box<str>),
1795 MultipleRowsFromSubquery,
1796 NegativeRowsFromSubquery,
1797 Undefined(Box<str>),
1798 LikePatternTooLong,
1799 LikeEscapeTooLong,
1800 StringValueTooLong {
1801 target_type: Box<str>,
1802 length: usize,
1803 },
1804 MultidimensionalArrayRemovalNotSupported,
1805 IncompatibleArrayDimensions {
1806 dims: Option<(usize, usize)>,
1807 },
1808 TypeFromOid(Box<str>),
1809 InvalidRange(InvalidRangeError),
1810 InvalidRoleId(Box<str>),
1811 InvalidPrivileges(Box<str>),
1812 InvalidCatalogJson(Box<str>),
1813 LetRecLimitExceeded(Box<str>),
1814 MultiDimensionalArraySearch,
1815 MustNotBeNull(Box<str>),
1816 InvalidIdentifier {
1817 ident: Box<str>,
1818 detail: Option<Box<str>>,
1819 },
1820 ArrayFillWrongArraySubscripts,
1821 MaxArraySizeExceeded(usize),
1823 DateDiffOverflow {
1824 unit: Box<str>,
1825 a: Box<str>,
1826 b: Box<str>,
1827 },
1828 IfNullError(Box<str>),
1831 LengthTooLarge,
1832 AclArrayNullElement,
1833 MzAclArrayNullElement,
1834 PrettyError(Box<str>),
1835 RedactError(Box<str>),
1836}
1837
1838impl fmt::Display for EvalError {
1839 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1840 match self {
1841 EvalError::CharacterNotValidForEncoding(v) => {
1842 write!(f, "requested character not valid for encoding: {v}")
1843 }
1844 EvalError::CharacterTooLargeForEncoding(v) => {
1845 write!(f, "requested character too large for encoding: {v}")
1846 }
1847 EvalError::DateBinOutOfRange(message) => f.write_str(message),
1848 EvalError::DivisionByZero => f.write_str("division by zero"),
1849 EvalError::Unsupported {
1850 feature,
1851 discussion_no,
1852 } => {
1853 write!(f, "{} not yet supported", feature)?;
1854 if let Some(discussion_no) = discussion_no {
1855 write!(
1856 f,
1857 ", see https://github.com/MaterializeInc/materialize/discussions/{} for more details",
1858 discussion_no
1859 )?;
1860 }
1861 Ok(())
1862 }
1863 EvalError::FloatOverflow => f.write_str("value out of range: overflow"),
1864 EvalError::FloatUnderflow => f.write_str("value out of range: underflow"),
1865 EvalError::NumericFieldOverflow => f.write_str("numeric field overflow"),
1866 EvalError::Float32OutOfRange(val) => write!(f, "{} real out of range", val.quoted()),
1867 EvalError::Float64OutOfRange(val) => {
1868 write!(f, "{} double precision out of range", val.quoted())
1869 }
1870 EvalError::Int16OutOfRange(val) => write!(f, "{} smallint out of range", val.quoted()),
1871 EvalError::Int32OutOfRange(val) => write!(f, "{} integer out of range", val.quoted()),
1872 EvalError::Int64OutOfRange(val) => write!(f, "{} bigint out of range", val.quoted()),
1873 EvalError::UInt16OutOfRange(val) => write!(f, "{} uint2 out of range", val.quoted()),
1874 EvalError::UInt32OutOfRange(val) => write!(f, "{} uint4 out of range", val.quoted()),
1875 EvalError::UInt64OutOfRange(val) => write!(f, "{} uint8 out of range", val.quoted()),
1876 EvalError::MzTimestampOutOfRange(val) => {
1877 write!(f, "{} mz_timestamp out of range", val.quoted())
1878 }
1879 EvalError::MzTimestampStepOverflow => f.write_str("step mz_timestamp overflow"),
1880 EvalError::OidOutOfRange(val) => write!(f, "{} OID out of range", val.quoted()),
1881 EvalError::IntervalOutOfRange(val) => {
1882 write!(f, "{} interval out of range", val.quoted())
1883 }
1884 EvalError::TimestampCannotBeNan => f.write_str("timestamp cannot be NaN"),
1885 EvalError::TimestampOutOfRange => f.write_str("timestamp out of range"),
1886 EvalError::DateOutOfRange => f.write_str("date out of range"),
1887 EvalError::CharOutOfRange => f.write_str("\"char\" out of range"),
1888 EvalError::IndexOutOfRange {
1889 provided,
1890 valid_end,
1891 } => write!(f, "index {provided} out of valid range, 0..{valid_end}",),
1892 EvalError::InvalidBase64Equals => {
1893 f.write_str("unexpected \"=\" while decoding base64 sequence")
1894 }
1895 EvalError::InvalidBase64Symbol(c) => write!(
1896 f,
1897 "invalid symbol \"{}\" found while decoding base64 sequence",
1898 c.escape_default()
1899 ),
1900 EvalError::InvalidBase64EndSequence => f.write_str("invalid base64 end sequence"),
1901 EvalError::InvalidJsonbCast { from, to } => {
1902 write!(f, "cannot cast jsonb {} to type {}", from, to)
1903 }
1904 EvalError::InvalidTimezone(tz) => write!(f, "invalid time zone '{}'", tz),
1905 EvalError::InvalidTimezoneInterval => {
1906 f.write_str("timezone interval must not contain months or years")
1907 }
1908 EvalError::InvalidTimezoneConversion => f.write_str("invalid timezone conversion"),
1909 EvalError::InvalidIanaTimezoneId(tz) => {
1910 write!(f, "invalid IANA Time Zone Database identifier: '{}'", tz)
1911 }
1912 EvalError::InvalidLayer { max_layer, val } => write!(
1913 f,
1914 "invalid layer: {}; must use value within [1, {}]",
1915 val, max_layer
1916 ),
1917 EvalError::InvalidArray(e) => e.fmt(f),
1918 EvalError::InvalidEncodingName(name) => write!(f, "invalid encoding name '{}'", name),
1919 EvalError::InvalidHashAlgorithm(alg) => write!(f, "invalid hash algorithm '{}'", alg),
1920 EvalError::InvalidByteSequence {
1921 byte_sequence,
1922 encoding_name,
1923 } => write!(
1924 f,
1925 "invalid byte sequence '{}' for encoding '{}'",
1926 byte_sequence, encoding_name
1927 ),
1928 EvalError::InvalidDatePart(part) => write!(f, "invalid datepart {}", part.quoted()),
1929 EvalError::KeyCannotBeNull => f.write_str("key cannot be null"),
1930 EvalError::NegSqrt => f.write_str("cannot take square root of a negative number"),
1931 EvalError::NegLimit => f.write_str("LIMIT must not be negative"),
1932 EvalError::NullCharacterNotPermitted => f.write_str("null character not permitted"),
1933 EvalError::InvalidRegex(e) => write!(f, "invalid regular expression: {}", e),
1934 EvalError::InvalidRegexFlag(c) => write!(f, "invalid regular expression flag: {}", c),
1935 EvalError::InvalidParameterValue(s) => f.write_str(s),
1936 EvalError::UnknownUnits(units) => write!(f, "unit '{}' not recognized", units),
1937 EvalError::UnsupportedUnits(units, typ) => {
1938 write!(f, "unit '{}' not supported for type {}", units, typ)
1939 }
1940 EvalError::UnterminatedLikeEscapeSequence => {
1941 f.write_str("unterminated escape sequence in LIKE")
1942 }
1943 EvalError::Parse(e) => e.fmt(f),
1944 EvalError::PrettyError(e) => e.fmt(f),
1945 EvalError::RedactError(e) => e.fmt(f),
1946 EvalError::ParseHex(e) => e.fmt(f),
1947 EvalError::Internal(s) => write!(f, "internal error: {}", s),
1948 EvalError::InfinityOutOfDomain(s) => {
1949 write!(f, "function {} is only defined for finite arguments", s)
1950 }
1951 EvalError::NegativeOutOfDomain(s) => {
1952 write!(f, "function {} is not defined for negative numbers", s)
1953 }
1954 EvalError::ZeroOutOfDomain(s) => {
1955 write!(f, "function {} is not defined for zero", s)
1956 }
1957 EvalError::OutOfDomain(lower, upper, s) => {
1958 use DomainLimit::*;
1959 write!(f, "function {s} is defined for numbers ")?;
1960 match (lower, upper) {
1961 (Inclusive(n), None) => write!(f, "greater than or equal to {n}"),
1962 (Exclusive(n), None) => write!(f, "greater than {n}"),
1963 (None, Inclusive(n)) => write!(f, "less than or equal to {n}"),
1964 (None, Exclusive(n)) => write!(f, "less than {n}"),
1965 (Inclusive(lo), Inclusive(hi)) => write!(f, "between {lo} and {hi} inclusive"),
1966 (Exclusive(lo), Exclusive(hi)) => write!(f, "between {lo} and {hi} exclusive"),
1967 (Inclusive(lo), Exclusive(hi)) => {
1968 write!(f, "between {lo} inclusive and {hi} exclusive")
1969 }
1970 (Exclusive(lo), Inclusive(hi)) => {
1971 write!(f, "between {lo} exclusive and {hi} inclusive")
1972 }
1973 (None, None) => panic!("invalid domain error"),
1974 }
1975 }
1976 EvalError::ComplexOutOfRange(s) => {
1977 write!(f, "function {} cannot return complex numbers", s)
1978 }
1979 EvalError::MultipleRowsFromSubquery => {
1980 write!(f, "more than one record produced in subquery")
1981 }
1982 EvalError::NegativeRowsFromSubquery => {
1983 write!(f, "negative number of rows produced in subquery")
1984 }
1985 EvalError::Undefined(s) => {
1986 write!(f, "{} is undefined", s)
1987 }
1988 EvalError::LikePatternTooLong => {
1989 write!(f, "LIKE pattern exceeds maximum length")
1990 }
1991 EvalError::LikeEscapeTooLong => {
1992 write!(f, "invalid escape string")
1993 }
1994 EvalError::StringValueTooLong {
1995 target_type,
1996 length,
1997 } => {
1998 write!(f, "value too long for type {}({})", target_type, length)
1999 }
2000 EvalError::MultidimensionalArrayRemovalNotSupported => {
2001 write!(
2002 f,
2003 "removing elements from multidimensional arrays is not supported"
2004 )
2005 }
2006 EvalError::IncompatibleArrayDimensions { dims: _ } => {
2007 write!(f, "cannot concatenate incompatible arrays")
2008 }
2009 EvalError::TypeFromOid(msg) => write!(f, "{msg}"),
2010 EvalError::InvalidRange(e) => e.fmt(f),
2011 EvalError::InvalidRoleId(msg) => write!(f, "{msg}"),
2012 EvalError::InvalidPrivileges(privilege) => {
2013 write!(f, "unrecognized privilege type: {privilege}")
2014 }
2015 EvalError::InvalidCatalogJson(msg) => {
2016 write!(f, "invalid catalog JSON: {msg}")
2017 }
2018 EvalError::LetRecLimitExceeded(max_iters) => {
2019 write!(
2020 f,
2021 "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.)",
2022 max_iters
2023 )
2024 }
2025 EvalError::MultiDimensionalArraySearch => write!(
2026 f,
2027 "searching for elements in multidimensional arrays is not supported"
2028 ),
2029 EvalError::MustNotBeNull(v) => write!(f, "{v} must not be null"),
2030 EvalError::InvalidIdentifier { ident, .. } => {
2031 write!(f, "string is not a valid identifier: {}", ident.quoted())
2032 }
2033 EvalError::ArrayFillWrongArraySubscripts => {
2034 f.write_str("wrong number of array subscripts")
2035 }
2036 EvalError::MaxArraySizeExceeded(max_size) => {
2037 write!(
2038 f,
2039 "array size exceeds the maximum allowed ({max_size} bytes)"
2040 )
2041 }
2042 EvalError::DateDiffOverflow { unit, a, b } => {
2043 write!(f, "datediff overflow, {unit} of {a}, {b}")
2044 }
2045 EvalError::IfNullError(s) => f.write_str(s),
2046 EvalError::LengthTooLarge => write!(f, "requested length too large"),
2047 EvalError::AclArrayNullElement => write!(f, "ACL arrays must not contain null values"),
2048 EvalError::MzAclArrayNullElement => {
2049 write!(f, "MZ_ACL arrays must not contain null values")
2050 }
2051 }
2052 }
2053}
2054
2055impl EvalError {
2056 pub fn detail(&self) -> Option<String> {
2057 match self {
2058 EvalError::IncompatibleArrayDimensions { dims: None } => Some(
2059 "Arrays with differing dimensions are not compatible for concatenation.".into(),
2060 ),
2061 EvalError::IncompatibleArrayDimensions {
2062 dims: Some((a_dims, b_dims)),
2063 } => Some(format!(
2064 "Arrays of {} and {} dimensions are not compatible for concatenation.",
2065 a_dims, b_dims
2066 )),
2067 EvalError::InvalidIdentifier { detail, .. } => detail.as_deref().map(Into::into),
2068 EvalError::ArrayFillWrongArraySubscripts => {
2069 Some("Low bound array has different size than dimensions array.".into())
2070 }
2071 _ => None,
2072 }
2073 }
2074
2075 pub fn hint(&self) -> Option<String> {
2076 match self {
2077 EvalError::InvalidBase64EndSequence => Some(
2078 "Input data is missing padding, is truncated, or is otherwise corrupted.".into(),
2079 ),
2080 EvalError::LikeEscapeTooLong => {
2081 Some("Escape string must be empty or one character.".into())
2082 }
2083 EvalError::MzTimestampOutOfRange(_) => Some(
2084 "Integer, numeric, and text casts to mz_timestamp must be in the form of whole \
2085 milliseconds since the Unix epoch. Values with fractional parts cannot be \
2086 converted to mz_timestamp."
2087 .into(),
2088 ),
2089 _ => None,
2090 }
2091 }
2092}
2093
2094impl std::error::Error for EvalError {}
2095
2096impl From<ParseError> for EvalError {
2097 fn from(e: ParseError) -> EvalError {
2098 EvalError::Parse(e)
2099 }
2100}
2101
2102impl From<ParseHexError> for EvalError {
2103 fn from(e: ParseHexError) -> EvalError {
2104 EvalError::ParseHex(e)
2105 }
2106}
2107
2108impl From<InvalidArrayError> for EvalError {
2109 fn from(e: InvalidArrayError) -> EvalError {
2110 EvalError::InvalidArray(e)
2111 }
2112}
2113
2114impl From<RegexCompilationError> for EvalError {
2115 fn from(e: RegexCompilationError) -> EvalError {
2116 EvalError::InvalidRegex(e.to_string().into())
2117 }
2118}
2119
2120impl From<TypeFromOidError> for EvalError {
2121 fn from(e: TypeFromOidError) -> EvalError {
2122 EvalError::TypeFromOid(e.to_string().into())
2123 }
2124}
2125
2126impl From<DateError> for EvalError {
2127 fn from(e: DateError) -> EvalError {
2128 match e {
2129 DateError::OutOfRange => EvalError::DateOutOfRange,
2130 }
2131 }
2132}
2133
2134impl From<TimestampError> for EvalError {
2135 fn from(e: TimestampError) -> EvalError {
2136 match e {
2137 TimestampError::OutOfRange => EvalError::TimestampOutOfRange,
2138 }
2139 }
2140}
2141
2142impl From<InvalidRangeError> for EvalError {
2143 fn from(e: InvalidRangeError) -> EvalError {
2144 EvalError::InvalidRange(e)
2145 }
2146}
2147
2148impl RustType<ProtoEvalError> for EvalError {
2149 fn into_proto(&self) -> ProtoEvalError {
2150 use proto_eval_error::Kind::*;
2151 use proto_eval_error::*;
2152 let kind = match self {
2153 EvalError::CharacterNotValidForEncoding(v) => CharacterNotValidForEncoding(*v),
2154 EvalError::CharacterTooLargeForEncoding(v) => CharacterTooLargeForEncoding(*v),
2155 EvalError::DateBinOutOfRange(v) => DateBinOutOfRange(v.into_proto()),
2156 EvalError::DivisionByZero => DivisionByZero(()),
2157 EvalError::Unsupported {
2158 feature,
2159 discussion_no,
2160 } => Unsupported(ProtoUnsupported {
2161 feature: feature.into_proto(),
2162 discussion_no: discussion_no.into_proto(),
2163 }),
2164 EvalError::FloatOverflow => FloatOverflow(()),
2165 EvalError::FloatUnderflow => FloatUnderflow(()),
2166 EvalError::NumericFieldOverflow => NumericFieldOverflow(()),
2167 EvalError::Float32OutOfRange(val) => Float32OutOfRange(ProtoValueOutOfRange {
2168 value: val.to_string(),
2169 }),
2170 EvalError::Float64OutOfRange(val) => Float64OutOfRange(ProtoValueOutOfRange {
2171 value: val.to_string(),
2172 }),
2173 EvalError::Int16OutOfRange(val) => Int16OutOfRange(ProtoValueOutOfRange {
2174 value: val.to_string(),
2175 }),
2176 EvalError::Int32OutOfRange(val) => Int32OutOfRange(ProtoValueOutOfRange {
2177 value: val.to_string(),
2178 }),
2179 EvalError::Int64OutOfRange(val) => Int64OutOfRange(ProtoValueOutOfRange {
2180 value: val.to_string(),
2181 }),
2182 EvalError::UInt16OutOfRange(val) => Uint16OutOfRange(ProtoValueOutOfRange {
2183 value: val.to_string(),
2184 }),
2185 EvalError::UInt32OutOfRange(val) => Uint32OutOfRange(ProtoValueOutOfRange {
2186 value: val.to_string(),
2187 }),
2188 EvalError::UInt64OutOfRange(val) => Uint64OutOfRange(ProtoValueOutOfRange {
2189 value: val.to_string(),
2190 }),
2191 EvalError::MzTimestampOutOfRange(val) => MzTimestampOutOfRange(ProtoValueOutOfRange {
2192 value: val.to_string(),
2193 }),
2194 EvalError::MzTimestampStepOverflow => MzTimestampStepOverflow(()),
2195 EvalError::OidOutOfRange(val) => OidOutOfRange(ProtoValueOutOfRange {
2196 value: val.to_string(),
2197 }),
2198 EvalError::IntervalOutOfRange(val) => IntervalOutOfRange(ProtoValueOutOfRange {
2199 value: val.to_string(),
2200 }),
2201 EvalError::TimestampCannotBeNan => TimestampCannotBeNan(()),
2202 EvalError::TimestampOutOfRange => TimestampOutOfRange(()),
2203 EvalError::DateOutOfRange => DateOutOfRange(()),
2204 EvalError::CharOutOfRange => CharOutOfRange(()),
2205 EvalError::IndexOutOfRange {
2206 provided,
2207 valid_end,
2208 } => IndexOutOfRange(ProtoIndexOutOfRange {
2209 provided: *provided,
2210 valid_end: *valid_end,
2211 }),
2212 EvalError::InvalidBase64Equals => InvalidBase64Equals(()),
2213 EvalError::InvalidBase64Symbol(sym) => InvalidBase64Symbol(sym.into_proto()),
2214 EvalError::InvalidBase64EndSequence => InvalidBase64EndSequence(()),
2215 EvalError::InvalidTimezone(tz) => InvalidTimezone(tz.into_proto()),
2216 EvalError::InvalidTimezoneInterval => InvalidTimezoneInterval(()),
2217 EvalError::InvalidTimezoneConversion => InvalidTimezoneConversion(()),
2218 EvalError::InvalidLayer { max_layer, val } => InvalidLayer(ProtoInvalidLayer {
2219 max_layer: max_layer.into_proto(),
2220 val: *val,
2221 }),
2222 EvalError::InvalidArray(error) => InvalidArray(error.into_proto()),
2223 EvalError::InvalidEncodingName(v) => InvalidEncodingName(v.into_proto()),
2224 EvalError::InvalidHashAlgorithm(v) => InvalidHashAlgorithm(v.into_proto()),
2225 EvalError::InvalidByteSequence {
2226 byte_sequence,
2227 encoding_name,
2228 } => InvalidByteSequence(ProtoInvalidByteSequence {
2229 byte_sequence: byte_sequence.into_proto(),
2230 encoding_name: encoding_name.into_proto(),
2231 }),
2232 EvalError::InvalidJsonbCast { from, to } => InvalidJsonbCast(ProtoInvalidJsonbCast {
2233 from: from.into_proto(),
2234 to: to.into_proto(),
2235 }),
2236 EvalError::InvalidRegex(v) => InvalidRegex(v.into_proto()),
2237 EvalError::InvalidRegexFlag(v) => InvalidRegexFlag(v.into_proto()),
2238 EvalError::InvalidParameterValue(v) => InvalidParameterValue(v.into_proto()),
2239 EvalError::InvalidDatePart(part) => InvalidDatePart(part.into_proto()),
2240 EvalError::KeyCannotBeNull => KeyCannotBeNull(()),
2241 EvalError::NegSqrt => NegSqrt(()),
2242 EvalError::NegLimit => NegLimit(()),
2243 EvalError::NullCharacterNotPermitted => NullCharacterNotPermitted(()),
2244 EvalError::UnknownUnits(v) => UnknownUnits(v.into_proto()),
2245 EvalError::UnsupportedUnits(units, typ) => UnsupportedUnits(ProtoUnsupportedUnits {
2246 units: units.into_proto(),
2247 typ: typ.into_proto(),
2248 }),
2249 EvalError::UnterminatedLikeEscapeSequence => UnterminatedLikeEscapeSequence(()),
2250 EvalError::Parse(error) => Parse(error.into_proto()),
2251 EvalError::PrettyError(error) => PrettyError(error.into_proto()),
2252 EvalError::RedactError(error) => RedactError(error.into_proto()),
2253 EvalError::ParseHex(error) => ParseHex(error.into_proto()),
2254 EvalError::Internal(v) => Internal(v.into_proto()),
2255 EvalError::InfinityOutOfDomain(v) => InfinityOutOfDomain(v.into_proto()),
2256 EvalError::NegativeOutOfDomain(v) => NegativeOutOfDomain(v.into_proto()),
2257 EvalError::ZeroOutOfDomain(v) => ZeroOutOfDomain(v.into_proto()),
2258 EvalError::OutOfDomain(lower, upper, id) => OutOfDomain(ProtoOutOfDomain {
2259 lower: Some(lower.into_proto()),
2260 upper: Some(upper.into_proto()),
2261 id: id.into_proto(),
2262 }),
2263 EvalError::ComplexOutOfRange(v) => ComplexOutOfRange(v.into_proto()),
2264 EvalError::MultipleRowsFromSubquery => MultipleRowsFromSubquery(()),
2265 EvalError::NegativeRowsFromSubquery => NegativeRowsFromSubquery(()),
2266 EvalError::Undefined(v) => Undefined(v.into_proto()),
2267 EvalError::LikePatternTooLong => LikePatternTooLong(()),
2268 EvalError::LikeEscapeTooLong => LikeEscapeTooLong(()),
2269 EvalError::StringValueTooLong {
2270 target_type,
2271 length,
2272 } => StringValueTooLong(ProtoStringValueTooLong {
2273 target_type: target_type.into_proto(),
2274 length: length.into_proto(),
2275 }),
2276 EvalError::MultidimensionalArrayRemovalNotSupported => {
2277 MultidimensionalArrayRemovalNotSupported(())
2278 }
2279 EvalError::IncompatibleArrayDimensions { dims } => {
2280 IncompatibleArrayDimensions(ProtoIncompatibleArrayDimensions {
2281 dims: dims.into_proto(),
2282 })
2283 }
2284 EvalError::TypeFromOid(v) => TypeFromOid(v.into_proto()),
2285 EvalError::InvalidRange(error) => InvalidRange(error.into_proto()),
2286 EvalError::InvalidRoleId(v) => InvalidRoleId(v.into_proto()),
2287 EvalError::InvalidPrivileges(v) => InvalidPrivileges(v.into_proto()),
2288 EvalError::InvalidCatalogJson(v) => InvalidCatalogJson(v.into_proto()),
2289 EvalError::LetRecLimitExceeded(v) => WmrRecursionLimitExceeded(v.into_proto()),
2290 EvalError::MultiDimensionalArraySearch => MultiDimensionalArraySearch(()),
2291 EvalError::MustNotBeNull(v) => MustNotBeNull(v.into_proto()),
2292 EvalError::InvalidIdentifier { ident, detail } => {
2293 InvalidIdentifier(ProtoInvalidIdentifier {
2294 ident: ident.into_proto(),
2295 detail: detail.into_proto(),
2296 })
2297 }
2298 EvalError::ArrayFillWrongArraySubscripts => ArrayFillWrongArraySubscripts(()),
2299 EvalError::MaxArraySizeExceeded(max_size) => {
2300 MaxArraySizeExceeded(u64::cast_from(*max_size))
2301 }
2302 EvalError::DateDiffOverflow { unit, a, b } => DateDiffOverflow(ProtoDateDiffOverflow {
2303 unit: unit.into_proto(),
2304 a: a.into_proto(),
2305 b: b.into_proto(),
2306 }),
2307 EvalError::IfNullError(s) => IfNullError(s.into_proto()),
2308 EvalError::LengthTooLarge => LengthTooLarge(()),
2309 EvalError::AclArrayNullElement => AclArrayNullElement(()),
2310 EvalError::MzAclArrayNullElement => MzAclArrayNullElement(()),
2311 EvalError::InvalidIanaTimezoneId(s) => InvalidIanaTimezoneId(s.into_proto()),
2312 };
2313 ProtoEvalError { kind: Some(kind) }
2314 }
2315
2316 fn from_proto(proto: ProtoEvalError) -> Result<Self, TryFromProtoError> {
2317 use proto_eval_error::Kind::*;
2318 match proto.kind {
2319 Some(kind) => match kind {
2320 CharacterNotValidForEncoding(v) => Ok(EvalError::CharacterNotValidForEncoding(v)),
2321 CharacterTooLargeForEncoding(v) => Ok(EvalError::CharacterTooLargeForEncoding(v)),
2322 DateBinOutOfRange(v) => Ok(EvalError::DateBinOutOfRange(v.into())),
2323 DivisionByZero(()) => Ok(EvalError::DivisionByZero),
2324 Unsupported(v) => Ok(EvalError::Unsupported {
2325 feature: v.feature.into(),
2326 discussion_no: v.discussion_no.into_rust()?,
2327 }),
2328 FloatOverflow(()) => Ok(EvalError::FloatOverflow),
2329 FloatUnderflow(()) => Ok(EvalError::FloatUnderflow),
2330 NumericFieldOverflow(()) => Ok(EvalError::NumericFieldOverflow),
2331 Float32OutOfRange(val) => Ok(EvalError::Float32OutOfRange(val.value.into())),
2332 Float64OutOfRange(val) => Ok(EvalError::Float64OutOfRange(val.value.into())),
2333 Int16OutOfRange(val) => Ok(EvalError::Int16OutOfRange(val.value.into())),
2334 Int32OutOfRange(val) => Ok(EvalError::Int32OutOfRange(val.value.into())),
2335 Int64OutOfRange(val) => Ok(EvalError::Int64OutOfRange(val.value.into())),
2336 Uint16OutOfRange(val) => Ok(EvalError::UInt16OutOfRange(val.value.into())),
2337 Uint32OutOfRange(val) => Ok(EvalError::UInt32OutOfRange(val.value.into())),
2338 Uint64OutOfRange(val) => Ok(EvalError::UInt64OutOfRange(val.value.into())),
2339 MzTimestampOutOfRange(val) => {
2340 Ok(EvalError::MzTimestampOutOfRange(val.value.into()))
2341 }
2342 MzTimestampStepOverflow(()) => Ok(EvalError::MzTimestampStepOverflow),
2343 OidOutOfRange(val) => Ok(EvalError::OidOutOfRange(val.value.into())),
2344 IntervalOutOfRange(val) => Ok(EvalError::IntervalOutOfRange(val.value.into())),
2345 TimestampCannotBeNan(()) => Ok(EvalError::TimestampCannotBeNan),
2346 TimestampOutOfRange(()) => Ok(EvalError::TimestampOutOfRange),
2347 DateOutOfRange(()) => Ok(EvalError::DateOutOfRange),
2348 CharOutOfRange(()) => Ok(EvalError::CharOutOfRange),
2349 IndexOutOfRange(v) => Ok(EvalError::IndexOutOfRange {
2350 provided: v.provided,
2351 valid_end: v.valid_end,
2352 }),
2353 InvalidBase64Equals(()) => Ok(EvalError::InvalidBase64Equals),
2354 InvalidBase64Symbol(v) => char::from_proto(v).map(EvalError::InvalidBase64Symbol),
2355 InvalidBase64EndSequence(()) => Ok(EvalError::InvalidBase64EndSequence),
2356 InvalidTimezone(v) => Ok(EvalError::InvalidTimezone(v.into())),
2357 InvalidTimezoneInterval(()) => Ok(EvalError::InvalidTimezoneInterval),
2358 InvalidTimezoneConversion(()) => Ok(EvalError::InvalidTimezoneConversion),
2359 InvalidLayer(v) => Ok(EvalError::InvalidLayer {
2360 max_layer: usize::from_proto(v.max_layer)?,
2361 val: v.val,
2362 }),
2363 InvalidArray(error) => Ok(EvalError::InvalidArray(error.into_rust()?)),
2364 InvalidEncodingName(v) => Ok(EvalError::InvalidEncodingName(v.into())),
2365 InvalidHashAlgorithm(v) => Ok(EvalError::InvalidHashAlgorithm(v.into())),
2366 InvalidByteSequence(v) => Ok(EvalError::InvalidByteSequence {
2367 byte_sequence: v.byte_sequence.into(),
2368 encoding_name: v.encoding_name.into(),
2369 }),
2370 InvalidJsonbCast(v) => Ok(EvalError::InvalidJsonbCast {
2371 from: v.from.into(),
2372 to: v.to.into(),
2373 }),
2374 InvalidRegex(v) => Ok(EvalError::InvalidRegex(v.into())),
2375 InvalidRegexFlag(v) => Ok(EvalError::InvalidRegexFlag(char::from_proto(v)?)),
2376 InvalidParameterValue(v) => Ok(EvalError::InvalidParameterValue(v.into())),
2377 InvalidDatePart(part) => Ok(EvalError::InvalidDatePart(part.into())),
2378 KeyCannotBeNull(()) => Ok(EvalError::KeyCannotBeNull),
2379 NegSqrt(()) => Ok(EvalError::NegSqrt),
2380 NegLimit(()) => Ok(EvalError::NegLimit),
2381 NullCharacterNotPermitted(()) => Ok(EvalError::NullCharacterNotPermitted),
2382 UnknownUnits(v) => Ok(EvalError::UnknownUnits(v.into())),
2383 UnsupportedUnits(v) => {
2384 Ok(EvalError::UnsupportedUnits(v.units.into(), v.typ.into()))
2385 }
2386 UnterminatedLikeEscapeSequence(()) => Ok(EvalError::UnterminatedLikeEscapeSequence),
2387 Parse(error) => Ok(EvalError::Parse(error.into_rust()?)),
2388 ParseHex(error) => Ok(EvalError::ParseHex(error.into_rust()?)),
2389 Internal(v) => Ok(EvalError::Internal(v.into())),
2390 InfinityOutOfDomain(v) => Ok(EvalError::InfinityOutOfDomain(v.into())),
2391 NegativeOutOfDomain(v) => Ok(EvalError::NegativeOutOfDomain(v.into())),
2392 ZeroOutOfDomain(v) => Ok(EvalError::ZeroOutOfDomain(v.into())),
2393 OutOfDomain(v) => Ok(EvalError::OutOfDomain(
2394 v.lower.into_rust_if_some("ProtoDomainLimit::lower")?,
2395 v.upper.into_rust_if_some("ProtoDomainLimit::upper")?,
2396 v.id.into(),
2397 )),
2398 ComplexOutOfRange(v) => Ok(EvalError::ComplexOutOfRange(v.into())),
2399 MultipleRowsFromSubquery(()) => Ok(EvalError::MultipleRowsFromSubquery),
2400 NegativeRowsFromSubquery(()) => Ok(EvalError::NegativeRowsFromSubquery),
2401 Undefined(v) => Ok(EvalError::Undefined(v.into())),
2402 LikePatternTooLong(()) => Ok(EvalError::LikePatternTooLong),
2403 LikeEscapeTooLong(()) => Ok(EvalError::LikeEscapeTooLong),
2404 StringValueTooLong(v) => Ok(EvalError::StringValueTooLong {
2405 target_type: v.target_type.into(),
2406 length: usize::from_proto(v.length)?,
2407 }),
2408 MultidimensionalArrayRemovalNotSupported(()) => {
2409 Ok(EvalError::MultidimensionalArrayRemovalNotSupported)
2410 }
2411 IncompatibleArrayDimensions(v) => Ok(EvalError::IncompatibleArrayDimensions {
2412 dims: v.dims.into_rust()?,
2413 }),
2414 TypeFromOid(v) => Ok(EvalError::TypeFromOid(v.into())),
2415 InvalidRange(e) => Ok(EvalError::InvalidRange(e.into_rust()?)),
2416 InvalidRoleId(v) => Ok(EvalError::InvalidRoleId(v.into())),
2417 InvalidPrivileges(v) => Ok(EvalError::InvalidPrivileges(v.into())),
2418 InvalidCatalogJson(v) => Ok(EvalError::InvalidCatalogJson(v.into())),
2419 WmrRecursionLimitExceeded(v) => Ok(EvalError::LetRecLimitExceeded(v.into())),
2420 MultiDimensionalArraySearch(()) => Ok(EvalError::MultiDimensionalArraySearch),
2421 MustNotBeNull(v) => Ok(EvalError::MustNotBeNull(v.into())),
2422 InvalidIdentifier(v) => Ok(EvalError::InvalidIdentifier {
2423 ident: v.ident.into(),
2424 detail: v.detail.into_rust()?,
2425 }),
2426 ArrayFillWrongArraySubscripts(()) => Ok(EvalError::ArrayFillWrongArraySubscripts),
2427 MaxArraySizeExceeded(max_size) => {
2428 Ok(EvalError::MaxArraySizeExceeded(usize::cast_from(max_size)))
2429 }
2430 DateDiffOverflow(v) => Ok(EvalError::DateDiffOverflow {
2431 unit: v.unit.into(),
2432 a: v.a.into(),
2433 b: v.b.into(),
2434 }),
2435 IfNullError(v) => Ok(EvalError::IfNullError(v.into())),
2436 LengthTooLarge(()) => Ok(EvalError::LengthTooLarge),
2437 AclArrayNullElement(()) => Ok(EvalError::AclArrayNullElement),
2438 MzAclArrayNullElement(()) => Ok(EvalError::MzAclArrayNullElement),
2439 InvalidIanaTimezoneId(s) => Ok(EvalError::InvalidIanaTimezoneId(s.into())),
2440 PrettyError(s) => Ok(EvalError::PrettyError(s.into())),
2441 RedactError(s) => Ok(EvalError::RedactError(s.into())),
2442 },
2443 None => Err(TryFromProtoError::missing_field("ProtoEvalError::kind")),
2444 }
2445 }
2446}
2447
2448impl RustType<ProtoDims> for (usize, usize) {
2449 fn into_proto(&self) -> ProtoDims {
2450 ProtoDims {
2451 f0: self.0.into_proto(),
2452 f1: self.1.into_proto(),
2453 }
2454 }
2455
2456 fn from_proto(proto: ProtoDims) -> Result<Self, TryFromProtoError> {
2457 Ok((proto.f0.into_rust()?, proto.f1.into_rust()?))
2458 }
2459}
2460
2461#[cfg(test)]
2462mod tests {
2463 use super::*;
2464 use crate::scalar::func::variadic::Coalesce;
2465
2466 #[mz_ore::test]
2467 #[cfg_attr(miri, ignore)] fn test_reduce() {
2469 let relation_type: Vec<ReprColumnType> = vec![
2470 ReprScalarType::Int64.nullable(true),
2471 ReprScalarType::Int64.nullable(true),
2472 ReprScalarType::Int64.nullable(false),
2473 ]
2474 .into_iter()
2475 .collect();
2476 let col = MirScalarExpr::column;
2477 let int64_typ = ReprScalarType::Int64;
2478 let err = |e| MirScalarExpr::literal(Err(e), int64_typ.clone());
2479 let lit = |i| MirScalarExpr::literal_ok(Datum::Int64(i), int64_typ.clone());
2480 let null = || MirScalarExpr::literal_null(int64_typ.clone());
2481
2482 struct TestCase {
2483 input: MirScalarExpr,
2484 output: MirScalarExpr,
2485 }
2486
2487 let test_cases = vec![
2488 TestCase {
2489 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1)]),
2490 output: lit(1),
2491 },
2492 TestCase {
2493 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1), lit(2)]),
2494 output: lit(1),
2495 },
2496 TestCase {
2497 input: MirScalarExpr::call_variadic(Coalesce, vec![null(), lit(2), null()]),
2498 output: lit(2),
2499 },
2500 TestCase {
2501 input: MirScalarExpr::call_variadic(
2502 Coalesce,
2503 vec![null(), col(0), null(), col(1), lit(2), lit(3)],
2504 ),
2505 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(1), lit(2)]),
2506 },
2507 TestCase {
2508 input: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2), col(1)]),
2509 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2)]),
2510 },
2511 TestCase {
2512 input: MirScalarExpr::call_variadic(
2513 Coalesce,
2514 vec![lit(1), err(EvalError::DivisionByZero)],
2515 ),
2516 output: lit(1),
2517 },
2518 TestCase {
2519 input: MirScalarExpr::call_variadic(
2520 Coalesce,
2521 vec![
2522 null(),
2523 err(EvalError::DivisionByZero),
2524 err(EvalError::NumericFieldOverflow),
2525 ],
2526 ),
2527 output: err(EvalError::DivisionByZero),
2528 },
2529 ];
2530
2531 for tc in test_cases {
2532 let mut actual = tc.input.clone();
2533 actual.reduce(&relation_type);
2534 assert!(
2535 actual == tc.output,
2536 "input: {}\nactual: {}\nexpected: {}",
2537 tc.input,
2538 actual,
2539 tc.output
2540 );
2541 }
2542 }
2543}