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