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