1use std::collections::{BTreeMap, BTreeSet};
11use std::ops::BitOrAssign;
12use std::sync::Arc;
13use std::{fmt, mem};
14
15use itertools::Itertools;
16use mz_lowertest::MzReflect;
17use mz_ore::cast::CastFrom;
18use mz_ore::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};
41use crate::scalar::func::variadic::{And, Or};
42use crate::scalar::func::{BinaryFunc, UnaryFunc, UnmaterializableFunc, VariadicFunc};
43use crate::scalar::proto_eval_error::proto_incompatible_array_dimensions::ProtoDims;
44use crate::visit::{Visit, VisitChildren};
45
46pub mod func;
47pub mod like_pattern;
48mod reduce;
49
50include!(concat!(env!("OUT_DIR"), "/mz_expr.scalar.rs"));
51
52#[derive(
53 Clone,
54 PartialEq,
55 Eq,
56 PartialOrd,
57 Ord,
58 Hash,
59 Serialize,
60 Deserialize,
61 MzReflect
62)]
63pub enum MirScalarExpr {
64 Column(usize, TreatAsEqual<Option<Arc<str>>>),
66 Literal(Result<Row, EvalError>, ReprColumnType),
69 CallUnmaterializable(UnmaterializableFunc),
74 CallUnary {
76 func: UnaryFunc,
77 expr: Box<MirScalarExpr>,
78 },
79 CallBinary {
81 func: BinaryFunc,
82 expr1: Box<MirScalarExpr>,
83 expr2: Box<MirScalarExpr>,
84 },
85 CallVariadic {
87 func: VariadicFunc,
88 exprs: Vec<MirScalarExpr>,
89 },
90 If {
97 cond: Box<MirScalarExpr>,
98 then: Box<MirScalarExpr>,
99 els: Box<MirScalarExpr>,
100 },
101}
102
103impl std::fmt::Debug for MirScalarExpr {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 match self {
108 MirScalarExpr::Column(i, TreatAsEqual(Some(name))) => {
109 write!(f, "Column({i}, {name:?})")
110 }
111 MirScalarExpr::Column(i, TreatAsEqual(None)) => write!(f, "Column({i})"),
112 MirScalarExpr::Literal(lit, typ) => write!(f, "Literal({lit:?}, {typ:?})"),
113 MirScalarExpr::CallUnmaterializable(func) => {
114 write!(f, "CallUnmaterializable({func:?})")
115 }
116 MirScalarExpr::CallUnary { func, expr } => {
117 write!(f, "CallUnary({func:?}, {expr:?})")
118 }
119 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
120 write!(f, "CallBinary({func:?}, {expr1:?}, {expr2:?})")
121 }
122 MirScalarExpr::CallVariadic { func, exprs } => {
123 write!(f, "CallVariadic({func:?}, {exprs:?})")
124 }
125 MirScalarExpr::If { cond, then, els } => {
126 write!(f, "If({cond:?}, {then:?}, {els:?})")
127 }
128 }
129 }
130}
131
132impl MirScalarExpr {
133 pub fn columns(is: &[usize]) -> Vec<MirScalarExpr> {
134 is.iter().map(|i| MirScalarExpr::column(*i)).collect()
135 }
136
137 pub fn column(column: usize) -> Self {
138 MirScalarExpr::Column(column, TreatAsEqual(None))
139 }
140
141 pub fn named_column(column: usize, name: Arc<str>) -> Self {
142 MirScalarExpr::Column(column, TreatAsEqual(Some(name)))
143 }
144
145 pub fn literal(res: Result<Datum, EvalError>, typ: ReprScalarType) -> Self {
146 let typ = ReprColumnType {
147 scalar_type: typ,
148 nullable: matches!(res, Ok(Datum::Null)),
149 };
150 let row = res.map(|datum| Row::pack_slice(&[datum]));
151 MirScalarExpr::Literal(row, typ)
152 }
153
154 pub fn literal_ok(datum: Datum, typ: ReprScalarType) -> Self {
155 MirScalarExpr::literal(Ok(datum), typ)
156 }
157
158 pub fn literal_from_single_element_row(row: Row, typ: ReprScalarType) -> Self {
162 soft_assert_or_log!(
163 row.iter().count() == 1,
164 "literal_from_row called with a Row containing {} datums",
165 row.iter().count()
166 );
167 let nullable = row.unpack_first() == Datum::Null;
168 let typ = ReprColumnType {
169 scalar_type: typ,
170 nullable,
171 };
172 MirScalarExpr::Literal(Ok(row), typ)
173 }
174
175 pub fn literal_null(typ: ReprScalarType) -> Self {
176 MirScalarExpr::literal_ok(Datum::Null, typ)
177 }
178
179 pub fn literal_false() -> Self {
180 MirScalarExpr::literal_ok(Datum::False, ReprScalarType::Bool)
181 }
182
183 pub fn literal_true() -> Self {
184 MirScalarExpr::literal_ok(Datum::True, ReprScalarType::Bool)
185 }
186
187 pub fn call_unary<U: Into<UnaryFunc>>(self, func: U) -> Self {
188 MirScalarExpr::CallUnary {
189 func: func.into(),
190 expr: Box::new(self),
191 }
192 }
193
194 pub fn call_binary<B: Into<BinaryFunc>>(self, other: Self, func: B) -> Self {
195 MirScalarExpr::CallBinary {
196 func: func.into(),
197 expr1: Box::new(self),
198 expr2: Box::new(other),
199 }
200 }
201
202 pub fn call_variadic<V: Into<VariadicFunc>>(func: V, exprs: Vec<Self>) -> Self {
204 MirScalarExpr::CallVariadic {
205 func: func.into(),
206 exprs,
207 }
208 }
209
210 pub fn if_then_else(self, t: Self, f: Self) -> Self {
211 MirScalarExpr::If {
212 cond: Box::new(self),
213 then: Box::new(t),
214 els: Box::new(f),
215 }
216 }
217
218 pub fn or(self, other: Self) -> Self {
219 MirScalarExpr::call_variadic(Or, vec![self, other])
220 }
221
222 pub fn and(self, other: Self) -> Self {
223 MirScalarExpr::call_variadic(And, vec![self, other])
224 }
225
226 pub fn not(self) -> Self {
227 self.call_unary(UnaryFunc::Not(func::Not))
228 }
229
230 pub fn call_is_null(self) -> Self {
231 self.call_unary(UnaryFunc::IsNull(func::IsNull))
232 }
233
234 pub fn and_or_args(&self, func_to_match: VariadicFunc) -> Vec<MirScalarExpr> {
237 assert!(func_to_match == Or.into() || func_to_match == And.into());
238 match self {
239 MirScalarExpr::CallVariadic { func, exprs } if *func == func_to_match => exprs.clone(),
240 _ => vec![self.clone()],
241 }
242 }
243
244 pub fn expr_eq_literal(&self, expr: &MirScalarExpr) -> Option<(Row, bool)> {
255 if let MirScalarExpr::CallBinary {
256 func: BinaryFunc::Eq(_),
257 expr1,
258 expr2,
259 } = self
260 {
261 if expr1.is_literal_null() || expr2.is_literal_null() {
262 return None;
263 }
264 if let Some(Ok(lit)) = expr1.as_literal_owned() {
265 return Self::expr_eq_literal_inner(expr, lit, expr1, expr2);
266 }
267 if let Some(Ok(lit)) = expr2.as_literal_owned() {
268 return Self::expr_eq_literal_inner(expr, lit, expr2, expr1);
269 }
270 }
271 None
272 }
273
274 fn expr_eq_literal_inner(
275 expr_to_match: &MirScalarExpr,
276 literal: Row,
277 literal_expr: &MirScalarExpr,
278 other_side: &MirScalarExpr,
279 ) -> Option<(Row, bool)> {
280 if other_side == expr_to_match {
281 return Some((literal, false));
282 } else {
283 let (cast_removed, inv_cast_lit) =
285 Self::invert_casts_on_expr_eq_literal_inner(other_side, literal_expr);
286 if &cast_removed == expr_to_match {
287 if let Some(Ok(inv_cast_lit_row)) = inv_cast_lit.as_literal_owned() {
288 return Some((inv_cast_lit_row, true));
289 }
290 }
291 }
292 None
293 }
294
295 pub fn any_expr_eq_literal(&self) -> Option<MirScalarExpr> {
299 if let MirScalarExpr::CallBinary {
300 func: BinaryFunc::Eq(_),
301 expr1,
302 expr2,
303 } = self
304 {
305 if expr1.is_literal() {
306 let (expr, _literal) = Self::invert_casts_on_expr_eq_literal_inner(expr2, expr1);
307 return Some(expr);
308 }
309 if expr2.is_literal() {
310 let (expr, _literal) = Self::invert_casts_on_expr_eq_literal_inner(expr1, expr2);
311 return Some(expr);
312 }
313 }
314 None
315 }
316
317 pub fn invert_casts_on_expr_eq_literal(&self) -> MirScalarExpr {
322 if let MirScalarExpr::CallBinary {
323 func: BinaryFunc::Eq(_),
324 expr1,
325 expr2,
326 } = self
327 {
328 if expr1.is_literal() {
329 let (expr, literal) = Self::invert_casts_on_expr_eq_literal_inner(expr2, expr1);
330 return literal.call_binary(expr, func::Eq);
331 }
332 if expr2.is_literal() {
333 let (expr, literal) = Self::invert_casts_on_expr_eq_literal_inner(expr1, expr2);
334 return literal.call_binary(expr, func::Eq);
335 }
336 }
339 self.clone()
340 }
341
342 fn invert_casts_on_expr_eq_literal_inner(
354 expr: &MirScalarExpr,
355 literal: &MirScalarExpr,
356 ) -> (MirScalarExpr, MirScalarExpr) {
357 assert!(matches!(literal, MirScalarExpr::Literal(..)));
358
359 let temp_storage = &RowArena::new();
360 let eval = |e: &MirScalarExpr| {
361 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(&[]).scalar_type)
362 };
363
364 if let MirScalarExpr::CallUnary {
365 func,
366 expr: inner_expr,
367 } = expr
368 {
369 if let Some(inverse_func) = func.inverse() {
370 if func.preserves_uniqueness() && inverse_func.preserves_uniqueness() {
377 let lit_inv = eval(&MirScalarExpr::CallUnary {
378 func: inverse_func,
379 expr: Box::new(literal.clone()),
380 });
381 if !lit_inv.is_literal_err() {
384 return (*inner_expr.clone(), lit_inv);
385 }
386 }
387 }
388 }
389 (expr.clone(), literal.clone())
390 }
391
392 pub fn impossible_literal_equality_because_types(&self) -> bool {
398 if let MirScalarExpr::CallBinary {
399 func: BinaryFunc::Eq(_),
400 expr1,
401 expr2,
402 } = self
403 {
404 if expr1.is_literal() {
405 return Self::impossible_literal_equality_because_types_inner(expr1, expr2);
406 }
407 if expr2.is_literal() {
408 return Self::impossible_literal_equality_because_types_inner(expr2, expr1);
409 }
410 }
411 false
412 }
413
414 fn impossible_literal_equality_because_types_inner(
415 literal: &MirScalarExpr,
416 other_side: &MirScalarExpr,
417 ) -> bool {
418 assert!(matches!(literal, MirScalarExpr::Literal(..)));
419
420 let temp_storage = &RowArena::new();
421 let eval = |e: &MirScalarExpr| {
422 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(&[]).scalar_type)
423 };
424
425 if let MirScalarExpr::CallUnary { func, .. } = other_side {
426 if let Some(inverse_func) = func.inverse() {
427 if inverse_func.preserves_uniqueness()
428 && eval(&MirScalarExpr::CallUnary {
429 func: inverse_func,
430 expr: Box::new(literal.clone()),
431 })
432 .is_literal_err()
433 {
434 return true;
435 }
436 }
437 }
438
439 false
440 }
441
442 pub fn any_expr_ineq_literal(&self) -> bool {
452 match self {
453 MirScalarExpr::CallBinary {
454 func:
455 BinaryFunc::Lt(_) | BinaryFunc::Lte(_) | BinaryFunc::Gt(_) | BinaryFunc::Gte(_),
456 expr1,
457 expr2,
458 } => expr1.is_literal() || expr2.is_literal(),
459 _ => false,
460 }
461 }
462
463 pub fn permute(&mut self, permutation: &[usize]) {
469 self.visit_columns(|c| *c = permutation[*c]);
470 }
471
472 pub fn permute_map(&mut self, permutation: &BTreeMap<usize, usize>) {
478 self.visit_columns(|c| *c = permutation[c]);
479 }
480
481 pub fn visit_columns<F>(&mut self, mut action: F)
485 where
486 F: FnMut(&mut usize),
487 {
488 self.visit_pre_mut(|e| {
489 if let MirScalarExpr::Column(col, _) = e {
490 action(col);
491 }
492 });
493 }
494
495 pub fn support(&self) -> BTreeSet<usize> {
496 let mut support = BTreeSet::new();
497 self.support_into(&mut support);
498 support
499 }
500
501 pub fn support_into(&self, support: &mut BTreeSet<usize>) {
502 self.visit_pre(|e| {
503 if let MirScalarExpr::Column(i, _) = e {
504 support.insert(*i);
505 }
506 });
507 }
508
509 pub fn take(&mut self) -> Self {
510 mem::replace(self, MirScalarExpr::literal_null(ReprScalarType::String))
511 }
512
513 pub fn as_literal(&self) -> Option<Result<Datum<'_>, &EvalError>> {
516 if let MirScalarExpr::Literal(lit, _column_type) = self {
517 Some(lit.as_ref().map(|row| row.unpack_first()))
518 } else {
519 None
520 }
521 }
522
523 pub fn as_literal_non_error(&self) -> Option<Datum<'_>> {
526 self.as_literal().map(|eval_err| eval_err.ok()).flatten()
527 }
528
529 pub fn as_literal_owned(&self) -> Option<Result<Row, EvalError>> {
530 if let MirScalarExpr::Literal(lit, _column_type) = self {
531 Some(lit.clone())
532 } else {
533 None
534 }
535 }
536
537 pub fn as_literal_non_null_row(&self) -> Option<&Row> {
539 if let MirScalarExpr::Literal(Ok(row), _) = self {
540 if !row.unpack_first().is_null() {
541 return Some(row);
542 }
543 }
544 None
545 }
546
547 pub fn as_literal_str(&self) -> Option<&str> {
548 match self.as_literal() {
549 Some(Ok(Datum::String(s))) => Some(s),
550 _ => None,
551 }
552 }
553
554 pub fn as_literal_int64(&self) -> Option<i64> {
555 match self.as_literal() {
556 Some(Ok(Datum::Int64(i))) => Some(i),
557 _ => None,
558 }
559 }
560
561 pub fn as_literal_err(&self) -> Option<&EvalError> {
562 self.as_literal().and_then(|lit| lit.err())
563 }
564
565 pub fn is_literal(&self) -> bool {
566 matches!(self, MirScalarExpr::Literal(_, _))
567 }
568
569 pub fn is_literal_true(&self) -> bool {
570 Some(Ok(Datum::True)) == self.as_literal()
571 }
572
573 pub fn is_literal_false(&self) -> bool {
574 Some(Ok(Datum::False)) == self.as_literal()
575 }
576
577 pub fn is_literal_null(&self) -> bool {
578 Some(Ok(Datum::Null)) == self.as_literal()
579 }
580
581 pub fn is_literal_ok(&self) -> bool {
582 matches!(self, MirScalarExpr::Literal(Ok(_), _typ))
583 }
584
585 pub fn is_literal_err(&self) -> bool {
586 matches!(self, MirScalarExpr::Literal(Err(_), _typ))
587 }
588
589 pub fn is_column(&self) -> bool {
590 matches!(self, MirScalarExpr::Column(_col, _name))
591 }
592
593 pub fn is_error_if_null(&self) -> bool {
594 matches!(
595 self,
596 Self::CallVariadic {
597 func: VariadicFunc::ErrorIfNull(_),
598 ..
599 }
600 )
601 }
602
603 pub fn as_mut_temporal_filter(&mut self) -> Result<(&BinaryFunc, &mut MirScalarExpr), String> {
613 if !self.contains_temporal() {
614 return Err("Does not involve mz_now()".to_string());
615 }
616 if let MirScalarExpr::CallBinary { func, expr1, expr2 } = self {
618 if !expr1.contains_temporal()
620 && **expr2 == MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow)
621 {
622 let new_func = match func {
623 BinaryFunc::Eq(_) => func::Eq.into(),
624 BinaryFunc::Lt(_) => func::Gt.into(),
625 BinaryFunc::Lte(_) => func::Gte.into(),
626 BinaryFunc::Gt(_) => func::Lt.into(),
627 BinaryFunc::Gte(_) => func::Lte.into(),
628 x => {
629 return Err(format!("Unsupported binary temporal operation: {:?}", x));
630 }
631 };
632 std::mem::swap(expr1, expr2);
633 *func = new_func;
634 }
635
636 if expr2.contains_temporal()
638 || **expr1 != MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow)
639 {
640 let mode = HumanizedExplain::new(false); let bad_expr = MirScalarExpr::CallBinary {
642 func: func.clone(),
643 expr1: expr1.clone(),
644 expr2: expr2.clone(),
645 };
646 return Err(format!(
647 "Unsupported temporal predicate. Note: `mz_now()` must be directly compared to a mz_timestamp-castable expression. Expression found: {}",
648 mode.expr(&bad_expr, None),
649 ));
650 }
651
652 Ok((&*func, expr2))
653 } else {
654 let mode = HumanizedExplain::new(false); Err(format!(
656 "Unsupported temporal predicate. Note: `mz_now()` must be directly compared to a non-temporal expression of mz_timestamp-castable type. Expression found: {}",
657 mode.expr(self, None),
658 ))
659 }
660 }
661
662 #[deprecated = "Use `might_error` instead"]
663 pub fn contains_error_if_null(&self) -> bool {
664 let mut worklist = vec![self];
665 while let Some(expr) = worklist.pop() {
666 if expr.is_error_if_null() {
667 return true;
668 }
669 worklist.extend(expr.children());
670 }
671 false
672 }
673
674 pub fn contains_err(&self) -> bool {
675 let mut worklist = vec![self];
676 while let Some(expr) = worklist.pop() {
677 if expr.is_literal_err() {
678 return true;
679 }
680 worklist.extend(expr.children());
681 }
682 false
683 }
684
685 pub fn might_error(&self) -> bool {
691 let mut worklist = vec![self];
692 while let Some(expr) = worklist.pop() {
693 if expr.is_literal_err() || expr.is_error_if_null() {
694 return true;
695 }
696 worklist.extend(expr.children());
697 }
698 false
699 }
700
701 pub fn as_column(&self) -> Option<usize> {
703 if let MirScalarExpr::Column(c, _) = self {
704 Some(*c)
705 } else {
706 None
707 }
708 }
709
710 pub fn reduce(&mut self, column_types: &[ReprColumnType]) {
743 reduce::reduce(self, column_types);
744 }
745
746 fn decompose_is_null(&mut self) -> Option<MirScalarExpr> {
754 match self {
757 MirScalarExpr::CallUnary {
758 func,
759 expr: inner_expr,
760 } => {
761 if !func.introduces_nulls() {
762 if func.propagates_nulls() {
763 *self = inner_expr.take();
764 return self.decompose_is_null();
765 } else {
766 return Some(MirScalarExpr::literal_false());
785 }
786 }
787 }
788 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
789 if func.propagates_nulls() && !func.introduces_nulls() {
792 let expr1 = expr1.take().call_is_null();
793 let expr2 = expr2.take().call_is_null();
794 return Some(expr1.or(expr2));
795 }
796 }
797 MirScalarExpr::CallVariadic { func, exprs } => {
798 if func.propagates_nulls() && !func.introduces_nulls() {
799 let exprs = exprs.into_iter().map(|e| e.take().call_is_null()).collect();
800 return Some(MirScalarExpr::call_variadic(Or, exprs));
801 }
802 }
803 _ => {}
804 }
805
806 None
807 }
808
809 pub fn flatten_associative(&mut self) {
812 match self {
813 MirScalarExpr::CallVariadic {
814 exprs: outer_operands,
815 func: outer_func,
816 } if outer_func.is_associative() => {
817 *outer_operands = outer_operands
818 .into_iter()
819 .flat_map(|o| {
820 if let MirScalarExpr::CallVariadic {
821 exprs: inner_operands,
822 func: inner_func,
823 } = o
824 {
825 if *inner_func == *outer_func {
826 mem::take(inner_operands)
827 } else {
828 vec![o.take()]
829 }
830 } else {
831 vec![o.take()]
832 }
833 })
834 .collect();
835 }
836 _ => {}
837 }
838 }
839
840 fn reduce_and_canonicalize_and_or(&mut self) {
844 let mut old_self = MirScalarExpr::column(0);
848 while old_self != *self {
849 old_self = self.clone();
850 match self {
851 MirScalarExpr::CallVariadic {
852 func: func @ (VariadicFunc::And(_) | VariadicFunc::Or(_)),
853 exprs,
854 } => {
855 exprs.sort();
859
860 exprs.dedup(); if exprs.len() == 1 {
864 *self = exprs.swap_remove(0);
866 } else if exprs.len() == 0 {
867 *self = func.unit_of_and_or();
869 } else if exprs.iter().any(|e| *e == func.zero_of_and_or()) {
870 *self = func.zero_of_and_or();
872 } else {
873 exprs.retain(|e| *e != func.unit_of_and_or());
876 }
877 }
878 _ => {}
879 }
880 }
881 }
882
883 fn demorgans(&mut self) {
885 if let MirScalarExpr::CallUnary {
886 expr: inner,
887 func: UnaryFunc::Not(func::Not),
888 } = self
889 {
890 inner.flatten_associative();
891 match &mut **inner {
892 MirScalarExpr::CallVariadic {
893 func: inner_func @ (VariadicFunc::And(_) | VariadicFunc::Or(_)),
894 exprs,
895 } => {
896 *inner_func = inner_func.switch_and_or();
897 *exprs = exprs.into_iter().map(|e| e.take().not()).collect();
898 *self = (*inner).take(); }
900 _ => {}
901 }
902 }
903 }
904
905 fn undistribute_and_or(&mut self) {
970 let mut old_self = MirScalarExpr::column(0);
975 while old_self != *self {
976 old_self = self.clone();
977 self.reduce_and_canonicalize_and_or(); if let MirScalarExpr::CallVariadic {
979 exprs: outer_operands,
980 func: outer_func @ (VariadicFunc::Or(_) | VariadicFunc::And(_)),
981 } = self
982 {
983 let inner_func = outer_func.switch_and_or();
984
985 outer_operands.iter_mut().for_each(|o| {
988 if !matches!(o, MirScalarExpr::CallVariadic {func: f, ..} if *f == inner_func) {
989 *o = MirScalarExpr::CallVariadic {
990 func: inner_func.clone(),
991 exprs: vec![o.take()],
992 };
993 }
994 });
995
996 let mut inner_operands_refs: Vec<&mut Vec<MirScalarExpr>> = outer_operands
997 .iter_mut()
998 .map(|o| match o {
999 MirScalarExpr::CallVariadic { func: f, exprs } if *f == inner_func => exprs,
1000 _ => unreachable!(), })
1002 .collect();
1003
1004 let mut intersection = inner_operands_refs
1006 .iter()
1007 .map(|v| (*v).clone())
1008 .reduce(|ops1, ops2| ops1.into_iter().filter(|e| ops2.contains(e)).collect())
1009 .unwrap();
1010 intersection.sort();
1011 intersection.dedup();
1012
1013 if !intersection.is_empty() {
1014 inner_operands_refs
1018 .iter_mut()
1019 .for_each(|ops| (**ops).retain(|o| !intersection.contains(o)));
1020
1021 outer_operands
1023 .iter_mut()
1024 .for_each(|o| o.reduce_and_canonicalize_and_or());
1025
1026 *self = MirScalarExpr::CallVariadic {
1028 func: inner_func,
1029 exprs: intersection.into_iter().chain_one(self.clone()).collect(),
1030 };
1031 } else {
1032 let all_inner_operands = inner_operands_refs
1043 .iter()
1044 .enumerate()
1045 .flat_map(|(i, inner_vec)| inner_vec.iter().map(move |a| ((*a).clone(), i)))
1046 .sorted()
1047 .collect_vec();
1048
1049 let undistribution_opportunities = all_inner_operands
1054 .iter()
1055 .chunk_by(|(a, _i)| a)
1056 .into_iter()
1057 .map(|(_a, g)| g.map(|(_a, i)| *i).sorted().dedup().collect_vec())
1058 .filter(|g| g.len() > 1)
1059 .collect_vec();
1060
1061 let indexes_to_undistribute = undistribution_opportunities
1063 .iter()
1064 .find(|index_set| {
1066 index_set
1067 .iter()
1068 .any(|i| inner_operands_refs.get(*i).unwrap().len() == 1)
1069 })
1070 .or_else(|| undistribution_opportunities.first())
1072 .cloned();
1073
1074 outer_operands
1076 .iter_mut()
1077 .for_each(|o| o.reduce_and_canonicalize_and_or());
1078
1079 if let Some(indexes_to_undistribute) = indexes_to_undistribute {
1080 let mut undistribute_from = MirScalarExpr::CallVariadic {
1084 func: outer_func.clone(),
1085 exprs: swap_remove_multiple(outer_operands, indexes_to_undistribute),
1086 };
1087 undistribute_from.undistribute_and_or();
1090 outer_operands.push(undistribute_from);
1093 }
1094 }
1095 }
1096 }
1097 }
1098
1099 pub fn non_null_requirements(&self, columns: &mut BTreeSet<usize>) {
1103 match self {
1104 MirScalarExpr::Column(col, _name) => {
1105 columns.insert(*col);
1106 }
1107 MirScalarExpr::Literal(..) => {}
1108 MirScalarExpr::CallUnmaterializable(_) => (),
1109 MirScalarExpr::CallUnary { func, expr } => {
1110 if func.propagates_nulls() {
1111 expr.non_null_requirements(columns);
1112 }
1113 }
1114 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1115 if func.propagates_nulls() {
1116 expr1.non_null_requirements(columns);
1117 expr2.non_null_requirements(columns);
1118 }
1119 }
1120 MirScalarExpr::CallVariadic { func, exprs } => {
1121 if func.propagates_nulls() {
1122 for expr in exprs {
1123 expr.non_null_requirements(columns);
1124 }
1125 }
1126 }
1127 MirScalarExpr::If { .. } => (),
1128 }
1129 }
1130
1131 pub fn sql_typ(&self, column_types: &[SqlColumnType]) -> SqlColumnType {
1132 let repr_column_types = column_types.iter().map(ReprColumnType::from).collect_vec();
1133 SqlColumnType::from_repr(&self.typ(&repr_column_types))
1134 }
1135
1136 pub fn typ(&self, column_types: &[ReprColumnType]) -> ReprColumnType {
1137 match self {
1138 MirScalarExpr::Column(i, _name) => column_types[*i].clone(),
1139 MirScalarExpr::Literal(_, typ) => typ.clone(),
1140 MirScalarExpr::CallUnmaterializable(func) => func.output_type(),
1141 MirScalarExpr::CallUnary { expr, func } => func.output_type(expr.typ(column_types)),
1142 MirScalarExpr::CallBinary { expr1, expr2, func } => {
1143 func.output_type(&[expr1.typ(column_types), expr2.typ(column_types)])
1144 }
1145 MirScalarExpr::CallVariadic { exprs, func } => {
1146 func.output_type(exprs.iter().map(|e| e.typ(column_types)).collect())
1147 }
1148 MirScalarExpr::If { cond: _, then, els } => {
1149 let then_type = then.typ(column_types);
1150 let else_type = els.typ(column_types);
1151 then_type.union(&else_type).unwrap()
1152 }
1153 }
1154 }
1155
1156 pub fn eval<'a>(
1157 &'a self,
1158 datums: &[Datum<'a>],
1159 temp_storage: &'a RowArena,
1160 ) -> Result<Datum<'a>, EvalError> {
1161 match self {
1162 MirScalarExpr::Column(index, _name) => Ok(datums[*index]),
1163 MirScalarExpr::Literal(res, _column_type) => match res {
1164 Ok(row) => Ok(row.unpack_first()),
1165 Err(e) => Err(e.clone()),
1166 },
1167 MirScalarExpr::CallUnmaterializable(x) => Err(EvalError::Internal(
1171 format!("cannot evaluate unmaterializable function: {:?}", x).into(),
1172 )),
1173 MirScalarExpr::CallUnary { func, expr } => func.eval(datums, temp_storage, expr),
1174 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1175 func.eval(datums, temp_storage, &[expr1, expr2])
1176 }
1177 MirScalarExpr::CallVariadic { func, exprs } => func.eval(datums, temp_storage, exprs),
1178 MirScalarExpr::If { cond, then, els } => match cond.eval(datums, temp_storage)? {
1179 Datum::True => then.eval(datums, temp_storage),
1180 Datum::False | Datum::Null => els.eval(datums, temp_storage),
1181 d => Err(EvalError::Internal(
1182 format!("if condition evaluated to non-boolean datum: {:?}", d).into(),
1183 )),
1184 },
1185 }
1186 }
1187
1188 pub fn contains_temporal(&self) -> bool {
1191 let mut contains = false;
1192 self.visit_pre(|e| {
1193 if let MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow) = e {
1194 contains = true;
1195 }
1196 });
1197 contains
1198 }
1199
1200 pub fn contains_unmaterializable(&self) -> bool {
1202 let mut contains = false;
1203 self.visit_pre(|e| {
1204 if let MirScalarExpr::CallUnmaterializable(_) = e {
1205 contains = true;
1206 }
1207 });
1208 contains
1209 }
1210
1211 pub fn contains_unmaterializable_except(&self, exceptions: &[UnmaterializableFunc]) -> bool {
1214 let mut contains = false;
1215 self.visit_pre(|e| match e {
1216 MirScalarExpr::CallUnmaterializable(f) if !exceptions.contains(f) => contains = true,
1217 _ => (),
1218 });
1219 contains
1220 }
1221
1222 pub fn contains_column(&self) -> bool {
1224 let mut contains = false;
1225 self.visit_pre(|e| {
1226 if let MirScalarExpr::Column(_col, _name) = e {
1227 contains = true;
1228 }
1229 });
1230 contains
1231 }
1232
1233 pub fn contains_dummy(&self) -> bool {
1235 let mut contains = false;
1236 self.visit_pre(|e| {
1237 if let MirScalarExpr::Literal(row, _) = e {
1238 if let Ok(row) = row {
1239 contains |= row.iter().any(|d| d.contains_dummy());
1240 }
1241 }
1242 });
1243 contains
1244 }
1245
1246 pub fn size(&self) -> usize {
1248 let mut size = 0;
1249 self.visit_pre(&mut |_: &MirScalarExpr| {
1250 size += 1;
1251 });
1252 size
1253 }
1254}
1255
1256impl MirScalarExpr {
1257 pub fn could_error(&self) -> bool {
1259 match self {
1260 MirScalarExpr::Column(_col, _name) => false,
1261 MirScalarExpr::Literal(row, ..) => row.is_err(),
1262 MirScalarExpr::CallUnmaterializable(_) => true,
1263 MirScalarExpr::CallUnary { func, expr } => func.could_error() || expr.could_error(),
1264 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1265 func.could_error() || expr1.could_error() || expr2.could_error()
1266 }
1267 MirScalarExpr::CallVariadic { func, exprs } => {
1268 func.could_error() || exprs.iter().any(|e| e.could_error())
1269 }
1270 MirScalarExpr::If { cond, then, els } => {
1271 cond.could_error() || then.could_error() || els.could_error()
1272 }
1273 }
1274 }
1275}
1276
1277impl VisitChildren<Self> for MirScalarExpr {
1278 fn visit_children<F>(&self, mut f: F)
1279 where
1280 F: FnMut(&Self),
1281 {
1282 use MirScalarExpr::*;
1283 match self {
1284 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1285 CallUnary { expr, .. } => {
1286 f(expr);
1287 }
1288 CallBinary { expr1, expr2, .. } => {
1289 f(expr1);
1290 f(expr2);
1291 }
1292 CallVariadic { exprs, .. } => {
1293 for expr in exprs {
1294 f(expr);
1295 }
1296 }
1297 If { cond, then, els } => {
1298 f(cond);
1299 f(then);
1300 f(els);
1301 }
1302 }
1303 }
1304
1305 fn visit_mut_children<F>(&mut self, mut f: F)
1306 where
1307 F: FnMut(&mut Self),
1308 {
1309 use MirScalarExpr::*;
1310 match self {
1311 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1312 CallUnary { expr, .. } => {
1313 f(expr);
1314 }
1315 CallBinary { expr1, expr2, .. } => {
1316 f(expr1);
1317 f(expr2);
1318 }
1319 CallVariadic { exprs, .. } => {
1320 for expr in exprs {
1321 f(expr);
1322 }
1323 }
1324 If { cond, then, els } => {
1325 f(cond);
1326 f(then);
1327 f(els);
1328 }
1329 }
1330 }
1331
1332 fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
1333 where
1334 F: FnMut(&Self) -> Result<(), E>,
1335 E: From<RecursionLimitError>,
1336 {
1337 use MirScalarExpr::*;
1338 match self {
1339 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1340 CallUnary { expr, .. } => {
1341 f(expr)?;
1342 }
1343 CallBinary { expr1, expr2, .. } => {
1344 f(expr1)?;
1345 f(expr2)?;
1346 }
1347 CallVariadic { exprs, .. } => {
1348 for expr in exprs {
1349 f(expr)?;
1350 }
1351 }
1352 If { cond, then, els } => {
1353 f(cond)?;
1354 f(then)?;
1355 f(els)?;
1356 }
1357 }
1358 Ok(())
1359 }
1360
1361 fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
1362 where
1363 F: FnMut(&mut Self) -> Result<(), E>,
1364 E: From<RecursionLimitError>,
1365 {
1366 use MirScalarExpr::*;
1367 match self {
1368 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1369 CallUnary { expr, .. } => {
1370 f(expr)?;
1371 }
1372 CallBinary { expr1, expr2, .. } => {
1373 f(expr1)?;
1374 f(expr2)?;
1375 }
1376 CallVariadic { exprs, .. } => {
1377 for expr in exprs {
1378 f(expr)?;
1379 }
1380 }
1381 If { cond, then, els } => {
1382 f(cond)?;
1383 f(then)?;
1384 f(els)?;
1385 }
1386 }
1387 Ok(())
1388 }
1389}
1390
1391impl MirScalarExpr {
1392 pub fn children(&self) -> impl DoubleEndedIterator<Item = &Self> {
1394 let mut first = None;
1395 let mut second = None;
1396 let mut third = None;
1397 let mut variadic = None;
1398
1399 use MirScalarExpr::*;
1400 match self {
1401 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1402 CallUnary { expr, .. } => {
1403 first = Some(&**expr);
1404 }
1405 CallBinary { expr1, expr2, .. } => {
1406 first = Some(&**expr1);
1407 second = Some(&**expr2);
1408 }
1409 CallVariadic { exprs, .. } => {
1410 variadic = Some(exprs);
1411 }
1412 If { cond, then, els } => {
1413 first = Some(&**cond);
1414 second = Some(&**then);
1415 third = Some(&**els);
1416 }
1417 }
1418
1419 first
1420 .into_iter()
1421 .chain(second)
1422 .chain(third)
1423 .chain(variadic.into_iter().flatten())
1424 }
1425
1426 pub fn children_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Self> {
1428 let mut first = None;
1429 let mut second = None;
1430 let mut third = None;
1431 let mut variadic = None;
1432
1433 use MirScalarExpr::*;
1434 match self {
1435 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
1436 CallUnary { expr, .. } => {
1437 first = Some(&mut **expr);
1438 }
1439 CallBinary { expr1, expr2, .. } => {
1440 first = Some(&mut **expr1);
1441 second = Some(&mut **expr2);
1442 }
1443 CallVariadic { exprs, .. } => {
1444 variadic = Some(exprs);
1445 }
1446 If { cond, then, els } => {
1447 first = Some(&mut **cond);
1448 second = Some(&mut **then);
1449 third = Some(&mut **els);
1450 }
1451 }
1452
1453 first
1454 .into_iter()
1455 .chain(second)
1456 .chain(third)
1457 .chain(variadic.into_iter().flatten())
1458 }
1459
1460 pub fn visit_pre<F>(&self, mut f: F)
1462 where
1463 F: FnMut(&Self),
1464 {
1465 let mut worklist = vec![self];
1466 while let Some(e) = worklist.pop() {
1467 f(e);
1468 worklist.extend(e.children().rev());
1469 }
1470 }
1471
1472 pub fn visit_pre_mut<F: FnMut(&mut Self)>(&mut self, mut f: F) {
1474 let mut worklist = vec![self];
1475 while let Some(expr) = worklist.pop() {
1476 f(expr);
1477 worklist.extend(expr.children_mut().rev());
1478 }
1479 }
1480}
1481
1482#[derive(
1489 Eq,
1490 PartialEq,
1491 Ord,
1492 PartialOrd,
1493 Debug,
1494 Clone,
1495 Serialize,
1496 Deserialize,
1497 Hash,
1498 MzReflect
1499)]
1500pub struct FilterCharacteristics {
1501 literal_equality: bool,
1504 like: bool,
1506 is_null: bool,
1507 literal_inequality: usize,
1513 any_filter: bool,
1519}
1520
1521impl BitOrAssign for FilterCharacteristics {
1522 fn bitor_assign(&mut self, rhs: Self) {
1523 self.literal_equality |= rhs.literal_equality;
1524 self.like |= rhs.like;
1525 self.is_null |= rhs.is_null;
1526 self.literal_inequality += rhs.literal_inequality;
1527 self.any_filter |= rhs.any_filter;
1528 }
1529}
1530
1531impl FilterCharacteristics {
1532 pub fn none() -> FilterCharacteristics {
1533 FilterCharacteristics {
1534 literal_equality: false,
1535 like: false,
1536 is_null: false,
1537 literal_inequality: 0,
1538 any_filter: false,
1539 }
1540 }
1541
1542 pub fn explain(&self) -> String {
1543 let mut e = "".to_owned();
1544 if self.literal_equality {
1545 e.push_str("e");
1546 }
1547 if self.like {
1548 e.push_str("l");
1549 }
1550 if self.is_null {
1551 e.push_str("n");
1552 }
1553 for _ in 0..self.literal_inequality {
1554 e.push_str("i");
1555 }
1556 if self.any_filter {
1557 e.push_str("f");
1558 }
1559 e
1560 }
1561
1562 pub fn filter_characteristics(
1563 filters: &Vec<MirScalarExpr>,
1564 ) -> Result<FilterCharacteristics, RecursionLimitError> {
1565 let mut literal_equality = false;
1566 let mut like = false;
1567 let mut is_null = false;
1568 let mut literal_inequality = 0;
1569 let mut any_filter = false;
1570 filters.iter().try_for_each(|f| {
1571 let mut literal_inequality_in_current_filter = false;
1572 let mut is_not_null_in_current_filter = false;
1573 f.visit_pre_with_context(
1574 false,
1575 &mut |not_in_parent_chain, expr| {
1576 not_in_parent_chain
1577 || matches!(
1578 expr,
1579 MirScalarExpr::CallUnary {
1580 func: UnaryFunc::Not(func::Not),
1581 ..
1582 }
1583 )
1584 },
1585 &mut |not_in_parent_chain, expr| {
1586 if !not_in_parent_chain {
1587 if expr.any_expr_eq_literal().is_some() {
1588 literal_equality = true;
1589 }
1590 if expr.any_expr_ineq_literal() {
1591 literal_inequality_in_current_filter = true;
1592 }
1593 if matches!(
1594 expr,
1595 MirScalarExpr::CallUnary {
1596 func: UnaryFunc::IsLikeMatch(_),
1597 ..
1598 }
1599 ) {
1600 like = true;
1601 }
1602 };
1603 if matches!(
1604 expr,
1605 MirScalarExpr::CallUnary {
1606 func: UnaryFunc::IsNull(crate::func::IsNull),
1607 ..
1608 }
1609 ) {
1610 if *not_in_parent_chain {
1611 is_not_null_in_current_filter = true;
1612 } else {
1613 is_null = true;
1614 }
1615 }
1616 },
1617 )?;
1618 if literal_inequality_in_current_filter {
1619 literal_inequality += 1;
1620 }
1621 if !is_not_null_in_current_filter {
1622 any_filter = true;
1624 }
1625 Ok(())
1626 })?;
1627 Ok(FilterCharacteristics {
1628 literal_equality,
1629 like,
1630 is_null,
1631 literal_inequality,
1632 any_filter,
1633 })
1634 }
1635
1636 pub fn add_literal_equality(&mut self) {
1637 self.literal_equality = true;
1638 }
1639
1640 pub fn worst_case_scaling_factor(&self) -> f64 {
1641 let mut factor = 1.0;
1642
1643 if self.literal_equality {
1644 factor *= 0.1;
1645 }
1646
1647 if self.is_null {
1648 factor *= 0.1;
1649 }
1650
1651 if self.literal_inequality >= 2 {
1652 factor *= 0.25;
1653 } else if self.literal_inequality == 1 {
1654 factor *= 0.33;
1655 }
1656
1657 if !(self.literal_equality || self.is_null || self.literal_inequality > 0)
1659 && self.any_filter
1660 {
1661 factor *= 0.9;
1662 }
1663
1664 factor
1665 }
1666}
1667
1668#[derive(
1669 Ord,
1670 PartialOrd,
1671 Copy,
1672 Clone,
1673 Debug,
1674 Eq,
1675 PartialEq,
1676 Serialize,
1677 Deserialize,
1678 Hash,
1679 MzReflect
1680)]
1681#[cfg_attr(any(test, feature = "proptest"), derive(Arbitrary))]
1682pub enum DomainLimit {
1683 None,
1684 Inclusive(i64),
1685 Exclusive(i64),
1686}
1687
1688impl RustType<ProtoDomainLimit> for DomainLimit {
1689 fn into_proto(&self) -> ProtoDomainLimit {
1690 use proto_domain_limit::Kind::*;
1691 let kind = match self {
1692 DomainLimit::None => None(()),
1693 DomainLimit::Inclusive(v) => Inclusive(*v),
1694 DomainLimit::Exclusive(v) => Exclusive(*v),
1695 };
1696 ProtoDomainLimit { kind: Some(kind) }
1697 }
1698
1699 fn from_proto(proto: ProtoDomainLimit) -> Result<Self, TryFromProtoError> {
1700 use proto_domain_limit::Kind::*;
1701 if let Some(kind) = proto.kind {
1702 match kind {
1703 None(()) => Ok(DomainLimit::None),
1704 Inclusive(v) => Ok(DomainLimit::Inclusive(v)),
1705 Exclusive(v) => Ok(DomainLimit::Exclusive(v)),
1706 }
1707 } else {
1708 Err(TryFromProtoError::missing_field("ProtoDomainLimit::kind"))
1709 }
1710 }
1711}
1712
1713#[derive(
1714 Ord,
1715 PartialOrd,
1716 Clone,
1717 Debug,
1718 Eq,
1719 PartialEq,
1720 Serialize,
1721 Deserialize,
1722 Hash,
1723 MzReflect
1724)]
1725#[cfg_attr(any(test, feature = "proptest"), derive(Arbitrary))]
1726pub enum EvalError {
1727 CharacterNotValidForEncoding(i32),
1728 CharacterTooLargeForEncoding(i32),
1729 DateBinOutOfRange(Box<str>),
1730 DivisionByZero,
1731 Unsupported {
1732 feature: Box<str>,
1733 discussion_no: Option<usize>,
1734 },
1735 FloatOverflow,
1736 FloatUnderflow,
1737 NumericFieldOverflow,
1738 Float32OutOfRange(Box<str>),
1739 Float64OutOfRange(Box<str>),
1740 Int16OutOfRange(Box<str>),
1741 Int32OutOfRange(Box<str>),
1742 Int64OutOfRange(Box<str>),
1743 UInt16OutOfRange(Box<str>),
1744 UInt32OutOfRange(Box<str>),
1745 UInt64OutOfRange(Box<str>),
1746 MzTimestampOutOfRange(Box<str>),
1747 MzTimestampStepOverflow,
1748 OidOutOfRange(Box<str>),
1749 IntervalOutOfRange(Box<str>),
1750 TimestampCannotBeNan,
1751 TimestampOutOfRange,
1752 DateOutOfRange,
1753 CharOutOfRange,
1754 IndexOutOfRange {
1755 provided: i32,
1756 valid_end: i32,
1758 },
1759 InvalidBase64Equals,
1760 InvalidBase64Symbol(char),
1761 InvalidBase64EndSequence,
1762 InvalidTimezone(Box<str>),
1763 InvalidTimezoneInterval,
1764 InvalidTimezoneConversion,
1765 InvalidIanaTimezoneId(Box<str>),
1766 InvalidLayer {
1767 max_layer: usize,
1768 val: i64,
1769 },
1770 InvalidArray(InvalidArrayError),
1771 InvalidEncodingName(Box<str>),
1772 InvalidHashAlgorithm(Box<str>),
1773 InvalidByteSequence {
1774 byte_sequence: Box<str>,
1775 encoding_name: Box<str>,
1776 },
1777 InvalidJsonbCast {
1778 from: Box<str>,
1779 to: Box<str>,
1780 },
1781 InvalidRegex(Box<str>),
1782 InvalidRegexFlag(char),
1783 InvalidParameterValue(Box<str>),
1784 InvalidDatePart(Box<str>),
1785 KeyCannotBeNull,
1786 NegSqrt,
1787 NegLimit,
1788 NullCharacterNotPermitted,
1789 UnknownUnits(Box<str>),
1790 UnsupportedUnits(Box<str>, Box<str>),
1791 UnterminatedLikeEscapeSequence,
1792 Parse(ParseError),
1793 ParseHex(ParseHexError),
1794 Internal(Box<str>),
1795 InfinityOutOfDomain(Box<str>),
1796 NegativeOutOfDomain(Box<str>),
1797 ZeroOutOfDomain(Box<str>),
1798 OutOfDomain(DomainLimit, DomainLimit, Box<str>),
1799 ComplexOutOfRange(Box<str>),
1800 MultipleRowsFromSubquery,
1801 NegativeRowsFromSubquery,
1802 Undefined(Box<str>),
1803 LikePatternTooLong,
1804 LikeEscapeTooLong,
1805 StringValueTooLong {
1806 target_type: Box<str>,
1807 length: usize,
1808 },
1809 MultidimensionalArrayRemovalNotSupported,
1810 IncompatibleArrayDimensions {
1811 dims: Option<(usize, usize)>,
1812 },
1813 TypeFromOid(Box<str>),
1814 InvalidRange(InvalidRangeError),
1815 InvalidRoleId(Box<str>),
1816 InvalidPrivileges(Box<str>),
1817 InvalidCatalogJson(Box<str>),
1818 LetRecLimitExceeded(Box<str>),
1819 MultiDimensionalArraySearch,
1820 MustNotBeNull(Box<str>),
1821 InvalidIdentifier {
1822 ident: Box<str>,
1823 detail: Option<Box<str>>,
1824 },
1825 ArrayFillWrongArraySubscripts,
1826 MaxArraySizeExceeded(usize),
1828 DateDiffOverflow {
1829 unit: Box<str>,
1830 a: Box<str>,
1831 b: Box<str>,
1832 },
1833 IfNullError(Box<str>),
1836 LengthTooLarge,
1837 AclArrayNullElement,
1838 MzAclArrayNullElement,
1839 PrettyError(Box<str>),
1840 RedactError(Box<str>),
1841}
1842
1843impl fmt::Display for EvalError {
1844 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1845 match self {
1846 EvalError::CharacterNotValidForEncoding(v) => {
1847 write!(f, "requested character not valid for encoding: {v}")
1848 }
1849 EvalError::CharacterTooLargeForEncoding(v) => {
1850 write!(f, "requested character too large for encoding: {v}")
1851 }
1852 EvalError::DateBinOutOfRange(message) => f.write_str(message),
1853 EvalError::DivisionByZero => f.write_str("division by zero"),
1854 EvalError::Unsupported {
1855 feature,
1856 discussion_no,
1857 } => {
1858 write!(f, "{} not yet supported", feature)?;
1859 if let Some(discussion_no) = discussion_no {
1860 write!(
1861 f,
1862 ", see https://github.com/MaterializeInc/materialize/discussions/{} for more details",
1863 discussion_no
1864 )?;
1865 }
1866 Ok(())
1867 }
1868 EvalError::FloatOverflow => f.write_str("value out of range: overflow"),
1869 EvalError::FloatUnderflow => f.write_str("value out of range: underflow"),
1870 EvalError::NumericFieldOverflow => f.write_str("numeric field overflow"),
1871 EvalError::Float32OutOfRange(val) => write!(f, "{} real out of range", val.quoted()),
1872 EvalError::Float64OutOfRange(val) => {
1873 write!(f, "{} double precision out of range", val.quoted())
1874 }
1875 EvalError::Int16OutOfRange(val) => write!(f, "{} smallint out of range", val.quoted()),
1876 EvalError::Int32OutOfRange(val) => write!(f, "{} integer out of range", val.quoted()),
1877 EvalError::Int64OutOfRange(val) => write!(f, "{} bigint out of range", val.quoted()),
1878 EvalError::UInt16OutOfRange(val) => write!(f, "{} uint2 out of range", val.quoted()),
1879 EvalError::UInt32OutOfRange(val) => write!(f, "{} uint4 out of range", val.quoted()),
1880 EvalError::UInt64OutOfRange(val) => write!(f, "{} uint8 out of range", val.quoted()),
1881 EvalError::MzTimestampOutOfRange(val) => {
1882 write!(f, "{} mz_timestamp out of range", val.quoted())
1883 }
1884 EvalError::MzTimestampStepOverflow => f.write_str("step mz_timestamp overflow"),
1885 EvalError::OidOutOfRange(val) => write!(f, "{} OID out of range", val.quoted()),
1886 EvalError::IntervalOutOfRange(val) => {
1887 write!(f, "{} interval out of range", val.quoted())
1888 }
1889 EvalError::TimestampCannotBeNan => f.write_str("timestamp cannot be NaN"),
1890 EvalError::TimestampOutOfRange => f.write_str("timestamp out of range"),
1891 EvalError::DateOutOfRange => f.write_str("date out of range"),
1892 EvalError::CharOutOfRange => f.write_str("\"char\" out of range"),
1893 EvalError::IndexOutOfRange {
1894 provided,
1895 valid_end,
1896 } => write!(f, "index {provided} out of valid range, 0..{valid_end}",),
1897 EvalError::InvalidBase64Equals => {
1898 f.write_str("unexpected \"=\" while decoding base64 sequence")
1899 }
1900 EvalError::InvalidBase64Symbol(c) => write!(
1901 f,
1902 "invalid symbol \"{}\" found while decoding base64 sequence",
1903 c.escape_default()
1904 ),
1905 EvalError::InvalidBase64EndSequence => f.write_str("invalid base64 end sequence"),
1906 EvalError::InvalidJsonbCast { from, to } => {
1907 write!(f, "cannot cast jsonb {} to type {}", from, to)
1908 }
1909 EvalError::InvalidTimezone(tz) => write!(f, "invalid time zone '{}'", tz),
1910 EvalError::InvalidTimezoneInterval => {
1911 f.write_str("timezone interval must not contain months or years")
1912 }
1913 EvalError::InvalidTimezoneConversion => f.write_str("invalid timezone conversion"),
1914 EvalError::InvalidIanaTimezoneId(tz) => {
1915 write!(f, "invalid IANA Time Zone Database identifier: '{}'", tz)
1916 }
1917 EvalError::InvalidLayer { max_layer, val } => write!(
1918 f,
1919 "invalid layer: {}; must use value within [1, {}]",
1920 val, max_layer
1921 ),
1922 EvalError::InvalidArray(e) => e.fmt(f),
1923 EvalError::InvalidEncodingName(name) => write!(f, "invalid encoding name '{}'", name),
1924 EvalError::InvalidHashAlgorithm(alg) => write!(f, "invalid hash algorithm '{}'", alg),
1925 EvalError::InvalidByteSequence {
1926 byte_sequence,
1927 encoding_name,
1928 } => write!(
1929 f,
1930 "invalid byte sequence '{}' for encoding '{}'",
1931 byte_sequence, encoding_name
1932 ),
1933 EvalError::InvalidDatePart(part) => write!(f, "invalid datepart {}", part.quoted()),
1934 EvalError::KeyCannotBeNull => f.write_str("key cannot be null"),
1935 EvalError::NegSqrt => f.write_str("cannot take square root of a negative number"),
1936 EvalError::NegLimit => f.write_str("LIMIT must not be negative"),
1937 EvalError::NullCharacterNotPermitted => f.write_str("null character not permitted"),
1938 EvalError::InvalidRegex(e) => write!(f, "invalid regular expression: {}", e),
1939 EvalError::InvalidRegexFlag(c) => write!(f, "invalid regular expression flag: {}", c),
1940 EvalError::InvalidParameterValue(s) => f.write_str(s),
1941 EvalError::UnknownUnits(units) => write!(f, "unit '{}' not recognized", units),
1942 EvalError::UnsupportedUnits(units, typ) => {
1943 write!(f, "unit '{}' not supported for type {}", units, typ)
1944 }
1945 EvalError::UnterminatedLikeEscapeSequence => {
1946 f.write_str("unterminated escape sequence in LIKE")
1947 }
1948 EvalError::Parse(e) => e.fmt(f),
1949 EvalError::PrettyError(e) => e.fmt(f),
1950 EvalError::RedactError(e) => e.fmt(f),
1951 EvalError::ParseHex(e) => e.fmt(f),
1952 EvalError::Internal(s) => write!(f, "internal error: {}", s),
1953 EvalError::InfinityOutOfDomain(s) => {
1954 write!(f, "function {} is only defined for finite arguments", s)
1955 }
1956 EvalError::NegativeOutOfDomain(s) => {
1957 write!(f, "function {} is not defined for negative numbers", s)
1958 }
1959 EvalError::ZeroOutOfDomain(s) => {
1960 write!(f, "function {} is not defined for zero", s)
1961 }
1962 EvalError::OutOfDomain(lower, upper, s) => {
1963 use DomainLimit::*;
1964 write!(f, "function {s} is defined for numbers ")?;
1965 match (lower, upper) {
1966 (Inclusive(n), None) => write!(f, "greater than or equal to {n}"),
1967 (Exclusive(n), None) => write!(f, "greater than {n}"),
1968 (None, Inclusive(n)) => write!(f, "less than or equal to {n}"),
1969 (None, Exclusive(n)) => write!(f, "less than {n}"),
1970 (Inclusive(lo), Inclusive(hi)) => write!(f, "between {lo} and {hi} inclusive"),
1971 (Exclusive(lo), Exclusive(hi)) => write!(f, "between {lo} and {hi} exclusive"),
1972 (Inclusive(lo), Exclusive(hi)) => {
1973 write!(f, "between {lo} inclusive and {hi} exclusive")
1974 }
1975 (Exclusive(lo), Inclusive(hi)) => {
1976 write!(f, "between {lo} exclusive and {hi} inclusive")
1977 }
1978 (None, None) => panic!("invalid domain error"),
1979 }
1980 }
1981 EvalError::ComplexOutOfRange(s) => {
1982 write!(f, "function {} cannot return complex numbers", s)
1983 }
1984 EvalError::MultipleRowsFromSubquery => {
1985 write!(f, "more than one record produced in subquery")
1986 }
1987 EvalError::NegativeRowsFromSubquery => {
1988 write!(f, "negative number of rows produced in subquery")
1989 }
1990 EvalError::Undefined(s) => {
1991 write!(f, "{} is undefined", s)
1992 }
1993 EvalError::LikePatternTooLong => {
1994 write!(f, "LIKE pattern exceeds maximum length")
1995 }
1996 EvalError::LikeEscapeTooLong => {
1997 write!(f, "invalid escape string")
1998 }
1999 EvalError::StringValueTooLong {
2000 target_type,
2001 length,
2002 } => {
2003 write!(f, "value too long for type {}({})", target_type, length)
2004 }
2005 EvalError::MultidimensionalArrayRemovalNotSupported => {
2006 write!(
2007 f,
2008 "removing elements from multidimensional arrays is not supported"
2009 )
2010 }
2011 EvalError::IncompatibleArrayDimensions { dims: _ } => {
2012 write!(f, "cannot concatenate incompatible arrays")
2013 }
2014 EvalError::TypeFromOid(msg) => write!(f, "{msg}"),
2015 EvalError::InvalidRange(e) => e.fmt(f),
2016 EvalError::InvalidRoleId(msg) => write!(f, "{msg}"),
2017 EvalError::InvalidPrivileges(privilege) => {
2018 write!(f, "unrecognized privilege type: {privilege}")
2019 }
2020 EvalError::InvalidCatalogJson(msg) => {
2021 write!(f, "invalid catalog JSON: {msg}")
2022 }
2023 EvalError::LetRecLimitExceeded(max_iters) => {
2024 write!(
2025 f,
2026 "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.)",
2027 max_iters
2028 )
2029 }
2030 EvalError::MultiDimensionalArraySearch => write!(
2031 f,
2032 "searching for elements in multidimensional arrays is not supported"
2033 ),
2034 EvalError::MustNotBeNull(v) => write!(f, "{v} must not be null"),
2035 EvalError::InvalidIdentifier { ident, .. } => {
2036 write!(f, "string is not a valid identifier: {}", ident.quoted())
2037 }
2038 EvalError::ArrayFillWrongArraySubscripts => {
2039 f.write_str("wrong number of array subscripts")
2040 }
2041 EvalError::MaxArraySizeExceeded(max_size) => {
2042 write!(
2043 f,
2044 "array size exceeds the maximum allowed ({max_size} bytes)"
2045 )
2046 }
2047 EvalError::DateDiffOverflow { unit, a, b } => {
2048 write!(f, "datediff overflow, {unit} of {a}, {b}")
2049 }
2050 EvalError::IfNullError(s) => f.write_str(s),
2051 EvalError::LengthTooLarge => write!(f, "requested length too large"),
2052 EvalError::AclArrayNullElement => write!(f, "ACL arrays must not contain null values"),
2053 EvalError::MzAclArrayNullElement => {
2054 write!(f, "MZ_ACL arrays must not contain null values")
2055 }
2056 }
2057 }
2058}
2059
2060impl EvalError {
2061 pub fn detail(&self) -> Option<String> {
2062 match self {
2063 EvalError::IncompatibleArrayDimensions { dims: None } => Some(
2064 "Arrays with differing dimensions are not compatible for concatenation.".into(),
2065 ),
2066 EvalError::IncompatibleArrayDimensions {
2067 dims: Some((a_dims, b_dims)),
2068 } => Some(format!(
2069 "Arrays of {} and {} dimensions are not compatible for concatenation.",
2070 a_dims, b_dims
2071 )),
2072 EvalError::InvalidIdentifier { detail, .. } => detail.as_deref().map(Into::into),
2073 EvalError::ArrayFillWrongArraySubscripts => {
2074 Some("Low bound array has different size than dimensions array.".into())
2075 }
2076 _ => None,
2077 }
2078 }
2079
2080 pub fn hint(&self) -> Option<String> {
2081 match self {
2082 EvalError::InvalidBase64EndSequence => Some(
2083 "Input data is missing padding, is truncated, or is otherwise corrupted.".into(),
2084 ),
2085 EvalError::LikeEscapeTooLong => {
2086 Some("Escape string must be empty or one character.".into())
2087 }
2088 EvalError::MzTimestampOutOfRange(_) => Some(
2089 "Integer, numeric, and text casts to mz_timestamp must be in the form of whole \
2090 milliseconds since the Unix epoch. Values with fractional parts cannot be \
2091 converted to mz_timestamp."
2092 .into(),
2093 ),
2094 _ => None,
2095 }
2096 }
2097}
2098
2099impl std::error::Error for EvalError {}
2100
2101impl From<ParseError> for EvalError {
2102 fn from(e: ParseError) -> EvalError {
2103 EvalError::Parse(e)
2104 }
2105}
2106
2107impl From<ParseHexError> for EvalError {
2108 fn from(e: ParseHexError) -> EvalError {
2109 EvalError::ParseHex(e)
2110 }
2111}
2112
2113impl From<InvalidArrayError> for EvalError {
2114 fn from(e: InvalidArrayError) -> EvalError {
2115 EvalError::InvalidArray(e)
2116 }
2117}
2118
2119impl From<RegexCompilationError> for EvalError {
2120 fn from(e: RegexCompilationError) -> EvalError {
2121 EvalError::InvalidRegex(e.to_string().into())
2122 }
2123}
2124
2125impl From<TypeFromOidError> for EvalError {
2126 fn from(e: TypeFromOidError) -> EvalError {
2127 EvalError::TypeFromOid(e.to_string().into())
2128 }
2129}
2130
2131impl From<DateError> for EvalError {
2132 fn from(e: DateError) -> EvalError {
2133 match e {
2134 DateError::OutOfRange => EvalError::DateOutOfRange,
2135 }
2136 }
2137}
2138
2139impl From<TimestampError> for EvalError {
2140 fn from(e: TimestampError) -> EvalError {
2141 match e {
2142 TimestampError::OutOfRange => EvalError::TimestampOutOfRange,
2143 }
2144 }
2145}
2146
2147impl From<InvalidRangeError> for EvalError {
2148 fn from(e: InvalidRangeError) -> EvalError {
2149 EvalError::InvalidRange(e)
2150 }
2151}
2152
2153impl RustType<ProtoEvalError> for EvalError {
2154 fn into_proto(&self) -> ProtoEvalError {
2155 use proto_eval_error::Kind::*;
2156 use proto_eval_error::*;
2157 let kind = match self {
2158 EvalError::CharacterNotValidForEncoding(v) => CharacterNotValidForEncoding(*v),
2159 EvalError::CharacterTooLargeForEncoding(v) => CharacterTooLargeForEncoding(*v),
2160 EvalError::DateBinOutOfRange(v) => DateBinOutOfRange(v.into_proto()),
2161 EvalError::DivisionByZero => DivisionByZero(()),
2162 EvalError::Unsupported {
2163 feature,
2164 discussion_no,
2165 } => Unsupported(ProtoUnsupported {
2166 feature: feature.into_proto(),
2167 discussion_no: discussion_no.into_proto(),
2168 }),
2169 EvalError::FloatOverflow => FloatOverflow(()),
2170 EvalError::FloatUnderflow => FloatUnderflow(()),
2171 EvalError::NumericFieldOverflow => NumericFieldOverflow(()),
2172 EvalError::Float32OutOfRange(val) => Float32OutOfRange(ProtoValueOutOfRange {
2173 value: val.to_string(),
2174 }),
2175 EvalError::Float64OutOfRange(val) => Float64OutOfRange(ProtoValueOutOfRange {
2176 value: val.to_string(),
2177 }),
2178 EvalError::Int16OutOfRange(val) => Int16OutOfRange(ProtoValueOutOfRange {
2179 value: val.to_string(),
2180 }),
2181 EvalError::Int32OutOfRange(val) => Int32OutOfRange(ProtoValueOutOfRange {
2182 value: val.to_string(),
2183 }),
2184 EvalError::Int64OutOfRange(val) => Int64OutOfRange(ProtoValueOutOfRange {
2185 value: val.to_string(),
2186 }),
2187 EvalError::UInt16OutOfRange(val) => Uint16OutOfRange(ProtoValueOutOfRange {
2188 value: val.to_string(),
2189 }),
2190 EvalError::UInt32OutOfRange(val) => Uint32OutOfRange(ProtoValueOutOfRange {
2191 value: val.to_string(),
2192 }),
2193 EvalError::UInt64OutOfRange(val) => Uint64OutOfRange(ProtoValueOutOfRange {
2194 value: val.to_string(),
2195 }),
2196 EvalError::MzTimestampOutOfRange(val) => MzTimestampOutOfRange(ProtoValueOutOfRange {
2197 value: val.to_string(),
2198 }),
2199 EvalError::MzTimestampStepOverflow => MzTimestampStepOverflow(()),
2200 EvalError::OidOutOfRange(val) => OidOutOfRange(ProtoValueOutOfRange {
2201 value: val.to_string(),
2202 }),
2203 EvalError::IntervalOutOfRange(val) => IntervalOutOfRange(ProtoValueOutOfRange {
2204 value: val.to_string(),
2205 }),
2206 EvalError::TimestampCannotBeNan => TimestampCannotBeNan(()),
2207 EvalError::TimestampOutOfRange => TimestampOutOfRange(()),
2208 EvalError::DateOutOfRange => DateOutOfRange(()),
2209 EvalError::CharOutOfRange => CharOutOfRange(()),
2210 EvalError::IndexOutOfRange {
2211 provided,
2212 valid_end,
2213 } => IndexOutOfRange(ProtoIndexOutOfRange {
2214 provided: *provided,
2215 valid_end: *valid_end,
2216 }),
2217 EvalError::InvalidBase64Equals => InvalidBase64Equals(()),
2218 EvalError::InvalidBase64Symbol(sym) => InvalidBase64Symbol(sym.into_proto()),
2219 EvalError::InvalidBase64EndSequence => InvalidBase64EndSequence(()),
2220 EvalError::InvalidTimezone(tz) => InvalidTimezone(tz.into_proto()),
2221 EvalError::InvalidTimezoneInterval => InvalidTimezoneInterval(()),
2222 EvalError::InvalidTimezoneConversion => InvalidTimezoneConversion(()),
2223 EvalError::InvalidLayer { max_layer, val } => InvalidLayer(ProtoInvalidLayer {
2224 max_layer: max_layer.into_proto(),
2225 val: *val,
2226 }),
2227 EvalError::InvalidArray(error) => InvalidArray(error.into_proto()),
2228 EvalError::InvalidEncodingName(v) => InvalidEncodingName(v.into_proto()),
2229 EvalError::InvalidHashAlgorithm(v) => InvalidHashAlgorithm(v.into_proto()),
2230 EvalError::InvalidByteSequence {
2231 byte_sequence,
2232 encoding_name,
2233 } => InvalidByteSequence(ProtoInvalidByteSequence {
2234 byte_sequence: byte_sequence.into_proto(),
2235 encoding_name: encoding_name.into_proto(),
2236 }),
2237 EvalError::InvalidJsonbCast { from, to } => InvalidJsonbCast(ProtoInvalidJsonbCast {
2238 from: from.into_proto(),
2239 to: to.into_proto(),
2240 }),
2241 EvalError::InvalidRegex(v) => InvalidRegex(v.into_proto()),
2242 EvalError::InvalidRegexFlag(v) => InvalidRegexFlag(v.into_proto()),
2243 EvalError::InvalidParameterValue(v) => InvalidParameterValue(v.into_proto()),
2244 EvalError::InvalidDatePart(part) => InvalidDatePart(part.into_proto()),
2245 EvalError::KeyCannotBeNull => KeyCannotBeNull(()),
2246 EvalError::NegSqrt => NegSqrt(()),
2247 EvalError::NegLimit => NegLimit(()),
2248 EvalError::NullCharacterNotPermitted => NullCharacterNotPermitted(()),
2249 EvalError::UnknownUnits(v) => UnknownUnits(v.into_proto()),
2250 EvalError::UnsupportedUnits(units, typ) => UnsupportedUnits(ProtoUnsupportedUnits {
2251 units: units.into_proto(),
2252 typ: typ.into_proto(),
2253 }),
2254 EvalError::UnterminatedLikeEscapeSequence => UnterminatedLikeEscapeSequence(()),
2255 EvalError::Parse(error) => Parse(error.into_proto()),
2256 EvalError::PrettyError(error) => PrettyError(error.into_proto()),
2257 EvalError::RedactError(error) => RedactError(error.into_proto()),
2258 EvalError::ParseHex(error) => ParseHex(error.into_proto()),
2259 EvalError::Internal(v) => Internal(v.into_proto()),
2260 EvalError::InfinityOutOfDomain(v) => InfinityOutOfDomain(v.into_proto()),
2261 EvalError::NegativeOutOfDomain(v) => NegativeOutOfDomain(v.into_proto()),
2262 EvalError::ZeroOutOfDomain(v) => ZeroOutOfDomain(v.into_proto()),
2263 EvalError::OutOfDomain(lower, upper, id) => OutOfDomain(ProtoOutOfDomain {
2264 lower: Some(lower.into_proto()),
2265 upper: Some(upper.into_proto()),
2266 id: id.into_proto(),
2267 }),
2268 EvalError::ComplexOutOfRange(v) => ComplexOutOfRange(v.into_proto()),
2269 EvalError::MultipleRowsFromSubquery => MultipleRowsFromSubquery(()),
2270 EvalError::NegativeRowsFromSubquery => NegativeRowsFromSubquery(()),
2271 EvalError::Undefined(v) => Undefined(v.into_proto()),
2272 EvalError::LikePatternTooLong => LikePatternTooLong(()),
2273 EvalError::LikeEscapeTooLong => LikeEscapeTooLong(()),
2274 EvalError::StringValueTooLong {
2275 target_type,
2276 length,
2277 } => StringValueTooLong(ProtoStringValueTooLong {
2278 target_type: target_type.into_proto(),
2279 length: length.into_proto(),
2280 }),
2281 EvalError::MultidimensionalArrayRemovalNotSupported => {
2282 MultidimensionalArrayRemovalNotSupported(())
2283 }
2284 EvalError::IncompatibleArrayDimensions { dims } => {
2285 IncompatibleArrayDimensions(ProtoIncompatibleArrayDimensions {
2286 dims: dims.into_proto(),
2287 })
2288 }
2289 EvalError::TypeFromOid(v) => TypeFromOid(v.into_proto()),
2290 EvalError::InvalidRange(error) => InvalidRange(error.into_proto()),
2291 EvalError::InvalidRoleId(v) => InvalidRoleId(v.into_proto()),
2292 EvalError::InvalidPrivileges(v) => InvalidPrivileges(v.into_proto()),
2293 EvalError::InvalidCatalogJson(v) => InvalidCatalogJson(v.into_proto()),
2294 EvalError::LetRecLimitExceeded(v) => WmrRecursionLimitExceeded(v.into_proto()),
2295 EvalError::MultiDimensionalArraySearch => MultiDimensionalArraySearch(()),
2296 EvalError::MustNotBeNull(v) => MustNotBeNull(v.into_proto()),
2297 EvalError::InvalidIdentifier { ident, detail } => {
2298 InvalidIdentifier(ProtoInvalidIdentifier {
2299 ident: ident.into_proto(),
2300 detail: detail.into_proto(),
2301 })
2302 }
2303 EvalError::ArrayFillWrongArraySubscripts => ArrayFillWrongArraySubscripts(()),
2304 EvalError::MaxArraySizeExceeded(max_size) => {
2305 MaxArraySizeExceeded(u64::cast_from(*max_size))
2306 }
2307 EvalError::DateDiffOverflow { unit, a, b } => DateDiffOverflow(ProtoDateDiffOverflow {
2308 unit: unit.into_proto(),
2309 a: a.into_proto(),
2310 b: b.into_proto(),
2311 }),
2312 EvalError::IfNullError(s) => IfNullError(s.into_proto()),
2313 EvalError::LengthTooLarge => LengthTooLarge(()),
2314 EvalError::AclArrayNullElement => AclArrayNullElement(()),
2315 EvalError::MzAclArrayNullElement => MzAclArrayNullElement(()),
2316 EvalError::InvalidIanaTimezoneId(s) => InvalidIanaTimezoneId(s.into_proto()),
2317 };
2318 ProtoEvalError { kind: Some(kind) }
2319 }
2320
2321 fn from_proto(proto: ProtoEvalError) -> Result<Self, TryFromProtoError> {
2322 use proto_eval_error::Kind::*;
2323 match proto.kind {
2324 Some(kind) => match kind {
2325 CharacterNotValidForEncoding(v) => Ok(EvalError::CharacterNotValidForEncoding(v)),
2326 CharacterTooLargeForEncoding(v) => Ok(EvalError::CharacterTooLargeForEncoding(v)),
2327 DateBinOutOfRange(v) => Ok(EvalError::DateBinOutOfRange(v.into())),
2328 DivisionByZero(()) => Ok(EvalError::DivisionByZero),
2329 Unsupported(v) => Ok(EvalError::Unsupported {
2330 feature: v.feature.into(),
2331 discussion_no: v.discussion_no.into_rust()?,
2332 }),
2333 FloatOverflow(()) => Ok(EvalError::FloatOverflow),
2334 FloatUnderflow(()) => Ok(EvalError::FloatUnderflow),
2335 NumericFieldOverflow(()) => Ok(EvalError::NumericFieldOverflow),
2336 Float32OutOfRange(val) => Ok(EvalError::Float32OutOfRange(val.value.into())),
2337 Float64OutOfRange(val) => Ok(EvalError::Float64OutOfRange(val.value.into())),
2338 Int16OutOfRange(val) => Ok(EvalError::Int16OutOfRange(val.value.into())),
2339 Int32OutOfRange(val) => Ok(EvalError::Int32OutOfRange(val.value.into())),
2340 Int64OutOfRange(val) => Ok(EvalError::Int64OutOfRange(val.value.into())),
2341 Uint16OutOfRange(val) => Ok(EvalError::UInt16OutOfRange(val.value.into())),
2342 Uint32OutOfRange(val) => Ok(EvalError::UInt32OutOfRange(val.value.into())),
2343 Uint64OutOfRange(val) => Ok(EvalError::UInt64OutOfRange(val.value.into())),
2344 MzTimestampOutOfRange(val) => {
2345 Ok(EvalError::MzTimestampOutOfRange(val.value.into()))
2346 }
2347 MzTimestampStepOverflow(()) => Ok(EvalError::MzTimestampStepOverflow),
2348 OidOutOfRange(val) => Ok(EvalError::OidOutOfRange(val.value.into())),
2349 IntervalOutOfRange(val) => Ok(EvalError::IntervalOutOfRange(val.value.into())),
2350 TimestampCannotBeNan(()) => Ok(EvalError::TimestampCannotBeNan),
2351 TimestampOutOfRange(()) => Ok(EvalError::TimestampOutOfRange),
2352 DateOutOfRange(()) => Ok(EvalError::DateOutOfRange),
2353 CharOutOfRange(()) => Ok(EvalError::CharOutOfRange),
2354 IndexOutOfRange(v) => Ok(EvalError::IndexOutOfRange {
2355 provided: v.provided,
2356 valid_end: v.valid_end,
2357 }),
2358 InvalidBase64Equals(()) => Ok(EvalError::InvalidBase64Equals),
2359 InvalidBase64Symbol(v) => char::from_proto(v).map(EvalError::InvalidBase64Symbol),
2360 InvalidBase64EndSequence(()) => Ok(EvalError::InvalidBase64EndSequence),
2361 InvalidTimezone(v) => Ok(EvalError::InvalidTimezone(v.into())),
2362 InvalidTimezoneInterval(()) => Ok(EvalError::InvalidTimezoneInterval),
2363 InvalidTimezoneConversion(()) => Ok(EvalError::InvalidTimezoneConversion),
2364 InvalidLayer(v) => Ok(EvalError::InvalidLayer {
2365 max_layer: usize::from_proto(v.max_layer)?,
2366 val: v.val,
2367 }),
2368 InvalidArray(error) => Ok(EvalError::InvalidArray(error.into_rust()?)),
2369 InvalidEncodingName(v) => Ok(EvalError::InvalidEncodingName(v.into())),
2370 InvalidHashAlgorithm(v) => Ok(EvalError::InvalidHashAlgorithm(v.into())),
2371 InvalidByteSequence(v) => Ok(EvalError::InvalidByteSequence {
2372 byte_sequence: v.byte_sequence.into(),
2373 encoding_name: v.encoding_name.into(),
2374 }),
2375 InvalidJsonbCast(v) => Ok(EvalError::InvalidJsonbCast {
2376 from: v.from.into(),
2377 to: v.to.into(),
2378 }),
2379 InvalidRegex(v) => Ok(EvalError::InvalidRegex(v.into())),
2380 InvalidRegexFlag(v) => Ok(EvalError::InvalidRegexFlag(char::from_proto(v)?)),
2381 InvalidParameterValue(v) => Ok(EvalError::InvalidParameterValue(v.into())),
2382 InvalidDatePart(part) => Ok(EvalError::InvalidDatePart(part.into())),
2383 KeyCannotBeNull(()) => Ok(EvalError::KeyCannotBeNull),
2384 NegSqrt(()) => Ok(EvalError::NegSqrt),
2385 NegLimit(()) => Ok(EvalError::NegLimit),
2386 NullCharacterNotPermitted(()) => Ok(EvalError::NullCharacterNotPermitted),
2387 UnknownUnits(v) => Ok(EvalError::UnknownUnits(v.into())),
2388 UnsupportedUnits(v) => {
2389 Ok(EvalError::UnsupportedUnits(v.units.into(), v.typ.into()))
2390 }
2391 UnterminatedLikeEscapeSequence(()) => Ok(EvalError::UnterminatedLikeEscapeSequence),
2392 Parse(error) => Ok(EvalError::Parse(error.into_rust()?)),
2393 ParseHex(error) => Ok(EvalError::ParseHex(error.into_rust()?)),
2394 Internal(v) => Ok(EvalError::Internal(v.into())),
2395 InfinityOutOfDomain(v) => Ok(EvalError::InfinityOutOfDomain(v.into())),
2396 NegativeOutOfDomain(v) => Ok(EvalError::NegativeOutOfDomain(v.into())),
2397 ZeroOutOfDomain(v) => Ok(EvalError::ZeroOutOfDomain(v.into())),
2398 OutOfDomain(v) => Ok(EvalError::OutOfDomain(
2399 v.lower.into_rust_if_some("ProtoDomainLimit::lower")?,
2400 v.upper.into_rust_if_some("ProtoDomainLimit::upper")?,
2401 v.id.into(),
2402 )),
2403 ComplexOutOfRange(v) => Ok(EvalError::ComplexOutOfRange(v.into())),
2404 MultipleRowsFromSubquery(()) => Ok(EvalError::MultipleRowsFromSubquery),
2405 NegativeRowsFromSubquery(()) => Ok(EvalError::NegativeRowsFromSubquery),
2406 Undefined(v) => Ok(EvalError::Undefined(v.into())),
2407 LikePatternTooLong(()) => Ok(EvalError::LikePatternTooLong),
2408 LikeEscapeTooLong(()) => Ok(EvalError::LikeEscapeTooLong),
2409 StringValueTooLong(v) => Ok(EvalError::StringValueTooLong {
2410 target_type: v.target_type.into(),
2411 length: usize::from_proto(v.length)?,
2412 }),
2413 MultidimensionalArrayRemovalNotSupported(()) => {
2414 Ok(EvalError::MultidimensionalArrayRemovalNotSupported)
2415 }
2416 IncompatibleArrayDimensions(v) => Ok(EvalError::IncompatibleArrayDimensions {
2417 dims: v.dims.into_rust()?,
2418 }),
2419 TypeFromOid(v) => Ok(EvalError::TypeFromOid(v.into())),
2420 InvalidRange(e) => Ok(EvalError::InvalidRange(e.into_rust()?)),
2421 InvalidRoleId(v) => Ok(EvalError::InvalidRoleId(v.into())),
2422 InvalidPrivileges(v) => Ok(EvalError::InvalidPrivileges(v.into())),
2423 InvalidCatalogJson(v) => Ok(EvalError::InvalidCatalogJson(v.into())),
2424 WmrRecursionLimitExceeded(v) => Ok(EvalError::LetRecLimitExceeded(v.into())),
2425 MultiDimensionalArraySearch(()) => Ok(EvalError::MultiDimensionalArraySearch),
2426 MustNotBeNull(v) => Ok(EvalError::MustNotBeNull(v.into())),
2427 InvalidIdentifier(v) => Ok(EvalError::InvalidIdentifier {
2428 ident: v.ident.into(),
2429 detail: v.detail.into_rust()?,
2430 }),
2431 ArrayFillWrongArraySubscripts(()) => Ok(EvalError::ArrayFillWrongArraySubscripts),
2432 MaxArraySizeExceeded(max_size) => {
2433 Ok(EvalError::MaxArraySizeExceeded(usize::cast_from(max_size)))
2434 }
2435 DateDiffOverflow(v) => Ok(EvalError::DateDiffOverflow {
2436 unit: v.unit.into(),
2437 a: v.a.into(),
2438 b: v.b.into(),
2439 }),
2440 IfNullError(v) => Ok(EvalError::IfNullError(v.into())),
2441 LengthTooLarge(()) => Ok(EvalError::LengthTooLarge),
2442 AclArrayNullElement(()) => Ok(EvalError::AclArrayNullElement),
2443 MzAclArrayNullElement(()) => Ok(EvalError::MzAclArrayNullElement),
2444 InvalidIanaTimezoneId(s) => Ok(EvalError::InvalidIanaTimezoneId(s.into())),
2445 PrettyError(s) => Ok(EvalError::PrettyError(s.into())),
2446 RedactError(s) => Ok(EvalError::RedactError(s.into())),
2447 },
2448 None => Err(TryFromProtoError::missing_field("ProtoEvalError::kind")),
2449 }
2450 }
2451}
2452
2453impl RustType<ProtoDims> for (usize, usize) {
2454 fn into_proto(&self) -> ProtoDims {
2455 ProtoDims {
2456 f0: self.0.into_proto(),
2457 f1: self.1.into_proto(),
2458 }
2459 }
2460
2461 fn from_proto(proto: ProtoDims) -> Result<Self, TryFromProtoError> {
2462 Ok((proto.f0.into_rust()?, proto.f1.into_rust()?))
2463 }
2464}
2465
2466#[cfg(test)]
2467mod tests {
2468 use super::*;
2469 use crate::scalar::func::variadic::Coalesce;
2470
2471 #[mz_ore::test]
2472 #[cfg_attr(miri, ignore)] fn test_reduce() {
2474 let relation_type: Vec<ReprColumnType> = vec![
2475 ReprScalarType::Int64.nullable(true),
2476 ReprScalarType::Int64.nullable(true),
2477 ReprScalarType::Int64.nullable(false),
2478 ]
2479 .into_iter()
2480 .collect();
2481 let col = MirScalarExpr::column;
2482 let int64_typ = ReprScalarType::Int64;
2483 let err = |e| MirScalarExpr::literal(Err(e), int64_typ.clone());
2484 let lit = |i| MirScalarExpr::literal_ok(Datum::Int64(i), int64_typ.clone());
2485 let null = || MirScalarExpr::literal_null(int64_typ.clone());
2486
2487 struct TestCase {
2488 input: MirScalarExpr,
2489 output: MirScalarExpr,
2490 }
2491
2492 let test_cases = vec![
2493 TestCase {
2494 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1)]),
2495 output: lit(1),
2496 },
2497 TestCase {
2498 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1), lit(2)]),
2499 output: lit(1),
2500 },
2501 TestCase {
2502 input: MirScalarExpr::call_variadic(Coalesce, vec![null(), lit(2), null()]),
2503 output: lit(2),
2504 },
2505 TestCase {
2506 input: MirScalarExpr::call_variadic(
2507 Coalesce,
2508 vec![null(), col(0), null(), col(1), lit(2), lit(3)],
2509 ),
2510 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(1), lit(2)]),
2511 },
2512 TestCase {
2513 input: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2), col(1)]),
2514 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2)]),
2515 },
2516 TestCase {
2517 input: MirScalarExpr::call_variadic(
2518 Coalesce,
2519 vec![lit(1), err(EvalError::DivisionByZero)],
2520 ),
2521 output: lit(1),
2522 },
2523 TestCase {
2524 input: MirScalarExpr::call_variadic(
2525 Coalesce,
2526 vec![
2527 null(),
2528 err(EvalError::DivisionByZero),
2529 err(EvalError::NumericFieldOverflow),
2530 ],
2531 ),
2532 output: err(EvalError::DivisionByZero),
2533 },
2534 ];
2535
2536 for tc in test_cases {
2537 let mut actual = tc.input.clone();
2538 actual.reduce(&relation_type);
2539 assert!(
2540 actual == tc.output,
2541 "input: {}\nactual: {}\nexpected: {}",
2542 tc.input,
2543 actual,
2544 tc.output
2545 );
2546 }
2547 }
2548}