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 Undefined(Box<str>),
2687 LikePatternTooLong,
2688 LikeEscapeTooLong,
2689 StringValueTooLong {
2690 target_type: Box<str>,
2691 length: usize,
2692 },
2693 MultidimensionalArrayRemovalNotSupported,
2694 IncompatibleArrayDimensions {
2695 dims: Option<(usize, usize)>,
2696 },
2697 TypeFromOid(Box<str>),
2698 InvalidRange(InvalidRangeError),
2699 InvalidRoleId(Box<str>),
2700 InvalidPrivileges(Box<str>),
2701 InvalidCatalogJson(Box<str>),
2702 LetRecLimitExceeded(Box<str>),
2703 MultiDimensionalArraySearch,
2704 MustNotBeNull(Box<str>),
2705 InvalidIdentifier {
2706 ident: Box<str>,
2707 detail: Option<Box<str>>,
2708 },
2709 ArrayFillWrongArraySubscripts,
2710 MaxArraySizeExceeded(usize),
2712 DateDiffOverflow {
2713 unit: Box<str>,
2714 a: Box<str>,
2715 b: Box<str>,
2716 },
2717 IfNullError(Box<str>),
2720 LengthTooLarge,
2721 AclArrayNullElement,
2722 MzAclArrayNullElement,
2723 PrettyError(Box<str>),
2724}
2725
2726impl fmt::Display for EvalError {
2727 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2728 match self {
2729 EvalError::CharacterNotValidForEncoding(v) => {
2730 write!(f, "requested character not valid for encoding: {v}")
2731 }
2732 EvalError::CharacterTooLargeForEncoding(v) => {
2733 write!(f, "requested character too large for encoding: {v}")
2734 }
2735 EvalError::DateBinOutOfRange(message) => f.write_str(message),
2736 EvalError::DivisionByZero => f.write_str("division by zero"),
2737 EvalError::Unsupported {
2738 feature,
2739 discussion_no,
2740 } => {
2741 write!(f, "{} not yet supported", feature)?;
2742 if let Some(discussion_no) = discussion_no {
2743 write!(
2744 f,
2745 ", see https://github.com/MaterializeInc/materialize/discussions/{} for more details",
2746 discussion_no
2747 )?;
2748 }
2749 Ok(())
2750 }
2751 EvalError::FloatOverflow => f.write_str("value out of range: overflow"),
2752 EvalError::FloatUnderflow => f.write_str("value out of range: underflow"),
2753 EvalError::NumericFieldOverflow => f.write_str("numeric field overflow"),
2754 EvalError::Float32OutOfRange(val) => write!(f, "{} real out of range", val.quoted()),
2755 EvalError::Float64OutOfRange(val) => {
2756 write!(f, "{} double precision out of range", val.quoted())
2757 }
2758 EvalError::Int16OutOfRange(val) => write!(f, "{} smallint out of range", val.quoted()),
2759 EvalError::Int32OutOfRange(val) => write!(f, "{} integer out of range", val.quoted()),
2760 EvalError::Int64OutOfRange(val) => write!(f, "{} bigint out of range", val.quoted()),
2761 EvalError::UInt16OutOfRange(val) => write!(f, "{} uint2 out of range", val.quoted()),
2762 EvalError::UInt32OutOfRange(val) => write!(f, "{} uint4 out of range", val.quoted()),
2763 EvalError::UInt64OutOfRange(val) => write!(f, "{} uint8 out of range", val.quoted()),
2764 EvalError::MzTimestampOutOfRange(val) => {
2765 write!(f, "{} mz_timestamp out of range", val.quoted())
2766 }
2767 EvalError::MzTimestampStepOverflow => f.write_str("step mz_timestamp overflow"),
2768 EvalError::OidOutOfRange(val) => write!(f, "{} OID out of range", val.quoted()),
2769 EvalError::IntervalOutOfRange(val) => {
2770 write!(f, "{} interval out of range", val.quoted())
2771 }
2772 EvalError::TimestampCannotBeNan => f.write_str("timestamp cannot be NaN"),
2773 EvalError::TimestampOutOfRange => f.write_str("timestamp out of range"),
2774 EvalError::DateOutOfRange => f.write_str("date out of range"),
2775 EvalError::CharOutOfRange => f.write_str("\"char\" out of range"),
2776 EvalError::IndexOutOfRange {
2777 provided,
2778 valid_end,
2779 } => write!(f, "index {provided} out of valid range, 0..{valid_end}",),
2780 EvalError::InvalidBase64Equals => {
2781 f.write_str("unexpected \"=\" while decoding base64 sequence")
2782 }
2783 EvalError::InvalidBase64Symbol(c) => write!(
2784 f,
2785 "invalid symbol \"{}\" found while decoding base64 sequence",
2786 c.escape_default()
2787 ),
2788 EvalError::InvalidBase64EndSequence => f.write_str("invalid base64 end sequence"),
2789 EvalError::InvalidJsonbCast { from, to } => {
2790 write!(f, "cannot cast jsonb {} to type {}", from, to)
2791 }
2792 EvalError::InvalidTimezone(tz) => write!(f, "invalid time zone '{}'", tz),
2793 EvalError::InvalidTimezoneInterval => {
2794 f.write_str("timezone interval must not contain months or years")
2795 }
2796 EvalError::InvalidTimezoneConversion => f.write_str("invalid timezone conversion"),
2797 EvalError::InvalidIanaTimezoneId(tz) => {
2798 write!(f, "invalid IANA Time Zone Database identifier: '{}'", tz)
2799 }
2800 EvalError::InvalidLayer { max_layer, val } => write!(
2801 f,
2802 "invalid layer: {}; must use value within [1, {}]",
2803 val, max_layer
2804 ),
2805 EvalError::InvalidArray(e) => e.fmt(f),
2806 EvalError::InvalidEncodingName(name) => write!(f, "invalid encoding name '{}'", name),
2807 EvalError::InvalidHashAlgorithm(alg) => write!(f, "invalid hash algorithm '{}'", alg),
2808 EvalError::InvalidByteSequence {
2809 byte_sequence,
2810 encoding_name,
2811 } => write!(
2812 f,
2813 "invalid byte sequence '{}' for encoding '{}'",
2814 byte_sequence, encoding_name
2815 ),
2816 EvalError::InvalidDatePart(part) => write!(f, "invalid datepart {}", part.quoted()),
2817 EvalError::KeyCannotBeNull => f.write_str("key cannot be null"),
2818 EvalError::NegSqrt => f.write_str("cannot take square root of a negative number"),
2819 EvalError::NegLimit => f.write_str("LIMIT must not be negative"),
2820 EvalError::NullCharacterNotPermitted => f.write_str("null character not permitted"),
2821 EvalError::InvalidRegex(e) => write!(f, "invalid regular expression: {}", e),
2822 EvalError::InvalidRegexFlag(c) => write!(f, "invalid regular expression flag: {}", c),
2823 EvalError::InvalidParameterValue(s) => f.write_str(s),
2824 EvalError::UnknownUnits(units) => write!(f, "unit '{}' not recognized", units),
2825 EvalError::UnsupportedUnits(units, typ) => {
2826 write!(f, "unit '{}' not supported for type {}", units, typ)
2827 }
2828 EvalError::UnterminatedLikeEscapeSequence => {
2829 f.write_str("unterminated escape sequence in LIKE")
2830 }
2831 EvalError::Parse(e) => e.fmt(f),
2832 EvalError::PrettyError(e) => e.fmt(f),
2833 EvalError::ParseHex(e) => e.fmt(f),
2834 EvalError::Internal(s) => write!(f, "internal error: {}", s),
2835 EvalError::InfinityOutOfDomain(s) => {
2836 write!(f, "function {} is only defined for finite arguments", s)
2837 }
2838 EvalError::NegativeOutOfDomain(s) => {
2839 write!(f, "function {} is not defined for negative numbers", s)
2840 }
2841 EvalError::ZeroOutOfDomain(s) => {
2842 write!(f, "function {} is not defined for zero", s)
2843 }
2844 EvalError::OutOfDomain(lower, upper, s) => {
2845 use DomainLimit::*;
2846 write!(f, "function {s} is defined for numbers ")?;
2847 match (lower, upper) {
2848 (Inclusive(n), None) => write!(f, "greater than or equal to {n}"),
2849 (Exclusive(n), None) => write!(f, "greater than {n}"),
2850 (None, Inclusive(n)) => write!(f, "less than or equal to {n}"),
2851 (None, Exclusive(n)) => write!(f, "less than {n}"),
2852 (Inclusive(lo), Inclusive(hi)) => write!(f, "between {lo} and {hi} inclusive"),
2853 (Exclusive(lo), Exclusive(hi)) => write!(f, "between {lo} and {hi} exclusive"),
2854 (Inclusive(lo), Exclusive(hi)) => {
2855 write!(f, "between {lo} inclusive and {hi} exclusive")
2856 }
2857 (Exclusive(lo), Inclusive(hi)) => {
2858 write!(f, "between {lo} exclusive and {hi} inclusive")
2859 }
2860 (None, None) => panic!("invalid domain error"),
2861 }
2862 }
2863 EvalError::ComplexOutOfRange(s) => {
2864 write!(f, "function {} cannot return complex numbers", s)
2865 }
2866 EvalError::MultipleRowsFromSubquery => {
2867 write!(f, "more than one record produced in subquery")
2868 }
2869 EvalError::Undefined(s) => {
2870 write!(f, "{} is undefined", s)
2871 }
2872 EvalError::LikePatternTooLong => {
2873 write!(f, "LIKE pattern exceeds maximum length")
2874 }
2875 EvalError::LikeEscapeTooLong => {
2876 write!(f, "invalid escape string")
2877 }
2878 EvalError::StringValueTooLong {
2879 target_type,
2880 length,
2881 } => {
2882 write!(f, "value too long for type {}({})", target_type, length)
2883 }
2884 EvalError::MultidimensionalArrayRemovalNotSupported => {
2885 write!(
2886 f,
2887 "removing elements from multidimensional arrays is not supported"
2888 )
2889 }
2890 EvalError::IncompatibleArrayDimensions { dims: _ } => {
2891 write!(f, "cannot concatenate incompatible arrays")
2892 }
2893 EvalError::TypeFromOid(msg) => write!(f, "{msg}"),
2894 EvalError::InvalidRange(e) => e.fmt(f),
2895 EvalError::InvalidRoleId(msg) => write!(f, "{msg}"),
2896 EvalError::InvalidPrivileges(privilege) => {
2897 write!(f, "unrecognized privilege type: {privilege}")
2898 }
2899 EvalError::InvalidCatalogJson(msg) => {
2900 write!(f, "invalid catalog JSON: {msg}")
2901 }
2902 EvalError::LetRecLimitExceeded(max_iters) => {
2903 write!(
2904 f,
2905 "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.)",
2906 max_iters
2907 )
2908 }
2909 EvalError::MultiDimensionalArraySearch => write!(
2910 f,
2911 "searching for elements in multidimensional arrays is not supported"
2912 ),
2913 EvalError::MustNotBeNull(v) => write!(f, "{v} must not be null"),
2914 EvalError::InvalidIdentifier { ident, .. } => {
2915 write!(f, "string is not a valid identifier: {}", ident.quoted())
2916 }
2917 EvalError::ArrayFillWrongArraySubscripts => {
2918 f.write_str("wrong number of array subscripts")
2919 }
2920 EvalError::MaxArraySizeExceeded(max_size) => {
2921 write!(
2922 f,
2923 "array size exceeds the maximum allowed ({max_size} bytes)"
2924 )
2925 }
2926 EvalError::DateDiffOverflow { unit, a, b } => {
2927 write!(f, "datediff overflow, {unit} of {a}, {b}")
2928 }
2929 EvalError::IfNullError(s) => f.write_str(s),
2930 EvalError::LengthTooLarge => write!(f, "requested length too large"),
2931 EvalError::AclArrayNullElement => write!(f, "ACL arrays must not contain null values"),
2932 EvalError::MzAclArrayNullElement => {
2933 write!(f, "MZ_ACL arrays must not contain null values")
2934 }
2935 }
2936 }
2937}
2938
2939impl EvalError {
2940 pub fn detail(&self) -> Option<String> {
2941 match self {
2942 EvalError::IncompatibleArrayDimensions { dims: None } => Some(
2943 "Arrays with differing dimensions are not compatible for concatenation.".into(),
2944 ),
2945 EvalError::IncompatibleArrayDimensions {
2946 dims: Some((a_dims, b_dims)),
2947 } => Some(format!(
2948 "Arrays of {} and {} dimensions are not compatible for concatenation.",
2949 a_dims, b_dims
2950 )),
2951 EvalError::InvalidIdentifier { detail, .. } => detail.as_deref().map(Into::into),
2952 EvalError::ArrayFillWrongArraySubscripts => {
2953 Some("Low bound array has different size than dimensions array.".into())
2954 }
2955 _ => None,
2956 }
2957 }
2958
2959 pub fn hint(&self) -> Option<String> {
2960 match self {
2961 EvalError::InvalidBase64EndSequence => Some(
2962 "Input data is missing padding, is truncated, or is otherwise corrupted.".into(),
2963 ),
2964 EvalError::LikeEscapeTooLong => {
2965 Some("Escape string must be empty or one character.".into())
2966 }
2967 EvalError::MzTimestampOutOfRange(_) => Some(
2968 "Integer, numeric, and text casts to mz_timestamp must be in the form of whole \
2969 milliseconds since the Unix epoch. Values with fractional parts cannot be \
2970 converted to mz_timestamp."
2971 .into(),
2972 ),
2973 _ => None,
2974 }
2975 }
2976}
2977
2978impl std::error::Error for EvalError {}
2979
2980impl From<ParseError> for EvalError {
2981 fn from(e: ParseError) -> EvalError {
2982 EvalError::Parse(e)
2983 }
2984}
2985
2986impl From<ParseHexError> for EvalError {
2987 fn from(e: ParseHexError) -> EvalError {
2988 EvalError::ParseHex(e)
2989 }
2990}
2991
2992impl From<InvalidArrayError> for EvalError {
2993 fn from(e: InvalidArrayError) -> EvalError {
2994 EvalError::InvalidArray(e)
2995 }
2996}
2997
2998impl From<RegexCompilationError> for EvalError {
2999 fn from(e: RegexCompilationError) -> EvalError {
3000 EvalError::InvalidRegex(e.to_string().into())
3001 }
3002}
3003
3004impl From<TypeFromOidError> for EvalError {
3005 fn from(e: TypeFromOidError) -> EvalError {
3006 EvalError::TypeFromOid(e.to_string().into())
3007 }
3008}
3009
3010impl From<DateError> for EvalError {
3011 fn from(e: DateError) -> EvalError {
3012 match e {
3013 DateError::OutOfRange => EvalError::DateOutOfRange,
3014 }
3015 }
3016}
3017
3018impl From<TimestampError> for EvalError {
3019 fn from(e: TimestampError) -> EvalError {
3020 match e {
3021 TimestampError::OutOfRange => EvalError::TimestampOutOfRange,
3022 }
3023 }
3024}
3025
3026impl From<InvalidRangeError> for EvalError {
3027 fn from(e: InvalidRangeError) -> EvalError {
3028 EvalError::InvalidRange(e)
3029 }
3030}
3031
3032impl RustType<ProtoEvalError> for EvalError {
3033 fn into_proto(&self) -> ProtoEvalError {
3034 use proto_eval_error::Kind::*;
3035 use proto_eval_error::*;
3036 let kind = match self {
3037 EvalError::CharacterNotValidForEncoding(v) => CharacterNotValidForEncoding(*v),
3038 EvalError::CharacterTooLargeForEncoding(v) => CharacterTooLargeForEncoding(*v),
3039 EvalError::DateBinOutOfRange(v) => DateBinOutOfRange(v.into_proto()),
3040 EvalError::DivisionByZero => DivisionByZero(()),
3041 EvalError::Unsupported {
3042 feature,
3043 discussion_no,
3044 } => Unsupported(ProtoUnsupported {
3045 feature: feature.into_proto(),
3046 discussion_no: discussion_no.into_proto(),
3047 }),
3048 EvalError::FloatOverflow => FloatOverflow(()),
3049 EvalError::FloatUnderflow => FloatUnderflow(()),
3050 EvalError::NumericFieldOverflow => NumericFieldOverflow(()),
3051 EvalError::Float32OutOfRange(val) => Float32OutOfRange(ProtoValueOutOfRange {
3052 value: val.to_string(),
3053 }),
3054 EvalError::Float64OutOfRange(val) => Float64OutOfRange(ProtoValueOutOfRange {
3055 value: val.to_string(),
3056 }),
3057 EvalError::Int16OutOfRange(val) => Int16OutOfRange(ProtoValueOutOfRange {
3058 value: val.to_string(),
3059 }),
3060 EvalError::Int32OutOfRange(val) => Int32OutOfRange(ProtoValueOutOfRange {
3061 value: val.to_string(),
3062 }),
3063 EvalError::Int64OutOfRange(val) => Int64OutOfRange(ProtoValueOutOfRange {
3064 value: val.to_string(),
3065 }),
3066 EvalError::UInt16OutOfRange(val) => Uint16OutOfRange(ProtoValueOutOfRange {
3067 value: val.to_string(),
3068 }),
3069 EvalError::UInt32OutOfRange(val) => Uint32OutOfRange(ProtoValueOutOfRange {
3070 value: val.to_string(),
3071 }),
3072 EvalError::UInt64OutOfRange(val) => Uint64OutOfRange(ProtoValueOutOfRange {
3073 value: val.to_string(),
3074 }),
3075 EvalError::MzTimestampOutOfRange(val) => MzTimestampOutOfRange(ProtoValueOutOfRange {
3076 value: val.to_string(),
3077 }),
3078 EvalError::MzTimestampStepOverflow => MzTimestampStepOverflow(()),
3079 EvalError::OidOutOfRange(val) => OidOutOfRange(ProtoValueOutOfRange {
3080 value: val.to_string(),
3081 }),
3082 EvalError::IntervalOutOfRange(val) => IntervalOutOfRange(ProtoValueOutOfRange {
3083 value: val.to_string(),
3084 }),
3085 EvalError::TimestampCannotBeNan => TimestampCannotBeNan(()),
3086 EvalError::TimestampOutOfRange => TimestampOutOfRange(()),
3087 EvalError::DateOutOfRange => DateOutOfRange(()),
3088 EvalError::CharOutOfRange => CharOutOfRange(()),
3089 EvalError::IndexOutOfRange {
3090 provided,
3091 valid_end,
3092 } => IndexOutOfRange(ProtoIndexOutOfRange {
3093 provided: *provided,
3094 valid_end: *valid_end,
3095 }),
3096 EvalError::InvalidBase64Equals => InvalidBase64Equals(()),
3097 EvalError::InvalidBase64Symbol(sym) => InvalidBase64Symbol(sym.into_proto()),
3098 EvalError::InvalidBase64EndSequence => InvalidBase64EndSequence(()),
3099 EvalError::InvalidTimezone(tz) => InvalidTimezone(tz.into_proto()),
3100 EvalError::InvalidTimezoneInterval => InvalidTimezoneInterval(()),
3101 EvalError::InvalidTimezoneConversion => InvalidTimezoneConversion(()),
3102 EvalError::InvalidLayer { max_layer, val } => InvalidLayer(ProtoInvalidLayer {
3103 max_layer: max_layer.into_proto(),
3104 val: *val,
3105 }),
3106 EvalError::InvalidArray(error) => InvalidArray(error.into_proto()),
3107 EvalError::InvalidEncodingName(v) => InvalidEncodingName(v.into_proto()),
3108 EvalError::InvalidHashAlgorithm(v) => InvalidHashAlgorithm(v.into_proto()),
3109 EvalError::InvalidByteSequence {
3110 byte_sequence,
3111 encoding_name,
3112 } => InvalidByteSequence(ProtoInvalidByteSequence {
3113 byte_sequence: byte_sequence.into_proto(),
3114 encoding_name: encoding_name.into_proto(),
3115 }),
3116 EvalError::InvalidJsonbCast { from, to } => InvalidJsonbCast(ProtoInvalidJsonbCast {
3117 from: from.into_proto(),
3118 to: to.into_proto(),
3119 }),
3120 EvalError::InvalidRegex(v) => InvalidRegex(v.into_proto()),
3121 EvalError::InvalidRegexFlag(v) => InvalidRegexFlag(v.into_proto()),
3122 EvalError::InvalidParameterValue(v) => InvalidParameterValue(v.into_proto()),
3123 EvalError::InvalidDatePart(part) => InvalidDatePart(part.into_proto()),
3124 EvalError::KeyCannotBeNull => KeyCannotBeNull(()),
3125 EvalError::NegSqrt => NegSqrt(()),
3126 EvalError::NegLimit => NegLimit(()),
3127 EvalError::NullCharacterNotPermitted => NullCharacterNotPermitted(()),
3128 EvalError::UnknownUnits(v) => UnknownUnits(v.into_proto()),
3129 EvalError::UnsupportedUnits(units, typ) => UnsupportedUnits(ProtoUnsupportedUnits {
3130 units: units.into_proto(),
3131 typ: typ.into_proto(),
3132 }),
3133 EvalError::UnterminatedLikeEscapeSequence => UnterminatedLikeEscapeSequence(()),
3134 EvalError::Parse(error) => Parse(error.into_proto()),
3135 EvalError::PrettyError(error) => PrettyError(error.into_proto()),
3136 EvalError::ParseHex(error) => ParseHex(error.into_proto()),
3137 EvalError::Internal(v) => Internal(v.into_proto()),
3138 EvalError::InfinityOutOfDomain(v) => InfinityOutOfDomain(v.into_proto()),
3139 EvalError::NegativeOutOfDomain(v) => NegativeOutOfDomain(v.into_proto()),
3140 EvalError::ZeroOutOfDomain(v) => ZeroOutOfDomain(v.into_proto()),
3141 EvalError::OutOfDomain(lower, upper, id) => OutOfDomain(ProtoOutOfDomain {
3142 lower: Some(lower.into_proto()),
3143 upper: Some(upper.into_proto()),
3144 id: id.into_proto(),
3145 }),
3146 EvalError::ComplexOutOfRange(v) => ComplexOutOfRange(v.into_proto()),
3147 EvalError::MultipleRowsFromSubquery => MultipleRowsFromSubquery(()),
3148 EvalError::Undefined(v) => Undefined(v.into_proto()),
3149 EvalError::LikePatternTooLong => LikePatternTooLong(()),
3150 EvalError::LikeEscapeTooLong => LikeEscapeTooLong(()),
3151 EvalError::StringValueTooLong {
3152 target_type,
3153 length,
3154 } => StringValueTooLong(ProtoStringValueTooLong {
3155 target_type: target_type.into_proto(),
3156 length: length.into_proto(),
3157 }),
3158 EvalError::MultidimensionalArrayRemovalNotSupported => {
3159 MultidimensionalArrayRemovalNotSupported(())
3160 }
3161 EvalError::IncompatibleArrayDimensions { dims } => {
3162 IncompatibleArrayDimensions(ProtoIncompatibleArrayDimensions {
3163 dims: dims.into_proto(),
3164 })
3165 }
3166 EvalError::TypeFromOid(v) => TypeFromOid(v.into_proto()),
3167 EvalError::InvalidRange(error) => InvalidRange(error.into_proto()),
3168 EvalError::InvalidRoleId(v) => InvalidRoleId(v.into_proto()),
3169 EvalError::InvalidPrivileges(v) => InvalidPrivileges(v.into_proto()),
3170 EvalError::InvalidCatalogJson(v) => InvalidCatalogJson(v.into_proto()),
3171 EvalError::LetRecLimitExceeded(v) => WmrRecursionLimitExceeded(v.into_proto()),
3172 EvalError::MultiDimensionalArraySearch => MultiDimensionalArraySearch(()),
3173 EvalError::MustNotBeNull(v) => MustNotBeNull(v.into_proto()),
3174 EvalError::InvalidIdentifier { ident, detail } => {
3175 InvalidIdentifier(ProtoInvalidIdentifier {
3176 ident: ident.into_proto(),
3177 detail: detail.into_proto(),
3178 })
3179 }
3180 EvalError::ArrayFillWrongArraySubscripts => ArrayFillWrongArraySubscripts(()),
3181 EvalError::MaxArraySizeExceeded(max_size) => {
3182 MaxArraySizeExceeded(u64::cast_from(*max_size))
3183 }
3184 EvalError::DateDiffOverflow { unit, a, b } => DateDiffOverflow(ProtoDateDiffOverflow {
3185 unit: unit.into_proto(),
3186 a: a.into_proto(),
3187 b: b.into_proto(),
3188 }),
3189 EvalError::IfNullError(s) => IfNullError(s.into_proto()),
3190 EvalError::LengthTooLarge => LengthTooLarge(()),
3191 EvalError::AclArrayNullElement => AclArrayNullElement(()),
3192 EvalError::MzAclArrayNullElement => MzAclArrayNullElement(()),
3193 EvalError::InvalidIanaTimezoneId(s) => InvalidIanaTimezoneId(s.into_proto()),
3194 };
3195 ProtoEvalError { kind: Some(kind) }
3196 }
3197
3198 fn from_proto(proto: ProtoEvalError) -> Result<Self, TryFromProtoError> {
3199 use proto_eval_error::Kind::*;
3200 match proto.kind {
3201 Some(kind) => match kind {
3202 CharacterNotValidForEncoding(v) => Ok(EvalError::CharacterNotValidForEncoding(v)),
3203 CharacterTooLargeForEncoding(v) => Ok(EvalError::CharacterTooLargeForEncoding(v)),
3204 DateBinOutOfRange(v) => Ok(EvalError::DateBinOutOfRange(v.into())),
3205 DivisionByZero(()) => Ok(EvalError::DivisionByZero),
3206 Unsupported(v) => Ok(EvalError::Unsupported {
3207 feature: v.feature.into(),
3208 discussion_no: v.discussion_no.into_rust()?,
3209 }),
3210 FloatOverflow(()) => Ok(EvalError::FloatOverflow),
3211 FloatUnderflow(()) => Ok(EvalError::FloatUnderflow),
3212 NumericFieldOverflow(()) => Ok(EvalError::NumericFieldOverflow),
3213 Float32OutOfRange(val) => Ok(EvalError::Float32OutOfRange(val.value.into())),
3214 Float64OutOfRange(val) => Ok(EvalError::Float64OutOfRange(val.value.into())),
3215 Int16OutOfRange(val) => Ok(EvalError::Int16OutOfRange(val.value.into())),
3216 Int32OutOfRange(val) => Ok(EvalError::Int32OutOfRange(val.value.into())),
3217 Int64OutOfRange(val) => Ok(EvalError::Int64OutOfRange(val.value.into())),
3218 Uint16OutOfRange(val) => Ok(EvalError::UInt16OutOfRange(val.value.into())),
3219 Uint32OutOfRange(val) => Ok(EvalError::UInt32OutOfRange(val.value.into())),
3220 Uint64OutOfRange(val) => Ok(EvalError::UInt64OutOfRange(val.value.into())),
3221 MzTimestampOutOfRange(val) => {
3222 Ok(EvalError::MzTimestampOutOfRange(val.value.into()))
3223 }
3224 MzTimestampStepOverflow(()) => Ok(EvalError::MzTimestampStepOverflow),
3225 OidOutOfRange(val) => Ok(EvalError::OidOutOfRange(val.value.into())),
3226 IntervalOutOfRange(val) => Ok(EvalError::IntervalOutOfRange(val.value.into())),
3227 TimestampCannotBeNan(()) => Ok(EvalError::TimestampCannotBeNan),
3228 TimestampOutOfRange(()) => Ok(EvalError::TimestampOutOfRange),
3229 DateOutOfRange(()) => Ok(EvalError::DateOutOfRange),
3230 CharOutOfRange(()) => Ok(EvalError::CharOutOfRange),
3231 IndexOutOfRange(v) => Ok(EvalError::IndexOutOfRange {
3232 provided: v.provided,
3233 valid_end: v.valid_end,
3234 }),
3235 InvalidBase64Equals(()) => Ok(EvalError::InvalidBase64Equals),
3236 InvalidBase64Symbol(v) => char::from_proto(v).map(EvalError::InvalidBase64Symbol),
3237 InvalidBase64EndSequence(()) => Ok(EvalError::InvalidBase64EndSequence),
3238 InvalidTimezone(v) => Ok(EvalError::InvalidTimezone(v.into())),
3239 InvalidTimezoneInterval(()) => Ok(EvalError::InvalidTimezoneInterval),
3240 InvalidTimezoneConversion(()) => Ok(EvalError::InvalidTimezoneConversion),
3241 InvalidLayer(v) => Ok(EvalError::InvalidLayer {
3242 max_layer: usize::from_proto(v.max_layer)?,
3243 val: v.val,
3244 }),
3245 InvalidArray(error) => Ok(EvalError::InvalidArray(error.into_rust()?)),
3246 InvalidEncodingName(v) => Ok(EvalError::InvalidEncodingName(v.into())),
3247 InvalidHashAlgorithm(v) => Ok(EvalError::InvalidHashAlgorithm(v.into())),
3248 InvalidByteSequence(v) => Ok(EvalError::InvalidByteSequence {
3249 byte_sequence: v.byte_sequence.into(),
3250 encoding_name: v.encoding_name.into(),
3251 }),
3252 InvalidJsonbCast(v) => Ok(EvalError::InvalidJsonbCast {
3253 from: v.from.into(),
3254 to: v.to.into(),
3255 }),
3256 InvalidRegex(v) => Ok(EvalError::InvalidRegex(v.into())),
3257 InvalidRegexFlag(v) => Ok(EvalError::InvalidRegexFlag(char::from_proto(v)?)),
3258 InvalidParameterValue(v) => Ok(EvalError::InvalidParameterValue(v.into())),
3259 InvalidDatePart(part) => Ok(EvalError::InvalidDatePart(part.into())),
3260 KeyCannotBeNull(()) => Ok(EvalError::KeyCannotBeNull),
3261 NegSqrt(()) => Ok(EvalError::NegSqrt),
3262 NegLimit(()) => Ok(EvalError::NegLimit),
3263 NullCharacterNotPermitted(()) => Ok(EvalError::NullCharacterNotPermitted),
3264 UnknownUnits(v) => Ok(EvalError::UnknownUnits(v.into())),
3265 UnsupportedUnits(v) => {
3266 Ok(EvalError::UnsupportedUnits(v.units.into(), v.typ.into()))
3267 }
3268 UnterminatedLikeEscapeSequence(()) => Ok(EvalError::UnterminatedLikeEscapeSequence),
3269 Parse(error) => Ok(EvalError::Parse(error.into_rust()?)),
3270 ParseHex(error) => Ok(EvalError::ParseHex(error.into_rust()?)),
3271 Internal(v) => Ok(EvalError::Internal(v.into())),
3272 InfinityOutOfDomain(v) => Ok(EvalError::InfinityOutOfDomain(v.into())),
3273 NegativeOutOfDomain(v) => Ok(EvalError::NegativeOutOfDomain(v.into())),
3274 ZeroOutOfDomain(v) => Ok(EvalError::ZeroOutOfDomain(v.into())),
3275 OutOfDomain(v) => Ok(EvalError::OutOfDomain(
3276 v.lower.into_rust_if_some("ProtoDomainLimit::lower")?,
3277 v.upper.into_rust_if_some("ProtoDomainLimit::upper")?,
3278 v.id.into(),
3279 )),
3280 ComplexOutOfRange(v) => Ok(EvalError::ComplexOutOfRange(v.into())),
3281 MultipleRowsFromSubquery(()) => Ok(EvalError::MultipleRowsFromSubquery),
3282 Undefined(v) => Ok(EvalError::Undefined(v.into())),
3283 LikePatternTooLong(()) => Ok(EvalError::LikePatternTooLong),
3284 LikeEscapeTooLong(()) => Ok(EvalError::LikeEscapeTooLong),
3285 StringValueTooLong(v) => Ok(EvalError::StringValueTooLong {
3286 target_type: v.target_type.into(),
3287 length: usize::from_proto(v.length)?,
3288 }),
3289 MultidimensionalArrayRemovalNotSupported(()) => {
3290 Ok(EvalError::MultidimensionalArrayRemovalNotSupported)
3291 }
3292 IncompatibleArrayDimensions(v) => Ok(EvalError::IncompatibleArrayDimensions {
3293 dims: v.dims.into_rust()?,
3294 }),
3295 TypeFromOid(v) => Ok(EvalError::TypeFromOid(v.into())),
3296 InvalidRange(e) => Ok(EvalError::InvalidRange(e.into_rust()?)),
3297 InvalidRoleId(v) => Ok(EvalError::InvalidRoleId(v.into())),
3298 InvalidPrivileges(v) => Ok(EvalError::InvalidPrivileges(v.into())),
3299 InvalidCatalogJson(v) => Ok(EvalError::InvalidCatalogJson(v.into())),
3300 WmrRecursionLimitExceeded(v) => Ok(EvalError::LetRecLimitExceeded(v.into())),
3301 MultiDimensionalArraySearch(()) => Ok(EvalError::MultiDimensionalArraySearch),
3302 MustNotBeNull(v) => Ok(EvalError::MustNotBeNull(v.into())),
3303 InvalidIdentifier(v) => Ok(EvalError::InvalidIdentifier {
3304 ident: v.ident.into(),
3305 detail: v.detail.into_rust()?,
3306 }),
3307 ArrayFillWrongArraySubscripts(()) => Ok(EvalError::ArrayFillWrongArraySubscripts),
3308 MaxArraySizeExceeded(max_size) => {
3309 Ok(EvalError::MaxArraySizeExceeded(usize::cast_from(max_size)))
3310 }
3311 DateDiffOverflow(v) => Ok(EvalError::DateDiffOverflow {
3312 unit: v.unit.into(),
3313 a: v.a.into(),
3314 b: v.b.into(),
3315 }),
3316 IfNullError(v) => Ok(EvalError::IfNullError(v.into())),
3317 LengthTooLarge(()) => Ok(EvalError::LengthTooLarge),
3318 AclArrayNullElement(()) => Ok(EvalError::AclArrayNullElement),
3319 MzAclArrayNullElement(()) => Ok(EvalError::MzAclArrayNullElement),
3320 InvalidIanaTimezoneId(s) => Ok(EvalError::InvalidIanaTimezoneId(s.into())),
3321 PrettyError(s) => Ok(EvalError::PrettyError(s.into())),
3322 },
3323 None => Err(TryFromProtoError::missing_field("ProtoEvalError::kind")),
3324 }
3325 }
3326}
3327
3328impl RustType<ProtoDims> for (usize, usize) {
3329 fn into_proto(&self) -> ProtoDims {
3330 ProtoDims {
3331 f0: self.0.into_proto(),
3332 f1: self.1.into_proto(),
3333 }
3334 }
3335
3336 fn from_proto(proto: ProtoDims) -> Result<Self, TryFromProtoError> {
3337 Ok((proto.f0.into_rust()?, proto.f1.into_rust()?))
3338 }
3339}
3340
3341#[cfg(test)]
3342mod tests {
3343 use super::*;
3344
3345 #[mz_ore::test]
3346 #[cfg_attr(miri, ignore)] fn test_reduce() {
3348 let relation_type: Vec<ReprColumnType> = vec![
3349 ReprScalarType::Int64.nullable(true),
3350 ReprScalarType::Int64.nullable(true),
3351 ReprScalarType::Int64.nullable(false),
3352 ]
3353 .into_iter()
3354 .collect();
3355 let col = MirScalarExpr::column;
3356 let int64_typ = ReprScalarType::Int64;
3357 let err = |e| MirScalarExpr::literal(Err(e), int64_typ.clone());
3358 let lit = |i| MirScalarExpr::literal_ok(Datum::Int64(i), int64_typ.clone());
3359 let null = || MirScalarExpr::literal_null(int64_typ.clone());
3360
3361 struct TestCase {
3362 input: MirScalarExpr,
3363 output: MirScalarExpr,
3364 }
3365
3366 let test_cases = vec![
3367 TestCase {
3368 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1)]),
3369 output: lit(1),
3370 },
3371 TestCase {
3372 input: MirScalarExpr::call_variadic(Coalesce, vec![lit(1), lit(2)]),
3373 output: lit(1),
3374 },
3375 TestCase {
3376 input: MirScalarExpr::call_variadic(Coalesce, vec![null(), lit(2), null()]),
3377 output: lit(2),
3378 },
3379 TestCase {
3380 input: MirScalarExpr::call_variadic(
3381 Coalesce,
3382 vec![null(), col(0), null(), col(1), lit(2), lit(3)],
3383 ),
3384 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(1), lit(2)]),
3385 },
3386 TestCase {
3387 input: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2), col(1)]),
3388 output: MirScalarExpr::call_variadic(Coalesce, vec![col(0), col(2)]),
3389 },
3390 TestCase {
3391 input: MirScalarExpr::call_variadic(
3392 Coalesce,
3393 vec![lit(1), err(EvalError::DivisionByZero)],
3394 ),
3395 output: lit(1),
3396 },
3397 TestCase {
3398 input: MirScalarExpr::call_variadic(
3399 Coalesce,
3400 vec![
3401 null(),
3402 err(EvalError::DivisionByZero),
3403 err(EvalError::NumericFieldOverflow),
3404 ],
3405 ),
3406 output: err(EvalError::DivisionByZero),
3407 },
3408 ];
3409
3410 for tc in test_cases {
3411 let mut actual = tc.input.clone();
3412 actual.reduce(&relation_type);
3413 assert!(
3414 actual == tc.output,
3415 "input: {}\nactual: {}\nexpected: {}",
3416 tc.input,
3417 actual,
3418 tc.output
3419 );
3420 }
3421 }
3422}