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