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 self.could_error() {
940 return;
941 }
942
943 if let MirScalarExpr::CallVariadic {
944 exprs: outer_operands,
945 func: outer_func @ (VariadicFunc::Or(_) | VariadicFunc::And(_)),
946 } = self
947 {
948 let inner_func = outer_func.switch_and_or();
949
950 outer_operands.iter_mut().for_each(|o| {
953 if !matches!(o, MirScalarExpr::CallVariadic {func: f, ..} if *f == inner_func) {
954 *o = MirScalarExpr::CallVariadic {
955 func: inner_func.clone(),
956 exprs: vec![o.take()],
957 };
958 }
959 });
960
961 let mut inner_operands_refs: Vec<&mut Vec<MirScalarExpr>> = outer_operands
962 .iter_mut()
963 .map(|o| match o {
964 MirScalarExpr::CallVariadic { func: f, exprs } if *f == inner_func => exprs,
965 _ => unreachable!(), })
967 .collect();
968
969 let mut intersection = inner_operands_refs
971 .iter()
972 .map(|v| (*v).clone())
973 .reduce(|ops1, ops2| ops1.into_iter().filter(|e| ops2.contains(e)).collect())
974 .unwrap();
975 intersection.sort();
976 intersection.dedup();
977
978 if !intersection.is_empty() {
979 inner_operands_refs
983 .iter_mut()
984 .for_each(|ops| (**ops).retain(|o| !intersection.contains(o)));
985
986 outer_operands
988 .iter_mut()
989 .for_each(|o| o.reduce_and_canonicalize_and_or());
990
991 *self = MirScalarExpr::CallVariadic {
993 func: inner_func,
994 exprs: intersection.into_iter().chain_one(self.clone()).collect(),
995 };
996 } else {
997 let all_inner_operands = inner_operands_refs
1008 .iter()
1009 .enumerate()
1010 .flat_map(|(i, inner_vec)| inner_vec.iter().map(move |a| ((*a).clone(), i)))
1011 .sorted()
1012 .collect_vec();
1013
1014 let undistribution_opportunities = all_inner_operands
1019 .iter()
1020 .chunk_by(|(a, _i)| a)
1021 .into_iter()
1022 .map(|(_a, g)| g.map(|(_a, i)| *i).sorted().dedup().collect_vec())
1023 .filter(|g| g.len() > 1)
1024 .collect_vec();
1025
1026 let indexes_to_undistribute = undistribution_opportunities
1028 .iter()
1029 .find(|index_set| {
1031 index_set
1032 .iter()
1033 .any(|i| inner_operands_refs.get(*i).unwrap().len() == 1)
1034 })
1035 .or_else(|| undistribution_opportunities.first())
1037 .cloned();
1038
1039 outer_operands
1041 .iter_mut()
1042 .for_each(|o| o.reduce_and_canonicalize_and_or());
1043
1044 if let Some(indexes_to_undistribute) = indexes_to_undistribute {
1045 let mut undistribute_from = MirScalarExpr::CallVariadic {
1049 func: outer_func.clone(),
1050 exprs: swap_remove_multiple(outer_operands, indexes_to_undistribute),
1051 };
1052 undistribute_from.undistribute_and_or();
1055 outer_operands.push(undistribute_from);
1058 }
1059 }
1060 }
1061 }
1062 }
1063
1064 pub fn non_null_requirements(&self, columns: &mut BTreeSet<usize>) {
1068 match self {
1069 MirScalarExpr::Column(col, _name) => {
1070 columns.insert(*col);
1071 }
1072 MirScalarExpr::Literal(..) => {}
1073 MirScalarExpr::CallUnmaterializable(_) => (),
1074 MirScalarExpr::CallUnary { func, expr } => {
1075 if func.propagates_nulls() {
1076 expr.non_null_requirements(columns);
1077 }
1078 }
1079 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1080 if func.propagates_nulls() {
1081 expr1.non_null_requirements(columns);
1082 expr2.non_null_requirements(columns);
1083 }
1084 }
1085 MirScalarExpr::CallVariadic { func, exprs } => {
1086 if func.propagates_nulls() {
1087 for expr in exprs {
1088 expr.non_null_requirements(columns);
1089 }
1090 }
1091 }
1092 MirScalarExpr::If { .. } => (),
1093 }
1094 }
1095
1096 pub fn sql_typ(&self, column_types: &[SqlColumnType]) -> SqlColumnType {
1097 let repr_column_types = column_types.iter().map(ReprColumnType::from).collect_vec();
1098 SqlColumnType::from_repr(&self.typ(&repr_column_types))
1099 }
1100
1101 pub fn typ(&self, column_types: &[ReprColumnType]) -> ReprColumnType {
1102 match self {
1103 MirScalarExpr::Column(i, _name) => column_types[*i].clone(),
1104 MirScalarExpr::Literal(_, typ) => typ.clone(),
1105 MirScalarExpr::CallUnmaterializable(func) => func.output_type(),
1106 MirScalarExpr::CallUnary { expr, func } => func.output_type(expr.typ(column_types)),
1107 MirScalarExpr::CallBinary { expr1, expr2, func } => {
1108 func.output_type(&[expr1.typ(column_types), expr2.typ(column_types)])
1109 }
1110 MirScalarExpr::CallVariadic { exprs, func } => {
1111 func.output_type(exprs.iter().map(|e| e.typ(column_types)).collect())
1112 }
1113 MirScalarExpr::If { cond: _, then, els } => {
1114 let then_type = then.typ(column_types);
1115 let else_type = els.typ(column_types);
1116 then_type.union(&else_type).unwrap()
1117 }
1118 }
1119 }
1120
1121 pub fn contains_temporal(&self) -> bool {
1124 let mut contains = false;
1125 self.visit_pre(|e| {
1126 if let MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow) = e {
1127 contains = true;
1128 }
1129 });
1130 contains
1131 }
1132
1133 pub fn contains_unmaterializable(&self) -> bool {
1135 let mut contains = false;
1136 self.visit_pre(|e| {
1137 if let MirScalarExpr::CallUnmaterializable(_) = e {
1138 contains = true;
1139 }
1140 });
1141 contains
1142 }
1143
1144 pub fn contains_unmaterializable_except(&self, exceptions: &[UnmaterializableFunc]) -> bool {
1147 let mut contains = false;
1148 self.visit_pre(|e| match e {
1149 MirScalarExpr::CallUnmaterializable(f) if !exceptions.contains(f) => contains = true,
1150 _ => (),
1151 });
1152 contains
1153 }
1154
1155 pub fn contains_column(&self) -> bool {
1157 let mut contains = false;
1158 self.visit_pre(|e| {
1159 if let MirScalarExpr::Column(_col, _name) = e {
1160 contains = true;
1161 }
1162 });
1163 contains
1164 }
1165
1166 pub fn contains_dummy(&self) -> bool {
1168 let mut contains = false;
1169 self.visit_pre(|e| {
1170 if let MirScalarExpr::Literal(row, _) = e {
1171 if let Ok(row) = row {
1172 contains |= row.iter().any(|d| d.contains_dummy());
1173 }
1174 }
1175 });
1176 contains
1177 }
1178
1179 pub fn size(&self) -> usize {
1181 let mut size = 0;
1182 self.visit_pre(&mut |_: &MirScalarExpr| {
1183 size += 1;
1184 });
1185 size
1186 }
1187}
1188
1189impl Eval for MirScalarExpr {
1190 fn eval<'a>(
1191 &'a self,
1192 datums: &[Datum<'a>],
1193 temp_storage: &'a RowArena,
1194 ) -> Result<Datum<'a>, EvalError> {
1195 match self {
1196 MirScalarExpr::Column(index, _name) => Ok(datums[*index]),
1197 MirScalarExpr::Literal(res, _column_type) => match res {
1198 Ok(row) => Ok(row.unpack_first()),
1199 Err(e) => Err(e.clone()),
1200 },
1201 MirScalarExpr::CallUnmaterializable(x) => Err(EvalError::Internal(
1205 format!("cannot evaluate unmaterializable function: {:?}", x).into(),
1206 )),
1207 MirScalarExpr::CallUnary { func, expr } => {
1208 func.eval(datums, temp_storage, expr.as_ref())
1209 }
1210 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1211 func.eval(datums, temp_storage, &[expr1.as_ref(), expr2.as_ref()])
1212 }
1213 MirScalarExpr::CallVariadic { func, exprs } => {
1214 func.eval(datums, temp_storage, exprs.as_slice())
1215 }
1216 MirScalarExpr::If { cond, then, els } => match cond.eval(datums, temp_storage)? {
1217 Datum::True => then.eval(datums, temp_storage),
1218 Datum::False | Datum::Null => els.eval(datums, temp_storage),
1219 d => Err(EvalError::Internal(
1220 format!("if condition evaluated to non-boolean datum: {:?}", d).into(),
1221 )),
1222 },
1223 }
1224 }
1225
1226 fn could_error(&self) -> bool {
1227 match self {
1228 MirScalarExpr::Column(_col, _name) => false,
1229 MirScalarExpr::Literal(row, ..) => row.is_err(),
1230 MirScalarExpr::CallUnmaterializable(_) => true,
1231 MirScalarExpr::CallUnary { func, expr } => func.could_error() || expr.could_error(),
1232 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1233 func.could_error() || expr1.could_error() || expr2.could_error()
1234 }
1235 MirScalarExpr::CallVariadic { func, exprs } => {
1236 func.could_error() || exprs.iter().any(|e| e.could_error())
1237 }
1238 MirScalarExpr::If { cond, then, els } => {
1239 cond.could_error() || then.could_error() || els.could_error()
1240 }
1241 }
1242 }
1243}
1244
1245impl Columns for MirScalarExpr {
1246 fn column(c: usize) -> Self {
1247 MirScalarExpr::column(c)
1248 }
1249
1250 fn is_column(&self) -> bool {
1251 matches!(self, MirScalarExpr::Column(_col, _name))
1252 }
1253
1254 fn as_column(&self) -> Option<usize> {
1255 if let MirScalarExpr::Column(c, _) = self {
1256 Some(*c)
1257 } else {
1258 None
1259 }
1260 }
1261
1262 fn as_column_mut(&mut self) -> Option<&mut usize> {
1263 if let MirScalarExpr::Column(c, _) = self {
1264 Some(c)
1265 } else {
1266 None
1267 }
1268 }
1269
1270 fn support_into(&self, support: &mut BTreeSet<usize>) {
1271 self.visit_pre(|e| {
1272 if let MirScalarExpr::Column(i, _) = e {
1273 support.insert(*i);
1274 }
1275 });
1276 }
1277
1278 fn visit_columns<F>(&mut self, mut action: F)
1279 where
1280 F: FnMut(&mut usize),
1281 {
1282 self.visit_pre_mut(|e| {
1283 if let MirScalarExpr::Column(col, _) = e {
1284 action(col);
1285 }
1286 });
1287 }
1288}
1289
1290impl VisitChildren<Self> for MirScalarExpr {
1291 fn visit_children<F>(&self, mut f: F)
1292 where
1293 F: FnMut(&Self),
1294 {
1295 use MirScalarExpr::*;
1296 match self {
1297 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1298 CallUnary { expr, .. } => {
1299 f(expr);
1300 }
1301 CallBinary { expr1, expr2, .. } => {
1302 f(expr1);
1303 f(expr2);
1304 }
1305 CallVariadic { exprs, .. } => {
1306 for expr in exprs {
1307 f(expr);
1308 }
1309 }
1310 If { cond, then, els } => {
1311 f(cond);
1312 f(then);
1313 f(els);
1314 }
1315 }
1316 }
1317
1318 fn visit_mut_children<F>(&mut self, mut f: F)
1319 where
1320 F: FnMut(&mut Self),
1321 {
1322 use MirScalarExpr::*;
1323 match self {
1324 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1325 CallUnary { expr, .. } => {
1326 f(expr);
1327 }
1328 CallBinary { expr1, expr2, .. } => {
1329 f(expr1);
1330 f(expr2);
1331 }
1332 CallVariadic { exprs, .. } => {
1333 for expr in exprs {
1334 f(expr);
1335 }
1336 }
1337 If { cond, then, els } => {
1338 f(cond);
1339 f(then);
1340 f(els);
1341 }
1342 }
1343 }
1344
1345 fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
1346 where
1347 F: FnMut(&Self) -> Result<(), E>,
1348 {
1349 use MirScalarExpr::*;
1350 match self {
1351 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1352 CallUnary { expr, .. } => {
1353 f(expr)?;
1354 }
1355 CallBinary { expr1, expr2, .. } => {
1356 f(expr1)?;
1357 f(expr2)?;
1358 }
1359 CallVariadic { exprs, .. } => {
1360 for expr in exprs {
1361 f(expr)?;
1362 }
1363 }
1364 If { cond, then, els } => {
1365 f(cond)?;
1366 f(then)?;
1367 f(els)?;
1368 }
1369 }
1370 Ok(())
1371 }
1372
1373 fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
1374 where
1375 F: FnMut(&mut Self) -> Result<(), E>,
1376 {
1377 use MirScalarExpr::*;
1378 match self {
1379 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1380 CallUnary { expr, .. } => {
1381 f(expr)?;
1382 }
1383 CallBinary { expr1, expr2, .. } => {
1384 f(expr1)?;
1385 f(expr2)?;
1386 }
1387 CallVariadic { exprs, .. } => {
1388 for expr in exprs {
1389 f(expr)?;
1390 }
1391 }
1392 If { cond, then, els } => {
1393 f(cond)?;
1394 f(then)?;
1395 f(els)?;
1396 }
1397 }
1398 Ok(())
1399 }
1400
1401 fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Self>
1402 where
1403 Self: 'a,
1404 {
1405 self.children()
1406 }
1407
1408 fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut Self>
1409 where
1410 Self: 'a,
1411 {
1412 self.children_mut()
1413 }
1414}
1415
1416impl MirScalarExpr {
1417 pub fn children(&self) -> impl DoubleEndedIterator<Item = &Self> {
1419 let mut first = None;
1420 let mut second = None;
1421 let mut third = None;
1422 let mut variadic = None;
1423
1424 use MirScalarExpr::*;
1425 match self {
1426 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1427 CallUnary { expr, .. } => {
1428 first = Some(&**expr);
1429 }
1430 CallBinary { expr1, expr2, .. } => {
1431 first = Some(&**expr1);
1432 second = Some(&**expr2);
1433 }
1434 CallVariadic { exprs, .. } => {
1435 variadic = Some(exprs);
1436 }
1437 If { cond, then, els } => {
1438 first = Some(&**cond);
1439 second = Some(&**then);
1440 third = Some(&**els);
1441 }
1442 }
1443
1444 first
1445 .into_iter()
1446 .chain(second)
1447 .chain(third)
1448 .chain(variadic.into_iter().flatten())
1449 }
1450
1451 pub fn children_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Self> {
1453 let mut first = None;
1454 let mut second = None;
1455 let mut third = None;
1456 let mut variadic = None;
1457
1458 use MirScalarExpr::*;
1459 match self {
1460 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1461 CallUnary { expr, .. } => {
1462 first = Some(&mut **expr);
1463 }
1464 CallBinary { expr1, expr2, .. } => {
1465 first = Some(&mut **expr1);
1466 second = Some(&mut **expr2);
1467 }
1468 CallVariadic { exprs, .. } => {
1469 variadic = Some(exprs);
1470 }
1471 If { cond, then, els } => {
1472 first = Some(&mut **cond);
1473 second = Some(&mut **then);
1474 third = Some(&mut **els);
1475 }
1476 }
1477
1478 first
1479 .into_iter()
1480 .chain(second)
1481 .chain(third)
1482 .chain(variadic.into_iter().flatten())
1483 }
1484
1485 pub fn visit_pre<F>(&self, mut f: F)
1487 where
1488 F: FnMut(&Self),
1489 {
1490 let mut worklist = vec![self];
1491 while let Some(e) = worklist.pop() {
1492 f(e);
1493 worklist.extend(e.children().rev());
1494 }
1495 }
1496
1497 pub fn visit_pre_mut<F: FnMut(&mut Self)>(&mut self, mut f: F) {
1499 let mut worklist = vec![self];
1500 while let Some(expr) = worklist.pop() {
1501 f(expr);
1502 worklist.extend(expr.children_mut().rev());
1503 }
1504 }
1505}
1506
1507#[derive(
1514 Eq,
1515 PartialEq,
1516 Ord,
1517 PartialOrd,
1518 Debug,
1519 Clone,
1520 Serialize,
1521 Deserialize,
1522 Hash,
1523 MzReflect
1524)]
1525pub struct FilterCharacteristics {
1526 literal_equality: bool,
1529 like: bool,
1531 is_null: bool,
1532 literal_inequality: usize,
1538 any_filter: bool,
1544}
1545
1546impl BitOrAssign for FilterCharacteristics {
1547 fn bitor_assign(&mut self, rhs: Self) {
1548 self.literal_equality |= rhs.literal_equality;
1549 self.like |= rhs.like;
1550 self.is_null |= rhs.is_null;
1551 self.literal_inequality += rhs.literal_inequality;
1552 self.any_filter |= rhs.any_filter;
1553 }
1554}
1555
1556impl FilterCharacteristics {
1557 pub fn none() -> FilterCharacteristics {
1558 FilterCharacteristics {
1559 literal_equality: false,
1560 like: false,
1561 is_null: false,
1562 literal_inequality: 0,
1563 any_filter: false,
1564 }
1565 }
1566
1567 pub fn explain(&self) -> String {
1568 let mut e = "".to_owned();
1569 if self.literal_equality {
1570 e.push_str("e");
1571 }
1572 if self.like {
1573 e.push_str("l");
1574 }
1575 if self.is_null {
1576 e.push_str("n");
1577 }
1578 for _ in 0..self.literal_inequality {
1579 e.push_str("i");
1580 }
1581 if self.any_filter {
1582 e.push_str("f");
1583 }
1584 e
1585 }
1586
1587 pub fn filter_characteristics(
1588 filters: &Vec<MirScalarExpr>,
1589 ) -> Result<FilterCharacteristics, RecursionLimitError> {
1590 let mut literal_equality = false;
1591 let mut like = false;
1592 let mut is_null = false;
1593 let mut literal_inequality = 0;
1594 let mut any_filter = false;
1595 filters.iter().try_for_each(|f| {
1596 let mut literal_inequality_in_current_filter = false;
1597 let mut is_not_null_in_current_filter = false;
1598 f.visit_pre_with_context(
1599 false,
1600 &mut |not_in_parent_chain, expr| {
1601 not_in_parent_chain
1602 || matches!(
1603 expr,
1604 MirScalarExpr::CallUnary {
1605 func: UnaryFunc::Not(func::Not),
1606 ..
1607 }
1608 )
1609 },
1610 &mut |not_in_parent_chain, expr| {
1611 if !not_in_parent_chain {
1612 if expr.any_expr_eq_literal().is_some() {
1613 literal_equality = true;
1614 }
1615 if expr.any_expr_ineq_literal() {
1616 literal_inequality_in_current_filter = true;
1617 }
1618 if matches!(
1619 expr,
1620 MirScalarExpr::CallUnary {
1621 func: UnaryFunc::IsLikeMatch(_),
1622 ..
1623 }
1624 ) {
1625 like = true;
1626 }
1627 };
1628 if matches!(
1629 expr,
1630 MirScalarExpr::CallUnary {
1631 func: UnaryFunc::IsNull(crate::func::IsNull),
1632 ..
1633 }
1634 ) {
1635 if *not_in_parent_chain {
1636 is_not_null_in_current_filter = true;
1637 } else {
1638 is_null = true;
1639 }
1640 }
1641 },
1642 );
1643 if literal_inequality_in_current_filter {
1644 literal_inequality += 1;
1645 }
1646 if !is_not_null_in_current_filter {
1647 any_filter = true;
1649 }
1650 Ok(())
1651 })?;
1652 Ok(FilterCharacteristics {
1653 literal_equality,
1654 like,
1655 is_null,
1656 literal_inequality,
1657 any_filter,
1658 })
1659 }
1660
1661 pub fn add_literal_equality(&mut self) {
1662 self.literal_equality = true;
1663 }
1664
1665 pub fn worst_case_scaling_factor(&self) -> f64 {
1666 let mut factor = 1.0;
1667
1668 if self.literal_equality {
1669 factor *= 0.1;
1670 }
1671
1672 if self.is_null {
1673 factor *= 0.1;
1674 }
1675
1676 if self.literal_inequality >= 2 {
1677 factor *= 0.25;
1678 } else if self.literal_inequality == 1 {
1679 factor *= 0.33;
1680 }
1681
1682 if !(self.literal_equality || self.is_null || self.literal_inequality > 0)
1684 && self.any_filter
1685 {
1686 factor *= 0.9;
1687 }
1688
1689 factor
1690 }
1691}
1692
1693#[derive(
1694 Ord,
1695 PartialOrd,
1696 Copy,
1697 Clone,
1698 Debug,
1699 Eq,
1700 PartialEq,
1701 Serialize,
1702 Deserialize,
1703 Hash,
1704 MzReflect
1705)]
1706#[cfg_attr(any(test, feature = "proptest"), derive(Arbitrary))]
1707pub enum DomainLimit {
1708 None,
1709 Inclusive(i64),
1710 Exclusive(i64),
1711}
1712
1713impl RustType<ProtoDomainLimit> for DomainLimit {
1714 fn into_proto(&self) -> ProtoDomainLimit {
1715 use proto_domain_limit::Kind::*;
1716 let kind = match self {
1717 DomainLimit::None => None(()),
1718 DomainLimit::Inclusive(v) => Inclusive(*v),
1719 DomainLimit::Exclusive(v) => Exclusive(*v),
1720 };
1721 ProtoDomainLimit { kind: Some(kind) }
1722 }
1723
1724 fn from_proto(proto: ProtoDomainLimit) -> Result<Self, TryFromProtoError> {
1725 use proto_domain_limit::Kind::*;
1726 if let Some(kind) = proto.kind {
1727 match kind {
1728 None(()) => Ok(DomainLimit::None),
1729 Inclusive(v) => Ok(DomainLimit::Inclusive(v)),
1730 Exclusive(v) => Ok(DomainLimit::Exclusive(v)),
1731 }
1732 } else {
1733 Err(TryFromProtoError::missing_field("ProtoDomainLimit::kind"))
1734 }
1735 }
1736}
1737
1738#[derive(
1739 Ord,
1740 PartialOrd,
1741 Clone,
1742 Debug,
1743 Eq,
1744 PartialEq,
1745 Serialize,
1746 Deserialize,
1747 Hash,
1748 MzReflect
1749)]
1750#[cfg_attr(any(test, feature = "proptest"), derive(Arbitrary))]
1751pub enum EvalError {
1752 CharacterNotValidForEncoding(i32),
1753 CharacterTooLargeForEncoding(i32),
1754 DateBinOutOfRange(Box<str>),
1755 DivisionByZero,
1756 Unsupported {
1757 feature: Box<str>,
1758 discussion_no: Option<usize>,
1759 },
1760 FloatOverflow,
1761 FloatUnderflow,
1762 NumericFieldOverflow,
1763 Float32OutOfRange(Box<str>),
1764 Float64OutOfRange(Box<str>),
1765 Int16OutOfRange(Box<str>),
1766 Int32OutOfRange(Box<str>),
1767 Int64OutOfRange(Box<str>),
1768 UInt16OutOfRange(Box<str>),
1769 UInt32OutOfRange(Box<str>),
1770 UInt64OutOfRange(Box<str>),
1771 MzTimestampOutOfRange(Box<str>),
1772 MzTimestampStepOverflow,
1773 OidOutOfRange(Box<str>),
1774 IntervalOutOfRange(Box<str>),
1775 TimestampCannotBeNan,
1776 TimestampOutOfRange,
1777 DateOutOfRange,
1778 CharOutOfRange,
1779 IndexOutOfRange {
1780 provided: i32,
1781 valid_end: i32,
1783 },
1784 InvalidBase64Equals,
1785 InvalidBase64Symbol(char),
1786 InvalidBase64EndSequence,
1787 InvalidTimezone(Box<str>),
1788 InvalidTimezoneInterval,
1789 InvalidTimezoneConversion,
1790 InvalidIanaTimezoneId(Box<str>),
1791 InvalidLayer {
1792 max_layer: usize,
1793 val: i64,
1794 },
1795 InvalidArray(InvalidArrayError),
1796 InvalidEncodingName(Box<str>),
1797 InvalidHashAlgorithm(Box<str>),
1798 InvalidByteSequence {
1799 byte_sequence: Box<str>,
1800 encoding_name: Box<str>,
1801 },
1802 InvalidJsonbCast {
1803 from: Box<str>,
1804 to: Box<str>,
1805 },
1806 InvalidRegex(Box<str>),
1807 InvalidRegexFlag(char),
1808 InvalidParameterValue(Box<str>),
1809 InvalidDatePart(Box<str>),
1810 KeyCannotBeNull,
1811 NegSqrt,
1812 NegLimit,
1813 NullCharacterNotPermitted,
1814 UnknownUnits(Box<str>),
1815 UnsupportedUnits(Box<str>, Box<str>),
1816 UnterminatedLikeEscapeSequence,
1817 Parse(ParseError),
1818 ParseHex(ParseHexError),
1819 Internal(Box<str>),
1820 InfinityOutOfDomain(Box<str>),
1821 NegativeOutOfDomain(Box<str>),
1822 ZeroOutOfDomain(Box<str>),
1823 OutOfDomain(DomainLimit, DomainLimit, Box<str>),
1824 ComplexOutOfRange(Box<str>),
1825 MultipleRowsFromSubquery,
1826 NegativeRowsFromSubquery,
1827 Undefined(Box<str>),
1828 LikePatternTooLong,
1829 LikeEscapeTooLong,
1830 StringValueTooLong {
1831 target_type: Box<str>,
1832 length: usize,
1833 },
1834 MultidimensionalArrayRemovalNotSupported,
1835 IncompatibleArrayDimensions {
1836 dims: Option<(usize, usize)>,
1837 },
1838 TypeFromOid(Box<str>),
1839 InvalidRange(InvalidRangeError),
1840 InvalidRoleId(Box<str>),
1841 InvalidPrivileges(Box<str>),
1842 InvalidCatalogJson(Box<str>),
1843 LetRecLimitExceeded(Box<str>),
1844 MultiDimensionalArraySearch,
1845 MustNotBeNull(Box<str>),
1846 InvalidIdentifier {
1847 ident: Box<str>,
1848 detail: Option<Box<str>>,
1849 },
1850 ArrayFillWrongArraySubscripts,
1851 MaxArraySizeExceeded(usize),
1853 DateDiffOverflow {
1854 unit: Box<str>,
1855 a: Box<str>,
1856 b: Box<str>,
1857 },
1858 IfNullError(Box<str>),
1861 LengthTooLarge,
1862 AclArrayNullElement,
1863 MzAclArrayNullElement,
1864 PrettyError(Box<str>),
1865 RedactError(Box<str>),
1866}
1867
1868impl fmt::Display for EvalError {
1869 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1870 match self {
1871 EvalError::CharacterNotValidForEncoding(v) => {
1872 write!(f, "requested character not valid for encoding: {v}")
1873 }
1874 EvalError::CharacterTooLargeForEncoding(v) => {
1875 write!(f, "requested character too large for encoding: {v}")
1876 }
1877 EvalError::DateBinOutOfRange(message) => f.write_str(message),
1878 EvalError::DivisionByZero => f.write_str("division by zero"),
1879 EvalError::Unsupported {
1880 feature,
1881 discussion_no,
1882 } => {
1883 write!(f, "{} not yet supported", feature)?;
1884 if let Some(discussion_no) = discussion_no {
1885 write!(
1886 f,
1887 ", see https://github.com/MaterializeInc/materialize/discussions/{} for more details",
1888 discussion_no
1889 )?;
1890 }
1891 Ok(())
1892 }
1893 EvalError::FloatOverflow => f.write_str("value out of range: overflow"),
1894 EvalError::FloatUnderflow => f.write_str("value out of range: underflow"),
1895 EvalError::NumericFieldOverflow => f.write_str("numeric field overflow"),
1896 EvalError::Float32OutOfRange(val) => write!(f, "{} real out of range", val.quoted()),
1897 EvalError::Float64OutOfRange(val) => {
1898 write!(f, "{} double precision out of range", val.quoted())
1899 }
1900 EvalError::Int16OutOfRange(val) => write!(f, "{} smallint out of range", val.quoted()),
1901 EvalError::Int32OutOfRange(val) => write!(f, "{} integer out of range", val.quoted()),
1902 EvalError::Int64OutOfRange(val) => write!(f, "{} bigint out of range", val.quoted()),
1903 EvalError::UInt16OutOfRange(val) => write!(f, "{} uint2 out of range", val.quoted()),
1904 EvalError::UInt32OutOfRange(val) => write!(f, "{} uint4 out of range", val.quoted()),
1905 EvalError::UInt64OutOfRange(val) => write!(f, "{} uint8 out of range", val.quoted()),
1906 EvalError::MzTimestampOutOfRange(val) => {
1907 write!(f, "{} mz_timestamp out of range", val.quoted())
1908 }
1909 EvalError::MzTimestampStepOverflow => f.write_str("step mz_timestamp overflow"),
1910 EvalError::OidOutOfRange(val) => write!(f, "{} OID out of range", val.quoted()),
1911 EvalError::IntervalOutOfRange(val) => {
1912 write!(f, "{} interval out of range", val.quoted())
1913 }
1914 EvalError::TimestampCannotBeNan => f.write_str("timestamp cannot be NaN"),
1915 EvalError::TimestampOutOfRange => f.write_str("timestamp out of range"),
1916 EvalError::DateOutOfRange => f.write_str("date out of range"),
1917 EvalError::CharOutOfRange => f.write_str("\"char\" out of range"),
1918 EvalError::IndexOutOfRange {
1919 provided,
1920 valid_end,
1921 } => write!(f, "index {provided} out of valid range, 0..{valid_end}",),
1922 EvalError::InvalidBase64Equals => {
1923 f.write_str("unexpected \"=\" while decoding base64 sequence")
1924 }
1925 EvalError::InvalidBase64Symbol(c) => write!(
1926 f,
1927 "invalid symbol \"{}\" found while decoding base64 sequence",
1928 c.escape_default()
1929 ),
1930 EvalError::InvalidBase64EndSequence => f.write_str("invalid base64 end sequence"),
1931 EvalError::InvalidJsonbCast { from, to } => {
1932 write!(f, "cannot cast jsonb {} to type {}", from, to)
1933 }
1934 EvalError::InvalidTimezone(tz) => write!(f, "invalid time zone '{}'", tz),
1935 EvalError::InvalidTimezoneInterval => {
1936 f.write_str("timezone interval must not contain months or years")
1937 }
1938 EvalError::InvalidTimezoneConversion => f.write_str("invalid timezone conversion"),
1939 EvalError::InvalidIanaTimezoneId(tz) => {
1940 write!(f, "invalid IANA Time Zone Database identifier: '{}'", tz)
1941 }
1942 EvalError::InvalidLayer { max_layer, val } => write!(
1943 f,
1944 "invalid layer: {}; must use value within [1, {}]",
1945 val, max_layer
1946 ),
1947 EvalError::InvalidArray(e) => e.fmt(f),
1948 EvalError::InvalidEncodingName(name) => write!(f, "invalid encoding name '{}'", name),
1949 EvalError::InvalidHashAlgorithm(alg) => write!(f, "invalid hash algorithm '{}'", alg),
1950 EvalError::InvalidByteSequence {
1951 byte_sequence,
1952 encoding_name,
1953 } => write!(
1954 f,
1955 "invalid byte sequence '{}' for encoding '{}'",
1956 byte_sequence, encoding_name
1957 ),
1958 EvalError::InvalidDatePart(part) => write!(f, "invalid datepart {}", part.quoted()),
1959 EvalError::KeyCannotBeNull => f.write_str("key cannot be null"),
1960 EvalError::NegSqrt => f.write_str("cannot take square root of a negative number"),
1961 EvalError::NegLimit => f.write_str("LIMIT must not be negative"),
1962 EvalError::NullCharacterNotPermitted => f.write_str("null character not permitted"),
1963 EvalError::InvalidRegex(e) => write!(f, "invalid regular expression: {}", e),
1964 EvalError::InvalidRegexFlag(c) => write!(f, "invalid regular expression flag: {}", c),
1965 EvalError::InvalidParameterValue(s) => f.write_str(s),
1966 EvalError::UnknownUnits(units) => write!(f, "unit '{}' not recognized", units),
1967 EvalError::UnsupportedUnits(units, typ) => {
1968 write!(f, "unit '{}' not supported for type {}", units, typ)
1969 }
1970 EvalError::UnterminatedLikeEscapeSequence => {
1971 f.write_str("unterminated escape sequence in LIKE")
1972 }
1973 EvalError::Parse(e) => e.fmt(f),
1974 EvalError::PrettyError(e) => e.fmt(f),
1975 EvalError::RedactError(e) => e.fmt(f),
1976 EvalError::ParseHex(e) => e.fmt(f),
1977 EvalError::Internal(s) => write!(f, "internal error: {}", s),
1978 EvalError::InfinityOutOfDomain(s) => {
1979 write!(f, "function {} is only defined for finite arguments", s)
1980 }
1981 EvalError::NegativeOutOfDomain(s) => {
1982 write!(f, "function {} is not defined for negative numbers", s)
1983 }
1984 EvalError::ZeroOutOfDomain(s) => {
1985 write!(f, "function {} is not defined for zero", s)
1986 }
1987 EvalError::OutOfDomain(lower, upper, s) => {
1988 use DomainLimit::*;
1989 write!(f, "function {s} is defined for numbers ")?;
1990 match (lower, upper) {
1991 (Inclusive(n), None) => write!(f, "greater than or equal to {n}"),
1992 (Exclusive(n), None) => write!(f, "greater than {n}"),
1993 (None, Inclusive(n)) => write!(f, "less than or equal to {n}"),
1994 (None, Exclusive(n)) => write!(f, "less than {n}"),
1995 (Inclusive(lo), Inclusive(hi)) => write!(f, "between {lo} and {hi} inclusive"),
1996 (Exclusive(lo), Exclusive(hi)) => write!(f, "between {lo} and {hi} exclusive"),
1997 (Inclusive(lo), Exclusive(hi)) => {
1998 write!(f, "between {lo} inclusive and {hi} exclusive")
1999 }
2000 (Exclusive(lo), Inclusive(hi)) => {
2001 write!(f, "between {lo} exclusive and {hi} inclusive")
2002 }
2003 (None, None) => panic!("invalid domain error"),
2004 }
2005 }
2006 EvalError::ComplexOutOfRange(s) => {
2007 write!(f, "function {} cannot return complex numbers", s)
2008 }
2009 EvalError::MultipleRowsFromSubquery => {
2010 write!(f, "more than one record produced in subquery")
2011 }
2012 EvalError::NegativeRowsFromSubquery => {
2013 write!(f, "negative number of rows produced in subquery")
2014 }
2015 EvalError::Undefined(s) => {
2016 write!(f, "{} is undefined", s)
2017 }
2018 EvalError::LikePatternTooLong => {
2019 write!(f, "LIKE pattern exceeds maximum length")
2020 }
2021 EvalError::LikeEscapeTooLong => {
2022 write!(f, "invalid escape string")
2023 }
2024 EvalError::StringValueTooLong {
2025 target_type,
2026 length,
2027 } => {
2028 write!(f, "value too long for type {}({})", target_type, length)
2029 }
2030 EvalError::MultidimensionalArrayRemovalNotSupported => {
2031 write!(
2032 f,
2033 "removing elements from multidimensional arrays is not supported"
2034 )
2035 }
2036 EvalError::IncompatibleArrayDimensions { dims: _ } => {
2037 write!(f, "cannot concatenate incompatible arrays")
2038 }
2039 EvalError::TypeFromOid(msg) => write!(f, "{msg}"),
2040 EvalError::InvalidRange(e) => e.fmt(f),
2041 EvalError::InvalidRoleId(msg) => write!(f, "{msg}"),
2042 EvalError::InvalidPrivileges(privilege) => {
2043 write!(f, "unrecognized privilege type: {privilege}")
2044 }
2045 EvalError::InvalidCatalogJson(msg) => {
2046 write!(f, "invalid catalog JSON: {msg}")
2047 }
2048 EvalError::LetRecLimitExceeded(max_iters) => {
2049 write!(
2050 f,
2051 "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.)",
2052 max_iters
2053 )
2054 }
2055 EvalError::MultiDimensionalArraySearch => write!(
2056 f,
2057 "searching for elements in multidimensional arrays is not supported"
2058 ),
2059 EvalError::MustNotBeNull(v) => write!(f, "{v} must not be null"),
2060 EvalError::InvalidIdentifier { ident, .. } => {
2061 write!(f, "string is not a valid identifier: {}", ident.quoted())
2062 }
2063 EvalError::ArrayFillWrongArraySubscripts => {
2064 f.write_str("wrong number of array subscripts")
2065 }
2066 EvalError::MaxArraySizeExceeded(max_size) => {
2067 write!(
2068 f,
2069 "array size exceeds the maximum allowed ({max_size} bytes)"
2070 )
2071 }
2072 EvalError::DateDiffOverflow { unit, a, b } => {
2073 write!(f, "datediff overflow, {unit} of {a}, {b}")
2074 }
2075 EvalError::IfNullError(s) => f.write_str(s),
2076 EvalError::LengthTooLarge => write!(f, "requested length too large"),
2077 EvalError::AclArrayNullElement => write!(f, "ACL arrays must not contain null values"),
2078 EvalError::MzAclArrayNullElement => {
2079 write!(f, "MZ_ACL arrays must not contain null values")
2080 }
2081 }
2082 }
2083}
2084
2085impl EvalError {
2086 pub fn detail(&self) -> Option<String> {
2087 match self {
2088 EvalError::IncompatibleArrayDimensions { dims: None } => Some(
2089 "Arrays with differing dimensions are not compatible for concatenation.".into(),
2090 ),
2091 EvalError::IncompatibleArrayDimensions {
2092 dims: Some((a_dims, b_dims)),
2093 } => Some(format!(
2094 "Arrays of {} and {} dimensions are not compatible for concatenation.",
2095 a_dims, b_dims
2096 )),
2097 EvalError::InvalidIdentifier { detail, .. } => detail.as_deref().map(Into::into),
2098 EvalError::ArrayFillWrongArraySubscripts => {
2099 Some("Low bound array has different size than dimensions array.".into())
2100 }
2101 _ => None,
2102 }
2103 }
2104
2105 pub fn hint(&self) -> Option<String> {
2106 match self {
2107 EvalError::InvalidBase64EndSequence => Some(
2108 "Input data is missing padding, is truncated, or is otherwise corrupted.".into(),
2109 ),
2110 EvalError::LikeEscapeTooLong => {
2111 Some("Escape string must be empty or one character.".into())
2112 }
2113 EvalError::MzTimestampOutOfRange(_) => Some(
2114 "Integer, numeric, and text casts to mz_timestamp must be in the form of whole \
2115 milliseconds since the Unix epoch. Values with fractional parts cannot be \
2116 converted to mz_timestamp."
2117 .into(),
2118 ),
2119 _ => None,
2120 }
2121 }
2122}
2123
2124impl std::error::Error for EvalError {}
2125
2126impl From<ParseError> for EvalError {
2127 fn from(e: ParseError) -> EvalError {
2128 EvalError::Parse(e)
2129 }
2130}
2131
2132impl From<ParseHexError> for EvalError {
2133 fn from(e: ParseHexError) -> EvalError {
2134 EvalError::ParseHex(e)
2135 }
2136}
2137
2138impl From<InvalidArrayError> for EvalError {
2139 fn from(e: InvalidArrayError) -> EvalError {
2140 EvalError::InvalidArray(e)
2141 }
2142}
2143
2144impl From<RegexCompilationError> for EvalError {
2145 fn from(e: RegexCompilationError) -> EvalError {
2146 EvalError::InvalidRegex(e.to_string().into())
2147 }
2148}
2149
2150impl From<TypeFromOidError> for EvalError {
2151 fn from(e: TypeFromOidError) -> EvalError {
2152 EvalError::TypeFromOid(e.to_string().into())
2153 }
2154}
2155
2156impl From<DateError> for EvalError {
2157 fn from(e: DateError) -> EvalError {
2158 match e {
2159 DateError::OutOfRange => EvalError::DateOutOfRange,
2160 }
2161 }
2162}
2163
2164impl From<TimestampError> for EvalError {
2165 fn from(e: TimestampError) -> EvalError {
2166 match e {
2167 TimestampError::OutOfRange => EvalError::TimestampOutOfRange,
2168 }
2169 }
2170}
2171
2172impl From<InvalidRangeError> for EvalError {
2173 fn from(e: InvalidRangeError) -> EvalError {
2174 EvalError::InvalidRange(e)
2175 }
2176}
2177
2178impl RustType<ProtoEvalError> for EvalError {
2179 fn into_proto(&self) -> ProtoEvalError {
2180 use proto_eval_error::Kind::*;
2181 use proto_eval_error::*;
2182 let kind = match self {
2183 EvalError::CharacterNotValidForEncoding(v) => CharacterNotValidForEncoding(*v),
2184 EvalError::CharacterTooLargeForEncoding(v) => CharacterTooLargeForEncoding(*v),
2185 EvalError::DateBinOutOfRange(v) => DateBinOutOfRange(v.into_proto()),
2186 EvalError::DivisionByZero => DivisionByZero(()),
2187 EvalError::Unsupported {
2188 feature,
2189 discussion_no,
2190 } => Unsupported(ProtoUnsupported {
2191 feature: feature.into_proto(),
2192 discussion_no: discussion_no.into_proto(),
2193 }),
2194 EvalError::FloatOverflow => FloatOverflow(()),
2195 EvalError::FloatUnderflow => FloatUnderflow(()),
2196 EvalError::NumericFieldOverflow => NumericFieldOverflow(()),
2197 EvalError::Float32OutOfRange(val) => Float32OutOfRange(ProtoValueOutOfRange {
2198 value: val.to_string(),
2199 }),
2200 EvalError::Float64OutOfRange(val) => Float64OutOfRange(ProtoValueOutOfRange {
2201 value: val.to_string(),
2202 }),
2203 EvalError::Int16OutOfRange(val) => Int16OutOfRange(ProtoValueOutOfRange {
2204 value: val.to_string(),
2205 }),
2206 EvalError::Int32OutOfRange(val) => Int32OutOfRange(ProtoValueOutOfRange {
2207 value: val.to_string(),
2208 }),
2209 EvalError::Int64OutOfRange(val) => Int64OutOfRange(ProtoValueOutOfRange {
2210 value: val.to_string(),
2211 }),
2212 EvalError::UInt16OutOfRange(val) => Uint16OutOfRange(ProtoValueOutOfRange {
2213 value: val.to_string(),
2214 }),
2215 EvalError::UInt32OutOfRange(val) => Uint32OutOfRange(ProtoValueOutOfRange {
2216 value: val.to_string(),
2217 }),
2218 EvalError::UInt64OutOfRange(val) => Uint64OutOfRange(ProtoValueOutOfRange {
2219 value: val.to_string(),
2220 }),
2221 EvalError::MzTimestampOutOfRange(val) => MzTimestampOutOfRange(ProtoValueOutOfRange {
2222 value: val.to_string(),
2223 }),
2224 EvalError::MzTimestampStepOverflow => MzTimestampStepOverflow(()),
2225 EvalError::OidOutOfRange(val) => OidOutOfRange(ProtoValueOutOfRange {
2226 value: val.to_string(),
2227 }),
2228 EvalError::IntervalOutOfRange(val) => IntervalOutOfRange(ProtoValueOutOfRange {
2229 value: val.to_string(),
2230 }),
2231 EvalError::TimestampCannotBeNan => TimestampCannotBeNan(()),
2232 EvalError::TimestampOutOfRange => TimestampOutOfRange(()),
2233 EvalError::DateOutOfRange => DateOutOfRange(()),
2234 EvalError::CharOutOfRange => CharOutOfRange(()),
2235 EvalError::IndexOutOfRange {
2236 provided,
2237 valid_end,
2238 } => IndexOutOfRange(ProtoIndexOutOfRange {
2239 provided: *provided,
2240 valid_end: *valid_end,
2241 }),
2242 EvalError::InvalidBase64Equals => InvalidBase64Equals(()),
2243 EvalError::InvalidBase64Symbol(sym) => InvalidBase64Symbol(sym.into_proto()),
2244 EvalError::InvalidBase64EndSequence => InvalidBase64EndSequence(()),
2245 EvalError::InvalidTimezone(tz) => InvalidTimezone(tz.into_proto()),
2246 EvalError::InvalidTimezoneInterval => InvalidTimezoneInterval(()),
2247 EvalError::InvalidTimezoneConversion => InvalidTimezoneConversion(()),
2248 EvalError::InvalidLayer { max_layer, val } => InvalidLayer(ProtoInvalidLayer {
2249 max_layer: max_layer.into_proto(),
2250 val: *val,
2251 }),
2252 EvalError::InvalidArray(error) => InvalidArray(error.into_proto()),
2253 EvalError::InvalidEncodingName(v) => InvalidEncodingName(v.into_proto()),
2254 EvalError::InvalidHashAlgorithm(v) => InvalidHashAlgorithm(v.into_proto()),
2255 EvalError::InvalidByteSequence {
2256 byte_sequence,
2257 encoding_name,
2258 } => InvalidByteSequence(ProtoInvalidByteSequence {
2259 byte_sequence: byte_sequence.into_proto(),
2260 encoding_name: encoding_name.into_proto(),
2261 }),
2262 EvalError::InvalidJsonbCast { from, to } => InvalidJsonbCast(ProtoInvalidJsonbCast {
2263 from: from.into_proto(),
2264 to: to.into_proto(),
2265 }),
2266 EvalError::InvalidRegex(v) => InvalidRegex(v.into_proto()),
2267 EvalError::InvalidRegexFlag(v) => InvalidRegexFlag(v.into_proto()),
2268 EvalError::InvalidParameterValue(v) => InvalidParameterValue(v.into_proto()),
2269 EvalError::InvalidDatePart(part) => InvalidDatePart(part.into_proto()),
2270 EvalError::KeyCannotBeNull => KeyCannotBeNull(()),
2271 EvalError::NegSqrt => NegSqrt(()),
2272 EvalError::NegLimit => NegLimit(()),
2273 EvalError::NullCharacterNotPermitted => NullCharacterNotPermitted(()),
2274 EvalError::UnknownUnits(v) => UnknownUnits(v.into_proto()),
2275 EvalError::UnsupportedUnits(units, typ) => UnsupportedUnits(ProtoUnsupportedUnits {
2276 units: units.into_proto(),
2277 typ: typ.into_proto(),
2278 }),
2279 EvalError::UnterminatedLikeEscapeSequence => UnterminatedLikeEscapeSequence(()),
2280 EvalError::Parse(error) => Parse(error.into_proto()),
2281 EvalError::PrettyError(error) => PrettyError(error.into_proto()),
2282 EvalError::RedactError(error) => RedactError(error.into_proto()),
2283 EvalError::ParseHex(error) => ParseHex(error.into_proto()),
2284 EvalError::Internal(v) => Internal(v.into_proto()),
2285 EvalError::InfinityOutOfDomain(v) => InfinityOutOfDomain(v.into_proto()),
2286 EvalError::NegativeOutOfDomain(v) => NegativeOutOfDomain(v.into_proto()),
2287 EvalError::ZeroOutOfDomain(v) => ZeroOutOfDomain(v.into_proto()),
2288 EvalError::OutOfDomain(lower, upper, id) => OutOfDomain(ProtoOutOfDomain {
2289 lower: Some(lower.into_proto()),
2290 upper: Some(upper.into_proto()),
2291 id: id.into_proto(),
2292 }),
2293 EvalError::ComplexOutOfRange(v) => ComplexOutOfRange(v.into_proto()),
2294 EvalError::MultipleRowsFromSubquery => MultipleRowsFromSubquery(()),
2295 EvalError::NegativeRowsFromSubquery => NegativeRowsFromSubquery(()),
2296 EvalError::Undefined(v) => Undefined(v.into_proto()),
2297 EvalError::LikePatternTooLong => LikePatternTooLong(()),
2298 EvalError::LikeEscapeTooLong => LikeEscapeTooLong(()),
2299 EvalError::StringValueTooLong {
2300 target_type,
2301 length,
2302 } => StringValueTooLong(ProtoStringValueTooLong {
2303 target_type: target_type.into_proto(),
2304 length: length.into_proto(),
2305 }),
2306 EvalError::MultidimensionalArrayRemovalNotSupported => {
2307 MultidimensionalArrayRemovalNotSupported(())
2308 }
2309 EvalError::IncompatibleArrayDimensions { dims } => {
2310 IncompatibleArrayDimensions(ProtoIncompatibleArrayDimensions {
2311 dims: dims.into_proto(),
2312 })
2313 }
2314 EvalError::TypeFromOid(v) => TypeFromOid(v.into_proto()),
2315 EvalError::InvalidRange(error) => InvalidRange(error.into_proto()),
2316 EvalError::InvalidRoleId(v) => InvalidRoleId(v.into_proto()),
2317 EvalError::InvalidPrivileges(v) => InvalidPrivileges(v.into_proto()),
2318 EvalError::InvalidCatalogJson(v) => InvalidCatalogJson(v.into_proto()),
2319 EvalError::LetRecLimitExceeded(v) => WmrRecursionLimitExceeded(v.into_proto()),
2320 EvalError::MultiDimensionalArraySearch => MultiDimensionalArraySearch(()),
2321 EvalError::MustNotBeNull(v) => MustNotBeNull(v.into_proto()),
2322 EvalError::InvalidIdentifier { ident, detail } => {
2323 InvalidIdentifier(ProtoInvalidIdentifier {
2324 ident: ident.into_proto(),
2325 detail: detail.into_proto(),
2326 })
2327 }
2328 EvalError::ArrayFillWrongArraySubscripts => ArrayFillWrongArraySubscripts(()),
2329 EvalError::MaxArraySizeExceeded(max_size) => {
2330 MaxArraySizeExceeded(u64::cast_from(*max_size))
2331 }
2332 EvalError::DateDiffOverflow { unit, a, b } => DateDiffOverflow(ProtoDateDiffOverflow {
2333 unit: unit.into_proto(),
2334 a: a.into_proto(),
2335 b: b.into_proto(),
2336 }),
2337 EvalError::IfNullError(s) => IfNullError(s.into_proto()),
2338 EvalError::LengthTooLarge => LengthTooLarge(()),
2339 EvalError::AclArrayNullElement => AclArrayNullElement(()),
2340 EvalError::MzAclArrayNullElement => MzAclArrayNullElement(()),
2341 EvalError::InvalidIanaTimezoneId(s) => InvalidIanaTimezoneId(s.into_proto()),
2342 };
2343 ProtoEvalError { kind: Some(kind) }
2344 }
2345
2346 fn from_proto(proto: ProtoEvalError) -> Result<Self, TryFromProtoError> {
2347 use proto_eval_error::Kind::*;
2348 match proto.kind {
2349 Some(kind) => match kind {
2350 CharacterNotValidForEncoding(v) => Ok(EvalError::CharacterNotValidForEncoding(v)),
2351 CharacterTooLargeForEncoding(v) => Ok(EvalError::CharacterTooLargeForEncoding(v)),
2352 DateBinOutOfRange(v) => Ok(EvalError::DateBinOutOfRange(v.into())),
2353 DivisionByZero(()) => Ok(EvalError::DivisionByZero),
2354 Unsupported(v) => Ok(EvalError::Unsupported {
2355 feature: v.feature.into(),
2356 discussion_no: v.discussion_no.into_rust()?,
2357 }),
2358 FloatOverflow(()) => Ok(EvalError::FloatOverflow),
2359 FloatUnderflow(()) => Ok(EvalError::FloatUnderflow),
2360 NumericFieldOverflow(()) => Ok(EvalError::NumericFieldOverflow),
2361 Float32OutOfRange(val) => Ok(EvalError::Float32OutOfRange(val.value.into())),
2362 Float64OutOfRange(val) => Ok(EvalError::Float64OutOfRange(val.value.into())),
2363 Int16OutOfRange(val) => Ok(EvalError::Int16OutOfRange(val.value.into())),
2364 Int32OutOfRange(val) => Ok(EvalError::Int32OutOfRange(val.value.into())),
2365 Int64OutOfRange(val) => Ok(EvalError::Int64OutOfRange(val.value.into())),
2366 Uint16OutOfRange(val) => Ok(EvalError::UInt16OutOfRange(val.value.into())),
2367 Uint32OutOfRange(val) => Ok(EvalError::UInt32OutOfRange(val.value.into())),
2368 Uint64OutOfRange(val) => Ok(EvalError::UInt64OutOfRange(val.value.into())),
2369 MzTimestampOutOfRange(val) => {
2370 Ok(EvalError::MzTimestampOutOfRange(val.value.into()))
2371 }
2372 MzTimestampStepOverflow(()) => Ok(EvalError::MzTimestampStepOverflow),
2373 OidOutOfRange(val) => Ok(EvalError::OidOutOfRange(val.value.into())),
2374 IntervalOutOfRange(val) => Ok(EvalError::IntervalOutOfRange(val.value.into())),
2375 TimestampCannotBeNan(()) => Ok(EvalError::TimestampCannotBeNan),
2376 TimestampOutOfRange(()) => Ok(EvalError::TimestampOutOfRange),
2377 DateOutOfRange(()) => Ok(EvalError::DateOutOfRange),
2378 CharOutOfRange(()) => Ok(EvalError::CharOutOfRange),
2379 IndexOutOfRange(v) => Ok(EvalError::IndexOutOfRange {
2380 provided: v.provided,
2381 valid_end: v.valid_end,
2382 }),
2383 InvalidBase64Equals(()) => Ok(EvalError::InvalidBase64Equals),
2384 InvalidBase64Symbol(v) => char::from_proto(v).map(EvalError::InvalidBase64Symbol),
2385 InvalidBase64EndSequence(()) => Ok(EvalError::InvalidBase64EndSequence),
2386 InvalidTimezone(v) => Ok(EvalError::InvalidTimezone(v.into())),
2387 InvalidTimezoneInterval(()) => Ok(EvalError::InvalidTimezoneInterval),
2388 InvalidTimezoneConversion(()) => Ok(EvalError::InvalidTimezoneConversion),
2389 InvalidLayer(v) => Ok(EvalError::InvalidLayer {
2390 max_layer: usize::from_proto(v.max_layer)?,
2391 val: v.val,
2392 }),
2393 InvalidArray(error) => Ok(EvalError::InvalidArray(error.into_rust()?)),
2394 InvalidEncodingName(v) => Ok(EvalError::InvalidEncodingName(v.into())),
2395 InvalidHashAlgorithm(v) => Ok(EvalError::InvalidHashAlgorithm(v.into())),
2396 InvalidByteSequence(v) => Ok(EvalError::InvalidByteSequence {
2397 byte_sequence: v.byte_sequence.into(),
2398 encoding_name: v.encoding_name.into(),
2399 }),
2400 InvalidJsonbCast(v) => Ok(EvalError::InvalidJsonbCast {
2401 from: v.from.into(),
2402 to: v.to.into(),
2403 }),
2404 InvalidRegex(v) => Ok(EvalError::InvalidRegex(v.into())),
2405 InvalidRegexFlag(v) => Ok(EvalError::InvalidRegexFlag(char::from_proto(v)?)),
2406 InvalidParameterValue(v) => Ok(EvalError::InvalidParameterValue(v.into())),
2407 InvalidDatePart(part) => Ok(EvalError::InvalidDatePart(part.into())),
2408 KeyCannotBeNull(()) => Ok(EvalError::KeyCannotBeNull),
2409 NegSqrt(()) => Ok(EvalError::NegSqrt),
2410 NegLimit(()) => Ok(EvalError::NegLimit),
2411 NullCharacterNotPermitted(()) => Ok(EvalError::NullCharacterNotPermitted),
2412 UnknownUnits(v) => Ok(EvalError::UnknownUnits(v.into())),
2413 UnsupportedUnits(v) => {
2414 Ok(EvalError::UnsupportedUnits(v.units.into(), v.typ.into()))
2415 }
2416 UnterminatedLikeEscapeSequence(()) => Ok(EvalError::UnterminatedLikeEscapeSequence),
2417 Parse(error) => Ok(EvalError::Parse(error.into_rust()?)),
2418 ParseHex(error) => Ok(EvalError::ParseHex(error.into_rust()?)),
2419 Internal(v) => Ok(EvalError::Internal(v.into())),
2420 InfinityOutOfDomain(v) => Ok(EvalError::InfinityOutOfDomain(v.into())),
2421 NegativeOutOfDomain(v) => Ok(EvalError::NegativeOutOfDomain(v.into())),
2422 ZeroOutOfDomain(v) => Ok(EvalError::ZeroOutOfDomain(v.into())),
2423 OutOfDomain(v) => Ok(EvalError::OutOfDomain(
2424 v.lower.into_rust_if_some("ProtoDomainLimit::lower")?,
2425 v.upper.into_rust_if_some("ProtoDomainLimit::upper")?,
2426 v.id.into(),
2427 )),
2428 ComplexOutOfRange(v) => Ok(EvalError::ComplexOutOfRange(v.into())),
2429 MultipleRowsFromSubquery(()) => Ok(EvalError::MultipleRowsFromSubquery),
2430 NegativeRowsFromSubquery(()) => Ok(EvalError::NegativeRowsFromSubquery),
2431 Undefined(v) => Ok(EvalError::Undefined(v.into())),
2432 LikePatternTooLong(()) => Ok(EvalError::LikePatternTooLong),
2433 LikeEscapeTooLong(()) => Ok(EvalError::LikeEscapeTooLong),
2434 StringValueTooLong(v) => Ok(EvalError::StringValueTooLong {
2435 target_type: v.target_type.into(),
2436 length: usize::from_proto(v.length)?,
2437 }),
2438 MultidimensionalArrayRemovalNotSupported(()) => {
2439 Ok(EvalError::MultidimensionalArrayRemovalNotSupported)
2440 }
2441 IncompatibleArrayDimensions(v) => Ok(EvalError::IncompatibleArrayDimensions {
2442 dims: v.dims.into_rust()?,
2443 }),
2444 TypeFromOid(v) => Ok(EvalError::TypeFromOid(v.into())),
2445 InvalidRange(e) => Ok(EvalError::InvalidRange(e.into_rust()?)),
2446 InvalidRoleId(v) => Ok(EvalError::InvalidRoleId(v.into())),
2447 InvalidPrivileges(v) => Ok(EvalError::InvalidPrivileges(v.into())),
2448 InvalidCatalogJson(v) => Ok(EvalError::InvalidCatalogJson(v.into())),
2449 WmrRecursionLimitExceeded(v) => Ok(EvalError::LetRecLimitExceeded(v.into())),
2450 MultiDimensionalArraySearch(()) => Ok(EvalError::MultiDimensionalArraySearch),
2451 MustNotBeNull(v) => Ok(EvalError::MustNotBeNull(v.into())),
2452 InvalidIdentifier(v) => Ok(EvalError::InvalidIdentifier {
2453 ident: v.ident.into(),
2454 detail: v.detail.into_rust()?,
2455 }),
2456 ArrayFillWrongArraySubscripts(()) => Ok(EvalError::ArrayFillWrongArraySubscripts),
2457 MaxArraySizeExceeded(max_size) => {
2458 Ok(EvalError::MaxArraySizeExceeded(usize::cast_from(max_size)))
2459 }
2460 DateDiffOverflow(v) => Ok(EvalError::DateDiffOverflow {
2461 unit: v.unit.into(),
2462 a: v.a.into(),
2463 b: v.b.into(),
2464 }),
2465 IfNullError(v) => Ok(EvalError::IfNullError(v.into())),
2466 LengthTooLarge(()) => Ok(EvalError::LengthTooLarge),
2467 AclArrayNullElement(()) => Ok(EvalError::AclArrayNullElement),
2468 MzAclArrayNullElement(()) => Ok(EvalError::MzAclArrayNullElement),
2469 InvalidIanaTimezoneId(s) => Ok(EvalError::InvalidIanaTimezoneId(s.into())),
2470 PrettyError(s) => Ok(EvalError::PrettyError(s.into())),
2471 RedactError(s) => Ok(EvalError::RedactError(s.into())),
2472 },
2473 None => Err(TryFromProtoError::missing_field("ProtoEvalError::kind")),
2474 }
2475 }
2476}
2477
2478impl RustType<ProtoDims> for (usize, usize) {
2479 fn into_proto(&self) -> ProtoDims {
2480 ProtoDims {
2481 f0: self.0.into_proto(),
2482 f1: self.1.into_proto(),
2483 }
2484 }
2485
2486 fn from_proto(proto: ProtoDims) -> Result<Self, TryFromProtoError> {
2487 Ok((proto.f0.into_rust()?, proto.f1.into_rust()?))
2488 }
2489}
2490
2491#[cfg(test)]
2492mod tests {
2493 use super::*;
2494 use crate::scalar::func::variadic::Coalesce;
2495
2496 #[mz_ore::test]
2497 fn test_reduce_and_or_does_not_propagate_operand_error() {
2498 let bool_typ = ReprScalarType::Bool;
2504 let types = vec![bool_typ.clone().nullable(true)];
2505 let err = || MirScalarExpr::literal(Err(EvalError::DivisionByZero), bool_typ.clone());
2506 let arena = RowArena::new();
2507
2508 let mut and = MirScalarExpr::call_variadic(And, vec![MirScalarExpr::column(0), err()]);
2509 and.reduce(&types);
2510 assert!(
2511 !and.is_literal_err(),
2512 "reduce folded AND with an error operand to an error: {and:?}"
2513 );
2514 assert_eq!(and.eval(&[Datum::False], &arena), Ok(Datum::False));
2515
2516 let mut or = MirScalarExpr::call_variadic(Or, vec![MirScalarExpr::column(0), err()]);
2517 or.reduce(&types);
2518 assert!(
2519 !or.is_literal_err(),
2520 "reduce folded OR with an error operand to an error: {or:?}"
2521 );
2522 assert_eq!(or.eval(&[Datum::True], &arena), Ok(Datum::True));
2523 }
2524
2525 #[mz_ore::test]
2526 fn test_reduce_and_or_does_not_absorb_operand_error() {
2527 let bool_typ = ReprScalarType::Bool;
2537 let types = vec![bool_typ.clone().nullable(true)];
2538 let err = || MirScalarExpr::literal(Err(EvalError::DivisionByZero), bool_typ.clone());
2539 let arena = RowArena::new();
2540
2541 let mut or = MirScalarExpr::column(0).or(MirScalarExpr::column(0).and(err()));
2544 or.reduce(&types);
2545 assert_ne!(
2546 or,
2547 MirScalarExpr::column(0),
2548 "reduce absorbed an error operand to the bare column: {or:?}"
2549 );
2550 assert_eq!(or.eval(&[Datum::True], &arena), Ok(Datum::True));
2551 assert_eq!(or.eval(&[Datum::False], &arena), Ok(Datum::False));
2552 assert_eq!(
2553 or.eval(&[Datum::Null], &arena),
2554 Err(EvalError::DivisionByZero)
2555 );
2556
2557 let mut and = MirScalarExpr::column(0).and(MirScalarExpr::column(0).or(err()));
2560 and.reduce(&types);
2561 assert_ne!(
2562 and,
2563 MirScalarExpr::column(0),
2564 "reduce absorbed an error operand to the bare column: {and:?}"
2565 );
2566 assert_eq!(and.eval(&[Datum::False], &arena), Ok(Datum::False));
2567 assert_eq!(and.eval(&[Datum::True], &arena), Ok(Datum::True));
2568 assert_eq!(
2569 and.eval(&[Datum::Null], &arena),
2570 Err(EvalError::DivisionByZero)
2571 );
2572 }
2573
2574 #[mz_ore::test]
2575 #[cfg_attr(miri, ignore)] fn test_reduce() {
2577 let relation_type: Vec<ReprColumnType> = vec![
2578 ReprScalarType::Int64.nullable(true),
2579 ReprScalarType::Int64.nullable(true),
2580 ReprScalarType::Int64.nullable(false),
2581 ]
2582 .into_iter()
2583 .collect();
2584 let col = MirScalarExpr::column;
2585 let int64_typ = ReprScalarType::Int64;
2586 let err = |e| MirScalarExpr::literal(Err(e), int64_typ.clone());
2587 let lit = |i| MirScalarExpr::literal_ok(Datum::Int64(i), int64_typ.clone());
2588 let null = || MirScalarExpr::literal_null(int64_typ.clone());
2589
2590 struct TestCase {
2591 input: MirScalarExpr,
2592 output: MirScalarExpr,
2593 }
2594
2595 let test_cases = vec![
2596 TestCase {
2597 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1)]),
2598 output: lit(1),
2599 },
2600 TestCase {
2601 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1), lit(2)]),
2602 output: lit(1),
2603 },
2604 TestCase {
2605 input: MirScalarExpr::call_variadic(Coalesce, vec![null(), lit(2), null()]),
2606 output: lit(2),
2607 },
2608 TestCase {
2609 input: MirScalarExpr::call_variadic(
2610 Coalesce,
2611 vec![null(), col(0), null(), col(1), lit(2), lit(3)],
2612 ),
2613 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(1), lit(2)]),
2614 },
2615 TestCase {
2616 input: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2), col(1)]),
2617 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2)]),
2618 },
2619 TestCase {
2620 input: MirScalarExpr::call_variadic(
2621 Coalesce,
2622 vec![lit(1), err(EvalError::DivisionByZero)],
2623 ),
2624 output: lit(1),
2625 },
2626 TestCase {
2627 input: MirScalarExpr::call_variadic(
2628 Coalesce,
2629 vec![
2630 null(),
2631 err(EvalError::DivisionByZero),
2632 err(EvalError::NumericFieldOverflow),
2633 ],
2634 ),
2635 output: err(EvalError::DivisionByZero),
2636 },
2637 ];
2638
2639 for tc in test_cases {
2640 let mut actual = tc.input.clone();
2641 actual.reduce(&relation_type);
2642 assert!(
2643 actual == tc.output,
2644 "input: {}\nactual: {}\nexpected: {}",
2645 tc.input,
2646 actual,
2647 tc.output
2648 );
2649 }
2650 }
2651
2652 #[mz_ore::test]
2656 fn test_visit_mut_post_replace_subtrees() {
2657 let col = MirScalarExpr::column;
2658 let mut expr = col(0).if_then_else(col(1).if_then_else(col(2), col(3)), col(4));
2659
2660 expr.visit_mut_post(&mut |expr: &mut MirScalarExpr| match expr {
2661 MirScalarExpr::Column(n, _) => *n += 1,
2662 MirScalarExpr::If { then, .. } => {
2663 let then = then.take();
2664 *expr = then;
2665 }
2666 _ => {}
2667 });
2668
2669 assert_eq!(expr, col(3));
2671 }
2672
2673 #[mz_ore::test]
2679 fn test_visit_mut_pre_post_explicit_children() {
2680 let col = MirScalarExpr::column;
2681 let mut expr = col(5)
2682 .if_then_else(col(6), col(7))
2683 .if_then_else(col(1).if_then_else(col(2), col(3)), col(4));
2684
2685 expr.visit_mut_pre_post(
2689 &mut |expr: &mut MirScalarExpr| -> Option<Vec<&mut MirScalarExpr>> {
2690 if let MirScalarExpr::If { .. } = expr {
2691 let MirScalarExpr::If { then, els, .. } = expr else {
2692 unreachable!()
2693 };
2694 let then = then.take();
2695 let els = els.take();
2696 *expr = MirScalarExpr::column(0).if_then_else(then, els);
2697
2698 let MirScalarExpr::If { then, els, .. } = expr else {
2699 unreachable!()
2700 };
2701 Some(vec![then.as_mut(), els.as_mut()])
2702 } else {
2703 None
2705 }
2706 },
2707 &mut |expr: &mut MirScalarExpr| {
2708 if let MirScalarExpr::Column(n, _) = expr {
2709 *n += 10;
2710 }
2711 },
2712 );
2713
2714 let expected = col(0).if_then_else(col(0).if_then_else(col(12), col(13)), col(14));
2716 assert_eq!(expr, expected);
2717 }
2718}