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::collections::CollectionExt;
19use mz_ore::iter::IteratorExt;
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_pgtz::timezone::TimezoneSpec;
26use mz_proto::{IntoRustIfSome, ProtoType, RustType, TryFromProtoError};
27use mz_repr::adt::array::InvalidArrayError;
28use mz_repr::adt::date::DateError;
29use mz_repr::adt::datetime::DateTimeUnits;
30use mz_repr::adt::range::InvalidRangeError;
31use mz_repr::adt::regex::{Regex, RegexCompilationError};
32use mz_repr::adt::timestamp::TimestampError;
33use mz_repr::strconv::{ParseError, ParseHexError};
34use mz_repr::{Datum, Row, RowArena, SqlColumnType, SqlScalarType};
35use proptest::prelude::*;
36use proptest_derive::Arbitrary;
37use serde::{Deserialize, Serialize};
38
39use crate::scalar::func::format::DateTimeFormat;
40use crate::scalar::func::{
41 BinaryFunc, UnaryFunc, UnmaterializableFunc, VariadicFunc, parse_timezone,
42 regexp_replace_parse_flags,
43};
44use crate::scalar::proto_eval_error::proto_incompatible_array_dimensions::ProtoDims;
45use crate::visit::{Visit, VisitChildren};
46
47pub mod func;
48pub mod like_pattern;
49
50include!(concat!(env!("OUT_DIR"), "/mz_expr.scalar.rs"));
51
52#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, MzReflect)]
53pub enum MirScalarExpr {
54 Column(usize, TreatAsEqual<Option<Arc<str>>>),
56 Literal(Result<Row, EvalError>, SqlColumnType),
59 CallUnmaterializable(UnmaterializableFunc),
64 CallUnary {
66 func: UnaryFunc,
67 expr: Box<MirScalarExpr>,
68 },
69 CallBinary {
71 func: BinaryFunc,
72 expr1: Box<MirScalarExpr>,
73 expr2: Box<MirScalarExpr>,
74 },
75 CallVariadic {
77 func: VariadicFunc,
78 exprs: Vec<MirScalarExpr>,
79 },
80 If {
87 cond: Box<MirScalarExpr>,
88 then: Box<MirScalarExpr>,
89 els: Box<MirScalarExpr>,
90 },
91}
92
93impl std::fmt::Debug for MirScalarExpr {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 match self {
98 MirScalarExpr::Column(i, TreatAsEqual(Some(name))) => {
99 write!(f, "Column({i}, {name:?})")
100 }
101 MirScalarExpr::Column(i, TreatAsEqual(None)) => write!(f, "Column({i})"),
102 MirScalarExpr::Literal(lit, typ) => write!(f, "Literal({lit:?}, {typ:?})"),
103 MirScalarExpr::CallUnmaterializable(func) => {
104 write!(f, "CallUnmaterializable({func:?})")
105 }
106 MirScalarExpr::CallUnary { func, expr } => {
107 write!(f, "CallUnary({func:?}, {expr:?})")
108 }
109 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
110 write!(f, "CallBinary({func:?}, {expr1:?}, {expr2:?})")
111 }
112 MirScalarExpr::CallVariadic { func, exprs } => {
113 write!(f, "CallVariadic({func:?}, {exprs:?})")
114 }
115 MirScalarExpr::If { cond, then, els } => {
116 write!(f, "If({cond:?}, {then:?}, {els:?})")
117 }
118 }
119 }
120}
121
122impl MirScalarExpr {
123 pub fn columns(is: &[usize]) -> Vec<MirScalarExpr> {
124 is.iter().map(|i| MirScalarExpr::column(*i)).collect()
125 }
126
127 pub fn column(column: usize) -> Self {
128 MirScalarExpr::Column(column, TreatAsEqual(None))
129 }
130
131 pub fn named_column(column: usize, name: Arc<str>) -> Self {
132 MirScalarExpr::Column(column, TreatAsEqual(Some(name)))
133 }
134
135 pub fn literal(res: Result<Datum, EvalError>, typ: SqlScalarType) -> Self {
136 let typ = typ.nullable(matches!(res, Ok(Datum::Null)));
137 let row = res.map(|datum| Row::pack_slice(&[datum]));
138 MirScalarExpr::Literal(row, typ)
139 }
140
141 pub fn literal_ok(datum: Datum, typ: SqlScalarType) -> Self {
142 MirScalarExpr::literal(Ok(datum), typ)
143 }
144
145 pub fn literal_null(typ: SqlScalarType) -> Self {
146 MirScalarExpr::literal_ok(Datum::Null, typ)
147 }
148
149 pub fn literal_false() -> Self {
150 MirScalarExpr::literal_ok(Datum::False, SqlScalarType::Bool)
151 }
152
153 pub fn literal_true() -> Self {
154 MirScalarExpr::literal_ok(Datum::True, SqlScalarType::Bool)
155 }
156
157 pub fn call_unary<U: Into<UnaryFunc>>(self, func: U) -> Self {
158 MirScalarExpr::CallUnary {
159 func: func.into(),
160 expr: Box::new(self),
161 }
162 }
163
164 pub fn call_binary<B: Into<BinaryFunc>>(self, other: Self, func: B) -> Self {
165 MirScalarExpr::CallBinary {
166 func: func.into(),
167 expr1: Box::new(self),
168 expr2: Box::new(other),
169 }
170 }
171
172 pub fn if_then_else(self, t: Self, f: Self) -> Self {
173 MirScalarExpr::If {
174 cond: Box::new(self),
175 then: Box::new(t),
176 els: Box::new(f),
177 }
178 }
179
180 pub fn or(self, other: Self) -> Self {
181 MirScalarExpr::CallVariadic {
182 func: VariadicFunc::Or,
183 exprs: vec![self, other],
184 }
185 }
186
187 pub fn and(self, other: Self) -> Self {
188 MirScalarExpr::CallVariadic {
189 func: VariadicFunc::And,
190 exprs: vec![self, other],
191 }
192 }
193
194 pub fn not(self) -> Self {
195 self.call_unary(UnaryFunc::Not(func::Not))
196 }
197
198 pub fn call_is_null(self) -> Self {
199 self.call_unary(UnaryFunc::IsNull(func::IsNull))
200 }
201
202 pub fn and_or_args(&self, func_to_match: VariadicFunc) -> Vec<MirScalarExpr> {
205 assert!(func_to_match == VariadicFunc::Or || func_to_match == VariadicFunc::And);
206 match self {
207 MirScalarExpr::CallVariadic { func, exprs } if *func == func_to_match => exprs.clone(),
208 _ => vec![self.clone()],
209 }
210 }
211
212 pub fn expr_eq_literal(&self, expr: &MirScalarExpr) -> Option<(Row, bool)> {
223 if let MirScalarExpr::CallBinary {
224 func: BinaryFunc::Eq(_),
225 expr1,
226 expr2,
227 } = self
228 {
229 if expr1.is_literal_null() || expr2.is_literal_null() {
230 return None;
231 }
232 if let Some(Ok(lit)) = expr1.as_literal_owned() {
233 return Self::expr_eq_literal_inner(expr, lit, expr1, expr2);
234 }
235 if let Some(Ok(lit)) = expr2.as_literal_owned() {
236 return Self::expr_eq_literal_inner(expr, lit, expr2, expr1);
237 }
238 }
239 None
240 }
241
242 fn expr_eq_literal_inner(
243 expr_to_match: &MirScalarExpr,
244 literal: Row,
245 literal_expr: &MirScalarExpr,
246 other_side: &MirScalarExpr,
247 ) -> Option<(Row, bool)> {
248 if other_side == expr_to_match {
249 return Some((literal, false));
250 } else {
251 let (cast_removed, inv_cast_lit) =
253 Self::invert_casts_on_expr_eq_literal_inner(other_side, literal_expr);
254 if &cast_removed == expr_to_match {
255 if let Some(Ok(inv_cast_lit_row)) = inv_cast_lit.as_literal_owned() {
256 return Some((inv_cast_lit_row, true));
257 }
258 }
259 }
260 None
261 }
262
263 pub fn any_expr_eq_literal(&self) -> Option<MirScalarExpr> {
267 if let MirScalarExpr::CallBinary {
268 func: BinaryFunc::Eq(_),
269 expr1,
270 expr2,
271 } = self
272 {
273 if expr1.is_literal() {
274 let (expr, _literal) = Self::invert_casts_on_expr_eq_literal_inner(expr2, expr1);
275 return Some(expr);
276 }
277 if expr2.is_literal() {
278 let (expr, _literal) = Self::invert_casts_on_expr_eq_literal_inner(expr1, expr2);
279 return Some(expr);
280 }
281 }
282 None
283 }
284
285 pub fn invert_casts_on_expr_eq_literal(&self) -> MirScalarExpr {
290 if let MirScalarExpr::CallBinary {
291 func: BinaryFunc::Eq(_),
292 expr1,
293 expr2,
294 } = self
295 {
296 if expr1.is_literal() {
297 let (expr, literal) = Self::invert_casts_on_expr_eq_literal_inner(expr2, expr1);
298 return literal.call_binary(expr, func::Eq);
299 }
300 if expr2.is_literal() {
301 let (expr, literal) = Self::invert_casts_on_expr_eq_literal_inner(expr1, expr2);
302 return literal.call_binary(expr, func::Eq);
303 }
304 }
307 self.clone()
308 }
309
310 fn invert_casts_on_expr_eq_literal_inner(
322 expr: &MirScalarExpr,
323 literal: &MirScalarExpr,
324 ) -> (MirScalarExpr, MirScalarExpr) {
325 assert!(matches!(literal, MirScalarExpr::Literal(..)));
326
327 let temp_storage = &RowArena::new();
328 let eval = |e: &MirScalarExpr| {
329 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(&[]).scalar_type)
330 };
331
332 if let MirScalarExpr::CallUnary {
333 func,
334 expr: inner_expr,
335 } = expr
336 {
337 if let Some(inverse_func) = func.inverse() {
338 if func.preserves_uniqueness() && inverse_func.preserves_uniqueness() {
345 let lit_inv = eval(&MirScalarExpr::CallUnary {
346 func: inverse_func,
347 expr: Box::new(literal.clone()),
348 });
349 if !lit_inv.is_literal_err() {
352 return (*inner_expr.clone(), lit_inv);
353 }
354 }
355 }
356 }
357 (expr.clone(), literal.clone())
358 }
359
360 pub fn impossible_literal_equality_because_types(&self) -> bool {
366 if let MirScalarExpr::CallBinary {
367 func: BinaryFunc::Eq(_),
368 expr1,
369 expr2,
370 } = self
371 {
372 if expr1.is_literal() {
373 return Self::impossible_literal_equality_because_types_inner(expr1, expr2);
374 }
375 if expr2.is_literal() {
376 return Self::impossible_literal_equality_because_types_inner(expr2, expr1);
377 }
378 }
379 false
380 }
381
382 fn impossible_literal_equality_because_types_inner(
383 literal: &MirScalarExpr,
384 other_side: &MirScalarExpr,
385 ) -> bool {
386 assert!(matches!(literal, MirScalarExpr::Literal(..)));
387
388 let temp_storage = &RowArena::new();
389 let eval = |e: &MirScalarExpr| {
390 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(&[]).scalar_type)
391 };
392
393 if let MirScalarExpr::CallUnary { func, .. } = other_side {
394 if let Some(inverse_func) = func.inverse() {
395 if inverse_func.preserves_uniqueness()
396 && eval(&MirScalarExpr::CallUnary {
397 func: inverse_func,
398 expr: Box::new(literal.clone()),
399 })
400 .is_literal_err()
401 {
402 return true;
403 }
404 }
405 }
406
407 false
408 }
409
410 pub fn any_expr_ineq_literal(&self) -> bool {
420 match self {
421 MirScalarExpr::CallBinary {
422 func:
423 BinaryFunc::Lt(_) | BinaryFunc::Lte(_) | BinaryFunc::Gt(_) | BinaryFunc::Gte(_),
424 expr1,
425 expr2,
426 } => expr1.is_literal() || expr2.is_literal(),
427 _ => false,
428 }
429 }
430
431 pub fn permute(&mut self, permutation: &[usize]) {
437 self.visit_columns(|c| *c = permutation[*c]);
438 }
439
440 pub fn permute_map(&mut self, permutation: &BTreeMap<usize, usize>) {
446 self.visit_columns(|c| *c = permutation[c]);
447 }
448
449 pub fn visit_columns<F>(&mut self, mut action: F)
453 where
454 F: FnMut(&mut usize),
455 {
456 self.visit_pre_mut(|e| {
457 if let MirScalarExpr::Column(col, _) = e {
458 action(col);
459 }
460 });
461 }
462
463 pub fn support(&self) -> BTreeSet<usize> {
464 let mut support = BTreeSet::new();
465 self.support_into(&mut support);
466 support
467 }
468
469 pub fn support_into(&self, support: &mut BTreeSet<usize>) {
470 self.visit_pre(|e| {
471 if let MirScalarExpr::Column(i, _) = e {
472 support.insert(*i);
473 }
474 });
475 }
476
477 pub fn take(&mut self) -> Self {
478 mem::replace(self, MirScalarExpr::literal_null(SqlScalarType::String))
479 }
480
481 pub fn as_literal(&self) -> Option<Result<Datum<'_>, &EvalError>> {
484 if let MirScalarExpr::Literal(lit, _column_type) = self {
485 Some(lit.as_ref().map(|row| row.unpack_first()))
486 } else {
487 None
488 }
489 }
490
491 pub fn as_literal_non_error(&self) -> Option<Datum<'_>> {
494 self.as_literal().map(|eval_err| eval_err.ok()).flatten()
495 }
496
497 pub fn as_literal_owned(&self) -> Option<Result<Row, EvalError>> {
498 if let MirScalarExpr::Literal(lit, _column_type) = self {
499 Some(lit.clone())
500 } else {
501 None
502 }
503 }
504
505 pub fn as_literal_str(&self) -> Option<&str> {
506 match self.as_literal() {
507 Some(Ok(Datum::String(s))) => Some(s),
508 _ => None,
509 }
510 }
511
512 pub fn as_literal_int64(&self) -> Option<i64> {
513 match self.as_literal() {
514 Some(Ok(Datum::Int64(i))) => Some(i),
515 _ => None,
516 }
517 }
518
519 pub fn as_literal_err(&self) -> Option<&EvalError> {
520 self.as_literal().and_then(|lit| lit.err())
521 }
522
523 pub fn is_literal(&self) -> bool {
524 matches!(self, MirScalarExpr::Literal(_, _))
525 }
526
527 pub fn is_literal_true(&self) -> bool {
528 Some(Ok(Datum::True)) == self.as_literal()
529 }
530
531 pub fn is_literal_false(&self) -> bool {
532 Some(Ok(Datum::False)) == self.as_literal()
533 }
534
535 pub fn is_literal_null(&self) -> bool {
536 Some(Ok(Datum::Null)) == self.as_literal()
537 }
538
539 pub fn is_literal_ok(&self) -> bool {
540 matches!(self, MirScalarExpr::Literal(Ok(_), _typ))
541 }
542
543 pub fn is_literal_err(&self) -> bool {
544 matches!(self, MirScalarExpr::Literal(Err(_), _typ))
545 }
546
547 pub fn is_column(&self) -> bool {
548 matches!(self, MirScalarExpr::Column(_col, _name))
549 }
550
551 pub fn is_error_if_null(&self) -> bool {
552 matches!(
553 self,
554 Self::CallVariadic {
555 func: VariadicFunc::ErrorIfNull,
556 ..
557 }
558 )
559 }
560
561 pub fn as_mut_temporal_filter(&mut self) -> Result<(&BinaryFunc, &mut MirScalarExpr), String> {
571 if !self.contains_temporal() {
572 return Err("Does not involve mz_now()".to_string());
573 }
574 if let MirScalarExpr::CallBinary { func, expr1, expr2 } = self {
576 if !expr1.contains_temporal()
578 && **expr2 == MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow)
579 {
580 std::mem::swap(expr1, expr2);
581 *func = match func {
582 BinaryFunc::Eq(_) => func::Eq.into(),
583 BinaryFunc::Lt(_) => func::Gt.into(),
584 BinaryFunc::Lte(_) => func::Gte.into(),
585 BinaryFunc::Gt(_) => func::Lt.into(),
586 BinaryFunc::Gte(_) => func::Lte.into(),
587 x => {
588 return Err(format!("Unsupported binary temporal operation: {:?}", x));
589 }
590 };
591 }
592
593 if expr2.contains_temporal()
595 || **expr1 != MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow)
596 {
597 return Err(format!(
598 "Unsupported temporal predicate. Note: `mz_now()` must be directly compared to a mz_timestamp-castable expression. Expression found: {}",
599 MirScalarExpr::CallBinary {
600 func: func.clone(),
601 expr1: expr1.clone(),
602 expr2: expr2.clone()
603 },
604 ));
605 }
606
607 Ok((&*func, expr2))
608 } else {
609 Err(format!(
610 "Unsupported temporal predicate. Note: `mz_now()` must be directly compared to a non-temporal expression of mz_timestamp-castable type. Expression found: {}",
611 self,
612 ))
613 }
614 }
615
616 #[deprecated = "Use `might_error` instead"]
617 pub fn contains_error_if_null(&self) -> bool {
618 let mut worklist = vec![self];
619 while let Some(expr) = worklist.pop() {
620 if expr.is_error_if_null() {
621 return true;
622 }
623 worklist.extend(expr.children());
624 }
625 false
626 }
627
628 pub fn contains_err(&self) -> bool {
629 let mut worklist = vec![self];
630 while let Some(expr) = worklist.pop() {
631 if expr.is_literal_err() {
632 return true;
633 }
634 worklist.extend(expr.children());
635 }
636 false
637 }
638
639 pub fn might_error(&self) -> bool {
645 let mut worklist = vec![self];
646 while let Some(expr) = worklist.pop() {
647 if expr.is_literal_err() || expr.is_error_if_null() {
648 return true;
649 }
650 worklist.extend(expr.children());
651 }
652 false
653 }
654
655 pub fn as_column(&self) -> Option<usize> {
657 if let MirScalarExpr::Column(c, _) = self {
658 Some(*c)
659 } else {
660 None
661 }
662 }
663
664 pub fn reduce(&mut self, column_types: &[SqlColumnType]) {
696 let temp_storage = &RowArena::new();
697 let eval = |e: &MirScalarExpr| {
698 MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(column_types).scalar_type)
699 };
700
701 let mut old_self = MirScalarExpr::column(0);
703 while old_self != *self {
704 old_self = self.clone();
705 #[allow(deprecated)]
706 self.visit_mut_pre_post_nolimit(
707 &mut |e| {
708 match e {
709 MirScalarExpr::CallUnary { func, expr } => {
710 if *func == UnaryFunc::IsNull(func::IsNull) {
711 if !expr.typ(column_types).nullable {
712 *e = MirScalarExpr::literal_false();
713 } else {
714 if let Some(expr) = expr.decompose_is_null() {
717 *e = expr
718 }
719 }
720 } else if *func == UnaryFunc::Not(func::Not) {
721 match &mut **expr {
723 MirScalarExpr::CallUnary {
725 expr: inner_expr,
726 func: UnaryFunc::Not(func::Not),
727 } => *e = inner_expr.take(),
728 MirScalarExpr::CallBinary { expr1, expr2, func } => {
731 if let Some(negated_func) = func.negate() {
732 *e = MirScalarExpr::CallBinary {
733 expr1: Box::new(expr1.take()),
734 expr2: Box::new(expr2.take()),
735 func: negated_func,
736 }
737 }
738 }
739 MirScalarExpr::CallVariadic { .. } => {
740 e.demorgans();
741 }
742 _ => {}
743 }
744 }
745 }
746 _ => {}
747 };
748 None
749 },
750 &mut |e| match e {
751 MirScalarExpr::Column(_, _)
753 | MirScalarExpr::Literal(_, _)
754 | MirScalarExpr::CallUnmaterializable(_) => (),
755 MirScalarExpr::CallUnary { func, expr } => {
756 if expr.is_literal() && *func != UnaryFunc::Panic(func::Panic) {
757 *e = eval(e);
758 } else if let UnaryFunc::RecordGet(func::RecordGet(i)) = *func {
759 if let MirScalarExpr::CallVariadic {
760 func: VariadicFunc::RecordCreate { .. },
761 exprs,
762 } = &mut **expr
763 {
764 *e = exprs.swap_remove(i);
765 }
766 }
767 }
768 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
769 if expr1.is_literal() && expr2.is_literal() {
770 *e = eval(e);
771 } else if (expr1.is_literal_null() || expr2.is_literal_null())
772 && func.propagates_nulls()
773 {
774 *e = MirScalarExpr::literal_null(e.typ(column_types).scalar_type);
775 } else if let Some(err) = expr1.as_literal_err() {
776 *e = MirScalarExpr::literal(
777 Err(err.clone()),
778 e.typ(column_types).scalar_type,
779 );
780 } else if let Some(err) = expr2.as_literal_err() {
781 *e = MirScalarExpr::literal(
782 Err(err.clone()),
783 e.typ(column_types).scalar_type,
784 );
785 } else if let BinaryFunc::IsLikeMatchCaseInsensitive(_) = func {
786 if expr2.is_literal() {
787 let pattern = expr2.as_literal_str().unwrap();
789 *e = match like_pattern::compile(pattern, true) {
790 Ok(matcher) => expr1.take().call_unary(UnaryFunc::IsLikeMatch(
791 func::IsLikeMatch(matcher),
792 )),
793 Err(err) => MirScalarExpr::literal(
794 Err(err),
795 e.typ(column_types).scalar_type,
796 ),
797 };
798 }
799 } else if let BinaryFunc::IsLikeMatchCaseSensitive(_) = func {
800 if expr2.is_literal() {
801 let pattern = expr2.as_literal_str().unwrap();
803 *e = match like_pattern::compile(pattern, false) {
804 Ok(matcher) => expr1.take().call_unary(UnaryFunc::IsLikeMatch(
805 func::IsLikeMatch(matcher),
806 )),
807 Err(err) => MirScalarExpr::literal(
808 Err(err),
809 e.typ(column_types).scalar_type,
810 ),
811 };
812 }
813 } else if let BinaryFunc::IsRegexpMatch { case_insensitive } = func {
814 if let MirScalarExpr::Literal(Ok(row), _) = &**expr2 {
815 *e = match Regex::new(
816 row.unpack_first().unwrap_str(),
817 *case_insensitive,
818 ) {
819 Ok(regex) => expr1.take().call_unary(UnaryFunc::IsRegexpMatch(
820 func::IsRegexpMatch(regex),
821 )),
822 Err(err) => MirScalarExpr::literal(
823 Err(err.into()),
824 e.typ(column_types).scalar_type,
825 ),
826 };
827 }
828 } else if let BinaryFunc::ExtractInterval(_) = *func
829 && expr1.is_literal()
830 {
831 let units = expr1.as_literal_str().unwrap();
832 *e = match units.parse::<DateTimeUnits>() {
833 Ok(units) => MirScalarExpr::CallUnary {
834 func: UnaryFunc::ExtractInterval(func::ExtractInterval(units)),
835 expr: Box::new(expr2.take()),
836 },
837 Err(_) => MirScalarExpr::literal(
838 Err(EvalError::UnknownUnits(units.into())),
839 e.typ(column_types).scalar_type,
840 ),
841 }
842 } else if let BinaryFunc::ExtractTime(_) = *func
843 && expr1.is_literal()
844 {
845 let units = expr1.as_literal_str().unwrap();
846 *e = match units.parse::<DateTimeUnits>() {
847 Ok(units) => MirScalarExpr::CallUnary {
848 func: UnaryFunc::ExtractTime(func::ExtractTime(units)),
849 expr: Box::new(expr2.take()),
850 },
851 Err(_) => MirScalarExpr::literal(
852 Err(EvalError::UnknownUnits(units.into())),
853 e.typ(column_types).scalar_type,
854 ),
855 }
856 } else if let BinaryFunc::ExtractTimestamp(_) = *func
857 && expr1.is_literal()
858 {
859 let units = expr1.as_literal_str().unwrap();
860 *e = match units.parse::<DateTimeUnits>() {
861 Ok(units) => MirScalarExpr::CallUnary {
862 func: UnaryFunc::ExtractTimestamp(func::ExtractTimestamp(
863 units,
864 )),
865 expr: Box::new(expr2.take()),
866 },
867 Err(_) => MirScalarExpr::literal(
868 Err(EvalError::UnknownUnits(units.into())),
869 e.typ(column_types).scalar_type,
870 ),
871 }
872 } else if let BinaryFunc::ExtractTimestampTz(_) = *func
873 && expr1.is_literal()
874 {
875 let units = expr1.as_literal_str().unwrap();
876 *e = match units.parse::<DateTimeUnits>() {
877 Ok(units) => MirScalarExpr::CallUnary {
878 func: UnaryFunc::ExtractTimestampTz(func::ExtractTimestampTz(
879 units,
880 )),
881 expr: Box::new(expr2.take()),
882 },
883 Err(_) => MirScalarExpr::literal(
884 Err(EvalError::UnknownUnits(units.into())),
885 e.typ(column_types).scalar_type,
886 ),
887 }
888 } else if let BinaryFunc::ExtractDate(_) = *func
889 && expr1.is_literal()
890 {
891 let units = expr1.as_literal_str().unwrap();
892 *e = match units.parse::<DateTimeUnits>() {
893 Ok(units) => MirScalarExpr::CallUnary {
894 func: UnaryFunc::ExtractDate(func::ExtractDate(units)),
895 expr: Box::new(expr2.take()),
896 },
897 Err(_) => MirScalarExpr::literal(
898 Err(EvalError::UnknownUnits(units.into())),
899 e.typ(column_types).scalar_type,
900 ),
901 }
902 } else if let BinaryFunc::DatePartInterval(_) = *func
903 && expr1.is_literal()
904 {
905 let units = expr1.as_literal_str().unwrap();
906 *e = match units.parse::<DateTimeUnits>() {
907 Ok(units) => MirScalarExpr::CallUnary {
908 func: UnaryFunc::DatePartInterval(func::DatePartInterval(
909 units,
910 )),
911 expr: Box::new(expr2.take()),
912 },
913 Err(_) => MirScalarExpr::literal(
914 Err(EvalError::UnknownUnits(units.into())),
915 e.typ(column_types).scalar_type,
916 ),
917 }
918 } else if let BinaryFunc::DatePartTime(_) = *func
919 && expr1.is_literal()
920 {
921 let units = expr1.as_literal_str().unwrap();
922 *e = match units.parse::<DateTimeUnits>() {
923 Ok(units) => MirScalarExpr::CallUnary {
924 func: UnaryFunc::DatePartTime(func::DatePartTime(units)),
925 expr: Box::new(expr2.take()),
926 },
927 Err(_) => MirScalarExpr::literal(
928 Err(EvalError::UnknownUnits(units.into())),
929 e.typ(column_types).scalar_type,
930 ),
931 }
932 } else if let BinaryFunc::DatePartTimestamp(_) = *func
933 && expr1.is_literal()
934 {
935 let units = expr1.as_literal_str().unwrap();
936 *e = match units.parse::<DateTimeUnits>() {
937 Ok(units) => MirScalarExpr::CallUnary {
938 func: UnaryFunc::DatePartTimestamp(func::DatePartTimestamp(
939 units,
940 )),
941 expr: Box::new(expr2.take()),
942 },
943 Err(_) => MirScalarExpr::literal(
944 Err(EvalError::UnknownUnits(units.into())),
945 e.typ(column_types).scalar_type,
946 ),
947 }
948 } else if let BinaryFunc::DatePartTimestampTz(_) = *func
949 && expr1.is_literal()
950 {
951 let units = expr1.as_literal_str().unwrap();
952 *e = match units.parse::<DateTimeUnits>() {
953 Ok(units) => MirScalarExpr::CallUnary {
954 func: UnaryFunc::DatePartTimestampTz(
955 func::DatePartTimestampTz(units),
956 ),
957 expr: Box::new(expr2.take()),
958 },
959 Err(_) => MirScalarExpr::literal(
960 Err(EvalError::UnknownUnits(units.into())),
961 e.typ(column_types).scalar_type,
962 ),
963 }
964 } else if let BinaryFunc::DateTruncTimestamp(_) = *func
965 && expr1.is_literal()
966 {
967 let units = expr1.as_literal_str().unwrap();
968 *e = match units.parse::<DateTimeUnits>() {
969 Ok(units) => MirScalarExpr::CallUnary {
970 func: UnaryFunc::DateTruncTimestamp(func::DateTruncTimestamp(
971 units,
972 )),
973 expr: Box::new(expr2.take()),
974 },
975 Err(_) => MirScalarExpr::literal(
976 Err(EvalError::UnknownUnits(units.into())),
977 e.typ(column_types).scalar_type,
978 ),
979 }
980 } else if let BinaryFunc::DateTruncTimestampTz(_) = *func
981 && expr1.is_literal()
982 {
983 let units = expr1.as_literal_str().unwrap();
984 *e = match units.parse::<DateTimeUnits>() {
985 Ok(units) => MirScalarExpr::CallUnary {
986 func: UnaryFunc::DateTruncTimestampTz(
987 func::DateTruncTimestampTz(units),
988 ),
989 expr: Box::new(expr2.take()),
990 },
991 Err(_) => MirScalarExpr::literal(
992 Err(EvalError::UnknownUnits(units.into())),
993 e.typ(column_types).scalar_type,
994 ),
995 }
996 } else if *func == BinaryFunc::TimezoneTimestamp && expr1.is_literal() {
997 let tz = expr1.as_literal_str().unwrap();
1001 *e = match parse_timezone(tz, TimezoneSpec::Posix) {
1002 Ok(tz) => MirScalarExpr::CallUnary {
1003 func: UnaryFunc::TimezoneTimestamp(func::TimezoneTimestamp(tz)),
1004 expr: Box::new(expr2.take()),
1005 },
1006 Err(err) => MirScalarExpr::literal(
1007 Err(err),
1008 e.typ(column_types).scalar_type,
1009 ),
1010 }
1011 } else if *func == BinaryFunc::TimezoneTimestampTz && expr1.is_literal() {
1012 let tz = expr1.as_literal_str().unwrap();
1013 *e = match parse_timezone(tz, TimezoneSpec::Posix) {
1014 Ok(tz) => MirScalarExpr::CallUnary {
1015 func: UnaryFunc::TimezoneTimestampTz(
1016 func::TimezoneTimestampTz(tz),
1017 ),
1018 expr: Box::new(expr2.take()),
1019 },
1020 Err(err) => MirScalarExpr::literal(
1021 Err(err),
1022 e.typ(column_types).scalar_type,
1023 ),
1024 }
1025 } else if let BinaryFunc::ToCharTimestamp(_) = *func
1026 && expr2.is_literal()
1027 {
1028 let format_str = expr2.as_literal_str().unwrap();
1029 *e = MirScalarExpr::CallUnary {
1030 func: UnaryFunc::ToCharTimestamp(func::ToCharTimestamp {
1031 format_string: format_str.to_string(),
1032 format: DateTimeFormat::compile(format_str),
1033 }),
1034 expr: Box::new(expr1.take()),
1035 };
1036 } else if let BinaryFunc::ToCharTimestampTz(_) = *func
1037 && expr2.is_literal()
1038 {
1039 let format_str = expr2.as_literal_str().unwrap();
1040 *e = MirScalarExpr::CallUnary {
1041 func: UnaryFunc::ToCharTimestampTz(func::ToCharTimestampTz {
1042 format_string: format_str.to_string(),
1043 format: DateTimeFormat::compile(format_str),
1044 }),
1045 expr: Box::new(expr1.take()),
1046 };
1047 } else if matches!(*func, BinaryFunc::Eq(_) | BinaryFunc::NotEq(_))
1048 && expr2 < expr1
1049 {
1050 mem::swap(expr1, expr2);
1054 } else if let (
1055 BinaryFunc::Eq(_),
1056 MirScalarExpr::Literal(
1057 Ok(lit_row),
1058 SqlColumnType {
1059 scalar_type:
1060 SqlScalarType::Record {
1061 fields: field_types,
1062 ..
1063 },
1064 ..
1065 },
1066 ),
1067 MirScalarExpr::CallVariadic {
1068 func: VariadicFunc::RecordCreate { .. },
1069 exprs: rec_create_args,
1070 },
1071 ) = (&*func, &**expr1, &**expr2)
1072 {
1073 match lit_row.unpack_first() {
1082 Datum::List(datum_list) => {
1083 *e = MirScalarExpr::CallVariadic {
1084 func: VariadicFunc::And,
1085 exprs: datum_list
1086 .iter()
1087 .zip_eq(field_types)
1088 .zip_eq(rec_create_args)
1089 .map(|((d, (_, typ)), a)| {
1090 MirScalarExpr::literal_ok(
1091 d,
1092 typ.scalar_type.clone(),
1093 )
1094 .call_binary(a.clone(), func::Eq)
1095 })
1096 .collect(),
1097 };
1098 }
1099 _ => {}
1100 }
1101 } else if let (
1102 BinaryFunc::Eq(_),
1103 MirScalarExpr::CallVariadic {
1104 func: VariadicFunc::RecordCreate { .. },
1105 exprs: rec_create_args1,
1106 },
1107 MirScalarExpr::CallVariadic {
1108 func: VariadicFunc::RecordCreate { .. },
1109 exprs: rec_create_args2,
1110 },
1111 ) = (&*func, &**expr1, &**expr2)
1112 {
1113 *e = MirScalarExpr::CallVariadic {
1125 func: VariadicFunc::And,
1126 exprs: rec_create_args1
1127 .into_iter()
1128 .zip_eq(rec_create_args2)
1129 .map(|(a, b)| a.clone().call_binary(b.clone(), func::Eq))
1130 .collect(),
1131 }
1132 }
1133 }
1134 MirScalarExpr::CallVariadic { .. } => {
1135 e.flatten_associative();
1136 let (func, exprs) = match e {
1137 MirScalarExpr::CallVariadic { func, exprs } => (func, exprs),
1138 _ => unreachable!("`flatten_associative` shouldn't change node type"),
1139 };
1140 if *func == VariadicFunc::Coalesce {
1141 if exprs.iter().all(|expr| expr.is_literal_null()) {
1145 *e = MirScalarExpr::literal_null(e.typ(column_types).scalar_type);
1146 return;
1147 }
1148
1149 exprs.retain(|e| !e.is_literal_null());
1151
1152 if let Some(i) = exprs
1157 .iter()
1158 .position(|e| e.is_literal() || !e.typ(column_types).nullable)
1159 {
1160 exprs.truncate(i + 1);
1161 }
1162
1163 let mut prior_exprs = BTreeSet::new();
1165 exprs.retain(|e| prior_exprs.insert(e.clone()));
1166
1167 if exprs.len() == 1 {
1168 *e = exprs[0].take();
1170 }
1171 } else if exprs.iter().all(|e| e.is_literal()) {
1172 *e = eval(e);
1173 } else if func.propagates_nulls()
1174 && exprs.iter().any(|e| e.is_literal_null())
1175 {
1176 *e = MirScalarExpr::literal_null(e.typ(column_types).scalar_type);
1177 } else if let Some(err) = exprs.iter().find_map(|e| e.as_literal_err()) {
1178 *e = MirScalarExpr::literal(
1179 Err(err.clone()),
1180 e.typ(column_types).scalar_type,
1181 );
1182 } else if *func == VariadicFunc::RegexpMatch
1183 && exprs[1].is_literal()
1184 && exprs.get(2).map_or(true, |e| e.is_literal())
1185 {
1186 let needle = exprs[1].as_literal_str().unwrap();
1187 let flags = match exprs.len() {
1188 3 => exprs[2].as_literal_str().unwrap(),
1189 _ => "",
1190 };
1191 *e = match func::build_regex(needle, flags) {
1192 Ok(regex) => mem::take(exprs)
1193 .into_first()
1194 .call_unary(UnaryFunc::RegexpMatch(func::RegexpMatch(regex))),
1195 Err(err) => MirScalarExpr::literal(
1196 Err(err),
1197 e.typ(column_types).scalar_type,
1198 ),
1199 };
1200 } else if *func == VariadicFunc::RegexpReplace
1201 && exprs[1].is_literal()
1202 && exprs.get(3).map_or(true, |e| e.is_literal())
1203 {
1204 let pattern = exprs[1].as_literal_str().unwrap();
1205 let flags = exprs
1206 .get(3)
1207 .map_or("", |expr| expr.as_literal_str().unwrap());
1208 let (limit, flags) = regexp_replace_parse_flags(flags);
1209
1210 *e = match func::build_regex(pattern, &flags) {
1216 Ok(regex) => {
1217 let mut exprs = mem::take(exprs);
1218 let replacement = exprs.swap_remove(2);
1219 let source = exprs.swap_remove(0);
1220 source.call_binary(
1221 replacement,
1222 BinaryFunc::RegexpReplace { regex, limit },
1223 )
1224 }
1225 Err(err) => {
1226 let mut exprs = mem::take(exprs);
1227 let source = exprs.swap_remove(0);
1228 let scalar_type = e.typ(column_types).scalar_type;
1229 source.call_is_null().if_then_else(
1231 MirScalarExpr::literal_null(scalar_type.clone()),
1232 MirScalarExpr::literal(Err(err), scalar_type),
1233 )
1234 }
1235 };
1236 } else if *func == VariadicFunc::RegexpSplitToArray
1237 && exprs[1].is_literal()
1238 && exprs.get(2).map_or(true, |e| e.is_literal())
1239 {
1240 let needle = exprs[1].as_literal_str().unwrap();
1241 let flags = match exprs.len() {
1242 3 => exprs[2].as_literal_str().unwrap(),
1243 _ => "",
1244 };
1245 *e = match func::build_regex(needle, flags) {
1246 Ok(regex) => mem::take(exprs).into_first().call_unary(
1247 UnaryFunc::RegexpSplitToArray(func::RegexpSplitToArray(regex)),
1248 ),
1249 Err(err) => MirScalarExpr::literal(
1250 Err(err),
1251 e.typ(column_types).scalar_type,
1252 ),
1253 };
1254 } else if *func == VariadicFunc::ListIndex && is_list_create_call(&exprs[0])
1255 {
1256 let ind_exprs = exprs.split_off(1);
1259 let top_list_create = exprs.swap_remove(0);
1260 *e = reduce_list_create_list_index_literal(top_list_create, ind_exprs);
1261 } else if *func == VariadicFunc::Or || *func == VariadicFunc::And {
1262 e.undistribute_and_or();
1264 e.reduce_and_canonicalize_and_or();
1265 } else if let VariadicFunc::TimezoneTime = func {
1266 if exprs[0].is_literal() && exprs[2].is_literal_ok() {
1267 let tz = exprs[0].as_literal_str().unwrap();
1268 *e = match parse_timezone(tz, TimezoneSpec::Posix) {
1269 Ok(tz) => MirScalarExpr::CallUnary {
1270 func: UnaryFunc::TimezoneTime(func::TimezoneTime {
1271 tz,
1272 wall_time: exprs[2]
1273 .as_literal()
1274 .unwrap()
1275 .unwrap()
1276 .unwrap_timestamptz()
1277 .naive_utc(),
1278 }),
1279 expr: Box::new(exprs[1].take()),
1280 },
1281 Err(err) => MirScalarExpr::literal(
1282 Err(err),
1283 e.typ(column_types).scalar_type,
1284 ),
1285 }
1286 }
1287 }
1288 }
1289 MirScalarExpr::If { cond, then, els } => {
1290 if let Some(literal) = cond.as_literal() {
1291 match literal {
1292 Ok(Datum::True) => *e = then.take(),
1293 Ok(Datum::False) | Ok(Datum::Null) => *e = els.take(),
1294 Err(err) => {
1295 *e = MirScalarExpr::Literal(
1296 Err(err.clone()),
1297 then.typ(column_types)
1298 .union(&els.typ(column_types))
1299 .unwrap(),
1300 )
1301 }
1302 _ => unreachable!(),
1303 }
1304 } else if then == els {
1305 *e = then.take();
1306 } else if then.is_literal_ok()
1307 && els.is_literal_ok()
1308 && then.typ(column_types).scalar_type == SqlScalarType::Bool
1309 && els.typ(column_types).scalar_type == SqlScalarType::Bool
1310 {
1311 match (then.as_literal(), els.as_literal()) {
1312 (Some(Ok(Datum::True)), _) => {
1315 *e = cond
1318 .clone()
1319 .call_is_null()
1320 .not()
1321 .and(cond.take())
1322 .or(els.take());
1323 }
1324 (Some(Ok(Datum::False)), _) => {
1325 *e = cond
1328 .clone()
1329 .not()
1330 .or(cond.take().call_is_null())
1331 .and(els.take());
1332 }
1333 (_, Some(Ok(Datum::True))) => {
1334 *e = cond
1337 .clone()
1338 .not()
1339 .or(cond.take().call_is_null())
1340 .or(then.take());
1341 }
1342 (_, Some(Ok(Datum::False))) => {
1343 *e = cond
1346 .clone()
1347 .call_is_null()
1348 .not()
1349 .and(cond.take())
1350 .and(then.take());
1351 }
1352 _ => {}
1353 }
1354 } else {
1355 match (&mut **then, &mut **els) {
1367 (
1368 MirScalarExpr::CallUnary { func: f1, expr: e1 },
1369 MirScalarExpr::CallUnary { func: f2, expr: e2 },
1370 ) if f1 == f2
1371 && e1
1372 .typ(column_types)
1373 .union(&e2.typ(column_types))
1374 .is_ok() =>
1375 {
1376 *e = cond
1377 .take()
1378 .if_then_else(e1.take(), e2.take())
1379 .call_unary(f1.clone());
1380 }
1381 (
1382 MirScalarExpr::CallBinary {
1383 func: f1,
1384 expr1: e1a,
1385 expr2: e2a,
1386 },
1387 MirScalarExpr::CallBinary {
1388 func: f2,
1389 expr1: e1b,
1390 expr2: e2b,
1391 },
1392 ) if f1 == f2
1393 && e1a == e1b
1394 && e2a
1395 .typ(column_types)
1396 .union(&e2b.typ(column_types))
1397 .is_ok() =>
1398 {
1399 *e = e1a.take().call_binary(
1400 cond.take().if_then_else(e2a.take(), e2b.take()),
1401 f1.clone(),
1402 );
1403 }
1404 (
1405 MirScalarExpr::CallBinary {
1406 func: f1,
1407 expr1: e1a,
1408 expr2: e2a,
1409 },
1410 MirScalarExpr::CallBinary {
1411 func: f2,
1412 expr1: e1b,
1413 expr2: e2b,
1414 },
1415 ) if f1 == f2
1416 && e2a == e2b
1417 && e1a
1418 .typ(column_types)
1419 .union(&e1b.typ(column_types))
1420 .is_ok() =>
1421 {
1422 *e = cond
1423 .take()
1424 .if_then_else(e1a.take(), e1b.take())
1425 .call_binary(e2a.take(), f1.clone());
1426 }
1427 _ => {}
1428 }
1429 }
1430 }
1431 },
1432 );
1433 }
1434
1435 fn list_create_type(list_create: &MirScalarExpr) -> SqlScalarType {
1438 if let MirScalarExpr::CallVariadic {
1439 func: VariadicFunc::ListCreate { elem_type: typ },
1440 ..
1441 } = list_create
1442 {
1443 (*typ).clone()
1444 } else {
1445 unreachable!()
1446 }
1447 }
1448
1449 fn is_list_create_call(expr: &MirScalarExpr) -> bool {
1450 matches!(
1451 expr,
1452 MirScalarExpr::CallVariadic {
1453 func: VariadicFunc::ListCreate { .. },
1454 ..
1455 }
1456 )
1457 }
1458
1459 fn reduce_list_create_list_index_literal(
1474 mut list_create_to_reduce: MirScalarExpr,
1475 mut index_exprs: Vec<MirScalarExpr>,
1476 ) -> MirScalarExpr {
1477 let mut list_create_mut_refs = vec![&mut list_create_to_reduce];
1489 let mut earlier_list_create_types: Vec<&mut SqlScalarType> = vec![];
1490 let mut i = 0;
1491 while i < index_exprs.len()
1492 && list_create_mut_refs
1493 .iter()
1494 .all(|lc| is_list_create_call(lc))
1495 {
1496 if index_exprs[i].is_literal_ok() {
1497 let removed_index = index_exprs.remove(i);
1499 let index_i64 = match removed_index.as_literal().unwrap().unwrap() {
1500 Datum::Int64(sql_index_i64) => sql_index_i64 - 1,
1501 _ => unreachable!(), };
1503 for list_create in &mut list_create_mut_refs {
1506 let list_create_args = match list_create {
1507 MirScalarExpr::CallVariadic {
1508 func: VariadicFunc::ListCreate { elem_type: _ },
1509 exprs,
1510 } => exprs,
1511 _ => unreachable!(), };
1513 if index_i64 >= 0 && index_i64 < list_create_args.len().try_into().unwrap()
1515 {
1516 let index: usize = index_i64.try_into().unwrap();
1517 **list_create = list_create_args.swap_remove(index);
1518 } else {
1519 let typ = list_create_type(list_create);
1520 **list_create = MirScalarExpr::literal_null(typ);
1521 }
1522 }
1523 for t in earlier_list_create_types.iter_mut() {
1525 if let SqlScalarType::List {
1526 element_type,
1527 custom_id: _,
1528 } = t
1529 {
1530 **t = *element_type.clone();
1531 let mut u = &mut **t;
1534 while let SqlScalarType::List {
1535 element_type,
1536 custom_id,
1537 } = u
1538 {
1539 *custom_id = None;
1540 u = &mut **element_type;
1541 }
1542 } else {
1543 unreachable!("already matched below");
1544 }
1545 }
1546 } else {
1547 list_create_mut_refs = list_create_mut_refs
1551 .into_iter()
1552 .flat_map(|list_create| match list_create {
1553 MirScalarExpr::CallVariadic {
1554 func: VariadicFunc::ListCreate { elem_type },
1555 exprs: list_create_args,
1556 } => {
1557 earlier_list_create_types.push(elem_type);
1558 list_create_args
1559 }
1560 _ => unreachable!(),
1562 })
1563 .collect();
1564 i += 1; }
1566 }
1567 if index_exprs.is_empty() {
1570 assert_eq!(list_create_mut_refs.len(), 1);
1571 list_create_to_reduce
1572 } else {
1573 let mut exprs: Vec<MirScalarExpr> = vec![list_create_to_reduce];
1574 exprs.append(&mut index_exprs);
1575 MirScalarExpr::CallVariadic {
1576 func: VariadicFunc::ListIndex,
1577 exprs,
1578 }
1579 }
1580 }
1581
1582 }
1584
1585 fn decompose_is_null(&mut self) -> Option<MirScalarExpr> {
1593 match self {
1596 MirScalarExpr::CallUnary {
1597 func,
1598 expr: inner_expr,
1599 } => {
1600 if !func.introduces_nulls() {
1601 if func.propagates_nulls() {
1602 *self = inner_expr.take();
1603 return self.decompose_is_null();
1604 } else {
1605 return Some(MirScalarExpr::literal_false());
1608 }
1609 }
1610 }
1611 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1612 if func.propagates_nulls() && !func.introduces_nulls() {
1615 let expr1 = expr1.take().call_is_null();
1616 let expr2 = expr2.take().call_is_null();
1617 return Some(expr1.or(expr2));
1618 }
1619 }
1620 MirScalarExpr::CallVariadic { func, exprs } => {
1621 if func.propagates_nulls() && !func.introduces_nulls() {
1622 let exprs = exprs.into_iter().map(|e| e.take().call_is_null()).collect();
1623 return Some(MirScalarExpr::CallVariadic {
1624 func: VariadicFunc::Or,
1625 exprs,
1626 });
1627 }
1628 }
1629 _ => {}
1630 }
1631
1632 None
1633 }
1634
1635 pub fn flatten_associative(&mut self) {
1638 match self {
1639 MirScalarExpr::CallVariadic {
1640 exprs: outer_operands,
1641 func: outer_func,
1642 } if outer_func.is_associative() => {
1643 *outer_operands = outer_operands
1644 .into_iter()
1645 .flat_map(|o| {
1646 if let MirScalarExpr::CallVariadic {
1647 exprs: inner_operands,
1648 func: inner_func,
1649 } = o
1650 {
1651 if *inner_func == *outer_func {
1652 mem::take(inner_operands)
1653 } else {
1654 vec![o.take()]
1655 }
1656 } else {
1657 vec![o.take()]
1658 }
1659 })
1660 .collect();
1661 }
1662 _ => {}
1663 }
1664 }
1665
1666 fn reduce_and_canonicalize_and_or(&mut self) {
1670 let mut old_self = MirScalarExpr::column(0);
1674 while old_self != *self {
1675 old_self = self.clone();
1676 match self {
1677 MirScalarExpr::CallVariadic {
1678 func: func @ (VariadicFunc::And | VariadicFunc::Or),
1679 exprs,
1680 } => {
1681 exprs.sort();
1685
1686 exprs.dedup(); if exprs.len() == 1 {
1690 *self = exprs.swap_remove(0);
1692 } else if exprs.len() == 0 {
1693 *self = func.unit_of_and_or();
1695 } else if exprs.iter().any(|e| *e == func.zero_of_and_or()) {
1696 *self = func.zero_of_and_or();
1698 } else {
1699 exprs.retain(|e| *e != func.unit_of_and_or());
1702 }
1703 }
1704 _ => {}
1705 }
1706 }
1707 }
1708
1709 fn demorgans(&mut self) {
1711 if let MirScalarExpr::CallUnary {
1712 expr: inner,
1713 func: UnaryFunc::Not(func::Not),
1714 } = self
1715 {
1716 inner.flatten_associative();
1717 match &mut **inner {
1718 MirScalarExpr::CallVariadic {
1719 func: inner_func @ (VariadicFunc::And | VariadicFunc::Or),
1720 exprs,
1721 } => {
1722 *inner_func = inner_func.switch_and_or();
1723 *exprs = exprs.into_iter().map(|e| e.take().not()).collect();
1724 *self = (*inner).take(); }
1726 _ => {}
1727 }
1728 }
1729 }
1730
1731 fn undistribute_and_or(&mut self) {
1796 let mut old_self = MirScalarExpr::column(0);
1801 while old_self != *self {
1802 old_self = self.clone();
1803 self.reduce_and_canonicalize_and_or(); if let MirScalarExpr::CallVariadic {
1805 exprs: outer_operands,
1806 func: outer_func @ (VariadicFunc::Or | VariadicFunc::And),
1807 } = self
1808 {
1809 let inner_func = outer_func.switch_and_or();
1810
1811 outer_operands.iter_mut().for_each(|o| {
1814 if !matches!(o, MirScalarExpr::CallVariadic {func: f, ..} if *f == inner_func) {
1815 *o = MirScalarExpr::CallVariadic {
1816 func: inner_func.clone(),
1817 exprs: vec![o.take()],
1818 };
1819 }
1820 });
1821
1822 let mut inner_operands_refs: Vec<&mut Vec<MirScalarExpr>> = outer_operands
1823 .iter_mut()
1824 .map(|o| match o {
1825 MirScalarExpr::CallVariadic { func: f, exprs } if *f == inner_func => exprs,
1826 _ => unreachable!(), })
1828 .collect();
1829
1830 let mut intersection = inner_operands_refs
1832 .iter()
1833 .map(|v| (*v).clone())
1834 .reduce(|ops1, ops2| ops1.into_iter().filter(|e| ops2.contains(e)).collect())
1835 .unwrap();
1836 intersection.sort();
1837 intersection.dedup();
1838
1839 if !intersection.is_empty() {
1840 inner_operands_refs
1844 .iter_mut()
1845 .for_each(|ops| (**ops).retain(|o| !intersection.contains(o)));
1846
1847 outer_operands
1849 .iter_mut()
1850 .for_each(|o| o.reduce_and_canonicalize_and_or());
1851
1852 *self = MirScalarExpr::CallVariadic {
1854 func: inner_func,
1855 exprs: intersection.into_iter().chain_one(self.clone()).collect(),
1856 };
1857 } else {
1858 let all_inner_operands = inner_operands_refs
1869 .iter()
1870 .enumerate()
1871 .flat_map(|(i, inner_vec)| inner_vec.iter().map(move |a| ((*a).clone(), i)))
1872 .sorted()
1873 .collect_vec();
1874
1875 let undistribution_opportunities = all_inner_operands
1880 .iter()
1881 .chunk_by(|(a, _i)| a)
1882 .into_iter()
1883 .map(|(_a, g)| g.map(|(_a, i)| *i).sorted().dedup().collect_vec())
1884 .filter(|g| g.len() > 1)
1885 .collect_vec();
1886
1887 let indexes_to_undistribute = undistribution_opportunities
1889 .iter()
1890 .find(|index_set| {
1892 index_set
1893 .iter()
1894 .any(|i| inner_operands_refs.get(*i).unwrap().len() == 1)
1895 })
1896 .or_else(|| undistribution_opportunities.first())
1898 .cloned();
1899
1900 outer_operands
1902 .iter_mut()
1903 .for_each(|o| o.reduce_and_canonicalize_and_or());
1904
1905 if let Some(indexes_to_undistribute) = indexes_to_undistribute {
1906 let mut undistribute_from = MirScalarExpr::CallVariadic {
1910 func: outer_func.clone(),
1911 exprs: swap_remove_multiple(outer_operands, indexes_to_undistribute),
1912 };
1913 undistribute_from.undistribute_and_or();
1916 outer_operands.push(undistribute_from);
1919 }
1920 }
1921 }
1922 }
1923 }
1924
1925 pub fn non_null_requirements(&self, columns: &mut BTreeSet<usize>) {
1929 match self {
1930 MirScalarExpr::Column(col, _name) => {
1931 columns.insert(*col);
1932 }
1933 MirScalarExpr::Literal(..) => {}
1934 MirScalarExpr::CallUnmaterializable(_) => (),
1935 MirScalarExpr::CallUnary { func, expr } => {
1936 if func.propagates_nulls() {
1937 expr.non_null_requirements(columns);
1938 }
1939 }
1940 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1941 if func.propagates_nulls() {
1942 expr1.non_null_requirements(columns);
1943 expr2.non_null_requirements(columns);
1944 }
1945 }
1946 MirScalarExpr::CallVariadic { func, exprs } => {
1947 if func.propagates_nulls() {
1948 for expr in exprs {
1949 expr.non_null_requirements(columns);
1950 }
1951 }
1952 }
1953 MirScalarExpr::If { .. } => (),
1954 }
1955 }
1956
1957 pub fn typ(&self, column_types: &[SqlColumnType]) -> SqlColumnType {
1958 match self {
1959 MirScalarExpr::Column(i, _name) => column_types[*i].clone(),
1960 MirScalarExpr::Literal(_, typ) => typ.clone(),
1961 MirScalarExpr::CallUnmaterializable(func) => func.output_type(),
1962 MirScalarExpr::CallUnary { expr, func } => func.output_type(expr.typ(column_types)),
1963 MirScalarExpr::CallBinary { expr1, expr2, func } => {
1964 func.output_type(expr1.typ(column_types), expr2.typ(column_types))
1965 }
1966 MirScalarExpr::CallVariadic { exprs, func } => {
1967 func.output_type(exprs.iter().map(|e| e.typ(column_types)).collect())
1968 }
1969 MirScalarExpr::If { cond: _, then, els } => {
1970 let then_type = then.typ(column_types);
1971 let else_type = els.typ(column_types);
1972 then_type.union(&else_type).unwrap()
1973 }
1974 }
1975 }
1976
1977 pub fn eval<'a>(
1978 &'a self,
1979 datums: &[Datum<'a>],
1980 temp_storage: &'a RowArena,
1981 ) -> Result<Datum<'a>, EvalError> {
1982 match self {
1983 MirScalarExpr::Column(index, _name) => Ok(datums[*index].clone()),
1984 MirScalarExpr::Literal(res, _column_type) => match res {
1985 Ok(row) => Ok(row.unpack_first()),
1986 Err(e) => Err(e.clone()),
1987 },
1988 MirScalarExpr::CallUnmaterializable(x) => Err(EvalError::Internal(
1992 format!("cannot evaluate unmaterializable function: {:?}", x).into(),
1993 )),
1994 MirScalarExpr::CallUnary { func, expr } => func.eval(datums, temp_storage, expr),
1995 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
1996 func.eval(datums, temp_storage, expr1, expr2)
1997 }
1998 MirScalarExpr::CallVariadic { func, exprs } => func.eval(datums, temp_storage, exprs),
1999 MirScalarExpr::If { cond, then, els } => match cond.eval(datums, temp_storage)? {
2000 Datum::True => then.eval(datums, temp_storage),
2001 Datum::False | Datum::Null => els.eval(datums, temp_storage),
2002 d => Err(EvalError::Internal(
2003 format!("if condition evaluated to non-boolean datum: {:?}", d).into(),
2004 )),
2005 },
2006 }
2007 }
2008
2009 pub fn contains_temporal(&self) -> bool {
2012 let mut contains = false;
2013 self.visit_pre(|e| {
2014 if let MirScalarExpr::CallUnmaterializable(UnmaterializableFunc::MzNow) = e {
2015 contains = true;
2016 }
2017 });
2018 contains
2019 }
2020
2021 pub fn contains_unmaterializable(&self) -> bool {
2023 let mut contains = false;
2024 self.visit_pre(|e| {
2025 if let MirScalarExpr::CallUnmaterializable(_) = e {
2026 contains = true;
2027 }
2028 });
2029 contains
2030 }
2031
2032 pub fn contains_unmaterializable_except(&self, exceptions: &[UnmaterializableFunc]) -> bool {
2035 let mut contains = false;
2036 self.visit_pre(|e| match e {
2037 MirScalarExpr::CallUnmaterializable(f) if !exceptions.contains(f) => contains = true,
2038 _ => (),
2039 });
2040 contains
2041 }
2042
2043 pub fn contains_column(&self) -> bool {
2045 let mut contains = false;
2046 self.visit_pre(|e| {
2047 if let MirScalarExpr::Column(_col, _name) = e {
2048 contains = true;
2049 }
2050 });
2051 contains
2052 }
2053
2054 pub fn contains_dummy(&self) -> bool {
2056 let mut contains = false;
2057 self.visit_pre(|e| {
2058 if let MirScalarExpr::Literal(row, _) = e {
2059 if let Ok(row) = row {
2060 contains |= row.iter().any(|d| d == Datum::Dummy);
2061 }
2062 }
2063 });
2064 contains
2065 }
2066
2067 pub fn size(&self) -> usize {
2069 let mut size = 0;
2070 self.visit_pre(&mut |_: &MirScalarExpr| {
2071 size += 1;
2072 });
2073 size
2074 }
2075}
2076
2077impl MirScalarExpr {
2078 pub fn could_error(&self) -> bool {
2080 match self {
2081 MirScalarExpr::Column(_col, _name) => false,
2082 MirScalarExpr::Literal(row, ..) => row.is_err(),
2083 MirScalarExpr::CallUnmaterializable(_) => true,
2084 MirScalarExpr::CallUnary { func, expr } => func.could_error() || expr.could_error(),
2085 MirScalarExpr::CallBinary { func, expr1, expr2 } => {
2086 func.could_error() || expr1.could_error() || expr2.could_error()
2087 }
2088 MirScalarExpr::CallVariadic { func, exprs } => {
2089 func.could_error() || exprs.iter().any(|e| e.could_error())
2090 }
2091 MirScalarExpr::If { cond, then, els } => {
2092 cond.could_error() || then.could_error() || els.could_error()
2093 }
2094 }
2095 }
2096}
2097
2098impl VisitChildren<Self> for MirScalarExpr {
2099 fn visit_children<F>(&self, mut f: F)
2100 where
2101 F: FnMut(&Self),
2102 {
2103 use MirScalarExpr::*;
2104 match self {
2105 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2106 CallUnary { expr, .. } => {
2107 f(expr);
2108 }
2109 CallBinary { expr1, expr2, .. } => {
2110 f(expr1);
2111 f(expr2);
2112 }
2113 CallVariadic { exprs, .. } => {
2114 for expr in exprs {
2115 f(expr);
2116 }
2117 }
2118 If { cond, then, els } => {
2119 f(cond);
2120 f(then);
2121 f(els);
2122 }
2123 }
2124 }
2125
2126 fn visit_mut_children<F>(&mut self, mut f: F)
2127 where
2128 F: FnMut(&mut Self),
2129 {
2130 use MirScalarExpr::*;
2131 match self {
2132 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2133 CallUnary { expr, .. } => {
2134 f(expr);
2135 }
2136 CallBinary { expr1, expr2, .. } => {
2137 f(expr1);
2138 f(expr2);
2139 }
2140 CallVariadic { exprs, .. } => {
2141 for expr in exprs {
2142 f(expr);
2143 }
2144 }
2145 If { cond, then, els } => {
2146 f(cond);
2147 f(then);
2148 f(els);
2149 }
2150 }
2151 }
2152
2153 fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
2154 where
2155 F: FnMut(&Self) -> Result<(), E>,
2156 E: From<RecursionLimitError>,
2157 {
2158 use MirScalarExpr::*;
2159 match self {
2160 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2161 CallUnary { expr, .. } => {
2162 f(expr)?;
2163 }
2164 CallBinary { expr1, expr2, .. } => {
2165 f(expr1)?;
2166 f(expr2)?;
2167 }
2168 CallVariadic { exprs, .. } => {
2169 for expr in exprs {
2170 f(expr)?;
2171 }
2172 }
2173 If { cond, then, els } => {
2174 f(cond)?;
2175 f(then)?;
2176 f(els)?;
2177 }
2178 }
2179 Ok(())
2180 }
2181
2182 fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
2183 where
2184 F: FnMut(&mut Self) -> Result<(), E>,
2185 E: From<RecursionLimitError>,
2186 {
2187 use MirScalarExpr::*;
2188 match self {
2189 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2190 CallUnary { expr, .. } => {
2191 f(expr)?;
2192 }
2193 CallBinary { expr1, expr2, .. } => {
2194 f(expr1)?;
2195 f(expr2)?;
2196 }
2197 CallVariadic { exprs, .. } => {
2198 for expr in exprs {
2199 f(expr)?;
2200 }
2201 }
2202 If { cond, then, els } => {
2203 f(cond)?;
2204 f(then)?;
2205 f(els)?;
2206 }
2207 }
2208 Ok(())
2209 }
2210}
2211
2212impl MirScalarExpr {
2213 pub fn children(&self) -> impl DoubleEndedIterator<Item = &Self> {
2215 let mut first = None;
2216 let mut second = None;
2217 let mut third = None;
2218 let mut variadic = None;
2219
2220 use MirScalarExpr::*;
2221 match self {
2222 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2223 CallUnary { expr, .. } => {
2224 first = Some(&**expr);
2225 }
2226 CallBinary { expr1, expr2, .. } => {
2227 first = Some(&**expr1);
2228 second = Some(&**expr2);
2229 }
2230 CallVariadic { exprs, .. } => {
2231 variadic = Some(exprs);
2232 }
2233 If { cond, then, els } => {
2234 first = Some(&**cond);
2235 second = Some(&**then);
2236 third = Some(&**els);
2237 }
2238 }
2239
2240 first
2241 .into_iter()
2242 .chain(second)
2243 .chain(third)
2244 .chain(variadic.into_iter().flatten())
2245 }
2246
2247 pub fn children_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Self> {
2249 let mut first = None;
2250 let mut second = None;
2251 let mut third = None;
2252 let mut variadic = None;
2253
2254 use MirScalarExpr::*;
2255 match self {
2256 Column(_, _) | Literal(_, _) | CallUnmaterializable(_) => (),
2257 CallUnary { expr, .. } => {
2258 first = Some(&mut **expr);
2259 }
2260 CallBinary { expr1, expr2, .. } => {
2261 first = Some(&mut **expr1);
2262 second = Some(&mut **expr2);
2263 }
2264 CallVariadic { exprs, .. } => {
2265 variadic = Some(exprs);
2266 }
2267 If { cond, then, els } => {
2268 first = Some(&mut **cond);
2269 second = Some(&mut **then);
2270 third = Some(&mut **els);
2271 }
2272 }
2273
2274 first
2275 .into_iter()
2276 .chain(second)
2277 .chain(third)
2278 .chain(variadic.into_iter().flatten())
2279 }
2280
2281 pub fn visit_pre<F>(&self, mut f: F)
2283 where
2284 F: FnMut(&Self),
2285 {
2286 let mut worklist = vec![self];
2287 while let Some(e) = worklist.pop() {
2288 f(e);
2289 worklist.extend(e.children().rev());
2290 }
2291 }
2292
2293 pub fn visit_pre_mut<F: FnMut(&mut Self)>(&mut self, mut f: F) {
2295 let mut worklist = vec![self];
2296 while let Some(expr) = worklist.pop() {
2297 f(expr);
2298 worklist.extend(expr.children_mut().rev());
2299 }
2300 }
2301}
2302
2303#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Serialize, Deserialize, Hash, MzReflect)]
2310pub struct FilterCharacteristics {
2311 literal_equality: bool,
2314 like: bool,
2316 is_null: bool,
2317 literal_inequality: usize,
2323 any_filter: bool,
2329}
2330
2331impl BitOrAssign for FilterCharacteristics {
2332 fn bitor_assign(&mut self, rhs: Self) {
2333 self.literal_equality |= rhs.literal_equality;
2334 self.like |= rhs.like;
2335 self.is_null |= rhs.is_null;
2336 self.literal_inequality += rhs.literal_inequality;
2337 self.any_filter |= rhs.any_filter;
2338 }
2339}
2340
2341impl FilterCharacteristics {
2342 pub fn none() -> FilterCharacteristics {
2343 FilterCharacteristics {
2344 literal_equality: false,
2345 like: false,
2346 is_null: false,
2347 literal_inequality: 0,
2348 any_filter: false,
2349 }
2350 }
2351
2352 pub fn explain(&self) -> String {
2353 let mut e = "".to_owned();
2354 if self.literal_equality {
2355 e.push_str("e");
2356 }
2357 if self.like {
2358 e.push_str("l");
2359 }
2360 if self.is_null {
2361 e.push_str("n");
2362 }
2363 for _ in 0..self.literal_inequality {
2364 e.push_str("i");
2365 }
2366 if self.any_filter {
2367 e.push_str("f");
2368 }
2369 e
2370 }
2371
2372 pub fn filter_characteristics(
2373 filters: &Vec<MirScalarExpr>,
2374 ) -> Result<FilterCharacteristics, RecursionLimitError> {
2375 let mut literal_equality = false;
2376 let mut like = false;
2377 let mut is_null = false;
2378 let mut literal_inequality = 0;
2379 let mut any_filter = false;
2380 filters.iter().try_for_each(|f| {
2381 let mut literal_inequality_in_current_filter = false;
2382 let mut is_not_null_in_current_filter = false;
2383 f.visit_pre_with_context(
2384 false,
2385 &mut |not_in_parent_chain, expr| {
2386 not_in_parent_chain
2387 || matches!(
2388 expr,
2389 MirScalarExpr::CallUnary {
2390 func: UnaryFunc::Not(func::Not),
2391 ..
2392 }
2393 )
2394 },
2395 &mut |not_in_parent_chain, expr| {
2396 if !not_in_parent_chain {
2397 if expr.any_expr_eq_literal().is_some() {
2398 literal_equality = true;
2399 }
2400 if expr.any_expr_ineq_literal() {
2401 literal_inequality_in_current_filter = true;
2402 }
2403 if matches!(
2404 expr,
2405 MirScalarExpr::CallUnary {
2406 func: UnaryFunc::IsLikeMatch(_),
2407 ..
2408 }
2409 ) {
2410 like = true;
2411 }
2412 };
2413 if matches!(
2414 expr,
2415 MirScalarExpr::CallUnary {
2416 func: UnaryFunc::IsNull(crate::func::IsNull),
2417 ..
2418 }
2419 ) {
2420 if *not_in_parent_chain {
2421 is_not_null_in_current_filter = true;
2422 } else {
2423 is_null = true;
2424 }
2425 }
2426 },
2427 )?;
2428 if literal_inequality_in_current_filter {
2429 literal_inequality += 1;
2430 }
2431 if !is_not_null_in_current_filter {
2432 any_filter = true;
2434 }
2435 Ok(())
2436 })?;
2437 Ok(FilterCharacteristics {
2438 literal_equality,
2439 like,
2440 is_null,
2441 literal_inequality,
2442 any_filter,
2443 })
2444 }
2445
2446 pub fn add_literal_equality(&mut self) {
2447 self.literal_equality = true;
2448 }
2449
2450 pub fn worst_case_scaling_factor(&self) -> f64 {
2451 let mut factor = 1.0;
2452
2453 if self.literal_equality {
2454 factor *= 0.1;
2455 }
2456
2457 if self.is_null {
2458 factor *= 0.1;
2459 }
2460
2461 if self.literal_inequality >= 2 {
2462 factor *= 0.25;
2463 } else if self.literal_inequality == 1 {
2464 factor *= 0.33;
2465 }
2466
2467 if !(self.literal_equality || self.is_null || self.literal_inequality > 0)
2469 && self.any_filter
2470 {
2471 factor *= 0.9;
2472 }
2473
2474 factor
2475 }
2476}
2477
2478#[derive(
2479 Arbitrary,
2480 Ord,
2481 PartialOrd,
2482 Copy,
2483 Clone,
2484 Debug,
2485 Eq,
2486 PartialEq,
2487 Serialize,
2488 Deserialize,
2489 Hash,
2490 MzReflect,
2491)]
2492pub enum DomainLimit {
2493 None,
2494 Inclusive(i64),
2495 Exclusive(i64),
2496}
2497
2498impl RustType<ProtoDomainLimit> for DomainLimit {
2499 fn into_proto(&self) -> ProtoDomainLimit {
2500 use proto_domain_limit::Kind::*;
2501 let kind = match self {
2502 DomainLimit::None => None(()),
2503 DomainLimit::Inclusive(v) => Inclusive(*v),
2504 DomainLimit::Exclusive(v) => Exclusive(*v),
2505 };
2506 ProtoDomainLimit { kind: Some(kind) }
2507 }
2508
2509 fn from_proto(proto: ProtoDomainLimit) -> Result<Self, TryFromProtoError> {
2510 use proto_domain_limit::Kind::*;
2511 if let Some(kind) = proto.kind {
2512 match kind {
2513 None(()) => Ok(DomainLimit::None),
2514 Inclusive(v) => Ok(DomainLimit::Inclusive(v)),
2515 Exclusive(v) => Ok(DomainLimit::Exclusive(v)),
2516 }
2517 } else {
2518 Err(TryFromProtoError::missing_field("ProtoDomainLimit::kind"))
2519 }
2520 }
2521}
2522
2523#[derive(
2524 Arbitrary, Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect,
2525)]
2526pub enum EvalError {
2527 CharacterNotValidForEncoding(i32),
2528 CharacterTooLargeForEncoding(i32),
2529 DateBinOutOfRange(Box<str>),
2530 DivisionByZero,
2531 Unsupported {
2532 feature: Box<str>,
2533 discussion_no: Option<usize>,
2534 },
2535 FloatOverflow,
2536 FloatUnderflow,
2537 NumericFieldOverflow,
2538 Float32OutOfRange(Box<str>),
2539 Float64OutOfRange(Box<str>),
2540 Int16OutOfRange(Box<str>),
2541 Int32OutOfRange(Box<str>),
2542 Int64OutOfRange(Box<str>),
2543 UInt16OutOfRange(Box<str>),
2544 UInt32OutOfRange(Box<str>),
2545 UInt64OutOfRange(Box<str>),
2546 MzTimestampOutOfRange(Box<str>),
2547 MzTimestampStepOverflow,
2548 OidOutOfRange(Box<str>),
2549 IntervalOutOfRange(Box<str>),
2550 TimestampCannotBeNan,
2551 TimestampOutOfRange,
2552 DateOutOfRange,
2553 CharOutOfRange,
2554 IndexOutOfRange {
2555 provided: i32,
2556 valid_end: i32,
2558 },
2559 InvalidBase64Equals,
2560 InvalidBase64Symbol(char),
2561 InvalidBase64EndSequence,
2562 InvalidTimezone(Box<str>),
2563 InvalidTimezoneInterval,
2564 InvalidTimezoneConversion,
2565 InvalidIanaTimezoneId(Box<str>),
2566 InvalidLayer {
2567 max_layer: usize,
2568 val: i64,
2569 },
2570 InvalidArray(InvalidArrayError),
2571 InvalidEncodingName(Box<str>),
2572 InvalidHashAlgorithm(Box<str>),
2573 InvalidByteSequence {
2574 byte_sequence: Box<str>,
2575 encoding_name: Box<str>,
2576 },
2577 InvalidJsonbCast {
2578 from: Box<str>,
2579 to: Box<str>,
2580 },
2581 InvalidRegex(Box<str>),
2582 InvalidRegexFlag(char),
2583 InvalidParameterValue(Box<str>),
2584 InvalidDatePart(Box<str>),
2585 KeyCannotBeNull,
2586 NegSqrt,
2587 NegLimit,
2588 NullCharacterNotPermitted,
2589 UnknownUnits(Box<str>),
2590 UnsupportedUnits(Box<str>, Box<str>),
2591 UnterminatedLikeEscapeSequence,
2592 Parse(ParseError),
2593 ParseHex(ParseHexError),
2594 Internal(Box<str>),
2595 InfinityOutOfDomain(Box<str>),
2596 NegativeOutOfDomain(Box<str>),
2597 ZeroOutOfDomain(Box<str>),
2598 OutOfDomain(DomainLimit, DomainLimit, Box<str>),
2599 ComplexOutOfRange(Box<str>),
2600 MultipleRowsFromSubquery,
2601 Undefined(Box<str>),
2602 LikePatternTooLong,
2603 LikeEscapeTooLong,
2604 StringValueTooLong {
2605 target_type: Box<str>,
2606 length: usize,
2607 },
2608 MultidimensionalArrayRemovalNotSupported,
2609 IncompatibleArrayDimensions {
2610 dims: Option<(usize, usize)>,
2611 },
2612 TypeFromOid(Box<str>),
2613 InvalidRange(InvalidRangeError),
2614 InvalidRoleId(Box<str>),
2615 InvalidPrivileges(Box<str>),
2616 LetRecLimitExceeded(Box<str>),
2617 MultiDimensionalArraySearch,
2618 MustNotBeNull(Box<str>),
2619 InvalidIdentifier {
2620 ident: Box<str>,
2621 detail: Option<Box<str>>,
2622 },
2623 ArrayFillWrongArraySubscripts,
2624 MaxArraySizeExceeded(usize),
2626 DateDiffOverflow {
2627 unit: Box<str>,
2628 a: Box<str>,
2629 b: Box<str>,
2630 },
2631 IfNullError(Box<str>),
2634 LengthTooLarge,
2635 AclArrayNullElement,
2636 MzAclArrayNullElement,
2637 PrettyError(Box<str>),
2638}
2639
2640impl fmt::Display for EvalError {
2641 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2642 match self {
2643 EvalError::CharacterNotValidForEncoding(v) => {
2644 write!(f, "requested character not valid for encoding: {v}")
2645 }
2646 EvalError::CharacterTooLargeForEncoding(v) => {
2647 write!(f, "requested character too large for encoding: {v}")
2648 }
2649 EvalError::DateBinOutOfRange(message) => f.write_str(message),
2650 EvalError::DivisionByZero => f.write_str("division by zero"),
2651 EvalError::Unsupported {
2652 feature,
2653 discussion_no,
2654 } => {
2655 write!(f, "{} not yet supported", feature)?;
2656 if let Some(discussion_no) = discussion_no {
2657 write!(
2658 f,
2659 ", see https://github.com/MaterializeInc/materialize/discussions/{} for more details",
2660 discussion_no
2661 )?;
2662 }
2663 Ok(())
2664 }
2665 EvalError::FloatOverflow => f.write_str("value out of range: overflow"),
2666 EvalError::FloatUnderflow => f.write_str("value out of range: underflow"),
2667 EvalError::NumericFieldOverflow => f.write_str("numeric field overflow"),
2668 EvalError::Float32OutOfRange(val) => write!(f, "{} real out of range", val.quoted()),
2669 EvalError::Float64OutOfRange(val) => {
2670 write!(f, "{} double precision out of range", val.quoted())
2671 }
2672 EvalError::Int16OutOfRange(val) => write!(f, "{} smallint out of range", val.quoted()),
2673 EvalError::Int32OutOfRange(val) => write!(f, "{} integer out of range", val.quoted()),
2674 EvalError::Int64OutOfRange(val) => write!(f, "{} bigint out of range", val.quoted()),
2675 EvalError::UInt16OutOfRange(val) => write!(f, "{} uint2 out of range", val.quoted()),
2676 EvalError::UInt32OutOfRange(val) => write!(f, "{} uint4 out of range", val.quoted()),
2677 EvalError::UInt64OutOfRange(val) => write!(f, "{} uint8 out of range", val.quoted()),
2678 EvalError::MzTimestampOutOfRange(val) => {
2679 write!(f, "{} mz_timestamp out of range", val.quoted())
2680 }
2681 EvalError::MzTimestampStepOverflow => f.write_str("step mz_timestamp overflow"),
2682 EvalError::OidOutOfRange(val) => write!(f, "{} OID out of range", val.quoted()),
2683 EvalError::IntervalOutOfRange(val) => {
2684 write!(f, "{} interval out of range", val.quoted())
2685 }
2686 EvalError::TimestampCannotBeNan => f.write_str("timestamp cannot be NaN"),
2687 EvalError::TimestampOutOfRange => f.write_str("timestamp out of range"),
2688 EvalError::DateOutOfRange => f.write_str("date out of range"),
2689 EvalError::CharOutOfRange => f.write_str("\"char\" out of range"),
2690 EvalError::IndexOutOfRange {
2691 provided,
2692 valid_end,
2693 } => write!(f, "index {provided} out of valid range, 0..{valid_end}",),
2694 EvalError::InvalidBase64Equals => {
2695 f.write_str("unexpected \"=\" while decoding base64 sequence")
2696 }
2697 EvalError::InvalidBase64Symbol(c) => write!(
2698 f,
2699 "invalid symbol \"{}\" found while decoding base64 sequence",
2700 c.escape_default()
2701 ),
2702 EvalError::InvalidBase64EndSequence => f.write_str("invalid base64 end sequence"),
2703 EvalError::InvalidJsonbCast { from, to } => {
2704 write!(f, "cannot cast jsonb {} to type {}", from, to)
2705 }
2706 EvalError::InvalidTimezone(tz) => write!(f, "invalid time zone '{}'", tz),
2707 EvalError::InvalidTimezoneInterval => {
2708 f.write_str("timezone interval must not contain months or years")
2709 }
2710 EvalError::InvalidTimezoneConversion => f.write_str("invalid timezone conversion"),
2711 EvalError::InvalidIanaTimezoneId(tz) => {
2712 write!(f, "invalid IANA Time Zone Database identifier: '{}'", tz)
2713 }
2714 EvalError::InvalidLayer { max_layer, val } => write!(
2715 f,
2716 "invalid layer: {}; must use value within [1, {}]",
2717 val, max_layer
2718 ),
2719 EvalError::InvalidArray(e) => e.fmt(f),
2720 EvalError::InvalidEncodingName(name) => write!(f, "invalid encoding name '{}'", name),
2721 EvalError::InvalidHashAlgorithm(alg) => write!(f, "invalid hash algorithm '{}'", alg),
2722 EvalError::InvalidByteSequence {
2723 byte_sequence,
2724 encoding_name,
2725 } => write!(
2726 f,
2727 "invalid byte sequence '{}' for encoding '{}'",
2728 byte_sequence, encoding_name
2729 ),
2730 EvalError::InvalidDatePart(part) => write!(f, "invalid datepart {}", part.quoted()),
2731 EvalError::KeyCannotBeNull => f.write_str("key cannot be null"),
2732 EvalError::NegSqrt => f.write_str("cannot take square root of a negative number"),
2733 EvalError::NegLimit => f.write_str("LIMIT must not be negative"),
2734 EvalError::NullCharacterNotPermitted => f.write_str("null character not permitted"),
2735 EvalError::InvalidRegex(e) => write!(f, "invalid regular expression: {}", e),
2736 EvalError::InvalidRegexFlag(c) => write!(f, "invalid regular expression flag: {}", c),
2737 EvalError::InvalidParameterValue(s) => f.write_str(s),
2738 EvalError::UnknownUnits(units) => write!(f, "unit '{}' not recognized", units),
2739 EvalError::UnsupportedUnits(units, typ) => {
2740 write!(f, "unit '{}' not supported for type {}", units, typ)
2741 }
2742 EvalError::UnterminatedLikeEscapeSequence => {
2743 f.write_str("unterminated escape sequence in LIKE")
2744 }
2745 EvalError::Parse(e) => e.fmt(f),
2746 EvalError::PrettyError(e) => e.fmt(f),
2747 EvalError::ParseHex(e) => e.fmt(f),
2748 EvalError::Internal(s) => write!(f, "internal error: {}", s),
2749 EvalError::InfinityOutOfDomain(s) => {
2750 write!(f, "function {} is only defined for finite arguments", s)
2751 }
2752 EvalError::NegativeOutOfDomain(s) => {
2753 write!(f, "function {} is not defined for negative numbers", s)
2754 }
2755 EvalError::ZeroOutOfDomain(s) => {
2756 write!(f, "function {} is not defined for zero", s)
2757 }
2758 EvalError::OutOfDomain(lower, upper, s) => {
2759 use DomainLimit::*;
2760 write!(f, "function {s} is defined for numbers ")?;
2761 match (lower, upper) {
2762 (Inclusive(n), None) => write!(f, "greater than or equal to {n}"),
2763 (Exclusive(n), None) => write!(f, "greater than {n}"),
2764 (None, Inclusive(n)) => write!(f, "less than or equal to {n}"),
2765 (None, Exclusive(n)) => write!(f, "less than {n}"),
2766 (Inclusive(lo), Inclusive(hi)) => write!(f, "between {lo} and {hi} inclusive"),
2767 (Exclusive(lo), Exclusive(hi)) => write!(f, "between {lo} and {hi} exclusive"),
2768 (Inclusive(lo), Exclusive(hi)) => {
2769 write!(f, "between {lo} inclusive and {hi} exclusive")
2770 }
2771 (Exclusive(lo), Inclusive(hi)) => {
2772 write!(f, "between {lo} exclusive and {hi} inclusive")
2773 }
2774 (None, None) => panic!("invalid domain error"),
2775 }
2776 }
2777 EvalError::ComplexOutOfRange(s) => {
2778 write!(f, "function {} cannot return complex numbers", s)
2779 }
2780 EvalError::MultipleRowsFromSubquery => {
2781 write!(f, "more than one record produced in subquery")
2782 }
2783 EvalError::Undefined(s) => {
2784 write!(f, "{} is undefined", s)
2785 }
2786 EvalError::LikePatternTooLong => {
2787 write!(f, "LIKE pattern exceeds maximum length")
2788 }
2789 EvalError::LikeEscapeTooLong => {
2790 write!(f, "invalid escape string")
2791 }
2792 EvalError::StringValueTooLong {
2793 target_type,
2794 length,
2795 } => {
2796 write!(f, "value too long for type {}({})", target_type, length)
2797 }
2798 EvalError::MultidimensionalArrayRemovalNotSupported => {
2799 write!(
2800 f,
2801 "removing elements from multidimensional arrays is not supported"
2802 )
2803 }
2804 EvalError::IncompatibleArrayDimensions { dims: _ } => {
2805 write!(f, "cannot concatenate incompatible arrays")
2806 }
2807 EvalError::TypeFromOid(msg) => write!(f, "{msg}"),
2808 EvalError::InvalidRange(e) => e.fmt(f),
2809 EvalError::InvalidRoleId(msg) => write!(f, "{msg}"),
2810 EvalError::InvalidPrivileges(privilege) => {
2811 write!(f, "unrecognized privilege type: {privilege}")
2812 }
2813 EvalError::LetRecLimitExceeded(max_iters) => {
2814 write!(
2815 f,
2816 "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.)",
2817 max_iters
2818 )
2819 }
2820 EvalError::MultiDimensionalArraySearch => write!(
2821 f,
2822 "searching for elements in multidimensional arrays is not supported"
2823 ),
2824 EvalError::MustNotBeNull(v) => write!(f, "{v} must not be null"),
2825 EvalError::InvalidIdentifier { ident, .. } => {
2826 write!(f, "string is not a valid identifier: {}", ident.quoted())
2827 }
2828 EvalError::ArrayFillWrongArraySubscripts => {
2829 f.write_str("wrong number of array subscripts")
2830 }
2831 EvalError::MaxArraySizeExceeded(max_size) => {
2832 write!(
2833 f,
2834 "array size exceeds the maximum allowed ({max_size} bytes)"
2835 )
2836 }
2837 EvalError::DateDiffOverflow { unit, a, b } => {
2838 write!(f, "datediff overflow, {unit} of {a}, {b}")
2839 }
2840 EvalError::IfNullError(s) => f.write_str(s),
2841 EvalError::LengthTooLarge => write!(f, "requested length too large"),
2842 EvalError::AclArrayNullElement => write!(f, "ACL arrays must not contain null values"),
2843 EvalError::MzAclArrayNullElement => {
2844 write!(f, "MZ_ACL arrays must not contain null values")
2845 }
2846 }
2847 }
2848}
2849
2850impl EvalError {
2851 pub fn detail(&self) -> Option<String> {
2852 match self {
2853 EvalError::IncompatibleArrayDimensions { dims: None } => Some(
2854 "Arrays with differing dimensions are not compatible for concatenation.".into(),
2855 ),
2856 EvalError::IncompatibleArrayDimensions {
2857 dims: Some((a_dims, b_dims)),
2858 } => Some(format!(
2859 "Arrays of {} and {} dimensions are not compatible for concatenation.",
2860 a_dims, b_dims
2861 )),
2862 EvalError::InvalidIdentifier { detail, .. } => detail.as_deref().map(Into::into),
2863 EvalError::ArrayFillWrongArraySubscripts => {
2864 Some("Low bound array has different size than dimensions array.".into())
2865 }
2866 _ => None,
2867 }
2868 }
2869
2870 pub fn hint(&self) -> Option<String> {
2871 match self {
2872 EvalError::InvalidBase64EndSequence => Some(
2873 "Input data is missing padding, is truncated, or is otherwise corrupted.".into(),
2874 ),
2875 EvalError::LikeEscapeTooLong => {
2876 Some("Escape string must be empty or one character.".into())
2877 }
2878 EvalError::MzTimestampOutOfRange(_) => Some(
2879 "Integer, numeric, and text casts to mz_timestamp must be in the form of whole \
2880 milliseconds since the Unix epoch. Values with fractional parts cannot be \
2881 converted to mz_timestamp."
2882 .into(),
2883 ),
2884 _ => None,
2885 }
2886 }
2887}
2888
2889impl std::error::Error for EvalError {}
2890
2891impl From<ParseError> for EvalError {
2892 fn from(e: ParseError) -> EvalError {
2893 EvalError::Parse(e)
2894 }
2895}
2896
2897impl From<ParseHexError> for EvalError {
2898 fn from(e: ParseHexError) -> EvalError {
2899 EvalError::ParseHex(e)
2900 }
2901}
2902
2903impl From<InvalidArrayError> for EvalError {
2904 fn from(e: InvalidArrayError) -> EvalError {
2905 EvalError::InvalidArray(e)
2906 }
2907}
2908
2909impl From<RegexCompilationError> for EvalError {
2910 fn from(e: RegexCompilationError) -> EvalError {
2911 EvalError::InvalidRegex(e.to_string().into())
2912 }
2913}
2914
2915impl From<TypeFromOidError> for EvalError {
2916 fn from(e: TypeFromOidError) -> EvalError {
2917 EvalError::TypeFromOid(e.to_string().into())
2918 }
2919}
2920
2921impl From<DateError> for EvalError {
2922 fn from(e: DateError) -> EvalError {
2923 match e {
2924 DateError::OutOfRange => EvalError::DateOutOfRange,
2925 }
2926 }
2927}
2928
2929impl From<TimestampError> for EvalError {
2930 fn from(e: TimestampError) -> EvalError {
2931 match e {
2932 TimestampError::OutOfRange => EvalError::TimestampOutOfRange,
2933 }
2934 }
2935}
2936
2937impl From<InvalidRangeError> for EvalError {
2938 fn from(e: InvalidRangeError) -> EvalError {
2939 EvalError::InvalidRange(e)
2940 }
2941}
2942
2943impl RustType<ProtoEvalError> for EvalError {
2944 fn into_proto(&self) -> ProtoEvalError {
2945 use proto_eval_error::Kind::*;
2946 use proto_eval_error::*;
2947 let kind = match self {
2948 EvalError::CharacterNotValidForEncoding(v) => CharacterNotValidForEncoding(*v),
2949 EvalError::CharacterTooLargeForEncoding(v) => CharacterTooLargeForEncoding(*v),
2950 EvalError::DateBinOutOfRange(v) => DateBinOutOfRange(v.into_proto()),
2951 EvalError::DivisionByZero => DivisionByZero(()),
2952 EvalError::Unsupported {
2953 feature,
2954 discussion_no,
2955 } => Unsupported(ProtoUnsupported {
2956 feature: feature.into_proto(),
2957 discussion_no: discussion_no.into_proto(),
2958 }),
2959 EvalError::FloatOverflow => FloatOverflow(()),
2960 EvalError::FloatUnderflow => FloatUnderflow(()),
2961 EvalError::NumericFieldOverflow => NumericFieldOverflow(()),
2962 EvalError::Float32OutOfRange(val) => Float32OutOfRange(ProtoValueOutOfRange {
2963 value: val.to_string(),
2964 }),
2965 EvalError::Float64OutOfRange(val) => Float64OutOfRange(ProtoValueOutOfRange {
2966 value: val.to_string(),
2967 }),
2968 EvalError::Int16OutOfRange(val) => Int16OutOfRange(ProtoValueOutOfRange {
2969 value: val.to_string(),
2970 }),
2971 EvalError::Int32OutOfRange(val) => Int32OutOfRange(ProtoValueOutOfRange {
2972 value: val.to_string(),
2973 }),
2974 EvalError::Int64OutOfRange(val) => Int64OutOfRange(ProtoValueOutOfRange {
2975 value: val.to_string(),
2976 }),
2977 EvalError::UInt16OutOfRange(val) => Uint16OutOfRange(ProtoValueOutOfRange {
2978 value: val.to_string(),
2979 }),
2980 EvalError::UInt32OutOfRange(val) => Uint32OutOfRange(ProtoValueOutOfRange {
2981 value: val.to_string(),
2982 }),
2983 EvalError::UInt64OutOfRange(val) => Uint64OutOfRange(ProtoValueOutOfRange {
2984 value: val.to_string(),
2985 }),
2986 EvalError::MzTimestampOutOfRange(val) => MzTimestampOutOfRange(ProtoValueOutOfRange {
2987 value: val.to_string(),
2988 }),
2989 EvalError::MzTimestampStepOverflow => MzTimestampStepOverflow(()),
2990 EvalError::OidOutOfRange(val) => OidOutOfRange(ProtoValueOutOfRange {
2991 value: val.to_string(),
2992 }),
2993 EvalError::IntervalOutOfRange(val) => IntervalOutOfRange(ProtoValueOutOfRange {
2994 value: val.to_string(),
2995 }),
2996 EvalError::TimestampCannotBeNan => TimestampCannotBeNan(()),
2997 EvalError::TimestampOutOfRange => TimestampOutOfRange(()),
2998 EvalError::DateOutOfRange => DateOutOfRange(()),
2999 EvalError::CharOutOfRange => CharOutOfRange(()),
3000 EvalError::IndexOutOfRange {
3001 provided,
3002 valid_end,
3003 } => IndexOutOfRange(ProtoIndexOutOfRange {
3004 provided: *provided,
3005 valid_end: *valid_end,
3006 }),
3007 EvalError::InvalidBase64Equals => InvalidBase64Equals(()),
3008 EvalError::InvalidBase64Symbol(sym) => InvalidBase64Symbol(sym.into_proto()),
3009 EvalError::InvalidBase64EndSequence => InvalidBase64EndSequence(()),
3010 EvalError::InvalidTimezone(tz) => InvalidTimezone(tz.into_proto()),
3011 EvalError::InvalidTimezoneInterval => InvalidTimezoneInterval(()),
3012 EvalError::InvalidTimezoneConversion => InvalidTimezoneConversion(()),
3013 EvalError::InvalidLayer { max_layer, val } => InvalidLayer(ProtoInvalidLayer {
3014 max_layer: max_layer.into_proto(),
3015 val: *val,
3016 }),
3017 EvalError::InvalidArray(error) => InvalidArray(error.into_proto()),
3018 EvalError::InvalidEncodingName(v) => InvalidEncodingName(v.into_proto()),
3019 EvalError::InvalidHashAlgorithm(v) => InvalidHashAlgorithm(v.into_proto()),
3020 EvalError::InvalidByteSequence {
3021 byte_sequence,
3022 encoding_name,
3023 } => InvalidByteSequence(ProtoInvalidByteSequence {
3024 byte_sequence: byte_sequence.into_proto(),
3025 encoding_name: encoding_name.into_proto(),
3026 }),
3027 EvalError::InvalidJsonbCast { from, to } => InvalidJsonbCast(ProtoInvalidJsonbCast {
3028 from: from.into_proto(),
3029 to: to.into_proto(),
3030 }),
3031 EvalError::InvalidRegex(v) => InvalidRegex(v.into_proto()),
3032 EvalError::InvalidRegexFlag(v) => InvalidRegexFlag(v.into_proto()),
3033 EvalError::InvalidParameterValue(v) => InvalidParameterValue(v.into_proto()),
3034 EvalError::InvalidDatePart(part) => InvalidDatePart(part.into_proto()),
3035 EvalError::KeyCannotBeNull => KeyCannotBeNull(()),
3036 EvalError::NegSqrt => NegSqrt(()),
3037 EvalError::NegLimit => NegLimit(()),
3038 EvalError::NullCharacterNotPermitted => NullCharacterNotPermitted(()),
3039 EvalError::UnknownUnits(v) => UnknownUnits(v.into_proto()),
3040 EvalError::UnsupportedUnits(units, typ) => UnsupportedUnits(ProtoUnsupportedUnits {
3041 units: units.into_proto(),
3042 typ: typ.into_proto(),
3043 }),
3044 EvalError::UnterminatedLikeEscapeSequence => UnterminatedLikeEscapeSequence(()),
3045 EvalError::Parse(error) => Parse(error.into_proto()),
3046 EvalError::PrettyError(error) => PrettyError(error.into_proto()),
3047 EvalError::ParseHex(error) => ParseHex(error.into_proto()),
3048 EvalError::Internal(v) => Internal(v.into_proto()),
3049 EvalError::InfinityOutOfDomain(v) => InfinityOutOfDomain(v.into_proto()),
3050 EvalError::NegativeOutOfDomain(v) => NegativeOutOfDomain(v.into_proto()),
3051 EvalError::ZeroOutOfDomain(v) => ZeroOutOfDomain(v.into_proto()),
3052 EvalError::OutOfDomain(lower, upper, id) => OutOfDomain(ProtoOutOfDomain {
3053 lower: Some(lower.into_proto()),
3054 upper: Some(upper.into_proto()),
3055 id: id.into_proto(),
3056 }),
3057 EvalError::ComplexOutOfRange(v) => ComplexOutOfRange(v.into_proto()),
3058 EvalError::MultipleRowsFromSubquery => MultipleRowsFromSubquery(()),
3059 EvalError::Undefined(v) => Undefined(v.into_proto()),
3060 EvalError::LikePatternTooLong => LikePatternTooLong(()),
3061 EvalError::LikeEscapeTooLong => LikeEscapeTooLong(()),
3062 EvalError::StringValueTooLong {
3063 target_type,
3064 length,
3065 } => StringValueTooLong(ProtoStringValueTooLong {
3066 target_type: target_type.into_proto(),
3067 length: length.into_proto(),
3068 }),
3069 EvalError::MultidimensionalArrayRemovalNotSupported => {
3070 MultidimensionalArrayRemovalNotSupported(())
3071 }
3072 EvalError::IncompatibleArrayDimensions { dims } => {
3073 IncompatibleArrayDimensions(ProtoIncompatibleArrayDimensions {
3074 dims: dims.into_proto(),
3075 })
3076 }
3077 EvalError::TypeFromOid(v) => TypeFromOid(v.into_proto()),
3078 EvalError::InvalidRange(error) => InvalidRange(error.into_proto()),
3079 EvalError::InvalidRoleId(v) => InvalidRoleId(v.into_proto()),
3080 EvalError::InvalidPrivileges(v) => InvalidPrivileges(v.into_proto()),
3081 EvalError::LetRecLimitExceeded(v) => WmrRecursionLimitExceeded(v.into_proto()),
3082 EvalError::MultiDimensionalArraySearch => MultiDimensionalArraySearch(()),
3083 EvalError::MustNotBeNull(v) => MustNotBeNull(v.into_proto()),
3084 EvalError::InvalidIdentifier { ident, detail } => {
3085 InvalidIdentifier(ProtoInvalidIdentifier {
3086 ident: ident.into_proto(),
3087 detail: detail.into_proto(),
3088 })
3089 }
3090 EvalError::ArrayFillWrongArraySubscripts => ArrayFillWrongArraySubscripts(()),
3091 EvalError::MaxArraySizeExceeded(max_size) => {
3092 MaxArraySizeExceeded(u64::cast_from(*max_size))
3093 }
3094 EvalError::DateDiffOverflow { unit, a, b } => DateDiffOverflow(ProtoDateDiffOverflow {
3095 unit: unit.into_proto(),
3096 a: a.into_proto(),
3097 b: b.into_proto(),
3098 }),
3099 EvalError::IfNullError(s) => IfNullError(s.into_proto()),
3100 EvalError::LengthTooLarge => LengthTooLarge(()),
3101 EvalError::AclArrayNullElement => AclArrayNullElement(()),
3102 EvalError::MzAclArrayNullElement => MzAclArrayNullElement(()),
3103 EvalError::InvalidIanaTimezoneId(s) => InvalidIanaTimezoneId(s.into_proto()),
3104 };
3105 ProtoEvalError { kind: Some(kind) }
3106 }
3107
3108 fn from_proto(proto: ProtoEvalError) -> Result<Self, TryFromProtoError> {
3109 use proto_eval_error::Kind::*;
3110 match proto.kind {
3111 Some(kind) => match kind {
3112 CharacterNotValidForEncoding(v) => Ok(EvalError::CharacterNotValidForEncoding(v)),
3113 CharacterTooLargeForEncoding(v) => Ok(EvalError::CharacterTooLargeForEncoding(v)),
3114 DateBinOutOfRange(v) => Ok(EvalError::DateBinOutOfRange(v.into())),
3115 DivisionByZero(()) => Ok(EvalError::DivisionByZero),
3116 Unsupported(v) => Ok(EvalError::Unsupported {
3117 feature: v.feature.into(),
3118 discussion_no: v.discussion_no.into_rust()?,
3119 }),
3120 FloatOverflow(()) => Ok(EvalError::FloatOverflow),
3121 FloatUnderflow(()) => Ok(EvalError::FloatUnderflow),
3122 NumericFieldOverflow(()) => Ok(EvalError::NumericFieldOverflow),
3123 Float32OutOfRange(val) => Ok(EvalError::Float32OutOfRange(val.value.into())),
3124 Float64OutOfRange(val) => Ok(EvalError::Float64OutOfRange(val.value.into())),
3125 Int16OutOfRange(val) => Ok(EvalError::Int16OutOfRange(val.value.into())),
3126 Int32OutOfRange(val) => Ok(EvalError::Int32OutOfRange(val.value.into())),
3127 Int64OutOfRange(val) => Ok(EvalError::Int64OutOfRange(val.value.into())),
3128 Uint16OutOfRange(val) => Ok(EvalError::UInt16OutOfRange(val.value.into())),
3129 Uint32OutOfRange(val) => Ok(EvalError::UInt32OutOfRange(val.value.into())),
3130 Uint64OutOfRange(val) => Ok(EvalError::UInt64OutOfRange(val.value.into())),
3131 MzTimestampOutOfRange(val) => {
3132 Ok(EvalError::MzTimestampOutOfRange(val.value.into()))
3133 }
3134 MzTimestampStepOverflow(()) => Ok(EvalError::MzTimestampStepOverflow),
3135 OidOutOfRange(val) => Ok(EvalError::OidOutOfRange(val.value.into())),
3136 IntervalOutOfRange(val) => Ok(EvalError::IntervalOutOfRange(val.value.into())),
3137 TimestampCannotBeNan(()) => Ok(EvalError::TimestampCannotBeNan),
3138 TimestampOutOfRange(()) => Ok(EvalError::TimestampOutOfRange),
3139 DateOutOfRange(()) => Ok(EvalError::DateOutOfRange),
3140 CharOutOfRange(()) => Ok(EvalError::CharOutOfRange),
3141 IndexOutOfRange(v) => Ok(EvalError::IndexOutOfRange {
3142 provided: v.provided,
3143 valid_end: v.valid_end,
3144 }),
3145 InvalidBase64Equals(()) => Ok(EvalError::InvalidBase64Equals),
3146 InvalidBase64Symbol(v) => char::from_proto(v).map(EvalError::InvalidBase64Symbol),
3147 InvalidBase64EndSequence(()) => Ok(EvalError::InvalidBase64EndSequence),
3148 InvalidTimezone(v) => Ok(EvalError::InvalidTimezone(v.into())),
3149 InvalidTimezoneInterval(()) => Ok(EvalError::InvalidTimezoneInterval),
3150 InvalidTimezoneConversion(()) => Ok(EvalError::InvalidTimezoneConversion),
3151 InvalidLayer(v) => Ok(EvalError::InvalidLayer {
3152 max_layer: usize::from_proto(v.max_layer)?,
3153 val: v.val,
3154 }),
3155 InvalidArray(error) => Ok(EvalError::InvalidArray(error.into_rust()?)),
3156 InvalidEncodingName(v) => Ok(EvalError::InvalidEncodingName(v.into())),
3157 InvalidHashAlgorithm(v) => Ok(EvalError::InvalidHashAlgorithm(v.into())),
3158 InvalidByteSequence(v) => Ok(EvalError::InvalidByteSequence {
3159 byte_sequence: v.byte_sequence.into(),
3160 encoding_name: v.encoding_name.into(),
3161 }),
3162 InvalidJsonbCast(v) => Ok(EvalError::InvalidJsonbCast {
3163 from: v.from.into(),
3164 to: v.to.into(),
3165 }),
3166 InvalidRegex(v) => Ok(EvalError::InvalidRegex(v.into())),
3167 InvalidRegexFlag(v) => Ok(EvalError::InvalidRegexFlag(char::from_proto(v)?)),
3168 InvalidParameterValue(v) => Ok(EvalError::InvalidParameterValue(v.into())),
3169 InvalidDatePart(part) => Ok(EvalError::InvalidDatePart(part.into())),
3170 KeyCannotBeNull(()) => Ok(EvalError::KeyCannotBeNull),
3171 NegSqrt(()) => Ok(EvalError::NegSqrt),
3172 NegLimit(()) => Ok(EvalError::NegLimit),
3173 NullCharacterNotPermitted(()) => Ok(EvalError::NullCharacterNotPermitted),
3174 UnknownUnits(v) => Ok(EvalError::UnknownUnits(v.into())),
3175 UnsupportedUnits(v) => {
3176 Ok(EvalError::UnsupportedUnits(v.units.into(), v.typ.into()))
3177 }
3178 UnterminatedLikeEscapeSequence(()) => Ok(EvalError::UnterminatedLikeEscapeSequence),
3179 Parse(error) => Ok(EvalError::Parse(error.into_rust()?)),
3180 ParseHex(error) => Ok(EvalError::ParseHex(error.into_rust()?)),
3181 Internal(v) => Ok(EvalError::Internal(v.into())),
3182 InfinityOutOfDomain(v) => Ok(EvalError::InfinityOutOfDomain(v.into())),
3183 NegativeOutOfDomain(v) => Ok(EvalError::NegativeOutOfDomain(v.into())),
3184 ZeroOutOfDomain(v) => Ok(EvalError::ZeroOutOfDomain(v.into())),
3185 OutOfDomain(v) => Ok(EvalError::OutOfDomain(
3186 v.lower.into_rust_if_some("ProtoDomainLimit::lower")?,
3187 v.upper.into_rust_if_some("ProtoDomainLimit::upper")?,
3188 v.id.into(),
3189 )),
3190 ComplexOutOfRange(v) => Ok(EvalError::ComplexOutOfRange(v.into())),
3191 MultipleRowsFromSubquery(()) => Ok(EvalError::MultipleRowsFromSubquery),
3192 Undefined(v) => Ok(EvalError::Undefined(v.into())),
3193 LikePatternTooLong(()) => Ok(EvalError::LikePatternTooLong),
3194 LikeEscapeTooLong(()) => Ok(EvalError::LikeEscapeTooLong),
3195 StringValueTooLong(v) => Ok(EvalError::StringValueTooLong {
3196 target_type: v.target_type.into(),
3197 length: usize::from_proto(v.length)?,
3198 }),
3199 MultidimensionalArrayRemovalNotSupported(()) => {
3200 Ok(EvalError::MultidimensionalArrayRemovalNotSupported)
3201 }
3202 IncompatibleArrayDimensions(v) => Ok(EvalError::IncompatibleArrayDimensions {
3203 dims: v.dims.into_rust()?,
3204 }),
3205 TypeFromOid(v) => Ok(EvalError::TypeFromOid(v.into())),
3206 InvalidRange(e) => Ok(EvalError::InvalidRange(e.into_rust()?)),
3207 InvalidRoleId(v) => Ok(EvalError::InvalidRoleId(v.into())),
3208 InvalidPrivileges(v) => Ok(EvalError::InvalidPrivileges(v.into())),
3209 WmrRecursionLimitExceeded(v) => Ok(EvalError::LetRecLimitExceeded(v.into())),
3210 MultiDimensionalArraySearch(()) => Ok(EvalError::MultiDimensionalArraySearch),
3211 MustNotBeNull(v) => Ok(EvalError::MustNotBeNull(v.into())),
3212 InvalidIdentifier(v) => Ok(EvalError::InvalidIdentifier {
3213 ident: v.ident.into(),
3214 detail: v.detail.into_rust()?,
3215 }),
3216 ArrayFillWrongArraySubscripts(()) => Ok(EvalError::ArrayFillWrongArraySubscripts),
3217 MaxArraySizeExceeded(max_size) => {
3218 Ok(EvalError::MaxArraySizeExceeded(usize::cast_from(max_size)))
3219 }
3220 DateDiffOverflow(v) => Ok(EvalError::DateDiffOverflow {
3221 unit: v.unit.into(),
3222 a: v.a.into(),
3223 b: v.b.into(),
3224 }),
3225 IfNullError(v) => Ok(EvalError::IfNullError(v.into())),
3226 LengthTooLarge(()) => Ok(EvalError::LengthTooLarge),
3227 AclArrayNullElement(()) => Ok(EvalError::AclArrayNullElement),
3228 MzAclArrayNullElement(()) => Ok(EvalError::MzAclArrayNullElement),
3229 InvalidIanaTimezoneId(s) => Ok(EvalError::InvalidIanaTimezoneId(s.into())),
3230 PrettyError(s) => Ok(EvalError::PrettyError(s.into())),
3231 },
3232 None => Err(TryFromProtoError::missing_field("ProtoEvalError::kind")),
3233 }
3234 }
3235}
3236
3237impl RustType<ProtoDims> for (usize, usize) {
3238 fn into_proto(&self) -> ProtoDims {
3239 ProtoDims {
3240 f0: self.0.into_proto(),
3241 f1: self.1.into_proto(),
3242 }
3243 }
3244
3245 fn from_proto(proto: ProtoDims) -> Result<Self, TryFromProtoError> {
3246 Ok((proto.f0.into_rust()?, proto.f1.into_rust()?))
3247 }
3248}
3249
3250#[cfg(test)]
3251mod tests {
3252 use super::*;
3253
3254 #[mz_ore::test]
3255 #[cfg_attr(miri, ignore)] fn test_reduce() {
3257 let relation_type = vec![
3258 SqlScalarType::Int64.nullable(true),
3259 SqlScalarType::Int64.nullable(true),
3260 SqlScalarType::Int64.nullable(false),
3261 ];
3262 let col = MirScalarExpr::column;
3263 let err = |e| MirScalarExpr::literal(Err(e), SqlScalarType::Int64);
3264 let lit = |i| MirScalarExpr::literal_ok(Datum::Int64(i), SqlScalarType::Int64);
3265 let null = || MirScalarExpr::literal_null(SqlScalarType::Int64);
3266
3267 struct TestCase {
3268 input: MirScalarExpr,
3269 output: MirScalarExpr,
3270 }
3271
3272 let test_cases = vec![
3273 TestCase {
3274 input: MirScalarExpr::CallVariadic {
3275 func: VariadicFunc::Coalesce,
3276 exprs: vec![lit(1)],
3277 },
3278 output: lit(1),
3279 },
3280 TestCase {
3281 input: MirScalarExpr::CallVariadic {
3282 func: VariadicFunc::Coalesce,
3283 exprs: vec![lit(1), lit(2)],
3284 },
3285 output: lit(1),
3286 },
3287 TestCase {
3288 input: MirScalarExpr::CallVariadic {
3289 func: VariadicFunc::Coalesce,
3290 exprs: vec![null(), lit(2), null()],
3291 },
3292 output: lit(2),
3293 },
3294 TestCase {
3295 input: MirScalarExpr::CallVariadic {
3296 func: VariadicFunc::Coalesce,
3297 exprs: vec![null(), col(0), null(), col(1), lit(2), lit(3)],
3298 },
3299 output: MirScalarExpr::CallVariadic {
3300 func: VariadicFunc::Coalesce,
3301 exprs: vec![col(0), col(1), lit(2)],
3302 },
3303 },
3304 TestCase {
3305 input: MirScalarExpr::CallVariadic {
3306 func: VariadicFunc::Coalesce,
3307 exprs: vec![col(0), col(2), col(1)],
3308 },
3309 output: MirScalarExpr::CallVariadic {
3310 func: VariadicFunc::Coalesce,
3311 exprs: vec![col(0), col(2)],
3312 },
3313 },
3314 TestCase {
3315 input: MirScalarExpr::CallVariadic {
3316 func: VariadicFunc::Coalesce,
3317 exprs: vec![lit(1), err(EvalError::DivisionByZero)],
3318 },
3319 output: lit(1),
3320 },
3321 TestCase {
3322 input: MirScalarExpr::CallVariadic {
3323 func: VariadicFunc::Coalesce,
3324 exprs: vec![
3325 null(),
3326 err(EvalError::DivisionByZero),
3327 err(EvalError::NumericFieldOverflow),
3328 ],
3329 },
3330 output: err(EvalError::DivisionByZero),
3331 },
3332 ];
3333
3334 for tc in test_cases {
3335 let mut actual = tc.input.clone();
3336 actual.reduce(&relation_type);
3337 assert!(
3338 actual == tc.output,
3339 "input: {}\nactual: {}\nexpected: {}",
3340 tc.input,
3341 actual,
3342 tc.output
3343 );
3344 }
3345 }
3346}